summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Breunig <christian@breunig.cc>2023-12-28 13:15:50 +0100
committerGitHub <noreply@github.com>2023-12-28 13:15:50 +0100
commit8b646ed2c745a725aa22ad49e7e373c9f5fb2245 (patch)
treebd187f673f0c498e9288b972f361fb567dcf17ee
parente9310778ddb0118278396017026cb6fc1daff0c9 (diff)
parent09e0a2ca035ee39a68a510b28cc74560669d0420 (diff)
downloadvyos-1x-8b646ed2c745a725aa22ad49e7e373c9f5fb2245.tar.gz
vyos-1x-8b646ed2c745a725aa22ad49e7e373c9f5fb2245.zip
Merge pull request #2658 from aapostoliuk/T5801-circinus
T5801: Rewritten L2TP to get_config_dict
-rw-r--r--data/templates/accel-ppp/l2tp.config.j2145
-rw-r--r--data/templates/accel-ppp/sstp.config.j21
-rw-r--r--interface-definitions/include/accel-ppp/auth-protocols.xml.i2
-rw-r--r--interface-definitions/include/accel-ppp/mtu-128-16384.xml.i2
-rw-r--r--interface-definitions/include/version/l2tp-version.xml.i2
-rw-r--r--interface-definitions/vpn-l2tp.xml.in110
-rw-r--r--smoketest/scripts/cli/base_accel_ppp_test.py32
-rwxr-xr-xsmoketest/scripts/cli/test_service_pppoe-server.py6
-rwxr-xr-xsmoketest/scripts/cli/test_vpn_l2tp.py205
-rwxr-xr-xsrc/conf_mode/vpn_l2tp.py370
-rwxr-xr-xsrc/migration-scripts/l2tp/5-to-6110
11 files changed, 290 insertions, 695 deletions
diff --git a/data/templates/accel-ppp/l2tp.config.j2 b/data/templates/accel-ppp/l2tp.config.j2
index 89cc0eae7..49755254a 100644
--- a/data/templates/accel-ppp/l2tp.config.j2
+++ b/data/templates/accel-ppp/l2tp.config.j2
@@ -2,21 +2,17 @@
[modules]
log_syslog
l2tp
-chap-secrets
-{% for proto in auth_proto %}
-{{ proto }}
-{% endfor %}
-{% if auth_mode == 'radius' %}
-radius
-{% endif %}
-ippool
shaper
-ipv6pool
-ipv6_nd
-ipv6_dhcp
+{# Common authentication backend definitions #}
+{% include 'accel-ppp/config_modules_auth_mode.j2' %}
+ippool
+{# Common IPv6 definitions #}
+{% include 'accel-ppp/config_modules_ipv6.j2' %}
+{# Common authentication protocols (pap, chap ...) #}
+{% include 'accel-ppp/config_modules_auth_protocols.j2' %}
[core]
-thread-count={{ thread_cnt }}
+thread-count={{ thread_count }}
[common]
{% if max_concurrent_sessions is vyos_defined %}
@@ -28,23 +24,12 @@ syslog=accel-l2tp,daemon
copy=1
level=5
-{% if dnsv4 %}
-[dns]
-{% for dns in dnsv4 %}
-dns{{ loop.index }}={{ dns }}
-{% endfor %}
-{% endif %}
+{# Common DNS name-server definition #}
+{% include 'accel-ppp/config_name_server.j2' %}
-{% if dnsv6 %}
-[ipv6-dns]
-{% for dns in dnsv6 %}
-{{ dns }}
-{% endfor %}
-{% endif %}
-
-{% if wins %}
+{% if wins_server is vyos_defined %}
[wins]
-{% for server in wins %}
+{% for server in wins_server %}
wins{{ loop.index }}={{ server }}
{% endfor %}
{% endif %}
@@ -53,15 +38,15 @@ wins{{ loop.index }}={{ server }}
verbose=1
ifname=l2tp%d
ppp-max-mtu={{ mtu }}
-mppe={{ ppp_mppe }}
-{% if outside_addr %}
-bind={{ outside_addr }}
+mppe={{ ppp_options.mppe }}
+{% if outside_address is vyos_defined %}
+bind={{ outside_address }}
{% endif %}
-{% if lns_shared_secret %}
-secret={{ lns_shared_secret }}
+{% if lns.shared_secret is vyos_defined %}
+secret={{ lns.shared_secret }}
{% endif %}
-{% if lns_host_name %}
-host-name={{ lns_host_name }}
+{% if lns.host_name is vyos_defined %}
+host-name={{ lns.host_name }}
{% endif %}
{% if default_pool is vyos_defined %}
ip-pool={{ default_pool }}
@@ -73,87 +58,39 @@ ip-pool={{ default_pool }}
{# Common IP pool definitions #}
{% include 'accel-ppp/config_ip_pool.j2' %}
-{% if auth_mode == 'local' %}
-[chap-secrets]
-chap-secrets={{ chap_secrets_file }}
-{% elif auth_mode == 'radius' %}
-[radius]
-verbose=1
-{% for r in radius_server %}
-server={{ r.server }},{{ r.key }},auth-port={{ r.port }},acct-port={{ r.acct_port }},req-limit=0,fail-time={{ r.fail_time }}
-{% endfor %}
-{% if radius_dynamic_author.server is vyos_defined %}
-dae-server={{ radius_dynamic_author.server }}:{{ radius_dynamic_author.port }},{{ radius_dynamic_author.key }}
-{% endif %}
-{% if radius_acct_interim_interval is vyos_defined %}
-acct-interim-interval={{ radius_acct_interim_interval }}
-{% endif %}
-{% if radius_acct_inter_jitter %}
-acct-interim-jitter={{ radius_acct_inter_jitter }}
-{% endif %}
-acct-timeout={{ radius_acct_tmo }}
-timeout={{ radius_timeout }}
-max-try={{ radius_max_try }}
-{% if radius_nas_id %}
-nas-identifier={{ radius_nas_id }}
-{% endif %}
-{% if radius_nas_ip %}
-nas-ip-address={{ radius_nas_ip }}
-{% endif %}
-{% if radius_source_address %}
-bind={{ radius_source_address }}
-{% endif %}
-{% endif %}
-{% if gateway_address is vyos_defined %}
-gw-ip-address={{ gateway_address }}
-{% endif %}
+{# Common chap-secrets and RADIUS server/option definitions #}
+{% include 'accel-ppp/config_chap_secrets_radius.j2' %}
[ppp]
verbose=1
check-ip=1
single-session=replace
-lcp-echo-timeout={{ ppp_echo_timeout }}
-lcp-echo-interval={{ ppp_echo_interval }}
-lcp-echo-failure={{ ppp_echo_failure }}
-{% if ccp_disable %}
+lcp-echo-interval={{ ppp_options.lcp_echo_interval }}
+lcp-echo-timeout={{ ppp_options.lcp_echo_timeout }}
+lcp-echo-failure={{ ppp_options.lcp_echo_failure }}
+{# MTU #}
+mtu={{ mtu }}
+ipv6={{ 'allow' if ppp_options.ipv6 is vyos_defined("deny") and client_ipv6_pool is vyos_defined else ppp_options.ipv6 }}
+ipv4={{ ppp_options.ipv4 }}
+mppe={{ ppp_options.mppe }}
+{% if ccp_disable is vyos_defined %}
ccp=0
{% endif %}
-{% if ppp_ipv6 is vyos_defined %}
-ipv6={{ ppp_ipv6 }}
-{% else %}
-{{ 'ipv6=allow' if client_ipv6_pool_configured else '' }}
-{% endif %}
-{% if ppp_ipv6_intf_id is vyos_defined %}
-ipv6-intf-id={{ ppp_ipv6_intf_id }}
-{% endif %}
-{% if ppp_ipv6_peer_intf_id is vyos_defined %}
-ipv6-peer-intf-id={{ ppp_ipv6_peer_intf_id }}
-{% endif %}
-ipv6-accept-peer-intf-id={{ "1" if ppp_ipv6_accept_peer_intf_id else "0" }}
+unit-preallocate={{ "1" if authentication.radius.preallocate_vif is vyos_defined else "0" }}
-{% if client_ipv6_pool %}
-[ipv6-pool]
-{% for p in client_ipv6_pool %}
-{{ p.prefix }},{{ p.mask }}
-{% endfor %}
-{% for p in client_ipv6_delegate_prefix %}
-delegate={{ p.prefix }},{{ p.mask }}
-{% endfor %}
+{% if ppp_options.ipv6_intf_id is vyos_defined %}
+ipv6-intf-id={{ ppp_options.ipv6_intf_id }}
{% endif %}
-
-{% if client_ipv6_delegate_prefix %}
-[ipv6-dhcp]
-verbose=1
+{% if ppp_options.ipv6_peer_intf_id is vyos_defined %}
+ipv6-peer-intf-id={{ ppp_options.ipv6_peer_intf_id }}
{% endif %}
+ipv6-accept-peer-intf-id={{ "1" if ppp_options.ipv6_accept_peer_intf_id is vyos_defined else "0" }}
-{% if radius_shaper_attr %}
-[shaper]
-verbose=1
-attr={{ radius_shaper_attr }}
-{% if radius_shaper_vendor %}
-vendor={{ radius_shaper_vendor }}
-{% endif %}
-{% endif %}
+{# Common IPv6 pool definitions #}
+{% include 'accel-ppp/config_ipv6_pool.j2' %}
+
+{# Common RADIUS shaper configuration #}
+{% include 'accel-ppp/config_shaper_radius.j2' %}
[cli]
tcp=127.0.0.1:2004
diff --git a/data/templates/accel-ppp/sstp.config.j2 b/data/templates/accel-ppp/sstp.config.j2
index 6117cea1b..014ae1235 100644
--- a/data/templates/accel-ppp/sstp.config.j2
+++ b/data/templates/accel-ppp/sstp.config.j2
@@ -57,6 +57,7 @@ verbose=1
check-ip=1
{# MTU #}
mtu={{ mtu }}
+unit-preallocate={{ "1" if authentication.radius.preallocate_vif is vyos_defined else "0" }}
ipv6={{ 'allow' if ppp_options.ipv6 is vyos_defined("deny") and client_ipv6_pool is vyos_defined else ppp_options.ipv6 }}
ipv4={{ ppp_options.ipv4 }}
mppe={{ ppp_options.mppe }}
diff --git a/interface-definitions/include/accel-ppp/auth-protocols.xml.i b/interface-definitions/include/accel-ppp/auth-protocols.xml.i
index d43266152..4ab4753bb 100644
--- a/interface-definitions/include/accel-ppp/auth-protocols.xml.i
+++ b/interface-definitions/include/accel-ppp/auth-protocols.xml.i
@@ -1,7 +1,7 @@
<!-- include start from accel-ppp/auth-protocols.xml.i -->
<leafNode name="protocols">
<properties>
- <help>Authentication protocol for remote access peer SSTP VPN</help>
+ <help>Authentication protocol for remote access peer</help>
<completionHelp>
<list>pap chap mschap mschap-v2</list>
</completionHelp>
diff --git a/interface-definitions/include/accel-ppp/mtu-128-16384.xml.i b/interface-definitions/include/accel-ppp/mtu-128-16384.xml.i
index b4008a63b..5661bdc05 100644
--- a/interface-definitions/include/accel-ppp/mtu-128-16384.xml.i
+++ b/interface-definitions/include/accel-ppp/mtu-128-16384.xml.i
@@ -1,7 +1,7 @@
<!-- include start from accel-ppp/mtu-128-16384.xml.i -->
<leafNode name="mtu">
<properties>
- <help>Maximum Transmission Unit (MTU) - default 1492</help>
+ <help>Maximum Transmission Unit (MTU)</help>
<constraint>
<validator name="numeric" argument="--range 128-16384"/>
</constraint>
diff --git a/interface-definitions/include/version/l2tp-version.xml.i b/interface-definitions/include/version/l2tp-version.xml.i
index 89edb160c..f4507d93b 100644
--- a/interface-definitions/include/version/l2tp-version.xml.i
+++ b/interface-definitions/include/version/l2tp-version.xml.i
@@ -1,3 +1,3 @@
<!-- include start from include/version/l2tp-version.xml.i -->
-<syntaxVersion component='l2tp' version='5'></syntaxVersion>
+<syntaxVersion component='l2tp' version='6'></syntaxVersion>
<!-- include end -->
diff --git a/interface-definitions/vpn-l2tp.xml.in b/interface-definitions/vpn-l2tp.xml.in
index 7980cfdf5..3e2d00e6b 100644
--- a/interface-definitions/vpn-l2tp.xml.in
+++ b/interface-definitions/vpn-l2tp.xml.in
@@ -15,6 +15,9 @@
<children>
#include <include/accel-ppp/max-concurrent-sessions.xml.i>
#include <include/accel-ppp/mtu-128-16384.xml.i>
+ <leafNode name="mtu">
+ <defaultValue>1436</defaultValue>
+ </leafNode>
<leafNode name="outside-address">
<properties>
<help>External IP address to which VPN clients will connect</help>
@@ -120,116 +123,18 @@
#include <include/accel-ppp/client-ipv6-pool.xml.i>
#include <include/generic-description.xml.i>
#include <include/dhcp-interface.xml.i>
- <leafNode name="idle">
- <properties>
- <help>PPP idle timeout</help>
- <valueHelp>
- <format>u32:30-86400</format>
- <description>PPP idle timeout in seconds</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 30-86400"/>
- </constraint>
- </properties>
- </leafNode>
<node name="authentication">
<properties>
<help>Authentication for remote access L2TP VPN</help>
</properties>
<children>
- <leafNode name="require">
- <properties>
- <help>Authentication protocol for remote access peer L2TP VPN</help>
- <valueHelp>
- <format>pap</format>
- <description>Require the peer to authenticate itself using PAP [Password Authentication Protocol].</description>
- </valueHelp>
- <valueHelp>
- <format>chap</format>
- <description>Require the peer to authenticate itself using CHAP [Challenge Handshake Authentication Protocol].</description>
- </valueHelp>
- <valueHelp>
- <format>mschap</format>
- <description>Require the peer to authenticate itself using CHAP [Challenge Handshake Authentication Protocol].</description>
- </valueHelp>
- <valueHelp>
- <format>mschap-v2</format>
- <description>Require the peer to authenticate itself using MS-CHAPv2 [Microsoft Challenge Handshake Authentication Protocol, Version 2].</description>
- </valueHelp>
- <constraint>
- <regex>(pap|chap|mschap|mschap-v2)</regex>
- </constraint>
- <completionHelp>
- <list>pap chap mschap mschap-v2</list>
- </completionHelp>
- <multi />
- </properties>
- </leafNode>
- #include <include/accel-ppp/ppp-mppe.xml.i>
+ #include <include/accel-ppp/auth-protocols.xml.i>
#include <include/accel-ppp/auth-mode.xml.i>
#include <include/accel-ppp/auth-local-users.xml.i>
#include <include/radius-auth-server-ipv4.xml.i>
+ #include <include/accel-ppp/radius-additions.xml.i>
<node name="radius">
<children>
- #include <include/accel-ppp/radius-accounting-interim-interval.xml.i>
- <tagNode name="server">
- <children>
- #include <include/accel-ppp/radius-additions-disable-accounting.xml.i>
- <leafNode name="fail-time">
- <properties>
- <help>Mark server unavailable for N seconds on failure</help>
- <valueHelp>
- <format>u32:0-600</format>
- <description>Fail time penalty</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 0-600"/>
- </constraint>
- <constraintErrorMessage>Fail time must be between 0 and 600 seconds</constraintErrorMessage>
- </properties>
- </leafNode>
- </children>
- </tagNode>
- <leafNode name="timeout">
- <properties>
- <help>Timeout to wait response from server (seconds)</help>
- </properties>
- </leafNode>
- <leafNode name="acct-timeout">
- <properties>
- <help>Timeout to wait reply for Interim-Update packets</help>
- </properties>
- </leafNode>
- <leafNode name="max-try">
- <properties>
- <help>Maximum number of tries to send Access-Request/Accounting-Request queries</help>
- </properties>
- </leafNode>
- #include <include/radius-nas-identifier.xml.i>
- #include <include/radius-nas-ip-address.xml.i>
- <node name="dae-server">
- <properties>
- <help>IPv4 address and port to bind Dynamic Authorization Extension server (DM/CoA)</help>
- </properties>
- <children>
- <leafNode name="ip-address">
- <properties>
- <help>IP address for Dynamic Authorization Extension server (DM/CoA)</help>
- </properties>
- </leafNode>
- <leafNode name="port">
- <properties>
- <help>Port for Dynamic Authorization Extension server (DM/CoA)</help>
- </properties>
- <defaultValue>1700</defaultValue>
- </leafNode>
- <leafNode name="secret">
- <properties>
- <help>Secret for Dynamic Authorization Extension server (DM/CoA)</help>
- </properties>
- </leafNode>
- </children>
- </node>
#include <include/accel-ppp/radius-additions-rate-limit.xml.i>
</children>
</node>
@@ -240,9 +145,12 @@
<help>Advanced protocol options</help>
</properties>
<children>
- #include <include/accel-ppp/lcp-echo-interval-failure.xml.i>
+ #include <include/accel-ppp/ppp-mppe.xml.i>
+ #include <include/accel-ppp/ppp-options-ipv4.xml.i>
#include <include/accel-ppp/ppp-options-ipv6.xml.i>
#include <include/accel-ppp/ppp-options-ipv6-interface-id.xml.i>
+ #include <include/accel-ppp/lcp-echo-interval-failure.xml.i>
+ #include <include/accel-ppp/lcp-echo-timeout.xml.i>
</children>
</node>
#include <include/accel-ppp/default-pool.xml.i>
diff --git a/smoketest/scripts/cli/base_accel_ppp_test.py b/smoketest/scripts/cli/base_accel_ppp_test.py
index fad765c0d..682a0349a 100644
--- a/smoketest/scripts/cli/base_accel_ppp_test.py
+++ b/smoketest/scripts/cli/base_accel_ppp_test.py
@@ -166,7 +166,6 @@ class BasicAccelPPPTest:
static_ip = "100.100.100.101"
upload = "5000"
download = "10000"
-
self.set(
[
"authentication",
@@ -254,6 +253,9 @@ class BasicAccelPPPTest:
radius_key = "secretVyOS"
radius_port = "2000"
radius_port_acc = "3000"
+ acct_interim_jitter = '10'
+ acct_interim_interval = '10'
+ acct_timeout = '30'
self.set(["authentication", "mode", "radius"])
self.set(
@@ -279,6 +281,30 @@ class BasicAccelPPPTest:
radius_port_acc,
]
)
+ self.set(
+ [
+ "authentication",
+ "radius",
+ "acct-interim-jitter",
+ acct_interim_jitter,
+ ]
+ )
+ self.set(
+ [
+ "authentication",
+ "radius",
+ "accounting-interim-interval",
+ acct_interim_interval,
+ ]
+ )
+ self.set(
+ [
+ "authentication",
+ "radius",
+ "acct-timeout",
+ acct_timeout,
+ ]
+ )
coa_server = "4.4.4.4"
coa_key = "testCoA"
@@ -307,7 +333,9 @@ class BasicAccelPPPTest:
# check auth
self.assertTrue(conf["radius"].getboolean("verbose"))
- self.assertEqual(conf["radius"]["acct-timeout"], "3")
+ self.assertEqual(conf["radius"]["acct-timeout"], acct_timeout)
+ self.assertEqual(conf["radius"]["acct-interim-interval"], acct_interim_interval)
+ self.assertEqual(conf["radius"]["acct-interim-jitter"], acct_interim_jitter)
self.assertEqual(conf["radius"]["timeout"], "3")
self.assertEqual(conf["radius"]["max-try"], "3")
diff --git a/smoketest/scripts/cli/test_service_pppoe-server.py b/smoketest/scripts/cli/test_service_pppoe-server.py
index 3001e71bf..fa3bb87db 100755
--- a/smoketest/scripts/cli/test_service_pppoe-server.py
+++ b/smoketest/scripts/cli/test_service_pppoe-server.py
@@ -195,12 +195,8 @@ class TestServicePPPoEServer(BasicAccelPPPTest.TestCase):
def test_accel_radius_authentication(self):
radius_called_sid = 'ifname:mac'
- radius_acct_interim_jitter = '9'
- radius_acct_interim_interval = '60'
self.set(['authentication', 'radius', 'called-sid-format', radius_called_sid])
- self.set(['authentication', 'radius', 'acct-interim-jitter', radius_acct_interim_jitter])
- self.set(['authentication', 'radius', 'accounting-interim-interval', radius_acct_interim_interval])
# run common tests
super().test_accel_radius_authentication()
@@ -211,8 +207,6 @@ class TestServicePPPoEServer(BasicAccelPPPTest.TestCase):
# Validate configuration
self.assertEqual(conf['pppoe']['called-sid'], radius_called_sid)
- self.assertEqual(conf['radius']['acct-interim-jitter'], radius_acct_interim_jitter)
- self.assertEqual(conf['radius']['acct-interim-interval'], radius_acct_interim_interval)
def test_pppoe_server_vlan(self):
diff --git a/smoketest/scripts/cli/test_vpn_l2tp.py b/smoketest/scripts/cli/test_vpn_l2tp.py
index 05ffb6bb5..5b3e419bd 100755
--- a/smoketest/scripts/cli/test_vpn_l2tp.py
+++ b/smoketest/scripts/cli/test_vpn_l2tp.py
@@ -38,175 +38,98 @@ class TestVPNL2TPServer(BasicAccelPPPTest.TestCase):
def basic_protocol_specific_config(self):
pass
- def test_accel_local_authentication(self):
- # Test configuration of local authentication
+ def test_l2tp_server_ppp_options(self):
+ # Test configuration of local authentication for PPPoE server
self.basic_config()
-
- # upload / download limit
- user = "test"
- password = "test2"
- static_ip = "100.100.100.101"
- upload = "5000"
- download = "10000"
-
- self.set(
- [
- "authentication",
- "local-users",
- "username",
- user,
- "password",
- password,
- ]
- )
- self.set(
- [
- "authentication",
- "local-users",
- "username",
- user,
- "static-ip",
- static_ip,
- ]
- )
- self.set(
- [
- "authentication",
- "local-users",
- "username",
- user,
- "rate-limit",
- "upload",
- upload,
- ]
- )
- self.set(
- [
- "authentication",
- "local-users",
- "username",
- user,
- "rate-limit",
- "download",
- download,
- ]
- )
+ mtu = '1425'
+ lcp_echo_failure = '5'
+ lcp_echo_interval = '40'
+ lcp_echo_timeout = '3000'
+ # other settings
+ mppe = 'require'
+ self.set(['ccp-disable'])
+ self.set(['ppp-options', 'mppe', mppe])
+ self.set(['authentication', 'radius', 'preallocate-vif'])
+ self.set(['mtu', mtu])
+ self.set(['ppp-options', 'lcp-echo-failure', lcp_echo_failure])
+ self.set(['ppp-options', 'lcp-echo-interval', lcp_echo_interval])
+ self.set(['ppp-options', 'lcp-echo-timeout', lcp_echo_timeout])
# commit changes
self.cli_commit()
# Validate configuration values
- conf = ConfigParser(allow_no_value=True, delimiters="=", strict=False)
+ conf = ConfigParser(allow_no_value=True, delimiters='=')
conf.read(self._config_file)
- # check proper path to chap-secrets file
- self.assertEqual(conf["chap-secrets"]["chap-secrets"], self._chap_secrets)
-
# basic verification
self.verify(conf)
- # check local users
- tmp = cmd(f"sudo cat {self._chap_secrets}")
- regex = f"{user}\s+\*\s+{password}\s+{static_ip}\s+{download}/{upload}"
- tmp = re.findall(regex, tmp)
- self.assertTrue(tmp)
-
- # Check local-users default value(s)
- self.delete(["authentication", "local-users", "username", user, "static-ip"])
- # commit changes
- self.cli_commit()
-
- # check local users
- tmp = cmd(f"sudo cat {self._chap_secrets}")
- regex = f"{user}\s+\*\s+{password}\s+\*\s+{download}/{upload}"
- tmp = re.findall(regex, tmp)
- self.assertTrue(tmp)
-
- def test_accel_radius_authentication(self):
- # Test configuration of RADIUS authentication for PPPoE server
+ # check ppp
+ self.assertEqual(conf['ppp']['mppe'], mppe)
+ self.assertFalse(conf['ppp'].getboolean('ccp'))
+ self.assertEqual(conf['ppp']['unit-preallocate'], '1')
+ self.assertTrue(conf['ppp'].getboolean('verbose'))
+ self.assertTrue(conf['ppp'].getboolean('check-ip'))
+ self.assertEqual(conf['ppp']['mtu'], mtu)
+ self.assertEqual(conf['ppp']['lcp-echo-interval'], lcp_echo_interval)
+ self.assertEqual(conf['ppp']['lcp-echo-timeout'], lcp_echo_timeout)
+ self.assertEqual(conf['ppp']['lcp-echo-failure'], lcp_echo_failure)
+
+ def test_l2tp_server_authentication_protocols(self):
+ # Test configuration of local authentication for PPPoE server
self.basic_config()
- radius_server = "192.0.2.22"
- radius_key = "secretVyOS"
- radius_port = "2000"
-
- self.set(["authentication", "mode", "radius"])
- self.set(
- ["authentication", "radius", "server", radius_server, "key", radius_key]
- )
- self.set(
- [
- "authentication",
- "radius",
- "server",
- radius_server,
- "port",
- radius_port,
- ]
- )
-
-
- nas_id = "VyOS-PPPoE"
- nas_ip = "7.7.7.7"
- self.set(["authentication", "radius", "nas-identifier", nas_id])
- self.set(["authentication", "radius", "nas-ip-address", nas_ip])
-
- source_address = "1.2.3.4"
- self.set(["authentication", "radius", "source-address", source_address])
+ # explicitly test mschap-v2 - no special reason
+ self.set( ['authentication', 'protocols', 'mschap-v2'])
# commit changes
self.cli_commit()
# Validate configuration values
- conf = ConfigParser(allow_no_value=True, delimiters="=", strict=False)
+ conf = ConfigParser(allow_no_value=True)
conf.read(self._config_file)
- # basic verification
- self.verify(conf)
+ self.assertEqual(conf['modules']['auth_mschap_v2'], None)
+
+ def test_l2tp_server_client_ipv6_pool(self):
+ # Test configuration of IPv6 client pools
+ self.basic_config()
+
+ # Enable IPv6
+ allow_ipv6 = 'allow'
+ random = 'random'
+ self.set(['ppp-options', 'ipv6', allow_ipv6])
+ self.set(['ppp-options', 'ipv6-intf-id', random])
+ self.set(['ppp-options', 'ipv6-accept-peer-intf-id'])
+ self.set(['ppp-options', 'ipv6-peer-intf-id', random])
- # check auth
- self.assertTrue(conf["radius"].getboolean("verbose"))
- self.assertEqual(conf["radius"]["acct-timeout"], "3")
- self.assertEqual(conf["radius"]["timeout"], "3")
- self.assertEqual(conf["radius"]["max-try"], "3")
-
- self.assertEqual(conf["radius"]["nas-identifier"], nas_id)
- self.assertEqual(conf["radius"]["nas-ip-address"], nas_ip)
- self.assertEqual(conf["radius"]["bind"], source_address)
-
- server = conf["radius"]["server"].split(",")
- self.assertEqual(radius_server, server[0])
- self.assertEqual(radius_key, server[1])
- self.assertEqual(f"auth-port={radius_port}", server[2])
- self.assertEqual(f"req-limit=0", server[4])
- self.assertEqual(f"fail-time=0", server[5])
-
- #
- # Disable Radius Accounting
- #
- self.set(
- [
- "authentication",
- "radius",
- "server",
- radius_server,
- "disable-accounting",
- ]
- )
+ prefix = '2001:db8:ffff::/64'
+ prefix_mask = '128'
+ client_prefix = f'{prefix},{prefix_mask}'
+ self.set(['client-ipv6-pool', 'prefix', prefix, 'mask', prefix_mask])
+
+ delegate_prefix = '2001:db8::/40'
+ delegate_mask = '56'
+ self.set(['client-ipv6-pool', 'delegate', delegate_prefix, 'delegation-prefix', delegate_mask])
# commit changes
self.cli_commit()
+ # Validate configuration values
+ conf = ConfigParser(allow_no_value=True, delimiters='=')
conf.read(self._config_file)
- server = conf["radius"]["server"].split(",")
- self.assertEqual(radius_server, server[0])
- self.assertEqual(radius_key, server[1])
- self.assertEqual(f"auth-port={radius_port}", server[2])
- self.assertEqual(f"acct-port=0", server[3])
- self.assertEqual(f"req-limit=0", server[4])
- self.assertEqual(f"fail-time=0", server[5])
+ for tmp in ['ipv6pool', 'ipv6_nd', 'ipv6_dhcp']:
+ self.assertEqual(conf['modules'][tmp], None)
+
+ self.assertEqual(conf['ppp']['ipv6'], allow_ipv6)
+ self.assertEqual(conf['ppp']['ipv6-intf-id'], random)
+ self.assertEqual(conf['ppp']['ipv6-peer-intf-id'], random)
+ self.assertTrue(conf['ppp'].getboolean('ipv6-accept-peer-intf-id'))
+ self.assertEqual(conf['ipv6-pool'][client_prefix], None)
+ self.assertEqual(conf['ipv6-pool']['delegate'], f'{delegate_prefix},{delegate_mask}')
if __name__ == '__main__':
unittest.main(verbosity=2)
diff --git a/src/conf_mode/vpn_l2tp.py b/src/conf_mode/vpn_l2tp.py
index 9a022d93c..03a27d3cd 100755
--- a/src/conf_mode/vpn_l2tp.py
+++ b/src/conf_mode/vpn_l2tp.py
@@ -15,377 +15,73 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import os
-import re
-from copy import deepcopy
-from stat import S_IRUSR, S_IWUSR, S_IRGRP
from sys import exit
from vyos.config import Config
-from vyos.template import is_ipv4
+from vyos.configdict import get_accel_dict
from vyos.template import render
from vyos.utils.process import call
-from vyos.utils.system import get_half_cpus
from vyos.utils.dict import dict_search
-from vyos.utils.network import check_port_availability
-from vyos.utils.network import is_listen_port_bind_service
+from vyos.accel_ppp_util import verify_accel_ppp_base_service
from vyos.accel_ppp_util import verify_accel_ppp_ip_pool
from vyos.accel_ppp_util import get_pools_in_order
+from vyos.base import Warning
from vyos import ConfigError
from vyos import airbag
airbag.enable()
+
l2tp_conf = '/run/accel-pppd/l2tp.conf'
l2tp_chap_secrets = '/run/accel-pppd/l2tp.chap-secrets'
-default_config_data = {
- 'auth_mode': 'local',
- 'auth_ppp_mppe': 'prefer',
- 'auth_proto': ['auth_mschap_v2'],
- 'chap_secrets_file': l2tp_chap_secrets, # used in Jinja2 template
- 'client_ip_pool': {},
- 'client_ip_subnets': [],
- 'client_ipv6_pool': [],
- 'client_ipv6_pool_configured': False,
- 'client_ipv6_delegate_prefix': [],
- 'dnsv4': [],
- 'dnsv6': [],
- 'gateway_address': '10.255.255.0',
- 'local_users' : [],
- 'mtu': '1436',
- 'outside_addr': '',
- 'ppp_mppe': 'prefer',
- 'ppp_echo_failure' : '3',
- 'ppp_echo_interval' : '30',
- 'ppp_echo_timeout': '0',
- 'ppp_ipv6_accept_peer_intf_id': False,
- 'ppp_ipv6_intf_id': None,
- 'ppp_ipv6_peer_intf_id': None,
- 'radius_server': [],
- 'radius_acct_inter_jitter': '',
- 'radius_acct_interim_interval': None,
- 'radius_acct_tmo': '3',
- 'radius_max_try': '3',
- 'radius_timeout': '3',
- 'radius_nas_id': '',
- 'radius_nas_ip': '',
- 'radius_source_address': '',
- 'radius_shaper_attr': '',
- 'radius_shaper_vendor': '',
- 'radius_dynamic_author': {},
- 'wins': [],
- 'ip6_column': [],
- 'thread_cnt': get_half_cpus()
-}
-
def get_config(config=None):
if config:
conf = config
else:
conf = Config()
- base_path = ['vpn', 'l2tp', 'remote-access']
- if not conf.exists(base_path):
+ base = ['vpn', 'l2tp', 'remote-access']
+ if not conf.exists(base):
return None
- conf.set_level(base_path)
- l2tp = deepcopy(default_config_data)
-
- ### general options ###
- if conf.exists(['name-server']):
- for name_server in conf.return_values(['name-server']):
- if is_ipv4(name_server):
- l2tp['dnsv4'].append(name_server)
- else:
- l2tp['dnsv6'].append(name_server)
-
- if conf.exists(['wins-server']):
- l2tp['wins'] = conf.return_values(['wins-server'])
-
- if conf.exists('outside-address'):
- l2tp['outside_addr'] = conf.return_value('outside-address')
-
- if conf.exists(['authentication', 'mode']):
- l2tp['auth_mode'] = conf.return_value(['authentication', 'mode'])
-
- if conf.exists(['authentication', 'require']):
- l2tp['auth_proto'] = []
- auth_mods = {
- 'pap': 'auth_pap',
- 'chap': 'auth_chap_md5',
- 'mschap': 'auth_mschap_v1',
- 'mschap-v2': 'auth_mschap_v2'
- }
-
- for proto in conf.return_values(['authentication', 'require']):
- l2tp['auth_proto'].append(auth_mods[proto])
-
- if conf.exists(['authentication', 'mppe']):
- l2tp['auth_ppp_mppe'] = conf.return_value(['authentication', 'mppe'])
-
- #
- # local auth
- if conf.exists(['authentication', 'local-users']):
- for username in conf.list_nodes(['authentication', 'local-users', 'username']):
- user = {
- 'name' : username,
- 'password' : '',
- 'state' : 'enabled',
- 'ip' : '*',
- 'upload' : None,
- 'download' : None
- }
-
- conf.set_level(base_path + ['authentication', 'local-users', 'username', username])
-
- if conf.exists(['password']):
- user['password'] = conf.return_value(['password'])
-
- if conf.exists(['disable']):
- user['state'] = 'disable'
-
- if conf.exists(['static-ip']):
- user['ip'] = conf.return_value(['static-ip'])
-
- if conf.exists(['rate-limit', 'download']):
- user['download'] = conf.return_value(['rate-limit', 'download'])
-
- if conf.exists(['rate-limit', 'upload']):
- user['upload'] = conf.return_value(['rate-limit', 'upload'])
-
- l2tp['local_users'].append(user)
-
- #
- # RADIUS auth and settings
- conf.set_level(base_path + ['authentication', 'radius'])
- if conf.exists(['server']):
- for server in conf.list_nodes(['server']):
- radius = {
- 'server' : server,
- 'key' : '',
- 'fail_time' : 0,
- 'port' : '1812',
- 'acct_port' : '1813'
- }
-
- conf.set_level(base_path + ['authentication', 'radius', 'server', server])
-
- if conf.exists(['disable-accounting']):
- radius['acct_port'] = '0'
-
- if conf.exists(['fail-time']):
- radius['fail_time'] = conf.return_value(['fail-time'])
-
- if conf.exists(['port']):
- radius['port'] = conf.return_value(['port'])
-
- if conf.exists(['acct-port']):
- radius['acct_port'] = conf.return_value(['acct-port'])
-
- if conf.exists(['key']):
- radius['key'] = conf.return_value(['key'])
-
- if not conf.exists(['disable']):
- l2tp['radius_server'].append(radius)
-
- #
- # advanced radius-setting
- conf.set_level(base_path + ['authentication', 'radius'])
-
- if conf.exists(['accounting-interim-interval']):
- l2tp['radius_acct_interim_interval'] = conf.return_value(['accounting-interim-interval'])
-
- if conf.exists(['acct-interim-jitter']):
- l2tp['radius_acct_inter_jitter'] = conf.return_value(['acct-interim-jitter'])
-
- if conf.exists(['acct-timeout']):
- l2tp['radius_acct_tmo'] = conf.return_value(['acct-timeout'])
-
- if conf.exists(['max-try']):
- l2tp['radius_max_try'] = conf.return_value(['max-try'])
-
- if conf.exists(['timeout']):
- l2tp['radius_timeout'] = conf.return_value(['timeout'])
-
- if conf.exists(['nas-identifier']):
- l2tp['radius_nas_id'] = conf.return_value(['nas-identifier'])
-
- if conf.exists(['nas-ip-address']):
- l2tp['radius_nas_ip'] = conf.return_value(['nas-ip-address'])
-
- if conf.exists(['source-address']):
- l2tp['radius_source_address'] = conf.return_value(['source-address'])
-
- # Dynamic Authorization Extensions (DOA)/Change Of Authentication (COA)
- if conf.exists(['dae-server']):
- dae = {
- 'port' : '',
- 'server' : '',
- 'key' : ''
- }
-
- if conf.exists(['dae-server', 'ip-address']):
- dae['server'] = conf.return_value(['dae-server', 'ip-address'])
-
- if conf.exists(['dae-server', 'port']):
- dae['port'] = conf.return_value(['dae-server', 'port'])
-
- if conf.exists(['dae-server', 'secret']):
- dae['key'] = conf.return_value(['dae-server', 'secret'])
-
- l2tp['radius_dynamic_author'] = dae
-
- if conf.exists(['rate-limit', 'enable']):
- l2tp['radius_shaper_attr'] = 'Filter-Id'
- c_attr = ['rate-limit', 'enable', 'attribute']
- if conf.exists(c_attr):
- l2tp['radius_shaper_attr'] = conf.return_value(c_attr)
-
- c_vendor = ['rate-limit', 'enable', 'vendor']
- if conf.exists(c_vendor):
- l2tp['radius_shaper_vendor'] = conf.return_value(c_vendor)
-
- conf.set_level(base_path)
- if conf.exists(['client-ip-pool']):
- for pool_name in conf.list_nodes(['client-ip-pool']):
- l2tp['client_ip_pool'][pool_name] = {}
- l2tp['client_ip_pool'][pool_name]['range'] = conf.return_value(['client-ip-pool', pool_name, 'range'])
- l2tp['client_ip_pool'][pool_name]['next_pool'] = conf.return_value(['client-ip-pool', pool_name, 'next-pool'])
-
+ # retrieve common dictionary keys
+ l2tp = get_accel_dict(conf, base, l2tp_chap_secrets)
if dict_search('client_ip_pool', l2tp):
# Multiple named pools require ordered values T5099
- l2tp['ordered_named_pools'] = get_pools_in_order(dict_search('client_ip_pool', l2tp))
-
- if conf.exists(['client-ipv6-pool', 'prefix']):
- l2tp['client_ipv6_pool_configured'] = True
- l2tp['ip6_column'].append('ip6')
- for prefix in conf.list_nodes(['client-ipv6-pool', 'prefix']):
- tmp = {
- 'prefix': prefix,
- 'mask': '64'
- }
-
- if conf.exists(['client-ipv6-pool', 'prefix', prefix, 'mask']):
- tmp['mask'] = conf.return_value(['client-ipv6-pool', 'prefix', prefix, 'mask'])
-
- l2tp['client_ipv6_pool'].append(tmp)
-
- if conf.exists(['client-ipv6-pool', 'delegate']):
+ l2tp['ordered_named_pools'] = get_pools_in_order(
+ dict_search('client_ip_pool', l2tp))
+ l2tp['ip6_column'] = []
+ if dict_search('client_ipv6_pool.prefix', l2tp):
+ l2tp['ip6_column'].append('ipv6')
+ if dict_search('client_ipv6_pool.delegate', l2tp):
l2tp['ip6_column'].append('ip6-db')
- for prefix in conf.list_nodes(['client-ipv6-pool', 'delegate']):
- tmp = {
- 'prefix': prefix,
- 'mask': ''
- }
-
- if conf.exists(['client-ipv6-pool', 'delegate', prefix, 'delegation-prefix']):
- tmp['mask'] = conf.return_value(['client-ipv6-pool', 'delegate', prefix, 'delegation-prefix'])
-
- l2tp['client_ipv6_delegate_prefix'].append(tmp)
-
- if conf.exists(['default-pool']):
- l2tp['default_pool'] = conf.return_value(['default-pool'])
-
- if conf.exists(['mtu']):
- l2tp['mtu'] = conf.return_value(['mtu'])
-
- # gateway address
- if conf.exists(['gateway-address']):
- l2tp['gateway_address'] = conf.return_value(['gateway-address'])
-
- # LNS secret
- if conf.exists(['lns', 'shared-secret']):
- l2tp['lns_shared_secret'] = conf.return_value(['lns', 'shared-secret'])
- if conf.exists(['lns', 'host-name']):
- l2tp['lns_host_name'] = conf.return_value(['lns', 'host-name'])
-
- if conf.exists(['ccp-disable']):
- l2tp['ccp_disable'] = True
-
- # PPP options
- if conf.exists(['idle']):
- l2tp['ppp_echo_timeout'] = conf.return_value(['idle'])
-
- if conf.exists(['ppp-options', 'lcp-echo-failure']):
- l2tp['ppp_echo_failure'] = conf.return_value(['ppp-options', 'lcp-echo-failure'])
-
- if conf.exists(['ppp-options', 'lcp-echo-interval']):
- l2tp['ppp_echo_interval'] = conf.return_value(['ppp-options', 'lcp-echo-interval'])
-
- if conf.exists(['ppp-options', 'ipv6']):
- l2tp['ppp_ipv6'] = conf.return_value(['ppp-options', 'ipv6'])
-
- if conf.exists(['ppp-options', 'ipv6-accept-peer-intf-id']):
- l2tp['ppp_ipv6_accept_peer_intf_id'] = True
-
- if conf.exists(['ppp-options', 'ipv6-intf-id']):
- l2tp['ppp_ipv6_intf_id'] = conf.return_value(['ppp-options', 'ipv6-intf-id'])
-
- if conf.exists(['ppp-options', 'ipv6-peer-intf-id']):
- l2tp['ppp_ipv6_peer_intf_id'] = conf.return_value(['ppp-options', 'ipv6-peer-intf-id'])
-
l2tp['server_type'] = 'l2tp'
return l2tp
-
-
-
def verify(l2tp):
if not l2tp:
return None
- if l2tp['auth_mode'] == 'local':
- if not l2tp['local_users']:
- raise ConfigError('L2TP local auth mode requires local users to be configured!')
-
- for user in l2tp['local_users']:
- if not user['password']:
- raise ConfigError(f"Password required for user {user['name']}")
-
- elif l2tp['auth_mode'] == 'radius':
- if len(l2tp['radius_server']) == 0:
- raise ConfigError("RADIUS authentication requires at least one server")
-
- for radius in l2tp['radius_server']:
- if not radius['key']:
- raise ConfigError(f"Missing RADIUS secret for server { radius['key'] }")
+ verify_accel_ppp_base_service(l2tp)
- if l2tp['radius_dynamic_author']:
- if not l2tp['radius_dynamic_author']['server']:
- raise ConfigError("Missing ip-address for dae-server")
- if not l2tp['radius_dynamic_author']['key']:
- raise ConfigError("Missing secret for dae-server")
- address = l2tp['radius_dynamic_author']['server']
- port = l2tp['radius_dynamic_author']['port']
- proto = 'tcp'
- # check if dae listen port is not used by another service
- if check_port_availability(address, int(port), proto) is not True and \
- not is_listen_port_bind_service(int(port), 'accel-pppd'):
- raise ConfigError(f'"{proto}" port "{port}" is used by another service')
+ if dict_search('authentication.radius.dynamic_author.server', l2tp):
+ if not dict_search('authentication.radius.dynamic_author.key', l2tp):
+ raise ConfigError('DA/CoE server key required!')
- if l2tp['auth_mode'] == 'local' or l2tp['auth_mode'] == 'noauth':
- if not l2tp['client_ip_pool']:
+ if dict_search('authentication.mode', l2tp) in ['local', 'noauth']:
+ if not l2tp['client_ip_pool'] and not l2tp['client_ipv6_pool']:
raise ConfigError(
- "L2TP local auth mode requires local client-ip-pool to be configured!")
- verify_accel_ppp_ip_pool(l2tp)
-
- # check ipv6
- if l2tp['client_ipv6_delegate_prefix'] and not l2tp['client_ipv6_pool']:
- raise ConfigError('IPv6 prefix delegation requires client-ipv6-pool prefix')
-
- for prefix in l2tp['client_ipv6_delegate_prefix']:
- if not prefix['mask']:
- raise ConfigError('Delegation-prefix required for individual delegated networks')
+ "L2TP local auth mode requires local client-ip-pool or client-ipv6-pool to be configured!")
+ if dict_search('client_ip_pool', l2tp) and not dict_search('default_pool', l2tp):
+ Warning("'default-pool' is not defined")
- if len(l2tp['wins']) > 2:
- raise ConfigError('Not more then two IPv4 WINS name-servers can be configured')
-
- if len(l2tp['dnsv4']) > 2:
- raise ConfigError('Not more then two IPv4 DNS name-servers can be configured')
+ verify_accel_ppp_ip_pool(l2tp)
- if len(l2tp['dnsv6']) > 3:
- raise ConfigError('Not more then three IPv6 DNS name-servers can be configured')
+ if 'wins_server' in l2tp and len(l2tp['wins_server']) > 2:
+ raise ConfigError(
+ 'Not more then two WINS name-servers can be configured')
return None
@@ -396,13 +92,9 @@ def generate(l2tp):
render(l2tp_conf, 'accel-ppp/l2tp.config.j2', l2tp)
- if l2tp['auth_mode'] == 'local':
- render(l2tp_chap_secrets, 'accel-ppp/chap-secrets.j2', l2tp)
- os.chmod(l2tp_chap_secrets, S_IRUSR | S_IWUSR | S_IRGRP)
-
- else:
- if os.path.exists(l2tp_chap_secrets):
- os.unlink(l2tp_chap_secrets)
+ if dict_search('authentication.mode', l2tp) == 'local':
+ render(l2tp_chap_secrets, 'accel-ppp/chap-secrets.config_dict.j2',
+ l2tp, permission=0o640)
return None
@@ -418,12 +110,14 @@ def apply(l2tp):
call('systemctl restart accel-ppp@l2tp.service')
+
if __name__ == '__main__':
try:
c = get_config()
verify(c)
generate(c)
apply(c)
+
except ConfigError as e:
print(e)
exit(1)
diff --git a/src/migration-scripts/l2tp/5-to-6 b/src/migration-scripts/l2tp/5-to-6
new file mode 100755
index 000000000..ca0b13dcc
--- /dev/null
+++ b/src/migration-scripts/l2tp/5-to-6
@@ -0,0 +1,110 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2023 VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# published by the Free Software Foundation.
+#
+# This program 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 General Public License for more details.
+#
+# 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 sys import argv
+from sys import exit
+from vyos.configtree import ConfigTree
+
+
+if len(argv) < 2:
+ print("Must specify file name!")
+ exit(1)
+
+file_name = argv[1]
+
+with open(file_name, 'r') as f:
+ config_file = f.read()
+
+config = ConfigTree(config_file)
+base = ['vpn', 'l2tp', 'remote-access']
+if not config.exists(base):
+ exit(0)
+
+#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)
+
+try:
+ with open(file_name, 'w') as f:
+ f.write(config.to_string())
+except OSError as e:
+ print("Failed to save the modified config: {}".format(e))
+ exit(1)