From: Roy Marples Date: Thu, 4 Apr 2013 21:59:02 +0000 (+0000) Subject: Add RELEASE support to DHCPv6 X-Git-Tag: v5.99.6~20 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=a42c42f8992a84cc7ef1c9a1d9231af062c212ea;p=thirdparty%2Fdhcpcd.git Add RELEASE support to DHCPv6 --- diff --git a/dhcp6.c b/dhcp6.c index e5a384f7..aabd53de 100644 --- a/dhcp6.c +++ b/dhcp6.c @@ -92,6 +92,7 @@ static const struct dhcp6_op dhcp6_ops[] = { { DHCP6_REBIND, "REBIND6" }, { DHCP6_CONFIRM, "CONFIRM6" }, { DHCP6_INFORMATION_REQ, "INFORM6" }, + { DHCP6_RELEASE, "RELEASE6" }, { 0, NULL } }; @@ -373,15 +374,17 @@ dhcp6_makemessage(struct interface *ifp) ifo = ifp->options; len = 0; si = NULL; - for (opt = dhcp6_opts; opt->option; opt++) { - if (!(opt->type & REQUEST || - has_option_mask(ifo->requestmask6, opt->option))) - continue; - len += sizeof(*u16); + if (state->state != DH6S_RELEASE) { + for (opt = dhcp6_opts; opt->option; opt++) { + if (!(opt->type & REQUEST || + has_option_mask(ifo->requestmask6, opt->option))) + continue; + len += sizeof(*u16); + } + if (len == 0) + len = sizeof(*u16) * 2; + len += sizeof(*o); } - if (len == 0) - len = sizeof(*u16) * 2; - len += sizeof(*o); len += sizeof(*state->send); len += sizeof(*o) + 14; /* clientid */ @@ -398,6 +401,8 @@ dhcp6_makemessage(struct interface *ifp) m = state->recv; ml = state->recv_len; /* FALLTHROUGH */ + case DH6S_RELEASE: + /* FALLTHROUGH */ case DH6S_RENEW: if (m == NULL) { m = state->new; @@ -463,6 +468,9 @@ dhcp6_makemessage(struct interface *ifp) case DH6S_INFORM: state->send->type = DHCP6_INFORMATION_REQ; break; + case DH6S_RELEASE: + state->send->type = DHCP6_RELEASE; + break; default: errno = EINVAL; free(state->send); @@ -550,23 +558,25 @@ dhcp6_makemessage(struct interface *ifp) } } - o = D6_NEXT_OPTION(o); - o->code = htons(D6_OPTION_ORO); - o->len = 0; - u16 = (uint16_t *)(void *)D6_OPTION_DATA(o); - for (opt = dhcp6_opts; opt->option; opt++) { - if (!(opt->type & REQUEST || - has_option_mask(ifo->requestmask6, opt->option))) - continue; - *u16++ = htons(opt->option); - o->len += sizeof(*u16); - } - if (o->len == 0) { - *u16++ = htons(D6_OPTION_DNS_SERVERS); - *u16++ = htons(D6_OPTION_DOMAIN_LIST); - o->len = sizeof(*u16) * 2; + if (state->send->type != DHCP6_RELEASE) { + o = D6_NEXT_OPTION(o); + o->code = htons(D6_OPTION_ORO); + o->len = 0; + u16 = (uint16_t *)(void *)D6_OPTION_DATA(o); + for (opt = dhcp6_opts; opt->option; opt++) { + if (!(opt->type & REQUEST || + has_option_mask(ifo->requestmask6, opt->option))) + continue; + *u16++ = htons(opt->option); + o->len += sizeof(*u16); + } + if (o->len == 0) { + *u16++ = htons(D6_OPTION_DNS_SERVERS); + *u16++ = htons(D6_OPTION_DOMAIN_LIST); + o->len = sizeof(*u16) * 2; + } + o->len = htons(o->len); } - o->len = htons(o->len); return 0; } @@ -758,6 +768,15 @@ dhcp6_sendconfirm(void *arg) dhcp6_sendmessage(arg, dhcp6_sendconfirm); } +/* +static void +dhcp6_sendrelease(void *arg) +{ + + dhcp6_sendmessage(arg, dhcp6_sendrelease); +} +*/ + static void dhcp6_startrenew(void *arg) { @@ -942,6 +961,30 @@ dhcp6_startexpire(void *arg) dhcp6_startdiscover(ifp); } +static void +dhcp6_startrelease(struct interface *ifp) +{ + struct dhcp6_state *state; + + state = D6_STATE(ifp); + state->state = DH6S_RELEASE; + state->start_uptime = uptime(); + state->RTC = 0; + state->IRT = REL_TIMEOUT; + state->MRT = 0; + state->MRC = REL_MAX_RC; + //state->MRCcallback = dhcp6_failrelease; + state->MRCcallback = NULL; + + if (dhcp6_makemessage(ifp) == -1) + syslog(LOG_ERR, "%s: dhcp6_makemessage: %m", ifp->name); + else + /* XXX: We should loop a few times + * Luckily RFC3315 section 18.1.6 says this is optional */ + //dhcp6_sendrelease(ifp); + dhcp6_sendmessage(ifp, NULL); +} + static int dhcp6_getstatus(const struct dhcp6_option *o) { const struct dhcp6_status *s; @@ -1877,6 +1920,10 @@ dhcp6_freedrop(struct interface *ifp, int drop, const char *reason) eloop_timeout_delete(NULL, ifp); state = D6_STATE(ifp); if (state) { + if (ifp->options->options & DHCPCD_RELEASE) { + dhcp6_startrelease(ifp); + unlink(state->leasefile); + } dhcp6_freedrop_addrs(ifp, drop); if (drop && state->new) { if (reason == NULL) diff --git a/dhcp6.h b/dhcp6.h index 217c4cd2..921dc7a2 100644 --- a/dhcp6.h +++ b/dhcp6.h @@ -135,7 +135,7 @@ struct dhcp6_status { #define DHCP6_RAND_MIN -100 #define DHCP6_RAND_MAX 100 - + enum DH6S { DH6S_INIT, DH6S_DISCOVER, @@ -147,7 +147,8 @@ enum DH6S { DH6S_INFORM, DH6S_RENEW_REQUESTED, DH6S_PROBE, - DH6S_DELEGATED + DH6S_DELEGATED, + DH6S_RELEASE }; struct dhcp6_state {