When route priorities were added to the RA/redirects code, all
of them got set to RTP_CONNECTED. Most importantly, rt6_flush
was made to flush only RTP_CONNECTED routes. The purpose of
rt6_flush is to flush *all* routes going via a specified gw.
Now the problem is that the code in rtrequest1/mpath code
changes routing priorities. For example for default routes
which means that rt6_flush won't actually flush anything.
The problem became evident when tahi test used RA with
RouterLifetime set to 0 to remove routes and redirects. This
obviously doesn't work. Therefore IMHO rt6_flush should
actually use RTP_ANY.
The rest of the change changes RTP_CONNECTED to RTP_DEFAULT
for default and off-link routes, leaving RTP_CONNECTED for
directly connected ones.
Additional rt6_flush is there to faciliate a situation when
RA with RouterLifetime==0 is sent to clear a redirect. Consider
a following situation. Router R1 sends a redirect to R2 that
you don't know about and when you try using it, R2 sends you
a RA saying that it's not a valid router. In such situation
redirect is not valid anymore and should be removed. Obviously
R1 is misconfigured but it might be fixed before redirect
expires itself.
OK?
diff --git sys/netinet6/nd6_rtr.c sys/netinet6/nd6_rtr.c
index 5de5cf7..f846063 100644
--- sys/netinet6/nd6_rtr.c
+++ sys/netinet6/nd6_rtr.c
@@ -459,7 +459,7 @@ defrouter_addreq(struct nd_defrouter *new)
info.rti_info[RTAX_NETMASK] = (struct sockaddr *)&mask;
s = splsoftnet();
- error = rtrequest1(RTM_ADD, &info, RTP_CONNECTED, &newrt,
+ error = rtrequest1(RTM_ADD, &info, RTP_DEFAULT, &newrt,
new->ifp->if_rdomain);
if (newrt) {
nd6_rtmsg(RTM_ADD, newrt); /* tell user process */
@@ -563,7 +563,7 @@ defrouter_delreq(struct nd_defrouter *dr)
info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&gw;
info.rti_info[RTAX_NETMASK] = (struct sockaddr *)&mask;
- rtrequest1(RTM_DELETE, &info, RTP_CONNECTED, &oldrt,
+ rtrequest1(RTM_DELETE, &info, RTP_DEFAULT, &oldrt,
dr->ifp->if_rdomain);
if (oldrt) {
nd6_rtmsg(RTM_DELETE, oldrt);
@@ -788,6 +788,9 @@ defrtrlist_update(struct nd_defrouter *new)
/* entry does not exist */
if (new->rtlifetime == 0) {
+ /* flush all possible redirects */
+ if (!ip6_forwarding && ip6_accept_rtadv)
+ rt6_flush(&new->rtaddr, new->ifp);
splx(s);
return (NULL);
}
@@ -1669,7 +1672,7 @@ nd6_prefix_offlink(struct nd_prefix *pr)
bzero(&info, sizeof(info));
info.rti_info[RTAX_DST] = (struct sockaddr *)&sa6;
info.rti_info[RTAX_NETMASK] = (struct sockaddr *)&mask6;
- error = rtrequest1(RTM_DELETE, &info, RTP_CONNECTED, &rt,
+ error = rtrequest1(RTM_DELETE, &info, RTP_DEFAULT, &rt,
ifp->if_rdomain);
if (error == 0) {
pr->ndpr_stateflags &= ~NDPRF_ONLINK;
@@ -1980,7 +1983,7 @@ rt6_deleteroute(struct radix_node *rn, void *arg, u_int
id)
info.rti_info[RTAX_DST] = rt_key(rt);
info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
info.rti_info[RTAX_NETMASK] = rt_mask(rt);
- return (rtrequest1(RTM_DELETE, &info, RTP_CONNECTED, NULL, id));
+ return (rtrequest1(RTM_DELETE, &info, RTP_ANY, NULL, id));
#undef SIN6
}