From 766ce48c95982388ad9c23bde67678dde26354f1 Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Mon, 7 May 2018 21:20:26 +0100 Subject: [PATCH] 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. --- src/dhcp6.c | 13 ++++--------- src/dhcpcd.c | 28 ++++++++++++++++------------ src/if-options.c | 5 +---- 3 files changed, 21 insertions(+), 25 deletions(-) diff --git a/src/dhcp6.c b/src/dhcp6.c index 37be2078..18fb6079 100644 --- a/src/dhcp6.c +++ b/src/dhcp6.c @@ -2195,6 +2195,7 @@ dhcp6_findia(struct interface *ifp, struct dhcp6_message *m, size_t l, 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 @@ dhcp6_findia(struct interface *ifp, struct dhcp6_message *m, size_t l, 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 @@ dhcp6_findia(struct interface *ifp, struct dhcp6_message *m, size_t l, 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); diff --git a/src/dhcpcd.c b/src/dhcpcd.c index 4944c00f..2483e38c 100644 --- a/src/dhcpcd.c +++ b/src/dhcpcd.c @@ -770,20 +770,23 @@ dhcpcd_handlecarrier(struct dhcpcd_ctx *ctx, int carrier, unsigned int flags, } 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 @@ dhcpcd_startinterface(void *arg) } 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); } } } diff --git a/src/if-options.c b/src/if-options.c index 5943e700..b017bad5 100644 --- a/src/if-options.c +++ b/src/if-options.c @@ -1360,6 +1360,7 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo, 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 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo, 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)); -- 2.47.2