X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/fd59ca36b13d704a06beb9b4c1f2bd73a0f67dea..4c2790a43252b9cac1fe7f6b50b51c3c55d2370a:/print-ospf.c diff --git a/print-ospf.c b/print-ospf.c index c864ae99..f8ff4aea 100644 --- a/print-ospf.c +++ b/print-ospf.c @@ -23,7 +23,7 @@ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/tcpdump/print-ospf.c,v 1.62 2007-07-24 16:01:42 hannes Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/tcpdump/print-ospf.c,v 1.66 2007-10-08 07:53:21 hannes Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -44,11 +44,11 @@ static const char rcsid[] _U_ = #include "ip.h" static struct tok ospf_option_values[] = { - { OSPF_OPTION_T, "TOS" }, + { OSPF_OPTION_T, "MultiTopology" }, /* draft-ietf-ospf-mt-09 */ { OSPF_OPTION_E, "External" }, { OSPF_OPTION_MC, "Multicast" }, { OSPF_OPTION_NP, "NSSA" }, - { OSPF_OPTION_EA, "Advertise External" }, + { OSPF_OPTION_L, "LLS" }, { OSPF_OPTION_DC, "Demand Circuit" }, { OSPF_OPTION_O, "Opaque" }, { OSPF_OPTION_DN, "Up/Down" }, @@ -98,6 +98,7 @@ static struct tok ospf_dd_flag_values[] = { { OSPF_DB_INIT, "Init" }, { OSPF_DB_MORE, "More" }, { OSPF_DB_MASTER, "Master" }, + { OSPF_DB_RESYNC, "OOBResync" }, { 0, NULL } }; @@ -172,6 +173,18 @@ static struct tok lsa_opaque_ri_tlv_cap_values[] = { { 0, NULL } }; +static struct tok ospf_lls_tlv_values[] = { + { OSPF_LLS_EO, "Extended Options" }, + { OSPF_LLS_MD5, "MD5 Authentication" }, + { 0, NULL } +}; + +static struct tok ospf_lls_eo_options[] = { + { OSPF_LLS_EO_LR, "LSDB resync" }, + { OSPF_LLS_EO_RS, "Restart" }, + { 0, NULL } +}; + static char tstr[] = " [|ospf2]"; #ifdef WIN32 @@ -181,9 +194,10 @@ static char tstr[] = " [|ospf2]"; static int ospf_print_lshdr(const struct lsa_hdr *); static const u_char *ospf_print_lsa(const struct lsa *); static int ospf_decode_v2(const struct ospfhdr *, const u_char *); +static int ospf_decode_lls(const struct ospfhdr *, register u_int); int -ospf_print_grace_lsa (u_int8_t *tptr, u_int ls_length) { +ospf_print_grace_lsa (const u_int8_t *tptr, u_int ls_length) { u_int tlv_type, tlv_length; @@ -265,7 +279,7 @@ trunc: } int -ospf_print_te_lsa (u_int8_t *tptr, u_int ls_length) { +ospf_print_te_lsa (const u_int8_t *tptr, u_int ls_length) { u_int tlv_type, tlv_length, subtlv_type, subtlv_length; u_int priority_level, te_class, count_srlg; @@ -457,7 +471,7 @@ ospf_print_lshdr(register const struct lsa_hdr *lshp) 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, + printf("\n\t Bogus length %u < header (%lu)", ls_length, (unsigned long)sizeof(struct lsa_hdr)); return(-1); } @@ -505,6 +519,41 @@ trunc: return (-1); } +/* draft-ietf-ospf-mt-09 */ +static struct tok ospf_topology_values[] = { + { 0, "default " }, + { 1, "multicast " }, + { 2, "management " }, + { 0, NULL } +}; + +/* + * Print all the per-topology metrics. + */ +static void +ospf_print_tos_metrics(const union un_tos *tos) +{ + int metric_count; + int toscount; + + toscount = tos->link.link_tos_count+1; + metric_count = 0; + + /* + * All but the first metric contain a valid topology id. + */ + while (toscount) { + printf("\n\t\ttopology %s(%u), metric %u", + tok2str(ospf_topology_values, "", + metric_count ? tos->metrics.tos_type : 0), + metric_count ? tos->metrics.tos_type : 0, + EXTRACT_16BITS(&tos->metrics.tos_metric)); + metric_count++; + tos++; + toscount--; + } +} + /* * 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 @@ -515,12 +564,11 @@ ospf_print_lsa(register const struct lsa *lsap) { 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, tlv_type, tlv_length; + register int j, tlv_type, tlv_length, topology; register int ls_length; const u_int8_t *tptr; @@ -543,7 +591,7 @@ ospf_print_lsa(register const struct lsa *lsap) rlp = lsap->lsa_un.un_rla.rla_link; while (j--) { TCHECK(*rlp); - switch (rlp->link_type) { + switch (rlp->un_tos.link.link_type) { case RLA_TYPE_VIRTUAL: printf("\n\t Virtual Link: Neighbor Router-ID: %s, Interface Address: %s", @@ -571,20 +619,14 @@ ospf_print_lsa(register const struct lsa *lsap) default: printf("\n\t Unknown Router Link Type (%u)", - rlp->link_type); + rlp->un_tos.link.link_type); return (ls_end); } - printf(", tos 0, metric: %d", EXTRACT_16BITS(&rlp->link_tos0metric)); - tosp = (struct tos_metric *) - ((sizeof rlp->link_tos0metric) + (u_char *) rlp); - for (k = 0; k < (int) rlp->link_toscount; ++k, ++tosp) { - TCHECK(*tosp); - printf(", tos %d, metric: %d", - tosp->tos_type, - EXTRACT_16BITS(&tosp->tos_metric)); - } + + ospf_print_tos_metrics(&rlp->un_tos); + rlp = (struct rlalink *)((u_char *)(rlp + 1) + - ((rlp->link_toscount) * sizeof(*tosp))); + ((rlp->un_tos.link.link_tos_count) * sizeof(union un_tos))); } break; @@ -606,19 +648,16 @@ ospf_print_lsa(register const struct lsa *lsap) 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; - /* suppress tos if its not supported */ - if(!((lsap->ls_hdr.ls_options)&OSPF_OPTION_T)) { - printf(", metric %u", EXTRACT_32BITS(lp)&SLA_MASK_METRIC); - break; - } while ((u_char *)lp < ls_end) { register u_int32_t ul; TCHECK(*lp); ul = EXTRACT_32BITS(lp); - printf(", tos %d metric %d", - (ul & SLA_MASK_TOS) >> SLA_SHIFT_TOS, - ul & SLA_MASK_METRIC); + topology = (ul & SLA_MASK_TOS) >> SLA_SHIFT_TOS; + printf("\n\t\ttopology %s(%u) metric %d", + tok2str(ospf_topology_values, "", topology), + topology, + ul & SLA_MASK_METRIC); ++lp; } break; @@ -626,19 +665,16 @@ ospf_print_lsa(register const struct lsa *lsap) case LS_TYPE_SUM_ABR: TCHECK(lsap->lsa_un.un_sla.sla_tosmetric); lp = lsap->lsa_un.un_sla.sla_tosmetric; - /* suppress tos if its not supported */ - if(!((lsap->ls_hdr.ls_options)&OSPF_OPTION_T)) { - printf(", metric: %u", EXTRACT_32BITS(lp)&SLA_MASK_METRIC); - break; - } while ((u_char *)lp < ls_end) { register u_int32_t ul; TCHECK(*lp); ul = EXTRACT_32BITS(lp); - printf(", tos %d metric %d", - (ul & SLA_MASK_TOS) >> SLA_SHIFT_TOS, - ul & SLA_MASK_METRIC); + topology = (ul & SLA_MASK_TOS) >> SLA_SHIFT_TOS; + printf("\n\t\ttopology %s(%u) metric %d", + tok2str(ospf_topology_values, "", topology), + topology, + ul & SLA_MASK_METRIC); ++lp; } break; @@ -656,9 +692,11 @@ ospf_print_lsa(register const struct lsa *lsap) TCHECK(almp->asla_tosmetric); ul = EXTRACT_32BITS(&almp->asla_tosmetric); - printf(", type %d, tos %d metric:", - (ul & ASLA_FLAG_EXTERNAL) ? 2 : 1, - (ul & ASLA_MASK_TOS) >> ASLA_SHIFT_TOS); + topology = ((ul & ASLA_MASK_TOS) >> ASLA_SHIFT_TOS); + printf("\n\t\ttopology %s(%u), type %d, metric", + tok2str(ospf_topology_values, "", topology), + topology, + (ul & ASLA_FLAG_EXTERNAL) ? 2 : 1); if ((ul & ASLA_MASK_METRIC)==0xffffff) printf(" infinite"); else @@ -733,7 +771,6 @@ ospf_print_lsa(register const struct lsa *lsap) ls_length); return(ls_end); } - ls_length-=tlv_length; TCHECK2(*tptr, tlv_length); switch(tlv_type) { @@ -754,6 +791,7 @@ ospf_print_lsa(register const struct lsa *lsap) } tptr+=tlv_length; + ls_length-=tlv_length; } break; @@ -793,6 +831,98 @@ trunc: return (NULL); } +static int +ospf_decode_lls(register const struct ospfhdr *op, + register u_int length) +{ + register const u_char *dptr; + register const u_char *dataend; + register u_int length2; + register u_int16_t lls_type, lls_len; + register u_int32_t lls_flags; + + switch (op->ospf_type) { + + case OSPF_TYPE_HELLO: + if (!(op->ospf_hello.hello_options & OSPF_OPTION_L)) + return (0); + break; + + case OSPF_TYPE_DD: + if (!(op->ospf_db.db_options & OSPF_OPTION_L)) + return (0); + break; + + default: + return (0); + } + + /* dig deeper if LLS data is available; see RFC4813 */ + length2 = EXTRACT_16BITS(&op->ospf_len); + dptr = (u_char *)op + length2; + dataend = (u_char *)op + length; + + if (EXTRACT_16BITS(&op->ospf_authtype) == OSPF_AUTH_MD5) { + dptr = dptr + op->ospf_authdata[3]; + length2 += op->ospf_authdata[3]; + } + if (length2 >= length) { + printf("\n\t[LLS truncated]"); + return (1); + } + TCHECK2(*dptr, 2); + printf("\n\t LLS: checksum: 0x%04x", (u_int)EXTRACT_16BITS(dptr)); + + dptr += 2; + TCHECK2(*dptr, 2); + length2 = EXTRACT_16BITS(dptr); + printf(", length: %u", length2); + + dptr += 2; + TCHECK(*dptr); + while (dptr < dataend) { + TCHECK2(*dptr, 2); + lls_type = EXTRACT_16BITS(dptr); + printf("\n\t %s (%u)", + tok2str(ospf_lls_tlv_values,"Unknown TLV",lls_type), + lls_type); + dptr += 2; + TCHECK2(*dptr, 2); + lls_len = EXTRACT_16BITS(dptr); + printf(", length: %u", lls_len); + dptr += 2; + switch (lls_type) { + + case OSPF_LLS_EO: + if (lls_len != 4) { + printf(" [should be 4]"); + lls_len = 4; + } + TCHECK2(*dptr, 4); + lls_flags = EXTRACT_32BITS(dptr); + printf("\n\t Options: 0x%08x [%s]", lls_flags, + bittok2str(ospf_lls_eo_options,"?",lls_flags)); + + break; + + case OSPF_LLS_MD5: + if (lls_len != 20) { + printf(" [should be 20]"); + lls_len = 20; + } + TCHECK2(*dptr, 4); + printf("\n\t Sequence number: 0x%08x", EXTRACT_32BITS(dptr)); + break; + } + + dptr += lls_len; + } + + return (0); +trunc: + return (1); +} + static int ospf_decode_v2(register const struct ospfhdr *op, register const u_char *dataend) @@ -850,10 +980,16 @@ ospf_decode_v2(register const struct ospfhdr *op, TCHECK(op->ospf_db.db_flags); printf(", DD Flags [%s]", bittok2str(ospf_dd_flag_values,"none",op->ospf_db.db_flags)); + TCHECK(op->ospf_db.db_ifmtu); + if (op->ospf_db.db_ifmtu) { + printf(", MTU: %u", EXTRACT_16BITS(&op->ospf_db.db_ifmtu)); + } + TCHECK(op->ospf_db.db_seq); + printf(", Sequence: 0x%08x", EXTRACT_32BITS(&op->ospf_db.db_seq)); /* Print all the LS adv's */ lshp = op->ospf_db.db_lshdr; - while (ospf_print_lshdr(lshp) != -1) { + while (((u_char *)lshp < dataend) && ospf_print_lshdr(lshp) != -1) { ++lshp; } break; @@ -892,7 +1028,7 @@ ospf_decode_v2(register const struct ospfhdr *op, lsap = op->ospf_lsu.lsu_lsa; TCHECK(op->ospf_lsu.lsu_count); lsa_count_max = EXTRACT_32BITS(&op->ospf_lsu.lsu_count); - printf(", %d LSA%s",lsa_count_max, lsa_count_max > 1 ? "s" : ""); + printf(", %d LSA%s",lsa_count_max, PLURAL_SUFFIX(lsa_count_max)); 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); @@ -951,9 +1087,13 @@ ospf_print(register const u_char *bp, register u_int length, TCHECK(op->ospf_len); if (length != EXTRACT_16BITS(&op->ospf_len)) { printf(" [len %d]", EXTRACT_16BITS(&op->ospf_len)); - return; } - dataend = bp + length; + + if (length > EXTRACT_16BITS(&op->ospf_len)) { + dataend = bp + EXTRACT_16BITS(&op->ospf_len); + } else { + dataend = bp + length; + } TCHECK(op->ospf_routerid); printf("\n\tRouter-ID %s", ipaddr_string(&op->ospf_routerid)); @@ -1000,6 +1140,10 @@ ospf_print(register const u_char *bp, register u_int length, /* ospf version 2 */ if (ospf_decode_v2(op, dataend)) goto trunc; + if (length > EXTRACT_16BITS(&op->ospf_len)) { + if (ospf_decode_lls(op, length)) + goto trunc; + } break; default: