From cf03c8afd0fce4199c9d682fdd6a70a2da0f06ee Mon Sep 17 00:00:00 2001 From: luoguocui Date: Tue, 30 Sep 2025 03:33:21 +0000 Subject: [PATCH] adapt bugfix allow binding mac with ipv6 --- ...t-bugfix-allow-binding-mac-with-ipv6.patch | 194 ++++++++++++++++++ ...-DHCPCONFIRM-messages-wrong-message-.patch | 72 +++++++ dnsmasq.spec | 17 +- 3 files changed, 282 insertions(+), 1 deletion(-) create mode 100644 adapt-bugfix-allow-binding-mac-with-ipv6.patch create mode 100644 backport-Fix-bad-reply-to-DHCPCONFIRM-messages-wrong-message-.patch diff --git a/adapt-bugfix-allow-binding-mac-with-ipv6.patch b/adapt-bugfix-allow-binding-mac-with-ipv6.patch new file mode 100644 index 0000000..2ff95f3 --- /dev/null +++ b/adapt-bugfix-allow-binding-mac-with-ipv6.patch @@ -0,0 +1,194 @@ +From 16e2e5fd2ad49884b4dab5d53b8c4c16654f9d97 Mon Sep 17 00:00:00 2001 +From: luoguocui +Date: Tue, 30 Sep 2025 03:11:25 +0000 +Subject: [PATCH] adapt bugfix allow binding mac with ipv6 + +v1: + +In R8 and eariler versions, bugfix-allow-binding-mac-with-ipv6.patch +replaces check_address with check_and_try_preempte_address. +In the R9 version, the community adds check_address to config_valid. +Howerver, the adaptation is wrong. +As a result, dnsmasq always executes check_address instead of check_and_try_preempte_address. +Then, dhcp6 does not support lease preemption in scenarieos with the same Mac address but different duid. +This patch addapt correctly. + +v2: +Fix reply confirm packet when binding-mac-with-ipv6 on. +When dnsmasq processes the Confirm packet with binding-mac-with-ipv6 on, +if the packet falls into an abnormal branch, dnsmasq replies with an confirm packet. This issue has been fixed. +--- + src/rfc3315.c | 77 ++++++++++++++++++--------------------------------- + 1 file changed, 27 insertions(+), 50 deletions(-) + +diff --git a/src/rfc3315.c b/src/rfc3315.c +index 9bdb940..f253347 100644 +--- a/src/rfc3315.c ++++ b/src/rfc3315.c +@@ -48,9 +48,8 @@ static int build_ia(struct state *state, int *t1cntr); + static void end_ia(int t1cntr, unsigned int min_time, int do_fuzz); + static void mark_context_used(struct state *state, struct in6_addr *addr); + static void mark_config_used(struct dhcp_context *context, struct in6_addr *addr); +-static int check_address(struct state *state, struct in6_addr *addr); +-static int check_and_try_preempte_address(struct state *state, struct in6_addr *addr, time_t now, struct dhcp_config *config); +-static int config_valid(struct dhcp_config *config, struct dhcp_context *context, struct in6_addr *addr, struct state *state, time_t now); ++static int check_address(struct dhcp_config *config, struct state *state, struct in6_addr *addr, time_t now, int preempte); ++static int config_valid(struct dhcp_config *config, struct dhcp_context *context, struct in6_addr *addr, struct state *state, time_t now, int preempte); + static struct addrlist *config_implies(struct dhcp_config *config, struct dhcp_context *context, struct in6_addr *addr); + static void add_address(struct state *state, struct dhcp_context *context, unsigned int lease_time, void *ia_option, + unsigned int *min_time, struct in6_addr *addr, time_t now); +@@ -681,7 +680,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, unsigned char *inbu + /* If the client asks for an address on the same network as a configured address, + offer the configured address instead, to make moving to newly-configured + addresses automatic. */ +- if (!(c->flags & CONTEXT_CONF_USED) && config_valid(config, c, &addr, state, now)) ++ if (!(c->flags & CONTEXT_CONF_USED) && config_valid(config, c, &addr, state, now, 0)) + { + req_addr = addr; + mark_config_used(c, &addr); +@@ -690,7 +689,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, unsigned char *inbu + } + else if (!(c = address6_available(state->context, &req_addr, solicit_tags, plain_range))) + continue; /* not an address we're allowed */ +- else if (!check_address(state, &req_addr)) ++ else if (!check_address(config, state, &req_addr, now, 0)) + continue; /* address leased elsewhere */ + + /* add address to output packet */ +@@ -705,8 +704,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, unsigned char *inbu + for (c = state->context; c; c = c->current) + if (!(c->flags & CONTEXT_CONF_USED) && + match_netid(c->filter, solicit_tags, plain_range) && +- config_valid(config, c, &addr, state, now) && +- check_and_try_preempte_address(state, &addr, now, config)) ++ config_valid(config, c, &addr, state, now, 1)) + { + mark_config_used(state->context, &addr); + if (have_config(config, CONFIG_TIME)) +@@ -862,7 +860,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, unsigned char *inbu + put_opt6_string(_("address unavailable")); + end_opt6(o1); + } +- else if (!check_address(state, &req_addr)) ++ else if (!check_address(config, state, &req_addr, now, 0)) + { + /* Address leased to another DUID/IAID */ + o1 = new_opt6(OPTION6_STATUS_CODE); +@@ -1076,11 +1074,13 @@ static int dhcp6_no_relay(struct state *state, int msg_type, unsigned char *inbu + } + /* requires all mac has binding ipv6 address. */ + if (find_bind == 0) { +- o1 = new_opt6(OPTION6_STATUS_CODE); ++ bad_addr = 1; ++ log6_quiet(state, "DHCPREPLY", NULL, _("confirm failed, no binding found")); ++ o1 = new_opt6(OPTION6_STATUS_CODE); + put_opt6_short(DHCP6NOTONLINK); + put_opt6_string(_("confirm failed, no binding found")); + end_opt6(o1); +- return 1; ++ break; + } + } + +@@ -1107,13 +1107,10 @@ static int dhcp6_no_relay(struct state *state, int msg_type, unsigned char *inbu + good_addr = 1; + log6_quiet(state, "DHCPREPLY", &req_addr, state->hostname); + } +- if(daemon->bind_mac_with_ip6) { ++ if(daemon->bind_mac_with_ip6 && good_addr) { + if (!is_same_net6(&req_addr, &find_config->addr6, 128)) { +- o1 = new_opt6(OPTION6_STATUS_CODE); +- put_opt6_short(DHCP6NOTONLINK); +- put_opt6_string(_("confirm failed, not binding to this address")); +- end_opt6(o1); +- return 1; ++ bad_addr = 1; ++ log6_quiet(state, "DHCPREPLY", &req_addr, _("confirm failed, not binding to this address")); + } + } + } +@@ -1318,37 +1315,6 @@ static int dhcp6_no_relay(struct state *state, int msg_type, unsigned char *inbu + + } + +-static int check_and_try_preempte_address(struct state *state, struct in6_addr *addr, time_t now, struct dhcp_config *config) +-{ +- struct dhcp_lease *lease; +- +- if (!(lease = lease6_find_by_addr(addr, 128, 0))) +- { +- return 1; +- } +- +- +- if(daemon->bind_mac_with_ip6) { +- // break rfc3315 here +- // bind mac address with a lease +- if ((state->mac) && !(config->flags & CONFIG_CLID) && +- config_has_mac(config, state->mac, state->mac_len, state->mac_type)) { +- lease_prune(lease, now); +- return 1; +- } +- } +- +- // what rfc3315 do +- if (lease->clid_len != state->clid_len || +- memcmp(lease->clid, state->clid, state->clid_len) != 0 || +- lease->iaid != state->iaid) +- { +- return 0; +- } +- +- return 1; +-} +- + static struct dhcp_netid *add_options(struct state *state, int do_refresh) + { + void *oro; +@@ -1759,13 +1725,24 @@ static void mark_config_used(struct dhcp_context *context, struct in6_addr *addr + } + + /* make sure address not leased to another CLID/IAID */ +-static int check_address(struct state *state, struct in6_addr *addr) ++static int check_address(struct dhcp_config *config, struct state *state, struct in6_addr *addr, time_t now, int preempte) + { + struct dhcp_lease *lease; + + if (!(lease = lease6_find_by_addr(addr, 128, 0))) + return 1; ++ ++ if (preempte && daemon->bind_mac_with_ip6) { ++ // break rfc3315 here ++ // bind mac address with a lease ++ if ((state->mac) && !(config->flags & CONFIG_CLID) && ++ config_has_mac(config, state->mac, state->mac_len, state->mac_type)) { ++ lease_prune(lease, now); ++ return 1; ++ } ++ } + ++ // what rfc3315 do + if (lease->clid_len != state->clid_len || + memcmp(lease->clid, state->clid, state->clid_len) != 0 || + lease->iaid != state->iaid) +@@ -1805,7 +1782,7 @@ static struct addrlist *config_implies(struct dhcp_config *config, struct dhcp_c + return NULL; + } + +-static int config_valid(struct dhcp_config *config, struct dhcp_context *context, struct in6_addr *addr, struct state *state, time_t now) ++static int config_valid(struct dhcp_config *config, struct dhcp_context *context, struct in6_addr *addr, struct state *state, time_t now, int preempte) + { + u64 addrpart, i, addresses; + struct addrlist *addr_list; +@@ -1839,7 +1816,7 @@ static int config_valid(struct dhcp_config *config, struct dhcp_context *context + { + setaddr6part(addr, addrpart+i); + +- if (check_address(state, addr)) ++ if (check_address(config, state, addr, now, preempte)) + return 1; + } + } +-- +2.33.0 + diff --git a/backport-Fix-bad-reply-to-DHCPCONFIRM-messages-wrong-message-.patch b/backport-Fix-bad-reply-to-DHCPCONFIRM-messages-wrong-message-.patch new file mode 100644 index 0000000..c8d7ae2 --- /dev/null +++ b/backport-Fix-bad-reply-to-DHCPCONFIRM-messages-wrong-message-.patch @@ -0,0 +1,72 @@ +From 3868066085f4f73055d303ad2af59ad66245cf27 Mon Sep 17 00:00:00 2001 +From: Simon Kelley +Date: Wed, 11 Oct 2023 22:33:17 +0100 +Subject: [PATCH] Fix bad reply to DHCPCONFIRM messages (wrong message type). + +Thanks to renmingshuai for +spotting the error, and making the initial patch. + +Reference:https://thekelleys.org.uk/gitweb/?p=dnsmasq.git;a=patch;h=3868066085f4 +Conflict:allow binding-mac-with-ipv6 +--- + src/rfc3315.c | 23 +++++++++++------------ + 1 file changed, 11 insertions(+), 12 deletions(-) + +diff --git a/src/rfc3315.c b/src/rfc3315.c +index cdb4b64..9bdb940 100644 +--- a/src/rfc3315.c ++++ b/src/rfc3315.c +@@ -1057,7 +1057,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, unsigned char *inbu + + case DHCP6CONFIRM: + { +- int good_addr = 0; ++ int good_addr = 0, bad_addr = 0; + int find_bind = 0; + struct dhcp_config *find_config = NULL; + +@@ -1099,12 +1099,13 @@ static int dhcp6_no_relay(struct state *state, int msg_type, unsigned char *inbu + + if (!address6_valid(state->context, &req_addr, tagif, 1)) + { +- o1 = new_opt6(OPTION6_STATUS_CODE); +- put_opt6_short(DHCP6NOTONLINK); +- put_opt6_string(_("confirm failed")); +- end_opt6(o1); +- log6_quiet(state, "DHCPREPLY", &req_addr, _("confirm failed")); +- return 1; ++ bad_addr = 1; ++ log6_quiet(state, "DHCPREPLY", &req_addr, _("confirm failed")); ++ } ++ else ++ { ++ good_addr = 1; ++ log6_quiet(state, "DHCPREPLY", &req_addr, state->hostname); + } + if(daemon->bind_mac_with_ip6) { + if (!is_same_net6(&req_addr, &find_config->addr6, 128)) { +@@ -1115,18 +1116,16 @@ static int dhcp6_no_relay(struct state *state, int msg_type, unsigned char *inbu + return 1; + } + } +- good_addr = 1; +- log6_quiet(state, "DHCPREPLY", &req_addr, state->hostname); + } + } + + /* No addresses, no reply: RFC 3315 18.2.2 */ +- if (!good_addr) ++ if (!good_addr && !bad_addr) + return 0; + + o1 = new_opt6(OPTION6_STATUS_CODE); +- put_opt6_short(DHCP6SUCCESS ); +- put_opt6_string(_("all addresses still on link")); ++ put_opt6_short(bad_addr ? DHCP6NOTONLINK : DHCP6SUCCESS); ++ put_opt6_string(bad_addr ? (_("confirm failed")) : (_("all addresses still on link"))); + end_opt6(o1); + break; + } +-- +2.33.0 + diff --git a/dnsmasq.spec b/dnsmasq.spec index 5e7ce94..ca7c9de 100644 --- a/dnsmasq.spec +++ b/dnsmasq.spec @@ -1,6 +1,6 @@ Name: dnsmasq Version: 2.86 -Release: 10 +Release: 12 Summary: Dnsmasq provides network infrastructure for small networks License: GPLv2 or GPLv3 URL: http://www.thekelleys.org.uk/dnsmasq/ @@ -51,6 +51,9 @@ Patch40: backport-CVE-2023-49441-Fix-standalone-SHA256-implementation.pat Patch41: backport-Fix-crash-when-reloading-DHCP-config-on-SIGHUP.patch Patch42: backport-Fix-out-of-bounds-heap-read-in-order_qsort.patch Patch43: backport-Fix-buffer-overflow-when-configured-lease-change-scr.patch +Patch44: backport-Fix-bad-reply-to-DHCPCONFIRM-messages-wrong-message-.patch + +Patch9000: adapt-bugfix-allow-binding-mac-with-ipv6.patch BuildRequires: gcc BuildRequires: dbus-devel pkgconfig libidn2-devel nettle-devel systemd @@ -140,6 +143,18 @@ install -Dpm644 %{SOURCE2} $RPM_BUILD_ROOT%{_sysusersdir}/dnsmasq.conf %{_mandir}/man8/dnsmasq* %changelog +* Tue Sep 30 2025 luoguocui - 2.86-12 +- Type:bugfix +- CVE: +- SUG:NA +- DESC:adapt bugfix allow binding mac with ipv6 + +* Tue Sep 30 2025 luoguocui - 2.86-11 +- Type:bugfix +- CVE: +- SUG:NA +- DESC:Fix bad reply to DHCPCONFIRM messages (wrong message type). + * Thu Dec 12 2024 huyizhen - 2.86-10 - Type:bugfix - CVE: -- Gitee