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; > > >
-- Pali Rohár pali.ro...@gmail.com
signature.asc
Description: PGP signature
_______________________________________________ Dnsmasq-discuss mailing list Dnsmasq-discuss@lists.thekelleys.org.uk http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss