dnsmasq: add patch for DHCPv6 to honor IPv6 address on MAC address

This commit is contained in:
lean 2022-09-12 01:24:33 +08:00
parent e101ec4903
commit 168828486e
4 changed files with 169 additions and 3 deletions

View File

@ -20,7 +20,7 @@ config dnsmasq
#list notinterface lo
#list bogusnxdomain '64.94.110.11'
option localservice 1 # disable to allow DNS requests from non-local subnets
option filter_aaaa 0
option filter_aaaa 1
option cachesize 8000
option mini_ttl 3600
option ednspacket_max 1232

View File

@ -0,0 +1,166 @@
From 93ac8f9d469ff08d41170eb6934842b3626d5fdd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali@kernel.org>
Date: Wed, 23 Dec 2015 22:10:44 +0100
Subject: [PATCH] DHCPv6: Honor assigning IPv6 address based on MAC address
Currently IPv6 addresses are assigned to tuple (IAID, DUID). When system
changes IAID/DUID then old assigned IPv6 address cannot be reused, even
when in config file was DHCPv6 assignment based on MAC address (and not on
DUID).
IAID/DUID is changed when rebooting from one operating system to another;
or after reinstalling system. In reality it is normal that DUID of some
machine is changed, so people rather assign also IPv6 addresses based on
MAC address.
So assigning IPv6 based on MAC address in dnsmasq is currently semi-broken.
This patch tries to fix it and honors IPv6 config rules with MAC address,
to always assign particular IPv6 address to specific MAC address (when
configured). And ignores the fact if IAID/DUID was changed.
Normally IPv6 address should be assigned by IAID/DUID (which also state
DHCPv6 RFCs), but dnsmasq has already some support for assigning IPv6
address based on MAC address, when users configured in config file.
So this patch just tries to fix above problem for user configuration with
MAC addresses. It does not change assignment based on DUID.
---
src/rfc3315.c | 55 +++++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 47 insertions(+), 8 deletions(-)
--- a/src/rfc3315.c
+++ b/src/rfc3315.c
@@ -48,7 +48,7 @@ static int build_ia(struct state *state,
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_address(struct state *state, struct dhcp_config *config, struct in6_addr *addr);
static int config_valid(struct dhcp_config *config, struct dhcp_context *context, struct in6_addr *addr, struct state *state, time_t now);
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,
@@ -688,8 +688,13 @@ static int dhcp6_no_relay(struct state *
}
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(state, config, &req_addr))
continue; /* address leased elsewhere */
+ else if (state->mac_len && config &&
+ config_has_mac(config, state->mac, state->mac_len, state->mac_type) &&
+ match_netid(c->filter, solicit_tags, plain_range) &&
+ !config_implies(config, c, &req_addr))
+ continue; /* another static address is configured */
/* add address to output packet */
add_address(state, c, lease_time, ia_option, &min_time, &req_addr, now);
@@ -701,7 +706,10 @@ static int dhcp6_no_relay(struct state *
/* Suggest configured address(es) */
for (c = state->context; c; c = c->current)
- if (!(c->flags & CONTEXT_CONF_USED) &&
+ if ((!(c->flags & CONTEXT_CONF_USED) ||
+ (state->mac_len && config &&
+ config_has_mac(config, state->mac, state->mac_len, state->mac_type)
+ )) &&
match_netid(c->filter, solicit_tags, plain_range) &&
config_valid(config, c, &addr, state, now))
{
@@ -725,6 +733,11 @@ static int dhcp6_no_relay(struct state *
req_addr = ltmp->addr6;
if ((c = address6_available(state->context, &req_addr, solicit_tags, plain_range)))
{
+ if (state->mac_len && config &&
+ config_has_mac(config, state->mac, state->mac_len, state->mac_type) &&
+ match_netid(c->filter, solicit_tags, plain_range) &&
+ !config_implies(config, c, &req_addr))
+ continue; /* skip this lease because another static address is configured */
add_address(state, c, c->lease_time, NULL, &min_time, &req_addr, now);
mark_context_used(state, &req_addr);
get_context_tag(state, c);
@@ -859,7 +872,7 @@ static int dhcp6_no_relay(struct state *
put_opt6_string(_("address unavailable"));
end_opt6(o1);
}
- else if (!check_address(state, &req_addr))
+ else if (!check_address(state, config, &req_addr))
{
/* Address leased to another DUID/IAID */
o1 = new_opt6(OPTION6_STATUS_CODE);
@@ -989,6 +1002,16 @@ static int dhcp6_no_relay(struct state *
{
unsigned int lease_time;
+ /* check if another static address is preferred */
+ if (state->mac_len && config &&
+ config_has_mac(config, state->mac, state->mac_len, state->mac_type) &&
+ !config_implies(config, this_context, &req_addr))
+ {
+ preferred_time = valid_time = 0;
+ message = _("deprecated");
+ }
+ else
+ {
get_context_tag(state, this_context);
if (config_implies(config, this_context, &req_addr) && have_config(config, CONFIG_TIME))
@@ -1014,6 +1037,7 @@ static int dhcp6_no_relay(struct state *
if (preferred_time == 0)
message = _("deprecated");
+ }
address_assigned = 1;
}
@@ -1070,11 +1094,22 @@ static int dhcp6_no_relay(struct state *
ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
{
struct in6_addr req_addr;
+ struct dhcp_context *c;
+ int config_addr_ok = 1;
/* alignment */
memcpy(&req_addr, opt6_ptr(ia_option, 0), IN6ADDRSZ);
+
+ c = address6_valid(state->context, &req_addr, tagif, 1);
+
+ if (c && state->mac_len && config &&
+ config_has_mac(config, state->mac, state->mac_len, state->mac_type) &&
+ !config_implies(config, c, &req_addr))
+ {
+ config_addr_ok = 0;
+ }
- if (!address6_valid(state->context, &req_addr, tagif, 1))
+ if (!c || !config_addr_ok)
{
o1 = new_opt6(OPTION6_STATUS_CODE);
put_opt6_short(DHCP6NOTONLINK);
@@ -1692,11 +1727,15 @@ static void mark_config_used(struct dhcp
context->flags |= CONTEXT_CONF_USED;
}
-/* make sure address not leased to another CLID/IAID */
-static int check_address(struct state *state, struct in6_addr *addr)
+/* check that ipv6 address belongs to config with same mac address as in state or ipv6 address is not leased to another CLID/IAID */
+static int check_address(struct state *state, struct dhcp_config *config, struct in6_addr *addr)
{
struct dhcp_lease *lease;
+ if (state->mac_len && config &&
+ config_has_mac(config, state->mac, state->mac_len, state->mac_type))
+ return 1;
+
if (!(lease = lease6_find_by_addr(addr, 128, 0)))
return 1;
@@ -1773,7 +1812,7 @@ static int config_valid(struct dhcp_conf
{
setaddr6part(addr, addrpart+i);
- if (check_address(state, addr))
+ if (check_address(state, config, addr))
return 1;
}
}

View File

@ -2,7 +2,7 @@
choice
prompt "Binutils Version" if TOOLCHAINOPTS
default BINUTILS_USE_VERSION_2_34
default BINUTILS_USE_VERSION_2_37
help
Select the version of binutils you wish to use.

View File

@ -2,7 +2,6 @@ config BINUTILS_VERSION_2_32
bool
config BINUTILS_VERSION_2_34
default y if !TOOLCHAINOPTS
bool
config BINUTILS_VERSION_2_35_2
@ -12,6 +11,7 @@ config BINUTILS_VERSION_2_36_1
bool
config BINUTILS_VERSION_2_37
default y if !TOOLCHAINOPTS
bool
config BINUTILS_VERSION_2_38