summaryrefslogtreecommitdiff
path: root/src/conf_mode
diff options
context:
space:
mode:
Diffstat (limited to 'src/conf_mode')
-rwxr-xr-xsrc/conf_mode/dns_forwarding.py3
-rwxr-xr-xsrc/conf_mode/interfaces-openvpn.py43
-rwxr-xr-xsrc/conf_mode/ntp.py20
-rwxr-xr-xsrc/conf_mode/protocols_bgp.py4
-rwxr-xr-xsrc/conf_mode/service_ipoe-server.py14
-rwxr-xr-xsrc/conf_mode/service_router-advert.py34
6 files changed, 92 insertions, 26 deletions
diff --git a/src/conf_mode/dns_forwarding.py b/src/conf_mode/dns_forwarding.py
index f1c2d1f43..41023c135 100755
--- a/src/conf_mode/dns_forwarding.py
+++ b/src/conf_mode/dns_forwarding.py
@@ -98,6 +98,9 @@ def get_config(config=None):
dns['authoritative_zone_errors'].append('{}.{}: at least one address is required'.format(subnode, node))
continue
+ if subnode == 'any':
+ subnode = '*'
+
for address in rdata['address']:
zone['records'].append({
'name': subnode,
diff --git a/src/conf_mode/interfaces-openvpn.py b/src/conf_mode/interfaces-openvpn.py
index 4750ca3e8..280a62b9a 100755
--- a/src/conf_mode/interfaces-openvpn.py
+++ b/src/conf_mode/interfaces-openvpn.py
@@ -39,6 +39,8 @@ from vyos.configverify import verify_mirror_redirect
from vyos.ifconfig import VTunIf
from vyos.pki import load_dh_parameters
from vyos.pki import load_private_key
+from vyos.pki import sort_ca_chain
+from vyos.pki import verify_ca_chain
from vyos.pki import wrap_certificate
from vyos.pki import wrap_crl
from vyos.pki import wrap_dh_parameters
@@ -148,8 +150,14 @@ def verify_pki(openvpn):
if 'ca_certificate' not in tls:
raise ConfigError(f'Must specify "tls ca-certificate" on openvpn interface {interface}')
- if tls['ca_certificate'] not in pki['ca']:
- raise ConfigError(f'Invalid CA certificate on openvpn interface {interface}')
+ for ca_name in tls['ca_certificate']:
+ if ca_name not in pki['ca']:
+ raise ConfigError(f'Invalid CA certificate on openvpn interface {interface}')
+
+ if len(tls['ca_certificate']) > 1:
+ sorted_chain = sort_ca_chain(tls['ca_certificate'], pki['ca'])
+ if not verify_ca_chain(sorted_chain, pki['ca']):
+ raise ConfigError(f'CA certificates are not a valid chain')
if mode != 'client' and 'auth_key' not in tls:
if 'certificate' not in tls:
@@ -516,21 +524,28 @@ def generate_pki_files(openvpn):
if tls:
if 'ca_certificate' in tls:
- cert_name = tls['ca_certificate']
- pki_ca = pki['ca'][cert_name]
+ cert_path = os.path.join(cfg_dir, f'{interface}_ca.pem')
+ crl_path = os.path.join(cfg_dir, f'{interface}_crl.pem')
- if 'certificate' in pki_ca:
- cert_path = os.path.join(cfg_dir, f'{interface}_ca.pem')
- write_file(cert_path, wrap_certificate(pki_ca['certificate']),
- user=user, group=group, mode=0o600)
+ if os.path.exists(cert_path):
+ os.unlink(cert_path)
+
+ if os.path.exists(crl_path):
+ os.unlink(crl_path)
+
+ for cert_name in sort_ca_chain(tls['ca_certificate'], pki['ca']):
+ pki_ca = pki['ca'][cert_name]
+
+ if 'certificate' in pki_ca:
+ write_file(cert_path, wrap_certificate(pki_ca['certificate']) + "\n",
+ user=user, group=group, mode=0o600, append=True)
- if 'crl' in pki_ca:
- for crl in pki_ca['crl']:
- crl_path = os.path.join(cfg_dir, f'{interface}_crl.pem')
- write_file(crl_path, wrap_crl(crl), user=user, group=group,
- mode=0o600)
+ if 'crl' in pki_ca:
+ for crl in pki_ca['crl']:
+ write_file(crl_path, wrap_crl(crl) + "\n", user=user, group=group,
+ mode=0o600, append=True)
- openvpn['tls']['crl'] = True
+ openvpn['tls']['crl'] = True
if 'certificate' in tls:
cert_name = tls['certificate']
diff --git a/src/conf_mode/ntp.py b/src/conf_mode/ntp.py
index 0d6ec9ace..5490a794d 100755
--- a/src/conf_mode/ntp.py
+++ b/src/conf_mode/ntp.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2018-2021 VyOS maintainers and contributors
+# Copyright (C) 2018-2022 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
@@ -18,9 +18,11 @@ import os
from vyos.config import Config
from vyos.configverify import verify_vrf
-from vyos import ConfigError
+from vyos.configverify import verify_interface_exists
from vyos.util import call
+from vyos.util import get_interface_config
from vyos.template import render
+from vyos import ConfigError
from vyos import airbag
airbag.enable()
@@ -49,6 +51,20 @@ def verify(ntp):
raise ConfigError('NTP server not configured')
verify_vrf(ntp)
+
+ if 'interface' in ntp:
+ # If ntpd should listen on a given interface, ensure it exists
+ for interface in ntp['interface']:
+ verify_interface_exists(interface)
+
+ # If we run in a VRF, our interface must belong to this VRF, too
+ if 'vrf' in ntp:
+ tmp = get_interface_config(interface)
+ vrf_name = ntp['vrf']
+ if 'master' not in tmp or tmp['master'] != vrf_name:
+ raise ConfigError(f'NTP runs in VRF "{vrf_name}" - "{interface}" '\
+ f'does not belong to this VRF!')
+
return None
def generate(ntp):
diff --git a/src/conf_mode/protocols_bgp.py b/src/conf_mode/protocols_bgp.py
index cd46cbcb4..01f14df61 100755
--- a/src/conf_mode/protocols_bgp.py
+++ b/src/conf_mode/protocols_bgp.py
@@ -19,6 +19,7 @@ import os
from sys import exit
from sys import argv
+from vyos.base import Warning
from vyos.config import Config
from vyos.configdict import dict_merge
from vyos.configverify import verify_prefix_list
@@ -198,6 +199,9 @@ def verify(bgp):
if 'source_interface' in peer_config['interface']:
raise ConfigError(f'"source-interface" option not allowed for neighbor "{peer}"')
+ if 'address_family' not in peer_config:
+ Warning(f'BGP neighbor "{peer}" requires address-family!')
+
for afi in ['ipv4_unicast', 'ipv4_multicast', 'ipv4_labeled_unicast', 'ipv4_flowspec',
'ipv6_unicast', 'ipv6_multicast', 'ipv6_labeled_unicast', 'ipv6_flowspec',
'l2vpn_evpn']:
diff --git a/src/conf_mode/service_ipoe-server.py b/src/conf_mode/service_ipoe-server.py
index 559d1bcd5..61f484129 100755
--- a/src/conf_mode/service_ipoe-server.py
+++ b/src/conf_mode/service_ipoe-server.py
@@ -53,6 +53,8 @@ default_config_data = {
'radius_nas_ip': '',
'radius_source_address': '',
'radius_shaper_attr': '',
+ 'radius_shaper_enable': False,
+ 'radius_shaper_multiplier': '',
'radius_shaper_vendor': '',
'radius_dynamic_author': '',
'thread_cnt': get_half_cpus()
@@ -196,6 +198,18 @@ def get_config(config=None):
if conf.exists(['nas-ip-address']):
ipoe['radius_nas_ip'] = conf.return_value(['nas-ip-address'])
+ if conf.exists(['rate-limit', 'attribute']):
+ ipoe['radius_shaper_attr'] = conf.return_value(['rate-limit', 'attribute'])
+
+ if conf.exists(['rate-limit', 'enable']):
+ ipoe['radius_shaper_enable'] = True
+
+ if conf.exists(['rate-limit', 'multiplier']):
+ ipoe['radius_shaper_multiplier'] = conf.return_value(['rate-limit', 'multiplier'])
+
+ if conf.exists(['rate-limit', 'vendor']):
+ ipoe['radius_shaper_vendor'] = conf.return_value(['rate-limit', 'vendor'])
+
if conf.exists(['source-address']):
ipoe['radius_source_address'] = conf.return_value(['source-address'])
diff --git a/src/conf_mode/service_router-advert.py b/src/conf_mode/service_router-advert.py
index 71b758399..ff7caaa84 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-2021 VyOS maintainers and contributors
+# Copyright (C) 2018-2022 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,7 +17,7 @@
import os
from sys import exit
-
+from vyos.base import Warning
from vyos.config import Config
from vyos.configdict import dict_merge
from vyos.template import render
@@ -79,22 +79,35 @@ def verify(rtradv):
if 'interface' not in rtradv:
return None
- for interface in rtradv['interface']:
- interface = rtradv['interface'][interface]
+ for interface, interface_config in rtradv['interface'].items():
if 'prefix' in interface:
- for prefix in interface['prefix']:
- prefix = interface['prefix'][prefix]
- valid_lifetime = prefix['valid_lifetime']
+ for prefix, prefix_config in interface_config['prefix'].items():
+ valid_lifetime = prefix_config['valid_lifetime']
if valid_lifetime == 'infinity':
valid_lifetime = 4294967295
- preferred_lifetime = prefix['preferred_lifetime']
+ preferred_lifetime = prefix_config['preferred_lifetime']
if preferred_lifetime == 'infinity':
preferred_lifetime = 4294967295
if not (int(valid_lifetime) > int(preferred_lifetime)):
raise ConfigError('Prefix valid-lifetime must be greater then preferred-lifetime')
+ if 'name_server_lifetime' in interface_config:
+ # man page states:
+ # The maximum duration how long the RDNSS entries are used for name
+ # resolution. A value of 0 means the nameserver must no longer be
+ # used. The value, if not 0, must be at least MaxRtrAdvInterval. To
+ # 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!')
+ if lifetime > 2* interval_max:
+ Warning(f'RDNSS lifetime should not exceed "{2 * interval_max}" which is two times "interval max"!')
+
return None
def generate(rtradv):
@@ -105,15 +118,16 @@ def generate(rtradv):
return None
def apply(rtradv):
+ systemd_service = 'radvd.service'
if not rtradv:
# bail out early - looks like removal from running config
- call('systemctl stop radvd.service')
+ call(f'systemctl stop {systemd_service}')
if os.path.exists(config_file):
os.unlink(config_file)
return None
- call('systemctl restart radvd.service')
+ call(f'systemctl reload-or-restart {systemd_service}')
return None