import nftables-0.9.3-21.el8
This commit is contained in:
parent
ddc3de15f1
commit
d1de3e821a
497
SOURCES/0042-tests-Disable-tests-known-to-fail-on-RHEL8.patch
Normal file
497
SOURCES/0042-tests-Disable-tests-known-to-fail-on-RHEL8.patch
Normal file
@ -0,0 +1,497 @@
|
||||
From f9dca1704ce66be31eceac4d7317b825269b3d07 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Tue, 2 Mar 2021 17:06:06 +0100
|
||||
Subject: [PATCH] tests: Disable tests known to fail on RHEL8
|
||||
|
||||
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1919203
|
||||
Upstream Status: RHEL-only
|
||||
|
||||
RHEL8 kernel does not support:
|
||||
|
||||
- ct timeout or expectation objects
|
||||
- synproxy
|
||||
- flowtables in families other than inet
|
||||
- meta time
|
||||
- bridge family-specific meta expressions (e.g. ibrvproto, ibrpvid)
|
||||
- socket mark
|
||||
- osf
|
||||
- delete set elements from packet path
|
||||
- update stateful objects
|
||||
- explicitly setting set element expiration (commit 79ebb5bb4e3)
|
||||
- flushing chains and deleting referenced objects in the same
|
||||
transaction (upstream commits with 'bogus EBUSY' in subject)
|
||||
|
||||
Disable all related tests to make the testsuites pass.
|
||||
---
|
||||
tests/monitor/testcases/object.t | 14 +++----
|
||||
tests/py/any/meta.t | 36 ++++++++---------
|
||||
tests/py/bridge/meta.t | 8 ++--
|
||||
tests/py/inet/osf.t | 24 +++++------
|
||||
tests/py/inet/socket.t | 2 +-
|
||||
tests/py/inet/synproxy.t | 12 +++---
|
||||
tests/py/ip/objects.t | 46 +++++++++++-----------
|
||||
tests/py/ip6/sets.t | 2 +-
|
||||
.../testcases/flowtable/0002create_flowtable_0 | 8 ++--
|
||||
.../testcases/flowtable/0003add_after_flush_0 | 8 ++--
|
||||
.../testcases/flowtable/0004delete_after_add_0 | 6 +--
|
||||
.../shell/testcases/flowtable/0005delete_in_use_1 | 10 ++---
|
||||
tests/shell/testcases/flowtable/0007prio_0 | 6 +--
|
||||
tests/shell/testcases/flowtable/0008prio_1 | 4 +-
|
||||
.../testcases/flowtable/0009deleteafterflush_0 | 12 +++---
|
||||
tests/shell/testcases/listing/0013objects_0 | 2 +
|
||||
tests/shell/testcases/nft-f/0017ct_timeout_obj_0 | 2 +
|
||||
.../shell/testcases/nft-f/0018ct_expectation_obj_0 | 2 +
|
||||
.../testcases/nft-f/dumps/0017ct_timeout_obj_0.nft | 11 ------
|
||||
.../nft-f/dumps/0017ct_timeout_obj_0.nft.disabled | 11 ++++++
|
||||
.../testcases/optionals/update_object_handles_0 | 2 +
|
||||
.../sets/0036add_set_element_expiration_0 | 2 +
|
||||
tests/shell/testcases/transactions/0046set_0 | 2 +
|
||||
23 files changed, 122 insertions(+), 110 deletions(-)
|
||||
delete mode 100644 tests/shell/testcases/nft-f/dumps/0017ct_timeout_obj_0.nft
|
||||
create mode 100644 tests/shell/testcases/nft-f/dumps/0017ct_timeout_obj_0.nft.disabled
|
||||
|
||||
diff --git a/tests/monitor/testcases/object.t b/tests/monitor/testcases/object.t
|
||||
index 2afe33c..1b30384 100644
|
||||
--- a/tests/monitor/testcases/object.t
|
||||
+++ b/tests/monitor/testcases/object.t
|
||||
@@ -37,10 +37,10 @@ I delete ct helper ip t cth
|
||||
O -
|
||||
J {"delete": {"ct helper": {"family": "ip", "name": "cth", "table": "t", "handle": 0, "type": "sip", "protocol": "tcp", "l3proto": "ip"}}}
|
||||
|
||||
-I add ct timeout ip t ctt { protocol udp; l3proto ip; policy = { unreplied : 15, replied : 12 }; }
|
||||
-O -
|
||||
-J {"add": {"ct timeout": {"family": "ip", "name": "ctt", "table": "t", "handle": 0, "protocol": "udp", "l3proto": "ip", "policy": {"unreplied": 15, "replied": 12}}}}
|
||||
-
|
||||
-I delete ct timeout ip t ctt
|
||||
-O -
|
||||
-J {"delete": {"ct timeout": {"family": "ip", "name": "ctt", "table": "t", "handle": 0, "protocol": "udp", "l3proto": "ip", "policy": {"unreplied": 15, "replied": 12}}}}
|
||||
+# I add ct timeout ip t ctt { protocol udp; l3proto ip; policy = { unreplied : 15, replied : 12 }; }
|
||||
+# O -
|
||||
+# J {"add": {"ct timeout": {"family": "ip", "name": "ctt", "table": "t", "handle": 0, "protocol": "udp", "l3proto": "ip", "policy": {"unreplied": 15, "replied": 12}}}}
|
||||
+#
|
||||
+# I delete ct timeout ip t ctt
|
||||
+# O -
|
||||
+# J {"delete": {"ct timeout": {"family": "ip", "name": "ctt", "table": "t", "handle": 0, "protocol": "udp", "l3proto": "ip", "policy": {"unreplied": 15, "replied": 12}}}}
|
||||
diff --git a/tests/py/any/meta.t b/tests/py/any/meta.t
|
||||
index 327f973..241b466 100644
|
||||
--- a/tests/py/any/meta.t
|
||||
+++ b/tests/py/any/meta.t
|
||||
@@ -204,21 +204,21 @@ meta iif . meta oif vmap { "lo" . "lo" : drop };ok;iif . oif vmap { "lo" . "lo"
|
||||
meta random eq 1;ok;meta random 1
|
||||
meta random gt 1000000;ok;meta random > 1000000
|
||||
|
||||
-meta time "1970-05-23 21:07:14" drop;ok
|
||||
-meta time 12341234 drop;ok;meta time "1970-05-23 22:07:14" drop
|
||||
-meta time "2019-06-21 17:00:00" drop;ok
|
||||
-meta time "2019-07-01 00:00:00" drop;ok
|
||||
-meta time "2019-07-01 00:01:00" drop;ok
|
||||
-meta time "2019-07-01 00:00:01" drop;ok
|
||||
-meta day "Saturday" drop;ok
|
||||
-meta day 6 drop;ok;meta day "Saturday" drop
|
||||
-meta day "Satturday" drop;fail
|
||||
-meta hour "17:00" drop;ok
|
||||
-meta hour "17:00:00" drop;ok;meta hour "17:00" drop
|
||||
-meta hour "17:00:01" drop;ok
|
||||
-meta hour "00:00" drop;ok
|
||||
-meta hour "00:01" drop;ok
|
||||
-
|
||||
-meta time "meh";fail
|
||||
-meta hour "24:00" drop;fail
|
||||
-meta day 7 drop;fail
|
||||
+- meta time "1970-05-23 21:07:14" drop;ok
|
||||
+- meta time 12341234 drop;ok;meta time "1970-05-23 22:07:14" drop
|
||||
+- meta time "2019-06-21 17:00:00" drop;ok
|
||||
+- meta time "2019-07-01 00:00:00" drop;ok
|
||||
+- meta time "2019-07-01 00:01:00" drop;ok
|
||||
+- meta time "2019-07-01 00:00:01" drop;ok
|
||||
+- meta day "Saturday" drop;ok
|
||||
+- meta day 6 drop;ok;meta day "Saturday" drop
|
||||
+- meta day "Satturday" drop;fail
|
||||
+- meta hour "17:00" drop;ok
|
||||
+- meta hour "17:00:00" drop;ok;meta hour "17:00" drop
|
||||
+- meta hour "17:00:01" drop;ok
|
||||
+- meta hour "00:00" drop;ok
|
||||
+- meta hour "00:01" drop;ok
|
||||
+
|
||||
+- meta time "meh";fail
|
||||
+- meta hour "24:00" drop;fail
|
||||
+- meta day 7 drop;fail
|
||||
diff --git a/tests/py/bridge/meta.t b/tests/py/bridge/meta.t
|
||||
index 94525f2..9f55cde 100644
|
||||
--- a/tests/py/bridge/meta.t
|
||||
+++ b/tests/py/bridge/meta.t
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
*bridge;test-bridge;input
|
||||
|
||||
-meta obrname "br0";ok
|
||||
-meta ibrname "br0";ok
|
||||
-meta ibrvproto vlan;ok
|
||||
-meta ibrpvid 100;ok
|
||||
+- meta obrname "br0";ok
|
||||
+- meta ibrname "br0";ok
|
||||
+- meta ibrvproto vlan;ok
|
||||
+- meta ibrpvid 100;ok
|
||||
diff --git a/tests/py/inet/osf.t b/tests/py/inet/osf.t
|
||||
index c828541..5191e72 100644
|
||||
--- a/tests/py/inet/osf.t
|
||||
+++ b/tests/py/inet/osf.t
|
||||
@@ -4,15 +4,15 @@
|
||||
*ip6;osfip6;osfchain
|
||||
*inet;osfinet;osfchain
|
||||
|
||||
-osf name "Linux";ok
|
||||
-osf ttl loose name "Linux";ok
|
||||
-osf ttl skip name "Linux";ok
|
||||
-osf ttl skip version "Linux:3.0";ok
|
||||
-osf ttl skip version "morethan:sixteenbytes";fail
|
||||
-osf ttl nottl name "Linux";fail
|
||||
-osf name "morethansixteenbytes";fail
|
||||
-osf name ;fail
|
||||
-osf name { "Windows", "MacOs" };ok
|
||||
-osf version { "Windows:XP", "MacOs:Sierra" };ok
|
||||
-ct mark set osf name map { "Windows" : 0x00000001, "MacOs" : 0x00000002 };ok
|
||||
-ct mark set osf version map { "Windows:XP" : 0x00000003, "MacOs:Sierra" : 0x00000004 };ok
|
||||
+- osf name "Linux";ok
|
||||
+- osf ttl loose name "Linux";ok
|
||||
+- osf ttl skip name "Linux";ok
|
||||
+- osf ttl skip version "Linux:3.0";ok
|
||||
+- osf ttl skip version "morethan:sixteenbytes";fail
|
||||
+- osf ttl nottl name "Linux";fail
|
||||
+- osf name "morethansixteenbytes";fail
|
||||
+- osf name ;fail
|
||||
+- osf name { "Windows", "MacOs" };ok
|
||||
+- osf version { "Windows:XP", "MacOs:Sierra" };ok
|
||||
+- ct mark set osf name map { "Windows" : 0x00000001, "MacOs" : 0x00000002 };ok
|
||||
+- ct mark set osf version map { "Windows:XP" : 0x00000003, "MacOs:Sierra" : 0x00000004 };ok
|
||||
diff --git a/tests/py/inet/socket.t b/tests/py/inet/socket.t
|
||||
index 91846e8..dbc0554 100644
|
||||
--- a/tests/py/inet/socket.t
|
||||
+++ b/tests/py/inet/socket.t
|
||||
@@ -8,4 +8,4 @@ socket transparent 0;ok
|
||||
socket transparent 1;ok
|
||||
socket transparent 2;fail
|
||||
|
||||
-socket mark 0x00000005;ok
|
||||
+- socket mark 0x00000005;ok
|
||||
diff --git a/tests/py/inet/synproxy.t b/tests/py/inet/synproxy.t
|
||||
index 55a05e1..9c58239 100644
|
||||
--- a/tests/py/inet/synproxy.t
|
||||
+++ b/tests/py/inet/synproxy.t
|
||||
@@ -4,10 +4,10 @@
|
||||
*ip6;synproxyip6;synproxychain
|
||||
*inet;synproxyinet;synproxychain
|
||||
|
||||
-synproxy;ok
|
||||
-synproxy mss 1460 wscale 7;ok
|
||||
-synproxy mss 1460 wscale 5 timestamp sack-perm;ok
|
||||
-synproxy timestamp sack-perm;ok
|
||||
-synproxy timestamp;ok
|
||||
-synproxy sack-perm;ok
|
||||
+-synproxy;ok
|
||||
+-synproxy mss 1460 wscale 7;ok
|
||||
+-synproxy mss 1460 wscale 5 timestamp sack-perm;ok
|
||||
+-synproxy timestamp sack-perm;ok
|
||||
+-synproxy timestamp;ok
|
||||
+-synproxy sack-perm;ok
|
||||
|
||||
diff --git a/tests/py/ip/objects.t b/tests/py/ip/objects.t
|
||||
index 4fcde7c..06e94f1 100644
|
||||
--- a/tests/py/ip/objects.t
|
||||
+++ b/tests/py/ip/objects.t
|
||||
@@ -33,26 +33,26 @@ ip saddr 192.168.1.3 limit name "lim1";ok
|
||||
ip saddr 192.168.1.3 limit name "lim3";fail
|
||||
limit name tcp dport map {443 : "lim1", 80 : "lim2", 22 : "lim1"};ok
|
||||
|
||||
-# ct timeout
|
||||
-%cttime1 type ct timeout { protocol tcp; policy = { established:122 } ;};ok
|
||||
-%cttime2 type ct timeout { protocol udp; policy = { syn_sent:122 } ;};fail
|
||||
-%cttime3 type ct timeout { protocol tcp; policy = { established:132, close:16, close_wait:16 } ; l3proto ip ;};ok
|
||||
-%cttime4 type ct timeout { protocol udp; policy = { replied:14, unreplied:19 } ;};ok
|
||||
-%cttime5 type ct timeout {protocol tcp; policy = { estalbished:100 } ;};fail
|
||||
-
|
||||
-ct timeout set "cttime1";ok
|
||||
-
|
||||
-# ct expectation
|
||||
-%ctexpect1 type ct expectation { protocol tcp; dport 1234; timeout 2m; size 12; };ok
|
||||
-%ctexpect2 type ct expectation { protocol udp; };fail
|
||||
-%ctexpect3 type ct expectation { protocol tcp; dport 4321; };fail
|
||||
-%ctexpect4 type ct expectation { protocol tcp; dport 4321; timeout 2m; };fail
|
||||
-%ctexpect5 type ct expectation { protocol udp; dport 9876; timeout 2m; size 12; l3proto ip; };ok
|
||||
-
|
||||
-ct expectation set "ctexpect1";ok
|
||||
-
|
||||
-# synproxy
|
||||
-%synproxy1 type synproxy mss 1460 wscale 7;ok
|
||||
-%synproxy2 type synproxy mss 1460 wscale 7 timestamp sack-perm;ok
|
||||
-
|
||||
-synproxy name tcp dport map {443 : "synproxy1", 80 : "synproxy2"};ok
|
||||
+# # ct timeout
|
||||
+# %cttime1 type ct timeout { protocol tcp; policy = { established:122 } ;};ok
|
||||
+# %cttime2 type ct timeout { protocol udp; policy = { syn_sent:122 } ;};fail
|
||||
+# %cttime3 type ct timeout { protocol tcp; policy = { established:132, close:16, close_wait:16 } ; l3proto ip ;};ok
|
||||
+# %cttime4 type ct timeout { protocol udp; policy = { replied:14, unreplied:19 } ;};ok
|
||||
+# %cttime5 type ct timeout {protocol tcp; policy = { estalbished:100 } ;};fail
|
||||
+#
|
||||
+# ct timeout set "cttime1";ok
|
||||
+
|
||||
+# # ct expectation
|
||||
+# %ctexpect1 type ct expectation { protocol tcp; dport 1234; timeout 2m; size 12; };ok
|
||||
+# %ctexpect2 type ct expectation { protocol udp; };fail
|
||||
+# %ctexpect3 type ct expectation { protocol tcp; dport 4321; };fail
|
||||
+# %ctexpect4 type ct expectation { protocol tcp; dport 4321; timeout 2m; };fail
|
||||
+# %ctexpect5 type ct expectation { protocol udp; dport 9876; timeout 2m; size 12; l3proto ip; };ok
|
||||
+#
|
||||
+# ct expectation set "ctexpect1";ok
|
||||
+
|
||||
+# # synproxy
|
||||
+# %synproxy1 type synproxy mss 1460 wscale 7;ok
|
||||
+# %synproxy2 type synproxy mss 1460 wscale 7 timestamp sack-perm;ok
|
||||
+#
|
||||
+# synproxy name tcp dport map {443 : "synproxy1", 80 : "synproxy2"};ok
|
||||
diff --git a/tests/py/ip6/sets.t b/tests/py/ip6/sets.t
|
||||
index add82eb..cc43aca 100644
|
||||
--- a/tests/py/ip6/sets.t
|
||||
+++ b/tests/py/ip6/sets.t
|
||||
@@ -40,4 +40,4 @@ ip6 saddr != @set33 drop;fail
|
||||
!set5 type ipv6_addr . ipv6_addr;ok
|
||||
ip6 saddr . ip6 daddr @set5 drop;ok
|
||||
add @set5 { ip6 saddr . ip6 daddr };ok
|
||||
-delete @set5 { ip6 saddr . ip6 daddr };ok
|
||||
+- delete @set5 { ip6 saddr . ip6 daddr };ok
|
||||
diff --git a/tests/shell/testcases/flowtable/0002create_flowtable_0 b/tests/shell/testcases/flowtable/0002create_flowtable_0
|
||||
index 4c85c3f..8b80e34 100755
|
||||
--- a/tests/shell/testcases/flowtable/0002create_flowtable_0
|
||||
+++ b/tests/shell/testcases/flowtable/0002create_flowtable_0
|
||||
@@ -1,12 +1,12 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
-$NFT add table t
|
||||
-$NFT add flowtable t f { hook ingress priority 10 \; devices = { lo }\; }
|
||||
-if $NFT create flowtable t f { hook ingress priority 10 \; devices = { lo }\; } 2>/dev/null ; then
|
||||
+$NFT add table inet t
|
||||
+$NFT add flowtable inet t f { hook ingress priority 10 \; devices = { lo }\; }
|
||||
+if $NFT create flowtable inet t f { hook ingress priority 10 \; devices = { lo }\; } 2>/dev/null ; then
|
||||
echo "E: flowtable creation not failing on existing set" >&2
|
||||
exit 1
|
||||
fi
|
||||
-$NFT add flowtable t f { hook ingress priority 10 \; devices = { lo }\; }
|
||||
+$NFT add flowtable inet t f { hook ingress priority 10 \; devices = { lo }\; }
|
||||
|
||||
exit 0
|
||||
diff --git a/tests/shell/testcases/flowtable/0003add_after_flush_0 b/tests/shell/testcases/flowtable/0003add_after_flush_0
|
||||
index 481c7ed..b4243bc 100755
|
||||
--- a/tests/shell/testcases/flowtable/0003add_after_flush_0
|
||||
+++ b/tests/shell/testcases/flowtable/0003add_after_flush_0
|
||||
@@ -1,8 +1,8 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
-$NFT add table x
|
||||
-$NFT add flowtable x y { hook ingress priority 0\; devices = { lo }\;}
|
||||
+$NFT add table inet x
|
||||
+$NFT add flowtable inet x y { hook ingress priority 0\; devices = { lo }\;}
|
||||
$NFT flush ruleset
|
||||
-$NFT add table x
|
||||
-$NFT add flowtable x y { hook ingress priority 0\; devices = { lo }\;}
|
||||
+$NFT add table inet x
|
||||
+$NFT add flowtable inet x y { hook ingress priority 0\; devices = { lo }\;}
|
||||
diff --git a/tests/shell/testcases/flowtable/0004delete_after_add_0 b/tests/shell/testcases/flowtable/0004delete_after_add_0
|
||||
index 8d9a842..4618595 100755
|
||||
--- a/tests/shell/testcases/flowtable/0004delete_after_add_0
|
||||
+++ b/tests/shell/testcases/flowtable/0004delete_after_add_0
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
-$NFT add table x
|
||||
-$NFT add flowtable x y { hook ingress priority 0\; devices = { lo }\;}
|
||||
-$NFT delete flowtable x y
|
||||
+$NFT add table inet x
|
||||
+$NFT add flowtable inet x y { hook ingress priority 0\; devices = { lo }\;}
|
||||
+$NFT delete flowtable inet x y
|
||||
diff --git a/tests/shell/testcases/flowtable/0005delete_in_use_1 b/tests/shell/testcases/flowtable/0005delete_in_use_1
|
||||
index ef52620..eda1fb9 100755
|
||||
--- a/tests/shell/testcases/flowtable/0005delete_in_use_1
|
||||
+++ b/tests/shell/testcases/flowtable/0005delete_in_use_1
|
||||
@@ -1,11 +1,11 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
-$NFT add table x
|
||||
-$NFT add chain x x
|
||||
-$NFT add flowtable x y { hook ingress priority 0\; devices = { lo }\;}
|
||||
-$NFT add rule x x flow add @y
|
||||
+$NFT add table inet x
|
||||
+$NFT add chain inet x x
|
||||
+$NFT add flowtable inet x y { hook ingress priority 0\; devices = { lo }\;}
|
||||
+$NFT add rule inet x x flow add @y
|
||||
|
||||
-$NFT delete flowtable x y || exit 0
|
||||
+$NFT delete flowtable inet x y || exit 0
|
||||
echo "E: delete flowtable in use"
|
||||
exit 1
|
||||
diff --git a/tests/shell/testcases/flowtable/0007prio_0 b/tests/shell/testcases/flowtable/0007prio_0
|
||||
index 49bbcac..0ea262f 100755
|
||||
--- a/tests/shell/testcases/flowtable/0007prio_0
|
||||
+++ b/tests/shell/testcases/flowtable/0007prio_0
|
||||
@@ -15,10 +15,10 @@ format_offset () {
|
||||
fi
|
||||
}
|
||||
|
||||
-$NFT add table t
|
||||
+$NFT add table inet t
|
||||
for offset in -11 -10 0 10 11
|
||||
do
|
||||
- $NFT add flowtable t f "{ hook ingress priority filter `format_offset $offset`; devices = { lo }; }"
|
||||
- $NFT delete flowtable t f
|
||||
+ $NFT add flowtable inet t f "{ hook ingress priority filter `format_offset $offset`; devices = { lo }; }"
|
||||
+ $NFT delete flowtable inet t f
|
||||
done
|
||||
|
||||
diff --git a/tests/shell/testcases/flowtable/0008prio_1 b/tests/shell/testcases/flowtable/0008prio_1
|
||||
index 48953d7..0d8cdff 100755
|
||||
--- a/tests/shell/testcases/flowtable/0008prio_1
|
||||
+++ b/tests/shell/testcases/flowtable/0008prio_1
|
||||
@@ -1,9 +1,9 @@
|
||||
#!/bin/bash
|
||||
|
||||
-$NFT add table t
|
||||
+$NFT add table inet t
|
||||
for prioname in raw mangle dstnar security srcnat out dummy
|
||||
do
|
||||
- $NFT add flowtable t f { hook ingress priority $prioname \; devices = { lo }\; }
|
||||
+ $NFT add flowtable inet t f { hook ingress priority $prioname \; devices = { lo }\; }
|
||||
if (($? == 0))
|
||||
then
|
||||
echo "E: $prioname should not be a valid priority name for flowtables" >&2
|
||||
diff --git a/tests/shell/testcases/flowtable/0009deleteafterflush_0 b/tests/shell/testcases/flowtable/0009deleteafterflush_0
|
||||
index 2cda563..061e22e 100755
|
||||
--- a/tests/shell/testcases/flowtable/0009deleteafterflush_0
|
||||
+++ b/tests/shell/testcases/flowtable/0009deleteafterflush_0
|
||||
@@ -1,9 +1,9 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
-$NFT add table x
|
||||
-$NFT add chain x y
|
||||
-$NFT add flowtable x f { hook ingress priority 0\; devices = { lo }\;}
|
||||
-$NFT add rule x y flow add @f
|
||||
-$NFT flush chain x y
|
||||
-$NFT delete flowtable x f
|
||||
+$NFT add table inet x
|
||||
+$NFT add chain inet x y
|
||||
+$NFT add flowtable inet x f { hook ingress priority 0\; devices = { lo }\;}
|
||||
+$NFT add rule inet x y flow add @f
|
||||
+$NFT flush chain inet x y
|
||||
+$NFT delete flowtable inet x f
|
||||
diff --git a/tests/shell/testcases/listing/0013objects_0 b/tests/shell/testcases/listing/0013objects_0
|
||||
index 4d39143..130d02c 100755
|
||||
--- a/tests/shell/testcases/listing/0013objects_0
|
||||
+++ b/tests/shell/testcases/listing/0013objects_0
|
||||
@@ -1,5 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
+exit 0
|
||||
+
|
||||
# list table with all objects and chains
|
||||
|
||||
EXPECTED="table ip test {
|
||||
diff --git a/tests/shell/testcases/nft-f/0017ct_timeout_obj_0 b/tests/shell/testcases/nft-f/0017ct_timeout_obj_0
|
||||
index 4f40779..e0f9e44 100755
|
||||
--- a/tests/shell/testcases/nft-f/0017ct_timeout_obj_0
|
||||
+++ b/tests/shell/testcases/nft-f/0017ct_timeout_obj_0
|
||||
@@ -1,5 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
+exit 0
|
||||
+
|
||||
EXPECTED='table ip filter {
|
||||
ct timeout cttime{
|
||||
protocol tcp
|
||||
diff --git a/tests/shell/testcases/nft-f/0018ct_expectation_obj_0 b/tests/shell/testcases/nft-f/0018ct_expectation_obj_0
|
||||
index 4f9872f..f518cf7 100755
|
||||
--- a/tests/shell/testcases/nft-f/0018ct_expectation_obj_0
|
||||
+++ b/tests/shell/testcases/nft-f/0018ct_expectation_obj_0
|
||||
@@ -1,5 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
+exit 0
|
||||
+
|
||||
EXPECTED='table ip filter {
|
||||
ct expectation ctexpect{
|
||||
protocol tcp
|
||||
diff --git a/tests/shell/testcases/nft-f/dumps/0017ct_timeout_obj_0.nft b/tests/shell/testcases/nft-f/dumps/0017ct_timeout_obj_0.nft
|
||||
deleted file mode 100644
|
||||
index 7cff1ed..0000000
|
||||
--- a/tests/shell/testcases/nft-f/dumps/0017ct_timeout_obj_0.nft
|
||||
+++ /dev/null
|
||||
@@ -1,11 +0,0 @@
|
||||
-table ip filter {
|
||||
- ct timeout cttime {
|
||||
- protocol tcp
|
||||
- l3proto ip
|
||||
- policy = { established : 123, close : 12 }
|
||||
- }
|
||||
-
|
||||
- chain c {
|
||||
- ct timeout set "cttime"
|
||||
- }
|
||||
-}
|
||||
diff --git a/tests/shell/testcases/nft-f/dumps/0017ct_timeout_obj_0.nft.disabled b/tests/shell/testcases/nft-f/dumps/0017ct_timeout_obj_0.nft.disabled
|
||||
new file mode 100644
|
||||
index 0000000..7cff1ed
|
||||
--- /dev/null
|
||||
+++ b/tests/shell/testcases/nft-f/dumps/0017ct_timeout_obj_0.nft.disabled
|
||||
@@ -0,0 +1,11 @@
|
||||
+table ip filter {
|
||||
+ ct timeout cttime {
|
||||
+ protocol tcp
|
||||
+ l3proto ip
|
||||
+ policy = { established : 123, close : 12 }
|
||||
+ }
|
||||
+
|
||||
+ chain c {
|
||||
+ ct timeout set "cttime"
|
||||
+ }
|
||||
+}
|
||||
diff --git a/tests/shell/testcases/optionals/update_object_handles_0 b/tests/shell/testcases/optionals/update_object_handles_0
|
||||
index 8b12b8c..e11b4e7 100755
|
||||
--- a/tests/shell/testcases/optionals/update_object_handles_0
|
||||
+++ b/tests/shell/testcases/optionals/update_object_handles_0
|
||||
@@ -1,5 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
+exit 0
|
||||
+
|
||||
set -e
|
||||
$NFT add table test-ip
|
||||
$NFT add counter test-ip traffic-counter
|
||||
diff --git a/tests/shell/testcases/sets/0036add_set_element_expiration_0 b/tests/shell/testcases/sets/0036add_set_element_expiration_0
|
||||
index 51ed0f2..043bb8f 100755
|
||||
--- a/tests/shell/testcases/sets/0036add_set_element_expiration_0
|
||||
+++ b/tests/shell/testcases/sets/0036add_set_element_expiration_0
|
||||
@@ -1,5 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
+exit 0
|
||||
+
|
||||
set -e
|
||||
|
||||
RULESET="add table ip x
|
||||
diff --git a/tests/shell/testcases/transactions/0046set_0 b/tests/shell/testcases/transactions/0046set_0
|
||||
index 172e24d..1b24964 100755
|
||||
--- a/tests/shell/testcases/transactions/0046set_0
|
||||
+++ b/tests/shell/testcases/transactions/0046set_0
|
||||
@@ -1,5 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
+exit 0
|
||||
+
|
||||
RULESET='add table ip filter
|
||||
add chain ip filter group_7933
|
||||
add map ip filter group_7933 { type ipv4_addr : classid; flags interval; }
|
||||
--
|
||||
1.8.3.1
|
||||
|
@ -0,0 +1,41 @@
|
||||
From 1490609a3d82e494168a390b34094bacc5e83c02 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Tue, 18 May 2021 18:06:50 +0200
|
||||
Subject: [PATCH] monitor: Fix for use after free when printing map elements
|
||||
|
||||
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1919203
|
||||
Upstream Status: nftables commit 02174ffad484d
|
||||
|
||||
commit 02174ffad484d9711678e5d415c32307efc39857
|
||||
Author: Phil Sutter <phil@nwl.cc>
|
||||
Date: Thu Jan 9 17:43:11 2020 +0100
|
||||
|
||||
monitor: Fix for use after free when printing map elements
|
||||
|
||||
When populating the dummy set, 'data' field must be cloned just like
|
||||
'key' field.
|
||||
|
||||
Fixes: 343a51702656a ("src: store expr, not dtype to track data in sets")
|
||||
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||||
Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
---
|
||||
src/monitor.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/monitor.c b/src/monitor.c
|
||||
index 7927b6f..142cc92 100644
|
||||
--- a/src/monitor.c
|
||||
+++ b/src/monitor.c
|
||||
@@ -401,7 +401,8 @@ static int netlink_events_setelem_cb(const struct nlmsghdr *nlh, int type,
|
||||
*/
|
||||
dummyset = set_alloc(monh->loc);
|
||||
dummyset->key = expr_clone(set->key);
|
||||
- dummyset->data = set->data;
|
||||
+ if (set->data)
|
||||
+ dummyset->data = expr_clone(set->data);
|
||||
dummyset->flags = set->flags;
|
||||
dummyset->init = set_expr_alloc(monh->loc, set);
|
||||
|
||||
--
|
||||
1.8.3.1
|
||||
|
@ -0,0 +1,44 @@
|
||||
From 4ee4ed8d54a8b9f0f0a2b195b3b95b892e4e79a3 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Tue, 18 May 2021 18:06:50 +0200
|
||||
Subject: [PATCH] tests: monitor: use correct $nft value in EXIT trap
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1919203
|
||||
Upstream Status: nftables commit 990cbbf75c40b
|
||||
|
||||
commit 990cbbf75c40b92e6d6dc66721dfbedf33cacf8f
|
||||
Author: Štěpán Němec <snemec@redhat.com>
|
||||
Date: Wed Jan 27 15:02:03 2021 +0100
|
||||
|
||||
tests: monitor: use correct $nft value in EXIT trap
|
||||
|
||||
With double quotes, $nft was being expanded to the default value even
|
||||
in presence of the -H option.
|
||||
|
||||
Signed-off-by: Štěpán Němec <snemec@redhat.com>
|
||||
Helped-by: Tomáš Doležal <todoleza@redhat.com>
|
||||
Acked-by: Phil Sutter <phil@nwl.cc>
|
||||
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||||
---
|
||||
tests/monitor/run-tests.sh | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/tests/monitor/run-tests.sh b/tests/monitor/run-tests.sh
|
||||
index ffb833a..c1cacb4 100755
|
||||
--- a/tests/monitor/run-tests.sh
|
||||
+++ b/tests/monitor/run-tests.sh
|
||||
@@ -19,7 +19,7 @@ if [ ! -d $testdir ]; then
|
||||
echo "Failed to create test directory" >&2
|
||||
exit 1
|
||||
fi
|
||||
-trap "rm -rf $testdir; $nft flush ruleset" EXIT
|
||||
+trap 'rm -rf $testdir; $nft flush ruleset' EXIT
|
||||
|
||||
command_file=$(mktemp -p $testdir)
|
||||
output_file=$(mktemp -p $testdir)
|
||||
--
|
||||
1.8.3.1
|
||||
|
@ -0,0 +1,57 @@
|
||||
From 805fe6f5c9c8f2af78d8e94bd6b5c33724df3c80 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Tue, 18 May 2021 18:16:21 +0200
|
||||
Subject: [PATCH] evaluate: Reject quoted strings containing only wildcard
|
||||
|
||||
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1818117
|
||||
Upstream Status: nftables commit 032c9f745c6da
|
||||
|
||||
commit 032c9f745c6daab8c27176a95963b1c32b0a5d12
|
||||
Author: Phil Sutter <phil@nwl.cc>
|
||||
Date: Thu Sep 24 17:38:45 2020 +0200
|
||||
|
||||
evaluate: Reject quoted strings containing only wildcard
|
||||
|
||||
Fix for an assertion fail when trying to match against an all-wildcard
|
||||
interface name:
|
||||
|
||||
| % nft add rule t c iifname '"*"'
|
||||
| nft: expression.c:402: constant_expr_alloc: Assertion `(((len) + (8) - 1) / (8)) > 0' failed.
|
||||
| zsh: abort nft add rule t c iifname '"*"'
|
||||
|
||||
Fix this by detecting the string in expr_evaluate_string() and returning
|
||||
an error message:
|
||||
|
||||
| % nft add rule t c iifname '"*"'
|
||||
| Error: All-wildcard strings are not supported
|
||||
| add rule t c iifname "*"
|
||||
| ^^^
|
||||
|
||||
While being at it, drop the 'datalen >= 1' clause from the following
|
||||
conditional as together with the added check for 'datalen == 0', all
|
||||
possible other values have been caught already.
|
||||
---
|
||||
src/evaluate.c | 7 +++++--
|
||||
1 file changed, 5 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/evaluate.c b/src/evaluate.c
|
||||
index a966ed4..0181750 100644
|
||||
--- a/src/evaluate.c
|
||||
+++ b/src/evaluate.c
|
||||
@@ -321,8 +321,11 @@ static int expr_evaluate_string(struct eval_ctx *ctx, struct expr **exprp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
- if (datalen >= 1 &&
|
||||
- data[datalen - 1] == '\\') {
|
||||
+ if (datalen == 0)
|
||||
+ return expr_error(ctx->msgs, expr,
|
||||
+ "All-wildcard strings are not supported");
|
||||
+
|
||||
+ if (data[datalen - 1] == '\\') {
|
||||
char unescaped_str[data_len];
|
||||
|
||||
memset(unescaped_str, 0, sizeof(unescaped_str));
|
||||
--
|
||||
1.8.3.1
|
||||
|
64
SOURCES/0046-src-Support-odd-sized-payload-matches.patch
Normal file
64
SOURCES/0046-src-Support-odd-sized-payload-matches.patch
Normal file
@ -0,0 +1,64 @@
|
||||
From 64f34f34acedad6cce70f2dd91c82a814d4ffe34 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Wed, 19 May 2021 18:03:43 +0200
|
||||
Subject: [PATCH] src: Support odd-sized payload matches
|
||||
|
||||
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1934926
|
||||
Upstream Status: nftables commit 8a927c56d83ed
|
||||
|
||||
commit 8a927c56d83ed0f78785011bd92a53edc25a0ca0
|
||||
Author: Phil Sutter <phil@nwl.cc>
|
||||
Date: Tue Oct 27 17:05:25 2020 +0100
|
||||
|
||||
src: Support odd-sized payload matches
|
||||
|
||||
When expanding a payload match, don't disregard oversized templates at
|
||||
the right offset. A more flexible user may extract less bytes from the
|
||||
packet if only parts of a field are interesting, e.g. only the prefix of
|
||||
source/destination address. Support that by using the template, but fix
|
||||
the length. Later when creating a relational expression for it, detect
|
||||
the unusually small payload expression length and turn the RHS value
|
||||
into a prefix expression.
|
||||
|
||||
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||||
---
|
||||
src/netlink_delinearize.c | 6 ++++++
|
||||
src/payload.c | 5 +++++
|
||||
2 files changed, 11 insertions(+)
|
||||
|
||||
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
|
||||
index 88dbd5a..8bdee12 100644
|
||||
--- a/src/netlink_delinearize.c
|
||||
+++ b/src/netlink_delinearize.c
|
||||
@@ -1577,6 +1577,12 @@ static void payload_match_expand(struct rule_pp_ctx *ctx,
|
||||
tmp = constant_expr_splice(right, left->len);
|
||||
expr_set_type(tmp, left->dtype, left->byteorder);
|
||||
|
||||
+ if (left->payload.tmpl && (left->len < left->payload.tmpl->len)) {
|
||||
+ mpz_lshift_ui(tmp->value, left->payload.tmpl->len - left->len);
|
||||
+ tmp->len = left->payload.tmpl->len;
|
||||
+ tmp = prefix_expr_alloc(&tmp->location, tmp, left->len);
|
||||
+ }
|
||||
+
|
||||
nexpr = relational_expr_alloc(&expr->location, expr->op,
|
||||
left, tmp);
|
||||
if (expr->op == OP_EQ)
|
||||
diff --git a/src/payload.c b/src/payload.c
|
||||
index 3576400..45280ef 100644
|
||||
--- a/src/payload.c
|
||||
+++ b/src/payload.c
|
||||
@@ -746,6 +746,11 @@ void payload_expr_expand(struct list_head *list, struct expr *expr,
|
||||
expr->payload.offset += tmpl->len;
|
||||
if (expr->len == 0)
|
||||
return;
|
||||
+ } else if (expr->len > 0) {
|
||||
+ new = payload_expr_alloc(&expr->location, desc, i);
|
||||
+ new->len = expr->len;
|
||||
+ list_add_tail(&new->list, list);
|
||||
+ return;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
--
|
||||
1.8.3.1
|
||||
|
@ -0,0 +1,241 @@
|
||||
From 6fb6d8f15a82b3348184f6950a436becb06931cb Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Wed, 19 May 2021 18:03:43 +0200
|
||||
Subject: [PATCH] src: Optimize prefix matches on byte-boundaries
|
||||
|
||||
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1934926
|
||||
Upstream Status: nftables commit 25338cdb6c77a
|
||||
Conflicts: There is a hidden dependency on commit ee4391d0ac1e7 ("nat:
|
||||
transform range to prefix expression when possible").
|
||||
Backport only the single chunk required to keep prefix
|
||||
parsing intact to avoid having to backport 9599d9d25a6b3
|
||||
("src: NAT support for intervals in maps") as a dependency
|
||||
which is clearly oversized for the sake of this purpose.
|
||||
|
||||
commit 25338cdb6c77aa2f0977afbbb612571c9d325213
|
||||
Author: Phil Sutter <phil@nwl.cc>
|
||||
Date: Tue Oct 27 17:33:15 2020 +0100
|
||||
|
||||
src: Optimize prefix matches on byte-boundaries
|
||||
|
||||
If a prefix expression's length is on a byte-boundary, it is sufficient
|
||||
to just reduce the length passed to "cmp" expression. No need for
|
||||
explicit bitwise modification of data on LHS. The relevant code is
|
||||
already there, used for string prefix matches. There is one exception
|
||||
though, namely zero-length prefixes: Kernel doesn't accept zero-length
|
||||
"cmp" expressions, so keep them in the old code-path for now.
|
||||
|
||||
This patch depends upon the previous one to correctly parse odd-sized
|
||||
payload matches but has to extend support for non-payload LHS as well.
|
||||
In practice, this is needed for "ct" expressions as they allow matching
|
||||
against IP address prefixes, too.
|
||||
|
||||
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||||
---
|
||||
src/netlink_delinearize.c | 8 ++++++--
|
||||
src/netlink_linearize.c | 4 +++-
|
||||
tests/py/ip/ct.t.payload | 4 ----
|
||||
tests/py/ip/ip.t.payload | 6 ++----
|
||||
tests/py/ip/ip.t.payload.bridge | 6 ++----
|
||||
tests/py/ip/ip.t.payload.inet | 6 ++----
|
||||
tests/py/ip/ip.t.payload.netdev | 6 ++----
|
||||
tests/py/ip6/ip6.t.payload.inet | 5 ++---
|
||||
tests/py/ip6/ip6.t.payload.ip6 | 5 ++---
|
||||
9 files changed, 21 insertions(+), 29 deletions(-)
|
||||
|
||||
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
|
||||
index 8bdee12..157a473 100644
|
||||
--- a/src/netlink_delinearize.c
|
||||
+++ b/src/netlink_delinearize.c
|
||||
@@ -291,8 +291,9 @@ static void netlink_parse_cmp(struct netlink_parse_ctx *ctx,
|
||||
|
||||
if (left->len > right->len &&
|
||||
expr_basetype(left) != &string_type) {
|
||||
- netlink_error(ctx, loc, "Relational expression size mismatch");
|
||||
- goto err_free;
|
||||
+ mpz_lshift_ui(right->value, left->len - right->len);
|
||||
+ right = prefix_expr_alloc(loc, right, right->len);
|
||||
+ right->prefix->len = left->len;
|
||||
} else if (left->len > 0 && left->len < right->len) {
|
||||
expr_free(left);
|
||||
left = netlink_parse_concat_expr(ctx, loc, sreg, right->len);
|
||||
@@ -2164,6 +2165,9 @@ static void expr_postprocess(struct rule_pp_ctx *ctx, struct expr **exprp)
|
||||
expr_postprocess(ctx, &expr->left);
|
||||
expr_postprocess(ctx, &expr->right);
|
||||
break;
|
||||
+ case EXPR_PREFIX:
|
||||
+ expr_postprocess(ctx, &expr->prefix);
|
||||
+ break;
|
||||
case EXPR_SET_ELEM:
|
||||
expr_postprocess(ctx, &expr->key);
|
||||
break;
|
||||
diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c
|
||||
index 606d97a..25be634 100644
|
||||
--- a/src/netlink_linearize.c
|
||||
+++ b/src/netlink_linearize.c
|
||||
@@ -501,7 +501,9 @@ static void netlink_gen_relational(struct netlink_linearize_ctx *ctx,
|
||||
return netlink_gen_flagcmp(ctx, expr, dreg);
|
||||
case EXPR_PREFIX:
|
||||
sreg = get_register(ctx, expr->left);
|
||||
- if (expr_basetype(expr->left)->type != TYPE_STRING) {
|
||||
+ if (expr_basetype(expr->left)->type != TYPE_STRING &&
|
||||
+ (!expr->right->prefix_len ||
|
||||
+ expr->right->prefix_len % BITS_PER_BYTE)) {
|
||||
len = div_round_up(expr->right->len, BITS_PER_BYTE);
|
||||
netlink_gen_expr(ctx, expr->left, sreg);
|
||||
right = netlink_gen_prefix(ctx, expr, sreg);
|
||||
diff --git a/tests/py/ip/ct.t.payload b/tests/py/ip/ct.t.payload
|
||||
index d5faed4..a7e08f9 100644
|
||||
--- a/tests/py/ip/ct.t.payload
|
||||
+++ b/tests/py/ip/ct.t.payload
|
||||
@@ -21,25 +21,21 @@ ip test-ip4 output
|
||||
# ct original ip saddr 192.168.1.0/24
|
||||
ip test-ip4 output
|
||||
[ ct load src_ip => reg 1 , dir original ]
|
||||
- [ bitwise reg 1 = (reg=1 & 0x00ffffff ) ^ 0x00000000 ]
|
||||
[ cmp eq reg 1 0x0001a8c0 ]
|
||||
|
||||
# ct reply ip saddr 192.168.1.0/24
|
||||
ip test-ip4 output
|
||||
[ ct load src_ip => reg 1 , dir reply ]
|
||||
- [ bitwise reg 1 = (reg=1 & 0x00ffffff ) ^ 0x00000000 ]
|
||||
[ cmp eq reg 1 0x0001a8c0 ]
|
||||
|
||||
# ct original ip daddr 192.168.1.0/24
|
||||
ip test-ip4 output
|
||||
[ ct load dst_ip => reg 1 , dir original ]
|
||||
- [ bitwise reg 1 = (reg=1 & 0x00ffffff ) ^ 0x00000000 ]
|
||||
[ cmp eq reg 1 0x0001a8c0 ]
|
||||
|
||||
# ct reply ip daddr 192.168.1.0/24
|
||||
ip test-ip4 output
|
||||
[ ct load dst_ip => reg 1 , dir reply ]
|
||||
- [ bitwise reg 1 = (reg=1 & 0x00ffffff ) ^ 0x00000000 ]
|
||||
[ cmp eq reg 1 0x0001a8c0 ]
|
||||
|
||||
# ct l3proto ipv4
|
||||
diff --git a/tests/py/ip/ip.t.payload b/tests/py/ip/ip.t.payload
|
||||
index d627b22..825c0f0 100644
|
||||
--- a/tests/py/ip/ip.t.payload
|
||||
+++ b/tests/py/ip/ip.t.payload
|
||||
@@ -358,14 +358,12 @@ ip test-ip4 input
|
||||
|
||||
# ip saddr 192.168.2.0/24
|
||||
ip test-ip4 input
|
||||
- [ payload load 4b @ network header + 12 => reg 1 ]
|
||||
- [ bitwise reg 1 = (reg=1 & 0x00ffffff ) ^ 0x00000000 ]
|
||||
+ [ payload load 3b @ network header + 12 => reg 1 ]
|
||||
[ cmp eq reg 1 0x0002a8c0 ]
|
||||
|
||||
# ip saddr != 192.168.2.0/24
|
||||
ip test-ip4 input
|
||||
- [ payload load 4b @ network header + 12 => reg 1 ]
|
||||
- [ bitwise reg 1 = (reg=1 & 0x00ffffff ) ^ 0x00000000 ]
|
||||
+ [ payload load 3b @ network header + 12 => reg 1 ]
|
||||
[ cmp neq reg 1 0x0002a8c0 ]
|
||||
|
||||
# ip saddr 192.168.3.1 ip daddr 192.168.3.100
|
||||
diff --git a/tests/py/ip/ip.t.payload.bridge b/tests/py/ip/ip.t.payload.bridge
|
||||
index 91a4fde..e958a5b 100644
|
||||
--- a/tests/py/ip/ip.t.payload.bridge
|
||||
+++ b/tests/py/ip/ip.t.payload.bridge
|
||||
@@ -466,16 +466,14 @@ bridge test-bridge input
|
||||
bridge test-bridge input
|
||||
[ meta load protocol => reg 1 ]
|
||||
[ cmp eq reg 1 0x00000008 ]
|
||||
- [ payload load 4b @ network header + 12 => reg 1 ]
|
||||
- [ bitwise reg 1 = (reg=1 & 0x00ffffff ) ^ 0x00000000 ]
|
||||
+ [ payload load 3b @ network header + 12 => reg 1 ]
|
||||
[ cmp eq reg 1 0x0002a8c0 ]
|
||||
|
||||
# ip saddr != 192.168.2.0/24
|
||||
bridge test-bridge input
|
||||
[ meta load protocol => reg 1 ]
|
||||
[ cmp eq reg 1 0x00000008 ]
|
||||
- [ payload load 4b @ network header + 12 => reg 1 ]
|
||||
- [ bitwise reg 1 = (reg=1 & 0x00ffffff ) ^ 0x00000000 ]
|
||||
+ [ payload load 3b @ network header + 12 => reg 1 ]
|
||||
[ cmp neq reg 1 0x0002a8c0 ]
|
||||
|
||||
# ip saddr 192.168.3.1 ip daddr 192.168.3.100
|
||||
diff --git a/tests/py/ip/ip.t.payload.inet b/tests/py/ip/ip.t.payload.inet
|
||||
index b9cb28a..6501473 100644
|
||||
--- a/tests/py/ip/ip.t.payload.inet
|
||||
+++ b/tests/py/ip/ip.t.payload.inet
|
||||
@@ -466,16 +466,14 @@ inet test-inet input
|
||||
inet test-inet input
|
||||
[ meta load nfproto => reg 1 ]
|
||||
[ cmp eq reg 1 0x00000002 ]
|
||||
- [ payload load 4b @ network header + 12 => reg 1 ]
|
||||
- [ bitwise reg 1 = (reg=1 & 0x00ffffff ) ^ 0x00000000 ]
|
||||
+ [ payload load 3b @ network header + 12 => reg 1 ]
|
||||
[ cmp eq reg 1 0x0002a8c0 ]
|
||||
|
||||
# ip saddr != 192.168.2.0/24
|
||||
inet test-inet input
|
||||
[ meta load nfproto => reg 1 ]
|
||||
[ cmp eq reg 1 0x00000002 ]
|
||||
- [ payload load 4b @ network header + 12 => reg 1 ]
|
||||
- [ bitwise reg 1 = (reg=1 & 0x00ffffff ) ^ 0x00000000 ]
|
||||
+ [ payload load 3b @ network header + 12 => reg 1 ]
|
||||
[ cmp neq reg 1 0x0002a8c0 ]
|
||||
|
||||
# ip saddr 192.168.3.1 ip daddr 192.168.3.100
|
||||
diff --git a/tests/py/ip/ip.t.payload.netdev b/tests/py/ip/ip.t.payload.netdev
|
||||
index 588e5ca..58ae358 100644
|
||||
--- a/tests/py/ip/ip.t.payload.netdev
|
||||
+++ b/tests/py/ip/ip.t.payload.netdev
|
||||
@@ -379,16 +379,14 @@ netdev test-netdev ingress
|
||||
netdev test-netdev ingress
|
||||
[ meta load protocol => reg 1 ]
|
||||
[ cmp eq reg 1 0x00000008 ]
|
||||
- [ payload load 4b @ network header + 12 => reg 1 ]
|
||||
- [ bitwise reg 1 = (reg=1 & 0x00ffffff ) ^ 0x00000000 ]
|
||||
+ [ payload load 3b @ network header + 12 => reg 1 ]
|
||||
[ cmp eq reg 1 0x0002a8c0 ]
|
||||
|
||||
# ip saddr != 192.168.2.0/24
|
||||
netdev test-netdev ingress
|
||||
[ meta load protocol => reg 1 ]
|
||||
[ cmp eq reg 1 0x00000008 ]
|
||||
- [ payload load 4b @ network header + 12 => reg 1 ]
|
||||
- [ bitwise reg 1 = (reg=1 & 0x00ffffff ) ^ 0x00000000 ]
|
||||
+ [ payload load 3b @ network header + 12 => reg 1 ]
|
||||
[ cmp neq reg 1 0x0002a8c0 ]
|
||||
|
||||
# ip saddr 192.168.3.1 ip daddr 192.168.3.100
|
||||
diff --git a/tests/py/ip6/ip6.t.payload.inet b/tests/py/ip6/ip6.t.payload.inet
|
||||
index d015c8e..ffc9b9f 100644
|
||||
--- a/tests/py/ip6/ip6.t.payload.inet
|
||||
+++ b/tests/py/ip6/ip6.t.payload.inet
|
||||
@@ -604,9 +604,8 @@ inet test-inet input
|
||||
inet test-inet input
|
||||
[ meta load nfproto => reg 1 ]
|
||||
[ cmp eq reg 1 0x0000000a ]
|
||||
- [ payload load 16b @ network header + 8 => reg 1 ]
|
||||
- [ bitwise reg 1 = (reg=1 & 0xffffffff 0xffffffff 0x00000000 0x00000000 ) ^ 0x00000000 0x00000000 0x00000000 0x00000000 ]
|
||||
- [ cmp eq reg 1 0x00000000 0x00000000 0x00000000 0x00000000 ]
|
||||
+ [ payload load 8b @ network header + 8 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000000 0x00000000 ]
|
||||
|
||||
# ip6 saddr ::1 ip6 daddr ::2
|
||||
inet test-inet input
|
||||
diff --git a/tests/py/ip6/ip6.t.payload.ip6 b/tests/py/ip6/ip6.t.payload.ip6
|
||||
index b2e8363..18b8bcb 100644
|
||||
--- a/tests/py/ip6/ip6.t.payload.ip6
|
||||
+++ b/tests/py/ip6/ip6.t.payload.ip6
|
||||
@@ -452,9 +452,8 @@ ip6 test-ip6 input
|
||||
|
||||
# ip6 saddr ::/64
|
||||
ip6 test-ip6 input
|
||||
- [ payload load 16b @ network header + 8 => reg 1 ]
|
||||
- [ bitwise reg 1 = (reg=1 & 0xffffffff 0xffffffff 0x00000000 0x00000000 ) ^ 0x00000000 0x00000000 0x00000000 0x00000000 ]
|
||||
- [ cmp eq reg 1 0x00000000 0x00000000 0x00000000 0x00000000 ]
|
||||
+ [ payload load 8b @ network header + 8 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000000 0x00000000 ]
|
||||
|
||||
# ip6 saddr ::1 ip6 daddr ::2
|
||||
ip6 test-ip6 input
|
||||
--
|
||||
1.8.3.1
|
||||
|
2507
SOURCES/0048-tests-py-Move-tcpopt.t-to-any-directory.patch
Normal file
2507
SOURCES/0048-tests-py-Move-tcpopt.t-to-any-directory.patch
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,294 @@
|
||||
From f87960ecc2ed04c803b27bb6a9c42ecd0ba0bc96 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Mon, 12 Jul 2021 17:44:08 +0200
|
||||
Subject: [PATCH] parser: merge sack-perm/sack-permitted and maxseg/mss
|
||||
|
||||
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1979334
|
||||
Upstream Status: nftables commit 2a9aea6f2dfb6
|
||||
|
||||
commit 2a9aea6f2dfb6ee61528809af98860e06b38762b
|
||||
Author: Florian Westphal <fw@strlen.de>
|
||||
Date: Mon Nov 2 00:27:04 2020 +0100
|
||||
|
||||
parser: merge sack-perm/sack-permitted and maxseg/mss
|
||||
|
||||
One was added by the tcp option parsing ocde, the other by synproxy.
|
||||
|
||||
So we have:
|
||||
synproxy ... sack-perm
|
||||
synproxy ... mss
|
||||
|
||||
and
|
||||
|
||||
tcp option maxseg
|
||||
tcp option sack-permitted
|
||||
|
||||
This kills the extra tokens on the scanner/parser side,
|
||||
so sack-perm and sack-permitted can both be used.
|
||||
|
||||
Likewise, 'synproxy maxseg' and 'tcp option mss size 42' will work too.
|
||||
On the output side, the shorter form is now preferred, i.e. sack-perm
|
||||
and mss.
|
||||
|
||||
Signed-off-by: Florian Westphal <fw@strlen.de>
|
||||
---
|
||||
doc/payload-expression.txt | 8 ++++----
|
||||
src/parser_bison.y | 12 +++++-------
|
||||
src/scanner.l | 8 ++++----
|
||||
src/tcpopt.c | 2 +-
|
||||
tests/py/any/tcpopt.t | 4 ++--
|
||||
tests/py/any/tcpopt.t.json | 8 ++++----
|
||||
tests/py/any/tcpopt.t.payload | 12 ++++++------
|
||||
7 files changed, 26 insertions(+), 28 deletions(-)
|
||||
|
||||
diff --git a/doc/payload-expression.txt b/doc/payload-expression.txt
|
||||
index dba42fd..3d7057c 100644
|
||||
--- a/doc/payload-expression.txt
|
||||
+++ b/doc/payload-expression.txt
|
||||
@@ -525,13 +525,13 @@ nftables currently supports matching (finding) a given ipv6 extension header, TC
|
||||
*dst* {*nexthdr* | *hdrlength*}
|
||||
*mh* {*nexthdr* | *hdrlength* | *checksum* | *type*}
|
||||
*srh* {*flags* | *tag* | *sid* | *seg-left*}
|
||||
-*tcp option* {*eol* | *noop* | *maxseg* | *window* | *sack-permitted* | *sack* | *sack0* | *sack1* | *sack2* | *sack3* | *timestamp*} 'tcp_option_field'
|
||||
+*tcp option* {*eol* | *noop* | *maxseg* | *window* | *sack-perm* | *sack* | *sack0* | *sack1* | *sack2* | *sack3* | *timestamp*} 'tcp_option_field'
|
||||
*ip option* { lsrr | ra | rr | ssrr } 'ip_option_field'
|
||||
|
||||
The following syntaxes are valid only in a relational expression with boolean type on right-hand side for checking header existence only:
|
||||
[verse]
|
||||
*exthdr* {*hbh* | *frag* | *rt* | *dst* | *mh*}
|
||||
-*tcp option* {*eol* | *noop* | *maxseg* | *window* | *sack-permitted* | *sack* | *sack0* | *sack1* | *sack2* | *sack3* | *timestamp*}
|
||||
+*tcp option* {*eol* | *noop* | *maxseg* | *window* | *sack-perm* | *sack* | *sack0* | *sack1* | *sack2* | *sack3* | *timestamp*}
|
||||
*ip option* { lsrr | ra | rr | ssrr }
|
||||
|
||||
.IPv6 extension headers
|
||||
@@ -568,7 +568,7 @@ kind, length, size
|
||||
|window|
|
||||
TCP Window Scaling |
|
||||
kind, length, count
|
||||
-|sack-permitted|
|
||||
+|sack-perm |
|
||||
TCP SACK permitted |
|
||||
kind, length
|
||||
|sack|
|
||||
@@ -611,7 +611,7 @@ type, length, ptr, addr
|
||||
|
||||
.finding TCP options
|
||||
--------------------
|
||||
-filter input tcp option sack-permitted kind 1 counter
|
||||
+filter input tcp option sack-perm kind 1 counter
|
||||
--------------------
|
||||
|
||||
.matching IPv6 exthdr
|
||||
diff --git a/src/parser_bison.y b/src/parser_bison.y
|
||||
index 4cca31b..56d26e3 100644
|
||||
--- a/src/parser_bison.y
|
||||
+++ b/src/parser_bison.y
|
||||
@@ -221,7 +221,6 @@ int nft_lex(void *, void *, void *);
|
||||
%token SYNPROXY "synproxy"
|
||||
%token MSS "mss"
|
||||
%token WSCALE "wscale"
|
||||
-%token SACKPERM "sack-perm"
|
||||
|
||||
%token HOOK "hook"
|
||||
%token DEVICE "device"
|
||||
@@ -385,14 +384,13 @@ int nft_lex(void *, void *, void *);
|
||||
%token OPTION "option"
|
||||
%token ECHO "echo"
|
||||
%token EOL "eol"
|
||||
-%token MAXSEG "maxseg"
|
||||
%token NOOP "noop"
|
||||
%token SACK "sack"
|
||||
%token SACK0 "sack0"
|
||||
%token SACK1 "sack1"
|
||||
%token SACK2 "sack2"
|
||||
%token SACK3 "sack3"
|
||||
-%token SACK_PERMITTED "sack-permitted"
|
||||
+%token SACK_PERM "sack-permitted"
|
||||
%token TIMESTAMP "timestamp"
|
||||
%token KIND "kind"
|
||||
%token COUNT "count"
|
||||
@@ -2889,7 +2887,7 @@ synproxy_arg : MSS NUM
|
||||
{
|
||||
$<stmt>0->synproxy.flags |= NF_SYNPROXY_OPT_TIMESTAMP;
|
||||
}
|
||||
- | SACKPERM
|
||||
+ | SACK_PERM
|
||||
{
|
||||
$<stmt>0->synproxy.flags |= NF_SYNPROXY_OPT_SACK_PERM;
|
||||
}
|
||||
@@ -2944,7 +2942,7 @@ synproxy_ts : /* empty */ { $$ = 0; }
|
||||
;
|
||||
|
||||
synproxy_sack : /* empty */ { $$ = 0; }
|
||||
- | SACKPERM
|
||||
+ | SACK_PERM
|
||||
{
|
||||
$$ = NF_SYNPROXY_OPT_SACK_PERM;
|
||||
}
|
||||
@@ -4736,9 +4734,9 @@ tcp_hdr_field : SPORT { $$ = TCPHDR_SPORT; }
|
||||
|
||||
tcp_hdr_option_type : EOL { $$ = TCPOPTHDR_EOL; }
|
||||
| NOOP { $$ = TCPOPTHDR_NOOP; }
|
||||
- | MAXSEG { $$ = TCPOPTHDR_MAXSEG; }
|
||||
+ | MSS { $$ = TCPOPTHDR_MAXSEG; }
|
||||
| WINDOW { $$ = TCPOPTHDR_WINDOW; }
|
||||
- | SACK_PERMITTED { $$ = TCPOPTHDR_SACK_PERMITTED; }
|
||||
+ | SACK_PERM { $$ = TCPOPTHDR_SACK_PERMITTED; }
|
||||
| SACK { $$ = TCPOPTHDR_SACK0; }
|
||||
| SACK0 { $$ = TCPOPTHDR_SACK0; }
|
||||
| SACK1 { $$ = TCPOPTHDR_SACK1; }
|
||||
diff --git a/src/scanner.l b/src/scanner.l
|
||||
index 7daf5c1..a369802 100644
|
||||
--- a/src/scanner.l
|
||||
+++ b/src/scanner.l
|
||||
@@ -419,14 +419,16 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr})
|
||||
|
||||
"echo" { return ECHO; }
|
||||
"eol" { return EOL; }
|
||||
-"maxseg" { return MAXSEG; }
|
||||
+"maxseg" { return MSS; }
|
||||
+"mss" { return MSS; }
|
||||
"noop" { return NOOP; }
|
||||
"sack" { return SACK; }
|
||||
"sack0" { return SACK0; }
|
||||
"sack1" { return SACK1; }
|
||||
"sack2" { return SACK2; }
|
||||
"sack3" { return SACK3; }
|
||||
-"sack-permitted" { return SACK_PERMITTED; }
|
||||
+"sack-permitted" { return SACK_PERM; }
|
||||
+"sack-perm" { return SACK_PERM; }
|
||||
"timestamp" { return TIMESTAMP; }
|
||||
"time" { return TIME; }
|
||||
|
||||
@@ -562,9 +564,7 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr})
|
||||
"osf" { return OSF; }
|
||||
|
||||
"synproxy" { return SYNPROXY; }
|
||||
-"mss" { return MSS; }
|
||||
"wscale" { return WSCALE; }
|
||||
-"sack-perm" { return SACKPERM; }
|
||||
|
||||
"notrack" { return NOTRACK; }
|
||||
|
||||
diff --git a/src/tcpopt.c b/src/tcpopt.c
|
||||
index ec305d9..6dbaa9e 100644
|
||||
--- a/src/tcpopt.c
|
||||
+++ b/src/tcpopt.c
|
||||
@@ -55,7 +55,7 @@ static const struct exthdr_desc tcpopt_window = {
|
||||
};
|
||||
|
||||
static const struct exthdr_desc tcpopt_sack_permitted = {
|
||||
- .name = "sack-permitted",
|
||||
+ .name = "sack-perm",
|
||||
.type = TCPOPT_SACK_PERMITTED,
|
||||
.templates = {
|
||||
[TCPOPTHDR_FIELD_KIND] = PHT("kind", 0, 8),
|
||||
diff --git a/tests/py/any/tcpopt.t b/tests/py/any/tcpopt.t
|
||||
index 08b1dcb..5f21d49 100644
|
||||
--- a/tests/py/any/tcpopt.t
|
||||
+++ b/tests/py/any/tcpopt.t
|
||||
@@ -12,8 +12,8 @@ tcp option maxseg size 1;ok
|
||||
tcp option window kind 1;ok
|
||||
tcp option window length 1;ok
|
||||
tcp option window count 1;ok
|
||||
-tcp option sack-permitted kind 1;ok
|
||||
-tcp option sack-permitted length 1;ok
|
||||
+tcp option sack-perm kind 1;ok
|
||||
+tcp option sack-perm length 1;ok
|
||||
tcp option sack kind 1;ok
|
||||
tcp option sack length 1;ok
|
||||
tcp option sack left 1;ok
|
||||
diff --git a/tests/py/any/tcpopt.t.json b/tests/py/any/tcpopt.t.json
|
||||
index 48eb339..2c6236a 100644
|
||||
--- a/tests/py/any/tcpopt.t.json
|
||||
+++ b/tests/py/any/tcpopt.t.json
|
||||
@@ -126,14 +126,14 @@
|
||||
}
|
||||
]
|
||||
|
||||
-# tcp option sack-permitted kind 1
|
||||
+# tcp option sack-perm kind 1
|
||||
[
|
||||
{
|
||||
"match": {
|
||||
"left": {
|
||||
"tcp option": {
|
||||
"field": "kind",
|
||||
- "name": "sack-permitted"
|
||||
+ "name": "sack-perm"
|
||||
}
|
||||
},
|
||||
"op": "==",
|
||||
@@ -142,14 +142,14 @@
|
||||
}
|
||||
]
|
||||
|
||||
-# tcp option sack-permitted length 1
|
||||
+# tcp option sack-perm length 1
|
||||
[
|
||||
{
|
||||
"match": {
|
||||
"left": {
|
||||
"tcp option": {
|
||||
"field": "length",
|
||||
- "name": "sack-permitted"
|
||||
+ "name": "sack-perm"
|
||||
}
|
||||
},
|
||||
"op": "==",
|
||||
diff --git a/tests/py/any/tcpopt.t.payload b/tests/py/any/tcpopt.t.payload
|
||||
index 63751cf..f63076a 100644
|
||||
--- a/tests/py/any/tcpopt.t.payload
|
||||
+++ b/tests/py/any/tcpopt.t.payload
|
||||
@@ -166,42 +166,42 @@ inet
|
||||
[ exthdr load tcpopt 1b @ 3 + 2 => reg 1 ]
|
||||
[ cmp eq reg 1 0x00000001 ]
|
||||
|
||||
-# tcp option sack-permitted kind 1
|
||||
+# tcp option sack-perm kind 1
|
||||
ip
|
||||
[ meta load l4proto => reg 1 ]
|
||||
[ cmp eq reg 1 0x00000006 ]
|
||||
[ exthdr load tcpopt 1b @ 4 + 0 => reg 1 ]
|
||||
[ cmp eq reg 1 0x00000001 ]
|
||||
|
||||
-# tcp option sack-permitted kind 1
|
||||
+# tcp option sack-perm kind 1
|
||||
ip6
|
||||
[ meta load l4proto => reg 1 ]
|
||||
[ cmp eq reg 1 0x00000006 ]
|
||||
[ exthdr load tcpopt 1b @ 4 + 0 => reg 1 ]
|
||||
[ cmp eq reg 1 0x00000001 ]
|
||||
|
||||
-# tcp option sack-permitted kind 1
|
||||
+# tcp option sack-perm kind 1
|
||||
inet
|
||||
[ meta load l4proto => reg 1 ]
|
||||
[ cmp eq reg 1 0x00000006 ]
|
||||
[ exthdr load tcpopt 1b @ 4 + 0 => reg 1 ]
|
||||
[ cmp eq reg 1 0x00000001 ]
|
||||
|
||||
-# tcp option sack-permitted length 1
|
||||
+# tcp option sack-perm length 1
|
||||
ip
|
||||
[ meta load l4proto => reg 1 ]
|
||||
[ cmp eq reg 1 0x00000006 ]
|
||||
[ exthdr load tcpopt 1b @ 4 + 1 => reg 1 ]
|
||||
[ cmp eq reg 1 0x00000001 ]
|
||||
|
||||
-# tcp option sack-permitted length 1
|
||||
+# tcp option sack-perm length 1
|
||||
ip6
|
||||
[ meta load l4proto => reg 1 ]
|
||||
[ cmp eq reg 1 0x00000006 ]
|
||||
[ exthdr load tcpopt 1b @ 4 + 1 => reg 1 ]
|
||||
[ cmp eq reg 1 0x00000001 ]
|
||||
|
||||
-# tcp option sack-permitted length 1
|
||||
+# tcp option sack-perm length 1
|
||||
inet
|
||||
[ meta load l4proto => reg 1 ]
|
||||
[ cmp eq reg 1 0x00000006 ]
|
||||
--
|
||||
2.31.1
|
||||
|
387
SOURCES/0050-tcpopts-clean-up-parser-tcpopt.c-plumbing.patch
Normal file
387
SOURCES/0050-tcpopts-clean-up-parser-tcpopt.c-plumbing.patch
Normal file
@ -0,0 +1,387 @@
|
||||
From 0aa694acf7c233f9426e48d0644b29ddec4fb16d Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Mon, 12 Jul 2021 17:44:08 +0200
|
||||
Subject: [PATCH] tcpopts: clean up parser -> tcpopt.c plumbing
|
||||
|
||||
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1979334
|
||||
Upstream Status: nftables commit 41158e0388ac5
|
||||
|
||||
commit 41158e0388ac56380fc0ee301f0d43f95ec43fab
|
||||
Author: Florian Westphal <fw@strlen.de>
|
||||
Date: Mon Nov 2 14:53:26 2020 +0100
|
||||
|
||||
tcpopts: clean up parser -> tcpopt.c plumbing
|
||||
|
||||
tcpopt template mapping is asymmetric:
|
||||
one mapping is to match dumped netlink exthdr expression to the original
|
||||
tcp option template.
|
||||
|
||||
This struct is indexed by the raw, on-write kind/type number.
|
||||
|
||||
The other mapping maps parsed options to the tcp option template.
|
||||
Remove the latter. The parser is changed to translate the textual
|
||||
option name, e.g. "maxseg" to the on-wire number.
|
||||
|
||||
This avoids the second mapping, it will also allow to more easily
|
||||
support raw option matching in a followup patch.
|
||||
|
||||
Signed-off-by: Florian Westphal <fw@strlen.de>
|
||||
---
|
||||
doc/payload-expression.txt | 4 +-
|
||||
include/tcpopt.h | 35 ++++++++-------
|
||||
src/parser_bison.y | 26 +++++------
|
||||
src/parser_json.c | 10 ++---
|
||||
src/scanner.l | 3 +-
|
||||
src/tcpopt.c | 92 +++++++++++++++-----------------------
|
||||
6 files changed, 75 insertions(+), 95 deletions(-)
|
||||
|
||||
diff --git a/doc/payload-expression.txt b/doc/payload-expression.txt
|
||||
index 3d7057c..27145c3 100644
|
||||
--- a/doc/payload-expression.txt
|
||||
+++ b/doc/payload-expression.txt
|
||||
@@ -525,13 +525,13 @@ nftables currently supports matching (finding) a given ipv6 extension header, TC
|
||||
*dst* {*nexthdr* | *hdrlength*}
|
||||
*mh* {*nexthdr* | *hdrlength* | *checksum* | *type*}
|
||||
*srh* {*flags* | *tag* | *sid* | *seg-left*}
|
||||
-*tcp option* {*eol* | *noop* | *maxseg* | *window* | *sack-perm* | *sack* | *sack0* | *sack1* | *sack2* | *sack3* | *timestamp*} 'tcp_option_field'
|
||||
+*tcp option* {*eol* | *nop* | *maxseg* | *window* | *sack-perm* | *sack* | *sack0* | *sack1* | *sack2* | *sack3* | *timestamp*} 'tcp_option_field'
|
||||
*ip option* { lsrr | ra | rr | ssrr } 'ip_option_field'
|
||||
|
||||
The following syntaxes are valid only in a relational expression with boolean type on right-hand side for checking header existence only:
|
||||
[verse]
|
||||
*exthdr* {*hbh* | *frag* | *rt* | *dst* | *mh*}
|
||||
-*tcp option* {*eol* | *noop* | *maxseg* | *window* | *sack-perm* | *sack* | *sack0* | *sack1* | *sack2* | *sack3* | *timestamp*}
|
||||
+*tcp option* {*eol* | *nop* | *maxseg* | *window* | *sack-perm* | *sack* | *sack0* | *sack1* | *sack2* | *sack3* | *timestamp*}
|
||||
*ip option* { lsrr | ra | rr | ssrr }
|
||||
|
||||
.IPv6 extension headers
|
||||
diff --git a/include/tcpopt.h b/include/tcpopt.h
|
||||
index ffdbcb0..7f3fbb8 100644
|
||||
--- a/include/tcpopt.h
|
||||
+++ b/include/tcpopt.h
|
||||
@@ -6,7 +6,7 @@
|
||||
#include <statement.h>
|
||||
|
||||
extern struct expr *tcpopt_expr_alloc(const struct location *loc,
|
||||
- uint8_t type, uint8_t field);
|
||||
+ unsigned int kind, unsigned int field);
|
||||
|
||||
extern void tcpopt_init_raw(struct expr *expr, uint8_t type,
|
||||
unsigned int offset, unsigned int len,
|
||||
@@ -15,21 +15,22 @@ extern void tcpopt_init_raw(struct expr *expr, uint8_t type,
|
||||
extern bool tcpopt_find_template(struct expr *expr, const struct expr *mask,
|
||||
unsigned int *shift);
|
||||
|
||||
-enum tcpopt_hdr_types {
|
||||
- TCPOPTHDR_INVALID,
|
||||
- TCPOPTHDR_EOL,
|
||||
- TCPOPTHDR_NOOP,
|
||||
- TCPOPTHDR_MAXSEG,
|
||||
- TCPOPTHDR_WINDOW,
|
||||
- TCPOPTHDR_SACK_PERMITTED,
|
||||
- TCPOPTHDR_SACK0,
|
||||
- TCPOPTHDR_SACK1,
|
||||
- TCPOPTHDR_SACK2,
|
||||
- TCPOPTHDR_SACK3,
|
||||
- TCPOPTHDR_TIMESTAMP,
|
||||
- TCPOPTHDR_ECHO,
|
||||
- TCPOPTHDR_ECHO_REPLY,
|
||||
- __TCPOPTHDR_MAX
|
||||
+/* TCP option numbers used on wire */
|
||||
+enum tcpopt_kind {
|
||||
+ TCPOPT_KIND_EOL = 0,
|
||||
+ TCPOPT_KIND_NOP = 1,
|
||||
+ TCPOPT_KIND_MAXSEG = 2,
|
||||
+ TCPOPT_KIND_WINDOW = 3,
|
||||
+ TCPOPT_KIND_SACK_PERMITTED = 4,
|
||||
+ TCPOPT_KIND_SACK = 5,
|
||||
+ TCPOPT_KIND_TIMESTAMP = 8,
|
||||
+ TCPOPT_KIND_ECHO = 8,
|
||||
+ __TCPOPT_KIND_MAX,
|
||||
+
|
||||
+ /* extra oob info, internal to nft */
|
||||
+ TCPOPT_KIND_SACK1 = 256,
|
||||
+ TCPOPT_KIND_SACK2 = 257,
|
||||
+ TCPOPT_KIND_SACK3 = 258,
|
||||
};
|
||||
|
||||
enum tcpopt_hdr_fields {
|
||||
@@ -44,6 +45,6 @@ enum tcpopt_hdr_fields {
|
||||
TCPOPTHDR_FIELD_TSECR,
|
||||
};
|
||||
|
||||
-extern const struct exthdr_desc *tcpopthdr_protocols[__TCPOPTHDR_MAX];
|
||||
+extern const struct exthdr_desc *tcpopt_protocols[__TCPOPT_KIND_MAX];
|
||||
|
||||
#endif /* NFTABLES_TCPOPT_H */
|
||||
diff --git a/src/parser_bison.y b/src/parser_bison.y
|
||||
index 56d26e3..8f77766 100644
|
||||
--- a/src/parser_bison.y
|
||||
+++ b/src/parser_bison.y
|
||||
@@ -384,7 +384,7 @@ int nft_lex(void *, void *, void *);
|
||||
%token OPTION "option"
|
||||
%token ECHO "echo"
|
||||
%token EOL "eol"
|
||||
-%token NOOP "noop"
|
||||
+%token NOP "nop"
|
||||
%token SACK "sack"
|
||||
%token SACK0 "sack0"
|
||||
%token SACK1 "sack1"
|
||||
@@ -4732,18 +4732,18 @@ tcp_hdr_field : SPORT { $$ = TCPHDR_SPORT; }
|
||||
| URGPTR { $$ = TCPHDR_URGPTR; }
|
||||
;
|
||||
|
||||
-tcp_hdr_option_type : EOL { $$ = TCPOPTHDR_EOL; }
|
||||
- | NOOP { $$ = TCPOPTHDR_NOOP; }
|
||||
- | MSS { $$ = TCPOPTHDR_MAXSEG; }
|
||||
- | WINDOW { $$ = TCPOPTHDR_WINDOW; }
|
||||
- | SACK_PERM { $$ = TCPOPTHDR_SACK_PERMITTED; }
|
||||
- | SACK { $$ = TCPOPTHDR_SACK0; }
|
||||
- | SACK0 { $$ = TCPOPTHDR_SACK0; }
|
||||
- | SACK1 { $$ = TCPOPTHDR_SACK1; }
|
||||
- | SACK2 { $$ = TCPOPTHDR_SACK2; }
|
||||
- | SACK3 { $$ = TCPOPTHDR_SACK3; }
|
||||
- | ECHO { $$ = TCPOPTHDR_ECHO; }
|
||||
- | TIMESTAMP { $$ = TCPOPTHDR_TIMESTAMP; }
|
||||
+tcp_hdr_option_type : EOL { $$ = TCPOPT_KIND_EOL; }
|
||||
+ | NOP { $$ = TCPOPT_KIND_NOP; }
|
||||
+ | MSS { $$ = TCPOPT_KIND_MAXSEG; }
|
||||
+ | WINDOW { $$ = TCPOPT_KIND_WINDOW; }
|
||||
+ | SACK_PERM { $$ = TCPOPT_KIND_SACK_PERMITTED; }
|
||||
+ | SACK { $$ = TCPOPT_KIND_SACK; }
|
||||
+ | SACK0 { $$ = TCPOPT_KIND_SACK; }
|
||||
+ | SACK1 { $$ = TCPOPT_KIND_SACK1; }
|
||||
+ | SACK2 { $$ = TCPOPT_KIND_SACK2; }
|
||||
+ | SACK3 { $$ = TCPOPT_KIND_SACK3; }
|
||||
+ | ECHO { $$ = TCPOPT_KIND_ECHO; }
|
||||
+ | TIMESTAMP { $$ = TCPOPT_KIND_TIMESTAMP; }
|
||||
;
|
||||
|
||||
tcp_hdr_option_field : KIND { $$ = TCPOPTHDR_FIELD_KIND; }
|
||||
diff --git a/src/parser_json.c b/src/parser_json.c
|
||||
index 662bb4b..44b58a0 100644
|
||||
--- a/src/parser_json.c
|
||||
+++ b/src/parser_json.c
|
||||
@@ -456,9 +456,9 @@ static int json_parse_tcp_option_type(const char *name, int *val)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
- for (i = 0; i < array_size(tcpopthdr_protocols); i++) {
|
||||
- if (tcpopthdr_protocols[i] &&
|
||||
- !strcmp(tcpopthdr_protocols[i]->name, name)) {
|
||||
+ for (i = 0; i < array_size(tcpopt_protocols); i++) {
|
||||
+ if (tcpopt_protocols[i] &&
|
||||
+ !strcmp(tcpopt_protocols[i]->name, name)) {
|
||||
if (val)
|
||||
*val = i;
|
||||
return 0;
|
||||
@@ -467,7 +467,7 @@ static int json_parse_tcp_option_type(const char *name, int *val)
|
||||
/* special case for sack0 - sack3 */
|
||||
if (sscanf(name, "sack%u", &i) == 1 && i < 4) {
|
||||
if (val)
|
||||
- *val = TCPOPTHDR_SACK0 + i;
|
||||
+ *val = TCPOPT_KIND_SACK + i;
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
@@ -476,7 +476,7 @@ static int json_parse_tcp_option_type(const char *name, int *val)
|
||||
static int json_parse_tcp_option_field(int type, const char *name, int *val)
|
||||
{
|
||||
unsigned int i;
|
||||
- const struct exthdr_desc *desc = tcpopthdr_protocols[type];
|
||||
+ const struct exthdr_desc *desc = tcpopt_protocols[type];
|
||||
|
||||
for (i = 0; i < array_size(desc->templates); i++) {
|
||||
if (desc->templates[i].token &&
|
||||
diff --git a/src/scanner.l b/src/scanner.l
|
||||
index a369802..20b1b2d 100644
|
||||
--- a/src/scanner.l
|
||||
+++ b/src/scanner.l
|
||||
@@ -421,7 +421,8 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr})
|
||||
"eol" { return EOL; }
|
||||
"maxseg" { return MSS; }
|
||||
"mss" { return MSS; }
|
||||
-"noop" { return NOOP; }
|
||||
+"nop" { return NOP; }
|
||||
+"noop" { return NOP; }
|
||||
"sack" { return SACK; }
|
||||
"sack0" { return SACK0; }
|
||||
"sack1" { return SACK1; }
|
||||
diff --git a/src/tcpopt.c b/src/tcpopt.c
|
||||
index 6dbaa9e..8d5bdec 100644
|
||||
--- a/src/tcpopt.c
|
||||
+++ b/src/tcpopt.c
|
||||
@@ -20,7 +20,7 @@ static const struct proto_hdr_template tcpopt_unknown_template =
|
||||
__offset, __len)
|
||||
static const struct exthdr_desc tcpopt_eol = {
|
||||
.name = "eol",
|
||||
- .type = TCPOPT_EOL,
|
||||
+ .type = TCPOPT_KIND_EOL,
|
||||
.templates = {
|
||||
[TCPOPTHDR_FIELD_KIND] = PHT("kind", 0, 8),
|
||||
},
|
||||
@@ -28,7 +28,7 @@ static const struct exthdr_desc tcpopt_eol = {
|
||||
|
||||
static const struct exthdr_desc tcpopt_nop = {
|
||||
.name = "noop",
|
||||
- .type = TCPOPT_NOP,
|
||||
+ .type = TCPOPT_KIND_NOP,
|
||||
.templates = {
|
||||
[TCPOPTHDR_FIELD_KIND] = PHT("kind", 0, 8),
|
||||
},
|
||||
@@ -36,7 +36,7 @@ static const struct exthdr_desc tcpopt_nop = {
|
||||
|
||||
static const struct exthdr_desc tcptopt_maxseg = {
|
||||
.name = "maxseg",
|
||||
- .type = TCPOPT_MAXSEG,
|
||||
+ .type = TCPOPT_KIND_MAXSEG,
|
||||
.templates = {
|
||||
[TCPOPTHDR_FIELD_KIND] = PHT("kind", 0, 8),
|
||||
[TCPOPTHDR_FIELD_LENGTH] = PHT("length", 8, 8),
|
||||
@@ -46,7 +46,7 @@ static const struct exthdr_desc tcptopt_maxseg = {
|
||||
|
||||
static const struct exthdr_desc tcpopt_window = {
|
||||
.name = "window",
|
||||
- .type = TCPOPT_WINDOW,
|
||||
+ .type = TCPOPT_KIND_WINDOW,
|
||||
.templates = {
|
||||
[TCPOPTHDR_FIELD_KIND] = PHT("kind", 0, 8),
|
||||
[TCPOPTHDR_FIELD_LENGTH] = PHT("length", 8, 8),
|
||||
@@ -56,7 +56,7 @@ static const struct exthdr_desc tcpopt_window = {
|
||||
|
||||
static const struct exthdr_desc tcpopt_sack_permitted = {
|
||||
.name = "sack-perm",
|
||||
- .type = TCPOPT_SACK_PERMITTED,
|
||||
+ .type = TCPOPT_KIND_SACK_PERMITTED,
|
||||
.templates = {
|
||||
[TCPOPTHDR_FIELD_KIND] = PHT("kind", 0, 8),
|
||||
[TCPOPTHDR_FIELD_LENGTH] = PHT("length", 8, 8),
|
||||
@@ -65,7 +65,7 @@ static const struct exthdr_desc tcpopt_sack_permitted = {
|
||||
|
||||
static const struct exthdr_desc tcpopt_sack = {
|
||||
.name = "sack",
|
||||
- .type = TCPOPT_SACK,
|
||||
+ .type = TCPOPT_KIND_SACK,
|
||||
.templates = {
|
||||
[TCPOPTHDR_FIELD_KIND] = PHT("kind", 0, 8),
|
||||
[TCPOPTHDR_FIELD_LENGTH] = PHT("length", 8, 8),
|
||||
@@ -76,7 +76,7 @@ static const struct exthdr_desc tcpopt_sack = {
|
||||
|
||||
static const struct exthdr_desc tcpopt_timestamp = {
|
||||
.name = "timestamp",
|
||||
- .type = TCPOPT_TIMESTAMP,
|
||||
+ .type = TCPOPT_KIND_TIMESTAMP,
|
||||
.templates = {
|
||||
[TCPOPTHDR_FIELD_KIND] = PHT("kind", 0, 8),
|
||||
[TCPOPTHDR_FIELD_LENGTH] = PHT("length", 8, 8),
|
||||
@@ -86,19 +86,14 @@ static const struct exthdr_desc tcpopt_timestamp = {
|
||||
};
|
||||
#undef PHT
|
||||
|
||||
-#define TCPOPT_OBSOLETE ((struct exthdr_desc *)NULL)
|
||||
-#define TCPOPT_ECHO 6
|
||||
-#define TCPOPT_ECHO_REPLY 7
|
||||
-static const struct exthdr_desc *tcpopt_protocols[] = {
|
||||
- [TCPOPT_EOL] = &tcpopt_eol,
|
||||
- [TCPOPT_NOP] = &tcpopt_nop,
|
||||
- [TCPOPT_MAXSEG] = &tcptopt_maxseg,
|
||||
- [TCPOPT_WINDOW] = &tcpopt_window,
|
||||
- [TCPOPT_SACK_PERMITTED] = &tcpopt_sack_permitted,
|
||||
- [TCPOPT_SACK] = &tcpopt_sack,
|
||||
- [TCPOPT_ECHO] = TCPOPT_OBSOLETE,
|
||||
- [TCPOPT_ECHO_REPLY] = TCPOPT_OBSOLETE,
|
||||
- [TCPOPT_TIMESTAMP] = &tcpopt_timestamp,
|
||||
+const struct exthdr_desc *tcpopt_protocols[] = {
|
||||
+ [TCPOPT_KIND_EOL] = &tcpopt_eol,
|
||||
+ [TCPOPT_KIND_NOP] = &tcpopt_nop,
|
||||
+ [TCPOPT_KIND_MAXSEG] = &tcptopt_maxseg,
|
||||
+ [TCPOPT_KIND_WINDOW] = &tcpopt_window,
|
||||
+ [TCPOPT_KIND_SACK_PERMITTED] = &tcpopt_sack_permitted,
|
||||
+ [TCPOPT_KIND_SACK] = &tcpopt_sack,
|
||||
+ [TCPOPT_KIND_TIMESTAMP] = &tcpopt_timestamp,
|
||||
};
|
||||
|
||||
static unsigned int calc_offset(const struct exthdr_desc *desc,
|
||||
@@ -136,51 +131,34 @@ static unsigned int calc_offset_reverse(const struct exthdr_desc *desc,
|
||||
}
|
||||
}
|
||||
|
||||
-const struct exthdr_desc *tcpopthdr_protocols[__TCPOPTHDR_MAX] = {
|
||||
- [TCPOPTHDR_EOL] = &tcpopt_eol,
|
||||
- [TCPOPTHDR_NOOP] = &tcpopt_nop,
|
||||
- [TCPOPTHDR_MAXSEG] = &tcptopt_maxseg,
|
||||
- [TCPOPTHDR_WINDOW] = &tcpopt_window,
|
||||
- [TCPOPTHDR_SACK_PERMITTED] = &tcpopt_sack_permitted,
|
||||
- [TCPOPTHDR_SACK0] = &tcpopt_sack,
|
||||
- [TCPOPTHDR_SACK1] = &tcpopt_sack,
|
||||
- [TCPOPTHDR_SACK2] = &tcpopt_sack,
|
||||
- [TCPOPTHDR_SACK3] = &tcpopt_sack,
|
||||
- [TCPOPTHDR_ECHO] = TCPOPT_OBSOLETE,
|
||||
- [TCPOPTHDR_ECHO_REPLY] = TCPOPT_OBSOLETE,
|
||||
- [TCPOPTHDR_TIMESTAMP] = &tcpopt_timestamp,
|
||||
-};
|
||||
-
|
||||
-static uint8_t tcpopt_optnum[] = {
|
||||
- [TCPOPTHDR_SACK0] = 0,
|
||||
- [TCPOPTHDR_SACK1] = 1,
|
||||
- [TCPOPTHDR_SACK2] = 2,
|
||||
- [TCPOPTHDR_SACK3] = 3,
|
||||
-};
|
||||
-
|
||||
-static uint8_t tcpopt_find_optnum(uint8_t optnum)
|
||||
-{
|
||||
- if (optnum > TCPOPTHDR_SACK3)
|
||||
- return 0;
|
||||
-
|
||||
- return tcpopt_optnum[optnum];
|
||||
-}
|
||||
-
|
||||
-struct expr *tcpopt_expr_alloc(const struct location *loc, uint8_t type,
|
||||
- uint8_t field)
|
||||
+struct expr *tcpopt_expr_alloc(const struct location *loc,
|
||||
+ unsigned int kind,
|
||||
+ unsigned int field)
|
||||
{
|
||||
const struct proto_hdr_template *tmpl;
|
||||
const struct exthdr_desc *desc;
|
||||
+ uint8_t optnum = 0;
|
||||
struct expr *expr;
|
||||
- uint8_t optnum;
|
||||
|
||||
- desc = tcpopthdr_protocols[type];
|
||||
+ switch (kind) {
|
||||
+ case TCPOPT_KIND_SACK1:
|
||||
+ kind = TCPOPT_KIND_SACK;
|
||||
+ optnum = 1;
|
||||
+ break;
|
||||
+ case TCPOPT_KIND_SACK2:
|
||||
+ kind = TCPOPT_KIND_SACK;
|
||||
+ optnum = 2;
|
||||
+ break;
|
||||
+ case TCPOPT_KIND_SACK3:
|
||||
+ kind = TCPOPT_KIND_SACK;
|
||||
+ optnum = 3;
|
||||
+ }
|
||||
+
|
||||
+ desc = tcpopt_protocols[kind];
|
||||
tmpl = &desc->templates[field];
|
||||
if (!tmpl)
|
||||
return NULL;
|
||||
|
||||
- optnum = tcpopt_find_optnum(type);
|
||||
-
|
||||
expr = expr_alloc(loc, EXPR_EXTHDR, tmpl->dtype,
|
||||
BYTEORDER_BIG_ENDIAN, tmpl->len);
|
||||
expr->exthdr.desc = desc;
|
||||
@@ -206,7 +184,7 @@ void tcpopt_init_raw(struct expr *expr, uint8_t type, unsigned int offset,
|
||||
assert(type < array_size(tcpopt_protocols));
|
||||
expr->exthdr.desc = tcpopt_protocols[type];
|
||||
expr->exthdr.flags = flags;
|
||||
- assert(expr->exthdr.desc != TCPOPT_OBSOLETE);
|
||||
+ assert(expr->exthdr.desc != NULL);
|
||||
|
||||
for (i = 0; i < array_size(expr->exthdr.desc->templates); ++i) {
|
||||
tmpl = &expr->exthdr.desc->templates[i];
|
||||
--
|
||||
2.31.1
|
||||
|
118
SOURCES/0051-tcpopt-rename-noop-to-nop.patch
Normal file
118
SOURCES/0051-tcpopt-rename-noop-to-nop.patch
Normal file
@ -0,0 +1,118 @@
|
||||
From f4476f9428a79c5d6d8fe284f0da91c2d4177e66 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Mon, 12 Jul 2021 17:44:08 +0200
|
||||
Subject: [PATCH] tcpopt: rename noop to nop
|
||||
|
||||
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1979334
|
||||
Upstream Status: nftables commit 8f591eba561ac
|
||||
|
||||
commit 8f591eba561aceeef605283c693b659a708d1cd3
|
||||
Author: Florian Westphal <fw@strlen.de>
|
||||
Date: Mon Nov 2 14:58:41 2020 +0100
|
||||
|
||||
tcpopt: rename noop to nop
|
||||
|
||||
'nop' is the tcp padding "option". "noop" is retained for compatibility
|
||||
on parser side.
|
||||
|
||||
Signed-off-by: Florian Westphal <fw@strlen.de>
|
||||
---
|
||||
doc/payload-expression.txt | 4 ++--
|
||||
src/tcpopt.c | 2 +-
|
||||
tests/py/any/tcpopt.t | 2 +-
|
||||
tests/py/any/tcpopt.t.json | 4 ++--
|
||||
tests/py/any/tcpopt.t.payload | 16 +---------------
|
||||
5 files changed, 7 insertions(+), 21 deletions(-)
|
||||
|
||||
diff --git a/doc/payload-expression.txt b/doc/payload-expression.txt
|
||||
index 27145c3..3a07321 100644
|
||||
--- a/doc/payload-expression.txt
|
||||
+++ b/doc/payload-expression.txt
|
||||
@@ -559,8 +559,8 @@ Segment Routing Header
|
||||
|eol|
|
||||
End if option list|
|
||||
kind
|
||||
-|noop|
|
||||
-1 Byte TCP No-op options |
|
||||
+|nop|
|
||||
+1 Byte TCP Nop padding option |
|
||||
kind
|
||||
|maxseg|
|
||||
TCP Maximum Segment Size|
|
||||
diff --git a/src/tcpopt.c b/src/tcpopt.c
|
||||
index 8d5bdec..17cb580 100644
|
||||
--- a/src/tcpopt.c
|
||||
+++ b/src/tcpopt.c
|
||||
@@ -27,7 +27,7 @@ static const struct exthdr_desc tcpopt_eol = {
|
||||
};
|
||||
|
||||
static const struct exthdr_desc tcpopt_nop = {
|
||||
- .name = "noop",
|
||||
+ .name = "nop",
|
||||
.type = TCPOPT_KIND_NOP,
|
||||
.templates = {
|
||||
[TCPOPTHDR_FIELD_KIND] = PHT("kind", 0, 8),
|
||||
diff --git a/tests/py/any/tcpopt.t b/tests/py/any/tcpopt.t
|
||||
index 5f21d49..1d42de8 100644
|
||||
--- a/tests/py/any/tcpopt.t
|
||||
+++ b/tests/py/any/tcpopt.t
|
||||
@@ -5,7 +5,7 @@
|
||||
*inet;test-inet;input
|
||||
|
||||
tcp option eol kind 1;ok
|
||||
-tcp option noop kind 1;ok
|
||||
+tcp option nop kind 1;ok
|
||||
tcp option maxseg kind 1;ok
|
||||
tcp option maxseg length 1;ok
|
||||
tcp option maxseg size 1;ok
|
||||
diff --git a/tests/py/any/tcpopt.t.json b/tests/py/any/tcpopt.t.json
|
||||
index 2c6236a..b15e36e 100644
|
||||
--- a/tests/py/any/tcpopt.t.json
|
||||
+++ b/tests/py/any/tcpopt.t.json
|
||||
@@ -14,14 +14,14 @@
|
||||
}
|
||||
]
|
||||
|
||||
-# tcp option noop kind 1
|
||||
+# tcp option nop kind 1
|
||||
[
|
||||
{
|
||||
"match": {
|
||||
"left": {
|
||||
"tcp option": {
|
||||
"field": "kind",
|
||||
- "name": "noop"
|
||||
+ "name": "nop"
|
||||
}
|
||||
},
|
||||
"op": "==",
|
||||
diff --git a/tests/py/any/tcpopt.t.payload b/tests/py/any/tcpopt.t.payload
|
||||
index f63076a..9c480c8 100644
|
||||
--- a/tests/py/any/tcpopt.t.payload
|
||||
+++ b/tests/py/any/tcpopt.t.payload
|
||||
@@ -19,21 +19,7 @@ inet
|
||||
[ exthdr load tcpopt 1b @ 0 + 0 => reg 1 ]
|
||||
[ cmp eq reg 1 0x00000001 ]
|
||||
|
||||
-# tcp option noop kind 1
|
||||
-ip
|
||||
- [ meta load l4proto => reg 1 ]
|
||||
- [ cmp eq reg 1 0x00000006 ]
|
||||
- [ exthdr load tcpopt 1b @ 1 + 0 => reg 1 ]
|
||||
- [ cmp eq reg 1 0x00000001 ]
|
||||
-
|
||||
-# tcp option noop kind 1
|
||||
-ip6
|
||||
- [ meta load l4proto => reg 1 ]
|
||||
- [ cmp eq reg 1 0x00000006 ]
|
||||
- [ exthdr load tcpopt 1b @ 1 + 0 => reg 1 ]
|
||||
- [ cmp eq reg 1 0x00000001 ]
|
||||
-
|
||||
-# tcp option noop kind 1
|
||||
+# tcp option nop kind 1
|
||||
inet
|
||||
[ meta load l4proto => reg 1 ]
|
||||
[ cmp eq reg 1 0x00000006 ]
|
||||
--
|
||||
2.31.1
|
||||
|
@ -0,0 +1,538 @@
|
||||
From 9697436145bf374093dc61e3ad857f7122de08ee Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Mon, 12 Jul 2021 17:44:08 +0200
|
||||
Subject: [PATCH] tcpopt: split tcpopt_hdr_fields into per-option enum
|
||||
|
||||
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1979334
|
||||
Upstream Status: nftables commit 2e1f821d713aa
|
||||
|
||||
commit 2e1f821d713aa44717b38901ee80cac8e2aa0335
|
||||
Author: Florian Westphal <fw@strlen.de>
|
||||
Date: Mon Nov 2 15:22:40 2020 +0100
|
||||
|
||||
tcpopt: split tcpopt_hdr_fields into per-option enum
|
||||
|
||||
Currently we're limited to ten template fields in exthdr_desc struct.
|
||||
Using a single enum for all tpc option fields thus won't work
|
||||
indefinitely (TCPOPTHDR_FIELD_TSECR is 9) when new option templates get
|
||||
added.
|
||||
|
||||
Fortunately we can just use one enum per tcp option to avoid this.
|
||||
As a side effect this also allows to simplify the sack offset
|
||||
calculations. Rather than computing that on-the-fly, just add extra
|
||||
fields to the SACK template.
|
||||
|
||||
expr->exthdr.offset now holds the 'raw' value, filled in from the option
|
||||
template. This would ease implementation of 'raw option matching'
|
||||
using offset and length to load from the option.
|
||||
|
||||
Signed-off-by: Florian Westphal <fw@strlen.de>
|
||||
---
|
||||
include/tcpopt.h | 46 +++++++++++----
|
||||
src/evaluate.c | 16 ++---
|
||||
src/exthdr.c | 1 +
|
||||
src/ipopt.c | 2 +-
|
||||
src/netlink_delinearize.c | 2 +-
|
||||
src/netlink_linearize.c | 4 +-
|
||||
src/parser_bison.y | 18 +++---
|
||||
src/parser_json.c | 36 ++++++++++--
|
||||
src/tcpopt.c | 119 ++++++++++++++++----------------------
|
||||
9 files changed, 139 insertions(+), 105 deletions(-)
|
||||
|
||||
diff --git a/include/tcpopt.h b/include/tcpopt.h
|
||||
index 7f3fbb8..667c8a7 100644
|
||||
--- a/include/tcpopt.h
|
||||
+++ b/include/tcpopt.h
|
||||
@@ -33,16 +33,42 @@ enum tcpopt_kind {
|
||||
TCPOPT_KIND_SACK3 = 258,
|
||||
};
|
||||
|
||||
-enum tcpopt_hdr_fields {
|
||||
- TCPOPTHDR_FIELD_INVALID,
|
||||
- TCPOPTHDR_FIELD_KIND,
|
||||
- TCPOPTHDR_FIELD_LENGTH,
|
||||
- TCPOPTHDR_FIELD_SIZE,
|
||||
- TCPOPTHDR_FIELD_COUNT,
|
||||
- TCPOPTHDR_FIELD_LEFT,
|
||||
- TCPOPTHDR_FIELD_RIGHT,
|
||||
- TCPOPTHDR_FIELD_TSVAL,
|
||||
- TCPOPTHDR_FIELD_TSECR,
|
||||
+/* Internal identifiers */
|
||||
+enum tcpopt_common {
|
||||
+ TCPOPT_COMMON_KIND,
|
||||
+ TCPOPT_COMMON_LENGTH,
|
||||
+};
|
||||
+
|
||||
+enum tcpopt_maxseg {
|
||||
+ TCPOPT_MAXSEG_KIND,
|
||||
+ TCPOPT_MAXSEG_LENGTH,
|
||||
+ TCPOPT_MAXSEG_SIZE,
|
||||
+};
|
||||
+
|
||||
+enum tcpopt_timestamp {
|
||||
+ TCPOPT_TS_KIND,
|
||||
+ TCPOPT_TS_LENGTH,
|
||||
+ TCPOPT_TS_TSVAL,
|
||||
+ TCPOPT_TS_TSECR,
|
||||
+};
|
||||
+
|
||||
+enum tcpopt_windowscale {
|
||||
+ TCPOPT_WINDOW_KIND,
|
||||
+ TCPOPT_WINDOW_LENGTH,
|
||||
+ TCPOPT_WINDOW_COUNT,
|
||||
+};
|
||||
+
|
||||
+enum tcpopt_hdr_field_sack {
|
||||
+ TCPOPT_SACK_KIND,
|
||||
+ TCPOPT_SACK_LENGTH,
|
||||
+ TCPOPT_SACK_LEFT,
|
||||
+ TCPOPT_SACK_RIGHT,
|
||||
+ TCPOPT_SACK_LEFT1,
|
||||
+ TCPOPT_SACK_RIGHT1,
|
||||
+ TCPOPT_SACK_LEFT2,
|
||||
+ TCPOPT_SACK_RIGHT2,
|
||||
+ TCPOPT_SACK_LEFT3,
|
||||
+ TCPOPT_SACK_RIGHT3,
|
||||
};
|
||||
|
||||
extern const struct exthdr_desc *tcpopt_protocols[__TCPOPT_KIND_MAX];
|
||||
diff --git a/src/evaluate.c b/src/evaluate.c
|
||||
index 0181750..99a66c2 100644
|
||||
--- a/src/evaluate.c
|
||||
+++ b/src/evaluate.c
|
||||
@@ -474,7 +474,7 @@ static void expr_evaluate_bits(struct eval_ctx *ctx, struct expr **exprp)
|
||||
&extra_len);
|
||||
break;
|
||||
case EXPR_EXTHDR:
|
||||
- shift = expr_offset_shift(expr, expr->exthdr.tmpl->offset,
|
||||
+ shift = expr_offset_shift(expr, expr->exthdr.offset,
|
||||
&extra_len);
|
||||
break;
|
||||
default:
|
||||
@@ -526,18 +526,16 @@ static int __expr_evaluate_exthdr(struct eval_ctx *ctx, struct expr **exprp)
|
||||
if (expr_evaluate_primary(ctx, exprp) < 0)
|
||||
return -1;
|
||||
|
||||
- if (expr->exthdr.tmpl->offset % BITS_PER_BYTE != 0 ||
|
||||
+ if (expr->exthdr.offset % BITS_PER_BYTE != 0 ||
|
||||
expr->len % BITS_PER_BYTE != 0)
|
||||
expr_evaluate_bits(ctx, exprp);
|
||||
|
||||
switch (expr->exthdr.op) {
|
||||
case NFT_EXTHDR_OP_TCPOPT: {
|
||||
static const unsigned int max_tcpoptlen = (15 * 4 - 20) * BITS_PER_BYTE;
|
||||
- unsigned int totlen = 0;
|
||||
+ unsigned int totlen;
|
||||
|
||||
- totlen += expr->exthdr.tmpl->offset;
|
||||
- totlen += expr->exthdr.tmpl->len;
|
||||
- totlen += expr->exthdr.offset;
|
||||
+ totlen = expr->exthdr.tmpl->len + expr->exthdr.offset;
|
||||
|
||||
if (totlen > max_tcpoptlen)
|
||||
return expr_error(ctx->msgs, expr,
|
||||
@@ -547,11 +545,9 @@ static int __expr_evaluate_exthdr(struct eval_ctx *ctx, struct expr **exprp)
|
||||
}
|
||||
case NFT_EXTHDR_OP_IPV4: {
|
||||
static const unsigned int max_ipoptlen = 40 * BITS_PER_BYTE;
|
||||
- unsigned int totlen = 0;
|
||||
+ unsigned int totlen;
|
||||
|
||||
- totlen += expr->exthdr.tmpl->offset;
|
||||
- totlen += expr->exthdr.tmpl->len;
|
||||
- totlen += expr->exthdr.offset;
|
||||
+ totlen = expr->exthdr.offset + expr->exthdr.tmpl->len;
|
||||
|
||||
if (totlen > max_ipoptlen)
|
||||
return expr_error(ctx->msgs, expr,
|
||||
diff --git a/src/exthdr.c b/src/exthdr.c
|
||||
index e1ec6f3..c28213f 100644
|
||||
--- a/src/exthdr.c
|
||||
+++ b/src/exthdr.c
|
||||
@@ -99,6 +99,7 @@ struct expr *exthdr_expr_alloc(const struct location *loc,
|
||||
BYTEORDER_BIG_ENDIAN, tmpl->len);
|
||||
expr->exthdr.desc = desc;
|
||||
expr->exthdr.tmpl = tmpl;
|
||||
+ expr->exthdr.offset = tmpl->offset;
|
||||
return expr;
|
||||
}
|
||||
|
||||
diff --git a/src/ipopt.c b/src/ipopt.c
|
||||
index b3d0279..7ecb8b9 100644
|
||||
--- a/src/ipopt.c
|
||||
+++ b/src/ipopt.c
|
||||
@@ -102,7 +102,7 @@ struct expr *ipopt_expr_alloc(const struct location *loc, uint8_t type,
|
||||
expr->exthdr.desc = desc;
|
||||
expr->exthdr.tmpl = tmpl;
|
||||
expr->exthdr.op = NFT_EXTHDR_OP_IPV4;
|
||||
- expr->exthdr.offset = calc_offset(desc, tmpl, ptr);
|
||||
+ expr->exthdr.offset = tmpl->offset + calc_offset(desc, tmpl, ptr);
|
||||
|
||||
return expr;
|
||||
}
|
||||
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
|
||||
index 157a473..790336a 100644
|
||||
--- a/src/netlink_delinearize.c
|
||||
+++ b/src/netlink_delinearize.c
|
||||
@@ -727,8 +727,8 @@ static void netlink_parse_numgen(struct netlink_parse_ctx *ctx,
|
||||
const struct location *loc,
|
||||
const struct nftnl_expr *nle)
|
||||
{
|
||||
- enum nft_registers dreg;
|
||||
uint32_t type, until, offset;
|
||||
+ enum nft_registers dreg;
|
||||
struct expr *expr;
|
||||
|
||||
type = nftnl_expr_get_u32(nle, NFTNL_EXPR_NG_TYPE);
|
||||
diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c
|
||||
index 25be634..9d1a064 100644
|
||||
--- a/src/netlink_linearize.c
|
||||
+++ b/src/netlink_linearize.c
|
||||
@@ -168,7 +168,7 @@ static void netlink_gen_exthdr(struct netlink_linearize_ctx *ctx,
|
||||
const struct expr *expr,
|
||||
enum nft_registers dreg)
|
||||
{
|
||||
- unsigned int offset = expr->exthdr.tmpl->offset + expr->exthdr.offset;
|
||||
+ unsigned int offset = expr->exthdr.offset;
|
||||
struct nftnl_expr *nle;
|
||||
|
||||
nle = alloc_nft_expr("exthdr");
|
||||
@@ -896,7 +896,7 @@ static void netlink_gen_exthdr_stmt(struct netlink_linearize_ctx *ctx,
|
||||
|
||||
expr = stmt->exthdr.expr;
|
||||
|
||||
- offset = expr->exthdr.tmpl->offset + expr->exthdr.offset;
|
||||
+ offset = expr->exthdr.offset;
|
||||
|
||||
nle = alloc_nft_expr("exthdr");
|
||||
netlink_put_register(nle, NFTNL_EXPR_EXTHDR_SREG, sreg);
|
||||
diff --git a/src/parser_bison.y b/src/parser_bison.y
|
||||
index 8f77766..114b289 100644
|
||||
--- a/src/parser_bison.y
|
||||
+++ b/src/parser_bison.y
|
||||
@@ -4715,7 +4715,7 @@ tcp_hdr_expr : TCP tcp_hdr_field
|
||||
}
|
||||
| TCP OPTION tcp_hdr_option_type
|
||||
{
|
||||
- $$ = tcpopt_expr_alloc(&@$, $3, TCPOPTHDR_FIELD_KIND);
|
||||
+ $$ = tcpopt_expr_alloc(&@$, $3, TCPOPT_COMMON_KIND);
|
||||
$$->exthdr.flags = NFT_EXTHDR_F_PRESENT;
|
||||
}
|
||||
;
|
||||
@@ -4746,14 +4746,14 @@ tcp_hdr_option_type : EOL { $$ = TCPOPT_KIND_EOL; }
|
||||
| TIMESTAMP { $$ = TCPOPT_KIND_TIMESTAMP; }
|
||||
;
|
||||
|
||||
-tcp_hdr_option_field : KIND { $$ = TCPOPTHDR_FIELD_KIND; }
|
||||
- | LENGTH { $$ = TCPOPTHDR_FIELD_LENGTH; }
|
||||
- | SIZE { $$ = TCPOPTHDR_FIELD_SIZE; }
|
||||
- | COUNT { $$ = TCPOPTHDR_FIELD_COUNT; }
|
||||
- | LEFT { $$ = TCPOPTHDR_FIELD_LEFT; }
|
||||
- | RIGHT { $$ = TCPOPTHDR_FIELD_RIGHT; }
|
||||
- | TSVAL { $$ = TCPOPTHDR_FIELD_TSVAL; }
|
||||
- | TSECR { $$ = TCPOPTHDR_FIELD_TSECR; }
|
||||
+tcp_hdr_option_field : KIND { $$ = TCPOPT_COMMON_KIND; }
|
||||
+ | LENGTH { $$ = TCPOPT_COMMON_LENGTH; }
|
||||
+ | SIZE { $$ = TCPOPT_MAXSEG_SIZE; }
|
||||
+ | COUNT { $$ = TCPOPT_WINDOW_COUNT; }
|
||||
+ | LEFT { $$ = TCPOPT_SACK_LEFT; }
|
||||
+ | RIGHT { $$ = TCPOPT_SACK_RIGHT; }
|
||||
+ | TSVAL { $$ = TCPOPT_TS_TSVAL; }
|
||||
+ | TSECR { $$ = TCPOPT_TS_TSECR; }
|
||||
;
|
||||
|
||||
dccp_hdr_expr : DCCP dccp_hdr_field
|
||||
diff --git a/src/parser_json.c b/src/parser_json.c
|
||||
index 44b58a0..ab2375f 100644
|
||||
--- a/src/parser_json.c
|
||||
+++ b/src/parser_json.c
|
||||
@@ -466,8 +466,10 @@ static int json_parse_tcp_option_type(const char *name, int *val)
|
||||
}
|
||||
/* special case for sack0 - sack3 */
|
||||
if (sscanf(name, "sack%u", &i) == 1 && i < 4) {
|
||||
- if (val)
|
||||
- *val = TCPOPT_KIND_SACK + i;
|
||||
+ if (val && i == 0)
|
||||
+ *val = TCPOPT_KIND_SACK;
|
||||
+ else if (val && i > 0)
|
||||
+ *val = TCPOPT_KIND_SACK1 + i - 1;
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
@@ -475,12 +477,38 @@ static int json_parse_tcp_option_type(const char *name, int *val)
|
||||
|
||||
static int json_parse_tcp_option_field(int type, const char *name, int *val)
|
||||
{
|
||||
+ const struct exthdr_desc *desc;
|
||||
+ unsigned int block = 0;
|
||||
unsigned int i;
|
||||
- const struct exthdr_desc *desc = tcpopt_protocols[type];
|
||||
+
|
||||
+ switch (type) {
|
||||
+ case TCPOPT_KIND_SACK1:
|
||||
+ type = TCPOPT_KIND_SACK;
|
||||
+ block = 1;
|
||||
+ break;
|
||||
+ case TCPOPT_KIND_SACK2:
|
||||
+ type = TCPOPT_KIND_SACK;
|
||||
+ block = 2;
|
||||
+ break;
|
||||
+ case TCPOPT_KIND_SACK3:
|
||||
+ type = TCPOPT_KIND_SACK;
|
||||
+ block = 3;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (type < 0 || type >= (int)array_size(tcpopt_protocols))
|
||||
+ return 1;
|
||||
+
|
||||
+ desc = tcpopt_protocols[type];
|
||||
|
||||
for (i = 0; i < array_size(desc->templates); i++) {
|
||||
if (desc->templates[i].token &&
|
||||
!strcmp(desc->templates[i].token, name)) {
|
||||
+ if (block) {
|
||||
+ block--;
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
if (val)
|
||||
*val = i;
|
||||
return 0;
|
||||
@@ -585,7 +613,7 @@ static struct expr *json_parse_tcp_option_expr(struct json_ctx *ctx,
|
||||
|
||||
if (json_unpack(root, "{s:s}", "field", &field)) {
|
||||
expr = tcpopt_expr_alloc(int_loc, descval,
|
||||
- TCPOPTHDR_FIELD_KIND);
|
||||
+ TCPOPT_COMMON_KIND);
|
||||
expr->exthdr.flags = NFT_EXTHDR_F_PRESENT;
|
||||
|
||||
return expr;
|
||||
diff --git a/src/tcpopt.c b/src/tcpopt.c
|
||||
index 17cb580..d1dd13b 100644
|
||||
--- a/src/tcpopt.c
|
||||
+++ b/src/tcpopt.c
|
||||
@@ -22,7 +22,7 @@ static const struct exthdr_desc tcpopt_eol = {
|
||||
.name = "eol",
|
||||
.type = TCPOPT_KIND_EOL,
|
||||
.templates = {
|
||||
- [TCPOPTHDR_FIELD_KIND] = PHT("kind", 0, 8),
|
||||
+ [TCPOPT_COMMON_KIND] = PHT("kind", 0, 8),
|
||||
},
|
||||
};
|
||||
|
||||
@@ -30,7 +30,7 @@ static const struct exthdr_desc tcpopt_nop = {
|
||||
.name = "nop",
|
||||
.type = TCPOPT_KIND_NOP,
|
||||
.templates = {
|
||||
- [TCPOPTHDR_FIELD_KIND] = PHT("kind", 0, 8),
|
||||
+ [TCPOPT_COMMON_KIND] = PHT("kind", 0, 8),
|
||||
},
|
||||
};
|
||||
|
||||
@@ -38,9 +38,9 @@ static const struct exthdr_desc tcptopt_maxseg = {
|
||||
.name = "maxseg",
|
||||
.type = TCPOPT_KIND_MAXSEG,
|
||||
.templates = {
|
||||
- [TCPOPTHDR_FIELD_KIND] = PHT("kind", 0, 8),
|
||||
- [TCPOPTHDR_FIELD_LENGTH] = PHT("length", 8, 8),
|
||||
- [TCPOPTHDR_FIELD_SIZE] = PHT("size", 16, 16),
|
||||
+ [TCPOPT_MAXSEG_KIND] = PHT("kind", 0, 8),
|
||||
+ [TCPOPT_MAXSEG_LENGTH] = PHT("length", 8, 8),
|
||||
+ [TCPOPT_MAXSEG_SIZE] = PHT("size", 16, 16),
|
||||
},
|
||||
};
|
||||
|
||||
@@ -48,9 +48,9 @@ static const struct exthdr_desc tcpopt_window = {
|
||||
.name = "window",
|
||||
.type = TCPOPT_KIND_WINDOW,
|
||||
.templates = {
|
||||
- [TCPOPTHDR_FIELD_KIND] = PHT("kind", 0, 8),
|
||||
- [TCPOPTHDR_FIELD_LENGTH] = PHT("length", 8, 8),
|
||||
- [TCPOPTHDR_FIELD_COUNT] = PHT("count", 16, 8),
|
||||
+ [TCPOPT_WINDOW_KIND] = PHT("kind", 0, 8),
|
||||
+ [TCPOPT_WINDOW_LENGTH] = PHT("length", 8, 8),
|
||||
+ [TCPOPT_WINDOW_COUNT] = PHT("count", 16, 8),
|
||||
},
|
||||
};
|
||||
|
||||
@@ -58,8 +58,8 @@ static const struct exthdr_desc tcpopt_sack_permitted = {
|
||||
.name = "sack-perm",
|
||||
.type = TCPOPT_KIND_SACK_PERMITTED,
|
||||
.templates = {
|
||||
- [TCPOPTHDR_FIELD_KIND] = PHT("kind", 0, 8),
|
||||
- [TCPOPTHDR_FIELD_LENGTH] = PHT("length", 8, 8),
|
||||
+ [TCPOPT_COMMON_KIND] = PHT("kind", 0, 8),
|
||||
+ [TCPOPT_COMMON_LENGTH] = PHT("length", 8, 8),
|
||||
},
|
||||
};
|
||||
|
||||
@@ -67,10 +67,16 @@ static const struct exthdr_desc tcpopt_sack = {
|
||||
.name = "sack",
|
||||
.type = TCPOPT_KIND_SACK,
|
||||
.templates = {
|
||||
- [TCPOPTHDR_FIELD_KIND] = PHT("kind", 0, 8),
|
||||
- [TCPOPTHDR_FIELD_LENGTH] = PHT("length", 8, 8),
|
||||
- [TCPOPTHDR_FIELD_LEFT] = PHT("left", 16, 32),
|
||||
- [TCPOPTHDR_FIELD_RIGHT] = PHT("right", 48, 32),
|
||||
+ [TCPOPT_SACK_KIND] = PHT("kind", 0, 8),
|
||||
+ [TCPOPT_SACK_LENGTH] = PHT("length", 8, 8),
|
||||
+ [TCPOPT_SACK_LEFT] = PHT("left", 16, 32),
|
||||
+ [TCPOPT_SACK_RIGHT] = PHT("right", 48, 32),
|
||||
+ [TCPOPT_SACK_LEFT1] = PHT("left", 80, 32),
|
||||
+ [TCPOPT_SACK_RIGHT1] = PHT("right", 112, 32),
|
||||
+ [TCPOPT_SACK_LEFT2] = PHT("left", 144, 32),
|
||||
+ [TCPOPT_SACK_RIGHT2] = PHT("right", 176, 32),
|
||||
+ [TCPOPT_SACK_LEFT3] = PHT("left", 208, 32),
|
||||
+ [TCPOPT_SACK_RIGHT3] = PHT("right", 240, 32),
|
||||
},
|
||||
};
|
||||
|
||||
@@ -78,12 +84,13 @@ static const struct exthdr_desc tcpopt_timestamp = {
|
||||
.name = "timestamp",
|
||||
.type = TCPOPT_KIND_TIMESTAMP,
|
||||
.templates = {
|
||||
- [TCPOPTHDR_FIELD_KIND] = PHT("kind", 0, 8),
|
||||
- [TCPOPTHDR_FIELD_LENGTH] = PHT("length", 8, 8),
|
||||
- [TCPOPTHDR_FIELD_TSVAL] = PHT("tsval", 16, 32),
|
||||
- [TCPOPTHDR_FIELD_TSECR] = PHT("tsecr", 48, 32),
|
||||
+ [TCPOPT_TS_KIND] = PHT("kind", 0, 8),
|
||||
+ [TCPOPT_TS_LENGTH] = PHT("length", 8, 8),
|
||||
+ [TCPOPT_TS_TSVAL] = PHT("tsval", 16, 32),
|
||||
+ [TCPOPT_TS_TSECR] = PHT("tsecr", 48, 32),
|
||||
},
|
||||
};
|
||||
+
|
||||
#undef PHT
|
||||
|
||||
const struct exthdr_desc *tcpopt_protocols[] = {
|
||||
@@ -96,65 +103,43 @@ const struct exthdr_desc *tcpopt_protocols[] = {
|
||||
[TCPOPT_KIND_TIMESTAMP] = &tcpopt_timestamp,
|
||||
};
|
||||
|
||||
-static unsigned int calc_offset(const struct exthdr_desc *desc,
|
||||
- const struct proto_hdr_template *tmpl,
|
||||
- unsigned int num)
|
||||
-{
|
||||
- if (!desc || tmpl == &tcpopt_unknown_template)
|
||||
- return 0;
|
||||
-
|
||||
- switch (desc->type) {
|
||||
- case TCPOPT_SACK:
|
||||
- /* Make sure, offset calculations only apply to left and right
|
||||
- * fields
|
||||
- */
|
||||
- return (tmpl->offset < 16) ? 0 : num * 64;
|
||||
- default:
|
||||
- return 0;
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-
|
||||
-static unsigned int calc_offset_reverse(const struct exthdr_desc *desc,
|
||||
- const struct proto_hdr_template *tmpl,
|
||||
- unsigned int offset)
|
||||
-{
|
||||
- if (!desc || tmpl == &tcpopt_unknown_template)
|
||||
- return offset;
|
||||
-
|
||||
- switch (desc->type) {
|
||||
- case TCPOPT_SACK:
|
||||
- /* We can safely ignore the first left/right field */
|
||||
- return offset < 80 ? offset : (offset % 64);
|
||||
- default:
|
||||
- return offset;
|
||||
- }
|
||||
-}
|
||||
-
|
||||
struct expr *tcpopt_expr_alloc(const struct location *loc,
|
||||
unsigned int kind,
|
||||
unsigned int field)
|
||||
{
|
||||
const struct proto_hdr_template *tmpl;
|
||||
- const struct exthdr_desc *desc;
|
||||
- uint8_t optnum = 0;
|
||||
+ const struct exthdr_desc *desc = NULL;
|
||||
struct expr *expr;
|
||||
|
||||
switch (kind) {
|
||||
case TCPOPT_KIND_SACK1:
|
||||
kind = TCPOPT_KIND_SACK;
|
||||
- optnum = 1;
|
||||
+ if (field == TCPOPT_SACK_LEFT)
|
||||
+ field = TCPOPT_SACK_LEFT1;
|
||||
+ else if (field == TCPOPT_SACK_RIGHT)
|
||||
+ field = TCPOPT_SACK_RIGHT1;
|
||||
break;
|
||||
case TCPOPT_KIND_SACK2:
|
||||
kind = TCPOPT_KIND_SACK;
|
||||
- optnum = 2;
|
||||
+ if (field == TCPOPT_SACK_LEFT)
|
||||
+ field = TCPOPT_SACK_LEFT2;
|
||||
+ else if (field == TCPOPT_SACK_RIGHT)
|
||||
+ field = TCPOPT_SACK_RIGHT2;
|
||||
break;
|
||||
case TCPOPT_KIND_SACK3:
|
||||
kind = TCPOPT_KIND_SACK;
|
||||
- optnum = 3;
|
||||
+ if (field == TCPOPT_SACK_LEFT)
|
||||
+ field = TCPOPT_SACK_LEFT3;
|
||||
+ else if (field == TCPOPT_SACK_RIGHT)
|
||||
+ field = TCPOPT_SACK_RIGHT3;
|
||||
+ break;
|
||||
}
|
||||
|
||||
- desc = tcpopt_protocols[kind];
|
||||
+ if (kind < array_size(tcpopt_protocols))
|
||||
+ desc = tcpopt_protocols[kind];
|
||||
+
|
||||
+ if (!desc)
|
||||
+ return NULL;
|
||||
tmpl = &desc->templates[field];
|
||||
if (!tmpl)
|
||||
return NULL;
|
||||
@@ -164,34 +149,32 @@ struct expr *tcpopt_expr_alloc(const struct location *loc,
|
||||
expr->exthdr.desc = desc;
|
||||
expr->exthdr.tmpl = tmpl;
|
||||
expr->exthdr.op = NFT_EXTHDR_OP_TCPOPT;
|
||||
- expr->exthdr.offset = calc_offset(desc, tmpl, optnum);
|
||||
+ expr->exthdr.offset = tmpl->offset;
|
||||
|
||||
return expr;
|
||||
}
|
||||
|
||||
-void tcpopt_init_raw(struct expr *expr, uint8_t type, unsigned int offset,
|
||||
+void tcpopt_init_raw(struct expr *expr, uint8_t type, unsigned int off,
|
||||
unsigned int len, uint32_t flags)
|
||||
{
|
||||
const struct proto_hdr_template *tmpl;
|
||||
- unsigned int i, off;
|
||||
+ unsigned int i;
|
||||
|
||||
assert(expr->etype == EXPR_EXTHDR);
|
||||
|
||||
expr->len = len;
|
||||
expr->exthdr.flags = flags;
|
||||
- expr->exthdr.offset = offset;
|
||||
+ expr->exthdr.offset = off;
|
||||
+
|
||||
+ if (type >= array_size(tcpopt_protocols))
|
||||
+ return;
|
||||
|
||||
- assert(type < array_size(tcpopt_protocols));
|
||||
expr->exthdr.desc = tcpopt_protocols[type];
|
||||
expr->exthdr.flags = flags;
|
||||
assert(expr->exthdr.desc != NULL);
|
||||
|
||||
for (i = 0; i < array_size(expr->exthdr.desc->templates); ++i) {
|
||||
tmpl = &expr->exthdr.desc->templates[i];
|
||||
- /* We have to reverse calculate the offset for the sack options
|
||||
- * at this point
|
||||
- */
|
||||
- off = calc_offset_reverse(expr->exthdr.desc, tmpl, offset);
|
||||
if (tmpl->offset != off || tmpl->len != len)
|
||||
continue;
|
||||
|
||||
--
|
||||
2.31.1
|
||||
|
@ -0,0 +1,336 @@
|
||||
From 8a4b6cbf58e965d67b0337ba1736bd3691a49890 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Mon, 12 Jul 2021 17:44:08 +0200
|
||||
Subject: [PATCH] tcpopt: allow to check for presence of any tcp option
|
||||
|
||||
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1979334
|
||||
Upstream Status: nftables commit 24d8da3083422
|
||||
|
||||
commit 24d8da3083422da8336eeed2ee23b2ccf598ba5a
|
||||
Author: Florian Westphal <fw@strlen.de>
|
||||
Date: Wed Oct 21 23:54:17 2020 +0200
|
||||
|
||||
tcpopt: allow to check for presence of any tcp option
|
||||
|
||||
nft currently doesn't allow to check for presence of arbitrary tcp options.
|
||||
Only known options where nft provides a template can be tested for.
|
||||
|
||||
This allows to test for presence of raw protocol values as well.
|
||||
|
||||
Example:
|
||||
|
||||
tcp option 42 exists
|
||||
|
||||
Signed-off-by: Florian Westphal <fw@strlen.de>
|
||||
---
|
||||
include/expression.h | 3 +-
|
||||
src/exthdr.c | 12 ++++++++
|
||||
src/ipopt.c | 1 +
|
||||
src/netlink_linearize.c | 2 +-
|
||||
src/parser_bison.y | 7 +++++
|
||||
src/tcpopt.c | 42 +++++++++++++++++++++++----
|
||||
tests/py/any/tcpopt.t | 2 ++
|
||||
tests/py/any/tcpopt.t.payload | 53 +++--------------------------------
|
||||
8 files changed, 65 insertions(+), 57 deletions(-)
|
||||
|
||||
diff --git a/include/expression.h b/include/expression.h
|
||||
index 2e41aa0..b50183d 100644
|
||||
--- a/include/expression.h
|
||||
+++ b/include/expression.h
|
||||
@@ -299,7 +299,8 @@ struct expr {
|
||||
/* EXPR_EXTHDR */
|
||||
const struct exthdr_desc *desc;
|
||||
const struct proto_hdr_template *tmpl;
|
||||
- unsigned int offset;
|
||||
+ uint16_t offset;
|
||||
+ uint8_t raw_type;
|
||||
enum nft_exthdr_op op;
|
||||
unsigned int flags;
|
||||
} exthdr;
|
||||
diff --git a/src/exthdr.c b/src/exthdr.c
|
||||
index c28213f..68d5aa5 100644
|
||||
--- a/src/exthdr.c
|
||||
+++ b/src/exthdr.c
|
||||
@@ -32,6 +32,13 @@ static void exthdr_expr_print(const struct expr *expr, struct output_ctx *octx)
|
||||
*/
|
||||
unsigned int offset = expr->exthdr.offset / 64;
|
||||
|
||||
+ if (expr->exthdr.desc == NULL &&
|
||||
+ expr->exthdr.offset == 0 &&
|
||||
+ expr->exthdr.flags & NFT_EXTHDR_F_PRESENT) {
|
||||
+ nft_print(octx, "tcp option %d", expr->exthdr.raw_type);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
nft_print(octx, "tcp option %s", expr->exthdr.desc->name);
|
||||
if (expr->exthdr.flags & NFT_EXTHDR_F_PRESENT)
|
||||
return;
|
||||
@@ -59,6 +66,7 @@ static bool exthdr_expr_cmp(const struct expr *e1, const struct expr *e2)
|
||||
return e1->exthdr.desc == e2->exthdr.desc &&
|
||||
e1->exthdr.tmpl == e2->exthdr.tmpl &&
|
||||
e1->exthdr.op == e2->exthdr.op &&
|
||||
+ e1->exthdr.raw_type == e2->exthdr.raw_type &&
|
||||
e1->exthdr.flags == e2->exthdr.flags;
|
||||
}
|
||||
|
||||
@@ -69,6 +77,7 @@ static void exthdr_expr_clone(struct expr *new, const struct expr *expr)
|
||||
new->exthdr.offset = expr->exthdr.offset;
|
||||
new->exthdr.op = expr->exthdr.op;
|
||||
new->exthdr.flags = expr->exthdr.flags;
|
||||
+ new->exthdr.raw_type = expr->exthdr.raw_type;
|
||||
}
|
||||
|
||||
const struct expr_ops exthdr_expr_ops = {
|
||||
@@ -98,6 +107,7 @@ struct expr *exthdr_expr_alloc(const struct location *loc,
|
||||
expr = expr_alloc(loc, EXPR_EXTHDR, tmpl->dtype,
|
||||
BYTEORDER_BIG_ENDIAN, tmpl->len);
|
||||
expr->exthdr.desc = desc;
|
||||
+ expr->exthdr.raw_type = desc ? desc->type : 0;
|
||||
expr->exthdr.tmpl = tmpl;
|
||||
expr->exthdr.offset = tmpl->offset;
|
||||
return expr;
|
||||
@@ -176,6 +186,8 @@ void exthdr_init_raw(struct expr *expr, uint8_t type,
|
||||
unsigned int i;
|
||||
|
||||
assert(expr->etype == EXPR_EXTHDR);
|
||||
+ expr->exthdr.raw_type = type;
|
||||
+
|
||||
if (op == NFT_EXTHDR_OP_TCPOPT)
|
||||
return tcpopt_init_raw(expr, type, offset, len, flags);
|
||||
if (op == NFT_EXTHDR_OP_IPV4)
|
||||
diff --git a/src/ipopt.c b/src/ipopt.c
|
||||
index 7ecb8b9..5f9f908 100644
|
||||
--- a/src/ipopt.c
|
||||
+++ b/src/ipopt.c
|
||||
@@ -103,6 +103,7 @@ struct expr *ipopt_expr_alloc(const struct location *loc, uint8_t type,
|
||||
expr->exthdr.tmpl = tmpl;
|
||||
expr->exthdr.op = NFT_EXTHDR_OP_IPV4;
|
||||
expr->exthdr.offset = tmpl->offset + calc_offset(desc, tmpl, ptr);
|
||||
+ expr->exthdr.raw_type = desc->type;
|
||||
|
||||
return expr;
|
||||
}
|
||||
diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c
|
||||
index 9d1a064..28b0e6a 100644
|
||||
--- a/src/netlink_linearize.c
|
||||
+++ b/src/netlink_linearize.c
|
||||
@@ -174,7 +174,7 @@ static void netlink_gen_exthdr(struct netlink_linearize_ctx *ctx,
|
||||
nle = alloc_nft_expr("exthdr");
|
||||
netlink_put_register(nle, NFTNL_EXPR_EXTHDR_DREG, dreg);
|
||||
nftnl_expr_set_u8(nle, NFTNL_EXPR_EXTHDR_TYPE,
|
||||
- expr->exthdr.desc->type);
|
||||
+ expr->exthdr.raw_type);
|
||||
nftnl_expr_set_u32(nle, NFTNL_EXPR_EXTHDR_OFFSET, offset / BITS_PER_BYTE);
|
||||
nftnl_expr_set_u32(nle, NFTNL_EXPR_EXTHDR_LEN,
|
||||
div_round_up(expr->len, BITS_PER_BYTE));
|
||||
diff --git a/src/parser_bison.y b/src/parser_bison.y
|
||||
index 114b289..4ea9364 100644
|
||||
--- a/src/parser_bison.y
|
||||
+++ b/src/parser_bison.y
|
||||
@@ -4744,6 +4744,13 @@ tcp_hdr_option_type : EOL { $$ = TCPOPT_KIND_EOL; }
|
||||
| SACK3 { $$ = TCPOPT_KIND_SACK3; }
|
||||
| ECHO { $$ = TCPOPT_KIND_ECHO; }
|
||||
| TIMESTAMP { $$ = TCPOPT_KIND_TIMESTAMP; }
|
||||
+ | NUM {
|
||||
+ if ($1 > 255) {
|
||||
+ erec_queue(error(&@1, "value too large"), state->msgs);
|
||||
+ YYERROR;
|
||||
+ }
|
||||
+ $$ = $1;
|
||||
+ }
|
||||
;
|
||||
|
||||
tcp_hdr_option_field : KIND { $$ = TCPOPT_COMMON_KIND; }
|
||||
diff --git a/src/tcpopt.c b/src/tcpopt.c
|
||||
index d1dd13b..1cf97a5 100644
|
||||
--- a/src/tcpopt.c
|
||||
+++ b/src/tcpopt.c
|
||||
@@ -103,6 +103,19 @@ const struct exthdr_desc *tcpopt_protocols[] = {
|
||||
[TCPOPT_KIND_TIMESTAMP] = &tcpopt_timestamp,
|
||||
};
|
||||
|
||||
+/**
|
||||
+ * tcpopt_expr_alloc - allocate tcp option extension expression
|
||||
+ *
|
||||
+ * @loc: location from parser
|
||||
+ * @kind: raw tcp option value to find in packet
|
||||
+ * @field: highlevel field to find in the option if @kind is present in packet
|
||||
+ *
|
||||
+ * Allocate a new tcp option expression.
|
||||
+ * @kind is the raw option value to find in the packet.
|
||||
+ * Exception: SACK may use extra OOB data that is mangled here.
|
||||
+ *
|
||||
+ * @field is the optional field to extract from the @type option.
|
||||
+ */
|
||||
struct expr *tcpopt_expr_alloc(const struct location *loc,
|
||||
unsigned int kind,
|
||||
unsigned int field)
|
||||
@@ -138,8 +151,22 @@ struct expr *tcpopt_expr_alloc(const struct location *loc,
|
||||
if (kind < array_size(tcpopt_protocols))
|
||||
desc = tcpopt_protocols[kind];
|
||||
|
||||
- if (!desc)
|
||||
- return NULL;
|
||||
+ if (!desc) {
|
||||
+ if (field != TCPOPT_COMMON_KIND || kind > 255)
|
||||
+ return NULL;
|
||||
+
|
||||
+ expr = expr_alloc(loc, EXPR_EXTHDR, &integer_type,
|
||||
+ BYTEORDER_BIG_ENDIAN, 8);
|
||||
+
|
||||
+ desc = tcpopt_protocols[TCPOPT_NOP];
|
||||
+ tmpl = &desc->templates[field];
|
||||
+ expr->exthdr.desc = desc;
|
||||
+ expr->exthdr.tmpl = tmpl;
|
||||
+ expr->exthdr.op = NFT_EXTHDR_OP_TCPOPT;
|
||||
+ expr->exthdr.raw_type = kind;
|
||||
+ return expr;
|
||||
+ }
|
||||
+
|
||||
tmpl = &desc->templates[field];
|
||||
if (!tmpl)
|
||||
return NULL;
|
||||
@@ -149,6 +176,7 @@ struct expr *tcpopt_expr_alloc(const struct location *loc,
|
||||
expr->exthdr.desc = desc;
|
||||
expr->exthdr.tmpl = tmpl;
|
||||
expr->exthdr.op = NFT_EXTHDR_OP_TCPOPT;
|
||||
+ expr->exthdr.raw_type = desc->type;
|
||||
expr->exthdr.offset = tmpl->offset;
|
||||
|
||||
return expr;
|
||||
@@ -165,6 +193,10 @@ void tcpopt_init_raw(struct expr *expr, uint8_t type, unsigned int off,
|
||||
expr->len = len;
|
||||
expr->exthdr.flags = flags;
|
||||
expr->exthdr.offset = off;
|
||||
+ expr->exthdr.op = NFT_EXTHDR_OP_TCPOPT;
|
||||
+
|
||||
+ if (flags & NFT_EXTHDR_F_PRESENT)
|
||||
+ datatype_set(expr, &boolean_type);
|
||||
|
||||
if (type >= array_size(tcpopt_protocols))
|
||||
return;
|
||||
@@ -178,12 +210,10 @@ void tcpopt_init_raw(struct expr *expr, uint8_t type, unsigned int off,
|
||||
if (tmpl->offset != off || tmpl->len != len)
|
||||
continue;
|
||||
|
||||
- if (flags & NFT_EXTHDR_F_PRESENT)
|
||||
- datatype_set(expr, &boolean_type);
|
||||
- else
|
||||
+ if ((flags & NFT_EXTHDR_F_PRESENT) == 0)
|
||||
datatype_set(expr, tmpl->dtype);
|
||||
+
|
||||
expr->exthdr.tmpl = tmpl;
|
||||
- expr->exthdr.op = NFT_EXTHDR_OP_TCPOPT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
diff --git a/tests/py/any/tcpopt.t b/tests/py/any/tcpopt.t
|
||||
index 1d42de8..7b17014 100644
|
||||
--- a/tests/py/any/tcpopt.t
|
||||
+++ b/tests/py/any/tcpopt.t
|
||||
@@ -30,6 +30,7 @@ tcp option timestamp kind 1;ok
|
||||
tcp option timestamp length 1;ok
|
||||
tcp option timestamp tsval 1;ok
|
||||
tcp option timestamp tsecr 1;ok
|
||||
+tcp option 255 missing;ok
|
||||
|
||||
tcp option foobar;fail
|
||||
tcp option foo bar;fail
|
||||
@@ -38,6 +39,7 @@ tcp option eol left 1;fail
|
||||
tcp option eol left 1;fail
|
||||
tcp option sack window;fail
|
||||
tcp option sack window 1;fail
|
||||
+tcp option 256 exists;fail
|
||||
|
||||
tcp option window exists;ok
|
||||
tcp option window missing;ok
|
||||
diff --git a/tests/py/any/tcpopt.t.payload b/tests/py/any/tcpopt.t.payload
|
||||
index 9c480c8..34f8e26 100644
|
||||
--- a/tests/py/any/tcpopt.t.payload
|
||||
+++ b/tests/py/any/tcpopt.t.payload
|
||||
@@ -509,20 +509,6 @@ inet
|
||||
[ exthdr load tcpopt 4b @ 8 + 2 => reg 1 ]
|
||||
[ cmp eq reg 1 0x01000000 ]
|
||||
|
||||
-# tcp option timestamp tsecr 1
|
||||
-ip
|
||||
- [ meta load l4proto => reg 1 ]
|
||||
- [ cmp eq reg 1 0x00000006 ]
|
||||
- [ exthdr load tcpopt 4b @ 8 + 6 => reg 1 ]
|
||||
- [ cmp eq reg 1 0x01000000 ]
|
||||
-
|
||||
-# tcp option timestamp tsecr 1
|
||||
-ip6
|
||||
- [ meta load l4proto => reg 1 ]
|
||||
- [ cmp eq reg 1 0x00000006 ]
|
||||
- [ exthdr load tcpopt 4b @ 8 + 6 => reg 1 ]
|
||||
- [ cmp eq reg 1 0x01000000 ]
|
||||
-
|
||||
# tcp option timestamp tsecr 1
|
||||
inet
|
||||
[ meta load l4proto => reg 1 ]
|
||||
@@ -530,19 +516,12 @@ inet
|
||||
[ exthdr load tcpopt 4b @ 8 + 6 => reg 1 ]
|
||||
[ cmp eq reg 1 0x01000000 ]
|
||||
|
||||
-# tcp option window exists
|
||||
-ip
|
||||
- [ meta load l4proto => reg 1 ]
|
||||
- [ cmp eq reg 1 0x00000006 ]
|
||||
- [ exthdr load tcpopt 1b @ 3 + 0 present => reg 1 ]
|
||||
- [ cmp eq reg 1 0x00000001 ]
|
||||
-
|
||||
-# tcp option window exists
|
||||
-ip6
|
||||
+# tcp option 255 missing
|
||||
+inet
|
||||
[ meta load l4proto => reg 1 ]
|
||||
[ cmp eq reg 1 0x00000006 ]
|
||||
- [ exthdr load tcpopt 1b @ 3 + 0 present => reg 1 ]
|
||||
- [ cmp eq reg 1 0x00000001 ]
|
||||
+ [ exthdr load tcpopt 1b @ 255 + 0 present => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000000 ]
|
||||
|
||||
# tcp option window exists
|
||||
inet
|
||||
@@ -551,20 +530,6 @@ inet
|
||||
[ exthdr load tcpopt 1b @ 3 + 0 present => reg 1 ]
|
||||
[ cmp eq reg 1 0x00000001 ]
|
||||
|
||||
-# tcp option window missing
|
||||
-ip
|
||||
- [ meta load l4proto => reg 1 ]
|
||||
- [ cmp eq reg 1 0x00000006 ]
|
||||
- [ exthdr load tcpopt 1b @ 3 + 0 present => reg 1 ]
|
||||
- [ cmp eq reg 1 0x00000000 ]
|
||||
-
|
||||
-# tcp option window missing
|
||||
-ip6
|
||||
- [ meta load l4proto => reg 1 ]
|
||||
- [ cmp eq reg 1 0x00000006 ]
|
||||
- [ exthdr load tcpopt 1b @ 3 + 0 present => reg 1 ]
|
||||
- [ cmp eq reg 1 0x00000000 ]
|
||||
-
|
||||
# tcp option window missing
|
||||
inet
|
||||
[ meta load l4proto => reg 1 ]
|
||||
@@ -572,16 +537,6 @@ inet
|
||||
[ exthdr load tcpopt 1b @ 3 + 0 present => reg 1 ]
|
||||
[ cmp eq reg 1 0x00000000 ]
|
||||
|
||||
-# tcp option maxseg size set 1360
|
||||
-ip
|
||||
- [ immediate reg 1 0x00005005 ]
|
||||
- [ exthdr write tcpopt reg 1 => 2b @ 2 + 2 ]
|
||||
-
|
||||
-# tcp option maxseg size set 1360
|
||||
-ip6
|
||||
- [ immediate reg 1 0x00005005 ]
|
||||
- [ exthdr write tcpopt reg 1 => 2b @ 2 + 2 ]
|
||||
-
|
||||
# tcp option maxseg size set 1360
|
||||
inet
|
||||
[ immediate reg 1 0x00005005 ]
|
||||
--
|
||||
2.31.1
|
||||
|
137
SOURCES/0054-tcp-add-raw-tcp-option-match-support.patch
Normal file
137
SOURCES/0054-tcp-add-raw-tcp-option-match-support.patch
Normal file
@ -0,0 +1,137 @@
|
||||
From 267d86b62132a009badd57b2ffcffed6ae682a1e Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Mon, 12 Jul 2021 17:44:08 +0200
|
||||
Subject: [PATCH] tcp: add raw tcp option match support
|
||||
|
||||
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1979334
|
||||
Upstream Status: nftables commit 881d8cb21c0b9
|
||||
|
||||
commit 881d8cb21c0b9168787b932f41b801593bde2216
|
||||
Author: Florian Westphal <fw@strlen.de>
|
||||
Date: Mon Nov 2 20:10:25 2020 +0100
|
||||
|
||||
tcp: add raw tcp option match support
|
||||
|
||||
tcp option @42,16,4 (@kind,offset,length).
|
||||
|
||||
Signed-off-by: Florian Westphal <fw@strlen.de>
|
||||
---
|
||||
doc/payload-expression.txt | 6 ++++++
|
||||
src/exthdr.c | 13 +++++++++----
|
||||
src/parser_bison.y | 5 +++++
|
||||
src/tcpopt.c | 2 ++
|
||||
tests/py/any/tcpopt.t | 2 ++
|
||||
tests/py/any/tcpopt.t.payload | 7 +++++++
|
||||
6 files changed, 31 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/doc/payload-expression.txt b/doc/payload-expression.txt
|
||||
index 3a07321..b6d2a28 100644
|
||||
--- a/doc/payload-expression.txt
|
||||
+++ b/doc/payload-expression.txt
|
||||
@@ -591,6 +591,12 @@ TCP Timestamps |
|
||||
kind, length, tsval, tsecr
|
||||
|============================
|
||||
|
||||
+TCP option matching also supports raw expression syntax to access arbitrary options:
|
||||
+[verse]
|
||||
+*tcp option*
|
||||
+[verse]
|
||||
+*tcp option* *@*'number'*,*'offset'*,*'length'
|
||||
+
|
||||
.IP Options
|
||||
[options="header"]
|
||||
|==================
|
||||
diff --git a/src/exthdr.c b/src/exthdr.c
|
||||
index 68d5aa5..5c75720 100644
|
||||
--- a/src/exthdr.c
|
||||
+++ b/src/exthdr.c
|
||||
@@ -32,10 +32,15 @@ static void exthdr_expr_print(const struct expr *expr, struct output_ctx *octx)
|
||||
*/
|
||||
unsigned int offset = expr->exthdr.offset / 64;
|
||||
|
||||
- if (expr->exthdr.desc == NULL &&
|
||||
- expr->exthdr.offset == 0 &&
|
||||
- expr->exthdr.flags & NFT_EXTHDR_F_PRESENT) {
|
||||
- nft_print(octx, "tcp option %d", expr->exthdr.raw_type);
|
||||
+ if (expr->exthdr.desc == NULL) {
|
||||
+ if (expr->exthdr.offset == 0 &&
|
||||
+ expr->exthdr.flags & NFT_EXTHDR_F_PRESENT) {
|
||||
+ nft_print(octx, "tcp option %d", expr->exthdr.raw_type);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ nft_print(octx, "tcp option @%u,%u,%u", expr->exthdr.raw_type,
|
||||
+ expr->exthdr.offset, expr->len);
|
||||
return;
|
||||
}
|
||||
|
||||
diff --git a/src/parser_bison.y b/src/parser_bison.y
|
||||
index 4ea9364..5aedc55 100644
|
||||
--- a/src/parser_bison.y
|
||||
+++ b/src/parser_bison.y
|
||||
@@ -4718,6 +4718,11 @@ tcp_hdr_expr : TCP tcp_hdr_field
|
||||
$$ = tcpopt_expr_alloc(&@$, $3, TCPOPT_COMMON_KIND);
|
||||
$$->exthdr.flags = NFT_EXTHDR_F_PRESENT;
|
||||
}
|
||||
+ | TCP OPTION AT tcp_hdr_option_type COMMA NUM COMMA NUM
|
||||
+ {
|
||||
+ $$ = tcpopt_expr_alloc(&@$, $4, 0);
|
||||
+ tcpopt_init_raw($$, $4, $6, $8, 0);
|
||||
+ }
|
||||
;
|
||||
|
||||
tcp_hdr_field : SPORT { $$ = TCPHDR_SPORT; }
|
||||
diff --git a/src/tcpopt.c b/src/tcpopt.c
|
||||
index 1cf97a5..05b5ee6 100644
|
||||
--- a/src/tcpopt.c
|
||||
+++ b/src/tcpopt.c
|
||||
@@ -197,6 +197,8 @@ void tcpopt_init_raw(struct expr *expr, uint8_t type, unsigned int off,
|
||||
|
||||
if (flags & NFT_EXTHDR_F_PRESENT)
|
||||
datatype_set(expr, &boolean_type);
|
||||
+ else
|
||||
+ datatype_set(expr, &integer_type);
|
||||
|
||||
if (type >= array_size(tcpopt_protocols))
|
||||
return;
|
||||
diff --git a/tests/py/any/tcpopt.t b/tests/py/any/tcpopt.t
|
||||
index 7b17014..e759ac6 100644
|
||||
--- a/tests/py/any/tcpopt.t
|
||||
+++ b/tests/py/any/tcpopt.t
|
||||
@@ -31,6 +31,7 @@ tcp option timestamp length 1;ok
|
||||
tcp option timestamp tsval 1;ok
|
||||
tcp option timestamp tsecr 1;ok
|
||||
tcp option 255 missing;ok
|
||||
+tcp option @255,8,8 255;ok
|
||||
|
||||
tcp option foobar;fail
|
||||
tcp option foo bar;fail
|
||||
@@ -40,6 +41,7 @@ tcp option eol left 1;fail
|
||||
tcp option sack window;fail
|
||||
tcp option sack window 1;fail
|
||||
tcp option 256 exists;fail
|
||||
+tcp option @255,8,8 256;fail
|
||||
|
||||
tcp option window exists;ok
|
||||
tcp option window missing;ok
|
||||
diff --git a/tests/py/any/tcpopt.t.payload b/tests/py/any/tcpopt.t.payload
|
||||
index 34f8e26..cddba61 100644
|
||||
--- a/tests/py/any/tcpopt.t.payload
|
||||
+++ b/tests/py/any/tcpopt.t.payload
|
||||
@@ -523,6 +523,13 @@ inet
|
||||
[ exthdr load tcpopt 1b @ 255 + 0 present => reg 1 ]
|
||||
[ cmp eq reg 1 0x00000000 ]
|
||||
|
||||
+# tcp option @255,8,8 255
|
||||
+inet
|
||||
+ [ meta load l4proto => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x00000006 ]
|
||||
+ [ exthdr load tcpopt 1b @ 255 + 1 => reg 1 ]
|
||||
+ [ cmp eq reg 1 0x000000ff ]
|
||||
+
|
||||
# tcp option window exists
|
||||
inet
|
||||
[ meta load l4proto => reg 1 ]
|
||||
--
|
||||
2.31.1
|
||||
|
199
SOURCES/0055-json-tcp-add-raw-tcp-option-match-support.patch
Normal file
199
SOURCES/0055-json-tcp-add-raw-tcp-option-match-support.patch
Normal file
@ -0,0 +1,199 @@
|
||||
From ad566e27398e81ed803c4225179bb8df4718a2e9 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Mon, 12 Jul 2021 17:44:08 +0200
|
||||
Subject: [PATCH] json: tcp: add raw tcp option match support
|
||||
|
||||
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1979334
|
||||
Upstream Status: nftables commit cb21869649208
|
||||
|
||||
commit cb21869649208118ed61354e2674858e4ff6c23c
|
||||
Author: Florian Westphal <fw@strlen.de>
|
||||
Date: Tue Nov 3 12:04:20 2020 +0100
|
||||
|
||||
json: tcp: add raw tcp option match support
|
||||
|
||||
To similar change as in previous one, this time for the
|
||||
jason (de)serialization.
|
||||
|
||||
Re-uses the raw payload match syntax, i.e. base,offset,length.
|
||||
|
||||
Signed-off-by: Florian Westphal <fw@strlen.de>
|
||||
---
|
||||
src/json.c | 22 ++++++++--------
|
||||
src/parser_json.c | 52 ++++++++++++++++++++++++++------------
|
||||
tests/py/any/tcpopt.t.json | 34 +++++++++++++++++++++++++
|
||||
3 files changed, 82 insertions(+), 26 deletions(-)
|
||||
|
||||
diff --git a/src/json.c b/src/json.c
|
||||
index 1906e7d..b77c6d2 100644
|
||||
--- a/src/json.c
|
||||
+++ b/src/json.c
|
||||
@@ -656,30 +656,32 @@ json_t *map_expr_json(const struct expr *expr, struct output_ctx *octx)
|
||||
json_t *exthdr_expr_json(const struct expr *expr, struct output_ctx *octx)
|
||||
{
|
||||
const char *desc = expr->exthdr.desc ?
|
||||
- expr->exthdr.desc->name :
|
||||
- "unknown-exthdr";
|
||||
+ expr->exthdr.desc->name : NULL;
|
||||
const char *field = expr->exthdr.tmpl->token;
|
||||
json_t *root;
|
||||
bool is_exists = expr->exthdr.flags & NFT_EXTHDR_F_PRESENT;
|
||||
|
||||
if (expr->exthdr.op == NFT_EXTHDR_OP_TCPOPT) {
|
||||
+ static const char *offstrs[] = { "", "1", "2", "3" };
|
||||
unsigned int offset = expr->exthdr.offset / 64;
|
||||
+ const char *offstr = "";
|
||||
|
||||
- if (offset) {
|
||||
- const char *offstrs[] = { "0", "1", "2", "3" };
|
||||
- const char *offstr = "";
|
||||
-
|
||||
+ if (desc) {
|
||||
if (offset < 4)
|
||||
offstr = offstrs[offset];
|
||||
|
||||
root = json_pack("{s:s+}", "name", desc, offstr);
|
||||
+
|
||||
+ if (!is_exists)
|
||||
+ json_object_set_new(root, "field", json_string(field));
|
||||
} else {
|
||||
- root = json_pack("{s:s}", "name", desc);
|
||||
+ root = json_pack("{s:i, s:i, s:i}",
|
||||
+ "base", expr->exthdr.raw_type,
|
||||
+ "offset", expr->exthdr.offset,
|
||||
+ "len", expr->len);
|
||||
+ is_exists = false;
|
||||
}
|
||||
|
||||
- if (!is_exists)
|
||||
- json_object_set_new(root, "field", json_string(field));
|
||||
-
|
||||
return json_pack("{s:o}", "tcp option", root);
|
||||
}
|
||||
if (expr->exthdr.op == NFT_EXTHDR_OP_IPV4) {
|
||||
diff --git a/src/parser_json.c b/src/parser_json.c
|
||||
index ab2375f..fbf7db5 100644
|
||||
--- a/src/parser_json.c
|
||||
+++ b/src/parser_json.c
|
||||
@@ -500,6 +500,8 @@ static int json_parse_tcp_option_field(int type, const char *name, int *val)
|
||||
return 1;
|
||||
|
||||
desc = tcpopt_protocols[type];
|
||||
+ if (!desc)
|
||||
+ return 1;
|
||||
|
||||
for (i = 0; i < array_size(desc->templates); i++) {
|
||||
if (desc->templates[i].token &&
|
||||
@@ -599,30 +601,48 @@ static struct expr *json_parse_payload_expr(struct json_ctx *ctx,
|
||||
static struct expr *json_parse_tcp_option_expr(struct json_ctx *ctx,
|
||||
const char *type, json_t *root)
|
||||
{
|
||||
+ int fieldval, kind, offset, len;
|
||||
const char *desc, *field;
|
||||
- int descval, fieldval;
|
||||
struct expr *expr;
|
||||
|
||||
- if (json_unpack_err(ctx, root, "{s:s}", "name", &desc))
|
||||
- return NULL;
|
||||
-
|
||||
- if (json_parse_tcp_option_type(desc, &descval)) {
|
||||
- json_error(ctx, "Unknown tcp option name '%s'.", desc);
|
||||
- return NULL;
|
||||
- }
|
||||
+ if (!json_unpack(root, "{s:i, s:i, s:i}",
|
||||
+ "base", &kind, "offset", &offset, "len", &len)) {
|
||||
+ uint32_t flag = 0;
|
||||
|
||||
- if (json_unpack(root, "{s:s}", "field", &field)) {
|
||||
- expr = tcpopt_expr_alloc(int_loc, descval,
|
||||
+ expr = tcpopt_expr_alloc(int_loc, kind,
|
||||
TCPOPT_COMMON_KIND);
|
||||
- expr->exthdr.flags = NFT_EXTHDR_F_PRESENT;
|
||||
|
||||
+ if (kind < 0 || kind > 255)
|
||||
+ return NULL;
|
||||
+
|
||||
+ if (offset == TCPOPT_COMMON_KIND && len == 8)
|
||||
+ flag = NFT_EXTHDR_F_PRESENT;
|
||||
+
|
||||
+ tcpopt_init_raw(expr, kind, offset, len, flag);
|
||||
return expr;
|
||||
+ } else if (!json_unpack(root, "{s:s}", "name", &desc)) {
|
||||
+ if (json_parse_tcp_option_type(desc, &kind)) {
|
||||
+ json_error(ctx, "Unknown tcp option name '%s'.", desc);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ if (json_unpack(root, "{s:s}", "field", &field)) {
|
||||
+ expr = tcpopt_expr_alloc(int_loc, kind,
|
||||
+ TCPOPT_COMMON_KIND);
|
||||
+ expr->exthdr.flags = NFT_EXTHDR_F_PRESENT;
|
||||
+ return expr;
|
||||
+ }
|
||||
+
|
||||
+ if (json_parse_tcp_option_field(kind, field, &fieldval)) {
|
||||
+ json_error(ctx, "Unknown tcp option field '%s'.", field);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ return tcpopt_expr_alloc(int_loc, kind, fieldval);
|
||||
}
|
||||
- if (json_parse_tcp_option_field(descval, field, &fieldval)) {
|
||||
- json_error(ctx, "Unknown tcp option field '%s'.", field);
|
||||
- return NULL;
|
||||
- }
|
||||
- return tcpopt_expr_alloc(int_loc, descval, fieldval);
|
||||
+
|
||||
+ json_error(ctx, "Invalid tcp option expression properties.");
|
||||
+ return NULL;
|
||||
}
|
||||
|
||||
static int json_parse_ip_option_type(const char *name, int *val)
|
||||
diff --git a/tests/py/any/tcpopt.t.json b/tests/py/any/tcpopt.t.json
|
||||
index b15e36e..139e97d 100644
|
||||
--- a/tests/py/any/tcpopt.t.json
|
||||
+++ b/tests/py/any/tcpopt.t.json
|
||||
@@ -414,6 +414,40 @@
|
||||
}
|
||||
]
|
||||
|
||||
+# tcp option 255 missing
|
||||
+[
|
||||
+ {
|
||||
+ "match": {
|
||||
+ "left": {
|
||||
+ "tcp option": {
|
||||
+ "base": 255,
|
||||
+ "len": 8,
|
||||
+ "offset": 0
|
||||
+ }
|
||||
+ },
|
||||
+ "op": "==",
|
||||
+ "right": false
|
||||
+ }
|
||||
+ }
|
||||
+]
|
||||
+
|
||||
+# tcp option @255,8,8 255
|
||||
+[
|
||||
+ {
|
||||
+ "match": {
|
||||
+ "left": {
|
||||
+ "tcp option": {
|
||||
+ "base": 255,
|
||||
+ "len": 8,
|
||||
+ "offset": 8
|
||||
+ }
|
||||
+ },
|
||||
+ "op": "==",
|
||||
+ "right": 255
|
||||
+ }
|
||||
+ }
|
||||
+]
|
||||
+
|
||||
# tcp option window exists
|
||||
[
|
||||
{
|
||||
--
|
||||
2.31.1
|
||||
|
@ -0,0 +1,57 @@
|
||||
From 2026f7d056679508f8506fbba7f578aa15af7c05 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Mon, 12 Jul 2021 16:32:27 +0200
|
||||
Subject: [PATCH] json: Simplify non-tcpopt exthdr printing a bit
|
||||
|
||||
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1979334
|
||||
Upstream Status: nftables commit fd81d3ec3ae8b
|
||||
|
||||
commit fd81d3ec3ae8b8d1d54a708d63b2dab2c8508c90
|
||||
Author: Phil Sutter <phil@nwl.cc>
|
||||
Date: Tue May 4 13:18:11 2021 +0200
|
||||
|
||||
json: Simplify non-tcpopt exthdr printing a bit
|
||||
|
||||
This was just duplicate code apart from the object's name.
|
||||
|
||||
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||||
---
|
||||
src/json.c | 18 +++++++-----------
|
||||
1 file changed, 7 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/src/json.c b/src/json.c
|
||||
index b77c6d2..a6d0716 100644
|
||||
--- a/src/json.c
|
||||
+++ b/src/json.c
|
||||
@@ -684,21 +684,17 @@ json_t *exthdr_expr_json(const struct expr *expr, struct output_ctx *octx)
|
||||
|
||||
return json_pack("{s:o}", "tcp option", root);
|
||||
}
|
||||
- if (expr->exthdr.op == NFT_EXTHDR_OP_IPV4) {
|
||||
- root = json_pack("{s:s}", "name", desc);
|
||||
|
||||
- if (!is_exists)
|
||||
- json_object_set_new(root, "field", json_string(field));
|
||||
-
|
||||
- return json_pack("{s:o}", "ip option", root);
|
||||
- }
|
||||
-
|
||||
- root = json_pack("{s:s}",
|
||||
- "name", desc);
|
||||
+ root = json_pack("{s:s}", "name", desc);
|
||||
if (!is_exists)
|
||||
json_object_set_new(root, "field", json_string(field));
|
||||
|
||||
- return json_pack("{s:o}", "exthdr", root);
|
||||
+ switch (expr->exthdr.op) {
|
||||
+ case NFT_EXTHDR_OP_IPV4:
|
||||
+ return json_pack("{s:o}", "ip option", root);
|
||||
+ default:
|
||||
+ return json_pack("{s:o}", "exthdr", root);
|
||||
+ }
|
||||
}
|
||||
|
||||
json_t *verdict_expr_json(const struct expr *expr, struct output_ctx *octx)
|
||||
--
|
||||
2.31.1
|
||||
|
175
SOURCES/0057-scanner-introduce-start-condition-stack.patch
Normal file
175
SOURCES/0057-scanner-introduce-start-condition-stack.patch
Normal file
@ -0,0 +1,175 @@
|
||||
From c724812d9561021fb6a80c817d411d9ba2de5dbd Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Tue, 13 Jul 2021 13:54:12 +0200
|
||||
Subject: [PATCH] scanner: introduce start condition stack
|
||||
|
||||
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1979334
|
||||
Upstream Status: nftables commit 5896772fe3c5f
|
||||
|
||||
commit 5896772fe3c5f01696188ea04957a825ee601b12
|
||||
Author: Florian Westphal <fw@strlen.de>
|
||||
Date: Mon Mar 8 18:18:33 2021 +0100
|
||||
|
||||
scanner: introduce start condition stack
|
||||
|
||||
Add a small initial chunk of flex start conditionals.
|
||||
|
||||
This starts with two low-hanging fruits, numgen and j/symhash.
|
||||
|
||||
NUMGEN and HASH start conditions are entered from flex when
|
||||
the corresponding expression token is encountered.
|
||||
|
||||
Flex returns to the INIT condition when the bison parser
|
||||
has seen a complete numgen/hash statement.
|
||||
|
||||
This intentionally uses a stack rather than BEGIN()
|
||||
to eventually support nested states.
|
||||
|
||||
The scanner_pop_start_cond() function argument is not used yet, but
|
||||
will need to be used later to deal with nesting.
|
||||
|
||||
Signed-off-by: Florian Westphal <fw@strlen.de>
|
||||
---
|
||||
include/parser.h | 8 ++++++++
|
||||
src/parser_bison.y | 11 +++++++----
|
||||
src/scanner.l | 36 +++++++++++++++++++++++++++++-------
|
||||
3 files changed, 44 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/include/parser.h b/include/parser.h
|
||||
index 949284d..1d293f5 100644
|
||||
--- a/include/parser.h
|
||||
+++ b/include/parser.h
|
||||
@@ -28,6 +28,12 @@ struct parser_state {
|
||||
struct list_head *cmds;
|
||||
};
|
||||
|
||||
+enum startcond_type {
|
||||
+ PARSER_SC_BEGIN,
|
||||
+ PARSER_SC_EXPR_HASH,
|
||||
+ PARSER_SC_EXPR_NUMGEN,
|
||||
+};
|
||||
+
|
||||
struct mnl_socket;
|
||||
|
||||
extern void parser_init(struct nft_ctx *nft, struct parser_state *state,
|
||||
@@ -47,4 +53,6 @@ extern void scanner_push_buffer(void *scanner,
|
||||
const struct input_descriptor *indesc,
|
||||
const char *buffer);
|
||||
|
||||
+extern void scanner_pop_start_cond(void *scanner, enum startcond_type sc);
|
||||
+
|
||||
#endif /* NFTABLES_PARSER_H */
|
||||
diff --git a/src/parser_bison.y b/src/parser_bison.y
|
||||
index 5aedc55..9a9447f 100644
|
||||
--- a/src/parser_bison.y
|
||||
+++ b/src/parser_bison.y
|
||||
@@ -840,6 +840,9 @@ opt_newline : NEWLINE
|
||||
| /* empty */
|
||||
;
|
||||
|
||||
+close_scope_hash : { scanner_pop_start_cond(nft->scanner, PARSER_SC_EXPR_HASH); };
|
||||
+close_scope_numgen : { scanner_pop_start_cond(nft->scanner, PARSER_SC_EXPR_NUMGEN); };
|
||||
+
|
||||
common_block : INCLUDE QUOTED_STRING stmt_separator
|
||||
{
|
||||
if (scanner_include_file(nft, scanner, $2, &@$) < 0) {
|
||||
@@ -4249,7 +4252,7 @@ numgen_type : INC { $$ = NFT_NG_INCREMENTAL; }
|
||||
| RANDOM { $$ = NFT_NG_RANDOM; }
|
||||
;
|
||||
|
||||
-numgen_expr : NUMGEN numgen_type MOD NUM offset_opt
|
||||
+numgen_expr : NUMGEN numgen_type MOD NUM offset_opt close_scope_numgen
|
||||
{
|
||||
$$ = numgen_expr_alloc(&@$, $2, $4, $5);
|
||||
}
|
||||
@@ -4306,17 +4309,17 @@ xfrm_expr : IPSEC xfrm_dir xfrm_spnum xfrm_state_key
|
||||
}
|
||||
;
|
||||
|
||||
-hash_expr : JHASH expr MOD NUM SEED NUM offset_opt
|
||||
+hash_expr : JHASH expr MOD NUM SEED NUM offset_opt close_scope_hash
|
||||
{
|
||||
$$ = hash_expr_alloc(&@$, $4, true, $6, $7, NFT_HASH_JENKINS);
|
||||
$$->hash.expr = $2;
|
||||
}
|
||||
- | JHASH expr MOD NUM offset_opt
|
||||
+ | JHASH expr MOD NUM offset_opt close_scope_hash
|
||||
{
|
||||
$$ = hash_expr_alloc(&@$, $4, false, 0, $5, NFT_HASH_JENKINS);
|
||||
$$->hash.expr = $2;
|
||||
}
|
||||
- | SYMHASH MOD NUM offset_opt
|
||||
+ | SYMHASH MOD NUM offset_opt close_scope_hash
|
||||
{
|
||||
$$ = hash_expr_alloc(&@$, $3, false, 0, $4, NFT_HASH_SYM);
|
||||
}
|
||||
diff --git a/src/scanner.l b/src/scanner.l
|
||||
index 20b1b2d..68fe988 100644
|
||||
--- a/src/scanner.l
|
||||
+++ b/src/scanner.l
|
||||
@@ -98,6 +98,8 @@ static void reset_pos(struct parser_state *state, struct location *loc)
|
||||
state->indesc->column = 1;
|
||||
}
|
||||
|
||||
+static void scanner_push_start_cond(void *scanner, enum startcond_type type);
|
||||
+
|
||||
#define YY_USER_ACTION { \
|
||||
update_pos(yyget_extra(yyscanner), yylloc, yyleng); \
|
||||
update_offset(yyget_extra(yyscanner), yylloc, yyleng); \
|
||||
@@ -193,6 +195,9 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr})
|
||||
%option yylineno
|
||||
%option nodefault
|
||||
%option warn
|
||||
+%option stack
|
||||
+%s SCANSTATE_EXPR_HASH
|
||||
+%s SCANSTATE_EXPR_NUMGEN
|
||||
|
||||
%%
|
||||
|
||||
@@ -548,15 +553,21 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr})
|
||||
"state" { return STATE; }
|
||||
"status" { return STATUS; }
|
||||
|
||||
-"numgen" { return NUMGEN; }
|
||||
-"inc" { return INC; }
|
||||
-"mod" { return MOD; }
|
||||
-"offset" { return OFFSET; }
|
||||
+"numgen" { scanner_push_start_cond(yyscanner, SCANSTATE_EXPR_NUMGEN); return NUMGEN; }
|
||||
+<SCANSTATE_EXPR_NUMGEN>{
|
||||
+ "inc" { return INC; }
|
||||
+}
|
||||
|
||||
-"jhash" { return JHASH; }
|
||||
-"symhash" { return SYMHASH; }
|
||||
-"seed" { return SEED; }
|
||||
+"jhash" { scanner_push_start_cond(yyscanner, SCANSTATE_EXPR_HASH); return JHASH; }
|
||||
+"symhash" { scanner_push_start_cond(yyscanner, SCANSTATE_EXPR_HASH); return SYMHASH; }
|
||||
|
||||
+<SCANSTATE_EXPR_HASH>{
|
||||
+ "seed" { return SEED; }
|
||||
+}
|
||||
+<SCANSTATE_EXPR_HASH,SCANSTATE_EXPR_NUMGEN>{
|
||||
+ "mod" { return MOD; }
|
||||
+ "offset" { return OFFSET; }
|
||||
+}
|
||||
"dup" { return DUP; }
|
||||
"fwd" { return FWD; }
|
||||
|
||||
@@ -949,3 +960,14 @@ void scanner_destroy(struct nft_ctx *nft)
|
||||
input_descriptor_list_destroy(state);
|
||||
yylex_destroy(nft->scanner);
|
||||
}
|
||||
+
|
||||
+static void scanner_push_start_cond(void *scanner, enum startcond_type type)
|
||||
+{
|
||||
+ yy_push_state((int)type, scanner);
|
||||
+}
|
||||
+
|
||||
+void scanner_pop_start_cond(void *scanner, enum startcond_type t)
|
||||
+{
|
||||
+ yy_pop_state(scanner);
|
||||
+ (void)yy_top_state(scanner); /* suppress gcc warning wrt. unused function */
|
||||
+}
|
||||
--
|
||||
2.31.1
|
||||
|
96
SOURCES/0058-scanner-sctp-Move-to-own-scope.patch
Normal file
96
SOURCES/0058-scanner-sctp-Move-to-own-scope.patch
Normal file
@ -0,0 +1,96 @@
|
||||
From 595e79b1ccdfa6b11cd6c2b1c8eda0161b58d22a Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Tue, 13 Jul 2021 13:54:12 +0200
|
||||
Subject: [PATCH] scanner: sctp: Move to own scope
|
||||
|
||||
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1979334
|
||||
Upstream Status: nftables commit 0925d7e214825
|
||||
Conflicts: Context change due to missing other scopes.
|
||||
|
||||
commit 0925d7e214825628e7db4a86d5ebbad578ab0777
|
||||
Author: Phil Sutter <phil@nwl.cc>
|
||||
Date: Tue May 4 13:06:32 2021 +0200
|
||||
|
||||
scanner: sctp: Move to own scope
|
||||
|
||||
This isolates only "vtag" token for now.
|
||||
|
||||
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||||
Reviewed-by: Florian Westphal <fw@strlen.de>
|
||||
---
|
||||
include/parser.h | 1 +
|
||||
src/parser_bison.y | 5 +++--
|
||||
src/scanner.l | 8 ++++++--
|
||||
3 files changed, 10 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/include/parser.h b/include/parser.h
|
||||
index 1d293f5..2e6ef4d 100644
|
||||
--- a/include/parser.h
|
||||
+++ b/include/parser.h
|
||||
@@ -30,6 +30,7 @@ struct parser_state {
|
||||
|
||||
enum startcond_type {
|
||||
PARSER_SC_BEGIN,
|
||||
+ PARSER_SC_SCTP,
|
||||
PARSER_SC_EXPR_HASH,
|
||||
PARSER_SC_EXPR_NUMGEN,
|
||||
};
|
||||
diff --git a/src/parser_bison.y b/src/parser_bison.y
|
||||
index 9a9447f..beb5995 100644
|
||||
--- a/src/parser_bison.y
|
||||
+++ b/src/parser_bison.y
|
||||
@@ -842,6 +842,7 @@ opt_newline : NEWLINE
|
||||
|
||||
close_scope_hash : { scanner_pop_start_cond(nft->scanner, PARSER_SC_EXPR_HASH); };
|
||||
close_scope_numgen : { scanner_pop_start_cond(nft->scanner, PARSER_SC_EXPR_NUMGEN); };
|
||||
+close_scope_sctp : { scanner_pop_start_cond(nft->scanner, PARSER_SC_SCTP); };
|
||||
|
||||
common_block : INCLUDE QUOTED_STRING stmt_separator
|
||||
{
|
||||
@@ -4059,7 +4060,7 @@ primary_rhs_expr : symbol_expr { $$ = $1; }
|
||||
BYTEORDER_HOST_ENDIAN,
|
||||
sizeof(data) * BITS_PER_BYTE, &data);
|
||||
}
|
||||
- | SCTP
|
||||
+ | SCTP close_scope_sctp
|
||||
{
|
||||
uint8_t data = IPPROTO_SCTP;
|
||||
$$ = constant_expr_alloc(&@$, &inet_protocol_type,
|
||||
@@ -4782,7 +4783,7 @@ dccp_hdr_field : SPORT { $$ = DCCPHDR_SPORT; }
|
||||
| TYPE { $$ = DCCPHDR_TYPE; }
|
||||
;
|
||||
|
||||
-sctp_hdr_expr : SCTP sctp_hdr_field
|
||||
+sctp_hdr_expr : SCTP sctp_hdr_field close_scope_sctp
|
||||
{
|
||||
$$ = payload_expr_alloc(&@$, &proto_sctp, $2);
|
||||
}
|
||||
diff --git a/src/scanner.l b/src/scanner.l
|
||||
index 68fe988..b79ae55 100644
|
||||
--- a/src/scanner.l
|
||||
+++ b/src/scanner.l
|
||||
@@ -196,6 +196,7 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr})
|
||||
%option nodefault
|
||||
%option warn
|
||||
%option stack
|
||||
+%s SCANSTATE_SCTP
|
||||
%s SCANSTATE_EXPR_HASH
|
||||
%s SCANSTATE_EXPR_NUMGEN
|
||||
|
||||
@@ -488,8 +489,11 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr})
|
||||
|
||||
"dccp" { return DCCP; }
|
||||
|
||||
-"sctp" { return SCTP; }
|
||||
-"vtag" { return VTAG; }
|
||||
+"sctp" { scanner_push_start_cond(yyscanner, SCANSTATE_SCTP); return SCTP; }
|
||||
+
|
||||
+<SCANSTATE_SCTP>{
|
||||
+ "vtag" { return VTAG; }
|
||||
+}
|
||||
|
||||
"rt" { return RT; }
|
||||
"rt0" { return RT0; }
|
||||
--
|
||||
2.31.1
|
||||
|
1625
SOURCES/0059-exthdr-Implement-SCTP-Chunk-matching.patch
Normal file
1625
SOURCES/0059-exthdr-Implement-SCTP-Chunk-matching.patch
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,37 @@
|
||||
From 7ba8ea2cf06230e647b096f40d3006abec45f801 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Mon, 12 Jul 2021 16:33:20 +0200
|
||||
Subject: [PATCH] include: missing sctp_chunk.h in Makefile.am
|
||||
|
||||
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1979334
|
||||
Upstream Status: nftables commit 117ceb4f52711
|
||||
|
||||
commit 117ceb4f527119a6d44bf5e23f2ff7a8d116658a
|
||||
Author: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Date: Tue May 25 14:04:36 2021 +0200
|
||||
|
||||
include: missing sctp_chunk.h in Makefile.am
|
||||
|
||||
Fix make distcheck.
|
||||
|
||||
Fixes: 0e3871cfd9a1 ("exthdr: Implement SCTP Chunk matching")
|
||||
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
---
|
||||
include/Makefile.am | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/include/Makefile.am b/include/Makefile.am
|
||||
index 04a4a61..4ee5124 100644
|
||||
--- a/include/Makefile.am
|
||||
+++ b/include/Makefile.am
|
||||
@@ -30,6 +30,7 @@ noinst_HEADERS = cli.h \
|
||||
osf.h \
|
||||
parser.h \
|
||||
proto.h \
|
||||
+ sctp_chunk.h \
|
||||
socket.h \
|
||||
rule.h \
|
||||
rt.h \
|
||||
--
|
||||
2.31.1
|
||||
|
@ -0,0 +1,71 @@
|
||||
From 5a735f26b0c6617b2851a7399c8ad118e89deba8 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Mon, 12 Jul 2021 16:34:38 +0200
|
||||
Subject: [PATCH] doc: nft.8: Extend monitor description by trace
|
||||
|
||||
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1820365
|
||||
Upstream Status: nftables commit 2acf8b2caea19
|
||||
|
||||
commit 2acf8b2caea19d8abd46d475a908f8d6afb33aa0
|
||||
Author: Phil Sutter <phil@nwl.cc>
|
||||
Date: Wed May 19 13:12:48 2021 +0200
|
||||
|
||||
doc: nft.8: Extend monitor description by trace
|
||||
|
||||
Briefly describe 'nft monitor trace' command functionality.
|
||||
|
||||
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||||
---
|
||||
doc/nft.txt | 25 ++++++++++++++++++++++---
|
||||
1 file changed, 22 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/doc/nft.txt b/doc/nft.txt
|
||||
index abb9260..9cc35ee 100644
|
||||
--- a/doc/nft.txt
|
||||
+++ b/doc/nft.txt
|
||||
@@ -734,13 +734,26 @@ These are some additional commands included in nft.
|
||||
MONITOR
|
||||
~~~~~~~~
|
||||
The monitor command allows you to listen to Netlink events produced by the
|
||||
-nf_tables subsystem, related to creation and deletion of objects. When they
|
||||
+nf_tables subsystem. These are either related to creation and deletion of
|
||||
+objects or to packets for which *meta nftrace* was enabled. When they
|
||||
occur, nft will print to stdout the monitored events in either JSON or
|
||||
native nft format. +
|
||||
|
||||
-To filter events related to a concrete object, use one of the keywords 'tables', 'chains', 'sets', 'rules', 'elements', 'ruleset'. +
|
||||
+[verse]
|
||||
+____
|
||||
+*monitor* [*new* | *destroy*] 'MONITOR_OBJECT'
|
||||
+*monitor* *trace*
|
||||
+
|
||||
+'MONITOR_OBJECT' := *tables* | *chains* | *sets* | *rules* | *elements* | *ruleset*
|
||||
+____
|
||||
+
|
||||
+To filter events related to a concrete object, use one of the keywords in
|
||||
+'MONITOR_OBJECT'.
|
||||
|
||||
-To filter events related to a concrete action, use keyword 'new' or 'destroy'.
|
||||
+To filter events related to a concrete action, use keyword *new* or *destroy*.
|
||||
+
|
||||
+The second form of invocation takes no further options and exclusively prints
|
||||
+events generated for packets with *nftrace* enabled.
|
||||
|
||||
Hit ^C to finish the monitor operation.
|
||||
|
||||
@@ -764,6 +777,12 @@ Hit ^C to finish the monitor operation.
|
||||
% nft monitor ruleset
|
||||
---------------------
|
||||
|
||||
+.Trace incoming packets from host 10.0.0.1
|
||||
+------------------------------------------
|
||||
+% nft add rule filter input ip saddr 10.0.0.1 meta nftrace set 1
|
||||
+% nft monitor trace
|
||||
+------------------------------------------
|
||||
+
|
||||
ERROR REPORTING
|
||||
---------------
|
||||
When an error is detected, nft shows the line(s) containing the error, the
|
||||
--
|
||||
2.31.1
|
||||
|
@ -0,0 +1,44 @@
|
||||
From e8300966510001e38f2b6530607bac2a93de5c2e Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <psutter@redhat.com>
|
||||
Date: Mon, 2 Aug 2021 14:35:08 +0200
|
||||
Subject: [PATCH] tests: shell: Fix bogus testsuite failure with 100Hz
|
||||
|
||||
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1919203
|
||||
Upstream Status: nftables commit c9c5b5f621c37
|
||||
|
||||
commit c9c5b5f621c37d17140dac682d211825ef321093
|
||||
Author: Phil Sutter <phil@nwl.cc>
|
||||
Date: Mon Jul 26 15:27:32 2021 +0200
|
||||
|
||||
tests: shell: Fix bogus testsuite failure with 100Hz
|
||||
|
||||
On kernels with CONFIG_HZ=100, clock granularity does not allow tracking
|
||||
timeouts in single digit ms range. Change sets/0031set_timeout_size_0 to
|
||||
not expose this detail.
|
||||
|
||||
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||||
Acked-by: Florian Westphal <fw@strlen.de>
|
||||
---
|
||||
tests/shell/testcases/sets/0031set_timeout_size_0 | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/tests/shell/testcases/sets/0031set_timeout_size_0 b/tests/shell/testcases/sets/0031set_timeout_size_0
|
||||
index 9edd5f6..796640d 100755
|
||||
--- a/tests/shell/testcases/sets/0031set_timeout_size_0
|
||||
+++ b/tests/shell/testcases/sets/0031set_timeout_size_0
|
||||
@@ -3,10 +3,10 @@
|
||||
RULESET="add table x
|
||||
add set x y { type ipv4_addr; size 128; timeout 30s; flags dynamic; }
|
||||
add chain x test
|
||||
-add rule x test set update ip saddr timeout 1d2h3m4s8ms @y
|
||||
+add rule x test set update ip saddr timeout 1d2h3m4s10ms @y
|
||||
add rule x test set update ip daddr timeout 100ms @y"
|
||||
|
||||
set -e
|
||||
$NFT -f - <<< "$RULESET"
|
||||
-$NFT list chain x test | grep -q 'update @y { ip saddr timeout 1d2h3m4s8ms }'
|
||||
+$NFT list chain x test | grep -q 'update @y { ip saddr timeout 1d2h3m4s10ms }'
|
||||
$NFT list chain x test | grep -q 'update @y { ip daddr timeout 100ms }'
|
||||
--
|
||||
2.31.1
|
||||
|
@ -1,9 +1,9 @@
|
||||
%define rpmversion 0.9.3
|
||||
%define specrelease 18%{?dist}
|
||||
%define specrelease 21
|
||||
|
||||
Name: nftables
|
||||
Version: %{rpmversion}
|
||||
Release: %{specrelease}%{?buildid}
|
||||
Release: %{specrelease}%{?dist}%{?buildid}
|
||||
# Upstream released a 0.100 version, then 0.4. Need Epoch to get back on track.
|
||||
Epoch: 1
|
||||
Summary: Netfilter Tables userspace utillites
|
||||
@ -58,6 +58,27 @@ Patch38: 0038-json-echo-Speedup-seqnum_to_json.patch
|
||||
Patch39: 0039-json-Fix-seqnum_to_json-functionality.patch
|
||||
Patch40: 0040-json-don-t-leave-dangling-pointers-on-hlist.patch
|
||||
Patch41: 0041-json-init-parser-state-for-every-new-buffer-file.patch
|
||||
Patch42: 0042-tests-Disable-tests-known-to-fail-on-RHEL8.patch
|
||||
Patch43: 0043-monitor-Fix-for-use-after-free-when-printing-map-ele.patch
|
||||
Patch44: 0044-tests-monitor-use-correct-nft-value-in-EXIT-trap.patch
|
||||
Patch45: 0045-evaluate-Reject-quoted-strings-containing-only-wildc.patch
|
||||
Patch46: 0046-src-Support-odd-sized-payload-matches.patch
|
||||
Patch47: 0047-src-Optimize-prefix-matches-on-byte-boundaries.patch
|
||||
Patch48: 0048-tests-py-Move-tcpopt.t-to-any-directory.patch
|
||||
Patch49: 0049-parser-merge-sack-perm-sack-permitted-and-maxseg-mss.patch
|
||||
Patch50: 0050-tcpopts-clean-up-parser-tcpopt.c-plumbing.patch
|
||||
Patch51: 0051-tcpopt-rename-noop-to-nop.patch
|
||||
Patch52: 0052-tcpopt-split-tcpopt_hdr_fields-into-per-option-enum.patch
|
||||
Patch53: 0053-tcpopt-allow-to-check-for-presence-of-any-tcp-option.patch
|
||||
Patch54: 0054-tcp-add-raw-tcp-option-match-support.patch
|
||||
Patch55: 0055-json-tcp-add-raw-tcp-option-match-support.patch
|
||||
Patch56: 0056-json-Simplify-non-tcpopt-exthdr-printing-a-bit.patch
|
||||
Patch57: 0057-scanner-introduce-start-condition-stack.patch
|
||||
Patch58: 0058-scanner-sctp-Move-to-own-scope.patch
|
||||
Patch59: 0059-exthdr-Implement-SCTP-Chunk-matching.patch
|
||||
Patch60: 0060-include-missing-sctp_chunk.h-in-Makefile.am.patch
|
||||
Patch61: 0061-doc-nft.8-Extend-monitor-description-by-trace.patch
|
||||
Patch62: 0062-tests-shell-Fix-bogus-testsuite-failure-with-100Hz.patch
|
||||
|
||||
BuildRequires: autogen
|
||||
BuildRequires: autoconf
|
||||
@ -174,6 +195,35 @@ touch -r %{SOURCE2} $RPM_BUILD_ROOT/%{python3_sitelib}/nftables/nftables.py
|
||||
%{python3_sitelib}/nftables/
|
||||
|
||||
%changelog
|
||||
* Mon Aug 02 2021 Phil Sutter <psutter@redhat.com> [0.9.3-21.el8]
|
||||
- tests: shell: Fix bogus testsuite failure with 100Hz (Phil Sutter) [1919203]
|
||||
- doc: nft.8: Extend monitor description by trace (Phil Sutter) [1820365]
|
||||
- include: missing sctp_chunk.h in Makefile.am (Phil Sutter) [1979334]
|
||||
- exthdr: Implement SCTP Chunk matching (Phil Sutter) [1979334]
|
||||
- scanner: sctp: Move to own scope (Phil Sutter) [1979334]
|
||||
- scanner: introduce start condition stack (Phil Sutter) [1979334]
|
||||
- json: Simplify non-tcpopt exthdr printing a bit (Phil Sutter) [1979334]
|
||||
- json: tcp: add raw tcp option match support (Phil Sutter) [1979334]
|
||||
- tcp: add raw tcp option match support (Phil Sutter) [1979334]
|
||||
- tcpopt: allow to check for presence of any tcp option (Phil Sutter) [1979334]
|
||||
- tcpopt: split tcpopt_hdr_fields into per-option enum (Phil Sutter) [1979334]
|
||||
- tcpopt: rename noop to nop (Phil Sutter) [1979334]
|
||||
- tcpopts: clean up parser -> tcpopt.c plumbing (Phil Sutter) [1979334]
|
||||
- parser: merge sack-perm/sack-permitted and maxseg/mss (Phil Sutter) [1979334]
|
||||
- tests/py: Move tcpopt.t to any/ directory (Phil Sutter) [1979334]
|
||||
|
||||
* Thu May 20 2021 Phil Sutter <psutter@redhat.com> [0.9.3-20.el8]
|
||||
- src: Optimize prefix matches on byte-boundaries (Phil Sutter) [1934926]
|
||||
- src: Support odd-sized payload matches (Phil Sutter) [1934926]
|
||||
- spec: Add an rpminspect.yaml file to steer rpminspect (Phil Sutter) [1962184]
|
||||
- spec: Explicitly state dist string in Release tag (Phil Sutter) [1962184]
|
||||
|
||||
* Wed May 19 2021 Phil Sutter <psutter@redhat.com> [0.9.3-19.el8]
|
||||
- evaluate: Reject quoted strings containing only wildcard (Phil Sutter) [1818117]
|
||||
- tests: monitor: use correct $nft value in EXIT trap (Phil Sutter) [1919203]
|
||||
- monitor: Fix for use after free when printing map elements (Phil Sutter) [1919203]
|
||||
- tests: Disable tests known to fail on RHEL8 (Phil Sutter) [1919203]
|
||||
|
||||
* Sat Feb 20 2021 Phil Sutter <psutter@redhat.com> [0.9.3-18.el8]
|
||||
- json: init parser state for every new buffer/file (Phil Sutter) [1930873]
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user