File Index
Files and directories
Sign in
FILE

nf_hooks_lwtunnel.c

File preview with syntax highlighting.

linux-6.19.14/net/netfilter/nf_hooks_lwtunnel.c C
  1// SPDX-License-Identifier: GPL-2.0
  2
  3#include <linux/sysctl.h>
  4#include <net/lwtunnel.h>
  5#include <net/netfilter/nf_hooks_lwtunnel.h>
  6#include <linux/netfilter.h>
  7
  8#include "nf_internals.h"
  9
 10static inline int nf_hooks_lwtunnel_get(void)
 11{
 12	if (static_branch_unlikely(&nf_hooks_lwtunnel_enabled))
 13		return 1;
 14	else
 15		return 0;
 16}
 17
 18static inline int nf_hooks_lwtunnel_set(int enable)
 19{
 20	if (static_branch_unlikely(&nf_hooks_lwtunnel_enabled)) {
 21		if (!enable)
 22			return -EBUSY;
 23	} else if (enable) {
 24		static_branch_enable(&nf_hooks_lwtunnel_enabled);
 25	}
 26
 27	return 0;
 28}
 29
 30#ifdef CONFIG_SYSCTL
 31int nf_hooks_lwtunnel_sysctl_handler(const struct ctl_table *table, int write,
 32				     void *buffer, size_t *lenp, loff_t *ppos)
 33{
 34	int proc_nf_hooks_lwtunnel_enabled = 0;
 35	struct ctl_table tmp = {
 36		.procname = table->procname,
 37		.data = &proc_nf_hooks_lwtunnel_enabled,
 38		.maxlen = sizeof(int),
 39		.mode = table->mode,
 40		.extra1 = SYSCTL_ZERO,
 41		.extra2 = SYSCTL_ONE,
 42	};
 43	int ret;
 44
 45	if (!write)
 46		proc_nf_hooks_lwtunnel_enabled = nf_hooks_lwtunnel_get();
 47
 48	ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
 49
 50	if (write && ret == 0)
 51		ret = nf_hooks_lwtunnel_set(proc_nf_hooks_lwtunnel_enabled);
 52
 53	return ret;
 54}
 55EXPORT_SYMBOL_GPL(nf_hooks_lwtunnel_sysctl_handler);
 56
 57static struct ctl_table nf_lwtunnel_sysctl_table[] = {
 58	{
 59		.procname	= "nf_hooks_lwtunnel",
 60		.data		= NULL,
 61		.maxlen		= sizeof(int),
 62		.mode		= 0644,
 63		.proc_handler	= nf_hooks_lwtunnel_sysctl_handler,
 64	},
 65};
 66
 67static int __net_init nf_lwtunnel_net_init(struct net *net)
 68{
 69	struct ctl_table_header *hdr;
 70	struct ctl_table *table;
 71
 72	table = nf_lwtunnel_sysctl_table;
 73	if (!net_eq(net, &init_net)) {
 74		table = kmemdup(nf_lwtunnel_sysctl_table,
 75				sizeof(nf_lwtunnel_sysctl_table),
 76				GFP_KERNEL);
 77		if (!table)
 78			goto err_alloc;
 79	}
 80
 81	hdr = register_net_sysctl_sz(net, "net/netfilter", table,
 82				     ARRAY_SIZE(nf_lwtunnel_sysctl_table));
 83	if (!hdr)
 84		goto err_reg;
 85
 86	net->nf.nf_lwtnl_dir_header = hdr;
 87
 88	return 0;
 89err_reg:
 90	if (!net_eq(net, &init_net))
 91		kfree(table);
 92err_alloc:
 93	return -ENOMEM;
 94}
 95
 96static void __net_exit nf_lwtunnel_net_exit(struct net *net)
 97{
 98	const struct ctl_table *table;
 99
100	table = net->nf.nf_lwtnl_dir_header->ctl_table_arg;
101	unregister_net_sysctl_table(net->nf.nf_lwtnl_dir_header);
102	if (!net_eq(net, &init_net))
103		kfree(table);
104}
105
106static struct pernet_operations nf_lwtunnel_net_ops = {
107	.init = nf_lwtunnel_net_init,
108	.exit = nf_lwtunnel_net_exit,
109};
110
111int __init netfilter_lwtunnel_init(void)
112{
113	return register_pernet_subsys(&nf_lwtunnel_net_ops);
114}
115
116void netfilter_lwtunnel_fini(void)
117{
118	unregister_pernet_subsys(&nf_lwtunnel_net_ops);
119}
120#else
121int __init netfilter_lwtunnel_init(void) { return 0; }
122void netfilter_lwtunnel_fini(void) {}
123#endif /* CONFIG_SYSCTL */
~/ Read-only file preview.