]> The Tcpdump Group git mirrors - tcpdump/commitdiff
Merge branch 'master' into master 630/head
authorGuy Harris <[email protected]>
Sat, 16 Dec 2017 06:34:42 +0000 (22:34 -0800)
committerGitHub <[email protected]>
Sat, 16 Dec 2017 06:34:42 +0000 (22:34 -0800)
1  2 
print-bgp.c
tests/TESTLIST

diff --combined print-bgp.c
index fe83922ddb8b178463854838637931ee9aeaba89,bfb94df66c27dd98f78d8aa0a3cbe82561ee4d9b..443581de648c013d74bafe9625483d5ce4a2f409
@@@ -48,9 -48,9 +48,9 @@@
  #include "l2vpn.h"
  
  struct bgp {
-       uint8_t bgp_marker[16];
-       uint16_t bgp_len;
-       uint8_t bgp_type;
+       nd_byte     bgp_marker[16];
+       nd_uint16_t bgp_len;
+       nd_uint8_t  bgp_type;
  };
  #define BGP_SIZE              19      /* unaligned */
  
@@@ -70,49 -70,49 +70,49 @@@ static const struct tok bgp_msg_values[
  };
  
  struct bgp_open {
-       uint8_t bgpo_marker[16];
-       uint16_t bgpo_len;
-       uint8_t bgpo_type;
-       uint8_t bgpo_version;
-       uint16_t bgpo_myas;
-       uint16_t bgpo_holdtime;
-       uint32_t bgpo_id;
-       uint8_t bgpo_optlen;
+       nd_byte     bgpo_marker[16];
+       nd_uint16_t bgpo_len;
+       nd_uint8_t  bgpo_type;
+       nd_uint8_t  bgpo_version;
+       nd_uint16_t bgpo_myas;
+       nd_uint16_t bgpo_holdtime;
+       nd_uint32_t bgpo_id;
+       nd_uint8_t  bgpo_optlen;
        /* options should follow */
  };
  #define BGP_OPEN_SIZE         29      /* unaligned */
  
  struct bgp_opt {
-       uint8_t bgpopt_type;
-       uint8_t bgpopt_len;
+       nd_uint8_t bgpopt_type;
+       nd_uint8_t bgpopt_len;
        /* variable length */
  };
  #define BGP_OPT_SIZE          2       /* some compilers may pad to 4 bytes */
  #define BGP_CAP_HEADER_SIZE   2       /* some compilers may pad to 4 bytes */
  
  struct bgp_notification {
-       uint8_t bgpn_marker[16];
-       uint16_t bgpn_len;
-       uint8_t bgpn_type;
-       uint8_t bgpn_major;
-       uint8_t bgpn_minor;
+       nd_byte     bgpn_marker[16];
+       nd_uint16_t bgpn_len;
+       nd_uint8_t  bgpn_type;
+       nd_uint8_t  bgpn_major;
+       nd_uint8_t  bgpn_minor;
  };
  #define BGP_NOTIFICATION_SIZE         21      /* unaligned */
  
  struct bgp_route_refresh {
-     uint8_t  bgp_marker[16];
-     uint16_t len;
-     uint8_t  type;
-     uint8_t  afi[2]; /* the compiler messes this structure up               */
-     uint8_t  res;    /* when doing misaligned sequences of int8 and int16   */
-     uint8_t  safi;   /* afi should be int16 - so we have to access it using */
- };                    /* EXTRACT_16BITS(&bgp_route_refresh->afi) (sigh)      */
+       nd_byte     bgp_marker[16];
+       nd_uint16_t len;
+       nd_uint8_t  type;   /* No padding after this; afi is, in fact, not aligned */
+       nd_uint16_t afi;
+       nd_uint8_t  res;
+       nd_uint8_t  safi;
+ };
  #define BGP_ROUTE_REFRESH_SIZE          23
  
  #define bgp_attr_lenlen(flags, p) \
        (((flags) & 0x10) ? 2 : 1)
  #define bgp_attr_len(flags, p) \
-       (((flags) & 0x10) ? EXTRACT_16BITS(p) : *(p))
+       (((flags) & 0x10) ? EXTRACT_BE_U_2(p) : EXTRACT_U_1(p))
  
  #define BGPTYPE_ORIGIN                        1
  #define BGPTYPE_AS_PATH                       2
