--- sys/netinet6/nd6_nbr.c (svn+ssh://svn.freebsd.org/base/head) (revision 261548) +++ sys/netinet6/nd6_nbr.c (working copy) @@ -134,9 +134,6 @@ nd6_ns_input(struct mbuf *m, int off, int icmp6len #endif ip6 = mtod(m, struct ip6_hdr *); /* adjust pointer for safety */ taddr6 = nd_ns->nd_ns_target; - if (in6_setscope(&taddr6, ifp, NULL) != 0) - goto bad; - if (ip6->ip6_hlim != 255) { nd6log((LOG_ERR, "nd6_ns_input: invalid hlim (%d) from %s to %s on %s\n", @@ -147,8 +144,7 @@ nd6_ns_input(struct mbuf *m, int off, int icmp6len if (IN6_IS_ADDR_UNSPECIFIED(&saddr6)) { /* dst has to be a solicited node multicast address. */ - if (daddr6.s6_addr16[0] == IPV6_ADDR_INT16_MLL && - /* don't check ifindex portion */ + if (daddr6.s6_addr32[0] == IPV6_ADDR_INT32_MLL && daddr6.s6_addr32[1] == 0 && daddr6.s6_addr32[2] == IPV6_ADDR_INT32_ONE && daddr6.s6_addr8[12] == 0xff) { @@ -159,8 +155,6 @@ nd6_ns_input(struct mbuf *m, int off, int icmp6len goto bad; } } else if (!V_nd6_onlink_ns_rfc4861) { - struct sockaddr_in6 src_sa6; - /* * According to recent IETF discussions, it is not a good idea * to accept a NS from an address which would not be deemed @@ -167,11 +161,7 @@ nd6_ns_input(struct mbuf *m, int off, int icmp6len * to be a neighbor otherwise. This point is expected to be * clarified in future revisions of the specification. */ - bzero(&src_sa6, sizeof(src_sa6)); - src_sa6.sin6_family = AF_INET6; - src_sa6.sin6_len = sizeof(src_sa6); - src_sa6.sin6_addr = saddr6; - if (nd6_is_addr_neighbor(&src_sa6, ifp) == 0) { + if (nd6_is_addr_neighbor(&saddr6, ifp) == 0) { nd6log((LOG_INFO, "nd6_ns_input: " "NS packet from non-neighbor\n")); goto bad; @@ -231,7 +221,7 @@ nd6_ns_input(struct mbuf *m, int off, int icmp6len ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, &taddr6); /* (2) check. */ - if (ifa == NULL) { + if (ifa == NULL && !IN6_IS_ADDR_LINKLOCAL(&taddr6)) { struct route_in6 ro; int need_proxy; @@ -328,12 +318,7 @@ nd6_ns_input(struct mbuf *m, int off, int icmp6len * S bit ("solicited") must be zero. */ if (IN6_IS_ADDR_UNSPECIFIED(&saddr6)) { - struct in6_addr in6_all; - - in6_all = in6addr_linklocal_allnodes; - if (in6_setscope(&in6_all, ifp, NULL) != 0) - goto bad; - nd6_na_output_fib(ifp, &in6_all, &taddr6, + nd6_na_output_fib(ifp, &in6addr_linklocal_allnodes, &taddr6, ((anycast || proxy || !tlladdr) ? 0 : ND_NA_FLAG_OVERRIDE) | rflag, tlladdr, proxy ? (struct sockaddr *)&proxydl : NULL, M_GETFIB(m)); @@ -382,15 +367,15 @@ void nd6_ns_output(struct ifnet *ifp, const struct in6_addr *daddr6, const struct in6_addr *taddr6, struct llentry *ln, int dad) { + struct route_in6 ro; + struct ip6_moptions im6o; struct mbuf *m; struct m_tag *mtag; struct ip6_hdr *ip6; struct nd_neighbor_solicit *nd_ns; - struct ip6_moptions im6o; int icmp6len; - int maxlen; + int maxlen, flags; caddr_t mac; - struct route_in6 ro; if (IN6_IS_ADDR_MULTICAST(taddr6)) return; @@ -414,7 +399,6 @@ nd6_ns_output(struct ifnet *ifp, const struct in6_ return; bzero(&ro, sizeof(ro)); - if (daddr6 == NULL || IN6_IS_ADDR_MULTICAST(daddr6)) { m->m_flags |= M_MCAST; im6o.im6o_multicast_ifp = ifp; @@ -437,14 +421,11 @@ nd6_ns_output(struct ifnet *ifp, const struct in6_ if (daddr6) ip6->ip6_dst = *daddr6; else { - ip6->ip6_dst.s6_addr16[0] = IPV6_ADDR_INT16_MLL; - ip6->ip6_dst.s6_addr16[1] = 0; + ip6->ip6_dst.s6_addr32[0] = IPV6_ADDR_INT32_MLL; ip6->ip6_dst.s6_addr32[1] = 0; ip6->ip6_dst.s6_addr32[2] = IPV6_ADDR_INT32_ONE; ip6->ip6_dst.s6_addr32[3] = taddr6->s6_addr32[3]; ip6->ip6_dst.s6_addr8[12] = 0xff; - if (in6_setscope(&ip6->ip6_dst, ifp, NULL) != 0) - goto bad; } if (!dad) { struct ifaddr *ifa; @@ -499,6 +480,8 @@ nd6_ns_output(struct ifnet *ifp, const struct in6_ dst_sa.sin6_family = AF_INET6; dst_sa.sin6_len = sizeof(dst_sa); dst_sa.sin6_addr = ip6->ip6_dst; + dst_sa.sin6_scope_id = in6_getscopezone(ifp, + in6_addrscope(&ip6->ip6_dst)); oifp = ifp; error = in6_selectsrc(&dst_sa, NULL, @@ -529,7 +512,6 @@ nd6_ns_output(struct ifnet *ifp, const struct in6_ nd_ns->nd_ns_code = 0; nd_ns->nd_ns_reserved = 0; nd_ns->nd_ns_target = *taddr6; - in6_clearscope(&nd_ns->nd_ns_target); /* XXX */ /* * Add source link-layer address option. @@ -572,7 +554,10 @@ nd6_ns_output(struct ifnet *ifp, const struct in6_ m_tag_prepend(m, mtag); } - ip6_output(m, NULL, &ro, dad ? IPV6_UNSPECSRC : 0, &im6o, NULL, NULL); + flags = IPV6_USEROIF; + if (dad) + flags |= IPV6_UNSPECSRC; + ip6_output(m, NULL, &ro, flags, &im6o, &ifp, NULL); icmp6_ifstat_inc(ifp, ifs6_out_msg); icmp6_ifstat_inc(ifp, ifs6_out_neighborsolicit); ICMP6STAT_INC(icp6s_outhist[ND_NEIGHBOR_SOLICIT]); @@ -648,9 +633,6 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len is_override = ((flags & ND_NA_FLAG_OVERRIDE) != 0); taddr6 = nd_na->nd_na_target; - if (in6_setscope(&taddr6, ifp, NULL)) - goto bad; /* XXX: impossible */ - if (IN6_IS_ADDR_MULTICAST(&taddr6)) { nd6log((LOG_ERR, "nd6_na_input: invalid target address %s\n", @@ -1007,14 +989,10 @@ nd6_na_output_fib(struct ifnet *ifp, const struct ip6->ip6_hlim = 255; if (IN6_IS_ADDR_UNSPECIFIED(&daddr6)) { /* reply to DAD */ - daddr6.s6_addr16[0] = IPV6_ADDR_INT16_MLL; - daddr6.s6_addr16[1] = 0; + daddr6.s6_addr32[0] = IPV6_ADDR_INT32_MLL; daddr6.s6_addr32[1] = 0; daddr6.s6_addr32[2] = 0; daddr6.s6_addr32[3] = IPV6_ADDR_INT32_ONE; - if (in6_setscope(&daddr6, ifp, NULL)) - goto bad; - flags &= ~ND_NA_FLAG_SOLICITED; } ip6->ip6_dst = daddr6; @@ -1022,11 +1000,10 @@ nd6_na_output_fib(struct ifnet *ifp, const struct dst_sa.sin6_family = AF_INET6; dst_sa.sin6_len = sizeof(struct sockaddr_in6); dst_sa.sin6_addr = daddr6; - + dst_sa.sin6_scope_id = in6_getscopezone(ifp, in6_addrscope(&daddr6)); /* * Select a source whose scope is the same as that of the dest. */ - bcopy(&dst_sa, &ro.ro_dst, sizeof(dst_sa)); oifp = ifp; error = in6_selectsrc(&dst_sa, NULL, NULL, &ro, NULL, &oifp, &src); if (error) { @@ -1041,8 +1018,6 @@ nd6_na_output_fib(struct ifnet *ifp, const struct nd_na->nd_na_type = ND_NEIGHBOR_ADVERT; nd_na->nd_na_code = 0; nd_na->nd_na_target = *taddr6; - in6_clearscope(&nd_na->nd_na_target); /* XXX */ - /* * "tlladdr" indicates NS's condition for adding tlladdr or not. * see nd6_ns_input() for details. @@ -1099,7 +1074,7 @@ nd6_na_output_fib(struct ifnet *ifp, const struct m_tag_prepend(m, mtag); } - ip6_output(m, NULL, &ro, 0, &im6o, NULL, NULL); + ip6_output(m, NULL, &ro, IPV6_USEROIF, &im6o, &ifp, NULL); icmp6_ifstat_inc(ifp, ifs6_out_msg); icmp6_ifstat_inc(ifp, ifs6_out_neighboradvert); ICMP6STAT_INC(icp6s_outhist[ND_NEIGHBOR_ADVERT]);