I'm still looking for OKs on this.
On Mon, Apr 02, 2012 at 14:42 +0200, Mike Belopuhov wrote:
> 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
> }