diff options
Diffstat (limited to 'sys/netinet6/icmp6.c')
| -rw-r--r-- | sys/netinet6/icmp6.c | 34 |
1 files changed, 23 insertions, 11 deletions
diff --git a/sys/netinet6/icmp6.c b/sys/netinet6/icmp6.c index 29dd3edf841eb..c918e69627fb6 100644 --- a/sys/netinet6/icmp6.c +++ b/sys/netinet6/icmp6.c @@ -2434,27 +2434,39 @@ icmp6_redirect_input(struct mbuf *m, int off) nd6_cache_lladdr(ifp, &redtgt6, lladdr, lladdrlen, ND_REDIRECT, is_onlink ? ND_REDIRECT_ONLINK : ND_REDIRECT_ROUTER); - if (!is_onlink) { /* better router case. perform rtredirect. */ - /* perform rtredirect */ + /* + * Install a gateway route in the better-router case or an interface + * route in the on-link-destination case. + */ + { struct sockaddr_in6 sdst; struct sockaddr_in6 sgw; struct sockaddr_in6 ssrc; + struct sockaddr *gw; + int rt_flags; u_int fibnum; bzero(&sdst, sizeof(sdst)); - bzero(&sgw, sizeof(sgw)); bzero(&ssrc, sizeof(ssrc)); - sdst.sin6_family = sgw.sin6_family = ssrc.sin6_family = AF_INET6; - sdst.sin6_len = sgw.sin6_len = ssrc.sin6_len = - sizeof(struct sockaddr_in6); - bcopy(&redtgt6, &sgw.sin6_addr, sizeof(struct in6_addr)); + sdst.sin6_family = ssrc.sin6_family = AF_INET6; + sdst.sin6_len = ssrc.sin6_len = sizeof(struct sockaddr_in6); bcopy(&reddst6, &sdst.sin6_addr, sizeof(struct in6_addr)); bcopy(&src6, &ssrc.sin6_addr, sizeof(struct in6_addr)); + rt_flags = RTF_HOST; + if (is_router) { + bzero(&sgw, sizeof(sgw)); + sgw.sin6_family = AF_INET6; + sgw.sin6_len = sizeof(struct sockaddr_in6); + bcopy(&redtgt6, &sgw.sin6_addr, + sizeof(struct in6_addr)); + gw = (struct sockaddr *)&sgw; + rt_flags |= RTF_GATEWAY; + } else + gw = ifp->if_addr->ifa_addr; for (fibnum = 0; fibnum < rt_numfibs; fibnum++) - in6_rtredirect((struct sockaddr *)&sdst, - (struct sockaddr *)&sgw, (struct sockaddr *)NULL, - RTF_GATEWAY | RTF_HOST, (struct sockaddr *)&ssrc, - fibnum); + in6_rtredirect((struct sockaddr *)&sdst, gw, + (struct sockaddr *)NULL, rt_flags, + (struct sockaddr *)&ssrc, fibnum); } /* finally update cached route in each socket via pfctlinput */ { |
