summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/templates/frr/bgpd.frr.j22
-rw-r--r--data/templates/frr/static_routes_macro.j26
-rw-r--r--interface-definitions/include/bgp/neighbor-path-attribute.xml.i1
-rw-r--r--interface-definitions/include/static/static-route-reject.xml.i1
-rw-r--r--interface-definitions/include/static/static-route-segments.xml.i14
-rw-r--r--interface-definitions/include/static/static-route6.xml.i5
-rw-r--r--interface-definitions/include/version/dhcpv6-server-version.xml.i2
-rw-r--r--interface-definitions/service_dhcpv6-server.xml.in15
-rw-r--r--python/vyos/kea.py3
-rwxr-xr-xsmoketest/scripts/cli/test_firewall.py4
-rwxr-xr-xsmoketest/scripts/cli/test_protocols_bgp.py13
-rwxr-xr-xsmoketest/scripts/cli/test_protocols_static.py62
-rwxr-xr-xsmoketest/scripts/cli/test_service_dhcpv6-server.py2
-rwxr-xr-xsrc/init/vyos-router4
-rwxr-xr-xsrc/migration-scripts/dhcpv6-server/4-to-568
-rwxr-xr-xsrc/migration-scripts/ipsec/6-to-72
-rwxr-xr-xsrc/validators/ipv6-srv6-segments13
17 files changed, 183 insertions, 34 deletions
diff --git a/data/templates/frr/bgpd.frr.j2 b/data/templates/frr/bgpd.frr.j2
index 23f81348b..ed55db3f2 100644
--- a/data/templates/frr/bgpd.frr.j2
+++ b/data/templates/frr/bgpd.frr.j2
@@ -76,7 +76,7 @@
neighbor {{ neighbor }} password {{ config.password }}
{% endif %}
{% if config.path_attribute.discard is vyos_defined %}
- neighbor {{ neighbor }} path-attribute discard {{ config.path_attribute.discard }}
+ neighbor {{ neighbor }} path-attribute discard {{ config.path_attribute.discard | join(' ') }}
{% endif %}
{% if config.path_attribute.treat_as_withdraw is vyos_defined %}
neighbor {{ neighbor }} path-attribute treat-as-withdraw {{ config.path_attribute.treat_as_withdraw }}
diff --git a/data/templates/frr/static_routes_macro.j2 b/data/templates/frr/static_routes_macro.j2
index 8afd4a68a..cf8046968 100644
--- a/data/templates/frr/static_routes_macro.j2
+++ b/data/templates/frr/static_routes_macro.j2
@@ -13,17 +13,17 @@
{% endif %}
{% if prefix_config.interface is vyos_defined %}
{% for interface, interface_config in prefix_config.interface.items() if interface_config.disable is not defined %}
-{{ ip_ipv6 }} route {{ prefix }} {{ interface }} {{ interface_config.distance if interface_config.distance is vyos_defined }} {{ 'nexthop-vrf ' ~ interface_config.vrf if interface_config.vrf is vyos_defined }} {{ 'table ' ~ table if table is vyos_defined }}
+{{ ip_ipv6 }} route {{ prefix }} {{ interface }} {{ interface_config.distance if interface_config.distance is vyos_defined }} {{ 'nexthop-vrf ' ~ interface_config.vrf if interface_config.vrf is vyos_defined }} {{ 'segments ' ~ interface_config.segments if interface_config.segments is vyos_defined }} {{ 'table ' ~ table if table is vyos_defined }}
{% endfor %}
{% endif %}
{% if prefix_config.next_hop is vyos_defined and prefix_config.next_hop is not none %}
{% for next_hop, next_hop_config in prefix_config.next_hop.items() if next_hop_config.disable is not defined %}
-{{ ip_ipv6 }} route {{ prefix }} {{ next_hop }} {{ next_hop_config.interface if next_hop_config.interface is vyos_defined }} {{ next_hop_config.distance if next_hop_config.distance is vyos_defined }} {{ 'nexthop-vrf ' ~ next_hop_config.vrf if next_hop_config.vrf is vyos_defined }} {{ 'bfd profile ' ~ next_hop_config.bfd.profile if next_hop_config.bfd.profile is vyos_defined }} {{ 'table ' ~ table if table is vyos_defined }}
+{{ ip_ipv6 }} route {{ prefix }} {{ next_hop }} {{ next_hop_config.interface if next_hop_config.interface is vyos_defined }} {{ next_hop_config.distance if next_hop_config.distance is vyos_defined }} {{ 'nexthop-vrf ' ~ next_hop_config.vrf if next_hop_config.vrf is vyos_defined }} {{ 'bfd profile ' ~ next_hop_config.bfd.profile if next_hop_config.bfd.profile is vyos_defined }} {{ 'segments ' ~ next_hop_config.segments if next_hop_config.segments is vyos_defined }} {{ 'table ' ~ table if table is vyos_defined }}
{% if next_hop_config.bfd.multi_hop.source is vyos_defined %}
{% for source, source_config in next_hop_config.bfd.multi_hop.source.items() %}
{{ ip_ipv6 }} route {{ prefix }} {{ next_hop }} bfd multi-hop source {{ source }} profile {{ source_config.profile }}
{% endfor %}
-{% endif %}
+{% endif %}
{% endfor %}
{% endif %}
{% endmacro %}
diff --git a/interface-definitions/include/bgp/neighbor-path-attribute.xml.i b/interface-definitions/include/bgp/neighbor-path-attribute.xml.i
index 30568d8c6..399a6bcdd 100644
--- a/interface-definitions/include/bgp/neighbor-path-attribute.xml.i
+++ b/interface-definitions/include/bgp/neighbor-path-attribute.xml.i
@@ -14,6 +14,7 @@
<constraint>
<validator name="numeric" argument="--range 1-255"/>
</constraint>
+ <multi/>
</properties>
</leafNode>
<leafNode name="treat-as-withdraw">
diff --git a/interface-definitions/include/static/static-route-reject.xml.i b/interface-definitions/include/static/static-route-reject.xml.i
index 81d4f9afd..ef713ac85 100644
--- a/interface-definitions/include/static/static-route-reject.xml.i
+++ b/interface-definitions/include/static/static-route-reject.xml.i
@@ -9,4 +9,3 @@
</children>
</node>
<!-- include end -->
-
diff --git a/interface-definitions/include/static/static-route-segments.xml.i b/interface-definitions/include/static/static-route-segments.xml.i
new file mode 100644
index 000000000..2068b1ab4
--- /dev/null
+++ b/interface-definitions/include/static/static-route-segments.xml.i
@@ -0,0 +1,14 @@
+<!-- include start from static/static-route-segments.xml.i -->
+<leafNode name="segments">
+ <properties>
+ <help>SRv6 segments</help>
+ <valueHelp>
+ <format>txt</format>
+ <description>Segs (SIDs)</description>
+ </valueHelp>
+ <constraint>
+ <validator name="ipv6-srv6-segments"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <!-- include end -->
diff --git a/interface-definitions/include/static/static-route6.xml.i b/interface-definitions/include/static/static-route6.xml.i
index a83cc230b..4468c8025 100644
--- a/interface-definitions/include/static/static-route6.xml.i
+++ b/interface-definitions/include/static/static-route6.xml.i
@@ -31,6 +31,7 @@
<children>
#include <include/generic-disable-node.xml.i>
#include <include/static/static-route-distance.xml.i>
+ #include <include/static/static-route-segments.xml.i>
#include <include/static/static-route-vrf.xml.i>
</children>
</tagNode>
@@ -47,13 +48,13 @@
</properties>
<children>
#include <include/generic-disable-node.xml.i>
+ #include <include/static/static-route-bfd.xml.i>
#include <include/static/static-route-distance.xml.i>
#include <include/static/static-route-interface.xml.i>
+ #include <include/static/static-route-segments.xml.i>
#include <include/static/static-route-vrf.xml.i>
- #include <include/static/static-route-bfd.xml.i>
</children>
</tagNode>
</children>
</tagNode>
<!-- include end -->
-
diff --git a/interface-definitions/include/version/dhcpv6-server-version.xml.i b/interface-definitions/include/version/dhcpv6-server-version.xml.i
index bfef27b77..1f30368a3 100644
--- a/interface-definitions/include/version/dhcpv6-server-version.xml.i
+++ b/interface-definitions/include/version/dhcpv6-server-version.xml.i
@@ -1,3 +1,3 @@
<!-- include start from include/version/dhcpv6-server-version.xml.i -->
-<syntaxVersion component='dhcpv6-server' version='4'></syntaxVersion>
+<syntaxVersion component='dhcpv6-server' version='5'></syntaxVersion>
<!-- include end -->
diff --git a/interface-definitions/service_dhcpv6-server.xml.in b/interface-definitions/service_dhcpv6-server.xml.in
index 28b97a64b..daca7b43f 100644
--- a/interface-definitions/service_dhcpv6-server.xml.in
+++ b/interface-definitions/service_dhcpv6-server.xml.in
@@ -97,6 +97,21 @@
</properties>
<children>
#include <include/dhcp/option-v6.xml.i>
+ <leafNode name="interface">
+ <properties>
+ <help>Optional interface for this subnet to accept requests from</help>
+ <completionHelp>
+ <script>${vyos_completion_dir}/list_interfaces</script>
+ </completionHelp>
+ <valueHelp>
+ <format>txt</format>
+ <description>Interface name</description>
+ </valueHelp>
+ <constraint>
+ #include <include/constraint/interface-name.xml.i>
+ </constraint>
+ </properties>
+ </leafNode>
<tagNode name="range">
<properties>
<help>Parameters setting ranges for assigning IPv6 addresses</help>
diff --git a/python/vyos/kea.py b/python/vyos/kea.py
index 720bebec3..7365c1f02 100644
--- a/python/vyos/kea.py
+++ b/python/vyos/kea.py
@@ -212,6 +212,9 @@ def kea6_parse_subnet(subnet, config):
if 'option' in config:
out['option-data'] = kea6_parse_options(config['option'])
+ if 'interface' in config:
+ out['interface'] = config['interface']
+
if 'range' in config:
pools = []
for num, range_config in config['range'].items():
diff --git a/smoketest/scripts/cli/test_firewall.py b/smoketest/scripts/cli/test_firewall.py
index a7dd11145..415f3436f 100755
--- a/smoketest/scripts/cli/test_firewall.py
+++ b/smoketest/scripts/cli/test_firewall.py
@@ -652,8 +652,8 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase):
nftables_search = [
['ct state { established, related }', 'accept'],
['ct state invalid', 'reject'],
- ['ct state new', 'ct status dnat', 'accept'],
- ['ct state { established, new }', 'ct status snat', 'accept'],
+ ['ct state new', 'ct status == dnat', 'accept'],
+ ['ct state { established, new }', 'ct status == snat', 'accept'],
['ct state related', 'ct helper { "ftp", "pptp" }', 'accept'],
['drop', f'comment "{name} default-action drop"'],
['jump VYOS_STATE_POLICY'],
diff --git a/smoketest/scripts/cli/test_protocols_bgp.py b/smoketest/scripts/cli/test_protocols_bgp.py
index 08a6e1696..eadd8a004 100755
--- a/smoketest/scripts/cli/test_protocols_bgp.py
+++ b/smoketest/scripts/cli/test_protocols_bgp.py
@@ -60,7 +60,7 @@ neighbor_config = {
'route_map_out' : route_map_out,
'no_send_comm_ext' : '',
'addpath_all' : '',
- 'p_attr_discard' : '123',
+ 'p_attr_discard' : ['10', '20', '30', '40', '50'],
},
'192.0.2.2' : {
'bfd_profile' : bfd_profile,
@@ -137,7 +137,7 @@ peer_group_config = {
'cap_over' : '',
'ttl_security' : '5',
'disable_conn_chk' : '',
- 'p_attr_discard' : '250',
+ 'p_attr_discard' : ['100', '150', '200'],
},
'bar' : {
'remote_as' : '111',
@@ -284,7 +284,8 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase):
if 'addpath_all' in peer_config:
self.assertIn(f' neighbor {peer} addpath-tx-all-paths', frrconfig)
if 'p_attr_discard' in peer_config:
- self.assertIn(f' neighbor {peer} path-attribute discard {peer_config["p_attr_discard"]}', frrconfig)
+ tmp = ' '.join(peer_config["p_attr_discard"])
+ self.assertIn(f' neighbor {peer} path-attribute discard {tmp}', frrconfig)
if 'p_attr_taw' in peer_config:
self.assertIn(f' neighbor {peer} path-attribute treat-as-withdraw {peer_config["p_attr_taw"]}', frrconfig)
if 'addpath_per_as' in peer_config:
@@ -460,7 +461,8 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase):
if 'update_src' in peer_config:
self.cli_set(base_path + ['neighbor', peer, 'update-source', peer_config["update_src"]])
if 'p_attr_discard' in peer_config:
- self.cli_set(base_path + ['neighbor', peer, 'path-attribute', 'discard', peer_config["p_attr_discard"]])
+ for attribute in peer_config['p_attr_discard']:
+ self.cli_set(base_path + ['neighbor', peer, 'path-attribute', 'discard', attribute])
if 'p_attr_taw' in peer_config:
self.cli_set(base_path + ['neighbor', peer, 'path-attribute', 'treat-as-withdraw', peer_config["p_attr_taw"]])
if 'route_map_in' in peer_config:
@@ -584,7 +586,8 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase):
if 'disable_conn_chk' in config:
self.cli_set(base_path + ['peer-group', peer_group, 'disable-connected-check'])
if 'p_attr_discard' in config:
- self.cli_set(base_path + ['peer-group', peer_group, 'path-attribute', 'discard', config["p_attr_discard"]])
+ for attribute in config['p_attr_discard']:
+ self.cli_set(base_path + ['peer-group', peer_group, 'path-attribute', 'discard', attribute])
if 'p_attr_taw' in config:
self.cli_set(base_path + ['peer-group', peer_group, 'path-attribute', 'treat-as-withdraw', config["p_attr_taw"]])
diff --git a/smoketest/scripts/cli/test_protocols_static.py b/smoketest/scripts/cli/test_protocols_static.py
index abf1080ab..c5cf2aab6 100755
--- a/smoketest/scripts/cli/test_protocols_static.py
+++ b/smoketest/scripts/cli/test_protocols_static.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2021-2023 VyOS maintainers and contributors
+# Copyright (C) 2021-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
@@ -55,13 +55,13 @@ routes = {
'blackhole' : { 'distance' : '90' },
},
'100.64.0.0/16' : {
- 'blackhole' : { },
+ 'blackhole' : {},
},
'100.65.0.0/16' : {
'reject' : { 'distance' : '10', 'tag' : '200' },
},
'100.66.0.0/16' : {
- 'blackhole' : { },
+ 'blackhole' : {},
'reject' : { 'distance' : '10', 'tag' : '200' },
},
'2001:db8:100::/40' : {
@@ -88,8 +88,28 @@ routes = {
'2001:db8:300::/40' : {
'reject' : { 'distance' : '250', 'tag' : '500' },
},
+ '2001:db8:400::/40' : {
+ 'next_hop' : {
+ '2001:db8::400' : { 'segments' : '2001:db8:aaaa::400/2002::400/2003::400/2004::400' },
+ },
+ },
+ '2001:db8:500::/40' : {
+ 'next_hop' : {
+ '2001:db8::500' : { 'segments' : '2001:db8:aaaa::500/2002::500/2003::500/2004::500' },
+ },
+ },
+ '2001:db8:600::/40' : {
+ 'interface' : {
+ 'eth0' : { 'segments' : '2001:db8:aaaa::600/2002::600' },
+ },
+ },
+ '2001:db8:700::/40' : {
+ 'interface' : {
+ 'eth1' : { 'segments' : '2001:db8:aaaa::700' },
+ },
+ },
'2001:db8::/32' : {
- 'blackhole' : { 'distance' : '200', 'tag' : '600' },
+ 'blackhole' : { 'distance' : '200', 'tag' : '600' }
},
}
@@ -108,18 +128,14 @@ class TestProtocolsStatic(VyOSUnitTestSHIM.TestCase):
super(TestProtocolsStatic, cls).tearDownClass()
def tearDown(self):
- for route, route_config in routes.items():
- route_type = 'route'
- if is_ipv6(route):
- route_type = 'route6'
- self.cli_delete(base_path + [route_type, route])
-
- for table in tables:
- self.cli_delete(base_path + ['table', table])
-
- tmp = self.getFRRconfig('', end='')
+ self.cli_delete(base_path)
self.cli_commit()
+ v4route = self.getFRRconfig('ip route', end='')
+ self.assertFalse(v4route)
+ v6route = self.getFRRconfig('ipv6 route', end='')
+ self.assertFalse(v6route)
+
def test_01_static(self):
bfd_profile = 'vyos-test'
for route, route_config in routes.items():
@@ -142,7 +158,8 @@ class TestProtocolsStatic(VyOSUnitTestSHIM.TestCase):
self.cli_set(base + ['next-hop', next_hop, 'bfd', 'profile', bfd_profile ])
if 'bfd_source' in next_hop_config:
self.cli_set(base + ['next-hop', next_hop, 'bfd', 'multi-hop', 'source', next_hop_config['bfd_source'], 'profile', bfd_profile])
-
+ if 'segments' in next_hop_config:
+ self.cli_set(base + ['next-hop', next_hop, 'segments', next_hop_config['segments']])
if 'interface' in route_config:
for interface, interface_config in route_config['interface'].items():
@@ -153,6 +170,8 @@ class TestProtocolsStatic(VyOSUnitTestSHIM.TestCase):
self.cli_set(base + ['interface', interface, 'distance', interface_config['distance']])
if 'vrf' in interface_config:
self.cli_set(base + ['interface', interface, 'vrf', interface_config['vrf']])
+ if 'segments' in interface_config:
+ self.cli_set(base + ['interface', interface, 'segments', interface_config['segments']])
if 'blackhole' in route_config:
self.cli_set(base + ['blackhole'])
@@ -200,6 +219,8 @@ class TestProtocolsStatic(VyOSUnitTestSHIM.TestCase):
tmp += ' bfd profile ' + bfd_profile
if 'bfd_source' in next_hop_config:
tmp += ' bfd multi-hop source ' + next_hop_config['bfd_source'] + ' profile ' + bfd_profile
+ if 'segments' in next_hop_config:
+ tmp += ' segments ' + next_hop_config['segments']
if 'disable' in next_hop_config:
self.assertNotIn(tmp, frrconfig)
@@ -215,6 +236,8 @@ class TestProtocolsStatic(VyOSUnitTestSHIM.TestCase):
tmp += ' ' + interface_config['distance']
if 'vrf' in interface_config:
tmp += ' nexthop-vrf ' + interface_config['vrf']
+ if 'segments' in interface_config:
+ tmp += ' segments ' + interface_config['segments']
if 'disable' in interface_config:
self.assertNotIn(tmp, frrconfig)
@@ -369,7 +392,8 @@ class TestProtocolsStatic(VyOSUnitTestSHIM.TestCase):
self.cli_set(route_base_path + ['next-hop', next_hop, 'interface', next_hop_config['interface']])
if 'vrf' in next_hop_config:
self.cli_set(route_base_path + ['next-hop', next_hop, 'vrf', next_hop_config['vrf']])
-
+ if 'segments' in next_hop_config:
+ self.cli_set(route_base_path + ['next-hop', next_hop, 'segments', next_hop_config['segments']])
if 'interface' in route_config:
for interface, interface_config in route_config['interface'].items():
@@ -380,6 +404,8 @@ class TestProtocolsStatic(VyOSUnitTestSHIM.TestCase):
self.cli_set(route_base_path + ['interface', interface, 'distance', interface_config['distance']])
if 'vrf' in interface_config:
self.cli_set(route_base_path + ['interface', interface, 'vrf', interface_config['vrf']])
+ if 'segments' in interface_config:
+ self.cli_set(route_base_path + ['interface', interface, 'segments', interface_config['segments']])
if 'blackhole' in route_config:
self.cli_set(route_base_path + ['blackhole'])
@@ -417,6 +443,8 @@ class TestProtocolsStatic(VyOSUnitTestSHIM.TestCase):
tmp += ' ' + next_hop_config['distance']
if 'vrf' in next_hop_config:
tmp += ' nexthop-vrf ' + next_hop_config['vrf']
+ if 'segments' in next_hop_config:
+ tmp += ' segments ' + next_hop_config['segments']
if 'disable' in next_hop_config:
self.assertNotIn(tmp, frrconfig)
@@ -432,6 +460,8 @@ class TestProtocolsStatic(VyOSUnitTestSHIM.TestCase):
tmp += ' ' + interface_config['distance']
if 'vrf' in interface_config:
tmp += ' nexthop-vrf ' + interface_config['vrf']
+ if 'segments' in interface_config:
+ tmp += ' segments ' + interface_config['segments']
if 'disable' in interface_config:
self.assertNotIn(tmp, frrconfig)
diff --git a/smoketest/scripts/cli/test_service_dhcpv6-server.py b/smoketest/scripts/cli/test_service_dhcpv6-server.py
index 5a831b8a0..6ecf6c1cf 100755
--- a/smoketest/scripts/cli/test_service_dhcpv6-server.py
+++ b/smoketest/scripts/cli/test_service_dhcpv6-server.py
@@ -102,6 +102,7 @@ class TestServiceDHCPv6Server(VyOSUnitTestSHIM.TestCase):
pool = base_path + ['shared-network-name', shared_net_name, 'subnet', subnet]
self.cli_set(base_path + ['preference', preference])
+ self.cli_set(pool + ['interface', interface])
self.cli_set(pool + ['subnet-id', '1'])
# we use the first subnet IP address as default gateway
self.cli_set(pool + ['lease-time', 'default', lease_time])
@@ -146,6 +147,7 @@ class TestServiceDHCPv6Server(VyOSUnitTestSHIM.TestCase):
self.verify_config_value(obj, ['Dhcp6', 'shared-networks'], 'name', shared_net_name)
self.verify_config_value(obj, ['Dhcp6', 'shared-networks', 0, 'subnet6'], 'subnet', subnet)
+ self.verify_config_value(obj, ['Dhcp6', 'shared-networks', 0, 'subnet6'], 'interface', interface)
self.verify_config_value(obj, ['Dhcp6', 'shared-networks', 0, 'subnet6'], 'id', 1)
self.verify_config_value(obj, ['Dhcp6', 'shared-networks', 0, 'subnet6'], 'valid-lifetime', int(lease_time))
self.verify_config_value(obj, ['Dhcp6', 'shared-networks', 0, 'subnet6'], 'min-valid-lifetime', int(min_lease_time))
diff --git a/src/init/vyos-router b/src/init/vyos-router
index 2b4fac5ef..eac3e7e47 100755
--- a/src/init/vyos-router
+++ b/src/init/vyos-router
@@ -1,5 +1,5 @@
#!/bin/bash
-# Copyright (C) 2021 VyOS maintainers and contributors
+# Copyright (C) 2021-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
@@ -449,7 +449,7 @@ start ()
run_postconfig_scripts
tmp=$(${vyos_libexec_dir}/read-saved-value.py --path "protocols rpki cache")
- if [ ! -z $tmp ]; then
+ if [[ ! -z "$tmp" ]]; then
vtysh -c "rpki start"
fi
}
diff --git a/src/migration-scripts/dhcpv6-server/4-to-5 b/src/migration-scripts/dhcpv6-server/4-to-5
new file mode 100755
index 000000000..e808edbe0
--- /dev/null
+++ b/src/migration-scripts/dhcpv6-server/4-to-5
@@ -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/>.
+
+# T5993: Check if subnet is locally accessible and assign interface to subnet
+
+import sys
+from ipaddress import ip_network
+from vyos.configtree import ConfigTree
+
+if (len(sys.argv) < 1):
+ print("Must specify file name!")
+ sys.exit(1)
+
+file_name = sys.argv[1]
+
+with open(file_name, 'r') as f:
+ config_file = f.read()
+
+base = ['service', 'dhcpv6-server', 'shared-network-name']
+config = ConfigTree(config_file)
+
+if not config.exists(base):
+ # Nothing to do
+ exit(0)
+
+def find_subnet_interface(subnet):
+ subnet_net = ip_network(subnet)
+
+ for iftype in config.list_nodes(['interfaces']):
+ for ifname in config.list_nodes(['interfaces', iftype]):
+ if_base = ['interfaces', iftype, ifname]
+
+ if config.exists(if_base + ['address']):
+ for addr in config.return_values(if_base + ['address']):
+ if ip_network(addr, strict=False) == subnet_net:
+ return ifname
+
+ return False
+
+for network in config.list_nodes(base):
+ if not config.exists(base + [network, 'subnet']):
+ continue
+
+ for subnet in config.list_nodes(base + [network, 'subnet']):
+ subnet_interface = find_subnet_interface(subnet)
+
+ if subnet_interface:
+ config.set(base + [network, 'subnet', subnet, 'interface'], value=subnet_interface)
+
+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/ipsec/6-to-7 b/src/migration-scripts/ipsec/6-to-7
index 71fbbe8a1..f8b6de560 100755
--- a/src/migration-scripts/ipsec/6-to-7
+++ b/src/migration-scripts/ipsec/6-to-7
@@ -63,7 +63,7 @@ if config.exists(ipsec_site_base):
changes_made = True
peer_x509_base = ipsec_site_base + [peer, 'authentication', 'x509']
- pki_name = 'peer_' + peer.replace(".", "-")
+ pki_name = 'peer_' + peer.replace(".", "-").replace("@", "")
if config.exists(peer_x509_base + ['cert-file']):
cert_file = config.return_value(peer_x509_base + ['cert-file'])
diff --git a/src/validators/ipv6-srv6-segments b/src/validators/ipv6-srv6-segments
new file mode 100755
index 000000000..e72a4f90f
--- /dev/null
+++ b/src/validators/ipv6-srv6-segments
@@ -0,0 +1,13 @@
+#!/bin/sh
+segments="$1"
+export IFS="/"
+
+for ipv6addr in $segments; do
+ ipaddrcheck --is-ipv6-single $ipv6addr
+ if [ $? -gt 0 ]; then
+ echo "Error: $1 is not a valid IPv6 address"
+ exit 1
+ fi
+done
+exit 0
+