aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2005-03-31 06:27:11 -0800
committerDavid S. Miller <davem@sunset.davemloft.net>2005-03-31 06:27:11 -0800
commitb72e012203fe9a4c6083108ddf1f4d66143abe7f (patch)
tree9ee8705c224de698f78a3b03932dc05e1f605183
parent28a60e50ba50594a870e47784cf845142c5ed661 (diff)
downloadhistory-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.c26
-rw-r--r--net/ipv6/ipcomp6.c14
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,