summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/build-package.yml17
-rw-r--r--.github/workflows/repo-sync.yml2
-rw-r--r--Makefile1
-rw-r--r--data/config.boot.default53
-rw-r--r--data/templates/conntrack/sysctl.conf.j220
-rw-r--r--data/templates/firewall/nftables.j246
-rw-r--r--data/templates/firewall/sysctl-firewall.conf.j228
-rw-r--r--data/templates/frr/isisd.frr.j23
-rw-r--r--data/templates/load-balancing/haproxy.cfg.j27
-rw-r--r--data/templates/login/default_motd.j23
-rwxr-xr-xdebian/rules5
-rw-r--r--debian/vyos-1x.install1
-rw-r--r--interface-definitions/firewall.xml.in2
-rw-r--r--interface-definitions/include/firewall/action-and-notrack.xml.i10
-rw-r--r--interface-definitions/include/firewall/add-addr-to-group-ipv4.xml.i25
-rw-r--r--interface-definitions/include/firewall/add-addr-to-group-ipv6.xml.i25
-rw-r--r--interface-definitions/include/firewall/common-rule-inet.xml.i239
-rw-r--r--interface-definitions/include/firewall/common-rule-ipv4-raw.xml.i309
-rw-r--r--interface-definitions/include/firewall/common-rule-ipv4.xml.i57
-rw-r--r--interface-definitions/include/firewall/common-rule-ipv6-raw.xml.i50
-rw-r--r--interface-definitions/include/firewall/common-rule-ipv6.xml.i57
-rw-r--r--interface-definitions/include/firewall/connection-status.xml.i28
-rw-r--r--interface-definitions/include/firewall/fragment.xml.i21
-rw-r--r--interface-definitions/include/firewall/global-options.xml.i8
-rw-r--r--interface-definitions/include/firewall/icmp.xml.i34
-rw-r--r--interface-definitions/include/firewall/icmpv6.xml.i34
-rw-r--r--interface-definitions/include/firewall/ipv4-hook-output.xml.i27
-rw-r--r--interface-definitions/include/firewall/ipv4-hook-prerouting.xml.i34
-rw-r--r--interface-definitions/include/firewall/ipv6-hook-output.xml.i27
-rw-r--r--interface-definitions/include/firewall/ipv6-hook-prerouting.xml.i51
-rw-r--r--interface-definitions/include/firewall/limit.xml.i33
-rw-r--r--interface-definitions/include/firewall/protocol.xml.i34
-rw-r--r--interface-definitions/include/firewall/recent.xml.i44
-rw-r--r--interface-definitions/include/firewall/time.xml.i70
-rw-r--r--interface-definitions/include/firewall/timeout-common-protocols.xml.i (renamed from interface-definitions/include/conntrack/timeout-common-protocols.xml.i)3
-rw-r--r--interface-definitions/include/policy/route-common.xml.i72
-rw-r--r--interface-definitions/include/policy/route-ipv4.xml.i33
-rw-r--r--interface-definitions/include/version/firewall-version.xml.i2
-rw-r--r--interface-definitions/load-balancing_reverse-proxy.xml.in31
-rw-r--r--interface-definitions/system_conntrack.xml.in1
-rw-r--r--op-mode-definitions/mtr.xml.in4
-rw-r--r--python/vyos/compose_config.py84
-rw-r--r--python/vyos/configtree.py10
-rw-r--r--python/vyos/defaults.py3
-rw-r--r--python/vyos/firewall.py6
-rw-r--r--python/vyos/ifconfig/vxlan.py7
-rwxr-xr-xsmoketest/scripts/cli/test_firewall.py128
-rwxr-xr-xsmoketest/scripts/cli/test_load-balancing_reverse-proxy.py53
-rwxr-xr-xsmoketest/scripts/cli/test_protocols_isis.py4
-rwxr-xr-xsmoketest/scripts/cli/test_system_conntrack.py60
-rwxr-xr-xsrc/activation-scripts/20-ethernet_offload.py103
-rwxr-xr-xsrc/conf_mode/firewall.py43
-rwxr-xr-xsrc/conf_mode/interfaces_tunnel.py19
-rwxr-xr-xsrc/conf_mode/load-balancing_reverse-proxy.py13
-rwxr-xr-xsrc/conf_mode/nat64.py10
-rwxr-xr-xsrc/conf_mode/nat_cgnat.py71
-rwxr-xr-xsrc/conf_mode/protocols_bfd.py2
-rwxr-xr-xsrc/conf_mode/system_conntrack.py3
-rwxr-xr-xsrc/helpers/run-config-activation.py83
-rwxr-xr-xsrc/init/vyos-router23
-rwxr-xr-xsrc/migration-scripts/firewall/15-to-1655
61 files changed, 1391 insertions, 940 deletions
diff --git a/.github/workflows/build-package.yml b/.github/workflows/build-package.yml
new file mode 100644
index 000000000..0200aceb4
--- /dev/null
+++ b/.github/workflows/build-package.yml
@@ -0,0 +1,17 @@
+name: Debian Package Build
+on:
+ pull_request:
+ branches:
+ - current
+
+jobs:
+ package-build:
+ runs-on: ubuntu-latest
+ container:
+ image: vyos/vyos-build:current
+ options: --sysctl net.ipv6.conf.lo.disable_ipv6=0
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ - name: Build Debian package
+ run: dpkg-buildpackage -uc -us -tc -b
diff --git a/.github/workflows/repo-sync.yml b/.github/workflows/repo-sync.yml
index a2bf54f74..36f323cdd 100644
--- a/.github/workflows/repo-sync.yml
+++ b/.github/workflows/repo-sync.yml
@@ -1,7 +1,7 @@
name: Repo-sync
on:
- pull_request:
+ pull_request_target:
types:
- closed
branches:
diff --git a/Makefile b/Makefile
index 44a6e35ed..3b26273d6 100644
--- a/Makefile
+++ b/Makefile
@@ -66,6 +66,7 @@ op_mode_definitions: $(op_xml_obj)
ln -s ../node.tag $(OP_TMPL_DIR)/ping/node.tag/node.tag/
ln -s ../node.tag $(OP_TMPL_DIR)/traceroute/node.tag/node.tag/
ln -s ../node.tag $(OP_TMPL_DIR)/mtr/node.tag/node.tag/
+ ln -s ../node.tag $(OP_TMPL_DIR)/monitor/traceroute/node.tag/node.tag/
# XXX: test if there are empty node.def files - this is not allowed as these
# could mask help strings or mandatory priority statements
diff --git a/data/config.boot.default b/data/config.boot.default
new file mode 100644
index 000000000..93369d9b7
--- /dev/null
+++ b/data/config.boot.default
@@ -0,0 +1,53 @@
+interfaces {
+ loopback lo {
+ }
+}
+service {
+ ntp {
+ allow-client {
+ address "127.0.0.0/8"
+ address "169.254.0.0/16"
+ address "10.0.0.0/8"
+ address "172.16.0.0/12"
+ address "192.168.0.0/16"
+ address "::1/128"
+ address "fe80::/10"
+ address "fc00::/7"
+ }
+ server time1.vyos.net {
+ }
+ server time2.vyos.net {
+ }
+ server time3.vyos.net {
+ }
+ }
+}
+system {
+ config-management {
+ commit-revisions "100"
+ }
+ console {
+ device ttyS0 {
+ speed "115200"
+ }
+ }
+ host-name "vyos"
+ login {
+ user vyos {
+ authentication {
+ encrypted-password "$6$QxPS.uk6mfo$9QBSo8u1FkH16gMyAVhus6fU3LOzvLR9Z9.82m3tiHFAxTtIkhaZSWssSgzt4v4dGAL8rhVQxTg0oAG9/q11h/"
+ plaintext-password ""
+ }
+ }
+ }
+ syslog {
+ global {
+ facility all {
+ level "info"
+ }
+ facility local7 {
+ level "debug"
+ }
+ }
+ }
+}
diff --git a/data/templates/conntrack/sysctl.conf.j2 b/data/templates/conntrack/sysctl.conf.j2
index 986f75c61..554512f4d 100644
--- a/data/templates/conntrack/sysctl.conf.j2
+++ b/data/templates/conntrack/sysctl.conf.j2
@@ -3,25 +3,7 @@
net.netfilter.nf_conntrack_expect_max = {{ expect_table_size }}
net.netfilter.nf_conntrack_max = {{ table_size }}
-
net.ipv4.tcp_max_syn_backlog = {{ tcp.half_open_connections }}
-
net.netfilter.nf_conntrack_tcp_loose = {{ '1' if tcp.loose is vyos_defined('enable') else '0' }}
net.netfilter.nf_conntrack_tcp_max_retrans = {{ tcp.max_retrans }}
-
-net.netfilter.nf_conntrack_icmp_timeout = {{ timeout.icmp }}
-net.netfilter.nf_conntrack_generic_timeout = {{ timeout.other }}
-
-net.netfilter.nf_conntrack_tcp_timeout_close_wait = {{ timeout.tcp.close_wait }}
-net.netfilter.nf_conntrack_tcp_timeout_close = {{ timeout.tcp.close }}
-net.netfilter.nf_conntrack_tcp_timeout_established = {{ timeout.tcp.established }}
-net.netfilter.nf_conntrack_tcp_timeout_fin_wait = {{ timeout.tcp.fin_wait }}
-net.netfilter.nf_conntrack_tcp_timeout_last_ack = {{ timeout.tcp.last_ack }}
-net.netfilter.nf_conntrack_tcp_timeout_syn_recv = {{ timeout.tcp.syn_recv }}
-net.netfilter.nf_conntrack_tcp_timeout_syn_sent = {{ timeout.tcp.syn_sent }}
-net.netfilter.nf_conntrack_tcp_timeout_time_wait = {{ timeout.tcp.time_wait }}
-
-net.netfilter.nf_conntrack_udp_timeout = {{ timeout.udp.other }}
-net.netfilter.nf_conntrack_udp_timeout_stream = {{ timeout.udp.stream }}
-
-net.netfilter.nf_conntrack_acct = {{ '1' if flow_accounting is vyos_defined else '0' }}
+net.netfilter.nf_conntrack_acct = {{ '1' if flow_accounting is vyos_defined else '0' }} \ No newline at end of file
diff --git a/data/templates/firewall/nftables.j2 b/data/templates/firewall/nftables.j2
index 833df3a67..343917fee 100644
--- a/data/templates/firewall/nftables.j2
+++ b/data/templates/firewall/nftables.j2
@@ -57,7 +57,7 @@ table ip vyos_filter {
{% endif %}
{% endfor %}
{% endif %}
- {{ conf | nft_default_rule('FWD-filter', 'ipv4') }}
+ {{ conf | nft_default_rule('FWD-' + prior, 'ipv4') }}
}
{% endfor %}
{% endif %}
@@ -77,7 +77,7 @@ table ip vyos_filter {
{% endif %}
{% endfor %}
{% endif %}
- {{ conf | nft_default_rule('INP-filter', 'ipv4') }}
+ {{ conf | nft_default_rule('INP-' + prior, 'ipv4') }}
}
{% endfor %}
{% endif %}
@@ -97,14 +97,11 @@ table ip vyos_filter {
{% endif %}
{% endfor %}
{% endif %}
- {{ conf | nft_default_rule('OUT-filter', 'ipv4') }}
+ {{ conf | nft_default_rule('OUT-' + prior, 'ipv4') }}
}
{% endfor %}
{% endif %}
- chain VYOS_FRAG_MARK {
- type filter hook prerouting priority -450; policy accept;
- ip frag-off & 0x3fff != 0 meta mark set 0xffff1 return
- }
+
{% if ipv4.prerouting is vyos_defined %}
{% for prior, conf in ipv4.prerouting.items() %}
chain VYOS_PREROUTING_{{ prior }} {
@@ -117,11 +114,16 @@ table ip vyos_filter {
{% endif %}
{% endfor %}
{% endif %}
- {{ conf | nft_default_rule('PRE-filter', 'ipv4') }}
+ {{ conf | nft_default_rule('PRE-' + prior, 'ipv4') }}
}
{% endfor %}
{% endif %}
+ chain VYOS_FRAG_MARK {
+ type filter hook prerouting priority -450; policy accept;
+ ip frag-off & 0x3fff != 0 meta mark set 0xffff1 return
+ }
+
{% if ipv4.name is vyos_defined %}
{% for name_text, conf in ipv4.name.items() %}
chain NAME_{{ name_text }} {
@@ -202,13 +204,13 @@ table ip6 vyos_filter {
{% endif %}
{% if conf.rule is vyos_defined %}
{% for rule_id, rule_conf in conf.rule.items() if rule_conf.disable is not vyos_defined %}
- {{ rule_conf | nft_rule('FWD', prior, rule_id ,'ip6') }}
+ {{ rule_conf | nft_rule('FWD', prior, rule_id, 'ip6') }}
{% if rule_conf.recent is vyos_defined %}
{% set ns.sets = ns.sets + ['FWD_' + prior + '_' + rule_id] %}
{% endif %}
{% endfor %}
{% endif %}
- {{ conf | nft_default_rule('FWD-filter', 'ipv6') }}
+ {{ conf | nft_default_rule('FWD-' + prior, 'ipv6') }}
}
{% endfor %}
{% endif %}
@@ -222,13 +224,13 @@ table ip6 vyos_filter {
{% endif %}
{% if conf.rule is vyos_defined %}
{% for rule_id, rule_conf in conf.rule.items() if rule_conf.disable is not vyos_defined %}
- {{ rule_conf | nft_rule('INP', prior, rule_id ,'ip6') }}
+ {{ rule_conf | nft_rule('INP', prior, rule_id, 'ip6') }}
{% if rule_conf.recent is vyos_defined %}
{% set ns.sets = ns.sets + ['INP_' + prior + '_' + rule_id] %}
{% endif %}
{% endfor %}
{% endif %}
- {{ conf | nft_default_rule('INP-filter', 'ipv6') }}
+ {{ conf | nft_default_rule('INP-' + prior, 'ipv6') }}
}
{% endfor %}
{% endif %}
@@ -242,17 +244,33 @@ table ip6 vyos_filter {
{% endif %}
{% if conf.rule is vyos_defined %}
{% for rule_id, rule_conf in conf.rule.items() if rule_conf.disable is not vyos_defined %}
- {{ rule_conf | nft_rule('OUT', prior, rule_id ,'ip6') }}
+ {{ rule_conf | nft_rule('OUT', prior, rule_id, 'ip6') }}
{% if rule_conf.recent is vyos_defined %}
{% set ns.sets = ns.sets + ['OUT_ ' + prior + '_' + rule_id] %}
{% endif %}
{% endfor %}
{% endif %}
- {{ conf | nft_default_rule('OUT-filter', 'ipv6') }}
+ {{ conf | nft_default_rule('OUT-' + prior, 'ipv6') }}
}
{% endfor %}
{% endif %}
+{% if ipv6.prerouting is vyos_defined %}
+{% for prior, conf in ipv6.prerouting.items() %}
+ chain VYOS_IPV6_PREROUTING_{{ prior }} {
+ type filter hook prerouting priority {{ prior }}; policy accept;
+{% if conf.rule is vyos_defined %}
+{% for rule_id, rule_conf in conf.rule.items() if rule_conf.disable is not vyos_defined %}
+ {{ rule_conf | nft_rule('PRE', prior, rule_id, 'ip6') }}
+{% if rule_conf.recent is vyos_defined %}
+{% set ns.sets = ns.sets + ['PRE_' + prior + '_' + rule_id] %}
+{% endif %}
+{% endfor %}
+{% endif %}
+ {{ conf | nft_default_rule('PRE-' + prior, 'ipv6') }}
+ }
+{% endfor %}
+{% endif %}
chain VYOS_FRAG6_MARK {
type filter hook prerouting priority -450; policy accept;
exthdr frag exists meta mark set 0xffff1 return
diff --git a/data/templates/firewall/sysctl-firewall.conf.j2 b/data/templates/firewall/sysctl-firewall.conf.j2
new file mode 100644
index 000000000..b9c3311e2
--- /dev/null
+++ b/data/templates/firewall/sysctl-firewall.conf.j2
@@ -0,0 +1,28 @@
+# Autogenerated by firewall.py
+
+# gloabl options
+net.ipv4.icmp_echo_ignore_all = {{ 0 if global_options.all_ping == 'enable' else 1 }}
+net.ipv4.icmp_echo_ignore_broadcasts = {{ 0 if global_options.broadcast_ping == 'enable' else 1 }}
+net.ipv4.conf.all.bc_forwarding = {{ 1 if global_options.directed_broadcast == 'enable' else 0 }}
+net.ipv4.conf.*.accept_source_route = {{ 1 if global_options.ip_src_route == 'enable' else 0 }}
+net.ipv6.conf.*.accept_redirects = {{ 1 if global_options.ipv6_receive_redirects == 'enable' else 0 }}
+net.ipv6.conf.*.accept_source_route = {{ 0 if global_options.ipv6_src_route == 'enable' else -1 }}
+net.ipv4.conf.all.log_martians = {{ 1 if global_options.log_martians == 'enable' else 0 }}
+net.ipv4.conf.*.accept_redirects = {{ 1 if global_options.receive_redirects == 'enable' else 0 }}
+net.ipv4.conf.*.send_redirects = {{ 1 if global_options.send_redirects == 'enable' else 0 }}
+net.ipv4.tcp_syncookies = {{ 1 if global_options.syn_cookies == 'enable' else 0 }}
+net.ipv4.tcp_rfc1337 = {{ 1 if global_options.twa_hazards_protection == 'enable' else 0 }}
+
+## Timeout values:
+net.netfilter.nf_conntrack_icmp_timeout = {{ global_options.timeout.icmp }}
+net.netfilter.nf_conntrack_generic_timeout = {{ global_options.timeout.other }}
+net.netfilter.nf_conntrack_tcp_timeout_close_wait = {{ global_options.timeout.tcp.close_wait }}
+net.netfilter.nf_conntrack_tcp_timeout_close = {{ global_options.timeout.tcp.close }}
+net.netfilter.nf_conntrack_tcp_timeout_established = {{ global_options.timeout.tcp.established }}
+net.netfilter.nf_conntrack_tcp_timeout_fin_wait = {{ global_options.timeout.tcp.fin_wait }}
+net.netfilter.nf_conntrack_tcp_timeout_last_ack = {{ global_options.timeout.tcp.last_ack }}
+net.netfilter.nf_conntrack_tcp_timeout_syn_recv = {{ global_options.timeout.tcp.syn_recv }}
+net.netfilter.nf_conntrack_tcp_timeout_syn_sent = {{ global_options.timeout.tcp.syn_sent }}
+net.netfilter.nf_conntrack_tcp_timeout_time_wait = {{ global_options.timeout.tcp.time_wait }}
+net.netfilter.nf_conntrack_udp_timeout = {{ global_options.timeout.udp.other }}
+net.netfilter.nf_conntrack_udp_timeout_stream = {{ global_options.timeout.udp.stream }}
diff --git a/data/templates/frr/isisd.frr.j2 b/data/templates/frr/isisd.frr.j2
index 5570caaa7..eb14aade6 100644
--- a/data/templates/frr/isisd.frr.j2
+++ b/data/templates/frr/isisd.frr.j2
@@ -76,6 +76,9 @@ advertise-passive-only
{% if set_overload_bit is vyos_defined %}
set-overload-bit
{% endif %}
+{% if metric_style is vyos_defined %}
+ metric-style {{ metric_style }}
+{% endif %}
{% if domain_password.md5 is vyos_defined %}
domain-password md5 {{ domain_password.plaintext_password }}
{% elif domain_password.plaintext_password is vyos_defined %}
diff --git a/data/templates/load-balancing/haproxy.cfg.j2 b/data/templates/load-balancing/haproxy.cfg.j2
index b786a58f8..c6027e09b 100644
--- a/data/templates/load-balancing/haproxy.cfg.j2
+++ b/data/templates/load-balancing/haproxy.cfg.j2
@@ -131,6 +131,13 @@ frontend {{ front }}
{% if backend is vyos_defined %}
{% for back, back_config in backend.items() %}
backend {{ back }}
+{% if back_config.health_check is vyos_defined %}
+{% if back_config.health_check == 'smtp' %}
+ option smtpchk
+{% else %}
+ option {{ back_config.health_check }}-check
+{% endif %}
+{% endif %}
{% if back_config.http_check is vyos_defined %}
option httpchk
{% endif %}
diff --git a/data/templates/login/default_motd.j2 b/data/templates/login/default_motd.j2
index 543c6f8e0..0d52092f8 100644
--- a/data/templates/login/default_motd.j2
+++ b/data/templates/login/default_motd.j2
@@ -4,6 +4,9 @@ Welcome to VyOS!
. VyOS {{ version_data.version }}
└ ──┘ {{ version_data.release_train }}
+{% if version_data.lts_build %}
+ * Support portal: {{ version_data.support_url }}
+{% endif %}
* Documentation: {{ version_data.documentation_url }}
* Project news: {{ version_data.project_news_url }}
* Bug reports: {{ version_data.bugtracker_url }}
diff --git a/debian/rules b/debian/rules
index d007089a4..9da40465f 100755
--- a/debian/rules
+++ b/debian/rules
@@ -11,6 +11,7 @@ VYOS_MIBS_DIR := usr/share/snmp/mibs
VYOS_LOCALUI_DIR := srv/localui
MIGRATION_SCRIPTS_DIR := opt/vyatta/etc/config-migrate/migrate
+ACTIVATION_SCRIPTS_DIR := usr/libexec/vyos/activate
SYSTEM_SCRIPTS_DIR := usr/libexec/vyos/system
SERVICES_DIR := usr/libexec/vyos/services
@@ -67,6 +68,10 @@ override_dh_auto_install:
mkdir -p $(DIR)/$(MIGRATION_SCRIPTS_DIR)
cp -r src/migration-scripts/* $(DIR)/$(MIGRATION_SCRIPTS_DIR)
+ # Install activation scripts
+ mkdir -p $(DIR)/$(ACTIVATION_SCRIPTS_DIR)
+ cp -r src/activation-scripts/* $(DIR)/$(ACTIVATION_SCRIPTS_DIR)
+
# Install system scripts
mkdir -p $(DIR)/$(SYSTEM_SCRIPTS_DIR)
cp -r src/system/* $(DIR)/$(SYSTEM_SCRIPTS_DIR)
diff --git a/debian/vyos-1x.install b/debian/vyos-1x.install
index 9e43669be..b3978d38a 100644
--- a/debian/vyos-1x.install
+++ b/debian/vyos-1x.install
@@ -28,6 +28,7 @@ usr/bin/vyos-config-to-commands
usr/bin/vyos-config-to-json
usr/bin/vyos-hostsd-client
usr/lib
+usr/libexec/vyos/activate
usr/libexec/vyos/completion
usr/libexec/vyos/conf_mode
usr/libexec/vyos/init
diff --git a/interface-definitions/firewall.xml.in b/interface-definitions/firewall.xml.in
index 24e63c5ec..dc4625af0 100644
--- a/interface-definitions/firewall.xml.in
+++ b/interface-definitions/firewall.xml.in
@@ -378,6 +378,7 @@
#include <include/firewall/ipv4-hook-forward.xml.i>
#include <include/firewall/ipv4-hook-input.xml.i>
#include <include/firewall/ipv4-hook-output.xml.i>
+ #include <include/firewall/ipv4-hook-prerouting.xml.i>
#include <include/firewall/ipv4-custom-name.xml.i>
</children>
</node>
@@ -389,6 +390,7 @@
#include <include/firewall/ipv6-hook-forward.xml.i>
#include <include/firewall/ipv6-hook-input.xml.i>
#include <include/firewall/ipv6-hook-output.xml.i>
+ #include <include/firewall/ipv6-hook-prerouting.xml.i>
#include <include/firewall/ipv6-custom-name.xml.i>
</children>
</node>
diff --git a/interface-definitions/include/firewall/action-and-notrack.xml.i b/interface-definitions/include/firewall/action-and-notrack.xml.i
index 5f81a1451..de11f7dd5 100644
--- a/interface-definitions/include/firewall/action-and-notrack.xml.i
+++ b/interface-definitions/include/firewall/action-and-notrack.xml.i
@@ -3,13 +3,17 @@
<properties>
<help>Rule action</help>
<completionHelp>
- <list>accept jump notrack reject return drop queue</list>
+ <list>accept continue jump notrack reject return drop queue</list>
</completionHelp>
<valueHelp>
<format>accept</format>
<description>Accept matching entries</description>
</valueHelp>
<valueHelp>
+ <format>continue</format>
+ <description>Continue parsing next rule</description>
+ </valueHelp>
+ <valueHelp>
<format>jump</format>
<description>Jump to another chain</description>
</valueHelp>
@@ -31,10 +35,10 @@
</valueHelp>
<valueHelp>
<format>notrack</format>
- <description>Igone connection tracking</description>
+ <description>Ignore connection tracking</description>
</valueHelp>
<constraint>
- <regex>(accept|jump|notrack|reject|return|drop|queue)</regex>
+ <regex>(accept|continue|jump|notrack|reject|return|drop|queue)</regex>
</constraint>
</properties>
</leafNode>
diff --git a/interface-definitions/include/firewall/add-addr-to-group-ipv4.xml.i b/interface-definitions/include/firewall/add-addr-to-group-ipv4.xml.i
new file mode 100644
index 000000000..a47cadd55
--- /dev/null
+++ b/interface-definitions/include/firewall/add-addr-to-group-ipv4.xml.i
@@ -0,0 +1,25 @@
+<!-- include start from firewall/add-addr-to-group-ipv4.xml.i -->
+<node name="add-address-to-group">
+ <properties>
+ <help>Add ip address to dynamic address-group</help>
+ </properties>
+ <children>
+ <node name="source-address">
+ <properties>
+ <help>Add source ip addresses to dynamic address-group</help>
+ </properties>
+ <children>
+ #include <include/firewall/add-dynamic-address-groups.xml.i>
+ </children>
+ </node>
+ <node name="destination-address">
+ <properties>
+ <help>Add destination ip addresses to dynamic address-group</help>
+ </properties>
+ <children>
+ #include <include/firewall/add-dynamic-address-groups.xml.i>
+ </children>
+ </node>
+ </children>
+</node>
+<!-- include end --> \ No newline at end of file
diff --git a/interface-definitions/include/firewall/add-addr-to-group-ipv6.xml.i b/interface-definitions/include/firewall/add-addr-to-group-ipv6.xml.i
new file mode 100644
index 000000000..2cb077450
--- /dev/null
+++ b/interface-definitions/include/firewall/add-addr-to-group-ipv6.xml.i
@@ -0,0 +1,25 @@
+<!-- include start from firewall/add-addr-to-group-ipv6.xml.i -->
+<node name="add-address-to-group">
+ <properties>
+ <help>Add ipv6 address to dynamic ipv6-address-group</help>
+ </properties>
+ <children>
+ <node name="source-address">
+ <properties>
+ <help>Add source ipv6 addresses to dynamic ipv6-address-group</help>
+ </properties>
+ <children>
+ #include <include/firewall/add-dynamic-ipv6-address-groups.xml.i>
+ </children>
+ </node>
+ <node name="destination-address">
+ <properties>
+ <help>Add destination ipv6 addresses to dynamic ipv6-address-group</help>
+ </properties>
+ <children>
+ #include <include/firewall/add-dynamic-ipv6-address-groups.xml.i>
+ </children>
+ </node>
+ </children>
+</node>
+<!-- include end --> \ No newline at end of file
diff --git a/interface-definitions/include/firewall/common-rule-inet.xml.i b/interface-definitions/include/firewall/common-rule-inet.xml.i
index bef1c3da5..55ffa3a8b 100644
--- a/interface-definitions/include/firewall/common-rule-inet.xml.i
+++ b/interface-definitions/include/firewall/common-rule-inet.xml.i
@@ -1,235 +1,24 @@
<!-- include start from firewall/common-rule-inet.xml.i -->
#include <include/firewall/action.xml.i>
-#include <include/generic-description.xml.i>
-#include <include/firewall/dscp.xml.i>
-#include <include/firewall/packet-options.xml.i>
-#include <include/firewall/firewall-mark.xml.i>
-#include <include/firewall/connection-mark.xml.i>
#include <include/firewall/conntrack-helper.xml.i>
-#include <include/firewall/nft-queue.xml.i>
+#include <include/firewall/connection-mark.xml.i>
+#include <include/firewall/connection-status.xml.i>
+#include <include/generic-description.xml.i>
#include <include/generic-disable-node.xml.i>
-<node name="fragment">
- <properties>
- <help>IP fragment match</help>
- </properties>
- <children>
- <leafNode name="match-frag">
- <properties>
- <help>Second and further fragments of fragmented packets</help>
- <valueless/>
- </properties>
- </leafNode>
- <leafNode name="match-non-frag">
- <properties>
- <help>Head fragments or unfragmented packets</help>
- <valueless/>
- </properties>
- </leafNode>
- </children>
-</node>
-<node name="limit">
- <properties>
- <help>Rate limit using a token bucket filter</help>
- </properties>
- <children>
- <leafNode name="burst">
- <properties>
- <help>Maximum number of packets to allow in excess of rate</help>
- <valueHelp>
- <format>u32:0-4294967295</format>
- <description>Maximum number of packets to allow in excess of rate</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 0-4294967295"/>
- </constraint>
- </properties>
- </leafNode>
- <leafNode name="rate">
- <properties>
- <help>Maximum average matching rate</help>
- <valueHelp>
- <format>txt</format>
- <description>integer/unit (Example: 5/minute)</description>
- </valueHelp>
- <constraint>
- <regex>\d+/(second|minute|hour|day)</regex>
- </constraint>
- </properties>
- </leafNode>
- </children>
-</node>
+#include <include/firewall/dscp.xml.i>
+#include <include/firewall/fragment.xml.i>
+#include <include/firewall/match-ipsec.xml.i>
+#include <include/firewall/limit.xml.i>
#include <include/firewall/log.xml.i>
#include <include/firewall/log-options.xml.i>
-<node name="connection-status">
- <properties>
- <help>Connection status</help>
- </properties>
- <children>
- <leafNode name="nat">
- <properties>
- <help>NAT connection status</help>
- <completionHelp>
- <list>destination source</list>
- </completionHelp>
- <valueHelp>
- <format>destination</format>
- <description>Match connections that are subject to destination NAT</description>
- </valueHelp>
- <valueHelp>
- <format>source</format>
- <description>Match connections that are subject to source NAT</description>
- </valueHelp>
- <constraint>
- <regex>(destination|source)</regex>
- </constraint>
- </properties>
- </leafNode>
- </children>
-</node>
-<leafNode name="protocol">
- <properties>
- <help>Protocol to match (protocol name, number, or "all")</help>
- <completionHelp>
- <script>${vyos_completion_dir}/list_protocols.sh</script>
- <list>all tcp_udp</list>
- </completionHelp>
- <valueHelp>
- <format>all</format>
- <description>All IP protocols</description>
- </valueHelp>
- <valueHelp>
- <format>tcp_udp</format>
- <description>Both TCP and UDP</description>
- </valueHelp>
- <valueHelp>
- <format>u32:0-255</format>
- <description>IP protocol number</description>
- </valueHelp>
- <valueHelp>
- <format>&lt;protocol&gt;</format>
- <description>IP protocol name</description>
- </valueHelp>
- <valueHelp>
- <format>!&lt;protocol&gt;</format>
- <description>IP protocol name</description>
- </valueHelp>
- <constraint>
- <validator name="ip-protocol"/>
- </constraint>
- </properties>
-</leafNode>
-<node name="recent">
- <properties>
- <help>Parameters for matching recently seen sources</help>
- </properties>
- <children>
- <leafNode name="count">
- <properties>
- <help>Source addresses seen more than N times</help>
- <valueHelp>
- <format>u32:1-255</format>
- <description>Source addresses seen more than N times</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 1-255"/>
- </constraint>
- </properties>
- </leafNode>
- <leafNode name="time">
- <properties>
- <help>Source addresses seen in the last second/minute/hour</help>
- <completionHelp>
- <list>second minute hour</list>
- </completionHelp>
- <valueHelp>
- <format>second</format>
- <description>Source addresses seen COUNT times in the last second</description>
- </valueHelp>
- <valueHelp>
- <format>minute</format>
- <description>Source addresses seen COUNT times in the last minute</description>
- </valueHelp>
- <valueHelp>
- <format>hour</format>
- <description>Source addresses seen COUNT times in the last hour</description>
- </valueHelp>
- <constraint>
- <regex>(second|minute|hour)</regex>
- </constraint>
- </properties>
- </leafNode>
- </children>
-</node>
-#include <include/firewall/synproxy.xml.i>
+#include <include/firewall/firewall-mark.xml.i>
+#include <include/firewall/packet-options.xml.i>
+#include <include/firewall/protocol.xml.i>
+#include <include/firewall/nft-queue.xml.i>
+#include <include/firewall/recent.xml.i>
#include <include/firewall/state.xml.i>
+#include <include/firewall/synproxy.xml.i>
#include <include/firewall/tcp-flags.xml.i>
#include <include/firewall/tcp-mss.xml.i>
-<node name="time">
- <properties>
- <help>Time to match rule</help>
- </properties>
- <children>
- <leafNode name="startdate">
- <properties>
- <help>Date to start matching rule</help>
- <valueHelp>
- <format>txt</format>
- <description>Enter date using following notation - YYYY-MM-DD</description>
- </valueHelp>
- <constraint>
- <regex>(\d{4}\-\d{2}\-\d{2})</regex>
- </constraint>
- </properties>
- </leafNode>
- <leafNode name="starttime">
- <properties>
- <help>Time of day to start matching rule</help>
- <valueHelp>
- <format>txt</format>
- <description>Enter time using using 24 hour notation - hh:mm:ss</description>
- </valueHelp>
- <constraint>
- <regex>([0-2][0-9](\:[0-5][0-9]){1,2})</regex>
- </constraint>
- </properties>
- </leafNode>
- <leafNode name="stopdate">
- <properties>
- <help>Date to stop matching rule</help>
- <valueHelp>
- <format>txt</format>
- <description>Enter date using following notation - YYYY-MM-DD</description>
- </valueHelp>
- <constraint>
- <regex>(\d{4}\-\d{2}\-\d{2})</regex>
- </constraint>
- </properties>
- </leafNode>
- <leafNode name="stoptime">
- <properties>
- <help>Time of day to stop matching rule</help>
- <valueHelp>
- <format>txt</format>
- <description>Enter time using using 24 hour notation - hh:mm:ss</description>
- </valueHelp>
- <constraint>
- <regex>([0-2][0-9](\:[0-5][0-9]){1,2})</regex>
- </constraint>
- </properties>
- </leafNode>
- <leafNode name="weekdays">
- <properties>
- <help>Comma separated weekdays to match rule on</help>
- <valueHelp>
- <format>txt</format>
- <description>Name of day (Monday, Tuesday, Wednesday, Thursdays, Friday, Saturday, Sunday)</description>
- </valueHelp>
- <valueHelp>
- <format>u32:0-6</format>
- <description>Day number (0 = Sunday ... 6 = Saturday)</description>
- </valueHelp>
- </properties>
- </leafNode>
- </children>
-</node>
+#include <include/firewall/time.xml.i>
<!-- include end -->
diff --git a/interface-definitions/include/firewall/common-rule-ipv4-raw.xml.i b/interface-definitions/include/firewall/common-rule-ipv4-raw.xml.i
index e7468bfba..960c960db 100644
--- a/interface-definitions/include/firewall/common-rule-ipv4-raw.xml.i
+++ b/interface-definitions/include/firewall/common-rule-ipv4-raw.xml.i
@@ -1,9 +1,22 @@
<!-- include start from firewall/common-rule-ipv4-raw.xml.i -->
+#include <include/firewall/add-addr-to-group-ipv4.xml.i>
#include <include/firewall/action-and-notrack.xml.i>
#include <include/generic-description.xml.i>
#include <include/firewall/dscp.xml.i>
-#include <include/firewall/ttl.xml.i>
+#include <include/firewall/fragment.xml.i>
+#include <include/generic-disable-node.xml.i>
+#include <include/firewall/icmp.xml.i>
+#include <include/firewall/limit.xml.i>
+#include <include/firewall/log.xml.i>
+#include <include/firewall/log-options.xml.i>
+#include <include/firewall/match-ipsec.xml.i>
+#include <include/firewall/protocol.xml.i>
#include <include/firewall/nft-queue.xml.i>
+#include <include/firewall/recent.xml.i>
+#include <include/firewall/tcp-flags.xml.i>
+#include <include/firewall/tcp-mss.xml.i>
+#include <include/firewall/time.xml.i>
+#include <include/firewall/ttl.xml.i>
<node name="destination">
<properties>
<help>Destination parameters</help>
@@ -18,228 +31,6 @@
#include <include/firewall/source-destination-group.xml.i>
</children>
</node>
-#include <include/generic-disable-node.xml.i>
-<node name="fragment">
- <properties>
- <help>IP fragment match</help>
- </properties>
- <children>
- <leafNode name="match-frag">
- <properties>
- <help>Second and further fragments of fragmented packets</help>
- <valueless/>
- </properties>
- </leafNode>
- <leafNode name="match-non-frag">
- <properties>
- <help>Head fragments or unfragmented packets</help>
- <valueless/>
- </properties>
- </leafNode>
- </children>
-</node>
-<node name="icmp">
- <properties>
- <help>ICMP type and code information</help>
- </properties>
- <children>
- <leafNode name="code">
- <properties>
- <help>ICMP code</help>
- <valueHelp>
- <format>u32:0-255</format>
- <description>ICMP code (0-255)</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 0-255"/>
- </constraint>
- </properties>
- </leafNode>
- <leafNode name="type">
- <properties>
- <help>ICMP type</help>
- <valueHelp>
- <format>u32:0-255</format>
- <description>ICMP type (0-255)</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 0-255"/>
- </constraint>
- </properties>
- </leafNode>
- #include <include/firewall/icmp-type-name.xml.i>
- </children>
-</node>
-<node name="ipsec">
- <properties>
- <help>Inbound IPsec packets</help>
- </properties>
- <children>
- <leafNode name="match-ipsec">
- <properties>
- <help>Inbound IPsec packets</help>
- <valueless/>
- </properties>
- </leafNode>
- <leafNode name="match-none">
- <properties>
- <help>Inbound non-IPsec packets</help>
- <valueless/>
- </properties>
- </leafNode>
- </children>
-</node>
-<node name="limit">
- <properties>
- <help>Rate limit using a token bucket filter</help>
- </properties>
- <children>
- <leafNode name="burst">
- <properties>
- <help>Maximum number of packets to allow in excess of rate</help>
- <valueHelp>
- <format>u32:0-4294967295</format>
- <description>Maximum number of packets to allow in excess of rate</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 0-4294967295"/>
- </constraint>
- </properties>
- </leafNode>
- <leafNode name="rate">
- <properties>
- <help>Maximum average matching rate</help>
- <valueHelp>
- <format>txt</format>
- <description>integer/unit (Example: 5/minute)</description>
- </valueHelp>
- <constraint>
- <regex>\d+/(second|minute|hour|day)</regex>
- </constraint>
- </properties>
- </leafNode>
- </children>
-</node>
-<leafNode name="log">
- <properties>
- <help>Option to log packets matching rule</help>
- <completionHelp>
- <list>enable disable</list>
- </completionHelp>
- <valueHelp>
- <format>enable</format>
- <description>Enable log</description>
- </valueHelp>
- <valueHelp>
- <format>disable</format>
- <description>Disable log</description>
- </valueHelp>
- <constraint>
- <regex>(enable|disable)</regex>
- </constraint>
- </properties>
-</leafNode>
-#include <include/firewall/log-options.xml.i>
-<node name="connection-status">
- <properties>
- <help>Connection status</help>
- </properties>
- <children>
- <leafNode name="nat">
- <properties>
- <help>NAT connection status</help>
- <completionHelp>
- <list>destination source</list>
- </completionHelp>
- <valueHelp>
- <format>destination</format>
- <description>Match connections that are subject to destination NAT</description>
- </valueHelp>
- <valueHelp>
- <format>source</format>
- <description>Match connections that are subject to source NAT</description>
- </valueHelp>
- <constraint>
- <regex>(destination|source)</regex>
- </constraint>
- </properties>
- </leafNode>
- </children>
-</node>
-<leafNode name="protocol">
- <properties>
- <help>Protocol to match (protocol name, number, or "all")</help>
- <completionHelp>
- <script>${vyos_completion_dir}/list_protocols.sh</script>
- <list>all tcp_udp</list>
- </completionHelp>
- <valueHelp>
- <format>all</format>
- <description>All IP protocols</description>
- </valueHelp>
- <valueHelp>
- <format>tcp_udp</format>
- <description>Both TCP and UDP</description>
- </valueHelp>
- <valueHelp>
- <format>u32:0-255</format>
- <description>IP protocol number</description>
- </valueHelp>
- <valueHelp>
- <format>&lt;protocol&gt;</format>
- <description>IP protocol name</description>
- </valueHelp>
- <valueHelp>
- <format>!&lt;protocol&gt;</format>
- <description>IP protocol name</description>
- </valueHelp>
- <constraint>
- <validator name="ip-protocol"/>
- </constraint>
- </properties>
-</leafNode>
-<node name="recent">
- <properties>
- <help>Parameters for matching recently seen sources</help>
- </properties>
- <children>
- <leafNode name="count">
- <properties>
- <help>Source addresses seen more than N times</help>
- <valueHelp>
- <format>u32:1-255</format>
- <description>Source addresses seen more than N times</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 1-255"/>
- </constraint>
- </properties>
- </leafNode>
- <leafNode name="time">
- <properties>
- <help>Source addresses seen in the last second/minute/hour</help>
- <completionHelp>
- <list>second minute hour</list>
- </completionHelp>
- <valueHelp>
- <format>second</format>
- <description>Source addresses seen COUNT times in the last second</description>
- </valueHelp>
- <valueHelp>
- <format>minute</format>
- <description>Source addresses seen COUNT times in the last minute</description>
- </valueHelp>
- <valueHelp>
- <format>hour</format>
- <description>Source addresses seen COUNT times in the last hour</description>
- </valueHelp>
- <constraint>
- <regex>(second|minute|hour)</regex>
- </constraint>
- </properties>
- </leafNode>
- </children>
-</node>
<node name="source">
<properties>
<help>Source parameters</help>
@@ -254,74 +45,4 @@
#include <include/firewall/source-destination-group.xml.i>
</children>
</node>
-#include <include/firewall/tcp-flags.xml.i>
-#include <include/firewall/tcp-mss.xml.i>
-<node name="time">
- <properties>
- <help>Time to match rule</help>
- </properties>
- <children>
- <leafNode name="startdate">
- <properties>
- <help>Date to start matching rule</help>
- <valueHelp>
- <format>txt</format>
- <description>Enter date using following notation - YYYY-MM-DD</description>
- </valueHelp>
- <constraint>
- <regex>(\d{4}\-\d{2}\-\d{2})</regex>
- </constraint>
- </properties>
- </leafNode>
- <leafNode name="starttime">
- <properties>
- <help>Time of day to start matching rule</help>
- <valueHelp>
- <format>txt</format>
- <description>Enter time using using 24 hour notation - hh:mm:ss</description>
- </valueHelp>
- <constraint>
- <regex>([0-2][0-9](\:[0-5][0-9]){1,2})</regex>
- </constraint>
- </properties>
- </leafNode>
- <leafNode name="stopdate">
- <properties>
- <help>Date to stop matching rule</help>
- <valueHelp>
- <format>txt</format>
- <description>Enter date using following notation - YYYY-MM-DD</description>
- </valueHelp>
- <constraint>
- <regex>(\d{4}\-\d{2}\-\d{2})</regex>
- </constraint>
- </properties>
- </leafNode>
- <leafNode name="stoptime">
- <properties>
- <help>Time of day to stop matching rule</help>
- <valueHelp>
- <format>txt</format>
- <description>Enter time using using 24 hour notation - hh:mm:ss</description>
- </valueHelp>
- <constraint>
- <regex>([0-2][0-9](\:[0-5][0-9]){1,2})</regex>
- </constraint>
- </properties>
- </leafNode>
- <leafNode name="weekdays">
- <properties>
- <help>Comma separated weekdays to match rule on</help>
- <valueHelp>
- <format>txt</format>
- <description>Name of day (Monday, Tuesday, Wednesday, Thursdays, Friday, Saturday, Sunday)</description>
- </valueHelp>
- <valueHelp>
- <format>u32:0-6</format>
- <description>Day number (0 = Sunday ... 6 = Saturday)</description>
- </valueHelp>
- </properties>
- </leafNode>
- </children>
-</node>
-<!-- include end -->
+<!-- include end --> \ No newline at end of file
diff --git a/interface-definitions/include/firewall/common-rule-ipv4.xml.i b/interface-definitions/include/firewall/common-rule-ipv4.xml.i
index 158c7a662..803b94b06 100644
--- a/interface-definitions/include/firewall/common-rule-ipv4.xml.i
+++ b/interface-definitions/include/firewall/common-rule-ipv4.xml.i
@@ -1,29 +1,8 @@
<!-- include start from firewall/common-rule-ipv4.xml.i -->
+#include <include/firewall/add-addr-to-group-ipv4.xml.i>
#include <include/firewall/common-rule-inet.xml.i>
+#include <include/firewall/icmp.xml.i>
#include <include/firewall/ttl.xml.i>
-<node name="add-address-to-group">
- <properties>
- <help>Add ip address to dynamic address-group</help>
- </properties>
- <children>
- <node name="source-address">
- <properties>
- <help>Add source ip addresses to dynamic address-group</help>
- </properties>
- <children>
- #include <include/firewall/add-dynamic-address-groups.xml.i>
- </children>
- </node>
- <node name="destination-address">
- <properties>
- <help>Add destination ip addresses to dynamic address-group</help>
- </properties>
- <children>
- #include <include/firewall/add-dynamic-address-groups.xml.i>
- </children>
- </node>
- </children>
-</node>
<node name="destination">
<properties>
<help>Destination parameters</help>
@@ -39,38 +18,6 @@
#include <include/firewall/source-destination-dynamic-group.xml.i>
</children>
</node>
-<node name="icmp">
- <properties>
- <help>ICMP type and code information</help>
- </properties>
- <children>
- <leafNode name="code">
- <properties>
- <help>ICMP code</help>
- <valueHelp>
- <format>u32:0-255</format>
- <description>ICMP code (0-255)</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 0-255"/>
- </constraint>
- </properties>
- </leafNode>
- <leafNode name="type">
- <properties>
- <help>ICMP type</help>
- <valueHelp>
- <format>u32:0-255</format>
- <description>ICMP type (0-255)</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 0-255"/>
- </constraint>
- </properties>
- </leafNode>
- #include <include/firewall/icmp-type-name.xml.i>
- </children>
-</node>
<leafNode name="jump-target">
<properties>
<help>Set jump target. Action jump must be defined to use this setting</help>
diff --git a/interface-definitions/include/firewall/common-rule-ipv6-raw.xml.i b/interface-definitions/include/firewall/common-rule-ipv6-raw.xml.i
new file mode 100644
index 000000000..958167b89
--- /dev/null
+++ b/interface-definitions/include/firewall/common-rule-ipv6-raw.xml.i
@@ -0,0 +1,50 @@
+<!-- include start from firewall/common-rule-ipv6-raw.xml.i -->
+#include <include/firewall/add-addr-to-group-ipv6.xml.i>
+#include <include/firewall/action-and-notrack.xml.i>
+#include <include/generic-description.xml.i>
+#include <include/firewall/dscp.xml.i>
+#include <include/firewall/fragment.xml.i>
+#include <include/generic-disable-node.xml.i>
+#include <include/firewall/icmpv6.xml.i>
+#include <include/firewall/limit.xml.i>
+#include <include/firewall/log.xml.i>
+#include <include/firewall/log-options.xml.i>
+#include <include/firewall/match-ipsec.xml.i>
+#include <include/firewall/protocol.xml.i>
+#include <include/firewall/nft-queue.xml.i>
+#include <include/firewall/recent.xml.i>
+#include <include/firewall/tcp-flags.xml.i>
+#include <include/firewall/tcp-mss.xml.i>
+#include <include/firewall/time.xml.i>
+#include <include/firewall/hop-limit.xml.i>
+<node name="destination">
+ <properties>
+ <help>Destination parameters</help>
+ </properties>
+ <children>
+ #include <include/firewall/address-ipv6.xml.i>
+ #include <include/firewall/address-mask-ipv6.xml.i>
+ #include <include/firewall/fqdn.xml.i>
+ #include <include/firewall/geoip.xml.i>
+ #include <include/firewall/mac-address.xml.i>
+ #include <include/firewall/port.xml.i>
+ #include <include/firewall/source-destination-group-ipv6.xml.i>
+ #include <include/firewall/source-destination-dynamic-group-ipv6.xml.i>
+ </children>
+</node>
+<node name="source">
+ <properties>
+ <help>Source parameters</help>
+ </properties>
+ <children>
+ #include <include/firewall/address-ipv6.xml.i>
+ #include <include/firewall/address-mask-ipv6.xml.i>
+ #include <include/firewall/fqdn.xml.i>
+ #include <include/firewall/geoip.xml.i>
+ #include <include/firewall/mac-address.xml.i>
+ #include <include/firewall/port.xml.i>
+ #include <include/firewall/source-destination-group-ipv6.xml.i>
+ #include <include/firewall/source-destination-dynamic-group-ipv6.xml.i>
+ </children>
+</node>
+<!-- include end --> \ No newline at end of file
diff --git a/interface-definitions/include/firewall/common-rule-ipv6.xml.i b/interface-definitions/include/firewall/common-rule-ipv6.xml.i
index 78eeb361e..bb176fe71 100644
--- a/interface-definitions/include/firewall/common-rule-ipv6.xml.i
+++ b/interface-definitions/include/firewall/common-rule-ipv6.xml.i
@@ -1,29 +1,8 @@
<!-- include start from firewall/common-rule-ipv6.xml.i -->
+#include <include/firewall/add-addr-to-group-ipv6.xml.i>
#include <include/firewall/common-rule-inet.xml.i>
#include <include/firewall/hop-limit.xml.i>
-<node name="add-address-to-group">
- <properties>
- <help>Add ipv6 address to dynamic ipv6-address-group</help>
- </properties>
- <children>
- <node name="source-address">
- <properties>
- <help>Add source ipv6 addresses to dynamic ipv6-address-group</help>
- </properties>
- <children>
- #include <include/firewall/add-dynamic-ipv6-address-groups.xml.i>
- </children>
- </node>
- <node name="destination-address">
- <properties>
- <help>Add destination ipv6 addresses to dynamic ipv6-address-group</help>
- </properties>
- <children>
- #include <include/firewall/add-dynamic-ipv6-address-groups.xml.i>
- </children>
- </node>
- </children>
-</node>
+#include <include/firewall/icmpv6.xml.i>
<node name="destination">
<properties>
<help>Destination parameters</help>
@@ -39,38 +18,6 @@
#include <include/firewall/source-destination-dynamic-group-ipv6.xml.i>
</children>
</node>
-<node name="icmpv6">
- <properties>
- <help>ICMPv6 type and code information</help>
- </properties>
- <children>
- <leafNode name="code">
- <properties>
- <help>ICMPv6 code</help>
- <valueHelp>
- <format>u32:0-255</format>
- <description>ICMPv6 code (0-255)</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 0-255"/>
- </constraint>
- </properties>
- </leafNode>
- <leafNode name="type">
- <properties>
- <help>ICMPv6 type</help>
- <valueHelp>
- <format>u32:0-255</format>
- <description>ICMPv6 type (0-255)</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 0-255"/>
- </constraint>
- </properties>
- </leafNode>
- #include <include/firewall/icmpv6-type-name.xml.i>
- </children>
-</node>
<leafNode name="jump-target">
<properties>
<help>Set jump target. Action jump must be defined to use this setting</help>
diff --git a/interface-definitions/include/firewall/connection-status.xml.i b/interface-definitions/include/firewall/connection-status.xml.i
new file mode 100644
index 000000000..5236c2f4f
--- /dev/null
+++ b/interface-definitions/include/firewall/connection-status.xml.i
@@ -0,0 +1,28 @@
+<!-- include start from firewall/connection-status.xml.i -->
+<node name="connection-status">
+ <properties>
+ <help>Connection status</help>
+ </properties>
+ <children>
+ <leafNode name="nat">
+ <properties>
+ <help>NAT connection status</help>
+ <completionHelp>
+ <list>destination source</list>
+ </completionHelp>
+ <valueHelp>
+ <format>destination</format>
+ <description>Match connections that are subject to destination NAT</description>
+ </valueHelp>
+ <valueHelp>
+ <format>source</format>
+ <description>Match connections that are subject to source NAT</description>
+ </valueHelp>
+ <constraint>
+ <regex>(destination|source)</regex>
+ </constraint>
+ </properties>
+ </leafNode>
+ </children>
+</node>
+<!-- include end --> \ No newline at end of file
diff --git a/interface-definitions/include/firewall/fragment.xml.i b/interface-definitions/include/firewall/fragment.xml.i
new file mode 100644
index 000000000..1f4c11055
--- /dev/null
+++ b/interface-definitions/include/firewall/fragment.xml.i
@@ -0,0 +1,21 @@
+<!-- include start from firewall/fragment.xml.i -->
+<node name="fragment">
+ <properties>
+ <help>IP fragment match</help>
+ </properties>
+ <children>
+ <leafNode name="match-frag">
+ <properties>
+ <help>Second and further fragments of fragmented packets</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="match-non-frag">
+ <properties>
+ <help>Head fragments or unfragmented packets</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ </children>
+</node>
+<!-- include end --> \ No newline at end of file
diff --git a/interface-definitions/include/firewall/global-options.xml.i b/interface-definitions/include/firewall/global-options.xml.i
index 9cd0b3239..9039b76fd 100644
--- a/interface-definitions/include/firewall/global-options.xml.i
+++ b/interface-definitions/include/firewall/global-options.xml.i
@@ -244,6 +244,14 @@
</properties>
<defaultValue>enable</defaultValue>
</leafNode>
+ <node name="timeout">
+ <properties>
+ <help>Connection timeout options</help>
+ </properties>
+ <children>
+ #include <include/firewall/timeout-common-protocols.xml.i>
+ </children>
+ </node>
<leafNode name="twa-hazards-protection">
<properties>
<help>RFC1337 TCP TIME-WAIT assasination hazards protection</help>
diff --git a/interface-definitions/include/firewall/icmp.xml.i b/interface-definitions/include/firewall/icmp.xml.i
new file mode 100644
index 000000000..deb50a410
--- /dev/null
+++ b/interface-definitions/include/firewall/icmp.xml.i
@@ -0,0 +1,34 @@
+<!-- include start from firewall/icmp.xml.i -->
+<node name="icmp">
+ <properties>
+ <help>ICMP type and code information</help>
+ </properties>
+ <children>
+ <leafNode name="code">
+ <properties>
+ <help>ICMP code</help>
+ <valueHelp>
+ <format>u32:0-255</format>
+ <description>ICMP code (0-255)</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 0-255"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="type">
+ <properties>
+ <help>ICMP type</help>
+ <valueHelp>
+ <format>u32:0-255</format>
+ <description>ICMP type (0-255)</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 0-255"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ #include <include/firewall/icmp-type-name.xml.i>
+ </children>
+</node>
+<!-- include end --> \ No newline at end of file
diff --git a/interface-definitions/include/firewall/icmpv6.xml.i b/interface-definitions/include/firewall/icmpv6.xml.i
new file mode 100644
index 000000000..c0118626e
--- /dev/null
+++ b/interface-definitions/include/firewall/icmpv6.xml.i
@@ -0,0 +1,34 @@
+<!-- include start from firewall/icmpv6.xml.i -->
+<node name="icmpv6">
+ <properties>
+ <help>ICMPv6 type and code information</help>
+ </properties>
+ <children>
+ <leafNode name="code">
+ <properties>
+ <help>ICMPv6 code</help>
+ <valueHelp>
+ <format>u32:0-255</format>
+ <description>ICMPv6 code (0-255)</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 0-255"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="type">
+ <properties>
+ <help>ICMPv6 type</help>
+ <valueHelp>
+ <format>u32:0-255</format>
+ <description>ICMPv6 type (0-255)</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 0-255"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ #include <include/firewall/icmpv6-type-name.xml.i>
+ </children>
+</node>
+<!-- include end --> \ No newline at end of file
diff --git a/interface-definitions/include/firewall/ipv4-hook-output.xml.i b/interface-definitions/include/firewall/ipv4-hook-output.xml.i
index 2b537ce5e..ca47ae09b 100644
--- a/interface-definitions/include/firewall/ipv4-hook-output.xml.i
+++ b/interface-definitions/include/firewall/ipv4-hook-output.xml.i
@@ -31,6 +31,33 @@
</tagNode>
</children>
</node>
+ <node name="raw">
+ <properties>
+ <help>IPv4 firewall output raw</help>
+ </properties>
+ <children>
+ #include <include/firewall/default-action-base-chains.xml.i>
+ #include <include/firewall/default-log.xml.i>
+ #include <include/generic-description.xml.i>
+ <tagNode name="rule">
+ <properties>
+ <help>IPv4 Firewall output raw rule number</help>
+ <valueHelp>
+ <format>u32:1-999999</format>
+ <description>Number for this firewall rule</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-999999"/>
+ </constraint>
+ <constraintErrorMessage>Firewall rule number must be between 1 and 999999</constraintErrorMessage>
+ </properties>
+ <children>
+ #include <include/firewall/common-rule-ipv4-raw.xml.i>
+ #include <include/firewall/outbound-interface.xml.i>
+ </children>
+ </tagNode>
+ </children>
+ </node>
</children>
</node>
<!-- include end -->
diff --git a/interface-definitions/include/firewall/ipv4-hook-prerouting.xml.i b/interface-definitions/include/firewall/ipv4-hook-prerouting.xml.i
index c38918375..17ecfe824 100644
--- a/interface-definitions/include/firewall/ipv4-hook-prerouting.xml.i
+++ b/interface-definitions/include/firewall/ipv4-hook-prerouting.xml.i
@@ -4,40 +4,6 @@
<help>IPv4 prerouting firewall</help>
</properties>
<children>
- <node name="filter">
- <properties>
- <help>IPv4 firewall prerouting filter</help>
- </properties>
- <children>
- #include <include/firewall/default-action-base-chains.xml.i>
- #include <include/generic-description.xml.i>
- <tagNode name="rule">
- <properties>
- <help>IPv4 Firewall prerouting filter rule number</help>
- <valueHelp>
- <format>u32:1-999999</format>
- <description>Number for this firewall rule</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 1-999999"/>
- </constraint>
- <constraintErrorMessage>Firewall rule number must be between 1 and 999999</constraintErrorMessage>
- </properties>
- <children>
- #include <include/firewall/common-rule-ipv4.xml.i>
- #include <include/firewall/inbound-interface.xml.i>
- <leafNode name="jump-target">
- <properties>
- <help>Set jump target. Action jump must be defined to use this setting</help>
- <completionHelp>
- <path>firewall ipv4 name</path>
- </completionHelp>
- </properties>
- </leafNode>
- </children>
- </tagNode>
- </children>
- </node>
<node name="raw">
<properties>
<help>IPv4 firewall prerouting raw</help>
diff --git a/interface-definitions/include/firewall/ipv6-hook-output.xml.i b/interface-definitions/include/firewall/ipv6-hook-output.xml.i
index ffe1c72b8..f877cfaaf 100644
--- a/interface-definitions/include/firewall/ipv6-hook-output.xml.i
+++ b/interface-definitions/include/firewall/ipv6-hook-output.xml.i
@@ -31,6 +31,33 @@
</tagNode>
</children>
</node>
+ <node name="raw">
+ <properties>
+ <help>IPv6 firewall output raw</help>
+ </properties>
+ <children>
+ #include <include/firewall/default-action-base-chains.xml.i>
+ #include <include/firewall/default-log.xml.i>
+ #include <include/generic-description.xml.i>
+ <tagNode name="rule">
+ <properties>
+ <help>IPv6 Firewall output raw rule number</help>
+ <valueHelp>
+ <format>u32:1-999999</format>
+ <description>Number for this firewall rule</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-999999"/>
+ </constraint>
+ <constraintErrorMessage>Firewall rule number must be between 1 and 999999</constraintErrorMessage>
+ </properties>
+ <children>
+ #include <include/firewall/common-rule-ipv6-raw.xml.i>
+ #include <include/firewall/outbound-interface.xml.i>
+ </children>
+ </tagNode>
+ </children>
+ </node>
</children>
</node>
<!-- include end -->
diff --git a/interface-definitions/include/firewall/ipv6-hook-prerouting.xml.i b/interface-definitions/include/firewall/ipv6-hook-prerouting.xml.i
new file mode 100644
index 000000000..3f384828d
--- /dev/null
+++ b/interface-definitions/include/firewall/ipv6-hook-prerouting.xml.i
@@ -0,0 +1,51 @@
+<!-- include start from firewall/ipv6-hook-prerouting.xml.i -->
+<node name="prerouting">
+ <properties>
+ <help>IPv6 prerouting firewall</help>
+ </properties>
+ <children>
+ <node name="raw">
+ <properties>
+ <help>IPv6 firewall prerouting raw</help>
+ </properties>
+ <children>
+ #include <include/firewall/default-action-base-chains.xml.i>
+ #include <include/generic-description.xml.i>
+ <leafNode name="default-jump-target">
+ <properties>
+ <help>Set jump target. Action jump must be defined in default-action to use this setting</help>
+ <completionHelp>
+ <path>firewall ipv6 name</path>
+ </completionHelp>
+ </properties>
+ </leafNode>
+ <tagNode name="rule">
+ <properties>
+ <help>IPv6 Firewall prerouting raw rule number</help>
+ <valueHelp>
+ <format>u32:1-999999</format>
+ <description>Number for this firewall rule</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-999999"/>
+ </constraint>
+ <constraintErrorMessage>Firewall rule number must be between 1 and 999999</constraintErrorMessage>
+ </properties>
+ <children>
+ #include <include/firewall/common-rule-ipv6-raw.xml.i>
+ #include <include/firewall/inbound-interface.xml.i>
+ <leafNode name="jump-target">
+ <properties>
+ <help>Set jump target. Action jump must be defined to use this setting</help>
+ <completionHelp>
+ <path>firewall ipv6 name</path>
+ </completionHelp>
+ </properties>
+ </leafNode>
+ </children>
+ </tagNode>
+ </children>
+ </node>
+ </children>
+</node>
+<!-- include end --> \ No newline at end of file
diff --git a/interface-definitions/include/firewall/limit.xml.i b/interface-definitions/include/firewall/limit.xml.i
new file mode 100644
index 000000000..21068dec2
--- /dev/null
+++ b/interface-definitions/include/firewall/limit.xml.i
@@ -0,0 +1,33 @@
+<!-- include start from firewall/limit.xml.i -->
+<node name="limit">
+ <properties>
+ <help>Rate limit using a token bucket filter</help>
+ </properties>
+ <children>
+ <leafNode name="burst">
+ <properties>
+ <help>Maximum number of packets to allow in excess of rate</help>
+ <valueHelp>
+ <format>u32:0-4294967295</format>
+ <description>Maximum number of packets to allow in excess of rate</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 0-4294967295"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="rate">
+ <properties>
+ <help>Maximum average matching rate</help>
+ <valueHelp>
+ <format>txt</format>
+ <description>integer/unit (Example: 5/minute)</description>
+ </valueHelp>
+ <constraint>
+ <regex>\d+/(second|minute|hour|day)</regex>
+ </constraint>
+ </properties>
+ </leafNode>
+ </children>
+</node>
+<!-- include end --> \ No newline at end of file
diff --git a/interface-definitions/include/firewall/protocol.xml.i b/interface-definitions/include/firewall/protocol.xml.i
new file mode 100644
index 000000000..e391cae41
--- /dev/null
+++ b/interface-definitions/include/firewall/protocol.xml.i
@@ -0,0 +1,34 @@
+<!-- include start from firewall/protocol.xml.i -->
+<leafNode name="protocol">
+ <properties>
+ <help>Protocol to match (protocol name, number, or "all")</help>
+ <completionHelp>
+ <script>${vyos_completion_dir}/list_protocols.sh</script>
+ <list>all tcp_udp</list>
+ </completionHelp>
+ <valueHelp>
+ <format>all</format>
+ <description>All IP protocols</description>
+ </valueHelp>
+ <valueHelp>
+ <format>tcp_udp</format>
+ <description>Both TCP and UDP</description>
+ </valueHelp>
+ <valueHelp>
+ <format>u32:0-255</format>
+ <description>IP protocol number</description>
+ </valueHelp>
+ <valueHelp>
+ <format>&lt;protocol&gt;</format>
+ <description>IP protocol name</description>
+ </valueHelp>
+ <valueHelp>
+ <format>!&lt;protocol&gt;</format>
+ <description>IP protocol name</description>
+ </valueHelp>
+ <constraint>
+ <validator name="ip-protocol"/>
+ </constraint>
+ </properties>
+</leafNode>
+<!-- include end --> \ No newline at end of file
diff --git a/interface-definitions/include/firewall/recent.xml.i b/interface-definitions/include/firewall/recent.xml.i
new file mode 100644
index 000000000..38f40b916
--- /dev/null
+++ b/interface-definitions/include/firewall/recent.xml.i
@@ -0,0 +1,44 @@
+<!-- include start from firewall/recent.xml.i -->
+<node name="recent">
+ <properties>
+ <help>Parameters for matching recently seen sources</help>
+ </properties>
+ <children>
+ <leafNode name="count">
+ <properties>
+ <help>Source addresses seen more than N times</help>
+ <valueHelp>
+ <format>u32:1-255</format>
+ <description>Source addresses seen more than N times</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-255"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="time">
+ <properties>
+ <help>Source addresses seen in the last second/minute/hour</help>
+ <completionHelp>
+ <list>second minute hour</list>
+ </completionHelp>
+ <valueHelp>
+ <format>second</format>
+ <description>Source addresses seen COUNT times in the last second</description>
+ </valueHelp>
+ <valueHelp>
+ <format>minute</format>
+ <description>Source addresses seen COUNT times in the last minute</description>
+ </valueHelp>
+ <valueHelp>
+ <format>hour</format>
+ <description>Source addresses seen COUNT times in the last hour</description>
+ </valueHelp>
+ <constraint>
+ <regex>(second|minute|hour)</regex>
+ </constraint>
+ </properties>
+ </leafNode>
+ </children>
+</node>
+<!-- include end --> \ No newline at end of file
diff --git a/interface-definitions/include/firewall/time.xml.i b/interface-definitions/include/firewall/time.xml.i
new file mode 100644
index 000000000..7bd737450
--- /dev/null
+++ b/interface-definitions/include/firewall/time.xml.i
@@ -0,0 +1,70 @@
+<!-- include start from firewall/time.xml.i -->
+<node name="time">
+ <properties>
+ <help>Time to match rule</help>
+ </properties>
+ <children>
+ <leafNode name="startdate">
+ <properties>
+ <help>Date to start matching rule</help>
+ <valueHelp>
+ <format>txt</format>
+ <description>Enter date using following notation - YYYY-MM-DD</description>
+ </valueHelp>
+ <constraint>
+ <regex>(\d{4}\-\d{2}\-\d{2})</regex>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="starttime">
+ <properties>
+ <help>Time of day to start matching rule</help>
+ <valueHelp>
+ <format>txt</format>
+ <description>Enter time using using 24 hour notation - hh:mm:ss</description>
+ </valueHelp>
+ <constraint>
+ <regex>([0-2][0-9](\:[0-5][0-9]){1,2})</regex>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="stopdate">
+ <properties>
+ <help>Date to stop matching rule</help>
+ <valueHelp>
+ <format>txt</format>
+ <description>Enter date using following notation - YYYY-MM-DD</description>
+ </valueHelp>
+ <constraint>
+ <regex>(\d{4}\-\d{2}\-\d{2})</regex>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="stoptime">
+ <properties>
+ <help>Time of day to stop matching rule</help>
+ <valueHelp>
+ <format>txt</format>
+ <description>Enter time using using 24 hour notation - hh:mm:ss</description>
+ </valueHelp>
+ <constraint>
+ <regex>([0-2][0-9](\:[0-5][0-9]){1,2})</regex>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="weekdays">
+ <properties>
+ <help>Comma separated weekdays to match rule on</help>
+ <valueHelp>
+ <format>txt</format>
+ <description>Name of day (Monday, Tuesday, Wednesday, Thursdays, Friday, Saturday, Sunday)</description>
+ </valueHelp>
+ <valueHelp>
+ <format>u32:0-6</format>
+ <description>Day number (0 = Sunday ... 6 = Saturday)</description>
+ </valueHelp>
+ </properties>
+ </leafNode>
+ </children>
+</node>
+<!-- include end --> \ No newline at end of file
diff --git a/interface-definitions/include/conntrack/timeout-common-protocols.xml.i b/interface-definitions/include/firewall/timeout-common-protocols.xml.i
index 2676d846e..037d7d2b1 100644
--- a/interface-definitions/include/conntrack/timeout-common-protocols.xml.i
+++ b/interface-definitions/include/firewall/timeout-common-protocols.xml.i
@@ -1,4 +1,4 @@
-<!-- include start from conntrack/timeout-common-protocols.xml.i -->
+<!-- include start from firewall/timeout-common-protocols.xml.i -->
<leafNode name="icmp">
<properties>
<help>ICMP timeout in seconds</help>
@@ -169,4 +169,3 @@
</leafNode>
</children>
</node>
-<!-- include end -->
diff --git a/interface-definitions/include/policy/route-common.xml.i b/interface-definitions/include/policy/route-common.xml.i
index e412fe58e..97795601e 100644
--- a/interface-definitions/include/policy/route-common.xml.i
+++ b/interface-definitions/include/policy/route-common.xml.i
@@ -3,75 +3,9 @@
#include <include/generic-description.xml.i>
#include <include/firewall/firewall-mark.xml.i>
#include <include/generic-disable-node.xml.i>
-<node name="fragment">
- <properties>
- <help>IP fragment match</help>
- </properties>
- <children>
- <leafNode name="match-frag">
- <properties>
- <help>Second and further fragments of fragmented packets</help>
- <valueless/>
- </properties>
- </leafNode>
- <leafNode name="match-non-frag">
- <properties>
- <help>Head fragments or unfragmented packets</help>
- <valueless/>
- </properties>
- </leafNode>
- </children>
-</node>
-<node name="ipsec">
- <properties>
- <help>Inbound IPsec packets</help>
- </properties>
- <children>
- <leafNode name="match-ipsec">
- <properties>
- <help>Inbound IPsec packets</help>
- <valueless/>
- </properties>
- </leafNode>
- <leafNode name="match-none">
- <properties>
- <help>Inbound non-IPsec packets</help>
- <valueless/>
- </properties>
- </leafNode>
- </children>
-</node>
-<node name="limit">
- <properties>
- <help>Rate limit using a token bucket filter</help>
- </properties>
- <children>
- <leafNode name="burst">
- <properties>
- <help>Maximum number of packets to allow in excess of rate</help>
- <valueHelp>
- <format>u32:0-4294967295</format>
- <description>Maximum number of packets to allow in excess of rate</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 0-4294967295"/>
- </constraint>
- </properties>
- </leafNode>
- <leafNode name="rate">
- <properties>
- <help>Maximum average matching rate</help>
- <valueHelp>
- <format>u32:0-4294967295</format>
- <description>Maximum average matching rate</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 0-4294967295"/>
- </constraint>
- </properties>
- </leafNode>
- </children>
-</node>
+#include <include/firewall/fragment.xml.i>
+#include <include/firewall/match-ipsec.xml.i>
+#include <include/firewall/limit.xml.i>
#include <include/firewall/log.xml.i>
<leafNode name="protocol">
<properties>
diff --git a/interface-definitions/include/policy/route-ipv4.xml.i b/interface-definitions/include/policy/route-ipv4.xml.i
index 1f717a1a4..c12abcae2 100644
--- a/interface-definitions/include/policy/route-ipv4.xml.i
+++ b/interface-definitions/include/policy/route-ipv4.xml.i
@@ -10,36 +10,5 @@
#include <include/firewall/port.xml.i>
</children>
</node>
-<node name="icmp">
- <properties>
- <help>ICMP type and code information</help>
- </properties>
- <children>
- <leafNode name="code">
- <properties>
- <help>ICMP code (0-255)</help>
- <valueHelp>
- <format>u32:0-255</format>
- <description>ICMP code (0-255)</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 0-255"/>
- </constraint>
- </properties>
- </leafNode>
- <leafNode name="type">
- <properties>
- <help>ICMP type (0-255)</help>
- <valueHelp>
- <format>u32:0-255</format>
- <description>ICMP type (0-255)</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 0-255"/>
- </constraint>
- </properties>
- </leafNode>
- #include <include/firewall/icmp-type-name.xml.i>
- </children>
-</node>
+#include <include/firewall/icmp.xml.i>
<!-- include end -->
diff --git a/interface-definitions/include/version/firewall-version.xml.i b/interface-definitions/include/version/firewall-version.xml.i
index fa8e26f78..560ed9e5f 100644
--- a/interface-definitions/include/version/firewall-version.xml.i
+++ b/interface-definitions/include/version/firewall-version.xml.i
@@ -1,3 +1,3 @@
<!-- include start from include/version/firewall-version.xml.i -->
-<syntaxVersion component='firewall' version='15'></syntaxVersion>
+<syntaxVersion component='firewall' version='16'></syntaxVersion>
<!-- include end -->
diff --git a/interface-definitions/load-balancing_reverse-proxy.xml.in b/interface-definitions/load-balancing_reverse-proxy.xml.in
index 09fa9eb29..1a432be6d 100644
--- a/interface-definitions/load-balancing_reverse-proxy.xml.in
+++ b/interface-definitions/load-balancing_reverse-proxy.xml.in
@@ -152,6 +152,37 @@
</node>
</children>
</node>
+ <leafNode name="health-check">
+ <properties>
+ <help>Non HTTP health check options</help>
+ <completionHelp>
+ <list>ldap mysql pgsql redis smtp</list>
+ </completionHelp>
+ <valueHelp>
+ <format>ldap</format>
+ <description>LDAP protocol check</description>
+ </valueHelp>
+ <valueHelp>
+ <format>mysql</format>
+ <description>MySQL protocol check</description>
+ </valueHelp>
+ <valueHelp>
+ <format>pgsql</format>
+ <description>PostgreSQL protocol check</description>
+ </valueHelp>
+ <valueHelp>
+ <format>redis</format>
+ <description>Redis protocol check</description>
+ </valueHelp>
+ <valueHelp>
+ <format>smtp</format>
+ <description>SMTP protocol check</description>
+ </valueHelp>
+ <constraint>
+ <regex>(ldap|mysql|redis|pgsql|smtp)</regex>
+ </constraint>
+ </properties>
+ </leafNode>
#include <include/haproxy/rule-backend.xml.i>
<tagNode name="server">
<properties>
diff --git a/interface-definitions/system_conntrack.xml.in b/interface-definitions/system_conntrack.xml.in
index 66f3d4e05..0dfa2ea81 100644
--- a/interface-definitions/system_conntrack.xml.in
+++ b/interface-definitions/system_conntrack.xml.in
@@ -509,7 +509,6 @@
</node>
</children>
</node>
- #include <include/conntrack/timeout-common-protocols.xml.i>
</children>
</node>
</children>
diff --git a/op-mode-definitions/mtr.xml.in b/op-mode-definitions/mtr.xml.in
index 8239aec4c..66729e2bc 100644
--- a/op-mode-definitions/mtr.xml.in
+++ b/op-mode-definitions/mtr.xml.in
@@ -13,7 +13,7 @@
<children>
<leafNode name="node.tag">
<properties>
- <help>mtr options</help>
+ <help>Traceroute options</help>
<completionHelp>
<script>${vyos_op_scripts_dir}/mtr.py --get-options-nested "${COMP_WORDS[@]}"</script>
</completionHelp>
@@ -35,7 +35,7 @@
<children>
<leafNode name="node.tag">
<properties>
- <help>Traceroute options</help>
+ <help>mtr options</help>
<completionHelp>
<script>${vyos_op_scripts_dir}/mtr.py --get-options "${COMP_WORDS[@]}"</script>
</completionHelp>
diff --git a/python/vyos/compose_config.py b/python/vyos/compose_config.py
new file mode 100644
index 000000000..efa28babe
--- /dev/null
+++ b/python/vyos/compose_config.py
@@ -0,0 +1,84 @@
+# Copyright 2024 VyOS maintainers and contributors <maintainers@vyos.io>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+"""This module allows iterating over function calls to modify an existing
+config.
+"""
+
+from pathlib import Path
+from typing import TypeAlias, Union, Callable
+
+from vyos.configtree import ConfigTree
+from vyos.configtree import deep_copy as ct_deep_copy
+from vyos.utils.system import load_as_module
+
+ConfigObj: TypeAlias = Union[str, ConfigTree]
+
+class ComposeConfigError(Exception):
+ """Raised when an error occurs modifying a config object.
+ """
+
+class ComposeConfig:
+ """Apply function to config tree: for iteration over functions or files.
+ """
+ def __init__(self, config_obj: ConfigObj, checkpoint_file=None):
+ if isinstance(config_obj, ConfigTree):
+ self.config_tree = config_obj
+ else:
+ self.config_tree = ConfigTree(config_obj)
+
+ self.checkpoint = self.config_tree
+ self.checkpoint_file = checkpoint_file
+
+ def apply_func(self, func: Callable):
+ """Apply the function to the config tree.
+ """
+ if not callable(func):
+ raise ComposeConfigError(f'{func.__name__} is not callable')
+
+ if self.checkpoint_file is not None:
+ self.checkpoint = ct_deep_copy(self.config_tree)
+
+ try:
+ func(self.config_tree)
+ except Exception as e:
+ self.config_tree = self.checkpoint
+ raise ComposeConfigError(e) from e
+
+ def apply_file(self, func_file: str, func_name: str):
+ """Apply named function from file.
+ """
+ try:
+ mod_name = Path(func_file).stem.replace('-', '_')
+ mod = load_as_module(mod_name, func_file)
+ func = getattr(mod, func_name)
+ except Exception as e:
+ raise ComposeConfigError(f'Error with {func_file}: {e}') from e
+
+ try:
+ self.apply_func(func)
+ except ComposeConfigError as e:
+ raise ComposeConfigError(f'Error in {func_file}: {e}') from e
+
+ def to_string(self, with_version=False) -> str:
+ """Return the rendered config tree.
+ """
+ return self.config_tree.to_string(no_version=not with_version)
+
+ def write(self, config_file: str, with_version=False):
+ """Write the config tree to a file.
+ """
+ config_str = self.to_string(with_version=with_version)
+ Path(config_file).write_text(config_str)
diff --git a/python/vyos/configtree.py b/python/vyos/configtree.py
index e4b282d72..afd6e030b 100644
--- a/python/vyos/configtree.py
+++ b/python/vyos/configtree.py
@@ -175,9 +175,11 @@ class ConfigTree(object):
def get_version_string(self):
return self.__version
- def to_string(self, ordered_values=False):
+ def to_string(self, ordered_values=False, no_version=False):
config_string = self.__to_string(self.__config, ordered_values).decode()
config_string = unescape_backslash(config_string)
+ if no_version:
+ return config_string
config_string = "{0}\n{1}".format(config_string, self.__version)
return config_string
@@ -482,3 +484,9 @@ class DiffTree:
add = self.add.to_commands()
delete = self.delete.to_commands(op="delete")
return delete + "\n" + add
+
+def deep_copy(config_tree: ConfigTree) -> ConfigTree:
+ """An inelegant, but reasonably fast, copy; replace with backend copy
+ """
+ D = DiffTree(None, config_tree)
+ return D.add
diff --git a/python/vyos/defaults.py b/python/vyos/defaults.py
index 64145a42e..e7cd69a8b 100644
--- a/python/vyos/defaults.py
+++ b/python/vyos/defaults.py
@@ -25,6 +25,7 @@ directories = {
'services' : f'{base_dir}/services',
'config' : '/opt/vyatta/etc/config',
'migrate' : '/opt/vyatta/etc/config-migrate/migrate',
+ 'activate' : f'{base_dir}/activate',
'log' : '/var/log/vyatta',
'templates' : '/usr/share/vyos/templates/',
'certbot' : '/config/auth/letsencrypt',
@@ -46,3 +47,5 @@ cfg_vintage = 'vyos'
commit_lock = '/opt/vyatta/config/.lock'
component_version_json = os.path.join(directories['data'], 'component-versions.json')
+
+config_default = os.path.join(directories['data'], 'config.boot.default')
diff --git a/python/vyos/firewall.py b/python/vyos/firewall.py
index d7b7b80a8..664df28cc 100644
--- a/python/vyos/firewall.py
+++ b/python/vyos/firewall.py
@@ -178,6 +178,8 @@ def parse_rule(rule_conf, hook, fw_name, rule_id, ip_name):
hook_name = 'input'
if hook == 'OUT':
hook_name = 'output'
+ if hook == 'PRE':
+ hook_name = 'prerouting'
if hook == 'NAM':
hook_name = f'name{def_suffix}'
output.append(f'{ip_name} {prefix}addr {operator} @FQDN_{hook_name}_{fw_name}_{rule_id}_{prefix}')
@@ -193,6 +195,8 @@ def parse_rule(rule_conf, hook, fw_name, rule_id, ip_name):
hook_name = 'input'
if hook == 'OUT':
hook_name = 'output'
+ if hook == 'PRE':
+ hook_name = 'prerouting'
if hook == 'NAM':
hook_name = f'name'
output.append(f'{ip_name} {prefix}addr {operator} @GEOIP_CC{def_suffix}_{hook_name}_{fw_name}_{rule_id}')
@@ -477,8 +481,6 @@ def parse_rule(rule_conf, hook, fw_name, rule_id, ip_name):
output.append(f'tcp option maxseg size set {mss}')
if 'action' in rule_conf:
- # Change action=return to action=action
- # #output.append(nft_action(rule_conf['action']))
if rule_conf['action'] == 'offload':
offload_target = rule_conf['offload_target']
output.append(f'flow add @VYOS_FLOWTABLE_{offload_target}')
diff --git a/python/vyos/ifconfig/vxlan.py b/python/vyos/ifconfig/vxlan.py
index bdb48e303..918aea202 100644
--- a/python/vyos/ifconfig/vxlan.py
+++ b/python/vyos/ifconfig/vxlan.py
@@ -138,10 +138,13 @@ class VXLANIf(Interface):
raise ValueError('Value out of range')
if 'vlan_to_vni_removed' in self.config:
- cur_vni_filter = get_vxlan_vni_filter(self.ifname)
+ cur_vni_filter = None
+ if dict_search('parameters.vni_filter', self.config) != None:
+ cur_vni_filter = get_vxlan_vni_filter(self.ifname)
+
for vlan, vlan_config in self.config['vlan_to_vni_removed'].items():
# If VNI filtering is enabled, remove matching VNI filter
- if dict_search('parameters.vni_filter', self.config) != None:
+ if cur_vni_filter != None:
vni = vlan_config['vni']
if vni in cur_vni_filter:
self._cmd(f'bridge vni delete dev {self.ifname} vni {vni}')
diff --git a/smoketest/scripts/cli/test_firewall.py b/smoketest/scripts/cli/test_firewall.py
index c47562714..0943d8e24 100755
--- a/smoketest/scripts/cli/test_firewall.py
+++ b/smoketest/scripts/cli/test_firewall.py
@@ -23,6 +23,7 @@ from base_vyostest_shim import VyOSUnitTestSHIM
from vyos.configsession import ConfigSessionError
from vyos.utils.process import run
+from vyos.utils.file import read_file
sysfs_config = {
'all_ping': {'sysfs': '/proc/sys/net/ipv4/icmp_echo_ignore_all', 'default': '0', 'test_value': 'disable'},
@@ -38,6 +39,10 @@ sysfs_config = {
'twa_hazards_protection': {'sysfs': '/proc/sys/net/ipv4/tcp_rfc1337', 'default': '0', 'test_value': 'enable'}
}
+def get_sysctl(parameter):
+ tmp = parameter.replace(r'.', r'/')
+ return read_file(f'/proc/sys/{tmp}')
+
class TestFirewall(VyOSUnitTestSHIM.TestCase):
@classmethod
def setUpClass(cls):
@@ -236,6 +241,14 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase):
self.cli_set(['firewall', 'ipv4', 'output', 'filter', 'rule', '6', 'protocol', 'icmp'])
self.cli_set(['firewall', 'ipv4', 'output', 'filter', 'rule', '6', 'connection-mark', conn_mark])
+ self.cli_set(['firewall', 'ipv4', 'output', 'raw', 'default-action', 'drop'])
+ self.cli_set(['firewall', 'ipv4', 'output', 'raw', 'rule', '1', 'action', 'accept'])
+ self.cli_set(['firewall', 'ipv4', 'output', 'raw', 'rule', '1', 'protocol', 'udp'])
+
+ self.cli_set(['firewall', 'ipv4', 'prerouting', 'raw', 'rule', '1', 'action', 'notrack'])
+ self.cli_set(['firewall', 'ipv4', 'prerouting', 'raw', 'rule', '1', 'protocol', 'tcp'])
+ self.cli_set(['firewall', 'ipv4', 'prerouting', 'raw', 'rule', '1', 'destination', 'port', '23'])
+
self.cli_commit()
mark_hex = "{0:#010x}".format(int(conn_mark))
@@ -256,6 +269,14 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase):
['meta l4proto gre', f'oifname != "{interface}"', 'drop'],
['meta l4proto icmp', f'ct mark {mark_hex}', 'return'],
['log prefix "[ipv4-OUT-filter-default-D]"','OUT-filter default-action drop', 'drop'],
+ ['chain VYOS_OUTPUT_raw'],
+ ['type filter hook output priority raw; policy accept;'],
+ ['udp', 'accept'],
+ ['OUT-raw default-action drop', 'drop'],
+ ['chain VYOS_PREROUTING_raw'],
+ ['type filter hook prerouting priority raw; policy accept;'],
+ ['tcp dport 23', 'notrack'],
+ ['PRE-raw default-action accept', 'accept'],
['chain NAME_smoketest'],
['saddr 172.16.20.10', 'daddr 172.16.10.10', 'log prefix "[ipv4-NAM-smoketest-1-A]" log level debug', 'ip ttl 15', 'accept'],
['tcp flags syn / syn,ack', 'tcp dport 8888', 'log prefix "[ipv4-NAM-smoketest-2-R]" log level err', 'ip ttl > 102', 'reject'],
@@ -446,16 +467,24 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase):
self.cli_set(['firewall', 'ipv6', 'forward', 'filter', 'rule', '2', 'destination', 'port', '8888'])
self.cli_set(['firewall', 'ipv6', 'forward', 'filter', 'rule', '2', 'inbound-interface', 'name', interface])
+ self.cli_set(['firewall', 'ipv6', 'input', 'filter', 'rule', '3', 'action', 'accept'])
+ self.cli_set(['firewall', 'ipv6', 'input', 'filter', 'rule', '3', 'protocol', 'udp'])
+ self.cli_set(['firewall', 'ipv6', 'input', 'filter', 'rule', '3', 'source', 'address', '2002::1:2'])
+ self.cli_set(['firewall', 'ipv6', 'input', 'filter', 'rule', '3', 'inbound-interface', 'name', interface])
+
self.cli_set(['firewall', 'ipv6', 'output', 'filter', 'default-action', 'drop'])
self.cli_set(['firewall', 'ipv6', 'output', 'filter', 'default-log'])
self.cli_set(['firewall', 'ipv6', 'output', 'filter', 'rule', '3', 'action', 'return'])
self.cli_set(['firewall', 'ipv6', 'output', 'filter', 'rule', '3', 'protocol', 'gre'])
self.cli_set(['firewall', 'ipv6', 'output', 'filter', 'rule', '3', 'outbound-interface', 'name', interface])
- self.cli_set(['firewall', 'ipv6', 'input', 'filter', 'rule', '3', 'action', 'accept'])
- self.cli_set(['firewall', 'ipv6', 'input', 'filter', 'rule', '3', 'protocol', 'udp'])
- self.cli_set(['firewall', 'ipv6', 'input', 'filter', 'rule', '3', 'source', 'address', '2002::1:2'])
- self.cli_set(['firewall', 'ipv6', 'input', 'filter', 'rule', '3', 'inbound-interface', 'name', interface])
+ self.cli_set(['firewall', 'ipv6', 'output', 'raw', 'default-action', 'drop'])
+ self.cli_set(['firewall', 'ipv6', 'output', 'raw', 'rule', '1', 'action', 'notrack'])
+ self.cli_set(['firewall', 'ipv6', 'output', 'raw', 'rule', '1', 'protocol', 'udp'])
+
+ self.cli_set(['firewall', 'ipv6', 'prerouting', 'raw', 'rule', '1', 'action', 'drop'])
+ self.cli_set(['firewall', 'ipv6', 'prerouting', 'raw', 'rule', '1', 'protocol', 'tcp'])
+ self.cli_set(['firewall', 'ipv6', 'prerouting', 'raw', 'rule', '1', 'destination', 'port', '23'])
self.cli_commit()
@@ -472,6 +501,14 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase):
['type filter hook output priority filter; policy accept;'],
['meta l4proto gre', f'oifname "{interface}"', 'return'],
['log prefix "[ipv6-OUT-filter-default-D]"','OUT-filter default-action drop', 'drop'],
+ ['chain VYOS_IPV6_OUTPUT_raw'],
+ ['type filter hook output priority raw; policy accept;'],
+ ['udp', 'notrack'],
+ ['OUT-raw default-action drop', 'drop'],
+ ['chain VYOS_IPV6_PREROUTING_raw'],
+ ['type filter hook prerouting priority raw; policy accept;'],
+ ['tcp dport 23', 'drop'],
+ ['PRE-raw default-action accept', 'accept'],
[f'chain NAME6_{name}'],
['saddr 2002::1', 'daddr 2002::1:1', 'log prefix "[ipv6-NAM-v6-smoketest-1-A]" log level crit', 'accept'],
[f'"{name} default-action drop"', f'log prefix "[ipv6-{name}-default-D]"', 'drop'],
@@ -738,6 +775,89 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase):
with open(path, 'r') as f:
self.assertNotEqual(f.read().strip(), conf['default'], msg=path)
+ def test_timeout_sysctl(self):
+ timeout_config = {
+ 'net.netfilter.nf_conntrack_icmp_timeout' :{
+ 'cli' : ['global-options', 'timeout', 'icmp'],
+ 'test_value' : '180',
+ 'default_value' : '30',
+ },
+ 'net.netfilter.nf_conntrack_generic_timeout' :{
+ 'cli' : ['global-options', 'timeout', 'other'],
+ 'test_value' : '1200',
+ 'default_value' : '600',
+ },
+ 'net.netfilter.nf_conntrack_tcp_timeout_close_wait' :{
+ 'cli' : ['global-options', 'timeout', 'tcp', 'close-wait'],
+ 'test_value' : '30',
+ 'default_value' : '60',
+ },
+ 'net.netfilter.nf_conntrack_tcp_timeout_close' :{
+ 'cli' : ['global-options', 'timeout', 'tcp', 'close'],
+ 'test_value' : '20',
+ 'default_value' : '10',
+ },
+ 'net.netfilter.nf_conntrack_tcp_timeout_established' :{
+ 'cli' : ['global-options', 'timeout', 'tcp', 'established'],
+ 'test_value' : '1000',
+ 'default_value' : '432000',
+ },
+ 'net.netfilter.nf_conntrack_tcp_timeout_fin_wait' :{
+ 'cli' : ['global-options', 'timeout', 'tcp', 'fin-wait'],
+ 'test_value' : '240',
+ 'default_value' : '120',
+ },
+ 'net.netfilter.nf_conntrack_tcp_timeout_last_ack' :{
+ 'cli' : ['global-options', 'timeout', 'tcp', 'last-ack'],
+ 'test_value' : '300',
+ 'default_value' : '30',
+ },
+ 'net.netfilter.nf_conntrack_tcp_timeout_syn_recv' :{
+ 'cli' : ['global-options', 'timeout', 'tcp', 'syn-recv'],
+ 'test_value' : '100',
+ 'default_value' : '60',
+ },
+ 'net.netfilter.nf_conntrack_tcp_timeout_syn_sent' :{
+ 'cli' : ['global-options', 'timeout', 'tcp', 'syn-sent'],
+ 'test_value' : '300',
+ 'default_value' : '120',
+ },
+ 'net.netfilter.nf_conntrack_tcp_timeout_time_wait' :{
+ 'cli' : ['global-options', 'timeout', 'tcp', 'time-wait'],
+ 'test_value' : '303',
+ 'default_value' : '120',
+ },
+ 'net.netfilter.nf_conntrack_udp_timeout' :{
+ 'cli' : ['global-options', 'timeout', 'udp', 'other'],
+ 'test_value' : '90',
+ 'default_value' : '30',
+ },
+ 'net.netfilter.nf_conntrack_udp_timeout_stream' :{
+ 'cli' : ['global-options', 'timeout', 'udp', 'stream'],
+ 'test_value' : '200',
+ 'default_value' : '180',
+ },
+ }
+
+ for parameter, parameter_config in timeout_config.items():
+ self.cli_set(['firewall'] + parameter_config['cli'] + [parameter_config['test_value']])
+
+ # commit changes
+ self.cli_commit()
+
+ # validate configuration
+ for parameter, parameter_config in timeout_config.items():
+ tmp = parameter_config['test_value']
+ self.assertEqual(get_sysctl(f'{parameter}'), tmp)
+
+ # delete all configuration options and revert back to defaults
+ self.cli_delete(['firewall', 'global-options', 'timeout'])
+ self.cli_commit()
+
+ # validate configuration
+ for parameter, parameter_config in timeout_config.items():
+ self.assertEqual(get_sysctl(f'{parameter}'), parameter_config['default_value'])
+
### Zone
def test_zone_basic(self):
self.cli_set(['firewall', 'ipv4', 'name', 'smoketest', 'default-action', 'drop'])
diff --git a/smoketest/scripts/cli/test_load-balancing_reverse-proxy.py b/smoketest/scripts/cli/test_load-balancing_reverse-proxy.py
index 2b2f93cdf..aa796f59f 100755
--- a/smoketest/scripts/cli/test_load-balancing_reverse-proxy.py
+++ b/smoketest/scripts/cli/test_load-balancing_reverse-proxy.py
@@ -338,6 +338,11 @@ class TestLoadBalancingReverseProxy(VyOSUnitTestSHIM.TestCase):
self.assertIn('http-check send meth GET uri /health', config)
self.assertIn('http-check expect string success', config)
+ # Test configuring both http-check & health-check fails validation script
+ self.cli_set(base_path + ['backend', 'bk-01', 'health-check', 'ldap'])
+ with self.assertRaises(ConfigSessionError) as e:
+ self.cli_commit()
+
def test_06_lb_reverse_proxy_tcp_mode(self):
frontend = 'tcp_8443'
mode = 'tcp'
@@ -405,6 +410,54 @@ class TestLoadBalancingReverseProxy(VyOSUnitTestSHIM.TestCase):
with self.assertRaises(ConfigSessionError) as e:
self.cli_commit()
+ def test_08_lb_reverse_proxy_tcp_health_checks(self):
+ # Setup PKI
+ self.configure_pki()
+
+ # Define variables
+ frontend = 'fe_ldaps'
+ mode = 'tcp'
+ health_check = 'ldap'
+ front_port = '636'
+ bk_name = 'bk_ldap'
+ bk_servers = ['192.0.2.11', '192.0.2.12']
+ bk_server_port = '389'
+
+ # Configure frontend
+ self.cli_set(base_path + ['service', frontend, 'mode', mode])
+ self.cli_set(base_path + ['service', frontend, 'port', front_port])
+ self.cli_set(base_path + ['service', frontend, 'ssl', 'certificate', 'smoketest'])
+
+ # Configure backend
+ self.cli_set(base_path + ['backend', bk_name, 'mode', mode])
+ self.cli_set(base_path + ['backend', bk_name, 'health-check', health_check])
+ for index, bk_server in enumerate(bk_servers):
+ self.cli_set(base_path + ['backend', bk_name, 'server', f'srv-{index}', 'address', bk_server])
+ self.cli_set(base_path + ['backend', bk_name, 'server', f'srv-{index}', 'port', bk_server_port])
+
+ # Commit & read config
+ self.cli_commit()
+ config = read_file(HAPROXY_CONF)
+
+ # Validate Frontend
+ self.assertIn(f'frontend {frontend}', config)
+ self.assertIn(f'bind [::]:{front_port} v4v6 ssl crt /run/haproxy/smoketest.pem', config)
+ self.assertIn(f'mode {mode}', config)
+ self.assertIn(f'backend {bk_name}', config)
+
+ # Validate Backend
+ self.assertIn(f'backend {bk_name}', config)
+ self.assertIn(f'option {health_check}-check', config)
+ self.assertIn(f'mode {mode}', config)
+ for index, bk_server in enumerate(bk_servers):
+ self.assertIn(f'server srv-{index} {bk_server}:{bk_server_port}', config)
+
+ # Validate SMTP option renders correctly
+ self.cli_set(base_path + ['backend', bk_name, 'health-check', 'smtp'])
+ self.cli_commit()
+ config = read_file(HAPROXY_CONF)
+ self.assertIn(f'option smtpchk', config)
+
if __name__ == '__main__':
unittest.main(verbosity=2)
diff --git a/smoketest/scripts/cli/test_protocols_isis.py b/smoketest/scripts/cli/test_protocols_isis.py
index 9c57f2020..769f3dd33 100755
--- a/smoketest/scripts/cli/test_protocols_isis.py
+++ b/smoketest/scripts/cli/test_protocols_isis.py
@@ -60,6 +60,7 @@ class TestProtocolsISIS(VyOSUnitTestSHIM.TestCase):
prefix_list = 'EXPORT-ISIS'
route_map = 'EXPORT-ISIS'
rule = '10'
+ metric_style = 'transition'
self.cli_set(['policy', 'prefix-list', prefix_list, 'rule', rule, 'action', 'permit'])
self.cli_set(['policy', 'prefix-list', prefix_list, 'rule', rule, 'prefix', '203.0.113.0/24'])
@@ -80,6 +81,7 @@ class TestProtocolsISIS(VyOSUnitTestSHIM.TestCase):
self.cli_commit()
self.cli_set(base_path + ['redistribute', 'ipv4', 'connected', 'level-2', 'route-map', route_map])
+ self.cli_set(base_path + ['metric-style', metric_style])
self.cli_set(base_path + ['log-adjacency-changes'])
# Commit all changes
@@ -88,6 +90,7 @@ class TestProtocolsISIS(VyOSUnitTestSHIM.TestCase):
# Verify all changes
tmp = self.getFRRconfig(f'router isis {domain}', daemon='isisd')
self.assertIn(f' net {net}', tmp)
+ self.assertIn(f' metric-style {metric_style}', tmp)
self.assertIn(f' log-adjacency-changes', tmp)
self.assertIn(f' redistribute ipv4 connected level-2 route-map {route_map}', tmp)
@@ -401,7 +404,6 @@ class TestProtocolsISIS(VyOSUnitTestSHIM.TestCase):
# Set a basic IS-IS config
self.cli_set(base_path + ['net', net])
-
self.cli_set(base_path + ['interface', interface])
for topology in topologies:
self.cli_set(base_path + ['topology', topology])
diff --git a/smoketest/scripts/cli/test_system_conntrack.py b/smoketest/scripts/cli/test_system_conntrack.py
index c6d8a5436..3ae7b6217 100755
--- a/smoketest/scripts/cli/test_system_conntrack.py
+++ b/smoketest/scripts/cli/test_system_conntrack.py
@@ -68,66 +68,6 @@ class TestSystemConntrack(VyOSUnitTestSHIM.TestCase):
'test_value' : '128',
'default_value' : '3',
},
- 'net.netfilter.nf_conntrack_icmp_timeout' :{
- 'cli' : ['timeout', 'icmp'],
- 'test_value' : '180',
- 'default_value' : '30',
- },
- 'net.netfilter.nf_conntrack_generic_timeout' :{
- 'cli' : ['timeout', 'other'],
- 'test_value' : '1200',
- 'default_value' : '600',
- },
- 'net.netfilter.nf_conntrack_tcp_timeout_close_wait' :{
- 'cli' : ['timeout', 'tcp', 'close-wait'],
- 'test_value' : '30',
- 'default_value' : '60',
- },
- 'net.netfilter.nf_conntrack_tcp_timeout_close' :{
- 'cli' : ['timeout', 'tcp', 'close'],
- 'test_value' : '20',
- 'default_value' : '10',
- },
- 'net.netfilter.nf_conntrack_tcp_timeout_established' :{
- 'cli' : ['timeout', 'tcp', 'established'],
- 'test_value' : '1000',
- 'default_value' : '432000',
- },
- 'net.netfilter.nf_conntrack_tcp_timeout_fin_wait' :{
- 'cli' : ['timeout', 'tcp', 'fin-wait'],
- 'test_value' : '240',
- 'default_value' : '120',
- },
- 'net.netfilter.nf_conntrack_tcp_timeout_last_ack' :{
- 'cli' : ['timeout', 'tcp', 'last-ack'],
- 'test_value' : '300',
- 'default_value' : '30',
- },
- 'net.netfilter.nf_conntrack_tcp_timeout_syn_recv' :{
- 'cli' : ['timeout', 'tcp', 'syn-recv'],
- 'test_value' : '100',
- 'default_value' : '60',
- },
- 'net.netfilter.nf_conntrack_tcp_timeout_syn_sent' :{
- 'cli' : ['timeout', 'tcp', 'syn-sent'],
- 'test_value' : '300',
- 'default_value' : '120',
- },
- 'net.netfilter.nf_conntrack_tcp_timeout_time_wait' :{
- 'cli' : ['timeout', 'tcp', 'time-wait'],
- 'test_value' : '303',
- 'default_value' : '120',
- },
- 'net.netfilter.nf_conntrack_udp_timeout' :{
- 'cli' : ['timeout', 'udp', 'other'],
- 'test_value' : '90',
- 'default_value' : '30',
- },
- 'net.netfilter.nf_conntrack_udp_timeout_stream' :{
- 'cli' : ['timeout', 'udp', 'stream'],
- 'test_value' : '200',
- 'default_value' : '180',
- },
}
for parameter, parameter_config in conntrack_config.items():
diff --git a/src/activation-scripts/20-ethernet_offload.py b/src/activation-scripts/20-ethernet_offload.py
new file mode 100755
index 000000000..33b0ea469
--- /dev/null
+++ b/src/activation-scripts/20-ethernet_offload.py
@@ -0,0 +1,103 @@
+# Copyright 2021-2024 VyOS maintainers and contributors <maintainers@vyos.io>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+# T3619: mirror Linux Kernel defaults for ethernet offloading options into VyOS
+# CLI. See https://vyos.dev/T3619#102254 for all the details.
+# T3787: Remove deprecated UDP fragmentation offloading option
+# T6006: add to activation-scripts: migration-scripts/interfaces/20-to-21
+
+from vyos.ethtool import Ethtool
+from vyos.configtree import ConfigTree
+
+def activate(config: ConfigTree):
+ base = ['interfaces', 'ethernet']
+
+ if not config.exists(base):
+ return
+
+ for ifname in config.list_nodes(base):
+ eth = Ethtool(ifname)
+
+ # If GRO is enabled by the Kernel - we reflect this on the CLI. If GRO is
+ # enabled via CLI but not supported by the NIC - we remove it from the CLI
+ configured = config.exists(base + [ifname, 'offload', 'gro'])
+ enabled, fixed = eth.get_generic_receive_offload()
+ if configured and fixed:
+ config.delete(base + [ifname, 'offload', 'gro'])
+ elif enabled and not fixed:
+ config.set(base + [ifname, 'offload', 'gro'])
+
+ # If GSO is enabled by the Kernel - we reflect this on the CLI. If GSO is
+ # enabled via CLI but not supported by the NIC - we remove it from the CLI
+ configured = config.exists(base + [ifname, 'offload', 'gso'])
+ enabled, fixed = eth.get_generic_segmentation_offload()
+ if configured and fixed:
+ config.delete(base + [ifname, 'offload', 'gso'])
+ elif enabled and not fixed:
+ config.set(base + [ifname, 'offload', 'gso'])
+
+ # If LRO is enabled by the Kernel - we reflect this on the CLI. If LRO is
+ # enabled via CLI but not supported by the NIC - we remove it from the CLI
+ configured = config.exists(base + [ifname, 'offload', 'lro'])
+ enabled, fixed = eth.get_large_receive_offload()
+ if configured and fixed:
+ config.delete(base + [ifname, 'offload', 'lro'])
+ elif enabled and not fixed:
+ config.set(base + [ifname, 'offload', 'lro'])
+
+ # If SG is enabled by the Kernel - we reflect this on the CLI. If SG is
+ # enabled via CLI but not supported by the NIC - we remove it from the CLI
+ configured = config.exists(base + [ifname, 'offload', 'sg'])
+ enabled, fixed = eth.get_scatter_gather()
+ if configured and fixed:
+ config.delete(base + [ifname, 'offload', 'sg'])
+ elif enabled and not fixed:
+ config.set(base + [ifname, 'offload', 'sg'])
+
+ # If TSO is enabled by the Kernel - we reflect this on the CLI. If TSO is
+ # enabled via CLI but not supported by the NIC - we remove it from the CLI
+ configured = config.exists(base + [ifname, 'offload', 'tso'])
+ enabled, fixed = eth.get_tcp_segmentation_offload()
+ if configured and fixed:
+ config.delete(base + [ifname, 'offload', 'tso'])
+ elif enabled and not fixed:
+ config.set(base + [ifname, 'offload', 'tso'])
+
+ # Remove deprecated UDP fragmentation offloading option
+ if config.exists(base + [ifname, 'offload', 'ufo']):
+ config.delete(base + [ifname, 'offload', 'ufo'])
+
+ # Also while processing the interface configuration, not all adapters support
+ # changing the speed and duplex settings. If the desired speed and duplex
+ # values do not work for the NIC driver, we change them back to the default
+ # value of "auto" - which will be applied if the CLI node is deleted.
+ speed_path = base + [ifname, 'speed']
+ duplex_path = base + [ifname, 'duplex']
+ # speed and duplex must always be set at the same time if not set to "auto"
+ if config.exists(speed_path) and config.exists(duplex_path):
+ speed = config.return_value(speed_path)
+ duplex = config.return_value(duplex_path)
+ if speed != 'auto' and duplex != 'auto':
+ if not eth.check_speed_duplex(speed, duplex):
+ config.delete(speed_path)
+ config.delete(duplex_path)
+
+ # Also while processing the interface configuration, not all adapters support
+ # changing disabling flow-control - or change this setting. If disabling
+ # flow-control is not supported by the NIC, we remove the setting from CLI
+ flow_control_path = base + [ifname, 'disable-flow-control']
+ if config.exists(flow_control_path):
+ if not eth.check_flow_control():
+ config.delete(flow_control_path)
diff --git a/src/conf_mode/firewall.py b/src/conf_mode/firewall.py
index e96e57154..4c289b921 100755
--- a/src/conf_mode/firewall.py
+++ b/src/conf_mode/firewall.py
@@ -33,6 +33,7 @@ from vyos.template import render
from vyos.utils.dict import dict_search_args
from vyos.utils.dict import dict_search_recursive
from vyos.utils.process import call
+from vyos.utils.process import cmd
from vyos.utils.process import rc_cmd
from vyos import ConfigError
from vyos import airbag
@@ -40,20 +41,7 @@ from vyos import airbag
airbag.enable()
nftables_conf = '/run/nftables.conf'
-
-sysfs_config = {
- 'all_ping': {'sysfs': '/proc/sys/net/ipv4/icmp_echo_ignore_all', 'enable': '0', 'disable': '1'},
- 'broadcast_ping': {'sysfs': '/proc/sys/net/ipv4/icmp_echo_ignore_broadcasts', 'enable': '0', 'disable': '1'},
- 'directed_broadcast' : {'sysfs': '/proc/sys/net/ipv4/conf/all/bc_forwarding', 'enable': '1', 'disable': '0'},
- 'ip_src_route': {'sysfs': '/proc/sys/net/ipv4/conf/*/accept_source_route'},
- 'ipv6_receive_redirects': {'sysfs': '/proc/sys/net/ipv6/conf/*/accept_redirects'},
- 'ipv6_src_route': {'sysfs': '/proc/sys/net/ipv6/conf/*/accept_source_route', 'enable': '0', 'disable': '-1'},
- 'log_martians': {'sysfs': '/proc/sys/net/ipv4/conf/all/log_martians'},
- 'receive_redirects': {'sysfs': '/proc/sys/net/ipv4/conf/*/accept_redirects'},
- 'send_redirects': {'sysfs': '/proc/sys/net/ipv4/conf/*/send_redirects'},
- 'syn_cookies': {'sysfs': '/proc/sys/net/ipv4/tcp_syncookies'},
- 'twa_hazards_protection': {'sysfs': '/proc/sys/net/ipv4/tcp_rfc1337'}
-}
+sysctl_file = r'/run/sysctl/10-vyos-firewall.conf'
valid_groups = [
'address_group',
@@ -351,7 +339,7 @@ def verify(firewall):
verify_nested_group(group_name, group, groups, [])
if 'ipv4' in firewall:
- for name in ['name','forward','input','output']:
+ for name in ['name','forward','input','output', 'prerouting']:
if name in firewall['ipv4']:
for name_id, name_conf in firewall['ipv4'][name].items():
if 'jump' in name_conf['default_action'] and 'default_jump_target' not in name_conf:
@@ -371,7 +359,7 @@ def verify(firewall):
verify_rule(firewall, rule_conf, False)
if 'ipv6' in firewall:
- for name in ['name','forward','input','output']:
+ for name in ['name','forward','input','output', 'prerouting']:
if name in firewall['ipv6']:
for name_id, name_conf in firewall['ipv6'][name].items():
if 'jump' in name_conf['default_action'] and 'default_jump_target' not in name_conf:
@@ -467,33 +455,16 @@ def generate(firewall):
local_zone_conf['from_local'][zone] = zone_conf['from'][local_zone]
render(nftables_conf, 'firewall/nftables.j2', firewall)
+ render(sysctl_file, 'firewall/sysctl-firewall.conf.j2', firewall)
return None
-def apply_sysfs(firewall):
- for name, conf in sysfs_config.items():
- paths = glob(conf['sysfs'])
- value = None
-
- if name in firewall['global_options']:
- conf_value = firewall['global_options'][name]
- if conf_value in conf:
- value = conf[conf_value]
- elif conf_value == 'enable':
- value = '1'
- elif conf_value == 'disable':
- value = '0'
-
- if value:
- for path in paths:
- with open(path, 'w') as f:
- f.write(value)
-
def apply(firewall):
install_result, output = rc_cmd(f'nft --file {nftables_conf}')
if install_result == 1:
raise ConfigError(f'Failed to apply firewall: {output}')
- apply_sysfs(firewall)
+ # Apply firewall global-options sysctl settings
+ cmd(f'sysctl -f {sysctl_file}')
call_dependents()
diff --git a/src/conf_mode/interfaces_tunnel.py b/src/conf_mode/interfaces_tunnel.py
index 43ba72857..98ef98d12 100755
--- a/src/conf_mode/interfaces_tunnel.py
+++ b/src/conf_mode/interfaces_tunnel.py
@@ -145,11 +145,20 @@ def verify(tunnel):
# If no IP GRE key is defined we can not have more then one GRE tunnel
# bound to any one interface/IP address and the same remote. This will
# result in a OS PermissionError: add tunnel "gre0" failed: File exists
- if (their_address == our_address or our_source_if == their_source_if) and \
- our_remote == their_remote:
- raise ConfigError(f'Missing required "ip key" parameter when '\
- 'running more then one GRE based tunnel on the '\
- 'same source-interface/source-address')
+ if our_remote == their_remote:
+ if our_address is not None and their_address == our_address:
+ # If set to the same values, this is always a fail
+ raise ConfigError(f'Missing required "ip key" parameter when '\
+ 'running more then one GRE based tunnel on the '\
+ 'same source-address')
+
+ if their_source_if == our_source_if and their_address == our_address:
+ # Note that lack of None check on these is deliberate.
+ # source-if and source-ip matching while unset (all None) is a fail
+ # source-ifs set and matching with unset source-ips is a fail
+ raise ConfigError(f'Missing required "ip key" parameter when '\
+ 'running more then one GRE based tunnel on the '\
+ 'same source-interface')
# Keys are not allowed with ipip and sit tunnels
if tunnel['encapsulation'] in ['ipip', 'sit']:
diff --git a/src/conf_mode/load-balancing_reverse-proxy.py b/src/conf_mode/load-balancing_reverse-proxy.py
index 1c1252df0..09c68dadd 100755
--- a/src/conf_mode/load-balancing_reverse-proxy.py
+++ b/src/conf_mode/load-balancing_reverse-proxy.py
@@ -79,12 +79,21 @@ def verify(lb):
raise ConfigError(f'"TCP" port "{tmp_port}" is used by another service')
for back, back_config in lb['backend'].items():
- if 'http-check' in back_config:
- http_check = back_config['http-check']
+ if 'http_check' in back_config:
+ http_check = back_config['http_check']
if 'expect' in http_check and 'status' in http_check['expect'] and 'string' in http_check['expect']:
raise ConfigError(f'"expect status" and "expect string" can not be configured together!')
+
+ if 'health_check' in back_config:
+ if 'mode' not in back_config or back_config['mode'] != 'tcp':
+ raise ConfigError(f'backend "{back}" can only be configured with {back_config["health_check"]} ' +
+ f'health-check whilst in TCP mode!')
+ if 'http_check' in back_config:
+ raise ConfigError(f'backend "{back}" cannot be configured with both http-check and health-check!')
+
if 'server' not in back_config:
raise ConfigError(f'"{back} server" must be configured!')
+
for bk_server, bk_server_conf in back_config['server'].items():
if 'address' not in bk_server_conf or 'port' not in bk_server_conf:
raise ConfigError(f'"backend {back} server {bk_server} address and port" must be configured!')
diff --git a/src/conf_mode/nat64.py b/src/conf_mode/nat64.py
index c1e7ebf85..32a1c47d1 100755
--- a/src/conf_mode/nat64.py
+++ b/src/conf_mode/nat64.py
@@ -20,7 +20,7 @@ import csv
import os
import re
-from ipaddress import IPv6Network
+from ipaddress import IPv6Network, IPv6Address
from json import dumps as json_write
from vyos import ConfigError
@@ -103,8 +103,14 @@ def verify(nat64) -> None:
# Verify that source.prefix is set and is a /96
if not dict_search("source.prefix", instance):
raise ConfigError(f"Source NAT64 rule {rule} missing source prefix")
- if IPv6Network(instance["source"]["prefix"]).prefixlen != 96:
+ src_prefix = IPv6Network(instance["source"]["prefix"])
+ if src_prefix.prefixlen != 96:
raise ConfigError(f"Source NAT64 rule {rule} source prefix must be /96")
+ if (int(src_prefix[0]) & int(IPv6Address('0:0:0:0:ff00::'))) != 0:
+ raise ConfigError(
+ f'Source NAT64 rule {rule} source prefix is not RFC6052-compliant: '
+ 'bits 64 to 71 (9th octet) must be zeroed'
+ )
pools = dict_search("translation.pool", instance)
if pools:
diff --git a/src/conf_mode/nat_cgnat.py b/src/conf_mode/nat_cgnat.py
index 957b12c28..d429f6e21 100755
--- a/src/conf_mode/nat_cgnat.py
+++ b/src/conf_mode/nat_cgnat.py
@@ -111,7 +111,19 @@ def generate_port_rules(
port_count: int,
global_port_range: str = '1024-65535',
) -> list:
- """Generates list of nftables rules for the batch file."""
+ """Generates a list of nftables option rules for the batch file.
+
+ Args:
+ external_hosts (list): A list of external host IPs.
+ internal_hosts (list): A list of internal host IPs.
+ port_count (int): The number of ports required per host.
+ global_port_range (str): The global port range to be used. Default is '1024-65535'.
+
+ Returns:
+ list: A list containing two elements:
+ - proto_map_elements (list): A list of proto map elements.
+ - other_map_elements (list): A list of other map elements.
+ """
rules = []
proto_map_elements = []
other_map_elements = []
@@ -120,13 +132,6 @@ def generate_port_rules(
# Calculate the required number of ports per host
required_ports_per_host = port_count
-
- # Check if there are enough external addresses for all internal hosts
- if required_ports_per_host * len(internal_hosts) > total_possible_ports * len(
- external_hosts
- ):
- raise ConfigError("Not enough ports available for the specified parameters!")
-
current_port = start_port
current_external_index = 0
@@ -141,13 +146,6 @@ def generate_port_rules(
current_port = start_port
next_end_port = current_port + required_ports_per_host - 1
- # Ensure the same port is not assigned to the same external host
- if any(
- rule.endswith(f'{external_host}:{current_port}-{next_end_port}')
- for rule in rules
- ):
- raise ConfigError("Not enough ports available for the specified parameters")
-
proto_map_elements.append(
f'{internal_host} : {external_host} . {current_port}-{next_end_port}'
)
@@ -240,6 +238,49 @@ def verify(config):
used_external_pools[external_pool] = rule
used_internal_pools[internal_pool] = rule
+ # Check calculation for allocation
+ external_port_range: str = config['pool']['external'][external_pool]['external_port_range']
+
+ external_ip_ranges: list = list(
+ config['pool']['external'][external_pool]['range']
+ )
+ internal_ip_ranges: list = config['pool']['internal'][internal_pool]['range']
+ start_port, end_port = map(int, external_port_range.split('-'))
+ ports_per_range_count: int = (end_port - start_port) + 1
+
+ external_list_hosts_count = []
+ external_list_hosts = []
+ internal_list_hosts_count = []
+ internal_list_hosts = []
+ for ext_range in external_ip_ranges:
+ # External hosts count
+ e_count = IPOperations(ext_range).get_ips_count()
+ external_list_hosts_count.append(e_count)
+ # External hosts list
+ e_hosts = IPOperations(ext_range).convert_prefix_to_list_ips()
+ external_list_hosts.extend(e_hosts)
+ for int_range in internal_ip_ranges:
+ # Internal hosts count
+ i_count = IPOperations(int_range).get_ips_count()
+ internal_list_hosts_count.append(i_count)
+ # Internal hosts list
+ i_hosts = IPOperations(int_range).convert_prefix_to_list_ips()
+ internal_list_hosts.extend(i_hosts)
+
+ external_host_count = sum(external_list_hosts_count)
+ internal_host_count = sum(internal_list_hosts_count)
+ ports_per_user: int = int(
+ config['pool']['external'][external_pool]['per_user_limit']['port']
+ )
+ users_per_extip = ports_per_range_count // ports_per_user
+ max_users = users_per_extip * external_host_count
+
+ if internal_host_count > max_users:
+ raise ConfigError(
+ f'Rule "{rule}" does not have enough ports available for the '
+ f'specified parameters'
+ )
+
def generate(config):
if not config:
diff --git a/src/conf_mode/protocols_bfd.py b/src/conf_mode/protocols_bfd.py
index 1c01a9013..1361bb1a9 100755
--- a/src/conf_mode/protocols_bfd.py
+++ b/src/conf_mode/protocols_bfd.py
@@ -49,7 +49,7 @@ def verify(bfd):
for peer, peer_config in bfd['peer'].items():
# IPv6 link local peers require an explicit local address/interface
if is_ipv6_link_local(peer):
- if 'source' not in peer_config or len(peer_config['source'] < 2):
+ if 'source' not in peer_config or len(peer_config['source']) < 2:
raise ConfigError('BFD IPv6 link-local peers require explicit local address and interface setting')
# IPv6 peers require an explicit local address
diff --git a/src/conf_mode/system_conntrack.py b/src/conf_mode/system_conntrack.py
index 031fe63b0..aa290788c 100755
--- a/src/conf_mode/system_conntrack.py
+++ b/src/conf_mode/system_conntrack.py
@@ -18,6 +18,7 @@ import os
from sys import exit
+from vyos.base import Warning
from vyos.config import Config
from vyos.configdep import set_dependents, call_dependents
from vyos.utils.dict import dict_search
@@ -165,6 +166,8 @@ def verify(conntrack):
if not group_obj:
Warning(f'{error_group} "{group_name}" has no members!')
+ Warning(f'It is prefered to define {inet} conntrack ignore rules in <firewall {inet} prerouting raw> section')
+
if dict_search_args(conntrack, 'timeout', 'custom', inet, 'rule') != None:
for rule, rule_config in conntrack['timeout']['custom'][inet]['rule'].items():
if 'protocol' not in rule_config:
diff --git a/src/helpers/run-config-activation.py b/src/helpers/run-config-activation.py
new file mode 100755
index 000000000..58293702a
--- /dev/null
+++ b/src/helpers/run-config-activation.py
@@ -0,0 +1,83 @@
+#!/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 re
+import logging
+from pathlib import Path
+from argparse import ArgumentParser
+
+from vyos.compose_config import ComposeConfig
+from vyos.compose_config import ComposeConfigError
+from vyos.defaults import directories
+
+parser = ArgumentParser()
+parser.add_argument('config_file', type=str,
+ help="configuration file to modify with system-specific settings")
+parser.add_argument('--test-script', type=str,
+ help="test effect of named script")
+
+args = parser.parse_args()
+
+checkpoint_file = '/run/vyos-activate-checkpoint'
+log_file = Path(directories['config']).joinpath('vyos-activate.log')
+
+logger = logging.getLogger(__name__)
+fh = logging.FileHandler(log_file)
+formatter = logging.Formatter('%(message)s')
+fh.setFormatter(formatter)
+logger.addHandler(fh)
+
+if 'vyos-activate-debug' in Path('/proc/cmdline').read_text():
+ print(f'\nactivate-debug enabled: file {checkpoint_file}_* on error')
+ debug = checkpoint_file
+ logger.setLevel(logging.DEBUG)
+else:
+ debug = None
+ logger.setLevel(logging.INFO)
+
+def sort_key(s: Path):
+ s = s.stem
+ pre, rem = re.match(r'(\d*)(?:-)?(.+)', s).groups()
+ return int(pre or 0), rem
+
+def file_ext(file_name: str) -> str:
+ """Return an identifier from file name for checkpoint file extension.
+ """
+ return Path(file_name).stem
+
+script_dir = Path(directories['activate'])
+
+if args.test_script:
+ script_list = [script_dir.joinpath(args.test_script)]
+else:
+ script_list = sorted(script_dir.glob('*.py'), key=sort_key)
+
+config_file = args.config_file
+config_str = Path(config_file).read_text()
+
+compose = ComposeConfig(config_str, checkpoint_file=debug)
+
+for file in script_list:
+ file = file.as_posix()
+ logger.info(f'calling {file}')
+ try:
+ compose.apply_file(file, func_name='activate')
+ except ComposeConfigError as e:
+ if debug:
+ compose.write(f'{compose.checkpoint_file}_{file_ext(file)}')
+ logger.error(f'config-activation error in {file}: {e}')
+
+compose.write(config_file, with_version=True)
diff --git a/src/init/vyos-router b/src/init/vyos-router
index 15e37df07..59004fdc1 100755
--- a/src/init/vyos-router
+++ b/src/init/vyos-router
@@ -22,6 +22,7 @@ declare progname=${0##*/}
declare action=$1; shift
declare -x BOOTFILE=$vyatta_sysconfdir/config/config.boot
+declare -x DEFAULT_BOOTFILE=$vyatta_sysconfdir/config.boot.default
# If vyos-config= boot option is present, use that file instead
for x in $(cat /proc/cmdline); do
@@ -129,9 +130,16 @@ unmount_encrypted_config() {
# if necessary, provide initial config
init_bootfile () {
+ # define and version default boot config if not present
+ if [ ! -r $DEFAULT_BOOTFILE ]; then
+ if [ -f $vyos_data_dir/config.boot.default ]; then
+ cp $vyos_data_dir/config.boot.default $DEFAULT_BOOTFILE
+ $vyos_libexec_dir/system-versions-foot.py >> $DEFAULT_BOOTFILE
+ fi
+ fi
if [ ! -r $BOOTFILE ] ; then
- if [ -f $vyatta_sysconfdir/config.boot.default ]; then
- cp $vyatta_sysconfdir/config.boot.default $BOOTFILE
+ if [ -f $DEFAULT_BOOTFILE ]; then
+ cp $DEFAULT_BOOTFILE $BOOTFILE
else
$vyos_libexec_dir/system-versions-foot.py > $BOOTFILE
fi
@@ -149,6 +157,15 @@ migrate_bootfile ()
fi
}
+# configure system-specific settings
+system_config ()
+{
+ if [ -x $vyos_libexec_dir/run-config-activation.py ]; then
+ log_progress_msg system
+ sg ${GROUP} -c "$vyos_libexec_dir/run-config-activation.py $BOOTFILE"
+ fi
+}
+
# load the initial config
load_bootfile ()
{
@@ -493,6 +510,8 @@ start ()
update_interface_config
+ disabled system_config || system_config
+
for s in ${subinit[@]} ; do
if ! disabled $s; then
log_progress_msg $s
diff --git a/src/migration-scripts/firewall/15-to-16 b/src/migration-scripts/firewall/15-to-16
new file mode 100755
index 000000000..7c8d38fe6
--- /dev/null
+++ b/src/migration-scripts/firewall/15-to-16
@@ -0,0 +1,55 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2022-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/>.
+
+# T6394: Migrate conntrack timeout options to firewall global-options
+ # from: set system conntrack timeout ..
+ # to: set firewall global-options timeout ...
+
+from sys import argv
+from sys import exit
+
+from vyos.configtree import ConfigTree
+
+if len(argv) < 2:
+ print("Must specify file name!")
+ exit(1)
+
+file_name = argv[1]
+
+with open(file_name, 'r') as f:
+ config_file = f.read()
+
+firewall_base = ['firewall', 'global-options']
+conntrack_base = ['system', 'conntrack', 'timeout']
+config = ConfigTree(config_file)
+
+if not config.exists(conntrack_base):
+ # Nothing to do
+ exit(0)
+
+for protocol in ['icmp', 'tcp', 'udp', 'other']:
+ if config.exists(conntrack_base + [protocol]):
+ if not config.exists(firewall_base):
+ config.set(firewall_base + ['timeout'])
+ config.copy(conntrack_base + [protocol], firewall_base + ['timeout', protocol])
+ config.delete(conntrack_base + [protocol])
+
+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) \ No newline at end of file