[PATCH] babel: Don't try to remove multicast seqno request objects from neighbour list

Toke Høiland-Jørgensen toke at toke.dk
Thu May 12 14:12:13 CEST 2022


The Babel seqno request code keeps track of which seqno requests are
outstanding for a neighbour by putting them onto a per-neighbour list. When
reusing a seqno request, it will try to remove this node, but if the seqno
request in question was a multicast request with no neighbour attached this
will result in a crash because it tries to remove a list node that wasn't
added to any list.

Fix this by making the list remove conditional. Also add a check so that
seqno requests are only reused if the neighbour also matches, allowing
multiple outstanding requests for the same router ID.

Fixes: ebd5751cdeb4 ("Babel: Seqno requests are properly decoupled from neighbors when the underlying interface disappears")
Reported-by: Stefan Haller <stefan.haller at stha.de>
Signed-off-by: Toke Høiland-Jørgensen <toke at toke.dk>
---
 proto/babel/babel.c | 18 +++++++++++-------
 1 file changed, 11 insertions(+), 7 deletions(-)

diff --git a/proto/babel/babel.c b/proto/babel/babel.c
index 4a7d550f5efe..03f1cb500278 100644
--- a/proto/babel/babel.c
+++ b/proto/babel/babel.c
@@ -304,7 +304,7 @@ babel_add_seqno_request(struct babel_proto *p, struct babel_entry *e,
   struct babel_seqno_request *sr;
 
   WALK_LIST(sr, e->requests)
-    if (sr->router_id == router_id)
+    if (sr->router_id == router_id && sr->nbr == nbr)
     {
       /* Found matching or newer */
       if (ge_mod64k(sr->seqno, seqno) && seqno_request_valid(sr))
@@ -312,7 +312,8 @@ babel_add_seqno_request(struct babel_proto *p, struct babel_entry *e,
 
       /* Found older */
       rem_node(NODE sr);
-      rem_node(&sr->nbr_node);
+      if (sr->nbr)
+        rem_node(&sr->nbr_node);
 
       goto found;
     }
@@ -349,17 +350,20 @@ static int
 babel_satisfy_seqno_request(struct babel_proto *p, struct babel_entry *e,
 			   u64 router_id, u16 seqno)
 {
-  struct babel_seqno_request *sr;
+  struct babel_seqno_request *sr, *srx;
+  int ret = 0;
 
-  WALK_LIST(sr, e->requests)
+  WALK_LIST_DELSAFE(sr, srx, e->requests)
     if ((sr->router_id == router_id) && ge_mod64k(seqno, sr->seqno))
     {
-      /* Found the request, remove it */
+      /* Found a matching request, remove it; there may be multiple outstanding
+       * requests, so continue looping
+       */
       babel_remove_seqno_request(p, sr);
-      return 1;
+      ret = 1;
     }
 
-  return 0;
+  return ret;
 }
 
 static void
-- 
2.36.1



More information about the Bird-users mailing list