summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ct.c40
-rw-r--r--src/netlink_delinearize.c21
-rw-r--r--src/netlink_linearize.c4
-rw-r--r--src/parser_bison.y26
4 files changed, 79 insertions, 12 deletions
diff --git a/src/ct.c b/src/ct.c
index aa801388..07e7077b 100644
--- a/src/ct.c
+++ b/src/ct.c
@@ -207,17 +207,34 @@ static const struct ct_template ct_templates[] = {
static void ct_expr_print(const struct expr *expr)
{
+ const struct symbolic_constant *s;
+
printf("ct %s", ct_templates[expr->ct.key].token);
+
+ if (expr->ct.direction < 0)
+ return;
+
+ for (s = ct_dir_tbl.symbols; s->identifier != NULL; s++) {
+ if (expr->ct.direction == (int) s->value) {
+ printf(" %s", s->identifier);
+ return;
+ }
+ }
+
+ printf(" %d", expr->ct.direction);
}
static bool ct_expr_cmp(const struct expr *e1, const struct expr *e2)
{
- return e1->ct.key == e2->ct.key;
+ if (e1->ct.key != e2->ct.key)
+ return false;
+
+ return e1->ct.direction == e2->ct.direction;
}
static void ct_expr_clone(struct expr *new, const struct expr *expr)
{
- new->ct.key = expr->ct.key;
+ new->ct = expr->ct;
}
static void ct_expr_pctx_update(struct proto_ctx *ctx, const struct expr *expr)
@@ -249,7 +266,23 @@ static const struct expr_ops ct_expr_ops = {
.pctx_update = ct_expr_pctx_update,
};
-struct expr *ct_expr_alloc(const struct location *loc, enum nft_ct_keys key)
+struct error_record *ct_dir_parse(const struct location *loc, const char *str,
+ int8_t *direction)
+{
+ const struct symbolic_constant *s;
+
+ for (s = ct_dir_tbl.symbols; s->identifier != NULL; s++) {
+ if (!strcmp(str, s->identifier)) {
+ *direction = s->value;
+ return NULL;
+ }
+ }
+
+ return error(loc, "Could not parse direction %s", str);
+}
+
+struct expr *ct_expr_alloc(const struct location *loc, enum nft_ct_keys key,
+ int8_t direction)
{
const struct ct_template *tmpl = &ct_templates[key];
struct expr *expr;
@@ -257,6 +290,7 @@ struct expr *ct_expr_alloc(const struct location *loc, enum nft_ct_keys key)
expr = expr_alloc(loc, &ct_expr_ops, tmpl->dtype,
tmpl->byteorder, tmpl->len);
expr->ct.key = key;
+ expr->ct.direction = direction;
switch (key) {
case NFT_CT_PROTOCOL:
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
index f68fca09..769321aa 100644
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -536,12 +536,16 @@ static void netlink_parse_ct_expr(struct netlink_parse_ctx *ctx,
const struct location *loc,
const struct nftnl_expr *nle)
{
+ struct expr *expr = NULL;
enum nft_registers dreg;
+ int8_t dir = -1;
uint32_t key;
- struct expr *expr;
+
+ if (nftnl_expr_is_set(nle, NFTNL_EXPR_CT_DIR))
+ 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);
+ expr = ct_expr_alloc(loc, key, dir);
dreg = netlink_parse_register(nle, NFTNL_EXPR_CT_DREG);
netlink_set_register(ctx, dreg, expr);
@@ -1117,6 +1121,12 @@ static void meta_match_postprocess(struct rule_pp_ctx *ctx,
}
}
+static void ct_match_postprocess(struct rule_pp_ctx *ctx,
+ const struct expr *expr)
+{
+ return meta_match_postprocess(ctx, expr);
+}
+
/* Convert a bitmask to a prefix length */
static unsigned int expr_mask_to_prefix(const struct expr *expr)
{
@@ -1394,6 +1404,9 @@ static void expr_postprocess(struct rule_pp_ctx *ctx, struct expr **exprp)
expr_postprocess(ctx, &expr->right);
switch (expr->left->ops->type) {
+ case EXPR_CT:
+ ct_match_postprocess(ctx, expr);
+ break;
case EXPR_META:
meta_match_postprocess(ctx, expr);
break;
@@ -1431,9 +1444,11 @@ static void expr_postprocess(struct rule_pp_ctx *ctx, struct expr **exprp)
case EXPR_SET_REF:
case EXPR_EXTHDR:
case EXPR_META:
- case EXPR_CT:
case EXPR_VERDICT:
break;
+ case EXPR_CT:
+ ct_expr_update_type(&ctx->pctx, expr);
+ break;
default:
BUG("unknown expression type %s\n", expr->ops->name);
}
diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c
index 131c3f95..48f5f027 100644
--- a/src/netlink_linearize.c
+++ b/src/netlink_linearize.c
@@ -209,6 +209,10 @@ static void netlink_gen_ct(struct netlink_linearize_ctx *ctx,
nle = alloc_nft_expr("ct");
netlink_put_register(nle, NFTNL_EXPR_CT_DREG, dreg);
nftnl_expr_set_u32(nle, NFTNL_EXPR_CT_KEY, expr->ct.key);
+ if (expr->ct.direction >= 0)
+ nftnl_expr_set_u8(nle, NFTNL_EXPR_CT_DIR,
+ expr->ct.direction);
+
nftnl_rule_add_expr(ctx->nlr, nle);
}
diff --git a/src/parser_bison.y b/src/parser_bison.y
index af51e4dd..fcd4813e 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -567,7 +567,7 @@ static void location_update(struct location *loc, struct location *rhs, int n)
%type <expr> ct_expr
%destructor { expr_free($$); } ct_expr
-%type <val> ct_key
+%type <val> ct_key ct_key_dir
%type <val> export_format
%type <string> monitor_event
@@ -2264,9 +2264,22 @@ meta_stmt : META meta_key SET expr
}
;
-ct_expr : CT ct_key
+ct_expr : CT ct_key
{
- $$ = ct_expr_alloc(&@$, $2);
+ $$ = ct_expr_alloc(&@$, $2, -1);
+ }
+ | CT ct_key_dir STRING
+ {
+ struct error_record *erec;
+ int8_t direction;
+
+ erec = ct_dir_parse(&@$, $3, &direction);
+ if (erec != NULL) {
+ erec_queue(erec, state->msgs);
+ YYERROR;
+ }
+
+ $$ = ct_expr_alloc(&@$, $2, direction);
}
;
@@ -2276,13 +2289,14 @@ ct_key : STATE { $$ = NFT_CT_STATE; }
| MARK { $$ = NFT_CT_MARK; }
| EXPIRATION { $$ = NFT_CT_EXPIRATION; }
| HELPER { $$ = NFT_CT_HELPER; }
- | L3PROTOCOL { $$ = NFT_CT_L3PROTOCOL; }
- | SADDR { $$ = NFT_CT_SRC; }
+ | LABEL { $$ = NFT_CT_LABELS; }
+ ;
+ct_key_dir : SADDR { $$ = NFT_CT_SRC; }
| DADDR { $$ = NFT_CT_DST; }
+ | L3PROTOCOL { $$ = NFT_CT_L3PROTOCOL; }
| PROTOCOL { $$ = NFT_CT_PROTOCOL; }
| PROTO_SRC { $$ = NFT_CT_PROTO_SRC; }
| PROTO_DST { $$ = NFT_CT_PROTO_DST; }
- | LABEL { $$ = NFT_CT_LABELS; }
;
ct_stmt : CT ct_key SET expr