diff options
| -rw-r--r-- | data/templates/firewall/nftables-policy.tmpl | 10 | ||||
| -rw-r--r-- | data/templates/firewall/nftables.tmpl | 14 | ||||
| -rw-r--r-- | interface-definitions/policy-local-route.xml.in | 109 | ||||
| -rw-r--r-- | python/vyos/firewall.py | 3 | ||||
| -rw-r--r-- | python/vyos/template.py | 13 | ||||
| -rwxr-xr-x | smoketest/scripts/cli/test_policy.py | 258 | ||||
| -rwxr-xr-x | src/conf_mode/policy-local-route.py | 145 | ||||
| -rwxr-xr-x | src/helpers/vyos_net_name | 21 | 
8 files changed, 476 insertions, 97 deletions
diff --git a/data/templates/firewall/nftables-policy.tmpl b/data/templates/firewall/nftables-policy.tmpl index 484b6f203..905ffcd09 100644 --- a/data/templates/firewall/nftables-policy.tmpl +++ b/data/templates/firewall/nftables-policy.tmpl @@ -25,11 +25,7 @@ table ip mangle {          {{ rule_conf | nft_rule(route_text, rule_id, 'ip') }}  {%       endfor %}  {%     endif %} -{%     if conf.default_action is defined %} -        counter {{ conf.default_action | nft_action }} comment "{{ name_text }} default-action {{ conf.default_action }}" -{%     else %} -        counter return -{%     endif %} +        {{ conf | nft_default_rule(route_text) }}      }  {%   endfor %}  {%- endif %} @@ -52,9 +48,7 @@ table ip6 mangle {          {{ rule_conf | nft_rule(route_text, rule_id, 'ip6') }}  {%       endfor %}  {%     endif %} -{%     if conf.default_action is defined %} -        counter {{ conf.default_action | nft_action }} comment "{{ name_text }} default-action {{ conf.default_action }}" -{%     endif %} +        {{ conf | nft_default_rule(route_text) }}      }  {%   endfor %}  {% endif %} diff --git a/data/templates/firewall/nftables.tmpl b/data/templates/firewall/nftables.tmpl index 81b2c0b98..33c821e84 100644 --- a/data/templates/firewall/nftables.tmpl +++ b/data/templates/firewall/nftables.tmpl @@ -32,18 +32,13 @@ table ip filter {  {% endif %}  {% if name is defined %}  {%   for name_text, conf in name.items() %} -{%     set default_log = 'log' if 'enable_default_log' in conf else '' %}      chain {{ name_text }} {  {%     if conf.rule is defined %}  {%       for rule_id, rule_conf in conf.rule.items() if rule_conf.disable is not defined %}          {{ rule_conf | nft_rule(name_text, rule_id) }}  {%       endfor %}  {%     endif %} -{%     if conf.default_action is defined %} -        counter {{ default_log }} {{ conf.default_action | nft_action }} comment "{{ name_text }} default-action {{ conf.default_action }}" -{%     else %} -        return -{%     endif %} +        {{ conf | nft_default_rule(name_text) }}      }  {%   endfor %}  {% endif %} @@ -87,18 +82,13 @@ table ip6 filter {  {% endif %}  {% if ipv6_name is defined %}  {%   for name_text, conf in ipv6_name.items() %} -{%     set default_log = 'log' if 'enable_default_log' in conf else '' %}      chain {{ name_text }} {  {%     if conf.rule is defined %}  {%       for rule_id, rule_conf in conf.rule.items() if rule_conf.disable is not defined %}          {{ rule_conf | nft_rule(name_text, rule_id, 'ip6') }}  {%       endfor %}  {%     endif %} -{%     if conf.default_action is defined %} -        counter {{ default_log }} {{ conf.default_action | nft_action }} comment "{{ name_text }} default-action {{ conf.default_action }}" -{%     else %} -        return -{%     endif %} +        {{ conf | nft_default_rule(name_text) }}      }  {%   endfor %}  {% endif %} diff --git a/interface-definitions/policy-local-route.xml.in b/interface-definitions/policy-local-route.xml.in index 86445b65d..11b1e04d9 100644 --- a/interface-definitions/policy-local-route.xml.in +++ b/interface-definitions/policy-local-route.xml.in @@ -14,7 +14,7 @@                <valueHelp>                  <!-- table main with prio 32766 -->                  <format>u32:1-32765</format> -                <description>Local-route rule number (1-219)</description> +                <description>Local-route rule number (1-32765)</description>                </valueHelp>                <constraint>                  <validator name="numeric" argument="--range 1-32765"/> @@ -70,6 +70,113 @@                    <multi/>                  </properties>                </leafNode> +              <leafNode name="destination"> +                <properties> +                  <help>Destination address or prefix</help> +                  <valueHelp> +                    <format>ipv4</format> +                    <description>Address to match against</description> +                  </valueHelp> +                  <valueHelp> +                    <format>ipv4net</format> +                    <description>Prefix to match against</description> +                  </valueHelp> +                  <constraint> +                    <validator name="ipv4-address"/> +                    <validator name="ip-prefix"/> +                  </constraint> +                  <multi/> +                </properties> +              </leafNode> +            </children> +          </tagNode> +        </children> +      </node> +      <node name="local-route6" owner="${vyos_conf_scripts_dir}/policy-local-route.py"> +        <properties> +          <help>IPv6 policy route of local traffic</help> +        </properties> +        <children> +          <tagNode name="rule"> +            <properties> +              <help>IPv6 policy local-route rule set number</help> +              <valueHelp> +                <!-- table main with prio 32766 --> +                <format>u32:1-32765</format> +                <description>Local-route rule number (1-32765)</description> +              </valueHelp> +              <constraint> +                <validator name="numeric" argument="--range 1-32765"/> +              </constraint> +            </properties> +            <children> +              <node name="set"> +                <properties> +                  <help>Packet modifications</help> +                </properties> +                <children> +                  <leafNode name="table"> +                    <properties> +                      <help>Routing table to forward packet with</help> +                      <valueHelp> +                        <format>u32:1-200</format> +                        <description>Table number</description> +                      </valueHelp> +                      <completionHelp> +                        <list>main</list> +                      </completionHelp> +                    </properties> +                  </leafNode> +                </children> +              </node> +              <leafNode name="fwmark"> +                <properties> +                  <help>Match fwmark value</help> +                  <valueHelp> +                    <format>u32:1-2147483647</format> +                    <description>Address to match against</description> +                  </valueHelp> +                  <constraint> +                    <validator name="numeric" argument="--range 1-2147483647"/> +                  </constraint> +                </properties> +              </leafNode> +              <leafNode name="source"> +                <properties> +                  <help>Source address or prefix</help> +                  <valueHelp> +                    <format>ipv4</format> +                    <description>Address to match against</description> +                  </valueHelp> +                  <valueHelp> +                    <format>ipv4net</format> +                    <description>Prefix to match against</description> +                  </valueHelp> +                  <constraint> +                    <validator name="ipv6-address"/> +                    <validator name="ipv6-prefix"/> +                  </constraint> +                  <multi/> +                </properties> +              </leafNode> +              <leafNode name="destination"> +                <properties> +                  <help>Destination address or prefix</help> +                  <valueHelp> +                    <format>ipv6</format> +                    <description>Address to match against</description> +                  </valueHelp> +                  <valueHelp> +                    <format>ipv6net</format> +                    <description>Prefix to match against</description> +                  </valueHelp> +                  <constraint> +                    <validator name="ipv6-address"/> +                    <validator name="ipv6-prefix"/> +                  </constraint> +                  <multi/> +                </properties> +              </leafNode>              </children>            </tagNode>          </children> diff --git a/python/vyos/firewall.py b/python/vyos/firewall.py index 2ab78ff18..808e90e38 100644 --- a/python/vyos/firewall.py +++ b/python/vyos/firewall.py @@ -121,7 +121,8 @@ def parse_rule(rule_conf, fw_name, rule_id, ip_name):                      output.append(f'{proto} {prefix}port $P_{group_name}')      if 'log' in rule_conf and rule_conf['log'] == 'enable': -        output.append('log') +        action = rule_conf['action'] if 'action' in rule_conf else 'accept' +        output.append(f'log prefix "[{fw_name[:19]}-{rule_id}-{action[:1].upper()}] "')      if 'hop_limit' in rule_conf:          operators = {'eq': '==', 'gt': '>', 'lt': '<'} diff --git a/python/vyos/template.py b/python/vyos/template.py index 6f65c6c98..633b28ade 100644 --- a/python/vyos/template.py +++ b/python/vyos/template.py @@ -516,6 +516,19 @@ def nft_rule(rule_conf, fw_name, rule_id, ip_name='ip'):      from vyos.firewall import parse_rule      return parse_rule(rule_conf, fw_name, rule_id, ip_name) +@register_filter('nft_default_rule') +def nft_default_rule(fw_conf, fw_name): +    output = ['counter'] +    default_action = fw_conf.get('default_action', 'accept') + +    if 'enable_default_log' in fw_conf: +        action_suffix = default_action[:1].upper() +        output.append(f'log prefix "[{fw_name[:19]}-default-{action_suffix}] "') + +    output.append(nft_action(default_action)) +    output.append(f'comment "{fw_name} default-action {default_action}"') +    return " ".join(output) +  @register_filter('nft_state_policy')  def nft_state_policy(conf, state, ipv6=False):      out = [f'ct state {state}'] diff --git a/smoketest/scripts/cli/test_policy.py b/smoketest/scripts/cli/test_policy.py index 5844e1ec1..9f9c11fb5 100755 --- a/smoketest/scripts/cli/test_policy.py +++ b/smoketest/scripts/cli/test_policy.py @@ -1143,10 +1143,8 @@ class TestPolicy(VyOSUnitTestSHIM.TestCase):          50:	from 203.0.113.2 lookup 23          """          tmp = cmd('ip rule show prio 50') -        original = original.split() -        tmp = tmp.split() -        self.assertEqual(tmp, original) +        self.assertEqual(sort_ip(tmp), sort_ip(original))      # Test set table for fwmark      def test_fwmark_table_id(self): @@ -1168,10 +1166,31 @@ class TestPolicy(VyOSUnitTestSHIM.TestCase):          101:    from all fwmark 0x18 lookup 154          """          tmp = cmd('ip rule show prio 101') -        original = original.split() -        tmp = tmp.split() -        self.assertEqual(tmp, original) +        self.assertEqual(sort_ip(tmp), sort_ip(original)) + +    # Test set table for destination +    def test_destination_table_id(self): +        path = base_path + ['local-route'] + +        dst = '203.0.113.1' +        rule = '102' +        table = '154' + +        self.cli_set(path + ['rule', rule, 'set', 'table', table]) +        self.cli_set(path + ['rule', rule, 'destination', dst]) + +        self.cli_commit() + +        # Check generated configuration + +        # Expected values +        original = """ +        102:    from all to 203.0.113.1 lookup 154 +        """ +        tmp = cmd('ip rule show prio 102') + +        self.assertEqual(sort_ip(tmp), sort_ip(original))      # Test set table for sources with fwmark      def test_fwmark_sources_table_id(self): @@ -1196,10 +1215,231 @@ class TestPolicy(VyOSUnitTestSHIM.TestCase):          100:	from 203.0.113.12 fwmark 0x17 lookup 150          """          tmp = cmd('ip rule show prio 100') -        original = original.split() -        tmp = tmp.split() -        self.assertEqual(tmp, original) +        self.assertEqual(sort_ip(tmp), sort_ip(original)) + +    # Test set table for sources and destinations with fwmark +    def test_fwmark_sources_destination_table_id(self): +        path = base_path + ['local-route'] + +        sources = ['203.0.113.11', '203.0.113.12'] +        destinations = ['203.0.113.13', '203.0.113.15'] +        fwmk = '23' +        rule = '103' +        table = '150' +        for src in sources: +            for dst in destinations: +                self.cli_set(path + ['rule', rule, 'set', 'table', table]) +                self.cli_set(path + ['rule', rule, 'source', src]) +                self.cli_set(path + ['rule', rule, 'destination', dst]) +                self.cli_set(path + ['rule', rule, 'fwmark', fwmk]) + +        self.cli_commit() + +        # Check generated configuration + +        # Expected values +        original = """ +        103:	from 203.0.113.11 to 203.0.113.13 fwmark 0x17 lookup 150 +        103:	from 203.0.113.11 to 203.0.113.15 fwmark 0x17 lookup 150 +        103:	from 203.0.113.12 to 203.0.113.13 fwmark 0x17 lookup 150 +        103:	from 203.0.113.12 to 203.0.113.15 fwmark 0x17 lookup 150 +        """ +        tmp = cmd('ip rule show prio 103') + +        self.assertEqual(sort_ip(tmp), sort_ip(original)) + +    # Test set table ipv6 for some sources ipv6 +    def test_ipv6_table_id(self): +        path = base_path + ['local-route6'] + +        sources = ['2001:db8:123::/48', '2001:db8:126::/48'] +        rule = '50' +        table = '23' +        for src in sources: +            self.cli_set(path + ['rule', rule, 'set', 'table', table]) +            self.cli_set(path + ['rule', rule, 'source', src]) + +        self.cli_commit() + +        # Check generated configuration + +        # Expected values +        original = """ +        50:	from 2001:db8:123::/48 lookup 23 +        50:	from 2001:db8:126::/48 lookup 23 +        """ +        tmp = cmd('ip -6 rule show prio 50') + +        self.assertEqual(sort_ip(tmp), sort_ip(original)) + +    # Test set table for fwmark ipv6 +    def test_fwmark_ipv6_table_id(self): +        path = base_path + ['local-route6'] + +        fwmk = '24' +        rule = '100' +        table = '154' + +        self.cli_set(path + ['rule', rule, 'set', 'table', table]) +        self.cli_set(path + ['rule', rule, 'fwmark', fwmk]) + +        self.cli_commit() + +        # Check generated configuration + +        # Expected values +        original = """ +        100:    from all fwmark 0x18 lookup 154 +        """ +        tmp = cmd('ip -6 rule show prio 100') + +        self.assertEqual(sort_ip(tmp), sort_ip(original)) + +    # Test set table for destination ipv6 +    def test_destination_ipv6_table_id(self): +        path = base_path + ['local-route6'] + +        dst = '2001:db8:1337::/126' +        rule = '101' +        table = '154' + +        self.cli_set(path + ['rule', rule, 'set', 'table', table]) +        self.cli_set(path + ['rule', rule, 'destination', dst]) + +        self.cli_commit() + +        # Check generated configuration + +        # Expected values +        original = """ +        101:    from all to 2001:db8:1337::/126 lookup 154 +        """ +        tmp = cmd('ip -6 rule show prio 101') + +        self.assertEqual(sort_ip(tmp), sort_ip(original)) + +    # Test set table for sources with fwmark ipv6 +    def test_fwmark_sources_ipv6_table_id(self): +        path = base_path + ['local-route6'] + +        sources = ['2001:db8:1338::/126', '2001:db8:1339::/126'] +        fwmk = '23' +        rule = '102' +        table = '150' +        for src in sources: +            self.cli_set(path + ['rule', rule, 'set', 'table', table]) +            self.cli_set(path + ['rule', rule, 'source', src]) +            self.cli_set(path + ['rule', rule, 'fwmark', fwmk]) + +        self.cli_commit() + +        # Check generated configuration + +        # Expected values +        original = """ +        102:	from 2001:db8:1338::/126 fwmark 0x17 lookup 150 +        102:	from 2001:db8:1339::/126 fwmark 0x17 lookup 150 +        """ +        tmp = cmd('ip -6 rule show prio 102') + +        self.assertEqual(sort_ip(tmp), sort_ip(original)) + +    # Test set table for sources and destinations with fwmark ipv6 +    def test_fwmark_sources_destination_ipv6_table_id(self): +        path = base_path + ['local-route6'] + +        sources = ['2001:db8:1338::/126', '2001:db8:1339::/56'] +        destinations = ['2001:db8:13::/48', '2001:db8:16::/48'] +        fwmk = '23' +        rule = '103' +        table = '150' +        for src in sources: +            for dst in destinations: +                self.cli_set(path + ['rule', rule, 'set', 'table', table]) +                self.cli_set(path + ['rule', rule, 'source', src]) +                self.cli_set(path + ['rule', rule, 'destination', dst]) +                self.cli_set(path + ['rule', rule, 'fwmark', fwmk]) + +        self.cli_commit() + +        # Check generated configuration + +        # Expected values +        original = """ +        103:	from 2001:db8:1338::/126 to 2001:db8:13::/48 fwmark 0x17 lookup 150 +        103:	from 2001:db8:1338::/126 to 2001:db8:16::/48 fwmark 0x17 lookup 150 +        103:	from 2001:db8:1339::/56 to 2001:db8:13::/48 fwmark 0x17 lookup 150 +        103:	from 2001:db8:1339::/56 to 2001:db8:16::/48 fwmark 0x17 lookup 150 +        """ +        tmp = cmd('ip -6 rule show prio 103') + +        self.assertEqual(sort_ip(tmp), sort_ip(original)) + +    # Test delete table for sources and destination with fwmark ipv4/ipv6 +    def test_delete_ipv4_ipv6_table_id(self): +        path = base_path + ['local-route'] +        path_v6 = base_path + ['local-route6'] + +        sources = ['203.0.113.1/24', '203.0.114.5'] +        destinations = ['203.0.112.1/24', '203.0.116.5'] +        sources_v6 = ['2001:db8:1338::/126', '2001:db8:1339::/56'] +        destinations_v6 = ['2001:db8:13::/48', '2001:db8:16::/48'] +        fwmk = '23' +        rule = '103' +        table = '150' +        for src in sources: +            for dst in destinations: +                self.cli_set(path + ['rule', rule, 'set', 'table', table]) +                self.cli_set(path + ['rule', rule, 'source', src]) +                self.cli_set(path + ['rule', rule, 'destination', dst]) +                self.cli_set(path + ['rule', rule, 'fwmark', fwmk]) + +        for src in sources_v6: +            for dst in destinations_v6: +                self.cli_set(path_v6 + ['rule', rule, 'set', 'table', table]) +                self.cli_set(path_v6 + ['rule', rule, 'source', src]) +                self.cli_set(path_v6 + ['rule', rule, 'destination', dst]) +                self.cli_set(path_v6 + ['rule', rule, 'fwmark', fwmk]) + +        self.cli_commit() + +        # Check generated configuration + +        # Expected values +        original = """ +        103:	from 203.0.113.1/24 to 203.0.112.1/24 fwmark 0x17 lookup 150 +        103:	from 203.0.113.1/24 to 203.0.116.5 fwmark 0x17 lookup 150 +        103:	from 203.0.114.5 to 203.0.112.1/24 fwmark 0x17 lookup 150 +        103:	from 203.0.114.5 to 203.0.116.5 fwmark 0x17 lookup 150 +        """ +        original_v6 = """ +        103:	from 20016 to 2001:db8:13::/48 fwmark 0x17 lookup 150 +        103:	from 2001:db8:1338::/126 to 2001:db8:16::/48 fwmark 0x17 lookup 150 +        103:	from 2001:db8:1339::/56 to 2001:db8:13::/48 fwmark 0x17 lookup 150 +        103:	from 2001:db8:1339::/56 to 2001:db8:16::/48 fwmark 0x17 lookup 150 +        """ +        tmp = cmd('ip rule show prio 103') +        tmp_v6 = cmd('ip -6 rule show prio 103') + +        self.assertEqual(sort_ip(tmp), sort_ip(original)) +        self.assertEqual(sort_ip(tmp_v6), sort_ip(original_v6)) + +        self.cli_delete(path) +        self.cli_delete(path_v6) +        self.cli_commit() + +        tmp = cmd('ip rule show prio 103') +        tmp_v6 = cmd('ip -6 rule show prio 103') + +        original = [''] +        original_v6 = [''] + +        self.assertEqual(sort_ip(tmp), original) +        self.assertEqual(sort_ip(tmp_v6), original_v6) + +def sort_ip(output): +    return output.splitlines().sort()  if __name__ == '__main__':      unittest.main(verbosity=2) diff --git a/src/conf_mode/policy-local-route.py b/src/conf_mode/policy-local-route.py index 539189442..2541603e2 100755 --- a/src/conf_mode/policy-local-route.py +++ b/src/conf_mode/policy-local-route.py @@ -35,34 +35,53 @@ def get_config(config=None):          conf = config      else:          conf = Config() -    base = ['policy', 'local-route'] +    base = ['policy'] +      pbr = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True) -    # delete policy local-route -    dict = {} -    tmp = node_changed(conf, ['policy', 'local-route', 'rule'], key_mangling=('-', '_')) -    if tmp: -        for rule in (tmp or []): -            src = leaf_node_changed(conf, ['policy', 'local-route', 'rule', rule, 'source']) -            fwmk = leaf_node_changed(conf, ['policy', 'local-route', 'rule', rule, 'fwmark']) -            if src: -                dict = dict_merge({'rule_remove' : {rule : {'source' : src}}}, dict) -                pbr.update(dict) -            if fwmk: -                dict = dict_merge({'rule_remove' : {rule : {'fwmark' : fwmk}}}, dict) +    for route in ['local_route', 'local_route6']: +        dict_id = 'rule_remove' if route == 'local_route' else 'rule6_remove' +        route_key = 'local-route' if route == 'local_route' else 'local-route6' +        base_rule = base + [route_key, 'rule'] + +        # delete policy local-route +        dict = {} +        tmp = node_changed(conf, base_rule, key_mangling=('-', '_')) +        if tmp: +            for rule in (tmp or []): +                src = leaf_node_changed(conf, base_rule + [rule, 'source']) +                fwmk = leaf_node_changed(conf, base_rule + [rule, 'fwmark']) +                dst = leaf_node_changed(conf, base_rule + [rule, 'destination']) +                rule_def = {} +                if src: +                    rule_def = dict_merge({'source' : src}, rule_def) +                if fwmk: +                    rule_def = dict_merge({'fwmark' : fwmk}, rule_def) +                if dst: +                    rule_def = dict_merge({'destination' : dst}, rule_def) +                dict = dict_merge({dict_id : {rule : rule_def}}, dict)                  pbr.update(dict) -    # delete policy local-route rule x source x.x.x.x -    # delete policy local-route rule x fwmark x -    if 'rule' in pbr: -        for rule in pbr['rule']: -            src = leaf_node_changed(conf, ['policy', 'local-route', 'rule', rule, 'source']) -            fwmk = leaf_node_changed(conf, ['policy', 'local-route', 'rule', rule, 'fwmark']) -            if src: -                dict = dict_merge({'rule_remove' : {rule : {'source' : src}}}, dict) -                pbr.update(dict) -            if fwmk: -                dict = dict_merge({'rule_remove' : {rule : {'fwmark' : fwmk}}}, dict) +        if not route in pbr: +            continue + +        # delete policy local-route rule x source x.x.x.x +        # delete policy local-route rule x fwmark x +        # delete policy local-route rule x destination x.x.x.x +        if 'rule' in pbr[route]: +            for rule in pbr[route]['rule']: +                src = leaf_node_changed(conf, base_rule + [rule, 'source']) +                fwmk = leaf_node_changed(conf, base_rule + [rule, 'fwmark']) +                dst = leaf_node_changed(conf, base_rule + [rule, 'destination']) + +                rule_def = {} +                if src: +                    rule_def = dict_merge({'source' : src}, rule_def) +                if fwmk: +                    rule_def = dict_merge({'fwmark' : fwmk}, rule_def) +                if dst: +                    rule_def = dict_merge({'destination' : dst}, rule_def) +                dict = dict_merge({dict_id : {rule : rule_def}}, dict)                  pbr.update(dict)      return pbr @@ -72,13 +91,18 @@ def verify(pbr):      if not pbr:          return None -    if 'rule' in pbr: -        for rule in pbr['rule']: -            if 'source' not in pbr['rule'][rule] and 'fwmark' not in pbr['rule'][rule]: -                raise ConfigError('Source address or fwmark is required!') -            else: -                if 'set' not in pbr['rule'][rule] or 'table' not in pbr['rule'][rule]['set']: -                    raise ConfigError('Table set is required!') +    for route in ['local_route', 'local_route6']: +        if not route in pbr: +            continue + +        pbr_route = pbr[route] +        if 'rule' in pbr_route: +            for rule in pbr_route['rule']: +                if 'source' not in pbr_route['rule'][rule] and 'destination' not in pbr_route['rule'][rule] and 'fwmark' not in pbr_route['rule'][rule]: +                    raise ConfigError('Source or destination address or fwmark is required!') +                else: +                    if 'set' not in pbr_route['rule'][rule] or 'table' not in pbr_route['rule'][rule]['set']: +                        raise ConfigError('Table set is required!')      return None @@ -93,36 +117,39 @@ def apply(pbr):          return None      # Delete old rule if needed -    if 'rule_remove' in pbr: -        for rule in pbr['rule_remove']: -            if 'source' in pbr['rule_remove'][rule]: -                for src in pbr['rule_remove'][rule]['source']: -                    call(f'ip rule del prio {rule} from {src}') -            if 'fwmark' in  pbr['rule_remove'][rule]: -                for fwmk in pbr['rule_remove'][rule]['fwmark']: -                    call(f'ip rule del prio {rule} from all fwmark {fwmk}') +    for rule_rm in ['rule_remove', 'rule6_remove']: +        if rule_rm in pbr: +            v6 = " -6" if rule_rm == 'rule6_remove' else "" +            for rule, rule_config in pbr[rule_rm].items(): +                for src in (rule_config['source'] or ['']): +                    f_src = '' if src == '' else f' from {src} ' +                    for dst in (rule_config['destination'] or ['']): +                        f_dst = '' if dst == '' else f' to {dst} ' +                        for fwmk in (rule_config['fwmark'] or ['']): +                            f_fwmk = '' if fwmk == '' else f' fwmark {fwmk} ' +                            call(f'ip{v6} rule del prio {rule} {f_src}{f_dst}{f_fwmk}')      # Generate new config -    if 'rule' in pbr: -        for rule in pbr['rule']: -            table = pbr['rule'][rule]['set']['table'] -            # Only source in the rule -            # set policy local-route rule 100 source '203.0.113.1' -            if 'source' in pbr['rule'][rule] and not 'fwmark' in pbr['rule'][rule]: -                for src in pbr['rule'][rule]['source']: -                    call(f'ip rule add prio {rule} from {src} lookup {table}') -            # Only fwmark in the rule -            # set policy local-route rule 101 fwmark '23' -            if 'fwmark' in pbr['rule'][rule] and not 'source' in pbr['rule'][rule]: -                fwmk = pbr['rule'][rule]['fwmark'] -                call(f'ip rule add prio {rule} from all fwmark {fwmk} lookup {table}') -            # Source and fwmark in the rule -            # set policy local-route rule 100 source '203.0.113.1' -            # set policy local-route rule 100 fwmark '23' -            if 'source' in pbr['rule'][rule] and 'fwmark' in pbr['rule'][rule]: -                fwmk = pbr['rule'][rule]['fwmark'] -                for src in pbr['rule'][rule]['source']: -                    call(f'ip rule add prio {rule} from {src} fwmark {fwmk} lookup {table}') +    for route in ['local_route', 'local_route6']: +        if not route in pbr: +            continue + +        v6 = " -6" if route == 'local_route6' else "" + +        pbr_route = pbr[route] +        if 'rule' in pbr_route: +            for rule, rule_config in pbr_route['rule'].items(): +                table = rule_config['set']['table'] + +                for src in (rule_config['source'] or ['all']): +                    f_src = '' if src == '' else f' from {src} ' +                    for dst in (rule_config['destination'] or ['all']): +                        f_dst = '' if dst == '' else f' to {dst} ' +                        f_fwmk = '' +                        if 'fwmark' in rule_config: +                            fwmk = rule_config['fwmark'] +                            f_fwmk = f' fwmark {fwmk} ' +                        call(f'ip{v6} rule add prio {rule} {f_src}{f_dst}{f_fwmk} lookup {table}')      return None diff --git a/src/helpers/vyos_net_name b/src/helpers/vyos_net_name index afeef8f2d..1798e92db 100755 --- a/src/helpers/vyos_net_name +++ b/src/helpers/vyos_net_name @@ -20,12 +20,14 @@ import os  import re  import time  import logging +import tempfile  import threading  from sys import argv  from vyos.configtree import ConfigTree  from vyos.defaults import directories  from vyos.util import cmd, boot_configuration_complete +from vyos.migrator import VirtualMigrator  vyos_udev_dir = directories['vyos_udev_dir']  vyos_log_dir = '/run/udev/log' @@ -139,14 +141,20 @@ def get_configfile_interfaces() -> dict:      try:          config = ConfigTree(config_file)      except Exception: -        logging.debug(f"updating component version string syntax")          try: -            # this will update the component version string in place, for -            # updates 1.2 --> 1.3/1.4 -            os.system(f'/usr/libexec/vyos/run-config-migration.py {config_path} --virtual --set-vintage=vyos') -            with open(config_path) as f: -                config_file = f.read() +            logging.debug(f"updating component version string syntax") +            # this will update the component version string syntax, +            # required for updates 1.2 --> 1.3/1.4 +            with tempfile.NamedTemporaryFile() as fp: +                with open(fp.name, 'w') as fd: +                    fd.write(config_file) +                virtual_migration = VirtualMigrator(fp.name) +                virtual_migration.run() +                with open(fp.name) as fd: +                    config_file = fd.read() +              config = ConfigTree(config_file) +          except Exception as e:              logging.critical(f"ConfigTree error: {e}") @@ -246,4 +254,3 @@ if not boot_configuration_complete():  else:      logging.debug("boot configuration complete")  lock.release() -  | 
