* - Compression stats.
* - Adaptive compression.
*/
+#include <linux/config.h>
#include <linux/module.h>
#include <asm/scatterlist.h>
#include <asm/semaphore.h>
static int ipcomp_decompress(struct xfrm_state *x, struct sk_buff *skb)
{
int err, plen, dlen;
+ struct iphdr *iph;
struct ipcomp_data *ipcd = x->data;
u8 *start, *scratch;
struct crypto_tfm *tfm;
if (err)
goto out;
- skb->truesize += dlen - plen;
- __skb_put(skb, dlen - plen);
+ skb_put(skb, dlen - plen);
memcpy(skb->data, scratch, dlen);
+ iph = skb->nh.iph;
+ iph->tot_len = htons(dlen + iph->ihl * 4);
out:
put_cpu();
return err;
static int ipcomp_input(struct xfrm_state *x, struct sk_buff *skb)
{
+ u8 nexthdr;
int err = -ENOMEM;
struct iphdr *iph;
- struct ip_comp_hdr *ipch;
+ union {
+ struct iphdr iph;
+ char buf[60];
+ } tmp_iph;
+
if (skb_linearize_cow(skb))
goto out;
/* Remove ipcomp header and decompress original payload */
iph = skb->nh.iph;
- ipch = (void *)skb->data;
- iph->protocol = ipch->nexthdr;
- skb->h.raw = skb->nh.raw + sizeof(*ipch);
- __skb_pull(skb, sizeof(*ipch));
+ 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:
goto out;
err = -ENOMEM;
- ipcd = kzalloc(sizeof(*ipcd), GFP_KERNEL);
+ ipcd = kmalloc(sizeof(*ipcd), GFP_KERNEL);
if (!ipcd)
goto out;
+ memset(ipcd, 0, sizeof(*ipcd));
x->props.header_len = 0;
if (x->props.mode)
x->props.header_len += sizeof(struct iphdr);