12 #include <linux/types.h>
13 #include <linux/netfilter.h>
14 #include <linux/module.h>
17 #include <linux/stddef.h>
18 #include <linux/random.h>
20 #include <linux/kernel.h>
21 #include <linux/netdevice.h>
23 #include <linux/rtnetlink.h>
42 "Enable automatic conntrack helper assignment (default 1)");
45 static struct ctl_table helper_sysctl_table[] = {
48 .data = &
init_net.ct.sysctl_auto_assign_helper,
49 .maxlen =
sizeof(
unsigned int),
56 static int nf_conntrack_helper_init_sysctl(
struct net *
net)
60 table =
kmemdup(helper_sysctl_table,
sizeof(helper_sysctl_table),
65 table[0].
data = &net->ct.sysctl_auto_assign_helper;
67 net->ct.helper_sysctl_header =
70 if (!net->ct.helper_sysctl_header) {
71 pr_err(
"nf_conntrack_helper: can't register to sysctl.\n");
82 static void nf_conntrack_helper_fini_sysctl(
struct net *net)
86 table = net->ct.helper_sysctl_header->ctl_table_arg;
91 static int nf_conntrack_helper_init_sysctl(
struct net *net)
96 static void nf_conntrack_helper_fini_sysctl(
struct net *net)
105 return (((tuple->
src.l3num << 8) | tuple->
dst.protonum) ^
117 if (!nf_ct_helper_count)
120 h = helper_hash(tuple);
121 hlist_for_each_entry_rcu(helper, n, &nf_ct_helper_hash[h], hnode) {
122 if (nf_ct_tuple_src_mask_cmp(tuple, &helper->
tuple, &mask))
138 h->
tuple.src.l3num == l3num &&
139 h->
tuple.dst.protonum == protonum)
153 #ifdef CONFIG_MODULES
155 if (request_module(
"nfct-helper-%s", name) == 0)
159 if (h !=
NULL && !try_module_get(h->
me))
177 pr_debug(
"failed to add helper extension area");
187 struct net *net = nf_ct_net(ct);
200 help = nfct_help(tmpl);
207 help = nfct_help(ct);
208 if (net->ct.sysctl_auto_assign_helper && helper ==
NULL) {
210 if (
unlikely(!net->ct.auto_assign_helper_warned && helper)) {
211 pr_info(
"nf_conntrack: automatic helper "
212 "assignment is deprecated and it will "
213 "be removed soon. Use the iptables CT target "
214 "to attach helpers instead.\n");
215 net->ct.auto_assign_helper_warned =
true;
219 if (helper ==
NULL) {
235 if (help->
helper != helper) {
250 struct nf_conn *
ct = nf_ct_tuplehash_to_ctrack(i);
255 lockdep_is_held(&nf_conntrack_lock)
277 static LIST_HEAD(nf_ct_helper_expectfn_list);
282 list_add_rcu(&n->
head, &nf_ct_helper_expectfn_list);
290 list_del_rcu(&n->
head);
302 list_for_each_entry_rcu(cur, &nf_ct_helper_expectfn_list,
head) {
309 return found ? cur :
NULL;
320 list_for_each_entry_rcu(cur, &nf_ct_helper_expectfn_list,
head) {
327 return found ? cur :
NULL;
336 unsigned int h = helper_hash(&me->
tuple);
345 cur->
tuple.src.l3num == me->
tuple.src.l3num &&
346 cur->
tuple.dst.protonum == me->
tuple.dst.protonum) {
352 nf_ct_helper_count++;
371 &net->ct.expect_hash[i], hnode) {
375 lockdep_is_held(&nf_conntrack_lock)
376 ) == me || exp->
helper == me) &&
378 nf_ct_unlink_expect(exp);
387 for (i = 0; i < net->ct.htable_size; i++) {
398 hlist_del_rcu(&me->hnode);
399 nf_ct_helper_count--;
410 __nf_conntrack_helper_unregister(me, net);
426 net->ct.auto_assign_helper_warned =
false;
427 net->ct.sysctl_auto_assign_helper = nf_ct_auto_assign_helper;
441 err = nf_conntrack_helper_init_sysctl(net);
457 nf_conntrack_helper_fini_sysctl(net);