[PATCH] babel: Fix missing modulo comparison of seqnos
Juliusz noticed there were a couple of places we were doing straight inequality comparisons of seqnos in Babel. This is wrong because seqnos can wrap: so we need to use the modulo-64k comparison function for these cases as well. Introduce a strict-inequality version of the modulo-comparison for this purpose. Reported-by: Juliusz Chroboczek <jch@irif.fr> Signed-off-by: Toke Høiland-Jørgensen <toke@toke.dk> --- proto/babel/babel.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/proto/babel/babel.c b/proto/babel/babel.c index ff8b6b52ef4a..a20bd72456bb 100644 --- a/proto/babel/babel.c +++ b/proto/babel/babel.c @@ -49,6 +49,10 @@ static inline int ge_mod64k(uint a, uint b) { return (u16)(a - b) < 0x8000; } +/* Strict inequality version of the above */ +static inline int gt_mod64k(uint a, uint b) +{ return ge_mod64k(a, b) && a != b; } + static void babel_expire_requests(struct babel_proto *p, struct babel_entry *e); static void babel_select_route(struct babel_proto *p, struct babel_entry *e, struct babel_route *mod); static inline void babel_announce_retraction(struct babel_proto *p, struct babel_entry *e); @@ -559,7 +563,7 @@ babel_is_feasible(struct babel_source *s, u16 seqno, u16 metric) { return !s || (metric == BABEL_INFINITY) || - (seqno > s->seqno) || + gt_mod64k(seqno, s->seqno) || ((seqno == s->seqno) && (metric < s->metric)); } @@ -1013,7 +1017,7 @@ babel_send_update_(struct babel_iface *ifa, btime changed, struct fib *rtable) struct babel_source *s = babel_get_source(p, e, e->router_id); s->expires = current_time() + BABEL_GARBAGE_INTERVAL; - if ((msg.update.seqno > s->seqno) || + if (gt_mod64k(msg.update.seqno, s->seqno) || ((msg.update.seqno == s->seqno) && (msg.update.metric < s->metric))) { s->seqno = msg.update.seqno; -- 2.39.1
On Mon, Jan 30, 2023 at 11:15:52PM +0100, Toke Høiland-Jørgensen via Bird-users wrote:
Juliusz noticed there were a couple of places we were doing straight inequality comparisons of seqnos in Babel. This is wrong because seqnos can wrap: so we need to use the modulo-64k comparison function for these cases as well.
Introduce a strict-inequality version of the modulo-comparison for this purpose.
Thanks, merged: https://gitlab.nic.cz/labs/bird/-/commit/3e7e4a71868bc519aacc0eb785471b46fc3... -- Elen sila lumenn' omentielvo Ondrej 'Santiago' Zajicek (email: santiago@crfreenet.org) OpenPGP encrypted e-mails preferred (KeyID 0x11DEADC3, wwwkeys.pgp.net) "To err is human -- to blame it on a computer is even more so."
Ondrej Zajicek <santiago@crfreenet.org> writes:
On Mon, Jan 30, 2023 at 11:15:52PM +0100, Toke Høiland-Jørgensen via Bird-users wrote:
Juliusz noticed there were a couple of places we were doing straight inequality comparisons of seqnos in Babel. This is wrong because seqnos can wrap: so we need to use the modulo-64k comparison function for these cases as well.
Introduce a strict-inequality version of the modulo-comparison for this purpose.
Thanks, merged:
https://gitlab.nic.cz/labs/bird/-/commit/3e7e4a71868bc519aacc0eb785471b46fc3...
Uh, that must be a new record turnaround time - thanks! :) -Toke
Introduce a strict-inequality version of the modulo-comparison for this purpose.
Thanks. I'm a little worried about the code around line 1017: struct babel_source *s = babel_get_source(p, e, e->router_id); s->expires = current_time() + BABEL_GARBAGE_INTERVAL; if (gt_mod64k(msg.update.seqno, s->seqno) || ((msg.update.seqno == s->seqno) && (msg.update.metric < s->metric))) { s->seqno = msg.update.seqno; s->metric = msg.update.metric; } If the source is just being created, then the function babel_get_source will initialise s->seqno to 0. If msg.update.seqno happens to be in the interval [0x8000,0xFFFF], then the conditional at line 1020 will fail to trigger, and s->seqno will not be updated until msg.updae.seqno catches up with 0. I think that babel_get_source should take an extra argument, the initial seqno in case the source does not exist, and it should be called with msg.update.seqno. This corresponds to RFC 8966 Section 3.5.3. -- Juliusz
Juliusz Chroboczek <jch@irif.fr> writes:
Introduce a strict-inequality version of the modulo-comparison for this purpose.
Thanks.
I'm a little worried about the code around line 1017:
struct babel_source *s = babel_get_source(p, e, e->router_id); s->expires = current_time() + BABEL_GARBAGE_INTERVAL;
if (gt_mod64k(msg.update.seqno, s->seqno) || ((msg.update.seqno == s->seqno) && (msg.update.metric < s->metric))) { s->seqno = msg.update.seqno; s->metric = msg.update.metric; }
If the source is just being created, then the function babel_get_source will initialise s->seqno to 0. If msg.update.seqno happens to be in the interval [0x8000,0xFFFF], then the conditional at line 1020 will fail to trigger, and s->seqno will not be updated until msg.updae.seqno catches up with 0.
I think that babel_get_source should take an extra argument, the initial seqno in case the source does not exist, and it should be called with msg.update.seqno. This corresponds to RFC 8966 Section 3.5.3.
Ah, I see the problem. You're right, of course, sorry for not catching your meaning the first time around. I'll send (another) patch :) -Toke
participants (3)
-
Juliusz Chroboczek -
Ondrej Zajicek -
Toke Høiland-Jørgensen