Page MenuHomeVyOS Platform

No OneTemporary

Size
147 KB
Referenced Files
None
Subscribers
None
diff --git a/data/templates/accel-ppp/config_ipv6_pool.j2 b/data/templates/accel-ppp/config_ipv6_pool.j2
index a1562a1eb..86efdc1e1 100644
--- a/data/templates/accel-ppp/config_ipv6_pool.j2
+++ b/data/templates/accel-ppp/config_ipv6_pool.j2
@@ -1,22 +1,21 @@
{% if client_ipv6_pool is vyos_defined %}
[ipv6-nd]
AdvAutonomousFlag=1
verbose=1
-{% if client_ipv6_pool.prefix is vyos_defined %}
[ipv6-pool]
-{% for prefix, options in client_ipv6_pool.prefix.items() %}
-{{ prefix }},{{ options.mask }}
-{% endfor %}
-{% if client_ipv6_pool.delegate is vyos_defined %}
-{% for prefix, options in client_ipv6_pool.delegate.items() %}
-delegate={{ prefix }},{{ options.delegation_prefix }}
+{% for pool_name, pool_config in client_ipv6_pool.items() %}
+{% if pool_config.prefix is vyos_defined %}
+{% for prefix, options in pool_config.prefix.items() %}
+{{ prefix }},{{ options.mask }},name={{ pool_name }}
{% endfor %}
{% endif %}
-{% endif %}
-
-{% if client_ipv6_pool.delegate is vyos_defined %}
+{% if pool_config.delegate is vyos_defined %}
+{% for prefix, options in pool_config.delegate.items() %}
+delegate={{ prefix }},{{ options.delegation_prefix }},name={{ pool_name }}
+{% endfor %}
+{% endif %}
+{% endfor %}
[ipv6-dhcp]
verbose=1
-{% endif %}
{% endif %}
diff --git a/data/templates/accel-ppp/ipoe.config.j2 b/data/templates/accel-ppp/ipoe.config.j2
index 588f3d462..8b022eaa5 100644
--- a/data/templates/accel-ppp/ipoe.config.j2
+++ b/data/templates/accel-ppp/ipoe.config.j2
@@ -1,84 +1,88 @@
{# j2lint: disable=operator-enclosed-by-spaces #}
### generated by ipoe.py ###
[modules]
log_syslog
ipoe
shaper
{# Common authentication backend definitions #}
{% include 'accel-ppp/config_modules_auth_mode.j2' %}
ipv6pool
ipv6_nd
ipv6_dhcp
ippool
[core]
thread-count={{ thread_count }}
[common]
{% if max_concurrent_sessions is vyos_defined %}
max-starting={{ max_concurrent_sessions }}
{% endif %}
[log]
syslog=accel-ipoe,daemon
copy=1
level=5
[ipoe]
verbose=1
{% if interface is vyos_defined %}
{% for iface, iface_config in interface.items() %}
{% set tmp = 'interface=' %}
{% if iface_config.vlan is vyos_defined %}
{% set tmp = tmp ~ 're:^' ~ iface ~ '\.' ~ iface_config.vlan | range_to_regex ~ '$' %}
{% else %}
{% set tmp = tmp ~ iface %}
{% endif %}
{% set shared = '' %}
{% if iface_config.network is vyos_defined('shared') %}
{% set shared = 'shared=1,' %}
{% elif iface_config.network is vyos_defined('vlan') %}
{% set shared = 'shared=0,' %}
{% endif %}
{% set range = 'range=' ~ iface_config.client_subnet ~ ',' if iface_config.client_subnet is vyos_defined else '' %}
{% set relay = ',' ~ 'relay=' ~ iface_config.external_dhcp.dhcp_relay if iface_config.external_dhcp.dhcp_relay is vyos_defined else '' %}
{% set giaddr = ',' ~ 'giaddr=' ~ iface_config.external_dhcp.giaddr if iface_config.external_dhcp.giaddr is vyos_defined else '' %}
{{ tmp }},{{ shared }}mode={{ iface_config.mode | upper }},ifcfg=1,{{ range }}start=dhcpv4,ipv6=1{{ relay }}{{ giaddr }}
{% if iface_config.vlan is vyos_defined %}
vlan-mon={{ iface }},{{ iface_config.vlan | join(',') }}
{% endif %}
{% endfor %}
{% endif %}
{% if authentication.mode is vyos_defined('noauth') %}
noauth=1
{% elif authentication.mode is vyos_defined('local') %}
username=ifname
password=csid
{% endif %}
{% if default_pool is vyos_defined %}
ip-pool={{ default_pool }}
{% endif %}
+{% if default_ipv6_pool is vyos_defined %}
+ipv6-pool={{ default_ipv6_pool }}
+ipv6-pool-delegate={{ default_ipv6_pool }}
+{% endif %}
{% if gateway_address is vyos_defined %}
{% for gw_addr in gateway_address %}
gw-ip-address={{ gw_addr }}
{% endfor %}
{% endif %}
proxy-arp=1
{# Common IP pool definitions #}
{% include 'accel-ppp/config_ip_pool.j2' %}
{# Common IPv6 pool definitions #}
{% include 'accel-ppp/config_ipv6_pool.j2' %}
{# Common DNS name-server definition #}
{% include 'accel-ppp/config_name_server.j2' %}
{# Common chap-secrets and RADIUS server/option definitions #}
{% include 'accel-ppp/config_chap_secrets_radius.j2' %}
{# Common RADIUS shaper configuration #}
{% include 'accel-ppp/config_shaper_radius.j2' %}
[cli]
tcp=127.0.0.1:2002
diff --git a/data/templates/accel-ppp/l2tp.config.j2 b/data/templates/accel-ppp/l2tp.config.j2
index 49755254a..f041e278e 100644
--- a/data/templates/accel-ppp/l2tp.config.j2
+++ b/data/templates/accel-ppp/l2tp.config.j2
@@ -1,98 +1,102 @@
### generated by accel_l2tp.py ###
[modules]
log_syslog
l2tp
shaper
{# 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_count }}
[common]
{% if max_concurrent_sessions is vyos_defined %}
max-starting={{ max_concurrent_sessions }}
{% endif %}
[log]
syslog=accel-l2tp,daemon
copy=1
level=5
{# Common DNS name-server definition #}
{% include 'accel-ppp/config_name_server.j2' %}
{% if wins_server is vyos_defined %}
[wins]
{% for server in wins_server %}
wins{{ loop.index }}={{ server }}
{% endfor %}
{% endif %}
[l2tp]
verbose=1
ifname=l2tp%d
ppp-max-mtu={{ mtu }}
mppe={{ ppp_options.mppe }}
{% if outside_address is vyos_defined %}
bind={{ outside_address }}
{% endif %}
{% if lns.shared_secret is vyos_defined %}
secret={{ lns.shared_secret }}
{% endif %}
{% if lns.host_name is vyos_defined %}
host-name={{ lns.host_name }}
{% endif %}
{% if default_pool is vyos_defined %}
ip-pool={{ default_pool }}
{% endif %}
+{% if default_ipv6_pool is vyos_defined %}
+ipv6-pool={{ default_ipv6_pool }}
+ipv6-pool-delegate={{ default_ipv6_pool }}
+{% endif %}
[client-ip-range]
0.0.0.0/0
{# Common IP pool definitions #}
{% include 'accel-ppp/config_ip_pool.j2' %}
{# 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-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 %}
unit-preallocate={{ "1" if authentication.radius.preallocate_vif is vyos_defined else "0" }}
{% if ppp_options.ipv6_intf_id is vyos_defined %}
ipv6-intf-id={{ ppp_options.ipv6_intf_id }}
{% endif %}
{% 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" }}
{# 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
sessions-columns=ifname,username,calling-sid,ip,{{ ip6_column | join(',') }}{{ ',' if ip6_column }}rate-limit,type,comp,state,rx-bytes,tx-bytes,uptime
diff --git a/data/templates/accel-ppp/pppoe.config.j2 b/data/templates/accel-ppp/pppoe.config.j2
index 4bb1c4450..fb8a11366 100644
--- a/data/templates/accel-ppp/pppoe.config.j2
+++ b/data/templates/accel-ppp/pppoe.config.j2
@@ -1,174 +1,178 @@
### generated by accel_pppoe.py ###
[modules]
log_syslog
pppoe
shaper
{# 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' %}
{% if snmp is vyos_defined %}
net-snmp
{% endif %}
{% if limits is vyos_defined %}
connlimit
{% endif %}
{% if extended_scripts is vyos_defined %}
sigchld
pppd_compat
{% endif %}
[core]
thread-count={{ thread_count }}
[log]
syslog=accel-pppoe,daemon
copy=1
level=5
{% if authentication.mode is vyos_defined("noauth") %}
[auth]
noauth=1
{% endif %}
{% if snmp.master_agent is vyos_defined %}
[snmp]
master=1
{% endif %}
[client-ip-range]
disable
{# Common IP pool definitions #}
{% include 'accel-ppp/config_ip_pool.j2' %}
{# Common IPv6 pool definitions #}
{% include 'accel-ppp/config_ipv6_pool.j2' %}
{# Common DNS name-server definition #}
{% include 'accel-ppp/config_name_server.j2' %}
{% if wins_server is vyos_defined %}
[wins]
{% for server in wins_server %}
wins{{ loop.index }}={{ server }}
{% endfor %}
{% endif %}
{# Common chap-secrets and RADIUS server/option definitions #}
{% include 'accel-ppp/config_chap_secrets_radius.j2' %}
[common]
{% if session_control is vyos_defined and session_control is not vyos_defined('disable') %}
single-session={{ session_control }}
{% endif %}
{% if max_concurrent_sessions is vyos_defined %}
max-starting={{ max_concurrent_sessions }}
{% endif %}
[ppp]
verbose=1
check-ip=1
ccp={{ "1" if ppp_options.ccp is vyos_defined else "0" }}
unit-preallocate={{ "1" if authentication.radius.preallocate_vif is vyos_defined else "0" }}
{% if ppp_options.min_mtu is vyos_defined %}
min-mtu={{ ppp_options.min_mtu }}
{% endif %}
{% if ppp_options.mru is vyos_defined %}
mru={{ ppp_options.mru }}
{% endif %}
mppe={{ ppp_options.mppe }}
lcp-echo-interval={{ ppp_options.lcp_echo_interval }}
lcp-echo-timeout={{ ppp_options.lcp_echo_timeout }}
lcp-echo-failure={{ ppp_options.lcp_echo_failure }}
{% if ppp_options.ipv4 is vyos_defined %}
ipv4={{ ppp_options.ipv4 }}
{% endif %}
{# IPv6 #}
{% if ppp_options.ipv6 is vyos_defined %}
ipv6={{ ppp_options.ipv6 }}
{% if ppp_options.ipv6_intf_id is vyos_defined %}
ipv6-intf-id={{ ppp_options.ipv6_intf_id }}
{% endif %}
{% 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" }}
{% endif %}
{# MTU #}
mtu={{ mtu }}
{% if ppp_options.interface_cache is vyos_defined %}
unit-cache={{ ppp_options.interface_cache }}
{% endif %}
[pppoe]
verbose=1
ac-name={{ access_concentrator }}
{% if interface is vyos_defined %}
{% for iface, iface_config in interface.items() %}
{% if iface_config.vlan is not vyos_defined %}
interface={{ iface }}
{% else %}
{% for vlan in iface_config.vlan %}
interface=re:^{{ iface }}\.{{ vlan | range_to_regex }}$
{% endfor %}
vlan-mon={{ iface }},{{ iface_config.vlan | join(',') }}
{% endif %}
{% endfor %}
{% endif %}
{% if service_name %}
service-name={{ service_name | join(',') }}
{% endif %}
{% if pado_delay %}
{% set pado_delay_param = namespace(value='0') %}
{% for delay in pado_delay | sort(attribute='0') %}
{% if not loop.last %}
{% set pado_delay_param.value = pado_delay_param.value + ',' + delay + ':' + pado_delay[delay].sessions %}
{% else %}
{% set pado_delay_param.value = pado_delay_param.value + ',-1:' + pado_delay[delay].sessions %}
{% endif %}
{% endfor %}
pado-delay={{ pado_delay_param.value }}
{% endif %}
{% if authentication.radius.called_sid_format is vyos_defined %}
called-sid={{ authentication.radius.called_sid_format }}
{% endif %}
{% if authentication.mode is vyos_defined("noauth") %}
noauth=1
{% endif %}
{% if default_pool is vyos_defined %}
ip-pool={{ default_pool }}
{% endif %}
+{% if default_ipv6_pool is vyos_defined %}
+ipv6-pool={{ default_ipv6_pool }}
+ipv6-pool-delegate={{ default_ipv6_pool }}
+{% endif %}
{% if limits is vyos_defined %}
[connlimit]
{% if limits.connection_limit is vyos_defined %}
limit={{ limits.connection_limit }}
{% endif %}
{% if limits.burst is vyos_defined %}
burst={{ limits.burst }}
{% endif %}
{% if limits.timeout is vyos_defined %}
timeout={{ limits.timeout }}
{% endif %}
{% endif %}
{# Common RADIUS shaper configuration #}
{% include 'accel-ppp/config_shaper_radius.j2' %}
{% if extended_scripts is vyos_defined %}
[pppd-compat]
verbose=1
radattr-prefix=/run/accel-pppd/radattr
{% set script_name = {'on_up': 'ip-up', 'on_down': 'ip-down', 'on_change':'ip-change', 'on_pre_up':'ip-pre-up'} %}
{% for script in extended_scripts %}
{{ script_name[script] }}={{ extended_scripts[script] }}
{% endfor %}
{% endif %}
[cli]
tcp=127.0.0.1:2001
diff --git a/data/templates/accel-ppp/sstp.config.j2 b/data/templates/accel-ppp/sstp.config.j2
index 014ae1235..51f7dfca8 100644
--- a/data/templates/accel-ppp/sstp.config.j2
+++ b/data/templates/accel-ppp/sstp.config.j2
@@ -1,72 +1,76 @@
### generated by vpn_sstp.py ###
[modules]
log_syslog
sstp
shaper
{# 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_count }}
[common]
single-session=replace
{% if max_concurrent_sessions is vyos_defined %}
max-starting={{ max_concurrent_sessions }}
{% endif %}
[log]
syslog=accel-sstp,daemon
copy=1
level=5
[client-ip-range]
disable
[sstp]
verbose=1
ifname=sstp%d
port={{ port }}
accept=ssl
ssl-ca-file=/run/accel-pppd/sstp-ca.pem
ssl-pemfile=/run/accel-pppd/sstp-cert.pem
ssl-keyfile=/run/accel-pppd/sstp-cert.key
{% if default_pool is vyos_defined %}
ip-pool={{ default_pool }}
{% endif %}
+{% if default_ipv6_pool is vyos_defined %}
+ipv6-pool={{ default_ipv6_pool }}
+ipv6-pool-delegate={{ default_ipv6_pool }}
+{% endif %}
{# Common IP pool definitions #}
{% include 'accel-ppp/config_ip_pool.j2' %}
{# Common IPv6 pool definitions #}
{% include 'accel-ppp/config_ipv6_pool.j2' %}
{# Common DNS name-server definition #}
{% include 'accel-ppp/config_name_server.j2' %}
{# Common chap-secrets and RADIUS server/option definitions #}
{% include 'accel-ppp/config_chap_secrets_radius.j2' %}
[ppp]
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 }}
lcp-echo-interval={{ ppp_options.lcp_echo_interval }}
lcp-echo-timeout={{ ppp_options.lcp_echo_timeout }}
lcp-echo-failure={{ ppp_options.lcp_echo_failure }}
{# Common RADIUS shaper configuration #}
{% include 'accel-ppp/config_shaper_radius.j2' %}
[cli]
tcp=127.0.0.1:2005
diff --git a/interface-definitions/include/accel-ppp/client-ipv6-pool.xml.i b/interface-definitions/include/accel-ppp/client-ipv6-pool.xml.i
index 774741a5e..0c8c2e34c 100644
--- a/interface-definitions/include/accel-ppp/client-ipv6-pool.xml.i
+++ b/interface-definitions/include/accel-ppp/client-ipv6-pool.xml.i
@@ -1,62 +1,69 @@
<!-- include start from accel-ppp/client-ipv6-pool.xml.i -->
-<node name="client-ipv6-pool">
+<tagNode name="client-ipv6-pool">
<properties>
<help>Pool of client IPv6 addresses</help>
+ <valueHelp>
+ <format>txt</format>
+ <description>Name of IPv6 pool</description>
+ </valueHelp>
+ <constraint>
+ #include <include/constraint/alpha-numeric-hyphen-underscore-dot.xml.i>
+ </constraint>
</properties>
<children>
<tagNode name="prefix">
<properties>
<help>Pool of addresses used to assign to clients</help>
<valueHelp>
<format>ipv6net</format>
<description>IPv6 address and prefix length</description>
</valueHelp>
<constraint>
<validator name="ipv6-prefix"/>
</constraint>
</properties>
<children>
<leafNode name="mask">
<properties>
<help>Prefix length used for individual client</help>
<valueHelp>
<format>u32:48-128</format>
<description>Client prefix length</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 48-128"/>
</constraint>
</properties>
<defaultValue>64</defaultValue>
</leafNode>
</children>
</tagNode>
<tagNode name="delegate">
<properties>
<help>Subnet used to delegate prefix through DHCPv6-PD (RFC3633)</help>
<valueHelp>
<format>ipv6net</format>
<description>IPv6 address and prefix length</description>
</valueHelp>
<constraint>
<validator name="ipv6-prefix"/>
</constraint>
</properties>
<children>
<leafNode name="delegation-prefix">
<properties>
<help>Prefix length delegated to client</help>
<valueHelp>
<format>u32:32-64</format>
<description>Delegated prefix length</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 32-64"/>
</constraint>
</properties>
</leafNode>
</children>
</tagNode>
</children>
-</node>
+</tagNode>
<!-- include end -->
diff --git a/interface-definitions/include/accel-ppp/default-ipv6-pool.xml.i b/interface-definitions/include/accel-ppp/default-ipv6-pool.xml.i
new file mode 100644
index 000000000..1093f6713
--- /dev/null
+++ b/interface-definitions/include/accel-ppp/default-ipv6-pool.xml.i
@@ -0,0 +1,17 @@
+<!-- include start from accel-ppp/default-pool.xml.i -->
+<leafNode name="default-ipv6-pool">
+ <properties>
+ <help>Default client IPv6 pool name</help>
+ <completionHelp>
+ <path>${COMP_WORDS[@]:1:${#COMP_WORDS[@]}-3} client-ipv6-pool</path>
+ </completionHelp>
+ <valueHelp>
+ <format>txt</format>
+ <description>Default IPv6 pool</description>
+ </valueHelp>
+ <constraint>
+ #include <include/constraint/alpha-numeric-hyphen-underscore-dot.xml.i>
+ </constraint>
+ </properties>
+</leafNode>
+<!-- include end -->
diff --git a/interface-definitions/include/version/ipoe-server-version.xml.i b/interface-definitions/include/version/ipoe-server-version.xml.i
index e5983ab39..659433382 100644
--- a/interface-definitions/include/version/ipoe-server-version.xml.i
+++ b/interface-definitions/include/version/ipoe-server-version.xml.i
@@ -1,3 +1,3 @@
<!-- include start from include/version/ipoe-server-version.xml.i -->
-<syntaxVersion component='ipoe-server' version='2'></syntaxVersion>
+<syntaxVersion component='ipoe-server' version='3'></syntaxVersion>
<!-- include end -->
diff --git a/interface-definitions/include/version/l2tp-version.xml.i b/interface-definitions/include/version/l2tp-version.xml.i
index f4507d93b..793cd5d0c 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='6'></syntaxVersion>
+<syntaxVersion component='l2tp' version='7'></syntaxVersion>
<!-- include end -->
diff --git a/interface-definitions/include/version/pppoe-server-version.xml.i b/interface-definitions/include/version/pppoe-server-version.xml.i
index deed702f0..02f98cc16 100644
--- a/interface-definitions/include/version/pppoe-server-version.xml.i
+++ b/interface-definitions/include/version/pppoe-server-version.xml.i
@@ -1,3 +1,3 @@
<!-- include start from include/version/pppoe-server-version.xml.i -->
-<syntaxVersion component='pppoe-server' version='7'></syntaxVersion>
+<syntaxVersion component='pppoe-server' version='8'></syntaxVersion>
<!-- include end -->
diff --git a/interface-definitions/include/version/sstp-version.xml.i b/interface-definitions/include/version/sstp-version.xml.i
index 3ac54a3de..5e30950d8 100644
--- a/interface-definitions/include/version/sstp-version.xml.i
+++ b/interface-definitions/include/version/sstp-version.xml.i
@@ -1,3 +1,3 @@
<!-- include start from include/version/sstp-version.xml.i -->
-<syntaxVersion component='sstp' version='5'></syntaxVersion>
+<syntaxVersion component='sstp' version='6'></syntaxVersion>
<!-- include end -->
diff --git a/interface-definitions/service_ipoe-server.xml.in b/interface-definitions/service_ipoe-server.xml.in
index edfe6a34c..eeec2aeef 100644
--- a/interface-definitions/service_ipoe-server.xml.in
+++ b/interface-definitions/service_ipoe-server.xml.in
@@ -1,190 +1,191 @@
<?xml version="1.0"?>
<interfaceDefinition>
<node name="service">
<children>
<node name="ipoe-server" owner="${vyos_conf_scripts_dir}/service_ipoe-server.py">
<properties>
<help>Internet Protocol over Ethernet (IPoE) Server</help>
<priority>900</priority>
</properties>
<children>
<tagNode name="interface">
<properties>
<help>Interface to listen dhcp or unclassified packets</help>
<completionHelp>
<script>${vyos_completion_dir}/list_interfaces</script>
</completionHelp>
</properties>
<children>
<leafNode name="mode">
<properties>
<help>Client connectivity mode</help>
<completionHelp>
<list>l2 l3</list>
</completionHelp>
<valueHelp>
<format>l2</format>
<description>Client located on same interface as server</description>
</valueHelp>
<valueHelp>
<format>l3</format>
<description>Client located behind a router</description>
</valueHelp>
<constraint>
<regex>(l2|l3)</regex>
</constraint>
</properties>
<defaultValue>l2</defaultValue>
</leafNode>
<leafNode name="network">
<properties>
<help>Enables clients to share the same network or each client has its own vlan</help>
<completionHelp>
<list>shared vlan</list>
</completionHelp>
<constraint>
<regex>(shared|vlan)</regex>
</constraint>
<valueHelp>
<format>shared</format>
<description>Multiple clients share the same network</description>
</valueHelp>
<valueHelp>
<format>vlan</format>
<description>One VLAN per client</description>
</valueHelp>
</properties>
<defaultValue>shared</defaultValue>
</leafNode>
<leafNode name="client-subnet">
<properties>
<help>Client address pool</help>
<valueHelp>
<format>ipv4net</format>
<description>IPv4 address and prefix length</description>
</valueHelp>
<constraint>
<validator name="ipv4-prefix"/>
</constraint>
</properties>
</leafNode>
<node name="external-dhcp">
<properties>
<help>DHCP requests will be forwarded</help>
</properties>
<children>
<leafNode name="dhcp-relay">
<properties>
<help>DHCP Server the request will be redirected to.</help>
<valueHelp>
<format>ipv4</format>
<description>IPv4 address of the DHCP Server</description>
</valueHelp>
<constraint>
<validator name="ipv4-address"/>
</constraint>
</properties>
</leafNode>
<leafNode name="giaddr">
<properties>
<help>Relay Agent IPv4 Address</help>
<valueHelp>
<format>ipv4</format>
<description>Gateway IP address</description>
</valueHelp>
<constraint>
<validator name="ipv4-address"/>
</constraint>
</properties>
</leafNode>
</children>
</node>
#include <include/accel-ppp/vlan.xml.i>
</children>
</tagNode>
#include <include/accel-ppp/max-concurrent-sessions.xml.i>
#include <include/name-server-ipv4-ipv6.xml.i>
#include <include/accel-ppp/client-ip-pool.xml.i>
#include <include/accel-ppp/gateway-address-multi.xml.i>
#include <include/accel-ppp/client-ipv6-pool.xml.i>
<node name="authentication">
<properties>
<help>Client authentication methods</help>
</properties>
<children>
#include <include/accel-ppp/auth-mode.xml.i>
<tagNode name="interface">
<properties>
<help>Network interface for client MAC addresses</help>
<completionHelp>
<script>${vyos_completion_dir}/list_interfaces</script>
</completionHelp>
</properties>
<children>
<tagNode name="mac">
<properties>
<help>Media Access Control (MAC) address</help>
<valueHelp>
<format>macaddr</format>
<description>Hardware (MAC) address</description>
</valueHelp>
<constraint>
<validator name="mac-address"/>
</constraint>
</properties>
<children>
<node name="rate-limit">
<properties>
<help>Upload/Download speed limits</help>
</properties>
<children>
<leafNode name="upload">
<properties>
<help>Upload bandwidth limit in kbits/sec</help>
<constraint>
<validator name="numeric" argument="--range 1-65535"/>
</constraint>
</properties>
</leafNode>
<leafNode name="download">
<properties>
<help>Download bandwidth limit in kbits/sec</help>
<constraint>
<validator name="numeric" argument="--range 1-65535"/>
</constraint>
</properties>
</leafNode>
</children>
</node>
<leafNode name="vlan">
<properties>
<help>VLAN monitor for automatic creation of VLAN interfaces</help>
<valueHelp>
<format>u32:1-4094</format>
<description>Client VLAN id</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-4094"/>
</constraint>
<constraintErrorMessage>VLAN IDs need to be in range 1-4094</constraintErrorMessage>
</properties>
</leafNode>
</children>
</tagNode>
</children>
</tagNode>
<node name="radius">
<children>
#include <include/accel-ppp/radius-additions-rate-limit.xml.i>
</children>
</node>
#include <include/radius-auth-server-ipv4.xml.i>
#include <include/accel-ppp/radius-additions.xml.i>
</children>
</node>
#include <include/accel-ppp/default-pool.xml.i>
+ #include <include/accel-ppp/default-ipv6-pool.xml.i>
</children>
</node>
</children>
</node>
</interfaceDefinition>
diff --git a/interface-definitions/service_pppoe-server.xml.in b/interface-definitions/service_pppoe-server.xml.in
index f1b369936..6fdc2a65a 100644
--- a/interface-definitions/service_pppoe-server.xml.in
+++ b/interface-definitions/service_pppoe-server.xml.in
@@ -1,281 +1,282 @@
<?xml version="1.0"?>
<interfaceDefinition>
<node name="service">
<children>
<node name="pppoe-server" owner="${vyos_conf_scripts_dir}/service_pppoe-server.py">
<properties>
<help>Point to Point over Ethernet (PPPoE) Server</help>
<priority>900</priority>
</properties>
<children>
#include <include/pppoe-access-concentrator.xml.i>
<leafNode name="access-concentrator">
<defaultValue>vyos-ac</defaultValue>
</leafNode>
<node name="authentication">
<properties>
<help>Authentication for remote access PPPoE Server</help>
</properties>
<children>
#include <include/accel-ppp/auth-local-users.xml.i>
#include <include/accel-ppp/auth-mode.xml.i>
#include <include/accel-ppp/auth-protocols.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-additions-rate-limit.xml.i>
<leafNode name="called-sid-format">
<properties>
<help>Format of Called-Station-Id attribute</help>
<completionHelp>
<list>ifname ifname:mac</list>
</completionHelp>
<constraint>
<regex>(ifname|ifname:mac)</regex>
</constraint>
<constraintErrorMessage>Invalid Called-Station-Id format</constraintErrorMessage>
<valueHelp>
<format>ifname</format>
<description>NAS-Port-Id - should contain root interface name (NAS-Port-Id=eth1)</description>
</valueHelp>
<valueHelp>
<format>ifname:mac</format>
<description>NAS-Port-Id - should contain root interface name and mac address (NAS-Port-Id=eth1:00:00:00:00:00:00)</description>
</valueHelp>
</properties>
</leafNode>
</children>
</node>
</children>
</node>
#include <include/accel-ppp/client-ip-pool.xml.i>
#include <include/accel-ppp/client-ipv6-pool.xml.i>
#include <include/name-server-ipv4-ipv6.xml.i>
<tagNode name="interface">
<properties>
<help>interface(s) to listen on</help>
<completionHelp>
<script>${vyos_completion_dir}/list_interfaces</script>
</completionHelp>
</properties>
<children>
#include <include/accel-ppp/vlan.xml.i>
</children>
</tagNode>
#include <include/accel-ppp/gateway-address.xml.i>
#include <include/accel-ppp/max-concurrent-sessions.xml.i>
#include <include/accel-ppp/mtu-128-16384.xml.i>
<node name="limits">
<properties>
<help>Limits the connection rate from a single source</help>
</properties>
<children>
<leafNode name="connection-limit">
<properties>
<help>Acceptable rate of connections (e.g. 1/min, 60/sec)</help>
<constraint>
<regex>[0-9]+\/(min|sec)</regex>
</constraint>
<constraintErrorMessage>illegal value</constraintErrorMessage>
</properties>
</leafNode>
<leafNode name="burst">
<properties>
<help>Burst count</help>
</properties>
</leafNode>
<leafNode name="timeout">
<properties>
<help>Timeout in seconds</help>
</properties>
</leafNode>
</children>
</node>
<leafNode name="service-name">
<properties>
<help>Service name</help>
<constraint>
<regex>[a-zA-Z0-9\-]{1,100}</regex>
</constraint>
<constraintErrorMessage>Service-name can contain aplhanumerical characters and dashes only (max. 100)</constraintErrorMessage>
<multi/>
</properties>
</leafNode>
#include <include/accel-ppp/wins-server.xml.i>
<node name="ppp-options">
<properties>
<help>Advanced protocol options</help>
</properties>
<children>
<leafNode name="min-mtu">
<properties>
<help>Minimum acceptable MTU (68-65535)</help>
<constraint>
<validator name="numeric" argument="--range 68-65535"/>
</constraint>
</properties>
<defaultValue>1280</defaultValue>
</leafNode>
<leafNode name="mru">
<properties>
<help>Preferred MRU (68-65535)</help>
<constraint>
<validator name="numeric" argument="--range 68-65535"/>
</constraint>
</properties>
</leafNode>
<leafNode name="ccp">
<properties>
<help>CCP negotiation (default disabled)</help>
<valueless />
</properties>
</leafNode>
#include <include/accel-ppp/ppp-mppe.xml.i>
#include <include/accel-ppp/lcp-echo-interval-failure.xml.i>
#include <include/accel-ppp/lcp-echo-timeout.xml.i>
#include <include/accel-ppp/ppp-interface-cache.xml.i>
<leafNode name="ipv4">
<properties>
<help>IPv4 (IPCP) negotiation algorithm</help>
<constraint>
<regex>(deny|allow|prefer|require)</regex>
</constraint>
<constraintErrorMessage>invalid value</constraintErrorMessage>
<valueHelp>
<format>deny</format>
<description>Do not negotiate IPv4</description>
</valueHelp>
<valueHelp>
<format>allow</format>
<description>Negotiate IPv4 only if client requests</description>
</valueHelp>
<valueHelp>
<format>prefer</format>
<description>Ask client for IPv4 negotiation, do not fail if it rejects</description>
</valueHelp>
<valueHelp>
<format>require</format>
<description>Require IPv4 negotiation</description>
</valueHelp>
<completionHelp>
<list>deny allow prefer require</list>
</completionHelp>
</properties>
</leafNode>
#include <include/accel-ppp/ppp-options-ipv6.xml.i>
#include <include/accel-ppp/ppp-options-ipv6-interface-id.xml.i>
</children>
</node>
<tagNode name="pado-delay">
<properties>
<help>PADO delays</help>
<valueHelp>
<format>u32:1-999999</format>
<description>Number in ms</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-999999"/>
</constraint>
<constraintErrorMessage>Invalid PADO delay</constraintErrorMessage>
</properties>
<children>
<leafNode name="sessions">
<properties>
<help>Number of sessions</help>
<valueHelp>
<format>u32:1-999999</format>
<description>Number of sessions</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-999999"/>
</constraint>
<constraintErrorMessage>Invalid number of delayed sessions</constraintErrorMessage>
</properties>
</leafNode>
</children>
</tagNode>
<leafNode name="session-control">
<properties>
<help>control sessions count</help>
<constraint>
<regex>(deny|disable|replace)</regex>
</constraint>
<constraintErrorMessage>Invalid value</constraintErrorMessage>
<valueHelp>
<format>disable</format>
<description>Disables session control</description>
</valueHelp>
<valueHelp>
<format>deny</format>
<description>Deny second session authorization</description>
</valueHelp>
<valueHelp>
<format>replace</format>
<description>Terminate first session when second is authorized</description>
</valueHelp>
<completionHelp>
<list>deny disable replace</list>
</completionHelp>
</properties>
<defaultValue>replace</defaultValue>
</leafNode>
#include <include/accel-ppp/shaper.xml.i>
<node name="snmp">
<properties>
<help>Enable SNMP</help>
</properties>
<children>
<leafNode name="master-agent">
<properties>
<help>enable SNMP master agent mode</help>
<valueless />
</properties>
</leafNode>
</children>
</node>
<node name="extended-scripts">
<properties>
<help>Extended script execution</help>
</properties>
<children>
<leafNode name="on-pre-up">
<properties>
<help>Script to run before PPPoE session interface comes up</help>
<constraint>
<validator name="script"/>
</constraint>
</properties>
</leafNode>
<leafNode name="on-up">
<properties>
<help>Script to run when PPPoE session interface is completely configured and started</help>
<constraint>
<validator name="script"/>
</constraint>
</properties>
</leafNode>
<leafNode name="on-down">
<properties>
<help>Script to run when PPPoE session interface going to terminate</help>
<constraint>
<validator name="script"/>
</constraint>
</properties>
</leafNode>
<leafNode name="on-change">
<properties>
<help>Script to run when PPPoE session interface changed by RADIUS CoA handling</help>
<constraint>
<validator name="script"/>
</constraint>
</properties>
</leafNode>
</children>
</node>
#include <include/accel-ppp/default-pool.xml.i>
+ #include <include/accel-ppp/default-ipv6-pool.xml.i>
</children>
</node>
</children>
</node>
</interfaceDefinition>
diff --git a/interface-definitions/vpn_l2tp.xml.in b/interface-definitions/vpn_l2tp.xml.in
index 3e2d00e6b..d3fb58433 100644
--- a/interface-definitions/vpn_l2tp.xml.in
+++ b/interface-definitions/vpn_l2tp.xml.in
@@ -1,163 +1,164 @@
<?xml version="1.0"?>
<interfaceDefinition>
<node name="vpn">
<children>
<node name="l2tp" owner="${vyos_conf_scripts_dir}/vpn_l2tp.py">
<properties>
<help>L2TP Virtual Private Network (VPN)</help>
<priority>902</priority>
</properties>
<children>
<node name="remote-access">
<properties>
<help>Remote access L2TP VPN</help>
</properties>
<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>
<constraint>
<validator name="ipv4-address"/>
</constraint>
</properties>
</leafNode>
#include <include/accel-ppp/gateway-address.xml.i>
#include <include/name-server-ipv4-ipv6.xml.i>
<node name="lns">
<properties>
<help>L2TP Network Server (LNS)</help>
</properties>
<children>
<leafNode name="shared-secret">
<properties>
<help>Tunnel password used to authenticate the client (LAC)</help>
</properties>
</leafNode>
<leafNode name="host-name">
<properties>
<help>Sent to the client (LAC) in the Host-Name attribute</help>
<constraint>
#include <include/constraint/host-name.xml.i>
</constraint>
<constraintErrorMessage>Host-name must be alphanumeric and can contain hyphens</constraintErrorMessage>
</properties>
</leafNode>
</children>
</node>
<leafNode name="ccp-disable">
<properties>
<help>Disable Compression Control Protocol (CCP)</help>
<valueless />
</properties>
</leafNode>
<node name="ipsec-settings">
<properties>
<help>Internet Protocol Security (IPsec) for remote access L2TP VPN</help>
</properties>
<children>
<node name="authentication">
<properties>
<help>IPsec authentication settings</help>
</properties>
<children>
<leafNode name="mode">
<properties>
<help>Authentication mode for IPsec</help>
<valueHelp>
<format>pre-shared-secret</format>
<description>Use pre-shared secret for IPsec authentication</description>
</valueHelp>
<valueHelp>
<format>x509</format>
<description>Use X.509 certificate for IPsec authentication</description>
</valueHelp>
<constraint>
<regex>(pre-shared-secret|x509)</regex>
</constraint>
<completionHelp>
<list>pre-shared-secret x509</list>
</completionHelp>
</properties>
</leafNode>
#include <include/ipsec/authentication-pre-shared-secret.xml.i>
#include <include/ipsec/authentication-x509.xml.i>
</children>
</node>
<leafNode name="ike-lifetime">
<properties>
<help>IKE lifetime</help>
<valueHelp>
<format>u32:30-86400</format>
<description>IKE lifetime in seconds</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 30-86400"/>
</constraint>
</properties>
<defaultValue>3600</defaultValue>
</leafNode>
<leafNode name="lifetime">
<properties>
<help>ESP lifetime</help>
<valueHelp>
<format>u32:30-86400</format>
<description>IKE lifetime in seconds</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 30-86400"/>
</constraint>
</properties>
<defaultValue>3600</defaultValue>
</leafNode>
#include <include/ipsec/esp-group.xml.i>
#include <include/ipsec/ike-group.xml.i>
</children>
</node>
#include <include/accel-ppp/wins-server.xml.i>
#include <include/accel-ppp/client-ip-pool.xml.i>
#include <include/accel-ppp/client-ipv6-pool.xml.i>
#include <include/generic-description.xml.i>
#include <include/dhcp-interface.xml.i>
<node name="authentication">
<properties>
<help>Authentication for remote access L2TP VPN</help>
</properties>
<children>
#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-additions-rate-limit.xml.i>
</children>
</node>
</children>
</node>
<node name="ppp-options">
<properties>
<help>Advanced protocol options</help>
</properties>
<children>
#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>
+ #include <include/accel-ppp/default-ipv6-pool.xml.i>
</children>
</node>
</children>
</node>
</children>
</node>
</interfaceDefinition>
diff --git a/interface-definitions/vpn_pptp.xml.in b/interface-definitions/vpn_pptp.xml.in
index 7bb8db798..ec622b5d0 100644
--- a/interface-definitions/vpn_pptp.xml.in
+++ b/interface-definitions/vpn_pptp.xml.in
@@ -1,143 +1,144 @@
<?xml version="1.0"?>
<interfaceDefinition>
<node name="vpn">
<children>
<node name="pptp" owner="${vyos_conf_scripts_dir}/vpn_pptp.py">
<properties>
<help>Point to Point Tunneling Protocol (PPTP) Virtual Private Network (VPN)</help>
<priority>901</priority>
</properties>
<children>
<node name="remote-access">
<properties>
<help>Remote access PPTP VPN</help>
</properties>
<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>
<constraint>
<validator name="ipv4-address"/>
</constraint>
</properties>
</leafNode>
#include <include/accel-ppp/gateway-address.xml.i>
#include <include/name-server-ipv4.xml.i>
#include <include/accel-ppp/wins-server.xml.i>
#include <include/accel-ppp/client-ip-pool.xml.i>
<node name="authentication">
<properties>
<help>Authentication for remote access PPTP VPN</help>
</properties>
<children>
<leafNode name="require">
<properties>
<help>Authentication protocol for remote access peer PPTP VPN</help>
<completionHelp>
<list>pap chap mschap mschap-v2</list>
</completionHelp>
<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>
</properties>
<defaultValue>mschap-v2</defaultValue>
</leafNode>
<leafNode name="mppe">
<properties>
<help>Specifies mppe negotioation preference. (default require mppe 128-bit stateless</help>
<valueHelp>
<format>deny</format>
<description>deny mppe</description>
</valueHelp>
<valueHelp>
<format>prefer</format>
<description>ask client for mppe, if it rejects do not fail</description>
</valueHelp>
<valueHelp>
<format>require</format>
<description>ask client for mppe, if it rejects drop connection</description>
</valueHelp>
<constraint>
<regex>(deny|prefer|require)</regex>
</constraint>
<completionHelp>
<list>deny prefer require</list>
</completionHelp>
</properties>
<defaultValue>prefer</defaultValue>
</leafNode>
#include <include/accel-ppp/auth-mode.xml.i>
<node name="local-users">
<properties>
<help>Local user authentication for remote access PPTP VPN</help>
</properties>
<children>
<tagNode name="username">
<properties>
<help>User name for authentication</help>
</properties>
<children>
#include <include/generic-disable-node.xml.i>
<leafNode name="password">
<properties>
<help>Password for authentication</help>
</properties>
</leafNode>
<leafNode name="static-ip">
<properties>
<help>Static client IP address</help>
</properties>
<defaultValue>*</defaultValue>
</leafNode>
</children>
</tagNode>
</children>
</node>
<node name="radius">
<children>
#include <include/accel-ppp/radius-additions-rate-limit.xml.i>
</children>
</node>
#include <include/radius-auth-server-ipv4.xml.i>
#include <include/accel-ppp/radius-additions.xml.i>
<node name="radius">
<children>
<leafNode name="timeout">
<defaultValue>30</defaultValue>
</leafNode>
<leafNode name="acct-timeout">
<defaultValue>30</defaultValue>
</leafNode>
</children>
</node>
</children>
</node>
#include <include/accel-ppp/default-pool.xml.i>
+ #include <include/accel-ppp/default-ipv6-pool.xml.i>
</children>
</node>
</children>
</node>
</children>
</node>
</interfaceDefinition>
diff --git a/interface-definitions/vpn_sstp.xml.in b/interface-definitions/vpn_sstp.xml.in
index a1b69f990..2727540be 100644
--- a/interface-definitions/vpn_sstp.xml.in
+++ b/interface-definitions/vpn_sstp.xml.in
@@ -1,64 +1,65 @@
<?xml version="1.0"?>
<interfaceDefinition>
<node name="vpn">
<children>
<node name="sstp" owner="${vyos_conf_scripts_dir}/vpn_sstp.py">
<properties>
<help>Secure Socket Tunneling Protocol (SSTP) server</help>
<priority>901</priority>
</properties>
<children>
<node name="authentication">
<properties>
<help>Authentication for remote access SSTP Server</help>
</properties>
<children>
#include <include/accel-ppp/auth-local-users.xml.i>
#include <include/accel-ppp/auth-mode.xml.i>
#include <include/accel-ppp/auth-protocols.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-additions-rate-limit.xml.i>
</children>
</node>
</children>
</node>
#include <include/accel-ppp/max-concurrent-sessions.xml.i>
#include <include/interface/mtu-68-1500.xml.i>
#include <include/accel-ppp/gateway-address.xml.i>
#include <include/name-server-ipv4-ipv6.xml.i>
#include <include/accel-ppp/client-ip-pool.xml.i>
#include <include/accel-ppp/client-ipv6-pool.xml.i>
#include <include/port-number.xml.i>
<leafNode name="port">
<defaultValue>443</defaultValue>
</leafNode>
#include <include/accel-ppp/default-pool.xml.i>
+ #include <include/accel-ppp/default-ipv6-pool.xml.i>
<node name="ppp-options">
<properties>
<help>PPP (Point-to-Point Protocol) settings</help>
</properties>
<children>
#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/lcp-echo-interval-failure.xml.i>
#include <include/accel-ppp/lcp-echo-timeout.xml.i>
</children>
</node>
<node name="ssl">
<properties>
<help>SSL Certificate, SSL Key and CA</help>
</properties>
<children>
#include <include/pki/ca-certificate.xml.i>
#include <include/pki/certificate.xml.i>
</children>
</node>
</children>
</node>
</children>
</node>
</interfaceDefinition>
diff --git a/python/vyos/accel_ppp_util.py b/python/vyos/accel_ppp_util.py
index 757d447a2..2f029e042 100644
--- a/python/vyos/accel_ppp_util.py
+++ b/python/vyos/accel_ppp_util.py
@@ -1,193 +1,202 @@
-# Copyright 2023 VyOS maintainers and contributors <maintainers@vyos.io>
+# 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/>.
# The sole purpose of this module is to hold common functions used in
# all kinds of implementations to verify the CLI configuration.
# It is started by migrating the interfaces to the new get_config_dict()
# approach which will lead to a lot of code that can be reused.
# NOTE: imports should be as local as possible to the function which
# makes use of it!
from vyos import ConfigError
+from vyos.base import Warning
from vyos.utils.dict import dict_search
-
def get_pools_in_order(data: dict) -> list:
"""Return a list of dictionaries representing pool data in the order
in which they should be allocated. Pool must be defined before we can
use it with 'next-pool' option.
Args:
data: A dictionary of pool data, where the keys are pool names and the
values are dictionaries containing the 'subnet' key and the optional
'next_pool' key.
Returns:
list: A list of dictionaries
Raises:
ValueError: If a 'next_pool' key references a pool name that
has not been defined.
ValueError: If a circular reference is found in the 'next_pool' keys.
Example:
config_data = {
... 'first-pool': {
... 'next_pool': 'second-pool',
... 'subnet': '192.0.2.0/25'
... },
... 'second-pool': {
... 'next_pool': 'third-pool',
... 'subnet': '203.0.113.0/25'
... },
... 'third-pool': {
... 'subnet': '198.51.100.0/24'
... },
... 'foo': {
... 'subnet': '100.64.0.0/24',
... 'next_pool': 'second-pool'
... }
... }
% get_pools_in_order(config_data)
[{'third-pool': {'subnet': '198.51.100.0/24'}},
{'second-pool': {'next_pool': 'third-pool', 'subnet': '203.0.113.0/25'}},
{'first-pool': {'next_pool': 'second-pool', 'subnet': '192.0.2.0/25'}},
{'foo': {'next_pool': 'second-pool', 'subnet': '100.64.0.0/24'}}]
"""
pools = []
unresolved_pools = {}
for pool, pool_config in data.items():
if "next_pool" not in pool_config or not pool_config["next_pool"]:
pools.insert(0, {pool: pool_config})
else:
unresolved_pools[pool] = pool_config
while unresolved_pools:
resolved_pools = []
for pool, pool_config in unresolved_pools.items():
next_pool_name = pool_config["next_pool"]
if any(p for p in pools if next_pool_name in p):
index = next(
(i for i, p in enumerate(pools) if next_pool_name in p), None
)
pools.insert(index + 1, {pool: pool_config})
resolved_pools.append(pool)
elif next_pool_name in unresolved_pools:
# next pool not yet resolved
pass
else:
raise ConfigError(
f"Pool '{next_pool_name}' not defined in configuration data"
)
if not resolved_pools:
raise ConfigError("Circular reference in configuration data")
for pool in resolved_pools:
unresolved_pools.pop(pool)
return pools
def verify_accel_ppp_base_service(config, local_users=True):
"""
Common helper function which must be used by all Accel-PPP services based
on get_config_dict()
"""
# vertify auth settings
if local_users and dict_search("authentication.mode", config) == "local":
if (
dict_search("authentication.local_users", config) is None
or dict_search("authentication.local_users", config) == {}
):
raise ConfigError(
"Authentication mode local requires local users to be configured!"
)
for user in dict_search("authentication.local_users.username", config):
user_config = config["authentication"]["local_users"]["username"][user]
if "password" not in user_config:
raise ConfigError(f'Password required for local user "{user}"')
if "rate_limit" in user_config:
# if up/download is set, check that both have a value
if not {"upload", "download"} <= set(user_config["rate_limit"]):
raise ConfigError(
f'User "{user}" has rate-limit configured for only one '
"direction but both upload and download must be given!"
)
elif dict_search("authentication.mode", config) == "radius":
if not dict_search("authentication.radius.server", config):
raise ConfigError("RADIUS authentication requires at least one server")
for server in dict_search("authentication.radius.server", config):
radius_config = config["authentication"]["radius"]["server"][server]
if "key" not in radius_config:
raise ConfigError(f'Missing RADIUS secret key for server "{server}"')
if "name_server_ipv4" in config:
if len(config["name_server_ipv4"]) > 2:
raise ConfigError(
"Not more then two IPv4 DNS name-servers " "can be configured"
)
if "name_server_ipv6" in config:
if len(config["name_server_ipv6"]) > 3:
raise ConfigError(
"Not more then three IPv6 DNS name-servers " "can be configured"
)
- if "client_ipv6_pool" in config:
- ipv6_pool = config["client_ipv6_pool"]
- if "delegate" in ipv6_pool:
- if "prefix" not in ipv6_pool:
- raise ConfigError(
- 'IPv6 "delegate" also requires "prefix" to be defined!'
- )
-
- for delegate in ipv6_pool["delegate"]:
- if "delegation_prefix" not in ipv6_pool["delegate"][delegate]:
- raise ConfigError("delegation-prefix length required!")
def verify_accel_ppp_ip_pool(vpn_config):
"""
Common helper function which must be used by Accel-PPP
services (pptp, l2tp, sstp, pppoe) to verify client-ip-pool
+ and client-ipv6-pool
"""
if dict_search("client_ip_pool", vpn_config):
for pool_name, pool_config in vpn_config["client_ip_pool"].items():
next_pool = dict_search(f"next_pool", pool_config)
if next_pool:
if next_pool not in vpn_config["client_ip_pool"]:
- raise ConfigError(f'Next pool "{next_pool}" does not exist')
+ raise ConfigError(
+ f'Next pool "{next_pool}" does not exist')
if not dict_search(f"range", pool_config):
raise ConfigError(
f'Pool "{pool_name}" does not contain range but next-pool exists'
)
-
if not dict_search("gateway_address", vpn_config):
- raise ConfigError("Server requires gateway-address to be configured!")
+ Warning("IPv4 Server requires gateway-address to be configured!")
+
default_pool = dict_search("default_pool", vpn_config)
if default_pool:
if default_pool not in dict_search("client_ip_pool", vpn_config):
raise ConfigError(f'Default pool "{default_pool}" does not exists')
+
+ if 'client_ipv6_pool' in vpn_config:
+ for ipv6_pool, ipv6_pool_config in vpn_config['client_ipv6_pool'].items():
+ if 'delegate' in ipv6_pool_config and 'prefix' not in ipv6_pool_config:
+ raise ConfigError(
+ f'IPoE IPv6 deletate-prefix requires IPv6 prefix to be configured in "{ipv6_pool}"!')
+
+ if dict_search('authentication.mode', vpn_config) in ['local', 'noauth']:
+ if not dict_search('client_ip_pool', vpn_config) and not dict_search(
+ 'client_ipv6_pool', vpn_config):
+ raise ConfigError(
+ "L2TP local auth mode requires local client-ip-pool or client-ipv6-pool to be configured!")
+ if dict_search('client_ip_pool', vpn_config) and not dict_search(
+ 'default_pool', vpn_config):
+ Warning("'default-pool' is not defined")
+ if dict_search('client_ipv6_pool', vpn_config) and not dict_search(
+ 'default_ipv6_pool', vpn_config):
+ Warning("'default-ipv6-pool' is not defined")
diff --git a/smoketest/scripts/cli/base_accel_ppp_test.py b/smoketest/scripts/cli/base_accel_ppp_test.py
index 1ea5db898..6219a0a4c 100644
--- a/smoketest/scripts/cli/base_accel_ppp_test.py
+++ b/smoketest/scripts/cli/base_accel_ppp_test.py
@@ -1,443 +1,494 @@
-# Copyright (C) 2020-2023 VyOS maintainers and contributors
+# Copyright (C) 2020-2024 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 re
import unittest
from base_vyostest_shim import VyOSUnitTestSHIM
from configparser import ConfigParser
from vyos.configsession import ConfigSession
from vyos.configsession import ConfigSessionError
from vyos.template import is_ipv4
from vyos.utils.system import get_half_cpus
from vyos.utils.process import process_named_running
from vyos.utils.process import cmd
class BasicAccelPPPTest:
class TestCase(VyOSUnitTestSHIM.TestCase):
@classmethod
def setUpClass(cls):
cls._process_name = "accel-pppd"
super(BasicAccelPPPTest.TestCase, cls).setUpClass()
# ensure we can also run this test on a live system - so lets clean
# out the current configuration :)
cls.cli_delete(cls, cls._base_path)
def setUp(self):
self._gateway = "192.0.2.1"
# ensure we can also run this test on a live system - so lets clean
# out the current configuration :)
self.cli_delete(self._base_path)
def tearDown(self):
# Check for running process
self.assertTrue(process_named_running(self._process_name))
self.cli_delete(self._base_path)
self.cli_commit()
# Check for running process
self.assertFalse(process_named_running(self._process_name))
def set(self, path):
self.cli_set(self._base_path + path)
def delete(self, path):
self.cli_delete(self._base_path + path)
def basic_protocol_specific_config(self):
"""
An astract method.
Initialize protocol scpecific configureations.
"""
self.assertFalse(True, msg="Function must be defined")
def initial_auth_config(self):
"""
Initialization of default authentication for all protocols
"""
self.set(
[
"authentication",
"local-users",
"username",
"vyos",
"password",
"vyos",
]
)
self.set(["authentication", "mode", "local"])
def initial_gateway_config(self):
"""
Initialization of default gateway
"""
self.set(["gateway-address", self._gateway])
def initial_pool_config(self):
"""
Initialization of default client ip pool
"""
first_pool = "SIMPLE-POOL"
self.set(["client-ip-pool", first_pool, "range", "192.0.2.0/24"])
self.set(["default-pool", first_pool])
def basic_config(self, is_auth=True, is_gateway=True, is_client_pool=True):
"""
Initialization of basic configuration
:param is_auth: authentication initialization
:type is_auth: bool
:param is_gateway: gateway initialization
:type is_gateway: bool
:param is_client_pool: client ip pool initialization
:type is_client_pool: bool
"""
self.basic_protocol_specific_config()
if is_auth:
self.initial_auth_config()
if is_gateway:
self.initial_gateway_config()
if is_client_pool:
self.initial_pool_config()
def getConfig(self, start, end="cli"):
"""
Return part of configuration from line
where the first injection of start keyword to the line
where the first injection of end keyowrd
:param start: start keyword
:type start: str
:param end: end keyword
:type end: str
:return: part of config
:rtype: str
"""
command = f'cat {self._config_file} | sed -n "/^\[{start}/,/^\[{end}/p"'
out = cmd(command)
return out
def verify(self, conf):
self.assertEqual(conf["core"]["thread-count"], str(get_half_cpus()))
def test_accel_name_servers(self):
# Verify proper Name-Server configuration for IPv4 and IPv6
self.basic_config()
nameserver = ["192.0.2.1", "192.0.2.2", "2001:db8::1"]
for ns in nameserver:
self.set(["name-server", ns])
# commit changes
self.cli_commit()
# Validate configuration values
conf = ConfigParser(allow_no_value=True, delimiters="=", strict=False)
conf.read(self._config_file)
# IPv4 and IPv6 nameservers must be checked individually
for ns in nameserver:
if is_ipv4(ns):
self.assertIn(ns, [conf["dns"]["dns1"], conf["dns"]["dns2"]])
else:
self.assertEqual(conf["ipv6-dns"][ns], None)
def test_accel_local_authentication(self):
# Test configuration of local authentication
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,
]
)
# upload rate-limit requires also download rate-limit
with self.assertRaises(ConfigSessionError):
self.cli_commit()
self.set(
[
"authentication",
"local-users",
"username",
user,
"rate-limit",
"download",
download,
]
)
# commit changes
self.cli_commit()
# Validate configuration values
conf = ConfigParser(allow_no_value=True, delimiters="=", strict=False)
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
self.basic_config()
radius_server = "192.0.2.22"
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(
["authentication", "radius", "server", radius_server, "key", radius_key]
)
self.set(
[
"authentication",
"radius",
"server",
radius_server,
"port",
radius_port,
]
)
self.set(
[
"authentication",
"radius",
"server",
radius_server,
"acct-port",
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"
self.set(
["authentication", "radius", "dynamic-author", "server", coa_server]
)
self.set(["authentication", "radius", "dynamic-author", "key", coa_key])
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])
# commit changes
self.cli_commit()
# Validate configuration values
conf = ConfigParser(allow_no_value=True, delimiters="=", strict=False)
conf.read(self._config_file)
# basic verification
self.verify(conf)
# check auth
self.assertTrue(conf["radius"].getboolean("verbose"))
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")
self.assertEqual(
conf["radius"]["dae-server"], f"{coa_server}:1700,{coa_key}"
)
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"acct-port={radius_port_acc}", server[3])
self.assertEqual(f"req-limit=0", server[4])
self.assertEqual(f"fail-time=0", server[5])
#
# Disable Radius Accounting
#
self.delete(
["authentication", "radius", "server", radius_server, "acct-port"]
)
self.set(
[
"authentication",
"radius",
"server",
radius_server,
"disable-accounting",
]
)
# commit changes
self.cli_commit()
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])
def test_accel_ipv4_pool(self):
self.basic_config(is_gateway=False, is_client_pool=False)
gateway = "192.0.2.1"
subnet = "172.16.0.0/24"
first_pool = "POOL1"
second_pool = "POOL2"
range = "192.0.2.10-192.0.2.20"
range_config = "192.0.2.10-20"
self.set(["gateway-address", gateway])
self.set(["client-ip-pool", first_pool, "range", subnet])
self.set(["client-ip-pool", first_pool, "next-pool", second_pool])
self.set(["client-ip-pool", second_pool, "range", range])
self.set(["default-pool", first_pool])
# commit changes
self.cli_commit()
# Validate configuration values
conf = ConfigParser(allow_no_value=True, delimiters="=", strict=False)
conf.read(self._config_file)
self.assertEqual(
f"{first_pool},next={second_pool}", conf["ip-pool"][f"{subnet},name"]
)
self.assertEqual(second_pool, conf["ip-pool"][f"{range_config},name"])
self.assertEqual(gateway, conf["ip-pool"]["gw-ip-address"])
self.assertEqual(first_pool, conf[self._protocol_section]["ip-pool"])
def test_accel_next_pool(self):
# T5099 required specific order
self.basic_config(is_gateway=False, is_client_pool=False)
gateway = "192.0.2.1"
first_pool = "VyOS-pool1"
first_subnet = "192.0.2.0/25"
second_pool = "Vyos-pool2"
second_subnet = "203.0.113.0/25"
third_pool = "Vyos-pool3"
third_subnet = "198.51.100.0/24"
self.set(["gateway-address", gateway])
self.set(["client-ip-pool", first_pool, "range", first_subnet])
self.set(["client-ip-pool", first_pool, "next-pool", second_pool])
self.set(["client-ip-pool", second_pool, "range", second_subnet])
self.set(["client-ip-pool", second_pool, "next-pool", third_pool])
self.set(["client-ip-pool", third_pool, "range", third_subnet])
# commit changes
self.cli_commit()
config = self.getConfig("ip-pool")
pool_config = f"""gw-ip-address={gateway}
{third_subnet},name={third_pool}
{second_subnet},name={second_pool},next={third_pool}
{first_subnet},name={first_pool},next={second_pool}"""
self.assertIn(pool_config, config)
+
+ def test_accel_ipv6_pool(self):
+ # Test configuration of IPv6 client pools
+ self.basic_config(is_gateway=False, is_client_pool=False)
+
+ # Enable IPv6
+ allow_ipv6 = 'allow'
+ self.set(['ppp-options', 'ipv6', allow_ipv6])
+
+ pool_name = 'ipv6_test_pool'
+ prefix_1 = '2001:db8:fffe::/56'
+ prefix_mask = '64'
+ prefix_2 = '2001:db8:ffff::/56'
+ client_prefix_1 = f'{prefix_1},{prefix_mask}'
+ client_prefix_2 = f'{prefix_2},{prefix_mask}'
+ self.set(
+ ['client-ipv6-pool', pool_name, 'prefix', prefix_1, 'mask',
+ prefix_mask])
+ self.set(
+ ['client-ipv6-pool', pool_name, 'prefix', prefix_2, 'mask',
+ prefix_mask])
+
+ delegate_1_prefix = '2001:db8:fff1::/56'
+ delegate_2_prefix = '2001:db8:fff2::/56'
+ delegate_mask = '64'
+ self.set(
+ ['client-ipv6-pool', pool_name, 'delegate', delegate_1_prefix,
+ 'delegation-prefix', delegate_mask])
+ self.set(
+ ['client-ipv6-pool', pool_name, 'delegate', delegate_2_prefix,
+ 'delegation-prefix', delegate_mask])
+
+ # commit changes
+ self.cli_commit()
+
+ # Validate configuration values
+ conf = ConfigParser(allow_no_value=True, delimiters='=',
+ strict=False)
+ conf.read(self._config_file)
+
+ for tmp in ['ipv6pool', 'ipv6_nd', 'ipv6_dhcp']:
+ self.assertEqual(conf['modules'][tmp], None)
+
+ self.assertEqual(conf['ppp']['ipv6'], allow_ipv6)
+
+ config = self.getConfig("ipv6-pool")
+ pool_config = f"""{client_prefix_1},name={pool_name}
+{client_prefix_2},name={pool_name}
+delegate={delegate_1_prefix},{delegate_mask},name={pool_name}
+delegate={delegate_2_prefix},{delegate_mask},name={pool_name}"""
+ self.assertIn(pool_config, config)
diff --git a/smoketest/scripts/cli/test_service_ipoe-server.py b/smoketest/scripts/cli/test_service_ipoe-server.py
index 6e95b3bd1..cec6adb09 100755
--- a/smoketest/scripts/cli/test_service_ipoe-server.py
+++ b/smoketest/scripts/cli/test_service_ipoe-server.py
@@ -1,193 +1,232 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2022-2023 VyOS maintainers and contributors
+# Copyright (C) 2022-2024 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 re
import unittest
from collections import OrderedDict
from base_accel_ppp_test import BasicAccelPPPTest
from vyos.configsession import ConfigSessionError
from vyos.utils.process import cmd
from configparser import ConfigParser
from configparser import RawConfigParser
ac_name = "ACN"
interface = "eth0"
class MultiOrderedDict(OrderedDict):
# Accel-ppp has duplicate keys in config file (gw-ip-address)
# This class is used to define dictionary which can contain multiple values
# in one key.
def __setitem__(self, key, value):
if isinstance(value, list) and key in self:
self[key].extend(value)
else:
super(OrderedDict, self).__setitem__(key, value)
class TestServiceIPoEServer(BasicAccelPPPTest.TestCase):
@classmethod
def setUpClass(cls):
cls._base_path = ["service", "ipoe-server"]
cls._config_file = "/run/accel-pppd/ipoe.conf"
cls._chap_secrets = "/run/accel-pppd/ipoe.chap-secrets"
cls._protocol_section = "ipoe"
# call base-classes classmethod
super(TestServiceIPoEServer, cls).setUpClass()
def verify(self, conf):
super().verify(conf)
# Validate configuration values
accel_modules = list(conf["modules"].keys())
self.assertIn("log_syslog", accel_modules)
self.assertIn("ipoe", accel_modules)
self.assertIn("shaper", accel_modules)
self.assertIn("ipv6pool", accel_modules)
self.assertIn("ipv6_nd", accel_modules)
self.assertIn("ipv6_dhcp", accel_modules)
self.assertIn("ippool", accel_modules)
def initial_gateway_config(self):
self._gateway = "192.0.2.1/24"
super().initial_gateway_config()
def initial_auth_config(self):
self.set(["authentication", "mode", "noauth"])
def basic_protocol_specific_config(self):
self.set(["interface", interface, "client-subnet", "192.168.0.0/24"])
def test_accel_local_authentication(self):
mac_address = "08:00:27:2f:d8:06"
self.set(["authentication", "interface", interface, "mac", mac_address])
self.set(["authentication", "mode", "local"])
# No IPoE interface configured
with self.assertRaises(ConfigSessionError):
self.cli_commit()
# Test configuration of local authentication for PPPoE server
self.basic_config()
# Rewrite authentication from basic_config
self.set(["authentication", "interface", interface, "mac", mac_address])
self.set(["authentication", "mode", "local"])
# commit changes
self.cli_commit()
# Validate configuration values
conf = ConfigParser(allow_no_value=True, delimiters="=", strict=False)
conf.read(self._config_file)
# check proper path to chap-secrets file
self.assertEqual(conf["chap-secrets"]["chap-secrets"], self._chap_secrets)
accel_modules = list(conf["modules"].keys())
self.assertIn("chap-secrets", accel_modules)
# basic verification
self.verify(conf)
# check local users
tmp = cmd(f"sudo cat {self._chap_secrets}")
regex = f"{interface}\s+\*\s+{mac_address}\s+\*"
tmp = re.findall(regex, tmp)
self.assertTrue(tmp)
def test_accel_ipv4_pool(self):
self.basic_config(is_gateway=False, is_client_pool=False)
gateway = ["172.16.0.1/25", "192.0.2.1/24"]
subnet = "172.16.0.0/24"
first_pool = "POOL1"
second_pool = "POOL2"
range = "192.0.2.10-192.0.2.20"
range_config = "192.0.2.10-20"
for gw in gateway:
self.set(["gateway-address", gw])
self.set(["client-ip-pool", first_pool, "range", subnet])
self.set(["client-ip-pool", first_pool, "next-pool", second_pool])
self.set(["client-ip-pool", second_pool, "range", range])
self.set(["default-pool", first_pool])
# commit changes
self.cli_commit()
# Validate configuration values
conf = RawConfigParser(
allow_no_value=True,
delimiters="=",
strict=False,
dict_type=MultiOrderedDict,
)
conf.read(self._config_file)
self.assertIn(
f"{first_pool},next={second_pool}", conf["ip-pool"][f"{subnet},name"]
)
self.assertIn(second_pool, conf["ip-pool"][f"{range_config},name"])
gw_pool_config_list = conf.get("ip-pool", "gw-ip-address")
gw_ipoe_config_list = conf.get(self._protocol_section, "gw-ip-address")
for gw in gateway:
self.assertIn(gw.split("/")[0], gw_pool_config_list)
self.assertIn(gw, gw_ipoe_config_list)
self.assertIn(first_pool, conf[self._protocol_section]["ip-pool"])
def test_accel_next_pool(self):
self.basic_config(is_gateway=False, is_client_pool=False)
first_pool = "VyOS-pool1"
first_subnet = "192.0.2.0/25"
first_gateway = "192.0.2.1/24"
second_pool = "Vyos-pool2"
second_subnet = "203.0.113.0/25"
second_gateway = "203.0.113.1/24"
third_pool = "Vyos-pool3"
third_subnet = "198.51.100.0/24"
third_gateway = "198.51.100.1/24"
self.set(["gateway-address", f"{first_gateway}"])
self.set(["gateway-address", f"{second_gateway}"])
self.set(["gateway-address", f"{third_gateway}"])
self.set(["client-ip-pool", first_pool, "range", first_subnet])
self.set(["client-ip-pool", first_pool, "next-pool", second_pool])
self.set(["client-ip-pool", second_pool, "range", second_subnet])
self.set(["client-ip-pool", second_pool, "next-pool", third_pool])
self.set(["client-ip-pool", third_pool, "range", third_subnet])
# commit changes
self.cli_commit()
config = self.getConfig("ip-pool")
# T5099 required specific order
pool_config = f"""gw-ip-address={first_gateway.split('/')[0]}
gw-ip-address={second_gateway.split('/')[0]}
gw-ip-address={third_gateway.split('/')[0]}
{third_subnet},name={third_pool}
{second_subnet},name={second_pool},next={third_pool}
{first_subnet},name={first_pool},next={second_pool}"""
self.assertIn(pool_config, config)
+ def test_accel_ipv6_pool(self):
+ # Test configuration of IPv6 client pools
+ self.basic_config(is_gateway=False, is_client_pool=False)
+
+ pool_name = 'ipv6_test_pool'
+ prefix_1 = '2001:db8:fffe::/56'
+ prefix_mask = '64'
+ prefix_2 = '2001:db8:ffff::/56'
+ client_prefix_1 = f'{prefix_1},{prefix_mask}'
+ client_prefix_2 = f'{prefix_2},{prefix_mask}'
+ self.set(['client-ipv6-pool', pool_name, 'prefix', prefix_1, 'mask',
+ prefix_mask])
+ self.set(['client-ipv6-pool', pool_name, 'prefix', prefix_2, 'mask',
+ prefix_mask])
+
+ delegate_1_prefix = '2001:db8:fff1::/56'
+ delegate_2_prefix = '2001:db8:fff2::/56'
+ delegate_mask = '64'
+ self.set(['client-ipv6-pool', pool_name, 'delegate', delegate_1_prefix,
+ 'delegation-prefix', delegate_mask])
+ self.set(['client-ipv6-pool', pool_name, 'delegate', delegate_2_prefix,
+ 'delegation-prefix', delegate_mask])
+
+ # commit changes
+ self.cli_commit()
+
+ # Validate configuration values
+ conf = ConfigParser(allow_no_value=True, delimiters='=', strict=False)
+ conf.read(self._config_file)
+
+ for tmp in ['ipv6pool', 'ipv6_nd', 'ipv6_dhcp']:
+ self.assertEqual(conf['modules'][tmp], None)
+
+ config = self.getConfig("ipv6-pool")
+ pool_config = f"""{client_prefix_1},name={pool_name}
+{client_prefix_2},name={pool_name}
+delegate={delegate_1_prefix},{delegate_mask},name={pool_name}
+delegate={delegate_2_prefix},{delegate_mask},name={pool_name}"""
+ self.assertIn(pool_config, config)
if __name__ == "__main__":
unittest.main(verbosity=2)
diff --git a/smoketest/scripts/cli/test_service_pppoe-server.py b/smoketest/scripts/cli/test_service_pppoe-server.py
index fa3bb87db..11d5b8b78 100755
--- a/smoketest/scripts/cli/test_service_pppoe-server.py
+++ b/smoketest/scripts/cli/test_service_pppoe-server.py
@@ -1,235 +1,212 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2022-2023 VyOS maintainers and contributors
+# Copyright (C) 2022-2024 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 unittest
from base_accel_ppp_test import BasicAccelPPPTest
from configparser import ConfigParser
from vyos.utils.file import read_file
from vyos.template import range_to_regex
local_if = ['interfaces', 'dummy', 'dum667']
ac_name = 'ACN'
interface = 'eth0'
class TestServicePPPoEServer(BasicAccelPPPTest.TestCase):
@classmethod
def setUpClass(cls):
cls._base_path = ['service', 'pppoe-server']
cls._config_file = '/run/accel-pppd/pppoe.conf'
cls._chap_secrets = '/run/accel-pppd/pppoe.chap-secrets'
cls._protocol_section = 'pppoe'
# call base-classes classmethod
super(TestServicePPPoEServer, cls).setUpClass()
def tearDown(self):
self.cli_delete(local_if)
super().tearDown()
def verify(self, conf):
mtu = '1492'
# validate some common values in the configuration
for tmp in ['log_syslog', 'pppoe', 'ippool',
'auth_mschap_v2', 'auth_mschap_v1', 'auth_chap_md5',
'auth_pap', 'shaper']:
# Settings without values provide None
self.assertEqual(conf['modules'][tmp], None)
# check Access Concentrator setting
self.assertTrue(conf['pppoe']['ac-name'] == ac_name)
self.assertTrue(conf['pppoe'].getboolean('verbose'))
self.assertTrue(conf['pppoe']['interface'], interface)
# check ppp
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'], '30')
self.assertEqual(conf['ppp']['lcp-echo-timeout'], '0')
self.assertEqual(conf['ppp']['lcp-echo-failure'], '3')
super().verify(conf)
def basic_protocol_specific_config(self):
self.cli_set(local_if + ['address', '192.0.2.1/32'])
self.set(['access-concentrator', ac_name])
self.set(['interface', interface])
def test_pppoe_server_ppp_options(self):
# Test configuration of local authentication for PPPoE server
self.basic_config()
# other settings
mppe = 'require'
self.set(['ppp-options', 'ccp'])
self.set(['ppp-options', 'mppe', mppe])
self.set(['limits', 'connection-limit', '20/min'])
# min-mtu
min_mtu = '1400'
self.set(['ppp-options', 'min-mtu', min_mtu])
# mru
mru = '9000'
self.set(['ppp-options', 'mru', mru])
# interface-cache
interface_cache = '128000'
self.set(['ppp-options', 'interface-cache', interface_cache])
+ # 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])
# commit changes
self.cli_commit()
# Validate configuration values
conf = ConfigParser(allow_no_value=True, delimiters='=')
conf.read(self._config_file)
# basic verification
self.verify(conf)
self.assertEqual(conf['chap-secrets']['gw-ip-address'], self._gateway)
# check ppp
self.assertEqual(conf['ppp']['mppe'], mppe)
self.assertEqual(conf['ppp']['min-mtu'], min_mtu)
self.assertEqual(conf['ppp']['mru'], mru)
self.assertTrue(conf['ppp'].getboolean('ccp'))
# check other settings
self.assertEqual(conf['connlimit']['limit'], '20/min')
# check interface-cache
self.assertEqual(conf['ppp']['unit-cache'], interface_cache)
+ #check ipv6
+ 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'))
+
def test_pppoe_server_authentication_protocols(self):
# Test configuration of local authentication for PPPoE server
self.basic_config()
# 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)
conf.read(self._config_file)
self.assertEqual(conf['modules']['auth_mschap_v2'], None)
def test_pppoe_server_shaper(self):
fwmark = '223'
limiter = 'tbf'
self.basic_config()
self.set(['shaper', 'fwmark', fwmark])
# commit changes
self.cli_commit()
# Validate configuration values
conf = ConfigParser(allow_no_value=True, delimiters='=')
conf.read(self._config_file)
# basic verification
self.verify(conf)
self.assertEqual(conf['shaper']['fwmark'], fwmark)
self.assertEqual(conf['shaper']['down-limiter'], limiter)
- def test_pppoe_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])
-
- 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)
-
- 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}')
-
def test_accel_radius_authentication(self):
radius_called_sid = 'ifname:mac'
self.set(['authentication', 'radius', 'called-sid-format', radius_called_sid])
# run common tests
super().test_accel_radius_authentication()
# Validate configuration values
conf = ConfigParser(allow_no_value=True, delimiters='=')
conf.read(self._config_file)
# Validate configuration
self.assertEqual(conf['pppoe']['called-sid'], radius_called_sid)
def test_pppoe_server_vlan(self):
vlans = ['100', '200', '300-310']
# Test configuration of local authentication for PPPoE server
self.basic_config()
for vlan in vlans:
self.set(['interface', interface, 'vlan', vlan])
# commit changes
self.cli_commit()
# Validate configuration values
config = read_file(self._config_file)
for vlan in vlans:
tmp = range_to_regex(vlan)
self.assertIn(f'interface=re:^{interface}\.{tmp}$', config)
tmp = ','.join(vlans)
self.assertIn(f'vlan-mon={interface},{tmp}', config)
if __name__ == '__main__':
unittest.main(verbosity=2)
diff --git a/smoketest/scripts/cli/test_vpn_l2tp.py b/smoketest/scripts/cli/test_vpn_l2tp.py
index 5b3e419bd..129a9c602 100755
--- a/smoketest/scripts/cli/test_vpn_l2tp.py
+++ b/smoketest/scripts/cli/test_vpn_l2tp.py
@@ -1,135 +1,111 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2023 VyOS maintainers and contributors
+# Copyright (C) 2023-2024 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 re
import unittest
from base_accel_ppp_test import BasicAccelPPPTest
from configparser import ConfigParser
from vyos.utils.process import cmd
class TestVPNL2TPServer(BasicAccelPPPTest.TestCase):
@classmethod
def setUpClass(cls):
cls._base_path = ['vpn', 'l2tp', 'remote-access']
cls._config_file = '/run/accel-pppd/l2tp.conf'
cls._chap_secrets = '/run/accel-pppd/l2tp.chap-secrets'
cls._protocol_section = 'l2tp'
# call base-classes classmethod
super(TestVPNL2TPServer, cls).setUpClass()
@classmethod
def tearDownClass(cls):
super(TestVPNL2TPServer, cls).tearDownClass()
def basic_protocol_specific_config(self):
pass
def test_l2tp_server_ppp_options(self):
# Test configuration of local authentication for PPPoE server
self.basic_config()
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])
+ 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])
+
# commit changes
self.cli_commit()
# Validate configuration values
conf = ConfigParser(allow_no_value=True, delimiters='=')
conf.read(self._config_file)
# basic verification
self.verify(conf)
# 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)
+ 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'))
+
def test_l2tp_server_authentication_protocols(self):
# Test configuration of local authentication for PPPoE server
self.basic_config()
# 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)
conf.read(self._config_file)
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])
-
- 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)
-
- 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/smoketest/scripts/cli/test_vpn_pptp.py b/smoketest/scripts/cli/test_vpn_pptp.py
index 0d9ea312e..f3fce822b 100755
--- a/smoketest/scripts/cli/test_vpn_pptp.py
+++ b/smoketest/scripts/cli/test_vpn_pptp.py
@@ -1,223 +1,227 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2023 VyOS maintainers and contributors
+# Copyright (C) 2023-2024 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 re
import unittest
from configparser import ConfigParser
from vyos.utils.process import cmd
from base_accel_ppp_test import BasicAccelPPPTest
from vyos.template import is_ipv4
class TestVPNPPTPServer(BasicAccelPPPTest.TestCase):
@classmethod
def setUpClass(cls):
cls._base_path = ['vpn', 'pptp', 'remote-access']
cls._config_file = '/run/accel-pppd/pptp.conf'
cls._chap_secrets = '/run/accel-pppd/pptp.chap-secrets'
cls._protocol_section = 'pptp'
# call base-classes classmethod
super(TestVPNPPTPServer, cls).setUpClass()
@classmethod
def tearDownClass(cls):
super(TestVPNPPTPServer, cls).tearDownClass()
def basic_protocol_specific_config(self):
pass
def test_accel_name_servers(self):
# Verify proper Name-Server configuration for IPv4
self.basic_config()
nameserver = ["192.0.2.1", "192.0.2.2"]
for ns in nameserver:
self.set(["name-server", ns])
# commit changes
self.cli_commit()
# Validate configuration values
conf = ConfigParser(allow_no_value=True, delimiters="=", strict=False)
conf.read(self._config_file)
# IPv4 and IPv6 nameservers must be checked individually
for ns in nameserver:
self.assertIn(ns, [conf["dns"]["dns1"], conf["dns"]["dns2"]])
def test_accel_local_authentication(self):
# Test configuration of local authentication
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,
]
)
# commit changes
self.cli_commit()
# Validate configuration values
conf = ConfigParser(allow_no_value=True, delimiters="=", strict=False)
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"
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"
tmp = re.findall(regex, tmp)
self.assertTrue(tmp)
def test_accel_radius_authentication(self):
# Test configuration of RADIUS authentication for PPPoE server
self.basic_config()
radius_server = "192.0.2.22"
radius_key = "secretVyOS"
radius_port = "2000"
radius_port_acc = "3000"
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,
]
)
self.set(
[
"authentication",
"radius",
"server",
radius_server,
"acct-port",
radius_port_acc,
]
)
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])
# commit changes
self.cli_commit()
# Validate configuration values
conf = ConfigParser(allow_no_value=True, delimiters="=", strict=False)
conf.read(self._config_file)
# basic verification
self.verify(conf)
# check auth
self.assertTrue(conf["radius"].getboolean("verbose"))
self.assertEqual(conf["radius"]["acct-timeout"], "30")
self.assertEqual(conf["radius"]["timeout"], "30")
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"acct-port={radius_port_acc}", server[3])
self.assertEqual(f"req-limit=0", server[4])
self.assertEqual(f"fail-time=0", server[5])
#
# Disable Radius Accounting
#
self.delete(["authentication", "radius", "server", radius_server, "acct-port"])
self.set(
[
"authentication",
"radius",
"server",
radius_server,
"disable-accounting",
]
)
# commit changes
self.cli_commit()
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])
+ @unittest.skip("IPv6 is not implemented in PPTP")
+ def test_accel_ipv6_pool(self):
+ pass
+
if __name__ == '__main__':
unittest.main(verbosity=2)
diff --git a/src/conf_mode/service_ipoe-server.py b/src/conf_mode/service_ipoe-server.py
index 36f00dec5..6df6f3dc7 100755
--- a/src/conf_mode/service_ipoe-server.py
+++ b/src/conf_mode/service_ipoe-server.py
@@ -1,121 +1,118 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2018-2023 VyOS maintainers and contributors
+# Copyright (C) 2018-2024 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 exit
from vyos.config import Config
from vyos.configdict import get_accel_dict
from vyos.configverify import verify_interface_exists
from vyos.template import render
from vyos.utils.process import call
from vyos.utils.dict import dict_search
from vyos.accel_ppp_util import get_pools_in_order
from vyos.accel_ppp_util import verify_accel_ppp_ip_pool
from vyos import ConfigError
from vyos import airbag
airbag.enable()
ipoe_conf = '/run/accel-pppd/ipoe.conf'
ipoe_chap_secrets = '/run/accel-pppd/ipoe.chap-secrets'
def get_config(config=None):
if config:
conf = config
else:
conf = Config()
base = ['service', 'ipoe-server']
if not conf.exists(base):
return None
# retrieve common dictionary keys
ipoe = get_accel_dict(conf, base, ipoe_chap_secrets)
if dict_search('client_ip_pool', ipoe):
# Multiple named pools require ordered values T5099
ipoe['ordered_named_pools'] = get_pools_in_order(dict_search('client_ip_pool', ipoe))
ipoe['server_type'] = 'ipoe'
return ipoe
def verify(ipoe):
if not ipoe:
return None
if 'interface' not in ipoe:
raise ConfigError('No IPoE interface configured')
for interface, iface_config in ipoe['interface'].items():
verify_interface_exists(interface)
if 'client_subnet' in iface_config and 'vlan' in iface_config:
raise ConfigError('Option "client-subnet" incompatible with "vlan"!'
'Use "ipoe client-ip-pool" instead.')
verify_accel_ppp_ip_pool(ipoe)
if dict_search('authentication.mode', ipoe) == 'radius':
if not dict_search('authentication.radius.server', ipoe):
raise ConfigError('RADIUS authentication requires at least one server')
for server in dict_search('authentication.radius.server', ipoe):
radius_config = ipoe['authentication']['radius']['server'][server]
if 'key' not in radius_config:
raise ConfigError(f'Missing RADIUS secret key for server "{server}"')
- if 'client_ipv6_pool' in ipoe:
- if 'delegate' in ipoe['client_ipv6_pool'] and 'prefix' not in ipoe['client_ipv6_pool']:
- raise ConfigError('IPoE IPv6 deletate-prefix requires IPv6 prefix to be configured!')
return None
def generate(ipoe):
if not ipoe:
return None
render(ipoe_conf, 'accel-ppp/ipoe.config.j2', ipoe)
if dict_search('authentication.mode', ipoe) == 'local':
render(ipoe_chap_secrets, 'accel-ppp/chap-secrets.ipoe.j2',
ipoe, permission=0o640)
return None
def apply(ipoe):
systemd_service = 'accel-ppp@ipoe.service'
if ipoe == None:
call(f'systemctl stop {systemd_service}')
for file in [ipoe_conf, ipoe_chap_secrets]:
if os.path.exists(file):
os.unlink(file)
return None
call(f'systemctl reload-or-restart {systemd_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/conf_mode/service_pppoe-server.py b/src/conf_mode/service_pppoe-server.py
index 7c624f034..31299a15c 100755
--- a/src/conf_mode/service_pppoe-server.py
+++ b/src/conf_mode/service_pppoe-server.py
@@ -1,125 +1,126 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2018-2023 VyOS maintainers and contributors
+# Copyright (C) 2018-2024 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 exit
from vyos.config import Config
from vyos.configdict import get_accel_dict
from vyos.configdict import is_node_changed
from vyos.configverify import verify_interface_exists
from vyos.template import render
from vyos.utils.process import call
from vyos.utils.dict import dict_search
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 import ConfigError
from vyos import airbag
airbag.enable()
pppoe_conf = r'/run/accel-pppd/pppoe.conf'
pppoe_chap_secrets = r'/run/accel-pppd/pppoe.chap-secrets'
def get_config(config=None):
if config:
conf = config
else:
conf = Config()
base = ['service', 'pppoe-server']
if not conf.exists(base):
return None
# retrieve common dictionary keys
pppoe = get_accel_dict(conf, base, pppoe_chap_secrets)
if dict_search('client_ip_pool', pppoe):
# Multiple named pools require ordered values T5099
pppoe['ordered_named_pools'] = get_pools_in_order(dict_search('client_ip_pool', pppoe))
# reload-or-restart does not implemented in accel-ppp
# use this workaround until it will be implemented
# https://phabricator.accel-ppp.org/T3
conditions = [is_node_changed(conf, base + ['client-ip-pool']),
is_node_changed(conf, base + ['client-ipv6-pool']),
is_node_changed(conf, base + ['interface'])]
if any(conditions):
pppoe.update({'restart_required': {}})
pppoe['server_type'] = 'pppoe'
return pppoe
def verify(pppoe):
if not pppoe:
return None
verify_accel_ppp_base_service(pppoe)
if 'wins_server' in pppoe and len(pppoe['wins_server']) > 2:
raise ConfigError('Not more then two WINS name-servers can be configured')
if 'interface' not in pppoe:
raise ConfigError('At least one listen interface must be defined!')
# Check is interface exists in the system
for interface in pppoe['interface']:
verify_interface_exists(interface)
verify_accel_ppp_ip_pool(pppoe)
if dict_search('authentication.radius.dynamic_author.server', pppoe):
if not dict_search('authentication.radius.dynamic_author.key', pppoe):
raise ConfigError('DA/CoE server key required!')
+
return None
def generate(pppoe):
if not pppoe:
return None
render(pppoe_conf, 'accel-ppp/pppoe.config.j2', pppoe)
if dict_search('authentication.mode', pppoe) == 'local':
render(pppoe_chap_secrets, 'accel-ppp/chap-secrets.config_dict.j2',
pppoe, permission=0o640)
return None
def apply(pppoe):
systemd_service = 'accel-ppp@pppoe.service'
if not pppoe:
call(f'systemctl stop {systemd_service}')
for file in [pppoe_conf, pppoe_chap_secrets]:
if os.path.exists(file):
os.unlink(file)
return None
if 'restart_required' in pppoe:
call(f'systemctl restart {systemd_service}')
else:
call(f'systemctl reload-or-restart {systemd_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/conf_mode/vpn_l2tp.py b/src/conf_mode/vpn_l2tp.py
index 1a91951b4..b569ca140 100755
--- a/src/conf_mode/vpn_l2tp.py
+++ b/src/conf_mode/vpn_l2tp.py
@@ -1,123 +1,117 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2019-2023 VyOS maintainers and contributors
+# Copyright (C) 2019-2024 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 exit
from vyos.config import Config
from vyos.configdict import get_accel_dict
from vyos.template import render
from vyos.utils.process import call
from vyos.utils.dict import dict_search
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'
def get_config(config=None):
if config:
conf = config
else:
conf = Config()
base = ['vpn', 'l2tp', 'remote-access']
if not conf.exists(base):
return None
# 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))
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')
l2tp['server_type'] = 'l2tp'
return l2tp
def verify(l2tp):
if not l2tp:
return None
verify_accel_ppp_base_service(l2tp)
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 dict_search('authentication.mode', l2tp) in ['local', 'noauth']:
- if not dict_search('client_ip_pool', l2tp) and not dict_search('client_ipv6_pool', l2tp):
- raise ConfigError(
- "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")
-
verify_accel_ppp_ip_pool(l2tp)
+
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
def generate(l2tp):
if not l2tp:
return None
render(l2tp_conf, 'accel-ppp/l2tp.config.j2', l2tp)
if dict_search('authentication.mode', l2tp) == 'local':
render(l2tp_chap_secrets, 'accel-ppp/chap-secrets.config_dict.j2',
l2tp, permission=0o640)
return None
def apply(l2tp):
if not l2tp:
call('systemctl stop accel-ppp@l2tp.service')
for file in [l2tp_chap_secrets, l2tp_conf]:
if os.path.exists(file):
os.unlink(file)
return None
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/conf_mode/vpn_pptp.py b/src/conf_mode/vpn_pptp.py
index f769be39f..0629625bf 100755
--- a/src/conf_mode/vpn_pptp.py
+++ b/src/conf_mode/vpn_pptp.py
@@ -1,134 +1,128 @@
#!/usr/bin/env python3
#
# Copyright (C) 2018-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 exit
from vyos.config import Config
from vyos.template import render
from vyos.utils.process import call
from vyos.utils.dict import dict_search
from vyos.accel_ppp_util import verify_accel_ppp_ip_pool
from vyos.accel_ppp_util import get_pools_in_order
from vyos import ConfigError
from vyos.configdict import get_accel_dict
from vyos import airbag
airbag.enable()
pptp_conf = '/run/accel-pppd/pptp.conf'
pptp_chap_secrets = '/run/accel-pppd/pptp.chap-secrets'
def get_config(config=None):
if config:
conf = config
else:
conf = Config()
base = ['vpn', 'pptp', 'remote-access']
if not conf.exists(base):
return None
# retrieve common dictionary keys
pptp = get_accel_dict(conf, base, pptp_chap_secrets)
if dict_search('client_ip_pool', pptp):
# Multiple named pools require ordered values T5099
pptp['ordered_named_pools'] = get_pools_in_order(
dict_search('client_ip_pool', pptp))
pptp['chap_secrets_file'] = pptp_chap_secrets
pptp['server_type'] = 'pptp'
return pptp
def verify(pptp):
if not pptp:
return None
auth_mode = dict_search('authentication.mode', pptp)
if auth_mode == 'local':
if not dict_search('authentication.local_users', pptp):
raise ConfigError(
'PPTP local auth mode requires local users to be configured!')
for user in dict_search('authentication.local_users.username', pptp):
user_config = pptp['authentication']['local_users']['username'][
user]
if 'password' not in user_config:
raise ConfigError(f'Password required for local user "{user}"')
elif auth_mode == 'radius':
if not dict_search('authentication.radius.server', pptp):
raise ConfigError(
'RADIUS authentication requires at least one server')
for server in dict_search('authentication.radius.server', pptp):
radius_config = pptp['authentication']['radius']['server'][server]
if 'key' not in radius_config:
raise ConfigError(
f'Missing RADIUS secret key for server "{server}"')
- if auth_mode == 'local' or auth_mode == 'noauth':
- if not dict_search('client_ip_pool', pptp):
- raise ConfigError(
- 'PPTP local auth mode requires local client-ip-pool '
- 'to be configured!')
-
verify_accel_ppp_ip_pool(pptp)
if 'name_server' in pptp:
if len(pptp['name_server']) > 2:
raise ConfigError(
'Not more then two IPv4 DNS name-servers can be configured'
)
if 'wins_server' in pptp and len(pptp['wins_server']) > 2:
raise ConfigError(
'Not more then two WINS name-servers can be configured')
def generate(pptp):
if not pptp:
return None
render(pptp_conf, 'accel-ppp/pptp.config.j2', pptp)
if dict_search('authentication.mode', pptp) == 'local':
render(pptp_chap_secrets, 'accel-ppp/chap-secrets.config_dict.j2',
pptp, permission=0o640)
return None
def apply(pptp):
if not pptp:
call('systemctl stop accel-ppp@pptp.service')
for file in [pptp_conf, pptp_chap_secrets]:
if os.path.exists(file):
os.unlink(file)
return None
call('systemctl restart accel-ppp@pptp.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/conf_mode/vpn_sstp.py b/src/conf_mode/vpn_sstp.py
index 6bf9307e1..a84513a0f 100755
--- a/src/conf_mode/vpn_sstp.py
+++ b/src/conf_mode/vpn_sstp.py
@@ -1,170 +1,167 @@
#!/usr/bin/env python3
#
# Copyright (C) 2018-2024 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 exit
from vyos.config import Config
from vyos.configdict import get_accel_dict
from vyos.configdict import dict_merge
from vyos.pki import wrap_certificate
from vyos.pki import wrap_private_key
from vyos.template import render
from vyos.utils.process import call
from vyos.utils.network import check_port_availability
from vyos.utils.dict import dict_search
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.utils.network import is_listen_port_bind_service
from vyos.utils.file import write_file
from vyos import ConfigError
from vyos import airbag
airbag.enable()
cfg_dir = '/run/accel-pppd'
sstp_conf = '/run/accel-pppd/sstp.conf'
sstp_chap_secrets = '/run/accel-pppd/sstp.chap-secrets'
cert_file_path = os.path.join(cfg_dir, 'sstp-cert.pem')
cert_key_path = os.path.join(cfg_dir, 'sstp-cert.key')
ca_cert_file_path = os.path.join(cfg_dir, 'sstp-ca.pem')
def get_config(config=None):
if config:
conf = config
else:
conf = Config()
base = ['vpn', 'sstp']
if not conf.exists(base):
return None
# retrieve common dictionary keys
sstp = get_accel_dict(conf, base, sstp_chap_secrets, with_pki=True)
if dict_search('client_ip_pool', sstp):
# Multiple named pools require ordered values T5099
sstp['ordered_named_pools'] = get_pools_in_order(dict_search('client_ip_pool', sstp))
sstp['server_type'] = 'sstp'
return sstp
def verify(sstp):
if not sstp:
return None
port = sstp.get('port')
proto = 'tcp'
if check_port_availability('0.0.0.0', 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')
verify_accel_ppp_base_service(sstp)
-
- if 'client_ip_pool' not in sstp and 'client_ipv6_pool' not in sstp:
- raise ConfigError('Client IP subnet required')
-
verify_accel_ppp_ip_pool(sstp)
+
#
# SSL certificate checks
#
if not sstp['pki']:
raise ConfigError('PKI is not configured')
if 'ssl' not in sstp:
raise ConfigError('SSL missing on SSTP config')
ssl = sstp['ssl']
# CA
if 'ca_certificate' not in ssl:
raise ConfigError('SSL CA certificate missing on SSTP config')
ca_name = ssl['ca_certificate']
if ca_name not in sstp['pki']['ca']:
raise ConfigError('Invalid CA certificate on SSTP config')
if 'certificate' not in sstp['pki']['ca'][ca_name]:
raise ConfigError('Missing certificate data for CA certificate on SSTP config')
# Certificate
if 'certificate' not in ssl:
raise ConfigError('SSL certificate missing on SSTP config')
cert_name = ssl['certificate']
if cert_name not in sstp['pki']['certificate']:
raise ConfigError('Invalid certificate on SSTP config')
pki_cert = sstp['pki']['certificate'][cert_name]
if 'certificate' not in pki_cert:
raise ConfigError('Missing certificate data for certificate on SSTP config')
if 'private' not in pki_cert or 'key' not in pki_cert['private']:
raise ConfigError('Missing private key for certificate on SSTP config')
if 'password_protected' in pki_cert['private']:
raise ConfigError('Encrypted private key is not supported on SSTP config')
def generate(sstp):
if not sstp:
return None
# accel-cmd reload doesn't work so any change results in a restart of the daemon
render(sstp_conf, 'accel-ppp/sstp.config.j2', sstp)
cert_name = sstp['ssl']['certificate']
pki_cert = sstp['pki']['certificate'][cert_name]
ca_cert_name = sstp['ssl']['ca_certificate']
pki_ca = sstp['pki']['ca'][ca_cert_name]
write_file(cert_file_path, wrap_certificate(pki_cert['certificate']))
write_file(cert_key_path, wrap_private_key(pki_cert['private']['key']))
write_file(ca_cert_file_path, wrap_certificate(pki_ca['certificate']))
if dict_search('authentication.mode', sstp) == 'local':
render(sstp_chap_secrets, 'accel-ppp/chap-secrets.config_dict.j2',
sstp, permission=0o640)
else:
if os.path.exists(sstp_chap_secrets):
os.unlink(sstp_chap_secrets)
return sstp
def apply(sstp):
if not sstp:
call('systemctl stop accel-ppp@sstp.service')
for file in [sstp_chap_secrets, sstp_conf]:
if os.path.exists(file):
os.unlink(file)
return None
call('systemctl restart accel-ppp@sstp.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/ipoe-server/2-to-3 b/src/migration-scripts/ipoe-server/2-to-3
new file mode 100755
index 000000000..d4ae0a7ba
--- /dev/null
+++ b/src/migration-scripts/ipoe-server/2-to-3
@@ -0,0 +1,61 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2024 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/>.
+
+# Migrating to named ipv6 pools
+
+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 = ['service', 'ipoe-server']
+pool_base = base + ['client-ipv6-pool']
+if not config.exists(base):
+ exit(0)
+
+if not config.exists(pool_base):
+ exit(0)
+
+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)
+
+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)
diff --git a/src/migration-scripts/l2tp/6-to-7 b/src/migration-scripts/l2tp/6-to-7
new file mode 100755
index 000000000..f49c4ab08
--- /dev/null
+++ b/src/migration-scripts/l2tp/6-to-7
@@ -0,0 +1,60 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2024 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/>.
+
+# Migrating to named ipv6 pools
+
+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']
+pool_base = base + ['client-ipv6-pool']
+if not config.exists(base):
+ exit(0)
+
+if not config.exists(pool_base):
+ exit(0)
+
+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)
+
+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)
diff --git a/src/migration-scripts/pppoe-server/7-to-8 b/src/migration-scripts/pppoe-server/7-to-8
new file mode 100755
index 000000000..b0d9bb464
--- /dev/null
+++ b/src/migration-scripts/pppoe-server/7-to-8
@@ -0,0 +1,61 @@
+#!/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/>.
+
+# Migrating to named ipv6 pools
+
+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 = ['service', 'pppoe-server']
+pool_base = base + ['client-ipv6-pool']
+if not config.exists(base):
+ exit(0)
+
+if not config.exists(pool_base):
+ exit(0)
+
+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)
+
+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)
diff --git a/src/migration-scripts/sstp/5-to-6 b/src/migration-scripts/sstp/5-to-6
new file mode 100755
index 000000000..bac9975b2
--- /dev/null
+++ b/src/migration-scripts/sstp/5-to-6
@@ -0,0 +1,62 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2024 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/>.
+
+# Migrating to named ipv6 pools
+
+import os
+import pprint
+
+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', 'sstp']
+pool_base = base + ['client-ipv6-pool']
+if not config.exists(base):
+ exit(0)
+
+if not config.exists(pool_base):
+ exit(0)
+
+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)
+
+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)

File Metadata

Mime Type
text/x-diff
Expires
Fri, Nov 6, 6:53 AM (7 h, 33 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
4643785
Default Alt Text
(147 KB)

Event Timeline