]> The Tcpdump Group git mirrors - tcpdump/blobdiff - print-bgp.c
Handle very large -f files by rejecting them.
[tcpdump] / print-bgp.c
index c82f1cc7df10d580f892b77297b307739e41202d..7db3c6bb0f93931a2cdddae9ff55cdf544dac2f5 100644 (file)
@@ -47,6 +47,8 @@
 #include "af.h"
 #include "l2vpn.h"
 
+static const char tstr[] = "[|BGP]";
+
 struct bgp {
        uint8_t bgp_marker[16];
        uint16_t bgp_len;
@@ -1013,7 +1015,7 @@ trunc:
  */
 #define UPDATE_BUF_BUFLEN(buf, buflen, stringlen) \
     if (stringlen<0) \
-               buflen=0; \
+        buflen=0; \
     else if ((u_int)stringlen>buflen) \
         buflen=0; \
     else { \
@@ -1359,7 +1361,7 @@ trunc:
 
 static int
 bgp_attr_print(netdissect_options *ndo,
-               u_int atype, const u_char *pptr, u_int len)
+               u_int atype, const u_char *pptr, u_int len, const unsigned attr_set_level)
 {
        int i;
        uint16_t af;
@@ -1482,7 +1484,7 @@ bgp_attr_print(netdissect_options *ndo,
                }
                ND_TCHECK2(tptr[0], 8);
                ND_PRINT((ndo, " AS #%s, origin %s",
-                   as_printf(ndo, astostr, sizeof(astostr), EXTRACT_32BITS(tptr)),
+                   as_printf(ndo, astostr, sizeof(astostr), EXTRACT_32BITS(tptr)),
                    ipaddr_string(ndo, tptr + 4)));
                break;
        case BGPTYPE_COMMUNITIES:
@@ -1698,10 +1700,12 @@ bgp_attr_print(netdissect_options *ndo,
                                        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 (tlen == BGP_VPN_RD_LEN + 4 + sizeof(struct in_addr)
+                                    && EXTRACT_32BITS(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 (tlen == BGP_VPN_RD_LEN + 3 + sizeof(struct in6_addr)
+                                         && EXTRACT_24BITS(tptr+BGP_VPN_RD_LEN) ==  0x350000)
                                     ND_PRINT((ndo, " = %s", ip6addr_string(ndo, tptr+BGP_VPN_RD_LEN+3)));
                                 tptr += tlen;
                                 tlen = 0;
@@ -2280,8 +2284,16 @@ bgp_attr_print(netdissect_options *ndo,
                             ND_PRINT((ndo, "+%x", aflags & 0xf));
                         ND_PRINT((ndo, "]: "));
                     }
-                    /* FIXME check for recursion */
-                    if (!bgp_attr_print(ndo, atype, tptr, alen))
+                    /* The protocol encoding per se allows ATTR_SET to be nested as many times
+                     * as the message can accommodate. This printer used to be able to recurse
+                     * into ATTR_SET contents until the stack exhaustion, but now there is a
+                     * limit on that (if live protocol exchange goes that many levels deep,
+                     * something is probably wrong anyway). Feel free to refine this value if
+                     * you can find the spec with respective normative text.
+                     */
+                    if (attr_set_level == 10)
+                        ND_PRINT((ndo, "(too many nested levels, not recursing)"));
+                    else if (!bgp_attr_print(ndo, atype, tptr, alen, attr_set_level + 1))
                         return 0;
                     tptr += alen;
                     len -= alen;
@@ -2342,6 +2354,8 @@ bgp_capabilities_print(netdissect_options *ndo,
                 ND_TCHECK2(opt[i+2], cap_len);
                 switch (cap_type) {
                 case BGP_CAPCODE_MP:
+                    /* AFI (16 bits), Reserved (8 bits), SAFI (8 bits) */
+                    ND_TCHECK_8BITS(opt + i + 5);
                     ND_PRINT((ndo, "\n\t\tAFI %s (%u), SAFI %s (%u)",
                            tok2str(af_values, "Unknown",
                                       EXTRACT_16BITS(opt+i+2)),
@@ -2351,12 +2365,15 @@ bgp_capabilities_print(netdissect_options *ndo,
                            opt[i+5]));
                     break;
                 case BGP_CAPCODE_RESTART:
+                    /* Restart Flags (4 bits), Restart Time in seconds (12 bits) */
+                    ND_TCHECK_16BITS(opt + i + 2);
                     ND_PRINT((ndo, "\n\t\tRestart Flags: [%s], Restart Time %us",
                            ((opt[i+2])&0x80) ? "R" : "none",
                            EXTRACT_16BITS(opt+i+2)&0xfff));
                     tcap_len-=2;
                     cap_offset=4;
                     while(tcap_len>=4) {
+                        ND_TCHECK_8BITS(opt + i + cap_offset + 3);
                         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)),
@@ -2420,7 +2437,7 @@ bgp_capabilities_print(netdissect_options *ndo,
         return;
 
 trunc:
-       ND_PRINT((ndo, "[|BGP]"));
+       ND_PRINT((ndo, "%s", tstr));
 }
 
 static void
@@ -2483,7 +2500,7 @@ bgp_open_print(netdissect_options *ndo,
        }
        return;
 trunc:
-       ND_PRINT((ndo, "[|BGP]"));
+       ND_PRINT((ndo, "%s", tstr));
 }
 
 static void
@@ -2583,7 +2600,7 @@ bgp_update_print(netdissect_options *ndo,
                                goto trunc;
                        if (length < alen)
                                goto trunc;
-                       if (!bgp_attr_print(ndo, atype, p, alen))
+                       if (!bgp_attr_print(ndo, atype, p, alen, 0))
                                goto trunc;
                        p += alen;
                        len -= alen;
@@ -2620,7 +2637,7 @@ bgp_update_print(netdissect_options *ndo,
        }
        return;
 trunc:
-       ND_PRINT((ndo, "[|BGP]"));
+       ND_PRINT((ndo, "%s", tstr));
 }
 
 static void
@@ -2701,7 +2718,7 @@ bgp_notification_print(netdissect_options *ndo,
 
        return;
 trunc:
-       ND_PRINT((ndo, "[|BGP]"));
+       ND_PRINT((ndo, "%s", tstr));
 }
 
 static void
@@ -2735,7 +2752,7 @@ bgp_route_refresh_print(netdissect_options *ndo,
 
         return;
 trunc:
-       ND_PRINT((ndo, "[|BGP]"));
+       ND_PRINT((ndo, "%s", tstr));
 }
 
 static int
@@ -2775,7 +2792,7 @@ bgp_header_print(netdissect_options *ndo,
        }
        return 1;
 trunc:
-       ND_PRINT((ndo, "[|BGP]"));
+       ND_PRINT((ndo, "%s", tstr));
        return 0;
 }
 
@@ -2824,7 +2841,7 @@ bgp_print(netdissect_options *ndo,
                memcpy(&bgp, p, BGP_SIZE);
 
                if (start != p)
-                       ND_PRINT((ndo, " [|BGP]"));
+                       ND_PRINT((ndo, " %s", tstr));
 
                hlen = ntohs(bgp.bgp_len);
                if (hlen < BGP_SIZE) {
@@ -2850,7 +2867,7 @@ bgp_print(netdissect_options *ndo,
        return;
 
 trunc:
-       ND_PRINT((ndo, " [|BGP]"));
+       ND_PRINT((ndo, "%s", tstr));
 }
 
 /*