static int __init nf_nat_standalone_init(void) { int ret = 0; need_ipv4_conntrack(); #ifdef CONFIG_XFRM BUG_ON(ip_nat_decode_session != NULL); rcu_assign_pointer_nonull(ip_nat_decode_session, nat_decode_session); #endif ret = nf_nat_rule_init(); if (ret < 0) { pr_err("nf_nat_init: can't setup rules.\n"); goto cleanup_decode_session; } ret = nf_register_hooks(nf_nat_ops, ARRAY_SIZE(nf_nat_ops)); if (ret < 0) { pr_err("nf_nat_init: can't register hooks.\n"); goto cleanup_rule_init; } return ret; cleanup_rule_init: nf_nat_rule_cleanup(); cleanup_decode_session: #ifdef CONFIG_XFRM rcu_assign_pointer(ip_nat_decode_session, NULL); synchronize_net(); #endif 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) 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_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; }
static int __init nf_nat_sip_init(void) { BUG_ON(nf_nat_sip_hook != NULL); BUG_ON(nf_nat_sip_seq_adjust_hook != NULL); BUG_ON(nf_nat_sip_expect_hook != NULL); BUG_ON(nf_nat_sdp_addr_hook != NULL); BUG_ON(nf_nat_sdp_port_hook != NULL); BUG_ON(nf_nat_sdp_session_hook != NULL); BUG_ON(nf_nat_sdp_media_hook != NULL); rcu_assign_pointer_nonull(nf_nat_sip_hook, ip_nat_sip); rcu_assign_pointer_nonull(nf_nat_sip_seq_adjust_hook, ip_nat_sip_seq_adjust); rcu_assign_pointer_nonull(nf_nat_sip_expect_hook, ip_nat_sip_expect); rcu_assign_pointer_nonull(nf_nat_sdp_addr_hook, ip_nat_sdp_addr); rcu_assign_pointer_nonull(nf_nat_sdp_port_hook, ip_nat_sdp_port); rcu_assign_pointer_nonull(nf_nat_sdp_session_hook, ip_nat_sdp_session); rcu_assign_pointer_nonull(nf_nat_sdp_media_hook, ip_nat_sdp_media); return 0; }
void nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *l4proto) { struct net *net; BUG_ON(l4proto->l3proto >= PF_MAX); mutex_lock(&nf_ct_proto_mutex); BUG_ON(nf_ct_protos[l4proto->l3proto][l4proto->l4proto] != l4proto); rcu_assign_pointer_nonull(nf_ct_protos[l4proto->l3proto][l4proto->l4proto], &nf_conntrack_l4proto_generic); nf_ct_l4proto_unregister_sysctl(l4proto); mutex_unlock(&nf_ct_proto_mutex); synchronize_rcu(); /* Remove all contrack entries for this protocol */ rtnl_lock(); for_each_net(net) nf_ct_iterate_cleanup(net, kill_l4proto, l4proto); rtnl_unlock(); }
void nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto) { struct net *net; BUG_ON(proto->l3proto >= AF_MAX); 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_nonull(nf_ct_l3protos[proto->l3proto], &nf_conntrack_l3proto_generic); nf_ct_l3proto_unregister_sysctl(proto); mutex_unlock(&nf_ct_proto_mutex); synchronize_rcu(); /* Remove all contrack entries for this protocol */ rtnl_lock(); for_each_net(net) nf_ct_iterate_cleanup(net, kill_l3proto, proto); rtnl_unlock(); }
static int __init nf_nat_ftp_init(void) { BUG_ON(nf_nat_ftp_hook != NULL); rcu_assign_pointer_nonull(nf_nat_ftp_hook, nf_nat_ftp); return 0; }