- /* Quickhack - completely ignore DAD NS packets */
- if (dad_ignore_ns) {
- struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa;
- IFA_LOCK(&ia->ia_ifa);
- nd6log((LOG_INFO,
- "nd6_dad_ns_input: ignoring DAD NS packet for "
- "address %s(%s)\n", ip6_sprintf(&ia->ia_addr.sin6_addr),
- if_name(ifa->ifa_ifp)));
- IFA_UNLOCK(&ia->ia_ifa);
- return;
+ VERIFY(ifa != NULL);
+ candisable = FALSE;
+ IFA_LOCK(ifa);
+ ia = (struct in6_ifaddr *) ifa;
+ if (IN6_IS_ADDR_LINKLOCAL(&ia->ia_addr.sin6_addr)) {
+ struct ip6aux *ip6a;
+
+ candisable = TRUE;
+ ip6a = ip6_findaux(m);
+
+ if (ip6a && (ip6a->ip6a_flags & IP6A_HASEEN) != 0) {
+ struct in6_addr in6 = ia->ia_addr.sin6_addr;
+
+ nd6log((LOG_INFO,
+ "%s: eh_src=%02x:%02x:%02x:%02x:%02x:%02x -> %s\n",
+ __func__,
+ ip6a->ip6a_ehsrc[0], ip6a->ip6a_ehsrc[1],
+ ip6a->ip6a_ehsrc[2], ip6a->ip6a_ehsrc[3],
+ ip6a->ip6a_ehsrc[4], ip6a->ip6a_ehsrc[5],
+ if_name(ifa->ifa_ifp)));
+
+ in6.s6_addr8[8] = ip6a->ip6a_ehsrc[0] ^ ND6_EUI64_UBIT;
+ in6.s6_addr8[9] = ip6a->ip6a_ehsrc[1];
+ in6.s6_addr8[10] = ip6a->ip6a_ehsrc[2];
+ in6.s6_addr8[11] = 0xff;
+ in6.s6_addr8[12] = 0xfe;
+ in6.s6_addr8[13] = ip6a->ip6a_ehsrc[3];
+ in6.s6_addr8[14] = ip6a->ip6a_ehsrc[4];
+ in6.s6_addr8[15] = ip6a->ip6a_ehsrc[5];
+
+ if (!IN6_ARE_ADDR_EQUAL(&in6, &ia->ia_addr.sin6_addr)) {
+ nd6log((LOG_ERR, "%s: DAD NS for %s on %s "
+ "is from another MAC address.\n", __func__,
+ ip6_sprintf(&ia->ia_addr.sin6_addr),
+ if_name(ifa->ifa_ifp)));
+ candisable = FALSE;
+ }
+ } else {
+ nd6log((LOG_INFO,
+ "%s: no eh_src for DAD NS %s at %s.\n", __func__,
+ ip6_sprintf(&ia->ia_addr.sin6_addr),
+ if_name(ifa->ifa_ifp)));
+ }