Exemplo n.º 1
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;

	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;
}
Exemplo n.º 3
0
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;
}
Exemplo n.º 4
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_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;
}
Exemplo n.º 9
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;
}