UPDATE_BUF_BUFLEN(buf, buflen, stringlen);
pptr += 12;
tlen -= 12;
- return plen;
+ return plen + 2;
} else if (plen > 17) {
/* assume old format */
/* RD, ID, LBLKOFF, LBLBASE */
tlen -= 15;
/* ok now the variable part - lets read out TLVs*/
- while (tlen != 00) {
- if (tlen < 3)
- return -1;
+ while (tlen != 0) {
+ if (tlen < 3) {
+ if (buflen != 0) {
+ stringlen=snprintf(buf,buflen, "\n\t\tran past the end");
+ UPDATE_BUF_BUFLEN(buf, buflen, stringlen);
+ }
+ return plen + 2;
+ }
ND_TCHECK_3(pptr);
tlv_type = EXTRACT_U_1(pptr);
pptr++;
- tlv_len = EXTRACT_BE_U_2(pptr);
- ttlv_len = tlv_len;
+ tlv_len = EXTRACT_BE_U_2(pptr); /* length, in *bits* */
+ ttlv_len = (tlv_len + 7)/8; /* length, in *bytes* */
pptr += 2;
switch(tlv_type) {
tlv_len);
UPDATE_BUF_BUFLEN(buf, buflen, stringlen);
}
- ttlv_len = ttlv_len/8+1; /* how many bytes do we need to read ? */
- while (ttlv_len > 0) {
+ while (ttlv_len != 0) {
+ if (tlen < 1) {
+ if (buflen != 0) {
+ stringlen=snprintf(buf,buflen, " (ran past the end)");
+ UPDATE_BUF_BUFLEN(buf, buflen, stringlen);
+ }
+ return plen + 2;
+ }
ND_TCHECK_1(pptr);
if (buflen != 0) {
stringlen=snprintf(buf,buflen, "%02x",
UPDATE_BUF_BUFLEN(buf, buflen, stringlen);
}
ttlv_len--;
+ tlen--;
}
break;
default:
tlv_len);
UPDATE_BUF_BUFLEN(buf, buflen, stringlen);
}
+ if (tlen < ttlv_len) {
+ if (buflen != 0) {
+ stringlen=snprintf(buf,buflen, " (ran past the end)");
+ UPDATE_BUF_BUFLEN(buf, buflen, stringlen);
+ }
+ return plen + 2;
+ }
+ tlen -= ttlv_len;
break;
}
- tlen -= (tlv_len<<3); /* the tlv-length is expressed in bits so lets shift it right */
}
return plen + 2;
} else {
* and if so it checks that standard BGP doesn't make sense.
*/
static int
-check_add_path(const u_char *pptr, u_int length, u_int max_prefix_length)
+check_add_path(netdissect_options *ndo, const u_char *pptr, u_int length,
+ u_int max_prefix_length)
{
u_int offset, prefix_length;
/* check if it could be add path */
for (offset = 0; offset < length;) {
offset += 4;
+ ND_TCHECK_1(pptr + offset);
prefix_length = EXTRACT_U_1(pptr + offset);
/*
* Add 4 to cover the path id
/* check it's not standard BGP */
for (offset = 0; offset < length; ) {
+ ND_TCHECK_1(pptr + offset);
prefix_length = EXTRACT_U_1(pptr + offset);
/*
* If the prefix_length is zero (0.0.0.0/0)
/* assume not add-path by default */
return 0;
+trunc:
+ return -1;
}
static int
ND_PRINT((ndo, "invalid len"));
break;
}
- while (tlen>0) {
+ while (tlen != 0) {
uint32_t comm;
ND_TCHECK_4(tptr);
+ if (tlen < 4)
+ goto trunc;
comm = EXTRACT_BE_U_4(tptr);
switch (comm) {
case BGP_COMMUNITY_NO_EXPORT:
ND_PRINT((ndo, "invalid len"));
break;
}
- while (tlen>0) {
+ while (tlen != 0) {
ND_TCHECK_4(tptr);
+ if (tlen < 4)
+ goto trunc;
ND_PRINT((ndo, "%s%s",
ipaddr_string(ndo, tptr),
(tlen>4) ? ", " : ""));
if (snpa) {
ND_PRINT((ndo, "\n\t %u SNPA", snpa));
- for (/*nothing*/; snpa > 0; snpa--) {
+ for (/*nothing*/; snpa != 0; snpa--) {
ND_TCHECK_1(tptr);
ND_PRINT((ndo, "\n\t %u bytes", EXTRACT_U_1(tptr)));
tptr += EXTRACT_U_1(tptr) + 1;
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);
+ add_path4 = check_add_path(ndo, tptr, (len-(tptr - pptr)), 32);
+ if (add_path4 == -1)
+ goto trunc;
+ add_path6 = check_add_path(ndo, tptr, (len-(tptr - pptr)), 128);
+ if (add_path6 == -1)
+ goto trunc;
while (tptr < pptr + len) {
switch (af<<8 | safi) {
tptr += 3;
- add_path4 = check_add_path(tptr, (len-(tptr - pptr)), 32);
- add_path6 = check_add_path(tptr, (len-(tptr - pptr)), 128);
+ add_path4 = check_add_path(ndo, tptr, (len-(tptr - pptr)), 32);
+ if (add_path4 == -1)
+ goto trunc;
+ add_path6 = check_add_path(ndo, tptr, (len-(tptr - pptr)), 128);
+ if (add_path6 == -1)
+ goto trunc;
while (tptr < pptr + len) {
switch (af<<8 | safi) {
ND_PRINT((ndo, "invalid len"));
break;
}
- while (tlen>0) {
+ while (tlen != 0) {
uint16_t extd_comm;
ND_TCHECK_2(tptr);
+ if (tlen < 2)
+ goto trunc;
extd_comm=EXTRACT_BE_U_2(tptr);
ND_PRINT((ndo, "\n\t %s (0x%04x), Flags [%s]",
bittok2str(bgp_extd_comm_flag_values, "none", extd_comm)));
ND_TCHECK_6(tptr + 2);
+ if (tlen < 8)
+ goto trunc;
switch(extd_comm) {
case BGP_EXT_COM_RT_0:
case BGP_EXT_COM_RO_0:
break;
}
ND_PRINT((ndo, "\n\t "));
- while (len > 0) {
+ while (len != 0) {
ND_TCHECK_LEN(tptr, 12);
ND_PRINT((ndo, "%u:%u:%u%s",
EXTRACT_BE_U_4(tptr),
EXTRACT_BE_U_4(tptr + 8),
(len > 12) ? ", " : ""));
tptr += 12;
+ /*
+ * len will always be a multiple of 12, as per the above,
+ * so this will never underflow.
+ */
len -= 12;
}
break;
ND_PRINT((ndo, " (bogus)")); /* length */
break;
}
- while (tcap_len > 0) {
+ while (tcap_len != 0) {
if (tcap_len < 4) {
ND_PRINT((ndo, "\n\t\t(invalid)"));
break;
cap_len);
break;
}
- if (ndo->ndo_vflag > 1 && cap_len > 0) {
+ if (ndo->ndo_vflag > 1 && cap_len != 0) {
print_unknown_data(ndo, opt + i + 2, "\n\t\t", cap_len);
}
i += BGP_CAP_HEADER_SIZE + cap_len;
if (length < withdrawn_routes_len)
goto trunc;
ND_PRINT((ndo, "\n\t Withdrawn routes:"));
- add_path = check_add_path(p, withdrawn_routes_len, 32);
- while (withdrawn_routes_len > 0) {
+ add_path = check_add_path(ndo, p, withdrawn_routes_len, 32);
+ if (add_path == -1)
+ goto trunc;
+ while (withdrawn_routes_len != 0) {
if (add_path) {
+ if (withdrawn_routes_len < 4) {
+ p += withdrawn_routes_len;
+ length -= withdrawn_routes_len;
+ break;
+ }
path_id = EXTRACT_BE_U_4(p);
p += 4;
length -= 4;
}
if (length) {
- add_path = check_add_path(p, length, 32);
+ add_path = check_add_path(ndo, p, length, 32);
+ if (add_path == -1)
+ goto trunc;
ND_PRINT((ndo, "\n\t Updated routes:"));
- while (length > 0) {
+ while (length != 0) {
if (add_path) {
path_id = EXTRACT_BE_U_4(p);
p += 4;