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

Reply via email to