BSD systems where this has been fixed are:
NetBSD-5.0
-Some BSD systems announce IPv6 addresses to userland when the address has
-been added, not when it's actually ready to use. This is important because
-no kernel allows to send from the unspecified address which means userland
-cannot be RFC conformation when creating DAD messages so we need to rely on
-the kernel implementation.
-You can find the discussion here:
- http://mail-index.netbsd.org/tech-net/2013/03/15/msg004019.html
-BSD systems where this will be fixed are:
- NetBSD-7.0
-
We try and detect how dhcpcd should interact with system services during the
configure stage. If we cannot auto-detect how do to this, or it is wrong then
you can change this by passing shell commands to --service-exists,
struct sockaddr_dl sdl;
unsigned char *hwaddr;
#endif
-#ifdef INET6
+#if defined(INET6) && !defined(LISTEN_DAD)
struct in6_addr ia6;
struct sockaddr_in6 *sin6;
#endif
&rt.dest, &rt.net, &rt.gate);
break;
#endif
-#ifdef INET6
+#if defined(INET6) && !defined(LISTEN_DAD)
case AF_INET6:
sin6 = (struct sockaddr_in6*)
rti_info[RTAX_IFA];
#define ROUNDUP8(a) (1 + (((a) - 1) | 7))
+/*
+ * BSD kernels don't inform userland of DAD results.
+ * Also, for RTM_NEWADDR messages the address flags could be
+ * undefined leading to false positive duplicate address errors.
+ * As such we listen for duplicate addresses on the wire and
+ * wait the maxium possible length of time as dictated by the DAD transmission
+ * counter and RFC timings.
+ * See the discussion here:
+ * http://mail-index.netbsd.org/tech-net/2013/03/15/msg004019.html
+ */
+#ifdef BSD
+# define LISTEN_DAD
+#endif
+
+/* This was fixed in NetBSD */
+#ifdef __NetBSD_Prereq__
+# if __NetBSD_Prereq__(6, 99, 20)
+# undef LISTEN_DAD
+# endif
+#endif
+
+#ifdef LISTEN_DAD
+# warning kernel does not report DAD results to userland
+# warning listening to duplicated addresses on the wire
+#endif
+
struct ipv6_addr {
TAILQ_ENTRY(ipv6_addr) next;
struct interface *iface;
atexit(ipv6ns_cleanup);
#endif
+#ifdef LISTEN_DAD
+ syslog(LOG_WARNING, "kernel does not report DAD results to userland");
+ syslog(LOG_WARNING,
+ "warning listening to duplicated addresses on the wire");
+#endif
+
len = CMSG_SPACE(sizeof(struct in6_pktinfo)) + CMSG_SPACE(sizeof(int));
sndbuf = calloc(1, len);
if (sndbuf == NULL)