On 2019-07-25, at 11:14:00 +0200, Pablo Neira Ayuso wrote:
> This patch allows you to match on tunnel metadata.
>
> Signed-off-by: Pablo Neira Ayuso <[email protected]>
> ---
>  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           \

Typo?

>                       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 <[email protected]>
> + *
> + * 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
>
>

Attachment: signature.asc
Description: PGP signature

Reply via email to