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 10 static 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 18 static 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 31 int 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 } 55 EXPORT_SYMBOL_GPL(nf_hooks_lwtunnel_sysctl_handler); 56 57 static 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 67 static 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; 89 err_reg: 90 if (!net_eq(net, &init_net)) 91 kfree(table); 92 err_alloc: 93 return -ENOMEM; 94 } 95 96 static 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 106 static struct pernet_operations nf_lwtunnel_net_ops = { 107 .init = nf_lwtunnel_net_init, 108 .exit = nf_lwtunnel_net_exit, 109 }; 110 111 int __init netfilter_lwtunnel_init(void) 112 { 113 return register_pernet_subsys(&nf_lwtunnel_net_ops); 114 } 115 116 void netfilter_lwtunnel_fini(void) 117 { 118 unregister_pernet_subsys(&nf_lwtunnel_net_ops); 119 } 120 #else 121 int __init netfilter_lwtunnel_init(void) { return 0; } 122 void netfilter_lwtunnel_fini(void) {} 123 #endif /* CONFIG_SYSCTL */ 124
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.