]> The Tcpdump Group git mirrors - tcpdump/commitdiff
Merge branch 'master' of git://github.com/mcr/tcpdump
authorBill Fenner <[email protected]>
Fri, 22 Feb 2013 19:51:33 +0000 (11:51 -0800)
committerBill Fenner <[email protected]>
Fri, 22 Feb 2013 19:51:33 +0000 (11:51 -0800)
Conflicts:
tests/TESTLIST

1  2 
print-bgp.c
tests/TESTLIST

diff --combined print-bgp.c
index 36f9a345d0a775d754791ad3804366212b1cfc2e,c1e382fd76bea0589cfac176e6e35b779dc73114..4f7053c284c6db29a659878eeac171e98a80002e
@@@ -95,8 -95,6 +95,6 @@@ struct bgp_opt 
  #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 */
  
- #define BGP_UPDATE_MINSIZE      23
  struct bgp_notification {
        u_int8_t bgpn_marker[16];
        u_int16_t bgpn_len;
@@@ -116,19 -114,10 +114,10 @@@ struct bgp_route_refresh 
  };                    /* EXTRACT_16BITS(&bgp_route_refresh->afi) (sigh)      */ 
  #define BGP_ROUTE_REFRESH_SIZE          23
  
- struct bgp_attr {
-       u_int8_t bgpa_flags;
-       u_int8_t bgpa_type;
-       union {
-               u_int8_t len;
-               u_int16_t elen;
-       } bgpa_len;
- #define bgp_attr_len(p) \
-       (((p)->bgpa_flags & 0x10) ? \
-               EXTRACT_16BITS(&(p)->bgpa_len.elen) : (p)->bgpa_len.len)
- #define bgp_attr_off(p) \
-       (((p)->bgpa_flags & 0x10) ? 4 : 3)
- };
+ #define bgp_attr_lenlen(flags, p) \
+       (((flags) & 0x10) ? 2 : 1)
+ #define bgp_attr_len(flags, p) \
+       (((flags) & 0x10) ? EXTRACT_16BITS(p) : *(p))
  
  #define BGPTYPE_ORIGIN                        1
  #define BGPTYPE_AS_PATH                       2
@@@ -494,38 -483,49 +483,49 @@@ as_printf (char *str, int size, u_int a
        return str;
  }
  
+ #define ITEMCHECK(minlen) if (itemlen < minlen) goto badtlv;
  int
- decode_prefix4(const u_char *pptr, char *buf, u_int buflen)
+ decode_prefix4(const u_char *pptr, u_int itemlen, char *buf, u_int buflen)
  {
        struct in_addr addr;
-       u_int plen;
+       u_int plen, plenbytes;
  
        TCHECK(pptr[0]);
+       ITEMCHECK(1);
        plen = pptr[0];
        if (32 < plen)
                return -1;
+       itemlen -= 1;
  
        memset(&addr, 0, sizeof(addr));
-       TCHECK2(pptr[1], (plen + 7) / 8);
-       memcpy(&addr, &pptr[1], (plen + 7) / 8);
+       plenbytes = (plen + 7) / 8;
+       TCHECK2(pptr[1], plenbytes);
+       ITEMCHECK(plenbytes);
+       memcpy(&addr, &pptr[1], plenbytes);
        if (plen % 8) {
-               ((u_char *)&addr)[(plen + 7) / 8 - 1] &=
+               ((u_char *)&addr)[plenbytes - 1] &=
                        ((0xff00 >> (plen % 8)) & 0xff);
        }
        snprintf(buf, buflen, "%s/%d", getname((u_char *)&addr), plen);
-       return 1 + (plen + 7) / 8;
+       return 1 + plenbytes;
  
  trunc:
        return -2;
+ badtlv:
+       return -3;
  }
  
  static int
