#include "af.h"
#include "l2vpn.h"
+static const char tstr[] = "[|BGP]";
+
struct bgp {
uint8_t bgp_marker[16];
uint16_t bgp_len;
*/
#define UPDATE_BUF_BUFLEN(buf, buflen, stringlen) \
if (stringlen<0) \
- buflen=0; \
+ buflen=0; \
else if ((u_int)stringlen>buflen) \
buflen=0; \
else { \
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;
}
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:
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;
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;
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)),
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)),
return;
trunc:
- ND_PRINT((ndo, "[|BGP]"));
+ ND_PRINT((ndo, "%s", tstr));
}
static void
}
return;
trunc:
- ND_PRINT((ndo, "[|BGP]"));
+ ND_PRINT((ndo, "%s", tstr));
}
static void
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;
}
return;
trunc:
- ND_PRINT((ndo, "[|BGP]"));
+ ND_PRINT((ndo, "%s", tstr));
}
static void
return;
trunc:
- ND_PRINT((ndo, "[|BGP]"));
+ ND_PRINT((ndo, "%s", tstr));
}
static void
return;
trunc:
- ND_PRINT((ndo, "[|BGP]"));
+ ND_PRINT((ndo, "%s", tstr));
}
static int
}
return 1;
trunc:
- ND_PRINT((ndo, "[|BGP]"));
+ ND_PRINT((ndo, "%s", tstr));
return 0;
}
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) {
return;
trunc:
- ND_PRINT((ndo, " [|BGP]"));
+ ND_PRINT((ndo, "%s", tstr));
}
/*