]> The Tcpdump Group git mirrors - tcpdump/blobdiff - print-ospf.c
Backout CHANGES update - wrong branch
[tcpdump] / print-ospf.c
index 9eeadfc5fb2a5fb5f8d5f6eeb491711d5fbbcaeb..8a6511462e6c6b28a4383342c7864b8f6fa1b70f 100644 (file)
@@ -22,8 +22,8 @@
  */
 
 #ifndef lint
-static const char rcsid[] =
-    "@(#) $Header: /tcpdump/master/tcpdump/print-ospf.c,v 1.44 2003-10-22 17:08:45 hannes Exp $ (LBL)";
+static const char rcsid[] _U_ =
+    "@(#) $Header: /tcpdump/master/tcpdump/print-ospf.c,v 1.56.2.4 2006-12-13 08:24:27 hannes Exp $ (LBL)";
 #endif
 
 #ifdef HAVE_CONFIG_H
@@ -51,12 +51,13 @@ 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 }
 };
 
 static struct tok ospf_authtype_values[] = {
        { OSPF_AUTH_NONE,       "none" },
-       { OSPF_AUTH_NONE,       "simple" },
+       { OSPF_AUTH_SIMPLE,     "simple" },
        { OSPF_AUTH_MD5,        "MD5" },
        { 0,                    NULL }
 };
@@ -103,6 +104,7 @@ static struct tok ospf_dd_flag_values[] = {
 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 }
 };
 
@@ -126,11 +128,24 @@ static struct tok lsa_opaque_te_link_tlv_subtlv_values[] = {
        { 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_BW_CONSTRAINTS,       "Bandwidth Constraints" },
        { 0,                    NULL }
 };
 
-#define LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE_PTP        1  /* rfc3630 */
-#define LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE_MA         2  /* rfc3630 */
+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" },
@@ -138,6 +153,25 @@ static struct tok lsa_opaque_te_tlv_link_type_sub_tlv_values[] = {
        { 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
@@ -145,21 +179,30 @@ 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) {
-
-       TCHECK(lshp->ls_type);
-       TCHECK(lshp->ls_options);
+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_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),
-               EXTRACT_16BITS(&lshp->ls_length)-sizeof(struct lsa_hdr));
+               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:
@@ -187,27 +230,31 @@ ospf_print_lshdr(register const struct lsa_hdr *lshp) {
             break;
         }
 
+       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,ls_length, tlv_type, tlv_length, subtlv_type, subtlv_length, priority_level;
+       register int j, k, tlv_type, tlv_length, subtlv_type, subtlv_length, priority_level, te_class;
+       register int ls_length;
        const u_int8_t *tptr;
        int count_srlg;
         union { /* int to float conversion buffer for several subTLVs */
@@ -216,12 +263,11 @@ ospf_print_lsa(register const struct lsa *lsap)
         } bw;
 
        tptr = (u_int8_t *)lsap->lsa_un.un_unknown; /* squelch compiler warnings */
-        ls_length = EXTRACT_16BITS(&lsap->ls_hdr.ls_length)-sizeof(struct lsa_hdr);
-
-        ospf_print_lshdr(&lsap->ls_hdr);
-
-       TCHECK(lsap->ls_hdr.ls_length);
-       ls_end = (u_char *)lsap + EXTRACT_16BITS(&lsap->ls_hdr.ls_length);
+        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) {
 
@@ -264,7 +310,7 @@ ospf_print_lsa(register const struct lsa *lsap)
                        default:
                                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 *)
@@ -336,6 +382,7 @@ 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",
                    ipaddr_string(&lsap->lsa_un.un_asla.asla_mask));
@@ -400,40 +447,162 @@ ospf_print_lsa(register const struct lsa *lsap)
        case LS_TYPE_OPAQUE_DW:
 
            switch (*(&lsap->ls_hdr.un_lsa_id.opaque_field.opaque_type)) {
-           case LS_OPAQUE_TYPE_TE:
-               if (!TTEST2(*tptr, 4))
-                   goto trunc;
+            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) {
 
-               tptr = (u_int8_t *)(&lsap->lsa_un.un_te_lsa_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;
 
-               while (ls_length > 0) {
+                    }
+                    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);
-                    ls_length-=(tlv_length+4);
                     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 (!TTEST2(*tptr, 4))
-                                goto trunc;
+                        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);
-                            tlv_length-=4;
                             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);
                             
