]> The Tcpdump Group git mirrors - tcpdump/blobdiff - print-bgp.c
Add EXTRACT_ calls.
[tcpdump] / print-bgp.c
index d21a976a04cf45efb90b0fa9b2cfd0c86e32f6e4..c401d0049cc602dcd9640ca52d1d70f090ba094b 100644 (file)
@@ -32,6 +32,8 @@
 
 /* \summary: Border Gateway Protocol (BGP) printer */
 
+/* specification: RFC 4771 */
+
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
@@ -110,7 +112,7 @@ struct bgp_route_refresh {
 #define BGP_ROUTE_REFRESH_SIZE          23
 
 #define bgp_attr_lenlen(flags, p) \
-    (((flags) & 0x10) ? 2 : 1)
+    (((flags) & 0x10) ? 2U : 1U)
 #define bgp_attr_len(flags, p) \
     (((flags) & 0x10) ? EXTRACT_BE_U_2(p) : EXTRACT_U_1(p))
 
@@ -519,7 +521,7 @@ static char astostr[20];
  */
 static char *
 as_printf(netdissect_options *ndo,
-          char *str, int size, u_int asnum)
+          char *str, size_t size, u_int asnum)
 {
     if (!ndo->ndo_bflag || asnum <= 0xFFFF) {
         snprintf(str, size, "%u", asnum);
@@ -553,7 +555,7 @@ decode_prefix4(netdissect_options *ndo,
     if (plen % 8) {
         ((u_char *)&addr)[plenbytes - 1] &= ((0xff00 >> (plen % 8)) & 0xff);
     }
-    snprintf(buf, buflen, "%s/%d", ipaddr_string(ndo, &addr), plen);
+    snprintf(buf, buflen, "%s/%u", ipaddr_string(ndo, &addr), plen);
     return 1 + plenbytes;
 
 trunc:
@@ -601,11 +603,11 @@ decode_labeled_prefix4(netdissect_options *ndo,
         ((u_char *)&addr)[plenbytes - 1] &= ((0xff00 >> (plen % 8)) & 0xff);
     }
     /* the label may get offsetted by 4 bits so lets shift it right */
-    snprintf(buf, buflen, "%s/%d, label:%u %s",
+    snprintf(buf, buflen, "%s/%u, label:%u %s",
              ipaddr_string(ndo, &addr),
              plen,
              EXTRACT_BE_U_3(pptr + 1)>>4,
-             ((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
+             ((EXTRACT_U_1(pptr + 3) & 1) == 0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
 
     return 4 + plenbytes;
 
@@ -668,7 +670,7 @@ trunc:
  *
  * return the number of bytes read from the wire.
  */
-static int
+static u_int
 bgp_vpn_sg_print(netdissect_options *ndo,
                  const u_char *pptr, char *buf, u_int buflen)
 {
@@ -841,12 +843,12 @@ decode_labeled_vpn_prefix4(netdissect_options *ndo,
             ((0xff00 >> (plen % 8)) & 0xff);
     }
     /* the label may get offsetted by 4 bits so lets shift it right */
-    snprintf(buf, buflen, "RD: %s, %s/%d, label:%u %s",
+    snprintf(buf, buflen, "RD: %s, %s/%u, label:%u %s",
              bgp_vpn_rd_print(ndo, pptr+4),
              ipaddr_string(ndo, &addr),
              plen,
              EXTRACT_BE_U_3(pptr + 1)>>4,
-             ((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
+             ((EXTRACT_U_1(pptr + 3) & 1) == 0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
 
     return 12 + (plen + 7) / 8;
 
@@ -868,7 +870,7 @@ trunc:
 
 static int
 decode_mdt_vpn_nlri(netdissect_options *ndo,
-            const u_char *pptr, char *buf, u_int buflen)
+                    const u_char *pptr, char *buf, u_int buflen)
 {
     const u_char *rd;
     const u_char *vpn_ip;
@@ -923,9 +925,10 @@ static const struct tok bgp_multicast_vpn_route_type_values[] = {
 
 static int
 decode_multicast_vpn(netdissect_options *ndo,
-             const u_char *pptr, char *buf, u_int buflen)
+                     const u_char *pptr, char *buf, size_t buflen)
 {
-    uint8_t route_type, route_length, addr_length, sg_length;
+    uint8_t route_type, route_length, addr_length;
+    u_int sg_length;
     u_int offset;
 
     ND_TCHECK_2(pptr);
@@ -988,9 +991,9 @@ decode_multicast_vpn(netdissect_options *ndo,
         ND_TCHECK_LEN(pptr, BGP_VPN_RD_LEN + 4);
         offset = strlen(buf);
         snprintf(buf + offset, buflen - offset, ", RD: %s, Source-AS %s",
-        bgp_vpn_rd_print(ndo, pptr),
-        as_printf(ndo, astostr, sizeof(astostr),
-        EXTRACT_BE_U_4(pptr + BGP_VPN_RD_LEN)));
+                 bgp_vpn_rd_print(ndo, pptr),
+                 as_printf(ndo, astostr, sizeof(astostr),
+                 EXTRACT_BE_U_4(pptr + BGP_VPN_RD_LEN)));
         pptr += BGP_VPN_RD_LEN + 4;
 
         bgp_vpn_sg_print(ndo, pptr, buf, buflen);
@@ -1032,89 +1035,107 @@ trunc:
 
 static int
 decode_labeled_vpn_l2(netdissect_options *ndo,
-              const u_char *pptr, char *buf, u_int buflen)
+                      const u_char *pptr, char *buf, u_int buflen)
 {
-    int plen,tlen,stringlen,tlv_type,tlv_len,ttlv_len;
+    u_int plen, tlen, tlv_type, tlv_len, ttlv_len;
+    int stringlen;
 
     ND_TCHECK_2(pptr);
-    plen=EXTRACT_BE_U_2(pptr);
-    tlen=plen;
+    plen = EXTRACT_BE_U_2(pptr);
+    tlen = plen;
     pptr += 2;
     /* Old and new L2VPN NLRI share AFI/SAFI
      *   -> Assume a 12 Byte-length NLRI is auto-discovery-only
      *      and > 17 as old format. Complain for the middle case
      */
-    if (plen==12) {
+    if (plen == 12) {
         /* assume AD-only with RD, BGPNH */
         ND_TCHECK_LEN(pptr, 12);
-        buf[0]='\0';
-        stringlen=snprintf(buf, buflen, "RD: %s, BGPNH: %s",
-                           bgp_vpn_rd_print(ndo, pptr),
-                           ipaddr_string(ndo, pptr+8)
-                   );
+        buf[0] = '\0';
+        stringlen = snprintf(buf, buflen, "RD: %s, BGPNH: %s",
+                             bgp_vpn_rd_print(ndo, pptr),
+                             ipaddr_string(ndo, pptr+8));
         UPDATE_BUF_BUFLEN(buf, buflen, stringlen);
-        pptr+=12;
-        tlen-=12;
-        return plen;
-    } else if (plen>17) {
+        pptr += 12;
+        tlen -= 12;
+        return plen + 2;
+    } else if (plen > 17) {
         /* assume old format */
         /* RD, ID, LBLKOFF, LBLBASE */
 
         ND_TCHECK_LEN(pptr, 15);
-        buf[0]='\0';
-        stringlen=snprintf(buf, buflen, "RD: %s, CE-ID: %u, Label-Block Offset: %u, Label Base %u",
-                           bgp_vpn_rd_print(ndo, pptr),
-                           EXTRACT_BE_U_2(pptr + 8),
-                           EXTRACT_BE_U_2(pptr + 10),
-                           EXTRACT_BE_U_3(pptr + 12)>>4); /* the label is offsetted by 4 bits so lets shift it right */
+        buf[0] = '\0';
+        stringlen = snprintf(buf, buflen, "RD: %s, CE-ID: %u, Label-Block Offset: %u, Label Base %u",
+                             bgp_vpn_rd_print(ndo, pptr),
+                             EXTRACT_BE_U_2(pptr + 8),
+                             EXTRACT_BE_U_2(pptr + 10),
+                             EXTRACT_BE_U_3(pptr + 12)>>4); /* the label is offsetted by 4 bits so lets shift it right */
         UPDATE_BUF_BUFLEN(buf, buflen, stringlen);
-        pptr+=15;
-        tlen-=15;
+        pptr += 15;
+        tlen -= 15;
 
         /* ok now the variable part - lets read out TLVs*/
-        while (tlen>0) {
-            if (tlen < 3)
-                return -1;
+        while (tlen != 0) {
+            if (tlen < 3) {
+                if (buflen != 0) {
+                    stringlen=snprintf(buf,buflen, "\n\t\tran past the end");
+                    UPDATE_BUF_BUFLEN(buf, buflen, stringlen);
+                }
+                return plen + 2;
+            }
             ND_TCHECK_3(pptr);
-            tlv_type=EXTRACT_U_1(pptr);
+            tlv_type = EXTRACT_U_1(pptr);
             pptr++;
-            tlv_len=EXTRACT_BE_U_2(pptr);
-            ttlv_len=tlv_len;
-            pptr+=2;
+            tlv_len = EXTRACT_BE_U_2(pptr);  /* length, in *bits* */
+            ttlv_len = (tlv_len + 7)/8;      /* length, in *bytes* */
+            pptr += 2;
 
             switch(tlv_type) {
             case 1:
-                if (buflen!=0) {
+                if (buflen != 0) {
                     stringlen=snprintf(buf,buflen, "\n\t\tcircuit status vector (%u) length: %u: 0x",
                                        tlv_type,
                                        tlv_len);
                     UPDATE_BUF_BUFLEN(buf, buflen, stringlen);
                 }
-                ttlv_len=ttlv_len/8+1; /* how many bytes do we need to read ? */
-                while (ttlv_len>0) {
+                while (ttlv_len != 0) {
+                    if (tlen < 1) {
+                        if (buflen != 0) {
+                            stringlen=snprintf(buf,buflen, " (ran past the end)");
+                            UPDATE_BUF_BUFLEN(buf, buflen, stringlen);
+                        }
+                        return plen + 2;
+                    }
                     ND_TCHECK_1(pptr);
-                    if (buflen!=0) {
+                    if (buflen != 0) {
                         stringlen=snprintf(buf,buflen, "%02x",
                                            EXTRACT_U_1(pptr));
                         pptr++;
                         UPDATE_BUF_BUFLEN(buf, buflen, stringlen);
                     }
                     ttlv_len--;
+                    tlen--;
                 }
                 break;
             default:
-                if (buflen!=0) {
+                if (buflen != 0) {
                     stringlen=snprintf(buf,buflen, "\n\t\tunknown TLV #%u, length: %u",
                                        tlv_type,
                                        tlv_len);
                     UPDATE_BUF_BUFLEN(buf, buflen, stringlen);
                 }
+                if (tlen < ttlv_len) {
+                    if (buflen != 0) {
+                        stringlen=snprintf(buf,buflen, " (ran past the end)");
+                        UPDATE_BUF_BUFLEN(buf, buflen, stringlen);
+                    }
+                    return plen + 2;
+                }
+                tlen -= ttlv_len;
                 break;
             }
-            tlen-=(tlv_len<<3); /* the tlv-length is expressed in bits so lets shift it right */
         }
-        return plen+2;
-
+        return plen + 2;
     } else {
         /* complain bitterly ? */
         /* fall through */
@@ -1148,7 +1169,7 @@ decode_prefix6(netdissect_options *ndo,
         addr.s6_addr[plenbytes - 1] &=
             ((0xff00 >> (plen % 8)) & 0xff);
     }
-    snprintf(buf, buflen, "%s/%d", ip6addr_string(ndo, &addr), plen);
+    snprintf(buf, buflen, "%s/%u", ip6addr_string(ndo, &addr), plen);
     return 1 + plenbytes;
 
 trunc:
@@ -1188,11 +1209,11 @@ decode_labeled_prefix6(netdissect_options *ndo,
             ((0xff00 >> (plen % 8)) & 0xff);
     }
     /* the label may get offsetted by 4 bits so lets shift it right */
-    snprintf(buf, buflen, "%s/%d, label:%u %s",
+    snprintf(buf, buflen, "%s/%u, label:%u %s",
              ip6addr_string(ndo, &addr),
              plen,
              EXTRACT_BE_U_3(pptr + 1)>>4,
-             ((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
+             ((EXTRACT_U_1(pptr + 3) & 1) == 0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
 
     return 4 + plenbytes;
 
@@ -1229,12 +1250,12 @@ decode_labeled_vpn_prefix6(netdissect_options *ndo,
             ((0xff00 >> (plen % 8)) & 0xff);
     }
     /* the label may get offsetted by 4 bits so lets shift it right */
-    snprintf(buf, buflen, "RD: %s, %s/%d, label:%u %s",
+    snprintf(buf, buflen, "RD: %s, %s/%u, label:%u %s",
              bgp_vpn_rd_print(ndo, pptr+4),
              ip6addr_string(ndo, &addr),
              plen,
              EXTRACT_BE_U_3(pptr + 1)>>4,
-              ((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
+             ((EXTRACT_U_1(pptr + 3) & 1) == 0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
 
     return 12 + (plen + 7) / 8;
 
@@ -1262,7 +1283,7 @@ decode_clnp_prefix(netdissect_options *ndo,
         addr[(plen + 7) / 8 - 1] &=
             ((0xff00 >> (plen % 8)) & 0xff);
     }
-    snprintf(buf, buflen, "%s/%d",
+    snprintf(buf, buflen, "%s/%u",
              isonsap_string(ndo, addr,(plen + 7) / 8),
              plen);
 
@@ -1274,7 +1295,7 @@ trunc:
 
 static int
 decode_labeled_vpn_clnp_prefix(netdissect_options *ndo,
-                   const u_char *pptr, char *buf, u_int buflen)
+                               const u_char *pptr, char *buf, u_int buflen)
 {
     uint8_t addr[19];
     u_int plen;
@@ -1294,16 +1315,15 @@ decode_labeled_vpn_clnp_prefix(netdissect_options *ndo,
     ND_TCHECK_LEN(pptr + 12, (plen + 7) / 8);
     memcpy(&addr, pptr + 12, (plen + 7) / 8);
     if (plen % 8) {
-        addr[(plen + 7) / 8 - 1] &=
-            ((0xff00 >> (plen % 8)) & 0xff);
+        addr[(plen + 7) / 8 - 1] &= ((0xff00 >> (plen % 8)) & 0xff);
     }
     /* the label may get offsetted by 4 bits so lets shift it right */
-    snprintf(buf, buflen, "RD: %s, %s/%d, label:%u %s",
+    snprintf(buf, buflen, "RD: %s, %s/%u, label:%u %s",
              bgp_vpn_rd_print(ndo, pptr+4),
              isonsap_string(ndo, addr,(plen + 7) / 8),
              plen,
              EXTRACT_BE_U_3(pptr + 1)>>4,
-             ((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
+             ((EXTRACT_U_1(pptr + 3) & 1) == 0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
 
     return 12 + (plen + 7) / 8;
 
@@ -1318,9 +1338,9 @@ trunc:
  * both Old speakers that do not support 4 byte AS, and the new speakers that do
  * support, exchange AS-Path with the same path-attribute type value 0x02.
  */
-static int
+static u_int
 bgp_attr_get_as_size(netdissect_options *ndo,
-                     uint8_t bgpa_type, const u_char *pptr, int len)
+                     uint8_t bgpa_type, const u_char *pptr, u_int len)
 {
     const u_char *tptr = pptr;
 
@@ -1376,9 +1396,11 @@ trunc:
  * and if so it checks that standard BGP doesn't make sense.
  */
 static int
-check_add_path(const u_char *pptr, u_int length, u_int max_prefix_length)
+check_add_path(netdissect_options *ndo, const u_char *pptr, u_int length,
+               u_int max_prefix_length)
 {
     u_int offset, prefix_length;
+
     if (length < 5) {
         return 0;
     }
@@ -1386,7 +1408,8 @@ check_add_path(const u_char *pptr, u_int length, u_int max_prefix_length)
     /* check if it could be add path */
     for (offset = 0; offset < length;) {
         offset += 4;
-        prefix_length = pptr[offset];
+        ND_TCHECK_1(pptr + offset);
+        prefix_length = EXTRACT_U_1(pptr + offset);
         /*
          * Add 4 to cover the path id
          * and check the prefix length isn't greater than 32/128.
@@ -1404,7 +1427,8 @@ check_add_path(const u_char *pptr, u_int length, u_int max_prefix_length)
 
     /* check it's not standard BGP */
     for (offset = 0; offset < length; ) {
-        prefix_length = pptr[offset];
+        ND_TCHECK_1(pptr + offset);
+        prefix_length = EXTRACT_U_1(pptr + offset);
         /*
          * If the prefix_length is zero (0.0.0.0/0)
          * and since it's not the only address (length >= 5)
@@ -1421,13 +1445,15 @@ check_add_path(const u_char *pptr, u_int length, u_int max_prefix_length)
 
     /* assume not add-path by default */
     return 0;
+trunc:
+    return -1;
 }
 
 static int
 bgp_attr_print(netdissect_options *ndo,
                u_int atype, const u_char *pptr, u_int len)
 {
-    int i;
+    u_int i;
     uint16_t af;
     uint8_t safi, snpa, nhlen;
     union { /* copy buffer for bandwidth values */
@@ -1438,8 +1464,9 @@ bgp_attr_print(netdissect_options *ndo,
     u_int tlen;
     const u_char *tptr;
     char buf[MAXHOSTNAMELEN + 100];
-    int as_size;
-    int add_path4, add_path6, path_id;
+    u_int as_size;
+    int add_path4, add_path6;
+    u_int path_id = 0;
 
     tptr = pptr;
     tlen = len;
@@ -1485,13 +1512,13 @@ bgp_attr_print(netdissect_options *ndo,
             ND_PRINT((ndo, "%s", tok2str(bgp_as_path_segment_open_values,
                       "?", EXTRACT_U_1(tptr))));
             ND_TCHECK_1(tptr + 1);
-            for (i = 0; i < tptr[1] * as_size; i += as_size) {
+            for (i = 0; i < EXTRACT_U_1(tptr + 1) * as_size; i += as_size) {
                 ND_TCHECK_LEN(tptr + 2 + i, as_size);
                 ND_PRINT((ndo, "%s ",
                           as_printf(ndo, astostr, sizeof(astostr),
-                as_size == 2 ?
-                    EXTRACT_BE_U_2(tptr + i + 2) :
-                    EXTRACT_BE_U_4(tptr + i + 2))));
+                          as_size == 2 ?
+                              EXTRACT_BE_U_2(tptr + i + 2) :
+                              EXTRACT_BE_U_4(tptr + i + 2))));
             }
             ND_TCHECK_1(tptr);
             ND_PRINT((ndo, "%s", tok2str(bgp_as_path_segment_close_values,
@@ -1557,9 +1584,11 @@ bgp_attr_print(netdissect_options *ndo,
             ND_PRINT((ndo, "invalid len"));
             break;
         }
-        while (tlen>0) {
+        while (tlen != 0) {
             uint32_t comm;
             ND_TCHECK_4(tptr);
+            if (tlen < 4)
+                goto trunc;
             comm = EXTRACT_BE_U_4(tptr);
             switch (comm) {
             case BGP_COMMUNITY_NO_EXPORT:
@@ -1595,8 +1624,10 @@ bgp_attr_print(netdissect_options *ndo,
             ND_PRINT((ndo, "invalid len"));
             break;
         }
-        while (tlen>0) {
+        while (tlen != 0) {
             ND_TCHECK_4(tptr);
+            if (tlen < 4)
+                goto trunc;
             ND_PRINT((ndo, "%s%s",
                       ipaddr_string(ndo, tptr),
                       (tlen>4) ? ", " : ""));
@@ -1662,9 +1693,9 @@ bgp_attr_print(netdissect_options *ndo,
         tptr++;
 
         if (tlen) {
-            int nnh = 0;
+            u_int nnh = 0;
             ND_PRINT((ndo, "\n\t    nexthop: "));
-            while (tlen > 0) {
+            while (tlen != 0) {
                 if (nnh++ > 0) {
                     ND_PRINT((ndo,  ", " ));
                 }
@@ -1797,17 +1828,21 @@ bgp_attr_print(netdissect_options *ndo,
 
         if (snpa) {
             ND_PRINT((ndo, "\n\t    %u SNPA", snpa));
-            for (/*nothing*/; snpa > 0; snpa--) {
+            for (/*nothing*/; snpa != 0; snpa--) {
                 ND_TCHECK_1(tptr);
-                ND_PRINT((ndo, "\n\t      %d bytes", EXTRACT_U_1(tptr)));
+                ND_PRINT((ndo, "\n\t      %u bytes", EXTRACT_U_1(tptr)));
                 tptr += EXTRACT_U_1(tptr) + 1;
             }
         } else {
             ND_PRINT((ndo, ", no SNPA"));
         }
 
-        add_path4 = check_add_path(tptr, (len-(tptr - pptr)), 32);
-        add_path6 = check_add_path(tptr, (len-(tptr - pptr)), 128);
+        add_path4 = check_add_path(ndo, tptr, (len-(tptr - pptr)), 32);
+        if (add_path4 == -1)
+            goto trunc;
+        add_path6 = check_add_path(ndo, tptr, (len-(tptr - pptr)), 128);
+        if (add_path6 == -1)
+            goto trunc;
 
         while (tptr < pptr + len) {
             switch (af<<8 | safi) {
@@ -1828,7 +1863,7 @@ bgp_attr_print(netdissect_options *ndo,
                 else
                     ND_PRINT((ndo, "\n\t      %s", buf));
                 if (add_path4) {
-                    ND_PRINT((ndo, "   Path Id: %d", path_id));
+                    ND_PRINT((ndo, "   Path Id: %u", path_id));
                 }
                 break;
             case (AFNUM_INET<<8 | SAFNUM_LABUNICAST):
@@ -1899,7 +1934,7 @@ bgp_attr_print(netdissect_options *ndo,
                 else
                     ND_PRINT((ndo, "\n\t      %s", buf));
                 if (add_path6) {
-                    ND_PRINT((ndo, "   Path Id: %d", path_id));
+                    ND_PRINT((ndo, "   Path Id: %u", path_id));
                 }
                 break;
             case (AFNUM_INET6<<8 | SAFNUM_LABUNICAST):
@@ -1991,8 +2026,12 @@ bgp_attr_print(netdissect_options *ndo,
 
         tptr += 3;
 
-        add_path4 = check_add_path(tptr, (len-(tptr - pptr)), 32);
-        add_path6 = check_add_path(tptr, (len-(tptr - pptr)), 128);
+        add_path4 = check_add_path(ndo, tptr, (len-(tptr - pptr)), 32);
+        if (add_path4 == -1)
+            goto trunc;
+        add_path6 = check_add_path(ndo, tptr, (len-(tptr - pptr)), 128);
+        if (add_path6 == -1)
+            goto trunc;
 
         while (tptr < pptr + len) {
             switch (af<<8 | safi) {
@@ -2013,7 +2052,7 @@ bgp_attr_print(netdissect_options *ndo,
                 else
                     ND_PRINT((ndo, "\n\t      %s", buf));
                 if (add_path4) {
-                    ND_PRINT((ndo, "   Path Id: %d", path_id));
+                    ND_PRINT((ndo, "   Path Id: %u", path_id));
                 }
                 break;
             case (AFNUM_INET<<8 | SAFNUM_LABUNICAST):
@@ -2055,7 +2094,7 @@ bgp_attr_print(netdissect_options *ndo,
                 else
                     ND_PRINT((ndo, "\n\t      %s", buf));
                 if (add_path6) {
-                    ND_PRINT((ndo, "   Path Id: %d", path_id));
+                    ND_PRINT((ndo, "   Path Id: %u", path_id));
                 }
                 break;
             case (AFNUM_INET6<<8 | SAFNUM_LABUNICAST):
@@ -2152,10 +2191,12 @@ bgp_attr_print(netdissect_options *ndo,
             ND_PRINT((ndo, "invalid len"));
             break;
         }
-        while (tlen>0) {
+        while (tlen != 0) {
             uint16_t extd_comm;
 
             ND_TCHECK_2(tptr);
+            if (tlen < 2)
+                goto trunc;
             extd_comm=EXTRACT_BE_U_2(tptr);
 
             ND_PRINT((ndo, "\n\t    %s (0x%04x), Flags [%s]",
@@ -2166,6 +2207,8 @@ bgp_attr_print(netdissect_options *ndo,
                       bittok2str(bgp_extd_comm_flag_values, "none", extd_comm)));
 
             ND_TCHECK_6(tptr + 2);
+            if (tlen < 8)
+                goto trunc;
             switch(extd_comm) {
             case BGP_EXT_COM_RT_0:
             case BGP_EXT_COM_RO_0:
@@ -2385,7 +2428,7 @@ bgp_attr_print(netdissect_options *ndo,
             }
             /* FIXME check for recursion */
             if (!bgp_attr_print(ndo, atype, tptr, alen))
-            return 0;
+                return 0;
             tptr += alen;
             len -= alen;
         }
@@ -2397,7 +2440,7 @@ bgp_attr_print(netdissect_options *ndo,
             break;
         }
         ND_PRINT((ndo, "\n\t    "));
-        while (len > 0) {
+        while (len != 0) {
             ND_TCHECK_LEN(tptr, 12);
             ND_PRINT((ndo, "%u:%u:%u%s",
                       EXTRACT_BE_U_4(tptr),
@@ -2405,6 +2448,10 @@ bgp_attr_print(netdissect_options *ndo,
                       EXTRACT_BE_U_4(tptr + 8),
                       (len > 12) ? ", " : ""));
             tptr += 12;
+            /*
+             * len will always be a multiple of 12, as per the above,
+             * so this will never underflow.
+             */
             len -= 12;
         }
         break;
@@ -2489,7 +2536,7 @@ bgp_capabilities_print(netdissect_options *ndo,
                 ND_PRINT((ndo, " (bogus)")); /* length */
                 break;
             }
-            while (tcap_len > 0) {
+            while (tcap_len != 0) {
                 if (tcap_len < 4) {
                     ND_PRINT((ndo, "\n\t\t(invalid)"));
                     break;
@@ -2513,7 +2560,7 @@ bgp_capabilities_print(netdissect_options *ndo,
                                    cap_len);
             break;
         }
-        if (ndo->ndo_vflag > 1 && cap_len > 0) {
+        if (ndo->ndo_vflag > 1 && cap_len != 0) {
             print_unknown_data(ndo, opt + i + 2, "\n\t\t", cap_len);
         }
         i += BGP_CAP_HEADER_SIZE + cap_len;
@@ -2597,22 +2644,20 @@ trunc:
 
 static void
 bgp_update_print(netdissect_options *ndo,
-                 const u_char *dat, int length)
+                 const u_char *dat, u_int length)
 {
-    const struct bgp *bgp_header;
     const u_char *p;
-    int withdrawn_routes_len;
+    u_int withdrawn_routes_len;
     char buf[MAXHOSTNAMELEN + 100];
     int wpfx;
-    int len;
+    u_int len;
     int i;
     int add_path;
-    int path_id;
+    u_int path_id = 0;
 
     ND_TCHECK_LEN(dat, BGP_SIZE);
     if (length < BGP_SIZE)
         goto trunc;
-    bgp_header = (const struct bgp *)dat;
     p = dat + BGP_SIZE;
     length -= BGP_SIZE;
 
@@ -2633,9 +2678,16 @@ bgp_update_print(netdissect_options *ndo,
         if (length < withdrawn_routes_len)
             goto trunc;
         ND_PRINT((ndo, "\n\t  Withdrawn routes:"));
-        add_path = check_add_path(p, withdrawn_routes_len, 32);
-        while (withdrawn_routes_len > 0) {
+        add_path = check_add_path(ndo, p, withdrawn_routes_len, 32);
+        if (add_path == -1)
+            goto trunc;
+        while (withdrawn_routes_len != 0) {
             if (add_path) {
+               if (withdrawn_routes_len < 4) {
+                   p += withdrawn_routes_len;
+                   length -= withdrawn_routes_len;
+                   break;
+               }
                 path_id = EXTRACT_BE_U_4(p);
                 p += 4;
                 length -= 4;
@@ -2652,7 +2704,7 @@ bgp_update_print(netdissect_options *ndo,
             else {
                 ND_PRINT((ndo, "\n\t    %s", buf));
                 if (add_path) {
-                    ND_PRINT((ndo, "   Path Id: %d", path_id));
+                    ND_PRINT((ndo, "   Path Id: %u", path_id));
                 }
                 p += wpfx;
                 length -= wpfx;
@@ -2680,7 +2732,7 @@ bgp_update_print(netdissect_options *ndo,
     if (len) {
         /* do something more useful!*/
         while (len) {
-            int aflags, atype, alenlen, alen;
+            u_int aflags, atype, alenlen, alen;
 
             ND_TCHECK_2(p);
             if (len < 2)
@@ -2731,9 +2783,11 @@ bgp_update_print(netdissect_options *ndo,
     }
 
     if (length) {
-        add_path = check_add_path(p, length, 32);
+        add_path = check_add_path(ndo, p, length, 32);
+        if (add_path == -1)
+            goto trunc;
         ND_PRINT((ndo, "\n\t  Updated routes:"));
-        while (length > 0) {
+        while (length != 0) {
             if (add_path) {
                 path_id = EXTRACT_BE_U_4(p);
                 p += 4;
@@ -2750,7 +2804,7 @@ bgp_update_print(netdissect_options *ndo,
             else {
                 ND_PRINT((ndo, "\n\t    %s", buf));
                 if (add_path) {
-                    ND_PRINT((ndo, "   Path Id: %d", path_id));
+                    ND_PRINT((ndo, "   Path Id: %u", path_id));
                 }
                 p += i;
                 length -= i;
@@ -2764,7 +2818,7 @@ trunc:
 
 static void
 bgp_notification_print(netdissect_options *ndo,
-                       const u_char *dat, int length)
+                       const u_char *dat, u_int length)
 {
     const struct bgp_notification *bgp_notification_header;
     const u_char *tptr;
@@ -2882,7 +2936,7 @@ trunc:
 
 static void
 bgp_route_refresh_print(netdissect_options *ndo,
-                        const u_char *pptr, int len)
+                        const u_char *pptr, u_int len)
 {
     const struct bgp_route_refresh *bgp_route_refresh_header;
 
@@ -2958,7 +3012,7 @@ trunc:
 
 void
 bgp_print(netdissect_options *ndo,
-          const u_char *dat, int length)
+          const u_char *dat, u_int length)
 {
     const u_char *p;
     const u_char *ep;