diff options
Diffstat (limited to 'python/vyos/configverify.py')
-rw-r--r-- | python/vyos/configverify.py | 105 |
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!') |