]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
dhcp6: IAID is now unique for IA type
authorRoy Marples <roy@marples.name>
Mon, 7 May 2018 20:20:26 +0000 (21:20 +0100)
committerRoy Marples <roy@marples.name>
Mon, 7 May 2018 20:20:26 +0000 (21:20 +0100)
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
src/dhcpcd.c
src/if-options.c

index 37be20788ddf002a0bc1c28b2a1611860e402c66..18fb6079b3930401d42b8f79d6a38681aca32676 100644 (file)
@@ -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);
index 4944c00f537307b3a04817ad184df30f0a6ccce0..2483e38c3cbe03315d6c4e982b03fee1113d60bc 100644 (file)
@@ -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);
                        }
                }
        }
index 5943e70046187893fd8adceb331beaef148c2753..b017bad53a42b218a21daf1cc50122dd2e627760 100644 (file)
@@ -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));