@@@ -538,18 -538,18 +538,18 @@@ decode_prefix4(netdissect_options *ndo
        struct in_addr addr;
        u_int plen, plenbytes;
  
-       ND_TCHECK(pptr[0]);
+       ND_TCHECK_1(pptr);
        ITEMCHECK(1);
-       plen = pptr[0];
+       plen = EXTRACT_U_1(pptr);
        if (32 < plen)
                return -1;
        itemlen -= 1;
  
        memset(&addr, 0, sizeof(addr));
        plenbytes = (plen + 7) / 8;
-       ND_TCHECK2(pptr[1], plenbytes);
+       ND_TCHECK_LEN(pptr + 1, plenbytes);
        ITEMCHECK(plenbytes);
-       memcpy(&addr, &pptr[1], plenbytes);
+       memcpy(&addr, pptr + 1, plenbytes);
        if (plen % 8) {
                ((u_char *)&addr)[plenbytes - 1] &=
                        ((0xff00 >> (plen % 8)) & 0xff);
@@@ -572,9 -572,9 +572,9 @@@ decode_labeled_prefix4(netdissect_optio
        u_int plen, plenbytes;
  
        /* prefix length and label = 4 bytes */
-       ND_TCHECK2(pptr[0], 4);
+       ND_TCHECK_4(pptr);
        ITEMCHECK(4);
-       plen = pptr[0];   /* get prefix length */
+       plen = EXTRACT_U_1(pptr);   /* get prefix length */
  
          /* this is one of the weirdnesses of rfc3107
             the label length (actually the label + COS bits)
  
        memset(&addr, 0, sizeof(addr));
        plenbytes = (plen + 7) / 8;
-       ND_TCHECK2(pptr[4], plenbytes);
+       ND_TCHECK_LEN(pptr + 4, plenbytes);
        ITEMCHECK(plenbytes);
-       memcpy(&addr, &pptr[4], plenbytes);
+       memcpy(&addr, pptr + 4, plenbytes);
        if (plen % 8) {
                ((u_char *)&addr)[plenbytes - 1] &=
                        ((0xff00 >> (plen % 8)) & 0xff);
        snprintf(buf, buflen, "%s/%d, label:%u %s",
                   ipaddr_string(ndo, &addr),
                   plen,
-                  EXTRACT_24BITS(pptr+1)>>4,
+                  EXTRACT_BE_U_3(pptr + 1)>>4,
                   ((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
  
        return 4 + plenbytes;
@@@ -634,11 -634,11 +634,11 @@@ bgp_vpn_ip_print(netdissect_options *nd
  
      switch(addr_length) {
      case (sizeof(struct in_addr) << 3): /* 32 */
-         ND_TCHECK2(pptr[0], sizeof(struct in_addr));
+         ND_TCHECK_LEN(pptr, sizeof(struct in_addr));
          snprintf(pos, sizeof(addr), "%s", ipaddr_string(ndo, pptr));
          break;
      case (sizeof(struct in6_addr) << 3): /* 128 */
-         ND_TCHECK2(pptr[0], sizeof(struct in6_addr));
+         ND_TCHECK_LEN(pptr, sizeof(struct in6_addr));
          snprintf(pos, sizeof(addr), "%s", ip6addr_string(ndo, pptr));
          break;
      default:
@@@ -680,11 -680,12 +680,12 @@@ bgp_vpn_sg_print(netdissect_options *nd
      total_length = 0;
  
      /* Source address length, encoded in bits */
-     ND_TCHECK2(pptr[0], 1);
-     addr_length =  *pptr++;
+     ND_TCHECK_1(pptr);
+     addr_length = EXTRACT_U_1(pptr);
+     pptr++;
  
      /* Source address */
-     ND_TCHECK2(pptr[0], (addr_length >> 3));
+     ND_TCHECK_LEN(pptr, (addr_length >> 3));
      total_length += (addr_length >> 3) + 1;
      offset = strlen(buf);
      if (addr_length) {
      }
  
      /* Group address length, encoded in bits */
-     ND_TCHECK2(pptr[0], 1);
-     addr_length =  *pptr++;
+     ND_TCHECK_1(pptr);
+     addr_length = EXTRACT_U_1(pptr);
+     pptr++;
  
      /* Group address */
-     ND_TCHECK2(pptr[0], (addr_length >> 3));
+     ND_TCHECK_LEN(pptr, (addr_length >> 3));
      total_length += (addr_length >> 3) + 1;
      offset = strlen(buf);
      if (addr_length) {
@@@ -723,28 -725,32 +725,32 @@@ bgp_vpn_rd_print(netdissect_options *nd
      char *pos = rd;
  
      /* ok lets load the RD format */
-     switch (EXTRACT_16BITS(pptr)) {
+     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_16BITS(pptr+2),
-                  EXTRACT_32BITS(pptr+4),
-                  *(pptr+4), *(pptr+5), *(pptr+6), *(pptr+7));
+                  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",
-             *(pptr+2), *(pptr+3), *(pptr+4), *(pptr+5), EXTRACT_16BITS(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;
  
          /* 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_32BITS(pptr+2)),
-           EXTRACT_16BITS(pptr+6), *(pptr+2), *(pptr+3), *(pptr+4),
-           *(pptr+5), EXTRACT_16BITS(pptr+6));
+           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");
@@@ -764,8 -770,8 +770,8 @@@ decode_rt_routing_info(netdissect_optio
        char asbuf[sizeof(astostr)]; /* bgp_vpn_rd_print() overwrites astostr */
  
        /* NLRI "prefix length" from RFC 2858 Section 4. */
-       ND_TCHECK(pptr[0]);
-       plen = pptr[0];   /* get prefix length */
+       ND_TCHECK_1(pptr);
+       plen = EXTRACT_U_1(pptr);   /* get prefix length */
  
        /* NLRI "prefix" (ibid), valid lengths are { 0, 32, 33, ..., 96 } bits.
         * RFC 4684 Section 4 defines the layout of "origin AS" and "route
                return -1;
  
        /* With at least "origin AS", possibly with "route target". */
-       ND_TCHECK_32BITS(pptr + 1);
-       as_printf(ndo, asbuf, sizeof(asbuf), EXTRACT_32BITS(pptr + 1));
+       ND_TCHECK_4(pptr + 1);
+       as_printf(ndo, asbuf, sizeof(asbuf), EXTRACT_BE_U_4(pptr + 1));
  
          plen-=32; /* adjust prefix length */
  
         * target" field inside this NLRI "prefix". Look for it.
         */
        memset(&route_target, 0, sizeof(route_target));
-       ND_TCHECK2(pptr[5], (plen + 7) / 8);
-       memcpy(&route_target, &pptr[5], (plen + 7) / 8);
+       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] &=
@@@ -818,8 -824,8 +824,8 @@@ decode_labeled_vpn_prefix4(netdissect_o
        struct in_addr addr;
        u_int plen;
  
-       ND_TCHECK(pptr[0]);
-       plen = pptr[0];   /* get prefix length */
+       ND_TCHECK_1(pptr);
+       plen = EXTRACT_U_1(pptr);   /* get prefix length */
  
        if ((24+64) > plen)
                return -1;
                return -1;
  
        memset(&addr, 0, sizeof(addr));
-       ND_TCHECK2(pptr[12], (plen + 7) / 8);
-       memcpy(&addr, &pptr[12], (plen + 7) / 8);
+       ND_TCHECK_LEN(pptr + 12, (plen + 7) / 8);
+       memcpy(&addr, pptr + 12, (plen + 7) / 8);
        if (plen % 8) {
                ((u_char *)&addr)[(plen + 7) / 8 - 1] &=
                        ((0xff00 >> (plen % 8)) & 0xff);
                   bgp_vpn_rd_print(ndo, pptr+4),
                   ipaddr_string(ndo, &addr),
                   plen,
-                  EXTRACT_24BITS(pptr+1)>>4,
+                  EXTRACT_BE_U_3(pptr + 1)>>4,
                   ((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
  
        return 12 + (plen + 7) / 8;
@@@ -870,25 -876,25 +876,25 @@@ decode_mdt_vpn_nlri(netdissect_options 
      const u_char *rd;
      const u_char *vpn_ip;
  
-     ND_TCHECK(pptr[0]);
+     ND_TCHECK_1(pptr);
  
      /* if the NLRI is not predefined length, quit.*/
-     if (*pptr != MDT_VPN_NLRI_LEN * 8)
+     if (EXTRACT_U_1(pptr) != MDT_VPN_NLRI_LEN * 8)
        return -1;
      pptr++;
  
      /* RD */
-     ND_TCHECK2(pptr[0], 8);
+     ND_TCHECK_8(pptr);
      rd = pptr;
      pptr+=8;
  
      /* IPv4 address */
-     ND_TCHECK2(pptr[0], sizeof(struct in_addr));
+     ND_TCHECK_LEN(pptr, sizeof(struct in_addr));
      vpn_ip = pptr;
      pptr+=sizeof(struct in_addr);
  
      /* MDT Group Address */
-     ND_TCHECK2(pptr[0], sizeof(struct in_addr));
+     ND_TCHECK_LEN(pptr, sizeof(struct in_addr));
  
      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));
@@@ -926,9 -932,11 +932,11 @@@ decode_multicast_vpn(netdissect_option
          uint8_t route_type, route_length, addr_length, sg_length;
          u_int offset;
  
-       ND_TCHECK2(pptr[0], 2);
-         route_type = *pptr++;
-         route_length = *pptr++;
+       ND_TCHECK_2(pptr);
+         route_type = EXTRACT_U_1(pptr);
+         pptr++;
+         route_length = EXTRACT_U_1(pptr);
+         pptr++;
  
          snprintf(buf, buflen, "Route-Type: %s (%u), length: %u",
                   tok2str(bgp_multicast_vpn_route_type_values,
  
          switch(route_type) {
          case BGP_MULTICAST_VPN_ROUTE_TYPE_INTRA_AS_I_PMSI:
-             ND_TCHECK2(pptr[0], BGP_VPN_RD_LEN);
+             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),
                                        (route_length - BGP_VPN_RD_LEN) << 3));
              break;
          case BGP_MULTICAST_VPN_ROUTE_TYPE_INTER_AS_I_PMSI:
-             ND_TCHECK2(pptr[0], BGP_VPN_RD_LEN + 4);
+             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_32BITS(pptr + BGP_VPN_RD_LEN)));
+               EXTRACT_BE_U_4(pptr + BGP_VPN_RD_LEN)));
              break;
  
          case BGP_MULTICAST_VPN_ROUTE_TYPE_S_PMSI:
-             ND_TCHECK2(pptr[0], BGP_VPN_RD_LEN);
+             ND_TCHECK_LEN(pptr, BGP_VPN_RD_LEN);
              offset = strlen(buf);
              snprintf(buf + offset, buflen - offset, ", RD: %s",
                       bgp_vpn_rd_print(ndo, pptr));
              sg_length = bgp_vpn_sg_print(ndo, pptr, buf, buflen);
              addr_length =  route_length - sg_length;
  
-             ND_TCHECK2(pptr[0], addr_length);
+             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));
              break;
  
          case BGP_MULTICAST_VPN_ROUTE_TYPE_SOURCE_ACTIVE:
-             ND_TCHECK2(pptr[0], BGP_VPN_RD_LEN);
+             ND_TCHECK_LEN(pptr, BGP_VPN_RD_LEN);
              offset = strlen(buf);
              snprintf(buf + offset, buflen - offset, ", RD: %s",
                       bgp_vpn_rd_print(ndo, pptr));
  
          case BGP_MULTICAST_VPN_ROUTE_TYPE_SHARED_TREE_JOIN: /* fall through */
          case BGP_MULTICAST_VPN_ROUTE_TYPE_SOURCE_TREE_JOIN:
-             ND_TCHECK2(pptr[0], BGP_VPN_RD_LEN + 4);
+             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_32BITS(pptr + BGP_VPN_RD_LEN)));
+               EXTRACT_BE_U_4(pptr + BGP_VPN_RD_LEN)));
              pptr += BGP_VPN_RD_LEN + 4;
  
              bgp_vpn_sg_print(ndo, pptr, buf, buflen);
