aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/ah6.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/ah6.c')
-rw-r--r--net/ipv6/ah6.c34
1 files changed, 19 insertions, 15 deletions
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index dc68b7269c3c..b696c8401200 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -238,8 +238,8 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb)
238 top_iph = (struct ipv6hdr *)skb->data; 238 top_iph = (struct ipv6hdr *)skb->data;
239 top_iph->payload_len = htons(skb->len - sizeof(*top_iph)); 239 top_iph->payload_len = htons(skb->len - sizeof(*top_iph));
240 240
241 nexthdr = *skb->nh.raw; 241 nexthdr = *skb_network_header(skb);
242 *skb->nh.raw = IPPROTO_AH; 242 *skb_network_header(skb) = IPPROTO_AH;
243 243
244 /* When there are no extension headers, we only need to save the first 244 /* When there are no extension headers, we only need to save the first
245 * 8 bytes of the base IP header. 245 * 8 bytes of the base IP header.
@@ -247,7 +247,7 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb)
247 memcpy(tmp_base, top_iph, sizeof(tmp_base)); 247 memcpy(tmp_base, top_iph, sizeof(tmp_base));
248 248
249 tmp_ext = NULL; 249 tmp_ext = NULL;
250 extlen = skb->h.raw - (unsigned char *)(top_iph + 1); 250 extlen = skb_transport_offset(skb) + sizeof(struct ipv6hdr);
251 if (extlen) { 251 if (extlen) {
252 extlen += sizeof(*tmp_ext); 252 extlen += sizeof(*tmp_ext);
253 tmp_ext = kmalloc(extlen, GFP_ATOMIC); 253 tmp_ext = kmalloc(extlen, GFP_ATOMIC);
@@ -268,7 +268,7 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb)
268 goto error_free_iph; 268 goto error_free_iph;
269 } 269 }
270 270
271 ah = (struct ip_auth_hdr *)skb->h.raw; 271 ah = (struct ip_auth_hdr *)skb_transport_header(skb);
272 ah->nexthdr = nexthdr; 272 ah->nexthdr = nexthdr;
273 273
274 top_iph->priority = 0; 274 top_iph->priority = 0;
@@ -316,8 +316,8 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb)
316 * 316 *
317 * To erase AH: 317 * To erase AH:
318 * Keeping copy of cleared headers. After AH processing, 318 * Keeping copy of cleared headers. After AH processing,
319 * Moving the pointer of skb->nh.raw by using skb_pull as long as AH 319 * Moving the pointer of skb->network_header by using skb_pull as long
320 * header length. Then copy back the copy as long as hdr_len 320 * as AH header length. Then copy back the copy as long as hdr_len
321 * If destination header following AH exists, copy it into after [Ext2]. 321 * If destination header following AH exists, copy it into after [Ext2].
322 * 322 *
323 * |<>|[IPv6][Ext1][Ext2][Dest][Payload] 323 * |<>|[IPv6][Ext1][Ext2][Dest][Payload]
@@ -325,6 +325,7 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb)
325 */ 325 */
326 326
327 struct ipv6_auth_hdr *ah; 327 struct ipv6_auth_hdr *ah;
328 struct ipv6hdr *ip6h;
328 struct ah_data *ahp; 329 struct ah_data *ahp;
329 unsigned char *tmp_hdr = NULL; 330 unsigned char *tmp_hdr = NULL;
330 u16 hdr_len; 331 u16 hdr_len;
@@ -341,7 +342,7 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb)
341 pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) 342 pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
342 goto out; 343 goto out;
343 344
344 hdr_len = skb->data - skb->nh.raw; 345 hdr_len = skb->data - skb_network_header(skb);
345 ah = (struct ipv6_auth_hdr*)skb->data; 346 ah = (struct ipv6_auth_hdr*)skb->data;
346 ahp = x->data; 347 ahp = x->data;
347 nexthdr = ah->nexthdr; 348 nexthdr = ah->nexthdr;
@@ -354,16 +355,17 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb)
354 if (!pskb_may_pull(skb, ah_hlen)) 355 if (!pskb_may_pull(skb, ah_hlen))
355 goto out; 356 goto out;
356 357
357 tmp_hdr = kmemdup(skb->nh.raw, hdr_len, GFP_ATOMIC); 358 tmp_hdr = kmemdup(skb_network_header(skb), hdr_len, GFP_ATOMIC);
358 if (!tmp_hdr) 359 if (!tmp_hdr)
359 goto out; 360 goto out;
360 if (ipv6_clear_mutable_options(skb->nh.ipv6h, hdr_len, XFRM_POLICY_IN)) 361 ip6h = ipv6_hdr(skb);
362 if (ipv6_clear_mutable_options(ip6h, hdr_len, XFRM_POLICY_IN))
361 goto free_out; 363 goto free_out;
362 skb->nh.ipv6h->priority = 0; 364 ip6h->priority = 0;
363 skb->nh.ipv6h->flow_lbl[0] = 0; 365 ip6h->flow_lbl[0] = 0;
364 skb->nh.ipv6h->flow_lbl[1] = 0; 366 ip6h->flow_lbl[1] = 0;
365 skb->nh.ipv6h->flow_lbl[2] = 0; 367 ip6h->flow_lbl[2] = 0;
366 skb->nh.ipv6h->hop_limit = 0; 368 ip6h->hop_limit = 0;
367 369
368 { 370 {
369 u8 auth_data[MAX_AH_AUTH_LEN]; 371 u8 auth_data[MAX_AH_AUTH_LEN];
@@ -382,7 +384,9 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb)
382 } 384 }
383 } 385 }
384 386
385 skb->h.raw = memcpy(skb->nh.raw += ah_hlen, tmp_hdr, hdr_len); 387 skb->network_header += ah_hlen;
388 memcpy(skb_network_header(skb), tmp_hdr, hdr_len);
389 skb->transport_header = skb->network_header;
386 __skb_pull(skb, ah_hlen + hdr_len); 390 __skb_pull(skb, ah_hlen + hdr_len);
387 391
388 kfree(tmp_hdr); 392 kfree(tmp_hdr);