summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFlorian Westphal <fw@strlen.de>2017-09-29 13:55:54 +0200
committerFlorian Westphal <fw@strlen.de>2017-09-29 13:55:54 +0200
commit54a0c5dc0f4db879ad2f44fc77bcd2568719be42 (patch)
tree5d5e17e0fca1c3cdd9fd582f17273705f8d6555f
parent28180991740e6942adfb12650ff2472d73e89387 (diff)
parent26589362c1a3a7c3f0fdb5e70e831bcb4077b0d1 (diff)
Merge branch 'ct_rt_syntax_06'
inet family (and others, e.g. bridge) lack context to figure out the layer 3 address type. examples: ct original saddr $addr rt nexthop $addr We can't use $addr, because it might be a set reference, e.g. ct original saddr @whitelist currently implemented workaround is to use 'meta nfproto' to provide the l3 context, e.g. meta nfproto ip rt nexthop 10.2.3.4 i.e. users need to fill dependency manually. Pablo suggested to instead specify ip saddr, ip6 saddr: ct original ip saddr $address and then let nft handle the dependency injection, these changes do this. Old syntax is preserved. Signed-off-by: Florian Westphal <fw@strlen.de> Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r--doc/nft.xml23
-rw-r--r--include/ct.h3
-rw-r--r--include/expression.h2
-rw-r--r--src/ct.c71
-rw-r--r--src/evaluate.c92
-rw-r--r--src/netlink_delinearize.c52
-rw-r--r--src/parser_bison.y42
-rw-r--r--src/rt.c15
-rw-r--r--tests/py/bridge/icmpX.t4
-rw-r--r--tests/py/inet/ct.t7
-rw-r--r--tests/py/inet/ct.t.payload4
-rw-r--r--tests/py/inet/icmpX.t4
-rw-r--r--tests/py/inet/rt.t10
-rw-r--r--tests/py/inet/rt.t.payload4
-rw-r--r--tests/py/ip/ct.t18
-rw-r--r--tests/py/ip/ct.t.payload16
-rw-r--r--tests/py/ip/rt.t3
-rw-r--r--tests/py/ip6/rt0.t2
18 files changed, 262 insertions, 110 deletions
diff --git a/doc/nft.xml b/doc/nft.xml
index 9d97a782..c0f42ddc 100644
--- a/doc/nft.xml
+++ b/doc/nft.xml
@@ -608,7 +608,6 @@ filter input iif $int_ifs accept
hybrid IPv4/IPv6 tables. The <literal>meta</literal> expression <literal>nfproto</literal>
keyword can be used to test which family (ipv4 or ipv6) context the packet is being processed in.
-
When no address family is specified, <literal>ip</literal> is used by default.
</para>
@@ -2905,8 +2904,8 @@ filter output rt classid 10
# IP family dependent rt expressions
ip filter output rt nexthop 192.168.0.1
ip6 filter output rt nexthop fd00::1
-inet filter meta nfproto ipv4 output rt nexthop 192.168.0.1
-inet filter meta nfproto ipv6 output rt nexthop fd00::1
+inet filter output rt ip nexthop 192.168.0.1
+inet filter output rt ip6 nexthop fd00::1
</programlisting>
</example>
</para>
@@ -4025,8 +4024,6 @@ ip6 filter input frag more-fragments 1 counter
<group choice="req">
<arg>l3proto</arg>
<arg>protocol</arg>
- <arg>saddr</arg>
- <arg>daddr</arg>
<arg>proto-src</arg>
<arg>proto-dst</arg>
<arg>bytes</arg>
@@ -4035,6 +4032,22 @@ ip6 filter input frag more-fragments 1 counter
<arg>zone</arg>
</group>
</cmdsynopsis>
+ <cmdsynopsis>
+ <command>ct</command>
+ <group choice="req">
+ <arg>original</arg>
+ <arg>reply</arg>
+ </group>
+ <group choice="req">
+ <arg>ip</arg>
+ <arg>ip6</arg>
+ </group>
+ <group choice="req">
+ <arg>saddr</arg>
+ <arg>daddr</arg>
+ </group>
+ </cmdsynopsis>
+
</para>
<para>
<table frame="all">
diff --git a/include/ct.h b/include/ct.h
index d9a11a3f..ec5d55d8 100644
--- a/include/ct.h
+++ b/include/ct.h
@@ -24,7 +24,8 @@ struct ct_template {
}
extern struct expr *ct_expr_alloc(const struct location *loc,
- enum nft_ct_keys key, int8_t direction);
+ enum nft_ct_keys key, int8_t direction,
+ uint8_t nfproto);
extern void ct_expr_update_type(struct proto_ctx *ctx, struct expr *expr);
extern struct stmt *notrack_stmt_alloc(const struct location *loc);
diff --git a/include/expression.h b/include/expression.h
index ce6b702a..215cbc98 100644
--- a/include/expression.h
+++ b/include/expression.h
@@ -300,7 +300,9 @@ struct expr {
struct {
/* EXPR_CT */
enum nft_ct_keys key;
+ enum proto_bases base;
int8_t direction;
+ uint8_t nfproto;
} ct;
struct {
/* EXPR_NUMGEN */
diff --git a/src/ct.c b/src/ct.c
index b2faf627..58b873e7 100644
--- a/src/ct.c
+++ b/src/ct.c
@@ -16,6 +16,8 @@
#include <inttypes.h>
#include <string.h>
+#include <netinet/ip.h>
+#include <linux/netfilter.h>
#include <linux/netfilter/nf_tables.h>
#include <linux/netfilter/nf_conntrack_common.h>
#include <linux/netfilter/nf_conntrack_tuple_common.h>
@@ -269,9 +271,11 @@ static const struct ct_template ct_templates[] = {
BYTEORDER_HOST_ENDIAN, 32),
};
-static void ct_print(enum nft_ct_keys key, int8_t dir, struct output_ctx *octx)
+static void ct_print(enum nft_ct_keys key, int8_t dir, uint8_t nfproto,
+ struct output_ctx *octx)
{
const struct symbolic_constant *s;
+ const struct proto_desc *desc;
nft_print(octx, "ct ");
if (dir < 0)
@@ -283,13 +287,25 @@ static void ct_print(enum nft_ct_keys key, int8_t dir, struct output_ctx *octx)
break;
}
}
+
+ switch (key) {
+ case NFT_CT_SRC: /* fallthrough */
+ case NFT_CT_DST:
+ desc = proto_find_upper(&proto_inet, nfproto);
+ if (desc)
+ printf("%s ", desc->name);
+ break;
+ default:
+ break;
+ }
+
done:
nft_print(octx, "%s", ct_templates[key].token);
}
static void ct_expr_print(const struct expr *expr, struct output_ctx *octx)
{
- ct_print(expr->ct.key, expr->ct.direction, octx);
+ ct_print(expr->ct.key, expr->ct.direction, expr->ct.nfproto, octx);
}
static bool ct_expr_cmp(const struct expr *e1, const struct expr *e2)
@@ -308,21 +324,21 @@ static void ct_expr_clone(struct expr *new, const struct expr *expr)
static void ct_expr_pctx_update(struct proto_ctx *ctx, const struct expr *expr)
{
const struct expr *left = expr->left, *right = expr->right;
- const struct proto_desc *base, *desc;
+ const struct proto_desc *base = NULL, *desc;
+ uint32_t nhproto;
assert(expr->op == OP_EQ);
- switch (left->ct.key) {
- case NFT_CT_PROTOCOL:
- base = ctx->protocol[PROTO_BASE_NETWORK_HDR].desc;
- desc = proto_find_upper(base, mpz_get_uint32(right->value));
+ nhproto = mpz_get_uint32(right->value);
- proto_ctx_update(ctx, PROTO_BASE_TRANSPORT_HDR,
- &expr->location, desc);
- break;
- default:
- break;
- }
+ base = ctx->protocol[left->ct.base].desc;
+ if (!base)
+ return;
+ desc = proto_find_upper(base, nhproto);
+ if (!desc)
+ return;
+
+ proto_ctx_update(ctx, left->ct.base + 1, &expr->location, desc);
}
static const struct expr_ops ct_expr_ops = {
@@ -335,7 +351,7 @@ static const struct expr_ops ct_expr_ops = {
};
struct expr *ct_expr_alloc(const struct location *loc, enum nft_ct_keys key,
- int8_t direction)
+ int8_t direction, uint8_t nfproto)
{
const struct ct_template *tmpl = &ct_templates[key];
struct expr *expr;
@@ -344,10 +360,24 @@ struct expr *ct_expr_alloc(const struct location *loc, enum nft_ct_keys key,
tmpl->byteorder, tmpl->len);
expr->ct.key = key;
expr->ct.direction = direction;
+ expr->ct.nfproto = nfproto;
switch (key) {
+ case NFT_CT_SRC:
+ case NFT_CT_DST:
+ expr->ct.base = PROTO_BASE_NETWORK_HDR;
+ break;
+ case NFT_CT_PROTO_SRC:
+ case NFT_CT_PROTO_DST:
+ expr->ct.base = PROTO_BASE_TRANSPORT_HDR;
+ break;
case NFT_CT_PROTOCOL:
expr->flags = EXPR_F_PROTOCOL;
+ expr->ct.base = PROTO_BASE_NETWORK_HDR;
+ break;
+ case NFT_CT_L3PROTOCOL:
+ expr->flags = EXPR_F_PROTOCOL;
+ expr->ct.base = PROTO_BASE_LL_HDR;
break;
default:
break;
@@ -360,20 +390,23 @@ void ct_expr_update_type(struct proto_ctx *ctx, struct expr *expr)
{
const struct proto_desc *desc;
+ desc = ctx->protocol[expr->ct.base].desc;
+
switch (expr->ct.key) {
case NFT_CT_SRC:
case NFT_CT_DST:
- desc = ctx->protocol[PROTO_BASE_NETWORK_HDR].desc;
- if (desc == &proto_ip)
+ if (desc == &proto_ip) {
expr->dtype = &ipaddr_type;
- else if (desc == &proto_ip6)
+ expr->ct.nfproto = NFPROTO_IPV4;
+ } else if (desc == &proto_ip6) {
expr->dtype = &ip6addr_type;
+ expr->ct.nfproto = NFPROTO_IPV6;
+ }
expr->len = expr->dtype->size;
break;
case NFT_CT_PROTO_SRC:
case NFT_CT_PROTO_DST:
- desc = ctx->protocol[PROTO_BASE_TRANSPORT_HDR].desc;
if (desc == NULL)
break;
expr->dtype = &inet_service_type;
@@ -385,7 +418,7 @@ void ct_expr_update_type(struct proto_ctx *ctx, struct expr *expr)
static void ct_stmt_print(const struct stmt *stmt, struct output_ctx *octx)
{
- ct_print(stmt->ct.key, stmt->ct.direction, octx);
+ ct_print(stmt->ct.key, stmt->ct.direction, 0, octx);
nft_print(octx, " set ");
expr_print(stmt->ct.expr, octx);
}
diff --git a/src/evaluate.c b/src/evaluate.c
index c796c3c3..ca9180b7 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -662,32 +662,28 @@ static int expr_evaluate_payload(struct eval_ctx *ctx, struct expr **exprp)
return 0;
}
-static int expr_error_base(struct list_head *msgs, const struct expr *e)
-{
- return expr_error(msgs, e,
- "meta nfproto ipv4 or ipv6 must be specified "
- "before %s expression", e->ops->name);
-}
-
/*
* RT expression: validate protocol dependencies.
*/
static int expr_evaluate_rt(struct eval_ctx *ctx, struct expr **expr)
{
- const struct proto_desc *base;
+ static const char emsg[] = "cannot determine ip protocol version, use \"ip nexthop\" or \"ip6 nexthop\" instead";
struct expr *rt = *expr;
rt_expr_update_type(&ctx->pctx, rt);
- base = ctx->pctx.protocol[PROTO_BASE_NETWORK_HDR].desc;
switch (rt->rt.key) {
case NFT_RT_NEXTHOP4:
- if (base != &proto_ip)
- return expr_error_base(ctx->msgs, rt);
+ if (rt->dtype != &ipaddr_type)
+ return expr_error(ctx->msgs, rt, "%s", emsg);
+ if (ctx->pctx.family == NFPROTO_IPV6)
+ return expr_error(ctx->msgs, rt, "%s nexthop will not match", "ip");
break;
case NFT_RT_NEXTHOP6:
- if (base != &proto_ip6)
- return expr_error_base(ctx->msgs, rt);
+ if (rt->dtype != &ip6addr_type)
+ return expr_error(ctx->msgs, rt, "%s", emsg);
+ if (ctx->pctx.family == NFPROTO_IPV4)
+ return expr_error(ctx->msgs, rt, "%s nexthop will not match", "ip6");
break;
default:
break;
@@ -696,27 +692,85 @@ static int expr_evaluate_rt(struct eval_ctx *ctx, struct expr **expr)
return expr_evaluate_primary(ctx, expr);
}
+static int ct_gen_nh_dependency(struct eval_ctx *ctx, struct expr *ct)
+{
+ const struct proto_desc *base, *base_now;
+ struct expr *left, *right, *dep;
+ struct stmt *nstmt = NULL;
+
+ base_now = ctx->pctx.protocol[PROTO_BASE_NETWORK_HDR].desc;
+
+ switch (ct->ct.nfproto) {
+ case NFPROTO_IPV4:
+ base = &proto_ip;
+ break;
+ case NFPROTO_IPV6:
+ base = &proto_ip6;
+ break;
+ default:
+ base = ctx->pctx.protocol[PROTO_BASE_NETWORK_HDR].desc;
+ if (base == &proto_ip)
+ ct->ct.nfproto = NFPROTO_IPV4;
+ else if (base == &proto_ip)
+ ct->ct.nfproto = NFPROTO_IPV6;
+
+ if (base)
+ break;
+
+ return expr_error(ctx->msgs, ct,
+ "cannot determine ip protocol version, use \"ip %1$caddr\" or \"ip6 %1$caddr\" instead",
+ ct->ct.key == NFT_CT_SRC ? 's' : 'd');
+ }
+
+ /* no additional dependency needed? */
+ if (base == base_now)
+ return 0;
+
+ if (base_now && base_now != base)
+ return expr_error(ctx->msgs, ct,
+ "conflicting dependencies: %s vs. %s\n",
+ base->name,
+ ctx->pctx.protocol[PROTO_BASE_NETWORK_HDR].desc->name);
+ switch (ctx->pctx.family) {
+ case NFPROTO_IPV4:
+ case NFPROTO_IPV6:
+ return 0;
+ }
+
+ left = ct_expr_alloc(&ct->location, NFT_CT_L3PROTOCOL, ct->ct.direction, ct->ct.nfproto);
+
+ right = constant_expr_alloc(&ct->location, left->dtype,
+ left->dtype->byteorder, left->len,
+ constant_data_ptr(ct->ct.nfproto, left->len));
+ dep = relational_expr_alloc(&ct->location, OP_EQ, left, right);
+
+ left->ops->pctx_update(&ctx->pctx, dep);
+
+ nstmt = expr_stmt_alloc(&dep->location, dep);
+
+ list_add_tail(&nstmt->list, &ctx->stmt->list);
+ return 0;
+}
+
/*
* CT expression: update the protocol dependant types bases on the protocol
* context.
*/
static int expr_evaluate_ct(struct eval_ctx *ctx, struct expr **expr)
{
- const struct proto_desc *base;
struct expr *ct = *expr;
- ct_expr_update_type(&ctx->pctx, ct);
-
- base = ctx->pctx.protocol[PROTO_BASE_NETWORK_HDR].desc;
switch (ct->ct.key) {
case NFT_CT_SRC:
case NFT_CT_DST:
- if (base != &proto_ip && base != &proto_ip6)
- return expr_error_base(ctx->msgs, ct);
+ ct_gen_nh_dependency(ctx, ct);
+ break;
default:
break;
}
+ ct_expr_update_type(&ctx->pctx, ct);
+
return expr_evaluate_primary(ctx, expr);
}
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
index 42206ebc..44328879 100644
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -716,7 +716,7 @@ static void netlink_parse_ct_expr(struct netlink_parse_ctx *ctx,
dir = nftnl_expr_get_u8(nle, NFTNL_EXPR_CT_DIR);
key = nftnl_expr_get_u32(nle, NFTNL_EXPR_CT_KEY);
- expr = ct_expr_alloc(loc, key, dir);
+ expr = ct_expr_alloc(loc, key, dir, NFPROTO_UNSPEC);
dreg = netlink_parse_register(nle, NFTNL_EXPR_CT_DREG);
netlink_set_register(ctx, dreg, expr);
@@ -1385,12 +1385,29 @@ static void payload_match_postprocess(struct rule_pp_ctx *ctx,
}
}
-static void ct_meta_common_postprocess(const struct expr *expr)
+static void ct_meta_common_postprocess(struct rule_pp_ctx *ctx,
+ const struct expr *expr,
+ enum proto_bases base)
{
const struct expr *left = expr->left;
struct expr *right = expr->right;
switch (expr->op) {
+ case OP_EQ:
+ if (expr->right->ops->type == EXPR_RANGE)
+ break;
+
+ expr->left->ops->pctx_update(&ctx->pctx, expr);
+
+ if (ctx->pdctx.pbase == PROTO_BASE_INVALID &&
+ left->flags & EXPR_F_PROTOCOL) {
+ payload_dependency_store(&ctx->pdctx, ctx->stmt, base);
+ } else if (ctx->pdctx.pbase < PROTO_BASE_TRANSPORT_HDR) {
+ __payload_dependency_kill(&ctx->pdctx, base);
+ if (left->flags & EXPR_F_PROTOCOL)
+ payload_dependency_store(&ctx->pdctx, ctx->stmt, base);
+ }
+ break;
case OP_NEQ:
if (right->ops->type != EXPR_SET && right->ops->type != EXPR_SET_REF)
break;
@@ -1406,40 +1423,17 @@ static void ct_meta_common_postprocess(const struct expr *expr)
static void meta_match_postprocess(struct rule_pp_ctx *ctx,
const struct expr *expr)
{
- struct expr *left = expr->left;
-
- switch (expr->op) {
- case OP_EQ:
- if (expr->right->ops->type == EXPR_RANGE)
- break;
-
- expr->left->ops->pctx_update(&ctx->pctx, expr);
+ const struct expr *left = expr->left;
- if (ctx->pdctx.pbase == PROTO_BASE_INVALID &&
- left->flags & EXPR_F_PROTOCOL)
- payload_dependency_store(&ctx->pdctx, ctx->stmt,
- left->meta.base);
- break;
- default:
- ct_meta_common_postprocess(expr);
- break;
- }
+ ct_meta_common_postprocess(ctx, expr, left->meta.base);
}
static void ct_match_postprocess(struct rule_pp_ctx *ctx,
const struct expr *expr)
{
- switch (expr->op) {
- case OP_EQ:
- if (expr->right->ops->type == EXPR_RANGE)
- break;
+ const struct expr *left = expr->left;
- expr->left->ops->pctx_update(&ctx->pctx, expr);
- break;
- default:
- ct_meta_common_postprocess(expr);
- break;
- }
+ ct_meta_common_postprocess(ctx, expr, left->ct.base);
}
/* Convert a bitmask to a prefix length */
diff --git a/src/parser_bison.y b/src/parser_bison.y
index 75a77358..f996d9d9 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -665,11 +665,11 @@ static void location_update(struct location *loc, struct location *rhs, int n)
%type <expr> rt_expr
%destructor { expr_free($$); } rt_expr
-%type <val> rt_key
+%type <val> rt_key_proto rt_key
%type <expr> ct_expr
%destructor { expr_free($$); } ct_expr
-%type <val> ct_key ct_dir ct_key_dir_optional ct_key_dir
+%type <val> ct_key ct_dir ct_key_dir_optional ct_key_dir ct_key_proto ct_key_proto_field
%type <expr> fib_expr
%destructor { expr_free($$); } fib_expr
@@ -3246,10 +3246,32 @@ hash_expr : JHASH expr MOD NUM SEED NUM offset_opt
}
;
+rt_key_proto : IP { $$ = NFPROTO_IPV4; }
+ | IP6 { $$ = NFPROTO_IPV6; }
+ ;
+
rt_expr : RT rt_key
{
$$ = rt_expr_alloc(&@$, $2, true);
}
+ | RT rt_key_proto rt_key
+ {
+ enum nft_rt_keys rtk = $3;
+
+ switch ($2) {
+ case NFPROTO_IPV4:
+ break;
+ case NFPROTO_IPV6:
+ if ($3 == NFT_RT_NEXTHOP4)
+ rtk = NFT_RT_NEXTHOP6;
+ break;
+ default:
+ YYERROR;
+ break;
+ }
+
+ $$ = rt_expr_alloc(&@$, rtk, false);
+ }
;
rt_key : CLASSID { $$ = NFT_RT_CLASSID; }
@@ -3259,11 +3281,15 @@ rt_key : CLASSID { $$ = NFT_RT_CLASSID; }
ct_expr : CT ct_key
{
- $$ = ct_expr_alloc(&@$, $2, -1);
+ $$ = ct_expr_alloc(&@$, $2, -1, NFPROTO_UNSPEC);
}
| CT ct_dir ct_key_dir
{
- $$ = ct_expr_alloc(&@$, $3, $2);
+ $$ = ct_expr_alloc(&@$, $3, $2, NFPROTO_UNSPEC);
+ }
+ | CT ct_dir ct_key_proto ct_key_proto_field
+ {
+ $$ = ct_expr_alloc(&@$, $4, $2, $3);
}
;
@@ -3297,6 +3323,14 @@ ct_key_dir : SADDR { $$ = NFT_CT_SRC; }
| ct_key_dir_optional
;
+ct_key_proto : IP { $$ = NFPROTO_IPV4; }
+ | IP6 { $$ = NFPROTO_IPV6; }
+ ;
+
+ct_key_proto_field : SADDR { $$ = NFT_CT_SRC; }
+ | DADDR { $$ = NFT_CT_DST; }
+ ;
+
ct_key_dir_optional : BYTES { $$ = NFT_CT_BYTES; }
| PACKETS { $$ = NFT_CT_PKTS; }
| AVGPKT { $$ = NFT_CT_AVGPKT; }
diff --git a/src/rt.c b/src/rt.c
index 9ad9e398..041dbc2f 100644
--- a/src/rt.c
+++ b/src/rt.c
@@ -82,7 +82,20 @@ static const struct rt_template rt_templates[] = {
static void rt_expr_print(const struct expr *expr, struct output_ctx *octx)
{
- nft_print(octx, "rt %s", rt_templates[expr->rt.key].token);
+ const char *ip = "";
+
+ switch (expr->rt.key) {
+ case NFT_RT_NEXTHOP4:
+ ip = "ip ";
+ break;
+ case NFT_RT_NEXTHOP6:
+ ip = "ip6 ";
+ break;
+ default:
+ break;
+ }
+
+ nft_print(octx, "rt %s%s", ip, rt_templates[expr->rt.key].token);
}
static bool rt_expr_cmp(const struct expr *e1, const struct expr *e2)
diff --git a/tests/py/bridge/icmpX.t b/tests/py/bridge/icmpX.t
index 0a1019c3..8c0a5979 100644
--- a/tests/py/bridge/icmpX.t
+++ b/tests/py/bridge/icmpX.t
@@ -3,6 +3,6 @@
*bridge;test-bridge;input
ip protocol icmp icmp type echo-request;ok;icmp type echo-request
-icmp type echo-request;ok;ether type ip meta l4proto 1 icmp type echo-request
+icmp type echo-request;ok
ip6 nexthdr icmpv6 icmpv6 type echo-request;ok;icmpv6 type echo-request
-icmpv6 type echo-request;ok;ether type ip6 meta l4proto 58 icmpv6 type echo-request
+icmpv6 type echo-request;ok
diff --git a/tests/py/inet/ct.t b/tests/py/inet/ct.t
index c56c3bc8..1a656aa4 100644
--- a/tests/py/inet/ct.t
+++ b/tests/py/inet/ct.t
@@ -3,8 +3,11 @@
*inet;test-inet;input
-meta nfproto ipv4 ct original saddr 1.2.3.4;ok
-meta nfproto ipv6 ct original saddr ::1;ok
+meta nfproto ipv4 ct original saddr 1.2.3.4;ok;ct original ip saddr 1.2.3.4
+ct original ip6 saddr ::1;ok
# missing protocol context
ct original saddr ::1;fail
+
+# wrong protocol context
+ct original ip saddr ::1;fail
diff --git a/tests/py/inet/ct.t.payload b/tests/py/inet/ct.t.payload
index 21c74581..97128ecc 100644
--- a/tests/py/inet/ct.t.payload
+++ b/tests/py/inet/ct.t.payload
@@ -5,9 +5,9 @@ ip test-ip4 output
[ ct load src => reg 1 , dir original ]
[ cmp eq reg 1 0x04030201 ]
-# meta nfproto ipv6 ct original saddr ::1
+# ct original ip6 saddr ::1
inet test-inet input
- [ meta load nfproto => reg 1 ]
+ [ ct load l3protocol => reg 1 , dir original ]
[ cmp eq reg 1 0x0000000a ]
[ ct load src => reg 1 , dir original ]
[ cmp eq reg 1 0x00000000 0x00000000 0x00000000 0x01000000 ]
diff --git a/tests/py/inet/icmpX.t b/tests/py/inet/icmpX.t
index 7617e701..1b467a18 100644
--- a/tests/py/inet/icmpX.t
+++ b/tests/py/inet/icmpX.t
@@ -3,6 +3,6 @@
*inet;test-inet;input
ip protocol icmp icmp type echo-request;ok;icmp type echo-request
-icmp type echo-request;ok;meta nfproto ipv4 meta l4proto 1 icmp type echo-request
+icmp type echo-request;ok
ip6 nexthdr icmpv6 icmpv6 type echo-request;ok;icmpv6 type echo-request
-icmpv6 type echo-request;ok;meta nfproto ipv6 meta l4proto 58 icmpv6 type echo-request
+icmpv6 type echo-request;ok
diff --git a/tests/py/inet/rt.t b/tests/py/inet/rt.t
index 9543738b..23608ab2 100644
--- a/tests/py/inet/rt.t
+++ b/tests/py/inet/rt.t
@@ -4,7 +4,13 @@
rt nexthop 192.168.0.1;fail
rt nexthop fd00::1;fail
-meta nfproto ipv4 rt nexthop 192.168.0.1;ok
-meta nfproto ipv6 rt nexthop fd00::1;ok
+
+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 fd00::1;fail
+# wrong context
+rt ip nexthop fd00::1;fail
tcp option maxseg size set rt mtu;ok
diff --git a/tests/py/inet/rt.t.payload b/tests/py/inet/rt.t.payload
index 928e0095..84dea12c 100644
--- a/tests/py/inet/rt.t.payload
+++ b/tests/py/inet/rt.t.payload
@@ -5,10 +5,8 @@ inet test-inet output
[ rt load nexthop4 => reg 1 ]
[ cmp eq reg 1 0x0100a8c0 ]
-# meta nfproto ipv6 rt nexthop fd00::1
+# rt ip6 nexthop fd00::1
inet test-inet output
- [ meta load nfproto => reg 1 ]
- [ cmp eq reg 1 0x0000000a ]
[ rt load nexthop6 => reg 1 ]
[ cmp eq reg 1 0x000000fd 0x00000000 0x00000000 0x01000000 ]
diff --git a/tests/py/ip/ct.t b/tests/py/ip/ct.t
index d0f16c51..d3247f79 100644
--- a/tests/py/ip/ct.t
+++ b/tests/py/ip/ct.t
@@ -2,16 +2,16 @@
*ip;test-ip4;output
-ct original saddr 192.168.0.1;ok
-ct reply saddr 192.168.0.1;ok
-ct original daddr 192.168.0.1;ok
-ct reply daddr 192.168.0.1;ok
+ct original ip saddr 192.168.0.1;ok
+ct reply ip saddr 192.168.0.1;ok
+ct original ip daddr 192.168.0.1;ok
+ct reply ip daddr 192.168.0.1;ok
# same, but with a netmask
-ct original saddr 192.168.1.0/24;ok
-ct reply saddr 192.168.1.0/24;ok
-ct original daddr 192.168.1.0/24;ok
-ct reply daddr 192.168.1.0/24;ok
+ct original ip saddr 192.168.1.0/24;ok
+ct reply ip saddr 192.168.1.0/24;ok
+ct original ip daddr 192.168.1.0/24;ok
+ct reply ip daddr 192.168.1.0/24;ok
ct l3proto ipv4;ok
ct l3proto foobar;fail
@@ -20,4 +20,4 @@ ct protocol 6 ct original proto-dst 22;ok
ct original protocol 17 ct reply proto-src 53;ok;ct protocol 17 ct reply proto-src 53
# wrong address family
-ct reply daddr dead::beef;fail
+ct reply ip daddr dead::beef;fail
diff --git a/tests/py/ip/ct.t.payload b/tests/py/ip/ct.t.payload
index 56633a24..b7cd130d 100644
--- a/tests/py/ip/ct.t.payload
+++ b/tests/py/ip/ct.t.payload
@@ -1,42 +1,42 @@
-# ct original saddr 192.168.0.1
+# ct original ip saddr 192.168.0.1
ip test-ip4 output
[ ct load src => reg 1 , dir original ]
[ cmp eq reg 1 0x0100a8c0 ]
-# ct reply saddr 192.168.0.1
+# ct reply ip saddr 192.168.0.1
ip test-ip4 output
[ ct load src => reg 1 , dir reply ]
[ cmp eq reg 1 0x0100a8c0 ]
-# ct original daddr 192.168.0.1
+# ct original ip daddr 192.168.0.1
ip test-ip4 output
[ ct load dst => reg 1 , dir original ]
[ cmp eq reg 1 0x0100a8c0 ]
-# ct reply daddr 192.168.0.1
+# ct reply ip daddr 192.168.0.1
ip test-ip4 output
[ ct load dst => reg 1 , dir reply ]
[ cmp eq reg 1 0x0100a8c0 ]
-# ct original saddr 192.168.1.0/24
+# ct original ip saddr 192.168.1.0/24
ip test-ip4 output
[ ct load src => reg 1 , dir original ]
[ bitwise reg 1 = (reg=1 & 0x00ffffff ) ^ 0x00000000 ]
[ cmp eq reg 1 0x0001a8c0 ]
-# ct reply saddr 192.168.1.0/24
+# ct reply ip saddr 192.168.1.0/24
ip test-ip4 output
[ ct load src => reg 1 , dir reply ]
[ bitwise reg 1 = (reg=1 & 0x00ffffff ) ^ 0x00000000 ]
[ cmp eq reg 1 0x0001a8c0 ]
-# ct original daddr 192.168.1.0/24
+# ct original ip daddr 192.168.1.0/24
ip test-ip4 output
[ ct load dst => reg 1 , dir original ]
[ bitwise reg 1 = (reg=1 & 0x00ffffff ) ^ 0x00000000 ]
[ cmp eq reg 1 0x0001a8c0 ]
-# ct reply daddr 192.168.1.0/24
+# ct reply ip daddr 192.168.1.0/24
ip test-ip4 output
[ ct load dst => reg 1 , dir reply ]
[ bitwise reg 1 = (reg=1 & 0x00ffffff ) ^ 0x00000000 ]
diff --git a/tests/py/ip/rt.t b/tests/py/ip/rt.t
index 99750c5d..986bf341 100644
--- a/tests/py/ip/rt.t
+++ b/tests/py/ip/rt.t
@@ -2,5 +2,6 @@
*ip;test-ip4;output
-rt nexthop 192.168.0.1;ok
+rt nexthop 192.168.0.1;ok;rt ip nexthop 192.168.0.1
rt nexthop fd00::1;fail
+rt ip6 nexthop fd00::1;fail
diff --git a/tests/py/ip6/rt0.t b/tests/py/ip6/rt0.t
index 92614de3..1d50a89c 100644
--- a/tests/py/ip6/rt0.t
+++ b/tests/py/ip6/rt0.t
@@ -3,4 +3,4 @@
*ip6;test-ip6;output
rt nexthop 192.168.0.1;fail
-rt nexthop fd00::1;ok
+rt nexthop fd00::1;ok;rt ip6 nexthop fd00::1