diff --git a/data/templates/accel-ppp/config_ip_pool.j2 b/data/templates/accel-ppp/config_ip_pool.j2 index 6ac04e1a1..8e66486e6 100644 --- a/data/templates/accel-ppp/config_ip_pool.j2 +++ b/data/templates/accel-ppp/config_ip_pool.j2 @@ -1,28 +1,32 @@ {% if ordered_named_pools is vyos_defined %} [ip-pool] {% if gateway_address is vyos_defined %} {% if server_type == 'ipoe' %} {% for gw in gateway_address %} {% set host_address, _ = gw.split('/') %} gw-ip-address={{ host_address }} {% endfor %} {% else %} gw-ip-address={{ gateway_address }} {% endif %} {% endif %} {% for pool in ordered_named_pools %} {% for pool_name, pool_config in pool.items() %} -{% set iprange_str = pool_config.range %} -{% set iprange_list = pool_config.range.split('-') %} -{% if iprange_list | length == 2 %} -{% set last_ip_oct = iprange_list[1].split('.') %} -{% set iprange_str = iprange_list[0] + '-' + last_ip_oct[last_ip_oct | length - 1] %} -{% endif %} -{% if pool_config.next_pool is vyos_defined %} +{% if pool_config.range is vyos_defined %} +{% for range in pool_config.range %} +{% set iprange_str = range %} +{% set iprange_list = range.split('-') %} +{% if iprange_list | length == 2 %} +{% set last_ip_oct = iprange_list[1].split('.') %} +{% set iprange_str = iprange_list[0] + '-' + last_ip_oct[last_ip_oct | length - 1] %} +{% endif %} +{% if loop.last and pool_config.next_pool is vyos_defined %} {{ iprange_str }},name={{ pool_name }},next={{ pool_config.next_pool }} -{% else %} +{% else %} {{ iprange_str }},name={{ pool_name }} +{% endif %} +{% endfor %} {% endif %} {% endfor %} {% endfor %} {% endif %} \ No newline at end of file diff --git a/interface-definitions/include/accel-ppp/client-ip-pool.xml.i b/interface-definitions/include/accel-ppp/client-ip-pool.xml.i index 71fe69f8d..b30a5ee01 100644 --- a/interface-definitions/include/accel-ppp/client-ip-pool.xml.i +++ b/interface-definitions/include/accel-ppp/client-ip-pool.xml.i @@ -1,46 +1,50 @@ <!-- include start from accel-ppp/client-ip-pool.xml.i --> <tagNode name="client-ip-pool"> <properties> <help>Client IP pool</help> <valueHelp> <format>txt</format> <description>Name of IP pool</description> </valueHelp> <constraint> #include <include/constraint/alpha-numeric-hyphen-underscore-dot.xml.i> </constraint> </properties> <children> <leafNode name="range"> <properties> <help>Range of IP addresses</help> <valueHelp> <format>ipv4net</format> <description>IPv4 prefix</description> </valueHelp> <valueHelp> <format>ipv4range</format> <description>IPv4 address range inside /24 network</description> </valueHelp> <constraint> <validator name="ipv4-prefix"/> <validator name="ipv4-host"/> <validator name="ipv4-range-mask" argument="-m 24 -r"/> </constraint> + <multi/> </properties> </leafNode> <leafNode name="next-pool"> <properties> <help>Next pool name</help> + <completionHelp> + <path>${COMP_WORDS[@]:1:${#COMP_WORDS[@]}-4}</path> + </completionHelp> <valueHelp> <format>txt</format> <description>Name of IP pool</description> </valueHelp> <constraint> #include <include/constraint/alpha-numeric-hyphen-underscore-dot.xml.i> </constraint> </properties> </leafNode> </children> </tagNode> <!-- include end --> diff --git a/interface-definitions/include/accel-ppp/default-pool.xml.i b/interface-definitions/include/accel-ppp/default-pool.xml.i index a08b066b1..e06642c37 100644 --- a/interface-definitions/include/accel-ppp/default-pool.xml.i +++ b/interface-definitions/include/accel-ppp/default-pool.xml.i @@ -1,14 +1,17 @@ <!-- include start from accel-ppp/default-pool.xml.i --> <leafNode name="default-pool"> <properties> <help>Default client IP pool name</help> + <completionHelp> + <path>${COMP_WORDS[@]:1:${#COMP_WORDS[@]}-3} client-ip-pool</path> + </completionHelp> <valueHelp> <format>txt</format> <description>Default IP pool</description> </valueHelp> <constraint> #include <include/constraint/alpha-numeric-hyphen-underscore-dot.xml.i> </constraint> </properties> </leafNode> <!-- include end --> diff --git a/src/conf_mode/vpn_l2tp.py b/src/conf_mode/vpn_l2tp.py index 03a27d3cd..1a91951b4 100755 --- a/src/conf_mode/vpn_l2tp.py +++ b/src/conf_mode/vpn_l2tp.py @@ -1,123 +1,123 @@ #!/usr/bin/env python3 # # Copyright (C) 2019-2023 VyOS maintainers and contributors # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 or later as # published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. import os from sys import exit from vyos.config import Config from vyos.configdict import get_accel_dict from vyos.template import render from vyos.utils.process import call from vyos.utils.dict import dict_search from vyos.accel_ppp_util import verify_accel_ppp_base_service from vyos.accel_ppp_util import verify_accel_ppp_ip_pool from vyos.accel_ppp_util import get_pools_in_order from vyos.base import Warning from vyos import ConfigError from vyos import airbag airbag.enable() l2tp_conf = '/run/accel-pppd/l2tp.conf' l2tp_chap_secrets = '/run/accel-pppd/l2tp.chap-secrets' def get_config(config=None): if config: conf = config else: conf = Config() base = ['vpn', 'l2tp', 'remote-access'] if not conf.exists(base): return None # retrieve common dictionary keys l2tp = get_accel_dict(conf, base, l2tp_chap_secrets) if dict_search('client_ip_pool', l2tp): # Multiple named pools require ordered values T5099 l2tp['ordered_named_pools'] = get_pools_in_order( dict_search('client_ip_pool', l2tp)) l2tp['ip6_column'] = [] if dict_search('client_ipv6_pool.prefix', l2tp): l2tp['ip6_column'].append('ipv6') if dict_search('client_ipv6_pool.delegate', l2tp): l2tp['ip6_column'].append('ip6-db') l2tp['server_type'] = 'l2tp' return l2tp def verify(l2tp): if not l2tp: return None verify_accel_ppp_base_service(l2tp) if dict_search('authentication.radius.dynamic_author.server', l2tp): if not dict_search('authentication.radius.dynamic_author.key', l2tp): raise ConfigError('DA/CoE server key required!') if dict_search('authentication.mode', l2tp) in ['local', 'noauth']: - if not l2tp['client_ip_pool'] and not l2tp['client_ipv6_pool']: + if not dict_search('client_ip_pool', l2tp) and not dict_search('client_ipv6_pool', l2tp): raise ConfigError( "L2TP local auth mode requires local client-ip-pool or client-ipv6-pool to be configured!") if dict_search('client_ip_pool', l2tp) and not dict_search('default_pool', l2tp): Warning("'default-pool' is not defined") verify_accel_ppp_ip_pool(l2tp) if 'wins_server' in l2tp and len(l2tp['wins_server']) > 2: raise ConfigError( 'Not more then two WINS name-servers can be configured') return None def generate(l2tp): if not l2tp: return None render(l2tp_conf, 'accel-ppp/l2tp.config.j2', l2tp) if dict_search('authentication.mode', l2tp) == 'local': render(l2tp_chap_secrets, 'accel-ppp/chap-secrets.config_dict.j2', l2tp, permission=0o640) return None def apply(l2tp): if not l2tp: call('systemctl stop accel-ppp@l2tp.service') for file in [l2tp_chap_secrets, l2tp_conf]: if os.path.exists(file): os.unlink(file) return None call('systemctl restart accel-ppp@l2tp.service') if __name__ == '__main__': try: c = get_config() verify(c) generate(c) apply(c) except ConfigError as e: print(e) exit(1) diff --git a/src/migration-scripts/ipoe-server/1-to-2 b/src/migration-scripts/ipoe-server/1-to-2 index c8cec6835..11d7911e9 100755 --- a/src/migration-scripts/ipoe-server/1-to-2 +++ b/src/migration-scripts/ipoe-server/1-to-2 @@ -1,87 +1,87 @@ #!/usr/bin/env python3 # # Copyright (C) 2023 VyOS maintainers and contributors # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 or later as # published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # - changed cli of all named pools # - moved gateway-address from pool to global configuration with / netmask # gateway can exist without pool if radius is used # and Framed-ip-address is transmited # - There are several gateway-addresses in ipoe # - default-pool by migration. # 1. The first pool that contains next-poll. # 2. Else, the first pool in the list import os from sys import argv from sys import exit from vyos.configtree import ConfigTree if len(argv) < 2: print("Must specify file name!") exit(1) file_name = argv[1] with open(file_name, 'r') as f: config_file = f.read() config = ConfigTree(config_file) base = ['service', 'ipoe-server'] pool_base = base + ['client-ip-pool'] if not config.exists(base): exit(0) if not config.exists(pool_base): exit(0) default_pool = '' gateway = '' #named pool migration namedpools_base = pool_base + ['name'] for pool_name in config.list_nodes(namedpools_base): pool_path = namedpools_base + [pool_name] if config.exists(pool_path + ['subnet']): subnet = config.return_value(pool_path + ['subnet']) - config.set(pool_base + [pool_name, 'range'], value=subnet) + config.set(pool_base + [pool_name, 'range'], value=subnet, replace=False) # Get netmask from subnet mask = subnet.split("/")[1] if config.exists(pool_path + ['next-pool']): next_pool = config.return_value(pool_path + ['next-pool']) config.set(pool_base + [pool_name, 'next-pool'], value=next_pool) if not default_pool: default_pool = pool_name if config.exists(pool_path + ['gateway-address']) and mask: gateway = f'{config.return_value(pool_path + ["gateway-address"])}/{mask}' config.set(base + ['gateway-address'], value=gateway, replace=False) if not default_pool and config.list_nodes(namedpools_base): default_pool = config.list_nodes(namedpools_base)[0] config.delete(namedpools_base) if default_pool: config.set(base + ['default-pool'], value=default_pool) # format as tag node config.set_tag(pool_base) try: with open(file_name, 'w') as f: f.write(config.to_string()) except OSError as e: print("Failed to save the modified config: {}".format(e)) exit(1) diff --git a/src/migration-scripts/l2tp/4-to-5 b/src/migration-scripts/l2tp/4-to-5 index 496dc83d6..3176f895a 100755 --- a/src/migration-scripts/l2tp/4-to-5 +++ b/src/migration-scripts/l2tp/4-to-5 @@ -1,87 +1,87 @@ #!/usr/bin/env python3 # # Copyright (C) 2023 VyOS maintainers and contributors # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 or later as # published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # - move all pool to named pools # 'start-stop' migrate to namedpool 'default-range-pool' # 'subnet' migrate to namedpool 'default-subnet-pool' # 'default-subnet-pool' is the next pool for 'default-range-pool' import os from sys import argv from sys import exit from vyos.configtree import ConfigTree - +from vyos.base import Warning if len(argv) < 2: print("Must specify file name!") exit(1) file_name = argv[1] with open(file_name, 'r') as f: config_file = f.read() config = ConfigTree(config_file) base = ['vpn', 'l2tp', 'remote-access'] pool_base = base + ['client-ip-pool'] if not config.exists(base): exit(0) if not config.exists(pool_base): exit(0) default_pool = '' range_pool_name = 'default-range-pool' -subnet_base_name = 'default-subnet-pool' -number = 1 -subnet_pool_name = f'{subnet_base_name}-{number}' -prev_subnet_pool = subnet_pool_name -if config.exists(pool_base + ['subnet']): - default_pool = subnet_pool_name - for subnet in config.return_values(pool_base + ['subnet']): - config.set(pool_base + [subnet_pool_name, 'range'], value=subnet) - if prev_subnet_pool != subnet_pool_name: - config.set(pool_base + [prev_subnet_pool, 'next-pool'], - value=subnet_pool_name) - prev_subnet_pool = subnet_pool_name - number += 1 - subnet_pool_name = f'{subnet_base_name}-{number}' - - config.delete(pool_base + ['subnet']) if config.exists(pool_base + ['start']) and config.exists(pool_base + ['stop']): + def is_legalrange(ip1: str, ip2: str, mask: str): + from ipaddress import IPv4Interface + interface1 = IPv4Interface(f'{ip1}/{mask}') + + interface2 = IPv4Interface(f'{ip2}/{mask}') + return interface1.network.network_address == interface2.network.network_address and interface2.ip > interface1.ip + start_ip = config.return_value(pool_base + ['start']) stop_ip = config.return_value(pool_base + ['stop']) - ip_range = f'{start_ip}-{stop_ip}' + if is_legalrange(start_ip, stop_ip,'24'): + ip_range = f'{start_ip}-{stop_ip}' + config.set(pool_base + [range_pool_name, 'range'], value=ip_range, replace=False) + default_pool = range_pool_name + else: + Warning( + f'L2TP client-ip-pool range start-ip:{start_ip} and stop-ip:{stop_ip} can not be migrated.') + config.delete(pool_base + ['start']) config.delete(pool_base + ['stop']) - config.set(pool_base + [range_pool_name, 'range'], value=ip_range) - if default_pool: - config.set(pool_base + [range_pool_name, 'next-pool'], - value=default_pool) + +if config.exists(pool_base + ['subnet']): + for subnet in config.return_values(pool_base + ['subnet']): + config.set(pool_base + [range_pool_name, 'range'], value=subnet, replace=False) + + config.delete(pool_base + ['subnet']) default_pool = range_pool_name if default_pool: config.set(base + ['default-pool'], value=default_pool) # format as tag node config.set_tag(pool_base) try: with open(file_name, 'w') as f: f.write(config.to_string()) except OSError as e: print("Failed to save the modified config: {}".format(e)) exit(1) diff --git a/src/migration-scripts/pppoe-server/6-to-7 b/src/migration-scripts/pppoe-server/6-to-7 index d856c1f34..b94ce57f9 100755 --- a/src/migration-scripts/pppoe-server/6-to-7 +++ b/src/migration-scripts/pppoe-server/6-to-7 @@ -1,122 +1,119 @@ #!/usr/bin/env python3 # # Copyright (C) 2023 VyOS maintainers and contributors # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 or later as # published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # - move all pool to named pools # 'start-stop' migrate to namedpool 'default-range-pool' # 'subnet' migrate to namedpool 'default-subnet-pool' # 'default-subnet-pool' is the next pool for 'default-range-pool' # - There is only one gateway-address, take the first which is configured # - default-pool by migration. # 1. If authentication mode = 'local' then it is first named pool. # If there are not named pools, namedless pool will be default. # 2. If authentication mode = 'radius' then namedless pool will be default import os from sys import argv from sys import exit from vyos.configtree import ConfigTree - +from vyos.base import Warning if len(argv) < 2: print("Must specify file name!") exit(1) file_name = argv[1] with open(file_name, 'r') as f: config_file = f.read() config = ConfigTree(config_file) base = ['service', 'pppoe-server'] pool_base = base + ['client-ip-pool'] if not config.exists(base): exit(0) if not config.exists(pool_base): exit(0) + default_pool = '' range_pool_name = 'default-range-pool' -subnet_base_name = 'default-subnet-pool' -number = 1 -subnet_pool_name = f'{subnet_base_name}-{number}' -prev_subnet_pool = subnet_pool_name #Default nameless pools migrations -if config.exists(pool_base + ['subnet']): - default_pool = subnet_pool_name - for subnet in config.return_values(pool_base + ['subnet']): - config.set(pool_base + [subnet_pool_name, 'range'], value=subnet) - if prev_subnet_pool != subnet_pool_name: - config.set(pool_base + [prev_subnet_pool, 'next-pool'], - value=subnet_pool_name) - prev_subnet_pool = subnet_pool_name - number += 1 - subnet_pool_name = f'{subnet_base_name}-{number}' - - config.delete(pool_base + ['subnet']) - if config.exists(pool_base + ['start']) and config.exists(pool_base + ['stop']): + def is_legalrange(ip1: str, ip2: str, mask: str): + from ipaddress import IPv4Interface + interface1 = IPv4Interface(f'{ip1}/{mask}') + interface2 = IPv4Interface(f'{ip2}/{mask}') + return interface1.network.network_address == interface2.network.network_address and interface2.ip > interface1.ip + start_ip = config.return_value(pool_base + ['start']) stop_ip = config.return_value(pool_base + ['stop']) - ip_range = f'{start_ip}-{stop_ip}' + if is_legalrange(start_ip, stop_ip, '24'): + ip_range = f'{start_ip}-{stop_ip}' + config.set(pool_base + [range_pool_name, 'range'], value=ip_range, replace=False) + default_pool = range_pool_name + else: + Warning( + f'PPPoE client-ip-pool range start-ip:{start_ip} and stop-ip:{stop_ip} can not be migrated.') config.delete(pool_base + ['start']) config.delete(pool_base + ['stop']) - config.set(pool_base + [range_pool_name, 'range'], value=ip_range) - if default_pool: - config.set(pool_base + [range_pool_name, 'next-pool'], - value=default_pool) + +if config.exists(pool_base + ['subnet']): default_pool = range_pool_name + for subnet in config.return_values(pool_base + ['subnet']): + config.set(pool_base + [range_pool_name, 'range'], value=subnet, replace=False) + config.delete(pool_base + ['subnet']) gateway = '' if config.exists(base + ['gateway-address']): gateway = config.return_value(base + ['gateway-address']) #named pool migration namedpools_base = pool_base + ['name'] if config.exists(namedpools_base): if config.exists(base + ['authentication', 'mode']): if config.return_value(base + ['authentication', 'mode']) == 'local': if config.list_nodes(namedpools_base): default_pool = config.list_nodes(namedpools_base)[0] for pool_name in config.list_nodes(namedpools_base): pool_path = namedpools_base + [pool_name] if config.exists(pool_path + ['subnet']): subnet = config.return_value(pool_path + ['subnet']) - config.set(pool_base + [pool_name, 'range'], value=subnet) + config.set(pool_base + [pool_name, 'range'], value=subnet, replace=False) if config.exists(pool_path + ['next-pool']): next_pool = config.return_value(pool_path + ['next-pool']) config.set(pool_base + [pool_name, 'next-pool'], value=next_pool) if not gateway: if config.exists(pool_path + ['gateway-address']): gateway = config.return_value(pool_path + ['gateway-address']) config.delete(namedpools_base) if gateway: config.set(base + ['gateway-address'], value=gateway) if default_pool: config.set(base + ['default-pool'], value=default_pool) # format as tag node config.set_tag(pool_base) try: with open(file_name, 'w') as f: f.write(config.to_string()) except OSError as e: print("Failed to save the modified config: {}".format(e)) exit(1) diff --git a/src/migration-scripts/pptp/2-to-3 b/src/migration-scripts/pptp/2-to-3 index 98dc5c2a6..091cb68ec 100755 --- a/src/migration-scripts/pptp/2-to-3 +++ b/src/migration-scripts/pptp/2-to-3 @@ -1,64 +1,75 @@ #!/usr/bin/env python3 # # Copyright (C) 2023 VyOS maintainers and contributors # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 or later as # published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # - move all pool to named pools # 'start-stop' migrate to namedpool 'default-range-pool' # 'default-subnet-pool' is the next pool for 'default-range-pool' import os from sys import argv from sys import exit from vyos.configtree import ConfigTree - +from vyos.base import Warning if len(argv) < 2: print("Must specify file name!") exit(1) file_name = argv[1] with open(file_name, 'r') as f: config_file = f.read() config = ConfigTree(config_file) base = ['vpn', 'pptp', 'remote-access'] pool_base = base + ['client-ip-pool'] if not config.exists(base): exit(0) if not config.exists(pool_base): exit(0) range_pool_name = 'default-range-pool' if config.exists(pool_base + ['start']) and config.exists(pool_base + ['stop']): + def is_legalrange(ip1: str, ip2: str, mask: str): + from ipaddress import IPv4Interface + interface1 = IPv4Interface(f'{ip1}/{mask}') + interface2 = IPv4Interface(f'{ip2}/{mask}') + return interface1.network.network_address == interface2.network.network_address and interface2.ip > interface1.ip + start_ip = config.return_value(pool_base + ['start']) stop_ip = config.return_value(pool_base + ['stop']) - ip_range = f'{start_ip}-{stop_ip}' + if is_legalrange(start_ip, stop_ip, '24'): + ip_range = f'{start_ip}-{stop_ip}' + config.set(pool_base + [range_pool_name, 'range'], value=ip_range, replace=False) + config.set(base + ['default-pool'], value=range_pool_name) + else: + Warning( + f'PPTP client-ip-pool range start-ip:{start_ip} and stop-ip:{stop_ip} can not be migrated.') + config.delete(pool_base + ['start']) config.delete(pool_base + ['stop']) - config.set(pool_base + [range_pool_name, 'range'], value=ip_range) - config.set(base + ['default-pool'], value=range_pool_name) # format as tag node config.set_tag(pool_base) try: with open(file_name, 'w') as f: f.write(config.to_string()) except OSError as e: print("Failed to save the modified config: {}".format(e)) exit(1) diff --git a/src/migration-scripts/sstp/4-to-5 b/src/migration-scripts/sstp/4-to-5 index 3a86c79ec..95e482713 100755 --- a/src/migration-scripts/sstp/4-to-5 +++ b/src/migration-scripts/sstp/4-to-5 @@ -1,71 +1,62 @@ #!/usr/bin/env python3 # # Copyright (C) 2023 VyOS maintainers and contributors # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 or later as # published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # - move all pool to named pools # 'subnet' migrate to namedpool 'default-subnet-pool' # 'default-subnet-pool' is the next pool for 'default-range-pool' import os from sys import argv from sys import exit from vyos.configtree import ConfigTree if len(argv) < 2: print("Must specify file name!") exit(1) file_name = argv[1] with open(file_name, 'r') as f: config_file = f.read() config = ConfigTree(config_file) base = ['vpn', 'sstp'] pool_base = base + ['client-ip-pool'] if not config.exists(base): exit(0) if not config.exists(pool_base): exit(0) -subnet_base_name = 'default-subnet-pool' -number = 1 -subnet_pool_name = f'{subnet_base_name}-{number}' -prev_subnet_pool = subnet_pool_name +range_pool_name = 'default-range-pool' + if config.exists(pool_base + ['subnet']): - default_pool = subnet_pool_name + default_pool = range_pool_name for subnet in config.return_values(pool_base + ['subnet']): - config.set(pool_base + [subnet_pool_name, 'range'], value=subnet) - if prev_subnet_pool != subnet_pool_name: - config.set(pool_base + [prev_subnet_pool, 'next-pool'], - value=subnet_pool_name) - prev_subnet_pool = subnet_pool_name - number += 1 - subnet_pool_name = f'{subnet_base_name}-{number}' - + config.set(pool_base + [range_pool_name, 'range'], value=subnet, replace=False) config.delete(pool_base + ['subnet']) config.set(base + ['default-pool'], value=default_pool) # format as tag node config.set_tag(pool_base) try: with open(file_name, 'w') as f: f.write(config.to_string()) except OSError as e: print("Failed to save the modified config: {}".format(e)) exit(1) diff --git a/src/validators/ipv4-range-mask b/src/validators/ipv4-range-mask index 7bb4539af..9373328ff 100755 --- a/src/validators/ipv4-range-mask +++ b/src/validators/ipv4-range-mask @@ -1,59 +1,27 @@ #!/bin/bash -# snippet from https://stackoverflow.com/questions/10768160/ip-address-converter -ip2dec () { - local a b c d ip=$@ - IFS=. read -r a b c d <<< "$ip" - printf '%d\n' "$((a * 256 ** 3 + b * 256 ** 2 + c * 256 + d))" -} - error_exit() { echo "Error: $1 is not a valid IPv4 address range or these IPs are not under /$2" exit 1 } # Check if address range is under the same netmask # -m - mask # -r - IP range in format x.x.x.x-y.y.y.y while getopts m:r: flag do case "${flag}" in m) mask=${OPTARG};; r) range=${OPTARG} esac done -if [[ "${range}" =~ "-" ]]&&[[ ! -z ${mask} ]]; then - # This only works with real bash (<<<) - split IP addresses into array with - # hyphen as delimiter - readarray -d - -t strarr <<< ${range} - - ipaddrcheck --is-ipv4-single ${strarr[0]} - if [ $? -gt 0 ]; then - error_exit ${range} ${mask} - fi - ipaddrcheck --is-ipv4-single ${strarr[1]} +if [[ "${range}" =~ "-" ]]&&[[ ! -z ${mask} ]]; then + ipaddrcheck --range-prefix-length ${mask} --is-ipv4-range ${range} if [ $? -gt 0 ]; then error_exit ${range} ${mask} fi - - ${vyos_validators_dir}/numeric --range 0-32 ${mask} > /dev/null - if [ $? -ne 0 ]; then - error_exit ${range} ${mask} - fi - - is_in_24=$( grepcidr ${strarr[0]}"/"${mask} <(echo ${strarr[1]}) ) - if [ -z $is_in_24 ]; then - error_exit ${range} ${mask} - fi - - start=$(ip2dec ${strarr[0]}) - stop=$(ip2dec ${strarr[1]}) - if [ $start -ge $stop ]; then - error_exit ${range} ${mask} - fi - exit 0 fi error_exit ${range} ${mask}