import nftables-0.9.3-21.el8

This commit is contained in:
CentOS Sources 2021-11-09 05:08:13 -05:00 committed by Stepan Oksanichenko
parent ddc3de15f1
commit d1de3e821a
22 changed files with 7617 additions and 2 deletions

View 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

View File

@ -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

View File

@ -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

View File

@ -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

View 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

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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

View 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

View 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

View File

@ -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

View File

@ -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

View 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

View 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

View File

@ -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

View 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

View 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

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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]