kernel-netlink: Set NODAD flag for virtual IPv6 addresses
authorTobias Brunner <tobias@strongswan.org>
Tue, 13 Dec 2016 16:27:26 +0000 (17:27 +0100)
committerTobias Brunner <tobias@strongswan.org>
Mon, 6 Feb 2017 10:10:44 +0000 (11:10 +0100)
The Optimistic Duplicate Address Detection (DAD) seems to fail in some
cases (`dadfailed` in `ip addr`) rendering the virtual IP address unusable.

Fixes #2183.

src/libcharon/plugins/kernel_netlink/kernel_netlink_net.c

index 486e8db..4ecd976 100644 (file)
@@ -2155,16 +2155,22 @@ static status_t manage_ipaddr(private_kernel_netlink_net_t *this, int nlmsg_type
 
        netlink_add_attribute(hdr, IFA_LOCAL, chunk, sizeof(request));
 
-       if (ip->get_family(ip) == AF_INET6 && this->rta_prefsrc_for_ipv6)
-       {       /* if source routes are possible we let the virtual IP get deprecated
-                * immediately (but mark it as valid forever) so it gets only used if
-                * forced by our route, and not by the default IPv6 address selection */
-               struct ifa_cacheinfo cache = {
-                       .ifa_valid = 0xFFFFFFFF,
-                       .ifa_prefered = 0,
-               };
-               netlink_add_attribute(hdr, IFA_CACHEINFO, chunk_from_thing(cache),
-                                                         sizeof(request));
+       if (ip->get_family(ip) == AF_INET6)
+       {
+               msg->ifa_flags |= IFA_F_NODAD;
+               if (this->rta_prefsrc_for_ipv6)
+               {
+                       /* if source routes are possible we let the virtual IP get
+                        * deprecated immediately (but mark it as valid forever) so it gets
+                        * only used if forced by our route, and not by the default IPv6
+                        * address selection */
+                       struct ifa_cacheinfo cache = {
+                               .ifa_valid = 0xFFFFFFFF,
+                               .ifa_prefered = 0,
+                       };
+                       netlink_add_attribute(hdr, IFA_CACHEINFO, chunk_from_thing(cache),
+                                                                 sizeof(request));
+               }
        }
        return this->socket->send_ack(this->socket, hdr);
 }