@@@ -1032,8 -1040,8 +1040,8 @@@ decode_labeled_vpn_l2(netdissect_option
  {
          int plen,tlen,stringlen,tlv_type,tlv_len,ttlv_len;
  
-       ND_TCHECK2(pptr[0], 2);
-         plen=EXTRACT_16BITS(pptr);
+       ND_TCHECK_2(pptr);
+         plen=EXTRACT_BE_U_2(pptr);
          tlen=plen;
          pptr+=2;
        /* Old and new L2VPN NLRI share AFI/SAFI
           */
          if (plen==12) {
            /* assume AD-only with RD, BGPNH */
-           ND_TCHECK2(pptr[0],12);
+           ND_TCHECK_LEN(pptr, 12);
            buf[0]='\0';
            stringlen=snprintf(buf, buflen, "RD: %s, BGPNH: %s",
                               bgp_vpn_rd_print(ndo, pptr),
            /* assume old format */
            /* RD, ID, LBLKOFF, LBLBASE */
  
-           ND_TCHECK2(pptr[0],15);
+           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_16BITS(pptr+8),
-                              EXTRACT_16BITS(pptr+10),
-                              EXTRACT_24BITS(pptr+12)>>4); /* the label is offsetted by 4 bits so lets shift it right */
+                              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;
            while (tlen>0) {
                if (tlen < 3)
                    return -1;
-               ND_TCHECK2(pptr[0], 3);
-               tlv_type=*pptr++;
-               tlv_len=EXTRACT_16BITS(pptr);
+               ND_TCHECK_3(pptr);
+               tlv_type=EXTRACT_U_1(pptr);
+               pptr++;
+               tlv_len=EXTRACT_BE_U_2(pptr);
                ttlv_len=tlv_len;
                pptr+=2;
  
                    }
                    ttlv_len=ttlv_len/8+1; /* how many bytes do we need to read ? */
                    while (ttlv_len>0) {
-                       ND_TCHECK(pptr[0]);
+                       ND_TCHECK_1(pptr);
                        if (buflen!=0) {
-                           stringlen=snprintf(buf,buflen, "%02x",*pptr++);
+                           stringlen=snprintf(buf,buflen, "%02x",
+                                                EXTRACT_U_1(pptr));
+                           pptr++;
                            UPDATE_BUF_BUFLEN(buf, buflen, stringlen);
                        }
                        ttlv_len--;
@@@ -1125,18 -1136,18 +1136,18 @@@ decode_prefix6(netdissect_options *ndo
        struct in6_addr addr;
        u_int plen, plenbytes;
  
-       ND_TCHECK(pd[0]);
+       ND_TCHECK_1(pd);
        ITEMCHECK(1);
-       plen = pd[0];
+       plen = EXTRACT_U_1(pd);
        if (128 < plen)
                return -1;
        itemlen -= 1;
  
        memset(&addr, 0, sizeof(addr));
        plenbytes = (plen + 7) / 8;
-       ND_TCHECK2(pd[1], plenbytes);
+       ND_TCHECK_LEN(pd + 1, plenbytes);
        ITEMCHECK(plenbytes);
-       memcpy(&addr, &pd[1], plenbytes);
+       memcpy(&addr, pd + 1, plenbytes);
        if (plen % 8) {
                addr.s6_addr[plenbytes - 1] &=
                        ((0xff00 >> (plen % 8)) & 0xff);
@@@ -1159,9 -1170,9 +1170,9 @@@ decode_labeled_prefix6(netdissect_optio
        u_int plen, plenbytes;
  
        /* prefix length and label = 4 bytes */
-       ND_TCHECK2(pptr[0], 4);
+       ND_TCHECK_4(pptr);
        ITEMCHECK(4);
-       plen = pptr[0]; /* get prefix length */
+       plen = EXTRACT_U_1(pptr); /* get prefix length */
  
        if (24 > plen)
                return -1;
  
        memset(&addr, 0, sizeof(addr));
        plenbytes = (plen + 7) / 8;
-       ND_TCHECK2(pptr[4], plenbytes);
-       memcpy(&addr, &pptr[4], plenbytes);
+       ND_TCHECK_LEN(pptr + 4, plenbytes);
+       memcpy(&addr, pptr + 4, plenbytes);
        if (plen % 8) {
                addr.s6_addr[plenbytes - 1] &=
                        ((0xff00 >> (plen % 8)) & 0xff);
        snprintf(buf, buflen, "%s/%d, label:%u %s",
                   ip6addr_string(ndo, &addr),
                   plen,
-                  EXTRACT_24BITS(pptr+1)>>4,
+                  EXTRACT_BE_U_3(pptr + 1)>>4,
                   ((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
  
        return 4 + plenbytes;
@@@ -1203,8 -1214,8 +1214,8 @@@ decode_labeled_vpn_prefix6(netdissect_o
        struct in6_addr addr;
        u_int plen;
  
-       ND_TCHECK(pptr[0]);
-       plen = pptr[0];   /* get prefix length */
+       ND_TCHECK_1(pptr);
+       plen = EXTRACT_U_1(pptr);   /* get prefix length */
  
        if ((24+64) > plen)
                return -1;
                return -1;
  
        memset(&addr, 0, sizeof(addr));
-       ND_TCHECK2(pptr[12], (plen + 7) / 8);
-       memcpy(&addr, &pptr[12], (plen + 7) / 8);
+       ND_TCHECK_LEN(pptr + 12, (plen + 7) / 8);
+       memcpy(&addr, pptr + 12, (plen + 7) / 8);
        if (plen % 8) {
                addr.s6_addr[(plen + 7) / 8 - 1] &=
                        ((0xff00 >> (plen % 8)) & 0xff);
                   bgp_vpn_rd_print(ndo, pptr+4),
                   ip6addr_string(ndo, &addr),
                   plen,
-                  EXTRACT_24BITS(pptr+1)>>4,
+                  EXTRACT_BE_U_3(pptr + 1)>>4,
                   ((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
  
        return 12 + (plen + 7) / 8;
@@@ -1242,15 -1253,15 +1253,15 @@@ decode_clnp_prefix(netdissect_options *
          uint8_t addr[19];
        u_int plen;
  
-       ND_TCHECK(pptr[0]);
-       plen = pptr[0]; /* get prefix length */
+       ND_TCHECK_1(pptr);
+       plen = EXTRACT_U_1(pptr); /* get prefix length */
  
        if (152 < plen)
                return -1;
  
        memset(&addr, 0, sizeof(addr));
-       ND_TCHECK2(pptr[4], (plen + 7) / 8);
-       memcpy(&addr, &pptr[4], (plen + 7) / 8);
+       ND_TCHECK_LEN(pptr + 4, (plen + 7) / 8);
+       memcpy(&addr, pptr + 4, (plen + 7) / 8);
        if (plen % 8) {
                addr[(plen + 7) / 8 - 1] &=
                        ((0xff00 >> (plen % 8)) & 0xff);
@@@ -1272,8 -1283,8 +1283,8 @@@ decode_labeled_vpn_clnp_prefix(netdisse
          uint8_t addr[19];
        u_int plen;
  
-       ND_TCHECK(pptr[0]);
-       plen = pptr[0];   /* get prefix length */
+       ND_TCHECK_1(pptr);
+       plen = EXTRACT_U_1(pptr);   /* get prefix length */
  
        if ((24+64) > plen)
                return -1;
                return -1;
  
        memset(&addr, 0, sizeof(addr));
-       ND_TCHECK2(pptr[12], (plen + 7) / 8);
-       memcpy(&addr, &pptr[12], (plen + 7) / 8);
+       ND_TCHECK_LEN(pptr + 12, (plen + 7) / 8);
+       memcpy(&addr, pptr + 12, (plen + 7) / 8);
        if (plen % 8) {
                addr[(plen + 7) / 8 - 1] &=
                        ((0xff00 >> (plen % 8)) & 0xff);
                   bgp_vpn_rd_print(ndo, pptr+4),
                   isonsap_string(ndo, addr,(plen + 7) / 8),
                   plen,
-                  EXTRACT_24BITS(pptr+1)>>4,
+                  EXTRACT_BE_U_3(pptr + 1)>>4,
                   ((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
  
        return 12 + (plen + 7) / 8;
@@@ -1331,16 -1342,16 +1342,16 @@@ bgp_attr_get_as_size(netdissect_option
       * each.
       */
      while (tptr < pptr + len) {
-         ND_TCHECK(tptr[0]);
+         ND_TCHECK_1(tptr);
  
          /*
           * If we do not find a valid segment type, our guess might be wrong.
           */
-         if (tptr[0] < BGP_AS_SEG_TYPE_MIN || tptr[0] > BGP_AS_SEG_TYPE_MAX) {
+         if (EXTRACT_U_1(tptr) < BGP_AS_SEG_TYPE_MIN || EXTRACT_U_1(tptr) > BGP_AS_SEG_TYPE_MAX) {
              goto trunc;
          }
-         ND_TCHECK(tptr[1]);
-         tptr += 2 + tptr[1] * 2;
+         ND_TCHECK_1(tptr + 1);
+         tptr += 2 + EXTRACT_U_1(tptr + 1) * 2;
      }
  
      /*
@@@ -1362,62 -1373,6 +1373,62 @@@ trunc
     return 4;
  }
  
 +/*
 + * The only way to know that a BGP UPDATE message is using add path is
 + * by checking if the capability is in the OPEN message which we may have missed.
 + * So this function checks if it is possible that the update could contain add path
 + * 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) {
 +
 +    u_int offset, prefix_length;
 +    if (length < 5) {
 +        return 0;
 +    }
 +
 +    /* check if it could be add path */
 +    for(offset = 0; offset < length;) {
 +        offset += 4;
 +        prefix_length = pptr[offset];
 +        /*
 +         * Add 4 to cover the path id
 +         * and check the prefix length isn't greater than 32/128.
 +         */
 +        if (prefix_length > max_prefix_length) {
 +            return 0;
 +        }
 +        /* Add 1 for the prefix_length byte and prefix_length to cover the address */
 +        offset += 1 + ((prefix_length + 7) / 8);
 +    }
 +    /* check we haven't gone past the end of the section */
 +    if (offset > length) {
 +        return 0;
 +    }
 +
 +    /* check it's not standard BGP */
 +    for(offset = 0; offset < length; ) {
 +        prefix_length = pptr[offset];
 +        /*
 +         * If the prefix_length is zero (0.0.0.0/0)
 +         * and since it's not the only address (length >= 5)
 +         * then it is add-path
 +         */
 +        if (prefix_length < 1 || prefix_length > max_prefix_length) {
 +            return 1;
 +        }
 +        offset += 1 + ((prefix_length + 7) / 8);
 +    }
 +    if (offset > length) {
 +        return 1;
 +    }
 +
 +    /* assume not add-path by default */
 +    return 0;
 +}
 +
 +
  static int
  bgp_attr_print(netdissect_options *ndo,
                 u_int atype, const u_char *pptr, u_int len)
        const u_char *tptr;
        char buf[MAXHOSTNAMELEN + 100];
          int  as_size;
 +        int add_path4, add_path6, path_id;
  
          tptr = pptr;
          tlen=len;
                if (len != 1)
                        ND_PRINT((ndo, "invalid len"));
                else {
-                       ND_TCHECK(*tptr);
+                       ND_TCHECK_1(tptr);
                        ND_PRINT((ndo, "%s", tok2str(bgp_origin_values,
                                                "Unknown Origin Typecode",
-                                               tptr[0])));
+                                               EXTRACT_U_1(tptr))));
                }
                break;
  
                  as_size = bgp_attr_get_as_size(ndo, atype, pptr, len);
  
                while (tptr < pptr + len) {
-                       ND_TCHECK(tptr[0]);
+                       ND_TCHECK_1(tptr);
                          ND_PRINT((ndo, "%s", tok2str(bgp_as_path_segment_open_values,
-                                               "?", tptr[0])));
-                       ND_TCHECK(tptr[1]);
+                                               "?", EXTRACT_U_1(tptr))));
+                       ND_TCHECK_1(tptr + 1);
                          for (i = 0; i < tptr[1] * as_size; i += as_size) {
-                             ND_TCHECK2(tptr[2 + i], as_size);
+                             ND_TCHECK_LEN(tptr + 2 + i, as_size);
                            ND_PRINT((ndo, "%s ",
                                as_printf(ndo, astostr, sizeof(astostr),
                                as_size == 2 ?
-                               EXTRACT_16BITS(&tptr[2 + i]) :
-                               EXTRACT_32BITS(&tptr[2 + i]))));
+                               EXTRACT_BE_U_2(tptr + i + 2) :
+                               EXTRACT_BE_U_4(tptr + i + 2))));
                          }
-                       ND_TCHECK(tptr[0]);
+                       ND_TCHECK_1(tptr);
                          ND_PRINT((ndo, "%s", tok2str(bgp_as_path_segment_close_values,
-                                               "?", tptr[0])));
-                         ND_TCHECK(tptr[1]);
-                         tptr += 2 + tptr[1] * as_size;
+                                               "?", 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"));
                else {
-                       ND_TCHECK2(tptr[0], 4);
+                       ND_TCHECK_4(tptr);
                        ND_PRINT((ndo, "%s", ipaddr_string(ndo, tptr)));
                }
                break;
                if (len != 4)
                        ND_PRINT((ndo, "invalid len"));
                else {
-                       ND_TCHECK2(tptr[0], 4);
-                       ND_PRINT((ndo, "%u", EXTRACT_32BITS(tptr)));
+                       ND_TCHECK_4(tptr);
+                       ND_PRINT((ndo, "%u", EXTRACT_BE_U_4(tptr)));
                }
                break;
        case BGPTYPE_ATOMIC_AGGREGATE:
                      ND_PRINT((ndo, "invalid len"));
                      break;
                  }
-                 ND_TCHECK2(tptr[0], len);
+                 ND_TCHECK_LEN(tptr, len);
                  if (len == 6) {
                    ND_PRINT((ndo, " AS #%s, origin %s",
-                       as_printf(ndo, astostr, sizeof(astostr), EXTRACT_16BITS(tptr)),
+                       as_printf(ndo, astostr, sizeof(astostr), EXTRACT_BE_U_2(tptr)),
                        ipaddr_string(ndo, tptr + 2)));
                  } else {
                    ND_PRINT((ndo, " AS #%s, origin %s",
                        as_printf(ndo, astostr, sizeof(astostr),
-                       EXTRACT_32BITS(tptr)), ipaddr_string(ndo, tptr + 4)));
+                       EXTRACT_BE_U_4(tptr)), ipaddr_string(ndo, tptr + 4)));
                  }
                  break;
        case BGPTYPE_AGGREGATOR4:
                        ND_PRINT((ndo, "invalid len"));
                        break;
                }
-               ND_TCHECK2(tptr[0], 8);
+               ND_TCHECK_8(tptr);
                ND_PRINT((ndo, " AS #%s, origin %s",
-                   as_printf(ndo, astostr, sizeof(astostr), EXTRACT_32BITS(tptr)),
-                   ipaddr_string(ndo, tptr + 4)));
+                   as_printf(ndo, astostr, sizeof(astostr), EXTRACT_BE_U_4(tptr)),
+                   ipaddr_string(ndo, tptr + 4)));
                break;
        case BGPTYPE_COMMUNITIES:
                if (len % 4) {
                }
                while (tlen>0) {
                        uint32_t comm;
-                       ND_TCHECK2(tptr[0], 4);
-                       comm = EXTRACT_32BITS(tptr);
+                       ND_TCHECK_4(tptr);
+                       comm = EXTRACT_BE_U_4(tptr);
                        switch (comm) {
                        case BGP_COMMUNITY_NO_EXPORT:
                                ND_PRINT((ndo, " NO_EXPORT"));
                        ND_PRINT((ndo, "invalid len"));
                        break;
                }
-               ND_TCHECK2(tptr[0], 4);
+               ND_TCHECK_4(tptr);
                  ND_PRINT((ndo, "%s",ipaddr_string(ndo, tptr)));
                  break;
          case BGPTYPE_CLUSTER_LIST:
                        break;
                }
                  while (tlen>0) {
-                       ND_TCHECK2(tptr[0], 4);
+                       ND_TCHECK_4(tptr);
                          ND_PRINT((ndo, "%s%s",
                                 ipaddr_string(ndo, tptr),
                                  (tlen>4) ? ", " : ""));
                  }
                  break;
        case BGPTYPE_MP_REACH_NLRI:
-               ND_TCHECK2(tptr[0], 3);
-               af = EXTRACT_16BITS(tptr);
-               safi = tptr[2];
+               ND_TCHECK_3(tptr);
+               af = EXTRACT_BE_U_2(tptr);
+               safi = EXTRACT_U_1(tptr + 2);
  
                  ND_PRINT((ndo, "\n\t    AFI: %s (%u), %sSAFI: %s (%u)",
                         tok2str(af_values, "Unknown AFI", af),
                  case (AFNUM_VPLS<<8 | SAFNUM_VPLS):
                      break;
                  default:
-                     ND_TCHECK2(tptr[0], tlen);
+                     ND_TCHECK_LEN(tptr, tlen);
                      ND_PRINT((ndo, "\n\t    no AFI %u / SAFI %u decoder", af, safi));
                      if (ndo->ndo_vflag <= 1)
                          print_unknown_data(ndo, tptr, "\n\t    ", tlen);
  
                  tptr +=3;
  
-               ND_TCHECK(tptr[0]);
-               nhlen = tptr[0];
+               ND_TCHECK_1(tptr);
+               nhlen = EXTRACT_U_1(tptr);
                  tlen = nhlen;
                  tptr++;
  
                          case (AFNUM_INET<<8 | SAFNUM_RT_ROUTING_INFO):
                          case (AFNUM_INET<<8 | SAFNUM_MULTICAST_VPN):
                          case (AFNUM_INET<<8 | SAFNUM_MDT):
-                           if (tlen < (int)sizeof(struct in_addr)) {
+                           if (tlen < sizeof(struct in_addr)) {
                                  ND_PRINT((ndo, "invalid len"));
                                  tlen = 0;
                              } else {
-                                 ND_TCHECK2(tptr[0], sizeof(struct in_addr));
+                                 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);
                          case (AFNUM_INET<<8 | SAFNUM_VPNUNICAST):
                          case (AFNUM_INET<<8 | SAFNUM_VPNMULTICAST):
                          case (AFNUM_INET<<8 | SAFNUM_VPNUNIMULTICAST):
-                             if (tlen < (int)(sizeof(struct in_addr)+BGP_VPN_RD_LEN)) {
+                             if (tlen < sizeof(struct in_addr)+BGP_VPN_RD_LEN) {
                                  ND_PRINT((ndo, "invalid len"));
                                  tlen = 0;
                              } else {
-                                 ND_TCHECK2(tptr[0], sizeof(struct in_addr)+BGP_VPN_RD_LEN);
+                                 ND_TCHECK_LEN(tptr,
+                                               sizeof(struct in_addr) + BGP_VPN_RD_LEN);
                                  ND_PRINT((ndo, "RD: %s, %s",
                                         bgp_vpn_rd_print(ndo, tptr),
                                         ipaddr_string(ndo, tptr+BGP_VPN_RD_LEN)));
                          case (AFNUM_INET6<<8 | SAFNUM_MULTICAST):
                          case (AFNUM_INET6<<8 | SAFNUM_UNIMULTICAST):
                          case (AFNUM_INET6<<8 | SAFNUM_LABUNICAST):
-                             if (tlen < (int)sizeof(struct in6_addr)) {
+                             if (tlen < sizeof(struct in6_addr)) {
                                  ND_PRINT((ndo, "invalid len"));
                                  tlen = 0;
                              } else {
-                                 ND_TCHECK2(tptr[0], sizeof(struct in6_addr));
+                                 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);
                          case (AFNUM_INET6<<8 | SAFNUM_VPNUNICAST):
                          case (AFNUM_INET6<<8 | SAFNUM_VPNMULTICAST):
                          case (AFNUM_INET6<<8 | SAFNUM_VPNUNIMULTICAST):
-                             if (tlen < (int)(sizeof(struct in6_addr)+BGP_VPN_RD_LEN)) {
+                             if (tlen < sizeof(struct in6_addr)+BGP_VPN_RD_LEN) {
                                  ND_PRINT((ndo, "invalid len"));
                                  tlen = 0;
                              } else {
-                                 ND_TCHECK2(tptr[0], sizeof(struct in6_addr)+BGP_VPN_RD_LEN);
+                                 ND_TCHECK_LEN(tptr,
+                                               sizeof(struct in6_addr) + BGP_VPN_RD_LEN);
                                  ND_PRINT((ndo, "RD: %s, %s",
                                         bgp_vpn_rd_print(ndo, tptr),
                                         ip6addr_string(ndo, tptr+BGP_VPN_RD_LEN)));
                          case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNICAST):
                          case (AFNUM_L2VPN<<8 | SAFNUM_VPNMULTICAST):
                          case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNIMULTICAST):
-                             if (tlen < (int)sizeof(struct in_addr)) {
+                             if (tlen < sizeof(struct in_addr)) {
                                  ND_PRINT((ndo, "invalid len"));
                                  tlen = 0;
                              } else {
-                                 ND_TCHECK2(tptr[0], sizeof(struct in_addr));
+                                 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));
                          case (AFNUM_NSAP<<8 | SAFNUM_UNICAST):
                          case (AFNUM_NSAP<<8 | SAFNUM_MULTICAST):
                          case (AFNUM_NSAP<<8 | SAFNUM_UNIMULTICAST):
-                             ND_TCHECK2(tptr[0], tlen);
+                             ND_TCHECK_LEN(tptr, tlen);
                              ND_PRINT((ndo, "%s", isonsap_string(ndo, tptr, tlen)));
                              tptr += tlen;
                              tlen = 0;
                                  ND_PRINT((ndo, "invalid len"));
                                  tlen = 0;
                              } else {
-                                 ND_TCHECK2(tptr[0], tlen);
+                                 ND_TCHECK_LEN(tptr, tlen);
                                  ND_PRINT((ndo, "RD: %s, %s",
                                         bgp_vpn_rd_print(ndo, tptr),
                                         isonsap_string(ndo, tptr+BGP_VPN_RD_LEN,tlen-BGP_VPN_RD_LEN)));
                                  /* rfc986 mapped IPv4 address ? */
-                                 if (EXTRACT_32BITS(tptr+BGP_VPN_RD_LEN) ==  0x47000601)
+                                 if (EXTRACT_BE_U_4(tptr + BGP_VPN_RD_LEN) ==  0x47000601)
                                      ND_PRINT((ndo, " = %s", ipaddr_string(ndo, tptr+BGP_VPN_RD_LEN+4)));
                                  /* rfc1888 mapped IPv6 address ? */
-                                 else if (EXTRACT_24BITS(tptr+BGP_VPN_RD_LEN) ==  0x350000)
+                                 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)));
                                  tptr += tlen;
                                  tlen = 0;
                              }
                              break;
                          default:
-                             ND_TCHECK2(tptr[0], tlen);
+                             ND_TCHECK_LEN(tptr, tlen);
                              ND_PRINT((ndo, "no AFI %u/SAFI %u decoder", af, safi));
                              if (ndo->ndo_vflag <= 1)
                                  print_unknown_data(ndo, tptr, "\n\t    ", tlen);
                ND_PRINT((ndo, ", nh-length: %u", nhlen));
                tptr += tlen;
  
-               ND_TCHECK(tptr[0]);
-               snpa = tptr[0];
+               ND_TCHECK_1(tptr);
+               snpa = EXTRACT_U_1(tptr);
                tptr++;
  
                if (snpa) {
                        ND_PRINT((ndo, "\n\t    %u SNPA", snpa));
                        for (/*nothing*/; snpa > 0; snpa--) {
-                               ND_TCHECK(tptr[0]);
-                               ND_PRINT((ndo, "\n\t      %d bytes", tptr[0]));
-                               tptr += tptr[0] + 1;
+                               ND_TCHECK_1(tptr);
+                               ND_PRINT((ndo, "\n\t      %d bytes", EXTRACT_U_1(tptr)));
+                               tptr += EXTRACT_U_1(tptr) + 1;
                        }
                } else {
                        ND_PRINT((ndo, ", no SNPA"));
                  }
  
 +                add_path4 = check_add_path(tptr, (len-(tptr - pptr)), 32);
 +                add_path6 = check_add_path(tptr, (len-(tptr - pptr)), 128);
 +
                while (tptr < pptr + len) {
                      switch (af<<8 | safi) {
                      case (AFNUM_INET<<8 | SAFNUM_UNICAST):
                      case (AFNUM_INET<<8 | SAFNUM_MULTICAST):
                      case (AFNUM_INET<<8 | SAFNUM_UNIMULTICAST):
 +                        if (add_path4) {
 +                            path_id = EXTRACT_32BITS(tptr);
 +                            tptr += 4;
 +                        }
                          advance = decode_prefix4(ndo, tptr, len, buf, sizeof(buf));
                          if (advance == -1)
                              ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
                              break; /* bytes left, but not enough */
                          else
                              ND_PRINT((ndo, "\n\t      %s", buf));
 +                            if (add_path4) {
 +                                ND_PRINT((ndo, "   Path Id: %d", path_id));
 +                            }
                          break;
                      case (AFNUM_INET<<8 | SAFNUM_LABUNICAST):
                          advance = decode_labeled_prefix4(ndo, tptr, len, buf, sizeof(buf));
                      case (AFNUM_INET6<<8 | SAFNUM_UNICAST):
                      case (AFNUM_INET6<<8 | SAFNUM_MULTICAST):
                      case (AFNUM_INET6<<8 | SAFNUM_UNIMULTICAST):
 +                        if (add_path6) {
 +                            path_id = EXTRACT_32BITS(tptr);
 +                            tptr += 4;
 +                        }
                          advance = decode_prefix6(ndo, tptr, len, buf, sizeof(buf));
                          if (advance == -1)
                              ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
                              break; /* bytes left, but not enough */
                          else
                              ND_PRINT((ndo, "\n\t      %s", buf));
 +                            if (add_path6) {
 +                                ND_PRINT((ndo, "   Path Id: %d", path_id));
 +                            }
                          break;
                      case (AFNUM_INET6<<8 | SAFNUM_LABUNICAST):
                          advance = decode_labeled_prefix6(ndo, tptr, len, buf, sizeof(buf));
                              ND_PRINT((ndo, "\n\t      %s", buf));
                          break;
                      default:
-                         ND_TCHECK2(*tptr,tlen);
+                         ND_TCHECK_LEN(tptr, tlen);
                          ND_PRINT((ndo, "\n\t    no AFI %u / SAFI %u decoder", af, safi));
                          if (ndo->ndo_vflag <= 1)
                              print_unknown_data(ndo, tptr, "\n\t    ", tlen);
                break;
  
        case BGPTYPE_MP_UNREACH_NLRI:
-               ND_TCHECK2(tptr[0], BGP_MP_NLRI_MINSIZE);
-               af = EXTRACT_16BITS(tptr);
-               safi = tptr[2];
+               ND_TCHECK_LEN(tptr, BGP_MP_NLRI_MINSIZE);
+               af = EXTRACT_BE_U_2(tptr);
+               safi = EXTRACT_U_1(tptr + 2);
  
                  ND_PRINT((ndo, "\n\t    AFI: %s (%u), %sSAFI: %s (%u)",
                         tok2str(af_values, "Unknown AFI", af),
  
                tptr += 3;
  
 +                add_path4 = check_add_path(tptr, (len-(tptr - pptr)), 32);
 +                add_path6 = check_add_path(tptr, (len-(tptr - pptr)), 128);
 +
                while (tptr < pptr + len) {
                      switch (af<<8 | safi) {
                      case (AFNUM_INET<<8 | SAFNUM_UNICAST):
                      case (AFNUM_INET<<8 | SAFNUM_MULTICAST):
                      case (AFNUM_INET<<8 | SAFNUM_UNIMULTICAST):
 +                        if (add_path4) {
 +                            path_id = EXTRACT_32BITS(tptr);
 +                            tptr += 4;
 +                        }
                          advance = decode_prefix4(ndo, tptr, len, buf, sizeof(buf));
                          if (advance == -1)
                              ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
                              break; /* bytes left, but not enough */
                          else
                              ND_PRINT((ndo, "\n\t      %s", buf));
 +                            if (add_path4) {
 +                                ND_PRINT((ndo, "   Path Id: %d", path_id));
 +                            }
                          break;
                      case (AFNUM_INET<<8 | SAFNUM_LABUNICAST):
                          advance = decode_labeled_prefix4(ndo, tptr, len, buf, sizeof(buf));
                      case (AFNUM_INET6<<8 | SAFNUM_UNICAST):
                      case (AFNUM_INET6<<8 | SAFNUM_MULTICAST):
                      case (AFNUM_INET6<<8 | SAFNUM_UNIMULTICAST):
 +                        if (add_path6) {
 +                            path_id = EXTRACT_32BITS(tptr);
 +                            tptr += 4;
 +                        }
                          advance = decode_prefix6(ndo, tptr, len, buf, sizeof(buf));
                          if (advance == -1)
                              ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
                              break; /* bytes left, but not enough */
                          else
                              ND_PRINT((ndo, "\n\t      %s", buf));
 +                            if (add_path6) {
 +                                ND_PRINT((ndo, "   Path Id: %d", path_id));
 +                            }
                          break;
                      case (AFNUM_INET6<<8 | SAFNUM_LABUNICAST):
                          advance = decode_labeled_prefix6(ndo, tptr, len, buf, sizeof(buf));
                              ND_PRINT((ndo, "\n\t      %s", buf));
                          break;
                      default:
-                         ND_TCHECK2(*(tptr-3),tlen);
+                         ND_TCHECK_LEN(tptr - 3, tlen);
                          ND_PRINT((ndo, "no AFI %u / SAFI %u decoder", af, safi));
                          if (ndo->ndo_vflag <= 1)
                              print_unknown_data(ndo, tptr-3, "\n\t    ", tlen);
                  while (tlen>0) {
                      uint16_t extd_comm;
  
-                     ND_TCHECK2(tptr[0], 2);
-                     extd_comm=EXTRACT_16BITS(tptr);
+                     ND_TCHECK_2(tptr);
+                     extd_comm=EXTRACT_BE_U_2(tptr);
  
                    ND_PRINT((ndo, "\n\t    %s (0x%04x), Flags [%s]",
                           tok2str(bgp_extd_comm_subtype_values,
                           extd_comm,
                           bittok2str(bgp_extd_comm_flag_values, "none", extd_comm)));
  
-                     ND_TCHECK2(*(tptr+2), 6);
+                     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_16BITS(tptr+2),
-                                EXTRACT_32BITS(tptr+4),
+                                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_VRF_RT_IMP:
                          ND_PRINT((ndo, ": %s:%u",
                                 ipaddr_string(ndo, tptr+2),
-                                EXTRACT_16BITS(tptr+6)));
+                                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_32BITS(tptr+2)), EXTRACT_16BITS(tptr+6)));
+                           EXTRACT_BE_U_4(tptr + 2)), EXTRACT_BE_U_2(tptr + 6)));
                        break;
                      case BGP_EXT_COM_LINKBAND:
-                       bw.i = EXTRACT_32BITS(tptr+2);
+                       bw.i = EXTRACT_BE_U_4(tptr + 2);
                          ND_PRINT((ndo, ": bandwidth: %.3f Mbps",
                                 bw.f*8/1000000));
                          break;
                                 ipaddr_string(ndo, tptr+2),
                                 tok2str(bgp_extd_comm_ospf_rtype_values,
                                          "unknown (0x%02x)",
-                                         *(tptr+6)),
-                                (*(tptr+7) &  BGP_OSPF_RTYPE_METRIC_TYPE) ? "E2" : "",
-                                ((*(tptr+6) == BGP_OSPF_RTYPE_EXT) || (*(tptr+6) == BGP_OSPF_RTYPE_NSSA)) ? "E1" : ""));
+                                         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",
-                                         *(tptr+2)),
-                                        *(tptr+3),
-                                EXTRACT_16BITS(tptr+4)));
+                                         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_16BITS(tptr+2)));
+                         ND_PRINT((ndo, ": AS %u", EXTRACT_BE_U_2(tptr + 2)));
                          break;
                      default:
-                         ND_TCHECK2(*tptr,8);
+                         ND_TCHECK_8(tptr);
                          print_unknown_data(ndo, tptr, "\n\t      ", 8);
                          break;
                      }
          {
                  uint8_t tunnel_type, flags;
  
-                 ND_TCHECK2(tptr[0], 5);
-                 tunnel_type = *(tptr+1);
-                 flags = *tptr;
+                 ND_TCHECK_5(tptr);
+                 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",
                         tok2str(bgp_pmsi_tunnel_values, "Unknown", tunnel_type),
                         tunnel_type,
                         bittok2str(bgp_pmsi_flag_values, "none", flags),
-                        EXTRACT_24BITS(tptr+2)>>4));
+                        EXTRACT_BE_U_3(tptr + 2)>>4));
  
                  tptr +=5;
                  tlen -= 5;
                  switch (tunnel_type) {
                  case BGP_PMSI_TUNNEL_PIM_SM: /* fall through */
                  case BGP_PMSI_TUNNEL_PIM_BIDIR:
-                     ND_TCHECK2(tptr[0], 8);
+                     ND_TCHECK_8(tptr);
                      ND_PRINT((ndo, "\n\t      Sender %s, P-Group %s",
                             ipaddr_string(ndo, tptr),
                             ipaddr_string(ndo, tptr+4)));
                      break;
  
                  case BGP_PMSI_TUNNEL_PIM_SSM:
-                     ND_TCHECK2(tptr[0], 8);
+                     ND_TCHECK_8(tptr);
                      ND_PRINT((ndo, "\n\t      Root-Node %s, P-Group %s",
                             ipaddr_string(ndo, tptr),
                             ipaddr_string(ndo, tptr+4)));
                      break;
                  case BGP_PMSI_TUNNEL_INGRESS:
-                     ND_TCHECK2(tptr[0], 4);
+                     ND_TCHECK_4(tptr);
                      ND_PRINT((ndo, "\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_TCHECK2(tptr[0], 8);
+                     ND_TCHECK_8(tptr);
                      ND_PRINT((ndo, "\n\t      Root-Node %s, LSP-ID 0x%08x",
                             ipaddr_string(ndo, tptr),
-                            EXTRACT_32BITS(tptr+4)));
+                            EXTRACT_BE_U_4(tptr + 4)));
                      break;
                  case BGP_PMSI_TUNNEL_RSVP_P2MP:
-                     ND_TCHECK2(tptr[0], 8);
+                     ND_TCHECK_8(tptr);
                      ND_PRINT((ndo, "\n\t      Extended-Tunnel-ID %s, P2MP-ID 0x%08x",
                             ipaddr_string(ndo, tptr),
-                            EXTRACT_32BITS(tptr+4)));
+                            EXTRACT_BE_U_4(tptr + 4)));
                      break;
                  default:
                      if (ndo->ndo_vflag <= 1) {
  
                while (tlen >= 3) {
  
-                   ND_TCHECK2(tptr[0], 3);
+                   ND_TCHECK_3(tptr);
  
-                   type = *tptr;
-                   length = EXTRACT_16BITS(tptr+1);
+                   type = EXTRACT_U_1(tptr);
+                   length = EXTRACT_BE_U_2(tptr + 1);
                    tptr += 3;
                    tlen -= 3;
  
                    /*
                     * Check if we can read the TLV data.
                     */
-                   ND_TCHECK2(tptr[3], length);
+                   ND_TCHECK_LEN(tptr + 3, length);
  
                    switch (type) {
  
                        if (length < 8)
                            goto trunc;
                        ND_PRINT((ndo, ", metric %" PRIu64,
-                                 EXTRACT_64BITS(tptr)));
+                                 EXTRACT_BE_U_8(tptr)));
                        break;
  
                    default:
                break;
        }
          case BGPTYPE_ATTR_SET:
