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
 }

Reply via email to