summaryrefslogtreecommitdiff
path: root/src/conf_mode
diff options
context:
space:
mode:
Diffstat (limited to 'src/conf_mode')
-rwxr-xr-xsrc/conf_mode/firewall.py12
-rwxr-xr-xsrc/conf_mode/protocols_bgp.py2
-rwxr-xr-xsrc/conf_mode/protocols_isis.py16
-rwxr-xr-xsrc/conf_mode/protocols_ospf.py7
-rwxr-xr-xsrc/conf_mode/service_dhcp-server.py48
-rwxr-xr-xsrc/conf_mode/service_router-advert.py18
-rwxr-xr-xsrc/conf_mode/system_conntrack.py43
7 files changed, 94 insertions, 52 deletions
diff --git a/src/conf_mode/firewall.py b/src/conf_mode/firewall.py
index 3c27655b0..810437dda 100755
--- a/src/conf_mode/firewall.py
+++ b/src/conf_mode/firewall.py
@@ -268,6 +268,18 @@ def verify_rule(firewall, rule_conf, ipv6):
if 'port' in side_conf and dict_search_args(side_conf, 'group', 'port_group'):
raise ConfigError(f'{side} port-group and port cannot both be defined')
+ if 'add_address_to_group' in rule_conf:
+ for type in ['destination_address', 'source_address']:
+ if type in rule_conf['add_address_to_group']:
+ if 'address_group' not in rule_conf['add_address_to_group'][type]:
+ raise ConfigError(f'Dynamic address group must be defined.')
+ else:
+ target = rule_conf['add_address_to_group'][type]['address_group']
+ fwall_group = 'ipv6_address_group' if ipv6 else 'address_group'
+ group_obj = dict_search_args(firewall, 'group', 'dynamic_group', fwall_group, target)
+ if group_obj is None:
+ raise ConfigError(f'Invalid dynamic address group on firewall rule')
+
if 'log_options' in rule_conf:
if 'log' not in rule_conf:
raise ConfigError('log-options defined, but log is not enable')
diff --git a/src/conf_mode/protocols_bgp.py b/src/conf_mode/protocols_bgp.py
index d90dfe45b..f1c59cbde 100755
--- a/src/conf_mode/protocols_bgp.py
+++ b/src/conf_mode/protocols_bgp.py
@@ -457,6 +457,8 @@ def verify(bgp):
peer_group_as = dict_search(f'peer_group.{peer_group}.remote_as', bgp)
if peer_group_as != None and peer_group_as != 'internal' and peer_group_as != bgp['system_as']:
raise ConfigError('route-reflector-client only supported for iBGP peers')
+ else:
+ raise ConfigError('route-reflector-client only supported for iBGP peers')
# Throw an error if a peer group is not configured for allow range
for prefix in dict_search('listen.range', bgp) or []:
diff --git a/src/conf_mode/protocols_isis.py b/src/conf_mode/protocols_isis.py
index 8d594bb68..6c9925b80 100755
--- a/src/conf_mode/protocols_isis.py
+++ b/src/conf_mode/protocols_isis.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2020-2022 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
@@ -155,12 +155,12 @@ def verify(isis):
for proto, proto_config in isis['redistribute'][afi].items():
if 'level_1' not in proto_config and 'level_2' not in proto_config:
raise ConfigError(f'Redistribute level-1 or level-2 should be specified in ' \
- f'"protocols isis {process} redistribute {afi} {proto}"!')
+ f'"protocols isis redistribute {afi} {proto}"!')
for redistr_level, redistr_config in proto_config.items():
if proc_level and proc_level != 'level_1_2' and proc_level != redistr_level:
- raise ConfigError(f'"protocols isis {process} redistribute {afi} {proto} {redistr_level}" ' \
- f'can not be used with \"protocols isis {process} level {proc_level}\"')
+ raise ConfigError(f'"protocols isis redistribute {afi} {proto} {redistr_level}" ' \
+ f'can not be used with \"protocols isis level {proc_level}\"!')
# Segment routing checks
if dict_search('segment_routing.global_block', isis):
@@ -220,8 +220,8 @@ def verify(isis):
if ("explicit_null" in prefix_config['index']) and ("no_php_flag" in prefix_config['index']):
raise ConfigError(f'Segment routing prefix {prefix} cannot have both explicit-null '\
f'and no-php-flag configured at the same time.')
-
- # Check for index ranges being larger than the segment routing global block
+
+ # Check for index ranges being larger than the segment routing global block
if dict_search('segment_routing.global_block', isis):
g_high_label_value = dict_search('segment_routing.global_block.high_label_value', isis)
g_low_label_value = dict_search('segment_routing.global_block.low_label_value', isis)
@@ -233,7 +233,7 @@ def verify(isis):
if int(index_size) > int(g_label_difference):
raise ConfigError(f'Segment routing prefix {prefix} cannot have an '\
f'index base size larger than the SRGB label base.')
-
+
# Check for LFA tiebreaker index duplication
if dict_search('fast_reroute.lfa.local.tiebreaker', isis):
comparison_dictionary = {}
@@ -311,4 +311,4 @@ if __name__ == '__main__':
apply(c)
except ConfigError as e:
print(e)
- exit(1) \ No newline at end of file
+ exit(1)
diff --git a/src/conf_mode/protocols_ospf.py b/src/conf_mode/protocols_ospf.py
index 695842795..6fffe7e0d 100755
--- a/src/conf_mode/protocols_ospf.py
+++ b/src/conf_mode/protocols_ospf.py
@@ -127,6 +127,7 @@ def verify(ospf):
# Validate if configured Access-list exists
if 'area' in ospf:
+ networks = []
for area, area_config in ospf['area'].items():
if 'import_list' in area_config:
acl_import = area_config['import_list']
@@ -135,6 +136,12 @@ def verify(ospf):
acl_export = area_config['export_list']
if acl_export: verify_access_list(acl_export, ospf)
+ if 'network' in area_config:
+ for network in area_config['network']:
+ if network in networks:
+ raise ConfigError(f'Network "{network}" already defined in different area!')
+ networks.append(network)
+
if 'interface' in ospf:
for interface, interface_config in ospf['interface'].items():
verify_interface_exists(interface)
diff --git a/src/conf_mode/service_dhcp-server.py b/src/conf_mode/service_dhcp-server.py
index 91ea354b6..ba3d69b07 100755
--- a/src/conf_mode/service_dhcp-server.py
+++ b/src/conf_mode/service_dhcp-server.py
@@ -143,7 +143,7 @@ def get_config(config=None):
dhcp['shared_network_name'][network]['subnet'][subnet].update(
{'range' : new_range_dict})
- if dict_search('failover.certificate', dhcp):
+ if dict_search('high_availability.certificate', dhcp):
dhcp['pki'] = conf.get_config_dict(['pki'], key_mangling=('-', '_'), get_first_key=True, no_tag_node_value_mangle=True)
return dhcp
@@ -286,34 +286,34 @@ def verify(dhcp):
if (shared_networks - disabled_shared_networks) < 1:
raise ConfigError(f'At least one shared network must be active!')
- if 'failover' in dhcp:
+ if 'high_availability' in dhcp:
for key in ['name', 'remote', 'source_address', 'status']:
- if key not in dhcp['failover']:
+ if key not in dhcp['high_availability']:
tmp = key.replace('_', '-')
- raise ConfigError(f'DHCP failover requires "{tmp}" to be specified!')
+ raise ConfigError(f'DHCP high-availability requires "{tmp}" to be specified!')
- if len({'certificate', 'ca_certificate'} & set(dhcp['failover'])) == 1:
- raise ConfigError(f'DHCP secured failover requires both certificate and CA certificate')
+ if len({'certificate', 'ca_certificate'} & set(dhcp['high_availability'])) == 1:
+ raise ConfigError(f'DHCP secured high-availability requires both certificate and CA certificate')
- if 'certificate' in dhcp['failover']:
- cert_name = dhcp['failover']['certificate']
+ if 'certificate' in dhcp['high_availability']:
+ cert_name = dhcp['high_availability']['certificate']
if cert_name not in dhcp['pki']['certificate']:
- raise ConfigError(f'Invalid certificate specified for DHCP failover')
+ raise ConfigError(f'Invalid certificate specified for DHCP high-availability')
if not dict_search_args(dhcp['pki']['certificate'], cert_name, 'certificate'):
- raise ConfigError(f'Invalid certificate specified for DHCP failover')
+ raise ConfigError(f'Invalid certificate specified for DHCP high-availability')
if not dict_search_args(dhcp['pki']['certificate'], cert_name, 'private', 'key'):
- raise ConfigError(f'Missing private key on certificate specified for DHCP failover')
+ raise ConfigError(f'Missing private key on certificate specified for DHCP high-availability')
- if 'ca_certificate' in dhcp['failover']:
- ca_cert_name = dhcp['failover']['ca_certificate']
+ if 'ca_certificate' in dhcp['high_availability']:
+ ca_cert_name = dhcp['high_availability']['ca_certificate']
if ca_cert_name not in dhcp['pki']['ca']:
- raise ConfigError(f'Invalid CA certificate specified for DHCP failover')
+ raise ConfigError(f'Invalid CA certificate specified for DHCP high-availability')
if not dict_search_args(dhcp['pki']['ca'], ca_cert_name, 'certificate'):
- raise ConfigError(f'Invalid CA certificate specified for DHCP failover')
+ raise ConfigError(f'Invalid CA certificate specified for DHCP high-availability')
for address in (dict_search('listen_address', dhcp) or []):
if is_addr_assigned(address):
@@ -359,23 +359,23 @@ def generate(dhcp):
if os.path.exists(f):
os.unlink(f)
- if 'failover' in dhcp:
- if 'certificate' in dhcp['failover']:
- cert_name = dhcp['failover']['certificate']
+ if 'high_availability' in dhcp:
+ if 'certificate' in dhcp['high_availability']:
+ cert_name = dhcp['high_availability']['certificate']
cert_data = dhcp['pki']['certificate'][cert_name]['certificate']
key_data = dhcp['pki']['certificate'][cert_name]['private']['key']
write_file(cert_file, wrap_certificate(cert_data), user=user_group, mode=0o600)
write_file(cert_key_file, wrap_private_key(key_data), user=user_group, mode=0o600)
- dhcp['failover']['cert_file'] = cert_file
- dhcp['failover']['cert_key_file'] = cert_key_file
+ dhcp['high_availability']['cert_file'] = cert_file
+ dhcp['high_availability']['cert_key_file'] = cert_key_file
- if 'ca_certificate' in dhcp['failover']:
- ca_cert_name = dhcp['failover']['ca_certificate']
+ if 'ca_certificate' in dhcp['high_availability']:
+ ca_cert_name = dhcp['high_availability']['ca_certificate']
ca_cert_data = dhcp['pki']['ca'][ca_cert_name]['certificate']
write_file(ca_cert_file, wrap_certificate(ca_cert_data), user=user_group, mode=0o600)
- dhcp['failover']['ca_cert_file'] = ca_cert_file
+ dhcp['high_availability']['ca_cert_file'] = ca_cert_file
render(systemd_override, 'dhcp-server/10-override.conf.j2', dhcp)
@@ -402,7 +402,7 @@ def apply(dhcp):
if service == 'kea-dhcp-ddns-server' and 'dynamic_dns_update' not in dhcp:
action = 'stop'
- if service == 'kea-ctrl-agent' and 'failover' not in dhcp:
+ if service == 'kea-ctrl-agent' and 'high_availability' not in dhcp:
action = 'stop'
call(f'systemctl {action} {service}.service')
diff --git a/src/conf_mode/service_router-advert.py b/src/conf_mode/service_router-advert.py
index dbb47de4e..88d767bb8 100755
--- a/src/conf_mode/service_router-advert.py
+++ b/src/conf_mode/service_router-advert.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2018-2022 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
@@ -17,6 +17,8 @@
import os
from sys import exit
+from ipaddress import IPv6Network
+
from vyos.base import Warning
from vyos.config import Config
from vyos.template import render
@@ -47,7 +49,9 @@ def verify(rtradv):
return None
for interface, interface_config in rtradv['interface'].items():
- if 'prefix' in interface:
+ interval_max = int(interface_config['interval']['max'])
+
+ if 'prefix' in interface_config:
for prefix, prefix_config in interface_config['prefix'].items():
valid_lifetime = prefix_config['valid_lifetime']
if valid_lifetime == 'infinity':
@@ -60,6 +64,15 @@ def verify(rtradv):
if not (int(valid_lifetime) >= int(preferred_lifetime)):
raise ConfigError('Prefix valid-lifetime must be greater then or equal to preferred-lifetime')
+ if 'nat64prefix' in interface_config:
+ nat64_supported_lengths = [32, 40, 48, 56, 64, 96]
+ for prefix, prefix_config in interface_config['nat64prefix'].items():
+ if IPv6Network(prefix).prefixlen not in nat64_supported_lengths:
+ raise ConfigError(f'Invalid NAT64 prefix length for "{prefix}", can only be one of: /' + ', /'.join(nat64_supported_lengths))
+
+ if int(prefix_config['valid_lifetime']) < interval_max:
+ raise ConfigError(f'NAT64 valid-lifetime must not be smaller then "interval max" which is "{interval_max}"!')
+
if 'name_server' in interface_config:
if len(interface_config['name_server']) > 3:
raise ConfigError('No more then 3 IPv6 name-servers supported!')
@@ -72,7 +85,6 @@ def verify(rtradv):
# ensure stale RDNSS info gets removed in a timely fashion, this
# should not be greater than 2*MaxRtrAdvInterval.
lifetime = int(interface_config['name_server_lifetime'])
- interval_max = int(interface_config['interval']['max'])
if lifetime > 0:
if lifetime < int(interval_max):
raise ConfigError(f'RDNSS lifetime must be at least "{interval_max}" seconds!')
diff --git a/src/conf_mode/system_conntrack.py b/src/conf_mode/system_conntrack.py
index e075bc928..3d42389f6 100755
--- a/src/conf_mode/system_conntrack.py
+++ b/src/conf_mode/system_conntrack.py
@@ -42,33 +42,38 @@ nftables_ct_file = r'/run/nftables-ct.conf'
module_map = {
'ftp': {
'ko': ['nf_nat_ftp', 'nf_conntrack_ftp'],
- 'nftables': ['ct helper set "ftp_tcp" tcp dport {21} return']
+ 'nftables': ['tcp dport {21} ct helper set "ftp_tcp" return']
},
'h323': {
'ko': ['nf_nat_h323', 'nf_conntrack_h323'],
- 'nftables': ['ct helper set "ras_udp" udp dport {1719} return',
- 'ct helper set "q931_tcp" tcp dport {1720} return']
+ 'nftables': ['udp dport {1719} ct helper set "ras_udp" return',
+ 'tcp dport {1720} ct helper set "q931_tcp" return']
},
'nfs': {
- 'nftables': ['ct helper set "rpc_tcp" tcp dport {111} return',
- 'ct helper set "rpc_udp" udp dport {111} return']
+ 'nftables': ['tcp dport {111} ct helper set "rpc_tcp" return',
+ 'udp dport {111} ct helper set "rpc_udp" return']
},
'pptp': {
'ko': ['nf_nat_pptp', 'nf_conntrack_pptp'],
- 'nftables': ['ct helper set "pptp_tcp" tcp dport {1723} return'],
+ 'nftables': ['tcp dport {1723} ct helper set "pptp_tcp" return'],
'ipv4': True
},
+ 'rtsp': {
+ 'ko': ['nf_nat_rtsp', 'nf_conntrack_rtsp'],
+ 'nftables': ['tcp dport {554} ct helper set "rtsp_tcp" return'],
+ 'ipv4': True
+ },
'sip': {
'ko': ['nf_nat_sip', 'nf_conntrack_sip'],
- 'nftables': ['ct helper set "sip_tcp" tcp dport {5060,5061} return',
- 'ct helper set "sip_udp" udp dport {5060,5061} return']
+ 'nftables': ['tcp dport {5060,5061} ct helper set "sip_tcp" return',
+ 'udp dport {5060,5061} ct helper set "sip_udp" return']
},
'sqlnet': {
- 'nftables': ['ct helper set "tns_tcp" tcp dport {1521,1525,1536} return']
+ 'nftables': ['tcp dport {1521,1525,1536} ct helper set "tns_tcp" return']
},
'tftp': {
'ko': ['nf_nat_tftp', 'nf_conntrack_tftp'],
- 'nftables': ['ct helper set "tftp_udp" udp dport {69} return']
+ 'nftables': ['udp dport {69} ct helper set "tftp_udp" return']
},
}
@@ -180,12 +185,16 @@ def generate(conntrack):
conntrack['ipv4_firewall_action'] = 'return'
conntrack['ipv6_firewall_action'] = 'return'
- for rules, path in dict_search_recursive(conntrack['firewall'], 'rule'):
- if any(('state' in rule_conf or 'connection_status' in rule_conf or 'offload_target' in rule_conf) for rule_conf in rules.values()):
- if path[0] == 'ipv4':
- conntrack['ipv4_firewall_action'] = 'accept'
- elif path[0] == 'ipv6':
- conntrack['ipv6_firewall_action'] = 'accept'
+ if dict_search_args(conntrack['firewall'], 'global_options', 'state_policy') != None:
+ conntrack['ipv4_firewall_action'] = 'accept'
+ conntrack['ipv6_firewall_action'] = 'accept'
+ else:
+ for rules, path in dict_search_recursive(conntrack['firewall'], 'rule'):
+ if any(('state' in rule_conf or 'connection_status' in rule_conf or 'offload_target' in rule_conf) for rule_conf in rules.values()):
+ if path[0] == 'ipv4':
+ conntrack['ipv4_firewall_action'] = 'accept'
+ elif path[0] == 'ipv6':
+ conntrack['ipv6_firewall_action'] = 'accept'
render(conntrack_config, 'conntrack/vyos_nf_conntrack.conf.j2', conntrack)
render(sysctl_file, 'conntrack/sysctl.conf.j2', conntrack)
@@ -195,7 +204,7 @@ def generate(conntrack):
def apply(conntrack):
# Depending on the enable/disable state of the ALG (Application Layer Gateway)
# modules we need to either insmod or rmmod the helpers.
-
+
add_modules = []
rm_modules = []