Hello Simon and everyone, I am sending this patch on behalf of Tomáš Korbař, who worked on debugging the issue and even written a test [1] to verify it works. Test is written in our shell based beakerlib, but I think is readable enough even in basic form.
Currentdhcp-range does not work well in case DHCP client would refuse the offered address. When this happens, current dnsmasq does not even stop at maximal address specified. This change adds similar check like when no dhcp-sequential-ip is used. Tomáš tested it already, but would anyone mind testing it also? If there is no regression or need to adjust it, would you mind merging it? Thank you in advance! Cheers, Petr
1. https://gitlab.com/redhat/centos-stream/tests/dnsmasq/-/merge_requests/6 -- Petr Menšík Senior Software Engieer, RHEL Red Hat, https://www.redhat.com/ PGP: DFCF908DB7C87E8E529925BC4931CA5B6C9FC5CB
From 913472864bdcd5b7bb01c31ff27706b6dfbb99a2 Mon Sep 17 00:00:00 2001 From: Tomas Korbar <[email protected]> Date: Tue, 7 Oct 2025 19:12:00 +0200 Subject: [PATCH] Fix obeying dhcp-range if dhcp-sequential-ip and IPV6 is used Previously starting position for searching the next free address in IPV6 range was no checked whether it is in bounds. This commit adds modulo operation like when dhcp-sequential-ip is not used to ensure dnsmasq does not offer out of range address. --- src/dhcp6.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/dhcp6.c b/src/dhcp6.c index 482caf7d..99cc77b2 100644 --- a/src/dhcp6.c +++ b/src/dhcp6.c @@ -522,27 +522,26 @@ struct dhcp_context *address6_allocate(struct dhcp_context *context, unsigned c continue; else { + u64 range = 1 + addr6part(&c->end6) - addr6part(&c->start6); + u64 offset = c->addr_epoch; if (!temp_addr && option_bool(OPT_CONSEC_ADDR)) { /* seed is largest extant lease addr in this context, skip addresses equal to the number of addresses rejected by clients. This should avoid the same client being offered the same address after it has rjected it. */ - start = lease_find_max_addr6(c) + 1 + serial + c->addr_epoch; + offset += lease_find_max_addr6(c) - addr6part(&c->start6) + 1 + serial; if (c->addr_epoch) c->addr_epoch--; } else { - u64 range = 1 + addr6part(&c->end6) - addr6part(&c->start6); - u64 offset = j + c->addr_epoch; - - /* don't divide by zero if range is whole 2^64 */ - if (range != 0) - offset = offset % range; - - start = addr6part(&c->start6) + offset; + offset += j; } + /* don't divide by zero if range is whole 2^64 */ + if (range != 0) + offset = offset % range; + start = addr6part(&c->start6) + offset; /* iterate until we find a free address. */ addr = start; -- 2.51.0
_______________________________________________ Dnsmasq-discuss mailing list [email protected] https://lists.thekelleys.org.uk/cgi-bin/mailman/listinfo/dnsmasq-discuss
