From: Roy Marples Date: Tue, 8 May 2018 11:27:42 +0000 (+0100) Subject: dhcp6: match IA type with request X-Git-Tag: v7.0.5~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7e717094d3ad5b9d84941010134e9c7179b253f8;p=thirdparty%2Fdhcpcd.git dhcp6: match IA type with request So we don't send IA_NA, IA_TA and IA_PD addresses in the IA_NA request if they all share the same IAID. While here, fix a bug where IA_TA addresses would append the DHCP6 unknown option 0 by mistakenly trying to put T1 and T2 timers in where there should be none. --- diff --git a/src/dhcp6.c b/src/dhcp6.c index 18fb6079..a557632e 100644 --- a/src/dhcp6.c +++ b/src/dhcp6.c @@ -98,6 +98,11 @@ struct dhcp6_ia_na { }; __CTASSERT(sizeof(struct dhcp6_ia_na) == 12); +struct dhcp6_ia_ta { + uint8_t iaid[4]; +}; +__CTASSERT(sizeof(struct dhcp6_ia_ta) == 4); + struct dhcp6_ia_addr { struct in6_addr addr; uint32_t pltime; @@ -629,6 +634,7 @@ dhcp6_makemessage(struct interface *ifp) int fqdn; struct dhcp6_ia_na ia_na; uint16_t ia_na_len; + struct if_ia *ifia; #ifdef AUTH uint16_t auth_len; #endif @@ -899,19 +905,29 @@ dhcp6_makemessage(struct interface *ifp) COPYIN1(D6_OPTION_RAPID_COMMIT, 0); for (l = 0; IA && l < ifo->ia_len; l++) { + ifia = &ifo->ia[l]; o_lenp = NEXTLEN; - ia_na_len = sizeof(ia_na); - memcpy(ia_na.iaid, ifo->ia[l].iaid, sizeof(ia_na.iaid)); + /* TA structure is the same as the others, + * it just lacks the T1 and T2 timers. + * These happen to be at the end of the struct, + * so we just don't copy them in. */ + if (ifia->ia_type == D6_OPTION_IA_TA) + ia_na_len = sizeof(struct dhcp6_ia_ta); + else + ia_na_len = sizeof(ia_na); + memcpy(ia_na.iaid, ifia->iaid, sizeof(ia_na.iaid)); ia_na.t1 = 0; ia_na.t2 = 0; - COPYIN(ifo->ia[l].ia_type, &ia_na, sizeof(ia_na)); + COPYIN(ifia->ia_type, &ia_na, ia_na_len); TAILQ_FOREACH(ap, &state->addrs, next) { if (ap->flags & IPV6_AF_STALE) continue; if (ap->prefix_vltime == 0 && !(ap->flags & IPV6_AF_REQUEST)) continue; - if (memcmp(ifo->ia[l].iaid, ap->iaid, sizeof(uint32_t))) + if (ap->ia_type != ifia->ia_type) + continue; + if (memcmp(ap->iaid, ifia->iaid, sizeof(ap->iaid))) continue; if (ap->ia_type == D6_OPTION_IA_PD) { #ifndef SMALL