X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/810773f6e9b6b38b5727b1b8c65f73fcb2fb5515..41f87a79787f53df8a36796b7029e6c642cb1e23:/print-isoclns.c diff --git a/print-isoclns.c b/print-isoclns.c index 6df82300..ac3269c6 100644 --- a/print-isoclns.c +++ b/print-isoclns.c @@ -26,7 +26,7 @@ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/tcpdump/print-isoclns.c,v 1.129 2005-03-09 18:42:51 hannes Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/tcpdump/print-isoclns.c,v 1.133.2.8 2005-05-25 22:06:41 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -201,12 +201,131 @@ static struct tok esis_option_values[] = { #define CLNP_OPTION_DISCARD_REASON 193 #define CLNP_OPTION_QOS_MAINTENANCE 195 /* iso8473 */ +#define CLNP_OPTION_SECURITY 197 /* iso8473 */ +#define CLNP_OPTION_SOURCE_ROUTING 200 /* iso8473 */ +#define CLNP_OPTION_ROUTE_RECORDING 203 /* iso8473 */ +#define CLNP_OPTION_PADDING 204 /* iso8473 */ #define CLNP_OPTION_PRIORITY 205 /* iso8473 */ static struct tok clnp_option_values[] = { { CLNP_OPTION_DISCARD_REASON, "Discard Reason"}, { CLNP_OPTION_PRIORITY, "Priority"}, { CLNP_OPTION_QOS_MAINTENANCE, "QoS Maintenance"}, + { CLNP_OPTION_SECURITY, "Security"}, + { CLNP_OPTION_SOURCE_ROUTING, "Source Routing"}, + { CLNP_OPTION_ROUTE_RECORDING, "Route Recording"}, + { CLNP_OPTION_PADDING, "Padding"}, + { 0, NULL } +}; + +static struct tok clnp_option_rfd_class_values[] = { + { 0x0, "General"}, + { 0x8, "Address"}, + { 0x9, "Source Routeing"}, + { 0xa, "Lifetime"}, + { 0xb, "PDU Discarded"}, + { 0xc, "Reassembly"}, + { 0, NULL } +}; + +static struct tok clnp_option_rfd_general_values[] = { + { 0x0, "Reason not specified"}, + { 0x1, "Protocol procedure error"}, + { 0x2, "Incorrect checksum"}, + { 0x3, "PDU discarded due to congestion"}, + { 0x4, "Header syntax error (cannot be parsed)"}, + { 0x5, "Segmentation needed but not permitted"}, + { 0x6, "Incomplete PDU received"}, + { 0x7, "Duplicate option"}, + { 0, NULL } +}; + +static struct tok clnp_option_rfd_address_values[] = { + { 0x0, "Destination address unreachable"}, + { 0x1, "Destination address unknown"}, + { 0, NULL } +}; + +static struct tok clnp_option_rfd_source_routeing_values[] = { + { 0x0, "Unspecified source routeing error"}, + { 0x1, "Syntax error in source routeing field"}, + { 0x2, "Unknown address in source routeing field"}, + { 0x3, "Path not acceptable"}, + { 0, NULL } +}; + +static struct tok clnp_option_rfd_lifetime_values[] = { + { 0x0, "Lifetime expired while data unit in transit"}, + { 0x1, "Lifetime expired during reassembly"}, + { 0, NULL } +}; + +static struct tok clnp_option_rfd_pdu_discard_values[] = { + { 0x0, "Unsupported option not specified"}, + { 0x1, "Unsupported protocol version"}, + { 0x2, "Unsupported security option"}, + { 0x3, "Unsupported source routeing option"}, + { 0x4, "Unsupported recording of route option"}, + { 0, NULL } +}; + +static struct tok clnp_option_rfd_reassembly_values[] = { + { 0x0, "Reassembly interference"}, + { 0, NULL } +}; + +/* array of 16 error-classes */ +static struct tok *clnp_option_rfd_error_class[] = { + clnp_option_rfd_general_values, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + clnp_option_rfd_address_values, + clnp_option_rfd_source_routeing_values, + clnp_option_rfd_lifetime_values, + clnp_option_rfd_pdu_discard_values, + clnp_option_rfd_reassembly_values, + NULL, + NULL, + NULL +}; + +#define CLNP_OPTION_OPTION_QOS_MASK 0x3f +#define CLNP_OPTION_SCOPE_MASK 0xc0 +#define CLNP_OPTION_SCOPE_SA_SPEC 0x40 +#define CLNP_OPTION_SCOPE_DA_SPEC 0x80 +#define CLNP_OPTION_SCOPE_GLOBAL 0xc0 + +static struct tok clnp_option_scope_values[] = { + { CLNP_OPTION_SCOPE_SA_SPEC, "Source Address Specific"}, + { CLNP_OPTION_SCOPE_DA_SPEC, "Destination Address Specific"}, + { CLNP_OPTION_SCOPE_GLOBAL, "Globally unique"}, + { 0, NULL } +}; + +static struct tok clnp_option_sr_rr_values[] = { + { 0x0, "partial"}, + { 0x0, "complete"}, + { 0, NULL } +}; + +static struct tok clnp_option_sr_rr_string_values[] = { + { CLNP_OPTION_SOURCE_ROUTING, "source routing"}, + { CLNP_OPTION_ROUTE_RECORDING, "recording of route in progress"}, + { 0, NULL } +}; + +static struct tok clnp_option_qos_global_values[] = { + { 0x20, "reserved"}, + { 0x10, "sequencing vs. delay"}, + { 0x08, "congested"}, + { 0x04, "delay vs. cost"}, + { 0x02, "error vs. delay"}, + { 0x01, "error vs. cost"}, { 0, NULL } }; @@ -509,7 +628,9 @@ void isoclns_print(const u_int8_t *p, u_int length, u_int caplen) break; case NLPID_NULLNS: - (void)printf(", length: %u", length); + (void)printf("%slength: %u", + eflag ? "" : ", ", + length); break; case NLPID_Q933: @@ -517,7 +638,7 @@ void isoclns_print(const u_int8_t *p, u_int length, u_int caplen) break; case NLPID_IP: - ip_print(p+1, length-1); + ip_print(gndo, p+1, length-1); break; #ifdef INET6 @@ -533,7 +654,9 @@ void isoclns_print(const u_int8_t *p, u_int length, u_int caplen) default: if (!eflag) printf("OSI NLPID 0x%02x unknown",*p); - (void)printf(", length: %u", length); + (void)printf("%slength: %u", + eflag ? "" : ", ", + length); if (caplen > 1) print_unknown_data(p,"\n\t",caplen); break; @@ -579,9 +702,10 @@ struct clnp_segment_header_t { static int clnp_print (const u_int8_t *pptr, u_int length) { const u_int8_t *optr,*source_address,*dest_address; - u_int li,source_address_length,dest_address_length, clnp_pdu_type, clnp_flags; + u_int li,tlen,nsap_offset,source_address_length,dest_address_length, clnp_pdu_type, clnp_flags; const struct clnp_header_t *clnp_header; const struct clnp_segment_header_t *clnp_segment_header; + u_int8_t rfd_error_major,rfd_error_minor; clnp_header = (const struct clnp_header_t *) pptr; TCHECK(*clnp_header); @@ -668,8 +792,7 @@ static int clnp_print (const u_int8_t *pptr, u_int length) u_int op, opli; const u_int8_t *tptr; - if (snapend - pptr < 2) - return (0); + TCHECK2(*pptr, 2); if (li < 2) { printf(", bad opts/li"); return (0); @@ -677,15 +800,14 @@ static int clnp_print (const u_int8_t *pptr, u_int length) op = *pptr++; opli = *pptr++; li -= 2; + TCHECK2(*pptr, opli); if (opli > li) { printf(", opt (%d) too long", op); return (0); } li -= opli; tptr = pptr; - - if (snapend < pptr) - return(0); + tlen = opli; printf("\n\t %s Option #%u, length %u, value: ", tok2str(clnp_option_values,"Unknown",op), @@ -694,8 +816,74 @@ static int clnp_print (const u_int8_t *pptr, u_int length) switch (op) { + + case CLNP_OPTION_ROUTE_RECORDING: /* those two options share the format */ + case CLNP_OPTION_SOURCE_ROUTING: + printf("%s %s", + tok2str(clnp_option_sr_rr_values,"Unknown",*tptr), + tok2str(clnp_option_sr_rr_string_values,"Unknown Option %u",op)); + nsap_offset=*(tptr+1); + if (nsap_offset == 0) { + printf(" Bad NSAP offset (0)"); + break; + } + nsap_offset-=1; /* offset to nsap list */ + if (nsap_offset > tlen) { + printf(" Bad NSAP offset (past end of option)"); + break; + } + tptr+=nsap_offset; + tlen-=nsap_offset; + while (tlen > 0) { + source_address_length=*tptr; + if (tlen < source_address_length+1) { + printf("\n\t NSAP address goes past end of option"); + break; + } + if (source_address_length > 0) { + source_address=(tptr+1); + TCHECK2(*source_address, source_address_length); + printf("\n\t NSAP address (length %u): %s", + source_address_length, + isonsap_string(source_address, source_address_length)); + } + tlen-=source_address_length+1; + } + break; + case CLNP_OPTION_PRIORITY: - printf("%u", *tptr); + printf("0x%1x", *tptr&0x0f); + break; + + case CLNP_OPTION_QOS_MAINTENANCE: + printf("\n\t Format Code: %s", + tok2str(clnp_option_scope_values,"Reserved",*tptr&CLNP_OPTION_SCOPE_MASK)); + + if ((*tptr&CLNP_OPTION_SCOPE_MASK) == CLNP_OPTION_SCOPE_GLOBAL) + printf("\n\t QoS Flags [%s]", + bittok2str(clnp_option_qos_global_values, + "none", + *tptr&CLNP_OPTION_OPTION_QOS_MASK)); + break; + + case CLNP_OPTION_SECURITY: + printf("\n\t Format Code: %s, Security-Level %u", + tok2str(clnp_option_scope_values,"Reserved",*tptr&CLNP_OPTION_SCOPE_MASK), + *(tptr+1)); + break; + + case CLNP_OPTION_DISCARD_REASON: + rfd_error_major = (*tptr&0xf0) >> 4; + rfd_error_minor = *tptr&0x0f; + printf("\n\t Class: %s Error (0x%01x), %s (0x%01x)", + tok2str(clnp_option_rfd_class_values,"Unknown",rfd_error_major), + rfd_error_major, + tok2str(clnp_option_rfd_error_class[rfd_error_major],"Unknown",rfd_error_minor), + rfd_error_minor); + break; + + case CLNP_OPTION_PADDING: + printf("padding data"); break; /* @@ -703,8 +891,6 @@ static int clnp_print (const u_int8_t *pptr, u_int length) * you are welcome to contribute code ;-) */ - case CLNP_OPTION_DISCARD_REASON: - default: print_unknown_data(tptr,"\n\t ",opli); break; @@ -716,24 +902,26 @@ static int clnp_print (const u_int8_t *pptr, u_int length) switch (clnp_pdu_type) { + case CLNP_PDU_ER: /* fall through */ case CLNP_PDU_ERP: + TCHECK(*pptr); if (*(pptr) == NLPID_CLNP) { - printf("\n\t-----request packet-----\n\t"); + printf("\n\t-----original packet-----\n\t"); /* FIXME recursion protection */ clnp_print(pptr, length-clnp_header->length_indicator); break; } - case CLNP_PDU_ER: case CLNP_PDU_DT: case CLNP_PDU_MD: case CLNP_PDU_ERQ: default: /* dump the PDU specific data */ - printf("\n\t undecoded non-header data, length %u",length-clnp_header->length_indicator); - print_unknown_data(pptr,"\n\t ",length-(pptr-optr)); - + if (length-(pptr-optr) > 0) { + printf("\n\t undecoded non-header data, length %u",length-clnp_header->length_indicator); + print_unknown_data(pptr,"\n\t ",length-(pptr-optr)); + } } return (1); @@ -785,6 +973,7 @@ esis_print(const u_int8_t *pptr, u_int length) } esis_header = (const struct esis_header_t *) pptr; + TCHECK(*esis_header); li = esis_header->length_indicator; optr = pptr; @@ -834,7 +1023,8 @@ esis_print(const u_int8_t *pptr, u_int length) /* do not attempt to verify the checksum if it is zero */ if (EXTRACT_16BITS(esis_header->cksum) == 0) printf("(unverified)"); - else printf("(%s)", osi_cksum(pptr, li) ? "incorrect" : "correct"); + else + printf("(%s)", osi_cksum(pptr, li) ? "incorrect" : "correct"); printf(", holding time: %us, length indicator: %u",EXTRACT_16BITS(esis_header->holdtime),li); @@ -846,25 +1036,72 @@ esis_print(const u_int8_t *pptr, u_int length) switch (esis_pdu_type) { case ESIS_PDU_REDIRECT: { - const u_int8_t *dst, *snpa, *tptr; + const u_int8_t *dst, *snpa, *neta; + u_int dstl, snpal, netal; - dst = pptr; pptr += *pptr + 1; - if (pptr > snapend) + TCHECK(*pptr); + if (li < 1) { + printf(", bad redirect/li"); return; - printf("\n\t %s", isonsap_string(dst+1,*dst)); - snpa = pptr; pptr += *pptr + 1; - tptr = pptr; pptr += *pptr + 1; - if (pptr > snapend) + } + dstl = *pptr; + pptr++; + li--; + TCHECK2(*pptr, dstl); + if (li < dstl) { + printf(", bad redirect/li"); return; + } + dst = pptr; + pptr += dstl; + li -= dstl; + printf("\n\t %s", isonsap_string(dst,dstl)); + + TCHECK(*pptr); + if (li < 1) { + printf(", bad redirect/li"); + return; + } + snpal = *pptr; + pptr++; + li--; + TCHECK2(*pptr, snpal); + if (li < snpal) { + printf(", bad redirect/li"); + return; + } + snpa = pptr; + pptr += snpal; + li -= snpal; + TCHECK(*pptr); + if (li < 1) { + printf(", bad redirect/li"); + return; + } + netal = *pptr; + pptr++; + TCHECK2(*pptr, netal); + if (li < netal) { + printf(", bad redirect/li"); + return; + } + neta = pptr; + pptr += netal; + li -= netal; - if (tptr[0] == 0) - printf("\n\t %s", etheraddr_string(&snpa[1])); + if (netal == 0) + printf("\n\t %s", etheraddr_string(snpa)); else - printf("\n\t %s", isonsap_string(tptr+1,*tptr)); + printf("\n\t %s", isonsap_string(neta,netal)); break; } case ESIS_PDU_ESH: + TCHECK(*pptr); + if (li < 1) { + printf(", bad esh/li"); + return; + } source_address_number = *pptr; pptr++; li--; @@ -872,23 +1109,47 @@ esis_print(const u_int8_t *pptr, u_int length) printf("\n\t Number of Source Addresses: %u", source_address_number); while (source_address_number > 0) { + TCHECK(*pptr); + if (li < 1) { + printf(", bad esh/li"); + return; + } source_address_length = *pptr; + pptr++; + li--; + + TCHECK2(*pptr, source_address_length); + if (li < source_address_length) { + printf(", bad esh/li"); + return; + } printf("\n\t NET (length: %u): %s", source_address_length, - isonsap_string(pptr+1,source_address_length)); - - pptr += source_address_length+1; - li -= source_address_length+1; + isonsap_string(pptr,source_address_length)); + pptr += source_address_length; + li -= source_address_length; source_address_number--; } break; case ESIS_PDU_ISH: { + TCHECK(*pptr); + if (li < 1) { + printf(", bad ish/li"); + return; + } source_address_length = *pptr; - printf("\n\t NET (length: %u): %s", source_address_length, isonsap_string(pptr+1, source_address_length)); - pptr += source_address_length+1; - li -= source_address_length +1; + pptr++; + li--; + TCHECK2(*pptr, source_address_length); + if (li < source_address_length) { + printf(", bad ish/li"); + return; + } + printf("\n\t NET (length: %u): %s", source_address_length, isonsap_string(pptr, source_address_length)); + pptr += source_address_length; + li -= source_address_length; break; } @@ -905,8 +1166,7 @@ esis_print(const u_int8_t *pptr, u_int length) u_int op, opli; const u_int8_t *tptr; - if (snapend - pptr < 2) - return; + TCHECK2(*pptr, 2); if (li < 2) { printf(", bad opts/li"); return; @@ -921,9 +1181,6 @@ esis_print(const u_int8_t *pptr, u_int length) li -= opli; tptr = pptr; - if (snapend < pptr) - return; - printf("\n\t %s Option #%u, length %u, value: ", tok2str(esis_option_values,"Unknown",op), op, @@ -932,12 +1189,13 @@ esis_print(const u_int8_t *pptr, u_int length) switch (op) { case ESIS_OPTION_ES_CONF_TIME: + TCHECK2(*pptr, 2); printf("%us", EXTRACT_16BITS(tptr)); break; - case ESIS_OPTION_PROTOCOLS: while (opli>0) { + TCHECK(*pptr); printf("%s (0x%02x)", tok2str(nlpid_values, "unknown", @@ -969,6 +1227,8 @@ esis_print(const u_int8_t *pptr, u_int length) print_unknown_data(pptr,"\n\t ",opli); pptr += opli; } +trunc: + return; } /* shared routine for printing system, node and lsp-ids */ @@ -1818,6 +2078,9 @@ static int isis_print (const u_int8_t *p, u_int length) tlv_type, tlv_len); + if (tlv_len == 0) /* something is malformed */ + break; + /* now check if we have a decoder otherwise do a hexdump at the end*/ switch (tlv_type) { case ISIS_TLV_AREA_ADDR: @@ -1848,9 +2111,13 @@ static int isis_print (const u_int8_t *p, u_int length) break; case ISIS_TLV_ISNEIGH_VARLEN: - if (!TTEST2(*tptr, 1)) + if (!TTEST2(*tptr, 1) || tmp < 3) /* min. TLV length */ goto trunctlv; - lan_alen = *tptr++; /* LAN adress length */ + lan_alen = *tptr++; /* LAN address length */ + if (lan_alen == 0) { + printf("\n\t LAN address length 0 bytes (invalid)"); + break; + } tmp --; printf("\n\t LAN address length %u bytes ",lan_alen); while (tmp >= lan_alen) { @@ -2261,6 +2528,10 @@ static int isis_print (const u_int8_t *p, u_int length) if (!TTEST2(*tptr, 1)) goto trunctlv; prefix_len=*tptr++; /* read out prefix length in semioctets*/ + if (prefix_len < 2) { + printf("\n\t\tAddress: prefix length %u < 2", prefix_len); + break; + } tmp--; if (!TTEST2(*tptr, prefix_len/2)) goto trunctlv; @@ -2350,3 +2621,11 @@ osi_cksum(const u_int8_t *tptr, u_int len) } return (c0 | c1); } + + +/* + * Local Variables: + * c-style: whitesmith + * c-basic-offset: 8 + * End: + */