]> The Tcpdump Group git mirrors - tcpdump/blobdiff - print-olsr.c
C compilers can, and some do, optimize away pointer underflow checks.
[tcpdump] / print-olsr.c
index 07a04b537738431bfbeefd4a5ccd2b8da6b9f6cf..733780f233e3194ac6dbe6489278ab1eb7f07c67 100644 (file)
@@ -181,7 +181,7 @@ struct olsr_lq_neighbor6 {
 /*
  * print a neighbor list with LQ extensions.
  */
-static void
+static int
 olsr_print_lq_neighbor4 (const u_char *msg_data, u_int hello_len)
 {
     struct olsr_lq_neighbor4 *lq_neighbor;
@@ -189,6 +189,8 @@ olsr_print_lq_neighbor4 (const u_char *msg_data, u_int hello_len)
     while (hello_len >= sizeof(struct olsr_lq_neighbor4)) {
 
         lq_neighbor = (struct olsr_lq_neighbor4 *)msg_data;
+        if (!TTEST(*lq_neighbor))
+            return (-1);
 
         printf("\n\t      neighbor %s, link-quality %.2lf%%"
                ", neighbor-link-quality %.2lf%%",
@@ -199,10 +201,11 @@ olsr_print_lq_neighbor4 (const u_char *msg_data, u_int hello_len)
         msg_data += sizeof(struct olsr_lq_neighbor4);
         hello_len -= sizeof(struct olsr_lq_neighbor4);
     }
+    return (0);
 }
 
 #if INET6
-static void
+static int
 olsr_print_lq_neighbor6 (const u_char *msg_data, u_int hello_len)
 {
     struct olsr_lq_neighbor6 *lq_neighbor;
@@ -210,6 +213,8 @@ olsr_print_lq_neighbor6 (const u_char *msg_data, u_int hello_len)
     while (hello_len >= sizeof(struct olsr_lq_neighbor6)) {
 
         lq_neighbor = (struct olsr_lq_neighbor6 *)msg_data;
+        if (!TTEST(*lq_neighbor))
+            return (-1);
 
         printf("\n\t      neighbor %s, link-quality %.2lf%%"
                ", neighbor-link-quality %.2lf%%",
@@ -220,13 +225,14 @@ olsr_print_lq_neighbor6 (const u_char *msg_data, u_int hello_len)
         msg_data += sizeof(struct olsr_lq_neighbor6);
         hello_len -= sizeof(struct olsr_lq_neighbor6);
     }
+    return (0);
 }
 #endif /* INET6 */
 
 /*
  * print a neighbor list.
  */
-static void
+static int
 olsr_print_neighbor (const u_char *msg_data, u_int hello_len)
 {
     int neighbor;
@@ -236,6 +242,8 @@ olsr_print_neighbor (const u_char *msg_data, u_int hello_len)
 
     while (hello_len >= sizeof(struct in_addr)) {
 
+        if (!TTEST2(*msg_data, sizeof(struct in_addr)))
+            return (-1);
         /* print 4 neighbors per line */
 
         printf("%s%s", ipaddr_string(msg_data),
@@ -244,6 +252,7 @@ olsr_print_neighbor (const u_char *msg_data, u_int hello_len)
         msg_data += sizeof(struct in_addr);
         hello_len -= sizeof(struct in_addr);
     }
+    return (0);
 }
 
 
@@ -262,6 +271,7 @@ olsr_print (const u_char *pptr, u_int length, int is_ipv6)
 
     u_int msg_type, msg_len, msg_tlen, hello_len;
     u_int16_t name_entry_type, name_entry_len;
+    u_int name_entry_padding;
     u_int8_t link_type, neighbor_type;
     const u_char *tptr, *msg_data;
 
@@ -327,6 +337,9 @@ olsr_print (const u_char *pptr, u_int length, int is_ipv6)
                     ME_TO_DOUBLE(msgptr.v6->vtime),
                     EXTRACT_16BITS(msgptr.v6->msg_seq),
                     msg_len, (msg_len_valid == 0) ? " (invalid)" : "");
+            if (!msg_len_valid) {
+                return;
+            }
 
             msg_tlen = msg_len - sizeof(struct olsr_msg6);
             msg_data = tptr + sizeof(struct olsr_msg6);
@@ -355,6 +368,9 @@ olsr_print (const u_char *pptr, u_int length, int is_ipv6)
                     ME_TO_DOUBLE(msgptr.v4->vtime),
                     EXTRACT_16BITS(msgptr.v4->msg_seq),
                     msg_len, (msg_len_valid == 0) ? " (invalid)" : "");
+            if (!msg_len_valid) {
+                return;
+            }
 
             msg_tlen = msg_len - sizeof(struct olsr_msg4);
             msg_data = tptr + sizeof(struct olsr_msg4);
@@ -363,8 +379,9 @@ olsr_print (const u_char *pptr, u_int length, int is_ipv6)
         switch (msg_type) {
         case OLSR_HELLO_MSG:
         case OLSR_HELLO_LQ_MSG:
-            if (!TTEST2(*msg_data, sizeof(struct olsr_hello)))
+            if (msg_tlen < sizeof(struct olsr_hello))
                 goto trunc;
+            TCHECK2(*msg_data, sizeof(struct olsr_hello));
 
             ptr.hello = (struct olsr_hello *)msg_data;
             printf("\n\t  hello-time %.3lfs, MPR willingness %u",
@@ -404,15 +421,21 @@ olsr_print (const u_char *pptr, u_int length, int is_ipv6)
                 msg_tlen -= sizeof(struct olsr_hello_link);
                 hello_len -= sizeof(struct olsr_hello_link);
 
+                TCHECK2(*msg_data, hello_len);
                 if (msg_type == OLSR_HELLO_MSG) {
-                    olsr_print_neighbor(msg_data, hello_len);
+                    if (olsr_print_neighbor(msg_data, hello_len) == -1)
+                        goto trunc;
                 } else {
 #if INET6
-                    if (is_ipv6)
-                        olsr_print_lq_neighbor6(msg_data, hello_len);
-                    else
+                    if (is_ipv6) {
+                        if (olsr_print_lq_neighbor6(msg_data, hello_len) == -1)
+                            goto trunc;
+                    } else
 #endif
-                        olsr_print_lq_neighbor4(msg_data, hello_len);
+                    {
+                        if (olsr_print_lq_neighbor4(msg_data, hello_len) == -1)
+                            goto trunc;
+                    }
                 }
 
                 msg_data += hello_len;
@@ -422,8 +445,9 @@ olsr_print (const u_char *pptr, u_int length, int is_ipv6)
 
         case OLSR_TC_MSG:
         case OLSR_TC_LQ_MSG:
-            if (!TTEST2(*msg_data, sizeof(struct olsr_tc)))
+            if (msg_tlen < sizeof(struct olsr_tc))
                 goto trunc;
+            TCHECK2(*msg_data, sizeof(struct olsr_tc));
 
             ptr.tc = (struct olsr_tc *)msg_data;
             printf("\n\t    advertised neighbor seq 0x%04x",
@@ -432,14 +456,19 @@ olsr_print (const u_char *pptr, u_int length, int is_ipv6)
             msg_tlen -= sizeof(struct olsr_tc);
 
             if (msg_type == OLSR_TC_MSG) {
-                olsr_print_neighbor(msg_data, msg_tlen);
+                if (olsr_print_neighbor(msg_data, msg_tlen) == -1)
+                    goto trunc;
             } else {
 #if INET6
-                if (is_ipv6)
-                    olsr_print_lq_neighbor6(msg_data, msg_tlen);
-                else
+                if (is_ipv6) {
+                    if (olsr_print_lq_neighbor6(msg_data, msg_tlen) == -1)
+                        goto trunc;
+                } else
 #endif
-                    olsr_print_lq_neighbor4(msg_data, msg_tlen);
+                {
+                    if (olsr_print_lq_neighbor4(msg_data, msg_tlen) == -1)
+                        goto trunc;
+                }
             }
             break;
 
@@ -452,10 +481,10 @@ olsr_print (const u_char *pptr, u_int length, int is_ipv6)
                 addr_size = sizeof(struct in6_addr);
 #endif
 
-            if (!TTEST2(*msg_data, addr_size))
-                goto trunc;
-
             while (msg_tlen >= addr_size) {
+                if (!TTEST2(*msg_data, addr_size))
+                    goto trunc;
+
                 printf("\n\t  interface address %s",
 #if INET6
                         is_ipv6 ? ip6addr_string(msg_data) :
@@ -520,10 +549,10 @@ olsr_print (const u_char *pptr, u_int length, int is_ipv6)
 
         case OLSR_NAMESERVICE_MSG:
         {
-            u_int16_t name_entries = EXTRACT_16BITS(msg_data+2);
-            u_int16_t addr_size = 4;
+            u_int name_entries = EXTRACT_16BITS(msg_data+2);
+            u_int addr_size = 4;
             int name_entries_valid = 0;
-            u_int16_t i;
+            u_int i;
 
             if (is_ipv6)
                 addr_size = 16;
@@ -532,6 +561,11 @@ olsr_print (const u_char *pptr, u_int length, int is_ipv6)
                     && ((name_entries * (4 + addr_size)) <= msg_tlen))
                 name_entries_valid = 1;
 
+            if (msg_tlen < 4)
+                goto trunc;
+            if (!TTEST2(*msg_data, 4))
+                goto trunc;
+
             printf("\n\t  Version %u, Entries %u%s",
                    EXTRACT_16BITS(msg_data),
                    name_entries, (name_entries_valid == 0) ? " (invalid)" : "");
@@ -547,6 +581,8 @@ olsr_print (const u_char *pptr, u_int length, int is_ipv6)
 
                 if (msg_tlen < 4)
                     break;
+                if (!TTEST2(*msg_data, 4))
+                    goto trunc;
 
                 name_entry_type = EXTRACT_16BITS(msg_data);
                 name_entry_len = EXTRACT_16BITS(msg_data+2);
@@ -564,26 +600,30 @@ olsr_print (const u_char *pptr, u_int length, int is_ipv6)
                 if (name_entry_len_valid == 0)
                     break;
 
-                {
-                    char name[name_entry_len + 1];
-                    memcpy (name, msg_data + addr_size, name_entry_len);
-                    name[name_entry_len] = 0;
-#if INET6
-                    if (is_ipv6)
-                        printf(", address %s, name \"%s\"",
-                                ip6addr_string(msg_data), name);
-                    else
-#endif
-                        printf(", address %s, name \"%s\"",
-                                ipaddr_string(msg_data), name);
-                }
-
                 /* 32-bit alignment */
+                name_entry_padding = 0;
                 if (name_entry_len%4 != 0)
-                    name_entry_len+=4-(name_entry_len%4);
+                    name_entry_padding = 4-(name_entry_len%4);
+
+                if (msg_tlen < addr_size + name_entry_len + name_entry_padding)
+                    goto trunc;
+
+                if (!TTEST2(*msg_data, addr_size + name_entry_len + name_entry_padding))
+                    goto trunc;
+
+#if INET6
+                if (is_ipv6)
+                    printf(", address %s, name \"",
+                            ip6addr_string(msg_data));
+                else
+#endif
+                    printf(", address %s, name \"",
+                            ipaddr_string(msg_data));
+                fn_printn(msg_data + addr_size, name_entry_len, NULL);
+                printf("\"");
 
-                msg_data += addr_size + name_entry_len;
-                msg_tlen -= addr_size + name_entry_len;
+                msg_data += addr_size + name_entry_len + name_entry_padding;
+                msg_tlen -= addr_size + name_entry_len + name_entry_padding;
             } /* for (i = 0; i < name_entries; i++) */
             break;
         } /* case OLSR_NAMESERVICE_MSG */