summaryrefslogtreecommitdiff
path: root/python/vyos/configverify.py
diff options
context:
space:
mode:
Diffstat (limited to 'python/vyos/configverify.py')
-rw-r--r--python/vyos/configverify.py105
1 files changed, 89 insertions, 16 deletions
diff --git a/python/vyos/configverify.py b/python/vyos/configverify.py
index b4447306e..718b7445d 100644
--- a/python/vyos/configverify.py
+++ b/python/vyos/configverify.py
@@ -80,7 +80,7 @@ def verify_vrf(config):
recurring validation of VRF configuration.
"""
from netifaces import interfaces
- if 'vrf' in config:
+ if 'vrf' in config and config['vrf'] != 'default':
if config['vrf'] not in interfaces():
raise ConfigError('VRF "{vrf}" does not exist'.format(**config))
@@ -89,6 +89,50 @@ def verify_vrf(config):
'Interface "{ifname}" cannot be both a member of VRF "{vrf}" '
'and bridge "{is_bridge_member}"!'.format(**config))
+def verify_tunnel(config):
+ """
+ This helper is used to verify the common part of the tunnel
+ """
+ from vyos.template import is_ipv4
+ from vyos.template import is_ipv6
+
+ if 'encapsulation' not in config:
+ raise ConfigError('Must configure the tunnel encapsulation for '\
+ '{ifname}!'.format(**config))
+
+ if 'source_address' not in config and 'dhcp_interface' not in config:
+ raise ConfigError('source-address is mandatory for tunnel')
+
+ if 'remote' not in config and config['encapsulation'] != 'gre':
+ raise ConfigError('remote ip address is mandatory for tunnel')
+
+ if {'source_address', 'dhcp_interface'} <= set(config):
+ raise ConfigError('Can not use both source-address and dhcp-interface')
+
+ if config['encapsulation'] in ['ipip6', 'ip6ip6', 'ip6gre', 'ip6gretap', 'ip6erspan']:
+ error_ipv6 = 'Encapsulation mode requires IPv6'
+ if 'source_address' in config and not is_ipv6(config['source_address']):
+ raise ConfigError(f'{error_ipv6} source-address')
+
+ if 'remote' in config and not is_ipv6(config['remote']):
+ raise ConfigError(f'{error_ipv6} remote')
+ else:
+ error_ipv4 = 'Encapsulation mode requires IPv4'
+ if 'source_address' in config and not is_ipv4(config['source_address']):
+ raise ConfigError(f'{error_ipv4} source-address')
+
+ if 'remote' in config and not is_ipv4(config['remote']):
+ raise ConfigError(f'{error_ipv4} remote address')
+
+ if config['encapsulation'] in ['sit', 'gretap', 'ip6gretap']:
+ if 'source_interface' in config:
+ encapsulation = config['encapsulation']
+ raise ConfigError(f'Option source-interface can not be used with ' \
+ f'encapsulation "{encapsulation}"!')
+ elif config['encapsulation'] == 'gre':
+ if 'source_address' in config and is_ipv6(config['source_address']):
+ raise ConfigError('Can not use local IPv6 address is for mGRE tunnels')
+
def verify_eapol(config):
"""
Common helper function used by interface implementations to perform
@@ -136,15 +180,14 @@ def verify_bridge_delete(config):
'Interface "{ifname}" cannot be deleted as it is a '
'member of bridge "{is_bridge_member}"!'.format(**config))
-def verify_interface_exists(config):
+def verify_interface_exists(ifname):
"""
Common helper function used by interface implementations to perform
recurring validation if an interface actually exists.
"""
from netifaces import interfaces
- if not config['ifname'] in interfaces():
- raise ConfigError('Interface "{ifname}" does not exist!'
- .format(**config))
+ if ifname not in interfaces():
+ raise ConfigError(f'Interface "{ifname}" does not exist!')
def verify_source_interface(config):
"""
@@ -210,6 +253,13 @@ def verify_vlan_config(config):
Common helper function used by interface implementations to perform
recurring validation of interface VLANs
"""
+
+ # VLAN and Q-in-Q IDs are not allowed to overlap
+ if 'vif' in config and 'vif_s' in config:
+ duplicate = list(set(config['vif']) & set(config['vif_s']))
+ if duplicate:
+ raise ConfigError(f'Duplicate VLAN id "{duplicate[0]}" used for vif and vif-s interfaces!')
+
# 802.1q VLANs
for vlan in config.get('vif', {}):
vlan = config['vif'][vlan]
@@ -218,17 +268,17 @@ def verify_vlan_config(config):
verify_vrf(vlan)
# 802.1ad (Q-in-Q) VLANs
- for vlan in config.get('vif_s', {}):
- vlan = config['vif_s'][vlan]
- verify_dhcpv6(vlan)
- verify_address(vlan)
- verify_vrf(vlan)
-
- for vlan in config.get('vif_s', {}).get('vif_c', {}):
- vlan = config['vif_c'][vlan]
- verify_dhcpv6(vlan)
- verify_address(vlan)
- verify_vrf(vlan)
+ for s_vlan in config.get('vif_s', {}):
+ s_vlan = config['vif_s'][s_vlan]
+ verify_dhcpv6(s_vlan)
+ verify_address(s_vlan)
+ verify_vrf(s_vlan)
+
+ for c_vlan in s_vlan.get('vif_c', {}):
+ c_vlan = s_vlan['vif_c'][c_vlan]
+ verify_dhcpv6(c_vlan)
+ verify_address(c_vlan)
+ verify_vrf(c_vlan)
def verify_accel_ppp_base_service(config):
"""
@@ -308,3 +358,26 @@ def verify_diffie_hellman_length(file, min_keysize):
return False
+def verify_route_maps(config):
+ """
+ Common helper function used by routing protocol implementations to perform
+ recurring validation if the specified route-map for either zebra to kernel
+ installation exists (this is the top-level route_map key) or when a route
+ is redistributed with a route-map that it exists!
+ """
+ if 'route_map' in config:
+ route_map = config['route_map']
+ # Check if the specified route-map exists, if not error out
+ if dict_search(f'policy.route_map.{route_map}', config) == None:
+ raise ConfigError(f'Specified route-map "{route_map}" does not exist!')
+
+ if 'redistribute' in config:
+ for protocol, protocol_config in config['redistribute'].items():
+ if 'route_map' in protocol_config:
+ # A hyphen in a route-map name will be converted to _, take care
+ # about this effect during validation
+ route_map = protocol_config['route_map'].replace('-','_')
+ # Check if the specified route-map exists, if not error out
+ if dict_search(f'policy.route_map.{route_map}', config) == None:
+ raise ConfigError(f'Redistribution route-map "{route_map}" ' \
+ f'for "{protocol}" does not exist!')