changeset 4279:cdffb0137daa draft

dhcp6: IAID is now unique for IA type RFC3315 is a bit ambigious about this. At the start it says that IAID is supposed to be unique across the client, but futher down it starts to mention that the IAID number space is unqiuie to the IA type. RFC3315bis clarifies it's unique for the client and IA type, so you can now have ia_na 1 and ia_pd 1.
author Roy Marples <roy@marples.name>
date Mon, 07 May 2018 21:20:26 +0100
parents 7263f7c073b4
children 16dd1b6b5e13
files src/dhcp6.c src/dhcpcd.c src/if-options.c
diffstat 3 files changed, 21 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/src/dhcp6.c	Mon May 07 15:01:46 2018 +0100
+++ b/src/dhcp6.c	Mon May 07 21:20:26 2018 +0100
@@ -2195,6 +2195,7 @@
 	uint8_t iaid[4];
 	char buf[sizeof(iaid) * 3];
 	struct ipv6_addr *ap;
+	struct if_ia *ifia;
 
 	if (l < sizeof(*m)) {
 		/* Should be impossible with guards at packet in
@@ -2248,8 +2249,9 @@
 		o.len = (uint16_t)(o.len - nl);
 
 		for (j = 0; j < ifo->ia_len; j++) {
-			if (memcmp(&ifo->ia[j].iaid, ia.iaid,
-			    sizeof(ia.iaid)) == 0)
+			ifia = &ifo->ia[j];
+			if (ifia->ia_type == o.code &&
+			    memcmp(ifia->iaid, ia.iaid, sizeof(ia.iaid)) == 0)
 				break;
 		}
 		if (j == ifo->ia_len &&
@@ -2261,13 +2263,6 @@
 			    buf, sizeof(buf)));
 			continue;
 		}
-		if ( j < ifo->ia_len && ifo->ia[j].ia_type != o.code) {
-			logerrx("%s: IAID %s: option type mismatch",
-			    ifp->name,
-			    hwaddr_ntoa(ia.iaid, sizeof(ia.iaid),
-			    buf, sizeof(buf)));
-			continue;
-		}
 
 		if (o.code != D6_OPTION_IA_TA) {
 			ia.t1 = ntohl(ia.t1);
--- a/src/dhcpcd.c	Mon May 07 15:01:46 2018 +0100
+++ b/src/dhcpcd.c	Mon May 07 21:20:26 2018 +0100
@@ -770,20 +770,23 @@
 }
 
 static void
-warn_iaid_conflict(struct interface *ifp, uint8_t *iaid)
+warn_iaid_conflict(struct interface *ifp, uint16_t ia_type, uint8_t *iaid)
 {
 	struct interface *ifn;
 	size_t i;
+	struct if_ia *ia;
 
 	TAILQ_FOREACH(ifn, ifp->ctx->ifaces, next) {
 		if (ifn == ifp || !ifn->active)
 			continue;
-		if (memcmp(ifn->options->iaid, iaid,
+		if (ia_type == 0 &&
+		    memcmp(ifn->options->iaid, iaid,
 		    sizeof(ifn->options->iaid)) == 0)
 			break;
 		for (i = 0; i < ifn->options->ia_len; i++) {
-			if (memcmp(&ifn->options->ia[i].iaid, iaid,
-			    sizeof(ifn->options->ia[i].iaid)) == 0)
+			ia = &ifn->options->ia[i];
+			if (ia->ia_type == ia_type &&
+			    memcmp(ia->iaid, iaid, sizeof(ia->iaid)) == 0)
 				break;
 		}
 	}
@@ -839,20 +842,21 @@
 	}
 
 	if (ifo->options & (DHCPCD_DUID | DHCPCD_IPV6)) {
+		struct if_ia *ia;
+
 		/* Report IAIDs */
 		loginfox("%s: IAID %s", ifp->name,
 		    hwaddr_ntoa(ifo->iaid, sizeof(ifo->iaid),
 		    buf, sizeof(buf)));
-		warn_iaid_conflict(ifp, ifo->iaid);
+		warn_iaid_conflict(ifp, 0, ifo->iaid);
 		for (i = 0; i < ifo->ia_len; i++) {
-			if (memcmp(ifo->iaid, ifo->ia[i].iaid,
-			    sizeof(ifo->iaid)))
-			{
-				loginfox("%s: IAID %s",
-				    ifp->name, hwaddr_ntoa(ifo->ia[i].iaid,
-				    sizeof(ifo->ia[i].iaid),
+			ia = &ifo->ia[i];
+			if (memcmp(ifo->iaid, ia->iaid, sizeof(ifo->iaid))) {
+				loginfox("%s: IA type %u IAID %s",
+				    ifp->name, ia->ia_type,
+				    hwaddr_ntoa(ia->iaid, sizeof(ia->iaid),
 				    buf, sizeof(buf)));
-				warn_iaid_conflict(ifp, ifo->ia[i].iaid);
+				warn_iaid_conflict(ifp, ia->ia_type, ia->iaid);
 			}
 		}
 	}
--- a/src/if-options.c	Mon May 07 15:01:46 2018 +0100
+++ b/src/if-options.c	Mon May 07 21:20:26 2018 +0100
@@ -1360,6 +1360,7 @@
 		for (sl = 0; sl < ifo->ia_len; sl++) {
 			if ((arg == NULL && !ifo->ia[sl].iaid_set) ||
 			    (arg != NULL && ifo->ia[sl].iaid_set &&
+			    ifo->ia[sl].ia_type == (uint16_t)i &&
 			    ifo->ia[sl].iaid[0] == iaid[0] &&
 			    ifo->ia[sl].iaid[1] == iaid[1] &&
 			    ifo->ia[sl].iaid[2] == iaid[2] &&
@@ -1369,10 +1370,6 @@
 				break;
 			}
 		}
-		if (ia && ia->ia_type != (uint16_t)i) {
-			logerrx("Cannot mix IA for the same IAID");
-			break;
-		}
 		if (ia == NULL) {
 			ia = reallocarray(ifo->ia,
 			    ifo->ia_len + 1, sizeof(*ifo->ia));