[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