Apply by doing: cd /usr/src patch -p0 < 001_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.78 retrieving revision 1.78.2.1 diff -u -p -r1.78 -r1.78.2.1 --- sys/netinet6/in6.c 13 Jul 2008 20:41:39 -0000 1.78 +++ sys/netinet6/in6.c 2 Nov 2008 04:02:10 -0000 1.78.2.1 @@ -1941,6 +1941,31 @@ in6ifa_ifpwithaddr(struct ifnet *ifp, st } return ((struct in6_ifaddr *)ifa); +} + +/* + * 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; } /* Index: sys/netinet6/in6_var.h =================================================================== RCS file: /cvs/src/sys/netinet6/in6_var.h,v retrieving revision 1.29 retrieving revision 1.29.2.1 diff -u -p -r1.29 -r1.29.2.1 --- sys/netinet6/in6_var.h 11 Jun 2008 06:30:36 -0000 1.29 +++ sys/netinet6/in6_var.h 2 Nov 2008 04:02:10 -0000 1.29.2.1 @@ -588,6 +588,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.51 retrieving revision 1.51.2.1 diff -u -p -r1.51 -r1.51.2.1 --- sys/netinet6/nd6_nbr.c 11 Jun 2008 19:00:50 -0000 1.51 +++ sys/netinet6/nd6_nbr.c 2 Nov 2008 04:02:10 -0000 1.51.2.1 @@ -132,8 +132,18 @@ nd6_ns_input(struct mbuf *m, int off, in "(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; @@ -540,9 +550,7 @@ nd6_na_input(struct mbuf *m, int off, in 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; @@ -628,6 +636,14 @@ nd6_na_input(struct mbuf *m, int off, in "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) {