changeset 2264:dd9d8cc5871a draft

Support RECONFIGURE DHCPv6 messages.
author Roy Marples <roy@marples.name>
date Fri, 31 Jan 2014 14:25:18 +0000
parents f60ab8a8fb05
children f0ed6a59297f
files dhcp6.c dhcp6.h
diffstat 2 files changed, 74 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/dhcp6.c	Fri Jan 31 12:45:55 2014 +0000
+++ b/dhcp6.c	Fri Jan 31 14:25:18 2014 +0000
@@ -418,6 +418,8 @@
 
 		if (fqdn != FQDN_DISABLE)
 			len += sizeof(*o) + 1 + encode_rfc1035(hostname, NULL);
+
+		len += sizeof(*o); /* Reconfigure Accept */
 	}
 
 	len += sizeof(*state->send);
@@ -629,7 +631,7 @@
 		}
 	}
 
-	if (state->send->type !=  DHCP6_RELEASE) {
+	if (state->send->type != DHCP6_RELEASE) {
 		if (fqdn != FQDN_DISABLE) {
 			o = D6_NEXT_OPTION(o);
 			o->code = htons(D6_OPTION_FQDN);
@@ -651,6 +653,10 @@
 			o->len = htons(l + 1);
 		}
 
+		o = D6_NEXT_OPTION(o);
+		o->code = htons(D6_OPTION_RECONF_ACCEPT);
+		o->len = 0;
+
 		if (n_options) {
 			o = D6_NEXT_OPTION(o);
 			o->code = htons(D6_OPTION_ORO);
@@ -2048,7 +2054,7 @@
 	const char *sfrom, *op;
 	struct dhcp6_message *r;
 	struct dhcp6_state *state;
-	const struct dhcp6_option *o;
+	const struct dhcp6_option *o, *auth;
 	const struct dhcp_opt *opt;
 	const struct if_options *ifo;
 	struct ipv6_addr *ap;
@@ -2112,9 +2118,10 @@
 		return;
 
 	r = (struct dhcp6_message *)rcvhdr.msg_iov[0].iov_base;
-	if (r->xid[0] != state->send->xid[0] ||
+	if (r->type != DHCP6_RECONFIGURE &&
+	    (r->xid[0] != state->send->xid[0] ||
 	    r->xid[1] != state->send->xid[1] ||
-	    r->xid[2] != state->send->xid[2])
+	    r->xid[2] != state->send->xid[2]))
 	{
 		syslog(LOG_DEBUG,
 		    "%s: wrong xid 0x%02x%02x%02x"
@@ -2155,11 +2162,11 @@
 	}
 
 	/* Authenticate the message */
-	o = dhcp6_getmoption(D6_OPTION_AUTH, r, len);
-	if (o) {
+	auth = dhcp6_getmoption(D6_OPTION_AUTH, r, len);
+	if (auth) {
 		if (dhcp_auth_validate(&state->auth, &ifo->auth,
 		    (uint8_t *)r, len, 6, r->type,
-		    D6_COPTION_DATA(o), ntohs(o->len)) == NULL)
+		    D6_COPTION_DATA(auth), ntohs(auth->len)) == NULL)
 		{
 			syslog(LOG_DEBUG, "dhcp_auth_validate: %m");
 			syslog(LOG_ERR, "%s: authentication failed from %s",
@@ -2238,6 +2245,63 @@
 		if (dhcp6_validatelease(ifp, r, len, sfrom) == -1)
 			return;
 		break;
+	case DHCP6_RECONFIGURE:
+		if (auth == NULL) {
+			syslog(LOG_ERR,
+			    "%s: unauthenticated Force Renew from %s",
+			    ifp->name, sfrom);
+			return;
+		}
+		if (state->state != DH6S_BOUND &&
+		    state->state != DH6S_INFORMED)
+		{
+			syslog(LOG_DEBUG,
+			    "%s: not bound, ignoring Force Renew from %s",
+			    ifp->name, sfrom);
+			return;
+		}
+		syslog(LOG_INFO, "%s: Force Renew from %s", ifp->name, sfrom);
+		o = dhcp6_getmoption(D6_OPTION_RECONF_MSG, r, len);
+		if (o == NULL) {
+			syslog(LOG_ERR,
+			    "%s: missing Reconfigure Message option",
+			    ifp->name);
+			return;
+		}
+		if (ntohs(o->len) != 1) {
+			syslog(LOG_ERR,
+			    "%s: missing Reconfigure Message type",
+			    ifp->name);
+			return;
+		}
+		switch(*D6_COPTION_DATA(o)) {
+		case DHCP6_RENEW:
+			if (state->state != DH6S_BOUND) {
+				syslog(LOG_ERR,
+				    "%s: not bound, ignoring Force Renew",
+				    ifp->name);
+				return;
+			}
+			eloop_timeout_delete(dhcp6_startrenew, ifp);
+			dhcp6_startrenew(ifp);
+			break;
+		case DHCP6_INFORMATION_REQ:
+			if (state->state != DH6S_INFORMED) {
+				syslog(LOG_ERR,
+				    "%s: not informed, ignoring Force Renew",
+				    ifp->name);
+				return;
+			}
+			eloop_timeout_delete(dhcp6_sendinform, ifp);
+			dhcp6_startinform(ifp);
+			break;
+		default:
+			syslog(LOG_ERR,
+			    "%s: unsupported Reconfigure Message type",
+			    ifp->name);
+			return;
+		}
+		break;
 	default:
 		syslog(LOG_ERR, "%s: invalid DHCP6 type %s (%d)",
 		    ifp->name, op, r->type);
--- a/dhcp6.h	Fri Jan 31 12:45:55 2014 +0000
+++ b/dhcp6.h	Fri Jan 31 14:25:18 2014 +0000
@@ -67,6 +67,9 @@
 #define D6_OPTION_RAPID_COMMIT		14
 #define D6_OPTION_VENDOR_CLASS		16
 #define D6_OPTION_VENDOR_OPTS		17
+#define D6_OPTION_INTERFACE_ID		18
+#define D6_OPTION_RECONF_MSG		19
+#define D6_OPTION_RECONF_ACCEPT		20
 #define D6_OPTION_SIP_SERVERS_NAME	21
 #define D6_OPTION_SIP_SERVERS_ADDRESS	22
 #define D6_OPTION_DNS_SERVERS		23