summaryrefslogtreecommitdiff
path: root/bgpd/bgp_packet.c
diff options
context:
space:
mode:
authorPaul Jakma <paul@quagga.net>2012-01-09 20:59:26 +0000
committerPaul Jakma <paul@quagga.net>2012-03-04 23:55:02 +0000
commit5861739f8c38bc36ea9955e5cb2be2bf2f482d70 (patch)
tree9675845a0b3be97362f3426430c6c2e499e8525c /bgpd/bgp_packet.c
parent50e7a3885da44f8f6c5c639e111109deb055cdf3 (diff)
bgpd: Open option parse errors don't NOTIFY, resulting in abort & DoS
* bgp_packet.c: (bgp_open_receive) Errors from bgp_open_option_parse are detected, and the code will stop processing the OPEN and return. However it does so without calling bgp_notify_send to send a NOTIFY - which means the peer FSM doesn't get stopped, and bgp_read will be called again later. Because it returns, it doesn't go through the code near the end of the function that removes the current message from the peer input streaam. Thus the next call to bgp_read will try to parse a half-parsed stream as if it were a new BGP message, leading to an assert later in the code when it tries to read stuff that isn't there. Add the required call to bgp_notify_send before returning. * bgp_open.c: (bgp_capability_as4) Be a bit stricter, check the length field corresponds to the only value it can be, which is the amount we're going to read off the stream. And make sure the capability flag gets set, so callers can know this capability was read, regardless. (peek_for_as4_capability) Let bgp_capability_as4 do the length check.
Diffstat (limited to 'bgpd/bgp_packet.c')
-rw-r--r--bgpd/bgp_packet.c10
1 files changed, 7 insertions, 3 deletions
diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c
index f5a74d1b..5d8087a8 100644
--- a/bgpd/bgp_packet.c
+++ b/bgpd/bgp_packet.c
@@ -1459,9 +1459,13 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
/* Open option part parse. */
if (optlen != 0)
{
- ret = bgp_open_option_parse (peer, optlen, &capability);
- if (ret < 0)
- return ret;
+ if ((ret = bgp_open_option_parse (peer, optlen, &capability)) < 0)
+ {
+ bgp_notify_send (peer,
+ BGP_NOTIFY_OPEN_ERR,
+ BGP_NOTIFY_OPEN_UNACEP_HOLDTIME);
+ return ret;
+ }
}
else
{