summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Donald2025-12-18 14:10:24 +0000
committerÁlvaro Fernández Rojas2025-12-18 17:46:53 +0000
commit5ab3203875ad938ea85f6d0ceebdff113c355656 (patch)
treeda6ac2ae1e291ec314124b46f66b7cd76b4eed20
parent29922b7fb4974bbd475e5f76569cad81989169cc (diff)
downloadodhcp6c-5ab3203875ad938ea85f6d0ceebdff113c355656.tar.gz
dhcpv6: use stable IAID for IA_NA
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. (cherry picked from commit 9a4d6fe802d21e4fc1b84f7d55b5c3c23e71d6ba) 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>
-rw-r--r--src/dhcpv6.c15
-rw-r--r--src/odhcp6c.h1
2 files changed, 14 insertions, 2 deletions
diff --git a/src/dhcpv6.c b/src/dhcpv6.c
index d8bb8be..97860b1 100644
--- a/src/dhcpv6.c
+++ b/src/dhcpv6.c
@@ -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;
diff --git a/src/odhcp6c.h b/src/odhcp6c.h
index aa73bbc..c57f885 100644
--- a/src/odhcp6c.h
+++ b/src/odhcp6c.h
@@ -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);