From: Roy Marples Date: Wed, 12 Jun 2013 10:58:28 +0000 (+0000) Subject: Ensure we have the correct type to send in our saved lease as the X-Git-Tag: v6.0.0~17 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8fdedf593b1b7bfa89a04975381462addd3b5e57;p=thirdparty%2Fdhcpcd.git Ensure we have the correct type to send in our saved lease as the 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. --- diff --git a/dhcp6.c b/dhcp6.c index afd1a801..7edd8333 100644 --- 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 b706ab2f..de5513e8 100644 --- 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 bd54414b..5a827af1 100644 --- 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 *, diff --git a/ipv6rs.c b/ipv6rs.c index 0ce4d985..0d54b4e5 100644 --- 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)