cregit-Linux how code gets into the kernel

Release 4.14 net/netfilter/nf_conntrack_proto.c

Directory: net/netfilter
/* L3/L4 protocol support for nf_conntrack. */

/* (C) 1999-2001 Paul `Rusty' Russell
 * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org>
 * (C) 2003,2004 USAGI/WIDE Project <http://www.linux-ipv6.org>
 * (C) 2006-2012 Patrick McHardy <kaber@trash.net>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/types.h>
#include <linux/netfilter.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/mutex.h>
#include <linux/vmalloc.h>
#include <linux/stddef.h>
#include <linux/err.h>
#include <linux/percpu.h>
#include <linux/notifier.h>
#include <linux/kernel.h>
#include <linux/netdevice.h>

#include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_l3proto.h>
#include <net/netfilter/nf_conntrack_l4proto.h>
#include <net/netfilter/nf_conntrack_core.h>


static struct nf_conntrack_l4proto __rcu **nf_ct_protos[NFPROTO_NUMPROTO] __read_mostly;

struct nf_conntrack_l3proto __rcu *nf_ct_l3protos[NFPROTO_NUMPROTO] __read_mostly;

EXPORT_SYMBOL_GPL(nf_ct_l3protos);

static DEFINE_MUTEX(nf_ct_proto_mutex);

#ifdef CONFIG_SYSCTL

static int nf_ct_register_sysctl(struct net *net, struct ctl_table_header **header, const char *path, struct ctl_table *table) { if (*header == NULL) { *header = register_net_sysctl(net, path, table); if (*header == NULL) return -ENOMEM; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Patrick McHardy5283.87%125.00%
Gao Feng69.68%125.00%
Eric W. Biedermann46.45%250.00%
Total62100.00%4100.00%


static void nf_ct_unregister_sysctl(struct ctl_table_header **header, struct ctl_table **table, unsigned int users) { if (users > 0) return; unregister_net_sysctl_table(*header); kfree(*table); *header = NULL; *table = NULL; }

Contributors

PersonTokensPropCommitsCommitProp
Patrick McHardy3874.51%133.33%
Gao Feng1223.53%133.33%
Eric W. Biedermann11.96%133.33%
Total51100.00%3100.00%

#endif
const struct nf_conntrack_l4proto * __nf_ct_l4proto_find(u_int16_t l3proto, u_int8_t l4proto) { if (unlikely(l3proto >= NFPROTO_NUMPROTO || nf_ct_protos[l3proto] == NULL)) return &nf_conntrack_l4proto_generic; return rcu_dereference(nf_ct_protos[l3proto][l4proto]); }

Contributors

PersonTokensPropCommitsCommitProp
Martin Josefsson4189.13%240.00%
Patrick McHardy36.52%120.00%
Florian Westphal24.35%240.00%
Total46100.00%5100.00%

EXPORT_SYMBOL_GPL(__nf_ct_l4proto_find); /* this is guaranteed to always return a valid protocol helper, since * it falls back to generic_protocol */
const struct nf_conntrack_l3proto * nf_ct_l3proto_find_get(u_int16_t l3proto) { struct nf_conntrack_l3proto *p; rcu_read_lock(); p = __nf_ct_l3proto_find(l3proto); if (!try_module_get(p->me)) p = &nf_conntrack_l3proto_generic; rcu_read_unlock(); return p; }

Contributors

PersonTokensPropCommitsCommitProp
Martin Josefsson4493.62%250.00%
Patrick McHardy24.26%125.00%
Florian Westphal12.13%125.00%
Total47100.00%4100.00%

