]> The Tcpdump Group git mirrors - tcpdump/blobdiff - print-rsvp.c
Force -t on in TESTonce.
[tcpdump] / print-rsvp.c
index 06cd215f1d5b615701eec9c181d9f525e5b1ed92..be3dfa30b3626886dcc28166cf677e6563066536 100644 (file)
  * Original code by Hannes Gredler ([email protected])
  */
 
+/* \summary: Resource ReSerVation Protocol (RSVP) printer */
+
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
 
-#include <tcpdump-stdinc.h>
+#include <netdissect-stdinc.h>
 
 #include "netdissect.h"
 #include "extract.h"
@@ -29,6 +31,8 @@
 #include "af.h"
 #include "signature.h"
 
+static const char tstr[] = " [|rsvp]";
+
 /*
  * RFC 2205 common header
  *
@@ -81,7 +85,7 @@ struct rsvp_object_header {
 #define        RSVP_MSGTYPE_PATHTEAR   5
 #define        RSVP_MSGTYPE_RESVTEAR   6
 #define        RSVP_MSGTYPE_RESVCONF   7
-#define RSVP_MSGTYPE_AGGREGATE  12
+#define RSVP_MSGTYPE_BUNDLE     12
 #define RSVP_MSGTYPE_ACK        13
 #define RSVP_MSGTYPE_HELLO_OLD  14      /* ancient Hellos */
 #define RSVP_MSGTYPE_SREFRESH   15
