Another request for Hey, could this patch get reviewed?
On 06-02-2019 21:29, Pali Rohár wrote: > PING > > On Friday 11 January 2019 17:52:43 Pali Rohár wrote: >> Hello, can somebody look at this patch? >> >> I remember that more people asked for ability to assign IPv6 address >> based on MAC address specified in config file, rather then IAID/DUID. >> >> On Monday 17 December 2018 18:41:09 Pali Rohár wrote: >>> 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. >>> >>> Also this patch adds support for allowing IPv6 address to be associated >>> with multiple hardware addresses, and gives dnsmasq permission to abandon a >>> lease. This is similar functionality as already supported for IPv4 address. >>> --- >>> man/dnsmasq.8 | 9 ++++++--- >>> src/rfc3315.c | 62 >>> ++++++++++++++++++++++++++++++++++++++++++++++++++--------- >>> 2 files changed, 59 insertions(+), 12 deletions(-) >>> >>> diff --git a/man/dnsmasq.8 b/man/dnsmasq.8 >>> index f01a5ba..8614f08 100644 >>> --- a/man/dnsmasq.8 >>> +++ b/man/dnsmasq.8 >>> @@ -1068,10 +1068,13 @@ will only match a >>> Token-Ring hardware address, since the ARP-address type for token ring >>> is 6. >>> >>> -As a special case, in DHCPv4, it is possible to include more than one >>> -hardware address. eg: >>> +It is possible to include more than one hardware address. eg for IPv4: >>> .B --dhcp-host=11:22:33:44:55:66,12:34:56:78:90:12,192.168.0.2 >>> -This allows an IP address to be associated with >>> +or for IPv6: >>> +.B --dhcp-host=11:22:33:44:55:66,12:34:56:78:90:12,[::2] >>> +or for both: >>> +.B --dhcp-host=11:22:33:44:55:66,12:34:56:78:90:12,192.168.0.2,[::2] >>> +This allows an IPv4 and/or IPv6 address to be associated with >>> multiple hardware addresses, and gives dnsmasq permission to abandon a >>> DHCP lease to one of the hardware addresses when another one asks for >>> a lease. Beware that this is a dangerous thing to do, it will only >>> diff --git a/src/rfc3315.c b/src/rfc3315.c >>> index a20776d..c83cf2d 100644 >>> --- a/src/rfc3315.c >>> +++ b/src/rfc3315.c >>> @@ -54,7 +54,7 @@ static struct prefix_class >>> *prefix_class_from_context(struct dhcp_context *conte >>> #endif >>> 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 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 +746,7 @@ static int dhcp6_no_relay(struct state *state, int >>> msg_type, void *inbuff, size_ >>> /* 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) && check_address(state, &addr)) >>> + if (!(c->flags & CONTEXT_CONF_USED) && config_valid(config, >>> c, &addr) && check_address(state, config, &addr)) >>> { >>> req_addr = addr; >>> mark_config_used(c, &addr); >>> @@ -755,8 +755,14 @@ static int dhcp6_no_relay(struct state *state, int >>> msg_type, void *inbuff, size_ >>> } >>> 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_valid(config, c, &addr) && >>> + !IN6_ARE_ADDR_EQUAL(&req_addr, &addr)) >>> + continue; /* another static address is configured */ >>> >>> /* add address to output packet */ >>> #ifdef OPTION6_PREFIX_CLASS >>> @@ -772,10 +778,13 @@ static int dhcp6_no_relay(struct state *state, int >>> msg_type, void *inbuff, size_ >>> >>> /* 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) && >>> - check_address(state, &addr)) >>> + check_address(state, config, &addr)) >>> { >>> mark_config_used(state->context, &addr); >>> if (have_config(config, CONFIG_TIME)) >>> @@ -800,6 +809,12 @@ static int dhcp6_no_relay(struct state *state, int >>> msg_type, void *inbuff, size_ >>> 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_valid(config, c, &addr) && >>> + !IN6_ARE_ADDR_EQUAL(&req_addr, &addr)) >>> + continue; /* skip this lease because another static >>> address is configured */ >>> #ifdef OPTION6_PREFIX_CLASS >>> if (dump_all_prefix_classes && state->ia_type == >>> OPTION6_IA_NA) >>> state->send_prefix_class = prefix_class_from_context(c); >>> @@ -943,7 +958,7 @@ static int dhcp6_no_relay(struct state *state, int >>> msg_type, void *inbuff, size_ >>> 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); >>> @@ -1064,6 +1079,17 @@ static int dhcp6_no_relay(struct state *state, int >>> msg_type, void *inbuff, size_ >>> struct in6_addr addr; >>> 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_valid(config, this_context, &addr) && >>> + !IN6_ARE_ADDR_EQUAL(&req_addr, &addr)) >>> + { >>> + preferred_time = valid_time = 0; >>> + message = _("deprecated"); >>> + } >>> + else >>> + { >>> get_context_tag(state, this_context); >>> >>> if (config_valid(config, this_context, &addr) && >>> IN6_ARE_ADDR_EQUAL(&addr, &req_addr) && have_config(config, CONFIG_TIME)) >>> @@ -1089,6 +1115,7 @@ static int dhcp6_no_relay(struct state *state, int >>> msg_type, void *inbuff, size_ >>> >>> if (preferred_time == 0) >>> message = _("deprecated"); >>> + } >>> } >>> else >>> { >>> @@ -1135,11 +1162,24 @@ static int dhcp6_no_relay(struct state *state, int >>> msg_type, void *inbuff, size_ >>> ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, >>> OPTION6_IAADDR, 24)) >>> { >>> struct in6_addr req_addr; >>> + struct in6_addr 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_valid(config, c, &addr) && >>> + !IN6_ARE_ADDR_EQUAL(&req_addr, &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); >>> @@ -1772,11 +1812,15 @@ static void mark_config_used(struct dhcp_context >>> *context, struct in6_addr *addr >>> 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; >>> > > _______________________________________________ > Dnsmasq-discuss mailing list > Dnsmasq-discuss@lists.thekelleys.org.uk > http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss
_______________________________________________ Dnsmasq-discuss mailing list Dnsmasq-discuss@lists.thekelleys.org.uk http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss