X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=net%2Fipv6%2Fipcomp6.c;h=f28cd37feed3132444f84609cfaaed24ecfe3ede;hb=5806db22cffc7557b675d3c9229f327980aee797;hp=d4cfec3f414e32bbd7c981437b1666c393369f4b;hpb=95d465fd750897ab32462a6702fbfe1b122cbbc0;p=linux-2.6 diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c index d4cfec3f41..f28cd37fee 100644 --- a/net/ipv6/ipcomp6.c +++ b/net/ipv6/ipcomp6.c @@ -63,40 +63,27 @@ static void **ipcomp6_scratches; static int ipcomp6_scratch_users; static LIST_HEAD(ipcomp6_tfms_list); -static int ipcomp6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb) +static int ipcomp6_input(struct xfrm_state *x, struct sk_buff *skb) { - int err = 0; - u8 nexthdr = 0; - int hdr_len = skb->h.raw - skb->nh.raw; - unsigned char *tmp_hdr = NULL; + int err = -ENOMEM; struct ipv6hdr *iph; + struct ipv6_comp_hdr *ipch; int plen, dlen; struct ipcomp_data *ipcd = x->data; u8 *start, *scratch; struct crypto_tfm *tfm; int cpu; - if ((skb_is_nonlinear(skb) || skb_cloned(skb)) && - skb_linearize(skb, GFP_ATOMIC) != 0) { - err = -ENOMEM; + if (skb_linearize_cow(skb)) goto out; - } skb->ip_summed = CHECKSUM_NONE; /* Remove ipcomp header and decompress original payload */ iph = skb->nh.ipv6h; - tmp_hdr = kmalloc(hdr_len, GFP_ATOMIC); - if (!tmp_hdr) - goto out; - memcpy(tmp_hdr, iph, hdr_len); - nexthdr = *(u8 *)skb->data; - skb_pull(skb, sizeof(struct ipv6_comp_hdr)); - skb->nh.raw += sizeof(struct ipv6_comp_hdr); - memcpy(skb->nh.raw, tmp_hdr, hdr_len); - iph = skb->nh.ipv6h; - iph->payload_len = htons(ntohs(iph->payload_len) - sizeof(struct ipv6_comp_hdr)); - skb->h.raw = skb->data; + ipch = (void *)skb->data; + skb->h.raw = skb->nh.raw + sizeof(*ipch); + __skb_pull(skb, sizeof(*ipch)); /* decompression */ plen = skb->len; @@ -125,18 +112,11 @@ static int ipcomp6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, s skb_put(skb, dlen - plen); memcpy(skb->data, scratch, dlen); + err = ipch->nexthdr; - iph = skb->nh.ipv6h; - iph->payload_len = htons(skb->len); - out_put_cpu: put_cpu(); out: - kfree(tmp_hdr); - if (err) - goto error_out; - return nexthdr; -error_out: return err; } @@ -159,10 +139,8 @@ static int ipcomp6_output(struct xfrm_state *x, struct sk_buff *skb) goto out_ok; } - if ((skb_is_nonlinear(skb) || skb_cloned(skb)) && - skb_linearize(skb, GFP_ATOMIC) != 0) { + if (skb_linearize_cow(skb)) goto out_ok; - } /* compression */ plen = skb->len - hdr_len; @@ -208,7 +186,7 @@ static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, if (type != ICMPV6_DEST_UNREACH && type != ICMPV6_PKT_TOOBIG) return; - spi = ntohl(ntohs(ipcomph->cpi)); + spi = htonl(ntohs(ipcomph->cpi)); x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, spi, IPPROTO_COMP, AF_INET6); if (!x) return; @@ -290,7 +268,7 @@ static void ipcomp6_free_scratches(void) if (!scratches) return; - for_each_cpu(i) { + for_each_possible_cpu(i) { void *scratch = *per_cpu_ptr(scratches, i); vfree(scratch); @@ -313,7 +291,7 @@ static void **ipcomp6_alloc_scratches(void) ipcomp6_scratches = scratches; - for_each_cpu(i) { + for_each_possible_cpu(i) { void *scratch = vmalloc(IPCOMP_SCRATCH_SIZE); if (!scratch) return NULL; @@ -344,7 +322,7 @@ static void ipcomp6_free_tfms(struct crypto_tfm **tfms) if (!tfms) return; - for_each_cpu(cpu) { + for_each_possible_cpu(cpu) { struct crypto_tfm *tfm = *per_cpu_ptr(tfms, cpu); crypto_free_tfm(tfm); } @@ -384,7 +362,7 @@ static struct crypto_tfm **ipcomp6_alloc_tfms(const char *alg_name) if (!tfms) goto error; - for_each_cpu(cpu) { + for_each_possible_cpu(cpu) { struct crypto_tfm *tfm = crypto_alloc_tfm(alg_name, 0); if (!tfm) goto error;