diff options
52 files changed, 963 insertions, 202 deletions
diff --git a/data/templates/accel-ppp/config_ipv6_pool.j2 b/data/templates/accel-ppp/config_ipv6_pool.j2 index a1562a1eb..86efdc1e1 100644 --- a/data/templates/accel-ppp/config_ipv6_pool.j2 +++ b/data/templates/accel-ppp/config_ipv6_pool.j2 @@ -3,20 +3,19 @@ AdvAutonomousFlag=1 verbose=1 -{% if client_ipv6_pool.prefix is vyos_defined %} [ipv6-pool] -{% for prefix, options in client_ipv6_pool.prefix.items() %} -{{ prefix }},{{ options.mask }} -{% endfor %} -{% if client_ipv6_pool.delegate is vyos_defined %} -{% for prefix, options in client_ipv6_pool.delegate.items() %} -delegate={{ prefix }},{{ options.delegation_prefix }} +{% for pool_name, pool_config in client_ipv6_pool.items() %} +{% if pool_config.prefix is vyos_defined %} +{% for prefix, options in pool_config.prefix.items() %} +{{ prefix }},{{ options.mask }},name={{ pool_name }} {% endfor %} {% endif %} -{% endif %} - -{% if client_ipv6_pool.delegate is vyos_defined %} +{% if pool_config.delegate is vyos_defined %} +{% for prefix, options in pool_config.delegate.items() %} +delegate={{ prefix }},{{ options.delegation_prefix }},name={{ pool_name }} +{% endfor %} +{% endif %} +{% endfor %} [ipv6-dhcp] verbose=1 -{% endif %} {% endif %} diff --git a/data/templates/accel-ppp/ipoe.config.j2 b/data/templates/accel-ppp/ipoe.config.j2 index 588f3d462..8b022eaa5 100644 --- a/data/templates/accel-ppp/ipoe.config.j2 +++ b/data/templates/accel-ppp/ipoe.config.j2 @@ -58,6 +58,10 @@ password=csid {% if default_pool is vyos_defined %} ip-pool={{ default_pool }} {% endif %} +{% if default_ipv6_pool is vyos_defined %} +ipv6-pool={{ default_ipv6_pool }} +ipv6-pool-delegate={{ default_ipv6_pool }} +{% endif %} {% if gateway_address is vyos_defined %} {% for gw_addr in gateway_address %} gw-ip-address={{ gw_addr }} diff --git a/data/templates/accel-ppp/l2tp.config.j2 b/data/templates/accel-ppp/l2tp.config.j2 index 49755254a..f041e278e 100644 --- a/data/templates/accel-ppp/l2tp.config.j2 +++ b/data/templates/accel-ppp/l2tp.config.j2 @@ -51,6 +51,10 @@ host-name={{ lns.host_name }} {% if default_pool is vyos_defined %} ip-pool={{ default_pool }} {% endif %} +{% if default_ipv6_pool is vyos_defined %} +ipv6-pool={{ default_ipv6_pool }} +ipv6-pool-delegate={{ default_ipv6_pool }} +{% endif %} [client-ip-range] 0.0.0.0/0 diff --git a/data/templates/accel-ppp/pppoe.config.j2 b/data/templates/accel-ppp/pppoe.config.j2 index 4bb1c4450..fb8a11366 100644 --- a/data/templates/accel-ppp/pppoe.config.j2 +++ b/data/templates/accel-ppp/pppoe.config.j2 @@ -143,6 +143,10 @@ noauth=1 {% if default_pool is vyos_defined %} ip-pool={{ default_pool }} {% endif %} +{% if default_ipv6_pool is vyos_defined %} +ipv6-pool={{ default_ipv6_pool }} +ipv6-pool-delegate={{ default_ipv6_pool }} +{% endif %} {% if limits is vyos_defined %} [connlimit] diff --git a/data/templates/accel-ppp/sstp.config.j2 b/data/templates/accel-ppp/sstp.config.j2 index 014ae1235..51f7dfca8 100644 --- a/data/templates/accel-ppp/sstp.config.j2 +++ b/data/templates/accel-ppp/sstp.config.j2 @@ -39,6 +39,10 @@ ssl-keyfile=/run/accel-pppd/sstp-cert.key {% if default_pool is vyos_defined %} ip-pool={{ default_pool }} {% endif %} +{% if default_ipv6_pool is vyos_defined %} +ipv6-pool={{ default_ipv6_pool }} +ipv6-pool-delegate={{ default_ipv6_pool }} +{% endif %} {# Common IP pool definitions #} {% include 'accel-ppp/config_ip_pool.j2' %} diff --git a/data/templates/grub/grub_common.j2 b/data/templates/grub/grub_common.j2 index 29c2ab879..5e9b95cc0 100644 --- a/data/templates/grub/grub_common.j2 +++ b/data/templates/grub/grub_common.j2 @@ -8,7 +8,11 @@ fi function setup_serial { # initialize the first serial port by default if [ "${console_type}" == "ttyS" ]; then - serial --unit=${console_num} --speed=${console_speed} + if [ "${console_num}" == "0" ]; then + serial --unit=0 --speed=${console_speed} + else + serial --unit=${console_num} --speed=115200 + fi else serial --unit=0 --speed=${console_speed} fi diff --git a/data/templates/grub/grub_compat.j2 b/data/templates/grub/grub_compat.j2 index 887d5d0bd..d1085eec8 100644 --- a/data/templates/grub/grub_compat.j2 +++ b/data/templates/grub/grub_compat.j2 @@ -22,13 +22,13 @@ {%- endmacro %} {% macro console_opts(type) -%} {% if type == 'tty' -%} - console=ttyS0,115200 console=tty0 + console=ttyS0,{{ console_speed }} console=tty0 {%- elif type == 'ttyS' -%} - console=tty0 console=ttyS0,115200 + console=tty0 console=ttyS0,{{ console_speed }} {%- elif type == 'ttyUSB' -%} console=tty0 console=ttyUSB0,115200 {%- else -%} - console=tty0 console=ttyS0,115200 + console=tty0 console=ttyS0,{{ console_speed }} {%- endif %} {%- endmacro %} {% macro passwd_opts(mode) -%} @@ -39,9 +39,13 @@ set default={{ default }} set timeout={{ timeout }} {% if console_type == 'ttyS' %} +{% if console_num == '0' %} +serial --unit=0 --speed={{ console_speed }} +{% else %} serial --unit={{ console_num }} --speed=115200 +{% endif %} {% else %} -serial --unit=0 --speed=115200 +serial --unit=0 --speed={{ console_speed }} {% endif %} terminal_output --append serial terminal_input serial console diff --git a/data/templates/ipsec/swanctl/peer.j2 b/data/templates/ipsec/swanctl/peer.j2 index 9d95271fe..c5841fb91 100644 --- a/data/templates/ipsec/swanctl/peer.j2 +++ b/data/templates/ipsec/swanctl/peer.j2 @@ -83,10 +83,9 @@ start_action = none {% endif %} {% if ike.dead_peer_detection is vyos_defined %} -{% set dpd_translate = {'clear': 'clear', 'hold': 'trap', 'restart': 'restart'} %} - dpd_action = {{ dpd_translate[ike.dead_peer_detection.action] }} + dpd_action = {{ ike.dead_peer_detection.action }} {% endif %} - close_action = {{ {'none': 'none', 'hold': 'trap', 'restart': 'start'}[ike.close_action] }} + close_action = {{ ike.close_action }} } {% elif peer_conf.tunnel is vyos_defined %} {% for tunnel_id, tunnel_conf in peer_conf.tunnel.items() if tunnel_conf.disable is not defined %} @@ -134,10 +133,9 @@ start_action = none {% endif %} {% if ike.dead_peer_detection is vyos_defined %} -{% set dpd_translate = {'clear': 'clear', 'hold': 'trap', 'restart': 'restart'} %} - dpd_action = {{ dpd_translate[ike.dead_peer_detection.action] }} + dpd_action = {{ ike.dead_peer_detection.action }} {% endif %} - close_action = {{ {'none': 'none', 'hold': 'trap', 'restart': 'start'}[ike.close_action] }} + close_action = {{ ike.close_action }} {% if peer_conf.vti.bind is vyos_defined %} {# The key defaults to 0 and will match any policies which similarly do not have a lookup key configuration. #} {# Thus we simply shift the key by one to also support a vti0 interface #} diff --git a/interface-definitions/include/accel-ppp/client-ipv6-pool.xml.i b/interface-definitions/include/accel-ppp/client-ipv6-pool.xml.i index 774741a5e..0c8c2e34c 100644 --- a/interface-definitions/include/accel-ppp/client-ipv6-pool.xml.i +++ b/interface-definitions/include/accel-ppp/client-ipv6-pool.xml.i @@ -1,7 +1,14 @@ <!-- include start from accel-ppp/client-ipv6-pool.xml.i --> -<node name="client-ipv6-pool"> +<tagNode name="client-ipv6-pool"> <properties> <help>Pool of client IPv6 addresses</help> + <valueHelp> + <format>txt</format> + <description>Name of IPv6 pool</description> + </valueHelp> + <constraint> + #include <include/constraint/alpha-numeric-hyphen-underscore-dot.xml.i> + </constraint> </properties> <children> <tagNode name="prefix"> @@ -58,5 +65,5 @@ </children> </tagNode> </children> -</node> +</tagNode> <!-- include end --> diff --git a/interface-definitions/include/accel-ppp/default-ipv6-pool.xml.i b/interface-definitions/include/accel-ppp/default-ipv6-pool.xml.i new file mode 100644 index 000000000..1093f6713 --- /dev/null +++ b/interface-definitions/include/accel-ppp/default-ipv6-pool.xml.i @@ -0,0 +1,17 @@ +<!-- include start from accel-ppp/default-pool.xml.i --> +<leafNode name="default-ipv6-pool"> + <properties> + <help>Default client IPv6 pool name</help> + <completionHelp> + <path>${COMP_WORDS[@]:1:${#COMP_WORDS[@]}-3} client-ipv6-pool</path> + </completionHelp> + <valueHelp> + <format>txt</format> + <description>Default IPv6 pool</description> + </valueHelp> + <constraint> + #include <include/constraint/alpha-numeric-hyphen-underscore-dot.xml.i> + </constraint> + </properties> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/version/ipoe-server-version.xml.i b/interface-definitions/include/version/ipoe-server-version.xml.i index e5983ab39..659433382 100644 --- a/interface-definitions/include/version/ipoe-server-version.xml.i +++ b/interface-definitions/include/version/ipoe-server-version.xml.i @@ -1,3 +1,3 @@ <!-- include start from include/version/ipoe-server-version.xml.i --> -<syntaxVersion component='ipoe-server' version='2'></syntaxVersion> +<syntaxVersion component='ipoe-server' version='3'></syntaxVersion> <!-- include end --> diff --git a/interface-definitions/include/version/ipsec-version.xml.i b/interface-definitions/include/version/ipsec-version.xml.i index de7a9c088..a4d556cfc 100644 --- a/interface-definitions/include/version/ipsec-version.xml.i +++ b/interface-definitions/include/version/ipsec-version.xml.i @@ -1,3 +1,3 @@ <!-- include start from include/version/ipsec-version.xml.i --> -<syntaxVersion component='ipsec' version='12'></syntaxVersion> +<syntaxVersion component='ipsec' version='13'></syntaxVersion> <!-- include end --> diff --git a/interface-definitions/include/version/l2tp-version.xml.i b/interface-definitions/include/version/l2tp-version.xml.i index f4507d93b..793cd5d0c 100644 --- a/interface-definitions/include/version/l2tp-version.xml.i +++ b/interface-definitions/include/version/l2tp-version.xml.i @@ -1,3 +1,3 @@ <!-- include start from include/version/l2tp-version.xml.i --> -<syntaxVersion component='l2tp' version='6'></syntaxVersion> +<syntaxVersion component='l2tp' version='7'></syntaxVersion> <!-- include end --> diff --git a/interface-definitions/include/version/pppoe-server-version.xml.i b/interface-definitions/include/version/pppoe-server-version.xml.i index deed702f0..02f98cc16 100644 --- a/interface-definitions/include/version/pppoe-server-version.xml.i +++ b/interface-definitions/include/version/pppoe-server-version.xml.i @@ -1,3 +1,3 @@ <!-- include start from include/version/pppoe-server-version.xml.i --> -<syntaxVersion component='pppoe-server' version='7'></syntaxVersion> +<syntaxVersion component='pppoe-server' version='8'></syntaxVersion> <!-- include end --> diff --git a/interface-definitions/include/version/sstp-version.xml.i b/interface-definitions/include/version/sstp-version.xml.i index 3ac54a3de..5e30950d8 100644 --- a/interface-definitions/include/version/sstp-version.xml.i +++ b/interface-definitions/include/version/sstp-version.xml.i @@ -1,3 +1,3 @@ <!-- include start from include/version/sstp-version.xml.i --> -<syntaxVersion component='sstp' version='5'></syntaxVersion> +<syntaxVersion component='sstp' version='6'></syntaxVersion> <!-- include end --> diff --git a/interface-definitions/service_ipoe-server.xml.in b/interface-definitions/service_ipoe-server.xml.in index edfe6a34c..eeec2aeef 100644 --- a/interface-definitions/service_ipoe-server.xml.in +++ b/interface-definitions/service_ipoe-server.xml.in @@ -183,6 +183,7 @@ </children> </node> #include <include/accel-ppp/default-pool.xml.i> + #include <include/accel-ppp/default-ipv6-pool.xml.i> </children> </node> </children> diff --git a/interface-definitions/service_ndp-proxy.xml.in b/interface-definitions/service_ndp-proxy.xml.in index 9801c99ab..aabba3f4e 100644 --- a/interface-definitions/service_ndp-proxy.xml.in +++ b/interface-definitions/service_ndp-proxy.xml.in @@ -5,6 +5,7 @@ <node name="ndp-proxy" owner="${vyos_conf_scripts_dir}/service_ndp-proxy.py"> <properties> <help>Neighbor Discovery Protocol (NDP) Proxy</help> + <priority>600</priority> </properties> <children> <leafNode name="route-refresh"> diff --git a/interface-definitions/service_pppoe-server.xml.in b/interface-definitions/service_pppoe-server.xml.in index f1b369936..6fdc2a65a 100644 --- a/interface-definitions/service_pppoe-server.xml.in +++ b/interface-definitions/service_pppoe-server.xml.in @@ -274,6 +274,7 @@ </children> </node> #include <include/accel-ppp/default-pool.xml.i> + #include <include/accel-ppp/default-ipv6-pool.xml.i> </children> </node> </children> diff --git a/interface-definitions/system_config-management.xml.in b/interface-definitions/system_config-management.xml.in index 7ae347955..e666633b7 100644 --- a/interface-definitions/system_config-management.xml.in +++ b/interface-definitions/system_config-management.xml.in @@ -51,15 +51,7 @@ <multi/> </properties> </leafNode> - <leafNode name="source-address"> - <properties> - <help>Source address or interface for archive server connections</help> - <constraint> - <validator name="ip-address"/> - #include <include/constraint/interface-name.xml.i> - </constraint> - </properties> - </leafNode> + #include <include/source-address-ipv4-ipv6.xml.i> </children> </node> <leafNode name="commit-revisions"> diff --git a/interface-definitions/vpn_ipsec.xml.in b/interface-definitions/vpn_ipsec.xml.in index 1847401b5..9d1d5d824 100644 --- a/interface-definitions/vpn_ipsec.xml.in +++ b/interface-definitions/vpn_ipsec.xml.in @@ -251,22 +251,22 @@ <properties> <help>Action to take if a child SA is unexpectedly closed</help> <completionHelp> - <list>none hold restart</list> + <list>none trap start</list> </completionHelp> <valueHelp> <format>none</format> <description>Do nothing</description> </valueHelp> <valueHelp> - <format>hold</format> + <format>trap</format> <description>Attempt to re-negotiate when matching traffic is seen</description> </valueHelp> <valueHelp> - <format>restart</format> + <format>start</format> <description>Attempt to re-negotiate the connection immediately</description> </valueHelp> <constraint> - <regex>(none|hold|restart)</regex> + <regex>(none|trap|start)</regex> </constraint> </properties> <defaultValue>none</defaultValue> @@ -280,10 +280,10 @@ <properties> <help>Keep-alive failure action</help> <completionHelp> - <list>hold clear restart</list> + <list>trap clear restart</list> </completionHelp> <valueHelp> - <format>hold</format> + <format>trap</format> <description>Attempt to re-negotiate the connection when matching traffic is seen</description> </valueHelp> <valueHelp> @@ -295,7 +295,7 @@ <description>Attempt to re-negotiate the connection immediately</description> </valueHelp> <constraint> - <regex>(hold|clear|restart)</regex> + <regex>(trap|clear|restart)</regex> </constraint> </properties> <defaultValue>clear</defaultValue> diff --git a/interface-definitions/vpn_l2tp.xml.in b/interface-definitions/vpn_l2tp.xml.in index 3e2d00e6b..d3fb58433 100644 --- a/interface-definitions/vpn_l2tp.xml.in +++ b/interface-definitions/vpn_l2tp.xml.in @@ -154,6 +154,7 @@ </children> </node> #include <include/accel-ppp/default-pool.xml.i> + #include <include/accel-ppp/default-ipv6-pool.xml.i> </children> </node> </children> diff --git a/interface-definitions/vpn_pptp.xml.in b/interface-definitions/vpn_pptp.xml.in index 7bb8db798..ec622b5d0 100644 --- a/interface-definitions/vpn_pptp.xml.in +++ b/interface-definitions/vpn_pptp.xml.in @@ -134,6 +134,7 @@ </children> </node> #include <include/accel-ppp/default-pool.xml.i> + #include <include/accel-ppp/default-ipv6-pool.xml.i> </children> </node> </children> diff --git a/interface-definitions/vpn_sstp.xml.in b/interface-definitions/vpn_sstp.xml.in index a1b69f990..2727540be 100644 --- a/interface-definitions/vpn_sstp.xml.in +++ b/interface-definitions/vpn_sstp.xml.in @@ -36,6 +36,7 @@ <defaultValue>443</defaultValue> </leafNode> #include <include/accel-ppp/default-pool.xml.i> + #include <include/accel-ppp/default-ipv6-pool.xml.i> <node name="ppp-options"> <properties> <help>PPP (Point-to-Point Protocol) settings</help> diff --git a/python/vyos/accel_ppp_util.py b/python/vyos/accel_ppp_util.py index 757d447a2..2f029e042 100644 --- a/python/vyos/accel_ppp_util.py +++ b/python/vyos/accel_ppp_util.py @@ -1,4 +1,4 @@ -# Copyright 2023 VyOS maintainers and contributors <maintainers@vyos.io> +# Copyright 2023-2024 VyOS maintainers and contributors <maintainers@vyos.io> # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public @@ -22,9 +22,9 @@ # makes use of it! from vyos import ConfigError +from vyos.base import Warning from vyos.utils.dict import dict_search - def get_pools_in_order(data: dict) -> list: """Return a list of dictionaries representing pool data in the order in which they should be allocated. Pool must be defined before we can @@ -156,38 +156,47 @@ def verify_accel_ppp_base_service(config, local_users=True): "Not more then three IPv6 DNS name-servers " "can be configured" ) - if "client_ipv6_pool" in config: - ipv6_pool = config["client_ipv6_pool"] - if "delegate" in ipv6_pool: - if "prefix" not in ipv6_pool: - raise ConfigError( - 'IPv6 "delegate" also requires "prefix" to be defined!' - ) - - for delegate in ipv6_pool["delegate"]: - if "delegation_prefix" not in ipv6_pool["delegate"][delegate]: - raise ConfigError("delegation-prefix length required!") def verify_accel_ppp_ip_pool(vpn_config): """ Common helper function which must be used by Accel-PPP services (pptp, l2tp, sstp, pppoe) to verify client-ip-pool + and client-ipv6-pool """ if dict_search("client_ip_pool", vpn_config): for pool_name, pool_config in vpn_config["client_ip_pool"].items(): next_pool = dict_search(f"next_pool", pool_config) if next_pool: if next_pool not in vpn_config["client_ip_pool"]: - raise ConfigError(f'Next pool "{next_pool}" does not exist') + raise ConfigError( + f'Next pool "{next_pool}" does not exist') if not dict_search(f"range", pool_config): raise ConfigError( f'Pool "{pool_name}" does not contain range but next-pool exists' ) - if not dict_search("gateway_address", vpn_config): - raise ConfigError("Server requires gateway-address to be configured!") + Warning("IPv4 Server requires gateway-address to be configured!") + default_pool = dict_search("default_pool", vpn_config) if default_pool: if default_pool not in dict_search("client_ip_pool", vpn_config): raise ConfigError(f'Default pool "{default_pool}" does not exists') + + if 'client_ipv6_pool' in vpn_config: + for ipv6_pool, ipv6_pool_config in vpn_config['client_ipv6_pool'].items(): + if 'delegate' in ipv6_pool_config and 'prefix' not in ipv6_pool_config: + raise ConfigError( + f'IPoE IPv6 deletate-prefix requires IPv6 prefix to be configured in "{ipv6_pool}"!') + + if dict_search('authentication.mode', vpn_config) in ['local', 'noauth']: + if not dict_search('client_ip_pool', vpn_config) and not dict_search( + 'client_ipv6_pool', vpn_config): + raise ConfigError( + "L2TP local auth mode requires local client-ip-pool or client-ipv6-pool to be configured!") + if dict_search('client_ip_pool', vpn_config) and not dict_search( + 'default_pool', vpn_config): + Warning("'default-pool' is not defined") + if dict_search('client_ipv6_pool', vpn_config) and not dict_search( + 'default_ipv6_pool', vpn_config): + Warning("'default-ipv6-pool' is not defined") diff --git a/python/vyos/ifconfig/ethernet.py b/python/vyos/ifconfig/ethernet.py index aaf903acd..dde87149d 100644 --- a/python/vyos/ifconfig/ethernet.py +++ b/python/vyos/ifconfig/ethernet.py @@ -19,6 +19,7 @@ from glob import glob from vyos.base import Warning from vyos.ethtool import Ethtool +from vyos.ifconfig import Section from vyos.ifconfig.interface import Interface from vyos.utils.dict import dict_search from vyos.utils.file import read_file @@ -128,6 +129,10 @@ class EthernetIf(Interface): # will remain visible for the operating system. self.set_admin_state('down') + # Remove all VLAN subinterfaces - filter with the VLAN dot + for vlan in [x for x in Section.interfaces(self.iftype) if x.startswith(f'{self.ifname}.')]: + Interface(vlan).remove() + super().remove() def set_flow_control(self, enable): diff --git a/python/vyos/system/compat.py b/python/vyos/system/compat.py index 319c3dabf..436da14e8 100644 --- a/python/vyos/system/compat.py +++ b/python/vyos/system/compat.py @@ -27,7 +27,7 @@ TMPL_GRUB_COMPAT: str = 'grub/grub_compat.j2' # define regexes and variables REGEX_VERSION = r'^menuentry "[^\n]*{\n[^}]*\s+linux /boot/(?P<version>\S+)/[^}]*}' REGEX_MENUENTRY = r'^menuentry "[^\n]*{\n[^}]*\s+linux /boot/(?P<version>\S+)/vmlinuz (?P<options>[^\n]+)\n[^}]*}' -REGEX_CONSOLE = r'^.*console=(?P<console_type>[^\s\d]+)(?P<console_num>[\d]+).*$' +REGEX_CONSOLE = r'^.*console=(?P<console_type>[^\s\d]+)(?P<console_num>[\d]+)(,(?P<console_speed>[\d]+))?.*$' REGEX_SANIT_CONSOLE = r'\ ?console=[^\s\d]+[\d]+(,\d+)?\ ?' REGEX_SANIT_INIT = r'\ ?init=\S*\ ?' REGEX_SANIT_QUIET = r'\ ?quiet\ ?' @@ -131,6 +131,8 @@ def parse_entry(entry: tuple) -> dict: # find console type and number regex_filter = compile(REGEX_CONSOLE) entry_dict.update(regex_filter.match(entry[1]).groupdict()) + speed = entry_dict.get('console_speed', None) + entry_dict['console_speed'] = speed if speed is not None else '115200' entry_dict['boot_opts'] = sanitize_boot_opts(entry[1]) return entry_dict @@ -271,9 +273,11 @@ def grub_cfg_fields(root_dir: str = '') -> dict: root_dir = disk.find_persistence() grub_cfg_main = f'{root_dir}/{grub.GRUB_CFG_MAIN}' + grub_vars = f'{root_dir}/{grub.CFG_VYOS_VARS}' - fields = {'default': 0, 'timeout': 5} - # 'default' and 'timeout' from legacy grub.cfg + fields = grub.vars_read(grub_vars) + # 'default' and 'timeout' from legacy grub.cfg resets 'default' to + # index, rather than uuid fields |= grub.vars_read(grub_cfg_main) fields['tools_version'] = SYSTEM_CFG_VER diff --git a/python/vyos/system/grub.py b/python/vyos/system/grub.py index a94729964..781962dd0 100644 --- a/python/vyos/system/grub.py +++ b/python/vyos/system/grub.py @@ -354,5 +354,18 @@ def set_console_type(console_type: str, root_dir: str = '') -> None: vars_current['console_type'] = str(console_type) vars_write(vars_file, vars_current) -def set_raid(root_dir: str = '') -> None: - pass +def set_console_speed(console_speed: str, root_dir: str = '') -> None: + """Write default console speed to GRUB configuration + + Args: + console_speed (str): default console speed + root_dir (str, optional): an optional path to the root directory. + Defaults to empty. + """ + if not root_dir: + root_dir = disk.find_persistence() + + vars_file: str = f'{root_dir}/{CFG_VYOS_VARS}' + vars_current: dict[str, str] = vars_read(vars_file) + vars_current['console_speed'] = str(console_speed) + vars_write(vars_file, vars_current) diff --git a/python/vyos/system/grub_util.py b/python/vyos/system/grub_util.py new file mode 100644 index 000000000..9e79d41d4 --- /dev/null +++ b/python/vyos/system/grub_util.py @@ -0,0 +1,42 @@ +# Copyright 2024 VyOS maintainers and contributors <maintainers@vyos.io> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this library. If not, see <http://www.gnu.org/licenses/>. + +from vyos.system import disk, grub, compat + +@compat.grub_cfg_update +def set_console_speed(console_speed: str, root_dir: str = '') -> None: + """Write default console speed to GRUB configuration + + Args: + console_speed (str): default console speed + root_dir (str, optional): an optional path to the root directory. + Defaults to empty. + """ + if not root_dir: + root_dir = disk.find_persistence() + + grub.set_console_speed(console_speed, root_dir) + +def update_console_speed(console_speed: str, root_dir: str = '') -> None: + """Update console_speed if different from current value""" + + if not root_dir: + root_dir = disk.find_persistence() + + vars_file: str = f'{root_dir}/{grub.CFG_VYOS_VARS}' + vars_current: dict[str, str] = grub.vars_read(vars_file) + console_speed_current = vars_current.get('console_speed', None) + if console_speed != console_speed_current: + set_console_speed(console_speed, root_dir) diff --git a/smoketest/config-tests/bgp-medium-confederation b/smoketest/config-tests/bgp-medium-confederation new file mode 100644 index 000000000..ea3c2d144 --- /dev/null +++ b/smoketest/config-tests/bgp-medium-confederation @@ -0,0 +1,73 @@ +set interfaces dummy dum0 address '1.1.1.1/32' +set interfaces dummy dum0 address '2001:db8::1/128' +set interfaces ethernet eth0 address 'fd52:100:200:fffe::1/64' +set interfaces ethernet eth0 address '192.168.253.1/24' +set interfaces ethernet eth1 +set interfaces ethernet eth2 +set policy route-map BGP-IN rule 10 action 'permit' +set policy route-map BGP-OUT rule 10 action 'permit' +set policy route-map BGP-REDISTRIBUTE rule 10 action 'deny' +set policy route-map DEFAULT-ZEBRA-IN rule 10 action 'deny' +set protocols bgp address-family ipv4-unicast redistribute connected route-map 'BGP-REDISTRIBUTE' +set protocols bgp address-family ipv4-unicast redistribute static route-map 'BGP-REDISTRIBUTE' +set protocols bgp address-family ipv6-unicast redistribute connected route-map 'BGP-REDISTRIBUTE' +set protocols bgp neighbor 192.168.253.14 peer-group 'WDC07' +set protocols bgp neighbor 192.168.253.16 peer-group 'WDC07' +set protocols bgp neighbor 192.168.253.17 peer-group 'WDC07' +set protocols bgp neighbor 192.168.253.18 peer-group 'WDC07' +set protocols bgp neighbor 192.168.253.19 peer-group 'WDC07' +set protocols bgp neighbor eth1 interface v6only peer-group 'BACKBONE' +set protocols bgp neighbor eth1 interface v6only remote-as '666' +set protocols bgp neighbor eth2 interface v6only peer-group 'BACKBONE' +set protocols bgp neighbor eth2 interface v6only remote-as '666' +set protocols bgp neighbor fd52:100:200:fffe::14 address-family ipv6-unicast +set protocols bgp neighbor fd52:100:200:fffe::14 peer-group 'WDC07v6' +set protocols bgp neighbor fd52:100:200:fffe::16 address-family ipv6-unicast +set protocols bgp neighbor fd52:100:200:fffe::16 peer-group 'WDC07v6' +set protocols bgp neighbor fd52:100:200:fffe::17 address-family ipv6-unicast +set protocols bgp neighbor fd52:100:200:fffe::17 peer-group 'WDC07v6' +set protocols bgp neighbor fd52:100:200:fffe::18 address-family ipv6-unicast +set protocols bgp neighbor fd52:100:200:fffe::18 peer-group 'WDC07v6' +set protocols bgp neighbor fd52:100:200:fffe::19 address-family ipv6-unicast +set protocols bgp neighbor fd52:100:200:fffe::19 peer-group 'WDC07v6' +set protocols bgp parameters bestpath as-path confed +set protocols bgp parameters bestpath as-path multipath-relax +set protocols bgp parameters confederation identifier '696' +set protocols bgp parameters confederation peers '668' +set protocols bgp parameters confederation peers '669' +set protocols bgp parameters confederation peers '666' +set protocols bgp parameters graceful-restart +set protocols bgp parameters router-id '192.168.253.15' +set protocols bgp peer-group BACKBONE address-family ipv4-unicast nexthop-self +set protocols bgp peer-group BACKBONE address-family ipv4-unicast route-map export 'BGP-OUT' +set protocols bgp peer-group BACKBONE address-family ipv4-unicast route-map import 'BGP-IN' +set protocols bgp peer-group BACKBONE address-family ipv4-unicast soft-reconfiguration inbound +set protocols bgp peer-group BACKBONE address-family ipv6-unicast nexthop-self +set protocols bgp peer-group BACKBONE address-family ipv6-unicast route-map export 'BGP-OUT' +set protocols bgp peer-group BACKBONE address-family ipv6-unicast route-map import 'BGP-IN' +set protocols bgp peer-group BACKBONE address-family ipv6-unicast soft-reconfiguration inbound +set protocols bgp peer-group BACKBONE capability extended-nexthop +set protocols bgp peer-group WDC07 address-family ipv4-unicast default-originate +set protocols bgp peer-group WDC07 address-family ipv4-unicast nexthop-self +set protocols bgp peer-group WDC07 address-family ipv4-unicast route-map export 'BGP-OUT' +set protocols bgp peer-group WDC07 address-family ipv4-unicast route-map import 'BGP-IN' +set protocols bgp peer-group WDC07 address-family ipv4-unicast soft-reconfiguration inbound +set protocols bgp peer-group WDC07 remote-as '670' +set protocols bgp peer-group WDC07 update-source 'dum0' +set protocols bgp peer-group WDC07v6 address-family ipv6-unicast default-originate +set protocols bgp peer-group WDC07v6 address-family ipv6-unicast nexthop-self +set protocols bgp peer-group WDC07v6 address-family ipv6-unicast route-map export 'BGP-OUT' +set protocols bgp peer-group WDC07v6 address-family ipv6-unicast route-map import 'BGP-IN' +set protocols bgp peer-group WDC07v6 address-family ipv6-unicast soft-reconfiguration inbound +set protocols bgp peer-group WDC07v6 remote-as '670' +set protocols bgp peer-group WDC07v6 update-source 'dum0' +set protocols bgp system-as '670' +set system config-management commit-revisions '200' +set system console device ttyS0 speed '115200' +set system domain-name 'vyos.net' +set system host-name 'vyos' +set system ip protocol bgp route-map 'DEFAULT-ZEBRA-IN' +set system login user vyos authentication encrypted-password '$6$O5gJRlDYQpj$MtrCV9lxMnZPMbcxlU7.FI793MImNHznxGoMFgm3Q6QP3vfKJyOSRCt3Ka/GzFQyW1yZS4NS616NLHaIPPFHc0' +set system login user vyos authentication plaintext-password '' +set system syslog global facility all level 'notice' +set system syslog global facility local7 level 'debug' diff --git a/smoketest/configs/bgp-medium-confederation b/smoketest/configs/bgp-medium-confederation new file mode 100644 index 000000000..dfb944d09 --- /dev/null +++ b/smoketest/configs/bgp-medium-confederation @@ -0,0 +1,247 @@ +interfaces { + dummy dum0 { + address 1.1.1.1/32 + address 2001:db8::1/128 + } + ethernet eth0 { + address 192.168.253.1/24 + address fd52:100:200:fffe::1/64 + } + ethernet eth1 { + } + ethernet eth2 { + } +} +policy { + route-map BGP-IN { + rule 10 { + action permit + } + } + route-map BGP-OUT { + rule 10 { + action permit + } + } + route-map BGP-REDISTRIBUTE { + rule 10 { + action deny + } + } + route-map DEFAULT-ZEBRA-IN { + rule 10 { + action deny + } + } +} +protocols { + bgp 670 { + address-family { + ipv4-unicast { + redistribute { + connected { + route-map BGP-REDISTRIBUTE + } + static { + route-map BGP-REDISTRIBUTE + } + } + } + ipv6-unicast { + redistribute { + connected { + route-map BGP-REDISTRIBUTE + } + } + } + } + neighbor 192.168.253.14 { + peer-group WDC07 + } + neighbor 192.168.253.16 { + peer-group WDC07 + } + neighbor 192.168.253.17 { + peer-group WDC07 + } + neighbor 192.168.253.18 { + peer-group WDC07 + } + neighbor 192.168.253.19 { + peer-group WDC07 + } + neighbor eth1 { + interface { + v6only { + peer-group BACKBONE + remote-as 666 + } + } + } + neighbor eth2 { + interface { + v6only { + peer-group BACKBONE + remote-as 666 + } + } + } + neighbor fd52:100:200:fffe::14 { + address-family { + ipv6-unicast { + peer-group WDC07v6 + } + } + } + neighbor fd52:100:200:fffe::16 { + address-family { + ipv6-unicast { + peer-group WDC07v6 + } + } + } + neighbor fd52:100:200:fffe::17 { + address-family { + ipv6-unicast { + peer-group WDC07v6 + } + } + } + neighbor fd52:100:200:fffe::18 { + address-family { + ipv6-unicast { + peer-group WDC07v6 + } + } + } + neighbor fd52:100:200:fffe::19 { + address-family { + ipv6-unicast { + peer-group WDC07v6 + } + } + } + parameters { + bestpath { + as-path { + confed + multipath-relax + } + } + confederation { + identifier 696 + peers 668 + peers 669 + peers 666 + } + default { + no-ipv4-unicast + } + graceful-restart { + } + router-id 192.168.253.15 + } + peer-group BACKBONE { + address-family { + ipv4-unicast { + nexthop-self { + } + route-map { + export BGP-OUT + import BGP-IN + } + soft-reconfiguration { + inbound + } + } + ipv6-unicast { + nexthop-self { + } + route-map { + export BGP-OUT + import BGP-IN + } + soft-reconfiguration { + inbound + } + } + } + capability { + extended-nexthop + } + } + peer-group WDC07 { + address-family { + ipv4-unicast { + default-originate { + } + nexthop-self { + } + route-map { + export BGP-OUT + import BGP-IN + } + soft-reconfiguration { + inbound + } + } + } + remote-as 670 + update-source dum0 + } + peer-group WDC07v6 { + address-family { + ipv6-unicast { + default-originate { + } + nexthop-self { + } + route-map { + export BGP-OUT + import BGP-IN + } + soft-reconfiguration { + inbound + } + } + } + remote-as 670 + update-source dum0 + } + route-map DEFAULT-ZEBRA-IN + } +} +system { + config-management { + commit-revisions 200 + } + console { + device ttyS0 { + speed 115200 + } + } + domain-name vyos.net + host-name vyos + login { + user vyos { + authentication { + encrypted-password $6$O5gJRlDYQpj$MtrCV9lxMnZPMbcxlU7.FI793MImNHznxGoMFgm3Q6QP3vfKJyOSRCt3Ka/GzFQyW1yZS4NS616NLHaIPPFHc0 + plaintext-password "" + } + } + } + syslog { + global { + facility all { + level notice + } + facility protocols { + level debug + } + } + } +} + +// Warning: Do not remove the following line. +// vyos-config-version: "broadcast-relay@1:cluster@1:config-management@1:conntrack@3:conntrack-sync@2:container@1:dhcp-relay@2:dhcp-server@6:dhcpv6-server@1:dns-forwarding@3:firewall@5:https@2:interfaces@22:ipoe-server@1:ipsec@5:isis@1:l2tp@3:lldp@1:mdns@1:nat@5:ntp@1:pppoe-server@5:pptp@2:qos@1:quagga@8:rpki@1:salt@1:snmp@2:ssh@2:sstp@3:system@21:vrrp@2:vyos-accel-ppp@2:wanloadbalance@3:webproxy@2:zone-policy@1" +// Release version: 1.3.5 diff --git a/smoketest/scripts/cli/base_accel_ppp_test.py b/smoketest/scripts/cli/base_accel_ppp_test.py index 1ea5db898..6219a0a4c 100644 --- a/smoketest/scripts/cli/base_accel_ppp_test.py +++ b/smoketest/scripts/cli/base_accel_ppp_test.py @@ -1,4 +1,4 @@ -# Copyright (C) 2020-2023 VyOS maintainers and contributors +# Copyright (C) 2020-2024 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 @@ -441,3 +441,54 @@ class BasicAccelPPPTest: {second_subnet},name={second_pool},next={third_pool} {first_subnet},name={first_pool},next={second_pool}""" self.assertIn(pool_config, config) + + def test_accel_ipv6_pool(self): + # Test configuration of IPv6 client pools + self.basic_config(is_gateway=False, is_client_pool=False) + + # Enable IPv6 + allow_ipv6 = 'allow' + self.set(['ppp-options', 'ipv6', allow_ipv6]) + + pool_name = 'ipv6_test_pool' + prefix_1 = '2001:db8:fffe::/56' + prefix_mask = '64' + prefix_2 = '2001:db8:ffff::/56' + client_prefix_1 = f'{prefix_1},{prefix_mask}' + client_prefix_2 = f'{prefix_2},{prefix_mask}' + self.set( + ['client-ipv6-pool', pool_name, 'prefix', prefix_1, 'mask', + prefix_mask]) + self.set( + ['client-ipv6-pool', pool_name, 'prefix', prefix_2, 'mask', + prefix_mask]) + + delegate_1_prefix = '2001:db8:fff1::/56' + delegate_2_prefix = '2001:db8:fff2::/56' + delegate_mask = '64' + self.set( + ['client-ipv6-pool', pool_name, 'delegate', delegate_1_prefix, + 'delegation-prefix', delegate_mask]) + self.set( + ['client-ipv6-pool', pool_name, 'delegate', delegate_2_prefix, + 'delegation-prefix', delegate_mask]) + + # commit changes + self.cli_commit() + + # Validate configuration values + conf = ConfigParser(allow_no_value=True, delimiters='=', + strict=False) + conf.read(self._config_file) + + for tmp in ['ipv6pool', 'ipv6_nd', 'ipv6_dhcp']: + self.assertEqual(conf['modules'][tmp], None) + + self.assertEqual(conf['ppp']['ipv6'], allow_ipv6) + + config = self.getConfig("ipv6-pool") + pool_config = f"""{client_prefix_1},name={pool_name} +{client_prefix_2},name={pool_name} +delegate={delegate_1_prefix},{delegate_mask},name={pool_name} +delegate={delegate_2_prefix},{delegate_mask},name={pool_name}""" + self.assertIn(pool_config, config) diff --git a/smoketest/scripts/cli/test_service_ipoe-server.py b/smoketest/scripts/cli/test_service_ipoe-server.py index 6e95b3bd1..cec6adb09 100755 --- a/smoketest/scripts/cli/test_service_ipoe-server.py +++ b/smoketest/scripts/cli/test_service_ipoe-server.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2022-2023 VyOS maintainers and contributors +# Copyright (C) 2022-2024 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 @@ -188,6 +188,45 @@ gw-ip-address={third_gateway.split('/')[0]} {first_subnet},name={first_pool},next={second_pool}""" self.assertIn(pool_config, config) + def test_accel_ipv6_pool(self): + # Test configuration of IPv6 client pools + self.basic_config(is_gateway=False, is_client_pool=False) + + pool_name = 'ipv6_test_pool' + prefix_1 = '2001:db8:fffe::/56' + prefix_mask = '64' + prefix_2 = '2001:db8:ffff::/56' + client_prefix_1 = f'{prefix_1},{prefix_mask}' + client_prefix_2 = f'{prefix_2},{prefix_mask}' + self.set(['client-ipv6-pool', pool_name, 'prefix', prefix_1, 'mask', + prefix_mask]) + self.set(['client-ipv6-pool', pool_name, 'prefix', prefix_2, 'mask', + prefix_mask]) + + delegate_1_prefix = '2001:db8:fff1::/56' + delegate_2_prefix = '2001:db8:fff2::/56' + delegate_mask = '64' + self.set(['client-ipv6-pool', pool_name, 'delegate', delegate_1_prefix, + 'delegation-prefix', delegate_mask]) + self.set(['client-ipv6-pool', pool_name, 'delegate', delegate_2_prefix, + 'delegation-prefix', delegate_mask]) + + # commit changes + self.cli_commit() + + # Validate configuration values + conf = ConfigParser(allow_no_value=True, delimiters='=', strict=False) + conf.read(self._config_file) + + for tmp in ['ipv6pool', 'ipv6_nd', 'ipv6_dhcp']: + self.assertEqual(conf['modules'][tmp], None) + + config = self.getConfig("ipv6-pool") + pool_config = f"""{client_prefix_1},name={pool_name} +{client_prefix_2},name={pool_name} +delegate={delegate_1_prefix},{delegate_mask},name={pool_name} +delegate={delegate_2_prefix},{delegate_mask},name={pool_name}""" + self.assertIn(pool_config, config) if __name__ == "__main__": unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_service_pppoe-server.py b/smoketest/scripts/cli/test_service_pppoe-server.py index fa3bb87db..11d5b8b78 100755 --- a/smoketest/scripts/cli/test_service_pppoe-server.py +++ b/smoketest/scripts/cli/test_service_pppoe-server.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2022-2023 VyOS maintainers and contributors +# Copyright (C) 2022-2024 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 @@ -93,6 +93,13 @@ class TestServicePPPoEServer(BasicAccelPPPTest.TestCase): interface_cache = '128000' self.set(['ppp-options', 'interface-cache', interface_cache]) + # ipv6 + allow_ipv6 = 'allow' + random = 'random' + self.set(['ppp-options', 'ipv6', allow_ipv6]) + self.set(['ppp-options', 'ipv6-intf-id', random]) + self.set(['ppp-options', 'ipv6-accept-peer-intf-id']) + self.set(['ppp-options', 'ipv6-peer-intf-id', random]) # commit changes self.cli_commit() @@ -118,6 +125,15 @@ class TestServicePPPoEServer(BasicAccelPPPTest.TestCase): # check interface-cache self.assertEqual(conf['ppp']['unit-cache'], interface_cache) + #check ipv6 + for tmp in ['ipv6pool', 'ipv6_nd', 'ipv6_dhcp']: + self.assertEqual(conf['modules'][tmp], None) + + self.assertEqual(conf['ppp']['ipv6'], allow_ipv6) + self.assertEqual(conf['ppp']['ipv6-intf-id'], random) + self.assertEqual(conf['ppp']['ipv6-peer-intf-id'], random) + self.assertTrue(conf['ppp'].getboolean('ipv6-accept-peer-intf-id')) + def test_pppoe_server_authentication_protocols(self): # Test configuration of local authentication for PPPoE server self.basic_config() @@ -154,45 +170,6 @@ class TestServicePPPoEServer(BasicAccelPPPTest.TestCase): self.assertEqual(conf['shaper']['fwmark'], fwmark) self.assertEqual(conf['shaper']['down-limiter'], limiter) - def test_pppoe_server_client_ipv6_pool(self): - # Test configuration of IPv6 client pools - self.basic_config() - - # Enable IPv6 - allow_ipv6 = 'allow' - random = 'random' - self.set(['ppp-options', 'ipv6', allow_ipv6]) - self.set(['ppp-options', 'ipv6-intf-id', random]) - self.set(['ppp-options', 'ipv6-accept-peer-intf-id']) - self.set(['ppp-options', 'ipv6-peer-intf-id', random]) - - prefix = '2001:db8:ffff::/64' - prefix_mask = '128' - client_prefix = f'{prefix},{prefix_mask}' - self.set(['client-ipv6-pool', 'prefix', prefix, 'mask', prefix_mask]) - - delegate_prefix = '2001:db8::/40' - delegate_mask = '56' - self.set(['client-ipv6-pool', 'delegate', delegate_prefix, 'delegation-prefix', delegate_mask]) - - # commit changes - self.cli_commit() - - # Validate configuration values - conf = ConfigParser(allow_no_value=True, delimiters='=') - conf.read(self._config_file) - - for tmp in ['ipv6pool', 'ipv6_nd', 'ipv6_dhcp']: - self.assertEqual(conf['modules'][tmp], None) - - self.assertEqual(conf['ppp']['ipv6'], allow_ipv6) - self.assertEqual(conf['ppp']['ipv6-intf-id'], random) - self.assertEqual(conf['ppp']['ipv6-peer-intf-id'], random) - self.assertTrue(conf['ppp'].getboolean('ipv6-accept-peer-intf-id')) - - self.assertEqual(conf['ipv6-pool'][client_prefix], None) - self.assertEqual(conf['ipv6-pool']['delegate'], f'{delegate_prefix},{delegate_mask}') - def test_accel_radius_authentication(self): radius_called_sid = 'ifname:mac' diff --git a/smoketest/scripts/cli/test_vpn_l2tp.py b/smoketest/scripts/cli/test_vpn_l2tp.py index 5b3e419bd..129a9c602 100755 --- a/smoketest/scripts/cli/test_vpn_l2tp.py +++ b/smoketest/scripts/cli/test_vpn_l2tp.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2023 VyOS maintainers and contributors +# Copyright (C) 2023-2024 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 @@ -55,6 +55,13 @@ class TestVPNL2TPServer(BasicAccelPPPTest.TestCase): self.set(['ppp-options', 'lcp-echo-interval', lcp_echo_interval]) self.set(['ppp-options', 'lcp-echo-timeout', lcp_echo_timeout]) + allow_ipv6 = 'allow' + random = 'random' + self.set(['ppp-options', 'ipv6', allow_ipv6]) + self.set(['ppp-options', 'ipv6-intf-id', random]) + self.set(['ppp-options', 'ipv6-accept-peer-intf-id']) + self.set(['ppp-options', 'ipv6-peer-intf-id', random]) + # commit changes self.cli_commit() @@ -76,6 +83,13 @@ class TestVPNL2TPServer(BasicAccelPPPTest.TestCase): self.assertEqual(conf['ppp']['lcp-echo-timeout'], lcp_echo_timeout) self.assertEqual(conf['ppp']['lcp-echo-failure'], lcp_echo_failure) + for tmp in ['ipv6pool', 'ipv6_nd', 'ipv6_dhcp']: + self.assertEqual(conf['modules'][tmp], None) + self.assertEqual(conf['ppp']['ipv6'], allow_ipv6) + self.assertEqual(conf['ppp']['ipv6-intf-id'], random) + self.assertEqual(conf['ppp']['ipv6-peer-intf-id'], random) + self.assertTrue(conf['ppp'].getboolean('ipv6-accept-peer-intf-id')) + def test_l2tp_server_authentication_protocols(self): # Test configuration of local authentication for PPPoE server self.basic_config() @@ -92,44 +106,6 @@ class TestVPNL2TPServer(BasicAccelPPPTest.TestCase): self.assertEqual(conf['modules']['auth_mschap_v2'], None) - def test_l2tp_server_client_ipv6_pool(self): - # Test configuration of IPv6 client pools - self.basic_config() - - # Enable IPv6 - allow_ipv6 = 'allow' - random = 'random' - self.set(['ppp-options', 'ipv6', allow_ipv6]) - self.set(['ppp-options', 'ipv6-intf-id', random]) - self.set(['ppp-options', 'ipv6-accept-peer-intf-id']) - self.set(['ppp-options', 'ipv6-peer-intf-id', random]) - - prefix = '2001:db8:ffff::/64' - prefix_mask = '128' - client_prefix = f'{prefix},{prefix_mask}' - self.set(['client-ipv6-pool', 'prefix', prefix, 'mask', prefix_mask]) - - delegate_prefix = '2001:db8::/40' - delegate_mask = '56' - self.set(['client-ipv6-pool', 'delegate', delegate_prefix, 'delegation-prefix', delegate_mask]) - - # commit changes - self.cli_commit() - - # Validate configuration values - conf = ConfigParser(allow_no_value=True, delimiters='=') - conf.read(self._config_file) - - for tmp in ['ipv6pool', 'ipv6_nd', 'ipv6_dhcp']: - self.assertEqual(conf['modules'][tmp], None) - - self.assertEqual(conf['ppp']['ipv6'], allow_ipv6) - self.assertEqual(conf['ppp']['ipv6-intf-id'], random) - self.assertEqual(conf['ppp']['ipv6-peer-intf-id'], random) - self.assertTrue(conf['ppp'].getboolean('ipv6-accept-peer-intf-id')) - - self.assertEqual(conf['ipv6-pool'][client_prefix], None) - self.assertEqual(conf['ipv6-pool']['delegate'], f'{delegate_prefix},{delegate_mask}') if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_vpn_pptp.py b/smoketest/scripts/cli/test_vpn_pptp.py index 0d9ea312e..f3fce822b 100755 --- a/smoketest/scripts/cli/test_vpn_pptp.py +++ b/smoketest/scripts/cli/test_vpn_pptp.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2023 VyOS maintainers and contributors +# Copyright (C) 2023-2024 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 @@ -218,6 +218,10 @@ class TestVPNPPTPServer(BasicAccelPPPTest.TestCase): self.assertEqual(f"req-limit=0", server[4]) self.assertEqual(f"fail-time=0", server[5]) + @unittest.skip("IPv6 is not implemented in PPTP") + def test_accel_ipv6_pool(self): + pass + if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/src/conf_mode/protocols_bgp.py b/src/conf_mode/protocols_bgp.py index e8bb11828..f6f3370c3 100755 --- a/src/conf_mode/protocols_bgp.py +++ b/src/conf_mode/protocols_bgp.py @@ -220,9 +220,12 @@ def verify_afi(peer_config, bgp_config): # If address_family configured under peer-group # if neighbor interface configured - peer_group_name = '' + peer_group_name = None if dict_search('interface.peer_group', peer_config): peer_group_name = peer_config['interface']['peer_group'] + elif dict_search('interface.v6only.peer_group', peer_config): + peer_group_name = peer_config['interface']['v6only']['peer_group'] + # if neighbor IP configured. if 'peer_group' in peer_config: peer_group_name = peer_config['peer_group'] diff --git a/src/conf_mode/service_ipoe-server.py b/src/conf_mode/service_ipoe-server.py index 36f00dec5..6df6f3dc7 100755 --- a/src/conf_mode/service_ipoe-server.py +++ b/src/conf_mode/service_ipoe-server.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2018-2023 VyOS maintainers and contributors +# Copyright (C) 2018-2024 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 @@ -79,9 +79,6 @@ def verify(ipoe): if 'key' not in radius_config: raise ConfigError(f'Missing RADIUS secret key for server "{server}"') - if 'client_ipv6_pool' in ipoe: - if 'delegate' in ipoe['client_ipv6_pool'] and 'prefix' not in ipoe['client_ipv6_pool']: - raise ConfigError('IPoE IPv6 deletate-prefix requires IPv6 prefix to be configured!') return None diff --git a/src/conf_mode/service_pppoe-server.py b/src/conf_mode/service_pppoe-server.py index 7c624f034..31299a15c 100755 --- a/src/conf_mode/service_pppoe-server.py +++ b/src/conf_mode/service_pppoe-server.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2018-2023 VyOS maintainers and contributors +# Copyright (C) 2018-2024 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 @@ -85,6 +85,7 @@ def verify(pppoe): if not dict_search('authentication.radius.dynamic_author.key', pppoe): raise ConfigError('DA/CoE server key required!') + return None diff --git a/src/conf_mode/system_console.py b/src/conf_mode/system_console.py index ebf9a113b..a888b125e 100755 --- a/src/conf_mode/system_console.py +++ b/src/conf_mode/system_console.py @@ -22,6 +22,7 @@ from vyos.config import Config from vyos.utils.process import call from vyos.utils.file import read_file from vyos.utils.file import write_file +from vyos.system import grub_util from vyos.template import render from vyos import ConfigError from vyos import airbag @@ -114,30 +115,7 @@ def generate(console): return None speed = console['device']['ttyS0']['speed'] - grub_config = '/boot/grub/grub.cfg' - if not os.path.isfile(grub_config): - return None - - lines = read_file(grub_config).split('\n') - p = re.compile(r'^(.* console=ttyS0),[0-9]+(.*)$') - write = False - newlines = [] - for line in lines: - if line.startswith('serial --unit'): - newline = f'serial --unit=0 --speed={speed}' - elif p.match(line): - newline = '{},{}{}'.format(p.search(line)[1], speed, p.search(line)[2]) - else: - newline = line - - if newline != line: - write = True - - newlines.append(newline) - newlines.append('') - - if write: - write_file(grub_config, '\n'.join(newlines)) + grub_util.update_console_speed(speed) return None diff --git a/src/conf_mode/vpn_l2tp.py b/src/conf_mode/vpn_l2tp.py index 1a91951b4..b569ca140 100755 --- a/src/conf_mode/vpn_l2tp.py +++ b/src/conf_mode/vpn_l2tp.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2019-2023 VyOS maintainers and contributors +# Copyright (C) 2019-2024 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 @@ -70,15 +70,9 @@ def verify(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 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') diff --git a/src/conf_mode/vpn_pptp.py b/src/conf_mode/vpn_pptp.py index f769be39f..0629625bf 100755 --- a/src/conf_mode/vpn_pptp.py +++ b/src/conf_mode/vpn_pptp.py @@ -80,12 +80,6 @@ def verify(pptp): raise ConfigError( f'Missing RADIUS secret key for server "{server}"') - if auth_mode == 'local' or auth_mode == 'noauth': - if not dict_search('client_ip_pool', pptp): - raise ConfigError( - 'PPTP local auth mode requires local client-ip-pool ' - 'to be configured!') - verify_accel_ppp_ip_pool(pptp) if 'name_server' in pptp: diff --git a/src/conf_mode/vpn_sstp.py b/src/conf_mode/vpn_sstp.py index 6bf9307e1..a84513a0f 100755 --- a/src/conf_mode/vpn_sstp.py +++ b/src/conf_mode/vpn_sstp.py @@ -74,11 +74,8 @@ def verify(sstp): raise ConfigError(f'"{proto}" port "{port}" is used by another service') verify_accel_ppp_base_service(sstp) - - if 'client_ip_pool' not in sstp and 'client_ipv6_pool' not in sstp: - raise ConfigError('Client IP subnet required') - verify_accel_ppp_ip_pool(sstp) + # # SSL certificate checks # diff --git a/src/migration-scripts/bgp/0-to-1 b/src/migration-scripts/bgp/0-to-1 index 03c45107b..5b8e8a163 100755 --- a/src/migration-scripts/bgp/0-to-1 +++ b/src/migration-scripts/bgp/0-to-1 @@ -14,7 +14,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -# T3417: migrate IS-IS tagNode to node as we can only have one IS-IS process +# T3417: migrate BGP tagNode to node as we can only have one BGP process from sys import argv from sys import exit diff --git a/src/migration-scripts/bgp/1-to-2 b/src/migration-scripts/bgp/1-to-2 index 96b939b47..a40d86e67 100755 --- a/src/migration-scripts/bgp/1-to-2 +++ b/src/migration-scripts/bgp/1-to-2 @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2021-2022 VyOS maintainers and contributors +# Copyright (C) 2021-2024 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 @@ -15,6 +15,7 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. # T3741: no-ipv4-unicast is now enabled by default +# T5937: Migrate IPv6 BGP Neighbor Peer Groups from sys import argv from sys import exit @@ -66,6 +67,15 @@ else: if not config.exists(afi_ipv4): config.set(afi_ipv4) +# Migrate IPv6 AFI peer-group +if config.exists(base + ['neighbor']): + for neighbor in config.list_nodes(base + ['neighbor']): + tmp_path = base + ['neighbor', neighbor, 'address-family', 'ipv6-unicast', 'peer-group'] + if config.exists(tmp_path): + peer_group = config.return_value(tmp_path) + config.set(base + ['neighbor', neighbor, 'peer-group'], value=peer_group) + config.delete(tmp_path) + try: with open(file_name, 'w') as f: f.write(config.to_string()) diff --git a/src/migration-scripts/ipoe-server/2-to-3 b/src/migration-scripts/ipoe-server/2-to-3 new file mode 100755 index 000000000..d4ae0a7ba --- /dev/null +++ b/src/migration-scripts/ipoe-server/2-to-3 @@ -0,0 +1,61 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2024 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/>. + +# Migrating to named ipv6 pools + +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-ipv6-pool'] +if not config.exists(base): + exit(0) + +if not config.exists(pool_base): + exit(0) + +ipv6_pool_name = 'ipv6-pool' +config.copy(pool_base, pool_base + [ipv6_pool_name]) + +if config.exists(pool_base + ['prefix']): + config.delete(pool_base + ['prefix']) + config.set(base + ['default-ipv6-pool'], value=ipv6_pool_name) +if config.exists(pool_base + ['delegate']): + config.delete(pool_base + ['delegate']) + +# 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/ipsec/12-to-13 b/src/migration-scripts/ipsec/12-to-13 new file mode 100755 index 000000000..c11f708bd --- /dev/null +++ b/src/migration-scripts/ipsec/12-to-13 @@ -0,0 +1,59 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2024 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 value of dead-peer-detection.action from hold to trap +# Changed value of close-action from hold to trap and from restart to start + +import re + +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() + +base = ['vpn', 'ipsec', 'ike-group'] +config = ConfigTree(config_file) + +if not config.exists(base): + # Nothing to do + exit(0) +else: + for ike_group in config.list_nodes(base): + base_dpd_action = base + [ike_group, 'dead-peer-detection', 'action'] + base_close_action = base + [ike_group, 'close-action'] + if config.exists(base_dpd_action) and config.return_value(base_dpd_action) == 'hold': + config.set(base_dpd_action, 'trap', replace=True) + if config.exists(base_close_action): + if config.return_value(base_close_action) == 'hold': + config.set(base_close_action, 'trap', replace=True) + if config.return_value(base_close_action) == 'restart': + config.set(base_close_action, 'start', replace=True) + +try: + with open(file_name, 'w') as f: + f.write(config.to_string()) +except OSError as e: + print(f'Failed to save the modified config: {e}') + exit(1) diff --git a/src/migration-scripts/l2tp/6-to-7 b/src/migration-scripts/l2tp/6-to-7 new file mode 100755 index 000000000..f49c4ab08 --- /dev/null +++ b/src/migration-scripts/l2tp/6-to-7 @@ -0,0 +1,60 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2024 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/>. + +# Migrating to named ipv6 pools + +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', 'l2tp', 'remote-access'] +pool_base = base + ['client-ipv6-pool'] +if not config.exists(base): + exit(0) + +if not config.exists(pool_base): + exit(0) + +ipv6_pool_name = 'ipv6-pool' +config.copy(pool_base, pool_base + [ipv6_pool_name]) + +if config.exists(pool_base + ['prefix']): + config.delete(pool_base + ['prefix']) + config.set(base + ['default-ipv6-pool'], value=ipv6_pool_name) +if config.exists(pool_base + ['delegate']): + config.delete(pool_base + ['delegate']) +# 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/nat/5-to-6 b/src/migration-scripts/nat/5-to-6 index de3830582..c83b93d84 100755 --- a/src/migration-scripts/nat/5-to-6 +++ b/src/migration-scripts/nat/5-to-6 @@ -51,8 +51,9 @@ for direction in ['source', 'destination']: for iface in ['inbound-interface','outbound-interface']: if config.exists(base + [iface]): tmp = config.return_value(base + [iface]) - config.delete(base + [iface]) - config.set(base + [iface, 'interface-name'], value=tmp) + if tmp: + config.delete(base + [iface]) + config.set(base + [iface, 'interface-name'], value=tmp) try: with open(file_name, 'w') as f: diff --git a/src/migration-scripts/pppoe-server/7-to-8 b/src/migration-scripts/pppoe-server/7-to-8 new file mode 100755 index 000000000..b0d9bb464 --- /dev/null +++ b/src/migration-scripts/pppoe-server/7-to-8 @@ -0,0 +1,61 @@ +#!/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/>. + +# Migrating to named ipv6 pools + +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', 'pppoe-server'] +pool_base = base + ['client-ipv6-pool'] +if not config.exists(base): + exit(0) + +if not config.exists(pool_base): + exit(0) + +ipv6_pool_name = 'ipv6-pool' +config.copy(pool_base, pool_base + [ipv6_pool_name]) + +if config.exists(pool_base + ['prefix']): + config.delete(pool_base + ['prefix']) + config.set(base + ['default-ipv6-pool'], value=ipv6_pool_name) +if config.exists(pool_base + ['delegate']): + config.delete(pool_base + ['delegate']) + +# 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/5-to-6 b/src/migration-scripts/sstp/5-to-6 new file mode 100755 index 000000000..bac9975b2 --- /dev/null +++ b/src/migration-scripts/sstp/5-to-6 @@ -0,0 +1,62 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2024 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/>. + +# Migrating to named ipv6 pools + +import os +import pprint + +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-ipv6-pool'] +if not config.exists(base): + exit(0) + +if not config.exists(pool_base): + exit(0) + +ipv6_pool_name = 'ipv6-pool' +config.copy(pool_base, pool_base + [ipv6_pool_name]) + +if config.exists(pool_base + ['prefix']): + config.delete(pool_base + ['prefix']) + config.set(base + ['default-ipv6-pool'], value=ipv6_pool_name) +if config.exists(pool_base + ['delegate']): + config.delete(pool_base + ['delegate']) + +# 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/system/grub_update.py b/src/system/grub_update.py index 4d5e0b6ae..5a7d8eb72 100644 --- a/src/system/grub_update.py +++ b/src/system/grub_update.py @@ -69,7 +69,7 @@ if __name__ == '__main__': 'bootmode': default_entry['bootmode'], 'console_type': default_entry['console_type'], 'console_num': default_entry['console_num'], - 'console_speed': '115200' + 'console_speed': default_entry['console_speed'] } vars.update(default_settings) diff --git a/src/system/on-dhcp-event.sh b/src/system/on-dhcp-event.sh index e1a9f1884..3c11105d4 100755 --- a/src/system/on-dhcp-event.sh +++ b/src/system/on-dhcp-event.sh @@ -63,7 +63,7 @@ case "$action" in client_ip=${!client_ip_var} client_mac=${!client_mac_var} - client_name=${!client_name_var} + client_name=${!client_name_var//./} client_subnet_id=${!client_subnet_id_var} if [ -z "$client_name" ]; then |