Пример #1
0
static int xfrm4_output_one(struct sk_buff *skb)
{
	struct dst_entry *dst = skb->dst;
	struct xfrm_state *x = dst->xfrm;
	int err;
	
	err = skb_checksum_setup(skb);
	if (err)
		goto error_nolock;

	if (skb->ip_summed == CHECKSUM_HW) {
		err = skb_checksum_help(skb, 0);
		if (err)
			goto error_nolock;
	}

	if (x->props.mode) {
		err = xfrm4_tunnel_check_size(skb);
		if (err)
			goto error_nolock;
	}

	do {
		spin_lock_bh(&x->lock);
		err = xfrm_state_check(x, skb);
		if (err)
			goto error;

		err = x->mode->output(skb);
		if (err)
			goto error;

		err = x->type->output(x, skb);
		if (err)
			goto error;

		x->curlft.bytes += skb->len;
		x->curlft.packets++;

		spin_unlock_bh(&x->lock);
	
		if (!(skb->dst = dst_pop(dst))) {
			err = -EHOSTUNREACH;
			goto error_nolock;
		}
		dst = skb->dst;
		x = dst->xfrm;
	} while (x && !x->props.mode);

	IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
	err = 0;

out_exit:
	return err;
error:
	spin_unlock_bh(&x->lock);
error_nolock:
	kfree_skb(skb);
	goto out_exit;
}
Пример #2
0
static int ipip_output(struct sk_buff *skb)
{
	struct dst_entry *dst = skb->dst;
	struct xfrm_state *x = dst->xfrm;
	struct iphdr *iph, *top_iph;
	int tos, err;

	if ((err = xfrm4_tunnel_check_size(skb)) != 0)
		goto error_nolock;
		
	iph = skb->nh.iph;

	spin_lock_bh(&x->lock);

	tos = iph->tos;

	top_iph = (struct iphdr *) skb_push(skb, x->props.header_len);
	top_iph->ihl = 5;
	top_iph->version = 4;
	top_iph->tos = INET_ECN_encapsulate(tos, iph->tos);
	top_iph->tot_len = htons(skb->len);
	top_iph->frag_off = iph->frag_off & ~htons(IP_MF|IP_OFFSET);
	if (!(iph->frag_off & htons(IP_DF))) {
#ifdef NETIF_F_TSO
		__ip_select_ident(top_iph, dst, 0);
#else
		__ip_select_ident(top_iph, dst);
#endif
	}
	top_iph->ttl = iph->ttl;
	top_iph->protocol = IPPROTO_IPIP;
	top_iph->check = 0;
	top_iph->saddr = x->props.saddr.a4;
	top_iph->daddr = x->id.daddr.a4;
	memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
	ip_send_check(top_iph);

	skb->nh.raw = skb->data;
	x->curlft.bytes += skb->len;
	x->curlft.packets++;

	spin_unlock_bh(&x->lock);

	if ((skb->dst = dst_pop(dst)) == NULL) {
		kfree_skb(skb);
		err = -EHOSTUNREACH;
		goto error_nolock;
	}
	return NET_XMIT_BYPASS;

error_nolock:
	kfree_skb(skb);
	return err;
}
Пример #3
0
int xfrm4_extract_output(struct xfrm_state *x, struct sk_buff *skb)
{
	int err;

	err = xfrm4_tunnel_check_size(skb);
	if (err)
		return err;

	XFRM_MODE_SKB_CB(skb)->protocol = ip_hdr(skb)->protocol;

	return xfrm4_extract_header(skb);
}
int xfrm4_output(struct sk_buff **pskb)
{
	struct sk_buff *skb = *pskb;
	struct dst_entry *dst = skb->dst;
	struct xfrm_state *x = dst->xfrm;
	int err;
	
	if (skb->ip_summed == CHECKSUM_HW) {
		err = skb_checksum_help(pskb, 0);
		skb = *pskb;
		if (err)
			goto error_nolock;
	}

	spin_lock_bh(&x->lock);
	err = xfrm_state_check(x, skb);
	if (err)
		goto error;

	if (x->props.mode) {
		err = xfrm4_tunnel_check_size(skb);
		if (err)
			goto error;
	}

	xfrm4_encap(skb);

	err = x->type->output(pskb);
	skb = *pskb;
	if (err)
		goto error;

	x->curlft.bytes += skb->len;
	x->curlft.packets++;

	spin_unlock_bh(&x->lock);
	
	if (!(skb->dst = dst_pop(dst))) {
		err = -EHOSTUNREACH;
		goto error_nolock;
	}
	err = NET_XMIT_BYPASS;

out_exit:
	return err;
error:
	spin_unlock_bh(&x->lock);
error_nolock:
	kfree_skb(skb);
	goto out_exit;
}
static int xfrm4_output_one(struct sk_buff *skb)
{
	struct dst_entry *dst = skb->dst;
	struct xfrm_state *x = dst->xfrm;
	int err;

	/* purpose: 0014838 author: paul.chen date: 2011-12-06          */
	/* description: Fix reboot & plug in crash for VPN G2G wildcard */
	if(skb && skb->nh.iph && skb->nh.iph->protocol==IPPROTO_IGMP)
	{
		err = -EINVAL;
		goto error_nolock;
	}

	if (skb->ip_summed == CHECKSUM_HW) {
		err = skb_checksum_help(skb, 0);
		if (err)
			goto error_nolock;
	}

	if (x->props.mode) {
		err = xfrm4_tunnel_check_size(skb);
		if (err)
			goto error_nolock;
	}

	do {
		spin_lock_bh(&x->lock);
		err = xfrm_state_check(x, skb);
		if (err)
			goto error;

#if defined(CONFIG_CAVIUM_OCTEON_IPSEC) && defined(CONFIG_NET_KEY) 
		/*
		 * If Octeon IPSEC Acceleration module has been loaded
		 * call it, otherwise, follow the software path
		 */
		if(cavium_ipsec_process) 
		{
			if (skb_is_nonlinear(skb) &&
				skb_linearize(skb, GFP_ATOMIC) != 0) {
				err = -ENOMEM;
				goto error;
			}
			err = cavium_ipsec_process(x->sa_handle, skb, 0, 1 /*ENCRYPT*/);
		}
		else
		{
			xfrm4_encap(skb);
			err = x->type->output(x, skb);
		}
#else
		xfrm4_encap(skb);
		err = x->type->output(x, skb);
#endif
		if (err)
			goto error;

		x->curlft.bytes += skb->len;
		x->curlft.packets++;

		spin_unlock_bh(&x->lock);
	
		if (!(skb->dst = dst_pop(dst))) {
			err = -EHOSTUNREACH;
			goto error_nolock;
		}
		dst = skb->dst;
		x = dst->xfrm;
	} while (x && !x->props.mode);

	IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
	err = 0;

out_exit:
	return err;
error:
	spin_unlock_bh(&x->lock);
error_nolock:
	kfree_skb(skb);
	goto out_exit;
}