Apply by doing: cd /usr/src patch -p0 < 015_ndp.patch Then build and install a new kernel. Index: sys/netinet6/in6.c =================================================================== RCS file: /cvs/src/sys/netinet6/in6.c,v retrieving revision 1.72 diff -u -p -r1.72 in6.c --- sys/netinet6/in6.c 17 Nov 2006 01:11:23 -0000 1.72 +++ sys/netinet6/in6.c 1 Oct 2008 22:03:56 -0000 @@ -1974,6 +1974,31 @@ in6ifa_ifpwithaddr(ifp, addr) } /* + * find the internet address on a given interface corresponding to a neighbor's + * address. + */ +struct in6_ifaddr * +in6ifa_ifplocaladdr(const struct ifnet *ifp, const struct in6_addr *addr) +{ + struct ifaddr *ifa; + struct in6_ifaddr *ia; + + TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { + if (ifa->ifa_addr == NULL) + continue; /* just for safety */ + if (ifa->ifa_addr->sa_family != AF_INET6) + continue; + ia = (struct in6_ifaddr *)ifa; + if (IN6_ARE_MASKED_ADDR_EQUAL(addr, + &ia->ia_addr.sin6_addr, + &ia->ia_prefixmask.sin6_addr)) + return ia; + } + + return NULL; +} + +/* * Convert IP6 address to printable (loggable) representation. */ static char digits[] = "0123456789abcdef"; Index: sys/netinet6/in6_var.h =================================================================== RCS file: /cvs/src/sys/netinet6/in6_var.h,v retrieving revision 1.28 diff -u -p -r1.28 in6_var.h --- sys/netinet6/in6_var.h 6 Jul 2006 02:56:58 -0000 1.28 +++ sys/netinet6/in6_var.h 1 Oct 2008 22:03:56 -0000 @@ -586,6 +586,8 @@ void in6_createmkludge(struct ifnet *); void in6_purgemkludge(struct ifnet *); struct in6_ifaddr *in6ifa_ifpforlinklocal(struct ifnet *, int); struct in6_ifaddr *in6ifa_ifpwithaddr(struct ifnet *, struct in6_addr *); +struct in6_ifaddr *in6ifa_ifplocaladdr(const struct ifnet *, + const struct in6_addr *); char *ip6_sprintf(struct in6_addr *); int in6_addr2scopeid(struct ifnet *, struct in6_addr *); int in6_matchlen(struct in6_addr *, struct in6_addr *); Index: sys/netinet6/nd6_nbr.c =================================================================== RCS file: /cvs/src/sys/netinet6/nd6_nbr.c,v retrieving revision 1.45.2.1 diff -u -p -r1.45.2.1 nd6_nbr.c --- sys/netinet6/nd6_nbr.c 21 Mar 2008 20:39:45 -0000 1.45.2.1 +++ sys/netinet6/nd6_nbr.c 1 Oct 2008 22:03:56 -0000 @@ -134,8 +134,18 @@ nd6_ns_input(m, off, icmp6len) "(wrong ip6 dst)\n")); goto bad; } + } else { + /* + * Make sure the source address is from a neighbor's address. + */ + if (in6ifa_ifplocaladdr(ifp, &saddr6) == NULL) { + nd6log((LOG_INFO, "nd6_ns_input: " + "NS packet from non-neighbor\n")); + goto bad; + } } + if (IN6_IS_ADDR_MULTICAST(&taddr6)) { nd6log((LOG_INFO, "nd6_ns_input: bad NS target (multicast)\n")); goto bad; @@ -544,9 +554,7 @@ nd6_na_input(m, off, icmp6len) struct ifnet *ifp = m->m_pkthdr.rcvif; struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); struct nd_neighbor_advert *nd_na; -#if 0 struct in6_addr saddr6 = ip6->ip6_src; -#endif struct in6_addr daddr6 = ip6->ip6_dst; struct in6_addr taddr6; int flags; @@ -632,6 +640,14 @@ nd6_na_input(m, off, icmp6len) "nd6_na_input: duplicate IP6 address %s\n", ip6_sprintf(&taddr6)); goto freeit; + } + /* + * Make sure the source address is from a neighbor's address. + */ + if (in6ifa_ifplocaladdr(ifp, &saddr6) == NULL) { + nd6log((LOG_INFO, "nd6_na_input: " + "ND packet from non-neighbor\n")); + goto bad; } if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {