changeset 1900:c6cc0f957f86 draft

Add RELEASE support to DHCPv6
author Roy Marples <roy@marples.name>
date Thu, 04 Apr 2013 21:59:02 +0000
parents 715ffed82bb6
children 5ebd3a527c2b
files dhcp6.c dhcp6.h
diffstat 2 files changed, 74 insertions(+), 26 deletions(-) [+]
line wrap: on
line diff
--- a/dhcp6.c	Thu Apr 04 21:58:51 2013 +0000
+++ b/dhcp6.c	Thu Apr 04 21:59:02 2013 +0000
@@ -92,6 +92,7 @@
 	{ DHCP6_REBIND, "REBIND6" },
 	{ DHCP6_CONFIRM, "CONFIRM6" },
 	{ DHCP6_INFORMATION_REQ, "INFORM6" },
+	{ DHCP6_RELEASE, "RELEASE6" },
 	{ 0, NULL }
 };
 
@@ -373,15 +374,17 @@
 	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 @@
 		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 @@
 	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 @@
 		}
 	}
 
-	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 (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);
 	}
-	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);
 
 	return 0;
 }
@@ -758,6 +768,15 @@
 	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_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 @@
 	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)
--- a/dhcp6.h	Thu Apr 04 21:58:51 2013 +0000
+++ b/dhcp6.h	Thu Apr 04 21:59:02 2013 +0000
@@ -135,7 +135,7 @@
 
 #define DHCP6_RAND_MIN		-100
 #define DHCP6_RAND_MAX		100
- 
+
 enum DH6S {
 	DH6S_INIT,
 	DH6S_DISCOVER,
@@ -147,7 +147,8 @@
 	DH6S_INFORM,
 	DH6S_RENEW_REQUESTED,
 	DH6S_PROBE,
-	DH6S_DELEGATED
+	DH6S_DELEGATED,
+	DH6S_RELEASE
 };
 
 struct dhcp6_state {