summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoy Marples <roy@marples.name>2018-05-08 12:27:42 +0100
committerRoy Marples <roy@marples.name>2018-05-08 12:27:42 +0100
commit7e717094d3ad5b9d84941010134e9c7179b253f8 (patch)
tree15f21c944084dbd2aeb3f0a428149adc1bf88359
parent766ce48c95982388ad9c23bde67678dde26354f1 (diff)
downloaddhcpcd-7e717094d3ad5b9d84941010134e9c7179b253f8.tar.xz
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.
-rw-r--r--src/dhcp6.c24
1 files changed, 20 insertions, 4 deletions
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