summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorFlorian Westphal <fw@strlen.de>2016-12-11 18:02:34 +0100
committerFlorian Westphal <fw@strlen.de>2017-08-22 23:51:02 +0200
commit0c0b2452bc3c96cf3db09eb8cbf62778a2fd8f6c (patch)
tree8ab752666dda2f50c396501f1fb95ff43b90eac1 /src
parentd74eed8c9649e9278b69f2cd0fd92f71e3e19cfb (diff)
src: add tcp options set support
This adds support for tcp mss mangling: nft add rule filter input tcp option maxseg size 1200 Its also possible to change other tcp option fields, but maxseg is one of the more useful ones to change. Signed-off-by: Florian Westphal <fw@strlen.de> Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src')
-rw-r--r--src/evaluate.c15
-rw-r--r--src/exthdr.c25
-rw-r--r--src/netlink_delinearize.c21
-rw-r--r--src/netlink_linearize.c29
-rw-r--r--src/parser_bison.y5
5 files changed, 92 insertions, 3 deletions
diff --git a/src/evaluate.c b/src/evaluate.c
index f52a0843..3989d5e3 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -1835,6 +1835,19 @@ static bool stmt_evaluate_payload_need_csum(const struct expr *payload)
return desc && desc->checksum_key;
}
+static int stmt_evaluate_exthdr(struct eval_ctx *ctx, struct stmt *stmt)
+{
+ struct expr *exthdr;
+
+ if (__expr_evaluate_exthdr(ctx, &stmt->exthdr.expr) < 0)
+ return -1;
+
+ exthdr = stmt->exthdr.expr;
+ return stmt_evaluate_arg(ctx, stmt, exthdr->dtype, exthdr->len,
+ BYTEORDER_BIG_ENDIAN,
+ &stmt->exthdr.val);
+}
+
static int stmt_evaluate_payload(struct eval_ctx *ctx, struct stmt *stmt)
{
struct expr *binop, *mask, *and, *payload_bytes;
@@ -2700,6 +2713,8 @@ int stmt_evaluate(struct eval_ctx *ctx, struct stmt *stmt)
return stmt_evaluate_verdict(ctx, stmt);
case STMT_PAYLOAD:
return stmt_evaluate_payload(ctx, stmt);
+ case STMT_EXTHDR:
+ return stmt_evaluate_exthdr(ctx, stmt);
case STMT_FLOW:
return stmt_evaluate_flow(ctx, stmt);
case STMT_META:
diff --git a/src/exthdr.c b/src/exthdr.c
index a412025c..4add3da2 100644
--- a/src/exthdr.c
+++ b/src/exthdr.c
@@ -21,6 +21,7 @@
#include <utils.h>
#include <headers.h>
#include <expression.h>
+#include <statement.h>
static void exthdr_expr_print(const struct expr *expr, struct output_ctx *octx)
{
@@ -98,6 +99,30 @@ struct expr *exthdr_expr_alloc(const struct location *loc,
return expr;
}
+static void exthdr_stmt_print(const struct stmt *stmt, struct output_ctx *octx)
+{
+ expr_print(stmt->exthdr.expr, octx);
+ printf(" set ");
+ expr_print(stmt->exthdr.val, octx);
+}
+
+static const struct stmt_ops exthdr_stmt_ops = {
+ .type = STMT_EXTHDR,
+ .name = "exthdr",
+ .print = exthdr_stmt_print,
+};
+
+struct stmt *exthdr_stmt_alloc(const struct location *loc,
+ struct expr *expr, struct expr *val)
+{
+ struct stmt *stmt;
+
+ stmt = stmt_alloc(loc, &exthdr_stmt_ops);
+ stmt->exthdr.expr = expr;
+ stmt->exthdr.val = val;
+ return stmt;
+}
+
static const struct exthdr_desc *exthdr_protocols[IPPROTO_MAX] = {
[IPPROTO_HOPOPTS] = &exthdr_hbh,
[IPPROTO_ROUTING] = &exthdr_rt,
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
index 5317a830..51a61472 100644
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -513,8 +513,25 @@ static void netlink_parse_exthdr(struct netlink_parse_ctx *ctx,
expr = exthdr_expr_alloc(loc, NULL, 0);
exthdr_init_raw(expr, type, offset, len, op, flags);
- dreg = netlink_parse_register(nle, NFTNL_EXPR_EXTHDR_DREG);
- netlink_set_register(ctx, dreg, expr);
+ if (nftnl_expr_is_set(nle, NFTNL_EXPR_EXTHDR_DREG)) {
+ dreg = netlink_parse_register(nle, NFTNL_EXPR_EXTHDR_DREG);
+ netlink_set_register(ctx, dreg, expr);
+ } else if (nftnl_expr_is_set(nle, NFTNL_EXPR_EXTHDR_SREG)) {
+ enum nft_registers sreg;
+ struct stmt *stmt;
+ struct expr *val;
+
+ sreg = netlink_parse_register(nle, NFTNL_EXPR_EXTHDR_SREG);
+ val = netlink_get_register(ctx, loc, sreg);
+ if (val == NULL)
+ return netlink_error(ctx, loc,
+ "exthdr statement has no expression");
+
+ expr_set_type(val, expr->dtype, expr->byteorder);
+
+ stmt = exthdr_stmt_alloc(loc, expr, val);
+ list_add_tail(&stmt->list, &ctx->rule->stmts);
+ }
}
static void netlink_parse_hash(struct netlink_parse_ctx *ctx,
diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c
index 3d684569..c5a47dec 100644
--- a/src/netlink_linearize.c
+++ b/src/netlink_linearize.c
@@ -816,6 +816,33 @@ static bool payload_needs_l4csum_update_pseudohdr(const struct expr *expr,
return false;
}
+static void netlink_gen_exthdr_stmt(struct netlink_linearize_ctx *ctx,
+ const struct stmt *stmt)
+{
+ struct nftnl_expr *nle;
+ const struct expr *expr;
+ enum nft_registers sreg;
+ unsigned int offset;
+
+ sreg = get_register(ctx, stmt->exthdr.val);
+ netlink_gen_expr(ctx, stmt->exthdr.val, sreg);
+ release_register(ctx, stmt->exthdr.val);
+
+ expr = stmt->exthdr.expr;
+
+ offset = expr->exthdr.tmpl->offset + expr->exthdr.offset;
+
+ nle = alloc_nft_expr("exthdr");
+ netlink_put_register(nle, NFTNL_EXPR_EXTHDR_SREG, sreg);
+ nftnl_expr_set_u8(nle, NFTNL_EXPR_EXTHDR_TYPE,
+ expr->exthdr.desc->type);
+ nftnl_expr_set_u32(nle, NFTNL_EXPR_EXTHDR_OFFSET, offset / BITS_PER_BYTE);
+ nftnl_expr_set_u32(nle, NFTNL_EXPR_EXTHDR_LEN,
+ div_round_up(expr->len, BITS_PER_BYTE));
+ nftnl_expr_set_u8(nle, NFTNL_EXPR_EXTHDR_OP, expr->exthdr.op);
+ nftnl_rule_add_expr(ctx->nlr, nle);
+}
+
static void netlink_gen_payload_stmt(struct netlink_linearize_ctx *ctx,
const struct stmt *stmt)
{
@@ -1239,6 +1266,8 @@ static void netlink_gen_stmt(struct netlink_linearize_ctx *ctx,
return netlink_gen_verdict_stmt(ctx, stmt);
case STMT_FLOW:
return netlink_gen_flow_stmt(ctx, stmt);
+ case STMT_EXTHDR:
+ return netlink_gen_exthdr_stmt(ctx, stmt);
case STMT_PAYLOAD:
return netlink_gen_payload_stmt(ctx, stmt);
case STMT_META:
diff --git a/src/parser_bison.y b/src/parser_bison.y
index 783b72f5..7898ea3f 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -3209,7 +3209,10 @@ ct_stmt : CT ct_key SET expr
payload_stmt : payload_expr SET expr
{
- $$ = payload_stmt_alloc(&@$, $1, $3);
+ if ($1->ops->type == EXPR_EXTHDR)
+ $$ = exthdr_stmt_alloc(&@$, $1, $3);
+ else
+ $$ = payload_stmt_alloc(&@$, $1, $3);
}
;