diff options
-rw-r--r-- | data/templates/dhcp-client/override.conf.j2 | 2 | ||||
-rw-r--r-- | data/templates/frr/bgpd.frr.j2 | 3 | ||||
-rw-r--r-- | data/vyos-firewall-init.conf | 4 | ||||
-rw-r--r-- | interface-definitions/include/bgp/afi-label.xml.i | 13 | ||||
-rw-r--r-- | interface-definitions/include/interface/per-client-thread.xml.i | 8 | ||||
-rw-r--r-- | interface-definitions/include/radius-server-key.xml.i | 8 | ||||
-rw-r--r-- | interface-definitions/interfaces-wireguard.xml.in | 1 | ||||
-rw-r--r-- | interface-definitions/interfaces-wireless.xml.in | 1 | ||||
-rw-r--r-- | interface-definitions/system-login.xml.in | 7 | ||||
-rw-r--r-- | op-mode-definitions/monitor-log.xml.in | 6 | ||||
-rw-r--r-- | op-mode-definitions/show-log.xml.in | 6 | ||||
-rw-r--r-- | python/vyos/ifconfig/interface.py | 39 | ||||
-rw-r--r-- | python/vyos/ifconfig/wireguard.py | 4 | ||||
-rwxr-xr-x | smoketest/scripts/cli/test_interfaces_wireguard.py | 37 | ||||
-rwxr-xr-x | smoketest/scripts/cli/test_protocols_bgp.py | 2 | ||||
-rwxr-xr-x | src/conf_mode/firewall.py | 35 | ||||
-rwxr-xr-x | src/conf_mode/interfaces-wireguard.py | 6 | ||||
-rwxr-xr-x | src/conf_mode/interfaces-wireless.py | 2 |
18 files changed, 132 insertions, 52 deletions
diff --git a/data/templates/dhcp-client/override.conf.j2 b/data/templates/dhcp-client/override.conf.j2 index 03fd71bf1..d09320270 100644 --- a/data/templates/dhcp-client/override.conf.j2 +++ b/data/templates/dhcp-client/override.conf.j2 @@ -10,6 +10,6 @@ ConditionPathExists={{ isc_dhclient_dir }}/dhclient_%i.conf ExecStart= ExecStart={{ vrf_command }}/sbin/dhclient -4 {{ dhclient_options }} {{ ifname }} ExecStop= -ExecStop=/sbin/dhclient -4 -r {{ dhclient_options }} {{ ifname }} +ExecStop={{ vrf_command }}/sbin/dhclient -4 -r {{ dhclient_options }} {{ ifname }} WorkingDirectory={{ isc_dhclient_dir }} PIDFile={{ isc_dhclient_dir }}/dhclient_%i.pid diff --git a/data/templates/frr/bgpd.frr.j2 b/data/templates/frr/bgpd.frr.j2 index 4535758da..7fa974254 100644 --- a/data/templates/frr/bgpd.frr.j2 +++ b/data/templates/frr/bgpd.frr.j2 @@ -349,6 +349,9 @@ router bgp {{ system_as }} {{ 'vrf ' ~ vrf if vrf is vyos_defined }} {% if afi_config.label.vpn.export is vyos_defined %} label vpn export {{ afi_config.label.vpn.export }} {% endif %} +{% if afi_config.label.vpn.allocation_mode.per_nexthop is vyos_defined %} + label vpn export allocation-mode per-nexthop +{% endif %} {% if afi_config.local_install is vyos_defined %} {% for interface in afi_config.local_install.interface %} local-install {{ interface }} diff --git a/data/vyos-firewall-init.conf b/data/vyos-firewall-init.conf index 11a5bc7bf..36d92fe93 100644 --- a/data/vyos-firewall-init.conf +++ b/data/vyos-firewall-init.conf @@ -20,7 +20,7 @@ table raw { } chain PREROUTING { - type filter hook prerouting priority -200; policy accept; + type filter hook prerouting priority -300; policy accept; counter jump VYOS_CT_IGNORE counter jump VYOS_CT_TIMEOUT counter jump VYOS_CT_PREROUTING_HOOK @@ -29,7 +29,7 @@ table raw { } chain OUTPUT { - type filter hook output priority -200; policy accept; + type filter hook output priority -300; policy accept; counter jump VYOS_CT_IGNORE counter jump VYOS_CT_TIMEOUT counter jump VYOS_CT_OUTPUT_HOOK diff --git a/interface-definitions/include/bgp/afi-label.xml.i b/interface-definitions/include/bgp/afi-label.xml.i index 9535d19e8..2c5eed18b 100644 --- a/interface-definitions/include/bgp/afi-label.xml.i +++ b/interface-definitions/include/bgp/afi-label.xml.i @@ -29,6 +29,19 @@ </constraint> </properties> </leafNode> + <node name="allocation-mode"> + <properties> + <help>Label allocation mode</help> + </properties> + <children> + <leafNode name="per-nexthop"> + <properties> + <help>Allocate a label per connected next-hop in the VRF</help> + <valueless/> + </properties> + </leafNode> + </children> + </node> </children> </node> </children> diff --git a/interface-definitions/include/interface/per-client-thread.xml.i b/interface-definitions/include/interface/per-client-thread.xml.i new file mode 100644 index 000000000..2fd19b5ce --- /dev/null +++ b/interface-definitions/include/interface/per-client-thread.xml.i @@ -0,0 +1,8 @@ +<!-- include start from interface/per-client-thread.xml.i --> +<leafNode name="per-client-thread"> + <properties> + <help>Process traffic from each client in a dedicated thread</help> + <valueless/> + </properties> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/radius-server-key.xml.i b/interface-definitions/include/radius-server-key.xml.i index c6301646b..dd5cdb0c6 100644 --- a/interface-definitions/include/radius-server-key.xml.i +++ b/interface-definitions/include/radius-server-key.xml.i @@ -2,6 +2,14 @@ <leafNode name="key"> <properties> <help>Shared secret key</help> + <valueHelp> + <format>txt</format> + <description>Password string (key)</description> + </valueHelp> + <constraint> + <regex>[[:ascii:]]{1,128}</regex> + </constraint> + <constraintErrorMessage>Password must be less then 128 characters</constraintErrorMessage> </properties> </leafNode> <!-- include end --> diff --git a/interface-definitions/interfaces-wireguard.xml.in b/interface-definitions/interfaces-wireguard.xml.in index 2dd5b47d1..3c79cef28 100644 --- a/interface-definitions/interfaces-wireguard.xml.in +++ b/interface-definitions/interfaces-wireguard.xml.in @@ -120,6 +120,7 @@ </children> </tagNode> #include <include/interface/redirect.xml.i> + #include <include/interface/per-client-thread.xml.i> #include <include/interface/vrf.xml.i> </children> </tagNode> diff --git a/interface-definitions/interfaces-wireless.xml.in b/interface-definitions/interfaces-wireless.xml.in index a9538d577..421d46c6e 100644 --- a/interface-definitions/interfaces-wireless.xml.in +++ b/interface-definitions/interfaces-wireless.xml.in @@ -778,6 +778,7 @@ </properties> <defaultValue>monitor</defaultValue> </leafNode> + #include <include/interface/per-client-thread.xml.i> #include <include/interface/redirect.xml.i> #include <include/interface/vif.xml.i> #include <include/interface/vif-s.xml.i> diff --git a/interface-definitions/system-login.xml.in b/interface-definitions/system-login.xml.in index d772c7821..71db8b1d6 100644 --- a/interface-definitions/system-login.xml.in +++ b/interface-definitions/system-login.xml.in @@ -184,6 +184,13 @@ <leafNode name="home-directory"> <properties> <help>Home directory</help> + <valueHelp> + <format>txt</format> + <description>Path to home directory</description> + </valueHelp> + <constraint> + <regex>\/$|(\/[a-zA-Z_0-9-.]+)+</regex> + </constraint> </properties> </leafNode> </children> diff --git a/op-mode-definitions/monitor-log.xml.in b/op-mode-definitions/monitor-log.xml.in index ee52a7eb8..52b5b85d4 100644 --- a/op-mode-definitions/monitor-log.xml.in +++ b/op-mode-definitions/monitor-log.xml.in @@ -36,6 +36,12 @@ </properties> <command>journalctl --no-hostname --follow --boot --unit conntrackd.service</command> </leafNode> + <leafNode name="console-server"> + <properties> + <help>Monitor last lines of console server log</help> + </properties> + <command>journalctl --no-hostname --follow --boot --unit conserver-server.service</command> + </leafNode> <node name="dhcp"> <properties> <help>Monitor last lines of Dynamic Host Control Protocol log</help> diff --git a/op-mode-definitions/show-log.xml.in b/op-mode-definitions/show-log.xml.in index 925a780ac..747622db6 100644 --- a/op-mode-definitions/show-log.xml.in +++ b/op-mode-definitions/show-log.xml.in @@ -50,6 +50,12 @@ </properties> <command>journalctl --no-hostname --boot --unit conntrackd.service</command> </leafNode> + <leafNode name="console-server"> + <properties> + <help>Show log for console server</help> + </properties> + <command>journalctl --no-hostname --boot --unit conserver-server.service</command> + </leafNode> <node name="ids"> <properties> <help>Show log for for Intrusion Detection System</help> diff --git a/python/vyos/ifconfig/interface.py b/python/vyos/ifconfig/interface.py index cc6149428..ddac387e7 100644 --- a/python/vyos/ifconfig/interface.py +++ b/python/vyos/ifconfig/interface.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 @@ -224,6 +224,10 @@ class Interface(Control): 'validate': lambda link: assert_range(link,0,3), 'location': '/proc/sys/net/ipv4/conf/{ifname}/link_filter', }, + 'per_client_thread': { + 'validate': assert_boolean, + 'location': '/sys/class/net/{ifname}/threaded', + }, } _sysfs_get = { @@ -275,6 +279,10 @@ class Interface(Control): 'link_detect': { 'location': '/proc/sys/net/ipv4/conf/{ifname}/link_filter', }, + 'per_client_thread': { + 'validate': assert_boolean, + 'location': '/sys/class/net/{ifname}/threaded', + }, } @classmethod @@ -1386,6 +1394,30 @@ class Interface(Control): f'egress redirect dev {target_if}') if err: print('tc filter add for redirect failed') + def set_per_client_thread(self, enable): + """ + Per-device control to enable/disable the threaded mode for all the napi + instances of the given network device, without the need for a device up/down. + + User sets it to 1 or 0 to enable or disable threaded mode. + + Example: + >>> from vyos.ifconfig import Interface + >>> Interface('wg1').set_per_client_thread(1) + """ + # In the case of a "virtual" interface like wireguard, the sysfs + # node is only created once there is a peer configured. We can now + # add a verify() code-path for this or make this dynamic without + # nagging the user + tmp = self._sysfs_get['per_client_thread']['location'] + if not os.path.exists(tmp): + return None + + tmp = self.get_interface('per_client_thread') + if tmp == enable: + return None + self.set_interface('per_client_thread', enable) + def update(self, config): """ General helper function which works on a dictionary retrived by get_config_dict(). It's main intention is to consolidate the scattered @@ -1601,6 +1633,11 @@ class Interface(Control): # configure interface mirror or redirection target self.set_mirror_redirect() + # enable/disable NAPI threading mode + tmp = dict_search('per_client_thread', config) + value = '1' if (tmp != None) else '0' + self.set_per_client_thread(value) + # Enable/Disable of an interface must always be done at the end of the # derived class to make use of the ref-counting set_admin_state() # function. We will only enable the interface if 'up' was called as diff --git a/python/vyos/ifconfig/wireguard.py b/python/vyos/ifconfig/wireguard.py index fe5e9c519..4aac103ec 100644 --- a/python/vyos/ifconfig/wireguard.py +++ b/python/vyos/ifconfig/wireguard.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 @@ -25,6 +25,7 @@ from hurry.filesize import alternative from vyos.ifconfig import Interface from vyos.ifconfig import Operational from vyos.template import is_ipv6 +from vyos.base import Warning class WireGuardOperational(Operational): def _dump(self): @@ -184,7 +185,6 @@ class WireGuardIf(Interface): base_cmd += f' private-key {tmp_file.name}' base_cmd = base_cmd.format(**config) - if 'peer' in config: for peer, peer_config in config['peer'].items(): # T4702: No need to configure this peer when it was explicitly diff --git a/smoketest/scripts/cli/test_interfaces_wireguard.py b/smoketest/scripts/cli/test_interfaces_wireguard.py index f84ce159d..48c7cb6a1 100755 --- a/smoketest/scripts/cli/test_interfaces_wireguard.py +++ b/smoketest/scripts/cli/test_interfaces_wireguard.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2020-2021 VyOS maintainers and contributors +# Copyright (C) 2020-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 @@ -19,6 +19,7 @@ import unittest from base_vyostest_shim import VyOSUnitTestSHIM from vyos.configsession import ConfigSessionError +from vyos.utils.file import read_file base_path = ['interfaces', 'wireguard'] @@ -35,7 +36,7 @@ class WireGuardInterfaceTest(VyOSUnitTestSHIM.TestCase): self.cli_delete(base_path) self.cli_commit() - def test_wireguard_peer(self): + def test_01_wireguard_peer(self): # Create WireGuard interfaces with associated peers for intf in self._interfaces: peer = 'foo-' + intf @@ -62,7 +63,7 @@ class WireGuardInterfaceTest(VyOSUnitTestSHIM.TestCase): self.assertTrue(os.path.isdir(f'/sys/class/net/{intf}')) - def test_wireguard_add_remove_peer(self): + def test_02_wireguard_add_remove_peer(self): # T2939: Create WireGuard interfaces with associated peers. # Remove one of the configured peers. # T4774: Test prevention of duplicate peer public keys @@ -100,10 +101,9 @@ class WireGuardInterfaceTest(VyOSUnitTestSHIM.TestCase): self.cli_delete(base_path + [interface, 'peer', 'PEER01']) self.cli_commit() - def test_wireguard_same_public_key(self): - # T2939: Create WireGuard interfaces with associated peers. - # Remove one of the configured peers. - # T4774: Test prevention of duplicate peer public keys + def test_03_wireguard_same_public_key(self): + # T5413: Test prevention of equality interface public key and peer's + # public key interface = 'wg0' port = '12345' privkey = 'OOjcXGfgQlAuM6q8Z9aAYduCua7pxf7UKYvIqoUPoGQ=' @@ -129,5 +129,28 @@ class WireGuardInterfaceTest(VyOSUnitTestSHIM.TestCase): self.assertTrue(os.path.isdir(f'/sys/class/net/{interface}')) + def test_04_wireguard_threaded(self): + # T5409: Test adding threaded option on interface. + # Test prevention for adding threaded + # if no enabled peer is configured. + interface = 'wg0' + port = '12345' + privkey = 'OOjcXGfgQlAuM6q8Z9aAYduCua7pxf7UKYvIqoUPoGQ=' + pubkey = 'ebFx/1G0ti8tvuZd94sEIosAZZIznX+dBAKG/8DFm0I=' + + self.cli_set(base_path + [interface, 'address', '172.16.0.1/24']) + self.cli_set(base_path + [interface, 'private-key', privkey]) + + self.cli_set(base_path + [interface, 'peer', 'PEER01', 'port', port]) + self.cli_set(base_path + [interface, 'peer', 'PEER01', 'public-key', pubkey]) + self.cli_set(base_path + [interface, 'peer', 'PEER01', 'allowed-ips', '10.205.212.10/32']) + self.cli_set(base_path + [interface, 'peer', 'PEER01', 'address', '192.0.2.1']) + self.cli_set(base_path + [interface, 'per-client-thread']) + + # Commit peers + self.cli_commit() + tmp = read_file(f'/sys/class/net/{interface}/threaded') + self.assertTrue(tmp, "1") + if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_protocols_bgp.py b/smoketest/scripts/cli/test_protocols_bgp.py index 5b247a413..77952d8d9 100755 --- a/smoketest/scripts/cli/test_protocols_bgp.py +++ b/smoketest/scripts/cli/test_protocols_bgp.py @@ -868,6 +868,7 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase): self.cli_set(base_path + ['address-family', afi, 'export', 'vpn']) self.cli_set(base_path + ['address-family', afi, 'import', 'vpn']) self.cli_set(base_path + ['address-family', afi, 'label', 'vpn', 'export', label]) + self.cli_set(base_path + ['address-family', afi, 'label', 'vpn', 'allocation-mode', 'per-nexthop']) self.cli_set(base_path + ['address-family', afi, 'rd', 'vpn', 'export', rd]) self.cli_set(base_path + ['address-family', afi, 'route-map', 'vpn', 'export', route_map_out]) self.cli_set(base_path + ['address-family', afi, 'route-map', 'vpn', 'import', route_map_in]) @@ -887,6 +888,7 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase): self.assertIn(f' export vpn', afi_config) self.assertIn(f' import vpn', afi_config) self.assertIn(f' label vpn export {label}', afi_config) + self.assertIn(f' label vpn export allocation-mode per-nexthop', afi_config) self.assertIn(f' rd vpn export {rd}', afi_config) self.assertIn(f' route-map vpn export {route_map_out}', afi_config) self.assertIn(f' route-map vpn import {route_map_in}', afi_config) diff --git a/src/conf_mode/firewall.py b/src/conf_mode/firewall.py index e946704b3..8ad3f27fc 100755 --- a/src/conf_mode/firewall.py +++ b/src/conf_mode/firewall.py @@ -351,39 +351,6 @@ def apply_sysfs(firewall): with open(path, 'w') as f: f.write(value) -def post_apply_trap(firewall): - if 'first_install' in firewall: - return None - - if not process_named_running('snmpd'): - return None - - trap_username = os.getlogin() - - for host, target_conf in firewall['trap_targets'].items(): - community = target_conf['community'] if 'community' in target_conf else 'public' - port = int(target_conf['port']) if 'port' in target_conf else 162 - - base_cmd = f'snmptrap -v2c -c {community} {host}:{port} 0 {snmp_trap_mib}::{snmp_trap_name} ' - - for change_type, changes in firewall['trap_diff'].items(): - for path_str, value in changes.items(): - objects = [ - f'mgmtEventUser s "{trap_username}"', - f'mgmtEventSource i {snmp_event_source}', - f'mgmtEventType i {snmp_change_type[change_type]}' - ] - - if change_type == 'add': - objects.append(f'mgmtEventCurrCfg s "{path_str} {value}"') - elif change_type == 'delete': - objects.append(f'mgmtEventPrevCfg s "{path_str} {value}"') - elif change_type == 'change': - objects.append(f'mgmtEventPrevCfg s "{path_str} {value[0]}"') - objects.append(f'mgmtEventCurrCfg s "{path_str} {value[1]}"') - - cmd(base_cmd + ' '.join(objects)) - def apply(firewall): install_result, output = rc_cmd(f'nft -f {nftables_conf}') if install_result == 1: @@ -408,8 +375,6 @@ def apply(firewall): print('Updating GeoIP. Please wait...') geoip_update(firewall) - post_apply_trap(firewall) - return None if __name__ == '__main__': diff --git a/src/conf_mode/interfaces-wireguard.py b/src/conf_mode/interfaces-wireguard.py index 446399255..122d9589a 100755 --- a/src/conf_mode/interfaces-wireguard.py +++ b/src/conf_mode/interfaces-wireguard.py @@ -90,7 +90,6 @@ def verify(wireguard): # run checks on individual configured WireGuard peer public_keys = [] - for tmp in wireguard['peer']: peer = wireguard['peer'][tmp] @@ -107,8 +106,9 @@ def verify(wireguard): if peer['public_key'] in public_keys: raise ConfigError(f'Duplicate public-key defined on peer "{tmp}"') - if 'disable' not in peer and is_wireguard_key_pair(wireguard['private_key'], peer['public_key']): - raise ConfigError(f'Peer "{tmp}" has the same public key as the interface "{wireguard["ifname"]}"') + if 'disable' not in peer: + if is_wireguard_key_pair(wireguard['private_key'], peer['public_key']): + raise ConfigError(f'Peer "{tmp}" has the same public key as the interface "{wireguard["ifname"]}"') public_keys.append(peer['public_key']) diff --git a/src/conf_mode/interfaces-wireless.py b/src/conf_mode/interfaces-wireless.py index e49ad25ac..29ab9713f 100755 --- a/src/conf_mode/interfaces-wireless.py +++ b/src/conf_mode/interfaces-wireless.py @@ -116,7 +116,7 @@ def verify(wifi): raise ConfigError('You must specify a WiFi mode') if 'ssid' not in wifi and wifi['type'] != 'monitor': - raise ConfigError('SSID must be configured') + raise ConfigError('SSID must be configured unless type is set to "monitor"!') if wifi['type'] == 'access-point': if 'country_code' not in wifi: |