]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
BGP: Better handling of non-matching AFI in nexthops
authorOndrej Zajicek (work) <santiago@crfreenet.org>
Sat, 15 Dec 2018 13:01:57 +0000 (14:01 +0100)
committerOndrej Zajicek (work) <santiago@crfreenet.org>
Sun, 16 Dec 2018 14:43:58 +0000 (15:43 +0100)
proto/bgp/attrs.c
proto/bgp/packets.c

index 868caca5b53a444f286f3736cc72c60ebd335e72..cbb2203835876c2b8153434e995aebafb2433e27 100644 (file)
@@ -1386,8 +1386,6 @@ bgp_preexport(struct proto *P, rte **new, struct linpool *pool UNUSED)
   if (src == NULL)
     return 0;
 
-  // XXXX: Check next hop AF
-
   /* IBGP route reflection, RFC 4456 */
   if (p->is_internal && src->is_internal && (p->local_as == src->local_as))
   {
index c226187079c6aefbfdbe23269d7fdaee6e87360a..e7089eba0e8ccb31820567be4d1000fafe373cfb 100644 (file)
@@ -855,6 +855,7 @@ static inline int
 bgp_use_next_hop(struct bgp_export_state *s, eattr *a)
 {
   struct bgp_proto *p = s->proto;
+  struct bgp_channel *c = s->channel;
   ip_addr *nh = (void *) a->u.ptr->data;
 
   if (s->channel->cf->next_hop_self)
@@ -867,6 +868,10 @@ bgp_use_next_hop(struct bgp_export_state *s, eattr *a)
   if (a->type & EAF_FRESH)
     return 1;
 
+  /* Check for non-matching AF */
+  if ((ipa_is_ip4(*nh) != bgp_channel_is_ipv4(c)) && !c->ext_next_hop)
+    return 0;
+
   /* Keep it when exported to internal peers */
   if (p->is_interior && ipa_nonzero(*nh))
     return 1;
@@ -880,6 +885,7 @@ static inline int
 bgp_use_gateway(struct bgp_export_state *s)
 {
   struct bgp_proto *p = s->proto;
+  struct bgp_channel *c = s->channel;
   rta *ra = s->route->attrs;
 
   if (s->channel->cf->next_hop_self)
@@ -889,6 +895,10 @@ bgp_use_gateway(struct bgp_export_state *s)
   if ((ra->dest != RTD_UNICAST) || ra->nh.next || ipa_zero(ra->nh.gw) || ipa_is_link_local(ra->nh.gw))
     return 0;
 
+  /* Check for non-matching AF */
+  if ((ipa_is_ip4(ra->nh.gw) != bgp_channel_is_ipv4(c)) && !c->ext_next_hop)
+    return 0;
+
   /* Use it when exported to internal peers */
   if (p->is_interior)
     return 1;