From 83a9ce7991195c709736eec234fea3d60cde7582 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Tue, 22 Sep 2020 18:37:00 +0200 Subject: ifconfig: T2653: bond: bridge: ensure member interface is not a source-interface As we already check that a bond/bridge member interface is not a member of any other bridge or bond, the check must be extended. We also need to ensure that the bond member interface is not used as a source-interface to pppoe, macsec, tunnel, pseudo-ethernet, vxlan interfaces. --- python/vyos/configverify.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'python/vyos/configverify.py') diff --git a/python/vyos/configverify.py b/python/vyos/configverify.py index 7e1930878..bf4e26fa7 100644 --- a/python/vyos/configverify.py +++ b/python/vyos/configverify.py @@ -82,9 +82,20 @@ def verify_source_interface(config): if 'source_interface' not in config: raise ConfigError('Physical source-interface required for ' 'interface "{ifname}"'.format(**config)) + if config['source_interface'] not in interfaces(): - raise ConfigError('Source interface {source_interface} does not ' - 'exist'.format(**config)) + raise ConfigError('Specified source-interface {source_interface} does ' + 'not exist'.format(**config)) + + if 'source_interface_is_bridge_member' in config: + raise ConfigError('Invalid source-interface {source_interface}. Interface ' + 'is already a member of bridge ' + '{source_interface_is_bridge_member}'.format(**config)) + + if 'source_interface_is_bond_member' in config: + raise ConfigError('Invalid source-interface {source_interface}. Interface ' + 'is already a member of bond ' + '{source_interface_is_bond_member}'.format(**config)) def verify_dhcpv6(config): """ -- cgit v1.2.3 From 7f09beeac924b1bc9bf61f8153870bd4cb939b96 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Thu, 24 Sep 2020 21:31:47 +0200 Subject: dhcpv6-pd: verify: T2923: interface is required where the prefix is assigned When configuring DHCPv6-PD it is mandatory to also specify at least one interface where the newly delegated prefix will be used. Without this setting DHCPv6-PD makes no sense at all. --- python/vyos/configverify.py | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'python/vyos/configverify.py') diff --git a/python/vyos/configverify.py b/python/vyos/configverify.py index bf4e26fa7..afa6c7f06 100644 --- a/python/vyos/configverify.py +++ b/python/vyos/configverify.py @@ -113,6 +113,11 @@ def verify_dhcpv6(config): # assigned IPv6 subnet from a delegated prefix for pd in vyos_dict_search('dhcpv6_options.pd', config): sla_ids = [] + + if not vyos_dict_search(f'dhcpv6_options.pd.{pd}.interface', config): + raise ConfigError('DHCPv6-PD requires an interface where to assign ' + 'the delegated prefix!') + for interface in vyos_dict_search(f'dhcpv6_options.pd.{pd}.interface', config): sla_id = vyos_dict_search( f'dhcpv6_options.pd.{pd}.interface.{interface}.sla_id', config) -- cgit v1.2.3 From 9b268012252a4fe6f253177830abde950e2773b5 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Fri, 25 Sep 2020 20:57:37 +0200 Subject: ifconfig: T2912: add helper to verify interface min/max supported MTU Currently the MTU size of an interface is only checked when entered via CLI but if the interface supportes the configured MTU at all is not verified at all. New helper functions get_min_mtu(), get_max_mtu() and verify_mtu() have been added to provide a central API for validation. --- python/vyos/configverify.py | 21 +++++++++++++++++++++ python/vyos/ifconfig/interface.py | 4 ++-- 2 files changed, 23 insertions(+), 2 deletions(-) (limited to 'python/vyos/configverify.py') diff --git a/python/vyos/configverify.py b/python/vyos/configverify.py index afa6c7f06..6e5ba1df0 100644 --- a/python/vyos/configverify.py +++ b/python/vyos/configverify.py @@ -23,6 +23,27 @@ from vyos import ConfigError +def verify_mtu(config): + """ + Common helper function used by interface implementations to perform + recurring validation if the specified MTU can be used by the underlaying + hardware. + """ + from vyos.ifconfig import Interface + if 'mtu' in config: + mtu = int(config['mtu']) + + tmp = Interface(config['ifname']) + min_mtu = tmp.get_min_mtu() + max_mtu = tmp.get_max_mtu() + + if mtu < min_mtu: + raise ConfigError(f'Interface MTU too low, ' \ + f'minimum supported MTU is {min_mtu}!') + if mtu > max_mtu: + raise ConfigError(f'Interface MTU too high, ' \ + f'maximum supported MTU is {max_mtu}!') + def verify_vrf(config): """ Common helper function used by interface implementations to perform diff --git a/python/vyos/ifconfig/interface.py b/python/vyos/ifconfig/interface.py index a0f0ffe04..d200fc7a8 100644 --- a/python/vyos/ifconfig/interface.py +++ b/python/vyos/ifconfig/interface.py @@ -299,7 +299,7 @@ class Interface(Control): >>> Interface('eth0').get_min_mtu() '60' """ - return self.get_interface('min_mtu') + return int(self.get_interface('min_mtu')) def get_max_mtu(self): """ @@ -310,7 +310,7 @@ class Interface(Control): >>> Interface('eth0').get_max_mtu() '9000' """ - return self.get_interface('max_mtu') + return int(self.get_interface('max_mtu')) def get_mtu(self): """ -- cgit v1.2.3 From 5db3d63160670c796ed74a170862c367048d89bb Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sat, 26 Sep 2020 12:00:06 +0200 Subject: ifconfig: mtu: disallow MTU < 1280 bytes when IPv6 is enabled on the interface Using an MTU less then the required 1280 bytes (as per RFC) on an interface where IPv6 is not explicitly disabled by: - set interfaces ethernet eth1 ipv6 address no-default-link-local - not having any other IPv6 address configured Will now trigger a commit error via verify() instead of raising FileNotFoundError! --- python/vyos/configverify.py | 30 ++++++++++++++++++++++++++++++ src/conf_mode/interfaces-bonding.py | 2 ++ src/conf_mode/interfaces-bridge.py | 2 ++ src/conf_mode/interfaces-ethernet.py | 3 +++ src/conf_mode/interfaces-geneve.py | 2 ++ src/conf_mode/interfaces-l2tpv3.py | 2 ++ src/conf_mode/interfaces-macsec.py | 2 ++ src/conf_mode/interfaces-pppoe.py | 2 ++ src/conf_mode/interfaces-vxlan.py | 2 ++ src/conf_mode/interfaces-wireguard.py | 2 ++ 10 files changed, 49 insertions(+) (limited to 'python/vyos/configverify.py') diff --git a/python/vyos/configverify.py b/python/vyos/configverify.py index 6e5ba1df0..944fc4294 100644 --- a/python/vyos/configverify.py +++ b/python/vyos/configverify.py @@ -44,6 +44,36 @@ def verify_mtu(config): raise ConfigError(f'Interface MTU too high, ' \ f'maximum supported MTU is {max_mtu}!') +def verify_mtu_ipv6(config): + """ + Common helper function used by interface implementations to perform + recurring validation if the specified MTU can be used when IPv6 is + configured on the interface. IPv6 requires a 1280 bytes MTU. + """ + from vyos.validate import is_ipv6 + from vyos.util import vyos_dict_search + # IPv6 minimum required link mtu + min_mtu = 1280 + + if int(config['mtu']) < min_mtu: + interface = config['ifname'] + error_msg = f'IPv6 address will be configured on interface "{interface}" ' \ + f'thus the minimum MTU requirement is {min_mtu}!' + + if not vyos_dict_search('ipv6.address.no_default_link_local', config): + raise ConfigError('link-local ' + error_msg) + + for address in (vyos_dict_search('address', config) or []): + if address in ['dhcpv6'] or is_ipv6(address): + raise ConfigError(error_msg) + + if vyos_dict_search('ipv6.address.autoconf', config): + raise ConfigError(error_msg) + + if vyos_dict_search('ipv6.address.eui64', config): + raise ConfigError(error_msg) + + def verify_vrf(config): """ Common helper function used by interface implementations to perform diff --git a/src/conf_mode/interfaces-bonding.py b/src/conf_mode/interfaces-bonding.py index aece2a04b..9763620ac 100755 --- a/src/conf_mode/interfaces-bonding.py +++ b/src/conf_mode/interfaces-bonding.py @@ -28,6 +28,7 @@ from vyos.configverify import verify_address from vyos.configverify import verify_bridge_delete from vyos.configverify import verify_dhcpv6 from vyos.configverify import verify_source_interface +from vyos.configverify import verify_mtu_ipv6 from vyos.configverify import verify_vlan_config from vyos.configverify import verify_vrf from vyos.ifconfig import BondIf @@ -141,6 +142,7 @@ def verify(bond): raise ConfigError('Option primary - mode dependency failed, not' 'supported in mode {mode}!'.format(**bond)) + verify_mtu_ipv6(bond) verify_address(bond) verify_dhcpv6(bond) verify_vrf(bond) diff --git a/src/conf_mode/interfaces-bridge.py b/src/conf_mode/interfaces-bridge.py index 485decb17..4ac9c8963 100755 --- a/src/conf_mode/interfaces-bridge.py +++ b/src/conf_mode/interfaces-bridge.py @@ -25,6 +25,7 @@ from vyos.configdict import node_changed from vyos.configdict import is_member from vyos.configdict import is_source_interface from vyos.configverify import verify_dhcpv6 +from vyos.configverify import verify_mtu_ipv6 from vyos.configverify import verify_vrf from vyos.ifconfig import BridgeIf from vyos.validate import has_address_configured @@ -95,6 +96,7 @@ def verify(bridge): if 'deleted' in bridge: return None + verify_mtu_ipv6(bridge) verify_dhcpv6(bridge) verify_vrf(bridge) diff --git a/src/conf_mode/interfaces-ethernet.py b/src/conf_mode/interfaces-ethernet.py index 5468c7bda..1f622c003 100755 --- a/src/conf_mode/interfaces-ethernet.py +++ b/src/conf_mode/interfaces-ethernet.py @@ -24,6 +24,7 @@ from vyos.configverify import verify_address from vyos.configverify import verify_dhcpv6 from vyos.configverify import verify_interface_exists from vyos.configverify import verify_mtu +from vyos.configverify import verify_mtu_ipv6 from vyos.configverify import verify_vlan_config from vyos.configverify import verify_vrf from vyos.ifconfig import EthernetIf @@ -42,6 +43,7 @@ def get_config(config=None): conf = Config() base = ['interfaces', 'ethernet'] ethernet = get_interface_dict(conf, base) + return ethernet def verify(ethernet): @@ -59,6 +61,7 @@ def verify(ethernet): raise ConfigError('If duplex is hardcoded, speed must be hardcoded, too') verify_mtu(ethernet) + verify_mtu_ipv6(ethernet) verify_dhcpv6(ethernet) verify_address(ethernet) verify_vrf(ethernet) diff --git a/src/conf_mode/interfaces-geneve.py b/src/conf_mode/interfaces-geneve.py index af7c121f4..979a5612e 100755 --- a/src/conf_mode/interfaces-geneve.py +++ b/src/conf_mode/interfaces-geneve.py @@ -22,6 +22,7 @@ from netifaces import interfaces from vyos.config import Config from vyos.configdict import get_interface_dict from vyos.configverify import verify_address +from vyos.configverify import verify_mtu_ipv6 from vyos.configverify import verify_bridge_delete from vyos.ifconfig import GeneveIf from vyos import ConfigError @@ -47,6 +48,7 @@ def verify(geneve): verify_bridge_delete(geneve) return None + verify_mtu_ipv6(geneve) verify_address(geneve) if 'remote' not in geneve: diff --git a/src/conf_mode/interfaces-l2tpv3.py b/src/conf_mode/interfaces-l2tpv3.py index 2653ff19c..1118143e4 100755 --- a/src/conf_mode/interfaces-l2tpv3.py +++ b/src/conf_mode/interfaces-l2tpv3.py @@ -24,6 +24,7 @@ from vyos.configdict import get_interface_dict from vyos.configdict import leaf_node_changed from vyos.configverify import verify_address from vyos.configverify import verify_bridge_delete +from vyos.configverify import verify_mtu_ipv6 from vyos.ifconfig import L2TPv3If from vyos.util import check_kmod from vyos.validate import is_addr_assigned @@ -80,6 +81,7 @@ def verify(l2tpv3): raise ConfigError('L2TPv3 local-ip address ' '"{local_ip}" is not configured!'.format(**l2tpv3)) + verify_mtu_ipv6(l2tpv3) verify_address(l2tpv3) return None diff --git a/src/conf_mode/interfaces-macsec.py b/src/conf_mode/interfaces-macsec.py index a224c540e..0a20a121b 100755 --- a/src/conf_mode/interfaces-macsec.py +++ b/src/conf_mode/interfaces-macsec.py @@ -27,6 +27,7 @@ from vyos.util import call from vyos.configverify import verify_vrf from vyos.configverify import verify_address from vyos.configverify import verify_bridge_delete +from vyos.configverify import verify_mtu_ipv6 from vyos.configverify import verify_source_interface from vyos import ConfigError from vyos import airbag @@ -71,6 +72,7 @@ def verify(macsec): verify_source_interface(macsec) verify_vrf(macsec) + verify_mtu_ipv6(macsec) verify_address(macsec) if not (('security' in macsec) and diff --git a/src/conf_mode/interfaces-pppoe.py b/src/conf_mode/interfaces-pppoe.py index 1b4b9e4ee..ee3b142c8 100755 --- a/src/conf_mode/interfaces-pppoe.py +++ b/src/conf_mode/interfaces-pppoe.py @@ -24,6 +24,7 @@ from vyos.config import Config from vyos.configdict import get_interface_dict from vyos.configverify import verify_source_interface from vyos.configverify import verify_vrf +from vyos.configverify import verify_mtu_ipv6 from vyos.template import render from vyos.util import call from vyos import ConfigError @@ -57,6 +58,7 @@ def verify(pppoe): verify_source_interface(pppoe) verify_vrf(pppoe) + verify_mtu_ipv6(pppoe) if {'connect_on_demand', 'vrf'} <= set(pppoe): raise ConfigError('On-demand dialing and VRF can not be used at the same time') diff --git a/src/conf_mode/interfaces-vxlan.py b/src/conf_mode/interfaces-vxlan.py index 850ea28d7..002f40aef 100755 --- a/src/conf_mode/interfaces-vxlan.py +++ b/src/conf_mode/interfaces-vxlan.py @@ -23,6 +23,7 @@ from vyos.config import Config from vyos.configdict import get_interface_dict from vyos.configverify import verify_address from vyos.configverify import verify_bridge_delete +from vyos.configverify import verify_mtu_ipv6 from vyos.configverify import verify_source_interface from vyos.ifconfig import VXLANIf, Interface from vyos import ConfigError @@ -77,6 +78,7 @@ def verify(vxlan): raise ConfigError('VXLAN has a 50 byte overhead, underlaying device ' \ f'MTU is to small ({underlay_mtu} bytes)') + verify_mtu_ipv6(vxlan) verify_address(vxlan) return None diff --git a/src/conf_mode/interfaces-wireguard.py b/src/conf_mode/interfaces-wireguard.py index e7c22da1a..d5800264f 100755 --- a/src/conf_mode/interfaces-wireguard.py +++ b/src/conf_mode/interfaces-wireguard.py @@ -27,6 +27,7 @@ from vyos.configdict import leaf_node_changed from vyos.configverify import verify_vrf from vyos.configverify import verify_address from vyos.configverify import verify_bridge_delete +from vyos.configverify import verify_mtu_ipv6 from vyos.ifconfig import WireGuardIf from vyos.util import check_kmod from vyos import ConfigError @@ -71,6 +72,7 @@ def verify(wireguard): verify_bridge_delete(wireguard) return None + verify_mtu_ipv6(wireguard) verify_address(wireguard) verify_vrf(wireguard) -- cgit v1.2.3