diff options
Diffstat (limited to 'net/ipv6/ah6.c')
-rw-r--r-- | net/ipv6/ah6.c | 34 |
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); |