From a02f8c3f6456e9a84a6c3117f2539376b152ba1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Eckl?= Date: Thu, 31 May 2018 20:06:16 +0200 Subject: src: Introduce socket matching MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Signed-off-by: Pablo Neira Ayuso --- src/Makefile.am | 1 + src/evaluate.c | 9 ++++++++ src/netlink_delinearize.c | 17 ++++++++++++++ src/netlink_linearize.c | 14 ++++++++++++ src/parser_bison.y | 17 ++++++++++++++ src/scanner.l | 3 +++ src/socket.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 117 insertions(+) create mode 100644 src/socket.c (limited to 'src') 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 meta_key meta_key_qualified meta_key_unqualified numgen_type +%type socket_expr +%destructor { expr_free($$); } socket_expr +%type socket_key + %type nf_key_proto %type 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 + * + * 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 +#include +#include + +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; +} -- cgit v1.2.3