-                            if (!TTEST2(*tptr, subtlv_length))
-                                goto trunc;
+                            TCHECK2(*tptr, subtlv_length);
                             switch(subtlv_type) {
                             case LS_OPAQUE_TE_LINK_SUBTLV_ADMIN_GROUP:
                                 printf(", 0x%08x", EXTRACT_32BITS(tptr));
@@ -458,10 +627,22 @@ ospf_print_lsa(register const struct lsa *lsap)
                                 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,
+                                for (te_class = 0; te_class < 8; te_class++) {
+                                    bw.i = EXTRACT_32BITS(tptr+te_class*4);
+                                    printf("\n\t\tTE-Class %u: %.3f Mbps",
+                                           te_class,
+                                           bw.f*8/1000000 );
+                                }
+                                break;
+                            case LS_OPAQUE_TE_LINK_SUBTLV_BW_CONSTRAINTS:
+                                printf("\n\t\tBandwidth Constraints Model ID: %s (%u)",
+                                       tok2str(diffserv_te_bc_values, "unknown", *tptr),
+                                       *tptr);
+                                /* decode BCs until the subTLV ends */
+                                for (te_class = 0; te_class < (subtlv_length-4)/4; te_class++) {
+                                    bw.i = EXTRACT_32BITS(tptr+4+te_class*4);
+                                    printf("\n\t\t  Bandwidth constraint CT%u: %.3f Mbps",
+                                           te_class,
                                            bw.f*8/1000000 );
                                 }
                                 break;
@@ -508,7 +689,7 @@ ospf_print_lsa(register const struct lsa *lsap)
                             default:
                                 if (vflag <= 1) {
                                     if(!print_unknown_data(tptr,"\n\t\t",subtlv_length))
-                                        return(0);
+                                        return(ls_end);
                                 }
                                 break;
                             }
@@ -523,13 +704,18 @@ ospf_print_lsa(register const struct lsa *lsap)
                         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(0);
+                                return(ls_end);
                         }
                         break;
                     }
@@ -541,8 +727,8 @@ ospf_print_lsa(register const struct lsa *lsap)
         default:
             if (vflag <= 1) {
                 if(!print_unknown_data((u_int8_t *)lsap->lsa_un.un_unknown,
-                                       "\n\t    ", EXTRACT_16BITS(&lsap->ls_hdr.ls_length)-sizeof(struct lsa_hdr)))
-                    return(0);
+                                       "\n\t    ", ls_length))
+                    return(ls_end);
             } 
             break;
         }
@@ -550,13 +736,13 @@ ospf_print_lsa(register const struct lsa *lsap)
         /* do we want to see an additionally hexdump ? */
         if (vflag> 1)
             if(!print_unknown_data((u_int8_t *)lsap->lsa_un.un_unknown,
-                                   "\n\t    ", EXTRACT_16BITS(&lsap->ls_hdr.ls_length)-sizeof(struct lsa_hdr))) {
-                return(0);
+                                   "\n\t    ", ls_length)) {
+                return(ls_end);
             }
         
-       return (0);
+       return (ls_end);
 trunc:
-       return (1);
+       return (NULL);
 }
 
 static int
@@ -620,7 +806,7 @@ ospf_decode_v2(register const struct ospfhdr *op,
                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;
                        }
                }
@@ -663,16 +849,15 @@ ospf_decode_v2(register const struct ospfhdr *op,
                 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);
-                        if (ospf_print_lsa(lsap))
+                        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;
@@ -688,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);
@@ -709,10 +892,9 @@ ospf_print(register const u_char *bp, register u_int length,
        /* value.  If it's not valid, say so and return */
        TCHECK(op->ospf_type);
        cp = tok2str(type2str, "unknown LS-type", op->ospf_type);
-       printf("OSPFv%u, %s (%u), length: %u",
+       printf("OSPFv%u, %s, length: %u",
               op->ospf_version,
               cp,
-              op->ospf_type,
               length);
        if (*cp == 'u')
                return;
@@ -750,9 +932,8 @@ ospf_print(register const u_char *bp, register u_int length,
                        break;
 
                case OSPF_AUTH_SIMPLE:
-                       (void)fn_printn(op->ospf_authdata,
-                           sizeof(op->ospf_authdata), NULL);
-                       printf("\"");
+                        printf("\n\tSimple text password: ");
+                        safeputs(op->ospf_authdata, OSPF_AUTH_SIMPLE_LEN);
                        break;
 
                case OSPF_AUTH_MD5: