This patch allows you to match on tunnel metadata.

Signed-off-by: Pablo Neira Ayuso <pa...@netfilter.org>
---
 include/Makefile.am       |  4 ++-
 include/expression.h      |  6 ++++
 include/tunnel.h          | 33 +++++++++++++++++++++
 src/Makefile.am           |  1 +
 src/evaluate.c            |  7 +++++
 src/expression.c          |  1 +
 src/netlink_delinearize.c | 17 +++++++++++
 src/netlink_linearize.c   | 14 +++++++++
 src/parser_bison.y        | 33 +++++++++++++++++----
 src/scanner.l             |  2 ++
 src/statement.c           |  1 +
 src/tunnel.c              | 75 +++++++++++++++++++++++++++++++++++++++++++++++
 12 files changed, 188 insertions(+), 6 deletions(-)
 create mode 100644 include/tunnel.h
 create mode 100644 src/tunnel.c

diff --git a/include/Makefile.am b/include/Makefile.am
index 04a4a619a530..2224c5026836 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS =              linux           \
+uSUBDIRS =             linux           \
                        nftables
 
 noinst_HEADERS =       cli.h           \
@@ -31,8 +31,10 @@ noinst_HEADERS =     cli.h           \
                        parser.h        \
                        proto.h         \
                        socket.h        \
+                       tunnel.h        \
                        rule.h          \
                        rt.h            \
+                       tunnel.h        \
                        utils.h         \
                        xfrm.h          \
                        xt.h
diff --git a/include/expression.h b/include/expression.h
index 717b67550381..9941149a687b 100644
--- a/include/expression.h
+++ b/include/expression.h
@@ -70,6 +70,7 @@ enum expr_types {
        EXPR_RT,
        EXPR_FIB,
        EXPR_XFRM,
+       EXPR_TUNNEL,
 };
 
 enum ops {
@@ -196,6 +197,7 @@ enum expr_flags {
 #include <hash.h>
 #include <ct.h>
 #include <socket.h>
+#include <tunnel.h>
 #include <osf.h>
 #include <xfrm.h>
 
@@ -311,6 +313,10 @@ struct expr {
                        enum nft_socket_keys    key;
                } socket;
                struct {
+                       /* EXPR_TUNNEL */
+                       enum nft_tunnel_keys    key;
+               } tunnel;
+               struct {
                        /* EXPR_RT */
                        enum nft_rt_keys        key;
                } rt;
diff --git a/include/tunnel.h b/include/tunnel.h
new file mode 100644
index 000000000000..90d3f8f75ad7
--- /dev/null
+++ b/include/tunnel.h
@@ -0,0 +1,33 @@
+#ifndef NFTABLES_TUNNEL_H
+#define NFTABLES_TUNNEL_H
+
+/**
+ * struct tunnel_template - template for tunnel expressions
+ *
+ * @token:     parser token for the expression
+ * @dtype:     data type of the expression
+ * @len:       length of the expression
+ * @byteorder: byteorder
+ */
+struct tunnel_template {
+       const char              *token;
+       const struct datatype   *dtype;
+       enum byteorder          byteorder;
+       unsigned int            len;
+};
+
+extern const struct tunnel_template tunnel_templates[];
+
+#define TUNNEL_TEMPLATE(__token, __dtype, __len, __byteorder) {        \
+       .token          = (__token),                            \
+       .dtype          = (__dtype),                            \
+       .len            = (__len),                              \
+       .byteorder      = (__byteorder),                        \
+}
+
+extern struct expr *tunnel_expr_alloc(const struct location *loc,
+                                     enum nft_tunnel_keys key);
+
+const struct expr_ops tunnel_expr_ops;
+
+#endif /* NFTABLES_TUNNEL_H */
diff --git a/src/Makefile.am b/src/Makefile.am
index e2b531390cef..9b62c5325c8f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -63,6 +63,7 @@ libnftables_la_SOURCES =                      \
                nfnl_osf.c                      \
                tcpopt.c                        \
                socket.c                        \
+               tunnel.c                        \
                print.c                         \
                libnftables.c                   \
                libnftables.map
diff --git a/src/evaluate.c b/src/evaluate.c
index 0c2a8d0a9571..dca2bdfea917 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -1828,6 +1828,11 @@ static int expr_evaluate_osf(struct eval_ctx *ctx, 
struct expr **expr)
        return expr_evaluate_primary(ctx, expr);
 }
 
