# Copyright 2019-2023 VyOS maintainers and contributors <maintainers@vyos.io> # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library. If not, see <http://www.gnu.org/licenses/>. from time import sleep from time import time from vyos.utils.process import run from vyos.ifconfig.interface import Interface def wait_for_add_l2tpv3(timeout=10, sleep_interval=1, cmd=None): ''' In some cases, we need to wait until local address is assigned. And only then can the l2tpv3 tunnel be configured. For example when ipv6 address in tentative state or we wait for some routing daemon for remote address. ''' start_time = time() test_command = cmd while True: if (start_time + timeout) < time(): return None result = run(test_command) if result == 0: return True sleep(sleep_interval) @Interface.register class L2TPv3If(Interface): """ The Linux bonding driver provides a method for aggregating multiple network interfaces into a single logical "bonded" interface. The behavior of the bonded interfaces depends upon the mode; generally speaking, modes provide either hot standby or load balancing services. Additionally, link integrity monitoring may be performed. """ iftype = 'l2tp' definition = { **Interface.definition, **{ 'section': 'l2tpeth', 'prefixes': ['l2tpeth', ], 'bridgeable': True, } } def _create(self): # create tunnel interface cmd = 'ip l2tp add tunnel tunnel_id {tunnel_id}' cmd += ' peer_tunnel_id {peer_tunnel_id}' cmd += ' udp_sport {source_port}' cmd += ' udp_dport {destination_port}' cmd += ' encap {encapsulation}' cmd += ' local {source_address}' cmd += ' remote {remote}' c = cmd.format(**self.config) # wait until the local/remote address is available, but no more 10 sec. wait_for_add_l2tpv3(cmd=c) # setup session cmd = 'ip l2tp add session name {ifname}' cmd += ' tunnel_id {tunnel_id}' cmd += ' session_id {session_id}' cmd += ' peer_session_id {peer_session_id}' self._cmd(cmd.format(**self.config)) # No need for interface shut down. There exist no function to permanently enable tunnel. # But you can disable interface permanently with shutdown/disable command. self.set_admin_state('up') def remove(self): """ Remove interface from operating system. Removing the interface deconfigures all assigned IP addresses. Example: >>> from vyos.ifconfig import L2TPv3If >>> i = L2TPv3If('l2tpeth0') >>> i.remove() """ if self.exists(self.ifname): # interface is always A/D down. It needs to be enabled explicitly self.set_admin_state('down') if {'tunnel_id', 'session_id'} <= set(self.config): cmd = 'ip l2tp del session tunnel_id {tunnel_id}' cmd += ' session_id {session_id}' self._cmd(cmd.format(**self.config)) if 'tunnel_id' in self.config: cmd = 'ip l2tp del tunnel tunnel_id {tunnel_id}' self._cmd(cmd.format(**self.config))