[Babel-users] Babel MAC auth fails due to packet reordering

Toke Høiland-Jørgensen toke at toke.dk
Fri May 6 11:40:29 BST 2022


Daniel Gröber <dxld at darkboxed.org> writes:

> Hi Toke,
>
> On Thu, May 05, 2022 at 07:14:24PM +0200, Toke Høiland-Jørgensen wrote:
>> Could you please try turning off power saving on the client device and
>> see if that makes the problem go away? 'iw dev wlan0 set power_save off'
>> should do the trick. You'll also need to make sure no other devices are
>> connected to the AP while you're testing (or that they also all have
>> power save disabled).
>
> Yup, that did the trick. If I kick all the smartphones off my network (and
> disable power-save on the babel peer) the problem goes away but comes back
> as soon as I reconnect one.
>
> I was wondering why you wanted me to remove all clients but I think I get
> it: ordinarily the power save packet buffering would only affect one client
> but since we're talking about multicast here the AP (apparently) buffers
> those packets if _any_ client is requesting power save.

Yes, exactly! It has to: any station that's in power save will miss
multicast transmissions while it's sleeping, so all multicast has to be
delayed until the known wake-up time.

Thanks for testing this; guess we found the culprit! The bad news (from
Babel's perspective) is that this is intrinsic to (at least
infrastructure mode) WLANs, so I don't think there's any way around the
windowed PC if we want to support mixing multicast and unicast traffic.

I took a shot at implementing window-based PC verification in Bird,
patch below (compile-tested only); care to test if that allows you to
run with power-save enabled (the wireless client was running Bird,
right)?

-Toke

diff --git a/proto/babel/babel.c b/proto/babel/babel.c
index 4a7d550f5efe..126bf18c1feb 100644
--- a/proto/babel/babel.c
+++ b/proto/babel/babel.c
@@ -1514,9 +1514,53 @@ babel_auth_check_pc(struct babel_iface *ifa, struct babel_msg_auth *msg)
     return 0;
   }
 
-  n->auth_pc = msg->pc;
-  n->auth_passed = 1;
+  /* If msg PC is more than twice over the replay window, there's no point in
+   * gradually shifting the window, so just reset and exit immediately
+   */
+  if (msg->pc - n->auth_pc > 64) {
+    LOG_PKT_AUTH("Authentication PC moved past 2x reorder window "
+		 "(rcv %u, window end %u) - resetting window",
+                 msg->sender, ifa->ifname, msg->pc, n->auth_pc + 32);
+
+    n->auth_pc = msg->pc;
+    n->auth_pc_window = 0;
+    n->auth_passed = 1;
+    return 1;
+  }
+
+  u8 auth_bit = msg->pc - n->auth_pc - 1;
+
+  if (auth_bit >= 32)
+  {
+    u8 fwd = auth_bit - 31;
+
+    LOG_PKT_AUTH("Authentication PC moved past reorder window "
+		 "(rcv %u, window end %u) - fast-forwarding window by %u",
+                 msg->sender, ifa->ifname, msg->pc, n->auth_pc + 32, fwd);
 
+    n->auth_pc += fwd;
+    n->auth_pc_window >>= fwd;
+    auth_bit -= fwd;
+  }
+
+  if (n->auth_pc_window & (1 << auth_bit))
+  {
+    LOG_PKT_AUTH("Authentication PC %u already seen "
+                 "(window start %u, value %x)",
+                 msg->sender, ifa->ifname, msg->pc, n->auth_pc + 1, n->auth_pc_window);
+    return 0;
+  }
+  n->auth_pc_window |= (1 << auth_bit);
+
+  u32 auth_bit_mask = (((u32)-1) >> (32 - auth_bit - 1));
+
+  if ((n->auth_pc_window & auth_bit_mask) == auth_bit_mask)
+  {
+    n->auth_pc_window >>= auth_bit + 1;
+    n->auth_pc += auth_bit + 1;
+  }
+
+  n->auth_passed = 1;
   return 1;
 }
 
diff --git a/proto/babel/babel.h b/proto/babel/babel.h
index 84feb085dae7..07cce9cc5504 100644
--- a/proto/babel/babel.h
+++ b/proto/babel/babel.h
@@ -225,6 +225,7 @@ struct babel_neighbor {
   uint last_hello_int;
 
   u32 auth_pc;
+  u32 auth_pc_window;
   u8 auth_passed;
   u8 auth_index_len;
   u8 auth_index[BABEL_AUTH_INDEX_LEN];



More information about the Babel-users mailing list