]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Ensure we have the correct type to send in our saved lease as the
authorRoy Marples <roy@marples.name>
Wed, 12 Jun 2013 10:58:28 +0000 (10:58 +0000)
committerRoy Marples <roy@marples.name>
Wed, 12 Jun 2013 10:58:28 +0000 (10:58 +0000)
user could change from IA_PD to IA_NA.
Re-send INFORM_REQUEST at each ROUTERADVERT.
Save some code by sharing the drop addrs loop.

dhcp6.c
ipv6.c
ipv6.h
ipv6rs.c

diff --git a/dhcp6.c b/dhcp6.c
index afd1a8017a45fcf5bbef606d7ba1a0239349d03b..7edd8333611bb7e58ac29ffeb041a4244fe45035 100644 (file)
--- a/dhcp6.c
+++ b/dhcp6.c
@@ -676,34 +676,13 @@ dhcp6_freedrop_addrs(struct interface *ifp, int drop,
     const struct interface *ifd)
 {
        struct dhcp6_state *state;
-       struct ipv6_addr *ap, *apn;
 
        state = D6_STATE(ifp);
-       if (state == NULL)
-               return;
-       TAILQ_FOREACH_SAFE(ap, &state->addrs, next, apn) {
-               if (ifd && ap->delegating_iface != ifd)
-                       continue;
-               TAILQ_REMOVE(&state->addrs, ap, next);
-               if (ap->dadcallback)
-                       eloop_q_timeout_delete(0, NULL, ap->dadcallback);
-               /* Only drop the address if no other RAs have assigned it.
-                * This is safe because the RA is removed from the list
-                * before we are called. */
-               if (drop && ap->flags & IPV6_AF_ONLINK &&
-                   !dhcp6_addrexists(ap) &&
-                   !ipv6rs_addrexists(ap))
-               {
-                       syslog(LOG_INFO, "%s: deleting address %s",
-                           ap->iface->name, ap->saddr);
-                       if (del_address6(ap) == -1 &&
-                           errno != EADDRNOTAVAIL && errno != ENXIO)
-                               syslog(LOG_ERR, "del_address6 %m");
-               }
-               free(ap);
+       if (state) {
+               ipv6_freedrop_addrs(&state->addrs, drop, ifd);
+               if (drop)
+                       ipv6_buildroutes();
        }
-       if (drop)
-               ipv6_buildroutes();
 }
 
 static void dhcp6_delete_delegates(struct interface *ifp)
@@ -1077,9 +1056,10 @@ dhcp6_startinform(struct interface *ifp)
 {
        struct dhcp6_state *state;
 
-       syslog(LOG_INFO, "%s: requesting DHCPv6 information", ifp->name);
-
        state = D6_STATE(ifp);
+       if (state->new == NULL || ifp->options->options & DHCPCD_DEBUG)
+               syslog(LOG_INFO, "%s: requesting DHCPv6 information",
+                   ifp->name);
        state->state = DH6S_INFORM;
        state->start_uptime = uptime();
        state->RTC = 0;
@@ -1547,7 +1527,7 @@ dhcp6_writelease(const struct interface *ifp)
        return bytes;
 }
 
-static ssize_t
+static int
 dhcp6_readlease(struct interface *ifp)
 {
        struct dhcp6_state *state;
@@ -1575,8 +1555,14 @@ dhcp6_readlease(struct interface *ifp)
        close(fd);
 
        /* Check to see if the lease is still valid */
-       if (dhcp6_validatelease(ifp, state->new, state->new_len, NULL) == -1)
+       fd = dhcp6_validatelease(ifp, state->new, state->new_len, NULL);
+       if (fd == -1)
+               goto ex;
+       if (fd == 0) {
+               syslog(LOG_INFO, "%s: lease was for different IA type",
+                   ifp->name);
                goto ex;
+       }
 
        if (state->expire != ND6_INFINITE_LIFETIME) {
                gettimeofday(&now, NULL);
@@ -1587,7 +1573,7 @@ dhcp6_readlease(struct interface *ifp)
                }
        }
 
-       return bytes;
+       return fd;
 
 ex:
        dhcp6_freedrop_addrs(ifp, 0, NULL);
@@ -2146,7 +2132,8 @@ recv:
        if (options & DHCPCD_TEST)
                script_runreason(ifp, "TEST");
        else {
-               state->state = DH6S_BOUND;
+               if (state->state != DH6S_INFORM)
+                       state->state = DH6S_BOUND;
                if (state->renew && state->renew != ND6_INFINITE_LIFETIME)
                        eloop_timeout_add_sec(state->renew,
                            dhcp6_startrenew, ifp);
@@ -2300,6 +2287,10 @@ dhcp6_start(struct interface *ifp, enum DH6S init_state)
                        dhcp6_find_delegates(ifp);
                        return 0;
                }
+               if (state->state == DH6S_INFORM && init_state == DH6S_INFORM) {
+                       dhcp6_startinform(ifp);
+                       return 0;
+               }
                /* We're already running DHCP6 */
                /* XXX: What if the managed flag changes? */
                return 0;
diff --git a/ipv6.c b/ipv6.c
index b706ab2f41465f74ecaeb9fa77c75e1bd8e5074f..de5513e82d9d93a76ac3da50cd2898857307e9ea 100644 (file)
--- a/ipv6.c
+++ b/ipv6.c
@@ -443,6 +443,34 @@ ipv6_addaddr(struct ipv6_addr *ap)
        return 0;
 }
 