-                 ND_TCHECK2(tptr[0], 4);
+                 ND_TCHECK_4(tptr);
                  if (len < 4)
                        goto trunc;
                ND_PRINT((ndo, "\n\t    Origin AS: %s",
-                   as_printf(ndo, astostr, sizeof(astostr), EXTRACT_32BITS(tptr))));
+                   as_printf(ndo, astostr, sizeof(astostr), EXTRACT_BE_U_4(tptr))));
                tptr+=4;
                  len -=4;
  
                  while (len) {
                      u_int aflags, alenlen, alen;
  
-                     ND_TCHECK2(tptr[0], 2);
+                     ND_TCHECK_2(tptr);
                      if (len < 2)
                          goto trunc;
-                     aflags = *tptr;
-                     atype = *(tptr + 1);
+                     aflags = EXTRACT_U_1(tptr);
+                     atype = EXTRACT_U_1(tptr + 1);
                      tptr += 2;
                      len -= 2;
                      alenlen = bgp_attr_lenlen(aflags, tptr);
-                     ND_TCHECK2(tptr[0], alenlen);
+                     ND_TCHECK_LEN(tptr, alenlen);
                      if (len < alenlen)
                          goto trunc;
                      alen = bgp_attr_len(aflags, tptr);
                }
                ND_PRINT((ndo, "\n\t    "));
                while (len > 0) {
-                       ND_TCHECK2(*tptr, 12);
+                       ND_TCHECK_LEN(tptr, 12);
                        ND_PRINT((ndo, "%u:%u:%u%s",
-                                EXTRACT_32BITS(tptr),
-                                EXTRACT_32BITS(tptr + 4),
-                                EXTRACT_32BITS(tptr + 8),
+                                EXTRACT_BE_U_4(tptr),
+                                EXTRACT_BE_U_4(tptr + 4),
+                                EXTRACT_BE_U_4(tptr + 8),
                                 (len > 12) ? ", " : ""));
                          tptr += 12;
                          len -= 12;
                }
                break;
        default:
