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; err = nf_ct_l4proto_pernet_register(net, builtin_l4proto, ARRAY_SIZE(builtin_l4proto)); if (err < 0) { nf_ct_l4proto_unregister_sysctl(net, pn, &nf_conntrack_l4proto_generic); return err; } pn->users++; return 0; }
/* FIXME: Allow NULL functions and sub in pointers to generic for them. --RR */ int nf_conntrack_l4proto_register(struct nf_conntrack_l4proto *l4proto) { int ret = 0; if (l4proto->l3proto >= PF_MAX) 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; } ret = nf_ct_l4proto_register_sysctl(l4proto); if (ret < 0) 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_nonull(nf_ct_protos[l4proto->l3proto][l4proto->l4proto], l4proto); out_unlock: mutex_unlock(&nf_ct_proto_mutex); return ret; }
int nf_conntrack_l4proto_register(struct nf_conntrack_l4proto *l4proto) { int ret = 0; if (l4proto->l3proto >= PF_MAX) 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 **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++) proto_array[i] = &nf_conntrack_l4proto_generic; nf_ct_protos[l4proto->l3proto] = proto_array; } else if (nf_ct_protos[l4proto->l3proto][l4proto->l4proto] != &nf_conntrack_l4proto_generic) { ret = -EBUSY; goto out_unlock; } ret = nf_ct_l4proto_register_sysctl(l4proto); if (ret < 0) 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; }
int nf_conntrack_proto_init(void) { unsigned int i; int err; err = nf_ct_l4proto_register_sysctl(&nf_conntrack_l4proto_generic); if (err < 0) return err; for (i = 0; i < AF_MAX; i++) RCU_INIT_POINTER(nf_ct_l3protos[i], &nf_conntrack_l3proto_generic); return 0; }
int nf_conntrack_proto_init(void) { unsigned int i; int err; err = nf_ct_l4proto_register_sysctl(&nf_conntrack_l4proto_generic); if (err < 0) return err; for (i = 0; i < AF_MAX; i++) rcu_assign_pointer_nonull(nf_ct_l3protos[i], &nf_conntrack_l3proto_generic); return 0; }
int nf_conntrack_proto_init(void) { unsigned int i; int err; /* 调用函数里面存着kzalloc内存申请 */ err = nf_ct_l4proto_register_sysctl(&nf_conntrack_l4proto_generic); if (err < 0) return err; /* nf_ct_l3protos[i] = &nf_conntrack_l3proto_generic 赋值操作??? */ for (i = 0; i < AF_MAX; i++) rcu_assign_pointer(nf_ct_l3protos[i], &nf_conntrack_l3proto_generic); return 0; }
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; }
int nf_ct_l4proto_pernet_register(struct net *net, 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; }
/* FIXME: Allow NULL functions and sub in pointers to generic for them. --RR */ int nf_conntrack_l4proto_register(struct nf_conntrack_l4proto *l4proto) { int ret = 0; if (l4proto->l3proto >= PF_MAX) { ret = -EBUSY; goto out; } if (l4proto == &nf_conntrack_l4proto_generic) return nf_ct_l4proto_register_sysctl(l4proto); retry: write_lock_bh(&nf_conntrack_lock); if (nf_ct_protos[l4proto->l3proto]) { if (nf_ct_protos[l4proto->l3proto][l4proto->l4proto] != &nf_conntrack_l4proto_generic) { ret = -EBUSY; goto out_unlock; } } else { /* l3proto may be loaded latter. */ struct nf_conntrack_l4proto **proto_array; int i; write_unlock_bh(&nf_conntrack_lock); proto_array = (struct nf_conntrack_l4proto **) kmalloc(MAX_NF_CT_PROTO * sizeof(struct nf_conntrack_l4proto *), GFP_KERNEL); if (proto_array == NULL) { ret = -ENOMEM; goto out; } for (i = 0; i < MAX_NF_CT_PROTO; i++) proto_array[i] = &nf_conntrack_l4proto_generic; write_lock_bh(&nf_conntrack_lock); if (nf_ct_protos[l4proto->l3proto]) { /* bad timing, but no problem */ write_unlock_bh(&nf_conntrack_lock); kfree(proto_array); } else { nf_ct_protos[l4proto->l3proto] = proto_array; write_unlock_bh(&nf_conntrack_lock); } /* * Just once because array is never freed until unloading * nf_conntrack.ko */ goto retry; } nf_ct_protos[l4proto->l3proto][l4proto->l4proto] = l4proto; write_unlock_bh(&nf_conntrack_lock); ret = nf_ct_l4proto_register_sysctl(l4proto); if (ret < 0) nf_conntrack_l4proto_unregister(l4proto); return ret; out_unlock: write_unlock_bh(&nf_conntrack_lock); out: return ret; }