EXPORT_SYMBOL_GPL(nf_ct_l3proto_find_get);
int nf_ct_l3proto_try_module_get(unsigned short l3proto) { const struct nf_conntrack_l3proto *p; int ret; retry: p = nf_ct_l3proto_find_get(l3proto); if (p == &nf_conntrack_l3proto_generic) { ret = request_module("nf_conntrack-%d", l3proto); if (!ret) goto retry; return -EPROTOTYPE; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Martin Josefsson5693.33%266.67%
Florian Westphal46.67%133.33%
Total60100.00%3100.00%

EXPORT_SYMBOL_GPL(nf_ct_l3proto_try_module_get);
void nf_ct_l3proto_module_put(unsigned short l3proto) { struct nf_conntrack_l3proto *p; /* rcu_read_lock not necessary since the caller holds a reference, but * taken anyways to avoid lockdep warnings in __nf_ct_l3proto_find() */ rcu_read_lock(); p = __nf_ct_l3proto_find(l3proto); module_put(p->me); rcu_read_unlock(); }

Contributors

PersonTokensPropCommitsCommitProp
Martin Josefsson2880.00%150.00%
Patrick McHardy720.00%150.00%
Total35100.00%2100.00%

EXPORT_SYMBOL_GPL(nf_ct_l3proto_module_put);
int nf_ct_netns_get(struct net *net, u8 nfproto) { const struct nf_conntrack_l3proto *l3proto; int ret; might_sleep(); ret = nf_ct_l3proto_try_module_get(nfproto); if (ret < 0) return ret; /* we already have a reference, can't fail */ rcu_read_lock(); l3proto = __nf_ct_l3proto_find(nfproto); rcu_read_unlock(); if (!l3proto->net_ns_get) return 0; ret = l3proto->net_ns_get(net); if (ret < 0) nf_ct_l3proto_module_put(nfproto); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Florian Westphal88100.00%2100.00%
Total88100.00%2100.00%

EXPORT_SYMBOL_GPL(nf_ct_netns_get);
void nf_ct_netns_put(struct net *net, u8 nfproto) { const struct nf_conntrack_l3proto *l3proto; might_sleep(); /* same as nf_conntrack_netns_get(), reference assumed */ rcu_read_lock(); l3proto = __nf_ct_l3proto_find(nfproto); rcu_read_unlock(); if (WARN_ON(!l3proto)) return; if (l3proto->net_ns_put) l3proto->net_ns_put(net); nf_ct_l3proto_module_put(nfproto); }

Contributors

PersonTokensPropCommitsCommitProp
Florian Westphal63100.00%2100.00%
Total63100.00%2100.00%

EXPORT_SYMBOL_GPL(nf_ct_netns_put);
const struct nf_conntrack_l4proto * nf_ct_l4proto_find_get(u_int16_t l3num, u_int8_t l4num) { const struct nf_conntrack_l4proto *p; rcu_read_lock(); p = __nf_ct_l4proto_find(l3num, l4num); if (!try_module_get(p->me)) p = &nf_conntrack_l4proto_generic; rcu_read_unlock(); return p; }

Contributors

PersonTokensPropCommitsCommitProp
Pablo Neira Ayuso5196.23%150.00%
Florian Westphal23.77%150.00%
Total53100.00%2100.00%

EXPORT_SYMBOL_GPL(nf_ct_l4proto_find_get);
void nf_ct_l4proto_put(const struct nf_conntrack_l4proto *p) { module_put(p->me); }

Contributors

PersonTokensPropCommitsCommitProp
Pablo Neira Ayuso1794.44%150.00%
Julia Lawall15.56%150.00%
Total18100.00%2100.00%

EXPORT_SYMBOL_GPL(nf_ct_l4proto_put);
static int kill_l3proto(struct nf_conn *i, void *data) { return nf_ct_l3num(i) == ((const struct nf_conntrack_l3proto *)data)->l3proto; }

Contributors

PersonTokensPropCommitsCommitProp
Martin Josefsson2987.88%133.33%
Patrick McHardy39.09%133.33%
Florian Westphal13.03%133.33%
Total33100.00%3100.00%


static int kill_l4proto(struct nf_conn *i, void *data) { const struct nf_conntrack_l4proto *l4proto; l4proto = data; return nf_ct_protonum(i) == l4proto->l4proto && nf_ct_l3num(i) == l4proto->l3proto; }

Contributors

PersonTokensPropCommitsCommitProp
Martin Josefsson3784.09%250.00%
Patrick McHardy613.64%125.00%
Florian Westphal12.27%125.00%
Total44100.00%4100.00%


int nf_ct_l3proto_register(const struct nf_conntrack_l3proto *proto) { int ret = 0; struct nf_conntrack_l3proto *old; if (proto->l3proto >= NFPROTO_NUMPROTO) return -EBUSY; #if IS_ENABLED(CONFIG_NF_CT_NETLINK) if (proto->tuple_to_nlattr && proto->nla_size == 0) return -EINVAL; #endif mutex_lock(&nf_ct_proto_mutex); old = rcu_dereference_protected(nf_ct_l3protos[proto->l3proto], lockdep_is_held(&nf_ct_proto_mutex)); if (old != &nf_conntrack_l3proto_generic) { ret = -EBUSY; goto out_unlock; } rcu_assign_pointer(nf_ct_l3protos[proto->l3proto], proto); out_unlock: mutex_unlock(&nf_ct_proto_mutex); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Martin Josefsson5646.28%325.00%
Eric Dumazet2016.53%18.33%
Patrick McHardy1814.88%325.00%
Florian Westphal1310.74%325.00%
Holger Eitzenberger1310.74%18.33%
Gao Feng10.83%18.33%
Total121100.00%12100.00%

EXPORT_SYMBOL_GPL(nf_ct_l3proto_register);
void nf_ct_l3proto_unregister(const struct nf_conntrack_l3proto *proto) { BUG_ON(proto->l3proto >= NFPROTO_NUMPROTO); mutex_lock(&nf_ct_proto_mutex); BUG_ON(rcu_dereference_protected(nf_ct_l3protos[proto->l3proto], lockdep_is_held(&nf_ct_proto_mutex) ) != proto); rcu_assign_pointer(nf_ct_l3protos[proto->l3proto], &nf_conntrack_l3proto_generic); mutex_unlock(&nf_ct_proto_mutex); synchronize_rcu(); /* Remove all contrack entries for this protocol */ nf_ct_iterate_destroy(kill_l3proto, (void*)proto); }

Contributors

PersonTokensPropCommitsCommitProp
Martin Josefsson3948.15%325.00%
Patrick McHardy1720.99%325.00%
Florian Westphal1417.28%325.00%
Eric Dumazet911.11%18.33%
Gao Feng22.47%216.67%
Total81100.00%12100.00%

EXPORT_SYMBOL_GPL(nf_ct_l3proto_unregister);
static struct nf_proto_net *nf_ct_l4proto_net(struct net *net, const struct nf_conntrack_l4proto *l4proto) { if (l4proto->get_net_proto) { /* statically built-in protocols use static per-net */ return l4proto->get_net_proto(net); } else if (l4proto->net_id) { /* ... and loadable protocols use dynamic per-net */ return net_generic(net, *l4proto->net_id); } return NULL; }

Contributors

PersonTokensPropCommitsCommitProp
Gao Feng4778.33%457.14%
Pablo Neira Ayuso1118.33%114.29%
Julia Lawall11.67%114.29%
Patrick McHardy11.67%114.29%
Total60100.00%7100.00%


static int nf_ct_l4proto_register_sysctl(struct net *net, struct nf_proto_net *pn, const struct nf_conntrack_l4proto *l4proto) { int err = 0; #ifdef CONFIG_SYSCTL if (pn->ctl_table != NULL) { err = nf_ct_register_sysctl(net, &pn->ctl_table_header, "net/netfilter", pn->ctl_table); if (err < 0) { if (!pn->users) { kfree(pn->ctl_table); pn->ctl_table = NULL; } } } #endif /* CONFIG_SYSCTL */ return err; }

Contributors

PersonTokensPropCommitsCommitProp
Patrick McHardy5154.26%342.86%
Gao Feng4143.62%228.57%
Julia Lawall11.06%114.29%
Eric W. Biedermann11.06%114.29%
Total94100.00%7100.00%


static void nf_ct_l4proto_unregister_sysctl(struct net *net, struct nf_proto_net *pn, const struct nf_conntrack_l4proto *l4proto) { #ifdef CONFIG_SYSCTL if (pn->ctl_table_header != NULL) nf_ct_unregister_sysctl(&pn->ctl_table_header, &pn->ctl_table, pn->users); #endif /* CONFIG_SYSCTL */ }

Contributors

PersonTokensPropCommitsCommitProp
Patrick McHardy3566.04%240.00%
Gao Feng1732.08%240.00%
Julia Lawall11.89%120.00%
Total53100.00%5100.00%

/* FIXME: Allow NULL functions and sub in pointers to generic for them. --RR */
int nf_ct_l4proto_register_one(struct nf_conntrack_l4proto *l4proto) { int ret = 0; if (l4proto->l3proto >= ARRAY_SIZE(nf_ct_protos)) return -EBUSY; if ((l4proto->to_nlattr && !l4proto->nlattr_size) || (l4proto->tuple_to_nlattr && !l4proto->nlattr_tuple_size)) return -EINVAL; mutex_lock(&nf_ct_proto_mutex); if (!nf_ct_protos[l4proto->l3proto]) { /* l3proto may be loaded latter. */ struct nf_conntrack_l4proto __rcu **proto_array; int i; proto_array = kmalloc(MAX_NF_CT_PROTO * sizeof(struct nf_conntrack_l4proto *), GFP_KERNEL); if (proto_array == NULL) { ret = -ENOMEM; goto out_unlock; } for (i = 0; i < MAX_NF_CT_PROTO; i++) RCU_INIT_POINTER(proto_array[i], &nf_conntrack_l4proto_generic); /* Before making proto_array visible to lockless readers, * we must make sure its content is committed to memory. */ smp_wmb(); nf_ct_protos[l4proto->l3proto] = proto_array; } else if (rcu_dereference_protected( nf_ct_protos[l4proto->l3proto][l4proto->l4proto], lockdep_is_held(&nf_ct_proto_mutex) ) != &nf_conntrack_l4proto_generic) { ret = -EBUSY; goto out_unlock; } l4proto->nla_size = 0; if (l4proto->nlattr_size) l4proto->nla_size += l4proto->nlattr_size(); if (l4proto->nlattr_tuple_size) l4proto->nla_size += 3 * l4proto->nlattr_tuple_size(); rcu_assign_pointer(nf_ct_protos[l4proto->l3proto][l4proto->l4proto], l4proto); out_unlock: mutex_unlock(&nf_ct_proto_mutex); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Martin Josefsson12648.65%323.08%
Holger Eitzenberger6625.48%17.69%
Patrick McHardy4416.99%430.77%
Eric Dumazet186.95%323.08%
Florian Westphal41.54%17.69%
Davide Caratti10.39%17.69%
Total259100.00%13100.00%

EXPORT_SYMBOL_GPL(nf_ct_l4proto_register_one);
int nf_ct_l4proto_pernet_register_one(struct net *net, const struct nf_conntrack_l4proto *l4proto) { int ret = 0; struct nf_proto_net *pn = NULL; if (l4proto->init_net) { ret = l4proto->init_net(net, l4proto->l3proto); if (ret < 0) goto out; } pn = nf_ct_l4proto_net(net, l4proto); if (pn == NULL) goto out; ret = nf_ct_l4proto_register_sysctl(net, pn, l4proto); if (ret < 0) goto out; pn->users++; out: return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Gao Feng10498.11%466.67%
Julia Lawall10.94%116.67%
Davide Caratti10.94%116.67%
Total106100.00%6100.00%

EXPORT_SYMBOL_GPL(nf_ct_l4proto_pernet_register_one);
static void __nf_ct_l4proto_unregister_one(const struct nf_conntrack_l4proto *l4proto) { BUG_ON(l4proto->l3proto >= ARRAY_SIZE(nf_ct_protos)); BUG_ON(rcu_dereference_protected( nf_ct_protos[l4proto->l3proto][l4proto->l4proto], lockdep_is_held(&nf_ct_proto_mutex) ) != l4proto); rcu_assign_pointer(nf_ct_protos[l4proto->l3proto][l4proto->l4proto], &nf_conntrack_l4proto_generic); }

Contributors

PersonTokensPropCommitsCommitProp
Martin Josefsson4160.29%333.33%
Patrick McHardy1014.71%222.22%
Eric Dumazet913.24%111.11%
Florian Westphal710.29%222.22%
Julia Lawall11.47%111.11%
Total68100.00%9100.00%


void nf_ct_l4proto_unregister_one(const struct nf_conntrack_l4proto *l4proto) { mutex_lock(&nf_ct_proto_mutex); __nf_ct_l4proto_unregister_one(l4proto); mutex_unlock(&nf_ct_proto_mutex); synchronize_rcu(); }

Contributors

PersonTokensPropCommitsCommitProp
Florian Westphal2064.52%116.67%
Patrick McHardy516.13%233.33%
Martin Josefsson412.90%116.67%
Julia Lawall13.23%116.67%
Gao Feng13.23%116.67%
Total31100.00%6100.00%

EXPORT_SYMBOL_GPL(nf_ct_l4proto_unregister_one);
void nf_ct_l4proto_pernet_unregister_one(struct net *net, const struct nf_conntrack_l4proto *l4proto) { struct nf_proto_net *pn = nf_ct_l4proto_net(net, l4proto); if (pn == NULL) return; pn->users--; nf_ct_l4proto_unregister_sysctl(net, pn, l4proto); }

Contributors

PersonTokensPropCommitsCommitProp
Gao Feng4591.84%233.33%
Davide Caratti12.04%116.67%
Martin Josefsson12.04%116.67%
Aaron Conole12.04%116.67%
Julia Lawall12.04%116.67%
Total49100.00%6100.00%

EXPORT_SYMBOL_GPL(nf_ct_l4proto_pernet_unregister_one);
int nf_ct_l4proto_register(struct nf_conntrack_l4proto *l4proto[], unsigned int num_proto) { int ret = -EINVAL, ver; unsigned int i; for (i = 0; i < num_proto; i++) { ret = nf_ct_l4proto_register_one(l4proto[i]); if (ret < 0) break; } if (i != num_proto) { ver = l4proto[i]->l3proto == PF_INET6 ? 6 : 4; pr_err("nf_conntrack_ipv%d: can't register l4 %d proto.\n", ver, l4proto[i]->l4proto); nf_ct_l4proto_unregister(l4proto, i); } return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Davide Caratti10498.11%150.00%
Florian Westphal21.89%150.00%
Total106100.00%2100.00%

EXPORT_SYMBOL_GPL(nf_ct_l4proto_register);
int nf_ct_l4proto_pernet_register(struct net *net, struct nf_conntrack_l4proto *const l4proto[], unsigned int num_proto) { int ret = -EINVAL; unsigned int i; for (i = 0; i < num_proto; i++) { ret = nf_ct_l4proto_pernet_register_one(net, l4proto[i]); if (ret < 0) break; } if (i != num_proto) { pr_err("nf_conntrack_proto_%d %d: pernet registration failed\n", l4proto[i]->l4proto, l4proto[i]->l3proto == PF_INET6 ? 6 : 4); nf_ct_l4proto_pernet_unregister(net, l4proto, i); } return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Davide Caratti10797.27%133.33%
Florian Westphal21.82%133.33%
Julia Lawall10.91%133.33%
Total110100.00%3100.00%

EXPORT_SYMBOL_GPL(nf_ct_l4proto_pernet_register);
void nf_ct_l4proto_unregister(struct nf_conntrack_l4proto *l4proto[], unsigned int num_proto) { mutex_lock(&nf_ct_proto_mutex); while (num_proto-- != 0) __nf_ct_l4proto_unregister_one(l4proto[num_proto]); mutex_unlock(&nf_ct_proto_mutex); synchronize_net(); /* Remove all contrack entries for this protocol */ nf_ct_iterate_destroy(kill_l4proto, l4proto); }

Contributors

PersonTokensPropCommitsCommitProp
Davide Caratti2954.72%150.00%
Florian Westphal2445.28%150.00%
Total53100.00%2100.00%

EXPORT_SYMBOL_GPL(nf_ct_l4proto_unregister);
void nf_ct_l4proto_pernet_unregister(struct net *net, struct nf_conntrack_l4proto *const l4proto[], unsigned int num_proto) { while (num_proto-- != 0) nf_ct_l4proto_pernet_unregister_one(net, l4proto[num_proto]); }

Contributors

PersonTokensPropCommitsCommitProp
Davide Caratti3797.37%150.00%
Julia Lawall12.63%150.00%
Total38100.00%2100.00%

EXPORT_SYMBOL_GPL(nf_ct_l4proto_pernet_unregister);
int nf_conntrack_proto_pernet_init(struct net *net) { int err; struct nf_proto_net *pn = nf_ct_l4proto_net(net, &nf_conntrack_l4proto_generic); err = nf_conntrack_l4proto_generic.init_net(net, nf_conntrack_l4proto_generic.l3proto); if (err < 0) return err; err = nf_ct_l4proto_register_sysctl(net, pn, &nf_conntrack_l4proto_generic); if (err < 0) return err; pn->users++; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Gao Feng5064.94%583.33%
Patrick McHardy2735.06%116.67%
Total77100.00%6100.00%


void nf_conntrack_proto_pernet_fini(struct net *net) { struct nf_proto_net *pn = nf_ct_l4proto_net(net, &nf_conntrack_l4proto_generic); pn->users--; nf_ct_l4proto_unregister_sysctl(net, pn, &nf_conntrack_l4proto_generic); }

Contributors

PersonTokensPropCommitsCommitProp
Gao Feng2976.32%480.00%
Patrick McHardy923.68%120.00%
Total38100.00%5100.00%


int nf_conntrack_proto_init(void) { unsigned int i; for (i = 0; i < NFPROTO_NUMPROTO; i++) rcu_assign_pointer(nf_ct_l3protos[i], &nf_conntrack_l3proto_generic); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Gao Feng3797.37%266.67%
Florian Westphal12.63%133.33%
Total38100.00%3100.00%


void nf_conntrack_proto_fini(void) { unsigned int i; /* free l3proto protocol tables */ for (i = 0; i < ARRAY_SIZE(nf_ct_protos); i++) kfree(nf_ct_protos[i]); }

Contributors

PersonTokensPropCommitsCommitProp
Patrick McHardy2261.11%125.00%
Gao Feng1027.78%250.00%
Florian Westphal411.11%125.00%
Total36100.00%4100.00%


Overall Contributors

PersonTokensPropCommitsCommitProp
Martin Josefsson56425.66%36.25%
Gao Feng42119.15%1122.92%
Patrick McHardy39818.11%1327.08%
Davide Caratti30313.79%12.08%
Florian Westphal26512.06%714.58%
Pablo Neira Ayuso894.05%24.17%
Holger Eitzenberger793.59%12.08%
Eric Dumazet562.55%36.25%
Julia Lawall100.45%12.08%
Eric W. Biedermann60.27%24.17%
Tejun Heo30.14%12.08%
Arnd Bergmann20.09%12.08%
Aaron Conole10.05%12.08%
Adrian Bunk10.05%12.08%
Total2198100.00%48100.00%
Directory: net/netfilter
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.