-           ND_TCHECK2(*pptr,len);
+           ND_TCHECK_LEN(pptr, len);
              ND_PRINT((ndo, "\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;
        }
          if (ndo->ndo_vflag > 1 && len) { /* omit zero length attributes*/
-             ND_TCHECK2(*pptr,len);
+             ND_TCHECK_LEN(pptr, len);
              print_unknown_data(ndo, pptr, "\n\t    ", len);
          }
          return 1;
@@@ -2420,47 -2342,47 +2433,47 @@@ trunc
  
  static void
  bgp_capabilities_print(netdissect_options *ndo,
-                        const u_char *opt, int caps_len)
+                        const u_char *opt, u_int caps_len)
  {
-       int cap_type, cap_len, tcap_len, cap_offset;
-         int i = 0;
+       u_int cap_type, cap_len, tcap_len, cap_offset;
+         u_int i = 0;
  
          while (i < caps_len) {
-                 ND_TCHECK2(opt[i], BGP_CAP_HEADER_SIZE);
-                 cap_type=opt[i];
-                 cap_len=opt[i+1];
+                 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",
                         tok2str(bgp_capcode_values, "Unknown",
                                    cap_type),
                         cap_type,
                         cap_len));
-                 ND_TCHECK2(opt[i+2], 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)",
                             tok2str(af_values, "Unknown",
-                                       EXTRACT_16BITS(opt+i+2)),
-                            EXTRACT_16BITS(opt+i+2),
+                                       EXTRACT_BE_U_2(opt + i + 2)),
+                            EXTRACT_BE_U_2(opt + i + 2),
                             tok2str(bgp_safi_values, "Unknown",
-                                       opt[i+5]),
-                            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",
-                            ((opt[i+2])&0x80) ? "R" : "none",
-                            EXTRACT_16BITS(opt+i+2)&0xfff));
+                            ((EXTRACT_U_1(opt + i + 2))&0x80) ? "R" : "none",
+                            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",
                                 tok2str(af_values,"Unknown",
-                                           EXTRACT_16BITS(opt+i+cap_offset)),
-                                EXTRACT_16BITS(opt+i+cap_offset),
+                                           EXTRACT_BE_U_2(opt + i + cap_offset)),
+                                EXTRACT_BE_U_2(opt + i + cap_offset),
                                 tok2str(bgp_safi_values,"Unknown",
-                                           opt[i+cap_offset+2]),
-                                opt[i+cap_offset+2],
-                                ((opt[i+cap_offset+3])&0x80) ? "yes" : "no" ));
+                                           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" ));
                          tcap_len-=4;
                          cap_offset+=4;
                      }
                      if (cap_len == 4) {
                          ND_PRINT((ndo, "\n\t\t 4 Byte AS %s",
                              as_printf(ndo, astostr, sizeof(astostr),
-                             EXTRACT_32BITS(opt + i + 2))));
+                             EXTRACT_BE_U_4(opt + i + 2))));
                      }
                      break;
                  case BGP_CAPCODE_ADD_PATH:
                              break;
                          }
                          ND_PRINT((ndo, "\n\t\tAFI %s (%u), SAFI %s (%u), Send/Receive: %s",
-                                   tok2str(af_values,"Unknown",EXTRACT_16BITS(opt+i+cap_offset)),
-                                   EXTRACT_16BITS(opt+i+cap_offset),
-                                   tok2str(bgp_safi_values,"Unknown",opt[i+cap_offset+2]),
-                                   opt[i+cap_offset+2],
-                                   tok2str(bgp_add_path_recvsend,"Bogus (0x%02x)",opt[i+cap_offset+3])
+                                   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;
                      ND_PRINT((ndo, "\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);
+                         print_unknown_data(ndo, opt + i + 2, "\n\t\t",
+                                          cap_len);
                      break;
                  }
                  if (ndo->ndo_vflag > 1 && cap_len > 0) {
-                     print_unknown_data(ndo, &opt[i+2], "\n\t\t", cap_len);
+                     print_unknown_data(ndo, opt + i + 2, "\n\t\t", cap_len);
                  }
                  i += BGP_CAP_HEADER_SIZE + cap_len;
          }
@@@ -2521,61 -2444,69 +2535,69 @@@ trunc
  
  static void
  bgp_open_print(netdissect_options *ndo,
-                const u_char *dat, int length)
+                const u_char *dat, u_int length)
  {
-       struct bgp_open bgpo;
-       struct bgp_opt bgpopt;
+       const struct bgp_open *bgp_open_header;
+       u_int optslen;
+       const struct bgp_opt *bgpopt;
        const u_char *opt;
-       int i;
+       u_int i;
  
-       ND_TCHECK2(dat[0], BGP_OPEN_SIZE);
-       memcpy(&bgpo, dat, BGP_OPEN_SIZE);
+       ND_TCHECK_LEN(dat, BGP_OPEN_SIZE);
+       if (length < BGP_OPEN_SIZE)
+               goto trunc;
  
-       ND_PRINT((ndo, "\n\t  Version %d, ", bgpo.bgpo_version));
-       ND_PRINT((ndo, "my AS %s, ",
-           as_printf(ndo, astostr, sizeof(astostr), ntohs(bgpo.bgpo_myas))));
-       ND_PRINT((ndo, "Holdtime %us, ", ntohs(bgpo.bgpo_holdtime)));
-       ND_PRINT((ndo, "ID %s", ipaddr_string(ndo, &bgpo.bgpo_id)));
-       ND_PRINT((ndo, "\n\t  Optional parameters, length: %u", bgpo.bgpo_optlen));
+       bgp_open_header = (const struct bgp_open *)dat;
  
-         /* some little sanity checking */
-         if (length < bgpo.bgpo_optlen+BGP_OPEN_SIZE)
-             return;
+       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)));
+       optslen = EXTRACT_U_1(bgp_open_header->bgpo_optlen);
+       ND_PRINT((ndo, "\n\t  Optional parameters, length: %u", optslen));
  