+static int expr_evaluate_tunnel(struct eval_ctx *ctx, struct expr **exprp)
+{
+       return expr_evaluate_primary(ctx, exprp);
+}
+
 static int expr_evaluate_variable(struct eval_ctx *ctx, struct expr **exprp)
 {
        struct expr *new = expr_clone((*exprp)->sym->expr);
@@ -1884,6 +1889,8 @@ static int expr_evaluate(struct eval_ctx *ctx, struct 
expr **expr)
                return expr_evaluate_meta(ctx, expr);
        case EXPR_SOCKET:
                return expr_evaluate_socket(ctx, expr);
+       case EXPR_TUNNEL:
+               return expr_evaluate_tunnel(ctx, expr);
        case EXPR_OSF:
                return expr_evaluate_osf(ctx, expr);
        case EXPR_FIB:
diff --git a/src/expression.c b/src/expression.c
index cb49e0b73f5a..c97b2c9dd5c9 100644
--- a/src/expression.c
+++ b/src/expression.c
@@ -1204,6 +1204,7 @@ const struct expr_ops *expr_ops(const struct expr *e)
        case EXPR_RT: return &rt_expr_ops;
        case EXPR_FIB: return &fib_expr_ops;
        case EXPR_XFRM: return &xfrm_expr_ops;
+       case EXPR_TUNNEL: return &tunnel_expr_ops;
        }
 
        BUG("Unknown expression type %d\n", e->etype);
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
index fc2574b1dea9..25ce874b35d0 100644
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -668,6 +668,21 @@ static void netlink_parse_osf(struct netlink_parse_ctx 
*ctx,
        netlink_set_register(ctx, dreg, expr);
 }
 
