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; }
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; }