summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMáté Eckl <ecklm94@gmail.com>2018-05-31 20:06:16 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2018-06-06 19:43:00 +0200
commita02f8c3f6456e9a84a6c3117f2539376b152ba1f (patch)
tree80182a1faab00aa8ff43891da49ac0a62dacd136 /src
parent30d45266bf38b209df33e4df1a116c60531ae3e5 (diff)
src: Introduce socket matching
For now it can only match sockets with IP(V6)_TRANSPARENT socket option set. Example: table inet sockin { chain sockchain { type filter hook prerouting priority -150; policy accept; socket transparent 1 mark set 0x00000001 nftrace set 1 counter packets 9 bytes 504 accept } } Signed-off-by: Máté Eckl <ecklm94@gmail.com> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am1
-rw-r--r--src/evaluate.c9
-rw-r--r--src/netlink_delinearize.c17
-rw-r--r--src/netlink_linearize.c14
-rw-r--r--src/parser_bison.y17
-rw-r--r--src/scanner.l3
-rw-r--r--src/socket.c56
7 files changed, 117 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 6db31c81..a4ad8cb3 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -55,6 +55,7 @@ libnftables_la_SOURCES = \
services.c \
mergesort.c \
tcpopt.c \
+ socket.c \
libnftables.c
# yacc and lex generate dirty code
diff --git a/src/evaluate.c b/src/evaluate.c
index ba218ecb..27e4f611 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -1712,6 +1712,13 @@ static int expr_evaluate_meta(struct eval_ctx *ctx, struct expr **exprp)
return expr_evaluate_primary(ctx, exprp);
}
+static int expr_evaluate_socket(struct eval_ctx *ctx, struct expr **expr)
+{
+ __expr_set_context(&ctx->ectx, (*expr)->dtype, (*expr)->byteorder,
+ (*expr)->len, 1);
+ return 0;
+}
+
static int expr_evaluate_variable(struct eval_ctx *ctx, struct expr **exprp)
{
struct expr *new = expr_clone((*exprp)->sym->expr);
@@ -1749,6 +1756,8 @@ static int expr_evaluate(struct eval_ctx *ctx, struct expr **expr)
return expr_evaluate_primary(ctx, expr);
case EXPR_META:
return expr_evaluate_meta(ctx, expr);
+ case EXPR_SOCKET:
+ return expr_evaluate_socket(ctx, expr);
case EXPR_FIB:
return expr_evaluate_fib(ctx, expr);
case EXPR_PAYLOAD:
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
index 1c3a4fb7..8da7c17c 100644
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -615,6 +615,21 @@ static void netlink_parse_meta_expr(struct netlink_parse_ctx *ctx,
netlink_set_register(ctx, dreg, expr);
}
+static void netlink_parse_socket(struct netlink_parse_ctx *ctx,
+ const struct location *loc,
+ const struct nftnl_expr *nle)
+{
+ enum nft_registers dreg;
+ uint32_t key;
+ struct expr * expr;
+
+ key = nftnl_expr_get_u32(nle, NFTNL_EXPR_SOCKET_KEY);
+ expr = socket_expr_alloc(loc, key);
+
+ dreg = netlink_parse_register(nle, NFTNL_EXPR_SOCKET_DREG);
+ netlink_set_register(ctx, dreg, expr);
+}
+
static void netlink_parse_meta_stmt(struct netlink_parse_ctx *ctx,
const struct location *loc,
const struct nftnl_expr *nle)
@@ -1337,6 +1352,7 @@ static const struct {
{ .name = "payload", .parse = netlink_parse_payload },
{ .name = "exthdr", .parse = netlink_parse_exthdr },
{ .name = "meta", .parse = netlink_parse_meta },
+ { .name = "socket", .parse = netlink_parse_socket },
{ .name = "rt", .parse = netlink_parse_rt },
{ .name = "ct", .parse = netlink_parse_ct },
{ .name = "connlimit", .parse = netlink_parse_connlimit },
@@ -2022,6 +2038,7 @@ static void expr_postprocess(struct rule_pp_ctx *ctx, struct expr **exprp)
case EXPR_VERDICT:
case EXPR_NUMGEN:
case EXPR_FIB:
+ case EXPR_SOCKET:
break;
case EXPR_HASH:
if (expr->hash.expr)
diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c
index 2aadc1ee..8471e837 100644
--- a/src/netlink_linearize.c
+++ b/src/netlink_linearize.c
@@ -207,6 +207,18 @@ static void netlink_gen_rt(struct netlink_linearize_ctx *ctx,
nftnl_rule_add_expr(ctx->nlr, nle);
}
+static void netlink_gen_socket(struct netlink_linearize_ctx *ctx,
+ const struct expr *expr,
+ enum nft_registers dreg)
+{
+ struct nftnl_expr *nle;
+
+ nle = alloc_nft_expr("socket");
+ netlink_put_register(nle, NFTNL_EXPR_SOCKET_DREG, dreg);
+ nftnl_expr_set_u32(nle, NFTNL_EXPR_SOCKET_KEY, expr->socket.key);
+ nftnl_rule_add_expr(ctx->nlr, nle);
+}
+
static void netlink_gen_numgen(struct netlink_linearize_ctx *ctx,
const struct expr *expr,
enum nft_registers dreg)
@@ -694,6 +706,8 @@ static void netlink_gen_expr(struct netlink_linearize_ctx *ctx,
return netlink_gen_hash(ctx, expr, dreg);
case EXPR_FIB:
return netlink_gen_fib(ctx, expr, dreg);
+ case EXPR_SOCKET:
+ return netlink_gen_socket(ctx, expr, dreg);
default:
BUG("unknown expression type %s\n", expr->ops->name);
}
diff --git a/src/parser_bison.y b/src/parser_bison.y
index c6491a3b..33915ed8 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -189,6 +189,9 @@ int nft_lex(void *, void *, void *);
%token FIB "fib"
+%token SOCKET "socket"
+%token TRANSPARENT "transparent"
+
%token HOOK "hook"
%token DEVICE "device"
%token DEVICES "devices"
@@ -692,6 +695,10 @@ int nft_lex(void *, void *, void *);
%destructor { expr_free($$); } meta_expr
%type <val> meta_key meta_key_qualified meta_key_unqualified numgen_type
+%type <expr> socket_expr
+%destructor { expr_free($$); } socket_expr
+%type<val> socket_key
+
%type <val> nf_key_proto
%type <expr> rt_expr
@@ -2892,6 +2899,7 @@ primary_expr : symbol_expr { $$ = $1; }
| exthdr_expr { $$ = $1; }
| exthdr_exists_expr { $$ = $1; }
| meta_expr { $$ = $1; }
+ | socket_expr { $$ = $1; }
| rt_expr { $$ = $1; }
| ct_expr { $$ = $1; }
| numgen_expr { $$ = $1; }
@@ -3558,6 +3566,15 @@ meta_stmt : META meta_key SET stmt_expr
}
;
+socket_expr : SOCKET socket_key
+ {
+ $$ = socket_expr_alloc(&@$, $2);
+ }
+ ;
+
+socket_key : TRANSPARENT { $$ = NFT_SOCKET_TRANSPARENT; }
+ ;
+
offset_opt : /* empty */ { $$ = 0; }
| OFFSET NUM { $$ = $2; }
;
diff --git a/src/scanner.l b/src/scanner.l
index 6a861cf2..416bd27a 100644
--- a/src/scanner.l
+++ b/src/scanner.l
@@ -258,6 +258,9 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr})
"ruleset" { return RULESET; }
"trace" { return TRACE; }
+"socket" { return SOCKET; }
+"transparent" { return TRANSPARENT;}
+
"accept" { return ACCEPT; }
"drop" { return DROP; }
"continue" { return CONTINUE; }
diff --git a/src/socket.c b/src/socket.c
new file mode 100644
index 00000000..d5f401f0
--- /dev/null
+++ b/src/socket.c
@@ -0,0 +1,56 @@
+/*
+ * Socket expression/statement related definition and types.
+ *
+ * Copyright (c) 2018 Máté Eckl <ecklm94@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <nftables.h>
+#include <expression.h>
+#include <socket.h>
+
+const struct socket_template socket_templates[] = {
+ [NFT_SOCKET_TRANSPARENT] = {.token = "transparent",
+ .dtype = &integer_type,
+ .len = BITS_PER_BYTE,
+ .byteorder = BYTEORDER_HOST_ENDIAN,
+ }
+};
+
+static void socket_expr_print(const struct expr *expr, struct output_ctx *octx)
+{
+ nft_print(octx, "socket %s", socket_templates[expr->socket.key].token);
+}
+
+static bool socket_expr_cmp(const struct expr *e1, const struct expr *e2)
+{
+ return e1->socket.key == e2->socket.key;
+}
+
+static void socket_expr_clone(struct expr *new, const struct expr *expr)
+{
+ new->socket.key = expr->socket.key;
+}
+
+static const struct expr_ops socket_expr_ops = {
+ .type = EXPR_SOCKET,
+ .name = "socket",
+ .print = socket_expr_print,
+ .cmp = socket_expr_cmp,
+ .clone = socket_expr_clone,
+};
+
+struct expr *socket_expr_alloc(const struct location *loc, enum nft_socket_keys key)
+{
+ const struct socket_template *tmpl = &socket_templates[key];
+ struct expr *expr;
+
+ expr = expr_alloc(loc, &socket_expr_ops, tmpl->dtype,
+ tmpl->byteorder, tmpl->len);
+ expr->socket.key = key;
+
+ return expr;
+}