Ejemplo n.º 1
0
struct nf_conn_colo *
nf_ct_colo_get(struct sk_buff *skb, struct colo_node *node, u32 flag)
{
	enum ip_conntrack_info ctinfo;
	struct nf_conn *ct;
	struct nf_conn_colo *colo_conn;

	ct = nf_ct_get(skb, &ctinfo);

	if (ct == NULL || ct == nf_ct_untracked_get()) {
		return NULL;
	}

	colo_conn = nfct_colo(ct);
	if (colo_conn == NULL) {
		colo_conn = nfct_create_colo(ct, node->vm_pid, flag);
		if (colo_conn == NULL) {
			pr_dbg("create colo conn failed!\n");
			return NULL;
		}

		nfct_init_colo(colo_conn, node->vm_pid, flag);
		pr_dbg("colo_tg: create conn %p for contrack %p node:%d,\n",
		       colo_conn, ct, node->vm_pid);
	}

	return colo_conn;
}
Ejemplo n.º 2
0
static unsigned int
tee_tg6(struct sk_buff *skb, const struct xt_action_param *par)
{
	const struct xt_tee_tginfo *info = par->targinfo;

	if (percpu_read(tee_active))
		return XT_CONTINUE;
	skb = pskb_copy(skb, GFP_ATOMIC);
	if (skb == NULL)
		return XT_CONTINUE;

#ifdef WITH_CONNTRACK
	nf_conntrack_put(skb->nfct);
	skb->nfct     = &nf_ct_untracked_get()->ct_general;
	skb->nfctinfo = IP_CT_NEW;
	nf_conntrack_get(skb->nfct);
#endif
	if (par->hooknum == NF_INET_PRE_ROUTING ||
	    par->hooknum == NF_INET_LOCAL_IN) {
		struct ipv6hdr *iph = ipv6_hdr(skb);
		--iph->hop_limit;
	}
	if (tee_tg_route6(skb, info)) {
		percpu_write(tee_active, true);
		ip6_local_out(skb);
		percpu_write(tee_active, false);
	} else {
		kfree_skb(skb);
	}
	return XT_CONTINUE;
}
Ejemplo n.º 3
0
void nf_dup_ipv6(struct net *net, struct sk_buff *skb, unsigned int hooknum,
		 const struct in6_addr *gw, int oif)
{
	if (this_cpu_read(nf_skb_duplicated))
		return;
	skb = pskb_copy(skb, GFP_ATOMIC);
	if (skb == NULL)
		return;

#if IS_ENABLED(CONFIG_NF_CONNTRACK)
	nf_conntrack_put(skb->nfct);
	skb->nfct     = &nf_ct_untracked_get()->ct_general;
	skb->nfctinfo = IP_CT_NEW;
	nf_conntrack_get(skb->nfct);
#endif
	if (hooknum == NF_INET_PRE_ROUTING ||
	    hooknum == NF_INET_LOCAL_IN) {
		struct ipv6hdr *iph = ipv6_hdr(skb);
		--iph->hop_limit;
	}
	if (nf_dup_ipv6_route(net, skb, gw, oif)) {
		__this_cpu_write(nf_skb_duplicated, true);
		ip6_local_out(net, skb->sk, skb);
		__this_cpu_write(nf_skb_duplicated, false);
	} else {
		kfree_skb(skb);
	}
}
Ejemplo n.º 4
0
static unsigned int
notrack_tg(struct sk_buff *skb, const struct xt_action_param *par)
{
	/* Previously seen (loopback)? Ignore. */
	if (skb->nfct != NULL)
		return XT_CONTINUE;

	skb->nfct = &nf_ct_untracked_get()->ct_general;
	skb->nfctinfo = IP_CT_NEW;
	nf_conntrack_get(skb->nfct);

	return XT_CONTINUE;
}
Ejemplo n.º 5
0
static unsigned int
tee_tg4(struct sk_buff *skb, const struct xt_action_param *par)
{
	const struct xt_tee_tginfo *info = par->targinfo;
	struct iphdr *iph;

	if (percpu_read(tee_active))
		return XT_CONTINUE;
	/*
	 * Copy the skb, and route the copy. Will later return %XT_CONTINUE for
	 * the original skb, which should continue on its way as if nothing has
	 * happened. The copy should be independently delivered to the TEE
	 * --gateway.
	 */
	skb = pskb_copy(skb, GFP_ATOMIC);
	if (skb == NULL)
		return XT_CONTINUE;

#ifdef WITH_CONNTRACK
	/* Avoid counting cloned packets towards the original connection. */
	nf_conntrack_put(skb->nfct);
	skb->nfct     = &nf_ct_untracked_get()->ct_general;
	skb->nfctinfo = IP_CT_NEW;
	nf_conntrack_get(skb->nfct);
#endif
	/*
	 * If we are in PREROUTING/INPUT, the checksum must be recalculated
	 * since the length could have changed as a result of defragmentation.
	 *
	 * We also decrease the TTL to mitigate potential TEE loops
	 * between two hosts.
	 *
	 * Set %IP_DF so that the original source is notified of a potentially
	 * decreased MTU on the clone route. IPv6 does this too.
	 */
	iph = ip_hdr(skb);
	iph->frag_off |= htons(IP_DF);
	if (par->hooknum == NF_INET_PRE_ROUTING ||
	    par->hooknum == NF_INET_LOCAL_IN)
		--iph->ttl;
	ip_send_check(iph);

	if (tee_tg_route4(skb, info)) {
		percpu_write(tee_active, true);
		ip_local_out(skb);
		percpu_write(tee_active, false);
	} else {
		kfree_skb(skb);
	}
	return XT_CONTINUE;
}
Ejemplo n.º 6
0
static inline int xt_ct_target(struct sk_buff *skb, struct nf_conn *ct)
{
	/* Previously seen (loopback)? Ignore. */
	if (skb->nfct != NULL)
		return XT_CONTINUE;

	/* special case the untracked ct : we want the percpu object */
	if (!ct)
		ct = nf_ct_untracked_get();
	atomic_inc(&ct->ct_general.use);
	skb->nfct = &ct->ct_general;
	skb->nfctinfo = IP_CT_NEW;

	return XT_CONTINUE;
}
Ejemplo n.º 7
0
void nf_dup_ipv4(struct net *net, struct sk_buff *skb, unsigned int hooknum,
		 const struct in_addr *gw, int oif)
{
	struct iphdr *iph;

	if (this_cpu_read(nf_skb_duplicated))
		return;
	/*
	 * Copy the skb, and route the copy. Will later return %XT_CONTINUE for
	 * the original skb, which should continue on its way as if nothing has
	 * happened. The copy should be independently delivered to the gateway.
	 */
	skb = pskb_copy(skb, GFP_ATOMIC);
	if (skb == NULL)
		return;

#if IS_ENABLED(CONFIG_NF_CONNTRACK)
	/* Avoid counting cloned packets towards the original connection. */
	nf_conntrack_put(skb->nfct);
	skb->nfct     = &nf_ct_untracked_get()->ct_general;
	skb->nfctinfo = IP_CT_NEW;
	nf_conntrack_get(skb->nfct);
#endif
	/*
	 * If we are in PREROUTING/INPUT, the checksum must be recalculated
	 * since the length could have changed as a result of defragmentation.
	 *
	 * We also decrease the TTL to mitigate potential loops between two
	 * hosts.
	 *
	 * Set %IP_DF so that the original source is notified of a potentially
	 * decreased MTU on the clone route. IPv6 does this too.
	 */
	iph = ip_hdr(skb);
	iph->frag_off |= htons(IP_DF);
	if (hooknum == NF_INET_PRE_ROUTING ||
	    hooknum == NF_INET_LOCAL_IN)
		--iph->ttl;
	ip_send_check(iph);

	if (nf_dup_ipv4_route(net, skb, gw, oif)) {
		__this_cpu_write(nf_skb_duplicated, true);
		ip_local_out(net, skb->sk, skb);
		__this_cpu_write(nf_skb_duplicated, false);
	} else {
		kfree_skb(skb);
	}
}
Ejemplo n.º 8
0
static unsigned int
notrack_tg(struct sk_buff *skb, const struct xt_action_param *par)
{
	/* Previously seen (loopback)? Ignore. */
	if (skb->nfct != NULL)
		return XT_CONTINUE;

	/* Attach fake conntrack entry.
	   If there is a real ct entry correspondig to this packet,
	   it'll hang aroun till timing out. We don't deal with it
	   for performance reasons. JK */
	skb->nfct = &nf_ct_untracked_get()->ct_general;
	skb->nfctinfo = IP_CT_NEW;
	nf_conntrack_get(skb->nfct);

	return XT_CONTINUE;
}
static int
icmpv6_error(struct net *net, struct nf_conn *tmpl,
	     struct sk_buff *skb, unsigned int dataoff,
	     enum ip_conntrack_info *ctinfo, u_int8_t pf, unsigned int hooknum)
{
	const struct icmp6hdr *icmp6h;
	struct icmp6hdr _ih;
	int type;