-       /* ugly! */
-       opt = &((const struct bgp_open *)dat)->bgpo_optlen;
-       opt++;
+       opt = dat + BGP_OPEN_SIZE;
+       length -= BGP_OPEN_SIZE;
  
        i = 0;
-       while (i < bgpo.bgpo_optlen) {
-               ND_TCHECK2(opt[i], BGP_OPT_SIZE);
-               memcpy(&bgpopt, &opt[i], BGP_OPT_SIZE);
-               if (i + 2 + bgpopt.bgpopt_len > bgpo.bgpo_optlen) {
-                       ND_PRINT((ndo, "\n\t     Option %d, length: %u", bgpopt.bgpopt_type, bgpopt.bgpopt_len));
+       while (i < optslen) {
+               uint8_t opt_type, opt_len;
+               ND_TCHECK_LEN(opt + i, BGP_OPT_SIZE);
+               if (length < BGP_OPT_SIZE + i)
+                       goto trunc;
+               bgpopt = (const struct bgp_opt *)(opt + i);
+               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));
                        break;
                }
  
                ND_PRINT((ndo, "\n\t    Option %s (%u), length: %u",
-                      tok2str(bgp_opt_values,"Unknown",
-                                 bgpopt.bgpopt_type),
-                      bgpopt.bgpopt_type,
-                      bgpopt.bgpopt_len));
+                      tok2str(bgp_opt_values,"Unknown",opt_type),
+                      opt_type,
+                      opt_len));
  
                /* now let's decode the options we know*/
