Noticed while syncing code. I missed some scope_id assignments and checks
in a few places.
- VPN6 missed all of it
- in kr_redistribute6() the copy is not really needed since link local
address can not be redistributed (I still added it though)
- kroute6_compare() do actually compare the scope_id of a prefix.
This should make handling of link local addrs a bit more robust.
- in kroute6_find() set the scope_id else kroute6_compare() will match
against stack garbage.
- in kroute6_matchgw() we need to compare the scope_id as well
- in kr_fib_change() compare nexthop with scope_id to know if it changed
and update the scope_id as well afterwards.
Works for me
--
:wq Claudio
Index: kroute.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/kroute.c,v
retrieving revision 1.271
diff -u -p -r1.271 kroute.c
--- kroute.c 30 Jun 2022 20:33:14 -0000 1.271
+++ kroute.c 14 Jul 2022 10:20:00 -0000
@@ -725,8 +725,10 @@ krVPN6_change(struct ktable *kt, struct
return (-1);
}
memcpy(&kr6->prefix, &kf->prefix.v6, sizeof(struct in6_addr));
+ kr6->prefix_scope_id = kf->prefix.scope_id;
kr6->prefixlen = kf->prefixlen;
memcpy(&kr6->nexthop, &kf->nexthop.v6, sizeof(struct in6_addr));
+ kr6->nexthop_scope_id = kf->nexthop.scope_id;
kr6->flags = kf->flags | F_BGPD | F_MPLS;
kr6->priority = RTP_MINE;
kr6->labelid = labelid;
@@ -742,6 +744,7 @@ krVPN6_change(struct ktable *kt, struct
kr6->mplslabel = mplslabel;
kr6->ifindex = kf->ifindex;
memcpy(&kr6->nexthop, &kf->nexthop.v6, sizeof(struct in6_addr));
+ kr6->nexthop_scope_id = kf->nexthop.scope_id;
rtlabel_unref(kr6->labelid);
kr6->labelid = labelid;
if (kf->flags & F_BLACKHOLE)
@@ -1469,6 +1472,7 @@ kr_redistribute6(int type, struct ktable
bzero(&net, sizeof(net));
net.prefix.aid = AID_INET6;
memcpy(&net.prefix.v6, &kr6->prefix, sizeof(struct in6_addr));
+ net.prefix.scope_id = kr6->prefix_scope_id;
net.prefixlen = kr6->prefixlen;
net.rtlabel = kr6->labelid;
net.priority = kr6->priority;
@@ -1680,6 +1684,10 @@ kroute6_compare(struct kroute6 *a, struc
if (a->prefix.s6_addr[i] > b->prefix.s6_addr[i])
return (1);
}
+ if (a->prefix_scope_id < b->prefix_scope_id)
+ return (-1);
+ if (a->prefix_scope_id > b->prefix_scope_id)
+ return (1);
if (a->prefixlen < b->prefixlen)
return (-1);
@@ -1939,6 +1947,7 @@ kroute6_find(struct ktable *kt, const st
struct kroute6 *kn6, *tmp;
s.prefix = prefix->v6;
+ s.prefix_scope_id = prefix->scope_id;
s.prefixlen = prefixlen;
s.priority = prio;
@@ -1968,7 +1977,8 @@ kroute6_matchgw(struct kroute6 *kr, stru
nexthop = gw->v6;
do {
- if (memcmp(&kr->nexthop, &nexthop, sizeof(nexthop)) == 0)
+ if (memcmp(&kr->nexthop, &nexthop, sizeof(nexthop)) == 0 &&
+ kr->nexthop_scope_id == gw->scope_id)
return (kr);
kr = kr->next;
} while (kr);
@@ -3524,9 +3534,13 @@ add4:
if (kl->nexthop.aid == AID_INET6) {
if (memcmp(&kr6->nexthop,
&kl->nexthop.v6,
- sizeof(struct in6_addr)))
+ sizeof(struct in6_addr)) ||
+ kr6->nexthop_scope_id !=
+ kl->nexthop.scope_id)
changed = 1;
kr6->nexthop = kl->nexthop.v6;
+ kr6->nexthop_scope_id =
+ kl->nexthop.scope_id;
kr6->ifindex = kl->ifindex;
} else {
if (memcmp(&kr6->nexthop,
@@ -3534,6 +3548,7 @@ add4:
sizeof(struct in6_addr)))
changed = 1;
kr6->nexthop = in6addr_any;
+ kr6->nexthop_scope_id = 0;
kr6->ifindex = kl->ifindex;
}