--- sys/netinet6/nd6.c (svn+ssh://svn.freebsd.org/base/head) (revision 261548) +++ sys/netinet6/nd6.c (working copy) @@ -125,8 +125,7 @@ VNET_DEFINE(int, nd6_recalc_reachtm_interval) = ND int (*send_sendso_input_hook)(struct mbuf *, struct ifnet *, int, int); -static int nd6_is_new_addr_neighbor(struct sockaddr_in6 *, - struct ifnet *); +static int nd6_is_new_addr_neighbor(struct in6_addr *, struct ifnet *); static void nd6_setmtu0(struct ifnet *, struct nd_ifinfo *); static void nd6_slowtimo(void *); static int regen_tmpaddr(struct in6_ifaddr *); @@ -872,37 +871,23 @@ nd6_lookup(struct in6_addr *addr6, int flags, stru * to not reenter the routing code from within itself. */ static int -nd6_is_new_addr_neighbor(struct sockaddr_in6 *addr, struct ifnet *ifp) +nd6_is_new_addr_neighbor(struct in6_addr *addr, struct ifnet *ifp) { struct nd_prefix *pr; - struct ifaddr *dstaddr; + struct in6_ifaddr *ia6; /* * A link-local address is always a neighbor. - * XXX: a link does not necessarily specify a single interface. */ - if (IN6_IS_ADDR_LINKLOCAL(&addr->sin6_addr)) { - struct sockaddr_in6 sin6_copy; - u_int32_t zone; - - /* - * We need sin6_copy since sa6_recoverscope() may modify the - * content (XXX). - */ - sin6_copy = *addr; - if (sa6_recoverscope(&sin6_copy)) - return (0); /* XXX: should be impossible */ - if (in6_setscope(&sin6_copy.sin6_addr, ifp, &zone)) - return (0); - if (sin6_copy.sin6_scope_id == zone) - return (1); - else - return (0); - } - + if (IN6_IS_ADDR_LINKLOCAL(addr)) + return (1); /* * If the address matches one of our addresses, * it should be a neighbor. + */ + if (in6_localip(addr)) + return (1); + /* * If the address matches one of our on-link prefixes, it should be a * neighbor. */ @@ -937,7 +922,7 @@ static int } if (IN6_ARE_MASKED_ADDR_EQUAL(&pr->ndpr_prefix.sin6_addr, - &addr->sin6_addr, &pr->ndpr_mask)) + addr, &pr->ndpr_mask)) return (1); } @@ -945,13 +930,10 @@ static int * If the address is assigned on the node of the other side of * a p2p interface, the address should be a neighbor. */ - dstaddr = ifa_ifwithdstaddr((struct sockaddr *)addr); - if (dstaddr != NULL) { - if (dstaddr->ifa_ifp == ifp) { - ifa_free(dstaddr); - return (1); - } - ifa_free(dstaddr); + ia6 = in6ifa_ifpwithdstaddr(ifp, addr); + if (ia6 != NULL) { + ifa_free(&ia6->ia_ifa); + return (1); } /* @@ -973,7 +955,7 @@ static int * XXX: should take care of the destination of a p2p link? */ int -nd6_is_addr_neighbor(struct sockaddr_in6 *addr, struct ifnet *ifp) +nd6_is_addr_neighbor(struct in6_addr *addr, struct ifnet *ifp) { struct llentry *lle; int rc = 0; @@ -987,7 +969,7 @@ int * in the neighbor cache. */ IF_AFDATA_RLOCK(ifp); - if ((lle = nd6_lookup(&addr->sin6_addr, 0, ifp)) != NULL) { + if ((lle = nd6_lookup(addr, 0, ifp)) != NULL) { LLE_RUNLOCK(lle); rc = 1; } @@ -1243,8 +1225,6 @@ nd6_ioctl(u_long cmd, caddr_t data, struct ifnet * if (i >= DRLSTSIZ) break; drl->defrouter[i].rtaddr = dr->rtaddr; - in6_clearscope(&drl->defrouter[i].rtaddr); - drl->defrouter[i].flags = dr->flags; drl->defrouter[i].rtlifetime = dr->rtlifetime; drl->defrouter[i].expire = dr->expire + @@ -1301,10 +1281,8 @@ nd6_ioctl(u_long cmd, caddr_t data, struct ifnet * j = 0; LIST_FOREACH(pfr, &pr->ndpr_advrtrs, pfr_entry) { if (j < DRLSTSIZ) { -#define RTRADDR oprl->prefix[i].advrtr[j] - RTRADDR = pfr->router->rtaddr; - in6_clearscope(&RTRADDR); -#undef RTRADDR + oprl->prefix[i].advrtr[j] = + pfr->router->rtaddr; } j++; } @@ -1496,13 +1474,9 @@ nd6_ioctl(u_long cmd, caddr_t data, struct ifnet * case SIOCGNBRINFO_IN6: { struct llentry *ln; - struct in6_addr nb_addr = nbi->addr; /* make local for safety */ - if ((error = in6_setscope(&nb_addr, ifp, NULL)) != 0) - return (error); - IF_AFDATA_RLOCK(ifp); - ln = nd6_lookup(&nb_addr, 0, ifp); + ln = nd6_lookup(&nbi->addr, 0, ifp); IF_AFDATA_RUNLOCK(ifp); if (ln == NULL) { @@ -1895,7 +1869,7 @@ nd6_output_lle(struct ifnet *ifp, struct ifnet *or IF_AFDATA_RLOCK(ifp); ln = lla_lookup(LLTABLE6(ifp), flags, (struct sockaddr *)dst); IF_AFDATA_RUNLOCK(ifp); - if ((ln == NULL) && nd6_is_addr_neighbor(dst, ifp)) { + if (ln == NULL &&nd6_is_addr_neighbor(&dst->sin6_addr, ifp)) { /* * Since nd6_is_addr_neighbor() internally calls nd6_lookup(), * the condition below is not very efficient. But we believe @@ -2291,7 +2265,7 @@ nd6_storelladdr(struct ifnet *ifp, struct mbuf *m, LLE_RUNLOCK(ln); /* this could happen, if we could not allocate memory */ m_freem(m); - return (1); + return (EHOSTUNREACH); } bcopy(&ln->ll_addr, desten, ifp->if_addrlen); @@ -2348,9 +2322,8 @@ nd6_sysctl_drlist(SYSCTL_HANDLER_ARGS) */ TAILQ_FOREACH(dr, &V_nd_defrouter, dr_entry) { d.rtaddr.sin6_addr = dr->rtaddr; - error = sa6_recoverscope(&d.rtaddr); - if (error != 0) - return (error); + d.rtaddr.sin6_scope_id = in6_getscopezone(dr->ifp, + in6_addrscope(&dr->rtaddr)); d.flags = dr->flags; d.rtlifetime = dr->rtlifetime; d.expire = dr->expire + (time_second - time_uptime); @@ -2371,7 +2344,6 @@ nd6_sysctl_prlist(SYSCTL_HANDLER_ARGS) struct nd_pfxrouter *pfr; time_t maxexpire; int error; - char ip6buf[INET6_ADDRSTRLEN]; if (req->newptr) return (EPERM); @@ -2387,11 +2359,8 @@ nd6_sysctl_prlist(SYSCTL_HANDLER_ARGS) */ LIST_FOREACH(pr, &V_nd_prefix, ndpr_entry) { p.prefix = pr->ndpr_prefix; - if (sa6_recoverscope(&p.prefix)) { - log(LOG_ERR, "scope error in prefix list (%s)\n", - ip6_sprintf(ip6buf, &p.prefix.sin6_addr)); - /* XXX: press on... */ - } + p.prefix.sin6_scope_id = in6_getscopezone(pr->ndpr_ifp, + in6_addrscope(&pr->ndpr_prefix.sin6_addr)); p.raflags = pr->ndpr_raf; p.prefixlen = pr->ndpr_plen; p.vltime = pr->ndpr_vltime; @@ -2420,10 +2389,8 @@ nd6_sysctl_prlist(SYSCTL_HANDLER_ARGS) return (error); LIST_FOREACH(pfr, &pr->ndpr_advrtrs, pfr_entry) { s6.sin6_addr = pfr->router->rtaddr; - if (sa6_recoverscope(&s6)) - log(LOG_ERR, - "scope error in prefix list (%s)\n", - ip6_sprintf(ip6buf, &pfr->router->rtaddr)); + s6.sin6_scope_id = in6_getscopezone(pfr->router->ifp, + in6_addrscope(&pfr->router->rtaddr)); error = SYSCTL_OUT(req, &s6, sizeof(s6)); if (error != 0) return (error);