-               switch(bgpopt.bgpopt_type) {
+               switch(opt_type) {
  
                case BGP_OPT_CAP:
-                       bgp_capabilities_print(ndo, &opt[i+BGP_OPT_SIZE],
-                           bgpopt.bgpopt_len);
+                       bgp_capabilities_print(ndo, opt + BGP_OPT_SIZE + i,
+                                              opt_len);
                        break;
  
                case BGP_OPT_AUTH:
                default:
                       ND_PRINT((ndo, "\n\t      no decoder for option %u",
-                          bgpopt.bgpopt_type));
+                          opt_type));
                       break;
                }
-               i += BGP_OPT_SIZE + bgpopt.bgpopt_len;
+               i += BGP_OPT_SIZE + opt_len;
        }
        return;
  trunc:
@@@ -2586,71 -2517,44 +2608,76 @@@ static voi
  bgp_update_print(netdissect_options *ndo,
                   const u_char *dat, int length)
  {
-       struct bgp bgp;
+       const struct bgp *bgp_header;
        const u_char *p;
        int withdrawn_routes_len;
 +        char buf[MAXHOSTNAMELEN + 100];
 +        int wpfx;
        int len;
        int i;
 +        int add_path;
 +        int path_id;
  
-       ND_TCHECK2(dat[0], BGP_SIZE);
+       ND_TCHECK_LEN(dat, BGP_SIZE);
        if (length < BGP_SIZE)
                goto trunc;
-       memcpy(&bgp, dat, BGP_SIZE);
-       p = dat + BGP_SIZE;     /*XXX*/
+       bgp_header = (const struct bgp *)dat;
+       p = dat + BGP_SIZE;
        length -= BGP_SIZE;
  
        /* Unfeasible routes */
-       ND_TCHECK2(p[0], 2);
+       ND_TCHECK_2(p);
        if (length < 2)
                goto trunc;
-       withdrawn_routes_len = EXTRACT_16BITS(p);
+       withdrawn_routes_len = EXTRACT_BE_U_2(p);
        p += 2;
        length -= 2;
 -      if (withdrawn_routes_len) {
 +      if (withdrawn_routes_len > 1) {
-               ND_TCHECK2(p[0], withdrawn_routes_len);
+               /*
+                * Without keeping state from the original NLRI message,
+                * it's not possible to tell if this a v4 or v6 route,
+                * so only try to decode it if we're not v6 enabled.
 -               */
++         */
+               ND_TCHECK_LEN(p, withdrawn_routes_len);
                if (length < withdrawn_routes_len)
                        goto trunc;
 -              ND_PRINT((ndo, "\n\t  Withdrawn routes: %d bytes", withdrawn_routes_len));
 -              p += withdrawn_routes_len;
 -              length -= withdrawn_routes_len;
 -      }
 +
 +                ND_PRINT((ndo, "\n\t  Withdrawn routes:"));
 +                add_path = check_add_path(p, withdrawn_routes_len, 32);
 +                while(withdrawn_routes_len > 0) {
 +                        if (add_path) {
 +                                path_id = EXTRACT_32BITS(p);
 +                                p += 4;
 +                                length -= 4;
 +                                withdrawn_routes_len -= 4;
 +                        }
 +                        wpfx = decode_prefix4(ndo, p, withdrawn_routes_len, buf, sizeof(buf));
 +                        if (wpfx == -1) {
 +                                ND_PRINT((ndo, "\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));
 +                                if (add_path) {
 +                                    ND_PRINT((ndo, "   Path Id: %d", path_id));
 +                                }
 +                                p += wpfx;
 +                                length -= wpfx;
 +                                withdrawn_routes_len -= wpfx;
 +                        }
 +                }
 +      } else {
 +                p += withdrawn_routes_len;
 +                length -= withdrawn_routes_len;
 +        }
  
-       ND_TCHECK2(p[0], 2);
+       ND_TCHECK_2(p);
        if (length < 2)
                goto trunc;
-       len = EXTRACT_16BITS(p);
+       len = EXTRACT_BE_U_2(p);
        p += 2;
        length -= 2;
  
                while (len) {
                        int aflags, atype, alenlen, alen;
  
-                       ND_TCHECK2(p[0], 2);
+                       ND_TCHECK_2(p);
                        if (len < 2)
                            goto trunc;
                        if (length < 2)
                            goto trunc;
-                       aflags = *p;
-                       atype = *(p + 1);
+                       aflags = EXTRACT_U_1(p);
+                       atype = EXTRACT_U_1(p + 1);
                        p += 2;
                        len -= 2;
                        length -= 2;
                        alenlen = bgp_attr_lenlen(aflags, p);
-                       ND_TCHECK2(p[0], alenlen);
+                       ND_TCHECK_LEN(p, alenlen);
                        if (len < alenlen)
                            goto trunc;
                        if (length < alenlen)
        }
  
        if (length) {
 -              /*
 -               * XXX - what if they're using the "Advertisement of
 -               * Multiple Paths in BGP" feature:
 -               *
 -               * https://datatracker.ietf.org/doc/draft-ietf-idr-add-paths/
 -               *
 -               * http://tools.ietf.org/html/draft-ietf-idr-add-paths-06
 -               */
 +                add_path = check_add_path(p, length, 32);
                ND_PRINT((ndo, "\n\t  Updated routes:"));
 -              while (length) {
 -                      char buf[MAXHOSTNAMELEN + 100];
 +              while (length > 0) {
 +                      if (add_path) {
 +                                path_id = EXTRACT_32BITS(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)"));
                        else if (i == -3)
                                goto trunc; /* bytes left, but not enough */
                        else {
 -                              ND_PRINT((ndo, "\n\t    %s", buf));
 -                              p += i;
 -                              length -= i;
 +                                ND_PRINT((ndo, "\n\t    %s", buf));
 +                              if (add_path) {
 +                                        ND_PRINT((ndo, "   Path Id: %d", path_id));
 +                              }
 +                              p += i;
 +                                length -= i;
                        }
                }
        }
@@@ -2750,85 -2654,87 +2777,87 @@@ static voi
  bgp_notification_print(netdissect_options *ndo,
                         const u_char *dat, int length)
  {
-       struct bgp_notification bgpn;
+       const struct bgp_notification *bgp_notification_header;
        const u_char *tptr;
+       uint8_t bgpn_major, bgpn_minor;
        uint8_t shutdown_comm_length;
        uint8_t remainder_offset;
  
-       ND_TCHECK2(dat[0], BGP_NOTIFICATION_SIZE);
-       memcpy(&bgpn, dat, BGP_NOTIFICATION_SIZE);
-         /* some little sanity checking */
+       ND_TCHECK_LEN(dat, BGP_NOTIFICATION_SIZE);
          if (length<BGP_NOTIFICATION_SIZE)
              return;
  
+       bgp_notification_header = (const struct bgp_notification *)dat;
+       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)",
               tok2str(bgp_notify_major_values, "Unknown Error",
-                         bgpn.bgpn_major),
-              bgpn.bgpn_major));
+                         bgpn_major),
+              bgpn_major));
  
