struct capability_mp_data mpc;
struct stream *s = BGP_INPUT (peer);
+ /* Verify length is 4 */
+ if (hdr->length != 4)
+ {
+ zlog_warn("MP Cap: Received invalid length %d, non-multiple of 4",
+ hdr->length);
+ return -1;
+ }
+
bgp_capability_mp_data (s, &mpc);
if (bgp_debug_neighbor_events(peer))
zlog_info ("%s ORF Capability entry length error,"
" Cap length %u, num %u",
peer->host, hdr->length, entry.num);
- bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
+ bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_OPEN_MALFORMED_ATTR);
return -1;
}
int restart_bit = 0;
size_t end = stream_get_getp (s) + caphdr->length;
+ /* Verify length is a multiple of 4 */
+ if ((caphdr->length-2) % 4)
+ {
+ zlog_warn("Restart Cap: Received invalid length %d, non-multiple of 4",
+ caphdr->length);
+ return -1;
+ }
+
SET_FLAG (peer->cap, PEER_CAP_RESTART_RCV);
restart_flag_time = stream_getw(s);
if (CHECK_FLAG (restart_flag_time, RESTART_R_BIT))
{
if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s Addr-family %d/%d(afi/safi) not supported."
- " Ignore the Graceful Restart capability",
+ " Ignore the Graceful Restart capability for this AFI/SAFI",
peer->host, afi, safi);
}
else if (!peer->afc[afi][safi])
return 0;
}
+/* Unlike other capability parsing routines, this one returns 0 on error */
static as_t
bgp_capability_as4 (struct peer *peer, struct capability_header *hdr)
{
SET_FLAG (peer->cap, PEER_CAP_ADDPATH_RCV);
+ /* Verify length is a multiple of 4 */
+ if (hdr->length % 4)
+ {
+ zlog_warn("Add Path: Received invalid length %d, non-multiple of 4",
+ hdr->length);
+ return -1;
+ }
+
while (stream_get_getp (s) + 4 <= end)
{
afi_t afi = stream_getw (s);
struct stream *s = BGP_INPUT (peer);
size_t end = stream_get_getp (s) + hdr->length;
+ /* Verify length is a multiple of 4 */
+ if (hdr->length % 6)
+ {
+ zlog_warn("Extended NH: Received invalid length %d, non-multiple of 6",
+ hdr->length);
+ return -1;
+ }
+
while (stream_get_getp (s) + 6 <= end)
{
afi_t afi = stream_getw (s);
size_t start;
u_char *sp = stream_pnt (s);
struct capability_header caphdr;
-
+
+ ret = 0;
/* We need at least capability code and capability length. */
if (stream_get_getp(s) + 2 > end)
{
zlog_info ("%s Capability length error (< header)", peer->host);
- bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
+ bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_OPEN_MALFORMED_ATTR);
return -1;
}
if (start + caphdr.length > end)
{
zlog_info ("%s Capability length error (< length)", peer->host);
- bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
+ bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_OPEN_MALFORMED_ATTR);
return -1;
}
LOOKUP (capcode_str, caphdr.code),
caphdr.length,
(unsigned) cap_minsizes[caphdr.code]);
- bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
+ bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_OPEN_MALFORMED_ATTR);
return -1;
}
/* we deliberately ignore unknown codes, see below */
memcpy (*error, sp, caphdr.length + 2);
*error += caphdr.length + 2;
}
+ ret = 0; /* Don't return error for this */
}
}
break;
break;
case CAPABILITY_CODE_ORF:
case CAPABILITY_CODE_ORF_OLD:
- if (bgp_capability_orf_entry (peer, &caphdr))
- return -1;
+ ret = bgp_capability_orf_entry (peer, &caphdr);
break;
case CAPABILITY_CODE_RESTART:
- if (bgp_capability_restart (peer, &caphdr))
- return -1;
+ ret = bgp_capability_restart (peer, &caphdr);
break;
case CAPABILITY_CODE_DYNAMIC:
case CAPABILITY_CODE_DYNAMIC_OLD:
* for the value really, only error case.
*/
if (!bgp_capability_as4 (peer, &caphdr))
- return -1;
+ ret = -1;
break;
case CAPABILITY_CODE_ADDPATH:
- if (bgp_capability_addpath (peer, &caphdr))
- return -1;
+ ret = bgp_capability_addpath (peer, &caphdr);
break;
case CAPABILITY_CODE_ENHE:
- if (bgp_capability_enhe (peer, &caphdr))
- return -1;
+ ret = bgp_capability_enhe (peer, &caphdr);
break;
default:
if (caphdr.code > 128)
*error += caphdr.length + 2;
}
}
+
+ if (ret < 0)
+ {
+ bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_OPEN_MALFORMED_ATTR);
+ return -1;
+ }
if (stream_get_getp(s) != (start + caphdr.length))
{
if (stream_get_getp(s) > (start + caphdr.length))
if (STREAM_READABLE(s) < 2)
{
zlog_info ("%s Option length error", peer->host);
- bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
+ bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_OPEN_MALFORMED_ATTR);
return -1;
}
if (STREAM_READABLE (s) < opt_length)
{
zlog_info ("%s Option length error", peer->host);
- bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
+ bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_OPEN_MALFORMED_ATTR);
return -1;
}