@@ -95,7 +99,7 @@ static const struct tok rsvp_msg_type_values[] = {
     { RSVP_MSGTYPE_PATHTEAR,   "PathTear" },
     { RSVP_MSGTYPE_RESVTEAR,   "ResvTear" },
     { RSVP_MSGTYPE_RESVCONF,   "ResvConf" },
-    { RSVP_MSGTYPE_AGGREGATE,  "Aggregate" },
+    { RSVP_MSGTYPE_BUNDLE,     "Bundle" },
     { RSVP_MSGTYPE_ACK,                "Acknowledgement" },
     { RSVP_MSGTYPE_HELLO_OLD,  "Hello (Old)" },
     { RSVP_MSGTYPE_SREFRESH,   "Refresh" },
@@ -496,6 +500,7 @@ rsvp_intserv_print(netdissect_options *ndo,
     if (obj_tlen < 4)
         return 0;
     parameter_id = *(tptr);
+    ND_TCHECK2(*(tptr + 2), 2);
     parameter_length = EXTRACT_16BITS(tptr+2)<<2; /* convert wordcount to bytecount */
 
     ND_PRINT((ndo, "\n\t      Parameter ID: %s (%u), length: %u, Flags: [0x%02x]",
@@ -516,8 +521,10 @@ rsvp_intserv_print(netdissect_options *ndo,
         * |        IS hop cnt (32-bit unsigned integer)                   |
         * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
         */
-        if (parameter_length == 4)
+        if (parameter_length == 4) {
+           ND_TCHECK2(*(tptr + 4), 4);
             ND_PRINT((ndo, "\n\t\tIS hop count: %u", EXTRACT_32BITS(tptr + 4)));
+        }
         break;
 
     case 6:
@@ -529,6 +536,7 @@ rsvp_intserv_print(netdissect_options *ndo,
         * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
         */
         if (parameter_length == 4) {
+           ND_TCHECK2(*(tptr + 4), 4);
             bw.i = EXTRACT_32BITS(tptr+4);
             ND_PRINT((ndo, "\n\t\tPath b/w estimate: %.10g Mbps", bw.f / 125000));
         }
@@ -543,6 +551,7 @@ rsvp_intserv_print(netdissect_options *ndo,
         * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
         */
         if (parameter_length == 4) {
+           ND_TCHECK2(*(tptr + 4), 4);
             ND_PRINT((ndo, "\n\t\tMinimum path latency: "));
             if (EXTRACT_32BITS(tptr+4) == 0xffffffff)
                 ND_PRINT((ndo, "don't care"));
@@ -560,8 +569,10 @@ rsvp_intserv_print(netdissect_options *ndo,
         * |      Composed MTU (32-bit unsigned integer)                   |
         * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
         */
-        if (parameter_length == 4)
+        if (parameter_length == 4) {
+           ND_TCHECK2(*(tptr + 4), 4);
             ND_PRINT((ndo, "\n\t\tComposed MTU: %u bytes", EXTRACT_32BITS(tptr + 4)));
+        }
         break;
     case 127:
        /*
@@ -581,6 +592,7 @@ rsvp_intserv_print(netdissect_options *ndo,
         */
 
         if (parameter_length == 20) {
+           ND_TCHECK2(*(tptr + 4), 20);
             bw.i = EXTRACT_32BITS(tptr+4);
             ND_PRINT((ndo, "\n\t\tToken Bucket Rate: %.10g Mbps", bw.f / 125000));
             bw.i = EXTRACT_32BITS(tptr+8);
@@ -604,6 +616,7 @@ rsvp_intserv_print(netdissect_options *ndo,
         */
 
         if (parameter_length == 8) {
+           ND_TCHECK2(*(tptr + 4), 8);
             bw.i = EXTRACT_32BITS(tptr+4);
             ND_PRINT((ndo, "\n\t\tRate: %.10g Mbps", bw.f / 125000));
             ND_PRINT((ndo, "\n\t\tSlack Term: %u", EXTRACT_32BITS(tptr + 8)));
@@ -614,8 +627,10 @@ rsvp_intserv_print(netdissect_options *ndo,
     case 134:
     case 135:
     case 136:
-        if (parameter_length == 4)
+        if (parameter_length == 4) {
+           ND_TCHECK2(*(tptr + 4), 4);
             ND_PRINT((ndo, "\n\t\tValue: %u", EXTRACT_32BITS(tptr + 4)));
+        }
         break;
 
     default:
@@ -623,20 +638,29 @@ rsvp_intserv_print(netdissect_options *ndo,
             print_unknown_data(ndo, tptr + 4, "\n\t\t", parameter_length);
     }
     return (parameter_length+4); /* header length 4 bytes */
+
+trunc:
+    ND_PRINT((ndo, "%s", tstr));
+    return 0;
+}
+
+/*
+ * Clear checksum prior to signature verification.
+ */
+static void
+rsvp_clear_checksum(void *header)
+{
+    struct rsvp_common_header *rsvp_com_header = (struct rsvp_common_header *) header;
+
+    rsvp_com_header->checksum[0] = 0;
+    rsvp_com_header->checksum[1] = 0;
 }
 
 static int
 rsvp_obj_print(netdissect_options *ndo,
-                const u_char *pptr
-#ifndef HAVE_LIBCRYPTO
-_U_
-#endif
-, u_int plen
-#ifndef HAVE_LIBCRYPTO
-_U_
-#endif
-, const u_char *tptr,
-                const char *ident, u_int tlen)
+               const u_char *pptr, u_int plen, const u_char *tptr,
+               const char *ident, u_int tlen,
+               const struct rsvp_common_header *rsvp_com_header)
 {
     const struct rsvp_object_header *rsvp_obj_header;
     const u_char *obj_tptr;
@@ -722,7 +746,6 @@ _U_
                 obj_tlen-=8;
                 obj_tptr+=8;
                 break;
-#ifdef INET6
             case RSVP_CTYPE_IPV6:
                 if (obj_tlen < 20)
                     return -1;
@@ -761,7 +784,6 @@ _U_
                 obj_tlen-=26;
                 obj_tptr+=26;
                 break;
-#endif
             case RSVP_CTYPE_13: /* IPv4 p2mp LSP Tunnel */
                 if (obj_tlen < 12)
                     return -1;
@@ -801,7 +823,6 @@ _U_
                 obj_tlen-=sizeof(struct in_addr);
                 obj_tptr+=sizeof(struct in_addr);
                 break;
-#ifdef INET6
             case RSVP_CTYPE_IPV6:
                 if (obj_tlen < sizeof(struct in6_addr))
                     return -1;
@@ -811,7 +832,6 @@ _U_
                 obj_tlen-=sizeof(struct in6_addr);
                 obj_tptr+=sizeof(struct in6_addr);
                 break;
-#endif
             default:
                 hexdump=TRUE;
             }
@@ -828,7 +848,6 @@ _U_
                 obj_tlen-=sizeof(struct in_addr);
                 obj_tptr+=sizeof(struct in_addr);
                 break;
-#ifdef INET6
             case RSVP_CTYPE_IPV6:
                 if (obj_tlen < sizeof(struct in6_addr))
                     return-1;
@@ -838,7 +857,6 @@ _U_
                 obj_tlen-=sizeof(struct in6_addr);
                 obj_tptr+=sizeof(struct in6_addr);
                 break;
-#endif
             default:
                 hexdump=TRUE;
             }
@@ -913,7 +931,6 @@ _U_
                 obj_tlen-=8;
                 obj_tptr+=8;
                 break;
-#ifdef INET6
             case RSVP_CTYPE_IPV6:
                 if (obj_tlen < 20)
                     return-1;
@@ -938,7 +955,6 @@ _U_
                 obj_tlen-=40;
                 obj_tptr+=40;
                 break;
-#endif
             case RSVP_CTYPE_TUNNEL_IPV4:
                 if (obj_tlen < 8)
                     return-1;
@@ -1050,20 +1066,37 @@ _U_
             switch(rsvp_obj_ctype) {
             case RSVP_CTYPE_IPV4:
                 while(obj_tlen >= 4 ) {
+                   u_char length;
+
+                   ND_TCHECK2(*obj_tptr, 4);
+                   length = *(obj_tptr + 1);
                     ND_PRINT((ndo, "%s  Subobject Type: %s, length %u",
                            ident,
                            tok2str(rsvp_obj_xro_values,
                                    "Unknown %u",
                                    RSVP_OBJ_XRO_MASK_SUBOBJ(*obj_tptr)),
-                           *(obj_tptr + 1)));
+                           length));
 
-                    if (*(obj_tptr+1) == 0) { /* prevent infinite loops */
+                    if (length == 0) { /* prevent infinite loops */
                         ND_PRINT((ndo, "%s  ERROR: zero length ERO subtype", ident));
                         break;
                     }
 
                     switch(RSVP_OBJ_XRO_MASK_SUBOBJ(*obj_tptr)) {
+                   u_char prefix_length;
+
                     case RSVP_OBJ_XRO_IPV4:
+                       if (length != 8) {
+                               ND_PRINT((ndo, " ERROR: length != 8"));
+                               goto invalid;
+                       }
+                       ND_TCHECK2(*obj_tptr, 8);
+                       prefix_length = *(obj_tptr+6);
+                       if (prefix_length != 32) {
+                               ND_PRINT((ndo, " ERROR: Prefix length %u != 32",
+                                         prefix_length));
+                               goto invalid;
+                       }
                         ND_PRINT((ndo, ", %s, %s/%u, Flags: [%s]",
                                RSVP_OBJ_XRO_MASK_LOOSE(*obj_tptr) ? "Loose" : "Strict",
                                ipaddr_string(ndo, obj_tptr+2),
@@ -1073,6 +1106,11 @@ _U_
                                    *(obj_tptr + 7)))); /* rfc3209 says that this field is rsvd. */
                     break;
                     case RSVP_OBJ_XRO_LABEL:
+                       if (length != 8) {
+                               ND_PRINT((ndo, " ERROR: length != 8"));
+                               goto invalid;
+                       }
+                       ND_TCHECK2(*obj_tptr, 8);
                         ND_PRINT((ndo, ", Flags: [%s] (%#x), Class-Type: %s (%u), %u",
                                bittok2str(rsvp_obj_rro_label_flag_values,
                                    "none",
@@ -1178,6 +1216,9 @@ _U_
                            tok2str(af_values, "Unknown", af), af,
                            subobj_len));
 
+                    if(subobj_len == 0)
+                        goto invalid;
+
                     switch(subobj_type) {
                     case RSVP_GEN_UNI_SUBOBJ_SOURCE_TNA_ADDRESS:
                     case RSVP_GEN_UNI_SUBOBJ_DESTINATION_TNA_ADDRESS:
@@ -1189,14 +1230,12 @@ _U_
                             ND_PRINT((ndo, "%s    UNI IPv4 TNA address: %s",
                                    ident, ipaddr_string(ndo, obj_tptr + 4)));
                             break;
-#ifdef INET6
                         case AFNUM_INET6:
                             if (subobj_len < 20)
                                 return -1;
                             ND_PRINT((ndo, "%s    UNI IPv6 TNA address: %s",
                                    ident, ip6addr_string(ndo, obj_tptr + 4)));
                             break;
-#endif
                         case AFNUM_NSAP:
                             if (subobj_len) {
                                 /* unless we have a TLV parser lets just hexdump */
@@ -1270,7 +1309,6 @@ _U_
                 if (obj_tlen)
                     hexdump=TRUE; /* unless we have a TLV parser lets just hexdump */
                 break;
-#ifdef INET6
             case RSVP_CTYPE_4: /* fall through - FIXME add TLV parser */
             case RSVP_CTYPE_IPV6:
                 if (obj_tlen < 20)
@@ -1283,7 +1321,6 @@ _U_
                 obj_tptr+=20;
                 hexdump=TRUE; /* unless we have a TLV parser lets just hexdump */
                 break;
-#endif
             default:
                 hexdump=TRUE;
             }
@@ -1359,7 +1396,6 @@ _U_
                 obj_tlen-=8;
                 obj_tptr+=8;
                 break;
-#ifdef INET6
             case RSVP_CTYPE_IPV6:
                 if (obj_tlen < 20)
                     return-1;
@@ -1404,7 +1440,6 @@ _U_
                 obj_tlen-=40;
                 obj_tptr+=40;
                 break;
-#endif
             case RSVP_CTYPE_TUNNEL_IPV4:
                 if (obj_tlen < 8)
                     return-1;
@@ -1546,7 +1581,6 @@ _U_
                 obj_tlen-=8;
                 obj_tptr+=8;
                 break;
-#ifdef INET6
             case RSVP_CTYPE_4: /* fall through - FIXME add TLV parser */
             case RSVP_CTYPE_IPV6:
                 if (obj_tlen < 20)
@@ -1573,7 +1607,6 @@ _U_
                 obj_tlen-=20;
                 obj_tptr+=20;
                 break;
-#endif
             default:
                 hexdump=TRUE;
             }
@@ -1663,12 +1696,10 @@ _U_
                        EXTRACT_32BITS(obj_ptr.rsvp_obj_integrity->digest+8),
                        EXTRACT_32BITS(obj_ptr.rsvp_obj_integrity->digest + 12)));
 
-#ifdef HAVE_LIBCRYPTO
-                sigcheck = signature_verify(ndo, pptr, plen, (unsigned char *)obj_ptr.\
-                                             rsvp_obj_integrity->digest);
-#else
-                sigcheck = CANT_CHECK_SIGNATURE;
-#endif
+                sigcheck = signature_verify(ndo, pptr, plen,
+                                            obj_ptr.rsvp_obj_integrity->digest,
+                                            rsvp_clear_checksum,
+                                            rsvp_com_header);
                 ND_PRINT((ndo, " (%s)", tok2str(signature_check_values, "Unknown", sigcheck)));
 
                 obj_tlen+=sizeof(struct rsvp_obj_integrity_t);
@@ -1749,7 +1780,6 @@ _U_
                 obj_tlen-=4;
                 obj_tptr+=4;
                 break;
-#ifdef INET6
             case RSVP_CTYPE_IPV6:
                 if (obj_tlen < 16)
                     return-1;
@@ -1759,7 +1789,6 @@ _U_
                 obj_tlen-=16;
                 obj_tptr+=16;
                 break;
-#endif
             default:
                 hexdump=TRUE;
             }
@@ -1787,8 +1816,12 @@ _U_
         tlen-=rsvp_obj_len;
     }
     return 0;
+invalid:
+    ND_PRINT((ndo, "%s", istr));
+    return -1;
 trunc:
-    ND_PRINT((ndo, "\n\t\t packet exceeded snapshot"));
+    ND_PRINT((ndo, "\n\t\t"));
+    ND_PRINT((ndo, "%s", tstr));
     return -1;
 }
 
@@ -1796,13 +1829,13 @@ void
 rsvp_print(netdissect_options *ndo,
            register const u_char *pptr, register u_int len)
 {
-    struct rsvp_common_header *rsvp_com_header;
-    const u_char *tptr,*subtptr;
-    u_short plen, tlen, subtlen;
+    const struct rsvp_common_header *rsvp_com_header;
+    const u_char *tptr;
+    u_short plen, tlen;
 
     tptr=pptr;
 
-    rsvp_com_header = (struct rsvp_common_header *)pptr;
+    rsvp_com_header = (const struct rsvp_common_header *)pptr;
     ND_TCHECK(*rsvp_com_header);
 
     /*
@@ -1836,12 +1869,6 @@ rsvp_print(netdissect_options *ndo,
            rsvp_com_header->ttl,
            EXTRACT_16BITS(rsvp_com_header->checksum)));
 
-    /*
-     * Clear checksum prior to signature verification.
-     */
-    rsvp_com_header->checksum[0] = 0;
-    rsvp_com_header->checksum[1] = 0;
-
     if (tlen < sizeof(const struct rsvp_common_header)) {
         ND_PRINT((ndo, "ERROR: common header too short %u < %lu", tlen,
                (unsigned long)sizeof(const struct rsvp_common_header)));
@@ -1853,10 +1880,19 @@ rsvp_print(netdissect_options *ndo,
 
     switch(rsvp_com_header->msg_type) {
 
-    case RSVP_MSGTYPE_AGGREGATE:
+    case RSVP_MSGTYPE_BUNDLE:
+        /*
+         * Process each submessage in the bundle message.
+         * Bundle messages may not contain bundle submessages, so we don't
+         * need to handle bundle submessages specially.
+         */
         while(tlen > 0) {
-            subtptr=tptr;
-            rsvp_com_header = (struct rsvp_common_header *)subtptr;
+            const u_char *subpptr=tptr, *subtptr;
+            u_short subplen, subtlen;
+
+            subtptr=subpptr;
+
+            rsvp_com_header = (const struct rsvp_common_header *)subpptr;
             ND_TCHECK(*rsvp_com_header);
 
             /*
@@ -1867,7 +1903,8 @@ rsvp_print(netdissect_options *ndo,
                        RSVP_EXTRACT_VERSION(rsvp_com_header->version_flags)));
                 return;
             }
-            subtlen=EXTRACT_16BITS(rsvp_com_header->length);
+
+            subplen = subtlen = EXTRACT_16BITS(rsvp_com_header->length);
 
             ND_PRINT((ndo, "\n\t  RSVPv%u %s Message (%u), Flags: [%s], length: %u, ttl: %u, checksum: 0x%04x",
                    RSVP_EXTRACT_VERSION(rsvp_com_header->version_flags),
@@ -1878,12 +1915,6 @@ rsvp_print(netdissect_options *ndo,
                    rsvp_com_header->ttl,
                    EXTRACT_16BITS(rsvp_com_header->checksum)));
 
-            /*
-             * Clear checksum prior to signature verification.
-             */
-            rsvp_com_header->checksum[0] = 0;
-            rsvp_com_header->checksum[1] = 0;
-
             if (subtlen < sizeof(const struct rsvp_common_header)) {
                 ND_PRINT((ndo, "ERROR: common header too short %u < %lu", subtlen,
                        (unsigned long)sizeof(const struct rsvp_common_header)));
@@ -1899,7 +1930,10 @@ rsvp_print(netdissect_options *ndo,
             subtptr+=sizeof(const struct rsvp_common_header);
             subtlen-=sizeof(const struct rsvp_common_header);
 
-            if (rsvp_obj_print(ndo, pptr, plen, subtptr, "\n\t    ", subtlen) == -1)
+            /*
+             * Print all objects in the submessage.
+             */
+            if (rsvp_obj_print(ndo, subpptr, subplen, subtptr, "\n\t    ", subtlen, rsvp_com_header) == -1)
                 return;
 
             tptr+=subtlen+sizeof(const struct rsvp_common_header);
@@ -1919,7 +1953,10 @@ rsvp_print(netdissect_options *ndo,
     case RSVP_MSGTYPE_HELLO:
     case RSVP_MSGTYPE_ACK:
     case RSVP_MSGTYPE_SREFRESH:
-        if (rsvp_obj_print(ndo, pptr, plen, tptr, "\n\t  ", tlen) == -1)
+        /*
+         * Print all objects in the message.
+         */
+        if (rsvp_obj_print(ndo, pptr, plen, tptr, "\n\t  ", tlen, rsvp_com_header) == -1)
             return;
         break;
 
@@ -1930,5 +1967,6 @@ rsvp_print(netdissect_options *ndo,
 
     return;
 trunc:
-    ND_PRINT((ndo, "\n\t\t packet exceeded snapshot"));
+    ND_PRINT((ndo, "\n\t\t"));
+    ND_PRINT((ndo, "%s", tstr));
 }