]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
IPv6: Don't set IN6_IFF_TENTATIVE when the address exists
authorRoy Marples <roy@marples.name>
Wed, 9 Oct 2024 10:19:56 +0000 (11:19 +0100)
committerRoy Marples <roy@marples.name>
Wed, 9 Oct 2024 10:22:00 +0000 (11:22 +0100)
We can only work it out when we know the address, not beforehand.

src/ipv6.c

index 7e2f0bb1c826fd0d19bc9bf16b734eb5cd8aa521..576c63d93b4479f1723b1a16cb0a65eb26a1b491 100644 (file)
@@ -89,7 +89,6 @@
 
 #ifdef IPV6_POLLADDRFLAG
 #  warning kernel does not report IPv6 address flag changes
-#  warning polling tentative address flags periodically
 #endif
 
 /* Hackery at it's finest. */
@@ -661,8 +660,7 @@ ipv6_addaddr1(struct ipv6_addr *ia, const struct timespec *now)
        struct interface *ifp;
        uint32_t pltime, vltime;
        int loglevel;
-       struct ipv6_state *state;
-       struct ipv6_addr *ia2;
+       struct ipv6_addr *iaf;
 
 #ifdef __sun
        /* If we re-add then address on Solaris then the prefix
@@ -678,8 +676,9 @@ ipv6_addaddr1(struct ipv6_addr *ia, const struct timespec *now)
        /* Remember the interface of the address. */
        ifp = ia->iface;
 
-       if (!(ia->flags & IPV6_AF_DADCOMPLETED) &&
-           ipv6_iffindaddr(ifp, &ia->addr, IN6_IFF_NOTUSEABLE))
+       /* Find any existing address. */
+       iaf = ipv6_iffindaddr(ifp, &ia->addr, 0);
+       if (iaf != NULL && !(iaf->addr_flags & IN6_IFF_NOTUSEABLE))
                ia->flags |= IPV6_AF_DADCOMPLETED;
 
        /* Adjust plftime and vltime based on acquired time */
@@ -785,18 +784,15 @@ ipv6_addaddr1(struct ipv6_addr *ia, const struct timespec *now)
        /* Take a copy of the address and add it to our state if
         * it does not exist.
         * This is important if route overflow loses the message. */
