summaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--include/expression.h7
-rw-r--r--include/linux/netfilter/nf_tables.h28
-rw-r--r--include/socket.h24
-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
10 files changed, 176 insertions, 0 deletions
diff --git a/include/expression.h b/include/expression.h
index 15af35e8..2bb51e53 100644
--- a/include/expression.h
+++ b/include/expression.h
@@ -24,6 +24,7 @@
* @EXPR_PAYLOAD: payload expression
* @EXPR_EXTHDR: exthdr expression
* @EXPR_META: meta expression
+ * @EXPR_SOCKET: socket expression
* @EXPR_CT: conntrack expression
* @EXPR_CONCAT: concatenation
* @EXPR_LIST: list of expressions
@@ -50,6 +51,7 @@ enum expr_types {
EXPR_PAYLOAD,
EXPR_EXTHDR,
EXPR_META,
+ EXPR_SOCKET,
EXPR_CT,
EXPR_CONCAT,
EXPR_LIST,
@@ -188,6 +190,7 @@ enum expr_flags {
#include <rt.h>
#include <hash.h>
#include <ct.h>
+#include <socket.h>
/**
* struct expr
@@ -297,6 +300,10 @@ struct expr {
enum proto_bases base;
} meta;
struct {
+ /* SOCKET */
+ enum nft_socket_keys key;
+ } socket;
+ struct {
/* EXPR_RT */
enum nft_rt_keys key;
} rt;
diff --git a/include/linux/netfilter/nf_tables.h b/include/linux/netfilter/nf_tables.h
index f46239ec..88e0ca1c 100644
--- a/include/linux/netfilter/nf_tables.h
+++ b/include/linux/netfilter/nf_tables.h
@@ -905,6 +905,34 @@ enum nft_rt_attributes {
#define NFTA_RT_MAX (__NFTA_RT_MAX - 1)
/**
+ * enum nft_socket_attributes - nf_tables socket expression netlink attributes
+ *
+ * @NFTA_SOCKET_KEY: socket key to match
+ * @NFTA_SOCKET_DREG: destination register
+ */
+enum nft_socket_attributes {
+ NFTA_SOCKET_UNSPEC,
+
+ NFTA_SOCKET_KEY,
+ NFTA_SOCKET_DREG,
+
+ __NFTA_SOCKET_MAX
+};
+#define NFTA_SOCKET_MAX (__NFTA_SOCKET_MAX - 1)
+
+/*
+ * enum nft_socket_keys - nf_tables socket expression keys
+ *
+ * @NFT_SOCKET_TRANSPARENT: Value of the IP(V6)_TRANSPARENT socket option_
+ */
+enum nft_socket_keys {
+ NFT_SOCKET_TRANSPARENT,
+
+ __NFT_SOCKET_MAX
+};
+#define NFT_SOCKET_MAX (__NFT_SOCKET_MAX - 1)
+
+/**
* enum nft_ct_keys - nf_tables ct expression keys
*
* @NFT_CT_STATE: conntrack state (bitmask of enum ip_conntrack_info)
diff --git a/include/socket.h b/include/socket.h
new file mode 100644
index 00000000..a2ae9f10
--- /dev/null
+++ b/include/socket.h
@@ -0,0 +1,24 @@
+#ifndef NFTABLES_SOCKET_H
+#define NFTABLES_SOCKET_H
+
+//#include <parser.h>
+
+/**
+ * struct rt_template - template for routing expressions
+ *
+ * @token: parser token for the expression
+ * @dtype: data type of the expression
+ * @len: length of the expression
+ * @byteorder: byteorder
+ */
+struct socket_template {
+ const char *token;
+ const struct datatype *dtype;
+ unsigned int len;
+ enum byteorder byteorder;
+};
+
+extern struct expr *socket_expr_alloc(const struct location *loc,
+ enum nft_socket_keys key);
+
+#endif /* NFTABLES_SOCKET_H */
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;
+}