static int __init nf_conntrack_l3proto_ipv6_init(void)
{
	int ret = 0;

	need_conntrack();

	ret = nf_ct_frag6_init();
	if (ret < 0) {
		printk("nf_conntrack_ipv6: can't initialize frag6.\n");
		return ret;
	}
	ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_tcp6);
	if (ret < 0) {
		printk("nf_conntrack_ipv6: can't register tcp.\n");
		goto cleanup_frag6;
	}

	ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udp6);
	if (ret < 0) {
		printk("nf_conntrack_ipv6: can't register udp.\n");
		goto cleanup_tcp;
	}

	ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_icmpv6);
	if (ret < 0) {
		printk("nf_conntrack_ipv6: can't register icmpv6.\n");
		goto cleanup_udp;
	}

	ret = nf_conntrack_l3proto_register(&nf_conntrack_l3proto_ipv6);
	if (ret < 0) {
		printk("nf_conntrack_ipv6: can't register ipv6\n");
		goto cleanup_icmpv6;
	}

	ret = nf_register_hooks(ipv6_conntrack_ops,
				ARRAY_SIZE(ipv6_conntrack_ops));
	if (ret < 0) {
		printk("nf_conntrack_ipv6: can't register pre-routing defrag "
		       "hook.\n");
		goto cleanup_ipv6;
	}
	return ret;

 cleanup_ipv6:
	nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv6);
 cleanup_icmpv6:
	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_icmpv6);
 cleanup_udp:
	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp6);
 cleanup_tcp:
	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_tcp6);
 cleanup_frag6:
	nf_ct_frag6_cleanup();
	return ret;
}
static void __exit nf_conntrack_l3proto_ipv6_fini(void)
{
	synchronize_net();
	nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops));
	nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv6);
	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_icmpv6);
	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp6);
	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_tcp6);
	nf_ct_frag6_cleanup();
}
static void ipv4_net_exit(struct net *net)
{
	nf_conntrack_l3proto_unregister(net,
					&nf_conntrack_l3proto_ipv4);
	nf_conntrack_l4proto_unregister(net,
					&nf_conntrack_l4proto_icmp);
	nf_conntrack_l4proto_unregister(net,
					&nf_conntrack_l4proto_udp4);
	nf_conntrack_l4proto_unregister(net,
					&nf_conntrack_l4proto_tcp4);
}
static void __exit nf_conntrack_l3proto_ipv4_fini(void)
{
	synchronize_net();
#if defined(CONFIG_PROC_FS) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT)
	nf_conntrack_ipv4_compat_fini();
#endif
	nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops));
	nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4);
	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_icmp);
	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp4);
	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_tcp4);
	nf_unregister_sockopt(&so_getorigdst);
}
static int ipv4_net_init(struct net *net)
{
	int ret = 0;

	ret = nf_conntrack_l4proto_register(net,
					    &nf_conntrack_l4proto_tcp4);
	if (ret < 0) {
		pr_err("nf_conntrack_l4proto_tcp4 :protocol register failed\n");
		goto out_tcp;
	}
	ret = nf_conntrack_l4proto_register(net,
					    &nf_conntrack_l4proto_udp4);
	if (ret < 0) {
		pr_err("nf_conntrack_l4proto_udp4 :protocol register failed\n");
		goto out_udp;
	}
	ret = nf_conntrack_l4proto_register(net,
					    &nf_conntrack_l4proto_icmp);
	if (ret < 0) {
		pr_err("nf_conntrack_l4proto_icmp4 :protocol register failed\n");
		goto out_icmp;
	}
	ret = nf_conntrack_l3proto_register(net,
					    &nf_conntrack_l3proto_ipv4);
	if (ret < 0) {
		pr_err("nf_conntrack_l3proto_ipv4 :protocol register failed\n");
		goto out_ipv4;
	}
	return 0;
out_ipv4:
	nf_conntrack_l4proto_unregister(net,
					&nf_conntrack_l4proto_icmp);
out_icmp:
	nf_conntrack_l4proto_unregister(net,
					&nf_conntrack_l4proto_udp4);
out_udp:
	nf_conntrack_l4proto_unregister(net,
					&nf_conntrack_l4proto_tcp4);
out_tcp:
	return ret;
}
static int __init nf_conntrack_proto_udplite_init(void)
{
	int err;

	err = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udplite4);
	if (err < 0)
		goto err1;
	err = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udplite6);
	if (err < 0)
		goto err2;
	return 0;
