babel: Don't try to remove multicast seqno request objects from neighbour list
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: ebd5751cde
("Babel: Seqno requests are properly decoupled from neighbors when the underlying interface disappears")
Reported-by: Stefan Haller <stefan.haller@stha.de>
Signed-off-by: Toke Høiland-Jørgensen <toke@toke.dk>
This commit is contained in:
parent
207ac48533
commit
8f9a091d30
1 changed files with 11 additions and 7 deletions
|
@ -304,7 +304,7 @@ babel_add_seqno_request(struct babel_proto *p, struct babel_entry *e,
|
||||||
struct babel_seqno_request *sr;
|
struct babel_seqno_request *sr;
|
||||||
|
|
||||||
WALK_LIST(sr, e->requests)
|
WALK_LIST(sr, e->requests)
|
||||||
if (sr->router_id == router_id)
|
if (sr->router_id == router_id && sr->nbr == nbr)
|
||||||
{
|
{
|
||||||
/* Found matching or newer */
|
/* Found matching or newer */
|
||||||
if (ge_mod64k(sr->seqno, seqno) && seqno_request_valid(sr))
|
if (ge_mod64k(sr->seqno, seqno) && seqno_request_valid(sr))
|
||||||
|
@ -312,6 +312,7 @@ babel_add_seqno_request(struct babel_proto *p, struct babel_entry *e,
|
||||||
|
|
||||||
/* Found older */
|
/* Found older */
|
||||||
rem_node(NODE sr);
|
rem_node(NODE sr);
|
||||||
|
if (sr->nbr)
|
||||||
rem_node(&sr->nbr_node);
|
rem_node(&sr->nbr_node);
|
||||||
|
|
||||||
goto found;
|
goto found;
|
||||||
|
@ -349,17 +350,20 @@ static int
|
||||||
babel_satisfy_seqno_request(struct babel_proto *p, struct babel_entry *e,
|
babel_satisfy_seqno_request(struct babel_proto *p, struct babel_entry *e,
|
||||||
u64 router_id, u16 seqno)
|
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))
|
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);
|
babel_remove_seqno_request(p, sr);
|
||||||
return 1;
|
ret = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
Loading…
Reference in a new issue