Skip to content

Commit 39e6dea

Browse files
committed
netfilter: nf_tables: add forward expression to the netdev family
You can use this to forward packets from ingress to the egress path of the specified interface. This provides a fast path to bounce packets from one interface to another specific destination interface. Signed-off-by: Pablo Neira Ayuso <[email protected]>
1 parent 502061f commit 39e6dea

File tree

4 files changed

+117
-0
lines changed

4 files changed

+117
-0
lines changed

include/uapi/linux/netfilter/nf_tables.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -983,6 +983,18 @@ enum nft_dup_attributes {
983983
};
984984
#define NFTA_DUP_MAX (__NFTA_DUP_MAX - 1)
985985

986+
/**
987+
* enum nft_fwd_attributes - nf_tables fwd expression netlink attributes
988+
*
989+
* @NFTA_FWD_SREG_DEV: source register of output interface (NLA_U32: nft_register)
990+
*/
991+
enum nft_fwd_attributes {
992+
NFTA_FWD_UNSPEC,
993+
NFTA_FWD_SREG_DEV,
994+
__NFTA_FWD_MAX
995+
};
996+
#define NFTA_FWD_MAX (__NFTA_FWD_MAX - 1)
997+
986998
/**
987999
* enum nft_gen_attributes - nf_tables ruleset generation attributes
9881000
*

net/netfilter/Kconfig

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,12 @@ config NFT_DUP_NETDEV
577577
help
578578
This option enables packet duplication for the "netdev" family.
579579

580+
config NFT_FWD_NETDEV
581+
tristate "Netfilter nf_tables netdev packet forwarding support"
582+
select NF_DUP_NETDEV
583+
help
584+
This option enables packet forwarding for the "netdev" family.
585+
580586
endif # NF_TABLES_NETDEV
581587

582588
endif # NF_TABLES

net/netfilter/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ obj-$(CONFIG_NFT_REDIR) += nft_redir.o
9595

9696
# nf_tables netdev
9797
obj-$(CONFIG_NFT_DUP_NETDEV) += nft_dup_netdev.o
98+
obj-$(CONFIG_NFT_FWD_NETDEV) += nft_fwd_netdev.o
9899

99100
# generic X tables
100101
obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o

net/netfilter/nft_fwd_netdev.c

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/*
2+
* Copyright (c) 2015 Pablo Neira Ayuso <[email protected]>
3+
*
4+
* This program is free software; you can redistribute it and/or modify it
5+
* under the terms of the GNU General Public License version 2 as published by
6+
* the Free Software Foundation.
7+
*/
8+
9+
#include <linux/kernel.h>
10+
#include <linux/init.h>
11+
#include <linux/module.h>
12+
#include <linux/netlink.h>
13+
#include <linux/netfilter.h>
14+
#include <linux/netfilter/nf_tables.h>
15+
#include <net/netfilter/nf_tables.h>
16+
#include <net/netfilter/nf_dup_netdev.h>
17+
18+
struct nft_fwd_netdev {
19+
enum nft_registers sreg_dev:8;
20+
};
21+
22+
static void nft_fwd_netdev_eval(const struct nft_expr *expr,
23+
struct nft_regs *regs,
24+
const struct nft_pktinfo *pkt)
25+
{
26+
struct nft_fwd_netdev *priv = nft_expr_priv(expr);
27+
int oif = regs->data[priv->sreg_dev];
28+
29+
nf_dup_netdev_egress(pkt, oif);
30+
regs->verdict.code = NF_DROP;
31+
}
32+
33+
static const struct nla_policy nft_fwd_netdev_policy[NFTA_FWD_MAX + 1] = {
34+
[NFTA_FWD_SREG_DEV] = { .type = NLA_U32 },
35+
};
36+
37+
static int nft_fwd_netdev_init(const struct nft_ctx *ctx,
38+
const struct nft_expr *expr,
39+
const struct nlattr * const tb[])
40+
{
41+
struct nft_fwd_netdev *priv = nft_expr_priv(expr);
42+
43+
if (tb[NFTA_FWD_SREG_DEV] == NULL)
44+
return -EINVAL;
45+
46+
priv->sreg_dev = nft_parse_register(tb[NFTA_FWD_SREG_DEV]);
47+
return nft_validate_register_load(priv->sreg_dev, sizeof(int));
48+
}
49+
50+
static const struct nft_expr_ops nft_fwd_netdev_ingress_ops;
51+
52+
static int nft_fwd_netdev_dump(struct sk_buff *skb, const struct nft_expr *expr)
53+
{
54+
struct nft_fwd_netdev *priv = nft_expr_priv(expr);
55+
56+
if (nft_dump_register(skb, NFTA_FWD_SREG_DEV, priv->sreg_dev))
57+
goto nla_put_failure;
58+
59+
return 0;
60+
61+
nla_put_failure:
62+
return -1;
63+
}
64+
65+
static struct nft_expr_type nft_fwd_netdev_type;
66+
static const struct nft_expr_ops nft_fwd_netdev_ops = {
67+
.type = &nft_fwd_netdev_type,
68+
.size = NFT_EXPR_SIZE(sizeof(struct nft_fwd_netdev)),
69+
.eval = nft_fwd_netdev_eval,
70+
.init = nft_fwd_netdev_init,
71+
.dump = nft_fwd_netdev_dump,
72+
};
73+
74+
static struct nft_expr_type nft_fwd_netdev_type __read_mostly = {
75+
.family = NFPROTO_NETDEV,
76+
.name = "fwd",
77+
.ops = &nft_fwd_netdev_ops,
78+
.policy = nft_fwd_netdev_policy,
79+
.maxattr = NFTA_FWD_MAX,
80+
.owner = THIS_MODULE,
81+
};
82+
83+
static int __init nft_fwd_netdev_module_init(void)
84+
{
85+
return nft_register_expr(&nft_fwd_netdev_type);
86+
}
87+
88+
static void __exit nft_fwd_netdev_module_exit(void)
89+
{
90+
nft_unregister_expr(&nft_fwd_netdev_type);
91+
}
92+
93+
module_init(nft_fwd_netdev_module_init);
94+
module_exit(nft_fwd_netdev_module_exit);
95+
96+
MODULE_LICENSE("GPL");
97+
MODULE_AUTHOR("Pablo Neira Ayuso <[email protected]>");
98+
MODULE_ALIAS_NFT_AF_EXPR(5, "fwd");

0 commit comments

Comments
 (0)