int ipcomp_input(struct xfrm_state *x, struct sk_buff *skb)
{
	int nexthdr;
	int err = -ENOMEM;
	struct ip_comp_hdr *ipch;

	if (skb_linearize_cow(skb))
		goto out;

	skb->ip_summed = CHECKSUM_NONE;

	
	ipch = (void *)skb->data;
	nexthdr = ipch->nexthdr;

	skb->transport_header = skb->network_header + sizeof(*ipch);
	__skb_pull(skb, sizeof(*ipch));
	err = ipcomp_decompress(x, skb);
	if (err)
		goto out;

	err = nexthdr;

out:
	return err;
}
Example #2
0
static int ipcomp_input(struct xfrm_state *x,
                        struct xfrm_decap_state *decap, struct sk_buff *skb)
{
	u8 nexthdr;
	int err = 0;
	struct iphdr *iph;
	union {
		struct iphdr	iph;
		char 		buf[60];
	} tmp_iph;


	if ((skb_is_nonlinear(skb) || skb_cloned(skb)) &&
	    skb_linearize(skb, GFP_ATOMIC) != 0) {
	    	err = -ENOMEM;
	    	goto out;
	}

	skb->ip_summed = CHECKSUM_NONE;

	/* Remove ipcomp header and decompress original payload */	
	iph = skb->nh.iph;
	memcpy(&tmp_iph, iph, iph->ihl * 4);
	nexthdr = *(u8 *)skb->data;
	skb_pull(skb, sizeof(struct ip_comp_hdr));
	skb->nh.raw += sizeof(struct ip_comp_hdr);
	memcpy(skb->nh.raw, &tmp_iph, tmp_iph.iph.ihl * 4);
	iph = skb->nh.iph;
	iph->tot_len = htons(ntohs(iph->tot_len) - sizeof(struct ip_comp_hdr));
	iph->protocol = nexthdr;
	skb->h.raw = skb->data;
	err = ipcomp_decompress(x, skb);

out:	
	return err;
}