示例#1
0
static int check(const char *tablename,
		 const void *ip,
		 const struct xt_match *match,
		 void *matchinfo,
		 unsigned int hook_mask)
{
	const struct xt_connbytes_info *sinfo = matchinfo;

	if (sinfo->what != XT_CONNBYTES_PKTS &&
	    sinfo->what != XT_CONNBYTES_BYTES &&
	    sinfo->what != XT_CONNBYTES_AVGPKT)
		return 0;

	if (sinfo->direction != XT_CONNBYTES_DIR_ORIGINAL &&
	    sinfo->direction != XT_CONNBYTES_DIR_REPLY &&
	    sinfo->direction != XT_CONNBYTES_DIR_BOTH)
		return 0;

	if (nf_ct_l3proto_try_module_get(match->family) < 0) {
		printk(KERN_WARNING "can't load conntrack support for "
				    "proto=%d\n", match->family);
		return 0;
	}

	return 1;
}
示例#2
0
int nf_nat_l3proto_register(const struct nf_nat_l3proto *l3proto)
{
	int err;

	err = nf_ct_l3proto_try_module_get(l3proto->l3proto);
	if (err < 0)
		return err;

	mutex_lock(&nf_nat_proto_mutex);
	RCU_INIT_POINTER(nf_nat_l4protos[l3proto->l3proto][IPPROTO_TCP],
			 &nf_nat_l4proto_tcp);
	RCU_INIT_POINTER(nf_nat_l4protos[l3proto->l3proto][IPPROTO_UDP],
			 &nf_nat_l4proto_udp);
#ifdef CONFIG_NF_NAT_PROTO_DCCP
	RCU_INIT_POINTER(nf_nat_l4protos[l3proto->l3proto][IPPROTO_DCCP],
			 &nf_nat_l4proto_dccp);
#endif
#ifdef CONFIG_NF_NAT_PROTO_SCTP
	RCU_INIT_POINTER(nf_nat_l4protos[l3proto->l3proto][IPPROTO_SCTP],
			 &nf_nat_l4proto_sctp);
#endif
#ifdef CONFIG_NF_NAT_PROTO_UDPLITE
	RCU_INIT_POINTER(nf_nat_l4protos[l3proto->l3proto][IPPROTO_UDPLITE],
			 &nf_nat_l4proto_udplite);
#endif
	mutex_unlock(&nf_nat_proto_mutex);

	RCU_INIT_POINTER(nf_nat_l3protos[l3proto->l3proto], l3proto);
	return 0;
}
示例#3
0
static bool connsecmark_tg_check(const struct xt_tgchk_param *par)
{
	const struct xt_connsecmark_target_info *info = par->targinfo;

	if (strcmp(par->table, "mangle") != 0 &&
	    strcmp(par->table, "security") != 0) {
		printk(KERN_INFO PFX "target only valid in the \'mangle\' "
		       "or \'security\' tables, not \'%s\'.\n", par->table);
		return false;
	}

	switch (info->mode) {
	case CONNSECMARK_SAVE:
	case CONNSECMARK_RESTORE:
		break;

	default:
		printk(KERN_INFO PFX "invalid mode: %hu\n", info->mode);
		return false;
	}

	if (nf_ct_l3proto_try_module_get(par->family) < 0) {
		printk(KERN_WARNING "can't load conntrack support for "
				    "proto=%u\n", par->family);
		return false;
	}
	return true;
}
示例#4
0
static bool connbytes_mt_check(const struct xt_mtchk_param *par)
{
	const struct xt_connbytes_info *sinfo = par->matchinfo;

	if (sinfo->what != XT_CONNBYTES_PKTS &&
	    sinfo->what != XT_CONNBYTES_BYTES &&
	    sinfo->what != XT_CONNBYTES_AVGPKT)
		return false;

	if (sinfo->direction != XT_CONNBYTES_DIR_ORIGINAL &&
	    sinfo->direction != XT_CONNBYTES_DIR_REPLY &&
	    sinfo->direction != XT_CONNBYTES_DIR_BOTH)
		return false;

	if (nf_ct_l3proto_try_module_get(par->family) < 0) {
		printk(KERN_WARNING "can't load conntrack support for "
				    "proto=%u\n", par->family);
		return false;
	}

	/*
	 * This filter cannot function correctly unless connection tracking
	 * accounting is enabled, so complain in the hope that someone notices.
	 */
	if (!nf_ct_acct_enabled(&init_net)) {
		pr_warning("Forcing CT accounting to be enabled\n");
		nf_ct_set_acct(&init_net, true);
	}

	return true;
}
示例#5
0
static int connsecmark_tg_check(const struct xt_tgchk_param *par)
{
	const struct xt_connsecmark_target_info *info = par->targinfo;
	int ret;

	if (strcmp(par->table, "mangle") != 0 &&
	    strcmp(par->table, "security") != 0) {
		pr_info("target only valid in the \'mangle\' "
			"or \'security\' tables, not \'%s\'.\n", par->table);
		return -EINVAL;
	}

	switch (info->mode) {
	case CONNSECMARK_SAVE:
	case CONNSECMARK_RESTORE:
		break;

	default:
		pr_info("invalid mode: %hu\n", info->mode);
		return -EINVAL;
	}

	ret = nf_ct_l3proto_try_module_get(par->family);
	if (ret < 0)
		pr_info("cannot load conntrack support for proto=%u\n",
			par->family);
	return ret;
}
示例#6
0
static int connbytes_mt_check(const struct xt_mtchk_param *par)
{
    const struct xt_connbytes_info *sinfo = par->matchinfo;
    int ret;

    if (sinfo->what != XT_CONNBYTES_PKTS &&
            sinfo->what != XT_CONNBYTES_BYTES &&
            sinfo->what != XT_CONNBYTES_AVGPKT)
        return -EINVAL;

    if (sinfo->direction != XT_CONNBYTES_DIR_ORIGINAL &&
            sinfo->direction != XT_CONNBYTES_DIR_REPLY &&
            sinfo->direction != XT_CONNBYTES_DIR_BOTH)
        return -EINVAL;

    ret = nf_ct_l3proto_try_module_get(par->family);
    if (ret < 0)
        pr_info("cannot load conntrack support for proto=%u\n",
                par->family);

    /*
     * This filter cannot function correctly unless connection tracking
     * accounting is enabled, so complain in the hope that someone notices.
     */
    if (!nf_ct_acct_enabled(par->net)) {
        pr_warning("Forcing CT accounting to be enabled\n");
        nf_ct_set_acct(par->net, true);
    }

    return ret;
}
static int nf_ct_netns_do_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;
}
示例#8
0
static bool
checkentry(const char *tablename,
	   const void *entry,
	   const struct xt_target *target,
	   void *targinfo,
	   unsigned int hook_mask)
{
	const struct xt_connmark_target_info *matchinfo = targinfo;

	if (nf_ct_l3proto_try_module_get(target->family) < 0) {
		printk(KERN_WARNING "can't load conntrack support for "
				    "proto=%d\n", target->family);
		return false;
	}
	if (matchinfo->mode == XT_CONNMARK_RESTORE) {
		if (strcmp(tablename, "mangle") != 0) {
			printk(KERN_WARNING "CONNMARK: restore can only be "
			       "called from \"mangle\" table, not \"%s\"\n",
			       tablename);
			return false;
		}
	}
	if (matchinfo->mark > 0xffffffff || matchinfo->mask > 0xffffffff) {
		printk(KERN_WARNING "CONNMARK: Only supports 32bit mark\n");
		return false;
	}
	return true;
}
示例#9
0
文件: xt_CT.c 项目: 19Dan01/linux
static int xt_ct_tg_check(const struct xt_tgchk_param *par,
			  struct xt_ct_target_info_v1 *info)
{
	struct nf_conntrack_tuple t;
	struct nf_conn *ct;
	int ret = -EOPNOTSUPP;

