]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Better profylaction recursive route loops
authorMaria Matejka <mq@ucw.cz>
Fri, 22 Oct 2021 17:43:55 +0000 (19:43 +0200)
committerMaria Matejka <mq@ucw.cz>
Mon, 22 Nov 2021 18:05:43 +0000 (19:05 +0100)
In some specific configurations, it was possible to send BIRD into an
infinite loop of recursive next hop resolution. This was caused by route
priority inversion.

To prevent priority inversions affecting other next hops, we simply
refuse to resolve any next hop if the best route for the matching prefix
is recursive or any other route with the same preference is recursive.

Next hop resolution doesn't change route priority, therefore it is
perfectly OK to resolve BGP next hops e.g. by an OSPF route, yet if the
same (or covering) prefix is also announced by iBGP, by retraction of
the OSPF route we would get a possible priority inversion.

nest/rt-table.c

index 2f480992b6a125114008d4d1112d752f9f293c3f..2dcb2e261da100e289de29724552625ab7d5b3d1 100644 (file)
@@ -2649,9 +2649,10 @@ rt_update_hostentry(rtable *tab, struct hostentry *he)
     {
       struct rte_storage *e = n->routes;
       rta *a = e->rte.attrs;
-      pxlen = n->n.addr->pxlen;
+      word pref = a->pref;
 
-      if (a->hostentry)
+      for (struct rte_storage *ee = n->routes; ee; ee = ee->next)
+       if ((ee->rte.attrs->pref >= pref) && ee->rte.attrs->hostentry)
        {
          /* Recursive route should not depend on another recursive route */
          log(L_WARN "Next hop address %I resolvable through recursive route for %N",
@@ -2659,6 +2660,8 @@ rt_update_hostentry(rtable *tab, struct hostentry *he)
          goto done;
        }
 
+      pxlen = n->n.addr->pxlen;
+
       if (a->dest == RTD_UNICAST)
        {
          for (struct nexthop *nh = &(a->nh); nh; nh = nh->next)