代码拉取完成,页面将自动刷新
From 271510e5f7c2130ad4b7e33186e47daf0d3d2d30 Mon Sep 17 00:00:00 2001
From: huyizhen <huyizhen2@huawei.com>
Date: Fri, 28 Feb 2025 14:38:44 +0800
Subject: [PATCH] allow binding mac with ip6
Bind the IPv6 address to the MAC address of the client.
This command is used to solve the problem that the client cannot obtain an IPv6 address
after the system is reinstalled. If this parameter is not specified, the client duid changes
and cannot obtain the original IPv6 address. After this parameter is added, even if the DUID
of the client changes, the client can still obtain the bound IPv6 address.
Description:
This feature conflicts with the RFC 3315 standard and applies only to private networks.
In addition, all client MAC addresses and IPv6 addresses must be bound in one-to-one mode
using --dhcp-host.
Combine bugfix-allow-binding-mac-with-ipv6.patch
bugfix-deal-with-CONFRIM-when-binding-mac-with-ipv6.patch
to allow-binding-mac-with-ip6.patch
---
src/dnsmasq.c | 1 +
src/dnsmasq.h | 4 +++-
src/option.c | 3 +++
src/rfc3315.c | 61 ++++++++++++++++++++++++++++++++++++++++++---------
4 files changed, 58 insertions(+), 11 deletions(-)
diff --git a/src/dnsmasq.c b/src/dnsmasq.c
index f3d87cd..3609106 100644
--- a/src/dnsmasq.c
+++ b/src/dnsmasq.c
@@ -281,6 +281,7 @@ int main (int argc, char **argv)
{
daemon->doing_ra = option_bool(OPT_RA);
+ daemon->bind_mac_with_ip6 = option_bool(OPT_BIND_MAC_IP6);
for (context = daemon->dhcp6; context; context = context->next)
{
if (context->flags & CONTEXT_DHCP)
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index e455c3f..ef32f06 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -282,7 +282,8 @@ struct event_desc {
#define OPT_NO_IDENT 70
#define OPT_CACHE_RR 71
#define OPT_LOCALHOST_SERVICE 72
-#define OPT_LAST 73
+#define OPT_BIND_MAC_IP6 73
+#define OPT_LAST 74
#define OPTION_BITS (sizeof(unsigned int)*8)
#define OPTION_SIZE ( (OPT_LAST/OPTION_BITS)+((OPT_LAST%OPTION_BITS)!=0) )
@@ -1211,6 +1212,7 @@ extern struct daemon {
int override;
int enable_pxe;
int doing_ra, doing_dhcp6;
+ int bind_mac_with_ip6;
struct dhcp_netid_list *dhcp_ignore, *dhcp_ignore_names, *dhcp_gen_names;
struct dhcp_netid_list *force_broadcast, *bootp_dynamic;
struct hostsfile *dhcp_hosts_file, *dhcp_opts_file;
diff --git a/src/option.c b/src/option.c
index 9b5066e..7c316b9 100644
--- a/src/option.c
+++ b/src/option.c
@@ -192,6 +192,7 @@ struct myoption {
#define LOPT_NO_DHCP4 383
#define LOPT_MAX_PROCS 384
#define LOPT_DNSSEC_LIMITS 385
+#define LOPT_BIND_MAC_IP6 386
#ifdef HAVE_GETOPT_LONG
static const struct option opts[] =
@@ -388,6 +389,7 @@ static const struct myoption opts[] =
{ "use-stale-cache", 2, 0 , LOPT_STALE_CACHE },
{ "no-ident", 0, 0, LOPT_NO_IDENT },
{ "max-tcp-connections", 1, 0, LOPT_MAX_PROCS },
+ { "bind-mac-with-ip6", 0, 0 , LOPT_BIND_MAC_IP6 },
{ NULL, 0, 0, 0 }
};
@@ -591,6 +593,7 @@ static struct {
{ LOPT_NO_IDENT, OPT_NO_IDENT, NULL, gettext_noop("Do not add CHAOS TXT records."), NULL },
{ LOPT_CACHE_RR, ARG_DUP, "<RR-type>", gettext_noop("Cache this DNS resource record type."), NULL },
{ LOPT_MAX_PROCS, ARG_ONE, "<integer>", gettext_noop("Maximum number of concurrent tcp connections."), NULL },
+ { LOPT_BIND_MAC_IP6, OPT_BIND_MAC_IP6, NULL, gettext_noop("Bind mac with ipv6 address. This is an experimental feature and it conflicts with rfc3315."), NULL },
{ 0, 0, NULL, NULL, NULL }
};
diff --git a/src/rfc3315.c b/src/rfc3315.c
index 400d939..e579494 100644
--- a/src/rfc3315.c
+++ b/src/rfc3315.c
@@ -48,8 +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 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);
@@ -699,7 +699,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);
@@ -708,7 +708,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 */
@@ -723,7 +723,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))
+ config_valid(config, c, &addr, state, now, 1))
{
mark_config_used(state->context, &addr);
if (have_config(config, CONFIG_TIME))
@@ -879,7 +879,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);
@@ -1075,12 +1075,32 @@ static int dhcp6_no_relay(struct state *state, int msg_type, unsigned char *inbu
case DHCP6CONFIRM:
{
int good_addr = 0, bad_addr = 0;
+ int find_bind = 0;
+ struct dhcp_config *find_config = NULL;
/* set reply message type */
outmsgtype = DHCP6REPLY;
log6_quiet(state, "DHCPCONFIRM", NULL, NULL);
-
+
+ if(daemon->bind_mac_with_ip6) {
+ if(state->mac) {
+ for (find_config = daemon->dhcp_conf; find_config; find_config = find_config->next)
+ if (config_has_mac(find_config, state->mac, state->mac_len, state->mac_type) && have_config(find_config, CONFIG_ADDR6)) {
+ find_bind = 1;
+ break;
+ }
+ }
+ /* requires all mac has binding ipv6 address. */
+ if (find_bind == 0) {
+ o1 = new_opt6(OPTION6_STATUS_CODE);
+ put_opt6_short(DHCP6NOTONLINK);
+ put_opt6_string(_("confirm failed, no binding found"));
+ end_opt6(o1);
+ return 1;
+ }
+ }
+
for (opt = state->packet_options; opt; opt = opt6_next(opt, state->end))
{
void *ia_option, *ia_end;
@@ -1104,6 +1124,16 @@ 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 (!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;
+ }
+ }
}
}
@@ -1723,13 +1753,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)
@@ -1769,7 +1810,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;
@@ -1803,7 +1844,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
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。