-       state = IPV6_STATE(ifp);
-       TAILQ_FOREACH(ia2, &state->addrs, next) {
-               if (IN6_ARE_ADDR_EQUAL(&ia2->addr, &ia->addr))
-                       break;
-       }
-       if (ia2 == NULL) {
-               if ((ia2 = malloc(sizeof(*ia2))) == NULL) {
+       if (iaf == NULL) {
+               struct ipv6_state *state = IPV6_STATE(ifp);
+
+               if ((iaf = malloc(sizeof(*iaf))) == NULL) {
                        logerr(__func__);
                        return 0; /* Well, we did add the address */
                }
-               memcpy(ia2, ia, sizeof(*ia2));
-               TAILQ_INSERT_TAIL(&state->addrs, ia2, next);
+               memcpy(iaf, ia, sizeof(*iaf));
+               TAILQ_INSERT_TAIL(&state->addrs, iaf, next);
        }
 
        return 0;
@@ -1330,17 +1326,19 @@ ipv6_iffindaddr(struct interface *ifp, const struct in6_addr *addr,
        struct ipv6_addr *ap;
 
        state = IPV6_STATE(ifp);
-       if (state) {
-               TAILQ_FOREACH(ap, &state->addrs, next) {
-                       if (addr == NULL) {
-                               if (IN6_IS_ADDR_LINKLOCAL(&ap->addr) &&
-                                   (!revflags || !(ap->addr_flags & revflags)))
-                                       return ap;
-                       } else {
-                               if (IN6_ARE_ADDR_EQUAL(&ap->addr, addr) &&
-                                   (!revflags || !(ap->addr_flags & revflags)))
-                                       return ap;
-                       }
+       if (state == NULL)
+               return NULL;
+
+       TAILQ_FOREACH(ap, &state->addrs, next) {
+               if (addr == NULL) {
+                       if (IN6_IS_ADDR_LINKLOCAL(&ap->addr) &&
+                           (!revflags || !(ap->addr_flags & revflags)))
+                               return ap;
+               } else if (IN6_ARE_ADDR_EQUAL(&ap->addr, addr)) {
+                       /* This is our address so we will return now */
+                       if (!revflags || !(ap->addr_flags & revflags))
+                               return ap;
+                       return NULL;
                }
        }
        return NULL;
@@ -1606,38 +1604,13 @@ ipv6_newaddr(struct interface *ifp, const struct in6_addr *addr,
        struct ipv6_addr *ia, *iaf;
        char buf[INET6_ADDRSTRLEN];
        const char *cbp;
-       bool tempaddr;
-       int addr_flags;
-
-#ifdef IPV6_AF_TEMPORARY
-       tempaddr = flags & IPV6_AF_TEMPORARY;
-#else
-       tempaddr = false;
-#endif
-
-       /* If adding a new DHCP / RA derived address, check current flags
-        * from an existing address. */
-       if (tempaddr)
-               iaf = NULL;
-       else if (flags & IPV6_AF_AUTOCONF)
-               iaf = ipv6nd_iffindprefix(ifp, addr, prefix_len);
-       else
-               iaf = ipv6_iffindaddr(ifp, addr, 0);
-       if (iaf != NULL) {
-               addr_flags = iaf->addr_flags;
-               flags |= IPV6_AF_ADDED;
-       } else
-               addr_flags = IN6_IFF_TENTATIVE;
 
        ia = calloc(1, sizeof(*ia));
        if (ia == NULL)
                goto err;
 
        ia->iface = ifp;
-       ia->addr_flags = addr_flags;
        ia->flags = IPV6_AF_NEW | flags;
-       if (!(ia->addr_flags & IN6_IFF_NOTUSEABLE))
-               ia->flags |= IPV6_AF_DADCOMPLETED;
        ia->prefix_len = prefix_len;
        ia->dhcp6_fd = -1;
 
@@ -1649,6 +1622,7 @@ ipv6_newaddr(struct interface *ifp, const struct in6_addr *addr,
                goto makepfx;
        else if (ia->flags & IPV6_AF_AUTOCONF) {
                ia->prefix = *addr;
+               iaf = ipv6nd_iffindprefix(ifp, addr, prefix_len);
                if (iaf != NULL)
                        memcpy(&ia->addr, &iaf->addr, sizeof(ia->addr));
                else {
@@ -1666,7 +1640,7 @@ ipv6_newaddr(struct interface *ifp, const struct in6_addr *addr,
                cbp = inet_ntop(AF_INET6, &ia->addr, buf, sizeof(buf));
                goto paddr;
 #else
-               return ia;
+               goto flags;
 #endif
        } else if (ia->flags & (IPV6_AF_REQUEST | IPV6_AF_PFXDELEGATION)) {
                ia->prefix = *addr;
@@ -1686,6 +1660,21 @@ paddr:
                goto err;
        snprintf(ia->saddr, sizeof(ia->saddr), "%s/%d", cbp, ia->prefix_len);
 
+#ifndef __sun
+flags:
+#endif
+       /* If adding a new DHCP / RA derived address, check current flags
+        * from an existing address. */
+       iaf = ipv6_iffindaddr(ifp, &ia->addr, 0);
+       if (iaf != NULL) {
+               ia->addr_flags = iaf->addr_flags;
+               ia->flags |= IPV6_AF_ADDED;
+       } else
+               ia->addr_flags |= IN6_IFF_TENTATIVE;
+
+       if (!(ia->addr_flags & IN6_IFF_NOTUSEABLE))
+               ia->flags |= IPV6_AF_DADCOMPLETED;
+
        return ia;
 
 err: