summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/ct.h3
-rw-r--r--src/ct.c21
-rw-r--r--src/evaluate.c25
-rw-r--r--src/json.c13
-rw-r--r--src/netlink_delinearize.c2
-rw-r--r--src/parser_bison.y14
-rw-r--r--src/parser_json.c12
-rw-r--r--tests/py/any/ct.t4
-rw-r--r--tests/py/inet/ct.t.json3
-rw-r--r--tests/py/inet/ct.t.json.output1
-rw-r--r--tests/py/inet/ct.t.payload5
-rw-r--r--tests/py/ip/ct.t.json24
-rw-r--r--tests/py/ip/ct.t.payload16
13 files changed, 80 insertions, 63 deletions
diff --git a/include/ct.h b/include/ct.h
index 4c5bd804..063f8cdf 100644
--- a/include/ct.h
+++ b/include/ct.h
@@ -26,8 +26,7 @@ extern const struct ct_template ct_templates[__NFT_CT_MAX];
}
extern struct expr *ct_expr_alloc(const struct location *loc,
- enum nft_ct_keys key, int8_t direction,
- uint8_t nfproto);
+ enum nft_ct_keys key, int8_t direction);
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/src/ct.c b/src/ct.c
index 72346cd5..4f7807de 100644
--- a/src/ct.c
+++ b/src/ct.c
@@ -291,6 +291,14 @@ const struct ct_template ct_templates[__NFT_CT_MAX] = {
BYTEORDER_HOST_ENDIAN, 16),
[NFT_CT_EVENTMASK] = CT_TEMPLATE("event", &ct_event_type,
BYTEORDER_HOST_ENDIAN, 32),
+ [NFT_CT_SRC_IP] = CT_TEMPLATE("ip saddr", &ipaddr_type,
+ BYTEORDER_BIG_ENDIAN, 0),
+ [NFT_CT_DST_IP] = CT_TEMPLATE("ip daddr", &ipaddr_type,
+ BYTEORDER_BIG_ENDIAN, 0),
+ [NFT_CT_SRC_IP6] = CT_TEMPLATE("ip6 saddr", &ip6addr_type,
+ BYTEORDER_BIG_ENDIAN, 0),
+ [NFT_CT_DST_IP6] = CT_TEMPLATE("ip6 daddr", &ip6addr_type,
+ BYTEORDER_BIG_ENDIAN, 0),
};
static void ct_print(enum nft_ct_keys key, int8_t dir, uint8_t nfproto,
@@ -368,7 +376,7 @@ const struct expr_ops ct_expr_ops = {
};
struct expr *ct_expr_alloc(const struct location *loc, enum nft_ct_keys key,
- int8_t direction, uint8_t nfproto)
+ int8_t direction)
{
const struct ct_template *tmpl = &ct_templates[key];
struct expr *expr;
@@ -377,7 +385,6 @@ 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:
@@ -428,6 +435,16 @@ void ct_expr_update_type(struct proto_ctx *ctx, struct expr *expr)
break;
datatype_set(expr, &inet_service_type);
break;
+ case NFT_CT_SRC_IP:
+ case NFT_CT_DST_IP:
+ expr->dtype = &ipaddr_type;
+ expr->len = expr->dtype->size;
+ break;
+ case NFT_CT_SRC_IP6:
+ case NFT_CT_DST_IP6:
+ expr->dtype = &ip6addr_type;
+ expr->len = expr->dtype->size;
+ break;
default:
break;
}
diff --git a/src/evaluate.c b/src/evaluate.c
index dfdd3c24..19c2d4c6 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -782,7 +782,7 @@ static int ct_gen_nh_dependency(struct eval_ctx *ctx, struct expr *ct)
return 0;
}
- left = ct_expr_alloc(&ct->location, NFT_CT_L3PROTOCOL, ct->ct.direction, ct->ct.nfproto);
+ left = ct_expr_alloc(&ct->location, NFT_CT_L3PROTOCOL, ct->ct.direction);
right = constant_expr_alloc(&ct->location, left->dtype,
left->dtype->byteorder, left->len,
@@ -803,13 +803,30 @@ static int ct_gen_nh_dependency(struct eval_ctx *ctx, struct expr *ct)
*/
static int expr_evaluate_ct(struct eval_ctx *ctx, struct expr **expr)
{
+ const struct proto_desc *base, *error;
struct expr *ct = *expr;
+ base = ctx->pctx.protocol[PROTO_BASE_NETWORK_HDR].desc;
+
switch (ct->ct.key) {
case NFT_CT_SRC:
case NFT_CT_DST:
ct_gen_nh_dependency(ctx, ct);
break;
+ case NFT_CT_SRC_IP:
+ case NFT_CT_DST_IP:
+ if (base == &proto_ip6) {
+ error = &proto_ip;
+ goto err_conflict;
+ }
+ break;
+ case NFT_CT_SRC_IP6:
+ case NFT_CT_DST_IP6:
+ if (base == &proto_ip) {
+ error = &proto_ip6;
+ goto err_conflict;
+ }
+ break;
default:
break;
}
@@ -817,6 +834,12 @@ static int expr_evaluate_ct(struct eval_ctx *ctx, struct expr **expr)
ct_expr_update_type(&ctx->pctx, ct);
return expr_evaluate_primary(ctx, expr);
+
+err_conflict:
+ return stmt_binary_error(ctx, ct,
+ &ctx->pctx.protocol[PROTO_BASE_NETWORK_HDR],
+ "conflicting protocols specified: %s vs. %s",
+ base->name, error->name);
}
/*
diff --git a/src/json.c b/src/json.c
index e0127c57..4e646842 100644
--- a/src/json.c
+++ b/src/json.c
@@ -485,7 +485,6 @@ json_t *ct_expr_json(const struct expr *expr, struct output_ctx *octx)
{
const char *dirstr = ct_dir2str(expr->ct.direction);
enum nft_ct_keys key = expr->ct.key;
- const struct proto_desc *desc;
json_t *root;
root = json_pack("{s:s}", "key", ct_templates[key].token);
@@ -495,18 +494,6 @@ json_t *ct_expr_json(const struct expr *expr, struct output_ctx *octx)
if (dirstr)
json_object_set_new(root, "dir", json_string(dirstr));
-
- switch (key) {
- case NFT_CT_SRC:
- case NFT_CT_DST:
- desc = proto_find_upper(&proto_inet, expr->ct.nfproto);
- if (desc)
- json_object_set_new(root, "family",
- json_string(desc->name));
- break;
- default:
- break;
- }
out:
return json_pack("{s:o}", "ct", root);
}
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
index a4044f0c..1dd3ffd1 100644
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -788,7 +788,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, NFPROTO_UNSPEC);
+ expr = ct_expr_alloc(loc, key, dir);
dreg = netlink_parse_register(nle, NFTNL_EXPR_CT_DREG);
netlink_set_register(ctx, dreg, expr);
diff --git a/src/parser_bison.y b/src/parser_bison.y
index 1c0b60cf..670e91f5 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -4060,15 +4060,15 @@ rt_key : CLASSID { $$ = NFT_RT_CLASSID; }
ct_expr : CT ct_key
{
- $$ = ct_expr_alloc(&@$, $2, -1, NFPROTO_UNSPEC);
+ $$ = ct_expr_alloc(&@$, $2, -1);
}
| CT ct_dir ct_key_dir
{
- $$ = ct_expr_alloc(&@$, $3, $2, NFPROTO_UNSPEC);
+ $$ = ct_expr_alloc(&@$, $3, $2);
}
- | CT ct_dir nf_key_proto ct_key_proto_field
+ | CT ct_dir ct_key_proto_field
{
- $$ = ct_expr_alloc(&@$, $4, $2, $3);
+ $$ = ct_expr_alloc(&@$, $3, $2);
}
;
@@ -4102,8 +4102,10 @@ ct_key_dir : SADDR { $$ = NFT_CT_SRC; }
| ct_key_dir_optional
;
-ct_key_proto_field : SADDR { $$ = NFT_CT_SRC; }
- | DADDR { $$ = NFT_CT_DST; }
+ct_key_proto_field : IP SADDR { $$ = NFT_CT_SRC_IP; }
+ | IP DADDR { $$ = NFT_CT_DST_IP; }
+ | IP6 SADDR { $$ = NFT_CT_SRC_IP6; }
+ | IP6 DADDR { $$ = NFT_CT_DST_IP6; }
;
ct_key_dir_optional : BYTES { $$ = NFT_CT_BYTES; }
diff --git a/src/parser_json.c b/src/parser_json.c
index af7701fc..30b17173 100644
--- a/src/parser_json.c
+++ b/src/parser_json.c
@@ -714,6 +714,10 @@ static bool ct_key_is_dir(enum nft_ct_keys key)
NFT_CT_BYTES,
NFT_CT_AVGPKT,
NFT_CT_ZONE,
+ NFT_CT_SRC_IP,
+ NFT_CT_DST_IP,
+ NFT_CT_SRC_IP6,
+ NFT_CT_DST_IP6,
};
unsigned int i;
@@ -727,9 +731,9 @@ static bool ct_key_is_dir(enum nft_ct_keys key)
static struct expr *json_parse_ct_expr(struct json_ctx *ctx,
const char *type, json_t *root)
{
+ int dirval = -1, keyval = -1;
const char *key, *dir;
unsigned int i;
- int dirval = -1, familyval, keyval = -1;
if (json_unpack_err(ctx, root, "{s:s}", "key", &key))
return NULL;
@@ -746,10 +750,6 @@ static struct expr *json_parse_ct_expr(struct json_ctx *ctx,
return NULL;
}
- familyval = json_parse_family(ctx, root);
- if (familyval < 0)
- return NULL;
-
if (!json_unpack(root, "{s:s}", "dir", &dir)) {
if (!strcmp(dir, "original")) {
dirval = IP_CT_DIR_ORIGINAL;
@@ -766,7 +766,7 @@ static struct expr *json_parse_ct_expr(struct json_ctx *ctx,
}
}
- return ct_expr_alloc(int_loc, keyval, dirval, familyval);
+ return ct_expr_alloc(int_loc, keyval, dirval);
}
static struct expr *json_parse_numgen_expr(struct json_ctx *ctx,
diff --git a/tests/py/any/ct.t b/tests/py/any/ct.t
index 81d937d9..267eca1a 100644
--- a/tests/py/any/ct.t
+++ b/tests/py/any/ct.t
@@ -97,10 +97,10 @@ ct both bytes gt 1;fail
ct bytes original reply;fail
# missing direction
-ct saddr 1.2.3.4;fail
+ct ip saddr 1.2.3.4;fail
# wrong base (ip6 but ipv4 address given)
-meta nfproto ipv6 ct original saddr 1.2.3.4;fail
+meta nfproto ipv6 ct original ip saddr 1.2.3.4;fail
# direction, but must be used without
ct original mark 42;fail
diff --git a/tests/py/inet/ct.t.json b/tests/py/inet/ct.t.json
index 02bb2d27..d0c26aef 100644
--- a/tests/py/inet/ct.t.json
+++ b/tests/py/inet/ct.t.json
@@ -30,8 +30,7 @@
"left": {
"ct": {
"dir": "original",
- "family": "ip6",
- "key": "saddr"
+ "key": "ip6 saddr"
}
},
"op": "==",
diff --git a/tests/py/inet/ct.t.json.output b/tests/py/inet/ct.t.json.output
index 8b71519e..74c436a3 100644
--- a/tests/py/inet/ct.t.json.output
+++ b/tests/py/inet/ct.t.json.output
@@ -5,7 +5,6 @@
"left": {
"ct": {
"dir": "original",
- "family": "ip",
"key": "saddr"
}
},
diff --git a/tests/py/inet/ct.t.payload b/tests/py/inet/ct.t.payload
index 97128ecc..83146869 100644
--- a/tests/py/inet/ct.t.payload
+++ b/tests/py/inet/ct.t.payload
@@ -7,7 +7,6 @@ ip test-ip4 output
# ct original ip6 saddr ::1
inet test-inet input
- [ ct load l3protocol => reg 1 , dir original ]
- [ cmp eq reg 1 0x0000000a ]
- [ ct load src => reg 1 , dir original ]
+ [ ct load src_ip6 => reg 1 , dir original ]
[ cmp eq reg 1 0x00000000 0x00000000 0x00000000 0x01000000 ]
+
diff --git a/tests/py/ip/ct.t.json b/tests/py/ip/ct.t.json
index cc3ab692..881cd4c9 100644
--- a/tests/py/ip/ct.t.json
+++ b/tests/py/ip/ct.t.json
@@ -5,8 +5,7 @@
"left": {
"ct": {
"dir": "original",
- "family": "ip",
- "key": "saddr"
+ "key": "ip saddr"
}
},
"op": "==",
@@ -22,8 +21,7 @@
"left": {
"ct": {
"dir": "reply",
- "family": "ip",
- "key": "saddr"
+ "key": "ip saddr"
}
},
"op": "==",
@@ -39,8 +37,7 @@
"left": {
"ct": {
"dir": "original",
- "family": "ip",
- "key": "daddr"
+ "key": "ip daddr"
}
},
"op": "==",
@@ -56,8 +53,7 @@
"left": {
"ct": {
"dir": "reply",
- "family": "ip",
- "key": "daddr"
+ "key": "ip daddr"
}
},
"op": "==",
@@ -73,8 +69,7 @@
"left": {
"ct": {
"dir": "original",
- "family": "ip",
- "key": "saddr"
+ "key": "ip saddr"
}
},
"op": "==",
@@ -95,8 +90,7 @@
"left": {
"ct": {
"dir": "reply",
- "family": "ip",
- "key": "saddr"
+ "key": "ip saddr"
}
},
"op": "==",
@@ -117,8 +111,7 @@
"left": {
"ct": {
"dir": "original",
- "family": "ip",
- "key": "daddr"
+ "key": "ip daddr"
}
},
"op": "==",
@@ -139,8 +132,7 @@
"left": {
"ct": {
"dir": "reply",
- "family": "ip",
- "key": "daddr"
+ "key": "ip daddr"
}
},
"op": "==",
diff --git a/tests/py/ip/ct.t.payload b/tests/py/ip/ct.t.payload
index b7cd130d..d5faed4c 100644
--- a/tests/py/ip/ct.t.payload
+++ b/tests/py/ip/ct.t.payload
@@ -1,44 +1,44 @@
# ct original ip saddr 192.168.0.1
ip test-ip4 output
- [ ct load src => reg 1 , dir original ]
+ [ ct load src_ip => reg 1 , dir original ]
[ cmp eq reg 1 0x0100a8c0 ]
# ct reply ip saddr 192.168.0.1
ip test-ip4 output
- [ ct load src => reg 1 , dir reply ]
+ [ ct load src_ip => reg 1 , dir reply ]
[ cmp eq reg 1 0x0100a8c0 ]
# ct original ip daddr 192.168.0.1
ip test-ip4 output
- [ ct load dst => reg 1 , dir original ]
+ [ ct load dst_ip => reg 1 , dir original ]
[ cmp eq reg 1 0x0100a8c0 ]
# ct reply ip daddr 192.168.0.1
ip test-ip4 output
- [ ct load dst => reg 1 , dir reply ]
+ [ ct load dst_ip => reg 1 , dir reply ]
[ cmp eq reg 1 0x0100a8c0 ]
# ct original ip saddr 192.168.1.0/24
ip test-ip4 output
- [ ct load src => reg 1 , dir original ]
+ [ ct load src_ip => reg 1 , dir original ]
[ bitwise reg 1 = (reg=1 & 0x00ffffff ) ^ 0x00000000 ]
[ cmp eq reg 1 0x0001a8c0 ]
# ct reply ip saddr 192.168.1.0/24
ip test-ip4 output
- [ ct load src => reg 1 , dir reply ]
+ [ ct load src_ip => reg 1 , dir reply ]
[ bitwise reg 1 = (reg=1 & 0x00ffffff ) ^ 0x00000000 ]
[ cmp eq reg 1 0x0001a8c0 ]
# ct original ip daddr 192.168.1.0/24
ip test-ip4 output
- [ ct load dst => reg 1 , dir original ]
+ [ ct load dst_ip => reg 1 , dir original ]
[ bitwise reg 1 = (reg=1 & 0x00ffffff ) ^ 0x00000000 ]
[ cmp eq reg 1 0x0001a8c0 ]
# ct reply ip daddr 192.168.1.0/24
ip test-ip4 output
- [ ct load dst => reg 1 , dir reply ]
+ [ ct load dst_ip => reg 1 , dir reply ]
[ bitwise reg 1 = (reg=1 & 0x00ffffff ) ^ 0x00000000 ]
[ cmp eq reg 1 0x0001a8c0 ]