diff options
| author | Christian Poessinger <christian@poessinger.com> | 2019-10-03 22:46:52 +0200 | 
|---|---|---|
| committer | Christian Poessinger <christian@poessinger.com> | 2019-10-03 22:46:52 +0200 | 
| commit | 1182b44e6c90bf58ff0e1cf51a97f31c9c9d3f84 (patch) | |
| tree | 9ed3b51f0d5ebde6927798137b8c47c8533c83dd | |
| parent | 08b60ba1ccbb12d398a184f0303f2c150a15b918 (diff) | |
| download | vyos-1x-1182b44e6c90bf58ff0e1cf51a97f31c9c9d3f84.tar.gz vyos-1x-1182b44e6c90bf58ff0e1cf51a97f31c9c9d3f84.zip | |
dhcp-server: T1707: bugfix on subsequent DHCP exclude addresses
Moved the code for splicing a DHCP range into its dedicated function as this
will later be required again. Having subsequent DHCP exclude addresses
e.g. 192.0.2.70 and 192.0.2.71 did not work as the previous algorithm
created a range whose start address was after the end address.
(cherry picked from commit 0f0f9f2835cf85c1fd3652ec83368528754764cd)
| -rwxr-xr-x | src/conf_mode/dhcp_server.py | 107 | 
1 files changed, 63 insertions, 44 deletions
| diff --git a/src/conf_mode/dhcp_server.py b/src/conf_mode/dhcp_server.py index 3e1381cd0..c5d6b1052 100755 --- a/src/conf_mode/dhcp_server.py +++ b/src/conf_mode/dhcp_server.py @@ -253,6 +253,68 @@ default_config_data = {      'shared_network': [],  } +def dhcp_slice_range(exclude_list, range_list): +    """ +    This function is intended to slice a DHCP range. What does it mean? + +    Lets assume we have a DHCP range from '192.0.2.1' to '192.0.2.100' +    but want to exclude address '192.0.2.74' and '192.0.2.75'. We will +    pass an input 'range_list' in the format: +      [{'start' : '192.0.2.1', 'stop' : '192.0.2.100' }] +    and we will receive an output list of: +      [{'start' : '192.0.2.1' , 'stop' : '192.0.2.73'  }, +       {'start' : '192.0.2.76', 'stop' : '192.0.2.100' }] +    The resulting list can then be used in turn to build the proper dhcpd +    configuration file. +    """ +    output = [] +    # exclude list must be sorted for this to work +    exclude_list = sorted(exclude_list) +    for ra in range_list: +        range_start = ra['start'] +        range_stop = ra['stop'] +        range_last_exclude = '' + +        for e in exclude_list: +            if (ipaddress.ip_address(e) >= ipaddress.ip_address(range_start)) and \ +               (ipaddress.ip_address(e) <= ipaddress.ip_address(range_stop)): +                range_last_exclude = e + +        for e in exclude_list: +            if (ipaddress.ip_address(e) >= ipaddress.ip_address(range_start)) and \ +               (ipaddress.ip_address(e) <= ipaddress.ip_address(range_stop)): + +                # Build new IP address range ending one IP address before exclude address +                r = { +                    'start' : range_start, +                    'stop' : str(ipaddress.ip_address(e) -1) +                } +                # On the next run our IP address range will start one address after the exclude address +                range_start = str(ipaddress.ip_address(e) + 1) + +                # on subsequent exclude addresses we can not +                # append them to our output +                if not (ipaddress.ip_address(r['start']) > ipaddress.ip_address(r['stop'])): +                    # Everything is fine, add range to result +                    output.append(r) + +                # Take care of last IP address range spanning from the last exclude +                # address (+1) to the end of the initial configured range +                if ipaddress.ip_address(e) == ipaddress.ip_address(range_last_exclude): +                    r = { +                      'start': str(ipaddress.ip_address(e) + 1), +                      'stop': str(range_stop) +                    } +                    output.append(r) +            else: +              # if we have no exclude in the whole range - we just take the range +              # as it is +              if not range_last_exclude: +                  if ra not in output: +                      output.append(ra) + +    return output +  def get_config():      dhcp = default_config_data      conf = Config() @@ -460,51 +522,8 @@ def get_config():                      # IP address that needs to be excluded from DHCP lease range                      if conf.exists('exclude'): -                        # We have no need to store the exclude addresses. Exclude addresses -                        # are recalculated into several ranges -                        exclude = []                          subnet['exclude'] = conf.return_values('exclude') -                        for addr in subnet['exclude']: -                            exclude.append(ipaddress.ip_address(addr)) - -                        # sort excluded IP addresses ascending -                        exclude = sorted(exclude) - -                        # calculate multipe ranges based on the excluded IP addresses -                        output = [] -                        for range in subnet['range']: -                            range_start = range['start'] -                            range_stop = range['stop'] - -                            for i in exclude: -                                # Excluded IP address must be in out specified range -                                if (i >= ipaddress.ip_address(range_start)) and (i <= ipaddress.ip_address(range_stop)): -                                    # Build up new IP address range ending one IP address before -                                    # our exclude address -                                    range = { -                                        'start': str(range_start), -                                        'stop': str(i - 1) -                                    } -                                    # Our next IP address range will start one address after -                                    # our exclude address -                                    range_start = i + 1 -                                    output.append(range) - -                                    # Take care of last IP address range spanning from the last exclude -                                    # address (+1) to the end of the initial configured range -                                    if i is exclude[-1]: -                                        last = { -                                            'start': str(i + 1), -                                            'stop': str(range_stop) -                                        } -                                        output.append(last) -                                else: -                                    # IP address not inside search range, take range is it is -                                    output.append(range) - -                        # We successfully build up a new list containing several IP address -                        # ranges, replace IP address range in our dictionary -                        subnet['range'] = output +                        subnet['range'] = dhcp_slice_range(subnet['exclude'], subnet['range'])                      # Static DHCP leases                      if conf.exists('static-mapping'): | 
