aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/ipcomp.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/ipcomp.c')
-rw-r--r--net/ipv4/ipcomp.c34
1 files changed, 8 insertions, 26 deletions
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
index 95278b22b669..3ed8b57a1002 100644
--- a/net/ipv4/ipcomp.c
+++ b/net/ipv4/ipcomp.c
@@ -45,7 +45,6 @@ static LIST_HEAD(ipcomp_tfms_list);
45static int ipcomp_decompress(struct xfrm_state *x, struct sk_buff *skb) 45static int ipcomp_decompress(struct xfrm_state *x, struct sk_buff *skb)
46{ 46{
47 int err, plen, dlen; 47 int err, plen, dlen;
48 struct iphdr *iph;
49 struct ipcomp_data *ipcd = x->data; 48 struct ipcomp_data *ipcd = x->data;
50 u8 *start, *scratch; 49 u8 *start, *scratch;
51 struct crypto_tfm *tfm; 50 struct crypto_tfm *tfm;
@@ -74,8 +73,6 @@ static int ipcomp_decompress(struct xfrm_state *x, struct sk_buff *skb)
74 73
75 skb_put(skb, dlen - plen); 74 skb_put(skb, dlen - plen);
76 memcpy(skb->data, scratch, dlen); 75 memcpy(skb->data, scratch, dlen);
77 iph = skb->nh.iph;
78 iph->tot_len = htons(dlen + iph->ihl * 4);
79out: 76out:
80 put_cpu(); 77 put_cpu();
81 return err; 78 return err;
@@ -83,34 +80,21 @@ out:
83 80
84static int ipcomp_input(struct xfrm_state *x, struct sk_buff *skb) 81static int ipcomp_input(struct xfrm_state *x, struct sk_buff *skb)
85{ 82{
86 u8 nexthdr; 83 int err = -ENOMEM;
87 int err = 0;
88 struct iphdr *iph; 84 struct iphdr *iph;
89 union { 85 struct ip_comp_hdr *ipch;
90 struct iphdr iph;
91 char buf[60];
92 } tmp_iph;
93
94 86
95 if ((skb_is_nonlinear(skb) || skb_cloned(skb)) && 87 if (skb_linearize_cow(skb))
96 skb_linearize(skb, GFP_ATOMIC) != 0) {
97 err = -ENOMEM;
98 goto out; 88 goto out;
99 }
100 89
101 skb->ip_summed = CHECKSUM_NONE; 90 skb->ip_summed = CHECKSUM_NONE;
102 91
103 /* Remove ipcomp header and decompress original payload */ 92 /* Remove ipcomp header and decompress original payload */
104 iph = skb->nh.iph; 93 iph = skb->nh.iph;
105 memcpy(&tmp_iph, iph, iph->ihl * 4); 94 ipch = (void *)skb->data;
106 nexthdr = *(u8 *)skb->data; 95 iph->protocol = ipch->nexthdr;
107 skb_pull(skb, sizeof(struct ip_comp_hdr)); 96 skb->h.raw = skb->nh.raw + sizeof(*ipch);
108 skb->nh.raw += sizeof(struct ip_comp_hdr); 97 __skb_pull(skb, sizeof(*ipch));
109 memcpy(skb->nh.raw, &tmp_iph, tmp_iph.iph.ihl * 4);
110 iph = skb->nh.iph;
111 iph->tot_len = htons(ntohs(iph->tot_len) - sizeof(struct ip_comp_hdr));
112 iph->protocol = nexthdr;
113 skb->h.raw = skb->data;
114 err = ipcomp_decompress(x, skb); 98 err = ipcomp_decompress(x, skb);
115 99
116out: 100out:
@@ -171,10 +155,8 @@ static int ipcomp_output(struct xfrm_state *x, struct sk_buff *skb)
171 goto out_ok; 155 goto out_ok;
172 } 156 }
173 157
174 if ((skb_is_nonlinear(skb) || skb_cloned(skb)) && 158 if (skb_linearize_cow(skb))
175 skb_linearize(skb, GFP_ATOMIC) != 0) {
176 goto out_ok; 159 goto out_ok;
177 }
178 160
179 err = ipcomp_compress(x, skb); 161 err = ipcomp_compress(x, skb);
180 iph = skb->nh.iph; 162 iph = skb->nh.iph;