diff options
author | Herbert Xu <herbert@gondor.apana.org.au> | 2005-03-31 06:27:11 -0800 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2005-03-31 06:27:11 -0800 |
commit | b72e012203fe9a4c6083108ddf1f4d66143abe7f (patch) | |
tree | 9ee8705c224de698f78a3b03932dc05e1f605183 | |
parent | 28a60e50ba50594a870e47784cf845142c5ed661 (diff) | |
download | history-b72e012203fe9a4c6083108ddf1f4d66143abe7f.tar.gz |
[IPSEC]: Make IPCOMP more resilient.
Since the IPCOMP header is left off when the payload is incompressible
or too small, we can also do the same thing when we encounter an error
during compression.
In other words, we can let outbound IPCOMP always succeed. In the cases
where it would currently fail we simply skip the IPCOMP transform. This
makes IPCOMP slightly more resilient when memory is low and simplifies
the code quite a bit.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Acked-by: James Morris <jmorris@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/ipv4/ipcomp.c | 26 | ||||
-rw-r--r-- | net/ipv6/ipcomp6.c | 14 |
2 files changed, 11 insertions, 29 deletions
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c index 49eef7b3ec40ed..1a23c5263b993a 100644 --- a/net/ipv4/ipcomp.c +++ b/net/ipv4/ipcomp.c @@ -167,32 +167,22 @@ static int ipcomp_output(struct xfrm_state *x, struct sk_buff *skb) hdr_len = iph->ihl * 4; if ((skb->len - hdr_len) < ipcd->threshold) { /* Don't bother compressing */ - if (x->props.mode) { - ip_send_check(iph); - } goto out_ok; } if ((skb_is_nonlinear(skb) || skb_cloned(skb)) && skb_linearize(skb, GFP_ATOMIC) != 0) { - err = -ENOMEM; - goto error; + goto out_ok; } err = ipcomp_compress(x, skb); + iph = skb->nh.iph; + if (err) { - if (err == -EMSGSIZE) { - if (x->props.mode) { - iph = skb->nh.iph; - ip_send_check(iph); - } - goto out_ok; - } - goto error; + goto out_ok; } /* Install ipcomp header, convert into ipcomp datagram. */ - iph = skb->nh.iph; iph->tot_len = htons(skb->len); ipch = (struct ip_comp_hdr *)((char *)iph + iph->ihl * 4); ipch->nexthdr = iph->protocol; @@ -200,12 +190,12 @@ static int ipcomp_output(struct xfrm_state *x, struct sk_buff *skb) ipch->cpi = htons((u16 )ntohl(x->id.spi)); iph->protocol = IPPROTO_COMP; ip_send_check(iph); + return 0; out_ok: - err = 0; - -error: - return err; + if (x->props.mode) + ip_send_check(iph); + return 0; } static void ipcomp4_err(struct sk_buff *skb, u32 info) diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c index ecea6cf66055a2..6cde5310cd76b1 100644 --- a/net/ipv6/ipcomp6.c +++ b/net/ipv6/ipcomp6.c @@ -160,8 +160,7 @@ static int ipcomp6_output(struct xfrm_state *x, struct sk_buff *skb) if ((skb_is_nonlinear(skb) || skb_cloned(skb)) && skb_linearize(skb, GFP_ATOMIC) != 0) { - err = -ENOMEM; - goto error; + goto out_ok; } /* compression */ @@ -174,11 +173,7 @@ static int ipcomp6_output(struct xfrm_state *x, struct sk_buff *skb) tfm = *per_cpu_ptr(ipcd->tfms, cpu); err = crypto_comp_compress(tfm, start, plen, scratch, &dlen); - if (err) { - put_cpu(); - goto error; - } - if ((dlen + sizeof(struct ipv6_comp_hdr)) >= plen) { + if (err || (dlen + sizeof(struct ipv6_comp_hdr)) >= plen) { put_cpu(); goto out_ok; } @@ -198,10 +193,7 @@ static int ipcomp6_output(struct xfrm_state *x, struct sk_buff *skb) *skb->nh.raw = IPPROTO_COMP; out_ok: - err = 0; - -error: - return err; + return 0; } static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, |