summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--configure.ac15
-rw-r--r--doc/data-types.txt43
-rw-r--r--doc/nft.txt22
-rw-r--r--doc/payload-expression.txt5
-rw-r--r--doc/statements.txt3
-rw-r--r--include/cli.h2
-rw-r--r--include/expression.h3
-rw-r--r--include/exthdr.h1
-rw-r--r--include/json.h6
-rw-r--r--include/linux/netfilter/nf_tables.h29
-rw-r--r--include/list.h7
-rw-r--r--include/nftables.h1
-rw-r--r--include/owner.h6
-rw-r--r--include/payload.h7
-rw-r--r--include/proto.h34
-rw-r--r--include/rule.h8
-rw-r--r--include/statement.h4
-rw-r--r--src/Makefile.am1
-rw-r--r--src/cli.c75
-rw-r--r--src/erec.c3
-rw-r--r--src/evaluate.c169
-rw-r--r--src/expression.c36
-rw-r--r--src/exthdr.c4
-rw-r--r--src/json.c49
-rw-r--r--src/libnftables.c7
-rw-r--r--src/main.c9
-rw-r--r--src/mnl.c22
-rw-r--r--src/monitor.c38
-rw-r--r--src/netlink.c82
-rw-r--r--src/netlink_delinearize.c116
-rw-r--r--src/netlink_linearize.c52
-rw-r--r--src/owner.c173
-rw-r--r--src/parser_bison.y178
-rw-r--r--src/parser_json.c74
-rw-r--r--src/payload.c231
-rw-r--r--src/proto.c45
-rw-r--r--src/rule.c70
-rw-r--r--src/segtree.c36
-rw-r--r--src/statement.c36
-rwxr-xr-xtests/build/run-tests.sh2
-rwxr-xr-xtests/monitor/run-tests.sh2
-rw-r--r--tests/py/any/ct.t2
-rw-r--r--tests/py/any/ct.t.json56
-rw-r--r--tests/py/any/ct.t.payload15
-rw-r--r--tests/py/any/limit.t.json.output277
-rw-r--r--tests/py/any/limit.t.payload44
-rw-r--r--tests/py/any/meta.t34
-rw-r--r--tests/py/any/meta.t.payload44
-rw-r--r--tests/py/any/tcpopt.t1
-rw-r--r--tests/py/any/tcpopt.t.payload60
-rw-r--r--tests/py/arp/arp.t2
-rw-r--r--tests/py/arp/arp.t.json32
-rw-r--r--tests/py/arp/arp.t.payload10
-rw-r--r--tests/py/arp/arp.t.payload.netdev14
-rw-r--r--tests/py/bridge/reject.t.json.output130
-rw-r--r--tests/py/inet/ah.t2
-rw-r--r--tests/py/inet/dccp.t.json18
-rw-r--r--tests/py/inet/dccp.t.payload8
-rw-r--r--tests/py/inet/esp.t1
-rw-r--r--tests/py/inet/esp.t.json20
-rw-r--r--tests/py/inet/ether.t.payload.bridge21
-rw-r--r--tests/py/inet/ether.t.payload.ip23
-rw-r--r--tests/py/inet/reject.t33
-rw-r--r--tests/py/inet/reject.t.json.output194
-rw-r--r--tests/py/inet/reject.t.payload.inet104
-rw-r--r--tests/py/inet/rt.t5
-rw-r--r--tests/py/inet/sets.t.payload.bridge2
-rw-r--r--tests/py/inet/sets.t.payload.inet2
-rw-r--r--tests/py/inet/sets.t.payload.netdev4
-rw-r--r--tests/py/inet/synproxy.t.json32
-rw-r--r--tests/py/ip/ct.t7
-rw-r--r--tests/py/ip/ct.t.json109
-rw-r--r--tests/py/ip/ct.t.payload28
-rw-r--r--tests/py/ip/icmp.t40
-rw-r--r--tests/py/ip/icmp.t.json603
-rw-r--r--tests/py/ip/icmp.t.json.output134
-rw-r--r--tests/py/ip/icmp.t.payload.ip172
-rw-r--r--tests/py/ip/igmp.t.payload228
-rw-r--r--tests/py/ip/ip.t4
-rw-r--r--tests/py/ip/ip.t.payload10
-rw-r--r--tests/py/ip/ip.t.payload.inet12
-rw-r--r--tests/py/ip/ip.t.payload.netdev112
-rw-r--r--tests/py/ip/reject.t.json.output7
-rw-r--r--tests/py/ip6/dnat.t2
-rw-r--r--tests/py/ip6/ether.t2
-rw-r--r--tests/py/ip6/frag.t.payload.inet8
-rw-r--r--tests/py/ip6/frag.t.payload.ip66
-rw-r--r--tests/py/ip6/icmpv6.t46
-rw-r--r--tests/py/ip6/icmpv6.t.json66
-rw-r--r--tests/py/ip6/icmpv6.t.json.output586
-rw-r--r--tests/py/ip6/icmpv6.t.payload.ip6130
-rw-r--r--tests/py/ip6/ip6.t2
-rw-r--r--tests/py/ip6/ip6.t.payload.inet2
-rw-r--r--tests/py/ip6/ip6.t.payload.ip62
-rw-r--r--tests/py/ip6/reject.t.json.output7
-rw-r--r--tests/py/ip6/snat.t2
-rw-r--r--tests/py/netdev/reject.t48
-rw-r--r--tests/py/netdev/reject.t.json317
-rw-r--r--tests/py/netdev/reject.t.payload102
-rwxr-xr-xtests/py/nft-test.py5
-rwxr-xr-xtests/py/tools/test-sanitizer.sh78
-rw-r--r--tests/shell/testcases/chains/dumps/0031priority_variable_0.nft (renamed from tests/shell/testcases/nft-f/dumps/0021priority_variable_0.nft)0
-rw-r--r--tests/shell/testcases/chains/dumps/0035policy_variable_0.nft (renamed from tests/shell/testcases/nft-f/dumps/0025policy_variable_0.nft)0
-rw-r--r--tests/shell/testcases/maps/dumps/typeof_maps_0.nft4
-rwxr-xr-xtests/shell/testcases/maps/typeof_maps_04
-rwxr-xr-xtests/shell/testcases/nft-f/0024priority_014
-rwxr-xr-xtests/shell/testcases/nft-f/0025empty_dynset_022
-rw-r--r--tests/shell/testcases/nft-f/dumps/0024priority_0.nft10
-rw-r--r--tests/shell/testcases/nft-f/dumps/0025empty_dynset_0.nft18
-rwxr-xr-xtests/shell/testcases/sets/0029named_ifname_dtype_041
-rwxr-xr-xtests/shell/testcases/sets/0056dynamic_limit_019
-rwxr-xr-xtests/shell/testcases/sets/0057set_create_fails_018
-rwxr-xr-xtests/shell/testcases/sets/0058_setupdate_timeout_017
-rwxr-xr-xtests/shell/testcases/sets/0059set_update_multistmt_017
-rwxr-xr-xtests/shell/testcases/sets/0060set_multistmt_050
-rw-r--r--tests/shell/testcases/sets/dumps/0029named_ifname_dtype_0.nft44
-rw-r--r--tests/shell/testcases/sets/dumps/0058_setupdate_timeout_0.nft12
-rw-r--r--tests/shell/testcases/sets/dumps/0059set_update_multistmt_0.nft13
-rw-r--r--tests/shell/testcases/sets/dumps/0060set_multistmt_0.nft13
119 files changed, 4408 insertions, 1681 deletions
diff --git a/configure.ac b/configure.ac
index 5dacb43e..5f30760f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,5 +1,5 @@
-AC_INIT([nftables], [0.9.7], [netfilter-devel@vger.kernel.org])
-AC_DEFINE([RELEASE_NAME], ["Anyface"], [Release name])
+AC_INIT([nftables], [0.9.8], [netfilter-devel@vger.kernel.org])
+AC_DEFINE([RELEASE_NAME], ["E.D.S."], [Release name])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_MACRO_DIR([m4])
@@ -57,7 +57,7 @@ AS_IF([test "x$enable_man_doc" = "xyes"], [
])
PKG_CHECK_MODULES([LIBMNL], [libmnl >= 1.0.4])
-PKG_CHECK_MODULES([LIBNFTNL], [libnftnl >= 1.1.8])
+PKG_CHECK_MODULES([LIBNFTNL], [libnftnl >= 1.1.9])
AC_ARG_WITH([mini-gmp], [AS_HELP_STRING([--with-mini-gmp],
[Use builtin mini-gmp (for embedded builds)])],
@@ -68,7 +68,7 @@ AC_CHECK_LIB([gmp],[__gmpz_init], , AC_MSG_ERROR([No suitable version of libgmp
AM_CONDITIONAL([BUILD_MINIGMP], [test "x$with_mini_gmp" = xyes])
AC_ARG_WITH([cli], [AS_HELP_STRING([--without-cli],
- [disable interactive CLI (libreadline or linenoise support)])],
+ [disable interactive CLI (libreadline, editline or linenoise support)])],
[], [with_cli=readline])
AS_IF([test "x$with_cli" = xreadline], [
@@ -81,6 +81,11 @@ AC_CHECK_LIB([linenoise], [linenoise], ,
AC_MSG_ERROR([No suitable version of linenoise found]))
AC_DEFINE([HAVE_LIBLINENOISE], [1], [])
],
+ [test "x$with_cli" = xeditline], [
+AC_CHECK_LIB([edit], [readline], ,
+ AC_MSG_ERROR([No suitable version of libedit found]))
+AC_DEFINE([HAVE_LIBEDIT], [1], [])
+],
[test "x$with_cli" != xno], [
AC_MSG_ERROR([unexpected CLI value: $with_cli])
])
@@ -111,7 +116,7 @@ AC_ARG_ENABLE(python,
AC_ARG_WITH([python_bin],
[AS_HELP_STRING([--with-python-bin], [Specify Python binary to use])],
- [PYTHON_BIN="$withval"], [AC_PATH_PROGS(PYTHON_BIN, python python2 python2.7)]
+ [PYTHON_BIN="$withval"], [AC_PATH_PROGS(PYTHON_BIN, python python2 python2.7 python3)]
)
AS_IF([test "x$PYTHON_BIN" = "x"], [
diff --git a/doc/data-types.txt b/doc/data-types.txt
index a42a55fa..961fc624 100644
--- a/doc/data-types.txt
+++ b/doc/data-types.txt
@@ -492,3 +492,46 @@ For each of the types above, keywords are available for convenience:
|==================
Possible keywords for conntrack label type (ct_label) are read at runtime from /etc/connlabel.conf.
+
+DCCP PKTTYPE TYPE
+~~~~~~~~~~~~~~~~
+[options="header"]
+|==================
+|Name | Keyword | Size | Base type
+|DCCP packet type |
+dccp_pkttype |
+4 bit |
+integer
+|===================
+
+The DCCP packet type abstracts the different legal values of the respective
+four bit field in the DCCP header, as stated by RFC4340. Note that possible
+values 10-15 are considered reserved and therefore not allowed to be used. In
+iptables' *dccp* match, these values are aliased 'INVALID'. With nftables, one
+may simply match on the numeric value range, i.e. *10-15*.
+
+.keywords may be used when specifying the DCCP packet type
+[options="header"]
+|==================
+|Keyword |Value
+|request|
+0
+|response|
+1
+|data|
+2
+|ack|
+3
+|dataack|
+4
+|closereq|
+5
+|close|
+6
+|reset|
+7
+|sync|
+8
+|syncack|
+9
+|=================
diff --git a/doc/nft.txt b/doc/nft.txt
index 2642d890..32261e26 100644
--- a/doc/nft.txt
+++ b/doc/nft.txt
@@ -130,7 +130,7 @@ semicolon (;). +
A hash sign (#) begins a comment. All following characters on the same line are
ignored. +
-Identifiers begin with an alphabetic character (a-z,A-Z), followed zero or more
+Identifiers begin with an alphabetic character (a-z,A-Z), followed by zero or more
alphanumeric characters (a-z,A-Z,0-9) and the characters slash (/), backslash
(\), underscore (_) and dot (.). Identifiers using different characters or
clashing with a keyword need to be enclosed in double quotes (").
@@ -148,9 +148,9 @@ relative path) or / for file location expressed as an absolute path. +
If *-I*/*--includepath* is not specified, then nft relies on the default
directory that is specified at compile time. You can retrieve this default
-directory via *-h*/*--help* option. +
+directory via the *-h*/*--help* option. +
-Include statements support the usual shell wildcard symbols (\*,?,[]). Having no
+Include statements support the usual shell wildcard symbols (*,?,[]). Having no
matches for an include statement is not an error, if wildcard symbols are used
in the include statement. This allows having potentially empty include
directories for statements like **include "/etc/firewall/rules/"**. The wildcard
@@ -164,7 +164,7 @@ SYMBOLIC VARIABLES
*$variable*
Symbolic variables can be defined using the *define* statement. Variable
-references are expressions and can be used initialize other variables. The scope
+references are expressions and can be used to initialize other variables. The scope
of a definition is the current block and all blocks contained within.
.Using symbolic variables
@@ -396,7 +396,7 @@ further quirks worth noticing:
hook.
The *priority* parameter accepts a signed integer value or a standard priority
-name which specifies the order in which chains with same *hook* value are
+name which specifies the order in which chains with the same *hook* value are
traversed. The ordering is ascending, i.e. lower priority values have precedence
over higher ones.
@@ -435,7 +435,7 @@ the others. See the following tables that describe the values and compatibility.
Basic arithmetic expressions (addition and subtraction) can also be achieved
with these standard names to ease relative prioritizing, e.g. *mangle - 5* stands
for *-155*. Values will also be printed like this until the value is not
-further than 10 form the standard value.
+further than 10 from the standard value.
Base chains also allow to set the chain's *policy*, i.e. what happens to
packets not explicitly accepted or refused in contained rules. Supported policy
@@ -492,7 +492,7 @@ table inet filter {
ip saddr 10.1.1.1 tcp dport ssh accept # handle 5
...
# delete the rule with handle 5
-# nft delete rule inet filter input handle 5
+nft delete rule inet filter input handle 5
-------------------------
SETS
@@ -534,7 +534,7 @@ identified by a user-defined name and attached to tables. Their behaviour can
be tuned with the flags that can be specified at set creation time.
[horizontal]
-*add*:: Add a new set in the specified table. See the Set specification table below for more information about how to specify a sets properties.
+*add*:: Add a new set in the specified table. See the Set specification table below for more information about how to specify properties of a set.
*delete*:: Delete the specified set.
*list*:: Display the elements in the specified set.
*flush*:: Remove all elements from the specified set.
@@ -553,7 +553,7 @@ expression to derive the data type from
set flags |
string: constant, dynamic, interval, timeout
|timeout |
-time an element stays in the set, mandatory if set is added to from the packet path (ruleset).|
+time an element stays in the set, mandatory if set is added to from the packet path (ruleset)|
string, decimal followed by unit. Units are: d, h, m, s
|gc-interval |
garbage collection interval, only available when timeout or flag timeout are
@@ -563,7 +563,7 @@ string, decimal followed by unit. Units are: d, h, m, s
elements contained by the set |
set data type
|size |
-maximum number of elements in the set, mandatory if set is added to from the packet path (ruleset).|
+maximum number of elements in the set, mandatory if set is added to from the packet path (ruleset)|
unsigned integer (64 bit)
|policy |
set policy |
@@ -628,7 +628,7 @@ ____
Element-related commands allow to change contents of named sets and maps.
'key_expression' is typically a value matching the set type.
'value_expression' is not allowed in sets but mandatory when adding to maps, where it
-matches the data part in it's type definition. When deleting from maps, it may
+matches the data part in its type definition. When deleting from maps, it may
be specified but is optional as 'key_expression' uniquely identifies the
element.
diff --git a/doc/payload-expression.txt b/doc/payload-expression.txt
index ffd1b671..a593e2e7 100644
--- a/doc/payload-expression.txt
+++ b/doc/payload-expression.txt
@@ -392,7 +392,7 @@ integer (32 bit)
DCCP HEADER EXPRESSION
~~~~~~~~~~~~~~~~~~~~~~
[verse]
-*dccp* {*sport* | *dport*}
+*dccp* {*sport* | *dport* | *type*}
.DCCP header expression
[options="header"]
@@ -404,6 +404,9 @@ inet_service
|dport|
Destination port|
inet_service
+|type|
+Packet type|
+dccp_pkttype
|========================
AUTHENTICATION HEADER EXPRESSION
diff --git a/doc/statements.txt b/doc/statements.txt
index beebba16..aac7c7d6 100644
--- a/doc/statements.txt
+++ b/doc/statements.txt
@@ -324,7 +324,8 @@ ____
A limit statement matches at a limited rate using a token bucket filter. A rule
using this statement will match until this limit is reached. It can be used in
combination with the log statement to give limited logging. The optional
-*over* keyword makes it match over the specified rate.
+*over* keyword makes it match over the specified rate. Default *burst* is 5.
+if you specify *burst*, it must be non-zero value.
.limit statement values
[options="header"]
diff --git a/include/cli.h b/include/cli.h
index d8251775..609ed2ed 100644
--- a/include/cli.h
+++ b/include/cli.h
@@ -4,7 +4,7 @@
#include <nftables/libnftables.h>
#include <config.h>
-#if defined(HAVE_LIBREADLINE) || defined(HAVE_LIBLINENOISE)
+#if defined(HAVE_LIBREADLINE) || defined(HAVE_LIBEDIT) || defined(HAVE_LIBLINENOISE)
extern int cli_init(struct nft_ctx *nft);
#else
static inline int cli_init(struct nft_ctx *nft)
diff --git a/include/expression.h b/include/expression.h
index 894a68d2..2d07f3d9 100644
--- a/include/expression.h
+++ b/include/expression.h
@@ -93,6 +93,7 @@ enum ops {
OP_GT,
OP_LTE,
OP_GTE,
+ OP_NEG,
__OP_MAX
};
#define OP_MAX (__OP_MAX - 1)
@@ -280,7 +281,7 @@ struct expr {
uint64_t timeout;
uint64_t expiration;
const char *comment;
- struct stmt *stmt;
+ struct list_head stmt_list;
uint32_t elem_flags;
};
struct {
diff --git a/include/exthdr.h b/include/exthdr.h
index c9a3c211..1bc756f9 100644
--- a/include/exthdr.h
+++ b/include/exthdr.h
@@ -30,7 +30,6 @@ struct exthdr_desc {
const char *name;
enum exthdr_desc_id id;
uint8_t type;
- int proto_key;
struct proto_hdr_template templates[10];
};
diff --git a/include/json.h b/include/json.h
index 20d6c2a4..41142208 100644
--- a/include/json.h
+++ b/include/json.h
@@ -111,6 +111,7 @@ void monitor_print_rule_json(struct netlink_mon_handler *monh,
int json_events_cb(const struct nlmsghdr *nlh,
struct netlink_mon_handler *monh);
+void json_alloc_echo(struct nft_ctx *ctx);
void json_print_echo(struct nft_ctx *ctx);
#else /* ! HAVE_LIBJANSSON */
@@ -251,6 +252,11 @@ static inline int json_events_cb(const struct nlmsghdr *nlh,
return -1;
}
+static inline void json_alloc_echo(struct nft_ctx *ctx)
+{
+ /* empty */
+}
+
static inline void json_print_echo(struct nft_ctx *ctx)
{
/* empty */
diff --git a/include/linux/netfilter/nf_tables.h b/include/linux/netfilter/nf_tables.h
index 0b5fd5d5..b1633e7b 100644
--- a/include/linux/netfilter/nf_tables.h
+++ b/include/linux/netfilter/nf_tables.h
@@ -133,7 +133,7 @@ enum nf_tables_msg_types {
* @NFTA_LIST_ELEM: list element (NLA_NESTED)
*/
enum nft_list_attributes {
- NFTA_LIST_UNPEC,
+ NFTA_LIST_UNSPEC,
NFTA_LIST_ELEM,
__NFTA_LIST_MAX
};
@@ -172,6 +172,7 @@ enum nft_table_flags {
* @NFTA_TABLE_NAME: name of the table (NLA_STRING)
* @NFTA_TABLE_FLAGS: bitmask of enum nft_table_flags (NLA_U32)
* @NFTA_TABLE_USE: number of chains in this table (NLA_U32)
+ * @NFTA_TABLE_USERDATA: user data (NLA_BINARY)
*/
enum nft_table_attributes {
NFTA_TABLE_UNSPEC,
@@ -180,10 +181,20 @@ enum nft_table_attributes {
NFTA_TABLE_USE,
NFTA_TABLE_HANDLE,
NFTA_TABLE_PAD,
+ NFTA_TABLE_USERDATA,
__NFTA_TABLE_MAX
};
#define NFTA_TABLE_MAX (__NFTA_TABLE_MAX - 1)
+enum nft_chain_flags {
+ NFT_CHAIN_BASE = (1 << 0),
+ NFT_CHAIN_HW_OFFLOAD = (1 << 1),
+ NFT_CHAIN_BINDING = (1 << 2),
+};
+#define NFT_CHAIN_FLAGS (NFT_CHAIN_BASE | \
+ NFT_CHAIN_HW_OFFLOAD | \
+ NFT_CHAIN_BINDING)
+
/**
* enum nft_chain_attributes - nf_tables chain netlink attributes
*
@@ -196,6 +207,8 @@ enum nft_table_attributes {
* @NFTA_CHAIN_TYPE: type name of the string (NLA_NUL_STRING)
* @NFTA_CHAIN_COUNTERS: counter specification of the chain (NLA_NESTED: nft_counter_attributes)
* @NFTA_CHAIN_FLAGS: chain flags
+ * @NFTA_CHAIN_ID: uniquely identifies a chain in a transaction (NLA_U32)
+ * @NFTA_CHAIN_USERDATA: user data (NLA_BINARY)
*/
enum nft_chain_attributes {
NFTA_CHAIN_UNSPEC,
@@ -210,6 +223,7 @@ enum nft_chain_attributes {
NFTA_CHAIN_PAD,
NFTA_CHAIN_FLAGS,
NFTA_CHAIN_ID,
+ NFTA_CHAIN_USERDATA,
__NFTA_CHAIN_MAX
};
#define NFTA_CHAIN_MAX (__NFTA_CHAIN_MAX - 1)
@@ -279,6 +293,7 @@ enum nft_rule_compat_attributes {
* @NFT_SET_EVAL: set can be updated from the evaluation path
* @NFT_SET_OBJECT: set contains stateful objects
* @NFT_SET_CONCAT: set contains a concatenation
+ * @NFT_SET_EXPR: set contains expressions
*/
enum nft_set_flags {
NFT_SET_ANONYMOUS = 0x1,
@@ -289,6 +304,7 @@ enum nft_set_flags {
NFT_SET_EVAL = 0x20,
NFT_SET_OBJECT = 0x40,
NFT_SET_CONCAT = 0x80,
+ NFT_SET_EXPR = 0x100,
};
/**
@@ -347,6 +363,7 @@ enum nft_set_field_attributes {
* @NFTA_SET_OBJ_TYPE: stateful object type (NLA_U32: NFT_OBJECT_*)
* @NFTA_SET_HANDLE: set handle (NLA_U64)
* @NFTA_SET_EXPR: set expression (NLA_NESTED: nft_expr_attributes)
+ * @NFTA_SET_EXPRESSIONS: list of expressions (NLA_NESTED: nft_list_attributes)
*/
enum nft_set_attributes {
NFTA_SET_UNSPEC,
@@ -367,6 +384,7 @@ enum nft_set_attributes {
NFTA_SET_OBJ_TYPE,
NFTA_SET_HANDLE,
NFTA_SET_EXPR,
+ NFTA_SET_EXPRESSIONS,
__NFTA_SET_MAX
};
#define NFTA_SET_MAX (__NFTA_SET_MAX - 1)
@@ -392,6 +410,7 @@ enum nft_set_elem_flags {
* @NFTA_SET_ELEM_EXPR: expression (NLA_NESTED: nft_expr_attributes)
* @NFTA_SET_ELEM_OBJREF: stateful object reference (NLA_STRING)
* @NFTA_SET_ELEM_KEY_END: closing key value (NLA_NESTED: nft_data)
+ * @NFTA_SET_ELEM_EXPRESSIONS: list of expressions (NLA_NESTED: nft_list_attributes)
*/
enum nft_set_elem_attributes {
NFTA_SET_ELEM_UNSPEC,
@@ -405,6 +424,7 @@ enum nft_set_elem_attributes {
NFTA_SET_ELEM_PAD,
NFTA_SET_ELEM_OBJREF,
NFTA_SET_ELEM_KEY_END,
+ NFTA_SET_ELEM_EXPRESSIONS,
__NFTA_SET_ELEM_MAX
};
#define NFTA_SET_ELEM_MAX (__NFTA_SET_ELEM_MAX - 1)
@@ -470,11 +490,13 @@ enum nft_data_attributes {
*
* @NFTA_VERDICT_CODE: nf_tables verdict (NLA_U32: enum nft_verdicts)
* @NFTA_VERDICT_CHAIN: jump target chain name (NLA_STRING)
+ * @NFTA_VERDICT_CHAIN_ID: jump target chain ID (NLA_U32)
*/
enum nft_verdict_attributes {
NFTA_VERDICT_UNSPEC,
NFTA_VERDICT_CODE,
NFTA_VERDICT_CHAIN,
+ NFTA_VERDICT_CHAIN_ID,
__NFTA_VERDICT_MAX
};
#define NFTA_VERDICT_MAX (__NFTA_VERDICT_MAX - 1)
@@ -686,6 +708,7 @@ enum nft_dynset_ops {
enum nft_dynset_flags {
NFT_DYNSET_F_INV = (1 << 0),
+ NFT_DYNSET_F_EXPR = (1 << 1),
};
/**
@@ -699,6 +722,7 @@ enum nft_dynset_flags {
* @NFTA_DYNSET_TIMEOUT: timeout value for the new element (NLA_U64)
* @NFTA_DYNSET_EXPR: expression (NLA_NESTED: nft_expr_attributes)
* @NFTA_DYNSET_FLAGS: flags (NLA_U32)
+ * @NFTA_DYNSET_EXPRESSIONS: list of expressions (NLA_NESTED: nft_list_attributes)
*/
enum nft_dynset_attributes {
NFTA_DYNSET_UNSPEC,
@@ -711,6 +735,7 @@ enum nft_dynset_attributes {
NFTA_DYNSET_EXPR,
NFTA_DYNSET_PAD,
NFTA_DYNSET_FLAGS,
+ NFTA_DYNSET_EXPRESSIONS,
__NFTA_DYNSET_MAX,
};
#define NFTA_DYNSET_MAX (__NFTA_DYNSET_MAX - 1)
@@ -1547,6 +1572,7 @@ enum nft_ct_expectation_attributes {
* @NFTA_OBJ_DATA: stateful object data (NLA_NESTED)
* @NFTA_OBJ_USE: number of references to this expression (NLA_U32)
* @NFTA_OBJ_HANDLE: object handle (NLA_U64)
+ * @NFTA_OBJ_USERDATA: user data (NLA_BINARY)
*/
enum nft_object_attributes {
NFTA_OBJ_UNSPEC,
@@ -1557,6 +1583,7 @@ enum nft_object_attributes {
NFTA_OBJ_USE,
NFTA_OBJ_HANDLE,
NFTA_OBJ_PAD,
+ NFTA_OBJ_USERDATA,
__NFTA_OBJ_MAX
};
#define NFTA_OBJ_MAX (__NFTA_OBJ_MAX - 1)
diff --git a/include/list.h b/include/list.h
index 9c4da817..857921e3 100644
--- a/include/list.h
+++ b/include/list.h
@@ -348,6 +348,13 @@ static inline void list_splice_tail_init(struct list_head *list,
#define list_first_entry(ptr, type, member) \
list_entry((ptr)->next, type, member)
+/**
+ * list_next_entry - get the next element in list
+ * @pos: the type * to cursor
+ * @member: the name of the list_head within the struct.
+ */
+#define list_next_entry(pos, member) \
+ list_entry((pos)->member.next, typeof(*(pos)), member)
/**
* list_for_each_entry - iterate over list of given type
diff --git a/include/nftables.h b/include/nftables.h
index 3556728d..9095ff3d 100644
--- a/include/nftables.h
+++ b/include/nftables.h
@@ -122,6 +122,7 @@ struct nft_ctx {
void *scanner;
struct scope *top_scope;
void *json_root;
+ json_t *json_echo;
};
enum nftables_exit_codes {
diff --git a/include/owner.h b/include/owner.h
new file mode 100644
index 00000000..85d821cc
--- /dev/null
+++ b/include/owner.h
@@ -0,0 +1,6 @@
+#ifndef _NFT_OWNER_H_
+#define _NFT_OWNER_H_
+
+char *get_progname(uint32_t portid);
+
+#endif
diff --git a/include/payload.h b/include/payload.h
index a914d239..8bc3fb9a 100644
--- a/include/payload.h
+++ b/include/payload.h
@@ -15,6 +15,9 @@ struct eval_ctx;
struct stmt;
extern int payload_gen_dependency(struct eval_ctx *ctx, const struct expr *expr,
struct stmt **res);
+extern int payload_gen_icmp_dependency(struct eval_ctx *ctx,
+ const struct expr *expr,
+ struct stmt **res);
extern int exthdr_gen_dependency(struct eval_ctx *ctx, const struct expr *expr,
const struct proto_desc *dependency,
enum proto_bases pb, struct stmt **res);
@@ -23,11 +26,13 @@ extern int exthdr_gen_dependency(struct eval_ctx *ctx, const struct expr *expr,
* struct payload_dep_ctx - payload protocol dependency tracking
*
* @pbase: protocol base of last dependency match
+ * @icmp_type: extra info for icmp(6) decoding
* @pdep: last dependency match
* @prev: previous statement
*/
struct payload_dep_ctx {
- enum proto_bases pbase;
+ enum proto_bases pbase:8;
+ uint8_t icmp_type;
struct stmt *pdep;
struct stmt *prev;
};
diff --git a/include/proto.h b/include/proto.h
index 6ef332c3..b9217588 100644
--- a/include/proto.h
+++ b/include/proto.h
@@ -25,6 +25,17 @@ enum proto_bases {
extern const char *proto_base_names[];
extern const char *proto_base_tokens[];
+enum icmp_hdr_field_type {
+ PROTO_ICMP_ANY = 0,
+ PROTO_ICMP_ECHO, /* echo and reply */
+ PROTO_ICMP_MTU, /* destination unreachable */
+ PROTO_ICMP_ADDRESS, /* redirect */
+ PROTO_ICMP6_MTU,
+ PROTO_ICMP6_PPTR,
+ PROTO_ICMP6_ECHO,
+ PROTO_ICMP6_MGMQ,
+};
+
/**
* struct proto_hdr_template - protocol header field description
*
@@ -33,14 +44,16 @@ extern const char *proto_base_tokens[];
* @offset: offset of the header field from base
* @len: length of header field
* @meta_key: special case: meta expression key
+ * @icmp_dep: special case: icmp header dependency
*/
struct proto_hdr_template {
const char *token;
const struct datatype *dtype;
uint16_t offset;
uint16_t len;
- enum byteorder byteorder;
- enum nft_meta_keys meta_key;
+ enum byteorder byteorder:8;
+ enum nft_meta_keys meta_key:8;
+ enum icmp_hdr_field_type icmp_dep:8;
};
#define PROTO_HDR_TEMPLATE(__token, __dtype, __byteorder, __offset, __len)\
@@ -101,11 +114,11 @@ enum proto_desc_id {
*/
struct proto_desc {
const char *name;
- enum proto_desc_id id;
- enum proto_bases base;
- enum nft_payload_csum_types checksum_type;
- unsigned int checksum_key;
- unsigned int protocol_key;
+ enum proto_desc_id id:8;
+ enum proto_bases base:8;
+ enum nft_payload_csum_types checksum_type:8;
+ uint16_t checksum_key;
+ uint16_t protocol_key;
unsigned int length;
struct {
unsigned int num;
@@ -170,7 +183,12 @@ extern const struct proto_desc *proto_dev_desc(uint16_t type);
*/
struct proto_ctx {
unsigned int debug_mask;
- unsigned int family;
+ uint8_t family;
+ union {
+ struct {
+ uint8_t type;
+ } icmp;
+ } th_dep;
struct {
struct location location;
const struct proto_desc *desc;
diff --git a/include/rule.h b/include/rule.h
index 119fc19d..523435f6 100644
--- a/include/rule.h
+++ b/include/rule.h
@@ -131,10 +131,11 @@ struct symbol *symbol_get(const struct scope *scope, const char *identifier);
enum table_flags {
TABLE_F_DORMANT = (1 << 0),
+ TABLE_F_OWNER = (1 << 1),
};
-#define TABLE_FLAGS_MAX 1
+#define TABLE_FLAGS_MAX 2
-extern const char *table_flags_name[TABLE_FLAGS_MAX];
+const char *table_flag_name(uint32_t flag);
/**
* struct table - nftables table
@@ -162,6 +163,7 @@ struct table {
struct list_head chain_bindings;
enum table_flags flags;
unsigned int refcnt;
+ uint32_t owner;
const char *comment;
};
@@ -333,7 +335,7 @@ struct set {
struct expr *init;
struct expr *rg_cache;
uint32_t policy;
- struct stmt *stmt;
+ struct list_head stmt_list;
bool root;
bool automerge;
bool key_typeof_valid;
diff --git a/include/statement.h b/include/statement.h
index f2fc6ade..7637a82e 100644
--- a/include/statement.h
+++ b/include/statement.h
@@ -201,7 +201,7 @@ uint32_t fwd_stmt_type(const char *type);
struct set_stmt {
struct expr *set;
struct expr *key;
- struct stmt *stmt;
+ struct list_head stmt_list;
enum nft_dynset_ops op;
};
@@ -213,7 +213,7 @@ struct map_stmt {
struct expr *set;
struct expr *key;
struct expr *data;
- struct stmt *stmt;
+ struct list_head stmt_list;
enum nft_dynset_ops op;
};
diff --git a/src/Makefile.am b/src/Makefile.am
index 3041a933..2f6d434b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -61,6 +61,7 @@ libnftables_la_SOURCES = \
netlink_delinearize.c \
misspell.c \
monitor.c \
+ owner.c \
segtree.c \
rbtree.c \
gmputil.c \
diff --git a/src/cli.c b/src/cli.c
index 4c0c3e9d..4845e5cf 100644
--- a/src/cli.c
+++ b/src/cli.c
@@ -24,6 +24,9 @@
#ifdef HAVE_LIBREADLINE
#include <readline/readline.h>
#include <readline/history.h>
+#elif defined(HAVE_LIBEDIT)
+#include <editline/readline.h>
+#include <editline/history.h>
#else
#include <linenoise.h>
#endif
@@ -48,7 +51,26 @@ init_histfile(void)
snprintf(histfile, sizeof(histfile), "%s/%s", home, CMDLINE_HISTFILE);
}
-#ifdef HAVE_LIBREADLINE
+#if defined(HAVE_LIBREADLINE)
+static void nft_rl_prompt_save(void)
+{
+ rl_save_prompt();
+ rl_clear_message();
+ rl_set_prompt(".... ");
+}
+#define nft_rl_prompt_restore rl_restore_prompt
+#elif defined(HAVE_LIBEDIT)
+static void nft_rl_prompt_save(void)
+{
+ rl_set_prompt(".... ");
+}
+static void nft_rl_prompt_restore(void)
+{
+ rl_set_prompt("nft> ");
+}
+#endif
+
+#if defined(HAVE_LIBREADLINE) || defined(HAVE_LIBEDIT)
static struct nft_ctx *cli_nft;
static char *multiline;
@@ -72,9 +94,7 @@ static char *cli_append_multiline(char *line)
if (multiline == NULL) {
multiline = line;
- rl_save_prompt();
- rl_clear_message();
- rl_set_prompt(".... ");
+ nft_rl_prompt_save();
} else {
len += strlen(multiline);
s = malloc(len + 1);
@@ -93,7 +113,7 @@ static char *cli_append_multiline(char *line)
if (complete) {
line = multiline;
multiline = NULL;
- rl_restore_prompt();
+ nft_rl_prompt_restore();
}
return line;
}
@@ -134,6 +154,16 @@ static void cli_complete(char *line)
free(line);
}
+void cli_exit(void)
+{
+ rl_callback_handler_remove();
+ rl_deprep_terminal();
+ write_history(histfile);
+}
+#endif
+
+#if defined(HAVE_LIBREADLINE)
+
static char **cli_completion(const char *text, int start, int end)
{
return NULL;
@@ -142,7 +172,7 @@ static char **cli_completion(const char *text, int start, int end)
int cli_init(struct nft_ctx *nft)
{
cli_nft = nft;
- rl_readline_name = "nft";
+ rl_readline_name = (char *)"nft";
rl_instream = stdin;
rl_outstream = stdout;
@@ -159,14 +189,35 @@ int cli_init(struct nft_ctx *nft)
return 0;
}
-void cli_exit(void)
+#elif defined(HAVE_LIBEDIT)
+
+int cli_init(struct nft_ctx *nft)
{
- rl_callback_handler_remove();
- rl_deprep_terminal();
- write_history(histfile);
+ char *line;
+
+ cli_nft = nft;
+ rl_readline_name = (char *)"nft";
+ rl_instream = stdin;
+ rl_outstream = stdout;
+
+ init_histfile();
+
+ read_history(histfile);
+ history_set_pos(history_length);
+
+ rl_set_prompt(CMDLINE_PROMPT);
+ while ((line = readline(rl_prompt)) != NULL) {
+ line = cli_append_multiline(line);
+ if (!line)
+ continue;
+
+ cli_complete(line);
+ }
+
+ return 0;
}
-#else /* !HAVE_LIBREADLINE */
+#else /* HAVE_LINENOISE */
int cli_init(struct nft_ctx *nft)
{
@@ -195,4 +246,4 @@ void cli_exit(void)
linenoiseHistorySave(histfile);
}
-#endif /* HAVE_LIBREADLINE */
+#endif /* HAVE_LINENOISE */
diff --git a/src/erec.c b/src/erec.c
index c550a596..5c3351a5 100644
--- a/src/erec.c
+++ b/src/erec.c
@@ -38,7 +38,8 @@ void erec_add_location(struct error_record *erec, const struct location *loc)
{
assert(erec->num_locations < EREC_LOCATIONS_MAX);
erec->locations[erec->num_locations] = *loc;
- erec->locations[erec->num_locations].indesc = loc->indesc;
+ erec->locations[erec->num_locations].indesc = loc->indesc ?
+ : &internal_indesc;
erec->num_locations++;
}
diff --git a/src/evaluate.c b/src/evaluate.c
index 76b25b40..cebf7cb8 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -580,9 +580,7 @@ static int expr_evaluate_exthdr(struct eval_ctx *ctx, struct expr **exprp)
switch (expr->exthdr.op) {
case NFT_EXTHDR_OP_TCPOPT:
- dependency = &proto_tcp;
- pb = PROTO_BASE_TRANSPORT_HDR;
- break;
+ return __expr_evaluate_exthdr(ctx, exprp);
case NFT_EXTHDR_OP_IPV4:
dependency = &proto_ip;
break;
@@ -706,7 +704,8 @@ static int __expr_evaluate_payload(struct eval_ctx *ctx, struct expr *expr)
return -1;
rule_stmt_insert_at(ctx->rule, nstmt, ctx->stmt);
- return 0;
+ desc = ctx->pctx.protocol[base].desc;
+ goto check_icmp;
}
if (payload->payload.base == desc->base &&
@@ -724,7 +723,24 @@ static int __expr_evaluate_payload(struct eval_ctx *ctx, struct expr *expr)
* if needed.
*/
if (desc == payload->payload.desc) {
+ const struct proto_hdr_template *tmpl;
+
payload->payload.offset += ctx->pctx.protocol[base].offset;
+check_icmp:
+ if (desc != &proto_icmp && desc != &proto_icmp6)
+ return 0;
+
+ tmpl = expr->payload.tmpl;
+
+ if (!tmpl || !tmpl->icmp_dep)
+ return 0;
+
+ if (payload_gen_icmp_dependency(ctx, expr, &nstmt) < 0)
+ return -1;
+
+ if (nstmt)
+ rule_stmt_insert_at(ctx->rule, nstmt, ctx->stmt);
+
return 0;
}
/* If we already have context and this payload is on the same
@@ -1248,6 +1264,12 @@ static int expr_evaluate_concat(struct eval_ctx *ctx, struct expr **expr,
list_for_each_entry_safe(i, next, &(*expr)->expressions, list) {
unsigned dsize_bytes;
+ if (i->etype == EXPR_CT &&
+ (i->ct.key == NFT_CT_SRC ||
+ i->ct.key == NFT_CT_DST))
+ return expr_error(ctx->msgs, i,
+ "specify either ip or ip6 for address matching");
+
if (expr_is_constant(*expr) && dtype && off == 0)
return expr_binary_error(ctx->msgs, i, *expr,
"unexpected concat component, "
@@ -1322,27 +1344,65 @@ static int expr_evaluate_list(struct eval_ctx *ctx, struct expr **expr)
return 0;
}
-static int expr_evaluate_set_elem(struct eval_ctx *ctx, struct expr **expr)
+static int __expr_evaluate_set_elem(struct eval_ctx *ctx, struct expr *elem)
{
+ int num_elem_exprs = 0, num_set_exprs = 0;
struct set *set = ctx->set;
- struct expr *elem = *expr;
+ struct stmt *stmt;
+
+ list_for_each_entry(stmt, &elem->stmt_list, list)
+ num_elem_exprs++;
+ list_for_each_entry(stmt, &set->stmt_list, list)
+ num_set_exprs++;
+
+ if (num_elem_exprs > 0) {
+ struct stmt *set_stmt, *elem_stmt;
- if (elem->stmt) {
- if (set->stmt && set->stmt->ops != elem->stmt->ops) {
- return stmt_error(ctx, elem->stmt,
- "statement mismatch, element expects %s, "
- "but %s has type %s",
- elem->stmt->ops->name,
- set_is_map(set->flags) ? "map" : "set",
- set->stmt->ops->name);
- } else if (!set->stmt && !(set->flags & NFT_SET_EVAL)) {
- return stmt_error(ctx, elem->stmt,
- "missing %s statement in %s definition",
- elem->stmt->ops->name,
- set_is_map(set->flags) ? "map" : "set");
+ if (num_set_exprs > 0 && num_elem_exprs != num_set_exprs) {
+ return expr_error(ctx->msgs, elem,
+ "number of statements mismatch, set expects %d "
+ "but element has %d", num_set_exprs,
+ num_elem_exprs);
+ } else if (num_set_exprs == 0) {
+ if (!(set->flags & NFT_SET_EVAL))
+ return expr_error(ctx->msgs, elem,
+ "missing statements in %s definition",
+ set_is_map(set->flags) ? "map" : "set");
+ return 0;
+ }
+
+ set_stmt = list_first_entry(&set->stmt_list, struct stmt, list);
+
+ list_for_each_entry(elem_stmt, &elem->stmt_list, list) {
+ if (set_stmt->ops != elem_stmt->ops) {
+ return stmt_error(ctx, elem_stmt,
+ "statement mismatch, element expects %s, "
+ "but %s has type %s",
+ elem_stmt->ops->name,
+ set_is_map(set->flags) ? "map" : "set",
+ set_stmt->ops->name);
+ }
+ set_stmt = list_next_entry(set_stmt, list);
}
}
+ return 0;
+}
+
+static int expr_evaluate_set_elem(struct eval_ctx *ctx, struct expr **expr)
+{
+ struct expr *elem = *expr;
+
+ if (ctx->set) {
+ const struct expr *key;
+
+ if (__expr_evaluate_set_elem(ctx, elem) < 0)
+ return -1;
+
+ key = ctx->set->key;
+ __expr_set_context(&ctx->ectx, key->dtype, key->byteorder, key->len, 0);
+ }
+
if (expr_evaluate(ctx, &elem->key) < 0)
return -1;
@@ -1425,6 +1485,23 @@ static int expr_evaluate_map(struct eval_ctx *ctx, struct expr **expr)
const struct datatype *dtype;
struct expr *key, *data;
+ if (map->map->etype == EXPR_CT &&
+ (map->map->ct.key == NFT_CT_SRC ||
+ map->map->ct.key == NFT_CT_DST))
+ return expr_error(ctx->msgs, map->map,
+ "specify either ip or ip6 for address matching");
+ else if (map->map->etype == EXPR_CONCAT) {
+ struct expr *i;
+
+ list_for_each_entry(i, &map->map->expressions, list) {
+ if (i->etype == EXPR_CT &&
+ (i->ct.key == NFT_CT_SRC ||
+ i->ct.key == NFT_CT_DST))
+ return expr_error(ctx->msgs, i,
+ "specify either ip or ip6 for address matching");
+ }
+ }
+
expr_set_context(&ctx->ectx, NULL, 0);
if (expr_evaluate(ctx, &map->map) < 0)
return -1;
@@ -1528,7 +1605,7 @@ static int expr_evaluate_mapping(struct eval_ctx *ctx, struct expr **expr)
else
datalen = set->data->len;
- expr_set_context(&ctx->ectx, set->data->dtype, datalen);
+ __expr_set_context(&ctx->ectx, set->data->dtype, set->data->byteorder, datalen, 0);
} else {
assert((set->flags & NFT_SET_MAP) == 0);
}
@@ -1888,6 +1965,14 @@ static int expr_evaluate_relational(struct eval_ctx *ctx, struct expr **expr)
/* fall through */
case OP_NEQ:
+ case OP_NEG:
+ if (rel->op == OP_NEG &&
+ (right->etype != EXPR_VALUE ||
+ right->dtype->basetype == NULL ||
+ right->dtype->basetype->type != TYPE_BITMASK))
+ return expr_binary_error(ctx->msgs, left, right,
+ "negation can only be used with singleton bitmask values");
+
switch (right->etype) {
case EXPR_RANGE:
if (byteorder_conversion(ctx, &rel->left, BYTEORDER_BIG_ENDIAN) < 0)
@@ -2650,10 +2735,9 @@ static int stmt_evaluate_reject_bridge(struct eval_ctx *ctx, struct stmt *stmt,
const struct proto_desc *desc;
desc = ctx->pctx.protocol[PROTO_BASE_LL_HDR].desc;
- if (desc != &proto_eth && desc != &proto_vlan)
- return stmt_binary_error(ctx,
- &ctx->pctx.protocol[PROTO_BASE_LL_HDR],
- stmt, "unsupported link layer protocol");
+ if (desc != &proto_eth && desc != &proto_vlan && desc != &proto_netdev)
+ return __stmt_binary_error(ctx, &stmt->location, NULL,
+ "cannot reject from this link layer protocol");
desc = ctx->pctx.protocol[PROTO_BASE_NETWORK_HDR].desc;
if (desc != NULL &&
@@ -2690,6 +2774,7 @@ static int stmt_evaluate_reject_family(struct eval_ctx *ctx, struct stmt *stmt,
}
break;
case NFPROTO_BRIDGE:
+ case NFPROTO_NETDEV:
if (stmt_evaluate_reject_bridge(ctx, stmt, expr) < 0)
return -1;
break;
@@ -3352,6 +3437,8 @@ static int stmt_evaluate_log(struct eval_ctx *ctx, struct stmt *stmt)
static int stmt_evaluate_set(struct eval_ctx *ctx, struct stmt *stmt)
{
+ struct stmt *this;
+
expr_set_context(&ctx->ectx, NULL, 0);
if (expr_evaluate(ctx, &stmt->set.set) < 0)
return -1;
@@ -3371,12 +3458,12 @@ static int stmt_evaluate_set(struct eval_ctx *ctx, struct stmt *stmt)
if (stmt->set.key->comment != NULL)
return expr_error(ctx->msgs, stmt->set.key,
"Key expression comments are not supported");
- if (stmt->set.stmt) {
- if (stmt_evaluate(ctx, stmt->set.stmt) < 0)
+ list_for_each_entry(this, &stmt->set.stmt_list, list) {
+ if (stmt_evaluate(ctx, this) < 0)
return -1;
- if (!(stmt->set.stmt->flags & STMT_F_STATEFUL))
- return stmt_binary_error(ctx, stmt->set.stmt, stmt,
- "meter statement must be stateful");
+ if (!(this->flags & STMT_F_STATEFUL))
+ return stmt_error(ctx, this,
+ "statement must be stateful");
}
return 0;
@@ -3384,6 +3471,8 @@ static int stmt_evaluate_set(struct eval_ctx *ctx, struct stmt *stmt)
static int stmt_evaluate_map(struct eval_ctx *ctx, struct stmt *stmt)
{
+ struct stmt *this;
+
expr_set_context(&ctx->ectx, NULL, 0);
if (expr_evaluate(ctx, &stmt->map.set) < 0)
return -1;
@@ -3417,12 +3506,12 @@ static int stmt_evaluate_map(struct eval_ctx *ctx, struct stmt *stmt)
return expr_error(ctx->msgs, stmt->map.data,
"Data expression comments are not supported");
- if (stmt->map.stmt) {
- if (stmt_evaluate(ctx, stmt->map.stmt) < 0)
+ list_for_each_entry(this, &stmt->map.stmt_list, list) {
+ if (stmt_evaluate(ctx, this) < 0)
return -1;
- if (!(stmt->map.stmt->flags & STMT_F_STATEFUL))
- return stmt_binary_error(ctx, stmt->map.stmt, stmt,
- "meter statement must be stateful");
+ if (!(this->flags & STMT_F_STATEFUL))
+ return stmt_error(ctx, this,
+ "statement must be stateful");
}
return 0;
@@ -3620,7 +3709,9 @@ static int set_key_data_error(struct eval_ctx *ctx, const struct set *set,
static int set_evaluate(struct eval_ctx *ctx, struct set *set)
{
+ unsigned int num_stmts = 0;
struct table *table;
+ struct stmt *stmt;
const char *type;
table = table_lookup_global(ctx);
@@ -3681,6 +3772,12 @@ static int set_evaluate(struct eval_ctx *ctx, struct set *set)
if (set->timeout)
set->flags |= NFT_SET_TIMEOUT;
+ list_for_each_entry(stmt, &set->stmt_list, list)
+ num_stmts++;
+
+ if (num_stmts > 1)
+ set->flags |= NFT_SET_EXPR;
+
if (set_is_anonymous(set->flags))
return 0;
@@ -3709,8 +3806,8 @@ static bool evaluate_priority(struct eval_ctx *ctx, struct prio_spec *prio,
int prio_snd;
char op;
- ctx->ectx.dtype = &priority_type;
- ctx->ectx.len = NFT_NAME_MAXLEN * BITS_PER_BYTE;
+ expr_set_context(&ctx->ectx, &priority_type, NFT_NAME_MAXLEN * BITS_PER_BYTE);
+
if (expr_evaluate(ctx, &prio->expr) < 0)
return false;
if (prio->expr->etype != EXPR_VALUE) {
diff --git a/src/expression.c b/src/expression.c
index 87bd4d01..8c6beef9 100644
--- a/src/expression.c
+++ b/src/expression.c
@@ -252,6 +252,21 @@ static void verdict_expr_destroy(struct expr *expr)
expr_free(expr->chain);
}
+static int verdict_expr_build_udata(struct nftnl_udata_buf *udbuf,
+ const struct expr *expr)
+{
+ return 0;
+}
+
+static struct expr *verdict_expr_parse_udata(const struct nftnl_udata *attr)
+{
+ struct expr *e = verdict_expr_alloc(&internal_location, 0, NULL);
+
+ e = symbol_expr_alloc(&internal_location, SYMBOL_VALUE, NULL, "verdict");
+ e->len = NFT_REG_SIZE * BITS_PER_BYTE;
+ return e;
+}
+
static const struct expr_ops verdict_expr_ops = {
.type = EXPR_VERDICT,
.name = "verdict",
@@ -260,6 +275,8 @@ static const struct expr_ops verdict_expr_ops = {
.cmp = verdict_expr_cmp,
.clone = verdict_expr_clone,
.destroy = verdict_expr_destroy,
+ .build_udata = verdict_expr_build_udata,
+ .parse_udata = verdict_expr_parse_udata,
};
struct expr *verdict_expr_alloc(const struct location *loc,
@@ -560,6 +577,7 @@ const char *expr_op_symbols[] = {
[OP_GT] = ">",
[OP_LTE] = "<=",
[OP_GTE] = ">=",
+ [OP_NEG] = "!",
};
static void unary_expr_print(const struct expr *expr, struct output_ctx *octx)
@@ -1248,7 +1266,13 @@ struct expr *set_ref_expr_alloc(const struct location *loc, struct set *set)
static void set_elem_expr_print(const struct expr *expr,
struct output_ctx *octx)
{
+ struct stmt *stmt;
+
expr_print(expr->key, octx);
+ list_for_each_entry(stmt, &expr->stmt_list, list) {
+ nft_print(octx, " ");
+ stmt_print(stmt, octx);
+ }
if (expr->timeout) {
nft_print(octx, " timeout ");
time_print(expr->timeout, octx);
@@ -1257,19 +1281,18 @@ static void set_elem_expr_print(const struct expr *expr,
nft_print(octx, " expires ");
time_print(expr->expiration, octx);
}
- if (expr->stmt) {
- nft_print(octx, " ");
- stmt_print(expr->stmt, octx);
- }
if (expr->comment)
nft_print(octx, " comment \"%s\"", expr->comment);
}
static void set_elem_expr_destroy(struct expr *expr)
{
+ struct stmt *stmt, *next;
+
xfree(expr->comment);
expr_free(expr->key);
- stmt_free(expr->stmt);
+ list_for_each_entry_safe(stmt, next, &expr->stmt_list, list)
+ stmt_free(stmt);
}
static void set_elem_expr_clone(struct expr *new, const struct expr *expr)
@@ -1279,6 +1302,7 @@ static void set_elem_expr_clone(struct expr *new, const struct expr *expr)
new->timeout = expr->timeout;
if (expr->comment)
new->comment = xstrdup(expr->comment);
+ init_list_head(&new->stmt_list);
}
static const struct expr_ops set_elem_expr_ops = {
@@ -1297,6 +1321,8 @@ struct expr *set_elem_expr_alloc(const struct location *loc, struct expr *key)
expr = expr_alloc(loc, EXPR_SET_ELEM, key->dtype,
key->byteorder, key->len);
expr->key = key;
+ init_list_head(&expr->stmt_list);
+
return expr;
}
diff --git a/src/exthdr.c b/src/exthdr.c
index 5eb66529..b0243ada 100644
--- a/src/exthdr.c
+++ b/src/exthdr.c
@@ -409,7 +409,6 @@ const struct exthdr_desc exthdr_rt2 = {
.name = "rt2",
.id = EXTHDR_DESC_RT2,
.type = IPPROTO_ROUTING,
- .proto_key = 2,
.templates = {
[RT2HDR_RESERVED] = {},
[RT2HDR_ADDR] = {},
@@ -423,7 +422,6 @@ const struct exthdr_desc exthdr_rt0 = {
.name = "rt0",
.id = EXTHDR_DESC_RT0,
.type = IPPROTO_ROUTING,
- .proto_key = 0,
.templates = {
[RT0HDR_RESERVED] = RT0_FIELD("reserved", ip6r0_reserved, &integer_type),
[RT0HDR_ADDR_1] = RT0_FIELD("addr[1]", ip6r0_addr[0], &ip6addr_type),
@@ -439,7 +437,6 @@ const struct exthdr_desc exthdr_rt4 = {
.name = "srh",
.id = EXTHDR_DESC_SRH,
.type = IPPROTO_ROUTING,
- .proto_key = 4,
.templates = {
[RT4HDR_LASTENT] = RT4_FIELD("last-entry", ip6r4_last_entry, &integer_type),
[RT4HDR_FLAGS] = RT4_FIELD("flags", ip6r4_flags, &integer_type),
@@ -458,7 +455,6 @@ const struct exthdr_desc exthdr_rt = {
.name = "rt",
.id = EXTHDR_DESC_RT,
.type = IPPROTO_ROUTING,
- .proto_key = -1,
#if 0
.protocol_key = RTHDR_TYPE,
.protocols = {
diff --git a/src/json.c b/src/json.c
index ac3b1c83..defbc8fb 100644
--- a/src/json.c
+++ b/src/json.c
@@ -444,7 +444,7 @@ static json_t *table_flags_json(const struct table *table)
while (flags) {
if (flags & 0x1) {
- tmp = json_string(table_flags_name[i]);
+ tmp = json_string(table_flag_name(i));
json_array_append_new(root, tmp);
}
flags >>= 1;
@@ -583,13 +583,15 @@ json_t *set_ref_expr_json(const struct expr *expr, struct output_ctx *octx)
json_t *set_elem_expr_json(const struct expr *expr, struct output_ctx *octx)
{
json_t *root = expr_print_json(expr->key, octx);
+ struct stmt *stmt;
json_t *tmp;
if (!root)
return NULL;
/* these element attributes require formal set elem syntax */
- if (expr->timeout || expr->expiration || expr->comment || expr->stmt) {
+ if (expr->timeout || expr->expiration || expr->comment ||
+ !list_empty(&expr->stmt_list)) {
root = json_pack("{s:o}", "val", root);
if (expr->timeout) {
@@ -604,11 +606,13 @@ json_t *set_elem_expr_json(const struct expr *expr, struct output_ctx *octx)
tmp = json_string(expr->comment);
json_object_set_new(root, "comment", tmp);
}
- if (expr->stmt) {
- tmp = stmt_print_json(expr->stmt, octx);
+ list_for_each_entry(stmt, &expr->stmt_list, list) {
+ tmp = stmt_print_json(stmt, octx);
/* XXX: detect and complain about clashes? */
json_object_update_missing(root, tmp);
json_decref(tmp);
+ /* TODO: only one statement per element. */
+ break;
}
return json_pack("{s:o}", "elem", root);
}
@@ -1164,19 +1168,17 @@ json_t *limit_stmt_json(const struct stmt *stmt, struct output_ctx *octx)
burst_unit = get_rate(stmt->limit.burst, &burst);
}
- root = json_pack("{s:I, s:s}",
+ root = json_pack("{s:I, s:I, s:s}",
"rate", rate,
+ "burst", burst,
"per", get_unit(stmt->limit.unit));
if (inv)
json_object_set_new(root, "inv", json_boolean(inv));
if (rate_unit)
json_object_set_new(root, "rate_unit", json_string(rate_unit));
- if (burst && burst != 5) {
- json_object_set_new(root, "burst", json_integer(burst));
- if (burst_unit)
- json_object_set_new(root, "burst_unit",
- json_string(burst_unit));
- }
+ if (burst_unit)
+ json_object_set_new(root, "burst_unit",
+ json_string(burst_unit));
return json_pack("{s:o}", "limit", root);
}
@@ -1378,24 +1380,16 @@ json_t *reject_stmt_json(const struct stmt *stmt, struct output_ctx *octx)
type = "tcp reset";
break;
case NFT_REJECT_ICMPX_UNREACH:
- if (stmt->reject.icmp_code == NFT_REJECT_ICMPX_PORT_UNREACH)
- break;
type = "icmpx";
jexpr = expr_print_json(stmt->reject.expr, octx);
break;
case NFT_REJECT_ICMP_UNREACH:
switch (stmt->reject.family) {
case NFPROTO_IPV4:
- if (!stmt->reject.verbose_print &&
- stmt->reject.icmp_code == ICMP_PORT_UNREACH)
- break;
type = "icmp";
jexpr = expr_print_json(stmt->reject.expr, octx);
break;
case NFPROTO_IPV6:
- if (!stmt->reject.verbose_print &&
- stmt->reject.icmp_code == ICMP6_DST_UNREACH_NOPORT)
- break;
type = "icmpv6";
jexpr = expr_print_json(stmt->reject.expr, octx);
break;
@@ -1895,9 +1889,15 @@ int do_command_list_json(struct netlink_ctx *ctx, struct cmd *cmd)
static void monitor_print_json(struct netlink_mon_handler *monh,
const char *cmd, json_t *obj)
{
+ struct nft_ctx *nft = monh->ctx->nft;
+
obj = json_pack("{s:o}", cmd, obj);
- json_dumpf(obj, monh->ctx->nft->output.output_fp, 0);
- json_decref(obj);
+ if (nft_output_echo(&nft->output) && !nft->json_root) {
+ json_array_append_new(nft->json_echo, obj);
+ } else {
+ json_dumpf(obj, nft->output.output_fp, 0);
+ json_decref(obj);
+ }
}
void monitor_print_table_json(struct netlink_mon_handler *monh,
@@ -1941,3 +1941,10 @@ void monitor_print_rule_json(struct netlink_mon_handler *monh,
monitor_print_json(monh, cmd, rule_print_json(octx, r));
}
+
+void json_alloc_echo(struct nft_ctx *nft)
+{
+ nft->json_echo = json_array();
+ if (!nft->json_echo)
+ memory_allocation_error();
+}
diff --git a/src/libnftables.c b/src/libnftables.c
index a180a9a3..04436591 100644
--- a/src/libnftables.c
+++ b/src/libnftables.c
@@ -463,8 +463,13 @@ int nft_run_cmd_from_buffer(struct nft_ctx *nft, const char *buf)
parser_rc = rc;
rc = nft_evaluate(nft, &msgs, &cmds);
- if (rc < 0)
+ if (rc < 0) {
+ if (errno == EPERM) {
+ fprintf(stderr, "%s (you must be root)\n",
+ strerror(errno));
+ }
goto err;
+ }
if (parser_rc) {
rc = parser_rc;
diff --git a/src/main.c b/src/main.c
index 3c26f510..8c470644 100644
--- a/src/main.c
+++ b/src/main.c
@@ -175,16 +175,17 @@ static const struct option *get_options(void)
static void print_option(const struct nft_opt *opt)
{
- char optbuf[33] = "";
+ char optbuf[35] = "";
int i;
i = snprintf(optbuf, sizeof(optbuf), " -%c", opt->val);
if (opt->name)
- i += snprintf(optbuf + i, sizeof(optbuf) - i, ", %s", opt->name);
+ i += snprintf(optbuf + i, sizeof(optbuf) - i, ", --%s",
+ opt->name);
if (opt->arg)
i += snprintf(optbuf + i, sizeof(optbuf) - i, " %s", opt->arg);
- printf("%-32s%s\n", optbuf, opt->help);
+ printf("%-34s%s\n", optbuf, opt->help);
}
static void show_help(const char *name)
@@ -229,6 +230,8 @@ static void show_version(void)
#if defined(HAVE_LIBREADLINE)
cli = "readline";
+#elif defined(HAVE_LIBEDIT)
+ cli = "editline";
#elif defined(HAVE_LIBLINENOISE)
cli = "linenoise";
#else
diff --git a/src/mnl.c b/src/mnl.c
index ffa1e140..84cfb238 100644
--- a/src/mnl.c
+++ b/src/mnl.c
@@ -359,6 +359,9 @@ static int mnl_batch_extack_cb(const struct nlmsghdr *nlh, void *data)
}
#define NFT_MNL_ECHO_RCVBUFF_DEFAULT (MNL_SOCKET_BUFFER_SIZE * 1024)
+#define NFT_MNL_ACK_MAXSIZE ((sizeof(struct nlmsghdr) + \
+ sizeof(struct nfgenmsg) + (1 << 16)) + \
+ MNL_SOCKET_BUFFER_SIZE)
int mnl_batch_talk(struct netlink_ctx *ctx, struct list_head *err_list,
uint32_t num_cmds)
@@ -366,7 +369,7 @@ int mnl_batch_talk(struct netlink_ctx *ctx, struct list_head *err_list,
struct mnl_socket *nl = ctx->nft->nf_sock;
int ret, fd = mnl_socket_get_fd(nl), portid = mnl_socket_get_portid(nl);
uint32_t iov_len = nftnl_batch_iovec_len(ctx->batch);
- char rcv_buf[MNL_SOCKET_BUFFER_SIZE];
+ char rcv_buf[NFT_MNL_ACK_MAXSIZE];
const struct sockaddr_nl snl = {
.nl_family = AF_NETLINK
};
@@ -1043,6 +1046,8 @@ int mnl_nft_set_add(struct netlink_ctx *ctx, struct cmd *cmd,
struct set *set = cmd->set;
struct nftnl_set *nls;
struct nlmsghdr *nlh;
+ struct stmt *stmt;
+ int num_stmts = 0;
nls = nftnl_set_alloc();
if (!nls)
@@ -1125,9 +1130,18 @@ int mnl_nft_set_add(struct netlink_ctx *ctx, struct cmd *cmd,
nftnl_udata_buf_len(udbuf));
nftnl_udata_buf_free(udbuf);
- if (set->stmt) {
- nftnl_set_set_data(nls, NFTNL_SET_EXPR,
- netlink_gen_stmt_stateful(set->stmt), 0);
+ list_for_each_entry(stmt, &set->stmt_list, list)
+ num_stmts++;
+
+ if (num_stmts == 1) {
+ list_for_each_entry(stmt, &set->stmt_list, list) {
+ nftnl_set_set_data(nls, NFTNL_SET_EXPR,
+ netlink_gen_stmt_stateful(stmt), 0);
+ break;
+ }
+ } else if (num_stmts > 1) {
+ list_for_each_entry(stmt, &set->stmt_list, list)
+ nftnl_set_add_expr(nls, netlink_gen_stmt_stateful(stmt));
}
netlink_dump_set(nls, ctx);
diff --git a/src/monitor.c b/src/monitor.c
index 3872ebcf..047d89db 100644
--- a/src/monitor.c
+++ b/src/monitor.c
@@ -221,12 +221,14 @@ static int netlink_events_table_cb(const struct nlmsghdr *nlh, int type,
if (nft_output_handle(&monh->ctx->nft->output))
nft_mon_print(monh, " # handle %" PRIu64 "",
t->handle.handle.id);
+ nft_mon_print(monh, "\n");
break;
case NFTNL_OUTPUT_JSON:
monitor_print_table_json(monh, cmd, t);
+ if (!nft_output_echo(&monh->ctx->nft->output))
+ nft_mon_print(monh, "\n");
break;
}
- nft_mon_print(monh, "\n");
table_free(t);
nftnl_table_free(nlt);
return MNL_CB_OK;
@@ -258,12 +260,14 @@ static int netlink_events_chain_cb(const struct nlmsghdr *nlh, int type,
c->handle.chain.name);
break;
}
+ nft_mon_print(monh, "\n");
break;
case NFTNL_OUTPUT_JSON:
monitor_print_chain_json(monh, cmd, c);
+ if (!nft_output_echo(&monh->ctx->nft->output))
+ nft_mon_print(monh, "\n");
break;
}
- nft_mon_print(monh, "\n");
chain_free(c);
nftnl_chain_free(nlc);
return MNL_CB_OK;
@@ -304,12 +308,14 @@ static int netlink_events_set_cb(const struct nlmsghdr *nlh, int type,
set->handle.set.name);
break;
}
+ nft_mon_print(monh, "\n");
break;
case NFTNL_OUTPUT_JSON:
monitor_print_set_json(monh, cmd, set);
+ if (!nft_output_echo(&monh->ctx->nft->output))
+ nft_mon_print(monh, "\n");
break;
}
- nft_mon_print(monh, "\n");
set_free(set);
out:
nftnl_set_free(nls);
@@ -441,6 +447,7 @@ static int netlink_events_setelem_cb(const struct nlmsghdr *nlh, int type,
nft_mon_print(monh, "%s element %s %s %s ",
cmd, family2str(family), table, setname);
expr_print(dummyset->init, &monh->ctx->nft->output);
+ nft_mon_print(monh, "\n");
break;
case NFTNL_OUTPUT_JSON:
dummyset->handle.family = family;
@@ -450,9 +457,10 @@ static int netlink_events_setelem_cb(const struct nlmsghdr *nlh, int type,
/* prevent set_free() from trying to free those */
dummyset->handle.set.name = NULL;
dummyset->handle.table.name = NULL;
+ if (!nft_output_echo(&monh->ctx->nft->output))
+ nft_mon_print(monh, "\n");
break;
}
- nft_mon_print(monh, "\n");
set_free(dummyset);
out:
nftnl_set_free(nls);
@@ -492,12 +500,14 @@ static int netlink_events_obj_cb(const struct nlmsghdr *nlh, int type,
obj->handle.obj.name);
break;
}
+ nft_mon_print(monh, "\n");
break;
case NFTNL_OUTPUT_JSON:
monitor_print_obj_json(monh, cmd, obj);
+ if (!nft_output_echo(&monh->ctx->nft->output))
+ nft_mon_print(monh, "\n");
break;
}
- nft_mon_print(monh, "\n");
obj_free(obj);
nftnl_obj_free(nlo);
return MNL_CB_OK;
@@ -542,12 +552,14 @@ static int netlink_events_rule_cb(const struct nlmsghdr *nlh, int type,
r->handle.handle.id);
break;
}
+ nft_mon_print(monh, "\n");
break;
case NFTNL_OUTPUT_JSON:
monitor_print_rule_json(monh, cmd, r);
+ if (!nft_output_echo(&monh->ctx->nft->output))
+ nft_mon_print(monh, "\n");
break;
}
- nft_mon_print(monh, "\n");
rule_free(r);
nftnl_rule_free(nlr);
return MNL_CB_OK;
@@ -830,6 +842,9 @@ static int netlink_events_newgen_cb(const struct nlmsghdr *nlh, int type,
char name[256] = "";
int genid = -1, pid = -1;
+ if (monh->format != NFTNL_OUTPUT_DEFAULT)
+ return MNL_CB_OK;
+
mnl_attr_for_each(attr, nlh, sizeof(struct nfgenmsg)) {
switch (mnl_attr_get_type(attr)) {
case NFTA_GEN_ID:
@@ -912,6 +927,8 @@ int netlink_echo_callback(const struct nlmsghdr *nlh, void *data)
{
struct netlink_cb_data *nl_cb_data = data;
struct netlink_ctx *ctx = nl_cb_data->nl_ctx;
+ struct nft_ctx *nft = ctx->nft;
+
struct netlink_mon_handler echo_monh = {
.format = NFTNL_OUTPUT_DEFAULT,
.ctx = ctx,
@@ -922,8 +939,13 @@ int netlink_echo_callback(const struct nlmsghdr *nlh, void *data)
if (!nft_output_echo(&echo_monh.ctx->nft->output))
return MNL_CB_OK;
- if (nft_output_json(&ctx->nft->output))
- return json_events_cb(nlh, &echo_monh);
+ if (nft_output_json(&nft->output)) {
+ if (nft->json_root)
+ return json_events_cb(nlh, &echo_monh);
+ if (!nft->json_echo)
+ json_alloc_echo(nft);
+ echo_monh.format = NFTNL_OUTPUT_JSON;
+ }
return netlink_events_cb(nlh, &echo_monh);
}
diff --git a/src/netlink.c b/src/netlink.c
index f8ac2b9e..8c86789b 100644
--- a/src/netlink.c
+++ b/src/netlink.c
@@ -104,6 +104,8 @@ static struct nftnl_set_elem *alloc_nftnl_setelem(const struct expr *set,
struct nftnl_set_elem *nlse;
struct nft_data_linearize nld;
struct nftnl_udata_buf *udbuf = NULL;
+ int num_exprs = 0;
+ struct stmt *stmt;
struct expr *key;
nlse = nftnl_set_elem_alloc();
@@ -138,9 +140,20 @@ static struct nftnl_set_elem *alloc_nftnl_setelem(const struct expr *set,
if (elem->expiration)
nftnl_set_elem_set_u64(nlse, NFTNL_SET_ELEM_EXPIRATION,
elem->expiration);
- if (elem->stmt)
- nftnl_set_elem_set(nlse, NFTNL_SET_ELEM_EXPR,
- netlink_gen_stmt_stateful(elem->stmt), 0);
+ list_for_each_entry(stmt, &elem->stmt_list, list)
+ num_exprs++;
+
+ if (num_exprs == 1) {
+ list_for_each_entry(stmt, &elem->stmt_list, list) {
+ nftnl_set_elem_set(nlse, NFTNL_SET_ELEM_EXPR,
+ netlink_gen_stmt_stateful(stmt), 0);
+ }
+ } else if (num_exprs > 1) {
+ list_for_each_entry(stmt, &elem->stmt_list, list) {
+ nftnl_set_elem_add_expr(nlse,
+ netlink_gen_stmt_stateful(stmt));
+ }
+ }
if (elem->comment || expr->elem_flags) {
udbuf = nftnl_udata_buf_alloc(NFT_USERDATA_MAXLEN);
if (!udbuf)
@@ -601,6 +614,7 @@ struct table *netlink_delinearize_table(struct netlink_ctx *ctx,
table->handle.table.name = xstrdup(nftnl_table_get_str(nlt, NFTNL_TABLE_NAME));
table->flags = nftnl_table_get_u32(nlt, NFTNL_TABLE_FLAGS);
table->handle.handle.id = nftnl_table_get_u64(nlt, NFTNL_TABLE_HANDLE);
+ table->owner = nftnl_table_get_u32(nlt, NFTNL_TABLE_OWNER);
if (nftnl_table_is_set(nlt, NFTNL_TABLE_USERDATA)) {
udata = nftnl_table_get_data(nlt, NFTNL_TABLE_USERDATA, &ulen);
@@ -635,7 +649,7 @@ int netlink_list_tables(struct netlink_ctx *ctx, const struct handle *h)
if (errno == EINTR)
return -1;
- return 0;
+ return -1;
}
ctx->data = h;
@@ -766,6 +780,25 @@ static bool set_udata_key_valid(const struct expr *e, const struct datatype *d,
return div_round_up(e->len, BITS_PER_BYTE) == len / BITS_PER_BYTE;
}
+struct setelem_parse_ctx {
+ struct set *set;
+ struct nft_cache *cache;
+ struct list_head stmt_list;
+};
+
+static int set_elem_parse_expressions(struct nftnl_expr *e, void *data)
+{
+ struct setelem_parse_ctx *setelem_parse_ctx = data;
+ struct nft_cache *cache = setelem_parse_ctx->cache;
+ struct set *set = setelem_parse_ctx->set;
+ struct stmt *stmt;
+
+ stmt = netlink_parse_set_expr(set, cache, e);
+ list_add_tail(&stmt->list, &setelem_parse_ctx->stmt_list);
+
+ return 0;
+}
+
struct set *netlink_delinearize_set(struct netlink_ctx *ctx,
const struct nftnl_set *nls)
{
@@ -774,6 +807,7 @@ struct set *netlink_delinearize_set(struct netlink_ctx *ctx,
enum byteorder databyteorder = BYTEORDER_INVALID;
const struct datatype *keytype, *datatype = NULL;
struct expr *typeof_expr_key, *typeof_expr_data;
+ struct setelem_parse_ctx set_parse_ctx;
const char *udata, *comment = NULL;
uint32_t flags, key, objtype = 0;
const struct datatype *dtype;
@@ -847,12 +881,22 @@ struct set *netlink_delinearize_set(struct netlink_ctx *ctx,
if (comment)
set->comment = comment;
+ init_list_head(&set_parse_ctx.stmt_list);
+
if (nftnl_set_is_set(nls, NFTNL_SET_EXPR)) {
const struct nftnl_expr *nle;
+ struct stmt *stmt;
nle = nftnl_set_get(nls, NFTNL_SET_EXPR);
- set->stmt = netlink_parse_set_expr(set, &ctx->nft->cache, nle);
+ stmt = netlink_parse_set_expr(set, &ctx->nft->cache, nle);
+ list_add_tail(&stmt->list, &set_parse_ctx.stmt_list);
+ } else if (nftnl_set_is_set(nls, NFTNL_SET_EXPRESSIONS)) {
+ set_parse_ctx.cache = &ctx->nft->cache;
+ set_parse_ctx.set = set;
+ nftnl_set_expr_foreach(nls, set_elem_parse_expressions,
+ &set_parse_ctx);
}
+ list_splice_tail(&set_parse_ctx.stmt_list, &set->stmt_list);
if (datatype) {
dtype = set_datatype_alloc(datatype, databyteorder);
@@ -1107,10 +1151,16 @@ static void set_elem_parse_udata(struct nftnl_set_elem *nlse,
int netlink_delinearize_setelem(struct nftnl_set_elem *nlse,
struct set *set, struct nft_cache *cache)
{
+ struct setelem_parse_ctx setelem_parse_ctx = {
+ .set = set,
+ .cache = cache,
+ };
struct nft_data_delinearize nld;
struct expr *expr, *key, *data;
uint32_t flags = 0;
+ init_list_head(&setelem_parse_ctx.stmt_list);
+
nld.value =
nftnl_set_elem_get(nlse, NFTNL_SET_ELEM_KEY, &nld.len);
if (nftnl_set_elem_is_set(nlse, NFTNL_SET_ELEM_FLAGS))
@@ -1132,6 +1182,7 @@ key_end:
key = bitmask_expr_to_binops(key);
expr = set_elem_expr_alloc(&netlink_location, key);
+
if (nftnl_set_elem_is_set(nlse, NFTNL_SET_ELEM_TIMEOUT))
expr->timeout = nftnl_set_elem_get_u64(nlse, NFTNL_SET_ELEM_TIMEOUT);
if (nftnl_set_elem_is_set(nlse, NFTNL_SET_ELEM_EXPIRATION))
@@ -1140,10 +1191,17 @@ key_end:
set_elem_parse_udata(nlse, expr);
if (nftnl_set_elem_is_set(nlse, NFTNL_SET_ELEM_EXPR)) {
const struct nftnl_expr *nle;
+ struct stmt *stmt;
nle = nftnl_set_elem_get(nlse, NFTNL_SET_ELEM_EXPR, NULL);
- expr->stmt = netlink_parse_set_expr(set, cache, nle);
+ stmt = netlink_parse_set_expr(set, cache, nle);
+ list_add_tail(&stmt->list, &setelem_parse_ctx.stmt_list);
+ } else if (nftnl_set_elem_is_set(nlse, NFTNL_SET_ELEM_EXPRESSIONS)) {
+ nftnl_set_elem_expr_foreach(nlse, set_elem_parse_expressions,
+ &setelem_parse_ctx);
}
+ list_splice_tail(&setelem_parse_ctx.stmt_list, &expr->stmt_list);
+
if (flags & NFT_SET_ELEM_INTERVAL_END) {
expr->flags |= EXPR_F_INTERVAL_END;
if (mpz_cmp_ui(set->key->value, 0) == 0)
@@ -1802,7 +1860,9 @@ next:
pctx->pbase == PROTO_BASE_INVALID) {
payload_dependency_store(pctx, stmt, base - stacked);
} else {
- payload_dependency_kill(pctx, lhs, ctx->family);
+ /* Don't strip 'icmp type' from payload dump. */
+ if (pctx->icmp_type == 0)
+ payload_dependency_kill(pctx, lhs, ctx->family);
if (lhs->flags & EXPR_F_PROTOCOL)
payload_dependency_store(pctx, stmt, base - stacked);
}
@@ -1880,12 +1940,12 @@ int netlink_events_trace_cb(const struct nlmsghdr *nlh, int type,
if (nftnl_trace_nlmsg_parse(nlh, nlt) < 0)
netlink_abi_error();
+ if (nftnl_trace_is_set(nlt, NFTNL_TRACE_LL_HEADER) ||
+ nftnl_trace_is_set(nlt, NFTNL_TRACE_NETWORK_HEADER))
+ trace_print_packet(nlt, &monh->ctx->nft->output);
+
switch (nftnl_trace_get_u32(nlt, NFTNL_TRACE_TYPE)) {
case NFT_TRACETYPE_RULE:
- if (nftnl_trace_is_set(nlt, NFTNL_TRACE_LL_HEADER) ||
- nftnl_trace_is_set(nlt, NFTNL_TRACE_NETWORK_HEADER))
- trace_print_packet(nlt, &monh->ctx->nft->output);
-
if (nftnl_trace_is_set(nlt, NFTNL_TRACE_RULE_HANDLE))
trace_print_rule(nlt, &monh->ctx->nft->output,
&monh->ctx->nft->cache);
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
index 9faddde6..7cd7d403 100644
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -1489,17 +1489,47 @@ static void netlink_parse_queue(struct netlink_parse_ctx *ctx,
ctx->stmt = stmt;
}
+struct dynset_parse_ctx {
+ struct netlink_parse_ctx *nlctx;
+ const struct location *loc;
+ struct list_head stmt_list;
+};
+
+static int dynset_parse_expressions(struct nftnl_expr *e, void *data)
+{
+ struct dynset_parse_ctx *dynset_parse_ctx = data;
+ struct netlink_parse_ctx *ctx = dynset_parse_ctx->nlctx;
+ const struct location *loc = dynset_parse_ctx->loc;
+ struct stmt *stmt;
+
+ if (netlink_parse_expr(e, ctx) < 0 || !ctx->stmt) {
+ netlink_error(ctx, loc, "Could not parse dynset stmt");
+ return -1;
+ }
+ stmt = ctx->stmt;
+
+ list_add_tail(&stmt->list, &dynset_parse_ctx->stmt_list);
+
+ return 0;
+}
+
static void netlink_parse_dynset(struct netlink_parse_ctx *ctx,
const struct location *loc,
const struct nftnl_expr *nle)
{
+ struct dynset_parse_ctx dynset_parse_ctx = {
+ .nlctx = ctx,
+ .loc = loc,
+ };
struct expr *expr, *expr_data = NULL;
enum nft_registers sreg, sreg_data;
+ struct stmt *stmt, *dstmt, *next;
const struct nftnl_expr *dnle;
- struct stmt *stmt, *dstmt;
struct set *set;
const char *name;
+ init_list_head(&dynset_parse_ctx.stmt_list);
+
name = nftnl_expr_get_str(nle, NFTNL_EXPR_DYNSET_SET_NAME);
set = set_lookup(ctx->table, name);
if (set == NULL)
@@ -1523,16 +1553,25 @@ static void netlink_parse_dynset(struct netlink_parse_ctx *ctx,
expr = set_elem_expr_alloc(&expr->location, expr);
expr->timeout = nftnl_expr_get_u64(nle, NFTNL_EXPR_DYNSET_TIMEOUT);
- dstmt = NULL;
- dnle = nftnl_expr_get(nle, NFTNL_EXPR_DYNSET_EXPR, NULL);
- if (dnle != NULL) {
- if (netlink_parse_expr(dnle, ctx) < 0)
- goto out_err;
- if (ctx->stmt == NULL) {
- netlink_error(ctx, loc, "Could not parse dynset stmt");
- goto out_err;
+ if (nftnl_expr_is_set(nle, NFTNL_EXPR_DYNSET_EXPR)) {
+ dstmt = NULL;
+ dnle = nftnl_expr_get(nle, NFTNL_EXPR_DYNSET_EXPR, NULL);
+ if (dnle != NULL) {
+ if (netlink_parse_expr(dnle, ctx) < 0)
+ goto out_err;
+ if (ctx->stmt == NULL) {
+ netlink_error(ctx, loc,
+ "Could not parse dynset stmt");
+ goto out_err;
+ }
+ dstmt = ctx->stmt;
+ list_add_tail(&dstmt->list,
+ &dynset_parse_ctx.stmt_list);
}
- dstmt = ctx->stmt;
+ } else if (nftnl_expr_is_set(nle, NFTNL_EXPR_DYNSET_EXPRESSIONS)) {
+ if (nftnl_expr_expr_foreach(nle, dynset_parse_expressions,
+ &dynset_parse_ctx) < 0)
+ goto out_err;
}
if (nftnl_expr_is_set(nle, NFTNL_EXPR_DYNSET_SREG_DATA)) {
@@ -1546,27 +1585,34 @@ static void netlink_parse_dynset(struct netlink_parse_ctx *ctx,
stmt->map.set = set_ref_expr_alloc(loc, set);
stmt->map.key = expr;
stmt->map.data = expr_data;
- stmt->map.stmt = dstmt;
stmt->map.op = nftnl_expr_get_u32(nle, NFTNL_EXPR_DYNSET_OP);
+ list_splice_tail(&dynset_parse_ctx.stmt_list,
+ &stmt->map.stmt_list);
} else {
- if (dstmt != NULL && set->flags & NFT_SET_ANONYMOUS) {
+ if (!list_empty(&dynset_parse_ctx.stmt_list) &&
+ set->flags & NFT_SET_ANONYMOUS) {
stmt = meter_stmt_alloc(loc);
stmt->meter.set = set_ref_expr_alloc(loc, set);
stmt->meter.key = expr;
- stmt->meter.stmt = dstmt;
+ stmt->meter.stmt = list_first_entry(&dynset_parse_ctx.stmt_list,
+ struct stmt, list);
stmt->meter.size = set->desc.size;
} else {
stmt = set_stmt_alloc(loc);
stmt->set.set = set_ref_expr_alloc(loc, set);
stmt->set.op = nftnl_expr_get_u32(nle, NFTNL_EXPR_DYNSET_OP);
stmt->set.key = expr;
- stmt->set.stmt = dstmt;
+ list_splice_tail(&dynset_parse_ctx.stmt_list,
+ &stmt->set.stmt_list);
}
}
ctx->stmt = stmt;
return;
out_err:
+ list_for_each_entry_safe(dstmt, next, &dynset_parse_ctx.stmt_list, list)
+ stmt_free(dstmt);
+
xfree(expr);
}
@@ -1771,6 +1817,9 @@ static void payload_match_expand(struct rule_pp_ctx *ctx,
enum proto_bases base = left->payload.base;
bool stacked;
+ if (ctx->pdctx.icmp_type)
+ ctx->pctx.th_dep.icmp.type = ctx->pdctx.icmp_type;
+
payload_expr_expand(&list, left, &ctx->pctx);
list_for_each_entry(left, &list, list) {
@@ -2118,7 +2167,7 @@ static void relational_binop_postprocess(struct rule_pp_ctx *ctx, struct expr *e
{
struct expr *binop = expr->left, *value = expr->right;
- if (binop->op == OP_AND && expr->op == OP_NEQ &&
+ if (binop->op == OP_AND && (expr->op == OP_NEQ || expr->op == OP_EQ) &&
value->dtype->basetype &&
value->dtype->basetype->type == TYPE_BITMASK &&
!mpz_cmp_ui(value->value, 0)) {
@@ -2131,8 +2180,16 @@ static void relational_binop_postprocess(struct rule_pp_ctx *ctx, struct expr *e
expr->left = expr_get(binop->left);
expr->right = binop_tree_to_list(NULL, binop->right);
- expr->op = OP_IMPLICIT;
-
+ switch (expr->op) {
+ case OP_NEQ:
+ expr->op = OP_IMPLICIT;
+ break;
+ case OP_EQ:
+ expr->op = OP_NEG;
+ break;
+ default:
+ BUG("unknown operation type %d\n", expr->op);
+ }
expr_free(binop);
} else if (binop->left->dtype->flags & DTYPE_F_PREFIX &&
binop->op == OP_AND && expr->right->etype == EXPR_VALUE &&
@@ -2424,24 +2481,8 @@ static void stmt_reject_postprocess(struct rule_pp_ctx *rctx)
payload_dependency_release(&rctx->pdctx);
break;
case NFPROTO_INET:
- if (stmt->reject.type == NFT_REJECT_ICMPX_UNREACH) {
- datatype_set(stmt->reject.expr, &icmpx_code_type);
- break;
- }
- base = rctx->pctx.protocol[PROTO_BASE_LL_HDR].desc;
- desc = rctx->pctx.protocol[PROTO_BASE_NETWORK_HDR].desc;
- protocol = proto_find_num(base, desc);
- switch (protocol) {
- case NFPROTO_IPV4:
- datatype_set(stmt->reject.expr, &icmp_code_type);
- break;
- case NFPROTO_IPV6:
- datatype_set(stmt->reject.expr, &icmpv6_code_type);
- break;
- }
- stmt->reject.family = protocol;
- break;
case NFPROTO_BRIDGE:
+ case NFPROTO_NETDEV:
if (stmt->reject.type == NFT_REJECT_ICMPX_UNREACH) {
datatype_set(stmt->reject.expr, &icmpx_code_type);
break;
@@ -2456,11 +2497,13 @@ static void stmt_reject_postprocess(struct rule_pp_ctx *rctx)
desc = rctx->pctx.protocol[PROTO_BASE_NETWORK_HDR].desc;
protocol = proto_find_num(base, desc);
switch (protocol) {
- case __constant_htons(ETH_P_IP):
+ case NFPROTO_IPV4: /* INET */
+ case __constant_htons(ETH_P_IP): /* BRIDGE, NETDEV */
stmt->reject.family = NFPROTO_IPV4;
datatype_set(stmt->reject.expr, &icmp_code_type);
break;
- case __constant_htons(ETH_P_IPV6):
+ case NFPROTO_IPV6: /* INET */
+ case __constant_htons(ETH_P_IPV6): /* BRIDGE, NETDEV */
stmt->reject.family = NFPROTO_IPV6;
datatype_set(stmt->reject.expr, &icmpv6_code_type);
break;
@@ -2470,7 +2513,6 @@ static void stmt_reject_postprocess(struct rule_pp_ctx *rctx)
if (payload_dependency_exists(&rctx->pdctx, PROTO_BASE_NETWORK_HDR))
payload_dependency_release(&rctx->pdctx);
-
break;
default:
break;
diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c
index 05af8bb1..21bc492e 100644
--- a/src/netlink_linearize.c
+++ b/src/netlink_linearize.c
@@ -490,7 +490,11 @@ static void netlink_gen_flagcmp(struct netlink_linearize_ctx *ctx,
nle = alloc_nft_expr("cmp");
netlink_put_register(nle, NFTNL_EXPR_CMP_SREG, sreg);
- nftnl_expr_set_u32(nle, NFTNL_EXPR_CMP_OP, NFT_CMP_NEQ);
+ if (expr->op == OP_NEG)
+ nftnl_expr_set_u32(nle, NFTNL_EXPR_CMP_OP, NFT_CMP_EQ);
+ else
+ nftnl_expr_set_u32(nle, NFTNL_EXPR_CMP_OP, NFT_CMP_NEQ);
+
nftnl_expr_set(nle, NFTNL_EXPR_CMP_DATA, nld.value, nld.len);
nft_rule_add_expr(ctx, nle, &expr->location);
@@ -518,6 +522,7 @@ static void netlink_gen_relational(struct netlink_linearize_ctx *ctx,
case OP_GT:
case OP_LTE:
case OP_GTE:
+ case OP_NEG:
break;
default:
BUG("invalid relational operation %u\n", expr->op);
@@ -547,7 +552,7 @@ static void netlink_gen_relational(struct netlink_linearize_ctx *ctx,
}
break;
default:
- if (expr->op == OP_IMPLICIT &&
+ if ((expr->op == OP_IMPLICIT || expr->op == OP_NEG) &&
expr->right->dtype->basetype != NULL &&
expr->right->dtype->basetype->type == TYPE_BITMASK)
return netlink_gen_flagcmp(ctx, expr, dreg);
@@ -1397,8 +1402,10 @@ static void netlink_gen_set_stmt(struct netlink_linearize_ctx *ctx,
const struct stmt *stmt)
{
struct set *set = stmt->meter.set->set;
- struct nftnl_expr *nle;
enum nft_registers sreg_key;
+ struct nftnl_expr *nle;
+ int num_stmts = 0;
+ struct stmt *this;
sreg_key = get_register(ctx, stmt->set.key->key);
netlink_gen_expr(ctx, stmt->set.key->key, sreg_key);
@@ -1414,9 +1421,22 @@ static void netlink_gen_set_stmt(struct netlink_linearize_ctx *ctx,
nftnl_expr_set_u32(nle, NFTNL_EXPR_DYNSET_SET_ID, set->handle.set_id);
nft_rule_add_expr(ctx, nle, &stmt->location);
- if (stmt->set.stmt)
- nftnl_expr_set(nle, NFTNL_EXPR_DYNSET_EXPR,
- netlink_gen_stmt_stateful(stmt->set.stmt), 0);
+ list_for_each_entry(this, &stmt->set.stmt_list, list)
+ num_stmts++;
+
+ if (num_stmts == 1) {
+ list_for_each_entry(this, &stmt->set.stmt_list, list) {
+ nftnl_expr_set(nle, NFTNL_EXPR_DYNSET_EXPR,
+ netlink_gen_stmt_stateful(this), 0);
+ }
+ } else if (num_stmts > 1) {
+ list_for_each_entry(this, &stmt->set.stmt_list, list) {
+ nftnl_expr_add_expr(nle, NFTNL_EXPR_DYNSET_EXPRESSIONS,
+ netlink_gen_stmt_stateful(this));
+ }
+ nftnl_expr_set_u32(nle, NFTNL_EXPR_DYNSET_FLAGS,
+ NFT_DYNSET_F_EXPR);
+ }
}
static void netlink_gen_map_stmt(struct netlink_linearize_ctx *ctx,
@@ -1426,6 +1446,8 @@ static void netlink_gen_map_stmt(struct netlink_linearize_ctx *ctx,
enum nft_registers sreg_data;
enum nft_registers sreg_key;
struct nftnl_expr *nle;
+ int num_stmts = 0;
+ struct stmt *this;
sreg_key = get_register(ctx, stmt->map.key);
netlink_gen_expr(ctx, stmt->map.key, sreg_key);
@@ -1443,12 +1465,22 @@ static void netlink_gen_map_stmt(struct netlink_linearize_ctx *ctx,
nftnl_expr_set_u32(nle, NFTNL_EXPR_DYNSET_OP, stmt->map.op);
nftnl_expr_set_str(nle, NFTNL_EXPR_DYNSET_SET_NAME, set->handle.set.name);
nftnl_expr_set_u32(nle, NFTNL_EXPR_DYNSET_SET_ID, set->handle.set_id);
+ nft_rule_add_expr(ctx, nle, &stmt->location);
- if (stmt->map.stmt)
- nftnl_expr_set(nle, NFTNL_EXPR_DYNSET_EXPR,
- netlink_gen_stmt_stateful(stmt->map.stmt), 0);
+ list_for_each_entry(this, &stmt->map.stmt_list, list)
+ num_stmts++;
- nft_rule_add_expr(ctx, nle, &stmt->location);
+ if (num_stmts == 1) {
+ list_for_each_entry(this, &stmt->map.stmt_list, list) {
+ nftnl_expr_set(nle, NFTNL_EXPR_DYNSET_EXPR,
+ netlink_gen_stmt_stateful(this), 0);
+ }
+ } else if (num_stmts > 1) {
+ list_for_each_entry(this, &stmt->map.stmt_list, list) {
+ nftnl_expr_add_expr(nle, NFTNL_EXPR_DYNSET_EXPRESSIONS,
+ netlink_gen_stmt_stateful(this));
+ }
+ }
}
static void netlink_gen_meter_stmt(struct netlink_linearize_ctx *ctx,
diff --git a/src/owner.c b/src/owner.c
new file mode 100644
index 00000000..2d98a2e9
--- /dev/null
+++ b/src/owner.c
@@ -0,0 +1,173 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <time.h>
+#include <inttypes.h>
+#include <dirent.h>
+
+#include <netlink.h>
+#include <owner.h>
+
+static char *pid2name(pid_t pid)
+{
+ char procname[256], *prog;
+ FILE *fp;
+ int ret;
+
+ ret = snprintf(procname, sizeof(procname), "/proc/%lu/stat", (unsigned long)pid);
+ if (ret < 0 || ret > (int)sizeof(procname))
+ return NULL;
+
+ fp = fopen(procname, "r");
+ if (!fp)
+ return NULL;
+
+ ret = fscanf(fp, "%*u (%m[^)]", &prog);
+
+ fclose(fp);
+
+ if (ret == 1)
+ return prog;
+
+ return NULL;
+}
+
+static char *portid2name(pid_t pid, uint32_t portid, unsigned long inode)
+{
+ const struct dirent *ent;
+ char procname[256];
+ DIR *dir;
+ int ret;
+
+ ret = snprintf(procname, sizeof(procname), "/proc/%lu/fd/", (unsigned long)pid);
+ if (ret < 0 || ret >= (int)sizeof(procname))
+ return NULL;
+
+ dir = opendir(procname);
+ if (!dir)
+ return NULL;
+
+ for (;;) {
+ unsigned long ino;
+ char tmp[128];
+ ssize_t rl;
+
+ ent = readdir(dir);
+ if (!ent)
+ break;
+
+ if (ent->d_type != DT_LNK)
+ continue;
+
+ ret = snprintf(procname, sizeof(procname), "/proc/%d/fd/%s",
+ pid, ent->d_name);
+ if (ret < 0 || ret >= (int)sizeof(procname))
+ continue;
+
+ rl = readlink(procname, tmp, sizeof(tmp));
+ if (rl <= 0 || rl > (ssize_t)sizeof(tmp))
+ continue;
+
+ tmp[rl] = 0;
+
+ ret = sscanf(tmp, "socket:[%lu]", &ino);
+ if (ret == 1 && ino == inode) {
+ closedir(dir);
+ return pid2name(pid);
+ }
+ }
+
+ closedir(dir);
+ return NULL;
+}
+
+static char *name_by_portid(uint32_t portid, unsigned long inode)
+{
+ const struct dirent *ent;
+ char *prog;
+ DIR *dir;
+
+ /* Many netlink users use their process ID to allocate the first port id. */
+ prog = portid2name(portid, portid, inode);
+ if (prog)
+ return prog;
+
+ /* no luck, search harder. */
+ dir = opendir("/proc");
+ if (!dir)
+ return NULL;
+
+ for (;;) {
+ unsigned long pid;
+ char *end;
+
+ ent = readdir(dir);
+ if (!ent)
+ break;
+
+ if (ent->d_type != DT_DIR)
+ continue;
+
+ pid = strtoul(ent->d_name, &end, 10);
+ if (pid <= 1 || *end)
+ continue;
+
+ if (pid == portid) /* already tried */
+ continue;
+
+ prog = portid2name(pid, portid, inode);
+ if (prog)
+ break;
+ }
+
+ closedir(dir);
+ return prog;
+}
+
+char *get_progname(uint32_t portid)
+{
+ FILE *fp = fopen("/proc/net/netlink", "r");
+ uint32_t portid_check;
+ unsigned long inode;
+ int ret, prot;
+
+ if (!fp)
+ return NULL;
+
+ for (;;) {
+ char line[256];
+
+ if (!fgets(line, sizeof(line), fp))
+ break;
+
+ ret = sscanf(line, "%*x %d %u %*x %*d %*d %*x %*d %*u %lu\n",
+ &prot, &portid_check, &inode);
+
+ if (ret == EOF)
+ break;
+
+ if (ret == 3 && portid_check == portid && prot == NETLINK_NETFILTER) {
+ static uint32_t last_portid;
+ static uint32_t last_inode;
+ static char *last_program;
+ char *prog;
+
+ fclose(fp);
+
+ if (last_portid == portid && last_inode == inode)
+ return last_program;
+
+ prog = name_by_portid(portid, inode);
+
+ free(last_program);
+ last_program = prog;
+ last_portid = portid;
+ last_inode = inode;
+ return prog;
+ }
+ }
+
+ fclose(fp);
+ return NULL;
+}
diff --git a/src/parser_bison.y b/src/parser_bison.y
index a8884466..a2c15018 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -184,7 +184,6 @@ int nft_lex(void *, void *, void *);
struct handle_spec handle_spec;
struct position_spec position_spec;
struct prio_spec prio_spec;
- const struct exthdr_desc *exthdr_desc;
}
%token TOKEN_EOF 0 "end of file"
@@ -605,7 +604,7 @@ int nft_lex(void *, void *, void *);
%type <table> table_block_alloc table_block
%destructor { close_scope(state); table_free($$); } table_block_alloc
%type <chain> chain_block_alloc chain_block subchain_block
-%destructor { close_scope(state); chain_free($$); } chain_block_alloc subchain_block
+%destructor { close_scope(state); chain_free($$); } chain_block_alloc
%type <rule> rule rule_alloc
%destructor { rule_free($$); } rule
@@ -625,10 +624,10 @@ int nft_lex(void *, void *, void *);
%type <obj> obj_block_alloc counter_block quota_block ct_helper_block ct_timeout_block ct_expect_block limit_block secmark_block synproxy_block
%destructor { obj_free($$); } obj_block_alloc
-%type <list> stmt_list
-%destructor { stmt_list_free($$); xfree($$); } stmt_list
-%type <stmt> stmt match_stmt verdict_stmt
-%destructor { stmt_free($$); } stmt match_stmt verdict_stmt
+%type <list> stmt_list stateful_stmt_list set_elem_stmt_list
+%destructor { stmt_list_free($$); xfree($$); } stmt_list stateful_stmt_list set_elem_stmt_list
+%type <stmt> stmt match_stmt verdict_stmt set_elem_stmt
+%destructor { stmt_free($$); } stmt match_stmt verdict_stmt set_elem_stmt
%type <stmt> counter_stmt counter_stmt_alloc stateful_stmt
%destructor { stmt_free($$); } counter_stmt counter_stmt_alloc stateful_stmt
%type <stmt> payload_stmt
@@ -673,8 +672,8 @@ int nft_lex(void *, void *, void *);
%type <expr> symbol_expr verdict_expr integer_expr variable_expr chain_expr policy_expr
%destructor { expr_free($$); } symbol_expr verdict_expr integer_expr variable_expr chain_expr policy_expr
-%type <expr> primary_expr shift_expr and_expr typeof_expr
-%destructor { expr_free($$); } primary_expr shift_expr and_expr typeof_expr
+%type <expr> primary_expr shift_expr and_expr typeof_expr typeof_data_expr
+%destructor { expr_free($$); } primary_expr shift_expr and_expr typeof_expr typeof_data_expr
%type <expr> exclusive_or_expr inclusive_or_expr
%destructor { expr_free($$); } exclusive_or_expr inclusive_or_expr
%type <expr> basic_expr
@@ -1554,7 +1553,10 @@ table_block_alloc : /* empty */
table_options : FLAGS STRING
{
if (strcmp($2, "dormant") == 0) {
- $<table>0->flags = TABLE_F_DORMANT;
+ $<table>0->flags |= TABLE_F_DORMANT;
+ xfree($2);
+ } else if (strcmp($2, "owner") == 0) {
+ $<table>0->flags |= TABLE_F_OWNER;
xfree($2);
} else {
erec_queue(error(&@2, "unknown table option %s", $2),
@@ -1740,6 +1742,38 @@ subchain_block : /* empty */ { $$ = $<chain>-1; }
}
;
+typeof_data_expr : primary_expr
+ {
+ struct expr *e = $1;
+
+ if (e->etype == EXPR_SYMBOL &&
+ strcmp("verdict", e->identifier) == 0) {
+ struct expr *v = verdict_expr_alloc(&@1, NF_ACCEPT, NULL);
+
+ expr_free(e);
+ v->flags &= ~EXPR_F_CONSTANT;
+ e = v;
+ }
+
+ if (expr_ops(e)->build_udata == NULL) {
+ erec_queue(error(&@1, "map data type '%s' lacks typeof serialization", expr_ops(e)->name),
+ state->msgs);
+ expr_free(e);
+ YYERROR;
+ }
+ $$ = e;
+ }
+ | typeof_expr DOT primary_expr
+ {
+ struct location rhs[] = {
+ [1] = @2,
+ [2] = @3,
+ };
+
+ $$ = handle_concat_expr(&@$, $$, $1, $3, rhs);
+ }
+ ;
+
typeof_expr : primary_expr
{
if (expr_ops($1)->build_udata == NULL) {
@@ -1798,10 +1832,11 @@ set_block : /* empty */ { $$ = $<set>-1; }
$1->gc_int = $3;
$$ = $1;
}
- | set_block COUNTER stmt_separator
+ | set_block stateful_stmt_list stmt_separator
{
- $1->stmt = counter_stmt_alloc(&@$);
+ list_splice_tail($2, &$1->stmt_list);
$$ = $1;
+ free($2);
}
| set_block ELEMENTS '=' set_block_expr
{
@@ -1878,7 +1913,7 @@ map_block : /* empty */ { $$ = $<set>-1; }
$$ = $1;
}
| map_block TYPEOF
- typeof_expr COLON typeof_expr
+ typeof_expr COLON typeof_data_expr
stmt_separator
{
$1->key = $3;
@@ -2657,6 +2692,19 @@ stmt_list : stmt
}
;
+stateful_stmt_list : stateful_stmt
+ {
+ $$ = xmalloc(sizeof(*$$));
+ init_list_head($$);
+ list_add_tail(&$1->list, $$);
+ }
+ | stateful_stmt_list stateful_stmt
+ {
+ $$ = $1;
+ list_add_tail(&$2->list, $1);
+ }
+ ;
+
stateful_stmt : counter_stmt
| limit_stmt
| quota_stmt
@@ -3025,6 +3073,11 @@ log_flag_tcp : SEQUENCE
limit_stmt : LIMIT RATE limit_mode NUM SLASH time_unit limit_burst_pkts
{
+ if ($7 == 0) {
+ erec_queue(error(&@7, "limit burst must be > 0"),
+ state->msgs);
+ YYERROR;
+ }
$$ = limit_stmt_alloc(&@$);
$$->limit.rate = $4;
$$->limit.unit = $6;
@@ -3037,6 +3090,12 @@ limit_stmt : LIMIT RATE limit_mode NUM SLASH time_unit limit_burst_pkts
struct error_record *erec;
uint64_t rate, unit;
+ if ($6 == 0) {
+ erec_queue(error(&@6, "limit burst must be > 0"),
+ state->msgs);
+ YYERROR;
+ }
+
erec = rate_parse(&@$, $5, &rate, &unit);
xfree($5);
if (erec != NULL) {
@@ -3113,11 +3172,11 @@ limit_mode : OVER { $$ = NFT_LIMIT_F_INV; }
| /* empty */ { $$ = 0; }
;
-limit_burst_pkts : /* empty */ { $$ = 0; }
+limit_burst_pkts : /* empty */ { $$ = 5; }
| BURST NUM PACKETS { $$ = $2; }
;
-limit_burst_bytes : /* empty */ { $$ = 0; }
+limit_burst_bytes : /* empty */ { $$ = 5; }
| BURST NUM BYTES { $$ = $2; }
| BURST NUM STRING
{
@@ -3676,13 +3735,14 @@ set_stmt : SET set_stmt_op set_elem_expr_stmt set_ref_expr
$$->set.key = $4;
$$->set.set = $2;
}
- | set_stmt_op set_ref_expr '{' set_elem_expr_stmt stateful_stmt '}'
+ | set_stmt_op set_ref_expr '{' set_elem_expr_stmt stateful_stmt_list '}'
{
$$ = set_stmt_alloc(&@$);
$$->set.op = $1;
$$->set.key = $4;
$$->set.set = $2;
- $$->set.stmt = $5;
+ list_splice_tail($5, &$$->set.stmt_list);
+ free($5);
}
;
@@ -3699,14 +3759,15 @@ map_stmt : set_stmt_op set_ref_expr '{' set_elem_expr_stmt COLON set_elem_expr_
$$->map.data = $6;
$$->map.set = $2;
}
- | set_stmt_op set_ref_expr '{' set_elem_expr_stmt stateful_stmt COLON set_elem_expr_stmt '}'
+ | set_stmt_op set_ref_expr '{' set_elem_expr_stmt stateful_stmt_list COLON set_elem_expr_stmt '}'
{
$$ = map_stmt_alloc(&@$);
$$->map.op = $1;
$$->map.key = $4;
$$->map.data = $7;
- $$->map.stmt = $5;
$$->map.set = $2;
+ list_splice_tail($5, &$$->map.stmt_list);
+ free($5);
}
;
@@ -4038,7 +4099,13 @@ set_elem_expr : set_elem_expr_alloc
| set_elem_expr_alloc set_elem_expr_options
;
-set_elem_expr_alloc : set_lhs_expr
+set_elem_expr_alloc : set_lhs_expr set_elem_stmt_list
+ {
+ $$ = set_elem_expr_alloc(&@1, $1);
+ list_splice_tail($2, &$$->stmt_list);
+ xfree($2);
+ }
+ | set_lhs_expr
{
$$ = set_elem_expr_alloc(&@1, $1);
}
@@ -4076,26 +4143,76 @@ set_elem_expr_options : set_elem_expr_option
| set_elem_expr_options set_elem_expr_option
;
-set_elem_expr_option : TIMEOUT time_spec
+set_elem_stmt_list : set_elem_stmt
{
- $<expr>0->timeout = $2;
+ $$ = xmalloc(sizeof(*$$));
+ init_list_head($$);
+ list_add_tail(&$1->list, $$);
}
- | EXPIRES time_spec
+ | set_elem_stmt_list set_elem_stmt
{
- $<expr>0->expiration = $2;
+ $$ = $1;
+ list_add_tail(&$2->list, $1);
}
- | COUNTER
+ ;
+
+set_elem_stmt : COUNTER
{
- $<expr>0->stmt = counter_stmt_alloc(&@$);
+ $$ = counter_stmt_alloc(&@$);
}
| COUNTER PACKETS NUM BYTES NUM
{
- struct stmt *stmt;
+ $$ = counter_stmt_alloc(&@$);
+ $$->counter.packets = $3;
+ $$->counter.bytes = $5;
+ }
+ | LIMIT RATE limit_mode NUM SLASH time_unit limit_burst_pkts
+ {
+ if ($7 == 0) {
+ erec_queue(error(&@7, "limit burst must be > 0"),
+ state->msgs);
+ YYERROR;
+ }
+ $$ = limit_stmt_alloc(&@$);
+ $$->limit.rate = $4;
+ $$->limit.unit = $6;
+ $$->limit.burst = $7;
+ $$->limit.type = NFT_LIMIT_PKTS;
+ $$->limit.flags = $3;
+ }
+ | LIMIT RATE limit_mode NUM STRING limit_burst_bytes
+ {
+ struct error_record *erec;
+ uint64_t rate, unit;
+
+ if ($6 == 0) {
+ erec_queue(error(&@6, "limit burst must be > 0"),
+ state->msgs);
+ YYERROR;
+ }
+ erec = rate_parse(&@$, $5, &rate, &unit);
+ xfree($5);
+ if (erec != NULL) {
+ erec_queue(erec, state->msgs);
+ YYERROR;
+ }
- stmt = counter_stmt_alloc(&@$);
- stmt->counter.packets = $3;
- stmt->counter.bytes = $5;
- $<expr>0->stmt = stmt;
+ $$ = limit_stmt_alloc(&@$);
+ $$->limit.rate = rate * $4;
+ $$->limit.unit = unit;
+ $$->limit.burst = $6;
+ $$->limit.type = NFT_LIMIT_PKT_BYTES;
+ $$->limit.flags = $3;
+ }
+ ;
+
+set_elem_expr_option : TIMEOUT time_spec
+ {
+ $<expr>0->timeout = $2;
+ }
+ | EXPIRES time_spec
+ {
+ $<expr>0->expiration = $2;
}
| comment_spec
{
@@ -4557,6 +4674,7 @@ relational_op : EQ { $$ = OP_EQ; }
| GT { $$ = OP_GT; }
| GTE { $$ = OP_GTE; }
| LTE { $$ = OP_LTE; }
+ | NOT { $$ = OP_NEG; }
;
verdict_expr : ACCEPT
diff --git a/src/parser_json.c b/src/parser_json.c
index b1de56a4..ddbf9d9c 100644
--- a/src/parser_json.c
+++ b/src/parser_json.c
@@ -1784,7 +1784,7 @@ static struct stmt *json_parse_limit_stmt(struct json_ctx *ctx,
const char *key, json_t *value)
{
struct stmt *stmt;
- uint64_t rate, burst = 0;
+ uint64_t rate, burst = 5;
const char *rate_unit = "packets", *time, *burst_unit = "bytes";
int inv = 0;
@@ -3763,20 +3763,33 @@ static int json_verify_metainfo(struct json_ctx *ctx, json_t *root)
struct json_cmd_assoc {
struct json_cmd_assoc *next;
+ struct hlist_node hnode;
const struct cmd *cmd;
json_t *json;
};
-static struct json_cmd_assoc *json_cmd_list = NULL;
+#define CMD_ASSOC_HSIZE 512
+static struct hlist_head json_cmd_assoc_hash[CMD_ASSOC_HSIZE];
+static struct json_cmd_assoc *json_cmd_assoc_list;
static void json_cmd_assoc_free(void)
{
struct json_cmd_assoc *cur;
+ struct hlist_node *pos, *n;
+ int i;
- while (json_cmd_list) {
- cur = json_cmd_list;
- json_cmd_list = cur->next;
- free(cur);
+ while (json_cmd_assoc_list) {
+ cur = json_cmd_assoc_list->next;
+ free(json_cmd_assoc_list);
+ json_cmd_assoc_list = cur;
+ }
+
+ for (i = 0; i < CMD_ASSOC_HSIZE; i++) {
+ hlist_for_each_entry_safe(cur, pos, n,
+ &json_cmd_assoc_hash[i], hnode) {
+ hlist_del(&cur->hnode);
+ free(cur);
+ }
}
}
@@ -3784,20 +3797,33 @@ static void json_cmd_assoc_add(json_t *json, const struct cmd *cmd)
{
struct json_cmd_assoc *new = xzalloc(sizeof *new);
- new->next = json_cmd_list;
new->json = json;
new->cmd = cmd;
- json_cmd_list = new;
+ new->next = json_cmd_assoc_list;
+
+ json_cmd_assoc_list = new;
}
static json_t *seqnum_to_json(const uint32_t seqnum)
{
- const struct json_cmd_assoc *cur;
+ struct json_cmd_assoc *cur;
+ struct hlist_node *n;
+ int key;
+
+ while (json_cmd_assoc_list) {
+ cur = json_cmd_assoc_list;
+ json_cmd_assoc_list = cur->next;
- for (cur = json_cmd_list; cur; cur = cur->next) {
+ key = cur->cmd->seqnum % CMD_ASSOC_HSIZE;
+ hlist_add_head(&cur->hnode, &json_cmd_assoc_hash[key]);
+ }
+
+ key = seqnum % CMD_ASSOC_HSIZE;
+ hlist_for_each_entry(cur, n, &json_cmd_assoc_hash[key], hnode) {
if (cur->cmd->seqnum == seqnum)
return cur->json;
}
+
return NULL;
}
@@ -3867,6 +3893,7 @@ int nft_parse_json_buffer(struct nft_ctx *nft, const char *buf,
};
int ret;
+ parser_init(nft, nft->state, msgs, cmds, nft->top_scope);
nft->json_root = json_loads(buf, 0, NULL);
if (!nft->json_root)
return -EINVAL;
@@ -3895,6 +3922,7 @@ int nft_parse_json_filename(struct nft_ctx *nft, const char *filename,
json_error_t err;
int ret;
+ parser_init(nft, nft->state, msgs, cmds, nft->top_scope);
nft->json_root = json_load_file(filename, 0, &err);
if (!nft->json_root)
return -EINVAL;
@@ -3973,8 +4001,11 @@ int json_events_cb(const struct nlmsghdr *nlh, struct netlink_mon_handler *monh)
return MNL_CB_OK;
json = seqnum_to_json(nlh->nlmsg_seq);
- if (!json)
+ if (!json) {
+ json_echo_error(monh, "No JSON command found with seqnum %lu\n",
+ nlh->nlmsg_seq);
return MNL_CB_OK;
+ }
tmp = json_object_get(json, "add");
if (!tmp)
@@ -4000,11 +4031,20 @@ int json_events_cb(const struct nlmsghdr *nlh, struct netlink_mon_handler *monh)
void json_print_echo(struct nft_ctx *ctx)
{
- if (!ctx->json_root)
- return;
+ if (!ctx->json_root) {
+ if (!ctx->json_echo)
+ return;
- json_dumpf(ctx->json_root, ctx->output.output_fp, JSON_PRESERVE_ORDER);
- json_cmd_assoc_free();
- json_decref(ctx->json_root);
- ctx->json_root = NULL;
+ ctx->json_echo = json_pack("{s:o}", "nftables", ctx->json_echo);
+ json_dumpf(ctx->json_echo, ctx->output.output_fp, JSON_PRESERVE_ORDER);
+ json_decref(ctx->json_echo);
+ ctx->json_echo = NULL;
+ fprintf(ctx->output.output_fp, "\n");
+ fflush(ctx->output.output_fp);
+ } else {
+ json_dumpf(ctx->json_root, ctx->output.output_fp, JSON_PRESERVE_ORDER);
+ json_cmd_assoc_free();
+ json_decref(ctx->json_root);
+ ctx->json_root = NULL;
+ }
}
diff --git a/src/payload.c b/src/payload.c
index e51c5797..a77ca550 100644
--- a/src/payload.c
+++ b/src/payload.c
@@ -19,6 +19,8 @@
#include <arpa/inet.h>
#include <linux/netfilter.h>
#include <linux/if_ether.h>
+#include <netinet/ip_icmp.h>
+#include <netinet/icmp6.h>
#include <rule.h>
#include <expression.h>
@@ -95,8 +97,16 @@ static void payload_expr_pctx_update(struct proto_ctx *ctx,
base = ctx->protocol[left->payload.base].desc;
desc = proto_find_upper(base, proto);
- if (!desc)
+ if (!desc) {
+ if (base == &proto_icmp || base == &proto_icmp6) {
+ /* proto 0 is ECHOREPLY, just pretend its ECHO.
+ * Not doing this would need an additional marker
+ * bit to tell when icmp.type was set.
+ */
+ ctx->th_dep.icmp.type = proto ? proto : ICMP_ECHO;
+ }
return;
+ }
assert(desc->base <= PROTO_BASE_MAX);
if (desc->base == base->base) {
@@ -544,6 +554,35 @@ void payload_dependency_reset(struct payload_dep_ctx *ctx)
memset(ctx, 0, sizeof(*ctx));
}
+static uint8_t icmp_get_type(const struct proto_desc *desc, uint8_t value)
+{
+ if (desc == &proto_icmp && value == 0)
+ return ICMP_ECHO;
+
+ return value;
+}
+
+static uint8_t icmp_get_dep_type(const struct proto_desc *desc, struct expr *right)
+{
+ if (right->etype == EXPR_VALUE && right->len == BITS_PER_BYTE)
+ return icmp_get_type(desc, mpz_get_uint8(right->value));
+
+ return 0;
+}
+
+static void payload_dependency_store_icmp_type(struct payload_dep_ctx *ctx)
+{
+ struct expr *dep = ctx->pdep->expr;
+ const struct proto_desc *desc;
+
+ if (dep->left->etype != EXPR_PAYLOAD)
+ return;
+
+ desc = dep->left->payload.desc;
+ if (desc == &proto_icmp || desc == &proto_icmp6)
+ ctx->icmp_type = icmp_get_dep_type(dep->left->payload.desc, dep->right);
+}
+
/**
* payload_dependency_store - store a possibly redundant protocol match
*
@@ -556,6 +595,8 @@ void payload_dependency_store(struct payload_dep_ctx *ctx,
{
ctx->pbase = base + 1;
ctx->pdep = stmt;
+
+ payload_dependency_store_icmp_type(ctx);
}
/**
@@ -571,8 +612,8 @@ bool payload_dependency_exists(const struct payload_dep_ctx *ctx,
enum proto_bases base)
{
return ctx->pbase != PROTO_BASE_INVALID &&
- ctx->pbase == base &&
- ctx->pdep != NULL;
+ ctx->pdep != NULL &&
+ (ctx->pbase == base || (base == PROTO_BASE_TRANSPORT_HDR && ctx->pbase == base + 1));
}
void payload_dependency_release(struct payload_dep_ctx *ctx)
@@ -586,6 +627,40 @@ void payload_dependency_release(struct payload_dep_ctx *ctx)
ctx->pdep = NULL;
}
+static uint8_t icmp_dep_to_type(enum icmp_hdr_field_type t)
+{
+ switch (t) {
+ case PROTO_ICMP_ANY:
+ BUG("Invalid map for simple dependency");
+ case PROTO_ICMP_ECHO: return ICMP_ECHO;
+ case PROTO_ICMP6_ECHO: return ICMP6_ECHO_REQUEST;
+ case PROTO_ICMP_MTU: return ICMP_DEST_UNREACH;
+ case PROTO_ICMP_ADDRESS: return ICMP_REDIRECT;
+ case PROTO_ICMP6_MTU: return ICMP6_PACKET_TOO_BIG;
+ case PROTO_ICMP6_MGMQ: return MLD_LISTENER_QUERY;
+ case PROTO_ICMP6_PPTR: return ICMP6_PARAM_PROB;
+ }
+
+ BUG("Missing icmp type mapping");
+}
+
+static bool payload_may_dependency_kill_icmp(struct payload_dep_ctx *ctx, struct expr *expr)
+{
+ const struct expr *dep = ctx->pdep->expr;
+ uint8_t icmp_type;
+
+ icmp_type = expr->payload.tmpl->icmp_dep;
+ if (icmp_type == PROTO_ICMP_ANY)
+ return false;
+
+ if (dep->left->payload.desc != expr->payload.desc)
+ return false;
+
+ icmp_type = icmp_dep_to_type(expr->payload.tmpl->icmp_dep);
+
+ return ctx->icmp_type == icmp_type;
+}
+
static bool payload_may_dependency_kill(struct payload_dep_ctx *ctx,
unsigned int family, struct expr *expr)
{
@@ -620,6 +695,14 @@ static bool payload_may_dependency_kill(struct payload_dep_ctx *ctx,
break;
}
+ if (expr->payload.base == PROTO_BASE_TRANSPORT_HDR &&
+ dep->left->payload.base == PROTO_BASE_TRANSPORT_HDR) {
+ if (dep->left->payload.desc == &proto_icmp)
+ return payload_may_dependency_kill_icmp(ctx, expr);
+ if (dep->left->payload.desc == &proto_icmp6)
+ return payload_may_dependency_kill_icmp(ctx, expr);
+ }
+
return true;
}
@@ -689,6 +772,11 @@ void payload_expr_complete(struct expr *expr, const struct proto_ctx *ctx)
if (tmpl->offset != expr->payload.offset ||
tmpl->len != expr->len)
continue;
+
+ if (tmpl->icmp_dep && ctx->th_dep.icmp.type &&
+ ctx->th_dep.icmp.type != icmp_dep_to_type(tmpl->icmp_dep))
+ continue;
+
expr->dtype = tmpl->dtype;
expr->payload.desc = desc;
expr->payload.tmpl = tmpl;
@@ -815,6 +903,10 @@ void payload_expr_expand(struct list_head *list, struct expr *expr,
if (tmpl->offset != expr->payload.offset)
continue;
+ if (tmpl->icmp_dep && ctx->th_dep.icmp.type &&
+ ctx->th_dep.icmp.type != icmp_dep_to_type(tmpl->icmp_dep))
+ continue;
+
if (tmpl->len <= expr->len) {
new = payload_expr_alloc(&expr->location, desc, i);
list_add_tail(&new->list, list);
@@ -913,3 +1005,136 @@ struct expr *payload_expr_join(const struct expr *e1, const struct expr *e2)
expr->len = e1->len + e2->len;
return expr;
}
+
+static struct stmt *
+__payload_gen_icmp_simple_dependency(struct eval_ctx *ctx, const struct expr *expr,
+ const struct datatype *icmp_type,
+ const struct proto_desc *desc,
+ uint8_t type)
+{
+ struct expr *left, *right, *dep;
+
+ left = payload_expr_alloc(&expr->location, desc, desc->protocol_key);
+ right = constant_expr_alloc(&expr->location, icmp_type,
+ BYTEORDER_BIG_ENDIAN, BITS_PER_BYTE,
+ constant_data_ptr(type, BITS_PER_BYTE));
+
+ dep = relational_expr_alloc(&expr->location, OP_EQ, left, right);
+ return expr_stmt_alloc(&dep->location, dep);
+}
+
+static struct stmt *
+__payload_gen_icmp_echo_dependency(struct eval_ctx *ctx, const struct expr *expr,
+ uint8_t echo, uint8_t reply,
+ const struct datatype *icmp_type,
+ const struct proto_desc *desc)
+{
+ struct expr *left, *right, *dep, *set;
+
+ left = payload_expr_alloc(&expr->location, desc, desc->protocol_key);
+
+ set = set_expr_alloc(&expr->location, NULL);
+
+ right = constant_expr_alloc(&expr->location, icmp_type,
+ BYTEORDER_BIG_ENDIAN, BITS_PER_BYTE,
+ constant_data_ptr(echo, BITS_PER_BYTE));
+ right = set_elem_expr_alloc(&expr->location, right);
+ compound_expr_add(set, right);
+
+ right = constant_expr_alloc(&expr->location, icmp_type,
+ BYTEORDER_BIG_ENDIAN, BITS_PER_BYTE,
+ constant_data_ptr(reply, BITS_PER_BYTE));
+ right = set_elem_expr_alloc(&expr->location, right);
+ compound_expr_add(set, right);
+
+ dep = relational_expr_alloc(&expr->location, OP_IMPLICIT, left, set);
+ return expr_stmt_alloc(&dep->location, dep);
+}
+
+int payload_gen_icmp_dependency(struct eval_ctx *ctx, const struct expr *expr,
+ struct stmt **res)
+{
+ const struct proto_hdr_template *tmpl;
+ const struct proto_desc *desc;
+ struct stmt *stmt = NULL;
+ uint8_t type;
+
+ assert(expr->etype == EXPR_PAYLOAD);
+
+ tmpl = expr->payload.tmpl;
+ desc = expr->payload.desc;
+
+ switch (tmpl->icmp_dep) {
+ case PROTO_ICMP_ANY:
+ BUG("No dependency needed");
+ break;
+ case PROTO_ICMP_ECHO:
+ /* do not test ICMP_ECHOREPLY here: its 0 */
+ if (ctx->pctx.th_dep.icmp.type == ICMP_ECHO)
+ goto done;
+
+ type = ICMP_ECHO;
+ if (ctx->pctx.th_dep.icmp.type)
+ goto bad_proto;
+
+ stmt = __payload_gen_icmp_echo_dependency(ctx, expr,
+ ICMP_ECHO, ICMP_ECHOREPLY,
+ &icmp_type_type,
+ desc);
+ break;
+ case PROTO_ICMP_MTU:
+ case PROTO_ICMP_ADDRESS:
+ type = icmp_dep_to_type(tmpl->icmp_dep);
+ if (ctx->pctx.th_dep.icmp.type == type)
+ goto done;
+ if (ctx->pctx.th_dep.icmp.type)
+ goto bad_proto;
+ stmt = __payload_gen_icmp_simple_dependency(ctx, expr,
+ &icmp_type_type,
+ desc, type);
+ break;
+ case PROTO_ICMP6_ECHO:
+ if (ctx->pctx.th_dep.icmp.type == ICMP6_ECHO_REQUEST ||
+ ctx->pctx.th_dep.icmp.type == ICMP6_ECHO_REPLY)
+ goto done;
+
+ type = ICMP6_ECHO_REQUEST;
+ if (ctx->pctx.th_dep.icmp.type)
+ goto bad_proto;
+
+ stmt = __payload_gen_icmp_echo_dependency(ctx, expr,
+ ICMP6_ECHO_REQUEST,
+ ICMP6_ECHO_REPLY,
+ &icmp6_type_type,
+ desc);
+ break;
+ case PROTO_ICMP6_MTU:
+ case PROTO_ICMP6_MGMQ:
+ case PROTO_ICMP6_PPTR:
+ type = icmp_dep_to_type(tmpl->icmp_dep);
+ if (ctx->pctx.th_dep.icmp.type == type)
+ goto done;
+ if (ctx->pctx.th_dep.icmp.type)
+ goto bad_proto;
+ stmt = __payload_gen_icmp_simple_dependency(ctx, expr,
+ &icmp6_type_type,
+ desc, type);
+ break;
+ break;
+ default:
+ BUG("Unhandled icmp dependency code");
+ }
+
+ ctx->pctx.th_dep.icmp.type = type;
+
+ if (stmt_evaluate(ctx, stmt) < 0)
+ return expr_error(ctx->msgs, expr,
+ "icmp dependency statement is invalid");
+done:
+ *res = stmt;
+ return 0;
+
+bad_proto:
+ return expr_error(ctx->msgs, expr, "incompatible icmp match: rule has %d, need %u",
+ ctx->pctx.th_dep.icmp.type, type);
+}
diff --git a/src/proto.c b/src/proto.c
index c42e8f51..b75626df 100644
--- a/src/proto.c
+++ b/src/proto.c
@@ -396,25 +396,37 @@ const struct datatype icmp_type_type = {
.sym_tbl = &icmp_type_tbl,
};
-#define ICMPHDR_FIELD(__name, __member) \
- HDR_FIELD(__name, struct icmphdr, __member)
+#define ICMP46HDR_FIELD(__token, __struct, __member, __dep) \
+ { \
+ .token = (__token), \
+ .dtype = &integer_type, \
+ .byteorder = BYTEORDER_BIG_ENDIAN, \
+ .offset = offsetof(__struct, __member) * 8, \
+ .len = field_sizeof(__struct, __member) * 8, \
+ .icmp_dep = (__dep), \
+ }
+
+#define ICMPHDR_FIELD(__token, __member, __dep) \
+ ICMP46HDR_FIELD(__token, struct icmphdr, __member, __dep)
+
#define ICMPHDR_TYPE(__name, __type, __member) \
- HDR_TYPE(__name, __type, struct icmphdr, __member)
+ HDR_TYPE(__name, __type, struct icmphdr, __member)
const struct proto_desc proto_icmp = {
.name = "icmp",
.id = PROTO_DESC_ICMP,
.base = PROTO_BASE_TRANSPORT_HDR,
+ .protocol_key = ICMPHDR_TYPE,
.checksum_key = ICMPHDR_CHECKSUM,
.checksum_type = NFT_PAYLOAD_CSUM_INET,
.templates = {
[ICMPHDR_TYPE] = ICMPHDR_TYPE("type", &icmp_type_type, type),
[ICMPHDR_CODE] = ICMPHDR_TYPE("code", &icmp_code_type, code),
- [ICMPHDR_CHECKSUM] = ICMPHDR_FIELD("checksum", checksum),
- [ICMPHDR_ID] = ICMPHDR_FIELD("id", un.echo.id),
- [ICMPHDR_SEQ] = ICMPHDR_FIELD("sequence", un.echo.sequence),
- [ICMPHDR_GATEWAY] = ICMPHDR_FIELD("gateway", un.gateway),
- [ICMPHDR_MTU] = ICMPHDR_FIELD("mtu", un.frag.mtu),
+ [ICMPHDR_CHECKSUM] = ICMPHDR_FIELD("checksum", checksum, PROTO_ICMP_ANY),
+ [ICMPHDR_ID] = ICMPHDR_FIELD("id", un.echo.id, PROTO_ICMP_ECHO),
+ [ICMPHDR_SEQ] = ICMPHDR_FIELD("sequence", un.echo.sequence, PROTO_ICMP_ECHO),
+ [ICMPHDR_GATEWAY] = ICMPHDR_FIELD("gateway", un.gateway, PROTO_ICMP_ADDRESS),
+ [ICMPHDR_MTU] = ICMPHDR_FIELD("mtu", un.frag.mtu, PROTO_ICMP_MTU),
},
};
@@ -813,8 +825,8 @@ const struct datatype icmp6_type_type = {
.sym_tbl = &icmp6_type_tbl,
};
-#define ICMP6HDR_FIELD(__name, __member) \
- HDR_FIELD(__name, struct icmp6_hdr, __member)
+#define ICMP6HDR_FIELD(__token, __member, __dep) \
+ ICMP46HDR_FIELD(__token, struct icmp6_hdr, __member, __dep)
#define ICMP6HDR_TYPE(__name, __type, __member) \
HDR_TYPE(__name, __type, struct icmp6_hdr, __member)
@@ -822,17 +834,18 @@ const struct proto_desc proto_icmp6 = {
.name = "icmpv6",
.id = PROTO_DESC_ICMPV6,
.base = PROTO_BASE_TRANSPORT_HDR,
+ .protocol_key = ICMP6HDR_TYPE,
.checksum_key = ICMP6HDR_CHECKSUM,
.checksum_type = NFT_PAYLOAD_CSUM_INET,
.templates = {
[ICMP6HDR_TYPE] = ICMP6HDR_TYPE("type", &icmp6_type_type, icmp6_type),
[ICMP6HDR_CODE] = ICMP6HDR_TYPE("code", &icmpv6_code_type, icmp6_code),
- [ICMP6HDR_CHECKSUM] = ICMP6HDR_FIELD("checksum", icmp6_cksum),
- [ICMP6HDR_PPTR] = ICMP6HDR_FIELD("parameter-problem", icmp6_pptr),
- [ICMP6HDR_MTU] = ICMP6HDR_FIELD("mtu", icmp6_mtu),
- [ICMP6HDR_ID] = ICMP6HDR_FIELD("id", icmp6_id),
- [ICMP6HDR_SEQ] = ICMP6HDR_FIELD("sequence", icmp6_seq),
- [ICMP6HDR_MAXDELAY] = ICMP6HDR_FIELD("max-delay", icmp6_maxdelay),
+ [ICMP6HDR_CHECKSUM] = ICMP6HDR_FIELD("checksum", icmp6_cksum, PROTO_ICMP_ANY),
+ [ICMP6HDR_PPTR] = ICMP6HDR_FIELD("parameter-problem", icmp6_pptr, PROTO_ICMP6_PPTR),
+ [ICMP6HDR_MTU] = ICMP6HDR_FIELD("mtu", icmp6_mtu, PROTO_ICMP6_MTU),
+ [ICMP6HDR_ID] = ICMP6HDR_FIELD("id", icmp6_id, PROTO_ICMP6_ECHO),
+ [ICMP6HDR_SEQ] = ICMP6HDR_FIELD("sequence", icmp6_seq, PROTO_ICMP6_ECHO),
+ [ICMP6HDR_MAXDELAY] = ICMP6HDR_FIELD("max-delay", icmp6_maxdelay, PROTO_ICMP6_MGMQ),
},
};
diff --git a/src/rule.c b/src/rule.c
index dddfdf51..acb10f65 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -25,6 +25,7 @@
#include <misspell.h>
#include <json.h>
#include <cache.h>
+#include <owner.h>
#include <libnftnl/common.h>
#include <libnftnl/ruleset.h>
@@ -338,6 +339,9 @@ struct set *set_alloc(const struct location *loc)
set->handle.set_id = ++set_id;
if (loc != NULL)
set->location = *loc;
+
+ init_list_head(&set->stmt_list);
+
return set;
}
@@ -357,6 +361,7 @@ struct set *set_clone(const struct set *set)
new_set->policy = set->policy;
new_set->automerge = set->automerge;
new_set->desc = set->desc;
+ init_list_head(&new_set->stmt_list);
return new_set;
}
@@ -369,6 +374,8 @@ struct set *set_get(struct set *set)
void set_free(struct set *set)
{
+ struct stmt *stmt, *next;
+
if (--set->refcnt > 0)
return;
if (set->init != NULL)
@@ -376,7 +383,8 @@ void set_free(struct set *set)
if (set->comment)
xfree(set->comment);
handle_free(&set->handle);
- stmt_free(set->stmt);
+ list_for_each_entry_safe(stmt, next, &set->stmt_list, list)
+ stmt_free(stmt);
expr_free(set->key);
expr_free(set->data);
xfree(set);
@@ -500,6 +508,7 @@ static void set_print_declaration(const struct set *set,
struct output_ctx *octx)
{
const char *delim = "";
+ struct stmt *stmt;
const char *type;
uint32_t flags;
@@ -570,14 +579,22 @@ static void set_print_declaration(const struct set *set,
nft_print(octx, "%s", opts->stmt_separator);
}
- if (set->stmt) {
+ if (!list_empty(&set->stmt_list))
nft_print(octx, "%s%s", opts->tab, opts->tab);
+
+ if (!list_empty(&set->stmt_list)) {
octx->flags |= NFT_CTX_OUTPUT_STATELESS;
- stmt_print(set->stmt, octx);
+ list_for_each_entry(stmt, &set->stmt_list, list) {
+ stmt_print(stmt, octx);
+ if (!list_is_last(&stmt->list, &set->stmt_list))
+ nft_print(octx, " ");
+ }
octx->flags &= ~NFT_CTX_OUTPUT_STATELESS;
- nft_print(octx, "%s", opts->stmt_separator);
}
+ if (!list_empty(&set->stmt_list))
+ nft_print(octx, "%s", opts->stmt_separator);
+
if (set->automerge)
nft_print(octx, "%s%sauto-merge%s", opts->tab, opts->tab,
opts->stmt_separator);
@@ -1389,29 +1406,41 @@ struct table *table_lookup_fuzzy(const struct handle *h,
return st.obj;
}
-const char *table_flags_name[TABLE_FLAGS_MAX] = {
+static const char *table_flags_name[TABLE_FLAGS_MAX] = {
"dormant",
+ "owner",
};
-static void table_print_options(const struct table *table, const char **delim,
- struct output_ctx *octx)
+const char *table_flag_name(uint32_t flag)
+{
+ if (flag >= TABLE_FLAGS_MAX)
+ return "unknown";
+
+ return table_flags_name[flag];
+}
+
+static void table_print_flags(const struct table *table, const char **delim,
+ struct output_ctx *octx)
{
uint32_t flags = table->flags;
+ bool comma = false;
int i;
- if (flags) {
- nft_print(octx, "\tflags ");
+ if (!table->flags)
+ return;
- for (i = 0; i < TABLE_FLAGS_MAX; i++) {
- if (flags & 0x1)
- nft_print(octx, "%s", table_flags_name[i]);
- flags >>= 1;
- if (flags)
+ nft_print(octx, "\tflags ");
+ for (i = 0; i < TABLE_FLAGS_MAX; i++) {
+ if (flags & (1 << i)) {
+ if (comma)
nft_print(octx, ",");
+
+ nft_print(octx, "%s", table_flag_name(i));
+ comma = true;
}
- nft_print(octx, "\n");
- *delim = "\n";
}
+ nft_print(octx, "\n");
+ *delim = "\n";
}
static void table_print(const struct table *table, struct output_ctx *octx)
@@ -1424,10 +1453,15 @@ static void table_print(const struct table *table, struct output_ctx *octx)
const char *family = family2str(table->handle.family);
nft_print(octx, "table %s %s {", family, table->handle.table.name);
+ if (nft_output_handle(octx) || table->flags & TABLE_F_OWNER)
+ nft_print(octx, " #");
if (nft_output_handle(octx))
- nft_print(octx, " # handle %" PRIu64, table->handle.handle.id);
+ nft_print(octx, " handle %" PRIu64, table->handle.handle.id);
+ if (table->flags & TABLE_F_OWNER)
+ nft_print(octx, " progname %s", get_progname(table->owner));
+
nft_print(octx, "\n");
- table_print_options(table, &delim, octx);
+ table_print_flags(table, &delim, octx);
if (table->comment)
nft_print(octx, "\tcomment \"%s\"\n", table->comment);
diff --git a/src/segtree.c b/src/segtree.c
index ba455a6a..9aa39e52 100644
--- a/src/segtree.c
+++ b/src/segtree.c
@@ -568,6 +568,18 @@ static void segtree_linearize(struct list_head *list, const struct set *set,
mpz_clear(q);
}
+static void interval_expr_copy(struct expr *dst, struct expr *src)
+{
+ if (src->comment)
+ dst->comment = xstrdup(src->comment);
+ if (src->timeout)
+ dst->timeout = src->timeout;
+ if (src->expiration)
+ dst->expiration = src->expiration;
+
+ list_splice_init(&src->stmt_list, &dst->stmt_list);
+}
+
static void set_insert_interval(struct expr *set, struct seg_tree *tree,
const struct elementary_interval *ei)
{
@@ -580,17 +592,11 @@ static void set_insert_interval(struct expr *set, struct seg_tree *tree,
if (ei->expr != NULL) {
if (ei->expr->etype == EXPR_MAPPING) {
- if (ei->expr->left->comment)
- expr->comment = xstrdup(ei->expr->left->comment);
- if (ei->expr->left->timeout)
- expr->timeout = ei->expr->left->timeout;
+ interval_expr_copy(expr, ei->expr->left);
expr = mapping_expr_alloc(&ei->expr->location, expr,
expr_get(ei->expr->right));
} else {
- if (ei->expr->comment)
- expr->comment = xstrdup(ei->expr->comment);
- if (ei->expr->timeout)
- expr->timeout = ei->expr->timeout;
+ interval_expr_copy(expr, ei->expr);
}
}
@@ -927,20 +933,6 @@ next:
}
}
-static void interval_expr_copy(struct expr *dst, struct expr *src)
-{
- if (src->comment)
- dst->comment = xstrdup(src->comment);
- if (src->timeout)
- dst->timeout = src->timeout;
- if (src->expiration)
- dst->expiration = src->expiration;
- if (src->stmt) {
- dst->stmt = src->stmt;
- src->stmt = NULL;
- }
-}
-
void interval_map_decompose(struct expr *set)
{
struct expr **elements, **ranges;
diff --git a/src/statement.c b/src/statement.c
index 6fe8e9d9..f7f1c0c4 100644
--- a/src/statement.c
+++ b/src/statement.c
@@ -464,7 +464,7 @@ static void limit_stmt_print(const struct stmt *stmt, struct output_ctx *octx)
nft_print(octx, "limit rate %s%" PRIu64 " %s/%s",
inv ? "over " : "", rate, data_unit,
get_unit(stmt->limit.unit));
- if (stmt->limit.burst > 0) {
+ if (stmt->limit.burst != 5) {
uint64_t burst;
data_unit = get_rate(stmt->limit.burst, &burst);
@@ -732,15 +732,16 @@ const char * const set_stmt_op_names[] = {
static void set_stmt_print(const struct stmt *stmt, struct output_ctx *octx)
{
unsigned int flags = octx->flags;
+ struct stmt *this;
nft_print(octx, "%s ", set_stmt_op_names[stmt->set.op]);
expr_print(stmt->set.set, octx);
nft_print(octx, " { ");
expr_print(stmt->set.key, octx);
- if (stmt->set.stmt) {
+ list_for_each_entry(this, &stmt->set.stmt_list, list) {
nft_print(octx, " ");
octx->flags |= NFT_CTX_OUTPUT_STATELESS;
- stmt_print(stmt->set.stmt, octx);
+ stmt_print(this, octx);
octx->flags = flags;
}
nft_print(octx, " }");
@@ -748,9 +749,12 @@ static void set_stmt_print(const struct stmt *stmt, struct output_ctx *octx)
static void set_stmt_destroy(struct stmt *stmt)
{
+ struct stmt *this, *next;
+
expr_free(stmt->set.key);
expr_free(stmt->set.set);
- stmt_free(stmt->set.stmt);
+ list_for_each_entry_safe(this, next, &stmt->set.stmt_list, list)
+ stmt_free(this);
}
static const struct stmt_ops set_stmt_ops = {
@@ -763,21 +767,27 @@ static const struct stmt_ops set_stmt_ops = {
struct stmt *set_stmt_alloc(const struct location *loc)
{
- return stmt_alloc(loc, &set_stmt_ops);
+ struct stmt *stmt;
+
+ stmt = stmt_alloc(loc, &set_stmt_ops);
+ init_list_head(&stmt->set.stmt_list);
+
+ return stmt;
}
static void map_stmt_print(const struct stmt *stmt, struct output_ctx *octx)
{
unsigned int flags = octx->flags;
+ struct stmt *this;
nft_print(octx, "%s ", set_stmt_op_names[stmt->map.op]);
expr_print(stmt->map.set, octx);
nft_print(octx, " { ");
expr_print(stmt->map.key, octx);
- if (stmt->map.stmt) {
+ list_for_each_entry(this, &stmt->map.stmt_list, list) {
nft_print(octx, " ");
octx->flags |= NFT_CTX_OUTPUT_STATELESS;
- stmt_print(stmt->map.stmt, octx);
+ stmt_print(this, octx);
octx->flags = flags;
}
nft_print(octx, " : ");
@@ -787,10 +797,13 @@ static void map_stmt_print(const struct stmt *stmt, struct output_ctx *octx)
static void map_stmt_destroy(struct stmt *stmt)
{
+ struct stmt *this, *next;
+
expr_free(stmt->map.key);
expr_free(stmt->map.data);
expr_free(stmt->map.set);
- stmt_free(stmt->map.stmt);
+ list_for_each_entry_safe(this, next, &stmt->map.stmt_list, list)
+ stmt_free(this);
}
static const struct stmt_ops map_stmt_ops = {
@@ -802,7 +815,12 @@ static const struct stmt_ops map_stmt_ops = {
struct stmt *map_stmt_alloc(const struct location *loc)
{
- return stmt_alloc(loc, &map_stmt_ops);
+ struct stmt *stmt;
+
+ stmt = stmt_alloc(loc, &map_stmt_ops);
+ init_list_head(&stmt->map.stmt_list);
+
+ return stmt;
}
static void dup_stmt_print(const struct stmt *stmt, struct output_ctx *octx)
diff --git a/tests/build/run-tests.sh b/tests/build/run-tests.sh
index ccb62af3..9ce93a8e 100755
--- a/tests/build/run-tests.sh
+++ b/tests/build/run-tests.sh
@@ -2,7 +2,7 @@
log_file="`pwd`/tests.log"
dir=../..
-argument=( --without-cli --with-cli=linenoise --enable-debug --with-mini-gmp
+argument=( --without-cli --with-cli=linenoise --with-cli=editline --enable-debug --with-mini-gmp
--enable-man-doc --with-xtables --with-json)
ok=0
failed=0
diff --git a/tests/monitor/run-tests.sh b/tests/monitor/run-tests.sh
index 5a736fc6..1fe613c7 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)
diff --git a/tests/py/any/ct.t b/tests/py/any/ct.t
index cc09aebc..a44142ac 100644
--- a/tests/py/any/ct.t
+++ b/tests/py/any/ct.t
@@ -26,9 +26,11 @@ ct status != expected;ok
ct status seen-reply;ok
ct status != seen-reply;ok
ct status {expected, seen-reply, assured, confirmed, dying};ok
+ct status != {expected, seen-reply, assured, confirmed, dying};ok
ct status expected,seen-reply,assured,confirmed,snat,dnat,dying;ok
ct status snat;ok
ct status dnat;ok
+ct status ! dnat;ok
ct status xxx;fail
ct mark 0;ok;ct mark 0x00000000
diff --git a/tests/py/any/ct.t.json b/tests/py/any/ct.t.json
index c5c15b9c..d429ae73 100644
--- a/tests/py/any/ct.t.json
+++ b/tests/py/any/ct.t.json
@@ -311,6 +311,29 @@
}
]
+# ct status != {expected, seen-reply, assured, confirmed, dying}
+[
+ {
+ "match": {
+ "left": {
+ "ct": {
+ "key": "status"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ "expected",
+ "seen-reply",
+ "assured",
+ "confirmed",
+ "dying"
+ ]
+ }
+ }
+ }
+]
+
# ct status expected,seen-reply,assured,confirmed,snat,dnat,dying
[
{
@@ -989,39 +1012,6 @@
}
]
-# ct state . ct mark { new . 0x12345678}
-[
- {
- "match": {
- "left": {
- "concat": [
- {
- "ct": {
- "key": "state"
- }
- },
- {
- "ct": {
- "key": "mark"
- }
- }
- ]
- },
- "op": "==",
- "right": {
- "set": [
- {
- "concat": [
- "new",
- "0x12345678"
- ]
- }
- ]
- }
- }
- }
-]
-
# ct state . ct mark { new . 0x12345678, new . 0x34127856, established . 0x12785634}
[
{
diff --git a/tests/py/any/ct.t.payload b/tests/py/any/ct.t.payload
index 51a82503..a80e5a8d 100644
--- a/tests/py/any/ct.t.payload
+++ b/tests/py/any/ct.t.payload
@@ -306,15 +306,6 @@ ip test-ip4 output
[ ct load helper => reg 1 ]
[ cmp eq reg 1 0x00707466 0x00000000 0x00000000 0x00000000 ]
-# ct state . ct mark { new . 0x12345678}
-__set%d test 3
-__set%d test 0
- element 00000008 12345678 : 0 [end]
-ip test-ip4 output
- [ ct load state => reg 1 ]
- [ ct load mark => reg 9 ]
- [ lookup reg 1 set __set%d ]
-
# ct state . ct mark { new . 0x12345678, new . 0x34127856, established . 0x12785634}
__set%d test-ip4 3
__set%d test-ip4 0
@@ -511,3 +502,9 @@ ip test-ip4 output
[ ct load unknown => reg 1 ]
[ cmp eq reg 1 0x39300000 ]
+# ct status ! dnat
+ip6
+ [ ct load status => reg 1 ]
+ [ bitwise reg 1 = ( reg 1 & 0x00000020 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000000 ]
+
diff --git a/tests/py/any/limit.t.json.output b/tests/py/any/limit.t.json.output
new file mode 100644
index 00000000..e6f26496
--- /dev/null
+++ b/tests/py/any/limit.t.json.output
@@ -0,0 +1,277 @@
+# limit rate 400/minute
+[
+ {
+ "limit": {
+ "burst": 5,
+ "per": "minute",
+ "rate": 400
+ }
+ }
+]
+
+# limit rate 20/second
+[
+ {
+ "limit": {
+ "burst": 5,
+ "per": "second",
+ "rate": 20
+ }
+ }
+]
+
+# limit rate 400/hour
+[
+ {
+ "limit": {
+ "burst": 5,
+ "per": "hour",
+ "rate": 400
+ }
+ }
+]
+
+# limit rate 40/day
+[
+ {
+ "limit": {
+ "burst": 5,
+ "per": "day",
+ "rate": 40
+ }
+ }
+]
+
+# limit rate 400/week
+[
+ {
+ "limit": {
+ "burst": 5,
+ "per": "week",
+ "rate": 400
+ }
+ }
+]
+
+# limit rate 1 kbytes/second
+[
+ {
+ "limit": {
+ "burst": 5,
+ "burst_unit": "bytes",
+ "per": "second",
+ "rate": 1,
+ "rate_unit": "kbytes"
+ }
+ }
+]
+
+# limit rate 2 kbytes/second
+[
+ {
+ "limit": {
+ "burst": 5,
+ "burst_unit": "bytes",
+ "per": "second",
+ "rate": 2,
+ "rate_unit": "kbytes"
+ }
+ }
+]
+
+# limit rate 1025 kbytes/second
+[
+ {
+ "limit": {
+ "burst": 5,
+ "burst_unit": "bytes",
+ "per": "second",
+ "rate": 1025,
+ "rate_unit": "kbytes"
+ }
+ }
+]
+
+# limit rate 1023 mbytes/second
+[
+ {
+ "limit": {
+ "burst": 5,
+ "burst_unit": "bytes",
+ "per": "second",
+ "rate": 1023,
+ "rate_unit": "mbytes"
+ }
+ }
+]
+
+# limit rate 10230 mbytes/second
+[
+ {
+ "limit": {
+ "burst": 5,
+ "burst_unit": "bytes",
+ "per": "second",
+ "rate": 10230,
+ "rate_unit": "mbytes"
+ }
+ }
+]
+
+# limit rate 1023000 mbytes/second
+[
+ {
+ "limit": {
+ "burst": 5,
+ "burst_unit": "bytes",
+ "per": "second",
+ "rate": 1023000,
+ "rate_unit": "mbytes"
+ }
+ }
+]
+
+# limit rate over 400/minute
+[
+ {
+ "limit": {
+ "burst": 5,
+ "inv": true,
+ "per": "minute",
+ "rate": 400
+ }
+ }
+]
+
+# limit rate over 20/second
+[
+ {
+ "limit": {
+ "burst": 5,
+ "inv": true,
+ "per": "second",
+ "rate": 20
+ }
+ }
+]
+
+# limit rate over 400/hour
+[
+ {
+ "limit": {
+ "burst": 5,
+ "inv": true,
+ "per": "hour",
+ "rate": 400
+ }
+ }
+]
+
+# limit rate over 40/day
+[
+ {
+ "limit": {
+ "burst": 5,
+ "inv": true,
+ "per": "day",
+ "rate": 40
+ }
+ }
+]
+
+# limit rate over 400/week
+[
+ {
+ "limit": {
+ "burst": 5,
+ "inv": true,
+ "per": "week",
+ "rate": 400
+ }
+ }
+]
+
+# limit rate over 1 kbytes/second
+[
+ {
+ "limit": {
+ "burst": 5,
+ "burst_unit": "bytes",
+ "inv": true,
+ "per": "second",
+ "rate": 1,
+ "rate_unit": "kbytes"
+ }
+ }
+]
+
+# limit rate over 2 kbytes/second
+[
+ {
+ "limit": {
+ "burst": 5,
+ "burst_unit": "bytes",
+ "inv": true,
+ "per": "second",
+ "rate": 2,
+ "rate_unit": "kbytes"
+ }
+ }
+]
+
+# limit rate over 1025 kbytes/second
+[
+ {
+ "limit": {
+ "burst": 5,
+ "burst_unit": "bytes",
+ "inv": true,
+ "per": "second",
+ "rate": 1025,
+ "rate_unit": "kbytes"
+ }
+ }
+]
+
+# limit rate over 1023 mbytes/second
+[
+ {
+ "limit": {
+ "burst": 5,
+ "burst_unit": "bytes",
+ "inv": true,
+ "per": "second",
+ "rate": 1023,
+ "rate_unit": "mbytes"
+ }
+ }
+]
+
+# limit rate over 10230 mbytes/second
+[
+ {
+ "limit": {
+ "burst": 5,
+ "burst_unit": "bytes",
+ "inv": true,
+ "per": "second",
+ "rate": 10230,
+ "rate_unit": "mbytes"
+ }
+ }
+]
+
+# limit rate over 1023000 mbytes/second
+[
+ {
+ "limit": {
+ "burst": 5,
+ "burst_unit": "bytes",
+ "inv": true,
+ "per": "second",
+ "rate": 1023000,
+ "rate_unit": "mbytes"
+ }
+ }
+]
+
diff --git a/tests/py/any/limit.t.payload b/tests/py/any/limit.t.payload
index b0cc84b4..dc6cea9b 100644
--- a/tests/py/any/limit.t.payload
+++ b/tests/py/any/limit.t.payload
@@ -1,22 +1,22 @@
# limit rate 400/minute
ip test-ip4 output
- [ limit rate 400/minute burst 0 type packets flags 0x0 ]
+ [ limit rate 400/minute burst 5 type packets flags 0x0 ]
# limit rate 20/second
ip test-ip4 output
- [ limit rate 20/second burst 0 type packets flags 0x0 ]
+ [ limit rate 20/second burst 5 type packets flags 0x0 ]
# limit rate 400/hour
ip test-ip4 output
- [ limit rate 400/hour burst 0 type packets flags 0x0 ]
+ [ limit rate 400/hour burst 5 type packets flags 0x0 ]
# limit rate 400/week
ip test-ip4 output
- [ limit rate 400/week burst 0 type packets flags 0x0 ]
+ [ limit rate 400/week burst 5 type packets flags 0x0 ]
# limit rate 40/day
ip test-ip4 output
- [ limit rate 40/day burst 0 type packets flags 0x0 ]
+ [ limit rate 40/day burst 5 type packets flags 0x0 ]
# limit rate 1023/second burst 10 packets
ip test-ip4 output
@@ -24,27 +24,27 @@ ip test-ip4 output
# limit rate 1 kbytes/second
ip test-ip4 output
- [ limit rate 1024/second burst 0 type bytes flags 0x0 ]
+ [ limit rate 1024/second burst 5 type bytes flags 0x0 ]
# limit rate 2 kbytes/second
ip test-ip4 output
- [ limit rate 2048/second burst 0 type bytes flags 0x0 ]
+ [ limit rate 2048/second burst 5 type bytes flags 0x0 ]
# limit rate 1025 kbytes/second
ip test-ip4 output
- [ limit rate 1049600/second burst 0 type bytes flags 0x0 ]
+ [ limit rate 1049600/second burst 5 type bytes flags 0x0 ]
# limit rate 1023 mbytes/second
ip test-ip4 output
- [ limit rate 1072693248/second burst 0 type bytes flags 0x0 ]
+ [ limit rate 1072693248/second burst 5 type bytes flags 0x0 ]
# limit rate 10230 mbytes/second
ip test-ip4 output
- [ limit rate 10726932480/second burst 0 type bytes flags 0x0 ]
+ [ limit rate 10726932480/second burst 5 type bytes flags 0x0 ]
# limit rate 1023000 mbytes/second
ip test-ip4 output
- [ limit rate 1072693248000/second burst 0 type bytes flags 0x0 ]
+ [ limit rate 1072693248000/second burst 5 type bytes flags 0x0 ]
# limit rate 1025 bytes/second burst 512 bytes
ip test-ip4 output
@@ -64,23 +64,23 @@ ip test-ip4 output
# limit rate over 400/minute
ip test-ip4 output
- [ limit rate 400/minute burst 0 type packets flags 0x1 ]
+ [ limit rate 400/minute burst 5 type packets flags 0x1 ]
# limit rate over 20/second
ip test-ip4 output
- [ limit rate 20/second burst 0 type packets flags 0x1 ]
+ [ limit rate 20/second burst 5 type packets flags 0x1 ]
# limit rate over 400/hour
ip test-ip4 output
- [ limit rate 400/hour burst 0 type packets flags 0x1 ]
+ [ limit rate 400/hour burst 5 type packets flags 0x1 ]
# limit rate over 400/week
ip test-ip4 output
- [ limit rate 400/week burst 0 type packets flags 0x1 ]
+ [ limit rate 400/week burst 5 type packets flags 0x1 ]
# limit rate over 40/day
ip test-ip4 output
- [ limit rate 40/day burst 0 type packets flags 0x1 ]
+ [ limit rate 40/day burst 5 type packets flags 0x1 ]
# limit rate over 1023/second burst 10 packets
ip test-ip4 output
@@ -88,27 +88,27 @@ ip test-ip4 output
# limit rate over 1 kbytes/second
ip test-ip4 output
- [ limit rate 1024/second burst 0 type bytes flags 0x1 ]
+ [ limit rate 1024/second burst 5 type bytes flags 0x1 ]
# limit rate over 2 kbytes/second
ip test-ip4 output
- [ limit rate 2048/second burst 0 type bytes flags 0x1 ]
+ [ limit rate 2048/second burst 5 type bytes flags 0x1 ]
# limit rate over 1025 kbytes/second
ip test-ip4 output
- [ limit rate 1049600/second burst 0 type bytes flags 0x1 ]
+ [ limit rate 1049600/second burst 5 type bytes flags 0x1 ]
# limit rate over 1023 mbytes/second
ip test-ip4 output
- [ limit rate 1072693248/second burst 0 type bytes flags 0x1 ]
+ [ limit rate 1072693248/second burst 5 type bytes flags 0x1 ]
# limit rate over 10230 mbytes/second
ip test-ip4 output
- [ limit rate 10726932480/second burst 0 type bytes flags 0x1 ]
+ [ limit rate 10726932480/second burst 5 type bytes flags 0x1 ]
# limit rate over 1023000 mbytes/second
ip test-ip4 output
- [ limit rate 1072693248000/second burst 0 type bytes flags 0x1 ]
+ [ limit rate 1072693248000/second burst 5 type bytes flags 0x1 ]
# limit rate over 1025 bytes/second burst 512 bytes
ip test-ip4 output
diff --git a/tests/py/any/meta.t b/tests/py/any/meta.t
index 327f973f..7b582505 100644
--- a/tests/py/any/meta.t
+++ b/tests/py/any/meta.t
@@ -29,7 +29,7 @@ meta l4proto 22;ok
meta l4proto != 233;ok
meta l4proto 33-45;ok
meta l4proto != 33-45;ok
-meta l4proto { 33, 55, 67, 88};ok;meta l4proto { 33, 55, 67, 88}
+meta l4proto { 33, 55, 67, 88};ok
meta l4proto != { 33, 55, 67, 88};ok
meta l4proto { 33-55, 66-88};ok
meta l4proto != { 33-55, 66-88};ok
@@ -101,10 +101,10 @@ meta skuid != "root";ok;meta skuid != 0
meta skuid lt 3000 accept;ok;meta skuid < 3000 accept
meta skuid gt 3000 accept;ok;meta skuid > 3000 accept
meta skuid eq 3000 accept;ok;meta skuid 3000 accept
-meta skuid 3001-3005 accept;ok;meta skuid 3001-3005 accept
-meta skuid != 2001-2005 accept;ok;meta skuid != 2001-2005 accept
-meta skuid { 2001-2005, 3001-3005} accept;ok;meta skuid { 2001-2005, 3001-3005} accept
-meta skuid != { 2001-2005, 3001-3005} accept;ok;meta skuid != { 2001-2005, 3001-3005} accept
+meta skuid 3001-3005 accept;ok
+meta skuid != 2001-2005 accept;ok
+meta skuid { 2001-2005, 3001-3005} accept;ok
+meta skuid != { 2001-2005, 3001-3005} accept;ok
meta skgid {"bin", "root", "daemon"} accept;ok;meta skgid { 0, 1, 2} accept
meta skgid != {"bin", "root", "daemon"} accept;ok;meta skgid != { 1, 0, 2} accept
@@ -113,10 +113,10 @@ meta skgid != "root";ok;meta skgid != 0
meta skgid lt 3000 accept;ok;meta skgid < 3000 accept
meta skgid gt 3000 accept;ok;meta skgid > 3000 accept
meta skgid eq 3000 accept;ok;meta skgid 3000 accept
-meta skgid 2001-2005 accept;ok;meta skgid 2001-2005 accept
-meta skgid != 2001-2005 accept;ok;meta skgid != 2001-2005 accept
-meta skgid { 2001-2005} accept;ok;meta skgid { 2001-2005} accept
-meta skgid != { 2001-2005} accept;ok;meta skgid != { 2001-2005} accept
+meta skgid 2001-2005 accept;ok
+meta skgid != 2001-2005 accept;ok
+meta skgid { 2001-2005} accept;ok
+meta skgid != { 2001-2005} accept;ok
# BUG: meta nftrace 2 and meta nftrace 1
# $ sudo nft add rule ip test input meta nftrace 2
@@ -188,14 +188,14 @@ meta oifgroup {11-33, 44-55};ok;oifgroup {11-33, 44-55}
meta oifgroup != { 11,33};ok;oifgroup != { 11,33}
meta oifgroup != {11-33, 44-55};ok;oifgroup != {11-33, 44-55}
-meta cgroup 1048577;ok;meta cgroup 1048577
-meta cgroup != 1048577;ok;meta cgroup != 1048577
-meta cgroup { 1048577, 1048578 };ok;meta cgroup { 1048577, 1048578}
-meta cgroup != { 1048577, 1048578};ok;meta cgroup != { 1048577, 1048578}
-meta cgroup 1048577-1048578;ok;meta cgroup 1048577-1048578
-meta cgroup != 1048577-1048578;ok;meta cgroup != 1048577-1048578
-meta cgroup {1048577-1048578};ok;meta cgroup { 1048577-1048578}
-meta cgroup != { 1048577-1048578};ok;meta cgroup != { 1048577-1048578}
+meta cgroup 1048577;ok
+meta cgroup != 1048577;ok
+meta cgroup { 1048577, 1048578 };ok
+meta cgroup != { 1048577, 1048578};ok
+meta cgroup 1048577-1048578;ok
+meta cgroup != 1048577-1048578;ok
+meta cgroup {1048577-1048578};ok
+meta cgroup != { 1048577-1048578};ok
meta iif . meta oif { "lo" . "lo" };ok;iif . oif { "lo" . "lo" }
meta iif . meta oif . meta mark { "lo" . "lo" . 0x0000000a };ok;iif . oif . meta mark { "lo" . "lo" . 0x0000000a }
diff --git a/tests/py/any/meta.t.payload b/tests/py/any/meta.t.payload
index 463365e2..c3664525 100644
--- a/tests/py/any/meta.t.payload
+++ b/tests/py/any/meta.t.payload
@@ -631,22 +631,6 @@ ip test-ip4 input
[ meta load iifgroup => reg 1 ]
[ cmp neq reg 1 0x00000000 ]
-# meta iifgroup {"default"}
-__set%d test-ip4 3
-__set%d test-ip4 0
- element 00000000 : 0 [end]
-ip test-ip4 input
- [ meta load iifgroup => reg 1 ]
- [ lookup reg 1 set __set%d ]
-
-# meta iifgroup != {"default"}
-__set%d test-ip4 3
-__set%d test-ip4 0
- element 00000000 : 0 [end]
-ip test-ip4 input
- [ meta load iifgroup => reg 1 ]
- [ lookup reg 1 set __set%d 0x1 ]
-
# meta iifgroup { 11,33}
__set%d test-ip4 3
__set%d test-ip4 0
@@ -977,34 +961,6 @@ ip test-ip4 input
[ meta load oifgroup => reg 1 ]
[ lookup reg 1 set __set%d 0x1 ]
-# meta iif . meta oif { "lo" . "lo" , "dummy0" . "dummy0" }
-__set%d test-ip4 3 size 2
-__set%d test-ip4 0
- element 00000001 00000001 : 0 [end] element 00000005 00000005 : 0 [end]
-ip test-ip4 input
- [ meta load iif => reg 1 ]
- [ meta load oif => reg 9 ]
- [ lookup reg 1 set __set%d ]
-
-# meta iif . meta oif . meta mark { "lo" . "lo" . 0x0000000a, "dummy0" . "dummy0" . 0x0000000b }
-__set%d test-ip4 3 size 2
-__set%d test-ip4 0
- element 00000001 00000001 0000000a : 0 [end] element 00000005 00000005 0000000b : 0 [end]
-ip test-ip4 input
- [ meta load iif => reg 1 ]
- [ meta load oif => reg 9 ]
- [ meta load mark => reg 10 ]
- [ lookup reg 1 set __set%d ]
-
-# meta iif . meta oif vmap { "lo" . "lo" : drop, "dummy0" . "dummy0" : accept }
-__map%d test-ip4 b size 2
-__map%d test-ip4 0
- element 00000001 00000001 : 0 [end] element 00000005 00000005 : 0 [end]
-ip test-ip4 input
- [ meta load iif => reg 1 ]
- [ meta load oif => reg 9 ]
- [ lookup reg 1 set __map%d dreg 0 ]
-
# meta skgid { 2001-2005} accept
__set%d test-ip4 7 size 3
__set%d test-ip4 0
diff --git a/tests/py/any/tcpopt.t b/tests/py/any/tcpopt.t
index e759ac61..f17a20b5 100644
--- a/tests/py/any/tcpopt.t
+++ b/tests/py/any/tcpopt.t
@@ -37,7 +37,6 @@ tcp option foobar;fail
tcp option foo bar;fail
tcp option eol left;fail
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
diff --git a/tests/py/any/tcpopt.t.payload b/tests/py/any/tcpopt.t.payload
index 56473798..1005df32 100644
--- a/tests/py/any/tcpopt.t.payload
+++ b/tests/py/any/tcpopt.t.payload
@@ -1,210 +1,150 @@
# tcp option eol kind 1
inet
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000006 ]
[ exthdr load tcpopt 1b @ 0 + 0 => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
# tcp option nop kind 1
inet
- [ 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 maxseg kind 1
inet
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000006 ]
[ exthdr load tcpopt 1b @ 2 + 0 => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
# tcp option maxseg length 1
inet
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000006 ]
[ exthdr load tcpopt 1b @ 2 + 1 => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
# tcp option maxseg size 1
inet
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000006 ]
[ exthdr load tcpopt 2b @ 2 + 2 => reg 1 ]
[ cmp eq reg 1 0x00000100 ]
# tcp option window kind 1
inet
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000006 ]
[ exthdr load tcpopt 1b @ 3 + 0 => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
# tcp option window length 1
inet
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000006 ]
[ exthdr load tcpopt 1b @ 3 + 1 => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
# tcp option window count 1
inet
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000006 ]
[ exthdr load tcpopt 1b @ 3 + 2 => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
# 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-perm length 1
inet
- [ 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 kind 1
inet
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000006 ]
[ exthdr load tcpopt 1b @ 5 + 0 => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
# tcp option sack length 1
inet
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000006 ]
[ exthdr load tcpopt 1b @ 5 + 1 => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
# tcp option sack left 1
inet
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000006 ]
[ exthdr load tcpopt 4b @ 5 + 2 => reg 1 ]
[ cmp eq reg 1 0x01000000 ]
# tcp option sack0 left 1
inet
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000006 ]
[ exthdr load tcpopt 4b @ 5 + 2 => reg 1 ]
[ cmp eq reg 1 0x01000000 ]
# tcp option sack1 left 1
inet
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000006 ]
[ exthdr load tcpopt 4b @ 5 + 10 => reg 1 ]
[ cmp eq reg 1 0x01000000 ]
# tcp option sack2 left 1
inet
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000006 ]
[ exthdr load tcpopt 4b @ 5 + 18 => reg 1 ]
[ cmp eq reg 1 0x01000000 ]
# tcp option sack3 left 1
inet
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000006 ]
[ exthdr load tcpopt 4b @ 5 + 26 => reg 1 ]
[ cmp eq reg 1 0x01000000 ]
# tcp option sack right 1
inet
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000006 ]
[ exthdr load tcpopt 4b @ 5 + 6 => reg 1 ]
[ cmp eq reg 1 0x01000000 ]
# tcp option sack0 right 1
inet
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000006 ]
[ exthdr load tcpopt 4b @ 5 + 6 => reg 1 ]
[ cmp eq reg 1 0x01000000 ]
# tcp option sack1 right 1
inet
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000006 ]
[ exthdr load tcpopt 4b @ 5 + 14 => reg 1 ]
[ cmp eq reg 1 0x01000000 ]
# tcp option sack2 right 1
inet
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000006 ]
[ exthdr load tcpopt 4b @ 5 + 22 => reg 1 ]
[ cmp eq reg 1 0x01000000 ]
# tcp option sack3 right 1
inet
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000006 ]
[ exthdr load tcpopt 4b @ 5 + 30 => reg 1 ]
[ cmp eq reg 1 0x01000000 ]
# tcp option timestamp kind 1
inet
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000006 ]
[ exthdr load tcpopt 1b @ 8 + 0 => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
# tcp option timestamp length 1
inet
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000006 ]
[ exthdr load tcpopt 1b @ 8 + 1 => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
# tcp option timestamp tsval 1
inet
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000006 ]
[ exthdr load tcpopt 4b @ 8 + 2 => reg 1 ]
[ cmp eq reg 1 0x01000000 ]
# tcp option timestamp tsecr 1
inet
- [ 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 255 missing
inet
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000006 ]
[ 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 ]
- [ cmp eq reg 1 0x00000006 ]
[ exthdr load tcpopt 1b @ 3 + 0 present => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
# tcp option window 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 0x00000000 ]
diff --git a/tests/py/arp/arp.t b/tests/py/arp/arp.t
index 109d01d7..2eee7838 100644
--- a/tests/py/arp/arp.t
+++ b/tests/py/arp/arp.t
@@ -46,7 +46,6 @@ arp operation rreply;ok
arp operation inrequest;ok
arp operation inreply;ok
arp operation nak;ok
-arp operation reply;ok
arp operation != request;ok
arp operation != reply;ok
arp operation != rrequest;ok
@@ -54,7 +53,6 @@ arp operation != rreply;ok
arp operation != inrequest;ok
arp operation != inreply;ok
arp operation != nak;ok
-arp operation != reply;ok
arp saddr ip 1.2.3.4;ok
arp daddr ip 4.3.2.1;ok
diff --git a/tests/py/arp/arp.t.json b/tests/py/arp/arp.t.json
index 8508c170..73224f7e 100644
--- a/tests/py/arp/arp.t.json
+++ b/tests/py/arp/arp.t.json
@@ -693,22 +693,6 @@
}
]
-# arp operation reply
-[
- {
- "match": {
- "left": {
- "payload": {
- "field": "operation",
- "protocol": "arp"
- }
- },
- "op": "==",
- "right": "reply"
- }
- }
-]
-
# arp operation != request
[
{
@@ -821,22 +805,6 @@
}
]
-# arp operation != reply
-[
- {
- "match": {
- "left": {
- "payload": {
- "field": "operation",
- "protocol": "arp"
- }
- },
- "op": "!=",
- "right": "reply"
- }
- }
-]
-
# arp saddr ip 1.2.3.4
[
{
diff --git a/tests/py/arp/arp.t.payload b/tests/py/arp/arp.t.payload
index f819853f..a95c834e 100644
--- a/tests/py/arp/arp.t.payload
+++ b/tests/py/arp/arp.t.payload
@@ -229,11 +229,6 @@ arp test-arp input
[ payload load 2b @ network header + 6 => reg 1 ]
[ cmp eq reg 1 0x00000a00 ]
-# arp operation reply
-arp test-arp input
- [ payload load 2b @ network header + 6 => reg 1 ]
- [ cmp eq reg 1 0x00000200 ]
-
# arp operation != request
arp test-arp input
[ payload load 2b @ network header + 6 => reg 1 ]
@@ -269,11 +264,6 @@ arp test-arp input
[ payload load 2b @ network header + 6 => reg 1 ]
[ cmp neq reg 1 0x00000a00 ]
-# arp operation != reply
-arp test-arp input
- [ payload load 2b @ network header + 6 => reg 1 ]
- [ cmp neq reg 1 0x00000200 ]
-
# meta iifname "invalid" arp ptype 0x0800 arp htype 1 arp hlen 6 arp plen 4 @nh,192,32 0xc0a88f10 @nh,144,48 set 0x112233445566
arp test-arp input
[ meta load iifname => reg 1 ]
diff --git a/tests/py/arp/arp.t.payload.netdev b/tests/py/arp/arp.t.payload.netdev
index f57610cf..ac985a9a 100644
--- a/tests/py/arp/arp.t.payload.netdev
+++ b/tests/py/arp/arp.t.payload.netdev
@@ -303,13 +303,6 @@ netdev test-netdev ingress
[ payload load 2b @ network header + 6 => reg 1 ]
[ cmp eq reg 1 0x00000a00 ]
-# arp operation reply
-netdev test-netdev ingress
- [ meta load protocol => reg 1 ]
- [ cmp eq reg 1 0x00000608 ]
- [ payload load 2b @ network header + 6 => reg 1 ]
- [ cmp eq reg 1 0x00000200 ]
-
# arp operation != request
netdev test-netdev ingress
[ meta load protocol => reg 1 ]
@@ -359,13 +352,6 @@ netdev test-netdev ingress
[ payload load 2b @ network header + 6 => reg 1 ]
[ cmp neq reg 1 0x00000a00 ]
-# arp operation != reply
-netdev test-netdev ingress
- [ meta load protocol => reg 1 ]
- [ cmp eq reg 1 0x00000608 ]
- [ payload load 2b @ network header + 6 => reg 1 ]
- [ cmp neq reg 1 0x00000200 ]
-
# meta iifname "invalid" arp ptype 0x0800 arp htype 1 arp hlen 6 arp plen 4 @nh,192,32 0xc0a88f10 @nh,144,48 set 0x112233445566
netdev test-netdev ingress
[ meta load iifname => reg 1 ]
diff --git a/tests/py/bridge/reject.t.json.output b/tests/py/bridge/reject.t.json.output
index 4f83f803..e01a63af 100644
--- a/tests/py/bridge/reject.t.json.output
+++ b/tests/py/bridge/reject.t.json.output
@@ -1,103 +1,3 @@
-# reject with icmp type host-unreachable
-[
- {
- "reject": {
- "expr": "host-unreachable",
- "type": "icmp"
- }
- }
-]
-
-# reject with icmp type net-unreachable
-[
- {
- "reject": {
- "expr": "net-unreachable",
- "type": "icmp"
- }
- }
-]
-
-# reject with icmp type prot-unreachable
-[
- {
- "reject": {
- "expr": "prot-unreachable",
- "type": "icmp"
- }
- }
-]
-
-# reject with icmp type net-prohibited
-[
- {
- "reject": {
- "expr": "net-prohibited",
- "type": "icmp"
- }
- }
-]
-
-# reject with icmp type host-prohibited
-[
- {
- "reject": {
- "expr": "host-prohibited",
- "type": "icmp"
- }
- }
-]
-
-# reject with icmp type admin-prohibited
-[
- {
- "reject": {
- "expr": "admin-prohibited",
- "type": "icmp"
- }
- }
-]
-
-# reject with icmpv6 type no-route
-[
- {
- "reject": {
- "expr": "no-route",
- "type": "icmpv6"
- }
- }
-]
-
-# reject with icmpv6 type admin-prohibited
-[
- {
- "reject": {
- "expr": "admin-prohibited",
- "type": "icmpv6"
- }
- }
-]
-
-# reject with icmpv6 type addr-unreachable
-[
- {
- "reject": {
- "expr": "addr-unreachable",
- "type": "icmpv6"
- }
- }
-]
-
-# reject with icmpv6 type port-unreachable
-[
- {
- "reject": {
- "expr": "port-unreachable",
- "type": "icmpv6"
- }
- }
-]
-
# mark 12345 ip protocol tcp reject with tcp reset
[
{
@@ -130,10 +30,13 @@
}
]
-# reject with icmpx type port-unreachable
+# reject
[
{
- "reject": null
+ "reject": {
+ "expr": "port-unreachable",
+ "type": "icmpx"
+ }
}
]
@@ -156,3 +59,26 @@
}
}
]
+
+# ether type vlan reject
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "ether"
+ }
+ },
+ "op": "==",
+ "right": "vlan"
+ }
+ },
+ {
+ "reject": {
+ "expr": "port-unreachable",
+ "type": "icmpx"
+ }
+ }
+]
+
diff --git a/tests/py/inet/ah.t b/tests/py/inet/ah.t
index 8544d9dd..945db996 100644
--- a/tests/py/inet/ah.t
+++ b/tests/py/inet/ah.t
@@ -6,8 +6,6 @@
*inet;test-inet;input
*netdev;test-netdev;ingress
-# nexthdr Bug to list table.
-
- ah nexthdr esp;ok
- ah nexthdr ah;ok
- ah nexthdr comp;ok
diff --git a/tests/py/inet/dccp.t.json b/tests/py/inet/dccp.t.json
index 9260fbc5..97e33c14 100644
--- a/tests/py/inet/dccp.t.json
+++ b/tests/py/inet/dccp.t.json
@@ -98,24 +98,6 @@
}
]
-# dccp sport ftp-data - re-mail-ck
-[
- {
- "match": {
- "left": {
- "payload": {
- "field": "sport",
- "protocol": "dccp"
- }
- },
- "op": "==",
- "right": {
- "range": [ "ftp-data", "re-mail-ck" ]
- }
- }
- }
-]
-
# dccp sport 20-50
[
{
diff --git a/tests/py/inet/dccp.t.payload b/tests/py/inet/dccp.t.payload
index b830aa4f..b252d829 100644
--- a/tests/py/inet/dccp.t.payload
+++ b/tests/py/inet/dccp.t.payload
@@ -43,14 +43,6 @@ inet test-inet input
[ payload load 2b @ transport header + 0 => reg 1 ]
[ lookup reg 1 set __set%d ]
-# dccp sport ftp-data - re-mail-ck
-inet test-inet input
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000021 ]
- [ payload load 2b @ transport header + 0 => reg 1 ]
- [ cmp gte reg 1 0x00001400 ]
- [ cmp lte reg 1 0x00003200 ]
-
# dccp sport 20-50
inet test-inet input
[ meta load l4proto => reg 1 ]
diff --git a/tests/py/inet/esp.t b/tests/py/inet/esp.t
index e79eeada..ebba7d87 100644
--- a/tests/py/inet/esp.t
+++ b/tests/py/inet/esp.t
@@ -13,6 +13,7 @@ esp spi != 111-222;ok
esp spi { 100, 102};ok
esp spi != { 100, 102};ok
esp spi { 100-102};ok
+esp spi != { 100-102};ok
- esp spi {100-102};ok
esp sequence 22;ok
diff --git a/tests/py/inet/esp.t.json b/tests/py/inet/esp.t.json
index 84ea9eea..ee690f96 100644
--- a/tests/py/inet/esp.t.json
+++ b/tests/py/inet/esp.t.json
@@ -128,6 +128,26 @@
}
]
+# esp spi != { 100-102}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "spi",
+ "protocol": "esp"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ { "range": [ 100, 102 ] }
+ ]
+ }
+ }
+ }
+]
+
# esp sequence 22
[
{
diff --git a/tests/py/inet/ether.t.payload.bridge b/tests/py/inet/ether.t.payload.bridge
index 4a6bccbe..e9208008 100644
--- a/tests/py/inet/ether.t.payload.bridge
+++ b/tests/py/inet/ether.t.payload.bridge
@@ -1,17 +1,3 @@
-# tcp dport 22 iiftype ether ether saddr 00:0f:54:0c:11:4 meta nfproto ipv4 accept
-bridge test-bridge input
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000006 ]
- [ payload load 2b @ transport header + 2 => reg 1 ]
- [ cmp eq reg 1 0x00001600 ]
- [ meta load iiftype => reg 1 ]
- [ cmp eq reg 1 0x00000001 ]
- [ payload load 6b @ link header + 6 => reg 1 ]
- [ cmp eq reg 1 0x0c540f00 0x00000411 ]
- [ meta load nfproto => reg 1 ]
- [ cmp eq reg 1 0x00000002 ]
- [ immediate reg 0 accept ]
-
# tcp dport 22 iiftype ether ether saddr 00:0f:54:0c:11:4 accept
bridge test-bridge input
[ meta load l4proto => reg 1 ]
@@ -40,10 +26,3 @@ bridge test-bridge input
[ cmp eq reg 1 0x0c540f00 0x00000411 ]
[ immediate reg 0 accept ]
-# ether saddr 00:0f:54:0c:11:04 meta nfproto ipv4
-bridge test-bridge input
- [ payload load 6b @ link header + 6 => reg 1 ]
- [ cmp eq reg 1 0x0c540f00 0x00000411 ]
- [ meta load nfproto => reg 1 ]
- [ cmp eq reg 1 0x00000002 ]
-
diff --git a/tests/py/inet/ether.t.payload.ip b/tests/py/inet/ether.t.payload.ip
index 196930fd..a604f603 100644
--- a/tests/py/inet/ether.t.payload.ip
+++ b/tests/py/inet/ether.t.payload.ip
@@ -1,17 +1,3 @@
-# tcp dport 22 iiftype ether ether saddr 00:0f:54:0c:11:4 meta nfproto ipv4 accept
-ip test-ip4 input
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000006 ]
- [ payload load 2b @ transport header + 2 => reg 1 ]
- [ cmp eq reg 1 0x00001600 ]
- [ meta load iiftype => reg 1 ]
- [ cmp eq reg 1 0x00000001 ]
- [ payload load 6b @ link header + 6 => reg 1 ]
- [ cmp eq reg 1 0x0c540f00 0x00000411 ]
- [ meta load nfproto => reg 1 ]
- [ cmp eq reg 1 0x00000002 ]
- [ immediate reg 0 accept ]
-
# tcp dport 22 iiftype ether ether saddr 00:0f:54:0c:11:4 accept
ip test-ip4 input
[ meta load l4proto => reg 1 ]
@@ -44,12 +30,3 @@ ip test-ip4 input
[ cmp eq reg 1 0x0c540f00 0x00000411 ]
[ immediate reg 0 accept ]
-# ether saddr 00:0f:54:0c:11:04 meta nfproto ipv4
-ip test-ip4 input
- [ meta load iiftype => reg 1 ]
- [ cmp eq reg 1 0x00000001 ]
- [ payload load 6b @ link header + 6 => reg 1 ]
- [ cmp eq reg 1 0x0c540f00 0x00000411 ]
- [ meta load nfproto => reg 1 ]
- [ cmp eq reg 1 0x00000002 ]
-
diff --git a/tests/py/inet/reject.t b/tests/py/inet/reject.t
index 0e8966c9..a9ecd2ea 100644
--- a/tests/py/inet/reject.t
+++ b/tests/py/inet/reject.t
@@ -2,33 +2,32 @@
*inet;test-inet;input
-# The output is specific for inet family
-reject with icmp type host-unreachable;ok;meta nfproto ipv4 reject with icmp type host-unreachable
-reject with icmp type net-unreachable;ok;meta nfproto ipv4 reject with icmp type net-unreachable
-reject with icmp type prot-unreachable;ok;meta nfproto ipv4 reject with icmp type prot-unreachable
-reject with icmp type port-unreachable;ok;meta nfproto ipv4 reject
-reject with icmp type net-prohibited;ok;meta nfproto ipv4 reject with icmp type net-prohibited
-reject with icmp type host-prohibited;ok;meta nfproto ipv4 reject with icmp type host-prohibited
-reject with icmp type admin-prohibited;ok;meta nfproto ipv4 reject with icmp type admin-prohibited
-
-reject with icmpv6 type no-route;ok;meta nfproto ipv6 reject with icmpv6 type no-route
-reject with icmpv6 type admin-prohibited;ok;meta nfproto ipv6 reject with icmpv6 type admin-prohibited
-reject with icmpv6 type addr-unreachable;ok;meta nfproto ipv6 reject with icmpv6 type addr-unreachable
-reject with icmpv6 type port-unreachable;ok;meta nfproto ipv6 reject
+reject with icmp type host-unreachable;ok
+reject with icmp type net-unreachable;ok
+reject with icmp type prot-unreachable;ok
+reject with icmp type port-unreachable;ok
+reject with icmp type net-prohibited;ok
+reject with icmp type host-prohibited;ok
+reject with icmp type admin-prohibited;ok
+
+reject with icmpv6 type no-route;ok
+reject with icmpv6 type admin-prohibited;ok
+reject with icmpv6 type addr-unreachable;ok
+reject with icmpv6 type port-unreachable;ok
mark 12345 reject with tcp reset;ok;meta l4proto 6 meta mark 0x00003039 reject with tcp reset
reject;ok
-meta nfproto ipv4 reject;ok
-meta nfproto ipv6 reject;ok
+meta nfproto ipv4 reject;ok;reject with icmp type port-unreachable
+meta nfproto ipv6 reject;ok;reject with icmpv6 type port-unreachable
reject with icmpx type host-unreachable;ok
reject with icmpx type no-route;ok
reject with icmpx type admin-prohibited;ok
reject with icmpx type port-unreachable;ok;reject
-meta nfproto ipv4 reject with icmp type host-unreachable;ok
-meta nfproto ipv6 reject with icmpv6 type no-route;ok
+meta nfproto ipv4 reject with icmp type host-unreachable;ok;reject with icmp type host-unreachable
+meta nfproto ipv6 reject with icmpv6 type no-route;ok;reject with icmpv6 type no-route
meta nfproto ipv6 reject with icmp type host-unreachable;fail
meta nfproto ipv4 ip protocol icmp reject with icmpv6 type no-route;fail
diff --git a/tests/py/inet/reject.t.json.output b/tests/py/inet/reject.t.json.output
index 73846fb0..043617a7 100644
--- a/tests/py/inet/reject.t.json.output
+++ b/tests/py/inet/reject.t.json.output
@@ -1,145 +1,73 @@
-# reject with icmp type host-unreachable
+# mark 12345 reject with tcp reset
[
{
"match": {
"left": {
- "meta": { "key": "nfproto" }
+ "meta": { "key": "l4proto" }
},
"op": "==",
- "right": "ipv4"
+ "right": 6
}
},
{
- "reject": {
- "expr": "host-unreachable",
- "type": "icmp"
- }
- }
-]
-
-# reject with icmp type net-unreachable
-[
- {
"match": {
"left": {
- "meta": { "key": "nfproto" }
+ "meta": { "key": "mark" }
},
"op": "==",
- "right": "ipv4"
+ "right": 12345
}
},
{
"reject": {
- "expr": "net-unreachable",
- "type": "icmp"
+ "type": "tcp reset"
}
}
]
-# reject with icmp type prot-unreachable
+# reject
[
{
- "match": {
- "left": {
- "meta": { "key": "nfproto" }
- },
- "op": "==",
- "right": "ipv4"
- }
- },
- {
"reject": {
- "expr": "prot-unreachable",
- "type": "icmp"
- }
- }
-]
-
-# reject with icmp type port-unreachable
-[
- {
- "match": {
- "left": {
- "meta": { "key": "nfproto" }
- },
- "op": "==",
- "right": "ipv4"
+ "expr": "port-unreachable",
+ "type": "icmpx"
}
- },
- {
- "reject": null
}
]
-# reject with icmp type net-prohibited
+# meta nfproto ipv4 reject
[
{
- "match": {
- "left": {
- "meta": { "key": "nfproto" }
- },
- "op": "==",
- "right": "ipv4"
- }
- },
- {
"reject": {
- "expr": "net-prohibited",
+ "expr": "port-unreachable",
"type": "icmp"
}
}
]
-# reject with icmp type host-prohibited
+# meta nfproto ipv6 reject
[
{
- "match": {
- "left": {
- "meta": { "key": "nfproto" }
- },
- "op": "==",
- "right": "ipv4"
- }
- },
- {
"reject": {
- "expr": "host-prohibited",
- "type": "icmp"
+ "expr": "port-unreachable",
+ "type": "icmpv6"
}
}
]
-# reject with icmp type admin-prohibited
+# meta nfproto ipv4 reject with icmp type host-unreachable
[
{
- "match": {
- "left": {
- "meta": { "key": "nfproto" }
- },
- "op": "==",
- "right": "ipv4"
- }
- },
- {
"reject": {
- "expr": "admin-prohibited",
+ "expr": "host-unreachable",
"type": "icmp"
}
}
]
-# reject with icmpv6 type no-route
+# meta nfproto ipv6 reject with icmpv6 type no-route
[
{
- "match": {
- "left": {
- "meta": { "key": "nfproto" }
- },
- "op": "==",
- "right": "ipv6"
- }
- },
- {
"reject": {
"expr": "no-route",
"type": "icmpv6"
@@ -147,91 +75,3 @@
}
]
-# reject with icmpv6 type admin-prohibited
-[
- {
- "match": {
- "left": {
- "meta": { "key": "nfproto" }
- },
- "op": "==",
- "right": "ipv6"
- }
- },
- {
- "reject": {
- "expr": "admin-prohibited",
- "type": "icmpv6"
- }
- }
-]
-
-# reject with icmpv6 type addr-unreachable
-[
- {
- "match": {
- "left": {
- "meta": { "key": "nfproto" }
- },
- "op": "==",
- "right": "ipv6"
- }
- },
- {
- "reject": {
- "expr": "addr-unreachable",
- "type": "icmpv6"
- }
- }
-]
-
-# reject with icmpv6 type port-unreachable
-[
- {
- "match": {
- "left": {
- "meta": { "key": "nfproto" }
- },
- "op": "==",
- "right": "ipv6"
- }
- },
- {
- "reject": null
- }
-]
-
-# mark 12345 reject with tcp reset
-[
- {
- "match": {
- "left": {
- "meta": { "key": "l4proto" }
- },
- "op": "==",
- "right": 6
- }
- },
- {
- "match": {
- "left": {
- "meta": { "key": "mark" }
- },
- "op": "==",
- "right": 12345
- }
- },
- {
- "reject": {
- "type": "tcp reset"
- }
- }
-]
-
-# reject with icmpx type port-unreachable
-[
- {
- "reject": null
- }
-]
-
diff --git a/tests/py/inet/reject.t.payload.inet b/tests/py/inet/reject.t.payload.inet
index ee1aae02..3f220282 100644
--- a/tests/py/inet/reject.t.payload.inet
+++ b/tests/py/inet/reject.t.payload.inet
@@ -116,110 +116,6 @@ inet test-inet input
[ cmp eq reg 1 0x0000000a ]
[ reject type 0 code 0 ]
-# reject with icmp type prot-unreachable
-inet test-inet input
- [ meta load nfproto => reg 1 ]
- [ cmp eq reg 1 0x00000002 ]
- [ reject type 0 code 2 ]
-
-# reject with icmp type port-unreachable
-inet test-inet input
- [ meta load nfproto => reg 1 ]
- [ cmp eq reg 1 0x00000002 ]
- [ reject type 0 code 3 ]
-
-# reject with icmp type net-prohibited
-inet test-inet input
- [ meta load nfproto => reg 1 ]
- [ cmp eq reg 1 0x00000002 ]
- [ reject type 0 code 9 ]
-
-# reject with icmp type host-prohibited
-inet test-inet input
- [ meta load nfproto => reg 1 ]
- [ cmp eq reg 1 0x00000002 ]
- [ reject type 0 code 10 ]
-
-# reject with icmp type admin-prohibited
-inet test-inet input
- [ meta load nfproto => reg 1 ]
- [ cmp eq reg 1 0x00000002 ]
- [ reject type 0 code 13 ]
-
-# reject with icmpv6 type no-route
-inet test-inet input
- [ meta load nfproto => reg 1 ]
- [ cmp eq reg 1 0x0000000a ]
- [ reject type 0 code 0 ]
-
-# reject with icmpv6 type admin-prohibited
-inet test-inet input
- [ meta load nfproto => reg 1 ]
- [ cmp eq reg 1 0x0000000a ]
- [ reject type 0 code 1 ]
-
-# reject with icmpv6 type addr-unreachable
-inet test-inet input
- [ meta load nfproto => reg 1 ]
- [ cmp eq reg 1 0x0000000a ]
- [ reject type 0 code 3 ]
-
-# reject with icmpv6 type port-unreachable
-inet test-inet input
- [ meta load nfproto => reg 1 ]
- [ cmp eq reg 1 0x0000000a ]
- [ reject type 0 code 4 ]
-
-# reject with tcp reset
-inet test-inet input
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000006 ]
- [ reject type 1 code 0 ]
-
-# reject
-inet test-inet input
- [ reject type 2 code 1 ]
-
-# meta nfproto ipv4 reject
-inet test-inet input
- [ meta load nfproto => reg 1 ]
- [ cmp eq reg 1 0x00000002 ]
- [ reject type 0 code 3 ]
-
-# meta nfproto ipv6 reject
-inet test-inet input
- [ meta load nfproto => reg 1 ]
- [ cmp eq reg 1 0x0000000a ]
- [ reject type 0 code 4 ]
-
-# reject with icmpx type host-unreachable
-inet test-inet input
- [ reject type 2 code 2 ]
-
-# reject with icmpx type no-route
-inet test-inet input
- [ reject type 2 code 0 ]
-
-# reject with icmpx type admin-prohibited
-inet test-inet input
- [ reject type 2 code 3 ]
-
-# reject with icmpx type port-unreachable
-inet test-inet input
- [ reject type 2 code 1 ]
-
-# meta nfproto ipv4 reject with icmp type host-unreachable
-inet test-inet input
- [ meta load nfproto => reg 1 ]
- [ cmp eq reg 1 0x00000002 ]
- [ reject type 0 code 1 ]
-
-# meta nfproto ipv6 reject with icmpv6 type no-route
-inet test-inet input
- [ meta load nfproto => reg 1 ]
- [ cmp eq reg 1 0x0000000a ]
- [ reject type 0 code 0 ]
-
# meta nfproto ipv4 reject with icmpx type admin-prohibited
inet test-inet input
[ meta load nfproto => reg 1 ]
diff --git a/tests/py/inet/rt.t b/tests/py/inet/rt.t
index 23608ab2..a0e0d003 100644
--- a/tests/py/inet/rt.t
+++ b/tests/py/inet/rt.t
@@ -2,14 +2,13 @@
*inet;test-inet;output
-rt nexthop 192.168.0.1;fail
-rt nexthop fd00::1;fail
-
meta nfproto ipv4 rt nexthop 192.168.0.1;ok;meta nfproto ipv4 rt ip nexthop 192.168.0.1
rt ip6 nexthop fd00::1;ok
# missing context
+rt nexthop 192.168.0.1;fail
rt nexthop fd00::1;fail
+
# wrong context
rt ip nexthop fd00::1;fail
diff --git a/tests/py/inet/sets.t.payload.bridge b/tests/py/inet/sets.t.payload.bridge
index 92f5417c..3dd9d57b 100644
--- a/tests/py/inet/sets.t.payload.bridge
+++ b/tests/py/inet/sets.t.payload.bridge
@@ -29,7 +29,7 @@ bridge
# ip daddr . tcp dport { 10.0.0.0/8 . 10-23, 192.168.1.1-192.168.3.8 . 80-443 } accept
__set%d test-inet 87
__set%d test-inet 0
- element 0000000a 00000a00 : 0 [end] element 0101a8c0 00005000 : 0 [end]
+ element 0000000a 00000a00 - ffffff0a 00001700 : 0 [end] element 0101a8c0 00005000 - 0803a8c0 0000bb01 : 0 [end]
bridge
[ meta load protocol => reg 1 ]
[ cmp eq reg 1 0x00000008 ]
diff --git a/tests/py/inet/sets.t.payload.inet b/tests/py/inet/sets.t.payload.inet
index bd6e1b0f..53c6b182 100644
--- a/tests/py/inet/sets.t.payload.inet
+++ b/tests/py/inet/sets.t.payload.inet
@@ -29,7 +29,7 @@ inet
# ip daddr . tcp dport { 10.0.0.0/8 . 10-23, 192.168.1.1-192.168.3.8 . 80-443 } accept
__set%d test-inet 87
__set%d test-inet 0
- element 0000000a 00000a00 : 0 [end] element 0101a8c0 00005000 : 0 [end]
+ element 0000000a 00000a00 - ffffff0a 00001700 : 0 [end] element 0101a8c0 00005000 - 0803a8c0 0000bb01 : 0 [end]
inet
[ meta load nfproto => reg 1 ]
[ cmp eq reg 1 0x00000002 ]
diff --git a/tests/py/inet/sets.t.payload.netdev b/tests/py/inet/sets.t.payload.netdev
index f3032d8e..9d6f6bbd 100644
--- a/tests/py/inet/sets.t.payload.netdev
+++ b/tests/py/inet/sets.t.payload.netdev
@@ -14,7 +14,7 @@ netdev test-netdev ingress
[ lookup reg 1 set set2 0x1 ]
[ immediate reg 0 accept ]
-# ip saddr . ip daddr . tcp dport @ set3 accept
+# ip saddr . ip daddr . tcp dport @set3 accept
inet
[ meta load nfproto => reg 1 ]
[ cmp eq reg 1 0x00000002 ]
@@ -29,7 +29,7 @@ inet
# ip daddr . tcp dport { 10.0.0.0/8 . 10-23, 192.168.1.1-192.168.3.8 . 80-443 } accept
__set%d test-netdev 87
__set%d test-netdev 0
- element 0000000a 00000a00 : 0 [end] element 0101a8c0 00005000 : 0 [end]
+ element 0000000a 00000a00 - ffffff0a 00001700 : 0 [end] element 0101a8c0 00005000 - 0803a8c0 0000bb01 : 0 [end]
netdev
[ meta load protocol => reg 1 ]
[ cmp eq reg 1 0x00000008 ]
diff --git a/tests/py/inet/synproxy.t.json b/tests/py/inet/synproxy.t.json
index 92c69d75..1dd85a61 100644
--- a/tests/py/inet/synproxy.t.json
+++ b/tests/py/inet/synproxy.t.json
@@ -5,24 +5,6 @@
}
]
-# synproxy mss 1460
-[
- {
- "synproxy": {
- "mss": 1460
- }
- }
-]
-
-# synproxy wscale 7
-[
- {
- "synproxy": {
- "wscale": 7
- }
- }
-]
-
# synproxy mss 1460 wscale 7
[
{
@@ -56,20 +38,6 @@
}
]
-# synproxy mss 1460 wscale 7 timestamp sack-perm
-[
- {
- "synproxy": {
- "mss": 1460,
- "wscale": 7,
- "flags": [
- "timestamp",
- "sack-perm"
- ]
- }
- }
-]
-
# synproxy mss 1460 wscale 5 timestamp sack-perm
[
{
diff --git a/tests/py/ip/ct.t b/tests/py/ip/ct.t
index d3247f79..a387863e 100644
--- a/tests/py/ip/ct.t
+++ b/tests/py/ip/ct.t
@@ -21,3 +21,10 @@ ct original protocol 17 ct reply proto-src 53;ok;ct protocol 17 ct reply proto-s
# wrong address family
ct reply ip daddr dead::beef;fail
+
+meta mark set ct original daddr map { 1.1.1.1 : 0x00000011 };fail
+meta mark set ct original ip daddr map { 1.1.1.1 : 0x00000011 };ok
+meta mark set ct original saddr . meta mark map { 1.1.1.1 . 0x00000014 : 0x0000001e };fail
+meta mark set ct original ip saddr . meta mark map { 1.1.1.1 . 0x00000014 : 0x0000001e };ok
+ct original saddr . meta mark { 1.1.1.1 . 0x00000014 };fail
+ct original ip saddr . meta mark { 1.1.1.1 . 0x00000014 };ok
diff --git a/tests/py/ip/ct.t.json b/tests/py/ip/ct.t.json
index 881cd4c9..3288413f 100644
--- a/tests/py/ip/ct.t.json
+++ b/tests/py/ip/ct.t.json
@@ -216,3 +216,112 @@
}
]
+# meta mark set ct original ip daddr map { 1.1.1.1 : 0x00000011 }
+[
+ {
+ "mangle": {
+ "key": {
+ "meta": {
+ "key": "mark"
+ }
+ },
+ "value": {
+ "map": {
+ "data": {
+ "set": [
+ [
+ "1.1.1.1",
+ 17
+ ]
+ ]
+ },
+ "key": {
+ "ct": {
+ "dir": "original",
+ "key": "ip daddr"
+ }
+ }
+ }
+ }
+ }
+ }
+]
+
+# meta mark set ct original ip saddr . meta mark map { 1.1.1.1 . 0x00000014 : 0x0000001e }
+[
+ {
+ "mangle": {
+ "key": {
+ "meta": {
+ "key": "mark"
+ }
+ },
+ "value": {
+ "map": {
+ "data": {
+ "set": [
+ [
+ {
+ "concat": [
+ "1.1.1.1",
+ 20
+ ]
+ },
+ 30
+ ]
+ ]
+ },
+ "key": {
+ "concat": [
+ {
+ "ct": {
+ "dir": "original",
+ "key": "ip saddr"
+ }
+ },
+ {
+ "meta": {
+ "key": "mark"
+ }
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+]
+
+# ct original ip saddr . meta mark { 1.1.1.1 . 0x00000014 }
+[
+ {
+ "match": {
+ "left": {
+ "concat": [
+ {
+ "ct": {
+ "dir": "original",
+ "key": "ip saddr"
+ }
+ },
+ {
+ "meta": {
+ "key": "mark"
+ }
+ }
+ ]
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ {
+ "concat": [
+ "1.1.1.1",
+ 20
+ ]
+ }
+ ]
+ }
+ }
+ }
+]
diff --git a/tests/py/ip/ct.t.payload b/tests/py/ip/ct.t.payload
index a7e08f98..49f06a84 100644
--- a/tests/py/ip/ct.t.payload
+++ b/tests/py/ip/ct.t.payload
@@ -56,3 +56,31 @@ ip test-ip4 output
[ cmp eq reg 1 0x00000011 ]
[ ct load proto_src => reg 1 , dir reply ]
[ cmp eq reg 1 0x00003500 ]
+
+# meta mark set ct original ip daddr map { 1.1.1.1 : 0x00000011 }
+__map%d test-ip4 b
+__map%d test-ip4 0
+ element 01010101 : 00000011 0 [end]
+ip
+ [ ct load dst_ip => reg 1 , dir original ]
+ [ lookup reg 1 set __map%d dreg 1 ]
+ [ meta set mark with reg 1 ]
+
+# meta mark set ct original ip saddr . meta mark map { 1.1.1.1 . 0x00000014 : 0x0000001e }
+__map%d test-ip4 b
+__map%d test-ip4 0
+ element 01010101 00000014 : 0000001e 0 [end]
+ip
+ [ ct load src_ip => reg 1 , dir original ]
+ [ meta load mark => reg 9 ]
+ [ lookup reg 1 set __map%d dreg 1 ]
+ [ meta set mark with reg 1 ]
+
+# ct original ip saddr . meta mark { 1.1.1.1 . 0x00000014 }
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 01010101 00000014 : 0 [end]
+ip
+ [ ct load src_ip => reg 1 , dir original ]
+ [ meta load mark => reg 9 ]
+ [ lookup reg 1 set __set%d ]
diff --git a/tests/py/ip/icmp.t b/tests/py/ip/icmp.t
index cb3b3e35..11f3662e 100644
--- a/tests/py/ip/icmp.t
+++ b/tests/py/ip/icmp.t
@@ -40,24 +40,27 @@ icmp checksum != { 11-343} accept;ok
icmp checksum { 1111, 222, 343} accept;ok
icmp checksum != { 1111, 222, 343} accept;ok
-icmp id 1245 log;ok
-icmp id 22;ok
-icmp id != 233;ok
-icmp id 33-45;ok
-icmp id != 33-45;ok
-icmp id { 33-55};ok
-icmp id != { 33-55};ok
-icmp id { 22, 34, 333};ok
-icmp id != { 22, 34, 333};ok
+icmp id 1245 log;ok;icmp type { echo-reply, echo-request} icmp id 1245 log
+icmp id 22;ok;icmp type { echo-reply, echo-request} icmp id 22
+icmp id != 233;ok;icmp type { echo-reply, echo-request} icmp id != 233
+icmp id 33-45;ok;icmp type { echo-reply, echo-request} icmp id 33-45
+icmp id != 33-45;ok;icmp type { echo-reply, echo-request} icmp id != 33-45
+icmp id { 33-55};ok;icmp type { echo-reply, echo-request} icmp id { 33-55}
+icmp id != { 33-55};ok;icmp type { echo-reply, echo-request} icmp id != { 33-55}
-icmp sequence 22;ok
-icmp sequence != 233;ok
-icmp sequence 33-45;ok
-icmp sequence != 33-45;ok
-icmp sequence { 33, 55, 67, 88};ok
-icmp sequence != { 33, 55, 67, 88};ok
-icmp sequence { 33-55};ok
-icmp sequence != { 33-55};ok
+icmp id { 22, 34, 333};ok;icmp type { echo-request, echo-reply} icmp id { 22, 34, 333}
+icmp id != { 22, 34, 333};ok;icmp type { echo-request, echo-reply} icmp id != { 22, 34, 333}
+
+icmp sequence 22;ok;icmp type { echo-reply, echo-request} icmp sequence 22
+icmp sequence != 233;ok;icmp type { echo-reply, echo-request} icmp sequence != 233
+icmp sequence 33-45;ok;icmp type { echo-reply, echo-request} icmp sequence 33-45
+icmp sequence != 33-45;ok;icmp type { echo-reply, echo-request} icmp sequence != 33-45
+icmp sequence { 33, 55, 67, 88};ok;icmp type { echo-request, echo-reply} icmp sequence { 33, 55, 67, 88}
+icmp sequence != { 33, 55, 67, 88};ok;icmp type { echo-request, echo-reply} icmp sequence != { 33, 55, 67, 88}
+icmp sequence { 33-55};ok;icmp type { echo-request, echo-reply} icmp sequence { 33-55}
+icmp sequence != { 33-55};ok;icmp type { echo-request, echo-reply} icmp sequence != { 33-55}
+icmp id 1 icmp sequence 2;ok;icmp type { echo-reply, echo-request} icmp id 1 icmp sequence 2
+icmp type { echo-reply, echo-request} icmp id 1 icmp sequence 2;ok
icmp mtu 33;ok
icmp mtu 22-33;ok
@@ -82,3 +85,6 @@ icmp gateway { 33-55};ok
icmp gateway != { 33-55};ok
icmp gateway != 34;ok
icmp gateway != { 333, 334};ok
+
+icmp code 1 icmp type 2;ok;icmp type 2 icmp code host-unreachable
+icmp code != 1 icmp type 2 icmp mtu 5;fail
diff --git a/tests/py/ip/icmp.t.json b/tests/py/ip/icmp.t.json
index 965eb10b..12b53b0f 100644
--- a/tests/py/ip/icmp.t.json
+++ b/tests/py/ip/icmp.t.json
@@ -8,7 +8,7 @@
"protocol": "icmp"
}
},
- "op": "==",
+ "op": "==",
"right": "echo-reply"
}
},
@@ -27,7 +27,7 @@
"protocol": "icmp"
}
},
- "op": "==",
+ "op": "==",
"right": "destination-unreachable"
}
},
@@ -46,7 +46,7 @@
"protocol": "icmp"
}
},
- "op": "==",
+ "op": "==",
"right": "source-quench"
}
},
@@ -65,7 +65,7 @@
"protocol": "icmp"
}
},
- "op": "==",
+ "op": "==",
"right": "redirect"
}
},
@@ -84,7 +84,7 @@
"protocol": "icmp"
}
},
- "op": "==",
+ "op": "==",
"right": "echo-request"
}
},
@@ -103,7 +103,7 @@
"protocol": "icmp"
}
},
- "op": "==",
+ "op": "==",
"right": "time-exceeded"
}
},
@@ -122,7 +122,7 @@
"protocol": "icmp"
}
},
- "op": "==",
+ "op": "==",
"right": "parameter-problem"
}
},
@@ -141,7 +141,7 @@
"protocol": "icmp"
}
},
- "op": "==",
+ "op": "==",
"right": "timestamp-request"
}
},
@@ -160,7 +160,7 @@
"protocol": "icmp"
}
},
- "op": "==",
+ "op": "==",
"right": "timestamp-reply"
}
},
@@ -179,7 +179,7 @@
"protocol": "icmp"
}
},
- "op": "==",
+ "op": "==",
"right": "info-request"
}
},
@@ -198,7 +198,7 @@
"protocol": "icmp"
}
},
- "op": "==",
+ "op": "==",
"right": "info-reply"
}
},
@@ -217,7 +217,7 @@
"protocol": "icmp"
}
},
- "op": "==",
+ "op": "==",
"right": "address-mask-request"
}
},
@@ -236,7 +236,7 @@
"protocol": "icmp"
}
},
- "op": "==",
+ "op": "==",
"right": "address-mask-reply"
}
},
@@ -255,7 +255,7 @@
"protocol": "icmp"
}
},
- "op": "==",
+ "op": "==",
"right": "router-advertisement"
}
},
@@ -274,7 +274,7 @@
"protocol": "icmp"
}
},
- "op": "==",
+ "op": "==",
"right": "router-solicitation"
}
},
@@ -293,7 +293,7 @@
"protocol": "icmp"
}
},
- "op": "==",
+ "op": "==",
"right": {
"set": [
"echo-reply",
@@ -301,6 +301,8 @@
"source-quench",
"redirect",
"echo-request",
+ "router-advertisement",
+ "router-solicitation",
"time-exceeded",
"parameter-problem",
"timestamp-request",
@@ -308,9 +310,7 @@
"info-request",
"info-reply",
"address-mask-request",
- "address-mask-reply",
- "router-advertisement",
- "router-solicitation"
+ "address-mask-reply"
]
}
}
@@ -352,7 +352,7 @@
"protocol": "icmp"
}
},
- "op": "==",
+ "op": "==",
"right": 111
}
},
@@ -390,9 +390,12 @@
"protocol": "icmp"
}
},
- "op": "==",
+ "op": "==",
"right": {
- "range": [ 33, 55 ]
+ "range": [
+ 33,
+ 55
+ ]
}
}
}
@@ -410,7 +413,10 @@
},
"op": "!=",
"right": {
- "range": [ 33, 55 ]
+ "range": [
+ 33,
+ 55
+ ]
}
}
}
@@ -426,10 +432,15 @@
"protocol": "icmp"
}
},
- "op": "==",
+ "op": "==",
"right": {
"set": [
- { "range": [ 33, 55 ] }
+ {
+ "range": [
+ 33,
+ 55
+ ]
+ }
]
}
}
@@ -449,7 +460,12 @@
"op": "!=",
"right": {
"set": [
- { "range": [ 33, 55 ] }
+ {
+ "range": [
+ 33,
+ 55
+ ]
+ }
]
}
}
@@ -466,7 +482,7 @@
"protocol": "icmp"
}
},
- "op": "==",
+ "op": "==",
"right": {
"set": [
2,
@@ -514,7 +530,7 @@
"protocol": "icmp"
}
},
- "op": "==",
+ "op": "==",
"right": 12343
}
},
@@ -552,9 +568,12 @@
"protocol": "icmp"
}
},
- "op": "==",
+ "op": "==",
"right": {
- "range": [ 11, 343 ]
+ "range": [
+ 11,
+ 343
+ ]
}
}
},
@@ -575,7 +594,10 @@
},
"op": "!=",
"right": {
- "range": [ 11, 343 ]
+ "range": [
+ 11,
+ 343
+ ]
}
}
},
@@ -594,10 +616,15 @@
"protocol": "icmp"
}
},
- "op": "==",
+ "op": "==",
"right": {
"set": [
- { "range": [ 11, 343 ] }
+ {
+ "range": [
+ 11,
+ 343
+ ]
+ }
]
}
}
@@ -620,7 +647,12 @@
"op": "!=",
"right": {
"set": [
- { "range": [ 11, 343 ] }
+ {
+ "range": [
+ 11,
+ 343
+ ]
+ }
]
}
}
@@ -640,12 +672,12 @@
"protocol": "icmp"
}
},
- "op": "==",
+ "op": "==",
"right": {
"set": [
- 1111,
222,
- 343
+ 343,
+ 1111
]
}
}
@@ -668,9 +700,9 @@
"op": "!=",
"right": {
"set": [
- 1111,
222,
- 343
+ 343,
+ 1111
]
}
}
@@ -690,7 +722,7 @@
"protocol": "icmp"
}
},
- "op": "==",
+ "op": "==",
"right": 1245
}
},
@@ -709,7 +741,7 @@
"protocol": "icmp"
}
},
- "op": "==",
+ "op": "==",
"right": 22
}
}
@@ -737,13 +769,33 @@
"match": {
"left": {
"payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-reply",
+ "echo-request"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
"field": "id",
"protocol": "icmp"
}
},
- "op": "==",
+ "op": "==",
"right": {
- "range": [ 33, 45 ]
+ "range": [
+ 33,
+ 45
+ ]
}
}
}
@@ -755,13 +807,33 @@
"match": {
"left": {
"payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-reply",
+ "echo-request"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
"field": "id",
"protocol": "icmp"
}
},
"op": "!=",
"right": {
- "range": [ 33, 45 ]
+ "range": [
+ 33,
+ 45
+ ]
}
}
}
@@ -777,10 +849,15 @@
"protocol": "icmp"
}
},
- "op": "==",
+ "op": "==",
"right": {
"set": [
- { "range": [ 33, 55 ] }
+ {
+ "range": [
+ 33,
+ 55
+ ]
+ }
]
}
}
@@ -793,6 +870,23 @@
"match": {
"left": {
"payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-reply",
+ "echo-request"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
"field": "id",
"protocol": "icmp"
}
@@ -800,7 +894,12 @@
"op": "!=",
"right": {
"set": [
- { "range": [ 33, 55 ] }
+ {
+ "range": [
+ 33,
+ 55
+ ]
+ }
]
}
}
@@ -813,11 +912,28 @@
"match": {
"left": {
"payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-reply",
+ "echo-request"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
"field": "id",
"protocol": "icmp"
}
},
- "op": "==",
+ "op": "==",
"right": {
"set": [
22,
@@ -835,6 +951,23 @@
"match": {
"left": {
"payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-reply",
+ "echo-request"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
"field": "id",
"protocol": "icmp"
}
@@ -857,11 +990,28 @@
"match": {
"left": {
"payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-reply",
+ "echo-request"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
"field": "sequence",
"protocol": "icmp"
}
},
- "op": "==",
+ "op": "==",
"right": 22
}
}
@@ -873,6 +1023,23 @@
"match": {
"left": {
"payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-reply",
+ "echo-request"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
"field": "sequence",
"protocol": "icmp"
}
@@ -889,13 +1056,33 @@
"match": {
"left": {
"payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-reply",
+ "echo-request"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
"field": "sequence",
"protocol": "icmp"
}
},
- "op": "==",
+ "op": "==",
"right": {
- "range": [ 33, 45 ]
+ "range": [
+ 33,
+ 45
+ ]
}
}
}
@@ -907,13 +1094,33 @@
"match": {
"left": {
"payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-reply",
+ "echo-request"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
"field": "sequence",
"protocol": "icmp"
}
},
"op": "!=",
"right": {
- "range": [ 33, 45 ]
+ "range": [
+ 33,
+ 45
+ ]
}
}
}
@@ -925,11 +1132,28 @@
"match": {
"left": {
"payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-reply",
+ "echo-request"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
"field": "sequence",
"protocol": "icmp"
}
},
- "op": "==",
+ "op": "==",
"right": {
"set": [
33,
@@ -948,6 +1172,23 @@
"match": {
"left": {
"payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-reply",
+ "echo-request"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
"field": "sequence",
"protocol": "icmp"
}
@@ -971,14 +1212,36 @@
"match": {
"left": {
"payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-reply",
+ "echo-request"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
"field": "sequence",
"protocol": "icmp"
}
},
- "op": "==",
+ "op": "==",
"right": {
"set": [
- { "range": [ 33, 55 ] }
+ {
+ "range": [
+ 33,
+ 55
+ ]
+ }
]
}
}
@@ -991,6 +1254,23 @@
"match": {
"left": {
"payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-reply",
+ "echo-request"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
"field": "sequence",
"protocol": "icmp"
}
@@ -998,13 +1278,108 @@
"op": "!=",
"right": {
"set": [
- { "range": [ 33, 55 ] }
+ {
+ "range": [
+ 33,
+ 55
+ ]
+ }
]
}
}
}
]
+# icmp id 1 icmp sequence 2
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-reply",
+ "echo-request"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": 2
+ }
+ }
+]
+
+# icmp type { echo-reply, echo-request} icmp id 1 icmp sequence 2
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-reply",
+ "echo-request"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": 1
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": 2
+ }
+ }
+]
+
# icmp mtu 33
[
{
@@ -1015,7 +1390,7 @@
"protocol": "icmp"
}
},
- "op": "==",
+ "op": "==",
"right": 33
}
}
@@ -1031,9 +1406,12 @@
"protocol": "icmp"
}
},
- "op": "==",
+ "op": "==",
"right": {
- "range": [ 22, 33 ]
+ "range": [
+ 22,
+ 33
+ ]
}
}
}
@@ -1049,10 +1427,15 @@
"protocol": "icmp"
}
},
- "op": "==",
+ "op": "==",
"right": {
"set": [
- { "range": [ 22, 33 ] }
+ {
+ "range": [
+ 22,
+ 33
+ ]
+ }
]
}
}
@@ -1072,7 +1455,12 @@
"op": "!=",
"right": {
"set": [
- { "range": [ 22, 33 ] }
+ {
+ "range": [
+ 22,
+ 33
+ ]
+ }
]
}
}
@@ -1089,7 +1477,7 @@
"protocol": "icmp"
}
},
- "op": "==",
+ "op": "==",
"right": 22
}
}
@@ -1121,9 +1509,12 @@
"protocol": "icmp"
}
},
- "op": "==",
+ "op": "==",
"right": {
- "range": [ 33, 45 ]
+ "range": [
+ 33,
+ 45
+ ]
}
}
}
@@ -1141,7 +1532,10 @@
},
"op": "!=",
"right": {
- "range": [ 33, 45 ]
+ "range": [
+ 33,
+ 45
+ ]
}
}
}
@@ -1157,7 +1551,7 @@
"protocol": "icmp"
}
},
- "op": "==",
+ "op": "==",
"right": {
"set": [
33,
@@ -1203,10 +1597,15 @@
"protocol": "icmp"
}
},
- "op": "==",
+ "op": "==",
"right": {
"set": [
- { "range": [ 33, 55 ] }
+ {
+ "range": [
+ 33,
+ 55
+ ]
+ }
]
}
}
@@ -1226,7 +1625,12 @@
"op": "!=",
"right": {
"set": [
- { "range": [ 33, 55 ] }
+ {
+ "range": [
+ 33,
+ 55
+ ]
+ }
]
}
}
@@ -1243,7 +1647,7 @@
"protocol": "icmp"
}
},
- "op": "==",
+ "op": "==",
"right": 22
}
}
@@ -1275,9 +1679,12 @@
"protocol": "icmp"
}
},
- "op": "==",
+ "op": "==",
"right": {
- "range": [ 33, 45 ]
+ "range": [
+ 33,
+ 45
+ ]
}
}
}
@@ -1295,7 +1702,10 @@
},
"op": "!=",
"right": {
- "range": [ 33, 45 ]
+ "range": [
+ 33,
+ 45
+ ]
}
}
}
@@ -1311,7 +1721,7 @@
"protocol": "icmp"
}
},
- "op": "==",
+ "op": "==",
"right": {
"set": [
33,
@@ -1357,10 +1767,15 @@
"protocol": "icmp"
}
},
- "op": "==",
+ "op": "==",
"right": {
"set": [
- { "range": [ 33, 55 ] }
+ {
+ "range": [
+ 33,
+ 55
+ ]
+ }
]
}
}
@@ -1380,7 +1795,12 @@
"op": "!=",
"right": {
"set": [
- { "range": [ 33, 55 ] }
+ {
+ "range": [
+ 33,
+ 55
+ ]
+ }
]
}
}
@@ -1424,3 +1844,30 @@
}
]
+# icmp code 1 icmp type 2
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": 2
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "code",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": "host-unreachable"
+ }
+ }
+]
diff --git a/tests/py/ip/icmp.t.json.output b/tests/py/ip/icmp.t.json.output
index 2391983a..5a075858 100644
--- a/tests/py/ip/icmp.t.json.output
+++ b/tests/py/ip/icmp.t.json.output
@@ -1,4 +1,28 @@
-# icmp type {echo-reply, destination-unreachable, source-quench, redirect, echo-request, time-exceeded, parameter-problem, timestamp-request, timestamp-reply, info-request, info-reply, address-mask-request, address-mask-reply, router-advertisement, router-solicitation} accept
+# icmp code { 2, 4, 54, 33, 56}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "code",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "prot-unreachable",
+ "frag-needed",
+ 33,
+ 54,
+ 56
+ ]
+ }
+ }
+ }
+]
+
+# icmp id 1245 log
[
{
"match": {
@@ -8,104 +32,138 @@
"protocol": "icmp"
}
},
- "op": "==",
+ "op": "==",
"right": {
"set": [
"echo-reply",
- "destination-unreachable",
- "source-quench",
- "redirect",
- "echo-request",
- "router-advertisement",
- "router-solicitation",
- "time-exceeded",
- "parameter-problem",
- "timestamp-request",
- "timestamp-reply",
- "info-request",
- "info-reply",
- "address-mask-request",
- "address-mask-reply"
+ "echo-request"
]
}
}
},
{
- "accept": null
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": 1245
+ }
+ },
+ {
+ "log": null
}
]
-# icmp code { 2, 4, 54, 33, 56}
+# icmp id 22
[
{
"match": {
"left": {
"payload": {
- "field": "code",
+ "field": "type",
"protocol": "icmp"
}
},
"op": "==",
"right": {
"set": [
- "prot-unreachable",
- "frag-needed",
- 33,
- 54,
- 56
+ "echo-reply",
+ "echo-request"
]
}
}
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": 22
+ }
}
]
-# icmp checksum { 1111, 222, 343} accept
+# icmp id != 233
[
{
"match": {
"left": {
"payload": {
- "field": "checksum",
+ "field": "type",
"protocol": "icmp"
}
},
- "op": "==",
+ "op": "==",
"right": {
"set": [
- 222,
- 343,
- 1111
+ "echo-reply",
+ "echo-request"
]
}
}
},
{
- "accept": null
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "icmp"
+ }
+ },
+ "op": "!=",
+ "right": 233
+ }
}
]
-# icmp checksum != { 1111, 222, 343} accept
+# icmp id { 33-55}
[
{
"match": {
"left": {
"payload": {
- "field": "checksum",
+ "field": "type",
"protocol": "icmp"
}
},
- "op": "!=",
+ "op": "==",
"right": {
"set": [
- 222,
- 343,
- 1111
+ "echo-reply",
+ "echo-request"
]
}
}
},
{
- "accept": null
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "icmp"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ {
+ "range": [
+ 33,
+ 55
+ ]
+ }
+ ]
+ }
+ }
}
]
+
diff --git a/tests/py/ip/icmp.t.payload.ip b/tests/py/ip/icmp.t.payload.ip
index 2185feb8..dccff4c0 100644
--- a/tests/py/ip/icmp.t.payload.ip
+++ b/tests/py/ip/icmp.t.payload.ip
@@ -102,17 +102,6 @@ ip test-ip4 input
[ cmp eq reg 1 0x00000012 ]
[ immediate reg 0 accept ]
-# icmp type {echo-reply, destination-unreachable, source-quench, redirect, echo-request, time-exceeded, parameter-problem, timestamp-request, timestamp-reply, info-request, info-reply, address-mask-request, address-mask-reply} accept
-__set%d test-ip4 3
-__set%d test-ip4 0
- element 00000000 : 0 [end] element 00000003 : 0 [end] element 00000004 : 0 [end] element 00000005 : 0 [end] element 00000008 : 0 [end] element 0000000b : 0 [end] element 0000000c : 0 [end] element 0000000d : 0 [end] element 0000000e : 0 [end] element 0000000f : 0 [end] element 00000010 : 0 [end] element 00000011 : 0 [end] element 00000012 : 0 [end]
-ip test-ip4 input
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000001 ]
- [ payload load 1b @ transport header + 0 => reg 1 ]
- [ lookup reg 1 set __set%d ]
- [ immediate reg 0 accept ]
-
# icmp type != {echo-reply, destination-unreachable, source-quench}
__set%d test-ip4 3
__set%d test-ip4 0
@@ -272,155 +261,266 @@ ip test-ip4 input
[ immediate reg 0 accept ]
# icmp id 1245 log
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000008 : 0 [end] element 00000000 : 0 [end]
ip test-ip4 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
[ payload load 2b @ transport header + 4 => reg 1 ]
[ cmp eq reg 1 0x0000dd04 ]
[ log ]
# icmp id 22
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000008 : 0 [end] element 00000000 : 0 [end]
ip test-ip4 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
[ payload load 2b @ transport header + 4 => reg 1 ]
[ cmp eq reg 1 0x00001600 ]
# icmp id != 233
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000008 : 0 [end] element 00000000 : 0 [end]
ip test-ip4 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
[ payload load 2b @ transport header + 4 => reg 1 ]
[ cmp neq reg 1 0x0000e900 ]
# icmp id 33-45
+__set%d test-ip4 3
+__set%d test-ip4 input
+ element 00000008 : 0 [end] element 00000000 : 0 [end]
ip test-ip4 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
[ payload load 2b @ transport header + 4 => reg 1 ]
[ cmp gte reg 1 0x00002100 ]
[ cmp lte reg 1 0x00002d00 ]
# icmp id != 33-45
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000008 : 0 [end] element 00000000 : 0 [end]
ip test-ip4 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
[ payload load 2b @ transport header + 4 => reg 1 ]
[ range neq reg 1 0x00002100 0x00002d00 ]
# icmp id { 33-55}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000008 : 0 [end] element 00000000 : 0 [end]
__set%d test-ip4 7
__set%d test-ip4 0
element 00000000 : 1 [end] element 00002100 : 0 [end] element 00003800 : 1 [end]
ip test-ip4 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
[ payload load 2b @ transport header + 4 => reg 1 ]
[ lookup reg 1 set __set%d ]
# icmp id != { 33-55}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000008 : 0 [end] element 00000000 : 0 [end]
__set%d test-ip4 7
__set%d test-ip4 0
element 00000000 : 1 [end] element 00002100 : 0 [end] element 00003800 : 1 [end]
ip test-ip4 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
[ payload load 2b @ transport header + 4 => reg 1 ]
[ lookup reg 1 set __set%d 0x1 ]
# icmp id { 22, 34, 333}
__set%d test-ip4 3
__set%d test-ip4 0
+ element 00000008 : 0 [end] element 00000000 : 0 [end]
+__set%d test-ip4 3
+__set%d test-ip4 0
element 00001600 : 0 [end] element 00002200 : 0 [end] element 00004d01 : 0 [end]
ip test-ip4 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
[ payload load 2b @ transport header + 4 => reg 1 ]
[ lookup reg 1 set __set%d ]
# icmp id != { 22, 34, 333}
__set%d test-ip4 3
__set%d test-ip4 0
+ element 00000008 : 0 [end] element 00000000 : 0 [end]
+__set%d test-ip4 3
+__set%d test-ip4 0
element 00001600 : 0 [end] element 00002200 : 0 [end] element 00004d01 : 0 [end]
ip test-ip4 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
[ payload load 2b @ transport header + 4 => reg 1 ]
[ lookup reg 1 set __set%d 0x1 ]
# icmp sequence 22
-ip test-ip4 input
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000008 : 0 [end] element 00000000 : 0 [end]
+ip
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
[ payload load 2b @ transport header + 6 => reg 1 ]
[ cmp eq reg 1 0x00001600 ]
# icmp sequence != 233
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000008 : 0 [end] element 00000000 : 0 [end]
ip test-ip4 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
[ payload load 2b @ transport header + 6 => reg 1 ]
[ cmp neq reg 1 0x0000e900 ]
# icmp sequence 33-45
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000008 : 0 [end] element 00000000 : 0 [end]
ip test-ip4 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
[ payload load 2b @ transport header + 6 => reg 1 ]
[ cmp gte reg 1 0x00002100 ]
[ cmp lte reg 1 0x00002d00 ]
# icmp sequence != 33-45
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000008 : 0 [end] element 00000000 : 0 [end]
ip test-ip4 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
[ payload load 2b @ transport header + 6 => reg 1 ]
[ range neq reg 1 0x00002100 0x00002d00 ]
# icmp sequence { 33, 55, 67, 88}
__set%d test-ip4 3
__set%d test-ip4 0
+ element 00000008 : 0 [end] element 00000000 : 0 [end]
+__set%d test-ip4 3
+__set%d test-ip4 0
element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
ip test-ip4 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
[ payload load 2b @ transport header + 6 => reg 1 ]
[ lookup reg 1 set __set%d ]
# icmp sequence != { 33, 55, 67, 88}
__set%d test-ip4 3
__set%d test-ip4 0
+ element 00000008 : 0 [end] element 00000000 : 0 [end]
+__set%d test-ip4 3
+__set%d test-ip4 0
element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
ip test-ip4 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
[ payload load 2b @ transport header + 6 => reg 1 ]
[ lookup reg 1 set __set%d 0x1 ]
# icmp sequence { 33-55}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000008 : 0 [end] element 00000000 : 0 [end]
__set%d test-ip4 7
__set%d test-ip4 0
element 00000000 : 1 [end] element 00002100 : 0 [end] element 00003800 : 1 [end]
ip test-ip4 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
[ payload load 2b @ transport header + 6 => reg 1 ]
[ lookup reg 1 set __set%d ]
# icmp sequence != { 33-55}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000008 : 0 [end] element 00000000 : 0 [end]
__set%d test-ip4 7
__set%d test-ip4 0
element 00000000 : 1 [end] element 00002100 : 0 [end] element 00003800 : 1 [end]
ip test-ip4 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
[ payload load 2b @ transport header + 6 => reg 1 ]
[ lookup reg 1 set __set%d 0x1 ]
+# icmp id 1 icmp sequence 2
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000008 : 0 [end] element 00000000 : 0 [end]
+ip
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ payload load 4b @ transport header + 4 => reg 1 ]
+ [ cmp eq reg 1 0x02000100 ]
+
+# icmp type { echo-reply, echo-request} icmp id 1 icmp sequence 2
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element 00000000 : 0 [end] element 00000008 : 0 [end]
+ip
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+ [ payload load 4b @ transport header + 4 => reg 1 ]
+ [ cmp eq reg 1 0x02000100 ]
+
# icmp mtu 33
ip test-ip4 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000003 ]
[ payload load 2b @ transport header + 6 => reg 1 ]
[ cmp eq reg 1 0x00002100 ]
@@ -428,6 +528,8 @@ ip test-ip4 input
ip test-ip4 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000003 ]
[ payload load 2b @ transport header + 6 => reg 1 ]
[ cmp gte reg 1 0x00001600 ]
[ cmp lte reg 1 0x00002100 ]
@@ -439,6 +541,8 @@ __set%d test-ip4 0
ip test-ip4 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000003 ]
[ payload load 2b @ transport header + 6 => reg 1 ]
[ lookup reg 1 set __set%d ]
@@ -449,6 +553,8 @@ __set%d test-ip4 0
ip test-ip4 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000003 ]
[ payload load 2b @ transport header + 6 => reg 1 ]
[ lookup reg 1 set __set%d 0x1 ]
@@ -456,6 +562,8 @@ ip test-ip4 input
ip test-ip4 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000003 ]
[ payload load 2b @ transport header + 6 => reg 1 ]
[ cmp eq reg 1 0x00001600 ]
@@ -463,6 +571,8 @@ ip test-ip4 input
ip test-ip4 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000003 ]
[ payload load 2b @ transport header + 6 => reg 1 ]
[ cmp neq reg 1 0x0000e900 ]
@@ -470,6 +580,8 @@ ip test-ip4 input
ip test-ip4 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000003 ]
[ payload load 2b @ transport header + 6 => reg 1 ]
[ cmp gte reg 1 0x00002100 ]
[ cmp lte reg 1 0x00002d00 ]
@@ -478,6 +590,8 @@ ip test-ip4 input
ip test-ip4 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000003 ]
[ payload load 2b @ transport header + 6 => reg 1 ]
[ range neq reg 1 0x00002100 0x00002d00 ]
@@ -488,6 +602,8 @@ __set%d test-ip4 0
ip test-ip4 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000003 ]
[ payload load 2b @ transport header + 6 => reg 1 ]
[ lookup reg 1 set __set%d ]
@@ -498,6 +614,8 @@ __set%d test-ip4 0
ip test-ip4 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000003 ]
[ payload load 2b @ transport header + 6 => reg 1 ]
[ lookup reg 1 set __set%d 0x1 ]
@@ -508,6 +626,8 @@ __set%d test-ip4 0
ip test-ip4 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000003 ]
[ payload load 2b @ transport header + 6 => reg 1 ]
[ lookup reg 1 set __set%d ]
@@ -518,6 +638,8 @@ __set%d test-ip4 0
ip test-ip4 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000003 ]
[ payload load 2b @ transport header + 6 => reg 1 ]
[ lookup reg 1 set __set%d 0x1 ]
@@ -525,6 +647,8 @@ ip test-ip4 input
ip test-ip4 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000005 ]
[ payload load 4b @ transport header + 4 => reg 1 ]
[ cmp eq reg 1 0x16000000 ]
@@ -532,6 +656,8 @@ ip test-ip4 input
ip test-ip4 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000005 ]
[ payload load 4b @ transport header + 4 => reg 1 ]
[ cmp neq reg 1 0xe9000000 ]
@@ -539,6 +665,8 @@ ip test-ip4 input
ip test-ip4 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000005 ]
[ payload load 4b @ transport header + 4 => reg 1 ]
[ cmp gte reg 1 0x21000000 ]
[ cmp lte reg 1 0x2d000000 ]
@@ -547,6 +675,8 @@ ip test-ip4 input
ip test-ip4 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000005 ]
[ payload load 4b @ transport header + 4 => reg 1 ]
[ range neq reg 1 0x21000000 0x2d000000 ]
@@ -557,6 +687,8 @@ __set%d test-ip4 0
ip test-ip4 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000005 ]
[ payload load 4b @ transport header + 4 => reg 1 ]
[ lookup reg 1 set __set%d ]
@@ -567,6 +699,8 @@ __set%d test-ip4 0
ip test-ip4 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000005 ]
[ payload load 4b @ transport header + 4 => reg 1 ]
[ lookup reg 1 set __set%d 0x1 ]
@@ -577,6 +711,8 @@ __set%d test-ip4 0
ip test-ip4 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000005 ]
[ payload load 4b @ transport header + 4 => reg 1 ]
[ lookup reg 1 set __set%d ]
@@ -587,6 +723,8 @@ __set%d test-ip4 0
ip test-ip4 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000005 ]
[ payload load 4b @ transport header + 4 => reg 1 ]
[ lookup reg 1 set __set%d 0x1 ]
@@ -594,6 +732,8 @@ ip test-ip4 input
ip test-ip4 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000005 ]
[ payload load 4b @ transport header + 4 => reg 1 ]
[ cmp neq reg 1 0x22000000 ]
@@ -604,6 +744,8 @@ __set%d test-ip4 0
ip test-ip4 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000005 ]
[ payload load 4b @ transport header + 4 => reg 1 ]
[ lookup reg 1 set __set%d 0x1 ]
@@ -634,3 +776,9 @@ ip test-ip4 input
[ lookup reg 1 set __set%d ]
[ immediate reg 0 accept ]
+# icmp code 1 icmp type 2
+ip
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+ [ payload load 2b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000102 ]
diff --git a/tests/py/ip/igmp.t.payload b/tests/py/ip/igmp.t.payload
index 1319c324..b5207475 100644
--- a/tests/py/ip/igmp.t.payload
+++ b/tests/py/ip/igmp.t.payload
@@ -102,165 +102,6 @@ ip test-ip4 input
[ payload load 2b @ transport header + 2 => reg 1 ]
[ lookup reg 1 set __set%d 0x1 ]
-# igmp type membership-query
-ip test-ip4 input
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000002 ]
- [ payload load 1b @ transport header + 0 => reg 1 ]
- [ cmp eq reg 1 0x00000011 ]
-
-# igmp type membership-report-v1
-ip test-ip4 input
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000002 ]
- [ payload load 1b @ transport header + 0 => reg 1 ]
- [ cmp eq reg 1 0x00000012 ]
-
-# igmp type membership-report-v2
-ip test-ip4 input
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000002 ]
- [ payload load 1b @ transport header + 0 => reg 1 ]
- [ cmp eq reg 1 0x00000016 ]
-
-# igmp type membership-report-v3
-ip test-ip4 input
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000002 ]
- [ payload load 1b @ transport header + 0 => reg 1 ]
- [ cmp eq reg 1 0x00000022 ]
-
-# igmp type leave-group
-ip test-ip4 input
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000002 ]
- [ payload load 1b @ transport header + 0 => reg 1 ]
- [ cmp eq reg 1 0x00000017 ]
-
-# igmp type { membership-report-v1, membership-report-v2, membership-report-v3}
-__set%d test-ip4 3 size 3
-__set%d test-ip4 0
- element 00000012 : 0 [end] element 00000016 : 0 [end] element 00000022 : 0 [end]
-ip test-ip4 input
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000002 ]
- [ payload load 1b @ transport header + 0 => reg 1 ]
- [ lookup reg 1 set __set%d ]
-
-# igmp type != { membership-report-v1, membership-report-v2, membership-report-v3}
-__set%d test-ip4 3 size 3
-__set%d test-ip4 0
- element 00000012 : 0 [end] element 00000016 : 0 [end] element 00000022 : 0 [end]
-ip test-ip4 input
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000002 ]
- [ payload load 1b @ transport header + 0 => reg 1 ]
- [ lookup reg 1 set __set%d 0x1 ]
-
-# igmp checksum 12343
-ip test-ip4 input
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000002 ]
- [ payload load 2b @ transport header + 2 => reg 1 ]
- [ cmp eq reg 1 0x00003730 ]
-
-# igmp checksum != 12343
-ip test-ip4 input
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000002 ]
- [ payload load 2b @ transport header + 2 => reg 1 ]
- [ cmp neq reg 1 0x00003730 ]
-
-# igmp checksum 11-343
-ip test-ip4 input
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000002 ]
- [ payload load 2b @ transport header + 2 => reg 1 ]
- [ cmp gte reg 1 0x00000b00 ]
- [ cmp lte reg 1 0x00005701 ]
-
-# igmp checksum != 11-343
-ip test-ip4 input
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000002 ]
- [ payload load 2b @ transport header + 2 => reg 1 ]
- [ range neq reg 1 0x00000b00 0x00005701 ]
-
-# igmp checksum { 11-343}
-__set%d test-ip4 7 size 3
-__set%d test-ip4 0
- element 00000000 : 1 [end] element 00000b00 : 0 [end] element 00005801 : 1 [end]
-ip test-ip4 input
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000002 ]
- [ payload load 2b @ transport header + 2 => reg 1 ]
- [ lookup reg 1 set __set%d ]
-
-# igmp checksum != { 11-343}
-__set%d test-ip4 7 size 3
-__set%d test-ip4 0
- element 00000000 : 1 [end] element 00000b00 : 0 [end] element 00005801 : 1 [end]
-ip test-ip4 input
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000002 ]
- [ payload load 2b @ transport header + 2 => reg 1 ]
- [ lookup reg 1 set __set%d 0x1 ]
-
-# igmp checksum { 1111, 222, 343}
-__set%d test-ip4 3 size 3
-__set%d test-ip4 0
- element 00005704 : 0 [end] element 0000de00 : 0 [end] element 00005701 : 0 [end]
-ip test-ip4 input
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000002 ]
- [ payload load 2b @ transport header + 2 => reg 1 ]
- [ lookup reg 1 set __set%d ]
-
-# igmp checksum != { 1111, 222, 343}
-__set%d test-ip4 3 size 3
-__set%d test-ip4 0
- element 00005704 : 0 [end] element 0000de00 : 0 [end] element 00005701 : 0 [end]
-ip test-ip4 input
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000002 ]
- [ payload load 2b @ transport header + 2 => reg 1 ]
- [ lookup reg 1 set __set%d 0x1 ]
-
-# igmp type membership-query
-ip test-ip4 input
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000002 ]
- [ payload load 1b @ transport header + 0 => reg 1 ]
- [ cmp eq reg 1 0x00000011 ]
-
-# igmp type membership-report-v1
-ip test-ip4 input
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000002 ]
- [ payload load 1b @ transport header + 0 => reg 1 ]
- [ cmp eq reg 1 0x00000012 ]
-
-# igmp type membership-report-v2
-ip test-ip4 input
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000002 ]
- [ payload load 1b @ transport header + 0 => reg 1 ]
- [ cmp eq reg 1 0x00000016 ]
-
-# igmp type membership-report-v3
-ip test-ip4 input
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000002 ]
- [ payload load 1b @ transport header + 0 => reg 1 ]
- [ cmp eq reg 1 0x00000022 ]
-
-# igmp type leave-group
-ip test-ip4 input
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000002 ]
- [ payload load 1b @ transport header + 0 => reg 1 ]
- [ cmp eq reg 1 0x00000017 ]
-
# igmp type { membership-report-v1, membership-report-v2, membership-report-v3}
__set%d test-ip4 3 size 3
__set%d test-ip4 0
@@ -281,75 +122,6 @@ ip test-ip4 input
[ payload load 1b @ transport header + 0 => reg 1 ]
[ lookup reg 1 set __set%d 0x1 ]
-# igmp checksum 12343
-ip test-ip4 input
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000002 ]
- [ payload load 2b @ transport header + 2 => reg 1 ]
- [ cmp eq reg 1 0x00003730 ]
-
-# igmp checksum != 12343
-ip test-ip4 input
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000002 ]
- [ payload load 2b @ transport header + 2 => reg 1 ]
- [ cmp neq reg 1 0x00003730 ]
-
-# igmp checksum 11-343
-ip test-ip4 input
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000002 ]
- [ payload load 2b @ transport header + 2 => reg 1 ]
- [ cmp gte reg 1 0x00000b00 ]
- [ cmp lte reg 1 0x00005701 ]
-
-# igmp checksum != 11-343
-ip test-ip4 input
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000002 ]
- [ payload load 2b @ transport header + 2 => reg 1 ]
- [ range neq reg 1 0x00000b00 0x00005701 ]
-
-# igmp checksum { 11-343}
-__set%d test-ip4 7 size 3
-__set%d test-ip4 0
- element 00000000 : 1 [end] element 00000b00 : 0 [end] element 00005801 : 1 [end]
-ip test-ip4 input
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000002 ]
- [ payload load 2b @ transport header + 2 => reg 1 ]
- [ lookup reg 1 set __set%d ]
-
-# igmp checksum != { 11-343}
-__set%d test-ip4 7 size 3
-__set%d test-ip4 0
- element 00000000 : 1 [end] element 00000b00 : 0 [end] element 00005801 : 1 [end]
-ip test-ip4 input
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000002 ]
- [ payload load 2b @ transport header + 2 => reg 1 ]
- [ lookup reg 1 set __set%d 0x1 ]
-
-# igmp checksum { 1111, 222, 343}
-__set%d test-ip4 3 size 3
-__set%d test-ip4 0
- element 00005704 : 0 [end] element 0000de00 : 0 [end] element 00005701 : 0 [end]
-ip test-ip4 input
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000002 ]
- [ payload load 2b @ transport header + 2 => reg 1 ]
- [ lookup reg 1 set __set%d ]
-
-# igmp checksum != { 1111, 222, 343}
-__set%d test-ip4 3 size 3
-__set%d test-ip4 0
- element 00005704 : 0 [end] element 0000de00 : 0 [end] element 00005701 : 0 [end]
-ip test-ip4 input
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x00000002 ]
- [ payload load 2b @ transport header + 2 => reg 1 ]
- [ lookup reg 1 set __set%d 0x1 ]
-
# igmp mrt 10
ip test-ip4 input
[ meta load l4proto => reg 1 ]
diff --git a/tests/py/ip/ip.t b/tests/py/ip/ip.t
index 0421d01b..04aada2d 100644
--- a/tests/py/ip/ip.t
+++ b/tests/py/ip/ip.t
@@ -92,8 +92,8 @@ ip saddr set {192.19.1.2, 191.1.22.1};fail
ip saddr 192.168.2.0/24;ok
ip saddr != 192.168.2.0/24;ok
ip saddr 192.168.3.1 ip daddr 192.168.3.100;ok
-ip saddr != 1.1.1.1;ok;ip saddr != 1.1.1.1
-ip saddr 1.1.1.1;ok;ip saddr 1.1.1.1
+ip saddr != 1.1.1.1;ok
+ip saddr 1.1.1.1;ok
ip daddr 192.168.0.1-192.168.0.250;ok
ip daddr 10.0.0.0-10.255.255.255;ok
ip daddr 172.16.0.0-172.31.255.255;ok
diff --git a/tests/py/ip/ip.t.payload b/tests/py/ip/ip.t.payload
index 161ff0a5..578c8d37 100644
--- a/tests/py/ip/ip.t.payload
+++ b/tests/py/ip/ip.t.payload
@@ -502,16 +502,6 @@ ip test-ip4 input
[ bitwise reg 1 = ( reg 1 & 0x0000ffff ) ^ 0x00000000 ]
[ cmp eq reg 1 0x0000ffff ]
-# ip saddr . ip daddr . ip protocol { 1.1.1.1 . 2.2.2.2 . tcp, 1.1.1.1 . 3.3.3.3 . udp}
-__set%d test-ip 3
-__set%d test-ip 0
- element 01010101 02020202 00000006 : 0 [end] element 01010101 03030303 00000011 : 0 [end]
-ip test-ip input
- [ payload load 4b @ network header + 12 => reg 1 ]
- [ payload load 4b @ network header + 16 => reg 9 ]
- [ payload load 1b @ network header + 9 => reg 10 ]
- [ lookup reg 1 set __set%d ]
-
# ip version 4 ip hdrlength 5
ip test-ip4 input
[ payload load 1b @ network header + 0 => reg 1 ]
diff --git a/tests/py/ip/ip.t.payload.inet b/tests/py/ip/ip.t.payload.inet
index c1d70748..8c778f99 100644
--- a/tests/py/ip/ip.t.payload.inet
+++ b/tests/py/ip/ip.t.payload.inet
@@ -656,18 +656,6 @@ inet test-inet input
[ bitwise reg 1 = ( reg 1 & 0x0000ffff ) ^ 0x00000000 ]
[ cmp eq reg 1 0x0000ffff ]
-# ip saddr . ip daddr . ip protocol { 1.1.1.1 . 2.2.2.2 . tcp, 1.1.1.1 . 3.3.3.3 . udp}
-__set%d test-ip 3
-__set%d test-ip 0
- element 01010101 02020202 00000006 : 0 [end] element 01010101 03030303 00000011 : 0 [end]
-inet test-ip input
- [ meta load nfproto => reg 1 ]
- [ cmp eq reg 1 0x00000002 ]
- [ payload load 4b @ network header + 12 => reg 1 ]
- [ payload load 4b @ network header + 16 => reg 9 ]
- [ payload load 1b @ network header + 9 => reg 10 ]
- [ lookup reg 1 set __set%d ]
-
# ip version 4 ip hdrlength 5
inet test-inet input
[ meta load nfproto => reg 1 ]
diff --git a/tests/py/ip/ip.t.payload.netdev b/tests/py/ip/ip.t.payload.netdev
index 01044a58..d4e029b0 100644
--- a/tests/py/ip/ip.t.payload.netdev
+++ b/tests/py/ip/ip.t.payload.netdev
@@ -629,118 +629,6 @@ netdev test-netdev ingress
[ payload load 4b @ network header + 16 => reg 1 ]
[ cmp eq reg 1 0x0200a8c0 ]
-# ip ttl 233
-netdev test-netdev ingress
- [ meta load protocol => reg 1 ]
- [ cmp eq reg 1 0x00000008 ]
- [ payload load 1b @ network header + 8 => reg 1 ]
- [ cmp eq reg 1 0x000000e9 ]
-
-# ip protocol tcp
-netdev test-netdev ingress
- [ meta load protocol => reg 1 ]
- [ cmp eq reg 1 0x00000008 ]
- [ payload load 1b @ network header + 9 => reg 1 ]
- [ cmp eq reg 1 0x00000006 ]
-
-# ip protocol != tcp
-netdev test-netdev ingress
- [ meta load protocol => reg 1 ]
- [ cmp eq reg 1 0x00000008 ]
- [ payload load 1b @ network header + 9 => reg 1 ]
- [ cmp neq reg 1 0x00000006 ]
-
-# ip saddr != 1.1.1.1
-netdev test-netdev ingress
- [ meta load protocol => reg 1 ]
- [ cmp eq reg 1 0x00000008 ]
- [ payload load 4b @ network header + 12 => reg 1 ]
- [ cmp neq reg 1 0x01010101 ]
-
-# ip daddr 192.168.0.2
-netdev test-netdev ingress
- [ meta load protocol => reg 1 ]
- [ cmp eq reg 1 0x00000008 ]
- [ payload load 4b @ network header + 16 => reg 1 ]
- [ cmp eq reg 1 0x0200a8c0 ]
-
-# ip ttl 233
-netdev test-netdev ingress
- [ meta load protocol => reg 1 ]
- [ cmp eq reg 1 0x00000008 ]
- [ payload load 1b @ network header + 8 => reg 1 ]
- [ cmp eq reg 1 0x000000e9 ]
-
-# ip protocol tcp
-netdev test-netdev ingress
- [ meta load protocol => reg 1 ]
- [ cmp eq reg 1 0x00000008 ]
- [ payload load 1b @ network header + 9 => reg 1 ]
- [ cmp eq reg 1 0x00000006 ]
-
-# ip protocol != tcp
-netdev test-netdev ingress
- [ meta load protocol => reg 1 ]
- [ cmp eq reg 1 0x00000008 ]
- [ payload load 1b @ network header + 9 => reg 1 ]
- [ cmp neq reg 1 0x00000006 ]
-
-# ip saddr != 1.1.1.1
-netdev test-netdev ingress
- [ meta load protocol => reg 1 ]
- [ cmp eq reg 1 0x00000008 ]
- [ payload load 4b @ network header + 12 => reg 1 ]
- [ cmp neq reg 1 0x01010101 ]
-
-# ip daddr 192.168.0.2
-netdev test-netdev ingress
- [ meta load protocol => reg 1 ]
- [ cmp eq reg 1 0x00000008 ]
- [ payload load 4b @ network header + 16 => reg 1 ]
- [ cmp eq reg 1 0x0200a8c0 ]
-
-# ip ttl 233
-netdev test-netdev ingress
- [ meta load protocol => reg 1 ]
- [ cmp eq reg 1 0x00000008 ]
- [ payload load 1b @ network header + 8 => reg 1 ]
- [ cmp eq reg 1 0x000000e9 ]
-
-# ip protocol tcp
-netdev test-netdev ingress
- [ meta load protocol => reg 1 ]
- [ cmp eq reg 1 0x00000008 ]
- [ payload load 1b @ network header + 9 => reg 1 ]
- [ cmp eq reg 1 0x00000006 ]
-
-# ip protocol != tcp
-netdev test-netdev ingress
- [ meta load protocol => reg 1 ]
- [ cmp eq reg 1 0x00000008 ]
- [ payload load 1b @ network header + 9 => reg 1 ]
- [ cmp neq reg 1 0x00000006 ]
-
-# ip ttl 233
-netdev test-netdev ingress
- [ meta load protocol => reg 1 ]
- [ cmp eq reg 1 0x00000008 ]
- [ payload load 1b @ network header + 8 => reg 1 ]
- [ cmp eq reg 1 0x000000e9 ]
-
-# ip protocol tcp
-netdev test-netdev ingress
- [ meta load protocol => reg 1 ]
- [ cmp eq reg 1 0x00000008 ]
- [ payload load 1b @ network header + 9 => reg 1 ]
- [ cmp eq reg 1 0x00000006 ]
-
-# ip protocol != tcp
-netdev test-netdev ingress
- [ meta load protocol => reg 1 ]
- [ cmp eq reg 1 0x00000008 ]
- [ payload load 1b @ network header + 9 => reg 1 ]
- [ cmp neq reg 1 0x00000006 ]
-
# ip dscp cs1
netdev test-netdev ingress
[ meta load protocol => reg 1 ]
diff --git a/tests/py/ip/reject.t.json.output b/tests/py/ip/reject.t.json.output
index b2529dd7..3917413d 100644
--- a/tests/py/ip/reject.t.json.output
+++ b/tests/py/ip/reject.t.json.output
@@ -1,7 +1,10 @@
-# reject with icmp type port-unreachable
+# reject
[
{
- "reject": null
+ "reject": {
+ "expr": "port-unreachable",
+ "type": "icmp"
+ }
}
]
diff --git a/tests/py/ip6/dnat.t b/tests/py/ip6/dnat.t
index 28bd7ef9..89d5a5f9 100644
--- a/tests/py/ip6/dnat.t
+++ b/tests/py/ip6/dnat.t
@@ -3,7 +3,7 @@
*ip6;test-ip6;prerouting
tcp dport 80-90 dnat to [2001:838:35f:1::]-[2001:838:35f:2::]:80-100;ok
-tcp dport 80-90 dnat to [2001:838:35f:1::]-[2001:838:35f:2::]:100;ok;tcp dport 80-90 dnat to [2001:838:35f:1::]-[2001:838:35f:2::]:100
+tcp dport 80-90 dnat to [2001:838:35f:1::]-[2001:838:35f:2::]:100;ok
tcp dport 80-90 dnat to [2001:838:35f:1::]:80;ok
dnat to [2001:838:35f:1::]/64;ok;dnat to 2001:838:35f:1::/64
dnat to 2001:838:35f:1::-2001:838:35f:1:ffff:ffff:ffff:ffff;ok;dnat to 2001:838:35f:1::/64
diff --git a/tests/py/ip6/ether.t b/tests/py/ip6/ether.t
index d94a0d21..49d7d063 100644
--- a/tests/py/ip6/ether.t
+++ b/tests/py/ip6/ether.t
@@ -3,6 +3,6 @@
*ip6;test-ip6;input
tcp dport 22 iiftype ether ip6 daddr 1::2 ether saddr 00:0f:54:0c:11:4 accept;ok;tcp dport 22 ip6 daddr 1::2 ether saddr 00:0f:54:0c:11:04 accept
-tcp dport 22 ip6 daddr 1::2 ether saddr 00:0f:54:0c:11:04;ok;tcp dport 22 ip6 daddr 1::2 ether saddr 00:0f:54:0c:11:04
+tcp dport 22 ip6 daddr 1::2 ether saddr 00:0f:54:0c:11:04;ok
tcp dport 22 ether saddr 00:0f:54:0c:11:04 ip6 daddr 1::2;ok
ether saddr 00:0f:54:0c:11:04 ip6 daddr 1::2 accept;ok
diff --git a/tests/py/ip6/frag.t.payload.inet b/tests/py/ip6/frag.t.payload.inet
index 917742ff..ff1458d2 100644
--- a/tests/py/ip6/frag.t.payload.inet
+++ b/tests/py/ip6/frag.t.payload.inet
@@ -192,14 +192,6 @@ inet test-inet output
[ bitwise reg 1 = ( reg 1 & 0x0000f8ff ) ^ 0x00000000 ]
[ lookup reg 1 set __set%d 0x1 ]
-# frag more-fragments 1
-inet test-inet output
- [ meta load nfproto => reg 1 ]
- [ cmp eq reg 1 0x0000000a ]
- [ exthdr load ipv6 1b @ 44 + 3 => reg 1 ]
- [ bitwise reg 1 = ( reg 1 & 0x00000001 ) ^ 0x00000000 ]
- [ cmp eq reg 1 0x00000001 ]
-
# frag id 1
inet test-inet output
[ meta load nfproto => reg 1 ]
diff --git a/tests/py/ip6/frag.t.payload.ip6 b/tests/py/ip6/frag.t.payload.ip6
index 2405fff8..dc4103fd 100644
--- a/tests/py/ip6/frag.t.payload.ip6
+++ b/tests/py/ip6/frag.t.payload.ip6
@@ -148,12 +148,6 @@ ip6 test-ip6 output
[ bitwise reg 1 = ( reg 1 & 0x0000f8ff ) ^ 0x00000000 ]
[ lookup reg 1 set __set%d 0x1 ]
-# frag more-fragments 1
-ip6 test-ip6 output
- [ exthdr load ipv6 1b @ 44 + 3 => reg 1 ]
- [ bitwise reg 1 = ( reg 1 & 0x00000001 ) ^ 0x00000000 ]
- [ cmp eq reg 1 0x00000001 ]
-
# frag id 1
ip6 test-ip6 output
[ exthdr load ipv6 4b @ 44 + 4 => reg 1 ]
diff --git a/tests/py/ip6/icmpv6.t b/tests/py/ip6/icmpv6.t
index 8d794115..a45efed6 100644
--- a/tests/py/ip6/icmpv6.t
+++ b/tests/py/ip6/icmpv6.t
@@ -38,15 +38,14 @@ icmpv6 code != { 3-66};ok
icmpv6 checksum 2222 log;ok
icmpv6 checksum != 2222 log;ok
icmpv6 checksum 222-226;ok
-icmpv6 checksum != 2222 log;ok
+icmpv6 checksum != 222-226;ok
icmpv6 checksum { 222, 226};ok
icmpv6 checksum != { 222, 226};ok
icmpv6 checksum { 222-226};ok
icmpv6 checksum != { 222-226};ok
-# BUG: icmpv6 parameter-problem, pptr, mtu, packet-too-big
+# BUG: icmpv6 parameter-problem, pptr
# [ICMP6HDR_PPTR] = ICMP6HDR_FIELD("parameter-problem", icmp6_pptr),
-# [ICMP6HDR_MTU] = ICMP6HDR_FIELD("packet-too-big", icmp6_mtu),
# $ sudo nft add rule ip6 test6 input icmpv6 parameter-problem 35
# <cmdline>:1:53-53: Error: syntax error, unexpected end of file
# add rule ip6 test6 input icmpv6 parameter-problem 35
@@ -59,11 +58,6 @@ icmpv6 checksum != { 222-226};ok
# <cmdline>:1:54-54: Error: syntax error, unexpected end of file
# add rule ip6 test6 input icmpv6 parameter-problem 2-4
-# BUG: packet-too-big
-# $ sudo nft add rule ip6 test6 input icmpv6 packet-too-big 34
-# <cmdline>:1:50-50: Error: syntax error, unexpected end of file
-# add rule ip6 test6 input icmpv6 packet-too-big 34
-
icmpv6 mtu 22;ok
icmpv6 mtu != 233;ok
icmpv6 mtu 33-45;ok
@@ -72,31 +66,31 @@ icmpv6 mtu {33, 55, 67, 88};ok
icmpv6 mtu != {33, 55, 67, 88};ok
icmpv6 mtu {33-55};ok
icmpv6 mtu != {33-55};ok
+icmpv6 type packet-too-big icmpv6 mtu 1280;ok;icmpv6 mtu 1280
-- icmpv6 id 2;ok
-- icmpv6 id != 233;ok
-icmpv6 id 33-45;ok
-icmpv6 id != 33-45;ok
-icmpv6 id {33, 55, 67, 88};ok
-icmpv6 id != {33, 55, 67, 88};ok
-icmpv6 id {33-55};ok
-icmpv6 id != {33-55};ok
+icmpv6 id 33-45;ok;icmpv6 type { echo-request, echo-reply} icmpv6 id 33-45
+icmpv6 id != 33-45;ok;icmpv6 type { echo-request, echo-reply} icmpv6 id != 33-45
+icmpv6 id {33, 55, 67, 88};ok;icmpv6 type { echo-request, echo-reply} icmpv6 id { 33, 55, 67, 88}
+icmpv6 id != {33, 55, 67, 88};ok;icmpv6 type { echo-request, echo-reply} icmpv6 id != { 33, 55, 67, 88}
+icmpv6 id {33-55};ok;icmpv6 type { echo-request, echo-reply} icmpv6 id { 33-55}
+icmpv6 id != {33-55};ok;icmpv6 type { echo-request, echo-reply} icmpv6 id != { 33-55}
-icmpv6 sequence 2;ok
-icmpv6 sequence {3, 4, 5, 6, 7} accept;ok
+icmpv6 sequence 2;ok;icmpv6 type { echo-request, echo-reply} icmpv6 sequence 2
+icmpv6 sequence {3, 4, 5, 6, 7} accept;ok;icmpv6 type { echo-request, echo-reply} icmpv6 sequence { 3, 4, 5, 6, 7} accept
-icmpv6 sequence {2, 4};ok
-icmpv6 sequence != {2, 4};ok
-icmpv6 sequence 2-4;ok
-icmpv6 sequence != 2-4;ok
-icmpv6 sequence { 2-4};ok
-icmpv6 sequence != { 2-4};ok
-- icmpv6 max-delay 22;ok
-- icmpv6 max-delay != 233;ok
+icmpv6 sequence {2, 4};ok;icmpv6 type { echo-request, echo-reply} icmpv6 sequence { 2, 4}
+icmpv6 sequence != {2, 4};ok;icmpv6 type { echo-request, echo-reply} icmpv6 sequence != { 2, 4}
+icmpv6 sequence 2-4;ok;icmpv6 type { echo-request, echo-reply} icmpv6 sequence 2-4
+icmpv6 sequence != 2-4;ok;icmpv6 type { echo-request, echo-reply} icmpv6 sequence != 2-4
+icmpv6 sequence { 2-4};ok;icmpv6 type { echo-request, echo-reply} icmpv6 sequence { 2-4}
+icmpv6 sequence != { 2-4};ok;icmpv6 type { echo-request, echo-reply} icmpv6 sequence != { 2-4}
+
icmpv6 max-delay 33-45;ok
icmpv6 max-delay != 33-45;ok
icmpv6 max-delay {33, 55, 67, 88};ok
icmpv6 max-delay != {33, 55, 67, 88};ok
icmpv6 max-delay {33-55};ok
icmpv6 max-delay != {33-55};ok
+
+icmpv6 type parameter-problem icmpv6 code no-route;ok
diff --git a/tests/py/ip6/icmpv6.t.json b/tests/py/ip6/icmpv6.t.json
index f6cfbf17..96079042 100644
--- a/tests/py/ip6/icmpv6.t.json
+++ b/tests/py/ip6/icmpv6.t.json
@@ -640,7 +640,7 @@
}
]
-# icmpv6 checksum != 2222 log
+# icmpv6 checksum != 222-226
[
{
"match": {
@@ -650,12 +650,11 @@
"protocol": "icmpv6"
}
},
- "op": "!=",
- "right": 2222
+ "op": "!=",
+ "right": {
+ "range": [ 222, 226 ]
+ }
}
- },
- {
- "log": null
}
]
@@ -1185,7 +1184,7 @@
"left": {
"payload": {
"field": "max-delay",
- "name": "icmpv6"
+ "protocol": "icmpv6"
}
},
"op": "==",
@@ -1203,7 +1202,7 @@
"left": {
"payload": {
"field": "max-delay",
- "name": "icmpv6"
+ "protocol": "icmpv6"
}
},
"op": "!=",
@@ -1221,7 +1220,7 @@
"left": {
"payload": {
"field": "max-delay",
- "name": "icmpv6"
+ "protocol": "icmpv6"
}
},
"op": "==",
@@ -1244,7 +1243,7 @@
"left": {
"payload": {
"field": "max-delay",
- "name": "icmpv6"
+ "protocol": "icmpv6"
}
},
"op": "!=",
@@ -1267,7 +1266,7 @@
"left": {
"payload": {
"field": "max-delay",
- "name": "icmpv6"
+ "protocol": "icmpv6"
}
},
"op": "==",
@@ -1287,7 +1286,7 @@
"left": {
"payload": {
"field": "max-delay",
- "name": "icmpv6"
+ "protocol": "icmpv6"
}
},
"op": "!=",
@@ -1300,3 +1299,46 @@
}
]
+# icmpv6 type packet-too-big icmpv6 mtu 1280
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "mtu",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": 1280
+ }
+ }
+]
+
+# icmpv6 type parameter-problem icmpv6 code no-route
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": "parameter-problem"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "code",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": "no-route"
+ }
+ }
+]
diff --git a/tests/py/ip6/icmpv6.t.json.output b/tests/py/ip6/icmpv6.t.json.output
index 3a106621..7b8f5c19 100644
--- a/tests/py/ip6/icmpv6.t.json.output
+++ b/tests/py/ip6/icmpv6.t.json.output
@@ -8,7 +8,7 @@
"protocol": "icmpv6"
}
},
- "op": "==",
+ "op": "==",
"right": "mld-listener-done"
}
},
@@ -27,7 +27,7 @@
"protocol": "icmpv6"
}
},
- "op": "==",
+ "op": "==",
"right": {
"set": [
"time-exceeded",
@@ -53,7 +53,7 @@
"protocol": "icmpv6"
}
},
- "op": "==",
+ "op": "==",
"right": {
"set": [
"time-exceeded",
@@ -103,7 +103,7 @@
"protocol": "icmpv6"
}
},
- "op": "==",
+ "op": "==",
"right": "port-unreachable"
}
}
@@ -119,9 +119,12 @@
"protocol": "icmpv6"
}
},
- "op": "==",
+ "op": "==",
"right": {
- "range": [ "addr-unreachable", 66 ]
+ "range": [
+ "addr-unreachable",
+ 66
+ ]
}
}
}
@@ -137,7 +140,7 @@
"protocol": "icmpv6"
}
},
- "op": "==",
+ "op": "==",
"right": {
"set": [
"policy-fail",
@@ -162,10 +165,15 @@
"protocol": "icmpv6"
}
},
- "op": "==",
+ "op": "==",
"right": {
"set": [
- { "range": [ "addr-unreachable", 66 ] }
+ {
+ "range": [
+ "addr-unreachable",
+ 66
+ ]
+ }
]
}
}
@@ -185,7 +193,565 @@
"op": "!=",
"right": {
"set": [
- { "range": [ "addr-unreachable", 66 ] }
+ {
+ "range": [
+ "addr-unreachable",
+ 66
+ ]
+ }
+ ]
+ }
+ }
+ }
+]
+
+# icmpv6 id 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-request",
+ "echo-reply"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [
+ 33,
+ 45
+ ]
+ }
+ }
+ }
+]
+
+# icmpv6 id != 33-45
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-request",
+ "echo-reply"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [
+ 33,
+ 45
+ ]
+ }
+ }
+ }
+]
+
+# icmpv6 id {33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-request",
+ "echo-reply"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# icmpv6 id != {33, 55, 67, 88}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-request",
+ "echo-reply"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 33,
+ 55,
+ 67,
+ 88
+ ]
+ }
+ }
+ }
+]
+
+# icmpv6 id {33-55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-request",
+ "echo-reply"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ {
+ "range": [
+ 33,
+ 55
+ ]
+ }
+ ]
+ }
+ }
+ }
+]
+
+# icmpv6 id != {33-55}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-request",
+ "echo-reply"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "id",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ {
+ "range": [
+ 33,
+ 55
+ ]
+ }
+ ]
+ }
+ }
+ }
+]
+
+# icmpv6 sequence 2
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-request",
+ "echo-reply"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": 2
+ }
+ }
+]
+
+# icmpv6 sequence {3, 4, 5, 6, 7} accept
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-request",
+ "echo-reply"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 3,
+ 4,
+ 5,
+ 6,
+ 7
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
+
+# icmpv6 sequence {2, 4}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-request",
+ "echo-reply"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ 2,
+ 4
+ ]
+ }
+ }
+ }
+]
+
+# icmpv6 sequence != {2, 4}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-request",
+ "echo-reply"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ 2,
+ 4
+ ]
+ }
+ }
+ }
+]
+
+# icmpv6 sequence 2-4
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-request",
+ "echo-reply"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "range": [
+ 2,
+ 4
+ ]
+ }
+ }
+ }
+]
+
+# icmpv6 sequence != 2-4
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-request",
+ "echo-reply"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "range": [
+ 2,
+ 4
+ ]
+ }
+ }
+ }
+]
+
+# icmpv6 sequence { 2-4}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-request",
+ "echo-reply"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ {
+ "range": [
+ 2,
+ 4
+ ]
+ }
+ ]
+ }
+ }
+ }
+]
+
+# icmpv6 sequence != { 2-4}
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ "echo-request",
+ "echo-reply"
+ ]
+ }
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "sequence",
+ "protocol": "icmpv6"
+ }
+ },
+ "op": "!=",
+ "right": {
+ "set": [
+ {
+ "range": [
+ 2,
+ 4
+ ]
+ }
]
}
}
diff --git a/tests/py/ip6/icmpv6.t.payload.ip6 b/tests/py/ip6/icmpv6.t.payload.ip6
index 51d71f41..c98a2548 100644
--- a/tests/py/ip6/icmpv6.t.payload.ip6
+++ b/tests/py/ip6/icmpv6.t.payload.ip6
@@ -275,13 +275,12 @@ ip6 test-ip6 input
[ cmp gte reg 1 0x0000de00 ]
[ cmp lte reg 1 0x0000e200 ]
-# icmpv6 checksum != 2222 log
-ip6 test-ip6 input
+# icmpv6 checksum != 222-226
+ip6
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x0000003a ]
[ payload load 2b @ transport header + 2 => reg 1 ]
- [ cmp neq reg 1 0x0000ae08 ]
- [ log ]
+ [ range neq reg 1 0x0000de00 0x0000e200 ]
# icmpv6 checksum { 222, 226}
__set%d test-ip6 3
@@ -327,6 +326,8 @@ ip6 test-ip6 input
ip6 test-ip6 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
[ payload load 4b @ transport header + 4 => reg 1 ]
[ cmp eq reg 1 0x16000000 ]
@@ -334,6 +335,8 @@ ip6 test-ip6 input
ip6 test-ip6 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
[ payload load 4b @ transport header + 4 => reg 1 ]
[ cmp neq reg 1 0xe9000000 ]
@@ -341,6 +344,8 @@ ip6 test-ip6 input
ip6 test-ip6 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
[ payload load 4b @ transport header + 4 => reg 1 ]
[ cmp gte reg 1 0x21000000 ]
[ cmp lte reg 1 0x2d000000 ]
@@ -349,6 +354,8 @@ ip6 test-ip6 input
ip6 test-ip6 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
[ payload load 4b @ transport header + 4 => reg 1 ]
[ range neq reg 1 0x21000000 0x2d000000 ]
@@ -359,6 +366,8 @@ __set%d test-ip6 0
ip6 test-ip6 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
[ payload load 4b @ transport header + 4 => reg 1 ]
[ lookup reg 1 set __set%d ]
@@ -369,6 +378,8 @@ __set%d test-ip6 0
ip6 test-ip6 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
[ payload load 4b @ transport header + 4 => reg 1 ]
[ lookup reg 1 set __set%d 0x1 ]
@@ -379,6 +390,8 @@ __set%d test-ip6 0
ip6 test-ip6 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
[ payload load 4b @ transport header + 4 => reg 1 ]
[ lookup reg 1 set __set%d ]
@@ -389,145 +402,215 @@ __set%d test-ip6 0
ip6 test-ip6 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
[ payload load 4b @ transport header + 4 => reg 1 ]
[ lookup reg 1 set __set%d 0x1 ]
+# icmpv6 type packet-too-big icmpv6 mtu 1280
+ip6
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000002 ]
+ [ payload load 4b @ transport header + 4 => reg 1 ]
+ [ cmp eq reg 1 0x00050000 ]
+
# icmpv6 id 33-45
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000080 : 0 [end] element 00000081 : 0 [end]
ip6 test-ip6 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
[ payload load 2b @ transport header + 4 => reg 1 ]
[ cmp gte reg 1 0x00002100 ]
[ cmp lte reg 1 0x00002d00 ]
# icmpv6 id != 33-45
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000080 : 0 [end] element 00000081 : 0 [end]
ip6 test-ip6 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
[ payload load 2b @ transport header + 4 => reg 1 ]
[ range neq reg 1 0x00002100 0x00002d00 ]
# icmpv6 id {33, 55, 67, 88}
__set%d test-ip6 3
__set%d test-ip6 0
+ element 00000080 : 0 [end] element 00000081 : 0 [end]
+__set%d test-ip6 3
+__set%d test-ip6 0
element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
ip6 test-ip6 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
[ payload load 2b @ transport header + 4 => reg 1 ]
[ lookup reg 1 set __set%d ]
# icmpv6 id != {33, 55, 67, 88}
__set%d test-ip6 3
__set%d test-ip6 0
+ element 00000080 : 0 [end] element 00000081 : 0 [end]
+__set%d test-ip6 3
+__set%d test-ip6 0
element 00002100 : 0 [end] element 00003700 : 0 [end] element 00004300 : 0 [end] element 00005800 : 0 [end]
ip6 test-ip6 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
[ payload load 2b @ transport header + 4 => reg 1 ]
[ lookup reg 1 set __set%d 0x1 ]
# icmpv6 id {33-55}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000080 : 0 [end] element 00000081 : 0 [end]
__set%d test-ip6 7
__set%d test-ip6 0
element 00000000 : 1 [end] element 00002100 : 0 [end] element 00003800 : 1 [end]
ip6 test-ip6 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
[ payload load 2b @ transport header + 4 => reg 1 ]
[ lookup reg 1 set __set%d ]
# icmpv6 id != {33-55}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000080 : 0 [end] element 00000081 : 0 [end]
__set%d test-ip6 7
__set%d test-ip6 0
element 00000000 : 1 [end] element 00002100 : 0 [end] element 00003800 : 1 [end]
ip6 test-ip6 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
[ payload load 2b @ transport header + 4 => reg 1 ]
[ lookup reg 1 set __set%d 0x1 ]
# icmpv6 sequence 2
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000080 : 0 [end] element 00000081 : 0 [end]
ip6 test-ip6 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
[ payload load 2b @ transport header + 6 => reg 1 ]
[ cmp eq reg 1 0x00000200 ]
# icmpv6 sequence {3, 4, 5, 6, 7} accept
__set%d test-ip6 3
__set%d test-ip6 0
- element 00000300 : 0 [end] element 00000400 : 0 [end] element 00000500 : 0 [end] element 00000600 : 0 [end] element 00000700 : 0 [end]
-ip6 test-ip6 input
- [ meta load l4proto => reg 1 ]
- [ cmp eq reg 1 0x0000003a ]
- [ payload load 2b @ transport header + 6 => reg 1 ]
- [ lookup reg 1 set __set%d ]
- [ immediate reg 0 accept ]
-
-# icmpv6 sequence != {3, 4, 5, 6, 7} accept
+ element 00000080 : 0 [end] element 00000081 : 0 [end]
__set%d test-ip6 3
__set%d test-ip6 0
element 00000300 : 0 [end] element 00000400 : 0 [end] element 00000500 : 0 [end] element 00000600 : 0 [end] element 00000700 : 0 [end]
ip6 test-ip6 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
[ payload load 2b @ transport header + 6 => reg 1 ]
- [ lookup reg 1 set __set%d 0x1 ]
+ [ lookup reg 1 set __set%d ]
[ immediate reg 0 accept ]
# icmpv6 sequence {2, 4}
__set%d test-ip6 3
__set%d test-ip6 0
+ element 00000080 : 0 [end] element 00000081 : 0 [end]
+__set%d test-ip6 3
+__set%d test-ip6 0
element 00000200 : 0 [end] element 00000400 : 0 [end]
ip6 test-ip6 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
[ payload load 2b @ transport header + 6 => reg 1 ]
[ lookup reg 1 set __set%d ]
# icmpv6 sequence != {2, 4}
__set%d test-ip6 3
__set%d test-ip6 0
+ element 00000080 : 0 [end] element 00000081 : 0 [end]
+__set%d test-ip6 3
+__set%d test-ip6 0
element 00000200 : 0 [end] element 00000400 : 0 [end]
ip6 test-ip6 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
[ payload load 2b @ transport header + 6 => reg 1 ]
[ lookup reg 1 set __set%d 0x1 ]
# icmpv6 sequence 2-4
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000080 : 0 [end] element 00000081 : 0 [end]
ip6 test-ip6 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
[ payload load 2b @ transport header + 6 => reg 1 ]
[ cmp gte reg 1 0x00000200 ]
[ cmp lte reg 1 0x00000400 ]
# icmpv6 sequence != 2-4
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000080 : 0 [end] element 00000081 : 0 [end]
ip6 test-ip6 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
[ payload load 2b @ transport header + 6 => reg 1 ]
[ range neq reg 1 0x00000200 0x00000400 ]
# icmpv6 sequence { 2-4}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000080 : 0 [end] element 00000081 : 0 [end]
__set%d test-ip6 7
__set%d test-ip6 0
element 00000000 : 1 [end] element 00000200 : 0 [end] element 00000500 : 1 [end]
ip6 test-ip6 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
[ payload load 2b @ transport header + 6 => reg 1 ]
[ lookup reg 1 set __set%d ]
# icmpv6 sequence != { 2-4}
+__set%d test-ip6 3
+__set%d test-ip6 0
+ element 00000080 : 0 [end] element 00000081 : 0 [end]
__set%d test-ip6 7
__set%d test-ip6 0
element 00000000 : 1 [end] element 00000200 : 0 [end] element 00000500 : 1 [end]
ip6 test-ip6 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ lookup reg 1 set __set%d ]
[ payload load 2b @ transport header + 6 => reg 1 ]
[ lookup reg 1 set __set%d 0x1 ]
@@ -535,6 +618,8 @@ ip6 test-ip6 input
ip6 test-ip6 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000082 ]
[ payload load 2b @ transport header + 4 => reg 1 ]
[ cmp gte reg 1 0x00002100 ]
[ cmp lte reg 1 0x00002d00 ]
@@ -543,6 +628,8 @@ ip6 test-ip6 input
ip6 test-ip6 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000082 ]
[ payload load 2b @ transport header + 4 => reg 1 ]
[ range neq reg 1 0x00002100 0x00002d00 ]
@@ -553,6 +640,8 @@ __set%d test-ip6 0
ip6 test-ip6 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000082 ]
[ payload load 2b @ transport header + 4 => reg 1 ]
[ lookup reg 1 set __set%d ]
@@ -563,6 +652,8 @@ __set%d test-ip6 0
ip6 test-ip6 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000082 ]
[ payload load 2b @ transport header + 4 => reg 1 ]
[ lookup reg 1 set __set%d 0x1 ]
@@ -573,6 +664,8 @@ __set%d test-ip6 0
ip6 test-ip6 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000082 ]
[ payload load 2b @ transport header + 4 => reg 1 ]
[ lookup reg 1 set __set%d ]
@@ -583,6 +676,15 @@ __set%d test-ip6 0
ip6 test-ip6 input
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x0000003a ]
+ [ payload load 1b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000082 ]
[ payload load 2b @ transport header + 4 => reg 1 ]
[ lookup reg 1 set __set%d 0x1 ]
+# icmpv6 type parameter-problem icmpv6 code no-route
+ip6
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x0000003a ]
+ [ payload load 2b @ transport header + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000004 ]
+
diff --git a/tests/py/ip6/ip6.t b/tests/py/ip6/ip6.t
index 8210d22b..dbb56fa3 100644
--- a/tests/py/ip6/ip6.t
+++ b/tests/py/ip6/ip6.t
@@ -26,7 +26,7 @@ ip6 flowlabel { 33, 55, 67, 88};ok
ip6 flowlabel != { 33, 55, 67, 88};ok
ip6 flowlabel { 33-55};ok
ip6 flowlabel != { 33-55};ok
-ip6 flowlabel vmap { 0 : accept, 2 : continue } ;ok
+ip6 flowlabel vmap { 0 : accept, 2 : continue };ok
ip6 length 22;ok
ip6 length != 233;ok
diff --git a/tests/py/ip6/ip6.t.payload.inet b/tests/py/ip6/ip6.t.payload.inet
index 8912aadf..11ba34a1 100644
--- a/tests/py/ip6/ip6.t.payload.inet
+++ b/tests/py/ip6/ip6.t.payload.inet
@@ -113,7 +113,7 @@ inet test-inet input
[ bitwise reg 1 = ( reg 1 & 0x00ffff0f ) ^ 0x00000000 ]
[ lookup reg 1 set __set%d 0x1 ]
-# ip6 flowlabel vmap { 0 : accept, 2 : continue }
+# ip6 flowlabel vmap { 0 : accept, 2 : continue }
__map%d test-inet b size 2
__map%d test-inet 0
element 00000000 : 0 [end] element 00020000 : 0 [end]
diff --git a/tests/py/ip6/ip6.t.payload.ip6 b/tests/py/ip6/ip6.t.payload.ip6
index 287d58ac..78479253 100644
--- a/tests/py/ip6/ip6.t.payload.ip6
+++ b/tests/py/ip6/ip6.t.payload.ip6
@@ -89,7 +89,7 @@ ip6 test-ip6 input
[ bitwise reg 1 = ( reg 1 & 0x00ffff0f ) ^ 0x00000000 ]
[ lookup reg 1 set __set%d 0x1 ]
-# ip6 flowlabel vmap { 0 : accept, 2 : continue }
+# ip6 flowlabel vmap { 0 : accept, 2 : continue }
__map%d test-ip6 b size 2
__map%d test-ip6 0
element 00000000 : 0 [end] element 00020000 : 0 [end]
diff --git a/tests/py/ip6/reject.t.json.output b/tests/py/ip6/reject.t.json.output
index 4e2058fe..04f12f56 100644
--- a/tests/py/ip6/reject.t.json.output
+++ b/tests/py/ip6/reject.t.json.output
@@ -1,7 +1,10 @@
-# reject with icmpv6 type port-unreachable
+# reject
[
{
- "reject": null
+ "reject": {
+ "expr": "port-unreachable",
+ "type": "icmpv6"
+ }
}
]
diff --git a/tests/py/ip6/snat.t b/tests/py/ip6/snat.t
index c259f934..564f0894 100644
--- a/tests/py/ip6/snat.t
+++ b/tests/py/ip6/snat.t
@@ -2,5 +2,5 @@
*ip6;test-ip6;postrouting
-tcp dport 80-90 snat to [2001:838:35f:1::]-[2001:838:35f:2::]:80-100;ok;tcp dport 80-90 snat to [2001:838:35f:1::]-[2001:838:35f:2::]:80-100
+tcp dport 80-90 snat to [2001:838:35f:1::]-[2001:838:35f:2::]:80-100;ok
tcp dport 80-90 snat to [2001:838:35f:1::]-[2001:838:35f:2::]:100;ok
diff --git a/tests/py/netdev/reject.t b/tests/py/netdev/reject.t
index a4434b6c..af109086 100644
--- a/tests/py/netdev/reject.t
+++ b/tests/py/netdev/reject.t
@@ -2,19 +2,39 @@
*netdev;test-netdev;ingress
-reject with icmp type host-unreachable;ok;reject
-reject with icmp type net-unreachable;ok;reject
-reject with icmp type prot-unreachable;ok;reject
-reject with icmp type port-unreachable;ok;reject
-reject with icmp type net-prohibited;ok;reject
-reject with icmp type host-prohibited;ok;reject
-reject with icmp type admin-prohibited;ok;reject
-
-reject with icmpv6 type no-route;ok;reject
-reject with icmpv6 type admin-prohibited;ok;reject
-reject with icmpv6 type addr-unreachable;ok;reject
-reject with icmpv6 type port-unreachable;ok;reject
-reject with icmpv6 type policy-fail;ok;reject
-reject with icmpv6 type reject-route;ok;reject
+reject with icmp type host-unreachable;ok
+reject with icmp type net-unreachable;ok
+reject with icmp type prot-unreachable;ok
+reject with icmp type port-unreachable;ok
+reject with icmp type net-prohibited;ok
+reject with icmp type host-prohibited;ok
+reject with icmp type admin-prohibited;ok
+
+reject with icmpv6 type no-route;ok
+reject with icmpv6 type admin-prohibited;ok
+reject with icmpv6 type addr-unreachable;ok
+reject with icmpv6 type port-unreachable;ok
+reject with icmpv6 type policy-fail;ok
+reject with icmpv6 type reject-route;ok
+
+mark 12345 reject with tcp reset;ok;meta l4proto 6 meta mark 0x00003039 reject with tcp reset
reject;ok
+meta protocol ip reject;ok;reject with icmp type port-unreachable
+meta protocol ip6 reject;ok;reject with icmpv6 type port-unreachable
+
+reject with icmpx type host-unreachable;ok
+reject with icmpx type no-route;ok
+reject with icmpx type admin-prohibited;ok
+reject with icmpx type port-unreachable;ok;reject
+
+meta protocol ip reject with icmp type host-unreachable;ok;reject with icmp type host-unreachable
+meta protocol ip6 reject with icmpv6 type no-route;ok;reject with icmpv6 type no-route
+
+meta protocol ip6 reject with icmp type host-unreachable;fail
+meta protocol ip ip protocol icmp reject with icmpv6 type no-route;fail
+meta protocol ip6 ip protocol icmp reject with icmp type host-unreachable;fail
+meta l4proto udp reject with tcp reset;fail
+
+meta protocol ip reject with icmpx type admin-prohibited;ok
+meta protocol ip6 reject with icmpx type admin-prohibited;ok
diff --git a/tests/py/netdev/reject.t.json b/tests/py/netdev/reject.t.json
new file mode 100644
index 00000000..21e6ebb5
--- /dev/null
+++ b/tests/py/netdev/reject.t.json
@@ -0,0 +1,317 @@
+# reject with icmp type host-unreachable
+[
+ {
+ "reject": {
+ "expr": "host-unreachable",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp type net-unreachable
+[
+ {
+ "reject": {
+ "expr": "net-unreachable",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp type prot-unreachable
+[
+ {
+ "reject": {
+ "expr": "prot-unreachable",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp type port-unreachable
+[
+ {
+ "reject": {
+ "expr": "port-unreachable",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp type net-prohibited
+[
+ {
+ "reject": {
+ "expr": "net-prohibited",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp type host-prohibited
+[
+ {
+ "reject": {
+ "expr": "host-prohibited",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmp type admin-prohibited
+[
+ {
+ "reject": {
+ "expr": "admin-prohibited",
+ "type": "icmp"
+ }
+ }
+]
+
+# reject with icmpv6 type no-route
+[
+ {
+ "reject": {
+ "expr": "no-route",
+ "type": "icmpv6"
+ }
+ }
+]
+
+# reject with icmpv6 type admin-prohibited
+[
+ {
+ "reject": {
+ "expr": "admin-prohibited",
+ "type": "icmpv6"
+ }
+ }
+]
+
+# reject with icmpv6 type addr-unreachable
+[
+ {
+ "reject": {
+ "expr": "addr-unreachable",
+ "type": "icmpv6"
+ }
+ }
+]
+
+# reject with icmpv6 type port-unreachable
+[
+ {
+ "reject": {
+ "expr": "port-unreachable",
+ "type": "icmpv6"
+ }
+ }
+]
+
+# reject with icmpv6 type policy-fail
+[
+ {
+ "reject": {
+ "expr": "policy-fail",
+ "type": "icmpv6"
+ }
+ }
+]
+
+# reject with icmpv6 type reject-route
+[
+ {
+ "reject": {
+ "expr": "reject-route",
+ "type": "icmpv6"
+ }
+ }
+]
+
+# mark 12345 reject with tcp reset
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "mark"
+ }
+ },
+ "op": "==",
+ "right": 12345
+ }
+ },
+ {
+ "reject": {
+ "type": "tcp reset"
+ }
+ }
+]
+
+# reject
+[
+ {
+ "reject": null
+ }
+]
+
+# meta protocol ip reject
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "protocol"
+ }
+ },
+ "op": "==",
+ "right": "ip"
+ }
+ },
+ {
+ "reject": null
+ }
+]
+
+# meta protocol ip6 reject
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "protocol"
+ }
+ },
+ "op": "==",
+ "right": "ip6"
+ }
+ },
+ {
+ "reject": null
+ }
+]
+
+# reject with icmpx type host-unreachable
+[
+ {
+ "reject": {
+ "expr": "host-unreachable",
+ "type": "icmpx"
+ }
+ }
+]
+
+# reject with icmpx type no-route
+[
+ {
+ "reject": {
+ "expr": "no-route",
+ "type": "icmpx"
+ }
+ }
+]
+
+# reject with icmpx type admin-prohibited
+[
+ {
+ "reject": {
+ "expr": "admin-prohibited",
+ "type": "icmpx"
+ }
+ }
+]
+
+# reject with icmpx type port-unreachable
+[
+ {
+ "reject": {
+ "expr": "port-unreachable",
+ "type": "icmpx"
+ }
+ }
+]
+
+# meta protocol ip reject with icmp type host-unreachable
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "protocol"
+ }
+ },
+ "op": "==",
+ "right": "ip"
+ }
+ },
+ {
+ "reject": {
+ "expr": "host-unreachable",
+ "type": "icmp"
+ }
+ }
+]
+
+# meta protocol ip6 reject with icmpv6 type no-route
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "protocol"
+ }
+ },
+ "op": "==",
+ "right": "ip6"
+ }
+ },
+ {
+ "reject": {
+ "expr": "no-route",
+ "type": "icmpv6"
+ }
+ }
+]
+
+# meta protocol ip reject with icmpx type admin-prohibited
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "protocol"
+ }
+ },
+ "op": "==",
+ "right": "ip"
+ }
+ },
+ {
+ "reject": {
+ "expr": "admin-prohibited",
+ "type": "icmpx"
+ }
+ }
+]
+
+# meta protocol ip6 reject with icmpx type admin-prohibited
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "protocol"
+ }
+ },
+ "op": "==",
+ "right": "ip6"
+ }
+ },
+ {
+ "reject": {
+ "expr": "admin-prohibited",
+ "type": "icmpx"
+ }
+ }
+]
+
diff --git a/tests/py/netdev/reject.t.payload b/tests/py/netdev/reject.t.payload
index d3af2f33..5f76b091 100644
--- a/tests/py/netdev/reject.t.payload
+++ b/tests/py/netdev/reject.t.payload
@@ -1,56 +1,142 @@
# reject with icmp type host-unreachable
netdev
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
[ reject type 0 code 1 ]
-# reject
-netdev
- [ reject type 2 code 1 ]
-
-# reject with icmp type admin-prohibited
-netdev
- [ reject type 0 code 13 ]
-
# reject with icmp type net-unreachable
netdev
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
[ reject type 0 code 0 ]
# reject with icmp type prot-unreachable
netdev
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
[ reject type 0 code 2 ]
# reject with icmp type port-unreachable
netdev
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
[ reject type 0 code 3 ]
# reject with icmp type net-prohibited
netdev
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
[ reject type 0 code 9 ]
# reject with icmp type host-prohibited
netdev
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
[ reject type 0 code 10 ]
+# reject with icmp type admin-prohibited
+netdev
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ reject type 0 code 13 ]
+
# reject with icmpv6 type no-route
netdev
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
[ reject type 0 code 0 ]
# reject with icmpv6 type admin-prohibited
netdev
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
[ reject type 0 code 1 ]
# reject with icmpv6 type addr-unreachable
netdev
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
[ reject type 0 code 3 ]
# reject with icmpv6 type port-unreachable
netdev
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
[ reject type 0 code 4 ]
# reject with icmpv6 type policy-fail
netdev
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
[ reject type 0 code 5 ]
# reject with icmpv6 type reject-route
netdev
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
[ reject type 0 code 6 ]
+# mark 12345 reject with tcp reset
+netdev
+ [ meta load l4proto => reg 1 ]
+ [ cmp eq reg 1 0x00000006 ]
+ [ meta load mark => reg 1 ]
+ [ cmp eq reg 1 0x00003039 ]
+ [ reject type 1 code 0 ]
+
+# reject
+netdev
+ [ reject type 2 code 1 ]
+
+# meta protocol ip reject
+netdev
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ reject type 0 code 3 ]
+
+# meta protocol ip6 reject
+netdev
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ reject type 0 code 4 ]
+
+# reject with icmpx type host-unreachable
+netdev
+ [ reject type 2 code 2 ]
+
+# reject with icmpx type no-route
+netdev
+ [ reject type 2 code 0 ]
+
+# reject with icmpx type admin-prohibited
+netdev
+ [ reject type 2 code 3 ]
+
+# reject with icmpx type port-unreachable
+netdev
+ [ reject type 2 code 1 ]
+
+# meta protocol ip reject with icmp type host-unreachable
+netdev
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ reject type 0 code 1 ]
+
+# meta protocol ip6 reject with icmpv6 type no-route
+netdev
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ reject type 0 code 0 ]
+
+# meta protocol ip reject with icmpx type admin-prohibited
+netdev
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000008 ]
+ [ reject type 2 code 3 ]
+
+# meta protocol ip6 reject with icmpx type admin-prohibited
+netdev
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x0000dd86 ]
+ [ reject type 2 code 3 ]
+
diff --git a/tests/py/nft-test.py b/tests/py/nft-test.py
index 7ca5a22a..18e9c67f 100755
--- a/tests/py/nft-test.py
+++ b/tests/py/nft-test.py
@@ -712,8 +712,10 @@ def rule_add(rule, filename, lineno, force_all_family_option, filename_path):
if rule[1].strip() == "ok":
payload_expected = None
+ payload_path = None
try:
payload_log = open("%s.payload" % filename_path)
+ payload_path = payload_log.name
payload_expected = payload_find_expected(payload_log, rule[0])
except:
payload_log = None
@@ -756,6 +758,7 @@ def rule_add(rule, filename, lineno, force_all_family_option, filename_path):
table_payload_expected = None
try:
payload_log = open("%s.payload.%s" % (filename_path, table.family))
+ payload_path = payload_log.name
table_payload_expected = payload_find_expected(payload_log, rule[0])
except:
if not payload_log:
@@ -802,7 +805,7 @@ def rule_add(rule, filename, lineno, force_all_family_option, filename_path):
if state == "ok" and not payload_check(table_payload_expected,
payload_log, cmd):
error += 1
- gotf = open("%s.payload.got" % filename_path, 'a')
+ gotf = open("%s.got" % payload_path, 'a')
payload_log.seek(0, 0)
gotf.write("# %s\n" % rule[0])
while True:
diff --git a/tests/py/tools/test-sanitizer.sh b/tests/py/tools/test-sanitizer.sh
new file mode 100755
index 00000000..92354d2b
--- /dev/null
+++ b/tests/py/tools/test-sanitizer.sh
@@ -0,0 +1,78 @@
+#!/bin/bash
+
+# Do some simple sanity checks on tests:
+# - Report tests where reply matches command
+# - Report tests with non-ok exit but reply
+# - Check for duplicate test commands in *.t files
+# - Check for duplicate or stale payload records in *.t.payload* files
+# - Check for duplicate or stale json equivalents in *.t.json files
+
+cd $(dirname $0)/../
+
+[[ $1 ]] && tests="$@" || tests="*/*.t"
+
+reportfile=""
+report() { # (file, msg)
+ [[ "$reportfile" == "$1" ]] || {
+ reportfile="$1"
+ echo ""
+ echo "In $reportfile:"
+ }
+ shift
+ echo "$@"
+}
+
+for t in $tests; do
+ [[ -f $t ]] || continue
+
+ readarray -t cmdlines <<< $(grep -v -e '^ *[:*#-?]' -e '^ *$' $t)
+
+ cmds=""
+ for cmdline in "${cmdlines[@]}"; do
+ readarray -t -d ';' cmdparts <<< "$cmdline"
+ cmd="${cmdparts[0]}"
+ rc="${cmdparts[1]}"
+ out="${cmdparts[2]}"
+
+ [[ -n $cmd ]] || continue
+
+ #echo "cmdline: $cmdline"
+ #echo "cmd: $cmd"
+ #echo "rc: $rc"
+ #echo "out: $out"
+
+ [[ "$cmd" != "$out" ]] || \
+ report $t "reply matches cmd: $cmd"
+ [[ "$rc" != "ok" && "$out" ]] && \
+ report $t "output record with non-ok exit: $cmd"
+
+ cmds+="${cmd}\n"
+ done
+
+ readarray -t dups <<< $(echo -e "$cmds" | sort | uniq -d)
+ for dup in "${dups[@]}"; do
+ [[ -n $dup ]] || continue
+ report $t "duplicate command: $dup"
+ done
+
+ for p in $t.payload* $t.json; do
+ [[ -f $p ]] || continue
+ [[ $p == *.got ]] && continue
+ [[ $p == *.json ]] && t="json" || t="payload"
+
+ pcmds=$(grep '^#' $p)
+ readarray -t dups <<< $(echo "$pcmds" | sort | uniq -d)
+ readarray -t stales <<< $(echo "$pcmds" | while read hash pcmd; do
+ echo -e "$cmds" | grep -qxF "${pcmd}" || echo "# ${pcmd}"
+ done)
+
+ for stale in "${stales[@]}"; do
+ [[ -n $stale ]] || continue
+ report $p "stale $t record: $stale"
+ done
+ for dup in "${dups[@]}"; do
+ [[ -n $dup ]] || continue
+ report $p "duplicate $t record: $dup"
+ done
+ done
+done
diff --git a/tests/shell/testcases/nft-f/dumps/0021priority_variable_0.nft b/tests/shell/testcases/chains/dumps/0031priority_variable_0.nft
index f4093097..f4093097 100644
--- a/tests/shell/testcases/nft-f/dumps/0021priority_variable_0.nft
+++ b/tests/shell/testcases/chains/dumps/0031priority_variable_0.nft
diff --git a/tests/shell/testcases/nft-f/dumps/0025policy_variable_0.nft b/tests/shell/testcases/chains/dumps/0035policy_variable_0.nft
index f4093097..f4093097 100644
--- a/tests/shell/testcases/nft-f/dumps/0025policy_variable_0.nft
+++ b/tests/shell/testcases/chains/dumps/0035policy_variable_0.nft
diff --git a/tests/shell/testcases/maps/dumps/typeof_maps_0.nft b/tests/shell/testcases/maps/dumps/typeof_maps_0.nft
index faa73cd1..438b9829 100644
--- a/tests/shell/testcases/maps/dumps/typeof_maps_0.nft
+++ b/tests/shell/testcases/maps/dumps/typeof_maps_0.nft
@@ -15,6 +15,10 @@ table inet t {
2.3.4.5 . 6.7.8.9 : 0x00000002 }
}
+ map m4 {
+ typeof iifname . ip protocol . th dport : verdict
+ }
+
chain c {
ct mark set osf name map @m1
meta mark set vlan id map @m2
diff --git a/tests/shell/testcases/maps/typeof_maps_0 b/tests/shell/testcases/maps/typeof_maps_0
index e1c4bba9..f024ebe0 100755
--- a/tests/shell/testcases/maps/typeof_maps_0
+++ b/tests/shell/testcases/maps/typeof_maps_0
@@ -22,6 +22,10 @@ EXPECTED="table inet t {
2.3.4.5 . 6.7.8.9 : 0x00000002 }
}
+ map m4 {
+ typeof iifname . ip protocol . th dport : verdict
+ }
+
chain c {
ct mark set osf name map @m1
ether type vlan meta mark set vlan id map @m2
diff --git a/tests/shell/testcases/nft-f/0024priority_0 b/tests/shell/testcases/nft-f/0024priority_0
new file mode 100755
index 00000000..586f5c3f
--- /dev/null
+++ b/tests/shell/testcases/nft-f/0024priority_0
@@ -0,0 +1,14 @@
+#!/bin/bash
+
+RULESET="
+table inet statelessnat {
+ chain prerouting {
+ type filter hook prerouting priority -100;
+ ip daddr set numgen inc mod 16 map { 0-7 : 10.0.1.1, 8- 15 : 10.0.1.2 }
+ }
+ chain postrouting {
+ type filter hook postrouting priority 100
+ }
+}"
+
+exec $NFT -f - <<< "$RULESET"
diff --git a/tests/shell/testcases/nft-f/0025empty_dynset_0 b/tests/shell/testcases/nft-f/0025empty_dynset_0
new file mode 100755
index 00000000..10c5cc1b
--- /dev/null
+++ b/tests/shell/testcases/nft-f/0025empty_dynset_0
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+RULESET="table ip foo {
+ set inflows {
+ type ipv4_addr . inet_service . ifname . ipv4_addr . inet_service
+ flags dynamic
+ elements = { 10.1.0.3 . 39466 . \"veth1\" . 10.3.0.99 . 5201 counter packets 0 bytes 0 }
+ }
+
+ set inflows6 {
+ type ipv6_addr . inet_service . ifname . ipv6_addr . inet_service
+ flags dynamic
+ }
+
+ set inflows_ratelimit {
+ type ipv4_addr . inet_service . ifname . ipv4_addr . inet_service
+ flags dynamic
+ elements = { 10.1.0.3 . 39466 . \"veth1\" . 10.3.0.99 . 5201 limit rate 1/second counter packets 0 bytes 0 }
+ }
+}"
+
+$NFT -f - <<< "$RULESET"
diff --git a/tests/shell/testcases/nft-f/dumps/0024priority_0.nft b/tests/shell/testcases/nft-f/dumps/0024priority_0.nft
new file mode 100644
index 00000000..cd7fc504
--- /dev/null
+++ b/tests/shell/testcases/nft-f/dumps/0024priority_0.nft
@@ -0,0 +1,10 @@
+table inet statelessnat {
+ chain prerouting {
+ type filter hook prerouting priority dstnat; policy accept;
+ ip daddr set numgen inc mod 16 map { 0-7 : 10.0.1.1, 8-15 : 10.0.1.2 }
+ }
+
+ chain postrouting {
+ type filter hook postrouting priority srcnat; policy accept;
+ }
+}
diff --git a/tests/shell/testcases/nft-f/dumps/0025empty_dynset_0.nft b/tests/shell/testcases/nft-f/dumps/0025empty_dynset_0.nft
new file mode 100644
index 00000000..2bb35592
--- /dev/null
+++ b/tests/shell/testcases/nft-f/dumps/0025empty_dynset_0.nft
@@ -0,0 +1,18 @@
+table ip foo {
+ set inflows {
+ type ipv4_addr . inet_service . ifname . ipv4_addr . inet_service
+ flags dynamic
+ elements = { 10.1.0.3 . 39466 . "veth1" . 10.3.0.99 . 5201 counter packets 0 bytes 0 }
+ }
+
+ set inflows6 {
+ type ipv6_addr . inet_service . ifname . ipv6_addr . inet_service
+ flags dynamic
+ }
+
+ set inflows_ratelimit {
+ type ipv4_addr . inet_service . ifname . ipv4_addr . inet_service
+ flags dynamic
+ elements = { 10.1.0.3 . 39466 . "veth1" . 10.3.0.99 . 5201 limit rate 1/second counter packets 0 bytes 0 }
+ }
+}
diff --git a/tests/shell/testcases/sets/0029named_ifname_dtype_0 b/tests/shell/testcases/sets/0029named_ifname_dtype_0
index 39b3c90c..2dbcd22b 100755
--- a/tests/shell/testcases/sets/0029named_ifname_dtype_0
+++ b/tests/shell/testcases/sets/0029named_ifname_dtype_0
@@ -13,12 +13,53 @@ EXPECTED="table inet t {
elements = { \"ssh\" . \"eth0\" }
}
+ set nv {
+ type ifname . mark
+ }
+
+ set z {
+ typeof ct zone
+ elements = { 1 }
+ }
+
+ set m {
+ typeof meta mark
+ elements = { 1 }
+ }
+
+ map cz {
+ typeof meta iifname : ct zone
+ elements = { \"veth4\" : 1 }
+ }
+
+ map cm {
+ typeof meta iifname : ct mark
+ elements = { \"veth4\" : 1 }
+ }
+
chain c {
iifname @s accept
oifname @s accept
tcp dport . meta iifname @sc accept
+ meta iifname . meta mark @nv accept
}
}"
set -e
$NFT -f - <<< "$EXPECTED"
+$NFT add element inet t s '{ "eth1" }'
+$NFT add element inet t s '{ "eth2", "eth3", "veth1" }'
+
+$NFT add element inet t sc '{ 80 . "eth0" }'
+$NFT add element inet t sc '{ 80 . "eth0" }' || true
+$NFT add element inet t sc '{ 80 . "eth1" }'
+$NFT add element inet t sc '{ 81 . "eth0" }'
+
+$NFT add element inet t nv '{ "eth0" . 1 }'
+$NFT add element inet t nv '{ "eth0" . 2 }'
+
+$NFT add element inet t z '{ 2, 3, 4, 5, 6 }'
+$NFT add element inet t cz '{ "eth0" : 1, "eth1" : 2 }'
+
+$NFT add element inet t m '{ 2, 3, 4, 5, 6 }'
+$NFT add element inet t cm '{ "eth0" : 1, "eth1" : 2 }'
diff --git a/tests/shell/testcases/sets/0056dynamic_limit_0 b/tests/shell/testcases/sets/0056dynamic_limit_0
new file mode 100755
index 00000000..21fa0bff
--- /dev/null
+++ b/tests/shell/testcases/sets/0056dynamic_limit_0
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+RULESET="table inet filter {
+ set ssh_meter {
+ type ipv4_addr
+ size 65535
+ flags dynamic,timeout
+ timeout 1m
+ elements = { 127.0.0.1 expires 52s44ms limit rate over 1/minute }
+ }
+
+ chain output {
+ type filter hook output priority filter; policy accept;
+ ip protocol icmp add @ssh_meter { ip saddr timeout 1m limit rate over 1/minute }
+ }
+}"
+
+set -e
+$NFT -f - <<< $EXPECTED
diff --git a/tests/shell/testcases/sets/0057set_create_fails_0 b/tests/shell/testcases/sets/0057set_create_fails_0
new file mode 100755
index 00000000..5f0149a3
--- /dev/null
+++ b/tests/shell/testcases/sets/0057set_create_fails_0
@@ -0,0 +1,18 @@
+#!/bin/bash
+
+RULESET="table inet filter {
+ set test {
+ type ipv4_addr
+ size 65535
+ elements = { 1.1.1.1 }
+ }
+}"
+
+$NFT -f - <<< $RULESET
+
+CMD="create element inet filter test { 1.1.1.1, 1.1.1.2, 1.1.1.3, 1.1.1.4, 1.1.1.5, 1.1.1.6, 1.1.1.7, 1.1.1.8, 1.1.1.9, 1.1.1.10, 1.1.1.11, 1.1.1.12, 1.1.1.13, 1.1.1.14, 1.1.1.15, 1.1.1.16, 1.1.1.17, 1.1.1.18, 1.1.1.19, 1.1.1.20, 1.1.1.21, 1.1.1.22, 1.1.1.23, 1.1.1.24, 1.1.1.25, 1.1.1.26, 1.1.1.27, 1.1.1.28, 1.1.1.29, 1.1.1.30, 1.1.1.31, 1.1.1.32, 1.1.1.33, 1.1.1.34, 1.1.1.35, 1.1.1.36, 1.1.1.37, 1.1.1.38, 1.1.1.39, 1.1.1.40, 1.1.1.41, 1.1.1.42, 1.1.1.43, 1.1.1.44, 1.1.1.45, 1.1.1.46, 1.1.1.47, 1.1.1.48, 1.1.1.49, 1.1.1.50, 1.1.1.51, 1.1.1.52, 1.1.1.53, 1.1.1.54, 1.1.1.55, 1.1.1.56, 1.1.1.57, 1.1.1.58, 1.1.1.59, 1.1.1.60, 1.1.1.61, 1.1.1.62, 1.1.1.63, 1.1.1.64, 1.1.1.65, 1.1.1.66, 1.1.1.67, 1.1.1.68, 1.1.1.69, 1.1.1.70, 1.1.1.71, 1.1.1.72, 1.1.1.73, 1.1.1.74, 1.1.1.75, 1.1.1.76, 1.1.1.77, 1.1.1.78, 1.1.1.79, 1.1.1.80, 1.1.1.81, 1.1.1.82, 1.1.1.83, 1.1.1.84, 1.1.1.85, 1.1.1.86, 1.1.1.87, 1.1.1.88, 1.1.1.89, 1.1.1.90, 1.1.1.91, 1.1.1.92, 1.1.1.93, 1.1.1.94, 1.1.1.95, 1.1.1.96, 1.1.1.97, 1.1.1.98, 1.1.1.99, 1.1.1.100, 1.1.1.101, 1.1.1.102, 1.1.1.103, 1.1.1.104, 1.1.1.105, 1.1.1.106, 1.1.1.107, 1.1.1.108, 1.1.1.109, 1.1.1.110, 1.1.1.111, 1.1.1.112, 1.1.1.113, 1.1.1.114, 1.1.1.115, 1.1.1.116, 1.1.1.117, 1.1.1.118, 1.1.1.119, 1.1.1.120, 1.1.1.121, 1.1.1.122, 1.1.1.123, 1.1.1.124, 1.1.1.125, 1.1.1.126, 1.1.1.127, 1.1.1.128, 1.1.1.129, 1.1.1.130, 1.1.1.131, 1.1.1.132, 1.1.1.133, 1.1.1.134, 1.1.1.135, 1.1.1.136, 1.1.1.137, 1.1.1.138, 1.1.1.139, 1.1.1.140, 1.1.1.141, 1.1.1.142, 1.1.1.143, 1.1.1.144, 1.1.1.145, 1.1.1.146, 1.1.1.147, 1.1.1.148, 1.1.1.149, 1.1.1.150, 1.1.1.151, 1.1.1.152, 1.1.1.153, 1.1.1.154, 1.1.1.155, 1.1.1.156, 1.1.1.157, 1.1.1.158, 1.1.1.159, 1.1.1.160, 1.1.1.161, 1.1.1.162, 1.1.1.163, 1.1.1.164, 1.1.1.165, 1.1.1.166, 1.1.1.167, 1.1.1.168, 1.1.1.169, 1.1.1.170, 1.1.1.171, 1.1.1.172, 1.1.1.173, 1.1.1.174, 1.1.1.175, 1.1.1.176, 1.1.1.177, 1.1.1.178, 1.1.1.179, 1.1.1.180, 1.1.1.181, 1.1.1.182, 1.1.1.183, 1.1.1.184, 1.1.1.185, 1.1.1.186, 1.1.1.187, 1.1.1.188, 1.1.1.189, 1.1.1.190, 1.1.1.191, 1.1.1.192, 1.1.1.193, 1.1.1.194, 1.1.1.195, 1.1.1.196, 1.1.1.197, 1.1.1.198, 1.1.1.199, 1.1.1.200, 1.1.1.201, 1.1.1.202, 1.1.1.203, 1.1.1.204, 1.1.1.205, 1.1.1.206, 1.1.1.207, 1.1.1.208, 1.1.1.209, 1.1.1.210, 1.1.1.211, 1.1.1.212, 1.1.1.213, 1.1.1.214, 1.1.1.215, 1.1.1.216, 1.1.1.217, 1.1.1.218, 1.1.1.219, 1.1.1.220, 1.1.1.221, 1.1.1.222, 1.1.1.223, 1.1.1.224, 1.1.1.225, 1.1.1.226, 1.1.1.227, 1.1.1.228, 1.1.1.229, 1.1.1.230, 1.1.1.231, 1.1.1.232, 1.1.1.233, 1.1.1.234, 1.1.1.235, 1.1.1.236, 1.1.1.237, 1.1.1.238, 1.1.1.239, 1.1.1.240, 1.1.1.241, 1.1.1.242, 1.1.1.243, 1.1.1.244, 1.1.1.245, 1.1.1.246, 1.1.1.247, 1.1.1.248, 1.1.1.249, 1.1.1.250, 1.1.1.251, 1.1.1.252, 1.1.1.253 }"
+
+# If this returns ENOSPC, then nft is sending a netlink message that is larger
+# than NFT_MNL_ACK_MAXSIZE. Make sure this returns EEXIST.
+$NFT -f - <<< $CMD 2>&1 >/dev/null | grep "File exists"
+[ "$?" -eq 0 ] && exit 0
diff --git a/tests/shell/testcases/sets/0058_setupdate_timeout_0 b/tests/shell/testcases/sets/0058_setupdate_timeout_0
new file mode 100755
index 00000000..52a658e1
--- /dev/null
+++ b/tests/shell/testcases/sets/0058_setupdate_timeout_0
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+RULESET="table inet filter {
+ set ssh_meter {
+ type ipv4_addr
+ size 65535
+ flags dynamic,timeout
+ timeout 30d
+ }
+
+ chain test {
+ add @ssh_meter { ip saddr timeout 30d }
+ }
+}"
+
+set -e
+$NFT -f - <<< $RULESET
diff --git a/tests/shell/testcases/sets/0059set_update_multistmt_0 b/tests/shell/testcases/sets/0059set_update_multistmt_0
new file mode 100755
index 00000000..107bfb87
--- /dev/null
+++ b/tests/shell/testcases/sets/0059set_update_multistmt_0
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+RULESET="table x {
+ set y {
+ type ipv4_addr
+ size 65535
+ flags dynamic,timeout
+ timeout 1h
+ }
+ chain z {
+ type filter hook output priority 0;
+ update @y { ip daddr limit rate 1/second counter }
+ }
+}"
+
+set -e
+$NFT -f - <<< $RULESET
diff --git a/tests/shell/testcases/sets/0060set_multistmt_0 b/tests/shell/testcases/sets/0060set_multistmt_0
new file mode 100755
index 00000000..6bd147c3
--- /dev/null
+++ b/tests/shell/testcases/sets/0060set_multistmt_0
@@ -0,0 +1,50 @@
+#!/bin/bash
+
+RULESET="table x {
+ set y {
+ type ipv4_addr
+ limit rate 1/second counter
+ elements = { 5.5.5.5 limit rate 1/second counter packets 0 bytes 0 }
+ }
+ chain y {
+ type filter hook output priority filter; policy accept;
+ ip daddr @y
+ }
+}"
+
+$NFT -f - <<< $RULESET
+# should work
+if [ $? -ne 0 ]
+then
+ exit 1
+fi
+
+# should work
+$NFT add element x y { 1.1.1.1 limit rate 1/second counter }
+if [ $? -ne 0 ]
+then
+ exit 1
+fi
+
+# should fail
+$NFT add element x y { 2.2.2.2 limit rate 1/second }
+if [ $? -eq 0 ]
+then
+ exit 1
+fi
+
+# should fail
+$NFT add element x y { 3.3.3.3 counter limit rate 1/second }
+if [ $? -eq 0 ]
+then
+ exit 1
+fi
+
+# should work
+$NFT add element x y { 4.4.4.4 }
+if [ $? -ne 0 ]
+then
+ exit 1
+fi
+
+exit 0
diff --git a/tests/shell/testcases/sets/dumps/0029named_ifname_dtype_0.nft b/tests/shell/testcases/sets/dumps/0029named_ifname_dtype_0.nft
index 23ff89bb..55cd4f26 100644
--- a/tests/shell/testcases/sets/dumps/0029named_ifname_dtype_0.nft
+++ b/tests/shell/testcases/sets/dumps/0029named_ifname_dtype_0.nft
@@ -1,17 +1,57 @@
table inet t {
set s {
type ifname
- elements = { "eth0" }
+ elements = { "eth0",
+ "eth1",
+ "eth2",
+ "eth3",
+ "veth1" }
}
set sc {
type inet_service . ifname
- elements = { 22 . "eth0" }
+ elements = { 22 . "eth0",
+ 80 . "eth0",
+ 81 . "eth0",
+ 80 . "eth1" }
+ }
+
+ set nv {
+ type ifname . mark
+ elements = { "eth0" . 0x00000001,
+ "eth0" . 0x00000002 }
+ }
+
+ set z {
+ typeof ct zone
+ elements = { 1, 2, 3, 4, 5,
+ 6 }
+ }
+
+ set m {
+ typeof meta mark
+ elements = { 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005,
+ 0x00000006 }
+ }
+
+ map cz {
+ typeof iifname : ct zone
+ elements = { "eth0" : 1,
+ "eth1" : 2,
+ "veth4" : 1 }
+ }
+
+ map cm {
+ typeof iifname : ct mark
+ elements = { "eth0" : 0x00000001,
+ "eth1" : 0x00000002,
+ "veth4" : 0x00000001 }
}
chain c {
iifname @s accept
oifname @s accept
tcp dport . iifname @sc accept
+ iifname . meta mark @nv accept
}
}
diff --git a/tests/shell/testcases/sets/dumps/0058_setupdate_timeout_0.nft b/tests/shell/testcases/sets/dumps/0058_setupdate_timeout_0.nft
new file mode 100644
index 00000000..873adc63
--- /dev/null
+++ b/tests/shell/testcases/sets/dumps/0058_setupdate_timeout_0.nft
@@ -0,0 +1,12 @@
+table inet filter {
+ set ssh_meter {
+ type ipv4_addr
+ size 65535
+ flags dynamic,timeout
+ timeout 30d
+ }
+
+ chain test {
+ add @ssh_meter { ip saddr timeout 30d }
+ }
+}
diff --git a/tests/shell/testcases/sets/dumps/0059set_update_multistmt_0.nft b/tests/shell/testcases/sets/dumps/0059set_update_multistmt_0.nft
new file mode 100644
index 00000000..1b0ffae4
--- /dev/null
+++ b/tests/shell/testcases/sets/dumps/0059set_update_multistmt_0.nft
@@ -0,0 +1,13 @@
+table ip x {
+ set y {
+ type ipv4_addr
+ size 65535
+ flags dynamic,timeout
+ timeout 1h
+ }
+
+ chain z {
+ type filter hook output priority filter; policy accept;
+ update @y { ip daddr limit rate 1/second counter }
+ }
+}
diff --git a/tests/shell/testcases/sets/dumps/0060set_multistmt_0.nft b/tests/shell/testcases/sets/dumps/0060set_multistmt_0.nft
new file mode 100644
index 00000000..f23db534
--- /dev/null
+++ b/tests/shell/testcases/sets/dumps/0060set_multistmt_0.nft
@@ -0,0 +1,13 @@
+table ip x {
+ set y {
+ type ipv4_addr
+ limit rate 1/second counter
+ elements = { 1.1.1.1 limit rate 1/second counter packets 0 bytes 0, 4.4.4.4 limit rate 1/second counter packets 0 bytes 0,
+ 5.5.5.5 limit rate 1/second counter packets 0 bytes 0 }
+ }
+
+ chain y {
+ type filter hook output priority filter; policy accept;
+ ip daddr @y
+ }
+}