	icmp6h = skb_header_pointer(skb, dataoff, sizeof(_ih), &_ih);
	if (icmp6h == NULL) {
		if (LOG_INVALID(net, IPPROTO_ICMPV6))
		nf_log_packet(PF_INET6, 0, skb, NULL, NULL, NULL,
			      "nf_ct_icmpv6: short packet ");
		return -NF_ACCEPT;
	}

	if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING &&
	    nf_ip6_checksum(skb, hooknum, dataoff, IPPROTO_ICMPV6)) {
		if (LOG_INVALID(net, IPPROTO_ICMPV6))
			nf_log_packet(PF_INET6, 0, skb, NULL, NULL, NULL,
				      "nf_ct_icmpv6: ICMPv6 checksum failed ");
		return -NF_ACCEPT;
	}

	type = icmp6h->icmp6_type - 130;
	if (type >= 0 && type < sizeof(noct_valid_new) &&
	    noct_valid_new[type]) {
		skb->nfct = &nf_ct_untracked_get()->ct_general;
		skb->nfctinfo = IP_CT_NEW;
		nf_conntrack_get(skb->nfct);
		return NF_ACCEPT;
	}

	
	if (icmp6h->icmp6_type >= 128)
		return NF_ACCEPT;

	return icmpv6_error_message(net, tmpl, skb, dataoff, ctinfo, hooknum);
}
Ejemplo n.º 10
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;
}
Ejemplo n.º 11
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;
}