+static void netlink_parse_tunnel(struct netlink_parse_ctx *ctx,
+                                const struct location *loc,
+                                const struct nftnl_expr *nle)
+{
+       enum nft_registers dreg;
+       struct expr * expr;
+       uint32_t key;
+
+       key = nftnl_expr_get_u32(nle, NFTNL_EXPR_TUNNEL_KEY);
+       expr = tunnel_expr_alloc(loc, key);
+
+       dreg = netlink_parse_register(nle, NFTNL_EXPR_TUNNEL_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)
@@ -1464,6 +1479,7 @@ static const struct {
        { .name = "exthdr",     .parse = netlink_parse_exthdr },
        { .name = "meta",       .parse = netlink_parse_meta },
        { .name = "socket",     .parse = netlink_parse_socket },
+       { .name = "tunnel",     .parse = netlink_parse_tunnel },
        { .name = "osf",        .parse = netlink_parse_osf },
        { .name = "rt",         .parse = netlink_parse_rt },
        { .name = "ct",         .parse = netlink_parse_ct },
@@ -2158,6 +2174,7 @@ static void expr_postprocess(struct rule_pp_ctx *ctx, 
struct expr **exprp)
        case EXPR_NUMGEN:
        case EXPR_FIB:
        case EXPR_SOCKET:
+       case EXPR_TUNNEL:
        case EXPR_OSF:
        case EXPR_XFRM:
                break;
diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c
index 498326d0087a..b337539a44cf 100644
--- a/src/netlink_linearize.c
+++ b/src/netlink_linearize.c
@@ -232,6 +232,18 @@ static void netlink_gen_osf(struct netlink_linearize_ctx 
*ctx,
        nftnl_rule_add_expr(ctx->nlr, nle);
 }
 
+static void netlink_gen_tunnel(struct netlink_linearize_ctx *ctx,
+                              const struct expr *expr,
+                              enum nft_registers dreg)
+{
+       struct nftnl_expr *nle;
+
+       nle = alloc_nft_expr("tunnel");
+       netlink_put_register(nle, NFTNL_EXPR_TUNNEL_DREG, dreg);
+       nftnl_expr_set_u32(nle, NFTNL_EXPR_TUNNEL_KEY, expr->tunnel.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)
@@ -735,6 +747,8 @@ static void netlink_gen_expr(struct netlink_linearize_ctx 
*ctx,
                return netlink_gen_fib(ctx, expr, dreg);
        case EXPR_SOCKET:
                return netlink_gen_socket(ctx, expr, dreg);
+       case EXPR_TUNNEL:
+               return netlink_gen_tunnel(ctx, expr, dreg);
        case EXPR_OSF:
                return netlink_gen_osf(ctx, expr, dreg);
        case EXPR_XFRM:
diff --git a/src/parser_bison.y b/src/parser_bison.y
index d3b64b641700..ba28224a3b96 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -225,6 +225,8 @@ int nft_lex(void *, void *, void *);
 %token RULESET                 "ruleset"
 %token TRACE                   "trace"
 
+%token PATH                    "path"
+
 %token INET                    "inet"
 %token NETDEV                  "netdev"
 
@@ -601,8 +603,8 @@ int nft_lex(void *, void *, void *);
 %destructor { stmt_free($$); } counter_stmt counter_stmt_alloc stateful_stmt
 %type <stmt>                   payload_stmt
 %destructor { stmt_free($$); } payload_stmt
-%type <stmt>                   ct_stmt
-%destructor { stmt_free($$); } ct_stmt
+%type <stmt>                   ct_stmt tunnel_stmt
+%destructor { stmt_free($$); } ct_stmt tunnel_stmt
 %type <stmt>                   meta_stmt
 %destructor { stmt_free($$); } meta_stmt
 %type <stmt>                   log_stmt log_stmt_alloc
@@ -746,9 +748,9 @@ int nft_lex(void *, void *, void *);
 %destructor { expr_free($$); } mh_hdr_expr
 %type <val>                    mh_hdr_field
 
-%type <expr>                   meta_expr
-%destructor { expr_free($$); } meta_expr
-%type <val>                    meta_key        meta_key_qualified      
meta_key_unqualified    numgen_type
+%type <expr>                   meta_expr       tunnel_expr
+%destructor { expr_free($$); } meta_expr       tunnel_expr
+%type <val>                    meta_key        meta_key_qualified      
meta_key_unqualified    numgen_type     tunnel_key
 
 %type <expr>                   socket_expr
 %destructor { expr_free($$); } socket_expr
@@ -2310,6 +2312,7 @@ stmt                      :       verdict_stmt
                        |       tproxy_stmt
                        |       queue_stmt
                        |       ct_stmt
+                       |       tunnel_stmt
                        |       masq_stmt
                        |       redir_stmt
                        |       dup_stmt
@@ -2788,6 +2791,7 @@ primary_stmt_expr :       symbol_expr             { $$ = 
$1; }
                        |       integer_expr            { $$ = $1; }
                        |       boolean_expr            { $$ = $1; }
                        |       meta_expr               { $$ = $1; }
+                       |       tunnel_expr             { $$ = $1; }
                        |       rt_expr                 { $$ = $1; }
                        |       ct_expr                 { $$ = $1; }
                        |       numgen_expr             { $$ = $1; }
@@ -3243,6 +3247,7 @@ primary_expr              :       symbol_expr             
        { $$ = $1; }
                        |       exthdr_expr                     { $$ = $1; }
                        |       exthdr_exists_expr              { $$ = $1; }
                        |       meta_expr                       { $$ = $1; }
+                       |       tunnel_expr                     { $$ = $1; }
                        |       socket_expr                     { $$ = $1; }
                        |       rt_expr                         { $$ = $1; }
                        |       ct_expr                         { $$ = $1; }
@@ -4095,6 +4100,16 @@ meta_stmt                :       META    meta_key        
SET     stmt_expr
                        }
                        ;
 
+tunnel_key             :       PATH            { $$ = NFT_TUNNEL_PATH; }
+                       |       ID              { $$ = NFT_TUNNEL_ID; }
+                       ;
+
+tunnel_expr            :       TUNNEL  tunnel_key
+                       {
+                               $$ = tunnel_expr_alloc(&@$, $2);
+                       }
+                       ;
+
 socket_expr            :       SOCKET  socket_key
                        {
                                $$ = socket_expr_alloc(&@$, $2);
@@ -4326,6 +4341,14 @@ ct_stmt                  :       CT      ct_key          
SET     stmt_expr
                        }
                        ;
 
+tunnel_stmt            :       TUNNEL  NAME    stmt_expr
+                       {
+                               $$ = objref_stmt_alloc(&@$);
+                               $$->objref.type = NFT_OBJECT_TUNNEL;
+                               $$->objref.expr = $3;
+                       }
+                       ;
+
 payload_stmt           :       payload_expr            SET     stmt_expr
                        {
                                if ($1->etype == EXPR_EXTHDR)
diff --git a/src/scanner.l b/src/scanner.l
index f8575638a47b..7bbe5663dddd 100644
--- a/src/scanner.l
+++ b/src/scanner.l
@@ -329,6 +329,8 @@ addrstring  ({macaddr}|{ip4addr}|{ip6addr})
 "tunnel"               { return TUNNEL; }
 "tunnels"              { return TUNNELS; }
 
+"path"                 { return PATH; }
+
 "log"                  { return LOG; }
 "prefix"               { return PREFIX; }
 "group"                        { return GROUP; }
diff --git a/src/statement.c b/src/statement.c
index a9e72de3edfd..ab893be664e3 100644
--- a/src/statement.c
+++ b/src/statement.c
@@ -207,6 +207,7 @@ static const char *objref_type[NFT_OBJECT_MAX + 1] = {
        [NFT_OBJECT_QUOTA]      = "quota",
        [NFT_OBJECT_CT_HELPER]  = "ct helper",
        [NFT_OBJECT_LIMIT]      = "limit",
+       [NFT_OBJECT_TUNNEL]     = "tunnel",
        [NFT_OBJECT_CT_TIMEOUT] = "ct timeout",
        [NFT_OBJECT_SECMARK]    = "secmark",
        [NFT_OBJECT_CT_EXPECT]  = "ct expectation",
diff --git a/src/tunnel.c b/src/tunnel.c
new file mode 100644
index 000000000000..de01622246ef
--- /dev/null
+++ b/src/tunnel.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2018 Pablo Neira Ayuso <pa...@netfilter.org>
+ *
+ * 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 <errno.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <pwd.h>
+#include <grp.h>
+#include <arpa/inet.h>
+#include <linux/netfilter.h>
+#include <linux/pkt_sched.h>
+#include <linux/if_packet.h>
+
+#include <nftables.h>
+#include <expression.h>
+#include <datatype.h>
+#include <tunnel.h>
+#include <gmputil.h>
+#include <utils.h>
+#include <erec.h>
+
+const struct tunnel_template tunnel_templates[] = {
+       [NFT_TUNNEL_PATH]       = META_TEMPLATE("path", &boolean_type,
+                                               BITS_PER_BYTE, 
BYTEORDER_HOST_ENDIAN),
+       [NFT_TUNNEL_ID]         = META_TEMPLATE("id",  &integer_type,
+                                               4 * 8, BYTEORDER_HOST_ENDIAN),
+};
+
+static void tunnel_expr_print(const struct expr *expr, struct output_ctx *octx)
+{
+       nft_print(octx, "tunnel %s",
+                 tunnel_templates[expr->tunnel.key].token);
+}
+
+static bool tunnel_expr_cmp(const struct expr *e1, const struct expr *e2)
+{
+       return e1->tunnel.key == e2->tunnel.key;
+}
+
+static void tunnel_expr_clone(struct expr *new, const struct expr *expr)
+{
+       new->tunnel.key = expr->tunnel.key;
+}
+
+const struct expr_ops tunnel_expr_ops = {
+       .type           = EXPR_TUNNEL,
+       .name           = "tunnel",
+       .print          = tunnel_expr_print,
+       .cmp            = tunnel_expr_cmp,
+       .clone          = tunnel_expr_clone,
+};
+
+struct expr *tunnel_expr_alloc(const struct location *loc,
+                              enum nft_tunnel_keys key)
+{
+       const struct tunnel_template *tmpl = &tunnel_templates[key];
+       struct expr *expr;
+
+       expr = expr_alloc(loc, EXPR_TUNNEL, tmpl->dtype, tmpl->byteorder,
+                         tmpl->len);
+       expr->tunnel.key = key;
+
+       return expr;
+}
-- 
2.11.0

Reply via email to