]> The Tcpdump Group git mirrors - tcpdump/blobdiff - print-bgp.c
ICMPv6: Add the IPv6-Only flag
[tcpdump] / print-bgp.c
index 246964dc1690fdb6e17f8155035c11fa2a82c107..6f523585f0f0d3ad26f896e586d6cbee05dd7d57 100644 (file)
 
 /* \summary: Border Gateway Protocol (BGP) printer */
 
-/* specification: RFC 4771 */
+/* specification: RFC 4271 */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
-#include <netdissect-stdinc.h>
+#include "netdissect-stdinc.h"
 
 #include <stdio.h>
 #include <string.h>
@@ -131,20 +131,20 @@ struct bgp_route_refresh {
 #define BGPTYPE_RCID_PATH               13    /* deprecated RFC1863 */
 #define BGPTYPE_MP_REACH_NLRI           14    /* RFC4760 */
 #define BGPTYPE_MP_UNREACH_NLRI         15    /* RFC4760 */
-#define BGPTYPE_EXTD_COMMUNITIES        16      /* RFC4360 */
-#define BGPTYPE_AS4_PATH                17      /* RFC6793 */
-#define BGPTYPE_AGGREGATOR4             18      /* RFC6793 */
-#define BGPTYPE_PMSI_TUNNEL             22      /* RFC6514 */
-#define BGPTYPE_TUNNEL_ENCAP            23      /* RFC5512 */
-#define BGPTYPE_TRAFFIC_ENG             24      /* RFC5543 */
-#define BGPTYPE_IPV6_EXTD_COMMUNITIES   25      /* RFC5701 */
-#define BGPTYPE_AIGP                    26      /* RFC7311 */
-#define BGPTYPE_PE_DISTINGUISHER_LABEL  27      /* RFC6514 */
-#define BGPTYPE_ENTROPY_LABEL           28      /* RFC6790 */
-#define BGPTYPE_LARGE_COMMUNITY         32      /* draft-ietf-idr-large-community-05 */
-#define BGPTYPE_ATTR_SET               128      /* RFC6368 */
-
-#define BGP_MP_NLRI_MINSIZE              3       /* End of RIB Marker detection */
+#define BGPTYPE_EXTD_COMMUNITIES        16    /* RFC4360 */
+#define BGPTYPE_AS4_PATH                17    /* RFC6793 */
+#define BGPTYPE_AGGREGATOR4             18    /* RFC6793 */
+#define BGPTYPE_PMSI_TUNNEL             22    /* RFC6514 */
+#define BGPTYPE_TUNNEL_ENCAP            23    /* RFC5512 */
+#define BGPTYPE_TRAFFIC_ENG             24    /* RFC5543 */
+#define BGPTYPE_IPV6_EXTD_COMMUNITIES   25    /* RFC5701 */
+#define BGPTYPE_AIGP                    26    /* RFC7311 */
+#define BGPTYPE_PE_DISTINGUISHER_LABEL  27    /* RFC6514 */
+#define BGPTYPE_ENTROPY_LABEL           28    /* RFC6790 */
+#define BGPTYPE_LARGE_COMMUNITY         32    /* draft-ietf-idr-large-community-05 */
+#define BGPTYPE_ATTR_SET               128    /* RFC6368 */
+
+#define BGP_MP_NLRI_MINSIZE              3    /* End of RIB Marker detection */
 
 static const struct tok bgp_attr_values[] = {
     { BGPTYPE_ORIGIN,           "Origin"},
@@ -410,7 +410,7 @@ static const struct tok bgp_safi_values[] = {
 #define BGP_COMMUNITY_NO_ADVERT              0xffffff02
 #define BGP_COMMUNITY_NO_EXPORT_SUBCONFED    0xffffff03
 
-/* Extended community type - draft-ietf-idr-bgp-ext-communities-05 */
+/* Extended community type - RFC 4360 */
 #define BGP_EXT_COM_RT_0        0x0002  /* Route Target,Format AS(2bytes):AN(4bytes) */
 #define BGP_EXT_COM_RT_1        0x0102  /* Route Target,Format IP address:AN(2bytes) */
 #define BGP_EXT_COM_RT_2        0x0202  /* Route Target,Format AN(4bytes):local(2bytes) */
@@ -468,12 +468,12 @@ static const struct tok bgp_extd_comm_subtype_values[] = {
     { BGP_EXT_COM_OSPF_RID,    "ospf-router-id"},
     { BGP_EXT_COM_OSPF_RID2,   "ospf-router-id"},
     { BGP_EXT_COM_L2INFO,      "layer2-info"},
-    { BGP_EXT_COM_EIGRP_GEN , "eigrp-general-route (flag, tag)" },
-    { BGP_EXT_COM_EIGRP_METRIC_AS_DELAY , "eigrp-route-metric (AS, delay)" },
-    { BGP_EXT_COM_EIGRP_METRIC_REL_NH_BW , "eigrp-route-metric (reliability, nexthop, bandwidth)" },
-    { BGP_EXT_COM_EIGRP_METRIC_LOAD_MTU , "eigrp-route-metric (load, MTU)" },
-    { BGP_EXT_COM_EIGRP_EXT_REMAS_REMID , "eigrp-external-route (remote-AS, remote-ID)" },
-    { BGP_EXT_COM_EIGRP_EXT_REMPROTO_REMMETRIC , "eigrp-external-route (remote-proto, remote-metric)" },
+    { BGP_EXT_COM_EIGRP_GEN,   "eigrp-general-route (flag, tag)" },
+    { BGP_EXT_COM_EIGRP_METRIC_AS_DELAY, "eigrp-route-metric (AS, delay)" },
+    { BGP_EXT_COM_EIGRP_METRIC_REL_NH_BW, "eigrp-route-metric (reliability, nexthop, bandwidth)" },
+    { BGP_EXT_COM_EIGRP_METRIC_LOAD_MTU, "eigrp-route-metric (load, MTU)" },
+    { BGP_EXT_COM_EIGRP_EXT_REMAS_REMID, "eigrp-external-route (remote-AS, remote-ID)" },
+    { BGP_EXT_COM_EIGRP_EXT_REMPROTO_REMMETRIC, "eigrp-external-route (remote-proto, remote-metric)" },
     { BGP_EXT_COM_SOURCE_AS, "source-AS" },
     { BGP_EXT_COM_VRF_RT_IMP, "vrf-route-import"},
     { BGP_EXT_COM_L2VPN_RT_0, "l2vpn-id"},
@@ -524,9 +524,9 @@ as_printf(netdissect_options *ndo,
           char *str, size_t size, u_int asnum)
 {
     if (!ndo->ndo_bflag || asnum <= 0xFFFF) {
-        snprintf(str, size, "%u", asnum);
+        nd_snprintf(str, size, "%u", asnum);
     } else {
-        snprintf(str, size, "%u.%u", asnum >> 16, asnum & 0xFFFF);
+        nd_snprintf(str, size, "%u.%u", asnum >> 16, asnum & 0xFFFF);
     }
     return str;
 }
@@ -555,7 +555,7 @@ decode_prefix4(netdissect_options *ndo,
     if (plen % 8) {
         ((u_char *)&addr)[plenbytes - 1] &= ((0xff00 >> (plen % 8)) & 0xff);
     }
-    snprintf(buf, buflen, "%s/%u", ipaddr_string(ndo, &addr), plen);
+    nd_snprintf(buf, buflen, "%s/%u", ipaddr_string(ndo, (const u_char *)&addr), plen);
     return 1 + plenbytes;
 
 trunc:
@@ -603,8 +603,8 @@ 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/%u, label:%u %s",
-             ipaddr_string(ndo, &addr),
+    nd_snprintf(buf, buflen, "%s/%u, label:%u %s",
+             ipaddr_string(ndo, (const u_char *)&addr),
              plen,
              EXTRACT_BE_U_3(pptr + 1)>>4,
              ((EXTRACT_U_1(pptr + 3) & 1) == 0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
@@ -633,16 +633,16 @@ bgp_vpn_ip_print(netdissect_options *ndo,
     char *pos = addr;
 
     switch(addr_length) {
-    case (sizeof(struct in_addr) << 3): /* 32 */
-        ND_TCHECK_LEN(pptr, sizeof(struct in_addr));
-        snprintf(pos, sizeof(addr), "%s", ipaddr_string(ndo, pptr));
+    case (sizeof(nd_ipv4) << 3): /* 32 */
+        ND_TCHECK_LEN(pptr, sizeof(nd_ipv4));
+        nd_snprintf(pos, sizeof(addr), "%s", ipaddr_string(ndo, pptr));
         break;
-    case (sizeof(struct in6_addr) << 3): /* 128 */
-        ND_TCHECK_LEN(pptr, sizeof(struct in6_addr));
-        snprintf(pos, sizeof(addr), "%s", ip6addr_string(ndo, pptr));
+    case (sizeof(nd_ipv6) << 3): /* 128 */
+        ND_TCHECK_LEN(pptr, sizeof(nd_ipv6));
+        nd_snprintf(pos, sizeof(addr), "%s", ip6addr_string(ndo, pptr));
         break;
     default:
-        snprintf(pos, sizeof(addr), "bogus address length %u", addr_length);
+        nd_snprintf(pos, sizeof(addr), "bogus address length %u", addr_length);
         break;
     }
     pos += strlen(pos);
@@ -689,7 +689,7 @@ bgp_vpn_sg_print(netdissect_options *ndo,
     total_length += (addr_length >> 3) + 1;
     offset = strlen(buf);
     if (addr_length) {
-        snprintf(buf + offset, buflen - offset, ", Source %s",
+        nd_snprintf(buf + offset, buflen - offset, ", Source %s",
              bgp_vpn_ip_print(ndo, pptr, addr_length));
         pptr += (addr_length >> 3);
     }
@@ -704,7 +704,7 @@ bgp_vpn_sg_print(netdissect_options *ndo,
     total_length += (addr_length >> 3) + 1;
     offset = strlen(buf);
     if (addr_length) {
-        snprintf(buf + offset, buflen - offset, ", Group %s",
+        nd_snprintf(buf + offset, buflen - offset, ", Group %s",
              bgp_vpn_ip_print(ndo, pptr, addr_length));
         pptr += (addr_length >> 3);
     }
@@ -713,10 +713,8 @@ trunc:
     return (total_length);
 }
 
-/* RDs and RTs share the same semantics
- * we use bgp_vpn_rd_print for
- * printing route targets inside a NLRI */
-char *
+/* Print an RFC 4364 Route Distinguisher */
+const char *
 bgp_vpn_rd_print(netdissect_options *ndo,
                  const u_char *pptr)
 {
@@ -727,33 +725,33 @@ bgp_vpn_rd_print(netdissect_options *ndo,
     /* ok lets load the RD format */
     switch (EXTRACT_BE_U_2(pptr)) {
 
-        /* 2-byte-AS:number fmt*/
     case 0:
-        snprintf(pos, sizeof(rd) - (pos - rd), "%u:%u (= %u.%u.%u.%u)",
-                 EXTRACT_BE_U_2(pptr + 2),
-                 EXTRACT_BE_U_4(pptr + 4),
-                 EXTRACT_U_1(pptr + 4), EXTRACT_U_1(pptr + 5),
-                 EXTRACT_U_1(pptr + 6), EXTRACT_U_1(pptr + 7));
+        /* 2-byte-AS:number fmt */
+        nd_snprintf(pos, sizeof(rd) - (pos - rd), "%u:%u (= %u.%u.%u.%u)",
+                    EXTRACT_BE_U_2(pptr + 2),
+                    EXTRACT_BE_U_4(pptr + 4),
+                    EXTRACT_U_1(pptr + 4), EXTRACT_U_1(pptr + 5),
+                    EXTRACT_U_1(pptr + 6), EXTRACT_U_1(pptr + 7));
         break;
-        /* IP-address:AS fmt*/
 
     case 1:
-        snprintf(pos, sizeof(rd) - (pos - rd), "%u.%u.%u.%u:%u",
-                 EXTRACT_U_1(pptr + 2), EXTRACT_U_1(pptr + 3),
-                 EXTRACT_U_1(pptr + 4), EXTRACT_U_1(pptr + 5),
-                 EXTRACT_BE_U_2(pptr + 6));
+        /* IP-address:AS fmt */
+        nd_snprintf(pos, sizeof(rd) - (pos - rd), "%u.%u.%u.%u:%u",
+                    EXTRACT_U_1(pptr + 2), EXTRACT_U_1(pptr + 3),
+                    EXTRACT_U_1(pptr + 4), EXTRACT_U_1(pptr + 5),
+                    EXTRACT_BE_U_2(pptr + 6));
         break;
 
-        /* 4-byte-AS:number fmt*/
     case 2:
-        snprintf(pos, sizeof(rd) - (pos - rd), "%s:%u (%u.%u.%u.%u:%u)",
-                 as_printf(ndo, astostr, sizeof(astostr), EXTRACT_BE_U_4(pptr + 2)),
-                 EXTRACT_BE_U_2(pptr + 6), EXTRACT_U_1(pptr + 2),
-                 EXTRACT_U_1(pptr + 3), EXTRACT_U_1(pptr + 4),
-                 EXTRACT_U_1(pptr + 5), EXTRACT_BE_U_2(pptr + 6));
+        /* 4-byte-AS:number fmt */
+        nd_snprintf(pos, sizeof(rd) - (pos - rd), "%s:%u (%u.%u.%u.%u:%u)",
+                    as_printf(ndo, astostr, sizeof(astostr), EXTRACT_BE_U_4(pptr + 2)),
+                    EXTRACT_BE_U_2(pptr + 6), EXTRACT_U_1(pptr + 2),
+                    EXTRACT_U_1(pptr + 3), EXTRACT_U_1(pptr + 4),
+                    EXTRACT_U_1(pptr + 5), EXTRACT_BE_U_2(pptr + 6));
         break;
     default:
-        snprintf(pos, sizeof(rd) - (pos - rd), "unknown RD format");
+        nd_snprintf(pos, sizeof(rd) - (pos - rd), "unknown RD format");
         break;
     }
     pos += strlen(pos);
@@ -761,11 +759,101 @@ bgp_vpn_rd_print(netdissect_options *ndo,
     return (rd);
 }
 
+/*
+ * Print an RFC 4360 Extended Community.
+ */
+static void
+bgp_extended_community_print(netdissect_options *ndo,
+                             const u_char *pptr)
+{
+    union { /* copy buffer for bandwidth values */
+        float f;
+        uint32_t i;
+    } bw;
+
+    switch (EXTRACT_BE_U_2(pptr)) {
+
+    case BGP_EXT_COM_RT_0:
+    case BGP_EXT_COM_RO_0:
+    case BGP_EXT_COM_L2VPN_RT_0:
+        ND_PRINT("%u:%u (= %s)",
+                 EXTRACT_BE_U_2(pptr + 2),
+                 EXTRACT_BE_U_4(pptr + 4),
+                 ipaddr_string(ndo, pptr+4));
+        break;
+
+    case BGP_EXT_COM_RT_1:
+    case BGP_EXT_COM_RO_1:
+    case BGP_EXT_COM_L2VPN_RT_1:
+    case BGP_EXT_COM_VRF_RT_IMP:
+        ND_PRINT("%s:%u",
+                 ipaddr_string(ndo, pptr+2),
+                 EXTRACT_BE_U_2(pptr + 6));
+        break;
+
+    case BGP_EXT_COM_RT_2:
+        case BGP_EXT_COM_RO_2:
+            ND_PRINT("%s:%u",
+                     as_printf(ndo, astostr, sizeof(astostr),
+                     EXTRACT_BE_U_4(pptr + 2)), EXTRACT_BE_U_2(pptr + 6));
+            break;
+
+    case BGP_EXT_COM_LINKBAND:
+            bw.i = EXTRACT_BE_U_4(pptr + 2);
+            ND_PRINT("bandwidth: %.3f Mbps",
+                     bw.f*8/1000000);
+            break;
+
+    case BGP_EXT_COM_VPN_ORIGIN:
+    case BGP_EXT_COM_VPN_ORIGIN2:
+    case BGP_EXT_COM_VPN_ORIGIN3:
+    case BGP_EXT_COM_VPN_ORIGIN4:
+    case BGP_EXT_COM_OSPF_RID:
+    case BGP_EXT_COM_OSPF_RID2:
+        ND_PRINT("%s", ipaddr_string(ndo, pptr+2));
+        break;
+
+    case BGP_EXT_COM_OSPF_RTYPE:
+    case BGP_EXT_COM_OSPF_RTYPE2:
+        ND_PRINT("area:%s, router-type:%s, metric-type:%s%s",
+                 ipaddr_string(ndo, pptr+2),
+                 tok2str(bgp_extd_comm_ospf_rtype_values,
+                         "unknown (0x%02x)",
+                         EXTRACT_U_1((pptr + 6))),
+                 (EXTRACT_U_1(pptr + 7) &  BGP_OSPF_RTYPE_METRIC_TYPE) ? "E2" : "",
+                 ((EXTRACT_U_1(pptr + 6) == BGP_OSPF_RTYPE_EXT) || (EXTRACT_U_1(pptr + 6) == BGP_OSPF_RTYPE_NSSA)) ? "E1" : "");
+        break;
+
+    case BGP_EXT_COM_L2INFO:
+        ND_PRINT("%s Control Flags [0x%02x]:MTU %u",
+                 tok2str(l2vpn_encaps_values,
+                         "unknown encaps",
+                         EXTRACT_U_1((pptr + 2))),
+                 EXTRACT_U_1((pptr + 3)),
+                 EXTRACT_BE_U_2(pptr + 4));
+        break;
+
+    case BGP_EXT_COM_SOURCE_AS:
+        ND_PRINT("AS %u", EXTRACT_BE_U_2(pptr + 2));
+        break;
+
+    default:
+        ND_PRINT("%02x%02x%02x%02x%02x%02x",
+                 EXTRACT_U_1(pptr + 2),
+                 EXTRACT_U_1(pptr + 3),
+                 EXTRACT_U_1(pptr + 4),
+                 EXTRACT_U_1(pptr + 5),
+                 EXTRACT_U_1(pptr + 6),
+                 EXTRACT_U_1(pptr + 7));
+        break;
+    }
+}
+
+/* RFC 4684 */
 static int
 decode_rt_routing_info(netdissect_options *ndo,
-                       const u_char *pptr, char *buf, u_int buflen)
+                       const u_char *pptr)
 {
-    uint8_t route_target[8];
     u_int plen;
     char asbuf[sizeof(astostr)]; /* bgp_vpn_rd_print() overwrites astostr */
 
@@ -779,12 +867,14 @@ decode_rt_routing_info(netdissect_options *ndo,
      */
     if (0 == plen) {
         /* Without "origin AS", without "route target". */
-        snprintf(buf, buflen, "default route target");
+        ND_PRINT("\n\t      default route target");
         return 1;
     }
 
-    if (32 > plen)
+    if (32 > plen) {
+        ND_PRINT("\n\t      (illegal prefix length)");
         return -1;
+    }
 
     /* With at least "origin AS", possibly with "route target". */
     ND_TCHECK_4(pptr + 1);
@@ -792,26 +882,18 @@ decode_rt_routing_info(netdissect_options *ndo,
 
     plen -= 32; /* adjust prefix length */
 
-    if (64 < plen)
-        return -1;
-
-    /* From now on (plen + 7) / 8 evaluates to { 0, 1, 2, ..., 8 }
-     * and gives the number of octets in the variable-length "route
-     * target" field inside this NLRI "prefix". Look for it.
+    /* An extended community is 8 octets, so the remaining prefix
+     * length must be 64.
      */
-    memset(&route_target, 0, sizeof(route_target));
-    ND_TCHECK_LEN(pptr + 5, (plen + 7) / 8);
-    memcpy(&route_target, pptr + 5, (plen + 7) / 8);
-    /* Which specification says to do this? */
-    if (plen % 8) {
-        ((u_char *)&route_target)[(plen + 7) / 8 - 1] &=
-            ((0xff00 >> (plen % 8)) & 0xff);
+    if (64 != plen) {
+        ND_PRINT("\n\t    (illegal prefix length)");
+        return -1;
     }
-    snprintf(buf, buflen, "origin AS: %s, route target %s",
-             asbuf,
-             bgp_vpn_rd_print(ndo, (u_char *)&route_target));
+    ND_TCHECK_LEN(pptr + 5, 8);
+    ND_PRINT("\n\t      origin AS: %s, route target ", asbuf);
+    bgp_extended_community_print(ndo, pptr + 5);
 
-    return 5 + (plen + 7) / 8;
+    return 5 + 8;
 
 trunc:
     return -2;
@@ -843,12 +925,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/%u, label:%u %s",
-             bgp_vpn_rd_print(ndo, pptr+4),
-             ipaddr_string(ndo, &addr),
-             plen,
-             EXTRACT_BE_U_3(pptr + 1)>>4,
-             ((EXTRACT_U_1(pptr + 3) & 1) == 0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
+    nd_snprintf(buf, buflen, "RD: %s, %s/%u, label:%u %s",
+                bgp_vpn_rd_print(ndo, pptr+4),
+                ipaddr_string(ndo, (const u_char *)&addr),
+                plen,
+                EXTRACT_BE_U_3(pptr + 1)>>4,
+                ((EXTRACT_U_1(pptr + 3) & 1) == 0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
 
     return 12 + (plen + 7) / 8;
 
@@ -888,15 +970,15 @@ decode_mdt_vpn_nlri(netdissect_options *ndo,
     pptr += 8;
 
     /* IPv4 address */
-    ND_TCHECK_LEN(pptr, sizeof(struct in_addr));
+    ND_TCHECK_LEN(pptr, sizeof(nd_ipv4));
     vpn_ip = pptr;
-    pptr += sizeof(struct in_addr);
+    pptr += sizeof(nd_ipv4);
 
     /* MDT Group Address */
-    ND_TCHECK_LEN(pptr, sizeof(struct in_addr));
+    ND_TCHECK_LEN(pptr, sizeof(nd_ipv4));
 
-    snprintf(buf, buflen, "RD: %s, VPN IP Address: %s, MC Group Address: %s",
-             bgp_vpn_rd_print(ndo, rd), ipaddr_string(ndo, vpn_ip), ipaddr_string(ndo, pptr));
+    nd_snprintf(buf, buflen, "RD: %s, VPN IP Address: %s, MC Group Address: %s",
+                bgp_vpn_rd_print(ndo, rd), ipaddr_string(ndo, vpn_ip), ipaddr_string(ndo, pptr));
 
     return MDT_VPN_NLRI_LEN + 1;
 
@@ -937,7 +1019,7 @@ decode_multicast_vpn(netdissect_options *ndo,
     route_length = EXTRACT_U_1(pptr);
     pptr++;
 
-    snprintf(buf, buflen, "Route-Type: %s (%u), length: %u",
+    nd_snprintf(buf, buflen, "Route-Type: %s (%u), length: %u",
          tok2str(bgp_multicast_vpn_route_type_values,
                  "Unknown", route_type),
          route_type, route_length);
@@ -946,15 +1028,15 @@ decode_multicast_vpn(netdissect_options *ndo,
     case BGP_MULTICAST_VPN_ROUTE_TYPE_INTRA_AS_I_PMSI:
         ND_TCHECK_LEN(pptr, BGP_VPN_RD_LEN);
         offset = strlen(buf);
-        snprintf(buf + offset, buflen - offset, ", RD: %s, Originator %s",
-                 bgp_vpn_rd_print(ndo, pptr),
-                 bgp_vpn_ip_print(ndo, pptr + BGP_VPN_RD_LEN,
-                                  (route_length - BGP_VPN_RD_LEN) << 3));
+        nd_snprintf(buf + offset, buflen - offset, ", RD: %s, Originator %s",
+                    bgp_vpn_rd_print(ndo, pptr),
+                    bgp_vpn_ip_print(ndo, pptr + BGP_VPN_RD_LEN,
+                                     (route_length - BGP_VPN_RD_LEN) << 3));
         break;
     case BGP_MULTICAST_VPN_ROUTE_TYPE_INTER_AS_I_PMSI:
         ND_TCHECK_LEN(pptr, BGP_VPN_RD_LEN + 4);
         offset = strlen(buf);
-        snprintf(buf + offset, buflen - offset, ", RD: %s, Source-AS %s",
+        nd_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)));
@@ -963,8 +1045,8 @@ decode_multicast_vpn(netdissect_options *ndo,
     case BGP_MULTICAST_VPN_ROUTE_TYPE_S_PMSI:
         ND_TCHECK_LEN(pptr, BGP_VPN_RD_LEN);
         offset = strlen(buf);
-        snprintf(buf + offset, buflen - offset, ", RD: %s",
-                 bgp_vpn_rd_print(ndo, pptr));
+        nd_snprintf(buf + offset, buflen - offset, ", RD: %s",
+                    bgp_vpn_rd_print(ndo, pptr));
         pptr += BGP_VPN_RD_LEN;
 
         sg_length = bgp_vpn_sg_print(ndo, pptr, buf, buflen);
@@ -972,15 +1054,15 @@ decode_multicast_vpn(netdissect_options *ndo,
 
         ND_TCHECK_LEN(pptr, addr_length);
         offset = strlen(buf);
-        snprintf(buf + offset, buflen - offset, ", Originator %s",
-                 bgp_vpn_ip_print(ndo, pptr, addr_length << 3));
+        nd_snprintf(buf + offset, buflen - offset, ", Originator %s",
+                    bgp_vpn_ip_print(ndo, pptr, addr_length << 3));
         break;
 
     case BGP_MULTICAST_VPN_ROUTE_TYPE_SOURCE_ACTIVE:
         ND_TCHECK_LEN(pptr, BGP_VPN_RD_LEN);
         offset = strlen(buf);
-        snprintf(buf + offset, buflen - offset, ", RD: %s",
-                 bgp_vpn_rd_print(ndo, pptr));
+        nd_snprintf(buf + offset, buflen - offset, ", RD: %s",
+                    bgp_vpn_rd_print(ndo, pptr));
         pptr += BGP_VPN_RD_LEN;
 
         bgp_vpn_sg_print(ndo, pptr, buf, buflen);
@@ -990,10 +1072,10 @@ decode_multicast_vpn(netdissect_options *ndo,
     case BGP_MULTICAST_VPN_ROUTE_TYPE_SOURCE_TREE_JOIN:
         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)));
+        nd_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)));
         pptr += BGP_VPN_RD_LEN + 4;
 
         bgp_vpn_sg_print(ndo, pptr, buf, buflen);
@@ -1052,69 +1134,88 @@ decode_labeled_vpn_l2(netdissect_options *ndo,
         /* 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));
+        stringlen = nd_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;
+        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 */
+        stringlen = nd_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;
 
         /* ok now the variable part - lets read out TLVs*/
-        while (tlen != 00) {
-            if (tlen < 3)
-                return -1;
+        while (tlen != 0) {
+            if (tlen < 3) {
+                if (buflen != 0) {
+                    stringlen=nd_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);
             pptr++;
-            tlv_len = EXTRACT_BE_U_2(pptr);
-            ttlv_len = tlv_len;
+            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) {
-                    stringlen=snprintf(buf,buflen, "\n\t\tcircuit status vector (%u) length: %u: 0x",
-                                       tlv_type,
-                                       tlv_len);
+                    stringlen=nd_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=nd_snprintf(buf,buflen, " (ran past the end)");
+                            UPDATE_BUF_BUFLEN(buf, buflen, stringlen);
+                        }
+                        return plen + 2;
+                    }
                     ND_TCHECK_1(pptr);
                     if (buflen != 0) {
-                        stringlen=snprintf(buf,buflen, "%02x",
-                                           EXTRACT_U_1(pptr));
+                        stringlen=nd_snprintf(buf,buflen, "%02x",
+                                              EXTRACT_U_1(pptr));
                         pptr++;
                         UPDATE_BUF_BUFLEN(buf, buflen, stringlen);
                     }
                     ttlv_len--;
+                    tlen--;
                 }
                 break;
             default:
                 if (buflen != 0) {
-                    stringlen=snprintf(buf,buflen, "\n\t\tunknown TLV #%u, length: %u",
-                                       tlv_type,
-                                       tlv_len);
+                    stringlen=nd_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=nd_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;
     } else {
@@ -1150,7 +1251,7 @@ decode_prefix6(netdissect_options *ndo,
         addr.s6_addr[plenbytes - 1] &=
             ((0xff00 >> (plen % 8)) & 0xff);
     }
-    snprintf(buf, buflen, "%s/%u", ip6addr_string(ndo, &addr), plen);
+    nd_snprintf(buf, buflen, "%s/%u", ip6addr_string(ndo, (const u_char *)&addr), plen);
     return 1 + plenbytes;
 
 trunc:
@@ -1190,11 +1291,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/%u, label:%u %s",
-             ip6addr_string(ndo, &addr),
-             plen,
-             EXTRACT_BE_U_3(pptr + 1)>>4,
-             ((EXTRACT_U_1(pptr + 3) & 1) == 0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
+    nd_snprintf(buf, buflen, "%s/%u, label:%u %s",
+                ip6addr_string(ndo, (const u_char *)&addr),
+                plen,
+                EXTRACT_BE_U_3(pptr + 1)>>4,
+                ((EXTRACT_U_1(pptr + 3) & 1) == 0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
 
     return 4 + plenbytes;
 
@@ -1231,12 +1332,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/%u, label:%u %s",
-             bgp_vpn_rd_print(ndo, pptr+4),
-             ip6addr_string(ndo, &addr),
-             plen,
-             EXTRACT_BE_U_3(pptr + 1)>>4,
-             ((EXTRACT_U_1(pptr + 3) & 1) == 0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
+    nd_snprintf(buf, buflen, "RD: %s, %s/%u, label:%u %s",
+                bgp_vpn_rd_print(ndo, pptr+4),
+                ip6addr_string(ndo, (const u_char *)&addr),
+                plen,
+                EXTRACT_BE_U_3(pptr + 1)>>4,
+                ((EXTRACT_U_1(pptr + 3) & 1) == 0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
 
     return 12 + (plen + 7) / 8;
 
@@ -1264,9 +1365,9 @@ decode_clnp_prefix(netdissect_options *ndo,
         addr[(plen + 7) / 8 - 1] &=
             ((0xff00 >> (plen % 8)) & 0xff);
     }
-    snprintf(buf, buflen, "%s/%u",
-             isonsap_string(ndo, addr,(plen + 7) / 8),
-             plen);
+    nd_snprintf(buf, buflen, "%s/%u",
+                isonsap_string(ndo, addr,(plen + 7) / 8),
+                plen);
 
     return 1 + (plen + 7) / 8;
 
@@ -1299,12 +1400,12 @@ decode_labeled_vpn_clnp_prefix(netdissect_options *ndo,
         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/%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,
-             ((EXTRACT_U_1(pptr + 3) & 1) == 0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
+    nd_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,
+                ((EXTRACT_U_1(pptr + 3) & 1) == 0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
 
     return 12 + (plen + 7) / 8;
 
@@ -1377,7 +1478,8 @@ 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;
 
@@ -1385,9 +1487,16 @@ check_add_path(const u_char *pptr, u_int length, u_int max_prefix_length)
         return 0;
     }
 
-    /* check if it could be add path */
+    /*
+     * Scan through the NLRI information under the assumpetion that
+     * it doesn't have path IDs.
+     */
     for (offset = 0; offset < length;) {
         offset += 4;
+        if (!ND_TTEST_1(pptr + offset)) {
+            /* We ran out of captured data; quit scanning. */
+            break;
+        }
         prefix_length = EXTRACT_U_1(pptr + offset);
         /*
          * Add 4 to cover the path id
@@ -1406,6 +1515,10 @@ 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; ) {
+        if (!ND_TTEST_1(pptr + offset)) {
+            /* We ran out of captured data; quit scanning. */
+            break;
+        }
         prefix_length = EXTRACT_U_1(pptr + offset);
         /*
          * If the prefix_length is zero (0.0.0.0/0)
@@ -1432,10 +1545,6 @@ bgp_attr_print(netdissect_options *ndo,
     u_int i;
     uint16_t af;
     uint8_t safi, snpa, nhlen;
-    union { /* copy buffer for bandwidth values */
-        float f;
-        uint32_t i;
-    } bw;
     int advance;
     u_int tlen;
     const u_char *tptr;
@@ -1450,12 +1559,12 @@ bgp_attr_print(netdissect_options *ndo,
     switch (atype) {
     case BGPTYPE_ORIGIN:
         if (len != 1)
-            ND_PRINT((ndo, "invalid len"));
+            ND_PRINT("invalid len");
         else {
             ND_TCHECK_1(tptr);
-            ND_PRINT((ndo, "%s", tok2str(bgp_origin_values,
+            ND_PRINT("%s", tok2str(bgp_origin_values,
                       "Unknown Origin Typecode",
-                      EXTRACT_U_1(tptr))));
+                      EXTRACT_U_1(tptr)));
         }
         break;
 
@@ -1465,11 +1574,11 @@ bgp_attr_print(netdissect_options *ndo,
     case BGPTYPE_AS4_PATH:
     case BGPTYPE_AS_PATH:
         if (len % 2) {
-            ND_PRINT((ndo, "invalid len"));
+            ND_PRINT("invalid len");
             break;
         }
         if (!len) {
-            ND_PRINT((ndo, "empty"));
+            ND_PRINT("empty");
             break;
         }
 
@@ -1485,44 +1594,44 @@ bgp_attr_print(netdissect_options *ndo,
 
         while (tptr < pptr + len) {
             ND_TCHECK_1(tptr);
-            ND_PRINT((ndo, "%s", tok2str(bgp_as_path_segment_open_values,
-                      "?", EXTRACT_U_1(tptr))));
+            ND_PRINT("%s", tok2str(bgp_as_path_segment_open_values,
+                      "?", EXTRACT_U_1(tptr)));
             ND_TCHECK_1(tptr + 1);
             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 ",
+                ND_PRINT("%s ",
                           as_printf(ndo, astostr, sizeof(astostr),
                           as_size == 2 ?
                               EXTRACT_BE_U_2(tptr + i + 2) :
-                              EXTRACT_BE_U_4(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,
-                      "?", EXTRACT_U_1(tptr))));
+            ND_PRINT("%s", tok2str(bgp_as_path_segment_close_values,
+                      "?", EXTRACT_U_1(tptr)));
             ND_TCHECK_1(tptr + 1);
             tptr += 2 + EXTRACT_U_1(tptr + 1) * as_size;
         }
         break;
     case BGPTYPE_NEXT_HOP:
         if (len != 4)
-            ND_PRINT((ndo, "invalid len"));
+            ND_PRINT("invalid len");
         else {
             ND_TCHECK_4(tptr);
-            ND_PRINT((ndo, "%s", ipaddr_string(ndo, tptr)));
+            ND_PRINT("%s", ipaddr_string(ndo, tptr));
         }
         break;
     case BGPTYPE_MULTI_EXIT_DISC:
     case BGPTYPE_LOCAL_PREF:
         if (len != 4)
-            ND_PRINT((ndo, "invalid len"));
+            ND_PRINT("invalid len");
         else {
             ND_TCHECK_4(tptr);
-            ND_PRINT((ndo, "%u", EXTRACT_BE_U_4(tptr)));
+            ND_PRINT("%u", EXTRACT_BE_U_4(tptr));
         }
         break;
     case BGPTYPE_ATOMIC_AGGREGATE:
         if (len != 0)
-            ND_PRINT((ndo, "invalid len"));
+            ND_PRINT("invalid len");
         break;
     case BGPTYPE_AGGREGATOR:
 
@@ -1531,54 +1640,56 @@ bgp_attr_print(netdissect_options *ndo,
          * the length of this PA can be either 6 bytes or 8 bytes.
          */
         if (len != 6 && len != 8) {
-            ND_PRINT((ndo, "invalid len"));
+            ND_PRINT("invalid len");
             break;
         }
         ND_TCHECK_LEN(tptr, len);
         if (len == 6) {
-            ND_PRINT((ndo, " AS #%s, origin %s",
+            ND_PRINT(" AS #%s, origin %s",
                       as_printf(ndo, astostr, sizeof(astostr), EXTRACT_BE_U_2(tptr)),
-                      ipaddr_string(ndo, tptr + 2)));
+                      ipaddr_string(ndo, tptr + 2));
         } else {
-            ND_PRINT((ndo, " AS #%s, origin %s",
+            ND_PRINT(" AS #%s, origin %s",
                       as_printf(ndo, astostr, sizeof(astostr),
-                      EXTRACT_BE_U_4(tptr)), ipaddr_string(ndo, tptr + 4)));
+                      EXTRACT_BE_U_4(tptr)), ipaddr_string(ndo, tptr + 4));
         }
         break;
     case BGPTYPE_AGGREGATOR4:
         if (len != 8) {
-            ND_PRINT((ndo, "invalid len"));
+            ND_PRINT("invalid len");
             break;
         }
         ND_TCHECK_8(tptr);
-        ND_PRINT((ndo, " AS #%s, origin %s",
+        ND_PRINT(" AS #%s, origin %s",
                   as_printf(ndo, astostr, sizeof(astostr), EXTRACT_BE_U_4(tptr)),
-                  ipaddr_string(ndo, tptr + 4)));
+                  ipaddr_string(ndo, tptr + 4));
         break;
     case BGPTYPE_COMMUNITIES:
         if (len % 4) {
-            ND_PRINT((ndo, "invalid len"));
+            ND_PRINT("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:
-                ND_PRINT((ndo, " NO_EXPORT"));
+                ND_PRINT(" NO_EXPORT");
                 break;
             case BGP_COMMUNITY_NO_ADVERT:
-                ND_PRINT((ndo, " NO_ADVERTISE"));
+                ND_PRINT(" NO_ADVERTISE");
                 break;
             case BGP_COMMUNITY_NO_EXPORT_SUBCONFED:
-                ND_PRINT((ndo, " NO_EXPORT_SUBCONFED"));
+                ND_PRINT(" NO_EXPORT_SUBCONFED");
                 break;
             default:
-                ND_PRINT((ndo, "%u:%u%s",
+                ND_PRINT("%u:%u%s",
                          (comm >> 16) & 0xffff,
                          comm & 0xffff,
-                         (tlen>4) ? ", " : ""));
+                         (tlen>4) ? ", " : "");
                 break;
             }
             tlen -=4;
@@ -1587,37 +1698,41 @@ bgp_attr_print(netdissect_options *ndo,
         break;
     case BGPTYPE_ORIGINATOR_ID:
         if (len != 4) {
-            ND_PRINT((ndo, "invalid len"));
+            ND_PRINT("invalid len");
             break;
         }
         ND_TCHECK_4(tptr);
-        ND_PRINT((ndo, "%s",ipaddr_string(ndo, tptr)));
+        ND_PRINT("%s",ipaddr_string(ndo, tptr));
         break;
     case BGPTYPE_CLUSTER_LIST:
         if (len % 4) {
-            ND_PRINT((ndo, "invalid len"));
+            ND_PRINT("invalid len");
             break;
         }
-        while (tlen>0) {
+        while (tlen != 0) {
             ND_TCHECK_4(tptr);
-            ND_PRINT((ndo, "%s%s",
+            if (tlen < 4)
+                goto trunc;
+            ND_PRINT("%s%s",
                       ipaddr_string(ndo, tptr),
-                      (tlen>4) ? ", " : ""));
+                      (tlen>4) ? ", " : "");
             tlen -=4;
             tptr +=4;
         }
         break;
     case BGPTYPE_MP_REACH_NLRI:
         ND_TCHECK_3(tptr);
+        if (tlen < 3)
+            goto trunc;
         af = EXTRACT_BE_U_2(tptr);
         safi = EXTRACT_U_1(tptr + 2);
 
-        ND_PRINT((ndo, "\n\t    AFI: %s (%u), %sSAFI: %s (%u)",
+        ND_PRINT("\n\t    AFI: %s (%u), %sSAFI: %s (%u)",
                   tok2str(af_values, "Unknown AFI", af),
                   af,
                   (safi>128) ? "vendor specific " : "", /* 128 is meanwhile wellknown */
                   tok2str(bgp_safi_values, "Unknown SAFI", safi),
-                  safi));
+                  safi);
 
         switch(af<<8 | safi) {
         case (AFNUM_INET<<8 | SAFNUM_UNICAST):
@@ -1650,7 +1765,7 @@ bgp_attr_print(netdissect_options *ndo,
             break;
         default:
             ND_TCHECK_LEN(tptr, tlen);
-            ND_PRINT((ndo, "\n\t    no AFI %u / SAFI %u decoder", af, safi));
+            ND_PRINT("\n\t    no AFI %u / SAFI %u decoder", af, safi);
             if (ndo->ndo_vflag <= 1)
                 print_unknown_data(ndo, tptr, "\n\t    ", tlen);
             goto done;
@@ -1666,10 +1781,10 @@ bgp_attr_print(netdissect_options *ndo,
 
         if (tlen) {
             u_int nnh = 0;
-            ND_PRINT((ndo, "\n\t    nexthop: "));
+            ND_PRINT("\n\t    nexthop: ");
             while (tlen != 0) {
                 if (nnh++ > 0) {
-                    ND_PRINT((ndo,  ", " ));
+                    ND_PRINT(", " );
                 }
                 switch(af<<8 | safi) {
                 case (AFNUM_INET<<8 | SAFNUM_UNICAST):
@@ -1679,81 +1794,81 @@ bgp_attr_print(netdissect_options *ndo,
                 case (AFNUM_INET<<8 | SAFNUM_RT_ROUTING_INFO):
                 case (AFNUM_INET<<8 | SAFNUM_MULTICAST_VPN):
                 case (AFNUM_INET<<8 | SAFNUM_MDT):
-                    if (tlen < sizeof(struct in_addr)) {
-                        ND_PRINT((ndo, "invalid len"));
+                    if (tlen < sizeof(nd_ipv4)) {
+                        ND_PRINT("invalid len");
                         tlen = 0;
                     } else {
-                        ND_TCHECK_LEN(tptr, sizeof(struct in_addr));
-                        ND_PRINT((ndo, "%s",ipaddr_string(ndo, tptr)));
-                        tlen -= sizeof(struct in_addr);
-                        tptr += sizeof(struct in_addr);
+                        ND_TCHECK_LEN(tptr, sizeof(nd_ipv4));
+                        ND_PRINT("%s",ipaddr_string(ndo, tptr));
+                        tlen -= sizeof(nd_ipv4);
+                        tptr += sizeof(nd_ipv4);
                     }
                     break;
                 case (AFNUM_INET<<8 | SAFNUM_VPNUNICAST):
                 case (AFNUM_INET<<8 | SAFNUM_VPNMULTICAST):
                 case (AFNUM_INET<<8 | SAFNUM_VPNUNIMULTICAST):
-                    if (tlen < sizeof(struct in_addr)+BGP_VPN_RD_LEN) {
-                        ND_PRINT((ndo, "invalid len"));
+                    if (tlen < sizeof(nd_ipv4)+BGP_VPN_RD_LEN) {
+                        ND_PRINT("invalid len");
                         tlen = 0;
                     } else {
                         ND_TCHECK_LEN(tptr,
-                                      sizeof(struct in_addr) + BGP_VPN_RD_LEN);
-                        ND_PRINT((ndo, "RD: %s, %s",
+                                      sizeof(nd_ipv4) + BGP_VPN_RD_LEN);
+                        ND_PRINT("RD: %s, %s",
                                   bgp_vpn_rd_print(ndo, tptr),
-                                  ipaddr_string(ndo, tptr+BGP_VPN_RD_LEN)));
-                        tlen -= (sizeof(struct in_addr)+BGP_VPN_RD_LEN);
-                        tptr += (sizeof(struct in_addr)+BGP_VPN_RD_LEN);
+                                  ipaddr_string(ndo, tptr+BGP_VPN_RD_LEN));
+                        tlen -= (sizeof(nd_ipv4)+BGP_VPN_RD_LEN);
+                        tptr += (sizeof(nd_ipv4)+BGP_VPN_RD_LEN);
                     }
                     break;
                 case (AFNUM_INET6<<8 | SAFNUM_UNICAST):
                 case (AFNUM_INET6<<8 | SAFNUM_MULTICAST):
                 case (AFNUM_INET6<<8 | SAFNUM_UNIMULTICAST):
                 case (AFNUM_INET6<<8 | SAFNUM_LABUNICAST):
-                    if (tlen < sizeof(struct in6_addr)) {
-                        ND_PRINT((ndo, "invalid len"));
+                    if (tlen < sizeof(nd_ipv6)) {
+                        ND_PRINT("invalid len");
                         tlen = 0;
                     } else {
-                        ND_TCHECK_LEN(tptr, sizeof(struct in6_addr));
-                        ND_PRINT((ndo, "%s", ip6addr_string(ndo, tptr)));
-                        tlen -= sizeof(struct in6_addr);
-                        tptr += sizeof(struct in6_addr);
+                        ND_TCHECK_LEN(tptr, sizeof(nd_ipv6));
+                        ND_PRINT("%s", ip6addr_string(ndo, tptr));
+                        tlen -= sizeof(nd_ipv6);
+                        tptr += sizeof(nd_ipv6);
                     }
                     break;
                 case (AFNUM_INET6<<8 | SAFNUM_VPNUNICAST):
                 case (AFNUM_INET6<<8 | SAFNUM_VPNMULTICAST):
                 case (AFNUM_INET6<<8 | SAFNUM_VPNUNIMULTICAST):
-                    if (tlen < sizeof(struct in6_addr)+BGP_VPN_RD_LEN) {
-                        ND_PRINT((ndo, "invalid len"));
+                    if (tlen < sizeof(nd_ipv6)+BGP_VPN_RD_LEN) {
+                        ND_PRINT("invalid len");
                         tlen = 0;
                     } else {
                         ND_TCHECK_LEN(tptr,
-                                      sizeof(struct in6_addr) + BGP_VPN_RD_LEN);
-                        ND_PRINT((ndo, "RD: %s, %s",
+                                      sizeof(nd_ipv6) + BGP_VPN_RD_LEN);
+                        ND_PRINT("RD: %s, %s",
                                   bgp_vpn_rd_print(ndo, tptr),
-                                  ip6addr_string(ndo, tptr+BGP_VPN_RD_LEN)));
-                        tlen -= (sizeof(struct in6_addr)+BGP_VPN_RD_LEN);
-                        tptr += (sizeof(struct in6_addr)+BGP_VPN_RD_LEN);
+                                  ip6addr_string(ndo, tptr+BGP_VPN_RD_LEN));
+                        tlen -= (sizeof(nd_ipv6)+BGP_VPN_RD_LEN);
+                        tptr += (sizeof(nd_ipv6)+BGP_VPN_RD_LEN);
                     }
                     break;
                 case (AFNUM_VPLS<<8 | SAFNUM_VPLS):
                 case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNICAST):
                 case (AFNUM_L2VPN<<8 | SAFNUM_VPNMULTICAST):
                 case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNIMULTICAST):
-                    if (tlen < sizeof(struct in_addr)) {
-                        ND_PRINT((ndo, "invalid len"));
+                    if (tlen < sizeof(nd_ipv4)) {
+                        ND_PRINT("invalid len");
                         tlen = 0;
                     } else {
-                        ND_TCHECK_LEN(tptr, sizeof(struct in_addr));
-                        ND_PRINT((ndo, "%s", ipaddr_string(ndo, tptr)));
-                        tlen -= (sizeof(struct in_addr));
-                        tptr += (sizeof(struct in_addr));
+                        ND_TCHECK_LEN(tptr, sizeof(nd_ipv4));
+                        ND_PRINT("%s", ipaddr_string(ndo, tptr));
+                        tlen -= (sizeof(nd_ipv4));
+                        tptr += (sizeof(nd_ipv4));
                     }
                     break;
                 case (AFNUM_NSAP<<8 | SAFNUM_UNICAST):
                 case (AFNUM_NSAP<<8 | SAFNUM_MULTICAST):
                 case (AFNUM_NSAP<<8 | SAFNUM_UNIMULTICAST):
                     ND_TCHECK_LEN(tptr, tlen);
-                    ND_PRINT((ndo, "%s", isonsap_string(ndo, tptr, tlen)));
+                    ND_PRINT("%s", isonsap_string(ndo, tptr, tlen));
                     tptr += tlen;
                     tlen = 0;
                     break;
@@ -1762,26 +1877,26 @@ bgp_attr_print(netdissect_options *ndo,
                 case (AFNUM_NSAP<<8 | SAFNUM_VPNMULTICAST):
                 case (AFNUM_NSAP<<8 | SAFNUM_VPNUNIMULTICAST):
                     if (tlen < BGP_VPN_RD_LEN+1) {
-                        ND_PRINT((ndo, "invalid len"));
+                        ND_PRINT("invalid len");
                         tlen = 0;
                     } else {
                         ND_TCHECK_LEN(tptr, tlen);
-                        ND_PRINT((ndo, "RD: %s, %s",
+                        ND_PRINT("RD: %s, %s",
                                   bgp_vpn_rd_print(ndo, tptr),
-                                  isonsap_string(ndo, tptr+BGP_VPN_RD_LEN,tlen-BGP_VPN_RD_LEN)));
+                                  isonsap_string(ndo, tptr+BGP_VPN_RD_LEN,tlen-BGP_VPN_RD_LEN));
                         /* rfc986 mapped IPv4 address ? */
                         if (EXTRACT_BE_U_4(tptr + BGP_VPN_RD_LEN) ==  0x47000601)
-                            ND_PRINT((ndo, " = %s", ipaddr_string(ndo, tptr+BGP_VPN_RD_LEN+4)));
+                            ND_PRINT(" = %s", ipaddr_string(ndo, tptr+BGP_VPN_RD_LEN+4));
                         /* rfc1888 mapped IPv6 address ? */
                         else if (EXTRACT_BE_U_3(tptr + BGP_VPN_RD_LEN) ==  0x350000)
-                            ND_PRINT((ndo, " = %s", ip6addr_string(ndo, tptr+BGP_VPN_RD_LEN+3)));
+                            ND_PRINT(" = %s", ip6addr_string(ndo, tptr+BGP_VPN_RD_LEN+3));
                         tptr += tlen;
                         tlen = 0;
                     }
                     break;
                 default:
                     ND_TCHECK_LEN(tptr, tlen);
-                    ND_PRINT((ndo, "no AFI %u/SAFI %u decoder", af, safi));
+                    ND_PRINT("no AFI %u/SAFI %u decoder", af, safi);
                     if (ndo->ndo_vflag <= 1)
                         print_unknown_data(ndo, tptr, "\n\t    ", tlen);
                     tptr += tlen;
@@ -1791,7 +1906,7 @@ bgp_attr_print(netdissect_options *ndo,
                 }
             }
         }
-        ND_PRINT((ndo, ", nh-length: %u", nhlen));
+        ND_PRINT(", nh-length: %u", nhlen);
         tptr += tlen;
 
         ND_TCHECK_1(tptr);
@@ -1799,18 +1914,18 @@ bgp_attr_print(netdissect_options *ndo,
         tptr++;
 
         if (snpa) {
-            ND_PRINT((ndo, "\n\t    %u SNPA", snpa));
-            for (/*nothing*/; snpa > 0; snpa--) {
+            ND_PRINT("\n\t    %u SNPA", snpa);
+            for (/*nothing*/; snpa != 0; snpa--) {
                 ND_TCHECK_1(tptr);
-                ND_PRINT((ndo, "\n\t      %u bytes", EXTRACT_U_1(tptr)));
+                ND_PRINT("\n\t      %u bytes", EXTRACT_U_1(tptr));
                 tptr += EXTRACT_U_1(tptr) + 1;
             }
         } else {
-            ND_PRINT((ndo, ", no SNPA"));
+            ND_PRINT(", 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);
+        add_path6 = check_add_path(ndo, tptr, (len-(tptr - pptr)), 128);
 
         while (tptr < pptr + len) {
             switch (af<<8 | safi) {
@@ -1823,67 +1938,63 @@ bgp_attr_print(netdissect_options *ndo,
                 }
                 advance = decode_prefix4(ndo, tptr, len, buf, sizeof(buf));
                 if (advance == -1)
-                    ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
+                    ND_PRINT("\n\t    (illegal prefix length)");
                 else if (advance == -2)
                     goto trunc;
                 else if (advance == -3)
                     break; /* bytes left, but not enough */
                 else
-                    ND_PRINT((ndo, "\n\t      %s", buf));
+                    ND_PRINT("\n\t      %s", buf);
                 if (add_path4) {
-                    ND_PRINT((ndo, "   Path Id: %u", path_id));
+                    ND_PRINT("   Path Id: %u", path_id);
                 }
                 break;
             case (AFNUM_INET<<8 | SAFNUM_LABUNICAST):
                 advance = decode_labeled_prefix4(ndo, tptr, len, buf, sizeof(buf));
                 if (advance == -1)
-                    ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
+                    ND_PRINT("\n\t    (illegal prefix length)");
                 else if (advance == -2)
                     goto trunc;
                 else if (advance == -3)
                     break; /* bytes left, but not enough */
                 else
-                    ND_PRINT((ndo, "\n\t      %s", buf));
+                    ND_PRINT("\n\t      %s", buf);
                 break;
             case (AFNUM_INET<<8 | SAFNUM_VPNUNICAST):
             case (AFNUM_INET<<8 | SAFNUM_VPNMULTICAST):
             case (AFNUM_INET<<8 | SAFNUM_VPNUNIMULTICAST):
                 advance = decode_labeled_vpn_prefix4(ndo, tptr, buf, sizeof(buf));
                 if (advance == -1)
-                    ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
+                    ND_PRINT("\n\t    (illegal prefix length)");
                 else if (advance == -2)
                     goto trunc;
                 else
-                    ND_PRINT((ndo, "\n\t      %s", buf));
+                    ND_PRINT("\n\t      %s", buf);
                 break;
             case (AFNUM_INET<<8 | SAFNUM_RT_ROUTING_INFO):
-                advance = decode_rt_routing_info(ndo, tptr, buf, sizeof(buf));
-                if (advance == -1)
-                    ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
-                else if (advance == -2)
+                advance = decode_rt_routing_info(ndo, tptr);
+                if (advance == -2)
                     goto trunc;
-                else
-                    ND_PRINT((ndo, "\n\t      %s", buf));
                 break;
             case (AFNUM_INET<<8 | SAFNUM_MULTICAST_VPN): /* fall through */
             case (AFNUM_INET6<<8 | SAFNUM_MULTICAST_VPN):
                 advance = decode_multicast_vpn(ndo, tptr, buf, sizeof(buf));
                 if (advance == -1)
-                    ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
+                    ND_PRINT("\n\t    (illegal prefix length)");
                 else if (advance == -2)
                     goto trunc;
                 else
-                    ND_PRINT((ndo, "\n\t      %s", buf));
+                    ND_PRINT("\n\t      %s", buf);
                 break;
 
             case (AFNUM_INET<<8 | SAFNUM_MDT):
                 advance = decode_mdt_vpn_nlri(ndo, tptr, buf, sizeof(buf));
                 if (advance == -1)
-                    ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
+                    ND_PRINT("\n\t    (illegal prefix length)");
                 else if (advance == -2)
                     goto trunc;
                 else
-                    ND_PRINT((ndo, "\n\t      %s", buf));
+                    ND_PRINT("\n\t      %s", buf);
                 break;
             case (AFNUM_INET6<<8 | SAFNUM_UNICAST):
             case (AFNUM_INET6<<8 | SAFNUM_MULTICAST):
@@ -1894,38 +2005,38 @@ bgp_attr_print(netdissect_options *ndo,
                 }
                 advance = decode_prefix6(ndo, tptr, len, buf, sizeof(buf));
                 if (advance == -1)
-                    ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
+                    ND_PRINT("\n\t    (illegal prefix length)");
                 else if (advance == -2)
                     goto trunc;
                 else if (advance == -3)
                     break; /* bytes left, but not enough */
                 else
-                    ND_PRINT((ndo, "\n\t      %s", buf));
+                    ND_PRINT("\n\t      %s", buf);
                 if (add_path6) {
-                    ND_PRINT((ndo, "   Path Id: %u", path_id));
+                    ND_PRINT("   Path Id: %u", path_id);
                 }
                 break;
             case (AFNUM_INET6<<8 | SAFNUM_LABUNICAST):
                 advance = decode_labeled_prefix6(ndo, tptr, len, buf, sizeof(buf));
                 if (advance == -1)
-                    ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
+                    ND_PRINT("\n\t    (illegal prefix length)");
                 else if (advance == -2)
                     goto trunc;
                 else if (advance == -3)
                     break; /* bytes left, but not enough */
                 else
-                    ND_PRINT((ndo, "\n\t      %s", buf));
+                    ND_PRINT("\n\t      %s", buf);
                 break;
             case (AFNUM_INET6<<8 | SAFNUM_VPNUNICAST):
             case (AFNUM_INET6<<8 | SAFNUM_VPNMULTICAST):
             case (AFNUM_INET6<<8 | SAFNUM_VPNUNIMULTICAST):
                 advance = decode_labeled_vpn_prefix6(ndo, tptr, buf, sizeof(buf));
                 if (advance == -1)
-                    ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
+                    ND_PRINT("\n\t    (illegal prefix length)");
                 else if (advance == -2)
                     goto trunc;
                 else
-                    ND_PRINT((ndo, "\n\t      %s", buf));
+                    ND_PRINT("\n\t      %s", buf);
                 break;
             case (AFNUM_VPLS<<8 | SAFNUM_VPLS):
             case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNICAST):
@@ -1933,37 +2044,37 @@ bgp_attr_print(netdissect_options *ndo,
             case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNIMULTICAST):
                 advance = decode_labeled_vpn_l2(ndo, tptr, buf, sizeof(buf));
                 if (advance == -1)
-                    ND_PRINT((ndo, "\n\t    (illegal length)"));
+                    ND_PRINT("\n\t    (illegal length)");
                 else if (advance == -2)
                     goto trunc;
                 else
-                    ND_PRINT((ndo, "\n\t      %s", buf));
+                    ND_PRINT("\n\t      %s", buf);
                 break;
             case (AFNUM_NSAP<<8 | SAFNUM_UNICAST):
             case (AFNUM_NSAP<<8 | SAFNUM_MULTICAST):
             case (AFNUM_NSAP<<8 | SAFNUM_UNIMULTICAST):
                 advance = decode_clnp_prefix(ndo, tptr, buf, sizeof(buf));
                 if (advance == -1)
-                    ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
+                    ND_PRINT("\n\t    (illegal prefix length)");
                 else if (advance == -2)
                     goto trunc;
                 else
-                    ND_PRINT((ndo, "\n\t      %s", buf));
+                    ND_PRINT("\n\t      %s", buf);
                 break;
             case (AFNUM_NSAP<<8 | SAFNUM_VPNUNICAST):
             case (AFNUM_NSAP<<8 | SAFNUM_VPNMULTICAST):
             case (AFNUM_NSAP<<8 | SAFNUM_VPNUNIMULTICAST):
                 advance = decode_labeled_vpn_clnp_prefix(ndo, tptr, buf, sizeof(buf));
                 if (advance == -1)
-                    ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
+                    ND_PRINT("\n\t    (illegal prefix length)");
                 else if (advance == -2)
                     goto trunc;
                 else
-                    ND_PRINT((ndo, "\n\t      %s", buf));
+                    ND_PRINT("\n\t      %s", buf);
                 break;
             default:
                 ND_TCHECK_LEN(tptr, tlen);
-                ND_PRINT((ndo, "\n\t    no AFI %u / SAFI %u decoder", af, safi));
+                ND_PRINT("\n\t    no AFI %u / SAFI %u decoder", af, safi);
                 if (ndo->ndo_vflag <= 1)
                     print_unknown_data(ndo, tptr, "\n\t    ", tlen);
                 advance = 0;
@@ -1982,20 +2093,20 @@ bgp_attr_print(netdissect_options *ndo,
         af = EXTRACT_BE_U_2(tptr);
         safi = EXTRACT_U_1(tptr + 2);
 
-        ND_PRINT((ndo, "\n\t    AFI: %s (%u), %sSAFI: %s (%u)",
+        ND_PRINT("\n\t    AFI: %s (%u), %sSAFI: %s (%u)",
                   tok2str(af_values, "Unknown AFI", af),
                   af,
                   (safi>128) ? "vendor specific " : "", /* 128 is meanwhile wellknown */
                   tok2str(bgp_safi_values, "Unknown SAFI", safi),
-                  safi));
+                  safi);
 
         if (len == BGP_MP_NLRI_MINSIZE)
-            ND_PRINT((ndo, "\n\t      End-of-Rib Marker (empty NLRI)"));
+            ND_PRINT("\n\t      End-of-Rib Marker (empty NLRI)");
 
         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);
+        add_path6 = check_add_path(ndo, tptr, (len-(tptr - pptr)), 128);
 
         while (tptr < pptr + len) {
             switch (af<<8 | safi) {
@@ -2008,38 +2119,38 @@ bgp_attr_print(netdissect_options *ndo,
                 }
                 advance = decode_prefix4(ndo, tptr, len, buf, sizeof(buf));
                 if (advance == -1)
-                    ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
+                    ND_PRINT("\n\t    (illegal prefix length)");
                 else if (advance == -2)
                     goto trunc;
                 else if (advance == -3)
                     break; /* bytes left, but not enough */
                 else
-                    ND_PRINT((ndo, "\n\t      %s", buf));
+                    ND_PRINT("\n\t      %s", buf);
                 if (add_path4) {
-                    ND_PRINT((ndo, "   Path Id: %u", path_id));
+                    ND_PRINT("   Path Id: %u", path_id);
                 }
                 break;
             case (AFNUM_INET<<8 | SAFNUM_LABUNICAST):
                 advance = decode_labeled_prefix4(ndo, tptr, len, buf, sizeof(buf));
                 if (advance == -1)
-                    ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
+                    ND_PRINT("\n\t    (illegal prefix length)");
                 else if (advance == -2)
                     goto trunc;
                 else if (advance == -3)
                     break; /* bytes left, but not enough */
                 else
-                    ND_PRINT((ndo, "\n\t      %s", buf));
+                    ND_PRINT("\n\t      %s", buf);
                 break;
             case (AFNUM_INET<<8 | SAFNUM_VPNUNICAST):
             case (AFNUM_INET<<8 | SAFNUM_VPNMULTICAST):
             case (AFNUM_INET<<8 | SAFNUM_VPNUNIMULTICAST):
                 advance = decode_labeled_vpn_prefix4(ndo, tptr, buf, sizeof(buf));
                 if (advance == -1)
-                    ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
+                    ND_PRINT("\n\t    (illegal prefix length)");
                 else if (advance == -2)
                     goto trunc;
                 else
-                    ND_PRINT((ndo, "\n\t      %s", buf));
+                    ND_PRINT("\n\t      %s", buf);
                 break;
             case (AFNUM_INET6<<8 | SAFNUM_UNICAST):
             case (AFNUM_INET6<<8 | SAFNUM_MULTICAST):
@@ -2050,38 +2161,38 @@ bgp_attr_print(netdissect_options *ndo,
                 }
                 advance = decode_prefix6(ndo, tptr, len, buf, sizeof(buf));
                 if (advance == -1)
-                    ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
+                    ND_PRINT("\n\t    (illegal prefix length)");
                 else if (advance == -2)
                     goto trunc;
                 else if (advance == -3)
                     break; /* bytes left, but not enough */
                 else
-                    ND_PRINT((ndo, "\n\t      %s", buf));
+                    ND_PRINT("\n\t      %s", buf);
                 if (add_path6) {
-                    ND_PRINT((ndo, "   Path Id: %u", path_id));
+                    ND_PRINT("   Path Id: %u", path_id);
                 }
                 break;
             case (AFNUM_INET6<<8 | SAFNUM_LABUNICAST):
                 advance = decode_labeled_prefix6(ndo, tptr, len, buf, sizeof(buf));
                 if (advance == -1)
-                    ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
+                    ND_PRINT("\n\t    (illegal prefix length)");
                 else if (advance == -2)
                     goto trunc;
                 else if (advance == -3)
                     break; /* bytes left, but not enough */
                 else
-                    ND_PRINT((ndo, "\n\t      %s", buf));
+                    ND_PRINT("\n\t      %s", buf);
                 break;
             case (AFNUM_INET6<<8 | SAFNUM_VPNUNICAST):
             case (AFNUM_INET6<<8 | SAFNUM_VPNMULTICAST):
             case (AFNUM_INET6<<8 | SAFNUM_VPNUNIMULTICAST):
                 advance = decode_labeled_vpn_prefix6(ndo, tptr, buf, sizeof(buf));
                 if (advance == -1)
-                    ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
+                    ND_PRINT("\n\t    (illegal prefix length)");
                 else if (advance == -2)
                     goto trunc;
                 else
-                    ND_PRINT((ndo, "\n\t      %s", buf));
+                    ND_PRINT("\n\t      %s", buf);
                 break;
             case (AFNUM_VPLS<<8 | SAFNUM_VPLS):
             case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNICAST):
@@ -2089,56 +2200,56 @@ bgp_attr_print(netdissect_options *ndo,
             case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNIMULTICAST):
                 advance = decode_labeled_vpn_l2(ndo, tptr, buf, sizeof(buf));
                 if (advance == -1)
-                    ND_PRINT((ndo, "\n\t    (illegal length)"));
+                    ND_PRINT("\n\t    (illegal length)");
                 else if (advance == -2)
                     goto trunc;
                 else
-                    ND_PRINT((ndo, "\n\t      %s", buf));
+                    ND_PRINT("\n\t      %s", buf);
                 break;
             case (AFNUM_NSAP<<8 | SAFNUM_UNICAST):
             case (AFNUM_NSAP<<8 | SAFNUM_MULTICAST):
             case (AFNUM_NSAP<<8 | SAFNUM_UNIMULTICAST):
                 advance = decode_clnp_prefix(ndo, tptr, buf, sizeof(buf));
                 if (advance == -1)
-                    ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
+                    ND_PRINT("\n\t    (illegal prefix length)");
                 else if (advance == -2)
                     goto trunc;
                 else
-                    ND_PRINT((ndo, "\n\t      %s", buf));
+                    ND_PRINT("\n\t      %s", buf);
                 break;
             case (AFNUM_NSAP<<8 | SAFNUM_VPNUNICAST):
             case (AFNUM_NSAP<<8 | SAFNUM_VPNMULTICAST):
             case (AFNUM_NSAP<<8 | SAFNUM_VPNUNIMULTICAST):
                 advance = decode_labeled_vpn_clnp_prefix(ndo, tptr, buf, sizeof(buf));
                 if (advance == -1)
-                    ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
+                    ND_PRINT("\n\t    (illegal prefix length)");
                 else if (advance == -2)
                     goto trunc;
                 else
-                    ND_PRINT((ndo, "\n\t      %s", buf));
+                    ND_PRINT("\n\t      %s", buf);
                 break;
             case (AFNUM_INET<<8 | SAFNUM_MDT):
                 advance = decode_mdt_vpn_nlri(ndo, tptr, buf, sizeof(buf));
                 if (advance == -1)
-                    ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
+                    ND_PRINT("\n\t    (illegal prefix length)");
                 else if (advance == -2)
                     goto trunc;
                 else
-                    ND_PRINT((ndo, "\n\t      %s", buf));
+                    ND_PRINT("\n\t      %s", buf);
                 break;
             case (AFNUM_INET<<8 | SAFNUM_MULTICAST_VPN): /* fall through */
             case (AFNUM_INET6<<8 | SAFNUM_MULTICAST_VPN):
                 advance = decode_multicast_vpn(ndo, tptr, buf, sizeof(buf));
                 if (advance == -1)
-                    ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
+                    ND_PRINT("\n\t    (illegal prefix length)");
                 else if (advance == -2)
                     goto trunc;
                 else
-                    ND_PRINT((ndo, "\n\t      %s", buf));
+                    ND_PRINT("\n\t      %s", buf);
                 break;
             default:
                 ND_TCHECK_LEN(tptr - 3, tlen);
-                ND_PRINT((ndo, "no AFI %u / SAFI %u decoder", af, safi));
+                ND_PRINT("no AFI %u / SAFI %u decoder", af, safi);
                 if (ndo->ndo_vflag <= 1)
                     print_unknown_data(ndo, tptr-3, "\n\t    ", tlen);
                 advance = 0;
@@ -2152,85 +2263,29 @@ bgp_attr_print(netdissect_options *ndo,
         break;
     case BGPTYPE_EXTD_COMMUNITIES:
         if (len % 8) {
-            ND_PRINT((ndo, "invalid len"));
+            ND_PRINT("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]",
+            ND_PRINT("\n\t    %s (0x%04x), Flags [%s]",
                       tok2str(bgp_extd_comm_subtype_values,
                               "unknown extd community typecode",
                               extd_comm),
                       extd_comm,
-                      bittok2str(bgp_extd_comm_flag_values, "none", extd_comm)));
-
-            ND_TCHECK_6(tptr + 2);
-            switch(extd_comm) {
-            case BGP_EXT_COM_RT_0:
-            case BGP_EXT_COM_RO_0:
-            case BGP_EXT_COM_L2VPN_RT_0:
-                ND_PRINT((ndo, ": %u:%u (= %s)",
-                          EXTRACT_BE_U_2(tptr + 2),
-                          EXTRACT_BE_U_4(tptr + 4),
-                          ipaddr_string(ndo, tptr+4)));
-                break;
-            case BGP_EXT_COM_RT_1:
-            case BGP_EXT_COM_RO_1:
-            case BGP_EXT_COM_L2VPN_RT_1:
-            case BGP_EXT_COM_VRF_RT_IMP:
-                ND_PRINT((ndo, ": %s:%u",
-                          ipaddr_string(ndo, tptr+2),
-                          EXTRACT_BE_U_2(tptr + 6)));
-                break;
-            case BGP_EXT_COM_RT_2:
-            case BGP_EXT_COM_RO_2:
-                ND_PRINT((ndo, ": %s:%u",
-                          as_printf(ndo, astostr, sizeof(astostr),
-                          EXTRACT_BE_U_4(tptr + 2)), EXTRACT_BE_U_2(tptr + 6)));
-                break;
-            case BGP_EXT_COM_LINKBAND:
-                bw.i = EXTRACT_BE_U_4(tptr + 2);
-                ND_PRINT((ndo, ": bandwidth: %.3f Mbps",
-                          bw.f*8/1000000));
-                break;
-            case BGP_EXT_COM_VPN_ORIGIN:
-            case BGP_EXT_COM_VPN_ORIGIN2:
-            case BGP_EXT_COM_VPN_ORIGIN3:
-            case BGP_EXT_COM_VPN_ORIGIN4:
-            case BGP_EXT_COM_OSPF_RID:
-            case BGP_EXT_COM_OSPF_RID2:
-                ND_PRINT((ndo, "%s", ipaddr_string(ndo, tptr+2)));
-                break;
-            case BGP_EXT_COM_OSPF_RTYPE:
-            case BGP_EXT_COM_OSPF_RTYPE2:
-                ND_PRINT((ndo, ": area:%s, router-type:%s, metric-type:%s%s",
-                          ipaddr_string(ndo, tptr+2),
-                          tok2str(bgp_extd_comm_ospf_rtype_values,
-                                  "unknown (0x%02x)",
-                                  EXTRACT_U_1((tptr + 6))),
-                          (EXTRACT_U_1(tptr + 7) &  BGP_OSPF_RTYPE_METRIC_TYPE) ? "E2" : "",
-                          ((EXTRACT_U_1(tptr + 6) == BGP_OSPF_RTYPE_EXT) || (EXTRACT_U_1(tptr + 6) == BGP_OSPF_RTYPE_NSSA)) ? "E1" : ""));
-                break;
-            case BGP_EXT_COM_L2INFO:
-                ND_PRINT((ndo, ": %s Control Flags [0x%02x]:MTU %u",
-                          tok2str(l2vpn_encaps_values,
-                                  "unknown encaps",
-                                  EXTRACT_U_1((tptr + 2))),
-                          EXTRACT_U_1((tptr + 3)),
-                          EXTRACT_BE_U_2(tptr + 4)));
-                break;
-            case BGP_EXT_COM_SOURCE_AS:
-                ND_PRINT((ndo, ": AS %u", EXTRACT_BE_U_2(tptr + 2)));
-                break;
-            default:
-                ND_TCHECK_8(tptr);
-                print_unknown_data(ndo, tptr, "\n\t      ", 8);
-                break;
-            }
+                      bittok2str(bgp_extd_comm_flag_values, "none", extd_comm));
+
+            ND_TCHECK_8(tptr);
+            if (tlen < 8)
+                goto trunc;
+            ND_PRINT(": ");
+            bgp_extended_community_print(ndo, tptr);
             tlen -= 8;
             tptr += 8;
         }
@@ -2241,15 +2296,17 @@ bgp_attr_print(netdissect_options *ndo,
         uint8_t tunnel_type, flags;
 
         ND_TCHECK_5(tptr);
+        if (tlen < 5)
+            goto trunc;
         flags = EXTRACT_U_1(tptr);
         tunnel_type = EXTRACT_U_1(tptr + 1);
         tlen = len;
 
-        ND_PRINT((ndo, "\n\t    Tunnel-type %s (%u), Flags [%s], MPLS Label %u",
+        ND_PRINT("\n\t    Tunnel-type %s (%u), Flags [%s], MPLS Label %u",
                   tok2str(bgp_pmsi_tunnel_values, "Unknown", tunnel_type),
                   tunnel_type,
                   bittok2str(bgp_pmsi_flag_values, "none", flags),
-                  EXTRACT_BE_U_3(tptr + 2)>>4));
+                  EXTRACT_BE_U_3(tptr + 2)>>4);
 
         tptr +=5;
         tlen -= 5;
@@ -2258,34 +2315,34 @@ bgp_attr_print(netdissect_options *ndo,
         case BGP_PMSI_TUNNEL_PIM_SM: /* fall through */
         case BGP_PMSI_TUNNEL_PIM_BIDIR:
             ND_TCHECK_8(tptr);
-            ND_PRINT((ndo, "\n\t      Sender %s, P-Group %s",
+            ND_PRINT("\n\t      Sender %s, P-Group %s",
                       ipaddr_string(ndo, tptr),
-                      ipaddr_string(ndo, tptr+4)));
+                      ipaddr_string(ndo, tptr+4));
             break;
 
         case BGP_PMSI_TUNNEL_PIM_SSM:
             ND_TCHECK_8(tptr);
-            ND_PRINT((ndo, "\n\t      Root-Node %s, P-Group %s",
+            ND_PRINT("\n\t      Root-Node %s, P-Group %s",
                       ipaddr_string(ndo, tptr),
-                      ipaddr_string(ndo, tptr+4)));
+                      ipaddr_string(ndo, tptr+4));
             break;
         case BGP_PMSI_TUNNEL_INGRESS:
             ND_TCHECK_4(tptr);
-            ND_PRINT((ndo, "\n\t      Tunnel-Endpoint %s",
-                      ipaddr_string(ndo, tptr)));
+            ND_PRINT("\n\t      Tunnel-Endpoint %s",
+                      ipaddr_string(ndo, tptr));
             break;
         case BGP_PMSI_TUNNEL_LDP_P2MP: /* fall through */
         case BGP_PMSI_TUNNEL_LDP_MP2MP:
             ND_TCHECK_8(tptr);
-            ND_PRINT((ndo, "\n\t      Root-Node %s, LSP-ID 0x%08x",
+            ND_PRINT("\n\t      Root-Node %s, LSP-ID 0x%08x",
                       ipaddr_string(ndo, tptr),
-                      EXTRACT_BE_U_4(tptr + 4)));
+                      EXTRACT_BE_U_4(tptr + 4));
             break;
         case BGP_PMSI_TUNNEL_RSVP_P2MP:
             ND_TCHECK_8(tptr);
-            ND_PRINT((ndo, "\n\t      Extended-Tunnel-ID %s, P2MP-ID 0x%08x",
+            ND_PRINT("\n\t      Extended-Tunnel-ID %s, P2MP-ID 0x%08x",
                       ipaddr_string(ndo, tptr),
-                      EXTRACT_BE_U_4(tptr + 4)));
+                      EXTRACT_BE_U_4(tptr + 4));
             break;
         default:
             if (ndo->ndo_vflag <= 1) {
@@ -2310,9 +2367,9 @@ bgp_attr_print(netdissect_options *ndo,
             tptr += 3;
             tlen -= 3;
 
-            ND_PRINT((ndo, "\n\t    %s TLV (%u), length %u",
+            ND_PRINT("\n\t    %s TLV (%u), length %u",
                       tok2str(bgp_aigp_values, "Unknown", type),
-                      type, length));
+                      type, length);
 
             if (length < 3)
                 goto trunc;
@@ -2322,14 +2379,16 @@ bgp_attr_print(netdissect_options *ndo,
              * Check if we can read the TLV data.
              */
             ND_TCHECK_LEN(tptr + 3, length);
+            if (tlen < length)
+                goto trunc;
 
             switch (type) {
 
             case BGP_AIGP_TLV:
                 if (length < 8)
                     goto trunc;
-                ND_PRINT((ndo, ", metric %" PRIu64,
-                          EXTRACT_BE_U_8(tptr)));
+                ND_PRINT(", metric %" PRIu64,
+                          EXTRACT_BE_U_8(tptr));
                 break;
 
             default:
@@ -2347,8 +2406,8 @@ bgp_attr_print(netdissect_options *ndo,
         ND_TCHECK_4(tptr);
         if (len < 4)
             goto trunc;
-        ND_PRINT((ndo, "\n\t    Origin AS: %s",
-                  as_printf(ndo, astostr, sizeof(astostr), EXTRACT_BE_U_4(tptr))));
+        ND_PRINT("\n\t    Origin AS: %s",
+                  as_printf(ndo, astostr, sizeof(astostr), EXTRACT_BE_U_4(tptr)));
         tptr += 4;
         len -= 4;
 
@@ -2356,35 +2415,47 @@ bgp_attr_print(netdissect_options *ndo,
             u_int aflags, alenlen, alen;
 
             ND_TCHECK_2(tptr);
-            if (len < 2)
-                goto trunc;
+            if (len < 2) {
+                ND_PRINT(" [path attr too short]");
+                tptr += len;
+                break;
+            }
             aflags = EXTRACT_U_1(tptr);
             atype = EXTRACT_U_1(tptr + 1);
             tptr += 2;
             len -= 2;
             alenlen = bgp_attr_lenlen(aflags, tptr);
             ND_TCHECK_LEN(tptr, alenlen);
-            if (len < alenlen)
-                goto trunc;
+            if (len < alenlen) {
+                ND_PRINT(" [path attr too short]");
+                tptr += len;
+                break;
+            }
             alen = bgp_attr_len(aflags, tptr);
             tptr += alenlen;
             len -= alenlen;
 
-            ND_PRINT((ndo, "\n\t      %s (%u), length: %u",
+            ND_PRINT("\n\t      %s (%u), length: %u",
                       tok2str(bgp_attr_values,
                               "Unknown Attribute", atype),
                       atype,
-                      alen));
+                      alen);
 
             if (aflags) {
-                ND_PRINT((ndo, ", Flags [%s%s%s%s",
+                ND_PRINT(", Flags [%s%s%s%s",
                           aflags & 0x80 ? "O" : "",
                           aflags & 0x40 ? "T" : "",
                           aflags & 0x20 ? "P" : "",
-                          aflags & 0x10 ? "E" : ""));
+                          aflags & 0x10 ? "E" : "");
                 if (aflags & 0xf)
-                    ND_PRINT((ndo, "+%x", aflags & 0xf));
-                ND_PRINT((ndo, "]: "));
+                    ND_PRINT("+%x", aflags & 0xf);
+                ND_PRINT("]");
+            }
+            ND_PRINT(": ");
+            if (len < alen) {
+                ND_PRINT(" [path attr too short]");
+                tptr += len;
+                break;
             }
             /* FIXME check for recursion */
             if (!bgp_attr_print(ndo, atype, tptr, alen))
@@ -2396,24 +2467,28 @@ bgp_attr_print(netdissect_options *ndo,
 
     case BGPTYPE_LARGE_COMMUNITY:
         if (len == 0 || len % 12) {
-            ND_PRINT((ndo, "invalid len"));
+            ND_PRINT("invalid len");
             break;
         }
-        ND_PRINT((ndo, "\n\t    "));
-        while (len > 0) {
+        ND_PRINT("\n\t    ");
+        while (len != 0) {
             ND_TCHECK_LEN(tptr, 12);
-            ND_PRINT((ndo, "%u:%u:%u%s",
+            ND_PRINT("%u:%u:%u%s",
                       EXTRACT_BE_U_4(tptr),
                       EXTRACT_BE_U_4(tptr + 4),
                       EXTRACT_BE_U_4(tptr + 8),
-                      (len > 12) ? ", " : ""));
+                      (len > 12) ? ", " : "");
             tptr += 12;
+            /*
+             * len will always be a multiple of 12, as per the above,
+             * so this will never underflow.
+             */
             len -= 12;
         }
         break;
     default:
         ND_TCHECK_LEN(pptr, len);
-        ND_PRINT((ndo, "\n\t    no Attribute %u decoder", atype)); /* we have no decoder for the attribute */
+        ND_PRINT("\n\t    no Attribute %u decoder", atype); /* we have no decoder for the attribute */
         if (ndo->ndo_vflag <= 1)
             print_unknown_data(ndo, pptr, "\n\t    ", len);
         break;
@@ -2439,35 +2514,45 @@ bgp_capabilities_print(netdissect_options *ndo,
         ND_TCHECK_LEN(opt + i, BGP_CAP_HEADER_SIZE);
         cap_type=EXTRACT_U_1(opt + i);
         cap_len=EXTRACT_U_1(opt + i + 1);
-        tcap_len=cap_len;
-        ND_PRINT((ndo, "\n\t      %s (%u), length: %u",
+        ND_PRINT("\n\t      %s (%u), length: %u",
                   tok2str(bgp_capcode_values, "Unknown", cap_type),
                   cap_type,
-                  cap_len));
+                  cap_len);
         ND_TCHECK_LEN(opt + 2 + i, cap_len);
         switch (cap_type) {
         case BGP_CAPCODE_MP:
-            ND_PRINT((ndo, "\n\t\tAFI %s (%u), SAFI %s (%u)",
+            /* AFI (16 bits), Reserved (8 bits), SAFI (8 bits) */
+            if (cap_len < 4) {
+                ND_PRINT(" (too short, < 4)");
+                return;
+            }
+            ND_PRINT("\n\t\tAFI %s (%u), SAFI %s (%u)",
                tok2str(af_values, "Unknown", EXTRACT_BE_U_2(opt + i + 2)),
                EXTRACT_BE_U_2(opt + i + 2),
                tok2str(bgp_safi_values, "Unknown", EXTRACT_U_1(opt + i + 5)),
-               EXTRACT_U_1(opt + i + 5)));
+               EXTRACT_U_1(opt + i + 5));
             break;
         case BGP_CAPCODE_RESTART:
-            ND_PRINT((ndo, "\n\t\tRestart Flags: [%s], Restart Time %us",
+            /* Restart Flags (4 bits), Restart Time in seconds (12 bits) */
+            if (cap_len < 2) {
+                ND_PRINT(" (too short, < 2)");
+                return;
+            }
+            tcap_len=cap_len;
+            ND_PRINT("\n\t\tRestart Flags: [%s], Restart Time %us",
                       ((EXTRACT_U_1(opt + i + 2))&0x80) ? "R" : "none",
-                      EXTRACT_BE_U_2(opt + i + 2)&0xfff));
+                      EXTRACT_BE_U_2(opt + i + 2)&0xfff);
             tcap_len-=2;
             cap_offset=4;
             while(tcap_len>=4) {
-                ND_PRINT((ndo, "\n\t\t  AFI %s (%u), SAFI %s (%u), Forwarding state preserved: %s",
+                ND_PRINT("\n\t\t  AFI %s (%u), SAFI %s (%u), Forwarding state preserved: %s",
                           tok2str(af_values,"Unknown",
                                   EXTRACT_BE_U_2(opt + i + cap_offset)),
                           EXTRACT_BE_U_2(opt + i + cap_offset),
                           tok2str(bgp_safi_values,"Unknown",
                                   EXTRACT_U_1(opt + i + cap_offset + 2)),
                           EXTRACT_U_1(opt + (i + cap_offset + 2)),
-                          ((EXTRACT_U_1(opt + (i + cap_offset + 3)))&0x80) ? "yes" : "no" ));
+                          ((EXTRACT_U_1(opt + (i + cap_offset + 3)))&0x80) ? "yes" : "no" );
                 tcap_len -= 4;
                 cap_offset += 4;
             }
@@ -2476,47 +2561,49 @@ bgp_capabilities_print(netdissect_options *ndo,
         case BGP_CAPCODE_RR_CISCO:
             break;
         case BGP_CAPCODE_AS_NEW:
-
             /*
              * Extract the 4 byte AS number encoded.
              */
-            if (cap_len == 4) {
-            ND_PRINT((ndo, "\n\t\t 4 Byte AS %s",
-                      as_printf(ndo, astostr, sizeof(astostr),
-                      EXTRACT_BE_U_4(opt + i + 2))));
+            if (cap_len < 4) {
+                ND_PRINT(" (too short, < 4)");
+                return;
             }
+            ND_PRINT("\n\t\t 4 Byte AS %s",
+                      as_printf(ndo, astostr, sizeof(astostr),
+                      EXTRACT_BE_U_4(opt + i + 2)));
             break;
         case BGP_CAPCODE_ADD_PATH:
-            cap_offset=2;
-            if (tcap_len == 0) {
-                ND_PRINT((ndo, " (bogus)")); /* length */
+            if (cap_len == 0) {
+                ND_PRINT(" (bogus)"); /* length */
                 break;
             }
-            while (tcap_len > 0) {
+            tcap_len=cap_len;
+            cap_offset=2;
+            while (tcap_len != 0) {
                 if (tcap_len < 4) {
-                    ND_PRINT((ndo, "\n\t\t(invalid)"));
+                    nd_print_invalid(ndo);
                     break;
                 }
-                ND_PRINT((ndo, "\n\t\tAFI %s (%u), SAFI %s (%u), Send/Receive: %s",
+                ND_PRINT("\n\t\tAFI %s (%u), SAFI %s (%u), Send/Receive: %s",
                           tok2str(af_values,"Unknown",EXTRACT_BE_U_2(opt + i + cap_offset)),
                           EXTRACT_BE_U_2(opt + i + cap_offset),
                           tok2str(bgp_safi_values,"Unknown",EXTRACT_U_1(opt + i + cap_offset + 2)),
                           EXTRACT_U_1(opt + (i + cap_offset + 2)),
                           tok2str(bgp_add_path_recvsend,"Bogus (0x%02x)",EXTRACT_U_1(opt + i + cap_offset + 3))
-                ));
+                );
                 tcap_len -= 4;
                 cap_offset += 4;
             }
             break;
         default:
-            ND_PRINT((ndo, "\n\t\tno decoder for Capability %u",
-                      cap_type));
+            ND_PRINT("\n\t\tno decoder for Capability %u",
+                      cap_type);
             if (ndo->ndo_vflag <= 1)
                 print_unknown_data(ndo, opt + i + 2, "\n\t\t",
                                    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;
@@ -2524,7 +2611,7 @@ bgp_capabilities_print(netdissect_options *ndo,
     return;
 
 trunc:
-    ND_PRINT((ndo, "[|BGP]"));
+    nd_print_trunc(ndo);
 }
 
 static void
@@ -2543,15 +2630,15 @@ bgp_open_print(netdissect_options *ndo,
 
     bgp_open_header = (const struct bgp_open *)dat;
 
-    ND_PRINT((ndo, "\n\t  Version %u, ",
-        EXTRACT_U_1(bgp_open_header->bgpo_version)));
-    ND_PRINT((ndo, "my AS %s, ",
-        as_printf(ndo, astostr, sizeof(astostr), EXTRACT_BE_U_2(bgp_open_header->bgpo_myas))));
-    ND_PRINT((ndo, "Holdtime %us, ",
-        EXTRACT_BE_U_2(bgp_open_header->bgpo_holdtime)));
-    ND_PRINT((ndo, "ID %s", ipaddr_string(ndo, &bgp_open_header->bgpo_id)));
+    ND_PRINT("\n\t  Version %u, ",
+        EXTRACT_U_1(bgp_open_header->bgpo_version));
+    ND_PRINT("my AS %s, ",
+        as_printf(ndo, astostr, sizeof(astostr), EXTRACT_BE_U_2(bgp_open_header->bgpo_myas)));
+    ND_PRINT("Holdtime %us, ",
+        EXTRACT_BE_U_2(bgp_open_header->bgpo_holdtime));
+    ND_PRINT("ID %s", ipaddr_string(ndo, bgp_open_header->bgpo_id));
     optslen = EXTRACT_U_1(bgp_open_header->bgpo_optlen);
-    ND_PRINT((ndo, "\n\t  Optional parameters, length: %u", optslen));
+    ND_PRINT("\n\t  Optional parameters, length: %u", optslen);
 
     opt = dat + BGP_OPEN_SIZE;
     length -= BGP_OPEN_SIZE;
@@ -2567,15 +2654,15 @@ bgp_open_print(netdissect_options *ndo,
         opt_type = EXTRACT_U_1(bgpopt->bgpopt_type);
         opt_len = EXTRACT_U_1(bgpopt->bgpopt_len);
         if (BGP_OPT_SIZE + i + opt_len > optslen) {
-            ND_PRINT((ndo, "\n\t     Option %u, length: %u, goes past the end of the options",
-                      opt_type, opt_len));
+            ND_PRINT("\n\t     Option %u, length: %u, goes past the end of the options",
+                      opt_type, opt_len);
             break;
         }
 
-        ND_PRINT((ndo, "\n\t    Option %s (%u), length: %u",
+        ND_PRINT("\n\t    Option %s (%u), length: %u",
                   tok2str(bgp_opt_values,"Unknown",opt_type),
                   opt_type,
-                  opt_len));
+                  opt_len);
 
         /* now let's decode the options we know*/
         switch(opt_type) {
@@ -2587,15 +2674,15 @@ bgp_open_print(netdissect_options *ndo,
 
         case BGP_OPT_AUTH:
         default:
-               ND_PRINT((ndo, "\n\t      no decoder for option %u",
-               opt_type));
+               ND_PRINT("\n\t      no decoder for option %u",
+               opt_type);
                break;
         }
         i += BGP_OPT_SIZE + opt_len;
     }
     return;
 trunc:
-    ND_PRINT((ndo, "[|BGP]"));
+    nd_print_trunc(ndo);
 }
 
 static void
@@ -2633,10 +2720,15 @@ bgp_update_print(netdissect_options *ndo,
         ND_TCHECK_LEN(p, withdrawn_routes_len);
         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) {
+        ND_PRINT("\n\t  Withdrawn routes:");
+        add_path = check_add_path(ndo, p, withdrawn_routes_len, 32);
+        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;
@@ -2644,16 +2736,16 @@ bgp_update_print(netdissect_options *ndo,
             }
             wpfx = decode_prefix4(ndo, p, withdrawn_routes_len, buf, sizeof(buf));
             if (wpfx == -1) {
-                ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
+                ND_PRINT("\n\t    (illegal prefix length)");
                 break;
             } else if (wpfx == -2)
                 goto trunc;
             else if (wpfx == -3)
                 goto trunc; /* bytes left, but not enough */
             else {
-                ND_PRINT((ndo, "\n\t    %s", buf));
+                ND_PRINT("\n\t    %s", buf);
                 if (add_path) {
-                    ND_PRINT((ndo, "   Path Id: %u", path_id));
+                    ND_PRINT("   Path Id: %u", path_id);
                 }
                 p += wpfx;
                 length -= wpfx;
@@ -2661,6 +2753,9 @@ bgp_update_print(netdissect_options *ndo,
             }
         }
     } else {
+        ND_TCHECK_LEN(p, withdrawn_routes_len);
+        if (length < withdrawn_routes_len)
+            goto trunc;
         p += withdrawn_routes_len;
         length -= withdrawn_routes_len;
     }
@@ -2674,7 +2769,7 @@ bgp_update_print(netdissect_options *ndo,
 
     if (withdrawn_routes_len == 0 && len == 0 && length == 0) {
         /* No withdrawn routes, no path attributes, no NLRI */
-        ND_PRINT((ndo, "\n\t  End-of-Rib Marker (empty NLRI)"));
+        ND_PRINT("\n\t  End-of-Rib Marker (empty NLRI)");
         return;
     }
 
@@ -2684,10 +2779,14 @@ bgp_update_print(netdissect_options *ndo,
             u_int aflags, atype, alenlen, alen;
 
             ND_TCHECK_2(p);
-            if (len < 2)
-                goto trunc;
             if (length < 2)
                 goto trunc;
+            if (len < 2) {
+                ND_PRINT("\n\t  [path attrs too short]");
+                p += len;
+                length -= len;
+                break;
+            }
             aflags = EXTRACT_U_1(p);
             atype = EXTRACT_U_1(p + 1);
             p += 2;
@@ -2695,32 +2794,40 @@ bgp_update_print(netdissect_options *ndo,
             length -= 2;
             alenlen = bgp_attr_lenlen(aflags, p);
             ND_TCHECK_LEN(p, alenlen);
-            if (len < alenlen)
-                goto trunc;
             if (length < alenlen)
                 goto trunc;
+            if (len < alenlen) {
+                ND_PRINT("\n\t  [path attrs too short]");
+                p += len;
+                length -= len;
+                break;
+            }
             alen = bgp_attr_len(aflags, p);
             p += alenlen;
             len -= alenlen;
             length -= alenlen;
 
-            ND_PRINT((ndo, "\n\t  %s (%u), length: %u",
+            ND_PRINT("\n\t  %s (%u), length: %u",
                       tok2str(bgp_attr_values, "Unknown Attribute", atype),
                       atype,
-                      alen));
+                      alen);
 
             if (aflags) {
-                ND_PRINT((ndo, ", Flags [%s%s%s%s",
+                ND_PRINT(", Flags [%s%s%s%s",
                           aflags & 0x80 ? "O" : "",
                           aflags & 0x40 ? "T" : "",
                           aflags & 0x20 ? "P" : "",
-                          aflags & 0x10 ? "E" : ""));
+                          aflags & 0x10 ? "E" : "");
                 if (aflags & 0xf)
-                    ND_PRINT((ndo, "+%x", aflags & 0xf));
-                ND_PRINT((ndo, "]: "));
+                    ND_PRINT("+%x", aflags & 0xf);
+                ND_PRINT("]: ");
+            }
+            if (len < alen) {
+                ND_PRINT(" [path attrs too short]");
+                p += len;
+                length -= len;
+                break;
             }
-            if (len < alen)
-                goto trunc;
             if (length < alen)
                 goto trunc;
             if (!bgp_attr_print(ndo, atype, p, alen))
@@ -2732,26 +2839,29 @@ bgp_update_print(netdissect_options *ndo,
     }
 
     if (length) {
-        add_path = check_add_path(p, length, 32);
-        ND_PRINT((ndo, "\n\t  Updated routes:"));
-        while (length > 0) {
+        add_path = check_add_path(ndo, p, length, 32);
+        ND_PRINT("\n\t  Updated routes:");
+        while (length != 0) {
             if (add_path) {
+                ND_TCHECK_4(p);
+                if (length < 4)
+                    goto trunc;
                 path_id = EXTRACT_BE_U_4(p);
                 p += 4;
                 length -= 4;
             }
             i = decode_prefix4(ndo, p, length, buf, sizeof(buf));
             if (i == -1) {
-                ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
+                ND_PRINT("\n\t    (illegal prefix length)");
                 break;
             } else if (i == -2)
                 goto trunc;
             else if (i == -3)
                 goto trunc; /* bytes left, but not enough */
             else {
-                ND_PRINT((ndo, "\n\t    %s", buf));
+                ND_PRINT("\n\t    %s", buf);
                 if (add_path) {
-                    ND_PRINT((ndo, "   Path Id: %u", path_id));
+                    ND_PRINT("   Path Id: %u", path_id);
                 }
                 p += i;
                 length -= i;
@@ -2760,7 +2870,7 @@ bgp_update_print(netdissect_options *ndo,
     }
     return;
 trunc:
-    ND_PRINT((ndo, "[|BGP]"));
+    nd_print_trunc(ndo);
 }
 
 static void
@@ -2781,48 +2891,48 @@ bgp_notification_print(netdissect_options *ndo,
     bgpn_major = EXTRACT_U_1(bgp_notification_header->bgpn_major);
     bgpn_minor = EXTRACT_U_1(bgp_notification_header->bgpn_minor);
 
-    ND_PRINT((ndo, ", %s (%u)",
+    ND_PRINT(", %s (%u)",
               tok2str(bgp_notify_major_values, "Unknown Error",
                       bgpn_major),
-              bgpn_major));
+              bgpn_major);
 
     switch (bgpn_major) {
 
     case BGP_NOTIFY_MAJOR_MSG:
-        ND_PRINT((ndo, ", subcode %s (%u)",
+        ND_PRINT(", subcode %s (%u)",
                   tok2str(bgp_notify_minor_msg_values, "Unknown",
                           bgpn_minor),
-                  bgpn_minor));
+                  bgpn_minor);
         break;
     case BGP_NOTIFY_MAJOR_OPEN:
-        ND_PRINT((ndo, ", subcode %s (%u)",
+        ND_PRINT(", subcode %s (%u)",
                   tok2str(bgp_notify_minor_open_values, "Unknown",
                           bgpn_minor),
-                  bgpn_minor));
+                  bgpn_minor);
         break;
     case BGP_NOTIFY_MAJOR_UPDATE:
-        ND_PRINT((ndo, ", subcode %s (%u)",
+        ND_PRINT(", subcode %s (%u)",
                   tok2str(bgp_notify_minor_update_values, "Unknown",
                           bgpn_minor),
-                  bgpn_minor));
+                  bgpn_minor);
         break;
     case BGP_NOTIFY_MAJOR_FSM:
-        ND_PRINT((ndo, " subcode %s (%u)",
+        ND_PRINT(" subcode %s (%u)",
                   tok2str(bgp_notify_minor_fsm_values, "Unknown",
                           bgpn_minor),
-                  bgpn_minor));
+                  bgpn_minor);
         break;
     case BGP_NOTIFY_MAJOR_CAP:
-        ND_PRINT((ndo, " subcode %s (%u)",
+        ND_PRINT(" subcode %s (%u)",
                   tok2str(bgp_notify_minor_cap_values, "Unknown",
                           bgpn_minor),
-                  bgpn_minor));
+                  bgpn_minor);
         break;
     case BGP_NOTIFY_MAJOR_CEASE:
-        ND_PRINT((ndo, ", subcode %s (%u)",
+        ND_PRINT(", subcode %s (%u)",
                   tok2str(bgp_notify_minor_cease_values, "Unknown",
                           bgpn_minor),
-                  bgpn_minor));
+                  bgpn_minor);
 
         /* draft-ietf-idr-cease-subcode-02 mentions optionally 7 bytes
          * for the maxprefix subtype, which may contain AFI, SAFI and MAXPREFIXES
@@ -2830,12 +2940,12 @@ bgp_notification_print(netdissect_options *ndo,
         if(bgpn_minor == BGP_NOTIFY_MINOR_CEASE_MAXPRFX && length >= BGP_NOTIFICATION_SIZE + 7) {
             tptr = dat + BGP_NOTIFICATION_SIZE;
             ND_TCHECK_7(tptr);
-            ND_PRINT((ndo, ", AFI %s (%u), SAFI %s (%u), Max Prefixes: %u",
+            ND_PRINT(", AFI %s (%u), SAFI %s (%u), Max Prefixes: %u",
                       tok2str(af_values, "Unknown", EXTRACT_BE_U_2(tptr)),
                       EXTRACT_BE_U_2(tptr),
                       tok2str(bgp_safi_values, "Unknown", EXTRACT_U_1((tptr + 2))),
                       EXTRACT_U_1((tptr + 2)),
-                      EXTRACT_BE_U_4(tptr + 3)));
+                      EXTRACT_BE_U_4(tptr + 3));
         }
         /*
          * draft-ietf-idr-shutdown describes a method to send a communication
@@ -2851,23 +2961,23 @@ bgp_notification_print(netdissect_options *ndo,
             /* garbage, hexdump it all */
             if (shutdown_comm_length > BGP_NOTIFY_MINOR_CEASE_ADMIN_SHUTDOWN_LEN ||
                 shutdown_comm_length > length - (BGP_NOTIFICATION_SIZE + 1)) {
-                ND_PRINT((ndo, ", invalid Shutdown Communication length"));
+                ND_PRINT(", invalid Shutdown Communication length");
             }
             else if (shutdown_comm_length == 0) {
-                ND_PRINT((ndo, ", empty Shutdown Communication"));
+                ND_PRINT(", empty Shutdown Communication");
                 remainder_offset += 1;
             }
             /* a proper shutdown communication */
             else {
                 ND_TCHECK_LEN(tptr + 1, shutdown_comm_length);
-                ND_PRINT((ndo, ", Shutdown Communication (length: %u): \"", shutdown_comm_length));
-                (void)fn_printn(ndo, tptr+1, shutdown_comm_length, NULL);
-                ND_PRINT((ndo, "\""));
+                ND_PRINT(", Shutdown Communication (length: %u): \"", shutdown_comm_length);
+                (void)nd_printn(ndo, tptr+1, shutdown_comm_length, NULL);
+                ND_PRINT("\"");
                 remainder_offset += shutdown_comm_length + 1;
             }
             /* if there is trailing data, hexdump it */
             if(length - (remainder_offset + BGP_NOTIFICATION_SIZE) > 0) {
-                ND_PRINT((ndo, ", Data: (length: %u)", length - (remainder_offset + BGP_NOTIFICATION_SIZE)));
+                ND_PRINT(", Data: (length: %u)", length - (remainder_offset + BGP_NOTIFICATION_SIZE));
                 hex_print(ndo, "\n\t\t", tptr + remainder_offset, length - (remainder_offset + BGP_NOTIFICATION_SIZE));
             }
         }
@@ -2878,7 +2988,7 @@ bgp_notification_print(netdissect_options *ndo,
 
     return;
 trunc:
-    ND_PRINT((ndo, "[|BGP]"));
+    nd_print_trunc(ndo);
 }
 
 static void
@@ -2895,13 +3005,13 @@ bgp_route_refresh_print(netdissect_options *ndo,
 
     bgp_route_refresh_header = (const struct bgp_route_refresh *)pptr;
 
-    ND_PRINT((ndo, "\n\t  AFI %s (%u), SAFI %s (%u)",
+    ND_PRINT("\n\t  AFI %s (%u), SAFI %s (%u)",
               tok2str(af_values,"Unknown",
                       EXTRACT_BE_U_2(bgp_route_refresh_header->afi)),
               EXTRACT_BE_U_2(bgp_route_refresh_header->afi),
               tok2str(bgp_safi_values,"Unknown",
                       EXTRACT_U_1(bgp_route_refresh_header->safi)),
-              EXTRACT_U_1(bgp_route_refresh_header->safi)));
+              EXTRACT_U_1(bgp_route_refresh_header->safi));
 
     if (ndo->ndo_vflag > 1) {
         ND_TCHECK_LEN(pptr, len);
@@ -2910,7 +3020,7 @@ bgp_route_refresh_print(netdissect_options *ndo,
 
     return;
 trunc:
-    ND_PRINT((ndo, "[|BGP]"));
+    nd_print_trunc(ndo);
 }
 
 static int
@@ -2924,10 +3034,10 @@ bgp_pdu_print(netdissect_options *ndo,
     bgp_header = (const struct bgp *)dat;
     bgp_type = EXTRACT_U_1(bgp_header->bgp_type);
 
-    ND_PRINT((ndo, "\n\t%s Message (%u), length: %u",
+    ND_PRINT("\n\t%s Message (%u), length: %u",
               tok2str(bgp_msg_values, "Unknown", bgp_type),
               bgp_type,
-              length));
+              length);
 
     switch (bgp_type) {
     case BGP_OPEN:
@@ -2947,22 +3057,22 @@ bgp_pdu_print(netdissect_options *ndo,
     default:
         /* we have no decoder for the BGP message */
         ND_TCHECK_LEN(dat, length);
-        ND_PRINT((ndo, "\n\t  no Message %u decoder", bgp_type));
+        ND_PRINT("\n\t  no Message %u decoder", bgp_type);
         print_unknown_data(ndo, dat, "\n\t  ", length);
         break;
     }
     return 1;
 trunc:
-    ND_PRINT((ndo, "[|BGP]"));
+    nd_print_trunc(ndo);
     return 0;
 }
 
 void
 bgp_print(netdissect_options *ndo,
-          const u_char *dat, u_int length)
+          const u_char *dat, u_int length _U_)
 {
     const u_char *p;
-    const u_char *ep;
+    const u_char *ep = ndo->ndo_snapend;
     const u_char *start;
     const u_char marker[] = {
         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
@@ -2971,11 +3081,8 @@ bgp_print(netdissect_options *ndo,
     const struct bgp *bgp_header;
     uint16_t hlen;
 
-    ep = dat + length;
-    if (ndo->ndo_snapend < dat + length)
-        ep = ndo->ndo_snapend;
-
-    ND_PRINT((ndo, ": BGP"));
+    ndo->ndo_protocol = "bgp";
+    ND_PRINT(": BGP");
 
     if (ndo->ndo_vflag < 1) /* lets be less chatty */
         return;
@@ -3002,12 +3109,12 @@ bgp_print(netdissect_options *ndo,
         bgp_header = (const struct bgp *)p;
 
         if (start != p)
-            ND_PRINT((ndo, " [|BGP]"));
+            nd_print_trunc(ndo);
 
         hlen = EXTRACT_BE_U_2(bgp_header->bgp_len);
         if (hlen < BGP_SIZE) {
-            ND_PRINT((ndo, "\n[|BGP Bogus header length %u < %u]", hlen,
-                      BGP_SIZE));
+            ND_PRINT("\nmessage length %u < %u", hlen, BGP_SIZE);
+            nd_print_invalid(ndo);
             break;
         }
 
@@ -3017,10 +3124,10 @@ bgp_print(netdissect_options *ndo,
             p += hlen;
             start = p;
         } else {
-            ND_PRINT((ndo, "\n[|BGP %s]",
+            ND_PRINT("\n[|BGP %s]",
                       tok2str(bgp_msg_values,
                               "Unknown Message Type",
-                              EXTRACT_U_1(bgp_header->bgp_type))));
+                              EXTRACT_U_1(bgp_header->bgp_type)));
             break;
         }
     }
@@ -3028,12 +3135,5 @@ bgp_print(netdissect_options *ndo,
     return;
 
 trunc:
-    ND_PRINT((ndo, " [|BGP]"));
+    nd_print_trunc(ndo);
 }
-
-/*
- * Local Variables:
- * c-style: whitesmith
- * c-basic-offset: 4
- * End:
- */