- decode_labeled_prefix4(const u_char *pptr, char *buf, u_int buflen)
+ decode_labeled_prefix4(const u_char *pptr, u_int itemlen, char *buf, u_int buflen)
  {
        struct in_addr addr;
-       u_int plen;
+       u_int plen, plenbytes;
  
-       TCHECK(pptr[0]);
+       /* prefix length and label = 4 bytes */
+       TCHECK2(pptr[0], 4);
+       ITEMCHECK(4);
        plen = pptr[0];   /* get prefix length */
  
          /* this is one of the weirdnesses of rfc3107
  
        if (32 < plen)
                return -1;
+       itemlen -= 4;
  
        memset(&addr, 0, sizeof(addr));
-       TCHECK2(pptr[4], (plen + 7) / 8);
-       memcpy(&addr, &pptr[4], (plen + 7) / 8);
+       plenbytes = (plen + 7) / 8;
+       TCHECK2(pptr[4], plenbytes);
+       ITEMCHECK(plenbytes);
+       memcpy(&addr, &pptr[4], plenbytes);
        if (plen % 8) {
-               ((u_char *)&addr)[(plen + 7) / 8 - 1] &=
+               ((u_char *)&addr)[plenbytes - 1] &=
                        ((0xff00 >> (plen % 8)) & 0xff);
        }
          /* the label may get offsetted by 4 bits so lets shift it right */
                   EXTRACT_24BITS(pptr+1)>>4,
                   ((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
  
-       return 4 + (plen + 7) / 8;
+       return 4 + plenbytes;
  
  trunc:
        return -2;
+ badtlv:
+       return -3;
  }
  
  /*
@@@ -1042,37 -1048,46 +1048,46 @@@ trunc
  
  #ifdef INET6
  int
- decode_prefix6(const u_char *pd, char *buf, u_int buflen)
+ decode_prefix6(const u_char *pd, u_int itemlen, char *buf, u_int buflen)
  {
        struct in6_addr addr;
-       u_int plen;
+       u_int plen, plenbytes;
  
        TCHECK(pd[0]);
+       ITEMCHECK(1);
        plen = pd[0];
        if (128 < plen)
                return -1;
+       itemlen -= 1;
  
        memset(&addr, 0, sizeof(addr));
-       TCHECK2(pd[1], (plen + 7) / 8);
-       memcpy(&addr, &pd[1], (plen + 7) / 8);
+       plenbytes = (plen + 7) / 8;
+       TCHECK2(pd[1], plenbytes);
+       ITEMCHECK(plenbytes);
+       memcpy(&addr, &pd[1], plenbytes);
        if (plen % 8) {
-               addr.s6_addr[(plen + 7) / 8 - 1] &=
+               addr.s6_addr[plenbytes - 1] &=
                        ((0xff00 >> (plen % 8)) & 0xff);
        }
        snprintf(buf, buflen, "%s/%d", getname6((u_char *)&addr), plen);
-       return 1 + (plen + 7) / 8;
+       return 1 + plenbytes;
  
  trunc:
        return -2;
+ badtlv:
+       return -3;
  }
  
  static int
- decode_labeled_prefix6(const u_char *pptr, char *buf, u_int buflen)
+ decode_labeled_prefix6(const u_char *pptr, u_int itemlen, char *buf, u_int buflen)
  {
        struct in6_addr addr;
-       u_int plen;
+       u_int plen, plenbytes;
  
-       TCHECK(pptr[0]);
+       /* prefix length and label = 4 bytes */
+       TCHECK2(pptr[0], 4);
+       ITEMCHECK(4);
        plen = pptr[0]; /* get prefix length */
  
        if (24 > plen)
  
        if (128 < plen)
                return -1;
+       itemlen -= 4;
  
        memset(&addr, 0, sizeof(addr));
-       TCHECK2(pptr[4], (plen + 7) / 8);
-       memcpy(&addr, &pptr[4], (plen + 7) / 8);
+       plenbytes = (plen + 7) / 8;
+       TCHECK2(pptr[4], plenbytes);
+       memcpy(&addr, &pptr[4], plenbytes);
        if (plen % 8) {
-               addr.s6_addr[(plen + 7) / 8 - 1] &=
+               addr.s6_addr[plenbytes - 1] &=
                        ((0xff00 >> (plen % 8)) & 0xff);
        }
          /* the label may get offsetted by 4 bits so lets shift it right */
                   EXTRACT_24BITS(pptr+1)>>4,
                   ((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
  
-       return 4 + (plen + 7) / 8;
+       return 4 + plenbytes;
  
  trunc:
        return -2;
+ badtlv:
+       return -3;
  }
  
  static int
@@@ -1267,7 -1287,7 +1287,7 @@@ trunc
  }
  
  static int
- bgp_attr_print(const struct bgp_attr *attr, const u_char *pptr, int len)
+ bgp_attr_print(u_int atype, const u_char *pptr, u_int len)
  {
        int i;
        u_int16_t af;
              u_int32_t i;
          } bw;
        int advance;
-       int tlen;
+       u_int tlen;
        const u_char *tptr;
        char buf[MAXHOSTNAMELEN + 100];
        char tokbuf[TOKBUFSIZE];
          tptr = pptr;
          tlen=len;
  
-       switch (attr->bgpa_type) {
+       switch (atype) {
        case BGPTYPE_ORIGIN:
                if (len != 1)
                        printf("invalid len");
                   * 2 bytes first, and it does not pass, assume that ASs are
                   * encoded in 4 bytes format and move on.
                   */
-                 as_size = bgp_attr_get_as_size(attr->bgpa_type, pptr, len);
+                 as_size = bgp_attr_get_as_size(atype, pptr, len);
  
                while (tptr < pptr + len) {
                        TCHECK(tptr[0]);
                  tptr++;
  
                if (tlen) {
 +                    int nnh = 0;
                      printf("\n\t    nexthop: ");
                      while (tlen > 0) {
 +                        if ( nnh++ > 0 ) {
 +                            printf( ", " );
 +                        }
                          switch(af<<8 | safi) {
                          case (AFNUM_INET<<8 | SAFNUM_UNICAST):
                          case (AFNUM_INET<<8 | SAFNUM_MULTICAST):
                      case (AFNUM_INET<<8 | SAFNUM_UNICAST):
                      case (AFNUM_INET<<8 | SAFNUM_MULTICAST):
                      case (AFNUM_INET<<8 | SAFNUM_UNIMULTICAST):
-                         advance = decode_prefix4(tptr, buf, sizeof(buf));
+                         advance = decode_prefix4(tptr, len, buf, sizeof(buf));
                          if (advance == -1)
                              printf("\n\t    (illegal prefix length)");
                          else if (advance == -2)
                              goto trunc;
+                         else if (advance == -3)
+                             break; /* bytes left, but not enough */
                          else
                              printf("\n\t      %s", buf);
                          break;
                      case (AFNUM_INET<<8 | SAFNUM_LABUNICAST):
-                         advance = decode_labeled_prefix4(tptr, buf, sizeof(buf));
+                         advance = decode_labeled_prefix4(tptr, len, buf, sizeof(buf));
                          if (advance == -1)
                              printf("\n\t    (illegal prefix length)");
                          else if (advance == -2)
                              goto trunc;
+                         else if (advance == -3)
+                             break; /* bytes left, but not enough */
                          else
                              printf("\n\t      %s", buf);
                          break;
                      case (AFNUM_INET6<<8 | SAFNUM_UNICAST):
                      case (AFNUM_INET6<<8 | SAFNUM_MULTICAST):
                      case (AFNUM_INET6<<8 | SAFNUM_UNIMULTICAST):
-                         advance = decode_prefix6(tptr, buf, sizeof(buf));
+                         advance = decode_prefix6(tptr, len, buf, sizeof(buf));
                          if (advance == -1)
                              printf("\n\t    (illegal prefix length)");
                          else if (advance == -2)
                              goto trunc;
+                         else if (advance == -3)
+                             break; /* bytes left, but not enough */
                          else
                              printf("\n\t      %s", buf);
                          break;
                      case (AFNUM_INET6<<8 | SAFNUM_LABUNICAST):
-                         advance = decode_labeled_prefix6(tptr, buf, sizeof(buf));
+                         advance = decode_labeled_prefix6(tptr, len, buf, sizeof(buf));
                          if (advance == -1)
                              printf("\n\t    (illegal prefix length)");
                          else if (advance == -2)
                              goto trunc;
+                         else if (advance == -3)
+                             break; /* bytes left, but not enough */
                          else
                              printf("\n\t      %s", buf);
                          break;
                      case (AFNUM_INET<<8 | SAFNUM_UNICAST):
                      case (AFNUM_INET<<8 | SAFNUM_MULTICAST):
                      case (AFNUM_INET<<8 | SAFNUM_UNIMULTICAST):
-                         advance = decode_prefix4(tptr, buf, sizeof(buf));
+                         advance = decode_prefix4(tptr, len, buf, sizeof(buf));
                          if (advance == -1)
                              printf("\n\t    (illegal prefix length)");
                          else if (advance == -2)
                              goto trunc;
+                         else if (advance == -3)
+                             break; /* bytes left, but not enough */
                          else
                              printf("\n\t      %s", buf);
                          break;
                      case (AFNUM_INET<<8 | SAFNUM_LABUNICAST):
-                         advance = decode_labeled_prefix4(tptr, buf, sizeof(buf));
+                         advance = decode_labeled_prefix4(tptr, len, buf, sizeof(buf));
                          if (advance == -1)
                              printf("\n\t    (illegal prefix length)");
                          else if (advance == -2)
                              goto trunc;
+                         else if (advance == -3)
+                             break; /* bytes left, but not enough */
                          else
                              printf("\n\t      %s", buf);
                          break;
                      case (AFNUM_INET6<<8 | SAFNUM_UNICAST):
                      case (AFNUM_INET6<<8 | SAFNUM_MULTICAST):
                      case (AFNUM_INET6<<8 | SAFNUM_UNIMULTICAST):
-                         advance = decode_prefix6(tptr, buf, sizeof(buf));
+                         advance = decode_prefix6(tptr, len, buf, sizeof(buf));
                          if (advance == -1)
                              printf("\n\t    (illegal prefix length)");
                          else if (advance == -2)
                              goto trunc;
+                         else if (advance == -3)
+                             break; /* bytes left, but not enough */
                          else
                              printf("\n\t      %s", buf);
                          break;
                      case (AFNUM_INET6<<8 | SAFNUM_LABUNICAST):
-                         advance = decode_labeled_prefix6(tptr, buf, sizeof(buf));
+                         advance = decode_labeled_prefix6(tptr, len, buf, sizeof(buf));
                          if (advance == -1)
                              printf("\n\t    (illegal prefix length)");
                          else if (advance == -2)
                              goto trunc;
+                         else if (advance == -3)
+                             break; /* bytes left, but not enough */
                          else
                              printf("\n\t      %s", buf);
                          break;
          }
          case BGPTYPE_ATTR_SET:
                  TCHECK2(tptr[0], 4);
+                 if (len < 4)
+                       goto trunc;
                printf("\n\t    Origin AS: %s",
                    as_printf(astostr, sizeof(astostr), EXTRACT_32BITS(tptr)));
                tptr+=4;
                  len -=4;
  
-                 while (len >= 2 ) {
-                     int alen;
-                     struct bgp_attr bgpa;
+                 while (len) {
+                     u_int aflags, atype, alenlen, alen;
                      
-                     TCHECK2(tptr[0], sizeof(bgpa));
-                     memcpy(&bgpa, tptr, sizeof(bgpa));
-                     alen = bgp_attr_len(&bgpa);
-                     tptr += bgp_attr_off(&bgpa);
-                     len -= bgp_attr_off(&bgpa);
+                     TCHECK2(tptr[0], 2);
+                     if (len < 2)
+                         goto trunc;
+                     aflags = *tptr;
+                     atype = *(tptr + 1);
+                     tptr += 2;
+                     len -= 2;
+                     alenlen = bgp_attr_lenlen(aflags, tptr);
+                     TCHECK2(tptr[0], alenlen);
+                     if (len < alenlen)
+                         goto trunc;
+                     alen = bgp_attr_len(aflags, tptr);
+                     tptr += alenlen;
+                     len -= alenlen;
                      
                      printf("\n\t      %s (%u), length: %u",
                             tok2strbuf(bgp_attr_values,
-                                     "Unknown Attribute", bgpa.bgpa_type,
-                                     tokbuf, sizeof(tokbuf)),
-                            bgpa.bgpa_type,
+                                       "Unknown Attribute", atype,
+                                       tokbuf, sizeof(tokbuf)),
+                            atype,
                             alen);
                      
-                     if (bgpa.bgpa_flags) {
+                     if (aflags) {
                          printf(", Flags [%s%s%s%s",
-                                bgpa.bgpa_flags & 0x80 ? "O" : "",
-                                bgpa.bgpa_flags & 0x40 ? "T" : "",
-                                bgpa.bgpa_flags & 0x20 ? "P" : "",
-                                bgpa.bgpa_flags & 0x10 ? "E" : "");
-                         if (bgpa.bgpa_flags & 0xf)
-                             printf("+%x", bgpa.bgpa_flags & 0xf);
+                                aflags & 0x80 ? "O" : "",
+                                aflags & 0x40 ? "T" : "",
+                                aflags & 0x20 ? "P" : "",
+                                aflags & 0x10 ? "E" : "");
+                         if (aflags & 0xf)
+                             printf("+%x", aflags & 0xf);
                          printf("]: ");
                      }
                      /* FIXME check for recursion */
-                     if (!bgp_attr_print(&bgpa, tptr, alen))
+                     if (!bgp_attr_print(atype, tptr, alen))
                          return 0;
                      tptr += alen;
                      len -= alen;
  
        default:
            TCHECK2(*pptr,len);
-             printf("\n\t    no Attribute %u decoder",attr->bgpa_type); /* we have no decoder for the attribute */
+             printf("\n\t    no Attribute %u decoder",atype); /* we have no decoder for the attribute */
              if (vflag <= 1)
                  print_unknown_data(pptr,"\n\t    ",len);
              break;
@@@ -2312,107 -2354,163 +2358,163 @@@ static voi
  bgp_update_print(const u_char *dat, int length)
  {
        struct bgp bgp;
-       struct bgp_attr bgpa;
        const u_char *p;
+       int withdrawn_routes_len;
        int len;
        int i;
        char tokbuf[TOKBUFSIZE];
+ #ifndef INET6
+       char buf[MAXHOSTNAMELEN + 100];
+       int wpfx;
+ #endif
  
        TCHECK2(dat[0], BGP_SIZE);
+       if (length < BGP_SIZE)
+               goto trunc;
        memcpy(&bgp, dat, BGP_SIZE);
        p = dat + BGP_SIZE;     /*XXX*/
+       length -= BGP_SIZE;
  
        /* Unfeasible routes */
-       len = EXTRACT_16BITS(p);
-       if (len) {
+       TCHECK2(p[0], 2);
+       if (length < 2)
+               goto trunc;
+       withdrawn_routes_len = EXTRACT_16BITS(p);
+       p += 2;
+       length -= 2;
+       if (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.
                 */
+               TCHECK2(p[0], withdrawn_routes_len);
+               if (length < withdrawn_routes_len)
+                       goto trunc;
  #ifdef INET6
-               printf("\n\t  Withdrawn routes: %d bytes", len);
+               printf("\n\t  Withdrawn routes: %d bytes", withdrawn_routes_len);
+               p += withdrawn_routes_len;
+               length -= withdrawn_routes_len;
  #else
-               char buf[MAXHOSTNAMELEN + 100];
-               int wpfx;
+               if (withdrawn_routes_len < 2)
+                       goto trunc;
+               length -= 2;
+               withdrawn_routes_len -= 2;
  
-               TCHECK2(p[2], len);
-               i = 2;
  
                printf("\n\t  Withdrawn routes:");
  
-               while(i < 2 + len) {
-                       wpfx = decode_prefix4(&p[i], buf, sizeof(buf));
+               while(withdrawn_routes_len > 0) {
+                       wpfx = decode_prefix4(p, withdrawn_routes_len, buf, sizeof(buf));
                        if (wpfx == -1) {
                                printf("\n\t    (illegal prefix length)");
                                break;
                        } else if (wpfx == -2)
                                goto trunc;
+                       else if (wpfx == -3)
+                               goto trunc; /* bytes left, but not enough */
                        else {
-                               i += wpfx;
                                printf("\n\t    %s", buf);
+                               p += wpfx;
+                               length -= wpfx;
+                               withdrawn_routes_len -= wpfx;
                        }
                }
  #endif
        }
-       p += 2 + len;
  
        TCHECK2(p[0], 2);
+       if (length < 2)
+               goto trunc;
        len = EXTRACT_16BITS(p);
+       p += 2;
+       length -= 2;
  
-         if (len == 0 && length == BGP_UPDATE_MINSIZE) {
+         if (withdrawn_routes_len == 0 && len == 0 && length == 0) {
+             /* No withdrawn routes, no path attributes, no NLRI */
              printf("\n\t  End-of-Rib Marker (empty NLRI)");
              return;
          }
  
        if (len) {
                /* do something more useful!*/
-               i = 2;
-               while (i < 2 + len) {
-                       int alen, aoff;
-                       TCHECK2(p[i], sizeof(bgpa));
-                       memcpy(&bgpa, &p[i], sizeof(bgpa));
-                       alen = bgp_attr_len(&bgpa);
-                       aoff = bgp_attr_off(&bgpa);
-                      printf("\n\t  %s (%u), length: %u",
+               while (len) {
+                       int aflags, atype, alenlen, alen;
+                       TCHECK2(p[0], 2);
+                       if (len < 2)
+                           goto trunc;
+                       if (length < 2)
+                           goto trunc;
+                       aflags = *p;
+                       atype = *(p + 1);
+                       p += 2;
+                       len -= 2;
+                       length -= 2;
+                       alenlen = bgp_attr_lenlen(aflags, p);
+                       TCHECK2(p[0], alenlen);
+                       if (len < alenlen)
+                           goto trunc;
+                       if (length < alenlen)
+                           goto trunc;
+                       alen = bgp_attr_len(aflags, p);
+                       p += alenlen;
+                       len -= alenlen;
+                       length -= alenlen;
+                       printf("\n\t  %s (%u), length: %u",
                                tok2strbuf(bgp_attr_values, "Unknown Attribute",
-                                        bgpa.bgpa_type,
+                                        atype,
                                         tokbuf, sizeof(tokbuf)),
-                               bgpa.bgpa_type,
+                               atype,
                                alen);
  
-                       if (bgpa.bgpa_flags) {
+                       if (aflags) {
                                printf(", Flags [%s%s%s%s",
-                                       bgpa.bgpa_flags & 0x80 ? "O" : "",
-                                       bgpa.bgpa_flags & 0x40 ? "T" : "",
-                                       bgpa.bgpa_flags & 0x20 ? "P" : "",
-                                       bgpa.bgpa_flags & 0x10 ? "E" : "");
-                               if (bgpa.bgpa_flags & 0xf)
-                                       printf("+%x", bgpa.bgpa_flags & 0xf);
+                                       aflags & 0x80 ? "O" : "",
+                                       aflags & 0x40 ? "T" : "",
+                                       aflags & 0x20 ? "P" : "",
+                                       aflags & 0x10 ? "E" : "");
+                               if (aflags & 0xf)
+                                       printf("+%x", aflags & 0xf);
                                printf("]: ");
                        }
-                       if (!bgp_attr_print(&bgpa, &p[i + aoff], alen))
+                       if (len < alen)
+                               goto trunc;
+                       if (length < alen)
                                goto trunc;
-                       i += aoff + alen;
+                       if (!bgp_attr_print(atype, p, alen))
+                               goto trunc;
+                       p += alen;
+                       len -= alen;
+                       length -= alen;
                }
        } 
-       p += 2 + len;
  
-       if (dat + length > p) {
+       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
+                */
                printf("\n\t  Updated routes:");
-               while (dat + length > p) {
+               while (length) {
                        char buf[MAXHOSTNAMELEN + 100];
-                       i = decode_prefix4(p, buf, sizeof(buf));
+                       i = decode_prefix4(p, length, buf, sizeof(buf));
                        if (i == -1) {
                                printf("\n\t    (illegal prefix length)");
                                break;
                        } else if (i == -2)
                                goto trunc;
+                       else if (i == -3)
+                               goto trunc; /* bytes left, but not enough */
                        else {
                                printf("\n\t    %s", buf);
                                p += i;
+                               length -= i;
                        }
                }
        }
diff --combined tests/TESTLIST
index c978f4a671aaa0c63ef96924e198caf9a325bacc,aed8e0643eb44ddeefca5ac18606ac0fe98f3359..7e48b200717ffdaeaed7f528442f8801af18e89a
@@@ -1,18 -1,17 +1,18 @@@
 -# BGP test
 +# BGP tests
  bgp_vpn_attrset bgp_vpn_attrset.pcap bgp_vpn_attrset.out -t -v 
 +mpbgp-linklocal-nexthop mpbgp-linklocal-nexthop.pcap mpbgp-linklocal-nexthop.out -t -v
  
  # EAP tests
  eapon1 eapon1.pcap eapon1.out -t 
  
  # ESP tests
- esp0 02-sunrise-sunset-esp.pcap esp0.out -t 
+ esp0 02-sunrise-sunset-esp.pcap esp0.out -t -n
  esp1 02-sunrise-sunset-esp.pcap esp1.out -t -E "[email protected] 3des-cbc-hmac96:0x4043434545464649494a4a4c4c4f4f515152525454575758" 
  esp2 08-sunrise-sunset-esp2.pcap esp2.out -t -E "[email protected] 3des-cbc-hmac96:0x43434545464649494a4a4c4c4f4f51515252545457575840,[email protected] 3des-cbc-hmac96:0x434545464649494a4a4c4c4f4f5151525254545757584043"
  esp3 02-sunrise-sunset-esp.pcap esp1.out -t -E "3des-cbc-hmac96:0x4043434545464649494a4a4c4c4f4f515152525454575758"
  esp4 08-sunrise-sunset-esp2.pcap esp2.out -t -E "file esp-secrets.txt"
  esp5 08-sunrise-sunset-aes.pcap esp5.out -t -E "file esp-secrets.txt"
- espudp1 espudp1.pcap                    espudp1.out -nnn -t -E "file esp-secrets.txt"
+ espudp1 espudp1.pcap                    espudp1.out -nnnn -t -E "file esp-secrets.txt"
  
  # ISAKMP tests
  isakmp1 isakmp-delete-segfault.pcap isakmp1.out -t 
@@@ -61,9 -60,29 +61,32 @@@ sflow1          sflow_multiple_counter_
  # Babel tests
  babel1          babel.pcap             babel1.out      -t 
  babel1v         babel.pcap             babel1v.out     -t -v
+ babel_auth      babel_auth.pcap        babel_auth.out  -t -v
  
  # PPPoE tests
  pppoe           pppoe.pcap             pppoe.out       -t
  
 +# IGMP tests
 +igmpv3-queries  igmpv3-queries.pcap     igmpv3-queries.out      -t
++
+ # ICMPv6
+ icmpv6          icmpv6.pcap             icmpv6.out      -t -vv
+ # SPB tests
+ spb               spb.pcap                spb.out -t
+ # SPB BPDUv4 tests
+ spb_bpduv4      spb_bpduv4.pcap       spb_bpduv4.out -t
+ # RIP tests
+ ripv1v2         ripv1v2.pcap            ripv1v2.out     -t -v
+ ripv2_auth      ripv2_auth.pcap         ripv2_auth.out  -t -v
+ # DHCPv6 tests
+ dhcpv6-aftr-name      dhcpv6-AFTR-Name-RFC6334.pcap   dhcpv6-AFTR-Name-RFC6334.out    -t -v
+ dhcpv6-ia-na  dhcpv6-ia-na.pcap       dhcpv6-ia-na.out        -t -v
+ dhcpv6-ia-pd  dhcpv6-ia-pd.pcap       dhcpv6-ia-pd.out        -t -v
+ dhcpv6-ia-ta  dhcpv6-ia-ta.pcap       dhcpv6-ia-ta.out        -t -v
+ # ZeroMQ tests
+ zmtp1v                zmtp1.pcap              zmtp1.out       -t -v -T zmtp1