]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
src: Introduce socket matching
authorMáté Eckl <ecklm94@gmail.com>
Thu, 31 May 2018 18:06:16 +0000 (20:06 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Wed, 6 Jun 2018 17:43:00 +0000 (19:43 +0200)
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>
include/expression.h
include/linux/netfilter/nf_tables.h
include/socket.h [new file with mode: 0644]
src/Makefile.am
src/evaluate.c
src/netlink_delinearize.c
src/netlink_linearize.c
src/parser_bison.y
src/scanner.l
src/socket.c [new file with mode: 0644]

index 15af35e87a983f3e4a261c3637da6829099c4918..2bb51e531ecbeb550d8bf6be42ffdffb34ca6087 100644 (file)
@@ -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
@@ -296,6 +299,10 @@ struct expr {
                        enum nft_meta_keys      key;
                        enum proto_bases        base;
                } meta;
+               struct {
+                       /* SOCKET */
+                       enum nft_socket_keys    key;
+               } socket;
                struct {
                        /* EXPR_RT */
                        enum nft_rt_keys        key;
index f46239ecdd1a5eafd047b9a10610e74426a874c1..88e0ca1ca3e49f57f4aa6c8c82b0df0d9da820a7 100644 (file)
@@ -904,6 +904,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
  *
diff --git a/include/socket.h b/include/socket.h
new file mode 100644 (file)
index 0000000..a2ae9f1
--- /dev/null
@@ -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 */
index 6db31c813ab97a5e902981331af73e14d09fdac1..a4ad8cb31236bd876e017d89cb37dbc96fd9331e 100644 (file)
@@ -55,6 +55,7 @@ libnftables_la_SOURCES =                      \
                services.c                      \
                mergesort.c                     \
                tcpopt.c                        \
+               socket.c                        \
                libnftables.c
 
 # yacc and lex generate dirty code
index ba218ecb5f574b863c8cdbedbc6ab2021bd1f973..27e4f61137c0b8582893a8a5ace84a9bd710c3da 100644 (file)
@@ -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:
index 1c3a4fb72404d418cbfe8a34ed5808bd84ad917e..8da7c17c8c00d63dfe709629136fdebde74876ec 100644 (file)
@@ -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)
index 2aadc1ee856f23c7e93782d840b050fdd220c52d..8471e83749468a616129f857216b2d9b901745d9 100644 (file)
@@ -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);
        }
index c6491a3b0aa1572514715e66dff402356dbf57d3..33915ed8702a6809fb03bccc7084b46d4def241f 100644 (file)
@@ -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; }
                        ;
index 6a861cf255dcaffbed9794728c974a01ecb27790..416bd27af1427cc853920688fdf79802f439b125 100644 (file)
@@ -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 (file)
index 0000000..d5f401f
--- /dev/null
@@ -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;
+}