dhcpv6: use stable IAID for IA_NA
authorPaul Donald <newtwen+github@gmail.com>
Thu, 18 Dec 2025 14:10:24 +0000 (15:10 +0100)
committerÁlvaro Fernández Rojas <noltari@gmail.com>
Thu, 18 Dec 2025 17:44:07 +0000 (18:44 +0100)
https://www.rfc-editor.org/rfc/rfc8415.html#section-12

   ........  The IAID is chosen by the client.  For any given use of an
   IA by the client, the IAID for that IA MUST be consistent across
   restarts of the DHCP client.  The client may maintain consistency by
   either storing the IAID in non-volatile storage or using an algorithm
   that will consistently produce the same IAID as long as the
   configuration of the client has not changed.

Signed-off-by: Paul Donald <newtwen+github@gmail.com>
Link: https://github.com/openwrt/odhcp6c/pull/140
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
src/dhcpv6.c
src/odhcp6c.h

index d8bb8be6a08b06689896d20961d385cf9881b3d4..97860b1809c15e7cf31f9dffa24e579545464af0 100644 (file)
@@ -262,6 +262,9 @@ static struct dhcpv6_stats dhcpv6_stats = {0};
 // config
 static struct config_dhcp* config_dhcp = NULL;
 
+// store unique ifname hash to use as IA->IAID
+static uint32_t ifname_hash_iaid = 0;
+
 static uint32_t ntohl_unaligned(const uint8_t *data)
 {
        uint32_t buf;
@@ -542,6 +545,12 @@ void dhcpv6_reset_stats(void)
        memset(&dhcpv6_stats, 0, sizeof(dhcpv6_stats));
 }
 
+uint32_t hash_ifname(const char *s) {
+       uint32_t h = 0;
+       while (*s) h = h * 31 + *s++;
+       return h;
+}
+
 int init_dhcpv6(const char *ifname)
 {
        config_dhcp = config_dhcp_get();
@@ -566,6 +575,8 @@ int init_dhcpv6(const char *ifname)
        if (ioctl(sock, SIOCGIFINDEX, &ifr) < 0)
                goto failure;
 
+       ifname_hash_iaid = hash_ifname(ifname);
+
        ifindex = ifr.ifr_ifindex;
 
        // Set the socket to non-blocking mode
@@ -838,7 +849,7 @@ static void dhcpv6_send(enum dhcpv6_msg req_msg_type, uint8_t trid[3], uint32_t
        struct dhcpv6_ia_hdr hdr_ia_na = {
                .type = htons(DHCPV6_OPT_IA_NA),
                .len = htons(sizeof(hdr_ia_na) - DHCPV6_OPT_HDR_SIZE),
-               .iaid = htonl(ifindex),
+               .iaid = htonl(ifname_hash_iaid),
                .t1 = 0,
                .t2 = 0,
        };
@@ -1392,7 +1403,7 @@ static int dhcpv6_handle_reply(enum dhcpv6_msg orig, _o_unused const int rc,
                                                continue;
 
                                        // Test ID
-                                       if (ia_hdr->iaid != htonl(ifindex) && otype == DHCPV6_OPT_IA_NA)
+                                       if (ia_hdr->iaid != htonl(ifname_hash_iaid) && otype == DHCPV6_OPT_IA_NA)
                                                continue;
 
                                        uint16_t code = DHCPV6_Success;
index aa73bbc2f10fb618f4d74496f08744df755e839b..c57f88517ee4e68ca1b0a1b8f4ca9a3b223b12a5 100644 (file)
@@ -540,6 +540,7 @@ struct odhcp6c_opt {
        const char *str;
 };
 
+uint32_t hash_ifname(const char *s);
 int init_dhcpv6(const char *ifname);
 int dhcpv6_get_ia_mode(void);
 int dhcpv6_promote_server_cand(void);