diff options
Diffstat (limited to 'src')
-rwxr-xr-x | src/conf_mode/interfaces-ethernet.py | 23 | ||||
-rwxr-xr-x | src/conf_mode/interfaces-tunnel.py | 1 | ||||
-rwxr-xr-x | src/conf_mode/protocols_bgp.py | 12 | ||||
-rwxr-xr-x | src/conf_mode/service_console-server.py | 23 | ||||
-rwxr-xr-x | src/conf_mode/vrrp.py | 6 | ||||
-rwxr-xr-x | src/migration-scripts/nat/4-to-5 | 6 | ||||
-rwxr-xr-x | src/services/vyos-configd | 22 | ||||
-rwxr-xr-x | src/system/on-dhcp-event.sh | 25 | ||||
-rw-r--r-- | src/systemd/dropbear@.service | 5 | ||||
-rw-r--r-- | src/tests/test_util.py | 4 | ||||
-rwxr-xr-x | src/validators/interface-name | 2 |
11 files changed, 96 insertions, 33 deletions
diff --git a/src/conf_mode/interfaces-ethernet.py b/src/conf_mode/interfaces-ethernet.py index bf4650773..378f400b8 100755 --- a/src/conf_mode/interfaces-ethernet.py +++ b/src/conf_mode/interfaces-ethernet.py @@ -30,6 +30,7 @@ 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.ethtool import Ethtool from vyos.ifconfig import EthernetIf from vyos.template import render from vyos.util import call @@ -82,11 +83,31 @@ def verify(ethernet): driver = EthernetIf(ifname).get_driver_name() # T3342 - Xen driver requires special treatment - if driver == "vif": + if driver == 'vif': if int(ethernet['mtu']) > 1500 and dict_search('offload.sg', ethernet) == None: raise ConfigError('Xen netback drivers requires scatter-gatter offloading '\ 'for MTU size larger then 1500 bytes') + ethtool = Ethtool(ifname) + if 'ring_buffer' in ethernet: + max_rx = ethtool.get_rx_buffer() + if not max_rx: + raise ConfigError('Driver does not support RX ring-buffer configuration!') + + max_tx = ethtool.get_tx_buffer() + if not max_tx: + raise ConfigError('Driver does not support TX ring-buffer configuration!') + + rx = dict_search('ring_buffer.rx', ethernet) + if rx and int(rx) > int(max_rx): + raise ConfigError(f'Driver only supports a maximum RX ring-buffer '\ + f'size of "{max_rx}" bytes!') + + tx = dict_search('ring_buffer.tx', ethernet) + if tx and int(tx) > int(max_tx): + raise ConfigError(f'Driver only supports a maximum TX ring-buffer '\ + f'size of "{max_tx}" bytes!') + # XDP requires multiple TX queues if 'xdp' in ethernet: queues = glob(f'/sys/class/net/{ifname}/queues/tx-*') diff --git a/src/conf_mode/interfaces-tunnel.py b/src/conf_mode/interfaces-tunnel.py index 034bd6dd1..87da214a8 100755 --- a/src/conf_mode/interfaces-tunnel.py +++ b/src/conf_mode/interfaces-tunnel.py @@ -140,7 +140,6 @@ def apply(tunnel): 'parameters.ip.ttl' : 'ttl', 'parameters.ip.tos' : 'tos', 'parameters.ip.key' : 'key', - 'parameters.ipv6.encaplimit' : 'encaplimit' } # Add additional IPv6 options if tunnel is IPv6 aware diff --git a/src/conf_mode/protocols_bgp.py b/src/conf_mode/protocols_bgp.py index baf5c4159..1ce2d3e7c 100755 --- a/src/conf_mode/protocols_bgp.py +++ b/src/conf_mode/protocols_bgp.py @@ -23,6 +23,7 @@ from vyos.configdict import dict_merge from vyos.template import render_to_string from vyos.util import call from vyos.util import dict_search +from vyos.validate import is_addr_assigned from vyos import ConfigError from vyos import frr from vyos import airbag @@ -99,6 +100,13 @@ def verify(bgp): raise ConfigError(f'Specified peer-group "{peer_group}" for '\ f'neighbor "{neighbor}" does not exist!') + # ttl-security and ebgp-multihop can't be used in the same configration + if 'ebgp_multihop' in peer_config and 'ttl_security' in peer_config: + raise ConfigError('You can\'t set both ebgp-multihop and ttl-security hops') + + # Check spaces in the password + if 'password' in peer_config and ' ' in peer_config['password']: + raise ConfigError('You can\'t use spaces in the password') # Some checks can/must only be done on a neighbor and not a peer-group if neighbor == 'neighbor': @@ -107,6 +115,10 @@ def verify(bgp): if not verify_remote_as(peer_config, asn_config): raise ConfigError(f'Neighbor "{peer}" remote-as must be set!') + # Check if neighbor address is assigned as system interface address + if is_addr_assigned(peer): + raise ConfigError(f'Can\'t configure local address as neighbor "{peer}"') + for afi in ['ipv4_unicast', 'ipv6_unicast', 'l2vpn_evpn']: # Bail out early if address family is not configured if 'address_family' not in peer_config or afi not in peer_config['address_family']: diff --git a/src/conf_mode/service_console-server.py b/src/conf_mode/service_console-server.py index 0e5fc75b0..6e94a19ae 100755 --- a/src/conf_mode/service_console-server.py +++ b/src/conf_mode/service_console-server.py @@ -25,7 +25,8 @@ from vyos.util import call from vyos.xml import defaults from vyos import ConfigError -config_file = r'/run/conserver/conserver.cf' +config_file = '/run/conserver/conserver.cf' +dropbear_systemd_file = '/etc/systemd/system/dropbear@{port}.service.d/override.conf' def get_config(config=None): if config: @@ -75,9 +76,22 @@ def generate(proxy): return None render(config_file, 'conserver/conserver.conf.tmpl', proxy) + if 'device' in proxy: + for device in proxy['device']: + if 'ssh' not in proxy['device'][device]: + continue + + tmp = { + 'device' : device, + 'port' : proxy['device'][device]['ssh']['port'], + } + render(dropbear_systemd_file.format(**tmp), + 'conserver/dropbear@.service.tmpl', tmp) + return None def apply(proxy): + call('systemctl daemon-reload') call('systemctl stop dropbear@*.service conserver-server.service') if not proxy: @@ -89,9 +103,10 @@ def apply(proxy): if 'device' in proxy: for device in proxy['device']: - if 'ssh' in proxy['device'][device]: - port = proxy['device'][device]['ssh']['port'] - call(f'systemctl restart dropbear@{device}.service') + if 'ssh' not in proxy['device'][device]: + continue + port = proxy['device'][device]['ssh']['port'] + call(f'systemctl restart dropbear@{port}.service') return None diff --git a/src/conf_mode/vrrp.py b/src/conf_mode/vrrp.py index 4510dd3e7..680a80859 100755 --- a/src/conf_mode/vrrp.py +++ b/src/conf_mode/vrrp.py @@ -75,6 +75,7 @@ def get_config(config=None): group["backup_script"] = config.return_value("transition-script backup") group["fault_script"] = config.return_value("transition-script fault") group["stop_script"] = config.return_value("transition-script stop") + group["script_mode_force"] = config.exists("transition-script mode-force") if config.exists("no-preempt"): group["preempt"] = False @@ -183,6 +184,11 @@ def verify(data): if isinstance(pa, IPv4Address): raise ConfigError("VRRP group {0} uses IPv6 but its peer-address is IPv4".format(group["name"])) + # Warn the user about the deprecated mode-force option + if group['script_mode_force']: + print("""Warning: "transition-script mode-force" VRRP option is deprecated and will be removed in VyOS 1.4.""") + print("""It's no longer necessary, so you can safely remove it from your config now.""") + # Disallow same VRID on multiple interfaces _groups = sorted(vrrp_groups, key=(lambda x: x["interface"])) count = len(_groups) - 1 diff --git a/src/migration-scripts/nat/4-to-5 b/src/migration-scripts/nat/4-to-5 index dda191719..b791996e2 100755 --- a/src/migration-scripts/nat/4-to-5 +++ b/src/migration-scripts/nat/4-to-5 @@ -36,9 +36,15 @@ if not config.exists(['nat']): exit(0) else: for direction in ['source', 'destination']: + # If a node doesn't exist, we obviously have nothing to do. if not config.exists(['nat', direction]): continue + # However, we also need to handle the case when a 'source' or 'destination' sub-node does exist, + # but there are no rules under it. + if not config.list_nodes(['nat', direction]): + continue + for rule in config.list_nodes(['nat', direction, 'rule']): base = ['nat', direction, 'rule', rule] diff --git a/src/services/vyos-configd b/src/services/vyos-configd index 3bd516463..1e60e53df 100755 --- a/src/services/vyos-configd +++ b/src/services/vyos-configd @@ -34,6 +34,8 @@ from vyos import ConfigError CFG_GROUP = 'vyattacfg' +script_stdout_log = '/tmp/vyos-configd-script-stdout' + debug = True logger = logging.getLogger(__name__) @@ -60,7 +62,8 @@ configd_env_unset_file = os.path.join(directories['data'], 'vyos-configd-env-uns # sourced on entering config session configd_env_file = '/etc/default/vyos-configd-env' -session_tty = None +session_out = None +session_mode = None def key_name_from_file_name(f): return os.path.splitext(f)[0] @@ -109,7 +112,7 @@ include_set = {key_name_from_file_name(f) for f in filenames if f in include} def run_script(script, config) -> int: config.set_level([]) try: - with open(session_tty, 'w') as f, redirect_stdout(f): + with open(session_out, session_mode) as f, redirect_stdout(f): with redirect_stderr(f): c = script.get_config(config) script.verify(c) @@ -117,7 +120,7 @@ def run_script(script, config) -> int: script.apply(c) except ConfigError as e: logger.critical(e) - with open(session_tty, 'w') as f, redirect_stdout(f): + with open(session_out, session_mode) as f, redirect_stdout(f): print(f"{e}\n") return R_ERROR_COMMIT except Exception as e: @@ -127,7 +130,8 @@ def run_script(script, config) -> int: return R_SUCCESS def initialization(socket): - global session_tty + global session_out + global session_mode # Reset config strings: active_string = '' session_string = '' @@ -155,9 +159,15 @@ def initialization(socket): logger.debug(f"config session pid is {pid_string}") try: - session_tty = os.readlink(f"/proc/{pid_string}/fd/1") + session_out = os.readlink(f"/proc/{pid_string}/fd/1") + session_mode = 'w' except FileNotFoundError: - session_tty = None + session_out = None + + # if not a 'live' session, for example on boot, write to file + if not session_out or '/dev/pts' not in session_out: + session_out = script_stdout_log + session_mode = 'a' try: configsource = ConfigSourceString(running_config_text=active_string, diff --git a/src/system/on-dhcp-event.sh b/src/system/on-dhcp-event.sh index a062dc810..49e53d7e1 100755 --- a/src/system/on-dhcp-event.sh +++ b/src/system/on-dhcp-event.sh @@ -21,21 +21,20 @@ client_mac=$4 domain=$5 hostsd_client="/usr/bin/vyos-hostsd-client" -if [ -z "$client_name" ]; then - logger -s -t on-dhcp-event "Client name was empty, using MAC \"$client_mac\" instead" - client_name=$(echo "client-"$client_mac | tr : -) -fi - -if [ "$domain" == "..YYZ!" ]; then - client_fqdn_name=$client_name - client_search_expr=$client_name -else - client_fqdn_name=$client_name.$domain - client_search_expr="$client_name\\.$domain" -fi - case "$action" in commit) # add mapping for new lease + if [ -z "$client_name" ]; then + logger -s -t on-dhcp-event "Client name was empty, using MAC \"$client_mac\" instead" + client_name=$(echo "client-"$client_mac | tr : -) + fi + + if [ "$domain" == "..YYZ!" ]; then + client_fqdn_name=$client_name + client_search_expr=$client_name + else + client_fqdn_name=$client_name.$domain + client_search_expr="$client_name\\.$domain" + fi $hostsd_client --add-hosts "$client_fqdn_name,$client_ip" --tag "dhcp-server-$client_ip" --apply exit 0 ;; diff --git a/src/systemd/dropbear@.service b/src/systemd/dropbear@.service index a3fde5708..acf926af9 100644 --- a/src/systemd/dropbear@.service +++ b/src/systemd/dropbear@.service @@ -8,9 +8,8 @@ StartLimitIntervalSec=0 [Service] Type=forking -ExecStartPre=/usr/bin/bash -c '/usr/bin/systemctl set-environment PORT=$(cli-shell-api returnActiveValue service console-server device "%I" ssh port)' -ExecStart=-/usr/sbin/dropbear -w -j -k -r /etc/dropbear/dropbear_rsa_host_key -c "/usr/bin/console %I" -P /run/conserver/dropbear.%I.pid -p ${PORT} -PIDFile=/run/conserver/dropbear.%I.pid +ExecStart=/usr/sbin/dropbear -w -j -k -r /etc/dropbear/dropbear_rsa_host_key -P /run/dropbear/dropbear.%I.pid -p %I +PIDFile=/run/dropbear/dropbear.%I.pid KillMode=process Restart=always RestartSec=10 diff --git a/src/tests/test_util.py b/src/tests/test_util.py index f7405cbde..22bc085c5 100644 --- a/src/tests/test_util.py +++ b/src/tests/test_util.py @@ -17,11 +17,7 @@ from unittest import TestCase from vyos.util import mangle_dict_keys - class TestVyOSUtil(TestCase): - def setUp(self): - pass - def test_key_mangline(self): data = {"foo-bar": {"baz-quux": None}} expected_data = {"foo_bar": {"baz_quux": None}} diff --git a/src/validators/interface-name b/src/validators/interface-name index 8e337b401..72e9fd54a 100755 --- a/src/validators/interface-name +++ b/src/validators/interface-name @@ -17,7 +17,7 @@ import re import sys -pattern = '^(bond|br|dum|en|ersp|eth|gnv|lan|l2tp|l2tpeth|macsec|peth|ppp|pppoe|pptp|sstp|tun|vti|vtun|vxlan|wg|wlan|wlm)[0-9]+|lo$' +pattern = '^(bond|br|dum|en|ersp|eth|gnv|lan|l2tp|l2tpeth|macsec|peth|ppp|pppoe|pptp|sstp|tun|vti|vtun|vxlan|wg|wlan|wlm)[0-9]+(.\d+)?|lo$' if __name__ == '__main__': if len(sys.argv) != 2: |