summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/op-mode-standardized.json1
-rw-r--r--data/templates/accel-ppp/config_ip_pool.j212
-rw-r--r--data/templates/accel-ppp/pppoe.config.j213
-rw-r--r--interface-definitions/include/accel-ppp/client-ip-pool-name.xml.i18
-rw-r--r--interface-definitions/include/interface/authentication.xml.i8
-rw-r--r--interface-definitions/service-ipoe-server.xml.in17
-rw-r--r--interface-definitions/service-pppoe-server.xml.in1
-rw-r--r--op-mode-definitions/nhrp.xml.in4
-rw-r--r--python/vyos/configverify.py15
-rw-r--r--python/vyos/ifconfig/interface.py4
-rw-r--r--python/vyos/template.py20
-rwxr-xr-xsmoketest/scripts/cli/test_service_pppoe-server.py29
-rwxr-xr-xsrc/op_mode/nhrp.py101
13 files changed, 219 insertions, 24 deletions
diff --git a/data/op-mode-standardized.json b/data/op-mode-standardized.json
index abf562984..3b2599790 100644
--- a/data/op-mode-standardized.json
+++ b/data/op-mode-standardized.json
@@ -14,6 +14,7 @@
"memory.py",
"nat.py",
"neighbor.py",
+"nhrp.py",
"openconnect.py",
"openvpn.py",
"route.py",
diff --git a/data/templates/accel-ppp/config_ip_pool.j2 b/data/templates/accel-ppp/config_ip_pool.j2
index 0bef4ad69..f7511e445 100644
--- a/data/templates/accel-ppp/config_ip_pool.j2
+++ b/data/templates/accel-ppp/config_ip_pool.j2
@@ -11,4 +11,14 @@ gw-ip-address={{ gateway_address }}
{{ subnet }}
{% endfor %}
{% endif %}
-{% endif %}
+{% if client_ip_pool.name is vyos_defined %}
+{% for pool, pool_config in client_ip_pool.name.items() %}
+{% if pool_config.subnet is vyos_defined %}
+{{ pool_config.subnet }},name={{ pool }}
+{% endif %}
+{% if pool_config.gateway_address is vyos_defined %}
+gw-ip-address={{ pool_config.gateway_address }}
+{% endif %}
+{% endfor %}
+{% endif %}
+{% endif %} \ No newline at end of file
diff --git a/data/templates/accel-ppp/pppoe.config.j2 b/data/templates/accel-ppp/pppoe.config.j2
index c536bafa5..811c4ccc0 100644
--- a/data/templates/accel-ppp/pppoe.config.j2
+++ b/data/templates/accel-ppp/pppoe.config.j2
@@ -133,6 +133,19 @@ pado-delay={{ pado_delay_param.value }}
called-sid={{ authentication.radius.called_sid_format }}
{% endif %}
+{% if authentication.mode is vyos_defined("local") %}
+{% if client_ip_pool.name is vyos_defined %}
+{% for pool, pool_config in client_ip_pool.name.items() %}
+{% if pool_config.subnet is vyos_defined %}
+ip-pool={{ pool }}
+{% endif %}
+{% if pool_config.gateway_address is vyos_defined %}
+gw-ip-address={{ pool_config.gateway_address }}/{{ pool_config.subnet.split('/')[1] }}
+{% endif %}
+{% endfor %}
+{% endif %}
+{% endif %}
+
{% if limits is vyos_defined %}
[connlimit]
{% if limits.connection_limit is vyos_defined %}
diff --git a/interface-definitions/include/accel-ppp/client-ip-pool-name.xml.i b/interface-definitions/include/accel-ppp/client-ip-pool-name.xml.i
new file mode 100644
index 000000000..654b6727e
--- /dev/null
+++ b/interface-definitions/include/accel-ppp/client-ip-pool-name.xml.i
@@ -0,0 +1,18 @@
+<!-- include start from accel-ppp/client-ip-pool-name.xml.i -->
+<tagNode name="name">
+ <properties>
+ <help>Pool name</help>
+ <valueHelp>
+ <format>txt</format>
+ <description>Name of IP pool</description>
+ </valueHelp>
+ <constraint>
+ <regex>[-_a-zA-Z0-9.]+</regex>
+ </constraint>
+ </properties>
+ <children>
+ #include <include/accel-ppp/gateway-address.xml.i>
+ #include <include/accel-ppp/client-ip-pool-subnet-single.xml.i>
+ </children>
+</tagNode>
+<!-- include end -->
diff --git a/interface-definitions/include/interface/authentication.xml.i b/interface-definitions/include/interface/authentication.xml.i
index c097ca9dd..7d8352f2e 100644
--- a/interface-definitions/include/interface/authentication.xml.i
+++ b/interface-definitions/include/interface/authentication.xml.i
@@ -11,6 +11,10 @@
<format>txt</format>
<description>Username used for connection</description>
</valueHelp>
+ <constraint>
+ <regex>[[:alnum:]][-_#@[:alnum:]]{0,127}</regex>
+ </constraint>
+ <constraintErrorMessage>Username is limited to alphanumerical characters, -, _, #, and @ with a total lenght of 128</constraintErrorMessage>
</properties>
</leafNode>
<leafNode name="password">
@@ -20,6 +24,10 @@
<format>txt</format>
<description>Password used for connection</description>
</valueHelp>
+ <constraint>
+ <regex>[[:ascii:]]{1,128}</regex>
+ </constraint>
+ <constraintErrorMessage>Password is limited to ASCII characters only, with a total lenght of 128</constraintErrorMessage>
</properties>
</leafNode>
</children>
diff --git a/interface-definitions/service-ipoe-server.xml.in b/interface-definitions/service-ipoe-server.xml.in
index d778f9de0..ca4929249 100644
--- a/interface-definitions/service-ipoe-server.xml.in
+++ b/interface-definitions/service-ipoe-server.xml.in
@@ -108,22 +108,7 @@
<help>Client IP pools and gateway setting</help>
</properties>
<children>
- <tagNode name="name">
- <properties>
- <help>Pool name</help>
- <valueHelp>
- <format>txt</format>
- <description>Name of IP pool</description>
- </valueHelp>
- <constraint>
- <regex>[-_a-zA-Z0-9.]+</regex>
- </constraint>
- </properties>
- <children>
- #include <include/accel-ppp/gateway-address.xml.i>
- #include <include/accel-ppp/client-ip-pool-subnet-single.xml.i>
- </children>
- </tagNode>
+ #include <include/accel-ppp/client-ip-pool-name.xml.i>
</children>
</node>
#include <include/accel-ppp/client-ipv6-pool.xml.i>
diff --git a/interface-definitions/service-pppoe-server.xml.in b/interface-definitions/service-pppoe-server.xml.in
index 65e0f41c4..3fde07019 100644
--- a/interface-definitions/service-pppoe-server.xml.in
+++ b/interface-definitions/service-pppoe-server.xml.in
@@ -56,6 +56,7 @@
<children>
#include <include/accel-ppp/client-ip-pool-start-stop.xml.i>
#include <include/accel-ppp/client-ip-pool-subnet.xml.i>
+ #include <include/accel-ppp/client-ip-pool-name.xml.i>
</children>
</node>
#include <include/accel-ppp/client-ipv6-pool.xml.i>
diff --git a/op-mode-definitions/nhrp.xml.in b/op-mode-definitions/nhrp.xml.in
index c10b111a7..11a4b8814 100644
--- a/op-mode-definitions/nhrp.xml.in
+++ b/op-mode-definitions/nhrp.xml.in
@@ -50,13 +50,13 @@
<properties>
<help>Show NHRP interface connection information</help>
</properties>
- <command>if pgrep opennhrp >/dev/null; then sudo opennhrpctl interface show; else echo OpenNHRP is not running; fi</command>
+ <command>${vyos_op_scripts_dir}/nhrp.py show_interface</command>
</leafNode>
<leafNode name="tunnel">
<properties>
<help>Show NHRP tunnel connection information</help>
</properties>
- <command>if pgrep opennhrp >/dev/null; then sudo opennhrpctl show ; else echo OpenNHRP is not running; fi</command>
+ <command>${vyos_op_scripts_dir}/nhrp.py show_tunnel</command>
</leafNode>
</children>
</node>
diff --git a/python/vyos/configverify.py b/python/vyos/configverify.py
index 8e0ce701e..63edacc81 100644
--- a/python/vyos/configverify.py
+++ b/python/vyos/configverify.py
@@ -1,4 +1,4 @@
-# Copyright 2020-2022 VyOS maintainers and contributors <maintainers@vyos.io>
+# Copyright 2020-2023 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
@@ -23,6 +23,7 @@
from vyos import ConfigError
from vyos.util import dict_search
+from vyos.util import dict_search_recursive
def verify_mtu(config):
"""
@@ -414,7 +415,17 @@ def verify_accel_ppp_base_service(config, local_users=True):
if 'key' not in radius_config:
raise ConfigError(f'Missing RADIUS secret key for server "{server}"')
- if 'gateway_address' not in config:
+ # Check global gateway or gateway in named pool
+ gateway = False
+ if 'gateway_address' in config:
+ gateway = True
+ else:
+ if dict_search_recursive(config, 'gateway_address', ['client_ip_pool', 'name']):
+ for _, v in config['client_ip_pool']['name'].items():
+ if 'gateway_address' in v:
+ gateway = True
+ break
+ if not gateway:
raise ConfigError('Server requires gateway-address to be configured!')
if 'name_server_ipv4' in config:
diff --git a/python/vyos/ifconfig/interface.py b/python/vyos/ifconfig/interface.py
index c50ead89f..795df2462 100644
--- a/python/vyos/ifconfig/interface.py
+++ b/python/vyos/ifconfig/interface.py
@@ -751,8 +751,8 @@ class Interface(Control):
elif all_rp_filter == 2: global_setting = 'loose'
from vyos.base import Warning
- Warning(f'Global source-validation is set to "{global_setting} '\
- f'this overrides per interface setting!')
+ Warning(f'Global source-validation is set to "{global_setting}", this '\
+ f'overrides per interface setting on "{self.ifname}"!')
tmp = self.get_interface('rp_filter')
if int(tmp) == value:
diff --git a/python/vyos/template.py b/python/vyos/template.py
index 15240f815..6367f51e5 100644
--- a/python/vyos/template.py
+++ b/python/vyos/template.py
@@ -1,4 +1,4 @@
-# Copyright 2019-2022 VyOS maintainers and contributors <maintainers@vyos.io>
+# Copyright 2019-2023 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
@@ -158,6 +158,24 @@ def force_to_list(value):
else:
return [value]
+@register_filter('seconds_to_human')
+def seconds_to_human(seconds, separator=""):
+ """ Convert seconds to human-readable values like 1d6h15m23s """
+ from vyos.util import seconds_to_human
+ return seconds_to_human(seconds, separator=separator)
+
+@register_filter('bytes_to_human')
+def bytes_to_human(bytes, initial_exponent=0, precision=2):
+ """ Convert bytes to human-readable values like 1.44M """
+ from vyos.util import bytes_to_human
+ return bytes_to_human(bytes, initial_exponent=initial_exponent, precision=precision)
+
+@register_filter('human_to_bytes')
+def human_to_bytes(value):
+ """ Convert a data amount with a unit suffix to bytes, like 2K to 2048 """
+ from vyos.util import human_to_bytes
+ return human_to_bytes(value)
+
@register_filter('ip_from_cidr')
def ip_from_cidr(prefix):
""" Take an IPv4/IPv6 CIDR host and strip cidr mask.
diff --git a/smoketest/scripts/cli/test_service_pppoe-server.py b/smoketest/scripts/cli/test_service_pppoe-server.py
index 0b442067c..4f9181704 100755
--- a/smoketest/scripts/cli/test_service_pppoe-server.py
+++ b/smoketest/scripts/cli/test_service_pppoe-server.py
@@ -171,6 +171,35 @@ class TestServicePPPoEServer(BasicAccelPPPTest.TestCase):
self.assertEqual(conf['shaper']['down-limiter'], limiter)
+ def test_pppoe_server_client_ip_pool_name(self):
+ # Test configuration of named client pools
+ self.basic_config()
+
+ subnet = '192.0.2.0/24'
+ gateway = '192.0.2.1'
+ pool = 'VYOS'
+
+ subnet_name = f'{subnet},name'
+ gw_ip_prefix = f'{gateway}/24'
+
+ self.set(['client-ip-pool', 'name', pool, 'subnet', subnet])
+ self.set(['client-ip-pool', 'name', pool, 'gateway-address', gateway])
+ self.cli_delete(self._base_path + ['gateway-address'])
+
+ # commit changes
+ self.cli_commit()
+
+ # Validate configuration values
+ conf = ConfigParser(allow_no_value=True, delimiters='=')
+ conf.read(self._config_file)
+
+ # Validate configuration
+ self.assertEqual(conf['ip-pool'][subnet_name], pool)
+ self.assertEqual(conf['ip-pool']['gw-ip-address'], gateway)
+ self.assertEqual(conf['pppoe']['ip-pool'], pool)
+ self.assertEqual(conf['pppoe']['gw-ip-address'], gw_ip_prefix)
+
+
def test_pppoe_server_client_ipv6_pool(self):
# Test configuration of IPv6 client pools
self.basic_config()
diff --git a/src/op_mode/nhrp.py b/src/op_mode/nhrp.py
new file mode 100755
index 000000000..5ff91a59c
--- /dev/null
+++ b/src/op_mode/nhrp.py
@@ -0,0 +1,101 @@
+#!/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/>.
+
+import sys
+import tabulate
+import vyos.opmode
+
+from vyos.util import cmd
+from vyos.util import process_named_running
+from vyos.util import colon_separated_to_dict
+
+
+def _get_formatted_output(output_dict: dict) -> str:
+ """
+ Create formatted table for CLI output
+ :param output_dict: dictionary for API
+ :type output_dict: dict
+ :return: tabulate string
+ :rtype: str
+ """
+ print(f"Status: {output_dict['Status']}")
+ output: str = tabulate.tabulate(output_dict['routes'], headers='keys',
+ numalign="left")
+ return output
+
+
+def _get_formatted_dict(output_string: str) -> dict:
+ """
+ Format string returned from CMD to API list
+ :param output_string: String received by CMD
+ :type output_string: str
+ :return: dictionary for API
+ :rtype: dict
+ """
+ formatted_dict: dict = {
+ 'Status': '',
+ 'routes': []
+ }
+ output_list: list = output_string.split('\n\n')
+ for list_a in output_list:
+ output_dict = colon_separated_to_dict(list_a, True)
+ if 'Status' in output_dict:
+ formatted_dict['Status'] = output_dict['Status']
+ else:
+ formatted_dict['routes'].append(output_dict)
+ return formatted_dict
+
+
+def show_interface(raw: bool):
+ """
+ Command 'show nhrp interface'
+ :param raw: if API
+ :type raw: bool
+ """
+ if not process_named_running('opennhrp'):
+ raise vyos.opmode.UnconfiguredSubsystem('OpenNHRP is not running.')
+ interface_string: str = cmd('sudo opennhrpctl interface show')
+ interface_dict: dict = _get_formatted_dict(interface_string)
+ if raw:
+ return interface_dict
+ else:
+ return _get_formatted_output(interface_dict)
+
+
+def show_tunnel(raw: bool):
+ """
+ Command 'show nhrp tunnel'
+ :param raw: if API
+ :type raw: bool
+ """
+ if not process_named_running('opennhrp'):
+ raise vyos.opmode.UnconfiguredSubsystem('OpenNHRP is not running.')
+ tunnel_string: str = cmd('sudo opennhrpctl show')
+ tunnel_dict: list = _get_formatted_dict(tunnel_string)
+ if raw:
+ return tunnel_dict
+ else:
+ return _get_formatted_output(tunnel_dict)
+
+
+if __name__ == '__main__':
+ try:
+ res = vyos.opmode.run(sys.modules[__name__])
+ if res:
+ print(res)
+ except (ValueError, vyos.opmode.Error) as e:
+ print(e)
+ sys.exit(1)