]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Babel: Seqno requests are properly decoupled from neighbors when the underlying inter... mh-bird-apkg
authorMaria Matejka <mq@ucw.cz>
Sun, 30 May 2021 11:07:16 +0000 (13:07 +0200)
committerMaria Matejka <mq@ucw.cz>
Sun, 30 May 2021 11:29:21 +0000 (13:29 +0200)
When an interface disappears, all the neighbors are freed as well. Seqno
requests were anyway not decoupled from them, leading to strange
segfaults. This fix adds a proper seqno request list inside neighbors to
make sure that no pointer to neighbor is kept after free.

lib/lists.h
proto/babel/babel.c
proto/babel/babel.h

index 066eafbb0b620df62579903481b7bab27dcfa7ab..479f4ed1a64d5f95c9f6487c192038eaab7b4c97 100644 (file)
@@ -59,6 +59,8 @@ typedef union list {                  /* In fact two overlayed nodes */
 /* WALK_LIST_FIRST supposes that called code removes each processed node */
 #define WALK_LIST_FIRST(n,list) \
      while(n=HEAD(list), (NODE (n))->next)
+#define WALK_LIST_FIRST2(n,pos,list) \
+     while(n=SKIP_BACK(typeof(*n),pos,HEAD(list)), (n)->pos.next)
 #define WALK_LIST_BACKWARDS(n,list) for(n=TAIL(list);(NODE (n))->prev; \
                                n=(void *)((NODE (n))->prev))
 #define WALK_LIST_BACKWARDS_DELSAFE(n,prv,list) \
index 25d8e33047e2a9352f990eeda5ac458e3c940f0c..fdebc35265e984182b6973cd6ee067ea8740619e 100644 (file)
@@ -56,13 +56,6 @@ static void babel_update_cost(struct babel_neighbor *n);
 static inline void babel_kick_timer(struct babel_proto *p);
 static inline void babel_iface_kick_timer(struct babel_iface *ifa);
 
-static inline void babel_lock_neighbor(struct babel_neighbor *nbr)
-{ if (nbr) nbr->uc++; }
-
-static inline void babel_unlock_neighbor(struct babel_neighbor *nbr)
-{ if (nbr && !--nbr->uc) mb_free(nbr); }
-
-
 /*
  *     Functions to maintain data structures
  */
@@ -316,8 +309,9 @@ babel_add_seqno_request(struct babel_proto *p, struct babel_entry *e,
        return;
 
       /* Found older */
-      babel_unlock_neighbor(sr->nbr);
       rem_node(NODE sr);
+      rem_node(&sr->nbr_node);
+
       goto found;
     }
 
@@ -330,7 +324,10 @@ found:
   sr->hop_count = hop_count;
   sr->count = 0;
   sr->expires = current_time() + BABEL_SEQNO_REQUEST_EXPIRY;
-  babel_lock_neighbor(sr->nbr = nbr);
+
+  if (sr->nbr = nbr)
+    add_tail(&nbr->requests, &sr->nbr_node);
+
   add_tail(&e->requests, NODE sr);
 
   babel_send_seqno_request(p, e, sr);
@@ -339,7 +336,9 @@ found:
 static void
 babel_remove_seqno_request(struct babel_proto *p, struct babel_seqno_request *sr)
 {
-  babel_unlock_neighbor(sr->nbr);
+  if (sr->nbr)
+    rem_node(&sr->nbr_node);
+
   rem_node(NODE sr);
   sl_free(p->seqno_slab, sr);
 }
@@ -427,7 +426,7 @@ babel_get_neighbor(struct babel_iface *ifa, ip_addr addr)
   nbr->txcost = BABEL_INFINITY;
   nbr->cost = BABEL_INFINITY;
   init_list(&nbr->routes);
-  babel_lock_neighbor(nbr);
+  init_list(&nbr->requests);
   add_tail(&ifa->neigh_list, NODE nbr);
 
   return nbr;
@@ -448,9 +447,16 @@ babel_flush_neighbor(struct babel_proto *p, struct babel_neighbor *nbr)
     babel_flush_route(p, r);
   }
 
+  struct babel_seqno_request *sr;
+  WALK_LIST_FIRST2(sr, nbr_node, nbr->requests)
+  {
+    sr->nbr = NULL;
+    rem_node(&sr->nbr_node);
+  }
+
   nbr->ifa = NULL;
   rem_node(NODE nbr);
-  babel_unlock_neighbor(nbr);
+  mb_free(nbr);
 }
 
 static void
index e075024cb4dd154c982d11f7873321ab71cbb760..09bf530c2b35643364a37eb49f26d7c1a569eae8 100644 (file)
@@ -198,7 +198,6 @@ struct babel_neighbor {
   struct babel_iface *ifa;
 
   ip_addr addr;
-  uint uc;                             /* Reference counter for seqno requests */
   u16 rxcost;                          /* Sent in last IHU */
   u16 txcost;                          /* Received in last IHU */
   u16 cost;                            /* Computed neighbor cost */
@@ -212,6 +211,7 @@ struct babel_neighbor {
   btime ihu_expiry;
 
   list routes;                         /* Routes this neighbour has sent us (struct babel_route) */
+  list requests;                       /* Seqno requests bound to this neighbor */
 };
 
 struct babel_source {
@@ -241,6 +241,7 @@ struct babel_route {
 
 struct babel_seqno_request {
   node n;
+  node nbr_node;
   u64 router_id;
   u16 seqno;
   u8 hop_count;