include/statement.h \
include/tcpopt.h \
include/trace.h \
+ include/tunnel.h \
include/utils.h \
include/xfrm.h \
include/xt.h \
src/socket.c \
src/statement.c \
src/tcpopt.c \
+ src/tunnel.c \
src/utils.c \
src/xfrm.c \
$(NULL)
EXPR_NUMGEN,
EXPR_HASH,
EXPR_RT,
+ EXPR_TUNNEL,
EXPR_FIB,
EXPR_XFRM,
EXPR_SET_ELEM_CATCHALL,
#include <hash.h>
#include <ct.h>
#include <socket.h>
+#include <tunnel.h>
#include <osf.h>
#include <xfrm.h>
enum nft_socket_keys key;
uint32_t level;
} socket;
+ struct {
+ /* EXPR_TUNNEL */
+ enum nft_tunnel_keys key;
+ } tunnel;
struct {
/* EXPR_RT */
enum nft_rt_keys key;
--- /dev/null
+#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);
+
+extern const struct expr_ops tunnel_expr_ops;
+
+#endif /* NFTABLES_TUNNEL_H */
case EXPR_SOCKET:
case EXPR_OSF:
case EXPR_XFRM:
+ case EXPR_TUNNEL:
break;
case EXPR_RANGE:
case EXPR_PREFIX:
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 symbol *sym = (*exprp)->sym;
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:
case EXPR_NUMGEN: return &numgen_expr_ops;
case EXPR_HASH: return &hash_expr_ops;
case EXPR_RT: return &rt_expr_ops;
+ case EXPR_TUNNEL: return &tunnel_expr_ops;
case EXPR_FIB: return &fib_expr_ops;
case EXPR_XFRM: return &xfrm_expr_ops;
case EXPR_SET_ELEM_CATCHALL: return &set_elem_catchall_expr_ops;
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)
{ .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 },
case EXPR_NUMGEN:
case EXPR_FIB:
case EXPR_SOCKET:
+ case EXPR_TUNNEL:
case EXPR_OSF:
case EXPR_XFRM:
break;
nft_rule_add_expr(ctx, nle, &expr->location);
}
+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)
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:
%token RULESET "ruleset"
%token TRACE "trace"
+%token PATH "path"
+
%token INET "inet"
%token NETDEV "netdev"
%destructor { stmt_free($$); } counter_stmt counter_stmt_alloc stateful_stmt last_stmt
%type <stmt> limit_stmt_alloc quota_stmt_alloc last_stmt_alloc ct_limit_stmt_alloc
%destructor { stmt_free($$); } limit_stmt_alloc quota_stmt_alloc last_stmt_alloc ct_limit_stmt_alloc
-%type <stmt> objref_stmt objref_stmt_counter objref_stmt_limit objref_stmt_quota objref_stmt_ct objref_stmt_synproxy
-%destructor { stmt_free($$); } objref_stmt objref_stmt_counter objref_stmt_limit objref_stmt_quota objref_stmt_ct objref_stmt_synproxy
+%type <stmt> objref_stmt objref_stmt_counter objref_stmt_limit objref_stmt_quota objref_stmt_ct objref_stmt_synproxy objref_stmt_tunnel
+%destructor { stmt_free($$); } objref_stmt objref_stmt_counter objref_stmt_limit objref_stmt_quota objref_stmt_ct objref_stmt_synproxy objref_stmt_tunnel
%type <stmt> payload_stmt
%destructor { stmt_free($$); } payload_stmt
%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
}
;
+objref_stmt_tunnel : TUNNEL NAME stmt_expr close_scope_tunnel
+ {
+ $$ = objref_stmt_alloc(&@$);
+ $$->objref.type = NFT_OBJECT_TUNNEL;
+ $$->objref.expr = $3;
+ }
+ ;
+
objref_stmt_ct : CT TIMEOUT SET stmt_expr close_scope_ct
{
$$ = objref_stmt_alloc(&@$);
| objref_stmt_quota
| objref_stmt_synproxy
| objref_stmt_ct
+ | objref_stmt_tunnel
;
stateful_stmt : counter_stmt close_scope_counter
| boolean_expr { $$ = $1; }
| meta_expr { $$ = $1; }
| rt_expr { $$ = $1; }
+ | tunnel_expr { $$ = $1; }
| ct_expr { $$ = $1; }
| numgen_expr { $$ = $1; }
| hash_expr { $$ = $1; }
| exthdr_expr { $$ = $1; }
| exthdr_exists_expr { $$ = $1; }
| meta_expr { $$ = $1; }
+ | tunnel_expr { $$ = $1; }
| socket_expr { $$ = $1; }
| rt_expr { $$ = $1; }
| ct_expr { $$ = $1; }
| WILDCARD { $$ = NFT_SOCKET_WILDCARD; }
;
+tunnel_key : PATH { $$ = NFT_TUNNEL_PATH; }
+ | ID { $$ = NFT_TUNNEL_ID; }
+ ;
+
+tunnel_expr : TUNNEL tunnel_key
+ {
+ $$ = tunnel_expr_alloc(&@$, $2);
+ }
+ ;
+
offset_opt : /* empty */ { $$ = 0; }
| OFFSET NUM { $$ = $2; }
;
}
"counter" { scanner_push_start_cond(yyscanner, SCANSTATE_COUNTER); return COUNTER; }
-<SCANSTATE_COUNTER,SCANSTATE_LIMIT,SCANSTATE_QUOTA,SCANSTATE_STMT_SYNPROXY,SCANSTATE_EXPR_OSF>"name" { return NAME; }
+<SCANSTATE_COUNTER,SCANSTATE_LIMIT,SCANSTATE_QUOTA,SCANSTATE_STMT_SYNPROXY,SCANSTATE_EXPR_OSF,SCANSTATE_TUNNEL>"name" { return NAME; }
<SCANSTATE_COUNTER,SCANSTATE_CT,SCANSTATE_LIMIT>"packets" { return PACKETS; }
<SCANSTATE_COUNTER,SCANSTATE_CT,SCANSTATE_LIMIT,SCANSTATE_QUOTA>"bytes" { return BYTES; }
"erspan" { return ERSPAN; }
"egress" { return EGRESS; }
"ingress" { return INGRESS; }
+ "path" { return PATH; }
}
"notrack" { return NOTRACK; }
[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_SYNPROXY] = "synproxy",
--- /dev/null
+/*
+ * Copyright (c) 2018 Pablo Neira Ayuso <pablo@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 <stdbool.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)
+{
+ uint32_t key = expr->tunnel.key;
+ const char *token = "unknown";
+
+ if (key < array_size(tunnel_templates))
+ token = tunnel_templates[key].token;
+
+ nft_print(octx, "tunnel %s", 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;
+}