summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/templates/firewall/nftables.tmpl12
-rw-r--r--data/templates/frr/ospfd.frr.tmpl3
-rw-r--r--interface-definitions/include/ospf/protocol-common-config.xml.i12
-rwxr-xr-xsrc/conf_mode/firewall.py47
-rwxr-xr-xsrc/conf_mode/policy-route.py12
5 files changed, 86 insertions, 0 deletions
diff --git a/data/templates/firewall/nftables.tmpl b/data/templates/firewall/nftables.tmpl
index e8fa4e306..81b2c0b98 100644
--- a/data/templates/firewall/nftables.tmpl
+++ b/data/templates/firewall/nftables.tmpl
@@ -175,6 +175,7 @@ table raw {
counter jump VYOS_CT_IGNORE
counter jump VYOS_CT_TIMEOUT
counter jump VYOS_CT_PREROUTING_HOOK
+ counter jump FW_CONNTRACK
notrack
}
@@ -183,6 +184,7 @@ table raw {
counter jump VYOS_CT_IGNORE
counter jump VYOS_CT_TIMEOUT
counter jump VYOS_CT_OUTPUT_HOOK
+ counter jump FW_CONNTRACK
notrack
}
@@ -220,6 +222,10 @@ table raw {
chain VYOS_CT_OUTPUT_HOOK {
return
}
+
+ chain FW_CONNTRACK {
+ accept
+ }
}
table ip6 raw {
@@ -230,12 +236,14 @@ table ip6 raw {
chain PREROUTING {
type filter hook prerouting priority -300; policy accept;
counter jump VYOS_CT_PREROUTING_HOOK
+ counter jump FW_CONNTRACK
notrack
}
chain OUTPUT {
type filter hook output priority -300; policy accept;
counter jump VYOS_CT_OUTPUT_HOOK
+ counter jump FW_CONNTRACK
notrack
}
@@ -246,5 +254,9 @@ table ip6 raw {
chain VYOS_CT_OUTPUT_HOOK {
return
}
+
+ chain FW_CONNTRACK {
+ accept
+ }
}
{% endif %}
diff --git a/data/templates/frr/ospfd.frr.tmpl b/data/templates/frr/ospfd.frr.tmpl
index af66baf53..a6618b6af 100644
--- a/data/templates/frr/ospfd.frr.tmpl
+++ b/data/templates/frr/ospfd.frr.tmpl
@@ -126,6 +126,9 @@ router ospf {{ 'vrf ' + vrf if vrf is defined and vrf is not none }}
{% if default_metric is defined and default_metric is not none %}
default-metric {{ default_metric }}
{% endif %}
+{% if maximum_paths is defined and maximum_paths is not none %}
+ maximum-paths {{ maximum_paths }}
+{% endif %}
{% if distance is defined and distance is not none %}
{% if distance.global is defined and distance.global is not none %}
distance {{ distance.global }}
diff --git a/interface-definitions/include/ospf/protocol-common-config.xml.i b/interface-definitions/include/ospf/protocol-common-config.xml.i
index 688e78034..e783f4bec 100644
--- a/interface-definitions/include/ospf/protocol-common-config.xml.i
+++ b/interface-definitions/include/ospf/protocol-common-config.xml.i
@@ -289,6 +289,18 @@
</constraint>
</properties>
</leafNode>
+<leafNode name="maximum-paths">
+ <properties>
+ <help>Maximum multiple paths (ECMP)</help>
+ <valueHelp>
+ <format>u32:1-64</format>
+ <description>Maximum multiple paths (ECMP)</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-64"/>
+ </constraint>
+ </properties>
+</leafNode>
<node name="distance">
<properties>
<help>Administrative distance</help>
diff --git a/src/conf_mode/firewall.py b/src/conf_mode/firewall.py
index 906d477b0..82223d60b 100755
--- a/src/conf_mode/firewall.py
+++ b/src/conf_mode/firewall.py
@@ -15,6 +15,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import os
+import re
from glob import glob
from json import loads
@@ -101,6 +102,35 @@ def get_firewall_interfaces(conf):
out.update(find_interfaces(iftype_conf))
return out
+def get_firewall_zones(conf):
+ used_v4 = []
+ used_v6 = []
+ zone_policy = conf.get_config_dict(['zone-policy'], key_mangling=('-', '_'), get_first_key=True,
+ no_tag_node_value_mangle=True)
+
+ if 'zone' in zone_policy:
+ for zone, zone_conf in zone_policy['zone'].items():
+ if 'from' in zone_conf:
+ for from_zone, from_conf in zone_conf['from'].items():
+ name = dict_search_args(from_conf, 'firewall', 'name')
+ if name:
+ used_v4.append(name)
+
+ ipv6_name = dict_search_args(from_conf, 'firewall', 'ipv6_name')
+ if ipv6_name:
+ used_v6.append(ipv6_name)
+
+ if 'intra_zone_filtering' in zone_conf:
+ name = dict_search_args(zone_conf, 'intra_zone_filtering', 'firewall', 'name')
+ if name:
+ used_v4.append(name)
+
+ ipv6_name = dict_search_args(zone_conf, 'intra_zone_filtering', 'firewall', 'ipv6_name')
+ if ipv6_name:
+ used_v6.append(ipv6_name)
+
+ return {'name': used_v4, 'ipv6_name': used_v6}
+
def get_config(config=None):
if config:
conf = config
@@ -116,6 +146,7 @@ def get_config(config=None):
firewall['policy_resync'] = bool('group' in firewall or node_changed(conf, base + ['group']))
firewall['interfaces'] = get_firewall_interfaces(conf)
+ firewall['zone_policy'] = get_firewall_zones(conf)
if 'config_trap' in firewall and firewall['config_trap'] == 'enable':
diff = get_config_diff(conf)
@@ -210,8 +241,23 @@ def verify(firewall):
if ipv6_name and not dict_search_args(firewall, 'ipv6_name', ipv6_name):
raise ConfigError(f'Firewall ipv6-name "{ipv6_name}" is still referenced on interface {ifname}')
+ for fw_name, used_names in firewall['zone_policy'].items():
+ for name in used_names:
+ if not dict_search_args(firewall, fw_name, name):
+ raise ConfigError(f'Firewall {fw_name.replace("_", "-")} "{name}" is still referenced in zone-policy')
+
return None
+def cleanup_rule(table, jump_chain):
+ commands = []
+ results = cmd(f'nft -a list table {table}').split("\n")
+ for line in results:
+ if f'jump {jump_chain}' in line:
+ handle_search = re.search('handle (\d+)', line)
+ if handle_search:
+ commands.append(f'delete rule {table} {chain} handle {handle_search[1]}')
+ return commands
+
def cleanup_commands(firewall):
commands = []
for table in ['ip filter', 'ip6 filter']:
@@ -234,6 +280,7 @@ def cleanup_commands(firewall):
elif table == 'ip6 filter' and dict_search_args(firewall, 'ipv6_name', chain):
commands.append(f'flush chain {table} {chain}')
else:
+ commands += cleanup_rule(table, chain)
commands.append(f'delete chain {table} {chain}')
elif 'rule' in item:
rule = item['rule']
diff --git a/src/conf_mode/policy-route.py b/src/conf_mode/policy-route.py
index eb13788dd..ee5197af0 100755
--- a/src/conf_mode/policy-route.py
+++ b/src/conf_mode/policy-route.py
@@ -15,6 +15,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import os
+import re
from json import loads
from sys import exit
@@ -160,6 +161,16 @@ def verify(policy):
return None
+def cleanup_rule(table, jump_chain):
+ commands = []
+ results = cmd(f'nft -a list table {table}').split("\n")
+ for line in results:
+ if f'jump {jump_chain}' in line:
+ handle_search = re.search('handle (\d+)', line)
+ if handle_search:
+ commands.append(f'delete rule {table} {chain} handle {handle_search[1]}')
+ return commands
+
def cleanup_commands(policy):
commands = []
for table in ['ip mangle', 'ip6 mangle']:
@@ -178,6 +189,7 @@ def cleanup_commands(policy):
elif table == 'ip6 mangle' and dict_search_args(policy, 'route6', chain.replace("VYOS_PBR6_", "", 1)):
commands.append(f'flush chain {table} {chain}')
else:
+ commands += cleanup_rule(table, chain)
commands.append(f'delete chain {table} {chain}')
return commands