X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/7ddf914b27c09b75f8939f7f9e8f9b54bbef4cd2..94e46babc871019d30240ee0d4279afc6bca1da8:/print-juniper.c?ds=inline diff --git a/print-juniper.c b/print-juniper.c index 0636db33..32b2e11f 100644 --- a/print-juniper.c +++ b/print-juniper.c @@ -15,7 +15,7 @@ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/tcpdump/print-juniper.c,v 1.8.2.5 2005-05-10 10:47:47 hannes Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/tcpdump/print-juniper.c,v 1.8.2.9 2005-05-22 21:25:41 hannes Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -28,10 +28,12 @@ static const char rcsid[] _U_ = #include #include "interface.h" +#include "addrtoname.h" #include "extract.h" #include "ppp.h" #include "llc.h" #include "nlpid.h" +#include "ethertype.h" #define JUNIPER_BPF_OUT 0 /* Outgoing packet */ #define JUNIPER_BPF_IN 1 /* Incoming packet */ @@ -39,27 +41,34 @@ static const char rcsid[] _U_ = #define JUNIPER_BPF_NO_L2 0x2 /* L2 header stripped */ #define JUNIPER_MGC_NUMBER 0x4d4743 /* = "MGC" */ +#define JUNIPER_LSQ_L3_PROTO_SHIFT 4 +#define JUNIPER_LSQ_L3_PROTO_MASK (0x17 << JUNIPER_LSQ_L3_PROTO_SHIFT) +#define JUNIPER_LSQ_L3_PROTO_IPV4 (0 << JUNIPER_LSQ_L3_PROTO_SHIFT) +#define JUNIPER_LSQ_L3_PROTO_IPV6 (1 << JUNIPER_LSQ_L3_PROTO_SHIFT) +#define JUNIPER_LSQ_L3_PROTO_MPLS (2 << JUNIPER_LSQ_L3_PROTO_SHIFT) +#define JUNIPER_LSQ_L3_PROTO_ISO (3 << JUNIPER_LSQ_L3_PROTO_SHIFT) + +#define JUNIPER_IPSEC_O_ESP_ENCRYPT_ESP_AUTHEN_TYPE 1 +#define JUNIPER_IPSEC_O_ESP_ENCRYPT_AH_AUTHEN_TYPE 2 +#define JUNIPER_IPSEC_O_ESP_AUTHENTICATION_TYPE 3 +#define JUNIPER_IPSEC_O_AH_AUTHENTICATION_TYPE 4 +#define JUNIPER_IPSEC_O_ESP_ENCRYPTION_TYPE 5 + +static struct tok juniper_ipsec_type_values[] = { + { JUNIPER_IPSEC_O_ESP_ENCRYPT_ESP_AUTHEN_TYPE, "ESP ENCR-AUTH" }, + { JUNIPER_IPSEC_O_ESP_ENCRYPT_AH_AUTHEN_TYPE, "ESP ENCR-AH AUTH" }, + { JUNIPER_IPSEC_O_ESP_AUTHENTICATION_TYPE, "ESP AUTH" }, + { JUNIPER_IPSEC_O_AH_AUTHENTICATION_TYPE, "AH AUTH" }, + { JUNIPER_IPSEC_O_ESP_ENCRYPTION_TYPE, "ESP ENCR" }, + { 0, NULL} +}; + static struct tok juniper_direction_values[] = { { JUNIPER_BPF_IN, "In"}, { JUNIPER_BPF_OUT, "Out"}, { 0, NULL} }; -/* FIXME change enums to real DLT_s */ -enum { - JUNIPER_ATM1, - JUNIPER_ATM2, - JUNIPER_MLPPP, - JUNIPER_MLFR, - JUNIPER_MFR, - JUNIPER_PPPOE -}; - -enum { - DEFAULT, - LS_COOKIE -}; - struct juniper_cookie_table_t { u_int32_t pictype; /* pic type */ u_int8_t cookie_len; /* cookie len */ @@ -67,12 +76,17 @@ struct juniper_cookie_table_t { }; static struct juniper_cookie_table_t juniper_cookie_table[] = { - { JUNIPER_ATM1, 4, "ATM1"}, - { JUNIPER_ATM2, 8, "ATM2"}, - { JUNIPER_MLPPP, 2, "MLPPP"}, - { JUNIPER_MLFR, 2, "MLFR"}, - { JUNIPER_MFR, 4, "MFR"}, - { JUNIPER_PPPOE, 0, "PPPoE"}, + { DLT_JUNIPER_ATM1, 4, "ATM1"}, + { DLT_JUNIPER_ATM2, 8, "ATM2"}, + { DLT_JUNIPER_MLPPP, 2, "MLPPP"}, + { DLT_JUNIPER_MLFR, 2, "MLFR"}, + { DLT_JUNIPER_MFR, 4, "MFR"}, + { DLT_JUNIPER_PPPOE, 0, "PPPoE"}, + { DLT_JUNIPER_PPPOE_ATM, 0, "PPPoE ATM"}, + { DLT_JUNIPER_GGSN, 8, "GGSN"}, + { DLT_JUNIPER_MONITOR, 8, "MONITOR"}, + { DLT_JUNIPER_SERVICES, 8, "AS"}, + { DLT_JUNIPER_ES, 0, "ES"}, }; struct juniper_l2info_t { @@ -89,6 +103,7 @@ struct juniper_l2info_t { }; #define LS_COOKIE_ID 0x54 +#define AS_COOKIE_ID 0x47 #define LS_MLFR_COOKIE_LEN 4 #define ML_MLFR_COOKIE_LEN 2 #define LS_MFR_COOKIE_LEN 6 @@ -98,16 +113,202 @@ struct juniper_l2info_t { #define ATM2_PKT_TYPE_MASK 0x70 #define ATM2_GAP_COUNT_MASK 0x3F +#define JUNIPER_PROTO_NULL 1 +#define JUNIPER_PROTO_IPV4 2 +#define JUNIPER_PROTO_IPV6 6 + +static struct tok juniper_protocol_values[] = { + { JUNIPER_PROTO_NULL, "Null" }, + { JUNIPER_PROTO_IPV4, "IPv4" }, + { JUNIPER_PROTO_IPV6, "IPv6" }, + { 0, NULL} +}; + 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 *, const struct pcap_pkthdr *, struct juniper_l2info_t *); +u_int +juniper_ggsn_print(const struct pcap_pkthdr *h, register const u_char *p) +{ + struct juniper_l2info_t l2info; + struct juniper_ggsn_header { + u_int8_t svc_id; + u_int8_t flags_len; + u_int8_t proto; + u_int8_t flags; + u_int8_t vlan_id[2]; + u_int8_t res[2]; + }; + const struct juniper_ggsn_header *gh; + + l2info.pictype = DLT_JUNIPER_GGSN; + if(juniper_parse_header(p, h, &l2info) == 0) + return l2info.header_len; + + p+=l2info.header_len; + gh = (struct juniper_ggsn_header *)p; + + if (eflag) + printf("proto %s (%u), vlan %u: ", + tok2str(juniper_protocol_values,"Unknown",gh->proto), + gh->proto, + EXTRACT_16BITS(&gh->vlan_id[0])); + + switch (gh->proto) { + case JUNIPER_PROTO_IPV4: + ip_print(gndo, p, l2info.length); + break; +#ifdef INET6 + case JUNIPER_PROTO_IPV6: + ip6_print(p, l2info.length); + break; +#endif /* INET6 */ + default: + if (!eflag) + printf("unknown GGSN proto (%u)", gh->proto); + } + + return l2info.header_len; +} + +u_int +juniper_es_print(const struct pcap_pkthdr *h, register const u_char *p) +{ + struct juniper_l2info_t l2info; + struct juniper_ipsec_header { + u_int8_t sa_index[2]; + u_int8_t ttl; + u_int8_t type; + u_int8_t spi[4]; + u_int8_t src_ip[4]; + u_int8_t dst_ip[4]; + }; + u_int rewrite_len,es_type_bundle; + const struct juniper_ipsec_header *ih; + + l2info.pictype = DLT_JUNIPER_ES; + if(juniper_parse_header(p, h, &l2info) == 0) + return l2info.header_len; + + p+=l2info.header_len; + ih = (struct juniper_ipsec_header *)p; + + switch (ih->type) { + case JUNIPER_IPSEC_O_ESP_ENCRYPT_ESP_AUTHEN_TYPE: + case JUNIPER_IPSEC_O_ESP_ENCRYPT_AH_AUTHEN_TYPE: + rewrite_len = 0; + es_type_bundle = 1; + break; + case JUNIPER_IPSEC_O_ESP_AUTHENTICATION_TYPE: + case JUNIPER_IPSEC_O_AH_AUTHENTICATION_TYPE: + case JUNIPER_IPSEC_O_ESP_ENCRYPTION_TYPE: + rewrite_len = 16; + es_type_bundle = 0; + default: + printf("ES Invalid type %u, length %u", + ih->type, + l2info.length); + return l2info.header_len; + } + + l2info.length-=rewrite_len; + p+=rewrite_len; + + if (eflag) { + if (!es_type_bundle) { + printf("ES SA, index %u, ttl %u type %s (%u), spi %u, Tunnel %s > %s, length %u\n", + EXTRACT_16BITS(&ih->sa_index), + ih->ttl, + tok2str(juniper_ipsec_type_values,"Unknown",ih->type), + ih->type, + EXTRACT_32BITS(&ih->spi), + ipaddr_string(EXTRACT_32BITS(&ih->src_ip)), + ipaddr_string(EXTRACT_32BITS(&ih->dst_ip)), + l2info.length); + } else { + printf("ES SA, index %u, ttl %u type %s (%u), length %u\n", + EXTRACT_16BITS(&ih->sa_index), + ih->ttl, + tok2str(juniper_ipsec_type_values,"Unknown",ih->type), + ih->type, + l2info.length); + } + } + + ip_print(gndo, p, l2info.length); + return l2info.header_len; +} + +u_int +juniper_monitor_print(const struct pcap_pkthdr *h, register const u_char *p) +{ + struct juniper_l2info_t l2info; + struct juniper_monitor_header { + u_int8_t pkt_type; + u_int8_t padding; + u_int8_t iif[2]; + u_int8_t service_id[4]; + }; + const struct juniper_monitor_header *mh; + + l2info.pictype = DLT_JUNIPER_MONITOR; + if(juniper_parse_header(p, h, &l2info) == 0) + return l2info.header_len; + + p+=l2info.header_len; + mh = (struct juniper_monitor_header *)p; + + if (eflag) + printf("service-id %u, iif %u, pkt-type %u: ", + EXTRACT_32BITS(&mh->service_id), + EXTRACT_16BITS(&mh->iif), + mh->pkt_type); + + /* no proto field - lets guess by first byte of IP header*/ + ip_heuristic_guess(p, l2info.length); + + return l2info.header_len; +} + +u_int +juniper_services_print(const struct pcap_pkthdr *h, register const u_char *p) +{ + struct juniper_l2info_t l2info; + struct juniper_services_header { + u_int8_t svc_id; + u_int8_t flags_len; + u_int8_t svc_set_id[2]; + u_int8_t dir_iif[4]; + }; + const struct juniper_services_header *sh; + + l2info.pictype = DLT_JUNIPER_SERVICES; + if(juniper_parse_header(p, h, &l2info) == 0) + return l2info.header_len; + + p+=l2info.header_len; + sh = (struct juniper_services_header *)p; + + if (eflag) + printf("service-id %u flags 0x%02x service-set-id 0x%04x iif %u: ", + sh->svc_id, + sh->flags_len, + EXTRACT_16BITS(&sh->svc_set_id), + EXTRACT_24BITS(&sh->dir_iif[1])); + + /* no proto field - lets guess by first byte of IP header*/ + ip_heuristic_guess(p, l2info.length); + + return l2info.header_len; +} + u_int juniper_pppoe_print(const struct pcap_pkthdr *h, register const u_char *p) { struct juniper_l2info_t l2info; - l2info.pictype = JUNIPER_PPPOE; + l2info.pictype = DLT_JUNIPER_PPPOE; if(juniper_parse_header(p, h, &l2info) == 0) return l2info.header_len; @@ -117,13 +318,38 @@ juniper_pppoe_print(const struct pcap_pkthdr *h, register const u_char *p) return l2info.header_len; } +u_int +juniper_pppoe_atm_print(const struct pcap_pkthdr *h, register const u_char *p) +{ + struct juniper_l2info_t l2info; + u_int16_t extracted_ethertype; + + l2info.pictype = DLT_JUNIPER_PPPOE_ATM; + if(juniper_parse_header(p, h, &l2info) == 0) + return l2info.header_len; + + p+=l2info.header_len; + + extracted_ethertype = EXTRACT_16BITS(p); + /* this DLT contains nothing but raw PPPoE frames, + * prepended with a type field*/ + if (ether_encap_print(extracted_ethertype, + p+ETHERTYPE_LEN, + l2info.length-ETHERTYPE_LEN, + l2info.caplen-ETHERTYPE_LEN, + &extracted_ethertype) == 0) + /* ether_type not known, probably it wasn't one */ + printf("unknown ethertype 0x%04x", extracted_ethertype); + + return l2info.header_len; +} u_int juniper_mlppp_print(const struct pcap_pkthdr *h, register const u_char *p) { struct juniper_l2info_t l2info; - l2info.pictype = JUNIPER_MLPPP; + l2info.pictype = DLT_JUNIPER_MLPPP; if(juniper_parse_header(p, h, &l2info) == 0) return l2info.header_len; @@ -132,10 +358,29 @@ juniper_mlppp_print(const struct pcap_pkthdr *h, register const u_char *p) if (eflag && EXTRACT_16BITS(&l2info.cookie) != PPP_OSI && EXTRACT_16BITS(&l2info.cookie) != (PPP_ADDRESS << 8 | PPP_CONTROL)) - printf(", Bundle-ID %u: ",l2info.bundle); + printf("Bundle-ID %u: ",l2info.bundle); p+=l2info.header_len; + /* first try the LSQ protos */ + switch(l2info.proto) { + case JUNIPER_LSQ_L3_PROTO_IPV4: + ip_print(gndo, p, l2info.length); + return l2info.header_len; + case JUNIPER_LSQ_L3_PROTO_IPV6: + ip6_print(p,l2info.length); + return l2info.header_len; + case JUNIPER_LSQ_L3_PROTO_MPLS: + mpls_print(p,l2info.length); + return l2info.header_len; + case JUNIPER_LSQ_L3_PROTO_ISO: + isoclns_print(p,l2info.length,l2info.caplen); + return l2info.header_len; + default: + break; + } + + /* zero length cookie ? */ switch (EXTRACT_16BITS(&l2info.cookie)) { case PPP_OSI: ppp_print(p-2,l2info.length+2); @@ -155,7 +400,7 @@ juniper_mfr_print(const struct pcap_pkthdr *h, register const u_char *p) { struct juniper_l2info_t l2info; - l2info.pictype = JUNIPER_MFR; + l2info.pictype = DLT_JUNIPER_MFR; if(juniper_parse_header(p, h, &l2info) == 0) return l2info.header_len; @@ -184,7 +429,7 @@ juniper_mlfr_print(const struct pcap_pkthdr *h, register const u_char *p) { struct juniper_l2info_t l2info; - l2info.pictype = JUNIPER_MLFR; + l2info.pictype = DLT_JUNIPER_MLFR; if(juniper_parse_header(p, h, &l2info) == 0) return l2info.header_len; @@ -225,7 +470,7 @@ juniper_atm1_print(const struct pcap_pkthdr *h, register const u_char *p) struct juniper_l2info_t l2info; - l2info.pictype = JUNIPER_ATM1; + l2info.pictype = DLT_JUNIPER_ATM1; if(juniper_parse_header(p, h, &l2info) == 0) return l2info.header_len; @@ -271,7 +516,7 @@ juniper_atm2_print(const struct pcap_pkthdr *h, register const u_char *p) struct juniper_l2info_t l2info; - l2info.pictype = JUNIPER_ATM2; + l2info.pictype = DLT_JUNIPER_ATM2; if(juniper_parse_header(p, h, &l2info) == 0) return l2info.header_len; @@ -402,6 +647,7 @@ juniper_parse_header (const u_char *p, const struct pcap_pkthdr *h, struct junip l2info->caplen = h->caplen; l2info->direction = p[3]&JUNIPER_BPF_PKT_IN; + TCHECK2(p[0],4); if (EXTRACT_24BITS(p) != JUNIPER_MGC_NUMBER) /* magic number found ? */ return 0; else @@ -418,6 +664,7 @@ juniper_parse_header (const u_char *p, const struct pcap_pkthdr *h, struct junip * perform the v4/v6 heuristics * to figure out what it is */ + TCHECK2(p[8],1); if(ip_heuristic_guess(p+8,l2info->length-8) == 0) printf("no IP-hdr found!"); @@ -437,12 +684,22 @@ juniper_parse_header (const u_char *p, const struct pcap_pkthdr *h, struct junip l2info->cookie_len = lp->cookie_len; l2info->header_len += lp->cookie_len; - if(p[0] == LS_COOKIE_ID) { - l2info->cookie_type = LS_COOKIE; + switch (p[0]) { + case LS_COOKIE_ID: + l2info->cookie_type = LS_COOKIE_ID; l2info->cookie_len += 2; l2info->header_len += 2; - l2info->bundle = l2info->cookie[1]; - } else l2info->bundle = l2info->cookie[0]; + break; + case AS_COOKIE_ID: + l2info->cookie_type = AS_COOKIE_ID; + l2info->cookie_len += 6; + l2info->header_len += 6; + break; + + default: + l2info->bundle = l2info->cookie[0]; + break; + } if (eflag) printf("%s-PIC, cookie-len %u", @@ -450,6 +707,7 @@ juniper_parse_header (const u_char *p, const struct pcap_pkthdr *h, struct junip l2info->cookie_len); if (l2info->cookie_len > 0) { + TCHECK2(p[0],l2info->cookie_len); if (eflag) printf(", cookie 0x"); for (idx = 0; idx < l2info->cookie_len; idx++) { @@ -470,29 +728,49 @@ juniper_parse_header (const u_char *p, const struct pcap_pkthdr *h, struct junip /* DLT_ specific parsing */ switch(l2info->pictype) { - case JUNIPER_MLPPP: - if (l2info->cookie_type == LS_COOKIE) { + case DLT_JUNIPER_MLPPP: + switch (l2info->cookie_type) { + case LS_COOKIE_ID: l2info->bundle = l2info->cookie[1]; - } else { + break; + case AS_COOKIE_ID: + l2info->bundle = (EXTRACT_16BITS(&l2info->cookie[6])>>3)&0xfff; + l2info->proto = (l2info->cookie[5])&JUNIPER_LSQ_L3_PROTO_MASK; + break; + default: l2info->bundle = l2info->cookie[0]; + break; } break; - case JUNIPER_MLFR: /* fall through */ - case JUNIPER_MFR: - if (l2info->cookie_type == LS_COOKIE) { + case DLT_JUNIPER_MLFR: /* fall through */ + case DLT_JUNIPER_MFR: + switch (l2info->cookie_type) { + case LS_COOKIE_ID: l2info->bundle = l2info->cookie[1]; - } else { + break; + case AS_COOKIE_ID: + l2info->bundle = (EXTRACT_16BITS(&l2info->cookie[6])>>3)&0xfff; + break; + default: l2info->bundle = l2info->cookie[0]; + break; } l2info->proto = EXTRACT_16BITS(p); l2info->header_len += 2; l2info->length -= 2; l2info->caplen -= 2; break; - case JUNIPER_ATM2: - case JUNIPER_ATM1: + case DLT_JUNIPER_ATM2: + TCHECK2(p[0],4); + /* ATM cell relay control word present ? */ + if (l2info->cookie[7] & ATM2_PKT_TYPE_MASK && *p & 0x08) { + l2info->header_len += 4; + if (eflag) + printf("control-word 0x%08x ",EXTRACT_32BITS(p)); + } + break; + case DLT_JUNIPER_ATM1: default: - break; } @@ -500,6 +778,9 @@ juniper_parse_header (const u_char *p, const struct pcap_pkthdr *h, struct junip printf("hlen %u, proto 0x%04x, ",l2info->header_len,l2info->proto); return 1; /* everything went ok so far. continue parsing */ + trunc: + printf("[|juniper_hdr], length %u",h->len); + return 0; }