]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Test BSD kernels for a specific version so we can listen to either
authorRoy Marples <roy@marples.name>
Thu, 16 May 2013 14:28:42 +0000 (14:28 +0000)
committerRoy Marples <roy@marples.name>
Thu, 16 May 2013 14:28:42 +0000 (14:28 +0000)
RTM_NEWADDR for duplicates, or directly on the wire with a maximum
timeout.

Warn about this noisily as there is no reason why the kernel cannot be
easily patched to support this.

README
if-bsd.c
ipv6.h
ipv6ns.c

diff --git a/README b/README
index 17eb5108f5d039770b06cb74999d7b71e9427184..2ef4c9b31f000b3cebe30f48ec9de08b58995de1 100644 (file)
--- a/README
+++ b/README
@@ -38,16 +38,6 @@ routes. You can find discussion here:
 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,
index d664d4d1a68abe2aff15404a272267760ad514c9..136fab2db9f516241a88bd478571529e490892e0 100644 (file)
--- a/if-bsd.c
+++ b/if-bsd.c
@@ -481,7 +481,7 @@ manage_link(int fd)
        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
@@ -606,7 +606,7 @@ manage_link(int fd)
                                            &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];
diff --git a/ipv6.h b/ipv6.h
index 870cb0e4728cddd6368ff6df5312f944721e3db8..d730c78a14a6aa1a3a3b28f67bedc004046ff9f9 100644 (file)
--- a/ipv6.h
+++ b/ipv6.h
 
 #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;
index 16cc15ece569dfdac31112b50a1188bd311ee5c3..ba1eb56ec4256e3d65a7882a55c7b0cb34007522 100644 (file)
--- a/ipv6ns.c
+++ b/ipv6ns.c
@@ -164,6 +164,12 @@ ipv6ns_open(void)
        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)