#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.138 2005-04-26 07:14:07 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
{ 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 ISIS_SUBTLV_EXT_IS_REACH_ADMIN_GROUP 3 /* draft-ietf-isis-traffic-05 */
#define ISIS_SUBTLV_EXT_IS_REACH_LINK_LOCAL_REMOTE_ID 4 /* draft-ietf-isis-gmpls-extensions */
#define ISIS_SUBTLV_EXT_IS_REACH_LINK_REMOTE_ID 5 /* draft-ietf-isis-traffic-05 */
break;
case NLPID_NULLNS:
- (void)printf(", length: %u", length);
+ (void)printf("%slength: %u",
+ eflag ? "" : ", ",
+ length);
break;
case NLPID_Q933:
break;
case NLPID_IP:
- ip_print(p+1, length-1);
+ ip_print(gndo, p+1, length-1);
break;
#ifdef INET6
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;
u_int li,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);
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);
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);
-
printf("\n\t %s Option #%u, length %u, value: ",
tok2str(clnp_option_values,"Unknown",op),
op,
printf("%u", *tptr);
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;
+
/*
* FIXME those are the defined Options that lack a decoder
* you are welcome to contribute code ;-)
*/
- case CLNP_OPTION_DISCARD_REASON:
-
default:
print_unknown_data(tptr,"\n\t ",opli);
break;
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);
}
esis_header = (const struct esis_header_t *) pptr;
+ TCHECK(*esis_header);
li = esis_header->length_indicator;
optr = pptr;
/* 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);
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--;
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;
}
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;
li -= opli;
tptr = pptr;
- if (snapend < pptr)
- return;
-
printf("\n\t %s Option #%u, length %u, value: ",
tok2str(esis_option_values,"Unknown",op),
op,
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",
print_unknown_data(pptr,"\n\t ",opli);
pptr += opli;
}
+trunc:
+ return;
}
/* shared routine for printing system, node and lsp-ids */
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:
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) {
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;
}
return (c0 | c1);
}
+
+
+/*
+ * Local Variables:
+ * c-style: whitesmith
+ * c-basic-offset: 8
+ * End:
+ */