diff options
Diffstat (limited to 'src/conf_mode/interfaces-l2tpv3.py')
-rwxr-xr-x | src/conf_mode/interfaces-l2tpv3.py | 100 |
1 files changed, 59 insertions, 41 deletions
diff --git a/src/conf_mode/interfaces-l2tpv3.py b/src/conf_mode/interfaces-l2tpv3.py index ae49dadad..11ba9acdd 100755 --- a/src/conf_mode/interfaces-l2tpv3.py +++ b/src/conf_mode/interfaces-l2tpv3.py @@ -22,6 +22,8 @@ from copy import deepcopy from vyos.config import Config from vyos.ifconfig import L2TPv3If, Interface from vyos import ConfigError +from vyos.util import call +from vyos.util import is_bridge_member from netifaces import interfaces default_config_data = { @@ -33,6 +35,10 @@ default_config_data = { 'local_address': '', 'local_port': 5000, 'intf': '', + 'ipv6_autoconf': 0, + 'ipv6_eui64_prefix': '', + 'ipv6_forwarding': 1, + 'ipv6_dup_addr_detect': 1, 'mtu': 1488, 'peer_session_id': '', 'peer_tunnel_id': '', @@ -42,15 +48,22 @@ default_config_data = { 'tunnel_id': '' } +def check_kmod(): + modules = ['l2tp_eth', 'l2tp_netlink', 'l2tp_ip', 'l2tp_ip6'] + for module in modules: + if not os.path.exists(f'/sys/module/{module}'): + if call(f'modprobe {module}') != 0: + raise ConfigError(f'Loading Kernel module {module} failed') + def get_config(): l2tpv3 = deepcopy(default_config_data) conf = Config() # determine tagNode instance - try: - l2tpv3['intf'] = os.environ['VYOS_TAGNODE_VALUE'] - except KeyError as E: - print("Interface not specified") + if 'VYOS_TAGNODE_VALUE' not in os.environ: + raise ConfigError('Interface (VYOS_TAGNODE_VALUE) not specified') + + l2tpv3['intf'] = os.environ['VYOS_TAGNODE_VALUE'] # Check if interface has been removed if not conf.exists('interfaces l2tpv3 ' + l2tpv3['intf']): @@ -94,6 +107,22 @@ def get_config(): if conf.exists('local-ip'): l2tpv3['local_address'] = conf.return_value('local-ip') + # Enable acquisition of IPv6 address using stateless autoconfig (SLAAC) + if conf.exists('ipv6 address autoconf'): + l2tpv3['ipv6_autoconf'] = 1 + + # Get prefix for IPv6 addressing based on MAC address (EUI-64) + if conf.exists('ipv6 address eui64'): + l2tpv3['ipv6_eui64_prefix'] = conf.return_value('ipv6 address eui64') + + # Disable IPv6 forwarding on this interface + if conf.exists('ipv6 disable-forwarding'): + l2tpv3['ipv6_forwarding'] = 0 + + # IPv6 Duplicate Address Detection (DAD) tries + if conf.exists('ipv6 dup-addr-detect-transmits'): + l2tpv3['ipv6_dup_addr_detect'] = int(conf.return_value('ipv6 dup-addr-detect-transmits')) + # Maximum Transmission Unit (MTU) if conf.exists('mtu'): l2tpv3['mtu'] = int(conf.return_value('mtu')) @@ -126,61 +155,41 @@ def get_config(): def verify(l2tpv3): + interface = l2tpv3['intf'] + if l2tpv3['deleted']: - # bail out early + is_member, bridge = is_bridge_member(interface) + if is_member: + # can not use a f'' formatted-string here as bridge would not get + # expanded in the print statement + raise ConfigError('Can not delete interface "{0}" as it ' \ + 'is a member of bridge "{1}"!'.format(interface, bridge)) return None if not l2tpv3['local_address']: - raise ConfigError('Must configure the l2tpv3 local-ip for {}'.format(l2tpv3['intf'])) + raise ConfigError(f'Must configure the l2tpv3 local-ip for {interface}') if not l2tpv3['remote_address']: - raise ConfigError('Must configure the l2tpv3 remote-ip for {}'.format(l2tpv3['intf'])) + raise ConfigError(f'Must configure the l2tpv3 remote-ip for {interface}') if not l2tpv3['tunnel_id']: - raise ConfigError('Must configure the l2tpv3 tunnel-id for {}'.format(l2tpv3['intf'])) + raise ConfigError(f'Must configure the l2tpv3 tunnel-id for {interface}') if not l2tpv3['peer_tunnel_id']: - raise ConfigError('Must configure the l2tpv3 peer-tunnel-id for {}'.format(l2tpv3['intf'])) + raise ConfigError(f'Must configure the l2tpv3 peer-tunnel-id for {interface}') if not l2tpv3['session_id']: - raise ConfigError('Must configure the l2tpv3 session-id for {}'.format(l2tpv3['intf'])) + raise ConfigError(f'Must configure the l2tpv3 session-id for {interface}') if not l2tpv3['peer_session_id']: - raise ConfigError('Must configure the l2tpv3 peer-session-id for {}'.format(l2tpv3['intf'])) + raise ConfigError(f'Must configure the l2tpv3 peer-session-id for {interface}') return None def generate(l2tpv3): - if l2tpv3['deleted']: - # bail out early - return None - - # initialize kernel module if not loaded - if not os.path.isdir('/sys/module/l2tp_eth'): - if os.system('modprobe l2tp_eth') != 0: - raise ConfigError("failed loading l2tp_eth kernel module") - - if not os.path.isdir('/sys/module/l2tp_netlink'): - if os.system('modprobe l2tp_netlink') != 0: - raise ConfigError("failed loading l2tp_netlink kernel module") - - if not os.path.isdir('/sys/module/l2tp_ip'): - if os.system('modprobe l2tp_ip') != 0: - raise ConfigError("failed loading l2tp_ip kernel module") - - if l2tpv3['encapsulation'] == 'ip': - if not os.path.isdir('/sys/module/l2tp_ip'): - if os.system('modprobe l2tp_ip') != 0: - raise ConfigError("failed loading l2tp_ip kernel module") - - if not os.path.isdir('/sys/module/l2tp_ip6 '): - if os.system('modprobe l2tp_ip6 ') != 0: - raise ConfigError("failed loading l2tp_ip6 kernel module") - 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 @@ -193,7 +202,7 @@ def apply(l2tpv3): # always delete it first. conf['session_id'] = l2tpv3['session_id'] conf['tunnel_id'] = l2tpv3['tunnel_id'] - l = L2TPv3If(l2tpv3['intf'], config=conf) + l = L2TPv3If(l2tpv3['intf'], **conf) l.remove() if not l2tpv3['deleted']: @@ -208,11 +217,19 @@ def apply(l2tpv3): conf['peer_session_id'] = l2tpv3['peer_session_id'] # Finally create the new interface - l = L2TPv3If(l2tpv3['intf'], config=conf) + l = L2TPv3If(l2tpv3['intf'], **conf) # update interface description used e.g. by SNMP l.set_alias(l2tpv3['description']) # Maximum Transfer Unit (MTU) l.set_mtu(l2tpv3['mtu']) + # IPv6 address autoconfiguration + l.set_ipv6_autoconf(l2tpv3['ipv6_autoconf']) + # IPv6 EUI-based address + l.set_ipv6_eui64_address(l2tpv3['ipv6_eui64_prefix']) + # IPv6 forwarding + l.set_ipv6_forwarding(l2tpv3['ipv6_forwarding']) + # IPv6 Duplicate Address Detection (DAD) tries + l.set_ipv6_dad_messages(l2tpv3['ipv6_dup_addr_detect']) # Configure interface address(es) - no need to implicitly delete the # old addresses as they have already been removed by deleting the @@ -224,12 +241,13 @@ def apply(l2tpv3): # we will only re-enable the interface if it is not administratively # disabled if not l2tpv3['disable']: - l.set_state('up') + l.set_admin_state('up') return None if __name__ == '__main__': try: + check_kmod() c = get_config() verify(c) generate(c) |