err2:
	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udplite4);
err1:
	return err;
}
static int __init nf_conntrack_proto_dccp_init(void)
{
	int err;

	err = nf_conntrack_l4proto_register(&dccp_proto4);
	if (err < 0)
		goto err1;

	err = nf_conntrack_l4proto_register(&dccp_proto6);
	if (err < 0)
		goto err2;
	return 0;

err2:
	nf_conntrack_l4proto_unregister(&dccp_proto4);
err1:
	return err;
}
static int __init nf_conntrack_proto_dccp_init(void)
{
	int err;

	err = register_pernet_subsys(&dccp_net_ops);
	if (err < 0)
		goto err1;

	err = nf_conntrack_l4proto_register(&dccp_proto4);
	if (err < 0)
		goto err2;

	err = nf_conntrack_l4proto_register(&dccp_proto6);
	if (err < 0)
		goto err3;
	return 0;

err3:
	nf_conntrack_l4proto_unregister(&dccp_proto4);
err2:
	unregister_pernet_subsys(&dccp_net_ops);
err1:
	return err;
}
static void __exit nf_conntrack_proto_dccp_fini(void)
{
	unregister_pernet_subsys(&dccp_net_ops);
	nf_conntrack_l4proto_unregister(&dccp_proto6);
	nf_conntrack_l4proto_unregister(&dccp_proto4);
}
static int __init nf_conntrack_l3proto_ipv4_init(void)
{
	int ret = 0;

	need_conntrack();
	nf_defrag_ipv4_enable();

	ret = nf_register_sockopt(&so_getorigdst);
	if (ret < 0) {
		printk(KERN_ERR "Unable to register netfilter socket option\n");
		return ret;
	}

	ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_tcp4);
	if (ret < 0) {
		pr_err("nf_conntrack_ipv4: can't register tcp.\n");
		goto cleanup_sockopt;
	}

	ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udp4);
	if (ret < 0) {
		pr_err("nf_conntrack_ipv4: can't register udp.\n");
		goto cleanup_tcp;
	}

	ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_icmp);
	if (ret < 0) {
		pr_err("nf_conntrack_ipv4: can't register icmp.\n");
		goto cleanup_udp;
	}

	ret = nf_conntrack_l3proto_register(&nf_conntrack_l3proto_ipv4);
	if (ret < 0) {
		pr_err("nf_conntrack_ipv4: can't register ipv4\n");
		goto cleanup_icmp;
	}

	ret = nf_register_hooks(ipv4_conntrack_ops,
				ARRAY_SIZE(ipv4_conntrack_ops));
	if (ret < 0) {
		pr_err("nf_conntrack_ipv4: can't register hooks.\n");
		goto cleanup_ipv4;
	}
#if defined(CONFIG_PROC_FS) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT)
	ret = nf_conntrack_ipv4_compat_init();
	if (ret < 0)
		goto cleanup_hooks;
#endif
	return ret;
#if defined(CONFIG_PROC_FS) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT)
 cleanup_hooks:
	nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops));
#endif
 cleanup_ipv4:
	nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4);
 cleanup_icmp:
	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_icmp);
 cleanup_udp:
	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp4);
 cleanup_tcp:
	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_tcp4);
 cleanup_sockopt:
	nf_unregister_sockopt(&so_getorigdst);
	return ret;
}
示例#11
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) {
		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;
}
static void __exit nf_conntrack_proto_udplite_exit(void)
{
	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udplite6);
	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udplite4);
}
static void __exit nf_conntrack_proto_dccp_fini(void)
{
	nf_conntrack_l4proto_unregister(&dccp_proto6);
	nf_conntrack_l4proto_unregister(&dccp_proto4);
}