From 7d8a6199730a2fd0cd2a7cfa4fdb73b8399f110a Mon Sep 17 00:00:00 2001 From: Shufeng Cao Date: Tue, 27 Nov 2018 15:03:59 +0800 Subject: [PATCH 1/2] allow binding mac address with ipv6 This change introduces a new option --bind-mac-with-ip6, when this option is enabled, a client of same mac address will always get the bound ipv6 address, even when it's duid has been changed. --- src/dnsmasq.c | 1 + src/dnsmasq.h | 4 +++- src/option.c | 3 +++ src/rfc3315.c | 34 +++++++++++++++++++++++++++++++++- 4 files changed, 40 insertions(+), 2 deletions(-) diff --git a/src/dnsmasq.c b/src/dnsmasq.c index 9f6c020..32a4d22 100644 --- a/src/dnsmasq.c +++ b/src/dnsmasq.c @@ -243,6 +243,7 @@ int main (int argc, char **argv) if (daemon->dhcp6) { 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) { diff --git a/src/dnsmasq.h b/src/dnsmasq.h index 6773b69..8b31d42 100644 --- a/src/dnsmasq.h +++ b/src/dnsmasq.h @@ -250,7 +250,8 @@ struct event_desc { #define OPT_MAC_B64 54 #define OPT_MAC_HEX 55 #define OPT_TFTP_APREF_MAC 56 -#define OPT_LAST 57 +#define OPT_BIND_MAC_IP6 57 +#define OPT_LAST 58 /* extra flags for my_syslog, we use a couple of facilities since they are known not to occupy the same bits as priorities, no matter how syslog.h is set up. */ @@ -1000,6 +1001,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, *dynamic_dirs; diff --git a/src/option.c b/src/option.c index d358d99..919e5a3 100644 --- a/src/option.c +++ b/src/option.c @@ -160,6 +160,7 @@ struct myoption { #define LOPT_DHCPTTL 348 #define LOPT_TFTP_MTU 349 #define LOPT_REPLY_DELAY 350 +#define LOPT_BIND_MAC_IP6 351 #ifdef HAVE_GETOPT_LONG static const struct option opts[] = @@ -325,6 +326,7 @@ static const struct myoption opts[] = { "script-arp", 0, 0, LOPT_SCRIPT_ARP }, { "dhcp-ttl", 1, 0 , LOPT_DHCPTTL }, { "dhcp-reply-delay", 1, 0, LOPT_REPLY_DELAY }, + { "bind-mac-with-ip6", 0, 0 , LOPT_BIND_MAC_IP6 }, { NULL, 0, 0, 0 } }; @@ -497,6 +499,7 @@ static struct { { LOPT_IGNORE_ADDR, ARG_DUP, "", gettext_noop("Ignore DNS responses containing ipaddr."), NULL }, { LOPT_DHCPTTL, ARG_ONE, "", gettext_noop("Set TTL in DNS responses with DHCP-derived addresses."), NULL }, { LOPT_REPLY_DELAY, ARG_ONE, "", gettext_noop("Delay DHCP replies for at least number of seconds."), 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 21fcd9b..defd966 100644 --- a/src/rfc3315.c +++ b/src/rfc3315.c @@ -55,6 +55,7 @@ static struct prefix_class *prefix_class_from_context(struct dhcp_context *conte 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 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); static void update_leases(struct state *state, struct dhcp_context *context, struct in6_addr *addr, unsigned int lease_time, time_t now); @@ -746,7 +747,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_ if (!(c->flags & CONTEXT_CONF_USED) && match_netid(c->filter, solicit_tags, plain_range) && config_valid(config, c, &addr) && - check_address(state, &addr)) + check_and_try_preempte_address(state, &addr, now, config)) { mark_config_used(state->context, &addr); if (have_config(config, CONFIG_TIME)) @@ -1744,6 +1745,37 @@ static int check_address(struct state *state, struct in6_addr *addr) return 1; } +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; +} + /* Calculate valid and preferred times to send in leases/renewals. -- 2.19.1