summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/templates/conntrack/nftables-helpers.j26
-rw-r--r--data/templates/router-advert/radvd.conf.j27
-rw-r--r--debian/control3
-rw-r--r--interface-definitions/include/firewall/conntrack-helper.xml.i6
-rw-r--r--interface-definitions/nat64.xml.in2
-rw-r--r--interface-definitions/nat66.xml.in2
-rw-r--r--interface-definitions/pki.xml.in2
-rw-r--r--interface-definitions/policy.xml.in12
-rw-r--r--interface-definitions/service_config-sync.xml.in394
-rw-r--r--interface-definitions/service_router-advert.xml.in30
-rw-r--r--interface-definitions/system_conntrack.xml.in6
-rw-r--r--op-mode-definitions/force-commit-archive.xml.in13
-rw-r--r--op-mode-definitions/pki.xml.in2
-rw-r--r--op-mode-definitions/show-log.xml.in4
-rw-r--r--python/vyos/config_mgmt.py3
-rw-r--r--python/vyos/configtree.py24
-rwxr-xr-xsmoketest/scripts/cli/test_backslash_escape.py68
-rwxr-xr-xsmoketest/scripts/cli/test_policy.py1
-rwxr-xr-xsmoketest/scripts/cli/test_service_router-advert.py28
-rwxr-xr-xsmoketest/scripts/cli/test_system_conntrack.py8
-rwxr-xr-xsrc/conf_mode/firewall.py12
-rwxr-xr-xsrc/conf_mode/service_router-advert.py18
-rwxr-xr-xsrc/conf_mode/system_conntrack.py7
-rwxr-xr-xsrc/helpers/vyos_config_sync.py26
-rwxr-xr-xsrc/migration-scripts/policy/1-to-218
-rwxr-xr-xsrc/op_mode/conntrack.py3
26 files changed, 646 insertions, 59 deletions
diff --git a/data/templates/conntrack/nftables-helpers.j2 b/data/templates/conntrack/nftables-helpers.j2
index 433931162..63a0cc855 100644
--- a/data/templates/conntrack/nftables-helpers.j2
+++ b/data/templates/conntrack/nftables-helpers.j2
@@ -31,6 +31,12 @@
}
{% endif %}
+{% if modules.rtsp is vyos_defined and ipv4 %}
+ ct helper rtsp_tcp {
+ type "rtsp" protocol tcp;
+ }
+{% endif %}
+
{% if modules.sip is vyos_defined %}
ct helper sip_tcp {
type "sip" protocol tcp;
diff --git a/data/templates/router-advert/radvd.conf.j2 b/data/templates/router-advert/radvd.conf.j2
index 4ef4751dd..97180d164 100644
--- a/data/templates/router-advert/radvd.conf.j2
+++ b/data/templates/router-advert/radvd.conf.j2
@@ -50,6 +50,13 @@ interface {{ iface }} {
{% endfor %}
};
{% endif %}
+{% if iface_config.nat64prefix is vyos_defined %}
+{% for nat64prefix, nat64prefix_options in iface_config.nat64prefix.items() %}
+ nat64prefix {{ nat64prefix }} {
+ AdvValidLifetime {{ nat64prefix_options.valid_lifetime }};
+ };
+{% endfor %}
+{% endif %}
{% if iface_config.prefix is vyos_defined %}
{% for prefix, prefix_options in iface_config.prefix.items() %}
prefix {{ prefix }} {
diff --git a/debian/control b/debian/control
index dddc4e14c..c5a60f660 100644
--- a/debian/control
+++ b/debian/control
@@ -256,6 +256,9 @@ Depends:
# For "nat64"
jool,
# End "nat64"
+# For "system conntrack modules rtsp"
+ nat-rtsp,
+# End "system conntrack modules rtsp"
# For "system ntp"
chrony,
# End "system ntp"
diff --git a/interface-definitions/include/firewall/conntrack-helper.xml.i b/interface-definitions/include/firewall/conntrack-helper.xml.i
index ee17f2c61..3ca1a0353 100644
--- a/interface-definitions/include/firewall/conntrack-helper.xml.i
+++ b/interface-definitions/include/firewall/conntrack-helper.xml.i
@@ -22,6 +22,10 @@
<description>Related traffic from NFS helper</description>
</valueHelp>
<valueHelp>
+ <format>rtsp</format>
+ <description>Related traffic from RTSP helper</description>
+ </valueHelp>
+ <valueHelp>
<format>sip</format>
<description>Related traffic from SIP helper</description>
</valueHelp>
@@ -34,7 +38,7 @@
<description>Related traffic from SQLNet helper</description>
</valueHelp>
<constraint>
- <regex>(ftp|h323|pptp|nfs|sip|tftp|sqlnet)</regex>
+ <regex>(ftp|h323|pptp|nfs|rtsp|sip|tftp|sqlnet)</regex>
</constraint>
<multi/>
</properties>
diff --git a/interface-definitions/nat64.xml.in b/interface-definitions/nat64.xml.in
index dfdd295d2..4b3c157cc 100644
--- a/interface-definitions/nat64.xml.in
+++ b/interface-definitions/nat64.xml.in
@@ -2,7 +2,7 @@
<interfaceDefinition>
<node name="nat64" owner="${vyos_conf_scripts_dir}/nat64.py">
<properties>
- <help>IPv6-to-IPv4 Network Address Translation (NAT64) Settings</help>
+ <help>Network Address Translation (NAT64) parameters</help>
<priority>501</priority>
</properties>
<children>
diff --git a/interface-definitions/nat66.xml.in b/interface-definitions/nat66.xml.in
index 1518de8bd..32d501cce 100644
--- a/interface-definitions/nat66.xml.in
+++ b/interface-definitions/nat66.xml.in
@@ -2,7 +2,7 @@
<interfaceDefinition>
<node name="nat66" owner="${vyos_conf_scripts_dir}/nat66.py">
<properties>
- <help>IPv6-to-IPv6 Network Prefix Translation (NAT66/NPT) Settings</help>
+ <help>Network Prefix Translation (NAT66/NPTv6) parameters</help>
<priority>500</priority>
</properties>
<children>
diff --git a/interface-definitions/pki.xml.in b/interface-definitions/pki.xml.in
index 7a0b073b4..b922771c1 100644
--- a/interface-definitions/pki.xml.in
+++ b/interface-definitions/pki.xml.in
@@ -2,7 +2,7 @@
<interfaceDefinition>
<node name="pki" owner="${vyos_conf_scripts_dir}/pki.py">
<properties>
- <help>VyOS PKI configuration</help>
+ <help>Public key infrastructure (PKI)</help>
<priority>300</priority>
</properties>
<children>
diff --git a/interface-definitions/policy.xml.in b/interface-definitions/policy.xml.in
index 0d82cd3f8..791fa1d87 100644
--- a/interface-definitions/policy.xml.in
+++ b/interface-definitions/policy.xml.in
@@ -1124,12 +1124,20 @@
<leafNode name="exclude">
<properties>
<help>Remove/exclude from the as-path attribute</help>
+ <completionHelp>
+ <list>all</list>
+ </completionHelp>
<valueHelp>
- <format>u32</format>
+ <format>u32:1-4294967295</format>
<description>AS number</description>
</valueHelp>
+ <valueHelp>
+ <format>all</format>
+ <description>Exclude all AS numbers from the as-path</description>
+ </valueHelp>
<constraint>
<validator name="as-number-list"/>
+ <regex>(all)</regex>
</constraint>
</properties>
</leafNode>
@@ -1137,7 +1145,7 @@
<properties>
<help>Prepend to the as-path</help>
<valueHelp>
- <format>u32</format>
+ <format>u32:1-4294967295</format>
<description>AS number</description>
</valueHelp>
<constraint>
diff --git a/interface-definitions/service_config-sync.xml.in b/interface-definitions/service_config-sync.xml.in
index 9955acfee..9e9dcdb69 100644
--- a/interface-definitions/service_config-sync.xml.in
+++ b/interface-definitions/service_config-sync.xml.in
@@ -73,30 +73,382 @@
</constraint>
</properties>
</leafNode>
- <leafNode name="section">
+ <node name="section">
<properties>
<help>Section for synchronization</help>
- <completionHelp>
- <list>nat nat66 firewall</list>
- </completionHelp>
- <valueHelp>
- <format>nat</format>
- <description>NAT</description>
- </valueHelp>
- <valueHelp>
- <format>nat66</format>
- <description>NAT66</description>
- </valueHelp>
- <valueHelp>
- <format>firewall</format>
- <description>firewall</description>
- </valueHelp>
- <constraint>
- <regex>(nat|nat66|firewall)</regex>
- </constraint>
- <multi/>
</properties>
- </leafNode>
+ <children>
+ <leafNode name="firewall">
+ <properties>
+ <help>Firewall</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <node name="interfaces">
+ <properties>
+ <help>Interfaces</help>
+ </properties>
+ <children>
+ <leafNode name="bonding">
+ <properties>
+ <help>Bonding interface</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="bridge">
+ <properties>
+ <help>Bridge interface</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="dummy">
+ <properties>
+ <help>Dummy interface</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="ethernet">
+ <properties>
+ <help>Ethernet interface</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="geneve">
+ <properties>
+ <help>GENEVE interface</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="input">
+ <properties>
+ <help>Input interface</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="l2tpv3">
+ <properties>
+ <help>L2TPv3 interface</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="loopback">
+ <properties>
+ <help>Loopback interface</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="macsec">
+ <properties>
+ <help>MACsec interface</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="openvpn">
+ <properties>
+ <help>OpenVPN interface</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="pppoe">
+ <properties>
+ <help>PPPoE interface</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="pseudo-ethernet">
+ <properties>
+ <help>Pseudo-Ethernet interface</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="sstpc">
+ <properties>
+ <help>SSTP client interface</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="tunnel">
+ <properties>
+ <help>Tunnel interface</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="virtual-ethernet">
+ <properties>
+ <help>Virtual Ethernet interface</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="vti">
+ <properties>
+ <help>Virtual tunnel interface</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="vxlan">
+ <properties>
+ <help>VXLAN interface</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="wireguard">
+ <properties>
+ <help>Wireguard interface</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="wireless">
+ <properties>
+ <help>Wireless interface</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="wwan">
+ <properties>
+ <help>WWAN interface</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ </children>
+ </node>
+ <leafNode name="nat">
+ <properties>
+ <help>NAT</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="nat66">
+ <properties>
+ <help>NAT66</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="pki">
+ <properties>
+ <help>Public key infrastructure (PKI)</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="policy">
+ <properties>
+ <help>Routing policy</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <node name="protocols">
+ <properties>
+ <help>Routing protocols</help>
+ </properties>
+ <children>
+ <leafNode name="babel">
+ <properties>
+ <help>Babel Routing Protocol</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="bfd">
+ <properties>
+ <help>Bidirectional Forwarding Detection (BFD)</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="bgp">
+ <properties>
+ <help>Border Gateway Protocol (BGP)</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="failover">
+ <properties>
+ <help>Failover route</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="igmp-proxy">
+ <properties>
+ <help>Internet Group Management Protocol (IGMP) proxy</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="isis">
+ <properties>
+ <help>Intermediate System to Intermediate System (IS-IS)</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="mpls">
+ <properties>
+ <help>Multiprotocol Label Switching (MPLS)</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="nhrp">
+ <properties>
+ <help>Next Hop Resolution Protocol (NHRP) parameters</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="ospf">
+ <properties>
+ <help>Open Shortest Path First (OSPF)</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="ospfv3">
+ <properties>
+ <help>Open Shortest Path First (OSPF) for IPv6</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="pim">
+ <properties>
+ <help>Protocol Independent Multicast (PIM) and IGMP</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="pim6">
+ <properties>
+ <help>Protocol Independent Multicast for IPv6 (PIMv6) and MLD</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="rip">
+ <properties>
+ <help>Routing Information Protocol (RIP) parameters</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="ripng">
+ <properties>
+ <help>Routing Information Protocol (RIPng) parameters</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="rpki">
+ <properties>
+ <help>Resource Public Key Infrastructure (RPKI)</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="segment-routing">
+ <properties>
+ <help>Segment Routing</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="static">
+ <properties>
+ <help>Static Routing</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ </children>
+ </node>
+ <node name="service">
+ <properties>
+ <help>System services</help>
+ </properties>
+ <children>
+ <leafNode name="console-server">
+ <properties>
+ <help>Serial Console Server</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="dhcp-relay">
+ <properties>
+ <help>Host Configuration Protocol (DHCP) relay agent</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="dhcp-server">
+ <properties>
+ <help>Dynamic Host Configuration Protocol (DHCP) for DHCP server</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="dhcpv6-relay">
+ <properties>
+ <help>DHCPv6 Relay Agent parameters</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="dhcpv6-server">
+ <properties>
+ <help>DHCP for IPv6 (DHCPv6) server</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="dns">
+ <properties>
+ <help>Domain Name System (DNS) related services</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="lldp">
+ <properties>
+ <help>LLDP settings</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="mdns">
+ <properties>
+ <help>Multicast DNS (mDNS) parameters</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="monitoring">
+ <properties>
+ <help>Monitoring services</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="ndp-proxy">
+ <properties>
+ <help>Neighbor Discovery Protocol (NDP) Proxy</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="ntp">
+ <properties>
+ <help>Network Time Protocol (NTP) configuration</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="snmp">
+ <properties>
+ <help>Simple Network Management Protocol (SNMP)</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="tftp-server">
+ <properties>
+ <help>Trivial File Transfer Protocol (TFTP) server</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="webproxy">
+ <properties>
+ <help>Webproxy service settings</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ </children>
+ </node>
+ <leafNode name="vpn">
+ <properties>
+ <help>Virtual Private Network (VPN)</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="vrf">
+ <properties>
+ <help>Virtual Routing and Forwarding</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ </children>
+ </node>
</children>
</node>
</children>
diff --git a/interface-definitions/service_router-advert.xml.in b/interface-definitions/service_router-advert.xml.in
index 16c29022d..166a4a0cf 100644
--- a/interface-definitions/service_router-advert.xml.in
+++ b/interface-definitions/service_router-advert.xml.in
@@ -225,6 +225,36 @@
</leafNode>
</children>
</tagNode>
+ <tagNode name="nat64prefix">
+ <properties>
+ <help>NAT64 prefix included in the router advertisements</help>
+ <valueHelp>
+ <format>ipv6net</format>
+ <description>IPv6 prefix to be advertized</description>
+ </valueHelp>
+ <constraint>
+ <validator name="ipv6-prefix"/>
+ </constraint>
+ </properties>
+ <children>
+ <leafNode name="valid-lifetime">
+ <properties>
+ <help>Time in seconds that the prefix will remain valid</help>
+ <completionHelp>
+ <list>infinity</list>
+ </completionHelp>
+ <valueHelp>
+ <format>u32:4-65528</format>
+ <description>Time in seconds that the prefix will remain valid</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 4-65528"/>
+ </constraint>
+ </properties>
+ <defaultValue>65528</defaultValue>
+ </leafNode>
+ </children>
+ </tagNode>
<tagNode name="prefix">
<properties>
<help>IPv6 prefix to be advertised in Router Advertisements (RAs)</help>
diff --git a/interface-definitions/system_conntrack.xml.in b/interface-definitions/system_conntrack.xml.in
index a348097cc..219c6e28e 100644
--- a/interface-definitions/system_conntrack.xml.in
+++ b/interface-definitions/system_conntrack.xml.in
@@ -289,6 +289,12 @@
<valueless/>
</properties>
</leafNode>
+ <leafNode name="rtsp">
+ <properties>
+ <help>RTSP connection tracking</help>
+ <valueless/>
+ </properties>
+ </leafNode>
<leafNode name="sip">
<properties>
<help>SIP connection tracking</help>
diff --git a/op-mode-definitions/force-commit-archive.xml.in b/op-mode-definitions/force-commit-archive.xml.in
new file mode 100644
index 000000000..162323c20
--- /dev/null
+++ b/op-mode-definitions/force-commit-archive.xml.in
@@ -0,0 +1,13 @@
+<?xml version="1.0"?>
+<interfaceDefinition>
+ <node name="force">
+ <children>
+ <leafNode name="commit-archive">
+ <properties>
+ <help>Manually archive configuration</help>
+ </properties>
+ <command>/usr/bin/config-mgmt</command>
+ </leafNode>
+ </children>
+ </node>
+</interfaceDefinition>
diff --git a/op-mode-definitions/pki.xml.in b/op-mode-definitions/pki.xml.in
index a81c8d4f7..a5e01bade 100644
--- a/op-mode-definitions/pki.xml.in
+++ b/op-mode-definitions/pki.xml.in
@@ -4,7 +4,7 @@
<children>
<node name="pki">
<properties>
- <help>Generate PKI certificates and keys</help>
+ <help>Generate public key infrastructure (PKI) certificates and keys</help>
</properties>
<children>
<node name="ca">
diff --git a/op-mode-definitions/show-log.xml.in b/op-mode-definitions/show-log.xml.in
index a6ce04624..e13270364 100644
--- a/op-mode-definitions/show-log.xml.in
+++ b/op-mode-definitions/show-log.xml.in
@@ -219,7 +219,7 @@
<path>firewall ipv4 forward filter rule</path>
</completionHelp>
</properties>
- <command>journalctl --no-hostname --boot -k | egrep "\[ipv4-FWD-filter-$8-[ADRJC]\]"</command>
+ <command>journalctl --no-hostname --boot -k | egrep "\[ipv4-FWD-filter-$8-[ADRJCO]\]"</command>
</tagNode>
</children>
</node>
@@ -322,7 +322,7 @@
<path>firewall ipv6 forward filter rule</path>
</completionHelp>
</properties>
- <command>journalctl --no-hostname --boot -k | egrep "\[ipv6-FWD-filter-$8-[ADRJC]\]"</command>
+ <command>journalctl --no-hostname --boot -k | egrep "\[ipv6-FWD-filter-$8-[ADRJCO]\]"</command>
</tagNode>
</children>
</node>
diff --git a/python/vyos/config_mgmt.py b/python/vyos/config_mgmt.py
index ff078649d..28ccee769 100644
--- a/python/vyos/config_mgmt.py
+++ b/python/vyos/config_mgmt.py
@@ -132,6 +132,9 @@ class ConfigMgmt:
{}).get('source_address', '')
if config.exists(['system', 'host-name']):
self.hostname = config.return_value(['system', 'host-name'])
+ if config.exists(['system', 'domain-name']):
+ tmp = config.return_value(['system', 'domain-name'])
+ self.hostname += f'.{tmp}'
else:
self.hostname = 'vyos'
diff --git a/python/vyos/configtree.py b/python/vyos/configtree.py
index d048901f0..423fe01ed 100644
--- a/python/vyos/configtree.py
+++ b/python/vyos/configtree.py
@@ -20,10 +20,22 @@ from ctypes import cdll, c_char_p, c_void_p, c_int, c_bool
LIBPATH = '/usr/lib/libvyosconfig.so.0'
+def replace_backslash(s, search, replace):
+ """Modify quoted strings containing backslashes not of escape sequences"""
+ def replace_method(match):
+ result = match.group().replace(search, replace)
+ return result
+ p = re.compile(r'("[^"]*[\\][^"]*"\n|\'[^\']*[\\][^\']*\'\n)')
+ return p.sub(replace_method, s)
+
def escape_backslash(string: str) -> str:
- """Escape single backslashes in string that are not in escape sequence"""
- p = re.compile(r'(?<!\\)[\\](?!b|f|n|r|t|\\[^bfnrt])')
- result = p.sub(r'\\\\', string)
+ """Escape single backslashes in quoted strings"""
+ result = replace_backslash(string, '\\', '\\\\')
+ return result
+
+def unescape_backslash(string: str) -> str:
+ """Unescape backslashes in quoted strings"""
+ result = replace_backslash(string, '\\\\', '\\')
return result
def extract_version(s):
@@ -165,11 +177,14 @@ class ConfigTree(object):
def to_string(self, ordered_values=False):
config_string = self.__to_string(self.__config, ordered_values).decode()
+ config_string = unescape_backslash(config_string)
config_string = "{0}\n{1}".format(config_string, self.__version)
return config_string
def to_commands(self, op="set"):
- return self.__to_commands(self.__config, op.encode()).decode()
+ commands = self.__to_commands(self.__config, op.encode()).decode()
+ commands = unescape_backslash(commands)
+ return commands
def to_json(self):
return self.__to_json(self.__config).decode()
@@ -362,6 +377,7 @@ def show_diff(left, right, path=[], commands=False, libpath=LIBPATH):
msg = __get_error().decode()
raise ConfigTreeError(msg)
+ res = unescape_backslash(res)
return res
def union(left, right, libpath=LIBPATH):
diff --git a/smoketest/scripts/cli/test_backslash_escape.py b/smoketest/scripts/cli/test_backslash_escape.py
new file mode 100755
index 000000000..e94e9ab0a
--- /dev/null
+++ b/smoketest/scripts/cli/test_backslash_escape.py
@@ -0,0 +1,68 @@
+#!/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/>.
+
+import unittest
+
+from base_vyostest_shim import VyOSUnitTestSHIM
+from vyos.configtree import ConfigTree
+
+base_path = ['interfaces', 'ethernet', 'eth0', 'description']
+
+cases_word = [r'fo\o', r'fo\\o', r'foço\o', r'foço\\o']
+# legacy CLI output quotes only if whitespace present; this is a notable
+# difference that confounds the translation legacy -> modern, hence
+# determines the regex used in function replace_backslash
+cases_phrase = [r'some fo\o', r'some fo\\o', r'some foço\o', r'some foço\\o']
+
+case_save_config = '/tmp/smoketest-case-save'
+
+class TestBackslashEscape(VyOSUnitTestSHIM.TestCase):
+ def test_backslash_escape_word(self):
+ for case in cases_word:
+ self.cli_set(base_path + [case])
+ self.cli_commit()
+ # save_config tests translation though subsystems:
+ # legacy output -> config -> configtree -> file
+ self._session.save_config(case_save_config)
+ # reload to configtree and confirm:
+ with open(case_save_config) as f:
+ config_string = f.read()
+ ct = ConfigTree(config_string)
+ res = ct.return_value(base_path)
+ self.assertEqual(case, res, msg=res)
+ print(f'description: {res}')
+ self.cli_delete(base_path)
+ self.cli_commit()
+
+ def test_backslash_escape_phrase(self):
+ for case in cases_phrase:
+ self.cli_set(base_path + [case])
+ self.cli_commit()
+ # save_config tests translation though subsystems:
+ # legacy output -> config -> configtree -> file
+ self._session.save_config(case_save_config)
+ # reload to configtree and confirm:
+ with open(case_save_config) as f:
+ config_string = f.read()
+ ct = ConfigTree(config_string)
+ res = ct.return_value(base_path)
+ self.assertEqual(case, res, msg=res)
+ print(f'description: {res}')
+ self.cli_delete(base_path)
+ self.cli_commit()
+
+if __name__ == '__main__':
+ unittest.main(verbosity=2)
diff --git a/smoketest/scripts/cli/test_policy.py b/smoketest/scripts/cli/test_policy.py
index c21d8af4e..ee4445251 100755
--- a/smoketest/scripts/cli/test_policy.py
+++ b/smoketest/scripts/cli/test_policy.py
@@ -1065,6 +1065,7 @@ class TestPolicy(VyOSUnitTestSHIM.TestCase):
'20' : {
'action' : 'permit',
'set' : {
+ 'as-path-exclude' : 'all',
'evpn-gateway-ipv4' : '192.0.2.99',
'evpn-gateway-ipv6' : '2001:db8:f00::1',
},
diff --git a/smoketest/scripts/cli/test_service_router-advert.py b/smoketest/scripts/cli/test_service_router-advert.py
index 5fc2019fd..d1ff25a58 100755
--- a/smoketest/scripts/cli/test_service_router-advert.py
+++ b/smoketest/scripts/cli/test_service_router-advert.py
@@ -195,6 +195,34 @@ class TestServiceRADVD(VyOSUnitTestSHIM.TestCase):
for src in ra_src:
self.assertIn(f' {src};', config)
+ def test_nat64prefix(self):
+ nat64prefix = '64:ff9b::/96'
+ nat64prefix_invalid = '64:ff9b::/44'
+
+ self.cli_set(base_path + ['nat64prefix', nat64prefix])
+
+ # and another invalid prefix
+ # Invalid NAT64 prefix length for "2001:db8::/34", can only be one of:
+ # /32, /40, /48, /56, /64, /96
+ self.cli_set(base_path + ['nat64prefix', nat64prefix_invalid])
+ with self.assertRaises(ConfigSessionError):
+ self.cli_commit()
+ self.cli_delete(base_path + ['nat64prefix', nat64prefix_invalid])
+
+ # NAT64 valid-lifetime must not be smaller then "interval max"
+ self.cli_set(base_path + ['nat64prefix', nat64prefix, 'valid-lifetime', '500'])
+ with self.assertRaises(ConfigSessionError):
+ self.cli_commit()
+ self.cli_delete(base_path + ['nat64prefix', nat64prefix, 'valid-lifetime'])
+
+ # commit changes
+ self.cli_commit()
+
+ config = read_file(RADVD_CONF)
+
+ tmp = f'nat64prefix {nat64prefix}' + ' {'
+ self.assertIn(tmp, config)
+ self.assertIn('AdvValidLifetime 65528;', config) # default
if __name__ == '__main__':
unittest.main(verbosity=2)
diff --git a/smoketest/scripts/cli/test_system_conntrack.py b/smoketest/scripts/cli/test_system_conntrack.py
index f00626b3d..2d76da145 100755
--- a/smoketest/scripts/cli/test_system_conntrack.py
+++ b/smoketest/scripts/cli/test_system_conntrack.py
@@ -174,12 +174,16 @@ class TestSystemConntrack(VyOSUnitTestSHIM.TestCase):
'pptp': {
'driver': ['nf_nat_pptp', 'nf_conntrack_pptp'],
'nftables': ['ct helper set "pptp_tcp"']
- },
+ },
+ 'rtsp': {
+ 'driver': ['nf_nat_rtsp', 'nf_conntrack_rtsp'],
+ 'nftables': ['ct helper set "rtsp_tcp"']
+ },
'sip': {
'driver': ['nf_nat_sip', 'nf_conntrack_sip'],
'nftables': ['ct helper set "sip_tcp"',
'ct helper set "sip_udp"']
- },
+ },
'sqlnet': {
'nftables': ['ct helper set "tns_tcp"']
},
diff --git a/src/conf_mode/firewall.py b/src/conf_mode/firewall.py
index 3c27655b0..810437dda 100755
--- a/src/conf_mode/firewall.py
+++ b/src/conf_mode/firewall.py
@@ -268,6 +268,18 @@ def verify_rule(firewall, rule_conf, ipv6):
if 'port' in side_conf and dict_search_args(side_conf, 'group', 'port_group'):
raise ConfigError(f'{side} port-group and port cannot both be defined')
+ if 'add_address_to_group' in rule_conf:
+ for type in ['destination_address', 'source_address']:
+ if type in rule_conf['add_address_to_group']:
+ if 'address_group' not in rule_conf['add_address_to_group'][type]:
+ raise ConfigError(f'Dynamic address group must be defined.')
+ else:
+ target = rule_conf['add_address_to_group'][type]['address_group']
+ fwall_group = 'ipv6_address_group' if ipv6 else 'address_group'
+ group_obj = dict_search_args(firewall, 'group', 'dynamic_group', fwall_group, target)
+ if group_obj is None:
+ raise ConfigError(f'Invalid dynamic address group on firewall rule')
+
if 'log_options' in rule_conf:
if 'log' not in rule_conf:
raise ConfigError('log-options defined, but log is not enable')
diff --git a/src/conf_mode/service_router-advert.py b/src/conf_mode/service_router-advert.py
index dbb47de4e..88d767bb8 100755
--- a/src/conf_mode/service_router-advert.py
+++ b/src/conf_mode/service_router-advert.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2018-2022 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
@@ -17,6 +17,8 @@
import os
from sys import exit
+from ipaddress import IPv6Network
+
from vyos.base import Warning
from vyos.config import Config
from vyos.template import render
@@ -47,7 +49,9 @@ def verify(rtradv):
return None
for interface, interface_config in rtradv['interface'].items():
- if 'prefix' in interface:
+ interval_max = int(interface_config['interval']['max'])
+
+ if 'prefix' in interface_config:
for prefix, prefix_config in interface_config['prefix'].items():
valid_lifetime = prefix_config['valid_lifetime']
if valid_lifetime == 'infinity':
@@ -60,6 +64,15 @@ def verify(rtradv):
if not (int(valid_lifetime) >= int(preferred_lifetime)):
raise ConfigError('Prefix valid-lifetime must be greater then or equal to preferred-lifetime')
+ if 'nat64prefix' in interface_config:
+ nat64_supported_lengths = [32, 40, 48, 56, 64, 96]
+ for prefix, prefix_config in interface_config['nat64prefix'].items():
+ if IPv6Network(prefix).prefixlen not in nat64_supported_lengths:
+ raise ConfigError(f'Invalid NAT64 prefix length for "{prefix}", can only be one of: /' + ', /'.join(nat64_supported_lengths))
+
+ if int(prefix_config['valid_lifetime']) < interval_max:
+ raise ConfigError(f'NAT64 valid-lifetime must not be smaller then "interval max" which is "{interval_max}"!')
+
if 'name_server' in interface_config:
if len(interface_config['name_server']) > 3:
raise ConfigError('No more then 3 IPv6 name-servers supported!')
@@ -72,7 +85,6 @@ def verify(rtradv):
# ensure stale RDNSS info gets removed in a timely fashion, this
# should not be greater than 2*MaxRtrAdvInterval.
lifetime = int(interface_config['name_server_lifetime'])
- interval_max = int(interface_config['interval']['max'])
if lifetime > 0:
if lifetime < int(interval_max):
raise ConfigError(f'RDNSS lifetime must be at least "{interval_max}" seconds!')
diff --git a/src/conf_mode/system_conntrack.py b/src/conf_mode/system_conntrack.py
index 2a55daed4..a1472aaaa 100755
--- a/src/conf_mode/system_conntrack.py
+++ b/src/conf_mode/system_conntrack.py
@@ -58,6 +58,11 @@ module_map = {
'nftables': ['tcp dport {1723} ct helper set "pptp_tcp" return'],
'ipv4': True
},
+ 'rtsp': {
+ 'ko': ['nf_nat_rtsp', 'nf_conntrack_rtsp'],
+ 'nftables': ['tcp dport {554} ct helper set "rtsp_tcp" return'],
+ 'ipv4': True
+ },
'sip': {
'ko': ['nf_nat_sip', 'nf_conntrack_sip'],
'nftables': ['tcp dport {5060,5061} ct helper set "sip_tcp" return',
@@ -195,7 +200,7 @@ def generate(conntrack):
def apply(conntrack):
# Depending on the enable/disable state of the ALG (Application Layer Gateway)
# modules we need to either insmod or rmmod the helpers.
-
+
add_modules = []
rm_modules = []
diff --git a/src/helpers/vyos_config_sync.py b/src/helpers/vyos_config_sync.py
index 7cfa8fe88..572fea61f 100755
--- a/src/helpers/vyos_config_sync.py
+++ b/src/helpers/vyos_config_sync.py
@@ -1,6 +1,6 @@
#!/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
@@ -60,6 +60,7 @@ def post_request(url: str,
return response
+
def retrieve_config(section: str = None) -> Optional[Dict[str, Any]]:
"""Retrieves the configuration from the local server.
@@ -71,8 +72,6 @@ def retrieve_config(section: str = None) -> Optional[Dict[str, Any]]:
"""
if section is None:
section = []
- else:
- section = section.split()
conf = Config()
config = conf.get_config_dict(section, get_first_key=True)
@@ -101,8 +100,6 @@ def set_remote_config(
if path is None:
path = []
- else:
- path = path.split()
headers = {'Content-Type': 'application/json'}
# Disable the InsecureRequestWarning
@@ -127,17 +124,16 @@ def set_remote_config(
def is_section_revised(section: str) -> bool:
from vyos.config_mgmt import is_node_revised
- return is_node_revised([section])
+ return is_node_revised(section)
def config_sync(secondary_address: str,
secondary_key: str,
- sections: List[str],
+ sections: List[list],
mode: str):
"""Retrieve a config section from primary router in JSON format and send it to
secondary router
"""
- # Config sync only if sections changed
if not any(map(is_section_revised, sections)):
return
@@ -188,5 +184,17 @@ if __name__ == '__main__':
"Missing required configuration data for config synchronization.")
exit(0)
+ # Generate list_sections of sections/subsections
+ # [
+ # ['interfaces', 'pseudo-ethernet'], ['interfaces', 'virtual-ethernet'], ['nat'], ['nat66']
+ # ]
+ list_sections = []
+ for section, subsections in sections.items():
+ if subsections:
+ for subsection in subsections:
+ list_sections.append([section, subsection])
+ else:
+ list_sections.append([section])
+
config_sync(secondary_address, secondary_key,
- sections, mode)
+ list_sections, mode)
diff --git a/src/migration-scripts/policy/1-to-2 b/src/migration-scripts/policy/1-to-2
index c70490ce9..c7a983bba 100755
--- a/src/migration-scripts/policy/1-to-2
+++ b/src/migration-scripts/policy/1-to-2
@@ -32,23 +32,23 @@ file_name = argv[1]
with open(file_name, 'r') as f:
config_file = f.read()
-base = ['policy', 'ipv6-route']
+base = ['policy']
config = ConfigTree(config_file)
if not config.exists(base):
# Nothing to do
exit(0)
-config.rename(base, 'route6')
-config.set_tag(['policy', 'route6'])
+if config.exists(base + ['ipv6-route']):
+ config.rename(base + ['ipv6-route'],'route6')
+ config.set_tag(['policy', 'route6'])
for route in ['route', 'route6']:
- route_path = ['policy', route]
- if config.exists(route_path):
- for name in config.list_nodes(route_path):
- if config.exists(route_path + [name, 'rule']):
- for rule in config.list_nodes(route_path + [name, 'rule']):
- rule_tcp_flags = route_path + [name, 'rule', rule, 'tcp', 'flags']
+ if config.exists(base + [route]):
+ for name in config.list_nodes(base + [route]):
+ if config.exists(base + [route, name, 'rule']):
+ for rule in config.list_nodes(base + [route, name, 'rule']):
+ rule_tcp_flags = base + [route, name, 'rule', rule, 'tcp', 'flags']
if config.exists(rule_tcp_flags):
tmp = config.return_value(rule_tcp_flags)
diff --git a/src/op_mode/conntrack.py b/src/op_mode/conntrack.py
index cf8adf795..6ea213bec 100755
--- a/src/op_mode/conntrack.py
+++ b/src/op_mode/conntrack.py
@@ -112,7 +112,8 @@ def get_formatted_output(dict_data):
proto = meta['layer4']['protoname']
if direction == 'independent':
conn_id = meta['id']
- timeout = meta['timeout']
+ # T6138 flowtable offload conntrack entries without 'timeout'
+ timeout = meta.get('timeout', 'n/a')
orig_src = f'{orig_src}:{orig_sport}' if orig_sport else orig_src
orig_dst = f'{orig_dst}:{orig_dport}' if orig_dport else orig_dst
reply_src = f'{reply_src}:{reply_sport}' if reply_sport else reply_src