X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/0531555b158feffb9c62e4cbf8208b8c69c8a618..1ee09c1510704191a14df4eb914dba3d5dc9ab58:/print-ospf.c diff --git a/print-ospf.c b/print-ospf.c index 6cb6f98d..6fd33b28 100644 --- a/print-ospf.c +++ b/print-ospf.c @@ -22,8 +22,8 @@ */ #ifndef lint -static const char rcsid[] = - "@(#) $Header: /tcpdump/master/tcpdump/print-ospf.c,v 1.37 2003-10-02 13:35:52 hannes Exp $ (LBL)"; +static const char rcsid[] _U_ = + "@(#) $Header: /tcpdump/master/tcpdump/print-ospf.c,v 1.57 2005-04-20 21:55:14 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -37,6 +37,7 @@ static const char rcsid[] = #include "interface.h" #include "addrtoname.h" #include "extract.h" +#include "gmpls.h" #include "ospf.h" @@ -50,6 +51,7 @@ static struct tok ospf_option_values[] = { { OSPF_OPTION_EA, "Advertise External" }, { OSPF_OPTION_DC, "Demand Circuit" }, { OSPF_OPTION_O, "Opaque" }, + { OSPF_OPTION_DN, "Up/Down" }, { 0, NULL } }; @@ -99,6 +101,77 @@ static struct tok ospf_dd_flag_values[] = { { 0, NULL } }; +static struct tok lsa_opaque_values[] = { + { LS_OPAQUE_TYPE_TE, "Traffic Engineering" }, + { LS_OPAQUE_TYPE_GRACE, "Graceful restart" }, + { LS_OPAQUE_TYPE_RI, "Router Information" }, + { 0, NULL } +}; + +static struct tok lsa_opaque_te_tlv_values[] = { + { LS_OPAQUE_TE_TLV_ROUTER, "Router Address" }, + { LS_OPAQUE_TE_TLV_LINK, "Link" }, + { 0, NULL } +}; + +static struct tok lsa_opaque_te_link_tlv_subtlv_values[] = { + { LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE, "Link Type" }, + { LS_OPAQUE_TE_LINK_SUBTLV_LINK_ID, "Link ID" }, + { LS_OPAQUE_TE_LINK_SUBTLV_LOCAL_IP, "Local Interface IP address" }, + { LS_OPAQUE_TE_LINK_SUBTLV_REMOTE_IP, "Remote Interface IP address" }, + { LS_OPAQUE_TE_LINK_SUBTLV_TE_METRIC, "Traffic Engineering Metric" }, + { LS_OPAQUE_TE_LINK_SUBTLV_MAX_BW, "Maximum Bandwidth" }, + { LS_OPAQUE_TE_LINK_SUBTLV_MAX_RES_BW, "Maximum Reservable Bandwidth" }, + { LS_OPAQUE_TE_LINK_SUBTLV_UNRES_BW, "Unreserved Bandwidth" }, + { LS_OPAQUE_TE_LINK_SUBTLV_ADMIN_GROUP, "Administrative Group" }, + { LS_OPAQUE_TE_LINK_SUBTLV_LINK_LOCAL_REMOTE_ID, "Link Local/Remote Identifier" }, + { LS_OPAQUE_TE_LINK_SUBTLV_LINK_PROTECTION_TYPE, "Link Protection Type" }, + { LS_OPAQUE_TE_LINK_SUBTLV_INTF_SW_CAP_DESCR, "Interface Switching Capability" }, + { LS_OPAQUE_TE_LINK_SUBTLV_SHARED_RISK_GROUP, "Shared Risk Link Group" }, + { LS_OPAQUE_TE_LINK_SUBTLV_DIFFSERV_TE, "Diffserv TE" }, + { 0, NULL } +}; + +static struct tok lsa_opaque_grace_tlv_values[] = { + { LS_OPAQUE_GRACE_TLV_PERIOD, "Grace Period" }, + { LS_OPAQUE_GRACE_TLV_REASON, "Graceful restart Reason" }, + { LS_OPAQUE_GRACE_TLV_INT_ADDRESS, "IPv4 interface address" }, + { 0, NULL } +}; + +static struct tok lsa_opaque_grace_tlv_reason_values[] = { + { LS_OPAQUE_GRACE_TLV_REASON_UNKNOWN, "Unknown" }, + { LS_OPAQUE_GRACE_TLV_REASON_SW_RESTART, "Software Restart" }, + { LS_OPAQUE_GRACE_TLV_REASON_SW_UPGRADE, "Software Reload/Upgrade" }, + { LS_OPAQUE_GRACE_TLV_REASON_CP_SWITCH, "Control Processor Switch" }, + { 0, NULL } +}; + +static struct tok lsa_opaque_te_tlv_link_type_sub_tlv_values[] = { + { LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE_PTP, "Point-to-point" }, + { LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE_MA, "Multi-Access" }, + { 0, NULL } +}; + +static struct tok lsa_opaque_ri_tlv_values[] = { + { LS_OPAQUE_RI_TLV_CAP, "Router Capabilities" }, + { 0, NULL } +}; + +static struct tok lsa_opaque_ri_tlv_cap_values[] = { + { 1, "Reserved" }, + { 2, "Reserved" }, + { 4, "Reserved" }, + { 8, "Reserved" }, + { 16, "graceful restart capable" }, + { 32, "graceful restart helper" }, + { 64, "Stub router support" }, + { 128, "Traffic engineering" }, + { 256, "p2p over LAN" }, + { 512, "path computation server" }, + { 0, NULL } +}; + static char tstr[] = " [|ospf]"; #ifdef WIN32 @@ -106,60 +179,101 @@ static char tstr[] = " [|ospf]"; #endif /* WIN32 */ static int ospf_print_lshdr(const struct lsa_hdr *); -static int ospf_print_lsa(const struct lsa *); +static const u_char *ospf_print_lsa(const struct lsa *); static int ospf_decode_v2(const struct ospfhdr *, const u_char *); static int -ospf_print_lshdr(register const struct lsa_hdr *lshp) { +ospf_print_lshdr(register const struct lsa_hdr *lshp) +{ + u_int ls_length; + + TCHECK(lshp->ls_length); + ls_length = EXTRACT_16BITS(&lshp->ls_length); + if (ls_length < sizeof(struct lsa_hdr)) { + printf("\n\t Bogus length %u < %lu", ls_length, + (unsigned long)sizeof(struct lsa_hdr)); + return(-1); + } - TCHECK(lshp->ls_type); - TCHECK(lshp->ls_options); + TCHECK(lshp->ls_seq); /* XXX - ls_length check checked this */ + printf("\n\t Advertising Router: %s, seq 0x%08x, age %us, length: %u", + ipaddr_string(&lshp->ls_router), + EXTRACT_32BITS(&lshp->ls_seq), + EXTRACT_16BITS(&lshp->ls_age), + ls_length-(u_int)sizeof(struct lsa_hdr)); + + TCHECK(lshp->ls_type); /* XXX - ls_length check checked this */ + switch (lshp->ls_type) { + /* the LSA header for opaque LSAs was slightly changed */ + case LS_TYPE_OPAQUE_LL: + case LS_TYPE_OPAQUE_AL: + case LS_TYPE_OPAQUE_DW: + printf("\n\t %s LSA (%d), Opaque-Type: %s LSA (%u), Opaque-ID: %u", + tok2str(lsa_values,"unknown",lshp->ls_type), + lshp->ls_type, + + tok2str(lsa_opaque_values, + "unknown", + *(&lshp->un_lsa_id.opaque_field.opaque_type)), + *(&lshp->un_lsa_id.opaque_field.opaque_type), + EXTRACT_24BITS(&lshp->un_lsa_id.opaque_field.opaque_id) + + ); + break; + + /* all other LSA types use regular style LSA headers */ + default: + printf("\n\t %s LSA (%d), LSA-ID: %s", + tok2str(lsa_values,"unknown",lshp->ls_type), + lshp->ls_type, + ipaddr_string(&lshp->un_lsa_id.lsa_id)); + break; + } - printf("\n\t %s LSA (%d), LSA-ID: %s, Advertising Router: %s, seq 0x%08x, age %us", - tok2str(lsa_values,"unknown",lshp->ls_type), - lshp->ls_type, - ipaddr_string(&lshp->ls_stateid), - ipaddr_string(&lshp->ls_router), - EXTRACT_32BITS(&lshp->ls_seq), - EXTRACT_16BITS(&lshp->ls_age)); - printf("\n\t Options: %s", bittok2str(ospf_option_values,"none",lshp->ls_options)); + TCHECK(lshp->ls_options); /* XXX - ls_length check checked this */ + printf("\n\t Options: [%s]", bittok2str(ospf_option_values,"none",lshp->ls_options)); -return (0); + return (ls_length); trunc: - return (1); + return (-1); } /* - * Print a single link state advertisement. If truncated return 1, else 0. + * Print a single link state advertisement. If truncated or if LSA length + * field is less than the length of the LSA header, return NULl, else + * return pointer to data past end of LSA. */ -static int +static const u_int8_t * ospf_print_lsa(register const struct lsa *lsap) { - register const u_char *ls_end; + register const u_int8_t *ls_end; register const struct rlalink *rlp; register const struct tos_metric *tosp; register const struct in_addr *ap; register const struct aslametric *almp; register const struct mcla *mcp; register const u_int32_t *lp; - register int j, k; - - printf("\n\t %s LSA (%d), LSA-ID: %s, Advertising Router: %s, seq 0x%08x, age %us", - tok2str(lsa_values,"unknown",lsap->ls_hdr.ls_type), - lsap->ls_hdr.ls_type, - ipaddr_string(&lsap->ls_hdr.ls_stateid), - ipaddr_string(&lsap->ls_hdr.ls_router), - EXTRACT_32BITS(&lsap->ls_hdr.ls_seq), - EXTRACT_16BITS(&lsap->ls_hdr.ls_age)); - printf("\n\t Options: %s", bittok2str(ospf_option_values,"none",lsap->ls_hdr.ls_options)); - - TCHECK(lsap->ls_hdr.ls_length); - ls_end = (u_char *)lsap + EXTRACT_16BITS(&lsap->ls_hdr.ls_length); + register int j, k, tlv_type, tlv_length, subtlv_type, subtlv_length, priority_level, bandwidth_constraint; + register int ls_length; + const u_int8_t *tptr; + int count_srlg; + union { /* int to float conversion buffer for several subTLVs */ + float f; + u_int32_t i; + } bw; + + tptr = (u_int8_t *)lsap->lsa_un.un_unknown; /* squelch compiler warnings */ + ls_length = ospf_print_lshdr(&lsap->ls_hdr); + if (ls_length == -1) + return(NULL); + ls_end = (u_int8_t *)lsap + ls_length; + ls_length -= sizeof(struct lsa_hdr); + switch (lsap->ls_hdr.ls_type) { case LS_TYPE_ROUTER: TCHECK(lsap->lsa_un.un_rla.rla_flags); - printf("\n\t Router LSA Options: %s", bittok2str(ospf_rla_flag_values,"unknown (%u)",lsap->lsa_un.un_rla.rla_flags)); + printf("\n\t Router LSA Options: [%s]", bittok2str(ospf_rla_flag_values,"none",lsap->lsa_un.un_rla.rla_flags)); TCHECK(lsap->lsa_un.un_rla.rla_count); j = EXTRACT_16BITS(&lsap->lsa_un.un_rla.rla_count); @@ -170,33 +284,33 @@ ospf_print_lsa(register const struct lsa *lsap) switch (rlp->link_type) { case RLA_TYPE_VIRTUAL: - printf("\n\t Virtual Link: Neighbor-Router-ID: %s, Interface-IP: %s", + printf("\n\t Virtual Link: Neighbor Router-ID: %s, Interface Address: %s", ipaddr_string(&rlp->link_id), ipaddr_string(&rlp->link_data)); break; case RLA_TYPE_ROUTER: - printf("\n\t Neighbor-Router-ID: %s, Interface-IP: %s", + printf("\n\t Neighbor Router-ID: %s, Interface Address: %s", ipaddr_string(&rlp->link_id), ipaddr_string(&rlp->link_data)); break; case RLA_TYPE_TRANSIT: - printf("\n\t Neighbor-Network-ID: %s, Interface-IP: %s", + printf("\n\t Neighbor Network-ID: %s, Interface Address: %s", ipaddr_string(&rlp->link_id), ipaddr_string(&rlp->link_data)); break; case RLA_TYPE_STUB: - printf("\n\t Stub-Network: %s, mask: %s", + printf("\n\t Stub Network: %s, Mask: %s", ipaddr_string(&rlp->link_id), ipaddr_string(&rlp->link_data)); break; default: - printf("\n\t unknown Router Links Type (%u)", + printf("\n\t Unknown Router Link Type (%u)", rlp->link_type); - return (0); + return (ls_end); } printf(", tos 0, metric: %d", EXTRACT_16BITS(&rlp->link_tos0metric)); tosp = (struct tos_metric *) @@ -214,19 +328,19 @@ ospf_print_lsa(register const struct lsa *lsap) case LS_TYPE_NETWORK: TCHECK(lsap->lsa_un.un_nla.nla_mask); - printf("\n\t mask %s rtrs", + printf("\n\t Mask %s\n\t Connected Routers:", ipaddr_string(&lsap->lsa_un.un_nla.nla_mask)); ap = lsap->lsa_un.un_nla.nla_router; while ((u_char *)ap < ls_end) { TCHECK(*ap); - printf(" %s", ipaddr_string(ap)); + printf("\n\t %s", ipaddr_string(ap)); ++ap; } break; case LS_TYPE_SUM_IP: TCHECK(lsap->lsa_un.un_nla.nla_mask); - printf("\n\t mask %s", + printf("\n\t Mask %s", ipaddr_string(&lsap->lsa_un.un_sla.sla_mask)); TCHECK(lsap->lsa_un.un_sla.sla_tosmetric); lp = lsap->lsa_un.un_sla.sla_tosmetric; @@ -268,8 +382,9 @@ ospf_print_lsa(register const struct lsa *lsap) break; case LS_TYPE_ASE: + case LS_TYPE_NSSA: /* fall through - those LSAs share the same format */ TCHECK(lsap->lsa_un.un_nla.nla_mask); - printf("\n\t mask %s", + printf("\n\t Mask %s", ipaddr_string(&lsap->lsa_un.un_asla.asla_mask)); TCHECK(lsap->lsa_un.un_sla.sla_tosmetric); @@ -327,34 +442,307 @@ ospf_print_lsa(register const struct lsa *lsap) } break; - /* - * FIXME those are the defined LSAs that lack a decoder - * you are welcome to contribute code ;-) - */ - - case LS_TYPE_OPAQUE_LL: + case LS_TYPE_OPAQUE_LL: /* fall through */ case LS_TYPE_OPAQUE_AL: case LS_TYPE_OPAQUE_DW: + switch (*(&lsap->ls_hdr.un_lsa_id.opaque_field.opaque_type)) { + case LS_OPAQUE_TYPE_RI: + tptr = (u_int8_t *)(&lsap->lsa_un.un_ri_tlv.type); + + while (ls_length != 0) { + TCHECK2(*tptr, 4); + if (ls_length < 4) { + printf("\n\t Remaining LS length %u < 4", ls_length); + return(ls_end); + } + tlv_type = EXTRACT_16BITS(tptr); + tlv_length = EXTRACT_16BITS(tptr+2); + tptr+=4; + ls_length-=4; + + printf("\n\t %s TLV (%u), length: %u, value: ", + tok2str(lsa_opaque_ri_tlv_values,"unknown",tlv_type), + tlv_type, + tlv_length); + + if (tlv_length > ls_length) { + printf("\n\t Bogus length %u > %u", tlv_length, + ls_length); + return(ls_end); + } + ls_length-=tlv_length; + TCHECK2(*tptr, tlv_length); + switch(tlv_type) { + + case LS_OPAQUE_RI_TLV_CAP: + if (tlv_length != 4) { + printf("\n\t Bogus length %u != 4", tlv_length); + return(ls_end); + } + printf("Capabilities: %s", + bittok2str(lsa_opaque_ri_tlv_cap_values, "Unknown", EXTRACT_32BITS(tptr))); + break; + default: + if (vflag <= 1) { + if(!print_unknown_data(tptr,"\n\t ",tlv_length)) + return(ls_end); + } + break; + + } + tptr+=tlv_length; + } + + break; + case LS_OPAQUE_TYPE_GRACE: + tptr = (u_int8_t *)(&lsap->lsa_un.un_grace_tlv.type); + + while (ls_length != 0) { + TCHECK2(*tptr, 4); + if (ls_length < 4) { + printf("\n\t Remaining LS length %u < 4", ls_length); + return(ls_end); + } + tlv_type = EXTRACT_16BITS(tptr); + tlv_length = EXTRACT_16BITS(tptr+2); + tptr+=4; + ls_length-=4; + + printf("\n\t %s TLV (%u), length: %u, value: ", + tok2str(lsa_opaque_grace_tlv_values,"unknown",tlv_type), + tlv_type, + tlv_length); + + if (tlv_length > ls_length) { + printf("\n\t Bogus length %u > %u", tlv_length, + ls_length); + return(ls_end); + } + ls_length-=tlv_length; + TCHECK2(*tptr, tlv_length); + switch(tlv_type) { + + case LS_OPAQUE_GRACE_TLV_PERIOD: + if (tlv_length != 4) { + printf("\n\t Bogus length %u != 4", tlv_length); + return(ls_end); + } + printf("%us",EXTRACT_32BITS(tptr)); + break; + case LS_OPAQUE_GRACE_TLV_REASON: + if (tlv_length != 1) { + printf("\n\t Bogus length %u != 1", tlv_length); + return(ls_end); + } + printf("%s (%u)", + tok2str(lsa_opaque_grace_tlv_reason_values, "Unknown", *tptr), + *tptr); + break; + case LS_OPAQUE_GRACE_TLV_INT_ADDRESS: + if (tlv_length != 4) { + printf("\n\t Bogus length %u != 4", tlv_length); + return(ls_end); + } + printf("%s", ipaddr_string(tptr)); + break; + default: + if (vflag <= 1) { + if(!print_unknown_data(tptr,"\n\t ",tlv_length)) + return(ls_end); + } + break; + + } + tptr+=tlv_length; + } + + break; + case LS_OPAQUE_TYPE_TE: + tptr = (u_int8_t *)(&lsap->lsa_un.un_te_lsa_tlv.type); + + while (ls_length != 0) { + TCHECK2(*tptr, 4); + if (ls_length < 4) { + printf("\n\t Remaining LS length %u < 4", ls_length); + return(ls_end); + } + tlv_type = EXTRACT_16BITS(tptr); + tlv_length = EXTRACT_16BITS(tptr+2); + tptr+=4; + ls_length-=4; + + printf("\n\t %s TLV (%u), length: %u", + tok2str(lsa_opaque_te_tlv_values,"unknown",tlv_type), + tlv_type, + tlv_length); + + if (tlv_length > ls_length) { + printf("\n\t Bogus length %u > %u", tlv_length, + ls_length); + return(ls_end); + } + ls_length-=tlv_length; + switch(tlv_type) { + case LS_OPAQUE_TE_TLV_LINK: + while (tlv_length != 0) { + if (tlv_length < 4) { + printf("\n\t Remaining TLV length %u < 4", + tlv_length); + return(ls_end); + } + TCHECK2(*tptr, 4); + subtlv_type = EXTRACT_16BITS(tptr); + subtlv_length = EXTRACT_16BITS(tptr+2); + tptr+=4; + tlv_length-=4; + + printf("\n\t %s subTLV (%u), length: %u", + tok2str(lsa_opaque_te_link_tlv_subtlv_values,"unknown",subtlv_type), + subtlv_type, + subtlv_length); + + TCHECK2(*tptr, subtlv_length); + switch(subtlv_type) { + case LS_OPAQUE_TE_LINK_SUBTLV_ADMIN_GROUP: + printf(", 0x%08x", EXTRACT_32BITS(tptr)); + break; + case LS_OPAQUE_TE_LINK_SUBTLV_LINK_ID: + case LS_OPAQUE_TE_LINK_SUBTLV_LINK_LOCAL_REMOTE_ID: + printf(", %s (0x%08x)", + ipaddr_string(tptr), + EXTRACT_32BITS(tptr)); + if (subtlv_length == 8) /* draft-ietf-ccamp-ospf-gmpls-extensions */ + printf(", %s (0x%08x)", + ipaddr_string(tptr+4), + EXTRACT_32BITS(tptr+4)); + break; + case LS_OPAQUE_TE_LINK_SUBTLV_LOCAL_IP: + case LS_OPAQUE_TE_LINK_SUBTLV_REMOTE_IP: + printf(", %s", ipaddr_string(tptr)); + break; + case LS_OPAQUE_TE_LINK_SUBTLV_MAX_BW: + case LS_OPAQUE_TE_LINK_SUBTLV_MAX_RES_BW: + bw.i = EXTRACT_32BITS(tptr); + printf(", %.3f Mbps", bw.f*8/1000000 ); + break; + case LS_OPAQUE_TE_LINK_SUBTLV_UNRES_BW: + for (priority_level = 0; priority_level < 8; priority_level++) { + bw.i = EXTRACT_32BITS(tptr+priority_level*4); + printf("\n\t\tpriority level %d: %.3f Mbps", + priority_level, + bw.f*8/1000000 ); + } + break; + case LS_OPAQUE_TE_LINK_SUBTLV_DIFFSERV_TE: + printf("\n\t\tBandwidth Constraints Model ID: %s (%u)", + tok2str(diffserv_te_bc_values, "unknown", *tptr), + *tptr); + /* decode BCs until the subTLV ends */ + for (bandwidth_constraint = 0; bandwidth_constraint < (subtlv_length-4)/4; bandwidth_constraint++) { + bw.i = EXTRACT_32BITS(tptr+4+bandwidth_constraint*4); + printf("\n\t\t Bandwidth constraint %d: %.3f Mbps", + bandwidth_constraint, + bw.f*8/1000000 ); + } + break; + case LS_OPAQUE_TE_LINK_SUBTLV_TE_METRIC: + printf(", Metric %u", EXTRACT_32BITS(tptr)); + break; + case LS_OPAQUE_TE_LINK_SUBTLV_LINK_PROTECTION_TYPE: + printf(", %s, Priority %u", + bittok2str(gmpls_link_prot_values, "none", *tptr), + *(tptr+1)); + break; + case LS_OPAQUE_TE_LINK_SUBTLV_INTF_SW_CAP_DESCR: + printf("\n\t\tInterface Switching Capability: %s", + tok2str(gmpls_switch_cap_values, "Unknown", *(tptr))); + printf("\n\t\tLSP Encoding: %s\n\t\tMax LSP Bandwidth:", + tok2str(gmpls_encoding_values, "Unknown", *(tptr+1))); + for (priority_level = 0; priority_level < 8; priority_level++) { + bw.i = EXTRACT_32BITS(tptr+4+(priority_level*4)); + printf("\n\t\t priority level %d: %.3f Mbps", + priority_level, + bw.f*8/1000000 ); + } + break; + case LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE: + printf(", %s (%u)", + tok2str(lsa_opaque_te_tlv_link_type_sub_tlv_values,"unknown",*tptr), + *tptr); + break; + + case LS_OPAQUE_TE_LINK_SUBTLV_SHARED_RISK_GROUP: + count_srlg = subtlv_length / 4; + if (count_srlg != 0) + printf("\n\t\t Shared risk group: "); + while (count_srlg > 0) { + bw.i = EXTRACT_32BITS(tptr); + printf("%d",bw.i); + tptr+=4; + count_srlg--; + if (count_srlg > 0) + printf(", "); + } + break; + + default: + if (vflag <= 1) { + if(!print_unknown_data(tptr,"\n\t\t",subtlv_length)) + return(ls_end); + } + break; + } + /* in OSPF everything has to be 32-bit aligned, including TLVs */ + if (subtlv_length%4 != 0) + subtlv_length+=4-(subtlv_length%4); + + tlv_length-=subtlv_length; + tptr+=subtlv_length; + + } + break; + + case LS_OPAQUE_TE_TLV_ROUTER: + if (tlv_length < 4) { + printf("\n\t TLV length %u < 4", tlv_length); + return(ls_end); + } + TCHECK2(*tptr, 4); + printf(", %s", ipaddr_string(tptr)); + break; + + default: + if (vflag <= 1) { + if(!print_unknown_data(tptr,"\n\t ",tlv_length)) + return(ls_end); + } + break; + } + tptr+=tlv_length; + } + break; + } + break; default: - if (vflag <= 1) { - if(!print_unknown_data((u_char *)lsap->lsa_un.un_unknown, - "\n\t ", EXTRACT_16BITS(&lsap->ls_hdr.ls_length)-sizeof(struct lsa_hdr))) - return(0); - } - break; + if (vflag <= 1) { + if(!print_unknown_data((u_int8_t *)lsap->lsa_un.un_unknown, + "\n\t ", ls_length)) + return(ls_end); + } + break; } /* do we want to see an additionally hexdump ? */ - if (vflag> 1) { - if(!print_unknown_data((u_char *)lsap->lsa_un.un_unknown, - "\n\t ", EXTRACT_16BITS(&lsap->ls_hdr.ls_length)-sizeof(struct lsa_hdr))) - return(0); - } - - return (0); + if (vflag> 1) + if(!print_unknown_data((u_int8_t *)lsap->lsa_un.un_unknown, + "\n\t ", ls_length)) { + return(ls_end); + } + + return (ls_end); trunc: - return (1); + return (NULL); } static int @@ -365,7 +753,7 @@ ospf_decode_v2(register const struct ospfhdr *op, register const struct lsr *lsrp; register const struct lsa_hdr *lshp; register const struct lsa *lsap; - register int lsa_count; + register u_int32_t lsa_count,lsa_count_max; switch (op->ospf_type) { @@ -377,16 +765,16 @@ ospf_decode_v2(register const struct ospfhdr *op, break; case OSPF_TYPE_HELLO: + printf("\n\tOptions: [%s]", + bittok2str(ospf_option_values,"none",op->ospf_hello.hello_options)); + TCHECK(op->ospf_hello.hello_deadint); - printf("\n\t Hello Timer: %us, Dead Timer %us, mask: %s, Priority: %u", + printf("\n\t Hello Timer: %us, Dead Timer %us, Mask: %s, Priority: %u", EXTRACT_16BITS(&op->ospf_hello.hello_helloint), EXTRACT_32BITS(&op->ospf_hello.hello_deadint), ipaddr_string(&op->ospf_hello.hello_mask), op->ospf_hello.hello_priority); - printf("\n\t Options: %s", - bittok2str(ospf_option_values,"none",op->ospf_hello.hello_options)); - TCHECK(op->ospf_hello.hello_dr); if (op->ospf_hello.hello_dr.s_addr != 0) printf("\n\t Designated Router %s", @@ -409,16 +797,16 @@ ospf_decode_v2(register const struct ospfhdr *op, case OSPF_TYPE_DD: TCHECK(op->ospf_db.db_options); - printf("\n\t Options: %s", + printf("\n\tOptions: [%s]", bittok2str(ospf_option_values,"none",op->ospf_db.db_options)); TCHECK(op->ospf_db.db_flags); - printf("\n\t DD Flags: %s", + printf(", DD Flags: [%s]", bittok2str(ospf_dd_flag_values,"none",op->ospf_db.db_flags)); if (vflag) { /* Print all the LS adv's */ lshp = op->ospf_db.db_lshdr; - while (!ospf_print_lshdr(lshp)) { + while (ospf_print_lshdr(lshp) != -1) { ++lshp; } } @@ -427,33 +815,49 @@ ospf_decode_v2(register const struct ospfhdr *op, case OSPF_TYPE_LS_REQ: lsrp = op->ospf_lsr; while ((u_char *)lsrp < dataend) { - TCHECK(*lsrp); - - printf("\n\t %s LSA (%d), LSA-ID: %s, Advertising Router: %s", - tok2str(lsa_values,"unknown",lsrp->ls_type), - lsrp->ls_type, - ipaddr_string(&lsrp->ls_stateid), - ipaddr_string(&lsrp->ls_router)); - ++lsrp; + TCHECK(*lsrp); + + printf("\n\t Advertising Router: %s, %s LSA (%u)", + ipaddr_string(&lsrp->ls_router), + tok2str(lsa_values,"unknown",EXTRACT_32BITS(lsrp->ls_type)), + EXTRACT_32BITS(&lsrp->ls_type)); + + switch (EXTRACT_32BITS(lsrp->ls_type)) { + /* the LSA header for opaque LSAs was slightly changed */ + case LS_TYPE_OPAQUE_LL: + case LS_TYPE_OPAQUE_AL: + case LS_TYPE_OPAQUE_DW: + printf(", Opaque-Type: %s LSA (%u), Opaque-ID: %u", + tok2str(lsa_opaque_values, "unknown",lsrp->un_ls_stateid.opaque_field.opaque_type), + lsrp->un_ls_stateid.opaque_field.opaque_type, + EXTRACT_24BITS(&lsrp->un_ls_stateid.opaque_field.opaque_id)); + break; + default: + printf(", LSA-ID: %s", + ipaddr_string(&lsrp->un_ls_stateid.ls_stateid)); + break; + } + + ++lsrp; } break; case OSPF_TYPE_LS_UPDATE: lsap = op->ospf_lsu.lsu_lsa; TCHECK(op->ospf_lsu.lsu_count); - lsa_count = EXTRACT_32BITS(&op->ospf_lsu.lsu_count); - printf(", %d LSA%s",lsa_count, lsa_count > 1 ? "s" : ""); - while (lsa_count--) { - if (ospf_print_lsa(lsap)) + lsa_count_max = EXTRACT_32BITS(&op->ospf_lsu.lsu_count); + printf(", %d LSA%s",lsa_count_max, lsa_count_max > 1 ? "s" : ""); + for (lsa_count=1;lsa_count <= lsa_count_max;lsa_count++) { + printf("\n\t LSA #%u",lsa_count); + lsap = (const struct lsa *)ospf_print_lsa(lsap); + if (lsap == NULL) goto trunc; - lsap = (struct lsa *)((u_char *)lsap + - EXTRACT_16BITS(&lsap->ls_hdr.ls_length)); } break; case OSPF_TYPE_LS_ACK: lshp = op->ospf_lsa.lsa_lshdr; - while (!ospf_print_lshdr(lshp)) { + while (ospf_print_lshdr(lshp) != -1) { ++lshp; } break; @@ -469,15 +873,13 @@ trunc: void ospf_print(register const u_char *bp, register u_int length, - register const u_char *bp2) + const u_char *bp2 _U_) { register const struct ospfhdr *op; - register const struct ip *ip; register const u_char *dataend; register const char *cp; op = (struct ospfhdr *)bp; - ip = (struct ip *)bp2; /* XXX Before we do anything else, strip off the MD5 trailer */ TCHECK(op->ospf_authtype); @@ -489,8 +891,11 @@ ospf_print(register const u_char *bp, register u_int length, /* If the type is valid translate it, or just print the type */ /* value. If it's not valid, say so and return */ TCHECK(op->ospf_type); - cp = tok2str(type2str, "unknown LS-Type %d", op->ospf_type); - printf("OSPFv%d %s length: %d", op->ospf_version, cp, length); + cp = tok2str(type2str, "unknown LS-type", op->ospf_type); + printf("OSPFv%u, %s, length: %u", + op->ospf_version, + cp, + length); if (*cp == 'u') return;