diff options
author | Donald Sharp <sharpd@cumulusnetworks.com> | 2015-05-20 03:03:43 +0200 |
---|---|---|
committer | Donald Sharp <sharpd@cumulusnetworks.com> | 2015-05-20 03:03:43 +0200 |
commit | b184ccd889de7fd7557d0100385b0f232e46c0fe (patch) | |
tree | 5aa131f9dbbbc5db9f5fe46cdabc167b4c21e92e /bgpd/bgp_packet.c | |
parent | zebra-redistribute-table.patch (diff) | |
download | frr-b184ccd889de7fd7557d0100385b0f232e46c0fe.tar.xz frr-b184ccd889de7fd7557d0100385b0f232e46c0fe.zip |
Correct a few fuzz failures in BGP
Diffstat (limited to 'bgpd/bgp_packet.c')
-rw-r--r-- | bgpd/bgp_packet.c | 46 |
1 files changed, 40 insertions, 6 deletions
diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c index 16284bd5b..1d7d2d5f9 100644 --- a/bgpd/bgp_packet.c +++ b/bgpd/bgp_packet.c @@ -1343,6 +1343,34 @@ bgp_collision_detect (struct peer *new, struct in_addr remote_id) return 0; } +/* + * per draft-ietf-idr-error-handling-13 + * + * An IP host address SHOULD be considered invalid if it appears in the + * "IANA IPv4 Special-Purpose Address Registry" [IANA-IPV4] and either + * the "destination" or the "forwardable" boolean in that registry is + * given as "false". + */ +int +bgp_valid_host_address (unsigned long addr) +{ + if (IPV4_NET0(addr) || // 0.0.0.0/8 + IPV4_NET127(addr) || // 127.0.0.0/8 + IPV4_LINKLOCAL(addr) || // 169.254.0.0/16 + addr == 0xC00000AA || // 192.0.0.170/32 + addr == 0xC00000AB || // 192.0.0.171/32 + (addr & 0xffffff00) == 0xC0000200 || // 192.0.2.0/24 + (addr & 0xffffff00) == 0xC6336400 || // 198.51.100.0/24 + (addr & 0xffffff00) == 0xCB007100 || // 203.0.113.0/24 + IPV4_CLASS_DE(addr)) + { + return 0; + } + + return 1; +} + + static int bgp_open_receive (struct peer *peer, bgp_size_t size) { @@ -1358,11 +1386,15 @@ bgp_open_receive (struct peer *peer, bgp_size_t size) int mp_capability; u_int8_t notify_data_remote_as[2]; u_int8_t notify_data_remote_id[4]; + u_int16_t *holdtime_ptr; + unsigned long local_addr; + unsigned long remote_addr; /* Parse open packet. */ version = stream_getc (peer->ibuf); memcpy (notify_data_remote_as, stream_pnt (peer->ibuf), 2); remote_as = stream_getw (peer->ibuf); + holdtime_ptr = stream_pnt (peer->ibuf); holdtime = stream_getw (peer->ibuf); memcpy (notify_data_remote_id, stream_pnt (peer->ibuf), 4); remote_id.s_addr = stream_get_ipv4 (peer->ibuf); @@ -1438,10 +1470,11 @@ bgp_open_receive (struct peer *peer, bgp_size_t size) } } + local_addr = ntohl (peer->local_id.s_addr); + remote_addr = ntohl (remote_id.s_addr); + /* remote router-id check. */ - if (remote_id.s_addr == 0 - || IPV4_CLASS_DE (ntohl (remote_id.s_addr)) - || ntohl (peer->local_id.s_addr) == ntohl (remote_id.s_addr)) + if (local_addr == remote_addr || !bgp_valid_host_address(remote_addr)) { if (bgp_debug_neighbor_events(peer)) zlog_debug ("%s bad OPEN, wrong router identifier %s", @@ -1493,9 +1526,10 @@ bgp_open_receive (struct peer *peer, bgp_size_t size) if (holdtime < 3 && holdtime != 0) { - bgp_notify_send (peer, - BGP_NOTIFY_OPEN_ERR, - BGP_NOTIFY_OPEN_UNACEP_HOLDTIME); + bgp_notify_send_with_data (peer, + BGP_NOTIFY_OPEN_ERR, + BGP_NOTIFY_OPEN_UNACEP_HOLDTIME, + holdtime_ptr, 2); return -1; } |