	if (info->flags & XT_CT_NOTRACK) {
		ct = NULL;
		goto out;
	}

#ifndef CONFIG_NF_CONNTRACK_ZONES
	if (info->zone)
		goto err1;
#endif

	ret = nf_ct_l3proto_try_module_get(par->family);
	if (ret < 0)
		goto err1;

	memset(&t, 0, sizeof(t));
	ct = nf_conntrack_alloc(par->net, info->zone, &t, &t, GFP_KERNEL);
	ret = PTR_ERR(ct);
	if (IS_ERR(ct))
		goto err2;

	ret = 0;
	if ((info->ct_events || info->exp_events) &&
	    !nf_ct_ecache_ext_add(ct, info->ct_events, info->exp_events,
				  GFP_KERNEL)) {
		ret = -EINVAL;
		goto err3;
	}

	if (info->helper[0]) {
		ret = xt_ct_set_helper(ct, info->helper, par);
		if (ret < 0)
			goto err3;
	}

	if (info->timeout[0]) {
		ret = xt_ct_set_timeout(ct, par, info->timeout);
		if (ret < 0)
			goto err3;
	}

	nf_conntrack_tmpl_insert(par->net, ct);
out:
	info->ct = ct;
	return 0;

err3:
	nf_conntrack_free(ct);
err2:
	nf_ct_l3proto_module_put(par->family);
err1:
	return ret;
}
示例#10
0
文件: xt_state.c 项目: Arakmar/G3MOD
static int state_mt_check(const struct xt_mtchk_param *par)
{
	if (nf_ct_l3proto_try_module_get(par->match->family) < 0) {
		printk(KERN_WARNING "can't load conntrack support for "
				    "proto=%u\n", par->match->family);
		return false;
	}
	return true;
}
示例#11
0
static bool connmark_tg_check(const struct xt_tgchk_param *par)
{
	if (nf_ct_l3proto_try_module_get(par->family) < 0) {
		printk(KERN_WARNING "cannot load conntrack support for "
		       "proto=%u\n", par->family);
		return false;
	}
	return true;
}
示例#12
0
static int state_mt_check(const struct xt_mtchk_param *par)
{
	int ret;

	ret = nf_ct_l3proto_try_module_get(par->family);
	if (ret < 0)
		pr_info("cannot load conntrack support for proto=%u\n",
			par->family);
	return ret;
}
示例#13
0
int nat64_tg_check(const struct xt_tgchk_param *par)
{
    int ret;

    ret = nf_ct_l3proto_try_module_get(par->family);
    if (ret < 0)
        pr_info("cannot load support for proto=%u\n",
                par->family);
    return ret;
}
示例#14
0
static int synproxy_tg4_check(const struct xt_tgchk_param *par)
{
    const struct ipt_entry *e = par->entryinfo;

    if (e->ip.proto != IPPROTO_TCP ||
            e->ip.invflags & XT_INV_PROTO)
        return -EINVAL;

    return nf_ct_l3proto_try_module_get(par->family);
}
示例#15
0
static bool
conntrack_mt_check(const char *tablename, const void *ip,
                   const struct xt_match *match, void *matchinfo,
                   unsigned int hook_mask)
{
    if (nf_ct_l3proto_try_module_get(match->family) < 0) {
        printk(KERN_WARNING "can't load conntrack support for "
                    "proto=%u\n", match->family);
        return false;
    }
    return true;
}
static int helper_mt_check(const struct xt_mtchk_param *par)
{
	struct xt_helper_info *info = par->matchinfo;

	if (nf_ct_l3proto_try_module_get(par->family) < 0) {
		printk(KERN_WARNING "can't load conntrack support for "
				    "proto=%u\n", par->family);
		return false;
	}
	info->name[29] = '\0';
	return true;
}
示例#17
0
static int helper_mt_check(const struct xt_mtchk_param *par)
{
	struct xt_helper_info *info = par->matchinfo;
	int ret;

	ret = nf_ct_l3proto_try_module_get(par->family);
	if (ret < 0) {
		pr_info("cannot load conntrack support for proto=%u\n",
			par->family);
		return ret;
	}
	info->name[29] = '\0';
	return 0;
}
示例#18
0
static int nft_ct_l3proto_try_module_get(uint8_t family)
{
    int err;

    if (family == NFPROTO_INET) {
        err = nf_ct_l3proto_try_module_get(NFPROTO_IPV4);
        if (err < 0)
            goto err1;
        err = nf_ct_l3proto_try_module_get(NFPROTO_IPV6);
        if (err < 0)
            goto err2;
    } else {
        err = nf_ct_l3proto_try_module_get(family);
        if (err < 0)
            goto err1;
    }
    return 0;

err2:
    nf_ct_l3proto_module_put(NFPROTO_IPV4);
err1:
    return err;
}
示例#19
0
static bool connmark_mt_check_v0(const struct xt_mtchk_param *par)
{
	const struct xt_connmark_info *cm = par->matchinfo;

	if (cm->mark > 0xffffffff || cm->mask > 0xffffffff) {
		printk(KERN_WARNING "connmark: only support 32bit mark\n");
		return false;
	}
	if (nf_ct_l3proto_try_module_get(par->family) < 0) {
		printk(KERN_WARNING "can't load conntrack support for "
				    "proto=%u\n", par->family);
		return false;
	}
	return true;
}
示例#20
0
static int
checkentry(const char *tablename,
	   const void *ip,
	   const struct xt_match *match,
	   void *matchinfo,
	   unsigned int hook_mask)
{
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
	if (nf_ct_l3proto_try_module_get(match->family) < 0) {
		printk(KERN_WARNING "can't load nf_conntrack support for "
				    "proto=%d\n", match->family);
		return 0;
	}
#endif
	return 1;
}
示例#21
0
int nf_nat_l3proto_register(const struct nf_nat_l3proto *l3proto)
{
	int err;

	err = nf_ct_l3proto_try_module_get(l3proto->l3proto);
	if (err < 0)
		return err;

	mutex_lock(&nf_nat_proto_mutex);
	RCU_INIT_POINTER(nf_nat_l4protos[l3proto->l3proto][IPPROTO_TCP],
			 &nf_nat_l4proto_tcp);
	RCU_INIT_POINTER(nf_nat_l4protos[l3proto->l3proto][IPPROTO_UDP],
			 &nf_nat_l4proto_udp);
	mutex_unlock(&nf_nat_proto_mutex);

	RCU_INIT_POINTER(nf_nat_l3protos[l3proto->l3proto], l3proto);
	return 0;
}
示例#22
0
static int
checkentry(const char *tablename,
	   const void *ip,
	   const struct xt_match *match,
	   void *matchinfo,
	   unsigned int hook_mask)
{
	struct xt_connmark_info *cm = matchinfo;

	if (cm->mark > 0xffffffff || cm->mask > 0xffffffff) {
		printk(KERN_WARNING "connmark: only support 32bit mark\n");
		return 0;
	}
	if (nf_ct_l3proto_try_module_get(match->family) < 0) {
		printk(KERN_WARNING "can't load conntrack support for "
				    "proto=%d\n", match->family);
		return 0;
	}
	return 1;
}
示例#23
0
static bool csecmark_tg_check(const struct xt_tgchk_param *par)
{
	const struct xt_connsecmark_target_info *info = par->targinfo;

	if (nf_ct_l3proto_try_module_get(par->family) < 0) {
		printk(KERN_WARNING "can't load conntrack support for "
				    "proto=%u\n", par->family);
		return false;
	}
	switch (info->mode) {
	case CONNSECMARK_SAVE:
	case CONNSECMARK_RESTORE:
		break;

	default:
		printk(KERN_INFO PFX "invalid mode: %hu\n", info->mode);
		return false;
	}

	return true;
}
示例#24
0
static int connbytes_mt_check(const struct xt_mtchk_param *par)
{
	const struct xt_connbytes_info *sinfo = par->matchinfo;
	int ret;

	if (sinfo->what != XT_CONNBYTES_PKTS &&
	    sinfo->what != XT_CONNBYTES_BYTES &&
	    sinfo->what != XT_CONNBYTES_AVGPKT)
		return -EINVAL;

	if (sinfo->direction != XT_CONNBYTES_DIR_ORIGINAL &&
	    sinfo->direction != XT_CONNBYTES_DIR_REPLY &&
	    sinfo->direction != XT_CONNBYTES_DIR_BOTH)
		return -EINVAL;

	ret = nf_ct_l3proto_try_module_get(par->family);
	if (ret < 0)
		pr_info("cannot load conntrack support for proto=%u\n",
			par->family);
	return ret;
}
示例#25
0
static int connbytes_mt_check(const struct xt_mtchk_param *par)
{
	const struct xt_connbytes_info *sinfo = par->matchinfo;

	if (sinfo->what != XT_CONNBYTES_PKTS &&
	    sinfo->what != XT_CONNBYTES_BYTES &&
	    sinfo->what != XT_CONNBYTES_AVGPKT)
		return false;

	if (sinfo->direction != XT_CONNBYTES_DIR_ORIGINAL &&
	    sinfo->direction != XT_CONNBYTES_DIR_REPLY &&
	    sinfo->direction != XT_CONNBYTES_DIR_BOTH)
		return false;

	if (nf_ct_l3proto_try_module_get(par->family) < 0) {
		printk(KERN_WARNING "can't load conntrack support for "
				    "proto=%u\n", par->family);
		return false;
	}

	return true;
}
示例#26
0
static bool checkentry(const char *tablename, const void *entry,
		       const struct xt_target *target, void *targinfo,
		       unsigned int hook_mask)
{
	const struct xt_connsecmark_target_info *info = targinfo;

	if (nf_ct_l3proto_try_module_get(target->family) < 0) {
		printk(KERN_WARNING "can't load conntrack support for "
				    "proto=%d\n", target->family);
		return false;
	}
	switch (info->mode) {
	case CONNSECMARK_SAVE:
	case CONNSECMARK_RESTORE:
		break;

	default:
		printk(KERN_INFO PFX "invalid mode: %hu\n", info->mode);
		return false;
	}

	return true;
}
static int nft_ct_init(const struct nft_ctx *ctx,
		       const struct nft_expr *expr,
		       const struct nlattr * const tb[])
{
	struct nft_ct *priv = nft_expr_priv(expr);
	int err;

	if (tb[NFTA_CT_DREG] == NULL ||
	    tb[NFTA_CT_KEY] == NULL)
		return -EINVAL;

	priv->key = ntohl(nla_get_be32(tb[NFTA_CT_KEY]));
	if (tb[NFTA_CT_DIRECTION] != NULL) {
		priv->dir = nla_get_u8(tb[NFTA_CT_DIRECTION]);
		switch (priv->dir) {
		case IP_CT_DIR_ORIGINAL:
		case IP_CT_DIR_REPLY:
			break;
		default:
			return -EINVAL;
		}
	}

	switch (priv->key) {
	case NFT_CT_STATE:
	case NFT_CT_DIRECTION:
	case NFT_CT_STATUS:
#ifdef CONFIG_NF_CONNTRACK_MARK
	case NFT_CT_MARK:
#endif
#ifdef CONFIG_NF_CONNTRACK_SECMARK
	case NFT_CT_SECMARK:
#endif
	case NFT_CT_EXPIRATION:
	case NFT_CT_HELPER:
		if (tb[NFTA_CT_DIRECTION] != NULL)
			return -EINVAL;
		break;
	case NFT_CT_PROTOCOL:
	case NFT_CT_SRC:
	case NFT_CT_DST:
	case NFT_CT_PROTO_SRC:
	case NFT_CT_PROTO_DST:
		if (tb[NFTA_CT_DIRECTION] == NULL)
			return -EINVAL;
		break;
	default:
		return -EOPNOTSUPP;
	}

	err = nf_ct_l3proto_try_module_get(ctx->afi->family);
	if (err < 0)
		return err;
	priv->family = ctx->afi->family;

	priv->dreg = ntohl(nla_get_be32(tb[NFTA_CT_DREG]));
	err = nft_validate_output_register(priv->dreg);
	if (err < 0)
		goto err1;

	err = nft_validate_data_load(ctx, priv->dreg, NULL, NFT_DATA_VALUE);
	if (err < 0)
		goto err1;
	return 0;

err1:
	nf_ct_l3proto_module_put(ctx->afi->family);
	return err;
}
示例#28
0
static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par)
{
	struct xt_ct_target_info_v1 *info = par->targinfo;
	struct nf_conntrack_tuple t;
	struct nf_conn_help *help;
	struct nf_conn *ct;
	int ret = 0;
	u8 proto;
#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
	struct ctnl_timeout *timeout;
#endif
	if (info->flags & ~XT_CT_NOTRACK)
		return -EINVAL;

	if (info->flags & XT_CT_NOTRACK) {
		ct = nf_ct_untracked_get();
		atomic_inc(&ct->ct_general.use);
		goto out;
	}

#ifndef CONFIG_NF_CONNTRACK_ZONES
	if (info->zone)
		goto err1;
#endif

	ret = nf_ct_l3proto_try_module_get(par->family);
	if (ret < 0)
		goto err1;

	memset(&t, 0, sizeof(t));
	ct = nf_conntrack_alloc(par->net, info->zone, &t, &t, GFP_KERNEL);
	ret = PTR_ERR(ct);
	if (IS_ERR(ct))
		goto err2;

	ret = 0;
	if ((info->ct_events || info->exp_events) &&
	    !nf_ct_ecache_ext_add(ct, info->ct_events, info->exp_events,
				  GFP_KERNEL))
		goto err3;

	if (info->helper[0]) {
		ret = -ENOENT;
		proto = xt_ct_find_proto(par);
		if (!proto) {
			pr_info("You must specify a L4 protocol, "
				"and not use inversions on it.\n");
			goto err3;
		}

		ret = -ENOMEM;
		help = nf_ct_helper_ext_add(ct, GFP_KERNEL);
		if (help == NULL)
			goto err3;

		ret = -ENOENT;
		help->helper = nf_conntrack_helper_try_module_get(info->helper,
								  par->family,
								  proto);
		if (help->helper == NULL) {
			pr_info("No such helper \"%s\"\n", info->helper);
			goto err3;
		}
	}

#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
	if (info->timeout[0]) {
		typeof(nf_ct_timeout_find_get_hook) timeout_find_get;
		struct nf_conn_timeout *timeout_ext;

		rcu_read_lock();
		timeout_find_get =
			rcu_dereference(nf_ct_timeout_find_get_hook);

		if (timeout_find_get) {
			const struct ipt_entry *e = par->entryinfo;
			struct nf_conntrack_l4proto *l4proto;

			if (e->ip.invflags & IPT_INV_PROTO) {
				ret = -EINVAL;
				pr_info("You cannot use inversion on "
					 "L4 protocol\n");
				goto err4;
			}
			timeout = timeout_find_get(info->timeout);
			if (timeout == NULL) {
				ret = -ENOENT;
				pr_info("No such timeout policy \"%s\"\n",
					info->timeout);
				goto err4;
			}
			if (timeout->l3num != par->family) {
				ret = -EINVAL;
				pr_info("Timeout policy `%s' can only be "
					"used by L3 protocol number %d\n",
					info->timeout, timeout->l3num);
				goto err5;
			}
			/* Make sure the timeout policy matches any existing
			 * protocol tracker, otherwise default to generic.
			 */
			l4proto = __nf_ct_l4proto_find(par->family,
						       e->ip.proto);
			if (timeout->l4proto->l4proto != l4proto->l4proto) {
				ret = -EINVAL;
				pr_info("Timeout policy `%s' can only be "
					"used by L4 protocol number %d\n",
					info->timeout,
					timeout->l4proto->l4proto);
				goto err5;
			}
			timeout_ext = nf_ct_timeout_ext_add(ct, timeout,
							    GFP_ATOMIC);
			if (timeout_ext == NULL) {
				ret = -ENOMEM;
				goto err5;
			}
		} else {
			ret = -ENOENT;
			pr_info("Timeout policy base is empty\n");
			goto err4;
		}
		rcu_read_unlock();
	}
#endif

	__set_bit(IPS_TEMPLATE_BIT, &ct->status);
	__set_bit(IPS_CONFIRMED_BIT, &ct->status);
out:
	info->ct = ct;
	return 0;

#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
err5:
	__xt_ct_tg_timeout_put(timeout);
err4:
	rcu_read_unlock();
#endif
err3:
	nf_conntrack_free(ct);
err2:
	nf_ct_l3proto_module_put(par->family);
err1:
	return ret;
}
示例#29
0
static int xt_ct_tg_check(const struct xt_tgchk_param *par)
{
    struct xt_ct_target_info *info = par->targinfo;
    struct nf_conntrack_tuple t;
    struct nf_conn_help *help;
    struct nf_conn *ct;
    int ret = 0;
    u8 proto;

    if (info->flags & ~XT_CT_NOTRACK)
        return -EINVAL;

    if (info->flags & XT_CT_NOTRACK) {
        ct = nf_ct_untracked_get();
        atomic_inc(&ct->ct_general.use);
        goto out;
    }

#ifndef CONFIG_NF_CONNTRACK_ZONES
    if (info->zone)
        goto err1;
#endif

    ret = nf_ct_l3proto_try_module_get(par->family);
    if (ret < 0)
        goto err1;

    memset(&t, 0, sizeof(t));
    ct = nf_conntrack_alloc(par->net, info->zone, &t, &t, GFP_KERNEL);
    ret = PTR_ERR(ct);
    if (IS_ERR(ct))
        goto err2;

    ret = 0;
    if ((info->ct_events || info->exp_events) &&
            !nf_ct_ecache_ext_add(ct, info->ct_events, info->exp_events,
                                  GFP_KERNEL))
        goto err3;

    if (info->helper[0]) {
        ret = -ENOENT;
        proto = xt_ct_find_proto(par);
        if (!proto)
            goto err3;

        ret = -ENOMEM;
        help = nf_ct_helper_ext_add(ct, GFP_KERNEL);
        if (help == NULL)
            goto err3;

        ret = -ENOENT;
        help->helper = nf_conntrack_helper_try_module_get(info->helper,
                       par->family,
                       proto);
        if (help->helper == NULL)
            goto err3;
    }

    __set_bit(IPS_TEMPLATE_BIT, &ct->status);
    __set_bit(IPS_CONFIRMED_BIT, &ct->status);
out:
    info->ct = ct;
    return 0;

err3:
    nf_conntrack_free(ct);
err2:
    nf_ct_l3proto_module_put(par->family);
err1:
    return ret;
}