diff options
| -rwxr-xr-x | debian/rules | 2 | ||||
| -rw-r--r-- | interface-definitions/include/version/conntrack-version.xml.i | 2 | ||||
| -rw-r--r-- | interface-definitions/service_ndp-proxy.xml.in | 1 | ||||
| -rw-r--r-- | interface-definitions/system_config-management.xml.in | 10 | ||||
| -rw-r--r--[-rwxr-xr-x] | op-mode-definitions/generate-system-login-user.xml.in | 0 | ||||
| -rw-r--r-- | python/vyos/ifconfig/ethernet.py | 5 | ||||
| -rw-r--r-- | python/vyos/qos/base.py | 50 | ||||
| -rw-r--r-- | python/vyos/utils/network.py | 2 | ||||
| -rwxr-xr-x | smoketest/scripts/cli/test_service_dhcp-server.py | 24 | ||||
| -rwxr-xr-x | smoketest/scripts/cli/test_system_conntrack.py | 8 | ||||
| -rwxr-xr-x | src/conf_mode/service_dhcp-server.py | 17 | ||||
| -rwxr-xr-x | src/system/on-dhcp-event.sh | 4 | 
12 files changed, 87 insertions, 38 deletions
| diff --git a/debian/rules b/debian/rules index 9a6ab2996..d007089a4 100755 --- a/debian/rules +++ b/debian/rules @@ -24,7 +24,7 @@ DEB_TARGET_ARCH := $(shell dpkg-architecture -qDEB_TARGET_ARCH)  override_dh_strip_nondeterminism:  override_dh_gencontrol: -	dh_gencontrol -- -v$(shell (git describe --tags --long --match 'vyos/*' --dirty 2>/dev/null || echo 0.0-no.git.tag) | sed -E 's%vyos/%%' | sed -E 's%-dirty%+dirty%') +	dh_gencontrol -- -v$(shell (git describe --tags --long --match 'vyos/*' --match '1.4.*' --dirty 2>/dev/null || echo 0.0-no.git.tag) | sed -E 's%vyos/%%' | sed -E 's%-dirty%+dirty%')  override_dh_auto_build:  	make all diff --git a/interface-definitions/include/version/conntrack-version.xml.i b/interface-definitions/include/version/conntrack-version.xml.i index c0f632c70..6995ce119 100644 --- a/interface-definitions/include/version/conntrack-version.xml.i +++ b/interface-definitions/include/version/conntrack-version.xml.i @@ -1,3 +1,3 @@  <!-- include start from include/version/conntrack-version.xml.i --> -<syntaxVersion component='conntrack' version='4'></syntaxVersion> +<syntaxVersion component='conntrack' version='5'></syntaxVersion>  <!-- include end --> 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/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/op-mode-definitions/generate-system-login-user.xml.in b/op-mode-definitions/generate-system-login-user.xml.in index 6f65c12b3..6f65c12b3 100755..100644 --- a/op-mode-definitions/generate-system-login-user.xml.in +++ b/op-mode-definitions/generate-system-login-user.xml.in 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/qos/base.py b/python/vyos/qos/base.py index d8bbfe970..a22039e52 100644 --- a/python/vyos/qos/base.py +++ b/python/vyos/qos/base.py @@ -1,4 +1,4 @@ -# Copyright 2022-2023 VyOS maintainers and contributors <maintainers@vyos.io> +# Copyright 2022-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 @@ -14,6 +14,7 @@  # License along with this library.  If not, see <http://www.gnu.org/licenses/>.  import os +import jmespath  from vyos.base import Warning  from vyos.utils.process import cmd @@ -166,14 +167,17 @@ class QoSBase:          }          if rate == 'auto' or rate.endswith('%'): -            speed = 10 +            speed = 1000 +            default_speed = speed              # Not all interfaces have valid entries in the speed file. PPPoE              # interfaces have the appropriate speed file, but you can not read it:              # cat: /sys/class/net/pppoe7/speed: Invalid argument              try:                  speed = read_file(f'/sys/class/net/{self._interface}/speed')                  if not speed.isnumeric(): -                    Warning('Interface speed cannot be determined (assuming 10 Mbit/s)') +                    Warning('Interface speed cannot be determined (assuming 1000 Mbit/s)') +                if int(speed) < 1: +                    speed = default_speed                  if rate.endswith('%'):                      percent = rate.rstrip('%')                      speed = int(speed) * int(percent) // 100 @@ -223,6 +227,9 @@ class QoSBase:                          if 'mark' in match_config:                              mark = match_config['mark']                              filter_cmd += f' handle {mark} fw' +                        if 'vif' in match_config: +                            vif = match_config['vif'] +                            filter_cmd += f' basic match "meta(vlan mask 0xfff eq {vif})"'                          for af in ['ip', 'ipv6']:                              tc_af = af @@ -298,23 +305,28 @@ class QoSBase:                                  filter_cmd += f' flowid {self._parent:x}:{cls:x}'                                  self._cmd(filter_cmd) +                    vlan_expression = "match.*.vif" +                    match_vlan = jmespath.search(vlan_expression, cls_config) +                      if any(tmp in ['exceed', 'bandwidth', 'burst'] for tmp in cls_config): -                        filter_cmd += f' action police' - -                        if 'exceed' in cls_config: -                            action = cls_config['exceed'] -                            filter_cmd += f' conform-exceed {action}' -                        if 'not_exceed' in cls_config: -                            action = cls_config['not_exceed'] -                            filter_cmd += f'/{action}' - -                        if 'bandwidth' in cls_config: -                            rate = self._rate_convert(cls_config['bandwidth']) -                            filter_cmd += f' rate {rate}' - -                        if 'burst' in cls_config: -                            burst = cls_config['burst'] -                            filter_cmd += f' burst {burst}' +                        # For "vif" "basic match" is used instead of "action police" T5961 +                        if not match_vlan: +                            filter_cmd += f' action police' + +                            if 'exceed' in cls_config: +                                action = cls_config['exceed'] +                                filter_cmd += f' conform-exceed {action}' +                            if 'not_exceed' in cls_config: +                                action = cls_config['not_exceed'] +                                filter_cmd += f'/{action}' + +                            if 'bandwidth' in cls_config: +                                rate = self._rate_convert(cls_config['bandwidth']) +                                filter_cmd += f' rate {rate}' + +                            if 'burst' in cls_config: +                                burst = cls_config['burst'] +                                filter_cmd += f' burst {burst}'                          cls = int(cls)                          filter_cmd += f' flowid {self._parent:x}:{cls:x}'                          self._cmd(filter_cmd) diff --git a/python/vyos/utils/network.py b/python/vyos/utils/network.py index b782e0bd8..cac59475d 100644 --- a/python/vyos/utils/network.py +++ b/python/vyos/utils/network.py @@ -159,7 +159,9 @@ def is_wwan_connected(interface):      """ Determine if a given WWAN interface, e.g. wwan0 is connected to the      carrier network or not """      import json +    from vyos.utils.dict import dict_search      from vyos.utils.process import cmd +    from vyos.utils.process import is_systemd_service_active      if not interface.startswith('wwan'):          raise ValueError(f'Specified interface "{interface}" is not a WWAN interface') diff --git a/smoketest/scripts/cli/test_service_dhcp-server.py b/smoketest/scripts/cli/test_service_dhcp-server.py index 3e6adb149..849a411f1 100755 --- a/smoketest/scripts/cli/test_service_dhcp-server.py +++ b/smoketest/scripts/cli/test_service_dhcp-server.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2020-2021 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 @@ -383,12 +383,30 @@ class TestServiceDHCPServer(VyOSUnitTestSHIM.TestCase):          self.cli_delete(pool + ['static-mapping', 'client1', 'duid'])          # cannot have mappings with duplicate IP addresses +        self.cli_set(pool + ['static-mapping', 'dupe1', 'mac', '00:50:00:00:fe:ff']) +        self.cli_set(pool + ['static-mapping', 'dupe1', 'ip-address', inc_ip(subnet, 10)])          with self.assertRaises(ConfigSessionError): -            self.cli_set(pool + ['static-mapping', 'dupe1', 'mac', '00:50:00:00:00:01']) -            self.cli_set(pool + ['static-mapping', 'dupe1', 'ip-address', inc_ip(subnet, 10)])              self.cli_commit()          self.cli_delete(pool + ['static-mapping', 'dupe1']) +        # cannot have mappings with duplicate MAC addresses +        self.cli_set(pool + ['static-mapping', 'dupe2', 'mac', '00:50:00:00:00:10']) +        self.cli_set(pool + ['static-mapping', 'dupe2', 'ip-address', inc_ip(subnet, 120)]) +        with self.assertRaises(ConfigSessionError): +            self.cli_commit() +        self.cli_delete(pool + ['static-mapping', 'dupe2']) + + +        # cannot have mappings with duplicate MAC addresses +        self.cli_set(pool + ['static-mapping', 'dupe3', 'duid', '00:01:02:03:04:05:06:07:aa:aa:aa:aa:aa:01']) +        self.cli_set(pool + ['static-mapping', 'dupe3', 'ip-address', inc_ip(subnet, 121)]) +        self.cli_set(pool + ['static-mapping', 'dupe4', 'duid', '00:01:02:03:04:05:06:07:aa:aa:aa:aa:aa:01']) +        self.cli_set(pool + ['static-mapping', 'dupe4', 'ip-address', inc_ip(subnet, 121)]) +        with self.assertRaises(ConfigSessionError): +            self.cli_commit() +        self.cli_delete(pool + ['static-mapping', 'dupe3']) +        self.cli_delete(pool + ['static-mapping', 'dupe4']) +          # commit changes          self.cli_commit() diff --git a/smoketest/scripts/cli/test_system_conntrack.py b/smoketest/scripts/cli/test_system_conntrack.py index 0dbc97d49..cea34138e 100755 --- a/smoketest/scripts/cli/test_system_conntrack.py +++ b/smoketest/scripts/cli/test_system_conntrack.py @@ -31,6 +31,14 @@ def get_sysctl(parameter):      return read_file(f'/proc/sys/{tmp}')  class TestSystemConntrack(VyOSUnitTestSHIM.TestCase): +    @classmethod +    def setUpClass(cls): +        super(TestSystemConntrack, cls).setUpClass() + +        # ensure we can also run this test on a live system - so lets clean +        # out the current configuration :) +        cls.cli_delete(cls, base_path) +      def tearDown(self):          self.cli_delete(base_path)          self.cli_commit() diff --git a/src/conf_mode/service_dhcp-server.py b/src/conf_mode/service_dhcp-server.py index 2418c8faa..9632b91fc 100755 --- a/src/conf_mode/service_dhcp-server.py +++ b/src/conf_mode/service_dhcp-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 @@ -233,6 +233,8 @@ def verify(dhcp):              if 'static_mapping' in subnet_config:                  # Static mappings require just a MAC address (will use an IP from the dynamic pool if IP is not set)                  used_ips = [] +                used_mac = [] +                used_duid = []                  for mapping, mapping_config in subnet_config['static_mapping'].items():                      if 'ip_address' in mapping_config:                          if ip_address(mapping_config['ip_address']) not in ip_network(subnet): @@ -245,10 +247,19 @@ def verify(dhcp):                                                f'static mapping "{mapping}" within shared-network "{network}, {subnet}"!')                          if mapping_config['ip_address'] in used_ips: -                            raise ConfigError(f'Configured IP address for static mapping "{mapping}" exists on another static mapping') - +                            raise ConfigError(f'Configured IP address for static mapping "{mapping}" already exists on another static mapping')                          used_ips.append(mapping_config['ip_address']) +                    if 'mac' in mapping_config: +                        if mapping_config['mac'] in used_mac: +                            raise ConfigError(f'Configured MAC address for static mapping "{mapping}" already exists on another static mapping') +                        used_mac.append(mapping_config['mac']) + +                    if 'duid' in mapping_config: +                        if mapping_config['duid'] in used_duid: +                            raise ConfigError(f'Configured DUID for static mapping "{mapping}" already exists on another static mapping') +                        used_duid.append(mapping_config['duid']) +              # There must be one subnet connected to a listen interface.              # This only counts if the network itself is not disabled!              if 'disable' not in network_config: diff --git a/src/system/on-dhcp-event.sh b/src/system/on-dhcp-event.sh index 3c11105d4..52fadd428 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 @@ -73,7 +73,7 @@ case "$action" in        client_domain=$(get_subnet_domain_name $client_subnet_id) -      if [ -n "$client_domain" ]; then +      if [[ -n "$client_domain" ]] && ! [[ $client_name =~ .*$client_domain$ ]]; then          client_name="$client_name.$client_domain"        fi | 
