aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/ah6.c10
-rw-r--r--net/ipv6/esp6.c20
-rw-r--r--net/ipv6/ipcomp6.c27
-rw-r--r--net/ipv6/xfrm6_mode_transport.c15
4 files changed, 27 insertions, 45 deletions
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index 6778173a3dda..d31c0d6c0448 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -292,7 +292,7 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb)
292 292
293 memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len); 293 memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len);
294 memset(ah->auth_data, 0, ahp->icv_trunc_len); 294 memset(ah->auth_data, 0, ahp->icv_trunc_len);
295 skb_push(skb, skb->data - skb->nh.raw); 295 skb_push(skb, hdr_len);
296 ahp->icv(ahp, skb, ah->auth_data); 296 ahp->icv(ahp, skb, ah->auth_data);
297 if (memcmp(ah->auth_data, auth_data, ahp->icv_trunc_len)) { 297 if (memcmp(ah->auth_data, auth_data, ahp->icv_trunc_len)) {
298 LIMIT_NETDEBUG(KERN_WARNING "ipsec ah authentication error\n"); 298 LIMIT_NETDEBUG(KERN_WARNING "ipsec ah authentication error\n");
@@ -301,12 +301,8 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb)
301 } 301 }
302 } 302 }
303 303
304 skb->nh.raw = skb_pull(skb, ah_hlen); 304 skb->h.raw = memcpy(skb->nh.raw += ah_hlen, tmp_hdr, hdr_len);
305 memcpy(skb->nh.raw, tmp_hdr, hdr_len); 305 __skb_pull(skb, ah_hlen + hdr_len);
306 skb->nh.ipv6h->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
307 skb_pull(skb, hdr_len);
308 skb->h.raw = skb->data;
309
310 306
311 kfree(tmp_hdr); 307 kfree(tmp_hdr);
312 308
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index 22f046079037..a15a6f320f70 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -142,25 +142,17 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
142 142
143 int hdr_len = skb->h.raw - skb->nh.raw; 143 int hdr_len = skb->h.raw - skb->nh.raw;
144 int nfrags; 144 int nfrags;
145 unsigned char *tmp_hdr = NULL;
146 int ret = 0; 145 int ret = 0;
147 146
148 if (!pskb_may_pull(skb, sizeof(struct ipv6_esp_hdr))) { 147 if (!pskb_may_pull(skb, sizeof(struct ipv6_esp_hdr))) {
149 ret = -EINVAL; 148 ret = -EINVAL;
150 goto out_nofree; 149 goto out;
151 } 150 }
152 151
153 if (elen <= 0 || (elen & (blksize-1))) { 152 if (elen <= 0 || (elen & (blksize-1))) {
154 ret = -EINVAL; 153 ret = -EINVAL;
155 goto out_nofree; 154 goto out;
156 }
157
158 tmp_hdr = kmalloc(hdr_len, GFP_ATOMIC);
159 if (!tmp_hdr) {
160 ret = -ENOMEM;
161 goto out_nofree;
162 } 155 }
163 memcpy(tmp_hdr, skb->nh.raw, hdr_len);
164 156
165 /* If integrity check is required, do this. */ 157 /* If integrity check is required, do this. */
166 if (esp->auth.icv_full_len) { 158 if (esp->auth.icv_full_len) {
@@ -222,16 +214,12 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
222 /* ... check padding bits here. Silly. :-) */ 214 /* ... check padding bits here. Silly. :-) */
223 215
224 pskb_trim(skb, skb->len - alen - padlen - 2); 216 pskb_trim(skb, skb->len - alen - padlen - 2);
225 skb->h.raw = skb_pull(skb, sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen);
226 skb->nh.raw += sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen;
227 memcpy(skb->nh.raw, tmp_hdr, hdr_len);
228 skb->nh.ipv6h->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
229 ret = nexthdr[1]; 217 ret = nexthdr[1];
230 } 218 }
231 219
220 skb->h.raw = __skb_pull(skb, sizeof(*esph) + esp->conf.ivlen) - hdr_len;
221
232out: 222out:
233 kfree(tmp_hdr);
234out_nofree:
235 return ret; 223 return ret;
236} 224}
237 225
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c
index 48636436028a..cec3be544b69 100644
--- a/net/ipv6/ipcomp6.c
+++ b/net/ipv6/ipcomp6.c
@@ -66,10 +66,8 @@ static LIST_HEAD(ipcomp6_tfms_list);
66static int ipcomp6_input(struct xfrm_state *x, struct sk_buff *skb) 66static int ipcomp6_input(struct xfrm_state *x, struct sk_buff *skb)
67{ 67{
68 int err = 0; 68 int err = 0;
69 u8 nexthdr = 0;
70 int hdr_len = skb->h.raw - skb->nh.raw;
71 unsigned char *tmp_hdr = NULL;
72 struct ipv6hdr *iph; 69 struct ipv6hdr *iph;
70 struct ipv6_comp_hdr *ipch;
73 int plen, dlen; 71 int plen, dlen;
74 struct ipcomp_data *ipcd = x->data; 72 struct ipcomp_data *ipcd = x->data;
75 u8 *start, *scratch; 73 u8 *start, *scratch;
@@ -86,17 +84,9 @@ static int ipcomp6_input(struct xfrm_state *x, struct sk_buff *skb)
86 84
87 /* Remove ipcomp header and decompress original payload */ 85 /* Remove ipcomp header and decompress original payload */
88 iph = skb->nh.ipv6h; 86 iph = skb->nh.ipv6h;
89 tmp_hdr = kmalloc(hdr_len, GFP_ATOMIC); 87 ipch = (void *)skb->data;
90 if (!tmp_hdr) 88 skb->h.raw = skb->nh.raw + sizeof(*ipch);
91 goto out; 89 __skb_pull(skb, sizeof(*ipch));
92 memcpy(tmp_hdr, iph, hdr_len);
93 nexthdr = *(u8 *)skb->data;
94 skb_pull(skb, sizeof(struct ipv6_comp_hdr));
95 skb->nh.raw += sizeof(struct ipv6_comp_hdr);
96 memcpy(skb->nh.raw, tmp_hdr, hdr_len);
97 iph = skb->nh.ipv6h;
98 iph->payload_len = htons(ntohs(iph->payload_len) - sizeof(struct ipv6_comp_hdr));
99 skb->h.raw = skb->data;
100 90
101 /* decompression */ 91 /* decompression */
102 plen = skb->len; 92 plen = skb->len;
@@ -125,18 +115,11 @@ static int ipcomp6_input(struct xfrm_state *x, struct sk_buff *skb)
125 115
126 skb_put(skb, dlen - plen); 116 skb_put(skb, dlen - plen);
127 memcpy(skb->data, scratch, dlen); 117 memcpy(skb->data, scratch, dlen);
118 err = ipch->nexthdr;
128 119
129 iph = skb->nh.ipv6h;
130 iph->payload_len = htons(skb->len);
131
132out_put_cpu: 120out_put_cpu:
133 put_cpu(); 121 put_cpu();
134out: 122out:
135 kfree(tmp_hdr);
136 if (err)
137 goto error_out;
138 return nexthdr;
139error_out:
140 return err; 123 return err;
141} 124}
142 125
diff --git a/net/ipv6/xfrm6_mode_transport.c b/net/ipv6/xfrm6_mode_transport.c
index 5efbbae08ef0..711d713e36d8 100644
--- a/net/ipv6/xfrm6_mode_transport.c
+++ b/net/ipv6/xfrm6_mode_transport.c
@@ -42,8 +42,23 @@ static int xfrm6_transport_output(struct sk_buff *skb)
42 return 0; 42 return 0;
43} 43}
44 44
45/* Remove encapsulation header.
46 *
47 * The IP header will be moved over the top of the encapsulation header.
48 *
49 * On entry, skb->h shall point to where the IP header should be and skb->nh
50 * shall be set to where the IP header currently is. skb->data shall point
51 * to the start of the payload.
52 */
45static int xfrm6_transport_input(struct xfrm_state *x, struct sk_buff *skb) 53static int xfrm6_transport_input(struct xfrm_state *x, struct sk_buff *skb)
46{ 54{
55 int ihl = skb->data - skb->h.raw;
56
57 if (skb->h.raw != skb->nh.raw)
58 skb->nh.raw = memmove(skb->h.raw, skb->nh.raw, ihl);
59 skb->nh.ipv6h->payload_len = htons(skb->len + ihl -
60 sizeof(struct ipv6hdr));
61 skb->h.raw = skb->data;
47 return 0; 62 return 0;
48} 63}
49 64