X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fipv6%2Fipcomp6.c;h=d511a884dad07504fb73aeb5bf134086aff3c152;hb=987b0145d94eecf292d8b301228356f44611ab7c;hp=96cac9a943d4dbce84b01842745486bcd28b1d6e;hpb=f7ed79d23a47594e7834d66a8f14449796d4f3e6;p=linux-2.6.git diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c index 96cac9a94..d511a884d 100644 --- a/net/ipv6/ipcomp6.c +++ b/net/ipv6/ipcomp6.c @@ -50,7 +50,6 @@ #include #include #include -#include struct ipcomp6_tfms { struct list_head list; @@ -58,14 +57,14 @@ struct ipcomp6_tfms { int users; }; -static DEFINE_MUTEX(ipcomp6_resource_mutex); +static DECLARE_MUTEX(ipcomp6_resource_sem); static void **ipcomp6_scratches; static int ipcomp6_scratch_users; static LIST_HEAD(ipcomp6_tfms_list); -static int ipcomp6_input(struct xfrm_state *x, struct sk_buff *skb) +static int ipcomp6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb) { - int err = -ENOMEM; + int err = 0; u8 nexthdr = 0; int hdr_len = skb->h.raw - skb->nh.raw; unsigned char *tmp_hdr = NULL; @@ -76,8 +75,11 @@ static int ipcomp6_input(struct xfrm_state *x, struct sk_buff *skb) struct crypto_tfm *tfm; int cpu; - if (skb_linearize_cow(skb)) + if ((skb_is_nonlinear(skb) || skb_cloned(skb)) && + skb_linearize(skb, GFP_ATOMIC) != 0) { + err = -ENOMEM; goto out; + } skb->ip_summed = CHECKSUM_NONE; @@ -156,8 +158,10 @@ static int ipcomp6_output(struct xfrm_state *x, struct sk_buff *skb) goto out_ok; } - if (skb_linearize_cow(skb)) + if ((skb_is_nonlinear(skb) || skb_cloned(skb)) && + skb_linearize(skb, GFP_ATOMIC) != 0) { goto out_ok; + } /* compression */ plen = skb->len - hdr_len; @@ -203,7 +207,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 = htonl(ntohs(ipcomph->cpi)); + spi = ntohl(ntohs(ipcomph->cpi)); x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, spi, IPPROTO_COMP, AF_INET6); if (!x) return; @@ -223,9 +227,6 @@ static struct xfrm_state *ipcomp6_tunnel_create(struct xfrm_state *x) t->id.proto = IPPROTO_IPV6; t->id.spi = xfrm6_tunnel_alloc_spi((xfrm_address_t *)&x->props.saddr); - if (!t->id.spi) - goto error; - memcpy(t->id.daddr.a6, x->id.daddr.a6, sizeof(struct in6_addr)); memcpy(&t->sel, &x->sel, sizeof(t->sel)); t->props.family = AF_INET6; @@ -241,9 +242,7 @@ out: return t; error: - t->km.state = XFRM_STATE_DEAD; xfrm_state_put(t); - t = NULL; goto out; } @@ -285,10 +284,10 @@ static void ipcomp6_free_scratches(void) if (!scratches) return; - for_each_possible_cpu(i) { + for_each_cpu(i) { void *scratch = *per_cpu_ptr(scratches, i); - - vfree(scratch); + if (scratch) + vfree(scratch); } free_percpu(scratches); @@ -308,7 +307,7 @@ static void **ipcomp6_alloc_scratches(void) ipcomp6_scratches = scratches; - for_each_possible_cpu(i) { + for_each_cpu(i) { void *scratch = vmalloc(IPCOMP_SCRATCH_SIZE); if (!scratch) return NULL; @@ -339,7 +338,7 @@ static void ipcomp6_free_tfms(struct crypto_tfm **tfms) if (!tfms) return; - for_each_possible_cpu(cpu) { + for_each_cpu(cpu) { struct crypto_tfm *tfm = *per_cpu_ptr(tfms, cpu); crypto_free_tfm(tfm); } @@ -379,7 +378,7 @@ static struct crypto_tfm **ipcomp6_alloc_tfms(const char *alg_name) if (!tfms) goto error; - for_each_possible_cpu(cpu) { + for_each_cpu(cpu) { struct crypto_tfm *tfm = crypto_alloc_tfm(alg_name, 0); if (!tfm) goto error; @@ -406,9 +405,9 @@ static void ipcomp6_destroy(struct xfrm_state *x) if (!ipcd) return; xfrm_state_delete_tunnel(x); - mutex_lock(&ipcomp6_resource_mutex); + down(&ipcomp6_resource_sem); ipcomp6_free_data(ipcd); - mutex_unlock(&ipcomp6_resource_mutex); + up(&ipcomp6_resource_sem); kfree(ipcd); xfrm6_tunnel_free_spi((xfrm_address_t *)&x->props.saddr); @@ -428,22 +427,23 @@ static int ipcomp6_init_state(struct xfrm_state *x) 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 ipv6hdr); - mutex_lock(&ipcomp6_resource_mutex); + down(&ipcomp6_resource_sem); if (!ipcomp6_alloc_scratches()) goto error; ipcd->tfms = ipcomp6_alloc_tfms(x->calg->alg_name); if (!ipcd->tfms) goto error; - mutex_unlock(&ipcomp6_resource_mutex); + up(&ipcomp6_resource_sem); if (x->props.mode) { err = ipcomp6_tunnel_attach(x); @@ -459,10 +459,10 @@ static int ipcomp6_init_state(struct xfrm_state *x) out: return err; error_tunnel: - mutex_lock(&ipcomp6_resource_mutex); + down(&ipcomp6_resource_sem); error: ipcomp6_free_data(ipcd); - mutex_unlock(&ipcomp6_resource_mutex); + up(&ipcomp6_resource_sem); kfree(ipcd); goto out;