diff options
-rw-r--r-- | data/templates/firewall/nftables-nat66.j2 | 12 | ||||
-rw-r--r-- | data/templates/frr/bgpd.frr.j2 | 2 | ||||
-rw-r--r-- | data/templates/macsec/wpa_supplicant.conf.j2 | 12 | ||||
-rw-r--r-- | interface-definitions/include/bgp/protocol-common-config.xml.i | 2 | ||||
-rw-r--r-- | interface-definitions/include/version/bgp-version.xml.i | 2 | ||||
-rw-r--r-- | interface-definitions/nat66.xml.in | 73 | ||||
-rw-r--r-- | python/vyos/configdict.py | 4 | ||||
-rw-r--r-- | python/vyos/configverify.py | 13 | ||||
-rwxr-xr-x | smoketest/scripts/cli/test_interfaces_macsec.py | 45 | ||||
-rwxr-xr-x | smoketest/scripts/cli/test_protocols_bgp.py | 28 | ||||
-rwxr-xr-x | src/conf_mode/interfaces-macsec.py | 11 | ||||
-rwxr-xr-x | src/conf_mode/protocols_bgp.py | 14 | ||||
-rwxr-xr-x | src/migration-scripts/bgp/2-to-3 | 51 | ||||
-rwxr-xr-x | src/validators/ipv6-address-exclude | 7 | ||||
-rwxr-xr-x | src/validators/ipv6-prefix-exclude | 7 |
15 files changed, 233 insertions, 50 deletions
diff --git a/data/templates/firewall/nftables-nat66.j2 b/data/templates/firewall/nftables-nat66.j2 index 003b138b2..ca19506f2 100644 --- a/data/templates/firewall/nftables-nat66.j2 +++ b/data/templates/firewall/nftables-nat66.j2 @@ -3,8 +3,10 @@ {% macro nptv6_rule(rule,config, chain) %} {% set comment = '' %} {% set base_log = '' %} -{% set src_prefix = 'ip6 saddr ' ~ config.source.prefix if config.source.prefix is vyos_defined %} -{% set dest_address = 'ip6 daddr ' ~ config.destination.address if config.destination.address is vyos_defined %} +{% set dst_prefix = 'ip6 daddr ' ~ config.destination.prefix.replace('!','!= ') if config.destination.prefix is vyos_defined %} +{% set src_prefix = 'ip6 saddr ' ~ config.source.prefix.replace('!','!= ') if config.source.prefix is vyos_defined %} +{% set source_address = 'ip6 saddr ' ~ config.source.address.replace('!','!= ') if config.source.address is vyos_defined %} +{% set dest_address = 'ip6 daddr ' ~ config.destination.address.replace('!','!= ') if config.destination.address is vyos_defined %} {% if chain is vyos_defined('PREROUTING') %} {% set comment = 'DST-NAT66-' ~ rule %} {% set base_log = '[NAT66-DST-' ~ rule %} @@ -52,6 +54,12 @@ {% if src_prefix is vyos_defined %} {% set output = output ~ ' ' ~ src_prefix %} {% endif %} +{% if dst_prefix is vyos_defined %} +{% set output = output ~ ' ' ~ dst_prefix %} +{% endif %} +{% if source_address is vyos_defined %} +{% set output = output ~ ' ' ~ source_address %} +{% endif %} {% if dest_address is vyos_defined %} {% set output = output ~ ' ' ~ dest_address %} {% endif %} diff --git a/data/templates/frr/bgpd.frr.j2 b/data/templates/frr/bgpd.frr.j2 index 7029f39af..2ab7c8596 100644 --- a/data/templates/frr/bgpd.frr.j2 +++ b/data/templates/frr/bgpd.frr.j2 @@ -231,7 +231,7 @@ {% endif %} {% endmacro %} ! -router bgp {{ local_as }} {{ 'vrf ' ~ vrf if vrf is vyos_defined }} +router bgp {{ system_as }} {{ 'vrf ' ~ vrf if vrf is vyos_defined }} {% if parameters.ebgp_requires_policy is vyos_defined %} bgp ebgp-requires-policy {% else %} diff --git a/data/templates/macsec/wpa_supplicant.conf.j2 b/data/templates/macsec/wpa_supplicant.conf.j2 index d2529c50d..1f7ba16f4 100644 --- a/data/templates/macsec/wpa_supplicant.conf.j2 +++ b/data/templates/macsec/wpa_supplicant.conf.j2 @@ -47,6 +47,12 @@ network={ # 1: Integrity only macsec_integ_only={{ '0' if security.encrypt is vyos_defined else '1' }} + # macsec_csindex: IEEE 802.1X/MACsec cipher suite + # 0 = GCM-AES-128 + # 1 = GCM-AES-256 +{# security.cipher is a mandatory key #} + macsec_csindex={{ '1' if security.cipher is vyos_defined('gcm-aes-256') else '0' }} + {% if security.encrypt is vyos_defined %} # mka_cak, mka_ckn, and mka_priority: IEEE 802.1X/MACsec pre-shared key mode # This allows to configure MACsec with a pre-shared key using a (CAK,CKN) pair. @@ -62,12 +68,6 @@ network={ # mka_priority (Priority of MKA Actor) is in 0..255 range with 255 being # default priority mka_priority={{ security.mka.priority }} - - # macsec_csindex: IEEE 802.1X/MACsec cipher suite - # 0 = GCM-AES-128 - # 1 = GCM-AES-256 -{# security.cipher is a mandatory key #} - macsec_csindex={{ '1' if security.cipher is vyos_defined('gcm-aes-256') else '0' }} {% endif %} {% if security.replay_window is vyos_defined %} diff --git a/interface-definitions/include/bgp/protocol-common-config.xml.i b/interface-definitions/include/bgp/protocol-common-config.xml.i index c1b465e43..d2bcea62a 100644 --- a/interface-definitions/include/bgp/protocol-common-config.xml.i +++ b/interface-definitions/include/bgp/protocol-common-config.xml.i @@ -896,7 +896,7 @@ </tagNode> </children> </node> -<leafNode name="local-as"> +<leafNode name="system-as"> <properties> <help>Autonomous System Number (ASN)</help> <valueHelp> diff --git a/interface-definitions/include/version/bgp-version.xml.i b/interface-definitions/include/version/bgp-version.xml.i index 15bc5abd4..ced49e729 100644 --- a/interface-definitions/include/version/bgp-version.xml.i +++ b/interface-definitions/include/version/bgp-version.xml.i @@ -1,3 +1,3 @@ <!-- include start from include/version/bgp-version.xml.i --> -<syntaxVersion component='bgp' version='2'></syntaxVersion> +<syntaxVersion component='bgp' version='3'></syntaxVersion> <!-- include end --> diff --git a/interface-definitions/nat66.xml.in b/interface-definitions/nat66.xml.in index b47f653c6..ac3198f45 100644 --- a/interface-definitions/nat66.xml.in +++ b/interface-definitions/nat66.xml.in @@ -49,6 +49,30 @@ </completionHelp> </properties> </leafNode> + <node name="destination"> + <properties> + <help>IPv6 destination prefix options</help> + </properties> + <children> + <leafNode name="prefix"> + <properties> + <help>IPv6 prefix to be translated</help> + <valueHelp> + <format>ipv6net</format> + <description>IPv6 prefix</description> + </valueHelp> + <valueHelp> + <format>!ipv6net</format> + <description>Match everything except the specified IPv6 prefix</description> + </valueHelp> + <constraint> + <validator name="ipv6-prefix"/> + <validator name="ipv6-prefix-exclude"/> + </constraint> + </properties> + </leafNode> + </children> + </node> <node name="source"> <properties> <help>IPv6 source prefix options</help> @@ -61,8 +85,13 @@ <format>ipv6net</format> <description>IPv6 prefix</description> </valueHelp> + <valueHelp> + <format>!ipv6net</format> + <description>Match everything except the specified IPv6 prefix</description> + </valueHelp> <constraint> <validator name="ipv6-prefix"/> + <validator name="ipv6-prefix-exclude"/> </constraint> </properties> </leafNode> @@ -164,9 +193,53 @@ <format>ipv6net</format> <description>IPv6 prefix</description> </valueHelp> + <valueHelp> + <format>!ipv6</format> + <description>Match everything except the specified IPv6 address</description> + </valueHelp> + <valueHelp> + <format>!ipv6net</format> + <description>Match everything except the specified IPv6 prefix</description> + </valueHelp> + <constraint> + <validator name="ipv6-address"/> + <validator name="ipv6-prefix"/> + <validator name="ipv6-address-exclude"/> + <validator name="ipv6-prefix-exclude"/> + </constraint> + </properties> + </leafNode> + </children> + </node> + <node name="source"> + <properties> + <help>IPv6 source prefix options</help> + </properties> + <children> + <leafNode name="address"> + <properties> + <help>IPv6 address or prefix to be translated</help> + <valueHelp> + <format>ipv6</format> + <description>IPv6 address</description> + </valueHelp> + <valueHelp> + <format>ipv6net</format> + <description>IPv6 prefix</description> + </valueHelp> + <valueHelp> + <format>!ipv6</format> + <description>Match everything except the specified IPv6 address</description> + </valueHelp> + <valueHelp> + <format>!ipv6net</format> + <description>Match everything except the specified IPv6 prefix</description> + </valueHelp> <constraint> <validator name="ipv6-address"/> <validator name="ipv6-prefix"/> + <validator name="ipv6-address-exclude"/> + <validator name="ipv6-prefix-exclude"/> </constraint> </properties> </leafNode> diff --git a/python/vyos/configdict.py b/python/vyos/configdict.py index 20cc7de2a..8f822a97d 100644 --- a/python/vyos/configdict.py +++ b/python/vyos/configdict.py @@ -303,8 +303,8 @@ def is_source_interface(conf, interface, intftype=None): for it in intftype: base = ['interfaces', it] for intf in conf.list_nodes(base): - lower_intf = base + [intf, 'source-interface'] - if conf.exists(lower_intf) and interface in conf.return_values(lower_intf): + src_intf = base + [intf, 'source-interface'] + if conf.exists(src_intf) and interface in conf.return_values(src_intf): ret_val = intf break diff --git a/python/vyos/configverify.py b/python/vyos/configverify.py index ac56da204..2ab3cb408 100644 --- a/python/vyos/configverify.py +++ b/python/vyos/configverify.py @@ -284,15 +284,16 @@ def verify_source_interface(config): raise ConfigError('Specified source-interface {source_interface} does ' 'not exist'.format(**config)) + src_ifname = config['source_interface'] if 'source_interface_is_bridge_member' in config: - raise ConfigError('Invalid source-interface {source_interface}. Interface ' - 'is already a member of bridge ' - '{source_interface_is_bridge_member}'.format(**config)) + bridge_name = next(iter(config['source_interface_is_bridge_member'])) + raise ConfigError(f'Invalid source-interface "{src_ifname}". Interface ' + f'is already a member of bridge "{bridge_name}"!') if 'source_interface_is_bond_member' in config: - raise ConfigError('Invalid source-interface {source_interface}. Interface ' - 'is already a member of bond ' - '{source_interface_is_bond_member}'.format(**config)) + bond_name = next(iter(config['source_interface_is_bond_member'])) + raise ConfigError(f'Invalid source-interface "{src_ifname}". Interface ' + f'is already a member of bond "{bond_name}"!') def verify_dhcpv6(config): """ diff --git a/smoketest/scripts/cli/test_interfaces_macsec.py b/smoketest/scripts/cli/test_interfaces_macsec.py index e5e5a558e..f141cc6d3 100755 --- a/smoketest/scripts/cli/test_interfaces_macsec.py +++ b/smoketest/scripts/cli/test_interfaces_macsec.py @@ -28,6 +28,8 @@ from vyos.util import read_file from vyos.util import get_interface_config from vyos.util import process_named_running +PROCESS_NAME = 'wpa_supplicant' + def get_config_value(interface, key): tmp = read_file(f'/run/wpa_supplicant/{interface}.conf') tmp = re.findall(r'\n?{}=(.*)'.format(key), tmp) @@ -55,6 +57,10 @@ class MACsecInterfaceTest(BasicInterfaceTest.TestCase): # call base-classes classmethod super(MACsecInterfaceTest, cls).setUpClass() + def tearDown(self): + super().tearDown() + self.assertFalse(process_named_running(PROCESS_NAME)) + def test_macsec_encryption(self): # MACsec can be operating in authentication and encryption mode - both # using different mandatory settings, lets test encryption as the basic @@ -96,28 +102,29 @@ class MACsecInterfaceTest(BasicInterfaceTest.TestCase): self.cli_commit() tmp = get_config_value(src_interface, 'macsec_integ_only') - self.assertTrue("0" in tmp) + self.assertIn("0", tmp) tmp = get_config_value(src_interface, 'mka_cak') - self.assertTrue(mak_cak in tmp) + self.assertIn(mak_cak, tmp) tmp = get_config_value(src_interface, 'mka_ckn') - self.assertTrue(mak_ckn in tmp) + self.assertIn(mak_ckn, tmp) # check that the default priority of 255 is programmed tmp = get_config_value(src_interface, 'mka_priority') - self.assertTrue("255" in tmp) + self.assertIn("255", tmp) tmp = get_config_value(src_interface, 'macsec_replay_window') - self.assertTrue(replay_window in tmp) + self.assertIn(replay_window, tmp) tmp = read_file(f'/sys/class/net/{interface}/mtu') self.assertEqual(tmp, '1460') - # Check for running process - self.assertTrue(process_named_running('wpa_supplicant')) + # Check for running process + self.assertTrue(process_named_running(PROCESS_NAME)) def test_macsec_gcm_aes_128(self): + src_interface = 'eth0' interface = 'macsec1' cipher = 'gcm-aes-128' self.cli_set(self._base_path + [interface]) @@ -125,7 +132,7 @@ class MACsecInterfaceTest(BasicInterfaceTest.TestCase): # check validate() - source interface is mandatory with self.assertRaises(ConfigSessionError): self.cli_commit() - self.cli_set(self._base_path + [interface, 'source-interface', 'eth0']) + self.cli_set(self._base_path + [interface, 'source-interface', src_interface]) # check validate() - cipher is mandatory with self.assertRaises(ConfigSessionError): @@ -138,7 +145,15 @@ class MACsecInterfaceTest(BasicInterfaceTest.TestCase): self.assertIn(interface, interfaces()) self.assertEqual(cipher, get_cipher(interface)) + # check that we use the new macsec_csindex option (T4537) + tmp = get_config_value(src_interface, 'macsec_csindex') + self.assertIn("0", tmp) + + # Check for running process + self.assertTrue(process_named_running(PROCESS_NAME)) + def test_macsec_gcm_aes_256(self): + src_interface = 'eth0' interface = 'macsec4' cipher = 'gcm-aes-256' self.cli_set(self._base_path + [interface]) @@ -146,7 +161,7 @@ class MACsecInterfaceTest(BasicInterfaceTest.TestCase): # check validate() - source interface is mandatory with self.assertRaises(ConfigSessionError): self.cli_commit() - self.cli_set(self._base_path + [interface, 'source-interface', 'eth0']) + self.cli_set(self._base_path + [interface, 'source-interface', src_interface]) # check validate() - cipher is mandatory with self.assertRaises(ConfigSessionError): @@ -158,6 +173,13 @@ class MACsecInterfaceTest(BasicInterfaceTest.TestCase): self.assertIn(interface, interfaces()) self.assertEqual(cipher, get_cipher(interface)) + # check that we use the new macsec_csindex option (T4537) + tmp = get_config_value(src_interface, 'macsec_csindex') + self.assertIn("1", tmp) + + # Check for running process + self.assertTrue(process_named_running(PROCESS_NAME)) + def test_macsec_source_interface(self): # Ensure source-interface can bot be part of any other bond or bridge @@ -186,6 +208,9 @@ class MACsecInterfaceTest(BasicInterfaceTest.TestCase): self.cli_commit() self.assertIn(interface, interfaces()) + # Check for running process + self.assertTrue(process_named_running(PROCESS_NAME)) + if __name__ == '__main__': - unittest.main(verbosity=2) + unittest.main(verbosity=2, failfast=True) diff --git a/smoketest/scripts/cli/test_protocols_bgp.py b/smoketest/scripts/cli/test_protocols_bgp.py index 009dbc803..cefaad64a 100755 --- a/smoketest/scripts/cli/test_protocols_bgp.py +++ b/smoketest/scripts/cli/test_protocols_bgp.py @@ -46,7 +46,7 @@ neighbor_config = { 'shutdown' : '', 'cap_over' : '', 'ttl_security' : '5', - 'local_as' : '300', + 'system_as' : '300', 'route_map_in' : route_map_in, 'route_map_out' : route_map_out, 'no_send_comm_ext' : '', @@ -87,7 +87,7 @@ neighbor_config = { 'shutdown' : '', 'cap_over' : '', 'ttl_security' : '5', - 'local_as' : '300', + 'system_as' : '300', 'solo' : '', 'route_map_in' : route_map_in, 'route_map_out' : route_map_out, @@ -131,7 +131,7 @@ peer_group_config = { 'remote_as' : '200', 'shutdown' : '', 'no_cap_nego' : '', - 'local_as' : '300', + 'system_as' : '300', 'pfx_list_in' : prefix_list_in, 'pfx_list_out' : prefix_list_out, 'no_send_comm_ext' : '', @@ -177,7 +177,7 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase): cls.cli_delete(cls, ['policy']) def setUp(self): - self.cli_set(base_path + ['local-as', ASN]) + self.cli_set(base_path + ['system-as', ASN]) def tearDown(self): self.cli_delete(['vrf']) @@ -266,12 +266,12 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase): self.cli_set(base_path + ['parameters', 'router-id', router_id]) self.cli_set(base_path + ['parameters', 'log-neighbor-changes']) - # Local AS number MUST be defined - as this is set in setUp() we remove + # System AS number MUST be defined - as this is set in setUp() we remove # this once for testing of the proper error - self.cli_delete(base_path + ['local-as']) + self.cli_delete(base_path + ['system-as']) with self.assertRaises(ConfigSessionError): self.cli_commit() - self.cli_set(base_path + ['local-as', ASN]) + self.cli_set(base_path + ['system-as', ASN]) # Default local preference (higher = more preferred, default value is 100) self.cli_set(base_path + ['parameters', 'default', 'local-pref', local_pref]) @@ -760,13 +760,13 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase): # templates and Jinja2 FRR template. table = '1000' - self.cli_set(base_path + ['local-as', ASN]) + self.cli_set(base_path + ['system-as', ASN]) # testing only one AFI is sufficient as it's generic code for vrf in vrfs: vrf_base = ['vrf', 'name', vrf] self.cli_set(vrf_base + ['table', table]) - self.cli_set(vrf_base + ['protocols', 'bgp', 'local-as', ASN]) + self.cli_set(vrf_base + ['protocols', 'bgp', 'system-as', ASN]) self.cli_set(vrf_base + ['protocols', 'bgp', 'parameters', 'router-id', router_id]) self.cli_set(vrf_base + ['protocols', 'bgp', 'route-map', route_map_in]) table = str(int(table) + 1000) @@ -804,7 +804,7 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase): confed_id = str(int(ASN) + 1) confed_asns = '10 20 30 40' - self.cli_set(base_path + ['local-as', ASN]) + self.cli_set(base_path + ['system-as', ASN]) self.cli_set(base_path + ['parameters', 'router-id', router_id]) self.cli_set(base_path + ['parameters', 'confederation', 'identifier', confed_id]) for asn in confed_asns.split(): @@ -825,7 +825,7 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase): remote_asn = str(int(ASN) + 10) interface = 'eth0' - self.cli_set(base_path + ['local-as', ASN]) + self.cli_set(base_path + ['system-as', ASN]) self.cli_set(base_path + ['neighbor', interface, 'address-family', 'ipv6-unicast']) self.cli_set(base_path + ['neighbor', interface, 'interface', 'v6only', 'remote-as', remote_asn]) @@ -850,7 +850,7 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase): rt_export = f'{neighbor}:1002 1.2.3.4:567' rt_import = f'{neighbor}:1003 500:100' - self.cli_set(base_path + ['local-as', ASN]) + self.cli_set(base_path + ['system-as', ASN]) # testing only one AFI is sufficient as it's generic code for afi in ['ipv4-unicast', 'ipv6-unicast']: self.cli_set(base_path + ['address-family', afi, 'export', 'vpn']) @@ -889,7 +889,7 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase): peer_group = 'bar' interface = 'eth0' - self.cli_set(base_path + ['local-as', ASN]) + self.cli_set(base_path + ['system-as', ASN]) self.cli_set(base_path + ['neighbor', neighbor, 'remote-as', remote_asn]) self.cli_set(base_path + ['neighbor', neighbor, 'peer-group', peer_group]) self.cli_set(base_path + ['peer-group', peer_group, 'remote-as', remote_asn]) @@ -929,7 +929,7 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase): remote_asn = '500' local_asn = '400' - self.cli_set(base_path + ['local-as', ASN]) + self.cli_set(base_path + ['system-as', ASN]) self.cli_set(base_path + ['neighbor', neighbor, 'remote-as', ASN]) self.cli_set(base_path + ['neighbor', neighbor, 'local-as', local_asn]) diff --git a/src/conf_mode/interfaces-macsec.py b/src/conf_mode/interfaces-macsec.py index 65b0612ea..870049a88 100755 --- a/src/conf_mode/interfaces-macsec.py +++ b/src/conf_mode/interfaces-macsec.py @@ -22,6 +22,7 @@ from sys import exit from vyos.config import Config from vyos.configdict import get_interface_dict from vyos.configdict import is_node_changed +from vyos.configdict import is_source_interface from vyos.configverify import verify_vrf from vyos.configverify import verify_address from vyos.configverify import verify_bridge_delete @@ -65,6 +66,10 @@ def get_config(config=None): if is_node_changed(conf, base + [ifname, 'source_interface']): macsec.update({'shutdown_required': {}}) + if 'source_interface' in macsec: + tmp = is_source_interface(conf, macsec['source_interface'], 'macsec') + if tmp and tmp != ifname: macsec.update({'is_source_interface' : tmp}) + return macsec @@ -97,6 +102,12 @@ def verify(macsec): # gcm-aes-128 requires a 128bit long key - 64 characters (string) = 32byte = 256bit raise ConfigError('gcm-aes-128 requires a 256bit long key!') + if 'is_source_interface' in macsec: + tmp = macsec['is_source_interface'] + src_ifname = macsec['source_interface'] + raise ConfigError(f'Can not use source-interface "{src_ifname}", it already ' \ + f'belongs to interface "{tmp}"!') + if 'source_interface' in macsec: # MACsec adds a 40 byte overhead (32 byte MACsec + 8 bytes VLAN 802.1ad # and 802.1q) - we need to check the underlaying MTU if our configured diff --git a/src/conf_mode/protocols_bgp.py b/src/conf_mode/protocols_bgp.py index 7d3687094..87456f00b 100755 --- a/src/conf_mode/protocols_bgp.py +++ b/src/conf_mode/protocols_bgp.py @@ -121,8 +121,8 @@ def verify(bgp): 'dependent VRF instance(s) exist!') return None - if 'local_as' not in bgp: - raise ConfigError('BGP local-as number must be defined!') + if 'system_as' not in bgp: + raise ConfigError('BGP system-as number must be defined!') # Common verification for both peer-group and neighbor statements for neighbor in ['neighbor', 'peer_group']: @@ -147,8 +147,8 @@ def verify(bgp): # Neighbor local-as override can not be the same as the local-as # we use for this BGP instane! asn = list(peer_config['local_as'].keys())[0] - if asn == bgp['local_as']: - raise ConfigError('Cannot have local-as same as BGP AS number') + if asn == bgp['system_as']: + raise ConfigError('Cannot have local-as same as system-as number') # Neighbor AS specified for local-as and remote-as can not be the same if dict_search('remote_as', peer_config) == asn: @@ -216,7 +216,7 @@ def verify(bgp): # Local-AS allowed only for EBGP peers if 'local_as' in peer_config: remote_as = verify_remote_as(peer_config, bgp) - if remote_as == bgp['local_as']: + if remote_as == bgp['system_as']: raise ConfigError(f'local-as configured for "{peer}", allowed only for eBGP peers!') for afi in ['ipv4_unicast', 'ipv4_multicast', 'ipv4_labeled_unicast', 'ipv4_flowspec', @@ -279,12 +279,12 @@ def verify(bgp): verify_route_map(afi_config['route_map'][tmp], bgp) if 'route_reflector_client' in afi_config: - if 'remote_as' in peer_config and peer_config['remote_as'] != 'internal' and peer_config['remote_as'] != bgp['local_as']: + if 'remote_as' in peer_config and peer_config['remote_as'] != 'internal' and peer_config['remote_as'] != bgp['system_as']: raise ConfigError('route-reflector-client only supported for iBGP peers') else: if 'peer_group' in peer_config: peer_group_as = dict_search(f'peer_group.{peer_group}.remote_as', bgp) - if peer_group_as != None and peer_group_as != 'internal' and peer_group_as != bgp['local_as']: + if peer_group_as != None and peer_group_as != 'internal' and peer_group_as != bgp['system_as']: raise ConfigError('route-reflector-client only supported for iBGP peers') # Throw an error if a peer group is not configured for allow range diff --git a/src/migration-scripts/bgp/2-to-3 b/src/migration-scripts/bgp/2-to-3 new file mode 100755 index 000000000..7ced0a3b0 --- /dev/null +++ b/src/migration-scripts/bgp/2-to-3 @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2022 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/>. + +# T4257: Discussion on changing BGP autonomous system number syntax + +from sys import argv +from sys import exit + +from vyos.configtree import ConfigTree + +if (len(argv) < 1): + 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) + +# Check if BGP is even configured. Then check if local-as exists, then add the system-as, then remove the local-as. This is for global configuration. +if config.exists(['protocols', 'bgp']): + if config.exists(['protocols', 'bgp', 'local-as']): + config.rename(['protocols', 'bgp', 'local-as'], 'system-as') + +# Check if vrf names are configured. Then check if local-as exists inside of a name, then add the system-as, then remove the local-as. This is for vrf configuration. +if config.exists(['vrf', 'name']): + for vrf in config.list_nodes(['vrf', 'name']): + if config.exists(['vrf', f'name {vrf}', 'protocols', 'bgp', 'local-as']): + config.rename(['vrf', f'name {vrf}', 'protocols', 'bgp', 'local-as'], 'system-as') + +try: + with open(file_name, 'w') as f: + f.write(config.to_string()) +except OSError as e: + print(f'Failed to save the modified config: {e}') + exit(1) diff --git a/src/validators/ipv6-address-exclude b/src/validators/ipv6-address-exclude new file mode 100755 index 000000000..be1d3db25 --- /dev/null +++ b/src/validators/ipv6-address-exclude @@ -0,0 +1,7 @@ +#!/bin/sh +arg="$1" +if [ "${arg:0:1}" != "!" ]; then + exit 1 +fi +path=$(dirname "$0") +${path}/ipv6-address "${arg:1}" diff --git a/src/validators/ipv6-prefix-exclude b/src/validators/ipv6-prefix-exclude new file mode 100755 index 000000000..6fa4f1d8d --- /dev/null +++ b/src/validators/ipv6-prefix-exclude @@ -0,0 +1,7 @@ +#!/bin/sh +arg="$1" +if [ "${arg:0:1}" != "!" ]; then + exit 1 +fi +path=$(dirname "$0") +${path}/ipv6-prefix "${arg:1}" |