summaryrefslogtreecommitdiffstats
path: root/contrib/tcpdump/print-juniper.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/tcpdump/print-juniper.c')
-rw-r--r--contrib/tcpdump/print-juniper.c409
1 files changed, 409 insertions, 0 deletions
diff --git a/contrib/tcpdump/print-juniper.c b/contrib/tcpdump/print-juniper.c
new file mode 100644
index 0000000..5d48bf7
--- /dev/null
+++ b/contrib/tcpdump/print-juniper.c
@@ -0,0 +1,409 @@
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code
+ * distributions retain the above copyright notice and this paragraph
+ * in its entirety, and (2) distributions including binary code include
+ * the above copyright notice and this paragraph in its entirety in
+ * the documentation or other materials provided with the distribution.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
+ * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
+ * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * Original code by Hannes Gredler (hannes@juniper.net)
+ */
+
+#ifndef lint
+static const char rcsid[] _U_ =
+ "@(#) $Header: /tcpdump/master/tcpdump/print-juniper.c,v 1.8 2005/04/06 21:32:41 mcr Exp $ (LBL)";
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <tcpdump-stdinc.h>
+
+#include <pcap.h>
+#include <stdio.h>
+
+#include "interface.h"
+#include "extract.h"
+#include "ppp.h"
+#include "llc.h"
+#include "nlpid.h"
+
+#define JUNIPER_BPF_OUT 0 /* Outgoing packet */
+#define JUNIPER_BPF_IN 1 /* Incoming packet */
+#define JUNIPER_BPF_PKT_IN 0x1 /* Incoming packet */
+#define JUNIPER_BPF_NO_L2 0x2 /* L2 header stripped */
+
+#define LS_COOKIE_ID 0x54
+#define LS_MLFR_LEN 4
+#define ML_MLFR_LEN 2
+
+#define ATM2_PKT_TYPE_MASK 0x70
+#define ATM2_GAP_COUNT_MASK 0x3F
+
+int ip_heuristic_guess(register const u_char *, u_int);
+int juniper_ppp_heuristic_guess(register const u_char *, u_int);
+static int juniper_parse_header (const u_char *, u_int8_t *, u_int);
+
+u_int
+juniper_mlppp_print(const struct pcap_pkthdr *h, register const u_char *p)
+{
+ register u_int length = h->len;
+ register u_int caplen = h->caplen;
+ u_int8_t direction,bundle,cookie_len;
+ u_int32_t cookie,proto;
+
+ if(juniper_parse_header(p, &direction,length) == 0)
+ return 0;
+
+ p+=4;
+ length-=4;
+ caplen-=4;
+
+ if (p[0] == LS_COOKIE_ID) {
+ cookie=EXTRACT_32BITS(p);
+ if (eflag) printf("LSPIC-MLPPP cookie 0x%08x, ",cookie);
+ cookie_len = LS_MLFR_LEN;
+ bundle = cookie & 0xff;
+ } else {
+ cookie=EXTRACT_16BITS(p);
+ if (eflag) printf("MLPIC-MLPPP cookie 0x%04x, ",cookie);
+ cookie_len = ML_MLFR_LEN;
+ bundle = (cookie >> 8) & 0xff;
+ }
+
+ proto = EXTRACT_16BITS(p+cookie_len);
+ p += cookie_len;
+ length-= cookie_len;
+ caplen-= cookie_len;
+
+ /* suppress Bundle-ID if frame was captured on a child-link
+ * this may be the case if the cookie looks like a proto */
+ if (eflag &&
+ cookie != PPP_OSI &&
+ cookie != (PPP_ADDRESS << 8 | PPP_CONTROL))
+ printf("Bundle-ID %u, ",bundle);
+
+ switch (cookie) {
+ case PPP_OSI:
+ ppp_print(p-2,length+2);
+ break;
+ case (PPP_ADDRESS << 8 | PPP_CONTROL): /* fall through */
+ default:
+ ppp_print(p,length);
+ break;
+ }
+
+ return cookie_len;
+}
+
+
+u_int
+juniper_mlfr_print(const struct pcap_pkthdr *h, register const u_char *p)
+{
+ register u_int length = h->len;
+ register u_int caplen = h->caplen;
+ u_int8_t direction,bundle,cookie_len;
+ u_int32_t cookie,proto,frelay_len = 0;
+
+ if(juniper_parse_header(p, &direction,length) == 0)
+ return 0;
+
+ p+=4;
+ length-=4;
+ caplen-=4;
+
+ if (p[0] == LS_COOKIE_ID) {
+ cookie=EXTRACT_32BITS(p);
+ if (eflag) printf("LSPIC-MLFR cookie 0x%08x, ",cookie);
+ cookie_len = LS_MLFR_LEN;
+ bundle = cookie & 0xff;
+ } else {
+ cookie=EXTRACT_16BITS(p);
+ if (eflag) printf("MLPIC-MLFR cookie 0x%04x, ",cookie);
+ cookie_len = ML_MLFR_LEN;
+ bundle = (cookie >> 8) & 0xff;
+ }
+
+ proto = EXTRACT_16BITS(p+cookie_len);
+ p += cookie_len+2;
+ length-= cookie_len+2;
+ caplen-= cookie_len+2;
+
+ /* suppress Bundle-ID if frame was captured on a child-link */
+ if (eflag && cookie != 1) printf("Bundle-ID %u, ",bundle);
+
+ switch (proto) {
+ case (LLC_UI):
+ case (LLC_UI<<8):
+ isoclns_print(p, length, caplen);
+ break;
+ case (LLC_UI<<8 | NLPID_Q933):
+ case (LLC_UI<<8 | NLPID_IP):
+ case (LLC_UI<<8 | NLPID_IP6):
+ isoclns_print(p-1, length+1, caplen+1); /* pass IP{4,6} to the OSI layer for proper link-layer printing */
+ break;
+ default:
+ printf("unknown protocol 0x%04x, length %u",proto, length);
+ }
+
+ return cookie_len + frelay_len;
+}
+
+/*
+ * ATM1 PIC cookie format
+ *
+ * +-----+-------------------------+-------------------------------+
+ * |fmtid| vc index | channel ID |
+ * +-----+-------------------------+-------------------------------+
+ */
+
+u_int
+juniper_atm1_print(const struct pcap_pkthdr *h, register const u_char *p)
+{
+ register u_int length = h->len;
+ register u_int caplen = h->caplen;
+ u_int16_t extracted_ethertype;
+ u_int8_t direction;
+ u_int32_t cookie1;
+
+ if(juniper_parse_header(p, &direction,length) == 0)
+ return 0;
+
+ p+=4;
+ length-=4;
+ caplen-=4;
+
+ cookie1=EXTRACT_32BITS(p);
+
+ if (eflag) {
+ /* FIXME decode channel-id, vc-index, fmt-id
+ for once lets just hexdump the cookie */
+
+ printf("ATM1 cookie 0x%08x, ", cookie1);
+ }
+
+ p+=4;
+ length-=4;
+ caplen-=4;
+
+ if ((cookie1 >> 24) == 0x80) { /* OAM cell ? */
+ oam_print(p,length);
+ return 0;
+ }
+
+ if (EXTRACT_24BITS(p) == 0xfefe03 || /* NLPID encaps ? */
+ EXTRACT_24BITS(p) == 0xaaaa03) { /* SNAP encaps ? */
+
+ if (llc_print(p, length, caplen, NULL, NULL,
+ &extracted_ethertype) != 0)
+ return 8;
+ }
+
+ if (p[0] == 0x03) { /* Cisco style NLPID encaps ? */
+ isoclns_print(p + 1, length - 1, caplen - 1);
+ /* FIXME check if frame was recognized */
+ return 8;
+ }
+
+ if(ip_heuristic_guess(p, length) != 0) /* last try - vcmux encaps ? */
+ return 0;
+
+ return (8);
+}
+
+/*
+ * ATM2 PIC cookie format
+ *
+ * +-------------------------------+---------+---+-----+-----------+
+ * | channel ID | reserv |AAL| CCRQ| gap cnt |
+ * +-------------------------------+---------+---+-----+-----------+
+ */
+
+u_int
+juniper_atm2_print(const struct pcap_pkthdr *h, register const u_char *p)
+{
+ register u_int length = h->len;
+ register u_int caplen = h->caplen;
+ u_int16_t extracted_ethertype;
+ u_int8_t direction;
+ u_int32_t cookie1,cookie2;
+
+ if(juniper_parse_header(p, &direction,length) == 0)
+ return 0;
+
+ p+=4;
+ length-=4;
+ caplen-=4;
+
+ cookie1=EXTRACT_32BITS(p);
+ cookie2=EXTRACT_32BITS(p+4);
+
+ if (eflag) {
+ /* FIXME decode channel, fmt-id, ccrq, aal, gap cnt
+ for once lets just hexdump the cookie */
+
+ printf("ATM2 cookie 0x%08x%08x, ",
+ EXTRACT_32BITS(p),
+ EXTRACT_32BITS(p+4));
+ }
+
+ p+=8;
+ length-=8;
+ caplen-=8;
+
+ if (cookie2 & ATM2_PKT_TYPE_MASK) { /* OAM cell ? */
+ oam_print(p,length);
+ return 12;
+ }
+
+ if (EXTRACT_24BITS(p) == 0xfefe03 || /* NLPID encaps ? */
+ EXTRACT_24BITS(p) == 0xaaaa03) { /* SNAP encaps ? */
+
+ if (llc_print(p, length, caplen, NULL, NULL,
+ &extracted_ethertype) != 0)
+ return 12;
+ }
+
+ if (direction != JUNIPER_BPF_PKT_IN && /* ether-over-1483 encaps ? */
+ (cookie1 & ATM2_GAP_COUNT_MASK)) {
+ ether_print(p, length, caplen);
+ return 12;
+ }
+
+ if (p[0] == 0x03) { /* Cisco style NLPID encaps ? */
+ isoclns_print(p + 1, length - 1, caplen - 1);
+ /* FIXME check if frame was recognized */
+ return 12;
+ }
+
+ if(juniper_ppp_heuristic_guess(p, length) != 0) /* PPPoA vcmux encaps ? */
+ return 12;
+
+ if(ip_heuristic_guess(p, length) != 0) /* last try - vcmux encaps ? */
+ return 12;
+
+ return (12);
+}
+
+
+/* try to guess, based on all PPP protos that are supported in
+ * a juniper router if the payload data is encapsulated using PPP */
+int
+juniper_ppp_heuristic_guess(register const u_char *p, u_int length) {
+
+ switch(EXTRACT_16BITS(p)) {
+ case PPP_IP :
+ case PPP_OSI :
+ case PPP_MPLS_UCAST :
+ case PPP_MPLS_MCAST :
+ case PPP_IPCP :
+ case PPP_OSICP :
+ case PPP_MPLSCP :
+ case PPP_LCP :
+ case PPP_PAP :
+ case PPP_CHAP :
+ case PPP_ML :
+#ifdef INET6
+ case PPP_IPV6 :
+ case PPP_IPV6CP :
+#endif
+ ppp_print(p, length);
+ break;
+
+ default:
+ return 0; /* did not find a ppp header */
+ break;
+ }
+ return 1; /* we printed a ppp packet */
+}
+
+int
+ip_heuristic_guess(register const u_char *p, u_int length) {
+
+ switch(p[0]) {
+ case 0x45:
+ case 0x46:
+ case 0x47:
+ case 0x48:
+ case 0x49:
+ case 0x4a:
+ case 0x4b:
+ case 0x4c:
+ case 0x4d:
+ case 0x4e:
+ case 0x4f:
+ ip_print(gndo, p, length);
+ break;
+#ifdef INET6
+ case 0x60:
+ case 0x61:
+ case 0x62:
+ case 0x63:
+ case 0x64:
+ case 0x65:
+ case 0x66:
+ case 0x67:
+ case 0x68:
+ case 0x69:
+ case 0x6a:
+ case 0x6b:
+ case 0x6c:
+ case 0x6d:
+ case 0x6e:
+ case 0x6f:
+ ip6_print(p, length);
+ break;
+#endif
+ default:
+ return 0; /* did not find a ip header */
+ break;
+ }
+ return 1; /* we printed an v4/v6 packet */
+}
+
+static int
+juniper_parse_header (const u_char *p, u_int8_t *direction, u_int length) {
+
+ *direction = p[3]&JUNIPER_BPF_PKT_IN;
+
+ if (EXTRACT_24BITS(p) != 0x4d4743) /* magic number found ? */
+ return -1;
+
+ if (*direction == JUNIPER_BPF_PKT_IN) {
+ if (eflag)
+ printf("%3s ", "In");
+ }
+ else {
+ if (eflag)
+ printf("%3s ", "Out");
+ }
+
+ if ((p[3] & JUNIPER_BPF_NO_L2 ) == JUNIPER_BPF_NO_L2 ) {
+ if (eflag)
+ printf("no-L2-hdr, ");
+
+ /* there is no link-layer present -
+ * perform the v4/v6 heuristics
+ * to figure out what it is
+ */
+ if(ip_heuristic_guess(p+8,length-8) == 0)
+ printf("no IP-hdr found!");
+
+ return 0; /* stop parsing the output further */
+
+ }
+ return 1; /* everything went ok so far. continue parsing */
+}
+
+
+/*
+ * Local Variables:
+ * c-style: whitesmith
+ * c-basic-offset: 8
+ * End:
+ */
OpenPOWER on IntegriCloud