diff --git a/contrib/tcpdump/addrtoname.c b/contrib/tcpdump/addrtoname.c index af2a757325f0..8bfc3c379b49 100644 --- a/contrib/tcpdump/addrtoname.c +++ b/contrib/tcpdump/addrtoname.c @@ -467,15 +467,16 @@ isonsap_string(const u_char *nsap) if (tp->e_name) return tp->e_name; - tp->e_name = cp = (char *)malloc(nlen * 2 + 2); + tp->e_name = cp = (char *)malloc(nlen * 2 + 2 + (nlen>>1)); if (cp == NULL) error("isonsap_string: malloc"); nsap++; - *cp++ = '/'; - for (i = nlen; (int)--i >= 0;) { + for (i = 0; i < nlen; i++) { *cp++ = hex[*nsap >> 4]; *cp++ = hex[*nsap++ & 0xf]; + if (((i & 1) == 0) && (i + 1 < nlen)) + *cp++ = '.'; } *cp = '\0'; return (tp->e_name); diff --git a/contrib/tcpdump/print-isoclns.c b/contrib/tcpdump/print-isoclns.c index c7db005b780c..1825164b7e59 100644 --- a/contrib/tcpdump/print-isoclns.c +++ b/contrib/tcpdump/print-isoclns.c @@ -46,14 +46,16 @@ struct rtentry; #include "interface.h" #include "addrtoname.h" #include "ethertype.h" +#include "extract.h" -#define CLNS 129 -#define ESIS 130 -#define ISIS 131 -#define NULLNS 0 +#define NLPID_CLNS 129 /* 0x81 */ +#define NLPID_ESIS 130 /* 0x82 */ +#define NLPID_ISIS 131 /* 0x83 */ +#define NLPID_NULLNS 0 static int osi_cksum(const u_char *, u_int, const u_char *, u_char *, u_char *); static void esis_print(const u_char *, u_int); +static int isis_print(const u_char *, u_int); void isoclns_print(const u_char *p, u_int length, u_int caplen, @@ -70,17 +72,17 @@ isoclns_print(const u_char *p, u_int length, u_int caplen, switch (*p) { - case CLNS: + case NLPID_CLNS: /* esis_print(&p, &length); */ - printf("iso-clns"); + printf("iso clns"); if (!eflag) (void)printf(" %s > %s", etheraddr_string(esrc), etheraddr_string(edst)); break; - case ESIS: - printf("iso-esis"); + case NLPID_ESIS: + printf("iso esis"); if (!eflag) (void)printf(" %s > %s", etheraddr_string(esrc), @@ -88,20 +90,20 @@ isoclns_print(const u_char *p, u_int length, u_int caplen, esis_print(p, length); return; - case ISIS: - printf("iso-isis"); + case NLPID_ISIS: + printf("iso isis"); if (!eflag) (void)printf(" %s > %s", etheraddr_string(esrc), etheraddr_string(edst)); - /* isis_print(&p, &length); */ (void)printf(" len=%d ", length); - if (caplen > 1) - default_print_unaligned(p, caplen); + if (!isis_print(p, length)) { + default_print_unaligned(p, caplen); + } break; - case NULLNS: - printf("iso-nullns"); + case NLPID_NULLNS: + printf("iso nullns"); if (!eflag) (void)printf(" %s > %s", etheraddr_string(esrc), @@ -109,7 +111,7 @@ isoclns_print(const u_char *p, u_int length, u_int caplen, break; default: - printf("iso-clns %02x", p[0]); + printf("iso clns %02x", p[0]); if (!eflag) (void)printf(" %s > %s", etheraddr_string(esrc), @@ -206,7 +208,7 @@ esis_print(const u_char *p, u_int length) dst = p; p += *p + 1; if (p > snapend) return; - printf(" %s", isonsap_string(dst)); + printf("\n\t\t\t %s", isonsap_string(dst)); snpa = p; p += *p + 1; is = p; p += *p + 1; if (p > snapend) @@ -237,7 +239,7 @@ esis_print(const u_char *p, u_int length) } if (p > snapend) return; - printf(" %s", isonsap_string(is)); + printf("\n\t\t\t %s", isonsap_string(is)); li = ep - p; break; } @@ -284,6 +286,257 @@ esis_print(const u_char *p, u_int length) } } +/* + * print_nsap + * Print out an NSAP. + */ + +void +print_nsap (register const u_char *cp, register int length) +{ + int i; + + for (i = 0; i < length; i++) { + printf("%02x", *cp++); + if (((i & 1) == 0) && (i + 1 < length)) { + printf("."); + } + + } +} + +/* + * IS-IS is defined in ISO 10589. Look there for protocol definitions. + */ + +#define SYSTEM_ID_LEN sizeof(struct ether_addr) +#define ISIS_VERSION 1 +#define PDU_TYPE_MASK 0x1F +#define PRIORITY_MASK 0x7F + +#define L1_LAN_IIH 15 +#define L2_LAN_IIH 16 +#define PTP_IIH 17 + +#define TLV_AREA_ADDR 1 +#define TLV_ISNEIGH 6 +#define TLV_PADDING 8 +#define TLV_AUTHENT 10 + +struct isis_header { + u_char nlpid; + u_char fixed_len; + u_char version; /* Protocol version? */ + u_char id_length; + u_char enc_pdu_type; /* 3 MSbs are reserved */ + u_char pkt_version; /* Packet format version? */ + u_char reserved; + u_char enc_max_area; + u_char circuit; + u_char enc_source_id[SYSTEM_ID_LEN]; + u_char enc_holding_time[2]; + u_char enc_packet_len[2]; + u_char enc_priority; + u_char enc_lan_id[SYSTEM_ID_LEN+1]; +}; + +#define ISIS_HEADER_SIZE (15+(SYSTEM_ID_LEN<<1)) + +/* + * isis_print + * Decode IS-IS packets. Return 0 on error. + * + * So far, this is only smart enough to print IIH's. Someday... + */ + +static int +isis_print (const u_char *p, u_int length) +{ + struct isis_header *header; + u_char pdu_type, max_area, priority, *pptr, type, len, *tptr, tmp, alen; + u_short packet_len, holding_time; + + header = (struct isis_header *)p; + printf("\n\t\t\t"); + + /* + * Sanity checking of the header. + */ + if (header->nlpid != NLPID_ISIS) { + printf(" coding error!"); + return(0); + } + + if (header->version != ISIS_VERSION) { + printf(" version %d packet not supported", header->version); + return(0); + } + + if ((header->id_length != SYSTEM_ID_LEN) && (header->id_length != 0)) { + printf(" system ID length of %d is not supported", + header->id_length); + return(0); + } + + if ((header->fixed_len != ISIS_HEADER_SIZE)) { + printf(" bogus fixed header length %d should be %d", + header->fixed_len, ISIS_HEADER_SIZE); + return(0); + } + + pdu_type = header->enc_pdu_type & PDU_TYPE_MASK; + if ((pdu_type != L1_LAN_IIH) && (pdu_type != L2_LAN_IIH)) { + printf(" PDU type (%d) not supported", pdu_type); + return; + } + + if (header->pkt_version != ISIS_VERSION) { + printf(" version %d packet not supported", header->pkt_version); + return; + } + + max_area = header->enc_max_area; + switch(max_area) { + case 0: + max_area = 3; /* silly shit */ + break; + case 255: + printf(" bad packet -- 255 areas"); + return(0); + default: + break; + } + + switch (header->circuit) { + case 0: + printf(" PDU with circuit type 0"); + return(0); + case 1: + if (pdu_type == L2_LAN_IIH) { + printf(" L2 IIH on an L1 only circuit"); + return(0); + } + break; + case 2: + if (pdu_type == L1_LAN_IIH) { + printf(" L1 IIH on an L2 only circuit"); + return(0); + } + break; + case 3: + break; + default: + printf(" unknown circuit type"); + return(0); + } + + holding_time = EXTRACT_16BITS(header->enc_holding_time); + + packet_len = EXTRACT_16BITS(header->enc_packet_len); + if ((packet_len < ISIS_HEADER_SIZE) || + (packet_len > length)) { + printf(" bogus packet length %d, real length %d", packet_len, + length); + return(0); + } + + priority = header->enc_priority & PRIORITY_MASK; + + /* + * Now print the fixed header. + */ + switch (pdu_type) { + case L1_LAN_IIH: + printf(" L1 lan iih, "); + break; + case L2_LAN_IIH: + printf(" L2 lan iih, "); + break; + } + + printf("circuit "); + switch (header->circuit) { + case 1: + printf("l1 only, "); + break; + case 2: + printf("l2 only, "); + break; + case 3: + printf("l1-l2, "); + break; + } + + printf ("holding time %d ", holding_time); + printf ("\n\t\t\t source %s, length %d", + etheraddr_string(header->enc_source_id), packet_len); + printf ("\n\t\t\t lan id %s(%d)", etheraddr_string(header->enc_lan_id), + header->enc_lan_id[SYSTEM_ID_LEN]); + + /* + * Now print the TLV's. + */ + packet_len -= ISIS_HEADER_SIZE; + pptr = (char *)p + ISIS_HEADER_SIZE; + while (packet_len >= 2) { + if (pptr >= snapend) { + printf("\n\t\t\t packet exceeded snapshot"); + return(1); + } + type = *pptr++; + len = *pptr++; + packet_len -= 2; + if (len > packet_len) { + break; + } + + switch (type) { + case TLV_AREA_ADDR: + printf("\n\t\t\t area addresses"); + tmp = len; + tptr = pptr; + alen = *tptr++; + while (tmp && alen < tmp) { + printf("\n\t\t\t "); + print_nsap(tptr, alen); + printf(" (%d)", alen); + tptr += alen; + tmp -= alen + 1; + alen = *tptr++; + } + break; + case TLV_ISNEIGH: + printf("\n\t\t\t neighbor addresses"); + tmp = len; + tptr = pptr; + while (tmp >= sizeof(struct ether_addr)) { + printf("\n\t\t\t %s", etheraddr_string(tptr)); + tmp -= sizeof(struct ether_addr); + tptr += sizeof(struct ether_addr); + } + break; + case TLV_PADDING: + printf("\n\t\t\t padding for %d bytes", len); + break; + case TLV_AUTHENT: + printf("\n\t\t\t authentication data"); + default_print(pptr, len); + break; + default: + printf("\n\t\t\t unknown TLV, type %d, length %d", type, len); + break; + } + + pptr += len; + packet_len -= len; + } + + if (packet_len != 0) { + printf("\n\t\t\t %d straggler bytes", packet_len); + } + return(1); +} + static int osi_cksum(register const u_char *p, register u_int len, const u_char *toff, u_char *cksum, u_char *off)