This patch introduces new sysctl toggle for enabling lightweight tunnel netfilter hooks. Signed-off-by: Ryoga Saito <contact@xxxxxxxxxxxx> --- .../networking/nf_conntrack-sysctl.rst | 7 +++ include/net/lwtunnel.h | 2 + include/net/netfilter/nf_conntrack.h | 4 ++ net/core/lwtunnel.c | 3 ++ net/netfilter/Makefile | 2 +- net/netfilter/nf_conntrack_lwtunnel.c | 52 +++++++++++++++++++ net/netfilter/nf_conntrack_standalone.c | 8 +++ 7 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 net/netfilter/nf_conntrack_lwtunnel.c diff --git a/Documentation/networking/nf_conntrack-sysctl.rst b/Documentation/networking/nf_conntrack-sysctl.rst index d31ed6c1cb0d..5afa4603aa4b 100644 --- a/Documentation/networking/nf_conntrack-sysctl.rst +++ b/Documentation/networking/nf_conntrack-sysctl.rst @@ -30,6 +30,13 @@ nf_conntrack_checksum - BOOLEAN in INVALID state. If this is enabled, such packets will not be considered for connection tracking. +nf_conntrack_lwtunnel - BOOLEAN + - 0 - disabled (default) + - not 0 - enabled + + If this option is enabled, the lightweight tunnel netfilter hooks are + enabled. This option cannot be disabled once it is enabled. + nf_conntrack_count - INTEGER (read-only) Number of currently allocated flow entries. diff --git a/include/net/lwtunnel.h b/include/net/lwtunnel.h index 05cfd6ff6528..c6029f7eec14 100644 --- a/include/net/lwtunnel.h +++ b/include/net/lwtunnel.h @@ -51,6 +51,8 @@ struct lwtunnel_encap_ops { }; #ifdef CONFIG_LWTUNNEL +DECLARE_STATIC_KEY_FALSE(nf_ct_lwtunnel_enabled); + void lwtstate_free(struct lwtunnel_state *lws); static inline struct lwtunnel_state * diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index cc663c68ddc4..d2a74fc75346 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h @@ -360,4 +360,8 @@ static inline struct nf_conntrack_net *nf_ct_pernet(const struct net *net) #define MODULE_ALIAS_NFCT_HELPER(helper) \ MODULE_ALIAS("nfct-helper-" helper) +int nf_conntrack_lwtunnel_sysctl_handler(struct ctl_table *table, int write, + void *buffer, size_t *lenp, + loff_t *ppos); + #endif /* _NF_CONNTRACK_H */ diff --git a/net/core/lwtunnel.c b/net/core/lwtunnel.c index 8ec7d13d2860..8be3274e30ec 100644 --- a/net/core/lwtunnel.c +++ b/net/core/lwtunnel.c @@ -23,6 +23,9 @@ #include <net/ip6_fib.h> #include <net/rtnh.h> +DEFINE_STATIC_KEY_FALSE(nf_ct_lwtunnel_enabled); +EXPORT_SYMBOL_GPL(nf_ct_lwtunnel_enabled); + #ifdef CONFIG_MODULES static const char *lwtunnel_encap_str(enum lwtunnel_encap_types encap_type) diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index 049890e00a3d..dd784b872c61 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile @@ -4,7 +4,7 @@ netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o utils.o nf_conntrack-y := nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_expect.o nf_conntrack_helper.o \ nf_conntrack_proto.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o \ nf_conntrack_proto_icmp.o \ - nf_conntrack_extend.o nf_conntrack_acct.o nf_conntrack_seqadj.o + nf_conntrack_extend.o nf_conntrack_acct.o nf_conntrack_seqadj.o nf_conntrack_lwtunnel.o nf_conntrack-$(subst m,y,$(CONFIG_IPV6)) += nf_conntrack_proto_icmpv6.o nf_conntrack-$(CONFIG_NF_CONNTRACK_TIMEOUT) += nf_conntrack_timeout.o diff --git a/net/netfilter/nf_conntrack_lwtunnel.c b/net/netfilter/nf_conntrack_lwtunnel.c new file mode 100644 index 000000000000..cddbf8c5883a --- /dev/null +++ b/net/netfilter/nf_conntrack_lwtunnel.c @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <linux/sysctl.h> +#include <net/lwtunnel.h> +#include <net/netfilter/nf_conntrack.h> + +static inline int nf_conntrack_lwtunnel_get(void) +{ + if (static_branch_unlikely(&nf_ct_lwtunnel_enabled)) + return 1; + else + return 0; +} + +static inline int nf_conntrack_lwtunnel_set(int enable) +{ + if (static_branch_unlikely(&nf_ct_lwtunnel_enabled)) { + if (!enable) + return -EPERM; + } else if (enable) { + static_branch_enable(&nf_ct_lwtunnel_enabled); + } + + return 0; +} + +int nf_conntrack_lwtunnel_sysctl_handler(struct ctl_table *table, int write, + void *buffer, size_t *lenp, + loff_t *ppos) +{ + int proc_nf_ct_lwtunnel_enabled = 0; + struct ctl_table tmp = { + .procname = table->procname, + .data = &proc_nf_ct_lwtunnel_enabled, + .maxlen = sizeof(int), + .mode = table->mode, + .extra1 = SYSCTL_ZERO, + .extra2 = SYSCTL_ONE, + }; + int ret; + + if (!write) + proc_nf_ct_lwtunnel_enabled = nf_conntrack_lwtunnel_get(); + + ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos); + + if (write && ret == 0) + ret = nf_conntrack_lwtunnel_set(proc_nf_ct_lwtunnel_enabled); + + return ret; +} +EXPORT_SYMBOL_GPL(nf_conntrack_lwtunnel_sysctl_handler); \ No newline at end of file diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c index 214d9f9e499b..f20568496ef0 100644 --- a/net/netfilter/nf_conntrack_standalone.c +++ b/net/netfilter/nf_conntrack_standalone.c @@ -552,6 +552,7 @@ enum nf_ct_sysctl_index { NF_SYSCTL_CT_COUNT, NF_SYSCTL_CT_BUCKETS, NF_SYSCTL_CT_CHECKSUM, + NF_SYSCTL_CT_LWTUNNEL, NF_SYSCTL_CT_LOG_INVALID, NF_SYSCTL_CT_EXPECT_MAX, NF_SYSCTL_CT_ACCT, @@ -650,6 +651,13 @@ static struct ctl_table nf_ct_sysctl_table[] = { .extra1 = SYSCTL_ZERO, .extra2 = SYSCTL_ONE, }, + [NF_SYSCTL_CT_LWTUNNEL] = { + .procname = "nf_conntrack_lwtunnel", + .data = NULL, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = nf_conntrack_lwtunnel_sysctl_handler, + }, [NF_SYSCTL_CT_LOG_INVALID] = { .procname = "nf_conntrack_log_invalid", .data = &init_net.ct.sysctl_log_invalid, -- 2.25.1