+void
+ipv6_freedrop_addrs(struct ipv6_addrhead *addrs, int drop,
+    const struct interface *ifd)
+{
+       struct ipv6_addr *ap, *apn;
+
+       TAILQ_FOREACH_SAFE(ap, addrs, next, apn) {
+               if (ifd && ap->delegating_iface != ifd)
+                       continue;
+               TAILQ_REMOVE(addrs, ap, next);
+               if (ap->dadcallback)
+                       eloop_q_timeout_delete(0, NULL, ap->dadcallback);
+               /* Only drop the address if no other RAs have assigned it.
+                * This is safe because the RA is removed from the list
+                * before we are called. */
+               if (drop && ap->flags & IPV6_AF_ADDED &&
+                   !ipv6rs_addrexists(ap) && !dhcp6_addrexists(ap))
+               {
+                       syslog(LOG_INFO, "%s: deleting address %s",
+                           ap->iface->name, ap->saddr);
+                       if (del_address6(ap) == -1 &&
+                           errno != EADDRNOTAVAIL && errno != ENXIO)
+                               syslog(LOG_ERR, "del_address6 %m");
+               }
+               free(ap);
+       }
+}
+
 static struct ipv6_state *
 ipv6_getstate(struct interface *ifp)
 {
diff --git a/ipv6.h b/ipv6.h
index bd54414bf908dda69efe953686aeeff84108e29f..5a827af19395a37a16a85271610ecda97c188be9 100644 (file)
--- a/ipv6.h
+++ b/ipv6.h
@@ -147,6 +147,8 @@ int ipv6_prefixlen(const struct in6_addr *);
 int ipv6_userprefix( const struct in6_addr *, short prefix_len,
     uint64_t user_number, struct in6_addr *result, short result_len);
 int ipv6_addaddr(struct ipv6_addr *);
+void ipv6_freedrop_addrs(struct ipv6_addrhead *, int,
+    const struct interface *);
 void ipv6_handleifa(int, struct if_head *,
     const char *, const struct in6_addr *, int);
 int ipv6_handleifa_addrs(int, struct ipv6_addrhead *,
index 0ce4d9851fc62e8f6f74190f3c4c96c345f641f1..0d54b4e54a2b5910db611e944543842b98f9a755 100644 (file)
--- a/ipv6rs.c
+++ b/ipv6rs.c
@@ -306,32 +306,6 @@ ipv6rs_addrexists(const struct ipv6_addr *a)
        return 0;
 }
 
-static void
-ipv6rs_freedrop_addrs(struct ra *rap, int drop)
-{
-       struct ipv6_addr *ap;
-
-       while ((ap = TAILQ_FIRST(&rap->addrs))) {
-               TAILQ_REMOVE(&rap->addrs, ap, next);
-               if (ap->dadcallback)
-                       eloop_q_timeout_delete(0, NULL, ap->dadcallback);
-               /* Only drop the address if no other RAs have assigned it.
-                * This is safe because the RA is removed from the list
-                * before we are called. */
-               if (drop && ap->flags & IPV6_AF_ADDED &&
-                   !IN6_IS_ADDR_UNSPECIFIED(&ap->addr) &&
-                   !ipv6rs_addrexists(ap) && !dhcp6_addrexists(ap))
-               {
-                       syslog(LOG_INFO, "%s: deleting address %s",
-                           rap->iface->name, ap->saddr);
-                       if (del_address6(ap) == -1 &&
-                           errno != EADDRNOTAVAIL && errno != ENXIO)
-                               syslog(LOG_ERR, "del_address6 %m");
-               }
-               free(ap);
-       }
-}
-
 void ipv6rs_freedrop_ra(struct ra *rap, int drop)
 {
 
@@ -339,7 +313,7 @@ void ipv6rs_freedrop_ra(struct ra *rap, int drop)
        eloop_timeout_delete(NULL, rap);
        if (!drop)
                TAILQ_REMOVE(&ipv6_routers, rap, next);
-       ipv6rs_freedrop_addrs(rap, drop);
+       ipv6_freedrop_addrs(&rap->addrs, drop, NULL);
        ipv6rs_free_opts(rap);
        free(rap->data);
        free(rap->ns);
@@ -961,13 +935,13 @@ ipv6rs_handledata(__unused void *arg)
 
 handle_flag:
        if (rap->flags & ND_RA_FLAG_MANAGED) {
-               if (dhcp6_start(ifp, DH6S_INIT) == -1)
+               if (rap->lifetime && dhcp6_start(ifp, DH6S_INIT) == -1)
                        syslog(LOG_ERR, "dhcp6_start: %s: %m", ifp->name);
        } else if (rap->flags & ND_RA_FLAG_OTHER) {
-               if (dhcp6_start(ifp, DH6S_INFORM) == -1)
+               if (rap->lifetime && dhcp6_start(ifp, DH6S_INFORM) == -1)
                        syslog(LOG_ERR, "dhcp6_start: %s: %m", ifp->name);
        } else {
-               if (new_data)
+               if (rap->lifetime && new_data)
                        syslog(LOG_DEBUG, "%s: No DHCPv6 instruction in RA",
                            ifp->name);
                if (options & DHCPCD_TEST)