summaryrefslogtreecommitdiff
path: root/src/migration-scripts/l2tp
diff options
context:
space:
mode:
Diffstat (limited to 'src/migration-scripts/l2tp')
-rw-r--r--src/migration-scripts/l2tp/0-to-156
-rw-r--r--src/migration-scripts/l2tp/1-to-228
-rw-r--r--src/migration-scripts/l2tp/2-to-392
-rw-r--r--src/migration-scripts/l2tp/3-to-4148
-rw-r--r--src/migration-scripts/l2tp/4-to-568
-rw-r--r--src/migration-scripts/l2tp/5-to-688
-rw-r--r--src/migration-scripts/l2tp/6-to-739
-rw-r--r--src/migration-scripts/l2tp/7-to-847
-rw-r--r--src/migration-scripts/l2tp/8-to-928
9 files changed, 594 insertions, 0 deletions
diff --git a/src/migration-scripts/l2tp/0-to-1 b/src/migration-scripts/l2tp/0-to-1
new file mode 100644
index 0000000..f0cb6af
--- /dev/null
+++ b/src/migration-scripts/l2tp/0-to-1
@@ -0,0 +1,56 @@
+# Copyright 2018-2024 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/>.
+
+# T987: Unclutter L2TP/IPSec RADIUS configuration nodes
+# Unclutter L2TP VPN configuiration - move radius-server top level tag
+# nodes to a regular node which now also configures the radius source address
+# used when querying a radius server
+
+from vyos.configtree import ConfigTree
+
+cfg_base = ['vpn', 'l2tp', 'remote-access', 'authentication']
+
+def migrate(config: ConfigTree) -> None:
+ if not config.exists(cfg_base):
+ # Nothing to do
+ return
+
+ # Migrate "vpn l2tp authentication radius-source-address" to new
+ # "vpn l2tp authentication radius source-address"
+ if config.exists(cfg_base + ['radius-source-address']):
+ address = config.return_value(cfg_base + ['radius-source-address'])
+ # delete old configuration node
+ config.delete(cfg_base + ['radius-source-address'])
+ # write new configuration node
+ config.set(cfg_base + ['radius', 'source-address'], value=address)
+
+ # Migrate "vpn l2tp authentication radius-server" tag node to new
+ # "vpn l2tp authentication radius server" tag node
+ if config.exists(cfg_base + ['radius-server']):
+ for server in config.list_nodes(cfg_base + ['radius-server']):
+ base_server = cfg_base + ['radius-server', server]
+ key = config.return_value(base_server + ['key'])
+
+ # delete old configuration node
+ config.delete(base_server)
+ # write new configuration node
+ config.set(cfg_base + ['radius', 'server', server, 'key'], value=key)
+
+ # format as tag node
+ config.set_tag(cfg_base + ['radius', 'server'])
+
+ # delete top level tag node
+ if config.exists(cfg_base + ['radius-server']):
+ config.delete(cfg_base + ['radius-server'])
diff --git a/src/migration-scripts/l2tp/1-to-2 b/src/migration-scripts/l2tp/1-to-2
new file mode 100644
index 0000000..468d564
--- /dev/null
+++ b/src/migration-scripts/l2tp/1-to-2
@@ -0,0 +1,28 @@
+# Copyright 2019-2024 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/>.
+
+# T1858: Delete deprecated outside-nexthop
+
+from vyos.configtree import ConfigTree
+
+cfg_base = ['vpn', 'l2tp', 'remote-access']
+
+def migrate(config: ConfigTree) -> None:
+ if not config.exists(cfg_base):
+ # Nothing to do
+ return
+
+ if config.exists(cfg_base + ['outside-nexthop']):
+ config.delete(cfg_base + ['outside-nexthop'])
diff --git a/src/migration-scripts/l2tp/2-to-3 b/src/migration-scripts/l2tp/2-to-3
new file mode 100644
index 0000000..00fabb6
--- /dev/null
+++ b/src/migration-scripts/l2tp/2-to-3
@@ -0,0 +1,92 @@
+# Copyright 2020-2024 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/>.
+
+# T2264: combine IPv4/IPv6 name-server CLI syntax
+# T2264: combine WINS CLI syntax
+# T2264: remove RADIUS req-limit node
+# T2264: migrate IPv6 prefix node to common CLI style
+
+from vyos.configtree import ConfigTree
+
+base = ['vpn', 'l2tp', 'remote-access']
+
+def migrate(config: ConfigTree) -> None:
+ if not config.exists(base):
+ # Nothing to do
+ return
+
+ # Migrate IPv4 DNS servers
+ dns_base = base + ['dns-servers']
+ if config.exists(dns_base):
+ for server in ['server-1', 'server-2']:
+ if config.exists(dns_base + [server]):
+ dns = config.return_value(dns_base + [server])
+ config.set(base + ['name-server'], value=dns, replace=False)
+
+ config.delete(dns_base)
+
+ # Migrate IPv6 DNS servers
+ dns_base = base + ['dnsv6-servers']
+ if config.exists(dns_base):
+ for server in config.return_values(dns_base):
+ config.set(base + ['name-server'], value=server, replace=False)
+
+ config.delete(dns_base)
+
+ # Migrate IPv4 WINS servers
+ wins_base = base + ['wins-servers']
+ if config.exists(wins_base):
+ for server in ['server-1', 'server-2']:
+ if config.exists(wins_base + [server]):
+ wins = config.return_value(wins_base + [server])
+ config.set(base + ['wins-server'], value=wins, replace=False)
+
+ config.delete(wins_base)
+
+
+ # Remove RADIUS server req-limit node
+ radius_base = base + ['authentication', 'radius']
+ if config.exists(radius_base):
+ for server in config.list_nodes(radius_base + ['server']):
+ if config.exists(radius_base + ['server', server, 'req-limit']):
+ config.delete(radius_base + ['server', server, 'req-limit'])
+
+ # Migrate IPv6 prefixes
+ ipv6_base = base + ['client-ipv6-pool']
+ if config.exists(ipv6_base + ['prefix']):
+ prefix_old = config.return_values(ipv6_base + ['prefix'])
+ # delete old prefix CLI nodes
+ config.delete(ipv6_base + ['prefix'])
+ # create ned prefix tag node
+ config.set(ipv6_base + ['prefix'])
+ config.set_tag(ipv6_base + ['prefix'])
+
+ for p in prefix_old:
+ prefix = p.split(',')[0]
+ mask = p.split(',')[1]
+ config.set(ipv6_base + ['prefix', prefix, 'mask'], value=mask)
+
+ if config.exists(ipv6_base + ['delegate-prefix']):
+ prefix_old = config.return_values(ipv6_base + ['delegate-prefix'])
+ # delete old delegate prefix CLI nodes
+ config.delete(ipv6_base + ['delegate-prefix'])
+ # create ned delegation tag node
+ config.set(ipv6_base + ['delegate'])
+ config.set_tag(ipv6_base + ['delegate'])
+
+ for p in prefix_old:
+ prefix = p.split(',')[0]
+ mask = p.split(',')[1]
+ config.set(ipv6_base + ['delegate', prefix, 'delegate-prefix'], value=mask)
diff --git a/src/migration-scripts/l2tp/3-to-4 b/src/migration-scripts/l2tp/3-to-4
new file mode 100644
index 0000000..01c3fa8
--- /dev/null
+++ b/src/migration-scripts/l2tp/3-to-4
@@ -0,0 +1,148 @@
+# Copyright 2021-2024 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/>.
+
+# T2816: T3642: Move IPSec/L2TP code into vpn_ipsec.py and update to use PKI.
+
+import os
+
+from vyos.configtree import ConfigTree
+from vyos.pki import load_certificate
+from vyos.pki import load_private_key
+from vyos.pki import encode_certificate
+from vyos.pki import encode_private_key
+from vyos.utils.process import run
+
+base = ['vpn', 'l2tp', 'remote-access', 'ipsec-settings']
+pki_base = ['pki']
+
+AUTH_DIR = '/config/auth'
+
+def wrapped_pem_to_config_value(pem):
+ return "".join(pem.strip().split("\n")[1:-1])
+
+def migrate(config: ConfigTree) -> None:
+ if not config.exists(base):
+ return
+
+ if not config.exists(base + ['authentication', 'x509']):
+ return
+
+ x509_base = base + ['authentication', 'x509']
+ pki_name = 'l2tp_remote_access'
+
+ if not config.exists(pki_base + ['ca']):
+ config.set(pki_base + ['ca'])
+ config.set_tag(pki_base + ['ca'])
+
+ if not config.exists(pki_base + ['certificate']):
+ config.set(pki_base + ['certificate'])
+ config.set_tag(pki_base + ['certificate'])
+
+ if config.exists(x509_base + ['ca-cert-file']):
+ cert_file = config.return_value(x509_base + ['ca-cert-file'])
+ cert_path = os.path.join(AUTH_DIR, cert_file)
+ cert = None
+
+ if os.path.isfile(cert_path):
+ if not os.access(cert_path, os.R_OK):
+ run(f'sudo chmod 644 {cert_path}')
+
+ with open(cert_path, 'r') as f:
+ cert_data = f.read()
+ cert = load_certificate(cert_data, wrap_tags=False)
+
+ if cert:
+ cert_pem = encode_certificate(cert)
+ config.set(pki_base + ['ca', pki_name, 'certificate'], value=wrapped_pem_to_config_value(cert_pem))
+ config.set(x509_base + ['ca-certificate'], value=pki_name)
+ else:
+ print(f'Failed to migrate CA certificate on l2tp remote-access config')
+
+ config.delete(x509_base + ['ca-cert-file'])
+
+ if config.exists(x509_base + ['crl-file']):
+ crl_file = config.return_value(x509_base + ['crl-file'])
+ crl_path = os.path.join(AUTH_DIR, crl_file)
+ crl = None
+
+ if os.path.isfile(crl_path):
+ if not os.access(crl_path, os.R_OK):
+ run(f'sudo chmod 644 {crl_path}')
+
+ with open(crl_path, 'r') as f:
+ crl_data = f.read()
+ crl = load_certificate(crl_data, wrap_tags=False)
+
+ if crl:
+ crl_pem = encode_certificate(crl)
+ config.set(pki_base + ['ca', pki_name, 'crl'], value=wrapped_pem_to_config_value(crl_pem))
+ else:
+ print(f'Failed to migrate CRL on l2tp remote-access config')
+
+ config.delete(x509_base + ['crl-file'])
+
+ if config.exists(x509_base + ['server-cert-file']):
+ cert_file = config.return_value(x509_base + ['server-cert-file'])
+ cert_path = os.path.join(AUTH_DIR, cert_file)
+ cert = None
+
+ if os.path.isfile(cert_path):
+ if not os.access(cert_path, os.R_OK):
+ run(f'sudo chmod 644 {cert_path}')
+
+ with open(cert_path, 'r') as f:
+ cert_data = f.read()
+ cert = load_certificate(cert_data, wrap_tags=False)
+
+ if cert:
+ cert_pem = encode_certificate(cert)
+ config.set(pki_base + ['certificate', pki_name, 'certificate'], value=wrapped_pem_to_config_value(cert_pem))
+ config.set(x509_base + ['certificate'], value=pki_name)
+ else:
+ print(f'Failed to migrate certificate on l2tp remote-access config')
+
+ config.delete(x509_base + ['server-cert-file'])
+
+ if config.exists(x509_base + ['server-key-file']):
+ key_file = config.return_value(x509_base + ['server-key-file'])
+ key_passphrase = None
+
+ if config.exists(x509_base + ['server-key-password']):
+ key_passphrase = config.return_value(x509_base + ['server-key-password'])
+
+ key_path = os.path.join(AUTH_DIR, key_file)
+ key = None
+
+ if os.path.isfile(key_path):
+ if not os.access(key_path, os.R_OK):
+ run(f'sudo chmod 644 {key_path}')
+
+ with open(key_path, 'r') as f:
+ key_data = f.read()
+ key = load_private_key(key_data, passphrase=key_passphrase, wrap_tags=False)
+
+ if key:
+ key_pem = encode_private_key(key, passphrase=key_passphrase)
+ config.set(pki_base + ['certificate', pki_name, 'private', 'key'], value=wrapped_pem_to_config_value(key_pem))
+
+ if key_passphrase:
+ config.set(pki_base + ['certificate', pki_name, 'private', 'password-protected'])
+ config.set(x509_base + ['private-key-passphrase'], value=key_passphrase)
+ else:
+ print(f'Failed to migrate private key on l2tp remote-access config')
+
+ config.delete(x509_base + ['server-key-file'])
+ if config.exists(x509_base + ['server-key-password']):
+ config.delete(x509_base + ['server-key-password'])
diff --git a/src/migration-scripts/l2tp/4-to-5 b/src/migration-scripts/l2tp/4-to-5
new file mode 100644
index 0000000..56d451b
--- /dev/null
+++ b/src/migration-scripts/l2tp/4-to-5
@@ -0,0 +1,68 @@
+# Copyright 2023-2024 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/>.
+
+# - move all pool to named pools
+# 'start-stop' migrate to namedpool 'default-range-pool'
+# 'subnet' migrate to namedpool 'default-subnet-pool'
+# 'default-subnet-pool' is the next pool for 'default-range-pool'
+
+from vyos.configtree import ConfigTree
+from vyos.base import Warning
+
+base = ['vpn', 'l2tp', 'remote-access']
+pool_base = base + ['client-ip-pool']
+
+def migrate(config: ConfigTree) -> None:
+ if not config.exists(base):
+ return
+
+ if not config.exists(pool_base):
+ return
+
+ default_pool = ''
+ range_pool_name = 'default-range-pool'
+
+ if config.exists(pool_base + ['start']) and config.exists(pool_base + ['stop']):
+ def is_legalrange(ip1: str, ip2: str, mask: str):
+ from ipaddress import IPv4Interface
+ interface1 = IPv4Interface(f'{ip1}/{mask}')
+
+ interface2 = IPv4Interface(f'{ip2}/{mask}')
+ return interface1.network.network_address == interface2.network.network_address and interface2.ip > interface1.ip
+
+ start_ip = config.return_value(pool_base + ['start'])
+ stop_ip = config.return_value(pool_base + ['stop'])
+ if is_legalrange(start_ip, stop_ip,'24'):
+ ip_range = f'{start_ip}-{stop_ip}'
+ config.set(pool_base + [range_pool_name, 'range'], value=ip_range, replace=False)
+ default_pool = range_pool_name
+ else:
+ Warning(
+ f'L2TP client-ip-pool range start-ip:{start_ip} and stop-ip:{stop_ip} can not be migrated.')
+
+ config.delete(pool_base + ['start'])
+ config.delete(pool_base + ['stop'])
+
+ if config.exists(pool_base + ['subnet']):
+ for subnet in config.return_values(pool_base + ['subnet']):
+ config.set(pool_base + [range_pool_name, 'range'], value=subnet, replace=False)
+
+ config.delete(pool_base + ['subnet'])
+ default_pool = range_pool_name
+
+ if default_pool:
+ config.set(base + ['default-pool'], value=default_pool)
+ # format as tag node
+ config.set_tag(pool_base)
diff --git a/src/migration-scripts/l2tp/5-to-6 b/src/migration-scripts/l2tp/5-to-6
new file mode 100644
index 0000000..cc9f948
--- /dev/null
+++ b/src/migration-scripts/l2tp/5-to-6
@@ -0,0 +1,88 @@
+# Copyright 2023-2024 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 vyos.configtree import ConfigTree
+
+base = ['vpn', 'l2tp', 'remote-access']
+
+def migrate(config: ConfigTree) -> None:
+ if not config.exists(base):
+ return
+
+ #migrate idle to ppp option lcp-echo-timeout
+ idle_path = base + ['idle']
+ if config.exists(idle_path):
+ config.set(base + ['ppp-options', 'lcp-echo-timeout'],
+ value=config.return_value(idle_path))
+ config.delete(idle_path)
+
+ #migrate mppe from authentication to ppp-otion
+ mppe_path = base + ['authentication', 'mppe']
+ if config.exists(mppe_path):
+ config.set(base + ['ppp-options', 'mppe'],
+ value=config.return_value(mppe_path))
+ config.delete(mppe_path)
+
+ #migrate require to protocol
+ require_path = base + ['authentication', 'require']
+ if config.exists(require_path):
+ protocols = list(config.return_values(require_path))
+ for protocol in protocols:
+ config.set(base + ['authentication', 'protocols'], value=protocol,
+ replace=False)
+ config.delete(require_path)
+ else:
+ config.set(base + ['authentication', 'protocols'], value='mschap-v2')
+
+ #migrate default gateway if not exist
+ if not config.exists(base + ['gateway-address']):
+ config.set(base + ['gateway-address'], value='10.255.255.0')
+
+ #migrate authentication radius timeout
+ rad_timeout_path = base + ['authentication', 'radius', 'timeout']
+ if config.exists(rad_timeout_path):
+ if int(config.return_value(rad_timeout_path)) > 60:
+ config.set(rad_timeout_path, value=60)
+
+ #migrate authentication radius acct timeout
+ rad_acct_timeout_path = base + ['authentication', 'radius', 'acct-timeout']
+ if config.exists(rad_acct_timeout_path):
+ if int(config.return_value(rad_acct_timeout_path)) > 60:
+ config.set(rad_acct_timeout_path,value=60)
+
+ #migrate authentication radius max-try
+ rad_max_try_path = base + ['authentication', 'radius', 'max-try']
+ if config.exists(rad_max_try_path):
+ if int(config.return_value(rad_max_try_path)) > 20:
+ config.set(rad_max_try_path, value=20)
+
+ #migrate dae-server to dynamic-author
+ dae_path_old = base + ['authentication', 'radius', 'dae-server']
+ dae_path_new = base + ['authentication', 'radius', 'dynamic-author']
+
+ if config.exists(dae_path_old + ['ip-address']):
+ config.set(dae_path_new + ['server'],
+ value=config.return_value(dae_path_old + ['ip-address']))
+
+ if config.exists(dae_path_old + ['port']):
+ config.set(dae_path_new + ['port'],
+ value=config.return_value(dae_path_old + ['port']))
+
+ if config.exists(dae_path_old + ['secret']):
+ config.set(dae_path_new + ['key'],
+ value=config.return_value(dae_path_old + ['secret']))
+
+ if config.exists(dae_path_old):
+ config.delete(dae_path_old)
diff --git a/src/migration-scripts/l2tp/6-to-7 b/src/migration-scripts/l2tp/6-to-7
new file mode 100644
index 0000000..4dba597
--- /dev/null
+++ b/src/migration-scripts/l2tp/6-to-7
@@ -0,0 +1,39 @@
+# Copyright 2024 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/>.
+
+# Migrating to named ipv6 pools
+
+from vyos.configtree import ConfigTree
+
+base = ['vpn', 'l2tp', 'remote-access']
+pool_base = base + ['client-ipv6-pool']
+
+def migrate(config: ConfigTree) -> None:
+ if not config.exists(base):
+ return
+
+ if not config.exists(pool_base):
+ return
+
+ ipv6_pool_name = 'ipv6-pool'
+ config.copy(pool_base, pool_base + [ipv6_pool_name])
+
+ if config.exists(pool_base + ['prefix']):
+ config.delete(pool_base + ['prefix'])
+ config.set(base + ['default-ipv6-pool'], value=ipv6_pool_name)
+ if config.exists(pool_base + ['delegate']):
+ config.delete(pool_base + ['delegate'])
+ # format as tag node
+ config.set_tag(pool_base)
diff --git a/src/migration-scripts/l2tp/7-to-8 b/src/migration-scripts/l2tp/7-to-8
new file mode 100644
index 0000000..527906f
--- /dev/null
+++ b/src/migration-scripts/l2tp/7-to-8
@@ -0,0 +1,47 @@
+# Copyright 2024 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/>.
+
+# Migrate from 'ccp-disable' to 'ppp-options.disable-ccp'
+# Migration ipv6 options
+
+from vyos.configtree import ConfigTree
+
+base = ['vpn', 'l2tp', 'remote-access']
+
+def migrate(config: ConfigTree) -> None:
+ if not config.exists(base):
+ return
+
+ #CCP migration
+ if config.exists(base + ['ccp-disable']):
+ config.delete(base + ['ccp-disable'])
+ config.set(base + ['ppp-options', 'disable-ccp'])
+
+ #IPV6 options migrations
+ if config.exists(base + ['ppp-options','ipv6-peer-intf-id']):
+ intf_peer_id = config.return_value(base + ['ppp-options','ipv6-peer-intf-id'])
+ if intf_peer_id == 'ipv4':
+ intf_peer_id = 'ipv4-addr'
+ config.set(base + ['ppp-options','ipv6-peer-interface-id'], value=intf_peer_id, replace=True)
+ config.delete(base + ['ppp-options','ipv6-peer-intf-id'])
+
+ if config.exists(base + ['ppp-options','ipv6-intf-id']):
+ intf_id = config.return_value(base + ['ppp-options','ipv6-intf-id'])
+ config.set(base + ['ppp-options','ipv6-interface-id'], value=intf_id, replace=True)
+ config.delete(base + ['ppp-options','ipv6-intf-id'])
+
+ if config.exists(base + ['ppp-options','ipv6-accept-peer-intf-id']):
+ config.set(base + ['ppp-options','ipv6-accept-peer-interface-id'])
+ config.delete(base + ['ppp-options','ipv6-accept-peer-intf-id'])
diff --git a/src/migration-scripts/l2tp/8-to-9 b/src/migration-scripts/l2tp/8-to-9
new file mode 100644
index 0000000..e6b689e
--- /dev/null
+++ b/src/migration-scripts/l2tp/8-to-9
@@ -0,0 +1,28 @@
+# Copyright 2024 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/>.
+
+# Deleted 'dhcp-interface' from l2tp
+
+from vyos.configtree import ConfigTree
+
+base = ['vpn', 'l2tp', 'remote-access']
+
+def migrate(config: ConfigTree) -> None:
+ if not config.exists(base):
+ return
+
+ # deleting unused dhcp-interface
+ if config.exists(base + ['dhcp-interface']):
+ config.delete(base + ['dhcp-interface'])