diff options
30 files changed, 394 insertions, 416 deletions
diff --git a/data/templates/openvpn/server.conf.j2 b/data/templates/openvpn/server.conf.j2 index f76fbbe79..d7d4a5861 100644 --- a/data/templates/openvpn/server.conf.j2 +++ b/data/templates/openvpn/server.conf.j2 @@ -79,7 +79,7 @@ server {{ subnet | address_from_cidr }} {{ subnet | netmask_from_cidr }} nopool {% if server.push_route is vyos_defined %} {% for route, route_config in server.push_route.items() %} {% if route | is_ipv4 %} -push "route {{ route | address_from_cidr }} {{ route | netmask_from_cidr }} {{ subnet | first_host_address ~ ' ' ~ route_config.metric if route_config.metric is vyos_defined }}" +push "route {{ route | address_from_cidr }} {{ route | netmask_from_cidr }} {{ 'vpn_gateway' ~ ' ' ~ route_config.metric if route_config.metric is vyos_defined }}" {% elif route | is_ipv6 %} push "route-ipv6 {{ route }}" {% endif %} diff --git a/debian/control b/debian/control index ee45a5fe3..f31c5a510 100644 --- a/debian/control +++ b/debian/control @@ -91,7 +91,6 @@ Depends: libqmi-utils, libstrongswan-extra-plugins (>=5.9), libstrongswan-standard-plugins (>=5.9), - libvppinfra [amd64], libvyosconfig0, linux-cpupower, lldpd, @@ -145,7 +144,6 @@ Depends: python3-tabulate, python3-vici (>= 5.7.2), python3-voluptuous, - python3-vpp-api [amd64], python3-xmltodict, python3-zmq, qrencode, @@ -180,9 +178,6 @@ Depends: uidmap, usb-modeswitch, usbutils, - vpp [amd64], - vpp-plugin-core [amd64], - vpp-plugin-dpdk [amd64], vyatta-bash, vyatta-cfg, vyos-http-api-tools, diff --git a/debian/vyos-1x.preinst b/debian/vyos-1x.preinst index 2604f5ff4..12866cd55 100644 --- a/debian/vyos-1x.preinst +++ b/debian/vyos-1x.preinst @@ -7,7 +7,6 @@ dpkg-divert --package vyos-1x --add --no-rename /usr/share/pam-configs/tacplus dpkg-divert --package vyos-1x --add --no-rename /etc/rsyslog.conf dpkg-divert --package vyos-1x --add --no-rename /etc/skel/.bashrc dpkg-divert --package vyos-1x --add --no-rename /etc/skel/.profile -dpkg-divert --package vyos-1x --add --no-rename /etc/sysctl.d/80-vpp.conf dpkg-divert --package vyos-1x --add --no-rename /etc/netplug/netplugd.conf dpkg-divert --package vyos-1x --add --no-rename /etc/netplug/netplug dpkg-divert --package vyos-1x --add --no-rename /etc/rsyslog.d/45-frr.conf diff --git a/interface-definitions/dns-forwarding.xml.in b/interface-definitions/dns-forwarding.xml.in index 86dc47a47..c00051c47 100644 --- a/interface-definitions/dns-forwarding.xml.in +++ b/interface-definitions/dns-forwarding.xml.in @@ -654,25 +654,8 @@ <defaultValue>1500</defaultValue> </leafNode> #include <include/name-server-ipv4-ipv6-port.xml.i> + #include <include/source-address-ipv4-ipv6-multi.xml.i> <leafNode name="source-address"> - <properties> - <help>Local addresses from which to send DNS queries</help> - <completionHelp> - <script>${vyos_completion_dir}/list_local_ips.sh --both</script> - </completionHelp> - <valueHelp> - <format>ipv4</format> - <description>IPv4 address from which to send traffic</description> - </valueHelp> - <valueHelp> - <format>ipv6</format> - <description>IPv6 address from which to send traffic</description> - </valueHelp> - <multi/> - <constraint> - <validator name="ip-address"/> - </constraint> - </properties> <defaultValue>0.0.0.0 ::</defaultValue> </leafNode> <leafNode name="system"> diff --git a/interface-definitions/include/firewall/common-rule-inet.xml.i b/interface-definitions/include/firewall/common-rule-inet.xml.i index 88c055f52..52721ecc4 100644 --- a/interface-definitions/include/firewall/common-rule-inet.xml.i +++ b/interface-definitions/include/firewall/common-rule-inet.xml.i @@ -3,6 +3,7 @@ #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> @@ -81,44 +82,7 @@ </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> -<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.xml.i> #include <include/firewall/rule-log-options.xml.i> <node name="connection-status"> <properties> @@ -220,89 +184,7 @@ </leafNode> </children> </node> -<node name="state"> - <properties> - <help>Session state</help> - </properties> - <children> - <leafNode name="established"> - <properties> - <help>Established state</help> - <completionHelp> - <list>enable disable</list> - </completionHelp> - <valueHelp> - <format>enable</format> - <description>Enable</description> - </valueHelp> - <valueHelp> - <format>disable</format> - <description>Disable</description> - </valueHelp> - <constraint> - <regex>(enable|disable)</regex> - </constraint> - </properties> - </leafNode> - <leafNode name="invalid"> - <properties> - <help>Invalid state</help> - <completionHelp> - <list>enable disable</list> - </completionHelp> - <valueHelp> - <format>enable</format> - <description>Enable</description> - </valueHelp> - <valueHelp> - <format>disable</format> - <description>Disable</description> - </valueHelp> - <constraint> - <regex>(enable|disable)</regex> - </constraint> - </properties> - </leafNode> - <leafNode name="new"> - <properties> - <help>New state</help> - <completionHelp> - <list>enable disable</list> - </completionHelp> - <valueHelp> - <format>enable</format> - <description>Enable</description> - </valueHelp> - <valueHelp> - <format>disable</format> - <description>Disable</description> - </valueHelp> - <constraint> - <regex>(enable|disable)</regex> - </constraint> - </properties> - </leafNode> - <leafNode name="related"> - <properties> - <help>Related state</help> - <completionHelp> - <list>enable disable</list> - </completionHelp> - <valueHelp> - <format>enable</format> - <description>Enable</description> - </valueHelp> - <valueHelp> - <format>disable</format> - <description>Disable</description> - </valueHelp> - <constraint> - <regex>(enable|disable)</regex> - </constraint> - </properties> - </leafNode> - </children> -</node> +#include <include/firewall/state.xml.i> #include <include/firewall/tcp-flags.xml.i> <node name="time"> <properties> diff --git a/interface-definitions/include/firewall/firewall-mark.xml.i b/interface-definitions/include/firewall/firewall-mark.xml.i new file mode 100644 index 000000000..a4cee12d8 --- /dev/null +++ b/interface-definitions/include/firewall/firewall-mark.xml.i @@ -0,0 +1,26 @@ +<!-- include start from firewall/firewall-mark.xml.i --> +<leafNode name="mark"> + <properties> + <help>Firewall mark</help> + <valueHelp> + <format>u32:0-2147483647</format> + <description>Firewall mark to match</description> + </valueHelp> + <valueHelp> + <format>!u32:0-2147483647</format> + <description>Inverted Firewall mark to match</description> + </valueHelp> + <valueHelp> + <format><start-end></format> + <description>Firewall mark range to match</description> + </valueHelp> + <valueHelp> + <format>!<start-end></format> + <description>Firewall mark inverted range to match</description> + </valueHelp> + <constraint> + <validator name="numeric-exclude" argument="--allow-range --range 0-2147483647"/> + </constraint> + </properties> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/firewall/log.xml.i b/interface-definitions/include/firewall/log.xml.i index 46d20c1df..8f3fae1be 100644 --- a/interface-definitions/include/firewall/log.xml.i +++ b/interface-definitions/include/firewall/log.xml.i @@ -1,15 +1,7 @@ <!-- include start from firewall/log.xml.i --> -<node name="log"> +<leafNode name="log"> <properties> - <help>Option to log packets</help> + <help>Enable log</help> + <valueless/> </properties> - <children> - <leafNode name="enable"> - <properties> - <help>Enable logging</help> - <valueless/> - </properties> - </leafNode> - </children> -</node> -<!-- include end --> +</leafNode>
\ No newline at end of file diff --git a/interface-definitions/include/firewall/state.xml.i b/interface-definitions/include/firewall/state.xml.i new file mode 100644 index 000000000..47ce3c91d --- /dev/null +++ b/interface-definitions/include/firewall/state.xml.i @@ -0,0 +1,30 @@ +<!-- include start from firewall/state.xml.i --> +<leafNode name="state"> + <properties> + <help>Session state</help> + <completionHelp> + <list>established invalid new related</list> + </completionHelp> + <valueHelp> + <format>established</format> + <description>Established state</description> + </valueHelp> + <valueHelp> + <format>invalid</format> + <description>Invalid state</description> + </valueHelp> + <valueHelp> + <format>new</format> + <description>New state</description> + </valueHelp> + <valueHelp> + <format>related</format> + <description>Related state</description> + </valueHelp> + <constraint> + <regex>(established|invalid|new|related)</regex> + </constraint> + <multi/> + </properties> +</leafNode> +<!-- include end -->
\ No newline at end of file diff --git a/interface-definitions/include/nat-rule.xml.i b/interface-definitions/include/nat-rule.xml.i index 6234e6195..deb13529d 100644 --- a/interface-definitions/include/nat-rule.xml.i +++ b/interface-definitions/include/nat-rule.xml.i @@ -34,12 +34,7 @@ #include <include/firewall/nat-balance.xml.i> </children> </node> - <leafNode name="log"> - <properties> - <help>NAT rule logging</help> - <valueless/> - </properties> - </leafNode> + #include <include/firewall/log.xml.i> <leafNode name="packet-type"> <properties> <help>Packet type</help> diff --git a/interface-definitions/include/policy/route-common.xml.i b/interface-definitions/include/policy/route-common.xml.i index 216ec9bea..e68c18eef 100644 --- a/interface-definitions/include/policy/route-common.xml.i +++ b/interface-definitions/include/policy/route-common.xml.i @@ -1,6 +1,7 @@ <!-- include start from policy/route-common.xml.i -->
#include <include/policy/route-rule-action.xml.i>
#include <include/generic-description.xml.i>
+#include <include/firewall/firewall-mark.xml.i>
<leafNode name="disable">
<properties>
<help>Option to disable firewall rule</help>
@@ -76,25 +77,7 @@ </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.xml.i>
<leafNode name="protocol">
<properties>
<help>Protocol to match (protocol name, number, or "all")</help>
@@ -230,89 +213,7 @@ </leafNode>
</children>
</node>
-<node name="state">
- <properties>
- <help>Session state</help>
- </properties>
- <children>
- <leafNode name="established">
- <properties>
- <help>Established state</help>
- <completionHelp>
- <list>enable disable</list>
- </completionHelp>
- <valueHelp>
- <format>enable</format>
- <description>Enable</description>
- </valueHelp>
- <valueHelp>
- <format>disable</format>
- <description>Disable</description>
- </valueHelp>
- <constraint>
- <regex>(enable|disable)</regex>
- </constraint>
- </properties>
- </leafNode>
- <leafNode name="invalid">
- <properties>
- <help>Invalid state</help>
- <completionHelp>
- <list>enable disable</list>
- </completionHelp>
- <valueHelp>
- <format>enable</format>
- <description>Enable</description>
- </valueHelp>
- <valueHelp>
- <format>disable</format>
- <description>Disable</description>
- </valueHelp>
- <constraint>
- <regex>(enable|disable)</regex>
- </constraint>
- </properties>
- </leafNode>
- <leafNode name="new">
- <properties>
- <help>New state</help>
- <completionHelp>
- <list>enable disable</list>
- </completionHelp>
- <valueHelp>
- <format>enable</format>
- <description>Enable</description>
- </valueHelp>
- <valueHelp>
- <format>disable</format>
- <description>Disable</description>
- </valueHelp>
- <constraint>
- <regex>(enable|disable)</regex>
- </constraint>
- </properties>
- </leafNode>
- <leafNode name="related">
- <properties>
- <help>Related state</help>
- <completionHelp>
- <list>enable disable</list>
- </completionHelp>
- <valueHelp>
- <format>enable</format>
- <description>Enable</description>
- </valueHelp>
- <valueHelp>
- <format>disable</format>
- <description>Disable</description>
- </valueHelp>
- <constraint>
- <regex>(enable|disable)</regex>
- </constraint>
- </properties>
- </leafNode>
- </children>
-</node>
+#include <include/firewall/state.xml.i>
#include <include/firewall/tcp-flags.xml.i>
<node name="time">
<properties>
diff --git a/interface-definitions/include/radius-server-ipv4-ipv6.xml.i b/interface-definitions/include/radius-server-ipv4-ipv6.xml.i index efd418bb2..ac0950ae8 100644 --- a/interface-definitions/include/radius-server-ipv4-ipv6.xml.i +++ b/interface-definitions/include/radius-server-ipv4-ipv6.xml.i @@ -25,27 +25,7 @@ #include <include/radius-server-auth-port.xml.i> </children> </tagNode> - <leafNode name="source-address"> - <properties> - <help>Source IP address used to initiate connection</help> - <completionHelp> - <script>${vyos_completion_dir}/list_local_ips.sh --both</script> - </completionHelp> - <valueHelp> - <format>ipv4</format> - <description>IPv4 source address</description> - </valueHelp> - <valueHelp> - <format>ipv6</format> - <description>IPv6 source address</description> - </valueHelp> - <constraint> - <validator name="ipv4-address"/> - <validator name="ipv6-address"/> - </constraint> - <multi/> - </properties> - </leafNode> + #include <include/source-address-ipv4-ipv6-multi.xml.i> </children> </node> <!-- include end --> diff --git a/interface-definitions/include/source-address-ipv4-ipv6-multi.xml.i b/interface-definitions/include/source-address-ipv4-ipv6-multi.xml.i new file mode 100644 index 000000000..d56ca5be6 --- /dev/null +++ b/interface-definitions/include/source-address-ipv4-ipv6-multi.xml.i @@ -0,0 +1,22 @@ +<!-- include start from source-address-ipv4-ipv6-multi.xml.i --> +<leafNode name="source-address"> + <properties> + <help>Source IP address used to initiate connection</help> + <completionHelp> + <script>${vyos_completion_dir}/list_local_ips.sh --both</script> + </completionHelp> + <valueHelp> + <format>ipv4</format> + <description>IPv4 source address</description> + </valueHelp> + <valueHelp> + <format>ipv6</format> + <description>IPv6 source address</description> + </valueHelp> + <constraint> + <validator name="ip-address"/> + </constraint> + <multi/> + </properties> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/version/firewall-version.xml.i b/interface-definitions/include/version/firewall-version.xml.i index 39f0cdcba..299eebb00 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='12'></syntaxVersion> +<syntaxVersion component='firewall' version='13'></syntaxVersion> <!-- include end --> diff --git a/interface-definitions/include/version/policy-version.xml.i b/interface-definitions/include/version/policy-version.xml.i index 2c96e0f15..4fbe757f5 100644 --- a/interface-definitions/include/version/policy-version.xml.i +++ b/interface-definitions/include/version/policy-version.xml.i @@ -1,3 +1,3 @@ <!-- include start from include/version/policy-version.xml.i --> -<syntaxVersion component='policy' version='6'></syntaxVersion> +<syntaxVersion component='policy' version='7'></syntaxVersion> <!-- include end --> diff --git a/interface-definitions/nat66.xml.in b/interface-definitions/nat66.xml.in index a657535ba..2fd95e03a 100644 --- a/interface-definitions/nat66.xml.in +++ b/interface-definitions/nat66.xml.in @@ -32,12 +32,7 @@ </properties> </leafNode> #include <include/nat-exclude.xml.i> - <leafNode name="log"> - <properties> - <help>NAT66 rule logging</help> - <valueless/> - </properties> - </leafNode> + #include <include/firewall/log.xml.i> #include <include/firewall/outbound-interface-no-group.xml.i> #include <include/nat/protocol.xml.i> <node name="destination"> diff --git a/interface-definitions/system-login.xml.in b/interface-definitions/system-login.xml.in index 71db8b1d6..a0eda9045 100644 --- a/interface-definitions/system-login.xml.in +++ b/interface-definitions/system-login.xml.in @@ -244,21 +244,7 @@ </leafNode> </children> </tagNode> - <leafNode name="source-address"> - <properties> - <help>Source IP used to communicate with TACACS+ server</help> - <completionHelp> - <script>${vyos_completion_dir}/list_local_ips.sh --ipv4</script> - </completionHelp> - <valueHelp> - <format>ipv4</format> - <description>IPv4 source address</description> - </valueHelp> - <constraint> - <validator name="ipv4-address"/> - </constraint> - </properties> - </leafNode> + #include <include/source-address-ipv4.xml.i> #include <include/radius-timeout.xml.i> #include <include/interface/vrf.xml.i> </children> diff --git a/op-mode-definitions/include/bgp/show-bgp-common.xml.i b/op-mode-definitions/include/bgp/show-bgp-common.xml.i index de794a879..d888bc3b0 100644 --- a/op-mode-definitions/include/bgp/show-bgp-common.xml.i +++ b/op-mode-definitions/include/bgp/show-bgp-common.xml.i @@ -107,6 +107,12 @@ #include <include/vni-tagnode.xml.i> </children> </node> + <leafNode name="es-vrf"> + <properties> + <help>Ethernet Segment per VRF</help> + </properties> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> + </leafNode> <leafNode name="import-rt"> <properties> <help>Show import route target</help> @@ -136,11 +142,17 @@ </leafNode> </children> </tagNode> + <leafNode name="next-hops"> + <properties> + <help>EVPN Nexthops</help> + </properties> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> + </leafNode> <tagNode name="rd"> <properties> - <help>Show detailed BGP neighbor information</help> + <help>Display information for a route distinguisher</help> <completionHelp> - <list>ASN:NN IPADDRESS:NN</list> + <list>ASN:NN IPADDRESS:NN all</list> </completionHelp> </properties> <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> diff --git a/op-mode-definitions/monitor-log.xml.in b/op-mode-definitions/monitor-log.xml.in index ee066b39b..44628a112 100644 --- a/op-mode-definitions/monitor-log.xml.in +++ b/op-mode-definitions/monitor-log.xml.in @@ -341,12 +341,6 @@ </tagNode> </children> </node> - <leafNode name="vpp"> - <properties> - <help>Monitor last lines of Vector Packet Processor log</help> - </properties> - <command>journalctl --no-hostname --boot --follow --unit vpp.service</command> - </leafNode> <leafNode name="vrrp"> <properties> <help>Monitor last lines of Virtual Router Redundancy Protocol log</help> diff --git a/op-mode-definitions/show-log.xml.in b/op-mode-definitions/show-log.xml.in index 08d5ae11a..ee9f1cc3c 100644 --- a/op-mode-definitions/show-log.xml.in +++ b/op-mode-definitions/show-log.xml.in @@ -480,12 +480,6 @@ </tagNode> </children> </node> - <leafNode name="vpp"> - <properties> - <help>Show log for Vector Packet Processor (VPP)</help> - </properties> - <command>journalctl --no-hostname --boot --unit vpp.service</command> - </leafNode> <leafNode name="vrrp"> <properties> <help>Show log for Virtual Router Redundancy Protocol (VRRP)</help> diff --git a/python/vyos/firewall.py b/python/vyos/firewall.py index 2ad93a85d..06b58d4ed 100644 --- a/python/vyos/firewall.py +++ b/python/vyos/firewall.py @@ -87,7 +87,6 @@ def nft_action(vyos_action): def parse_rule(rule_conf, hook, fw_name, rule_id, ip_name): output = [] - #def_suffix = '6' if ip_name == 'ip6' else '' if ip_name == 'ip6': def_suffix = '6' family = 'ipv6' @@ -96,7 +95,7 @@ def parse_rule(rule_conf, hook, fw_name, rule_id, ip_name): family = 'bri' if ip_name == 'bri' else 'ipv4' if 'state' in rule_conf and rule_conf['state']: - states = ",".join([s for s, v in rule_conf['state'].items() if v == 'enable']) + states = ",".join([s for s in rule_conf['state']]) if states: output.append(f'ct state {{{states}}}') @@ -262,29 +261,6 @@ def parse_rule(rule_conf, hook, fw_name, rule_id, ip_name): output.append(f'{proto} {prefix}port {operator} @P_{group_name}') - if 'log' in rule_conf and rule_conf['log'] == 'enable': - action = rule_conf['action'] if 'action' in rule_conf else 'accept' - #output.append(f'log prefix "[{fw_name[:19]}-{rule_id}-{action[:1].upper()}]"') - output.append(f'log prefix "[{family}-{hook}-{fw_name}-{rule_id}-{action[:1].upper()}]"') - - if 'log_options' in rule_conf: - - if 'level' in rule_conf['log_options']: - log_level = rule_conf['log_options']['level'] - output.append(f'log level {log_level}') - - if 'group' in rule_conf['log_options']: - log_group = rule_conf['log_options']['group'] - output.append(f'log group {log_group}') - - if 'queue_threshold' in rule_conf['log_options']: - queue_threshold = rule_conf['log_options']['queue_threshold'] - output.append(f'queue-threshold {queue_threshold}') - - if 'snapshot_length' in rule_conf['log_options']: - log_snaplen = rule_conf['log_options']['snapshot_length'] - output.append(f'snaplen {log_snaplen}') - if 'hop_limit' in rule_conf: operators = {'eq': '==', 'gt': '>', 'lt': '<'} for op, operator in operators.items(): @@ -400,6 +376,43 @@ def parse_rule(rule_conf, hook, fw_name, rule_id, ip_name): conn_mark_str = ','.join(rule_conf['connection_mark']) output.append(f'ct mark {{{conn_mark_str}}}') + if 'mark' in rule_conf: + mark = rule_conf['mark'] + operator = '' + if mark[0] == '!': + operator = '!=' + mark = mark[1:] + output.append(f'meta mark {operator} {{{mark}}}') + + if 'vlan' in rule_conf: + if 'id' in rule_conf['vlan']: + output.append(f'vlan id {rule_conf["vlan"]["id"]}') + if 'priority' in rule_conf['vlan']: + output.append(f'vlan pcp {rule_conf["vlan"]["priority"]}') + + if 'log' in rule_conf: + action = rule_conf['action'] if 'action' in rule_conf else 'accept' + #output.append(f'log prefix "[{fw_name[:19]}-{rule_id}-{action[:1].upper()}]"') + output.append(f'log prefix "[{family}-{hook}-{fw_name}-{rule_id}-{action[:1].upper()}]"') + ##{family}-{hook}-{fw_name}-{rule_id} + if 'log_options' in rule_conf: + + if 'level' in rule_conf['log_options']: + log_level = rule_conf['log_options']['level'] + output.append(f'log level {log_level}') + + if 'group' in rule_conf['log_options']: + log_group = rule_conf['log_options']['group'] + output.append(f'log group {log_group}') + + if 'queue_threshold' in rule_conf['log_options']: + queue_threshold = rule_conf['log_options']['queue_threshold'] + output.append(f'queue-threshold {queue_threshold}') + + if 'snapshot_length' in rule_conf['log_options']: + log_snaplen = rule_conf['log_options']['snapshot_length'] + output.append(f'snaplen {log_snaplen}') + output.append('counter') if 'set' in rule_conf: diff --git a/python/vyos/progressbar.py b/python/vyos/progressbar.py index 1793c445b..7bc9d9856 100644 --- a/python/vyos/progressbar.py +++ b/python/vyos/progressbar.py @@ -19,26 +19,35 @@ import signal import subprocess import sys +from vyos.utils.io import is_dumb_terminal from vyos.utils.io import print_error + class Progressbar: def __init__(self, step=None): self.total = 0.0 self.step = step + # Silently ignore all calls if terminal capabilities are lacking. + # This will also prevent the output from littering Ansible logs, + # as `ansible.netcommon.network_cli' coaxes the terminal into believing + # it is interactive. + self._dumb = is_dumb_terminal() def __enter__(self): - # Recalculate terminal width with every window resize. - signal.signal(signal.SIGWINCH, lambda signum, frame: self._update_cols()) - # Disable line wrapping to prevent the staircase effect. - subprocess.run(['tput', 'rmam'], check=False) - self._update_cols() - # Print an empty progressbar with entry. - self.progress(0, 1) + if not self._dumb: + # Recalculate terminal width with every window resize. + signal.signal(signal.SIGWINCH, lambda signum, frame: self._update_cols()) + # Disable line wrapping to prevent the staircase effect. + subprocess.run(['tput', 'rmam'], check=False) + self._update_cols() + # Print an empty progressbar with entry. + self.progress(0, 1) return self def __exit__(self, exc_type, kexc_val, exc_tb): - # Revert to the default SIGWINCH handler (ie nothing). - signal.signal(signal.SIGWINCH, signal.SIG_DFL) - # Reenable line wrapping. - subprocess.run(['tput', 'smam'], check=False) + if not self._dumb: + # Revert to the default SIGWINCH handler (ie nothing). + signal.signal(signal.SIGWINCH, signal.SIG_DFL) + # Reenable line wrapping. + subprocess.run(['tput', 'smam'], check=False) def _update_cols(self): # `os.get_terminal_size()' is fast enough for our purposes. self.col = max(os.get_terminal_size().columns - 15, 20) @@ -60,7 +69,7 @@ class Progressbar: Stateless progressbar taking no input at init and current progress with final size at callback (for SSH) """ - if done <= total: + if done <= total and not self._dumb: length = math.ceil(self.col * done / total) percentage = str(math.ceil(100 * done / total)).rjust(3) # Carriage return at the end will make sure the line will get overwritten. diff --git a/python/vyos/remote.py b/python/vyos/remote.py index 1ca8a9530..4be477d24 100644 --- a/python/vyos/remote.py +++ b/python/vyos/remote.py @@ -34,6 +34,7 @@ from requests.packages.urllib3 import PoolManager from vyos.progressbar import Progressbar from vyos.utils.io import ask_yes_no +from vyos.utils.io import is_interactive from vyos.utils.io import print_error from vyos.utils.misc import begin from vyos.utils.process import cmd @@ -49,7 +50,7 @@ class InteractivePolicy(MissingHostKeyPolicy): def missing_host_key(self, client, hostname, key): print_error(f"Host '{hostname}' not found in known hosts.") print_error('Fingerprint: ' + key.get_fingerprint().hex()) - if sys.stdout.isatty() and ask_yes_no('Do you wish to continue?'): + if is_interactive() and ask_yes_no('Do you wish to continue?'): if client._host_keys_filename\ and ask_yes_no('Do you wish to permanently add this host/key pair to known hosts?'): client._host_keys.add(hostname, key.get_name(), key) @@ -250,7 +251,6 @@ class HttpC: allow_redirects=True, timeout=self.timeout) as r: # Abort early if the destination is inaccessible. - print('pre-3') r.raise_for_status() # If the request got redirected, keep the last URL we ended up with. final_urlstring = r.url @@ -323,17 +323,25 @@ def urlc(urlstring, *args, **kwargs): except KeyError: raise ValueError(f'Unsupported URL scheme: "{url.scheme}"') -def download(local_path, urlstring, *args, **kwargs): +def download(local_path, urlstring, progressbar=False, check_space=False, + source_host='', source_port=0, timeout=10.0): try: - urlc(urlstring, *args, **kwargs).download(local_path) + progressbar = progressbar and is_interactive() + urlc(urlstring, progressbar, check_space, source_host, source_port, timeout).download(local_path) except Exception as err: print_error(f'Unable to download "{urlstring}": {err}') + except KeyboardInterrupt: + print_error('\nDownload aborted by user.') -def upload(local_path, urlstring, *args, **kwargs): +def upload(local_path, urlstring, progressbar=False, + source_host='', source_port=0, timeout=10.0): try: - urlc(urlstring, *args, **kwargs).upload(local_path) + progressbar = progressbar and is_interactive() + urlc(urlstring, progressbar, source_host, source_port, timeout).upload(local_path) except Exception as err: print_error(f'Unable to upload "{urlstring}": {err}') + except KeyboardInterrupt: + print_error('\nUpload aborted by user.') def get_remote_config(urlstring, source_host='', source_port=0): """ @@ -346,26 +354,3 @@ def get_remote_config(urlstring, source_host='', source_port=0): return f.read() finally: os.remove(temp) - -def friendly_download(local_path, urlstring, source_host='', source_port=0): - """ - Download with a progress bar, reassuring messages and free space checks. - """ - try: - print_error('Downloading...') - download(local_path, urlstring, True, True, source_host, source_port) - except KeyboardInterrupt: - print_error('\nDownload aborted by user.') - sys.exit(1) - except: - import traceback - print_error(f'Failed to download {urlstring}.') - # There are a myriad different reasons a download could fail. - # SSH errors, FTP errors, I/O errors, HTTP errors (403, 404...) - # We omit the scary stack trace but print the error nevertheless. - exc_type, exc_value, exc_traceback = sys.exc_info() - traceback.print_exception(exc_type, exc_value, None, 0, None, False) - sys.exit(1) - else: - print_error('Download complete.') - sys.exit(0) diff --git a/python/vyos/utils/io.py b/python/vyos/utils/io.py index 5fffa62f8..8790cbaac 100644 --- a/python/vyos/utils/io.py +++ b/python/vyos/utils/io.py @@ -62,3 +62,13 @@ def ask_yes_no(question, default=False) -> bool: stdout.write("Please respond with yes/y or no/n\n") except EOFError: stdout.write("\nPlease respond with yes/y or no/n\n") + +def is_interactive(): + """Try to determine if the routine was called from an interactive shell.""" + import os, sys + return os.getenv('TERM', default=False) and sys.stderr.isatty() and sys.stdout.isatty() + +def is_dumb_terminal(): + """Check if the current TTY is dumb, so that we can disable advanced terminal features.""" + import os + return os.getenv('TERM') in ['vt100', 'dumb'] diff --git a/smoketest/scripts/cli/test_firewall.py b/smoketest/scripts/cli/test_firewall.py index 5f842727d..c51592ec2 100755 --- a/smoketest/scripts/cli/test_firewall.py +++ b/smoketest/scripts/cli/test_firewall.py @@ -213,13 +213,13 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase): self.cli_set(['firewall', 'ipv4', 'name', name, 'rule', '1', 'action', 'accept']) self.cli_set(['firewall', 'ipv4', 'name', name, 'rule', '1', 'source', 'address', '172.16.20.10']) self.cli_set(['firewall', 'ipv4', 'name', name, 'rule', '1', 'destination', 'address', '172.16.10.10']) - self.cli_set(['firewall', 'ipv4', 'name', name, 'rule', '1', 'log', 'enable']) + self.cli_set(['firewall', 'ipv4', 'name', name, 'rule', '1', 'log']) self.cli_set(['firewall', 'ipv4', 'name', name, 'rule', '1', 'log-options', 'level', 'debug']) self.cli_set(['firewall', 'ipv4', 'name', name, 'rule', '1', 'ttl', 'eq', '15']) self.cli_set(['firewall', 'ipv4', 'name', name, 'rule', '2', 'action', 'reject']) self.cli_set(['firewall', 'ipv4', 'name', name, 'rule', '2', 'protocol', 'tcp']) self.cli_set(['firewall', 'ipv4', 'name', name, 'rule', '2', 'destination', 'port', '8888']) - self.cli_set(['firewall', 'ipv4', 'name', name, 'rule', '2', 'log', 'enable']) + self.cli_set(['firewall', 'ipv4', 'name', name, 'rule', '2', 'log']) self.cli_set(['firewall', 'ipv4', 'name', name, 'rule', '2', 'log-options', 'level', 'err']) self.cli_set(['firewall', 'ipv4', 'name', name, 'rule', '2', 'tcp', 'flags', 'syn']) self.cli_set(['firewall', 'ipv4', 'name', name, 'rule', '2', 'tcp', 'flags', 'not', 'ack']) @@ -231,7 +231,7 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase): self.cli_set(['firewall', 'ipv4', 'forward', 'filter', 'rule', '3', 'protocol', 'tcp']) self.cli_set(['firewall', 'ipv4', 'forward', 'filter', 'rule', '3', 'destination', 'port', '22']) self.cli_set(['firewall', 'ipv4', 'forward', 'filter', 'rule', '3', 'limit', 'rate', '5/minute']) - self.cli_set(['firewall', 'ipv4', 'forward', 'filter', 'rule', '3', 'log', 'disable']) + self.cli_set(['firewall', 'ipv4', 'forward', 'filter', 'rule', '3', 'log']) self.cli_set(['firewall', 'ipv4', 'forward', 'filter', 'rule', '4', 'action', 'drop']) self.cli_set(['firewall', 'ipv4', 'forward', 'filter', 'rule', '4', 'protocol', 'tcp']) self.cli_set(['firewall', 'ipv4', 'forward', 'filter', 'rule', '4', 'destination', 'port', '22']) @@ -299,7 +299,7 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase): self.cli_set(['firewall', 'ipv4', 'name', name, 'rule', '6', 'packet-length', '1024']) self.cli_set(['firewall', 'ipv4', 'name', name, 'rule', '6', 'dscp', '17']) self.cli_set(['firewall', 'ipv4', 'name', name, 'rule', '6', 'dscp', '52']) - self.cli_set(['firewall', 'ipv4', 'name', name, 'rule', '6', 'log', 'enable']) + self.cli_set(['firewall', 'ipv4', 'name', name, 'rule', '6', 'log']) self.cli_set(['firewall', 'ipv4', 'name', name, 'rule', '6', 'log-options', 'group', '66']) self.cli_set(['firewall', 'ipv4', 'name', name, 'rule', '6', 'log-options', 'snapshot-length', '6666']) self.cli_set(['firewall', 'ipv4', 'name', name, 'rule', '6', 'log-options', 'queue-threshold','32000']) @@ -312,10 +312,12 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase): self.cli_set(['firewall', 'ipv4', 'forward', 'filter', 'default-action', 'drop']) self.cli_set(['firewall', 'ipv4', 'forward', 'filter', 'rule', '1', 'source', 'address', '198.51.100.1']) + self.cli_set(['firewall', 'ipv4', 'forward', 'filter', 'rule', '1', 'mark', '1010']) self.cli_set(['firewall', 'ipv4', 'forward', 'filter', 'rule', '1', 'action', 'jump']) self.cli_set(['firewall', 'ipv4', 'forward', 'filter', 'rule', '1', 'jump-target', name]) self.cli_set(['firewall', 'ipv4', 'input', 'filter', 'rule', '2', 'protocol', 'tcp']) + self.cli_set(['firewall', 'ipv4', 'input', 'filter', 'rule', '2', 'mark', '!98765']) self.cli_set(['firewall', 'ipv4', 'input', 'filter', 'rule', '2', 'action', 'queue']) self.cli_set(['firewall', 'ipv4', 'input', 'filter', 'rule', '2', 'queue', '3']) self.cli_set(['firewall', 'ipv4', 'input', 'filter', 'rule', '3', 'protocol', 'udp']) @@ -329,11 +331,11 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase): nftables_search = [ ['chain VYOS_FORWARD_filter'], ['type filter hook forward priority filter; policy accept;'], - ['ip saddr 198.51.100.1', f'jump NAME_{name}'], + ['ip saddr 198.51.100.1', 'meta mark 0x000003f2', f'jump NAME_{name}'], ['FWD-filter default-action drop', 'drop'], ['chain VYOS_INPUT_filter'], ['type filter hook input priority filter; policy accept;'], - [f'meta l4proto tcp','queue to 3'], + ['meta mark != 0x000181cd', 'meta l4proto tcp','queue to 3'], ['meta l4proto udp','queue flags bypass,fanout to 0-15'], ['INP-filter default-action accept', 'accept'], [f'chain NAME_{name}'], @@ -386,7 +388,7 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase): self.cli_set(['firewall', 'ipv6', 'name', name, 'rule', '1', 'action', 'accept']) self.cli_set(['firewall', 'ipv6', 'name', name, 'rule', '1', 'source', 'address', '2002::1']) self.cli_set(['firewall', 'ipv6', 'name', name, 'rule', '1', 'destination', 'address', '2002::1:1']) - self.cli_set(['firewall', 'ipv6', 'name', name, 'rule', '1', 'log', 'enable']) + self.cli_set(['firewall', 'ipv6', 'name', name, 'rule', '1', 'log']) self.cli_set(['firewall', 'ipv6', 'name', name, 'rule', '1', 'log-options', 'level', 'crit']) self.cli_set(['firewall', 'ipv6', 'forward', 'filter', 'default-action', 'accept']) @@ -508,19 +510,19 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase): self.cli_set(['firewall', 'ipv4', 'name', name, 'default-action', 'drop']) self.cli_set(['firewall', 'ipv4', 'name', name, 'rule', '1', 'action', 'accept']) - self.cli_set(['firewall', 'ipv4', 'name', name, 'rule', '1', 'state', 'established', 'enable']) - self.cli_set(['firewall', 'ipv4', 'name', name, 'rule', '1', 'state', 'related', 'enable']) + self.cli_set(['firewall', 'ipv4', 'name', name, 'rule', '1', 'state', 'established']) + self.cli_set(['firewall', 'ipv4', 'name', name, 'rule', '1', 'state', 'related']) self.cli_set(['firewall', 'ipv4', 'name', name, 'rule', '2', 'action', 'reject']) - self.cli_set(['firewall', 'ipv4', 'name', name, 'rule', '2', 'state', 'invalid', 'enable']) + self.cli_set(['firewall', 'ipv4', 'name', name, 'rule', '2', 'state', 'invalid']) self.cli_set(['firewall', 'ipv4', 'name', name, 'rule', '3', 'action', 'accept']) - self.cli_set(['firewall', 'ipv4', 'name', name, 'rule', '3', 'state', 'new', 'enable']) + self.cli_set(['firewall', 'ipv4', 'name', name, 'rule', '3', 'state', 'new']) self.cli_set(['firewall', 'ipv4', 'name', name, 'rule', '3', 'connection-status', 'nat', 'destination']) self.cli_set(['firewall', 'ipv4', 'name', name, 'rule', '4', 'action', 'accept']) - self.cli_set(['firewall', 'ipv4', 'name', name, 'rule', '4', 'state', 'new', 'enable']) - self.cli_set(['firewall', 'ipv4', 'name', name, 'rule', '4', 'state', 'established', 'enable']) + self.cli_set(['firewall', 'ipv4', 'name', name, 'rule', '4', 'state', 'new']) + self.cli_set(['firewall', 'ipv4', 'name', name, 'rule', '4', 'state', 'established']) self.cli_set(['firewall', 'ipv4', 'name', name, 'rule', '4', 'connection-status', 'nat', 'source']) self.cli_set(['firewall', 'ipv4', 'name', name, 'rule', '5', 'action', 'accept']) - self.cli_set(['firewall', 'ipv4', 'name', name, 'rule', '5', 'state', 'related', 'enable']) + self.cli_set(['firewall', 'ipv4', 'name', name, 'rule', '5', 'state', 'related']) self.cli_set(['firewall', 'ipv4', 'name', name, 'rule', '5', 'conntrack-helper', 'ftp']) self.cli_set(['firewall', 'ipv4', 'name', name, 'rule', '5', 'conntrack-helper', 'pptp']) diff --git a/smoketest/scripts/cli/test_policy_route.py b/smoketest/scripts/cli/test_policy_route.py index 118b1d3a2..40fff03e6 100755 --- a/smoketest/scripts/cli/test_policy_route.py +++ b/smoketest/scripts/cli/test_policy_route.py @@ -191,25 +191,29 @@ class TestPolicyRoute(VyOSUnitTestSHIM.TestCase): def test_pbr_matching_criteria(self): self.cli_set(['policy', 'route', 'smoketest', 'rule', '1', 'protocol', 'udp']) self.cli_set(['policy', 'route', 'smoketest', 'rule', '1', 'action', 'drop']) + self.cli_set(['policy', 'route', 'smoketest', 'rule', '1', 'mark', '2020']) self.cli_set(['policy', 'route', 'smoketest', 'rule', '2', 'protocol', 'tcp']) self.cli_set(['policy', 'route', 'smoketest', 'rule', '2', 'tcp', 'flags', 'syn']) self.cli_set(['policy', 'route', 'smoketest', 'rule', '2', 'tcp', 'flags', 'not', 'ack']) + self.cli_set(['policy', 'route', 'smoketest', 'rule', '2', 'mark', '2-3000']) self.cli_set(['policy', 'route', 'smoketest', 'rule', '2', 'set', 'table', table_id]) self.cli_set(['policy', 'route', 'smoketest', 'rule', '3', 'source', 'address', '198.51.100.0/24']) self.cli_set(['policy', 'route', 'smoketest', 'rule', '3', 'protocol', 'tcp']) self.cli_set(['policy', 'route', 'smoketest', 'rule', '3', 'destination', 'port', '22']) - self.cli_set(['policy', 'route', 'smoketest', 'rule', '3', 'state', 'new', 'enable']) + self.cli_set(['policy', 'route', 'smoketest', 'rule', '3', 'state', 'new']) self.cli_set(['policy', 'route', 'smoketest', 'rule', '3', 'ttl', 'gt', '2']) + self.cli_set(['policy', 'route', 'smoketest', 'rule', '3', 'mark', '!456']) self.cli_set(['policy', 'route', 'smoketest', 'rule', '3', 'set', 'table', table_id]) self.cli_set(['policy', 'route', 'smoketest', 'rule', '4', 'protocol', 'icmp']) self.cli_set(['policy', 'route', 'smoketest', 'rule', '4', 'icmp', 'type-name', 'echo-request']) self.cli_set(['policy', 'route', 'smoketest', 'rule', '4', 'packet-length', '128']) self.cli_set(['policy', 'route', 'smoketest', 'rule', '4', 'packet-length', '1024-2048']) self.cli_set(['policy', 'route', 'smoketest', 'rule', '4', 'packet-type', 'other']) - self.cli_set(['policy', 'route', 'smoketest', 'rule', '4', 'log', 'enable']) + self.cli_set(['policy', 'route', 'smoketest', 'rule', '4', 'log']) self.cli_set(['policy', 'route', 'smoketest', 'rule', '4', 'set', 'table', table_id]) self.cli_set(['policy', 'route', 'smoketest', 'rule', '5', 'dscp', '41']) self.cli_set(['policy', 'route', 'smoketest', 'rule', '5', 'dscp', '57-59']) + self.cli_set(['policy', 'route', 'smoketest', 'rule', '5', 'mark', '!456-500']) self.cli_set(['policy', 'route', 'smoketest', 'rule', '5', 'set', 'table', table_id]) self.cli_set(['policy', 'route6', 'smoketest6', 'rule', '1', 'protocol', 'udp']) @@ -221,7 +225,7 @@ class TestPolicyRoute(VyOSUnitTestSHIM.TestCase): self.cli_set(['policy', 'route6', 'smoketest6', 'rule', '3', 'source', 'address', '2001:db8::0/64']) self.cli_set(['policy', 'route6', 'smoketest6', 'rule', '3', 'protocol', 'tcp']) self.cli_set(['policy', 'route6', 'smoketest6', 'rule', '3', 'destination', 'port', '22']) - self.cli_set(['policy', 'route6', 'smoketest6', 'rule', '3', 'state', 'new', 'enable']) + self.cli_set(['policy', 'route6', 'smoketest6', 'rule', '3', 'state', 'new']) self.cli_set(['policy', 'route6', 'smoketest6', 'rule', '3', 'hop-limit', 'gt', '2']) self.cli_set(['policy', 'route6', 'smoketest6', 'rule', '3', 'set', 'table', table_id]) self.cli_set(['policy', 'route6', 'smoketest6', 'rule', '4', 'protocol', 'icmpv6']) @@ -230,7 +234,7 @@ class TestPolicyRoute(VyOSUnitTestSHIM.TestCase): self.cli_set(['policy', 'route6', 'smoketest6', 'rule', '4', 'packet-length-exclude', '1024-2048']) self.cli_set(['policy', 'route6', 'smoketest6', 'rule', '4', 'packet-type', 'multicast']) - self.cli_set(['policy', 'route6', 'smoketest6', 'rule', '4', 'log', 'enable']) + self.cli_set(['policy', 'route6', 'smoketest6', 'rule', '4', 'log']) self.cli_set(['policy', 'route6', 'smoketest6', 'rule', '4', 'set', 'table', table_id]) self.cli_set(['policy', 'route6', 'smoketest6', 'rule', '5', 'dscp-exclude', '61']) self.cli_set(['policy', 'route6', 'smoketest6', 'rule', '5', 'dscp-exclude', '14-19']) @@ -247,11 +251,11 @@ class TestPolicyRoute(VyOSUnitTestSHIM.TestCase): # IPv4 nftables_search = [ ['iifname { "' + interface + '", "' + interface_wc + '" }', 'jump VYOS_PBR_UD_smoketest'], - ['meta l4proto udp', 'drop'], - ['tcp flags syn / syn,ack', 'meta mark set ' + mark_hex], - ['ct state new', 'tcp dport 22', 'ip saddr 198.51.100.0/24', 'ip ttl > 2', 'meta mark set ' + mark_hex], - ['meta l4proto icmp', 'log prefix "[ipv4-route-smoketest-4-A]"', 'icmp type echo-request', 'ip length { 128, 1024-2048 }', 'meta pkttype other', 'meta mark set ' + mark_hex], - ['ip dscp { 0x29, 0x39-0x3b }', 'meta mark set ' + mark_hex] + ['meta l4proto udp', 'meta mark 0x000007e4', 'drop'], + ['tcp flags syn / syn,ack', 'meta mark 0x00000002-0x00000bb8', 'meta mark set ' + mark_hex], + ['ct state new', 'tcp dport 22', 'ip saddr 198.51.100.0/24', 'ip ttl > 2', 'meta mark != 0x000001c8', 'meta mark set ' + mark_hex], + ['log prefix "[ipv4-route-smoketest-4-A]"', 'icmp type echo-request', 'ip length { 128, 1024-2048 }', 'meta pkttype other', 'meta mark set ' + mark_hex], + ['ip dscp { 0x29, 0x39-0x3b }', 'meta mark != 0x000001c8-0x000001f4', 'meta mark set ' + mark_hex] ] self.verify_nftables(nftables_search, 'ip vyos_mangle') @@ -262,7 +266,7 @@ class TestPolicyRoute(VyOSUnitTestSHIM.TestCase): ['meta l4proto udp', 'drop'], ['tcp flags syn / syn,ack', 'meta mark set ' + mark_hex], ['ct state new', 'tcp dport 22', 'ip6 saddr 2001:db8::/64', 'ip6 hoplimit > 2', 'meta mark set ' + mark_hex], - ['meta l4proto ipv6-icmp', 'log prefix "[ipv6-route6-smoketest6-4-A]"', 'icmpv6 type echo-request', 'ip6 length != { 128, 1024-2048 }', 'meta pkttype multicast', 'meta mark set ' + mark_hex], + ['log prefix "[ipv6-route6-smoketest6-4-A]"', 'icmpv6 type echo-request', 'ip6 length != { 128, 1024-2048 }', 'meta pkttype multicast', 'meta mark set ' + mark_hex], ['ip6 dscp != { 0x0e-0x13, 0x3d }', 'meta mark set ' + mark_hex] ] diff --git a/src/conf_mode/firewall.py b/src/conf_mode/firewall.py index da22fad68..c4974d249 100755 --- a/src/conf_mode/firewall.py +++ b/src/conf_mode/firewall.py @@ -249,7 +249,7 @@ def verify_rule(firewall, rule_conf, ipv6): raise ConfigError(f'{side} port-group and port cannot both be defined') if 'log_options' in rule_conf: - if 'log' not in rule_conf or 'enable' not in rule_conf['log']: + if 'log' not in rule_conf: raise ConfigError('log-options defined, but log is not enable') if 'snapshot_length' in rule_conf['log_options'] and 'group' not in rule_conf['log_options']: diff --git a/src/migration-scripts/firewall/11-to-12 b/src/migration-scripts/firewall/11-to-12 index 51b2fa860..ba8374d66 100755 --- a/src/migration-scripts/firewall/11-to-12 +++ b/src/migration-scripts/firewall/11-to-12 @@ -46,7 +46,6 @@ if not config.exists(base): # Nothing to do exit(0) -## FORT ## Migration from base chains #if config.exists(base + ['interface', iface, direction]): for family in ['ipv4', 'ipv6']: diff --git a/src/migration-scripts/firewall/12-to-13 b/src/migration-scripts/firewall/12-to-13 new file mode 100755 index 000000000..4eaae779b --- /dev/null +++ b/src/migration-scripts/firewall/12-to-13 @@ -0,0 +1,83 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2023 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/>. + +# T5729: Switch to valueless whenever is possible. +# From + # set firewall ... rule <rule> log enable + # set firewall ... rule <rule> state <state> enable + # set firewall ... rule <rule> log disable + # set firewall ... rule <rule> state <state> disable +# To + # set firewall ... rule <rule> log + # set firewall ... rule <rule> state <state> + # Remove command if log=disable or <state>=disable + +import re + +from sys import argv +from sys import exit + +from vyos.configtree import ConfigTree +from vyos.ifconfig import Section + +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() + +base = ['firewall'] +config = ConfigTree(config_file) + +if not config.exists(base): + # Nothing to do + exit(0) + +for family in ['ipv4', 'ipv6', 'bridge']: + if config.exists(base + [family]): + for hook in ['forward', 'input', 'output', 'name']: + if config.exists(base + [family, hook]): + for priority in config.list_nodes(base + [family, hook]): + if config.exists(base + [family, hook, priority, 'rule']): + for rule in config.list_nodes(base + [family, hook, priority, 'rule']): + # Log + if config.exists(base + [family, hook, priority, 'rule', rule, 'log']): + log_value = config.return_value(base + [family, hook, priority, 'rule', rule, 'log']) + config.delete(base + [family, hook, priority, 'rule', rule, 'log']) + if log_value == 'enable': + config.set(base + [family, hook, priority, 'rule', rule, 'log']) + # State + if config.exists(base + [family, hook, priority, 'rule', rule, 'state']): + flag_enable = 'False' + for state in ['established', 'invalid', 'new', 'related']: + if config.exists(base + [family, hook, priority, 'rule', rule, 'state', state]): + state_value = config.return_value(base + [family, hook, priority, 'rule', rule, 'state', state]) + config.delete(base + [family, hook, priority, 'rule', rule, 'state', state]) + if state_value == 'enable': + config.set(base + [family, hook, priority, 'rule', rule, 'state'], value=state, replace=False) + flag_enable = 'True' + if flag_enable == 'False': + config.delete(base + [family, hook, priority, 'rule', rule, 'state']) + +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 diff --git a/src/migration-scripts/policy/6-to-7 b/src/migration-scripts/policy/6-to-7 new file mode 100755 index 000000000..e07822ffd --- /dev/null +++ b/src/migration-scripts/policy/6-to-7 @@ -0,0 +1,79 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2023 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/>. + +# T5729: Switch to valueless whenever is possible. +# From + # set policy [route | route6] ... rule <rule> log enable + # set policy [route | route6] ... rule <rule> log disable +# To + # set policy [route | route6] ... rule <rule> log + # Remove command if log=disable + +import re + +from sys import argv +from sys import exit + +from vyos.configtree import ConfigTree +from vyos.ifconfig import Section + +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() + +base = ['policy'] +config = ConfigTree(config_file) + +if not config.exists(base): + # Nothing to do + exit(0) + +for family in ['route', 'route6']: + if config.exists(base + [family]): + + for policy_name in config.list_nodes(base + [family]): + if config.exists(base + [family, policy_name, 'rule']): + for rule in config.list_nodes(base + [family, policy_name, 'rule']): + # Log + if config.exists(base + [family, policy_name, 'rule', rule, 'log']): + log_value = config.return_value(base + [family, policy_name, 'rule', rule, 'log']) + config.delete(base + [family, policy_name, 'rule', rule, 'log']) + if log_value == 'enable': + config.set(base + [family, policy_name, 'rule', rule, 'log']) + # State + if config.exists(base + [family, policy_name, 'rule', rule, 'state']): + flag_enable = 'False' + for state in ['established', 'invalid', 'new', 'related']: + if config.exists(base + [family, policy_name, 'rule', rule, 'state', state]): + state_value = config.return_value(base + [family, policy_name, 'rule', rule, 'state', state]) + config.delete(base + [family, policy_name, 'rule', rule, 'state', state]) + if state_value == 'enable': + config.set(base + [family, policy_name, 'rule', rule, 'state'], value=state, replace=False) + flag_enable = 'True' + if flag_enable == 'False': + config.delete(base + [family, policy_name, 'rule', rule, 'state']) + +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 diff --git a/src/validators/numeric-exclude b/src/validators/numeric-exclude new file mode 100755 index 000000000..d693ad16d --- /dev/null +++ b/src/validators/numeric-exclude @@ -0,0 +1,8 @@ +#!/bin/sh +path=$(dirname "$0") +num="${@: -1}" +if [ "${num:0:1}" != "!" ]; then + ${path}/numeric $@ +else + ${path}/numeric ${@:1:$#-1} ${num:1} +fi
\ No newline at end of file |