summaryrefslogtreecommitdiffstats
path: root/bgpd/bgp_packet.c
diff options
context:
space:
mode:
authorDonald Sharp <sharpd@cumulusnetworks.com>2015-05-20 03:03:43 +0200
committerDonald Sharp <sharpd@cumulusnetworks.com>2015-05-20 03:03:43 +0200
commitb184ccd889de7fd7557d0100385b0f232e46c0fe (patch)
tree5aa131f9dbbbc5db9f5fe46cdabc167b4c21e92e /bgpd/bgp_packet.c
parentzebra-redistribute-table.patch (diff)
downloadfrr-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.c46
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;
}