-         switch (bgpn.bgpn_major) {
+         switch (bgpn_major) {
  
          case BGP_NOTIFY_MAJOR_MSG:
              ND_PRINT((ndo, ", subcode %s (%u)",
                   tok2str(bgp_notify_minor_msg_values, "Unknown",
-                             bgpn.bgpn_minor),
-                  bgpn.bgpn_minor));
+                             bgpn_minor),
+                  bgpn_minor));
              break;
          case BGP_NOTIFY_MAJOR_OPEN:
              ND_PRINT((ndo, ", subcode %s (%u)",
                   tok2str(bgp_notify_minor_open_values, "Unknown",
-                             bgpn.bgpn_minor),
-                  bgpn.bgpn_minor));
+                             bgpn_minor),
+                  bgpn_minor));
              break;
          case BGP_NOTIFY_MAJOR_UPDATE:
              ND_PRINT((ndo, ", subcode %s (%u)",
                   tok2str(bgp_notify_minor_update_values, "Unknown",
-                             bgpn.bgpn_minor),
-                  bgpn.bgpn_minor));
+                             bgpn_minor),
+                  bgpn_minor));
              break;
          case BGP_NOTIFY_MAJOR_FSM:
              ND_PRINT((ndo, " subcode %s (%u)",
                   tok2str(bgp_notify_minor_fsm_values, "Unknown",
-                             bgpn.bgpn_minor),
-                  bgpn.bgpn_minor));
+                             bgpn_minor),
+                  bgpn_minor));
              break;
          case BGP_NOTIFY_MAJOR_CAP:
              ND_PRINT((ndo, " subcode %s (%u)",
                   tok2str(bgp_notify_minor_cap_values, "Unknown",
-                             bgpn.bgpn_minor),
-                  bgpn.bgpn_minor));
+                             bgpn_minor),
+                  bgpn_minor));
              break;
          case BGP_NOTIFY_MAJOR_CEASE:
              ND_PRINT((ndo, ", subcode %s (%u)",
                   tok2str(bgp_notify_minor_cease_values, "Unknown",
-                             bgpn.bgpn_minor),
-                  bgpn.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
               */
-           if(bgpn.bgpn_minor == BGP_NOTIFY_MINOR_CEASE_MAXPRFX && length >= BGP_NOTIFICATION_SIZE + 7) {
+           if(bgpn_minor == BGP_NOTIFY_MINOR_CEASE_MAXPRFX && length >= BGP_NOTIFICATION_SIZE + 7) {
                tptr = dat + BGP_NOTIFICATION_SIZE;
-               ND_TCHECK2(*tptr, 7);
+               ND_TCHECK_7(tptr);
                ND_PRINT((ndo, ", AFI %s (%u), SAFI %s (%u), Max Prefixes: %u",
                       tok2str(af_values, "Unknown",
-                                 EXTRACT_16BITS(tptr)),
-                      EXTRACT_16BITS(tptr),
-                      tok2str(bgp_safi_values, "Unknown", *(tptr+2)),
-                      *(tptr+2),
-                      EXTRACT_32BITS(tptr+3)));
+                                 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)));
            }
            /*
             * draft-ietf-idr-shutdown describes a method to send a communication
             * intended for human consumption regarding the Administrative Shutdown
             */
-           if ((bgpn.bgpn_minor == BGP_NOTIFY_MINOR_CEASE_SHUT ||
-               bgpn.bgpn_minor == BGP_NOTIFY_MINOR_CEASE_RESET) &&
+           if ((bgpn_minor == BGP_NOTIFY_MINOR_CEASE_SHUT ||
+               bgpn_minor == BGP_NOTIFY_MINOR_CEASE_RESET) &&
                length >= BGP_NOTIFICATION_SIZE + 1) {
                    tptr = dat + BGP_NOTIFICATION_SIZE;
-                   ND_TCHECK2(*tptr, 1);
-                   shutdown_comm_length = *(tptr);
+                   ND_TCHECK_1(tptr);
+                   shutdown_comm_length = EXTRACT_U_1(tptr);
                    remainder_offset = 0;
                    /* garbage, hexdump it all */
                    if (shutdown_comm_length > BGP_NOTIFY_MINOR_CEASE_ADMIN_SHUTDOWN_LEN ||
                    }
                    /* a proper shutdown communication */
                    else {
-                           ND_TCHECK2(*(tptr+1), shutdown_comm_length);
+                           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, "\""));
@@@ -2869,7 -2775,7 +2898,7 @@@ bgp_route_refresh_print(netdissect_opti
  {
          const struct bgp_route_refresh *bgp_route_refresh_header;
  
-       ND_TCHECK2(pptr[0], BGP_ROUTE_REFRESH_SIZE);
+       ND_TCHECK_LEN(pptr, BGP_ROUTE_REFRESH_SIZE);
  
          /* some little sanity checking */
          if (len<BGP_ROUTE_REFRESH_SIZE)
  
          ND_PRINT((ndo, "\n\t  AFI %s (%u), SAFI %s (%u)",
                 tok2str(af_values,"Unknown",
-                         /* this stinks but the compiler pads the structure
-                          * weird */
-                         EXTRACT_16BITS(&bgp_route_refresh_header->afi)),
-                EXTRACT_16BITS(&bgp_route_refresh_header->afi),
+                         EXTRACT_BE_U_2(bgp_route_refresh_header->afi)),
+                EXTRACT_BE_U_2(bgp_route_refresh_header->afi),
                 tok2str(bgp_safi_values,"Unknown",
-                         bgp_route_refresh_header->safi),
-                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_TCHECK2(*pptr, len);
+             ND_TCHECK_LEN(pptr, len);
              print_unknown_data(ndo, pptr, "\n\t  ", len);
          }
  
@@@ -2898,19 -2802,22 +2925,22 @@@ trunc
  }
  
  static int
- bgp_header_print(netdissect_options *ndo,
-                  const u_char *dat, int length)
+ bgp_pdu_print(netdissect_options *ndo,
+                  const u_char *dat, u_int length)
  {
-       struct bgp bgp;
+       const struct bgp *bgp_header;
+       uint8_t bgp_type;
+       ND_TCHECK_LEN(dat, BGP_SIZE);
+       bgp_header = (const struct bgp *)dat;
+       bgp_type = EXTRACT_U_1(bgp_header->bgp_type);
  
-       ND_TCHECK2(dat[0], BGP_SIZE);
-       memcpy(&bgp, dat, BGP_SIZE);
        ND_PRINT((ndo, "\n\t%s Message (%u), length: %u",
-                tok2str(bgp_msg_values, "Unknown", bgp.bgp_type),
-                bgp.bgp_type,
+                tok2str(bgp_msg_values, "Unknown", bgp_type),
+                bgp_type,
                 length));
  
-       switch (bgp.bgp_type) {
+       switch (bgp_type) {
        case BGP_OPEN:
                bgp_open_print(ndo, dat, length);
                break;
                  break;
          default:
                  /* we have no decoder for the BGP message */
-                 ND_TCHECK2(*dat, length);
-                 ND_PRINT((ndo, "\n\t  no Message %u decoder", bgp.bgp_type));
+                 ND_TCHECK_LEN(dat, length);
+                 ND_PRINT((ndo, "\n\t  no Message %u decoder", bgp_type));
                  print_unknown_data(ndo, dat, "\n\t  ", length);
                  break;
        }
@@@ -2949,7 -2856,7 +2979,7 @@@ bgp_print(netdissect_options *ndo
                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
        };
-       struct bgp bgp;
+       const struct bgp *bgp_header;
        uint16_t hlen;
  
        ep = dat + length;
        p = dat;
        start = p;
        while (p < ep) {
-               if (!ND_TTEST2(p[0], 1))
+               if (!ND_TTEST_1(p))
                        break;
-               if (p[0] != 0xff) {
+               if (EXTRACT_U_1(p) != 0xff) {
                        p++;
                        continue;
                }
  
-               if (!ND_TTEST2(p[0], sizeof(marker)))
+               if (!ND_TTEST_LEN(p, sizeof(marker)))
                        break;
                if (memcmp(p, marker, sizeof(marker)) != 0) {
                        p++;
                }
  
                /* found BGP header */
-               ND_TCHECK2(p[0], BGP_SIZE);     /*XXX*/
-               memcpy(&bgp, p, BGP_SIZE);
+               ND_TCHECK_LEN(p, BGP_SIZE);
+               bgp_header = (const struct bgp *)p;
  
                if (start != p)
                        ND_PRINT((ndo, " [|BGP]"));
  
-               hlen = ntohs(bgp.bgp_len);
+               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));
                        break;
                }
  
-               if (ND_TTEST2(p[0], hlen)) {
-                       if (!bgp_header_print(ndo, p, hlen))
+               if (ND_TTEST_LEN(p, hlen)) {
+                       if (!bgp_pdu_print(ndo, p, hlen))
                                return;
                        p += hlen;
                        start = p;
                        ND_PRINT((ndo, "\n[|BGP %s]",
                               tok2str(bgp_msg_values,
                                          "Unknown Message Type",
-                                         bgp.bgp_type)));
+                                         EXTRACT_U_1(bgp_header->bgp_type))));
                        break;
                }
        }
diff --combined tests/TESTLIST
index 31794a43630198b42715c5e335036ebc431b0d7d,230bb375051602a59b266a66bc72647014d86975..ecc93da8fd2994cf3ed497715e84f99b2d300295
@@@ -26,7 -26,6 +26,7 @@@ bgp_infloop-v         bgp-infinite-loop.pcap          
  bgp-aigp      bgp-aigp.pcap   bgp-aigp.out    -v
  bgp-large-community bgp-large-community.pcap bgp-large-community.out -v
  bgp-shutdown-communication bgp-shutdown-communication.pcap bgp-shutdown-communication.out -v
 +bgp-addpath bgp-addpath.pcap bgp-addpath.out -v
  
  # EAP tests
  eapon1                eapon1.pcap             eapon1.out
@@@ -85,6 -84,9 +85,9 @@@ daoack01        rpl-26-senddaoack.pca
  # IPNET encapsulated site
  e1000g                e1000g.pcap             e1000g.out
  
+ # IPX/Netware packets
+ ipx           ipx.pcap                ipx.out
  # IETF FORCES WG packets and printer
  forces01        forces1.pcap            forces1.out
  forces01vvv     forces1.pcap            forces1vvv.out  -v -v -v