From: Roy Marples Date: Mon, 10 Jun 2013 21:54:00 +0000 (+0000) Subject: If we fail to rebind a PD, drop the delegations. X-Git-Tag: v6.0.0~23 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=7523073337de373922c56a4bc2ac9f4342f73a19;p=thirdparty%2Fdhcpcd.git If we fail to rebind a PD, drop the delegations. --- diff --git a/dhcp6.c b/dhcp6.c index af0b5525..d297fd99 100644 --- a/dhcp6.c +++ b/dhcp6.c @@ -668,13 +668,18 @@ dhcp6_get_op(uint16_t type) } static void -dhcp6_freedrop_addrs(struct interface *ifp, int drop) +dhcp6_freedrop_addrs(struct interface *ifp, int drop, + const struct interface *ifd) { struct dhcp6_state *state; - struct ipv6_addr *ap; + struct ipv6_addr *ap, *apn; state = D6_STATE(ifp); - while ((ap = TAILQ_FIRST(&state->addrs))) { + 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); @@ -697,6 +702,16 @@ dhcp6_freedrop_addrs(struct interface *ifp, int drop) ipv6_buildroutes(); } +static void dhcp6_delete_delegates(struct interface *ifp) +{ + struct interface *ifp0; + + TAILQ_FOREACH(ifp0, ifaces, next) { + if (ifp0 != ifp) + dhcp6_freedrop_addrs(ifp0, 1, ifp); + } +} + static int dhcp6_sendmessage(struct interface *ifp, void (*callback)(void *)) { @@ -909,11 +924,10 @@ dhcp6_startdiscover(void *arg) struct interface *ifp; struct dhcp6_state *state; + syslog(LOG_INFO, "%s: soliciting a DHCPv6 lease", ifp->name); + ifp = arg; state = D6_STATE(ifp); - if (state->state == DH6S_REBIND) - syslog(LOG_ERR, "%s: failed to rebind DHCPv6, soliciting", - ifp->name); state->state = DH6S_DISCOVER; state->start_uptime = uptime(); state->RTC = 0; @@ -926,7 +940,7 @@ dhcp6_startdiscover(void *arg) state->new = NULL; state->new_len = 0; - dhcp6_freedrop_addrs(ifp, 0); + dhcp6_freedrop_addrs(ifp, 0, NULL); if (dhcp6_makemessage(ifp) == -1) syslog(LOG_ERR, "%s: dhcp6_makemessage: %m", ifp->name); @@ -940,10 +954,7 @@ dhcp6_failconfirm(void *arg) struct interface *ifp; ifp = arg; - if (ifp->options->ia_type != D6_OPTION_IA_PD) - syslog(LOG_ERR, - "%s: failed to confirm prior address", - ifp->name); + syslog(LOG_ERR, "%s: failed to confirm prior address", ifp->name); /* Section 18.1.2 says that we SHOULD use the last known * IP address(s) and lifetimes if we didn't get a reply. * I disagree with this. */ @@ -964,6 +975,20 @@ dhcp6_failrequest(void *arg) dhcp6_startdiscover(ifp); } +static void +dhcp6_failrebind(void *arg) +{ + struct interface *ifp; + + ifp = arg; + syslog(LOG_ERR, "%s: failed to rebind prior delegation", ifp->name); + dhcp6_delete_delegates(ifp); + /* Section 18.1.2 says that we SHOULD use the last known + * IP address(s) and lifetimes if we didn't get a reply. + * I disagree with this. */ + dhcp6_startdiscover(ifp); +} + static void dhcp6_startrebind(void *arg) { @@ -996,7 +1021,7 @@ dhcp6_startrebind(void *arg) /* RFC 3633 section 12.1 */ if (ifp->options->ia_type == D6_OPTION_IA_PD) - eloop_timeout_add_sec(CNF_MAX_RD, dhcp6_failconfirm, ifp); + eloop_timeout_add_sec(CNF_MAX_RD, dhcp6_failrebind, ifp); } @@ -1047,6 +1072,8 @@ dhcp6_startinform(struct interface *ifp) { struct dhcp6_state *state; + syslog(LOG_INFO, "%s: requesting DHCPv6 information", ifp->name); + state = D6_STATE(ifp); state->state = DH6S_INFORM; state->start_uptime = uptime(); @@ -1071,7 +1098,8 @@ dhcp6_startexpire(void *arg) eloop_timeout_delete(dhcp6_sendrebind, ifp); syslog(LOG_ERR, "%s: DHCPv6 lease expired", ifp->name); - dhcp6_freedrop_addrs(ifp, 1); + dhcp6_freedrop_addrs(ifp, 1, NULL); + dhcp6_delete_delegates(ifp); script_runreason(ifp, "EXPIRE6"); state = D6_CSTATE(ifp); unlink(state->leasefile); @@ -1438,7 +1466,7 @@ dhcp6_findia(struct interface *ifp, const uint8_t *d, size_t l, if (dhcp6_checkstatusok(ifp, NULL, p, ol) == -1) return -1; if (ifo->ia_type == D6_OPTION_IA_PD) { - dhcp6_freedrop_addrs(ifp, 0); + dhcp6_freedrop_addrs(ifp, 0, NULL); if (dhcp6_findpd(ifp, iaid, p, ol) == 0) { syslog(LOG_ERR, "%s: %s: DHCPv6 REPLY missing Prefix", @@ -1560,7 +1588,7 @@ dhcp6_readlease(struct interface *ifp) return bytes; ex: - dhcp6_freedrop_addrs(ifp, 0); + dhcp6_freedrop_addrs(ifp, 0, NULL); free(state->new); state->new = NULL; state->new_len = 0; @@ -2249,10 +2277,6 @@ dhcp6_start1(void *arg) add_option_mask(ifo->requestmask6, D6_OPTION_FQDN); } - syslog(LOG_INFO, "%s: %s", ifp->name, - state->state == DH6S_INFORM ? - "requesting DHCPv6 information" : - "soliciting a DHCPv6 address"); if (state->state == DH6S_INFORM) dhcp6_startinform(ifp); else @@ -2333,7 +2357,7 @@ dhcp6_freedrop(struct interface *ifp, int drop, const char *reason) dhcp6_startrelease(ifp); unlink(state->leasefile); } - dhcp6_freedrop_addrs(ifp, drop); + dhcp6_freedrop_addrs(ifp, drop, NULL); if (drop && state->new) { if (reason == NULL) reason = "STOP6";