summaryrefslogtreecommitdiff
path: root/src/conf_mode
diff options
context:
space:
mode:
authorMarcus Hoff <marcus.hoff@ring2.dk>2020-09-26 13:19:37 +0200
committerMarcus Hoff <marcus.hoff@ring2.dk>2020-09-26 13:19:37 +0200
commit1141bee72677b25d18436975625d2d298be503ff (patch)
tree4b6dc8fe1a8ced931e1ba08c58a348abfcd85a6b /src/conf_mode
parent45b30adfaaec7065f768d04085138a75a76ed376 (diff)
parent374724be64728101c262fcac1579beece63ee651 (diff)
downloadvyos-1x-1141bee72677b25d18436975625d2d298be503ff.tar.gz
vyos-1x-1141bee72677b25d18436975625d2d298be503ff.zip
Merge remote-tracking branch 'upstream/current' into current
Diffstat (limited to 'src/conf_mode')
-rwxr-xr-xsrc/conf_mode/dns_forwarding.py176
-rwxr-xr-xsrc/conf_mode/interfaces-bonding.py30
-rwxr-xr-xsrc/conf_mode/interfaces-bridge.py35
-rwxr-xr-xsrc/conf_mode/interfaces-ethernet.py11
-rwxr-xr-xsrc/conf_mode/interfaces-geneve.py13
-rwxr-xr-xsrc/conf_mode/interfaces-l2tpv3.py12
-rwxr-xr-xsrc/conf_mode/interfaces-macsec.py32
-rwxr-xr-xsrc/conf_mode/interfaces-openvpn.py11
-rwxr-xr-xsrc/conf_mode/interfaces-pppoe.py2
-rwxr-xr-xsrc/conf_mode/interfaces-pseudo-ethernet.py36
-rwxr-xr-xsrc/conf_mode/interfaces-tunnel.py9
-rwxr-xr-xsrc/conf_mode/interfaces-vxlan.py16
-rwxr-xr-xsrc/conf_mode/interfaces-wireguard.py2
-rwxr-xr-xsrc/conf_mode/interfaces-wireless.py11
-rwxr-xr-xsrc/conf_mode/snmp.py2
15 files changed, 192 insertions, 206 deletions
diff --git a/src/conf_mode/dns_forwarding.py b/src/conf_mode/dns_forwarding.py
index 53bc37882..5101c1e79 100755
--- a/src/conf_mode/dns_forwarding.py
+++ b/src/conf_mode/dns_forwarding.py
@@ -17,14 +17,17 @@
import os
from sys import exit
-from copy import deepcopy
from vyos.config import Config
+from vyos.configdict import dict_merge
from vyos.hostsd_client import Client as hostsd_client
-from vyos import ConfigError
-from vyos.util import call, chown
+from vyos.util import call
+from vyos.util import chown
+from vyos.util import vyos_dict_search
from vyos.template import render
+from vyos.xml import defaults
+from vyos import ConfigError
from vyos import airbag
airbag.enable()
@@ -35,136 +38,84 @@ pdns_rec_hostsd_lua_conf_file = f'{pdns_rec_run_dir}/recursor.vyos-hostsd.conf.l
pdns_rec_hostsd_zones_file = f'{pdns_rec_run_dir}/recursor.forward-zones.conf'
pdns_rec_config_file = f'{pdns_rec_run_dir}/recursor.conf'
-default_config_data = {
- 'allow_from': [],
- 'cache_size': 10000,
- 'export_hosts_file': 'yes',
- 'listen_address': [],
- 'name_servers': [],
- 'negative_ttl': 3600,
- 'system': False,
- 'domains': {},
- 'dnssec': 'process-no-validate',
- 'dhcp_interfaces': []
-}
-
hostsd_tag = 'static'
-def get_config(conf):
- dns = deepcopy(default_config_data)
+def get_config(config=None):
+ if config:
+ conf = config
+ else:
+ conf = Config()
base = ['service', 'dns', 'forwarding']
-
if not conf.exists(base):
return None
- conf.set_level(base)
-
- if conf.exists(['allow-from']):
- dns['allow_from'] = conf.return_values(['allow-from'])
-
- if conf.exists(['cache-size']):
- cache_size = conf.return_value(['cache-size'])
- dns['cache_size'] = cache_size
-
- if conf.exists('negative-ttl'):
- negative_ttl = conf.return_value(['negative-ttl'])
- dns['negative_ttl'] = negative_ttl
-
- if conf.exists(['domain']):
- for domain in conf.list_nodes(['domain']):
- conf.set_level(base + ['domain', domain])
- entry = {
- 'nslist': bracketize_ipv6_addrs(conf.return_values(['server'])),
- 'addNTA': conf.exists(['addnta']),
- 'recursion-desired': conf.exists(['recursion-desired'])
- }
- dns['domains'][domain] = entry
-
- conf.set_level(base)
+ dns = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True)
+ # We have gathered the dict representation of the CLI, but there are default
+ # options which we need to update into the dictionary retrived.
+ default_values = defaults(base)
+ dns = dict_merge(default_values, dns)
- if conf.exists(['ignore-hosts-file']):
- dns['export_hosts_file'] = "no"
+ # some additions to the default dictionary
+ if 'system' in dns:
+ base_nameservers = ['system', 'name-server']
+ if conf.exists(base_nameservers):
+ dns.update({'system_name_server': conf.return_values(base_nameservers)})
- if conf.exists(['name-server']):
- dns['name_servers'] = bracketize_ipv6_addrs(
- conf.return_values(['name-server']))
-
- if conf.exists(['system']):
- dns['system'] = True
-
- if conf.exists(['listen-address']):
- dns['listen_address'] = conf.return_values(['listen-address'])
-
- if conf.exists(['dnssec']):
- dns['dnssec'] = conf.return_value(['dnssec'])
-
- if conf.exists(['dhcp']):
- dns['dhcp_interfaces'] = conf.return_values(['dhcp'])
+ base_nameservers_dhcp = ['system', 'name-servers-dhcp']
+ if conf.exists(base_nameservers_dhcp):
+ dns.update({'system_name_server_dhcp': conf.return_values(base_nameservers_dhcp)})
return dns
-def bracketize_ipv6_addrs(addrs):
- """Wraps each IPv6 addr in addrs in [], leaving IPv4 addrs untouched."""
- return ['[{0}]'.format(a) if a.count(':') > 1 else a for a in addrs]
-
-def verify(conf, dns):
+def verify(dns):
# bail out early - looks like removal from running config
- if dns is None:
+ if not dns:
return None
- if not dns['listen_address']:
- raise ConfigError(
- "Error: DNS forwarding requires a listen-address")
-
- if not dns['allow_from']:
- raise ConfigError(
- "Error: DNS forwarding requires an allow-from network")
-
- if dns['domains']:
- for domain in dns['domains']:
- if not dns['domains'][domain]['nslist']:
- raise ConfigError((
- f'Error: No server configured for domain {domain}'))
-
- no_system_nameservers = False
- conf.set_level([])
- if dns['system'] and not (
- conf.exists(['system', 'name-server']) or
- conf.exists(['system', 'name-servers-dhcp']) ):
- no_system_nameservers = True
- print(("DNS forwarding warning: No 'system name-server' or "
- "'system name-servers-dhcp' set\n"))
-
- if (no_system_nameservers or not dns['system']) and not (
- dns['name_servers'] or dns['dhcp_interfaces']):
- print(("DNS forwarding warning: No 'dhcp', 'name-server' or 'system' "
- "nameservers set. Forwarding will operate as a recursor.\n"))
+ if 'listen_address' not in dns:
+ raise ConfigError('DNS forwarding requires a listen-address')
+
+ if 'allow_from' not in dns:
+ raise ConfigError('DNS forwarding requires an allow-from network')
+
+ # we can not use vyos_dict_search() when testing for domain servers
+ # as a domain will contains dot's which is out dictionary delimiter.
+ if 'domain' in dns:
+ for domain in dns['domain']:
+ if 'server' not in dns['domain'][domain]:
+ raise ConfigError(f'No server configured for domain {domain}!')
+
+ if 'system' in dns:
+ if not ('system_name_server' in dns or 'system_name_server_dhcp' in dns):
+ print("Warning: No 'system name-server' or 'system " \
+ "name-servers-dhcp' configured")
return None
def generate(dns):
# bail out early - looks like removal from running config
- if dns is None:
+ if not dns:
return None
render(pdns_rec_config_file, 'dns-forwarding/recursor.conf.tmpl',
- dns, user=pdns_rec_user, group=pdns_rec_group)
+ dns, trim_blocks=True, user=pdns_rec_user, group=pdns_rec_group)
render(pdns_rec_lua_conf_file, 'dns-forwarding/recursor.conf.lua.tmpl',
- dns, user=pdns_rec_user, group=pdns_rec_group)
+ dns, trim_blocks=True, user=pdns_rec_user, group=pdns_rec_group)
# if vyos-hostsd didn't create its files yet, create them (empty)
- for f in [pdns_rec_hostsd_lua_conf_file, pdns_rec_hostsd_zones_file]:
- with open(f, 'a'):
+ for file in [pdns_rec_hostsd_lua_conf_file, pdns_rec_hostsd_zones_file]:
+ with open(file, 'a'):
pass
- chown(f, user=pdns_rec_user, group=pdns_rec_group)
+ chown(file, user=pdns_rec_user, group=pdns_rec_group)
return None
def apply(dns):
- if dns is None:
+ if not dns:
# DNS forwarding is removed in the commit
- call("systemctl stop pdns-recursor.service")
+ call('systemctl stop pdns-recursor.service')
+
if os.path.isfile(pdns_rec_config_file):
os.unlink(pdns_rec_config_file)
else:
@@ -174,8 +125,8 @@ def apply(dns):
# add static nameservers to hostsd so they can be joined with other
# sources
hc.delete_name_servers([hostsd_tag])
- if dns['name_servers']:
- hc.add_name_servers({hostsd_tag: dns['name_servers']})
+ if 'name_server' in dns:
+ hc.add_name_servers({hostsd_tag: dns['name_server']})
# delete all nameserver tags
hc.delete_name_server_tags_recursor(hc.get_name_server_tags_recursor())
@@ -184,32 +135,33 @@ def apply(dns):
# our own tag (static)
hc.add_name_server_tags_recursor([hostsd_tag])
- if dns['system']:
+ if 'system' in dns:
hc.add_name_server_tags_recursor(['system'])
else:
hc.delete_name_server_tags_recursor(['system'])
# add dhcp nameserver tags for configured interfaces
- for intf in dns['dhcp_interfaces']:
- hc.add_name_server_tags_recursor(['dhcp-' + intf, 'dhcpv6-' + intf ])
+ if 'system_name_server_dhcp' in dns:
+ for interface in dns['system_name_server_dhcp']:
+ hc.add_name_server_tags_recursor(['dhcp-' + interface,
+ 'dhcpv6-' + interface ])
# hostsd will generate the forward-zones file
# the list and keys() are required as get returns a dict, not list
hc.delete_forward_zones(list(hc.get_forward_zones().keys()))
- if dns['domains']:
- hc.add_forward_zones(dns['domains'])
+ if 'domain' in dns:
+ hc.add_forward_zones(dns['domain'])
# call hostsd to generate forward-zones and its lua-config-file
hc.apply()
### finally (re)start pdns-recursor
- call("systemctl restart pdns-recursor.service")
+ call('systemctl restart pdns-recursor.service')
if __name__ == '__main__':
try:
- conf = Config()
- c = get_config(conf)
- verify(conf, c)
+ c = get_config()
+ verify(c)
generate(c)
apply(c)
except ConfigError as e:
diff --git a/src/conf_mode/interfaces-bonding.py b/src/conf_mode/interfaces-bonding.py
index a9679b47c..9763620ac 100755
--- a/src/conf_mode/interfaces-bonding.py
+++ b/src/conf_mode/interfaces-bonding.py
@@ -22,15 +22,18 @@ from netifaces import interfaces
from vyos.config import Config
from vyos.configdict import get_interface_dict
from vyos.configdict import leaf_node_changed
+from vyos.configdict import is_member
+from vyos.configdict import is_source_interface
from vyos.configverify import verify_address
from vyos.configverify import verify_bridge_delete
from vyos.configverify import verify_dhcpv6
from vyos.configverify import verify_source_interface
+from vyos.configverify import verify_mtu_ipv6
from vyos.configverify import verify_vlan_config
from vyos.configverify import verify_vrf
from vyos.ifconfig import BondIf
from vyos.ifconfig import Section
-from vyos.validate import is_member
+from vyos.util import vyos_dict_search
from vyos.validate import has_address_configured
from vyos import ConfigError
from vyos import airbag
@@ -98,18 +101,21 @@ def get_config(config=None):
# also present the interfaces to be removed from the bond as dictionary
bond['member'].update({'interface_remove': tmp})
- if 'member' in bond and 'interface' in bond['member']:
+ if vyos_dict_search('member.interface', bond):
for interface, interface_config in bond['member']['interface'].items():
- # Check if we are a member of another bond device
+ # Check if member interface is already member of another bridge
tmp = is_member(conf, interface, 'bridge')
- if tmp:
- interface_config.update({'is_bridge_member' : tmp})
+ if tmp: interface_config.update({'is_bridge_member' : tmp})
- # Check if we are a member of a bond device
+ # Check if member interface is already member of a bond
tmp = is_member(conf, interface, 'bonding')
if tmp and tmp != bond['ifname']:
interface_config.update({'is_bond_member' : tmp})
+ # Check if member interface is used as source-interface on another interface
+ tmp = is_source_interface(conf, interface)
+ if tmp: interface_config.update({'is_source_interface' : tmp})
+
# bond members must not have an assigned address
tmp = has_address_configured(conf, interface)
if tmp: interface_config.update({'has_address' : ''})
@@ -136,6 +142,7 @@ def verify(bond):
raise ConfigError('Option primary - mode dependency failed, not'
'supported in mode {mode}!'.format(**bond))
+ verify_mtu_ipv6(bond)
verify_address(bond)
verify_dhcpv6(bond)
verify_vrf(bond)
@@ -144,10 +151,9 @@ def verify(bond):
verify_vlan_config(bond)
bond_name = bond['ifname']
- if 'member' in bond:
- member = bond.get('member')
- for interface, interface_config in member.get('interface', {}).items():
- error_msg = f'Can not add interface "{interface}" to bond "{bond_name}", '
+ if vyos_dict_search('member.interface', bond):
+ for interface, interface_config in bond['member']['interface'].items():
+ error_msg = f'Can not add interface "{interface}" to bond, '
if interface == 'lo':
raise ConfigError('Loopback interface "lo" can not be added to a bond')
@@ -163,6 +169,10 @@ def verify(bond):
tmp = interface_config['is_bond_member']
raise ConfigError(error_msg + f'it is already a member of bond "{tmp}"!')
+ if 'is_source_interface' in interface_config:
+ tmp = interface_config['is_source_interface']
+ raise ConfigError(error_msg + f'it is the source-interface of "{tmp}"!')
+
if 'has_address' in interface_config:
raise ConfigError(error_msg + 'it has an address assigned!')
diff --git a/src/conf_mode/interfaces-bridge.py b/src/conf_mode/interfaces-bridge.py
index 47c8c05f9..485decb17 100755
--- a/src/conf_mode/interfaces-bridge.py
+++ b/src/conf_mode/interfaces-bridge.py
@@ -22,13 +22,16 @@ from netifaces import interfaces
from vyos.config import Config
from vyos.configdict import get_interface_dict
from vyos.configdict import node_changed
+from vyos.configdict import is_member
+from vyos.configdict import is_source_interface
from vyos.configverify import verify_dhcpv6
from vyos.configverify import verify_vrf
from vyos.ifconfig import BridgeIf
-from vyos.validate import is_member, has_address_configured
+from vyos.validate import has_address_configured
from vyos.xml import defaults
from vyos.util import cmd
+from vyos.util import vyos_dict_search
from vyos import ConfigError
from vyos import airbag
@@ -54,8 +57,8 @@ def get_config(config=None):
else:
bridge.update({'member': {'interface_remove': tmp }})
- if 'member' in bridge and 'interface' in bridge['member']:
- # XXX TT2665 we need a copy of the dict keys for iteration, else we will get:
+ if vyos_dict_search('member.interface', bridge):
+ # XXX: T2665: we need a copy of the dict keys for iteration, else we will get:
# RuntimeError: dictionary changed size during iteration
for interface in list(bridge['member']['interface']):
for key in ['cost', 'priority']:
@@ -69,20 +72,22 @@ def get_config(config=None):
for interface, interface_config in bridge['member']['interface'].items():
interface_config.update(default_member_values)
- # Check if we are a member of another bridge device
+ # Check if member interface is already member of another bridge
tmp = is_member(conf, interface, 'bridge')
if tmp and tmp != bridge['ifname']:
interface_config.update({'is_bridge_member' : tmp})
- # Check if we are a member of a bond device
+ # Check if member interface is already member of a bond
tmp = is_member(conf, interface, 'bonding')
- if tmp:
- interface_config.update({'is_bond_member' : tmp})
+ if tmp: interface_config.update({'is_bond_member' : tmp})
+
+ # Check if member interface is used as source-interface on another interface
+ tmp = is_source_interface(conf, interface)
+ if tmp: interface_config.update({'is_source_interface' : tmp})
# Bridge members must not have an assigned address
tmp = has_address_configured(conf, interface)
- if tmp:
- interface_config.update({'has_address' : ''})
+ if tmp: interface_config.update({'has_address' : ''})
return bridge
@@ -93,11 +98,9 @@ def verify(bridge):
verify_dhcpv6(bridge)
verify_vrf(bridge)
- if 'member' in bridge:
- member = bridge.get('member')
- bridge_name = bridge['ifname']
- for interface, interface_config in member.get('interface', {}).items():
- error_msg = f'Can not add interface "{interface}" to bridge "{bridge_name}", '
+ if vyos_dict_search('member.interface', bridge):
+ for interface, interface_config in bridge['member']['interface'].items():
+ error_msg = f'Can not add interface "{interface}" to bridge, '
if interface == 'lo':
raise ConfigError('Loopback interface "lo" can not be added to a bridge')
@@ -113,6 +116,10 @@ def verify(bridge):
tmp = interface_config['is_bond_member']
raise ConfigError(error_msg + f'it is already a member of bond "{tmp}"!')
+ if 'is_source_interface' in interface_config:
+ tmp = interface_config['is_source_interface']
+ raise ConfigError(error_msg + f'it is the source-interface of "{tmp}"!')
+
if 'has_address' in interface_config:
raise ConfigError(error_msg + 'it has an address assigned!')
diff --git a/src/conf_mode/interfaces-ethernet.py b/src/conf_mode/interfaces-ethernet.py
index a8df64cce..1f622c003 100755
--- a/src/conf_mode/interfaces-ethernet.py
+++ b/src/conf_mode/interfaces-ethernet.py
@@ -20,11 +20,13 @@ from sys import exit
from vyos.config import Config
from vyos.configdict import get_interface_dict
-from vyos.configverify import verify_interface_exists
-from vyos.configverify import verify_dhcpv6
from vyos.configverify import verify_address
-from vyos.configverify import verify_vrf
+from vyos.configverify import verify_dhcpv6
+from vyos.configverify import verify_interface_exists
+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.ifconfig import EthernetIf
from vyos import ConfigError
from vyos import airbag
@@ -41,6 +43,7 @@ def get_config(config=None):
conf = Config()
base = ['interfaces', 'ethernet']
ethernet = get_interface_dict(conf, base)
+
return ethernet
def verify(ethernet):
@@ -57,6 +60,8 @@ def verify(ethernet):
if ethernet.get('speed', None) != 'auto':
raise ConfigError('If duplex is hardcoded, speed must be hardcoded, too')
+ verify_mtu(ethernet)
+ verify_mtu_ipv6(ethernet)
verify_dhcpv6(ethernet)
verify_address(ethernet)
verify_vrf(ethernet)
diff --git a/src/conf_mode/interfaces-geneve.py b/src/conf_mode/interfaces-geneve.py
index cc2cf025a..979a5612e 100755
--- a/src/conf_mode/interfaces-geneve.py
+++ b/src/conf_mode/interfaces-geneve.py
@@ -17,12 +17,12 @@
import os
from sys import exit
-from copy import deepcopy
from netifaces import interfaces
from vyos.config import Config
from vyos.configdict import get_interface_dict
from vyos.configverify import verify_address
+from vyos.configverify import verify_mtu_ipv6
from vyos.configverify import verify_bridge_delete
from vyos.ifconfig import GeneveIf
from vyos import ConfigError
@@ -48,6 +48,7 @@ def verify(geneve):
verify_bridge_delete(geneve)
return None
+ verify_mtu_ipv6(geneve)
verify_address(geneve)
if 'remote' not in geneve:
@@ -62,7 +63,6 @@ def verify(geneve):
def generate(geneve):
return None
-
def apply(geneve):
# Check if GENEVE interface already exists
if geneve['ifname'] in interfaces():
@@ -72,10 +72,11 @@ def apply(geneve):
g.remove()
if 'deleted' not in geneve:
- # GENEVE interface needs to be created on-block
- # instead of passing a ton of arguments, I just use a dict
- # that is managed by vyos.ifconfig
- conf = deepcopy(GeneveIf.get_config())
+ # This is a special type of interface which needs additional parameters
+ # when created using iproute2. Instead of passing a ton of arguments,
+ # use a dictionary provided by the interface class which holds all the
+ # options necessary.
+ conf = GeneveIf.get_config()
# Assign GENEVE instance configuration parameters to config dict
conf['vni'] = geneve['vni']
diff --git a/src/conf_mode/interfaces-l2tpv3.py b/src/conf_mode/interfaces-l2tpv3.py
index 144cee5fe..1118143e4 100755
--- a/src/conf_mode/interfaces-l2tpv3.py
+++ b/src/conf_mode/interfaces-l2tpv3.py
@@ -17,7 +17,6 @@
import os
from sys import exit
-from copy import deepcopy
from netifaces import interfaces
from vyos.config import Config
@@ -25,6 +24,7 @@ from vyos.configdict import get_interface_dict
from vyos.configdict import leaf_node_changed
from vyos.configverify import verify_address
from vyos.configverify import verify_bridge_delete
+from vyos.configverify import verify_mtu_ipv6
from vyos.ifconfig import L2TPv3If
from vyos.util import check_kmod
from vyos.validate import is_addr_assigned
@@ -81,6 +81,7 @@ def verify(l2tpv3):
raise ConfigError('L2TPv3 local-ip address '
'"{local_ip}" is not configured!'.format(**l2tpv3))
+ verify_mtu_ipv6(l2tpv3)
verify_address(l2tpv3)
return None
@@ -88,10 +89,11 @@ def generate(l2tpv3):
return None
def apply(l2tpv3):
- # L2TPv3 interface needs to be created/deleted on-block, instead of
- # passing a ton of arguments, I just use a dict that is managed by
- # vyos.ifconfig
- conf = deepcopy(L2TPv3If.get_config())
+ # This is a special type of interface which needs additional parameters
+ # when created using iproute2. Instead of passing a ton of arguments,
+ # use a dictionary provided by the interface class which holds all the
+ # options necessary.
+ conf = L2TPv3If.get_config()
# Check if L2TPv3 interface already exists
if l2tpv3['ifname'] in interfaces():
diff --git a/src/conf_mode/interfaces-macsec.py b/src/conf_mode/interfaces-macsec.py
index 2866ccc0a..0a20a121b 100755
--- a/src/conf_mode/interfaces-macsec.py
+++ b/src/conf_mode/interfaces-macsec.py
@@ -16,17 +16,18 @@
import os
-from copy import deepcopy
from sys import exit
from vyos.config import Config
from vyos.configdict import get_interface_dict
from vyos.ifconfig import MACsecIf
+from vyos.ifconfig import Interface
from vyos.template import render
from vyos.util import call
from vyos.configverify import verify_vrf
from vyos.configverify import verify_address
from vyos.configverify import verify_bridge_delete
+from vyos.configverify import verify_mtu_ipv6
from vyos.configverify import verify_source_interface
from vyos import ConfigError
from vyos import airbag
@@ -47,6 +48,14 @@ def get_config(config=None):
base = ['interfaces', 'macsec']
macsec = get_interface_dict(conf, base)
+ # MACsec is "special" the default MTU is 1460 - update accordingly
+ # as the config_level is already st in get_interface_dict() - we can use []
+ tmp = conf.get_config_dict([], key_mangling=('-', '_'), get_first_key=True)
+ if 'mtu' not in tmp:
+ # base MTU for MACsec is 1468 bytes, but we leave room for 802.1ad and
+ # 802.1q VLAN tags, thus the limit is 1460 bytes.
+ macsec['mtu'] = '1460'
+
# Check if interface has been removed
if 'deleted' in macsec:
source_interface = conf.return_effective_value(
@@ -63,6 +72,7 @@ def verify(macsec):
verify_source_interface(macsec)
verify_vrf(macsec)
+ verify_mtu_ipv6(macsec)
verify_address(macsec)
if not (('security' in macsec) and
@@ -80,6 +90,15 @@ def verify(macsec):
raise ConfigError('Missing mandatory MACsec security '
'keys as encryption is enabled!')
+ if 'source_interface' in macsec:
+ # MACsec adds a 40 byte overhead (32 byte MACsec + 8 bytes VLAN 802.1ad
+ # and 802.1q) - we need to check the underlaying MTU if our configured
+ # MTU is at least 40 bytes less then the MTU of our physical interface.
+ lower_mtu = Interface(macsec['source_interface']).get_mtu()
+ if lower_mtu < (int(macsec['mtu']) + 40):
+ raise ConfigError('MACsec overhead does not fit into underlaying device MTU,\n' \
+ f'{underlay_mtu} bytes is too small!')
+
return None
@@ -102,12 +121,11 @@ def apply(macsec):
os.unlink(wpa_suppl_conf.format(**macsec))
else:
- # MACsec interfaces require a configuration when they are added using
- # iproute2. This static method will provide the configuration
- # dictionary used by this class.
-
- # XXX: subject of removal after completing T2653
- conf = deepcopy(MACsecIf.get_config())
+ # This is a special type of interface which needs additional parameters
+ # when created using iproute2. Instead of passing a ton of arguments,
+ # use a dictionary provided by the interface class which holds all the
+ # options necessary.
+ conf = MACsecIf.get_config()
conf['source_interface'] = macsec['source_interface']
conf['security_cipher'] = macsec['security']['cipher']
diff --git a/src/conf_mode/interfaces-openvpn.py b/src/conf_mode/interfaces-openvpn.py
index 958b305dd..518dbdc0e 100755
--- a/src/conf_mode/interfaces-openvpn.py
+++ b/src/conf_mode/interfaces-openvpn.py
@@ -26,10 +26,11 @@ from shutil import rmtree
from vyos.config import Config
from vyos.configdict import list_diff
+from vyos.configdict import is_member
from vyos.ifconfig import VTunIf
from vyos.template import render
from vyos.util import call, chown, chmod_600, chmod_755
-from vyos.validate import is_addr_assigned, is_member, is_ipv4
+from vyos.validate import is_addr_assigned, is_ipv4
from vyos import ConfigError
from vyos import airbag
@@ -256,7 +257,10 @@ def get_config(config=None):
if conf.exists('encryption ncp-ciphers'):
_ncp_ciphers = []
for enc in conf.return_values('encryption ncp-ciphers'):
- if enc == 'des':
+ if enc == 'none':
+ _ncp_ciphers.append('none')
+ _ncp_ciphers.append('NONE')
+ elif enc == 'des':
_ncp_ciphers.append('des-cbc')
_ncp_ciphers.append('DES-CBC')
elif enc == '3des':
@@ -943,6 +947,9 @@ def verify(openvpn):
else:
print('Diffie-Hellman prime file is unspecified, assuming ECDH')
+ if openvpn['encryption'] == 'none':
+ print('Warning: "encryption none" was specified. NO encryption will be performed and tunnelled data WILL be transmitted in clear text over the network!')
+
#
# Auth user/pass
#
diff --git a/src/conf_mode/interfaces-pppoe.py b/src/conf_mode/interfaces-pppoe.py
index 1b4b9e4ee..ee3b142c8 100755
--- a/src/conf_mode/interfaces-pppoe.py
+++ b/src/conf_mode/interfaces-pppoe.py
@@ -24,6 +24,7 @@ from vyos.config import Config
from vyos.configdict import get_interface_dict
from vyos.configverify import verify_source_interface
from vyos.configverify import verify_vrf
+from vyos.configverify import verify_mtu_ipv6
from vyos.template import render
from vyos.util import call
from vyos import ConfigError
@@ -57,6 +58,7 @@ def verify(pppoe):
verify_source_interface(pppoe)
verify_vrf(pppoe)
+ verify_mtu_ipv6(pppoe)
if {'connect_on_demand', 'vrf'} <= set(pppoe):
raise ConfigError('On-demand dialing and VRF can not be used at the same time')
diff --git a/src/conf_mode/interfaces-pseudo-ethernet.py b/src/conf_mode/interfaces-pseudo-ethernet.py
index 59edca1cc..ddbef56ac 100755
--- a/src/conf_mode/interfaces-pseudo-ethernet.py
+++ b/src/conf_mode/interfaces-pseudo-ethernet.py
@@ -14,9 +14,6 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-import os
-
-from copy import deepcopy
from sys import exit
from vyos.config import Config
@@ -28,7 +25,6 @@ from vyos.configverify import verify_bridge_delete
from vyos.configverify import verify_source_interface
from vyos.configverify import verify_vlan_config
from vyos.ifconfig import MACVLANIf
-from vyos.validate import is_member
from vyos import ConfigError
from vyos import airbag
@@ -47,19 +43,7 @@ def get_config(config=None):
peth = get_interface_dict(conf, base)
mode = leaf_node_changed(conf, ['mode'])
- if mode:
- peth.update({'mode_old' : mode})
-
- # Check if source-interface is member of a bridge device
- if 'source_interface' in peth:
- bridge = is_member(conf, peth['source_interface'], 'bridge')
- if bridge:
- peth.update({'source_interface_is_bridge_member' : bridge})
-
- # Check if we are a member of a bond device
- bond = is_member(conf, peth['source_interface'], 'bonding')
- if bond:
- peth.update({'source_interface_is_bond_member' : bond})
+ if mode: peth.update({'mode_old' : mode})
return peth
@@ -72,16 +56,6 @@ def verify(peth):
verify_vrf(peth)
verify_address(peth)
- if 'source_interface_is_bridge_member' in peth:
- raise ConfigError(
- 'Source interface "{source_interface}" can not be used as it is already a '
- 'member of bridge "{source_interface_is_bridge_member}"!'.format(**peth))
-
- if 'source_interface_is_bond_member' in peth:
- raise ConfigError(
- 'Source interface "{source_interface}" can not be used as it is already a '
- 'member of bond "{source_interface_is_bond_member}"!'.format(**peth))
-
# use common function to verify VLAN configuration
verify_vlan_config(peth)
return None
@@ -101,9 +75,11 @@ def apply(peth):
if 'mode_old' in peth:
MACVLANIf(peth['ifname']).remove()
- # MACVLAN interface needs to be created on-block instead of passing a ton
- # of arguments, I just use a dict that is managed by vyos.ifconfig
- conf = deepcopy(MACVLANIf.get_config())
+ # This is a special type of interface which needs additional parameters
+ # when created using iproute2. Instead of passing a ton of arguments,
+ # use a dictionary provided by the interface class which holds all the
+ # options necessary.
+ conf = MACVLANIf.get_config()
# Assign MACVLAN instance configuration parameters to config dict
conf['source_interface'] = peth['source_interface']
diff --git a/src/conf_mode/interfaces-tunnel.py b/src/conf_mode/interfaces-tunnel.py
index 11d8d6edc..f1d885b15 100755
--- a/src/conf_mode/interfaces-tunnel.py
+++ b/src/conf_mode/interfaces-tunnel.py
@@ -22,10 +22,11 @@ from copy import deepcopy
from netifaces import interfaces
from vyos.config import Config
+from vyos.configdict import is_member
from vyos.ifconfig import Interface, GREIf, GRETapIf, IPIPIf, IP6GREIf, IPIP6If, IP6IP6If, SitIf, Sit6RDIf
from vyos.ifconfig.afi import IP4, IP6
from vyos.configdict import list_diff
-from vyos.validate import is_ipv4, is_ipv6, is_member
+from vyos.validate import is_ipv4, is_ipv6
from vyos import ConfigError
from vyos.dicts import FixedDict
@@ -170,8 +171,8 @@ class ConfigurationState(object):
"""
>>> conf.get_values('addresses', 'address')
will place a list of the new IP present in 'interface dummy dum1 address'
- into the dictionnary entry "-add" (here 'addresses-add') using
- Config.return_values and will add the the one which were removed in into
+ into the dictionnary entry "-add" (here 'addresses-add') using
+ Config.return_values and will add the the one which were removed in into
the entry "-del" (here addresses-del')
"""
add_name = f'{name}-add'
@@ -263,7 +264,7 @@ class ConfigurationState(object):
d = d[lpath[-1]]
# XXX: it should have provided me the content and not the key
self._conf.set_level(l)
- return d
+ return d
def to_api(self):
"""
diff --git a/src/conf_mode/interfaces-vxlan.py b/src/conf_mode/interfaces-vxlan.py
index bea3aa25b..002f40aef 100755
--- a/src/conf_mode/interfaces-vxlan.py
+++ b/src/conf_mode/interfaces-vxlan.py
@@ -17,13 +17,13 @@
import os
from sys import exit
-from copy import deepcopy
from netifaces import interfaces
from vyos.config import Config
from vyos.configdict import get_interface_dict
from vyos.configverify import verify_address
from vyos.configverify import verify_bridge_delete
+from vyos.configverify import verify_mtu_ipv6
from vyos.configverify import verify_source_interface
from vyos.ifconfig import VXLANIf, Interface
from vyos import ConfigError
@@ -73,11 +73,12 @@ def verify(vxlan):
if 'source_interface' in vxlan:
# VXLAN adds a 50 byte overhead - we need to check the underlaying MTU
# if our configured MTU is at least 50 bytes less
- underlay_mtu = int(Interface(vxlan['source_interface']).get_mtu())
- if underlay_mtu < (int(vxlan['mtu']) + 50):
+ lower_mtu = Interface(vxlan['source_interface']).get_mtu()
+ if lower_mtu < (int(vxlan['mtu']) + 50):
raise ConfigError('VXLAN has a 50 byte overhead, underlaying device ' \
f'MTU is to small ({underlay_mtu} bytes)')
+ verify_mtu_ipv6(vxlan)
verify_address(vxlan)
return None
@@ -95,10 +96,11 @@ def apply(vxlan):
v.remove()
if 'deleted' not in vxlan:
- # VXLAN interface needs to be created on-block
- # instead of passing a ton of arguments, I just use a dict
- # that is managed by vyos.ifconfig
- conf = deepcopy(VXLANIf.get_config())
+ # This is a special type of interface which needs additional parameters
+ # when created using iproute2. Instead of passing a ton of arguments,
+ # use a dictionary provided by the interface class which holds all the
+ # options necessary.
+ conf = VXLANIf.get_config()
# Assign VXLAN instance configuration parameters to config dict
for tmp in ['vni', 'group', 'source_address', 'source_interface', 'remote', 'port']:
diff --git a/src/conf_mode/interfaces-wireguard.py b/src/conf_mode/interfaces-wireguard.py
index e7c22da1a..d5800264f 100755
--- a/src/conf_mode/interfaces-wireguard.py
+++ b/src/conf_mode/interfaces-wireguard.py
@@ -27,6 +27,7 @@ from vyos.configdict import leaf_node_changed
from vyos.configverify import verify_vrf
from vyos.configverify import verify_address
from vyos.configverify import verify_bridge_delete
+from vyos.configverify import verify_mtu_ipv6
from vyos.ifconfig import WireGuardIf
from vyos.util import check_kmod
from vyos import ConfigError
@@ -71,6 +72,7 @@ def verify(wireguard):
verify_bridge_delete(wireguard)
return None
+ verify_mtu_ipv6(wireguard)
verify_address(wireguard)
verify_vrf(wireguard)
diff --git a/src/conf_mode/interfaces-wireless.py b/src/conf_mode/interfaces-wireless.py
index c6c843e7b..f8520aecf 100755
--- a/src/conf_mode/interfaces-wireless.py
+++ b/src/conf_mode/interfaces-wireless.py
@@ -18,7 +18,6 @@ import os
from sys import exit
from re import findall
-from copy import deepcopy
from netaddr import EUI, mac_unix_expanded
from vyos.config import Config
@@ -233,13 +232,15 @@ def apply(wifi):
if 'deleted' in wifi:
WiFiIf(interface).remove()
else:
- # WiFi interface needs to be created on-block (e.g. mode or physical
- # interface) instead of passing a ton of arguments, I just use a dict
- # that is managed by vyos.ifconfig
- conf = deepcopy(WiFiIf.get_config())
+ # This is a special type of interface which needs additional parameters
+ # when created using iproute2. Instead of passing a ton of arguments,
+ # use a dictionary provided by the interface class which holds all the
+ # options necessary.
+ conf = WiFiIf.get_config()
# Assign WiFi instance configuration parameters to config dict
conf['phy'] = wifi['physical_device']
+ conf['wds'] = 'on' if 'wds' in wifi else 'off'
# Finally create the new interface
w = WiFiIf(interface, **conf)
diff --git a/src/conf_mode/snmp.py b/src/conf_mode/snmp.py
index e9806ef47..117bf0274 100755
--- a/src/conf_mode/snmp.py
+++ b/src/conf_mode/snmp.py
@@ -22,7 +22,7 @@ from vyos.config import Config
from vyos.configverify import verify_vrf
from vyos.snmpv3_hashgen import plaintext_to_md5, plaintext_to_sha1, random
from vyos.template import render
-from vyos.util import call
+from vyos.util import call, chmod_755
from vyos.validate import is_ipv4, is_addr_assigned
from vyos.version import get_version_data
from vyos import ConfigError, airbag