diff options
Diffstat (limited to 'net/ipv6/ip6_output.c')
-rw-r--r-- | net/ipv6/ip6_output.c | 187 |
1 files changed, 123 insertions, 64 deletions
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 305516921aa8..f508171bab73 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -88,8 +88,8 @@ static inline int ip6_output_finish(struct sk_buff *skb) | |||
88 | /* dev_loopback_xmit for use with netfilter. */ | 88 | /* dev_loopback_xmit for use with netfilter. */ |
89 | static int ip6_dev_loopback_xmit(struct sk_buff *newskb) | 89 | static int ip6_dev_loopback_xmit(struct sk_buff *newskb) |
90 | { | 90 | { |
91 | newskb->mac.raw = newskb->data; | 91 | skb_reset_mac_header(newskb); |
92 | __skb_pull(newskb, newskb->nh.raw - newskb->data); | 92 | __skb_pull(newskb, skb_network_offset(newskb)); |
93 | newskb->pkt_type = PACKET_LOOPBACK; | 93 | newskb->pkt_type = PACKET_LOOPBACK; |
94 | newskb->ip_summed = CHECKSUM_UNNECESSARY; | 94 | newskb->ip_summed = CHECKSUM_UNNECESSARY; |
95 | BUG_TRAP(newskb->dst); | 95 | BUG_TRAP(newskb->dst); |
@@ -107,13 +107,13 @@ static int ip6_output2(struct sk_buff *skb) | |||
107 | skb->protocol = htons(ETH_P_IPV6); | 107 | skb->protocol = htons(ETH_P_IPV6); |
108 | skb->dev = dev; | 108 | skb->dev = dev; |
109 | 109 | ||
110 | if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr)) { | 110 | if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr)) { |
111 | struct ipv6_pinfo* np = skb->sk ? inet6_sk(skb->sk) : NULL; | 111 | struct ipv6_pinfo* np = skb->sk ? inet6_sk(skb->sk) : NULL; |
112 | struct inet6_dev *idev = ip6_dst_idev(skb->dst); | 112 | struct inet6_dev *idev = ip6_dst_idev(skb->dst); |
113 | 113 | ||
114 | if (!(dev->flags & IFF_LOOPBACK) && (!np || np->mc_loop) && | 114 | if (!(dev->flags & IFF_LOOPBACK) && (!np || np->mc_loop) && |
115 | ipv6_chk_mcast_addr(dev, &skb->nh.ipv6h->daddr, | 115 | ipv6_chk_mcast_addr(dev, &ipv6_hdr(skb)->daddr, |
116 | &skb->nh.ipv6h->saddr)) { | 116 | &ipv6_hdr(skb)->saddr)) { |
117 | struct sk_buff *newskb = skb_clone(skb, GFP_ATOMIC); | 117 | struct sk_buff *newskb = skb_clone(skb, GFP_ATOMIC); |
118 | 118 | ||
119 | /* Do not check for IFF_ALLMULTI; multicast routing | 119 | /* Do not check for IFF_ALLMULTI; multicast routing |
@@ -124,7 +124,7 @@ static int ip6_output2(struct sk_buff *skb) | |||
124 | newskb->dev, | 124 | newskb->dev, |
125 | ip6_dev_loopback_xmit); | 125 | ip6_dev_loopback_xmit); |
126 | 126 | ||
127 | if (skb->nh.ipv6h->hop_limit == 0) { | 127 | if (ipv6_hdr(skb)->hop_limit == 0) { |
128 | IP6_INC_STATS(idev, IPSTATS_MIB_OUTDISCARDS); | 128 | IP6_INC_STATS(idev, IPSTATS_MIB_OUTDISCARDS); |
129 | kfree_skb(skb); | 129 | kfree_skb(skb); |
130 | return 0; | 130 | return 0; |
@@ -137,9 +137,17 @@ static int ip6_output2(struct sk_buff *skb) | |||
137 | return NF_HOOK(PF_INET6, NF_IP6_POST_ROUTING, skb,NULL, skb->dev,ip6_output_finish); | 137 | return NF_HOOK(PF_INET6, NF_IP6_POST_ROUTING, skb,NULL, skb->dev,ip6_output_finish); |
138 | } | 138 | } |
139 | 139 | ||
140 | static inline int ip6_skb_dst_mtu(struct sk_buff *skb) | ||
141 | { | ||
142 | struct ipv6_pinfo *np = skb->sk ? inet6_sk(skb->sk) : NULL; | ||
143 | |||
144 | return (np && np->pmtudisc == IPV6_PMTUDISC_PROBE) ? | ||
145 | skb->dst->dev->mtu : dst_mtu(skb->dst); | ||
146 | } | ||
147 | |||
140 | int ip6_output(struct sk_buff *skb) | 148 | int ip6_output(struct sk_buff *skb) |
141 | { | 149 | { |
142 | if ((skb->len > dst_mtu(skb->dst) && !skb_is_gso(skb)) || | 150 | if ((skb->len > ip6_skb_dst_mtu(skb) && !skb_is_gso(skb)) || |
143 | dst_allfrag(skb->dst)) | 151 | dst_allfrag(skb->dst)) |
144 | return ip6_fragment(skb, ip6_output2); | 152 | return ip6_fragment(skb, ip6_output2); |
145 | else | 153 | else |
@@ -191,7 +199,9 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, | |||
191 | ipv6_push_nfrag_opts(skb, opt, &proto, &first_hop); | 199 | ipv6_push_nfrag_opts(skb, opt, &proto, &first_hop); |
192 | } | 200 | } |
193 | 201 | ||
194 | hdr = skb->nh.ipv6h = (struct ipv6hdr*)skb_push(skb, sizeof(struct ipv6hdr)); | 202 | skb_push(skb, sizeof(struct ipv6hdr)); |
203 | skb_reset_network_header(skb); | ||
204 | hdr = ipv6_hdr(skb); | ||
195 | 205 | ||
196 | /* | 206 | /* |
197 | * Fill in the IPv6 header | 207 | * Fill in the IPv6 header |
@@ -239,6 +249,8 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, | |||
239 | return -EMSGSIZE; | 249 | return -EMSGSIZE; |
240 | } | 250 | } |
241 | 251 | ||
252 | EXPORT_SYMBOL(ip6_xmit); | ||
253 | |||
242 | /* | 254 | /* |
243 | * To avoid extra problems ND packets are send through this | 255 | * To avoid extra problems ND packets are send through this |
244 | * routine. It's code duplication but I really want to avoid | 256 | * routine. It's code duplication but I really want to avoid |
@@ -259,8 +271,9 @@ int ip6_nd_hdr(struct sock *sk, struct sk_buff *skb, struct net_device *dev, | |||
259 | 271 | ||
260 | totlen = len + sizeof(struct ipv6hdr); | 272 | totlen = len + sizeof(struct ipv6hdr); |
261 | 273 | ||
262 | hdr = (struct ipv6hdr *) skb_put(skb, sizeof(struct ipv6hdr)); | 274 | skb_reset_network_header(skb); |
263 | skb->nh.ipv6h = hdr; | 275 | skb_put(skb, sizeof(struct ipv6hdr)); |
276 | hdr = ipv6_hdr(skb); | ||
264 | 277 | ||
265 | *(__be32*)hdr = htonl(0x60000000); | 278 | *(__be32*)hdr = htonl(0x60000000); |
266 | 279 | ||
@@ -305,7 +318,7 @@ static int ip6_call_ra_chain(struct sk_buff *skb, int sel) | |||
305 | 318 | ||
306 | static int ip6_forward_proxy_check(struct sk_buff *skb) | 319 | static int ip6_forward_proxy_check(struct sk_buff *skb) |
307 | { | 320 | { |
308 | struct ipv6hdr *hdr = skb->nh.ipv6h; | 321 | struct ipv6hdr *hdr = ipv6_hdr(skb); |
309 | u8 nexthdr = hdr->nexthdr; | 322 | u8 nexthdr = hdr->nexthdr; |
310 | int offset; | 323 | int offset; |
311 | 324 | ||
@@ -319,10 +332,11 @@ static int ip6_forward_proxy_check(struct sk_buff *skb) | |||
319 | if (nexthdr == IPPROTO_ICMPV6) { | 332 | if (nexthdr == IPPROTO_ICMPV6) { |
320 | struct icmp6hdr *icmp6; | 333 | struct icmp6hdr *icmp6; |
321 | 334 | ||
322 | if (!pskb_may_pull(skb, skb->nh.raw + offset + 1 - skb->data)) | 335 | if (!pskb_may_pull(skb, (skb_network_header(skb) + |
336 | offset + 1 - skb->data))) | ||
323 | return 0; | 337 | return 0; |
324 | 338 | ||
325 | icmp6 = (struct icmp6hdr *)(skb->nh.raw + offset); | 339 | icmp6 = (struct icmp6hdr *)(skb_network_header(skb) + offset); |
326 | 340 | ||
327 | switch (icmp6->icmp6_type) { | 341 | switch (icmp6->icmp6_type) { |
328 | case NDISC_ROUTER_SOLICITATION: | 342 | case NDISC_ROUTER_SOLICITATION: |
@@ -361,7 +375,7 @@ static inline int ip6_forward_finish(struct sk_buff *skb) | |||
361 | int ip6_forward(struct sk_buff *skb) | 375 | int ip6_forward(struct sk_buff *skb) |
362 | { | 376 | { |
363 | struct dst_entry *dst = skb->dst; | 377 | struct dst_entry *dst = skb->dst; |
364 | struct ipv6hdr *hdr = skb->nh.ipv6h; | 378 | struct ipv6hdr *hdr = ipv6_hdr(skb); |
365 | struct inet6_skb_parm *opt = IP6CB(skb); | 379 | struct inet6_skb_parm *opt = IP6CB(skb); |
366 | 380 | ||
367 | if (ipv6_devconf.forwarding == 0) | 381 | if (ipv6_devconf.forwarding == 0) |
@@ -372,7 +386,7 @@ int ip6_forward(struct sk_buff *skb) | |||
372 | goto drop; | 386 | goto drop; |
373 | } | 387 | } |
374 | 388 | ||
375 | skb->ip_summed = CHECKSUM_NONE; | 389 | skb_forward_csum(skb); |
376 | 390 | ||
377 | /* | 391 | /* |
378 | * We DO NOT make any processing on | 392 | * We DO NOT make any processing on |
@@ -388,7 +402,7 @@ int ip6_forward(struct sk_buff *skb) | |||
388 | * that different fragments will go along one path. --ANK | 402 | * that different fragments will go along one path. --ANK |
389 | */ | 403 | */ |
390 | if (opt->ra) { | 404 | if (opt->ra) { |
391 | u8 *ptr = skb->nh.raw + opt->ra; | 405 | u8 *ptr = skb_network_header(skb) + opt->ra; |
392 | if (ip6_call_ra_chain(skb, (ptr[2]<<8) + ptr[3])) | 406 | if (ip6_call_ra_chain(skb, (ptr[2]<<8) + ptr[3])) |
393 | return 0; | 407 | return 0; |
394 | } | 408 | } |
@@ -470,7 +484,7 @@ int ip6_forward(struct sk_buff *skb) | |||
470 | goto drop; | 484 | goto drop; |
471 | } | 485 | } |
472 | 486 | ||
473 | hdr = skb->nh.ipv6h; | 487 | hdr = ipv6_hdr(skb); |
474 | 488 | ||
475 | /* Mangling hops number delayed to point after skb COW */ | 489 | /* Mangling hops number delayed to point after skb COW */ |
476 | 490 | ||
@@ -499,33 +513,18 @@ static void ip6_copy_metadata(struct sk_buff *to, struct sk_buff *from) | |||
499 | #ifdef CONFIG_NET_SCHED | 513 | #ifdef CONFIG_NET_SCHED |
500 | to->tc_index = from->tc_index; | 514 | to->tc_index = from->tc_index; |
501 | #endif | 515 | #endif |
502 | #ifdef CONFIG_NETFILTER | 516 | nf_copy(to, from); |
503 | /* Connection association is same as pre-frag packet */ | ||
504 | nf_conntrack_put(to->nfct); | ||
505 | to->nfct = from->nfct; | ||
506 | nf_conntrack_get(to->nfct); | ||
507 | to->nfctinfo = from->nfctinfo; | ||
508 | #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) | ||
509 | nf_conntrack_put_reasm(to->nfct_reasm); | ||
510 | to->nfct_reasm = from->nfct_reasm; | ||
511 | nf_conntrack_get_reasm(to->nfct_reasm); | ||
512 | #endif | ||
513 | #ifdef CONFIG_BRIDGE_NETFILTER | ||
514 | nf_bridge_put(to->nf_bridge); | ||
515 | to->nf_bridge = from->nf_bridge; | ||
516 | nf_bridge_get(to->nf_bridge); | ||
517 | #endif | ||
518 | #endif | ||
519 | skb_copy_secmark(to, from); | 517 | skb_copy_secmark(to, from); |
520 | } | 518 | } |
521 | 519 | ||
522 | int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) | 520 | int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) |
523 | { | 521 | { |
524 | u16 offset = sizeof(struct ipv6hdr); | 522 | u16 offset = sizeof(struct ipv6hdr); |
525 | struct ipv6_opt_hdr *exthdr = (struct ipv6_opt_hdr*)(skb->nh.ipv6h + 1); | 523 | struct ipv6_opt_hdr *exthdr = |
526 | unsigned int packet_len = skb->tail - skb->nh.raw; | 524 | (struct ipv6_opt_hdr *)(ipv6_hdr(skb) + 1); |
525 | unsigned int packet_len = skb->tail - skb->network_header; | ||
527 | int found_rhdr = 0; | 526 | int found_rhdr = 0; |
528 | *nexthdr = &skb->nh.ipv6h->nexthdr; | 527 | *nexthdr = &ipv6_hdr(skb)->nexthdr; |
529 | 528 | ||
530 | while (offset + 1 <= packet_len) { | 529 | while (offset + 1 <= packet_len) { |
531 | 530 | ||
@@ -550,7 +549,8 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) | |||
550 | 549 | ||
551 | offset += ipv6_optlen(exthdr); | 550 | offset += ipv6_optlen(exthdr); |
552 | *nexthdr = &exthdr->nexthdr; | 551 | *nexthdr = &exthdr->nexthdr; |
553 | exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset); | 552 | exthdr = (struct ipv6_opt_hdr *)(skb_network_header(skb) + |
553 | offset); | ||
554 | } | 554 | } |
555 | 555 | ||
556 | return offset; | 556 | return offset; |
@@ -574,7 +574,20 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | |||
574 | hlen = ip6_find_1stfragopt(skb, &prevhdr); | 574 | hlen = ip6_find_1stfragopt(skb, &prevhdr); |
575 | nexthdr = *prevhdr; | 575 | nexthdr = *prevhdr; |
576 | 576 | ||
577 | mtu = dst_mtu(&rt->u.dst); | 577 | mtu = ip6_skb_dst_mtu(skb); |
578 | |||
579 | /* We must not fragment if the socket is set to force MTU discovery | ||
580 | * or if the skb it not generated by a local socket. (This last | ||
581 | * check should be redundant, but it's free.) | ||
582 | */ | ||
583 | if (!np || np->pmtudisc >= IPV6_PMTUDISC_DO) { | ||
584 | skb->dev = skb->dst->dev; | ||
585 | icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, skb->dev); | ||
586 | IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_FRAGFAILS); | ||
587 | kfree_skb(skb); | ||
588 | return -EMSGSIZE; | ||
589 | } | ||
590 | |||
578 | if (np && np->frag_size < mtu) { | 591 | if (np && np->frag_size < mtu) { |
579 | if (np->frag_size) | 592 | if (np->frag_size) |
580 | mtu = np->frag_size; | 593 | mtu = np->frag_size; |
@@ -616,7 +629,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | |||
616 | /* BUILD HEADER */ | 629 | /* BUILD HEADER */ |
617 | 630 | ||
618 | *prevhdr = NEXTHDR_FRAGMENT; | 631 | *prevhdr = NEXTHDR_FRAGMENT; |
619 | tmp_hdr = kmemdup(skb->nh.raw, hlen, GFP_ATOMIC); | 632 | tmp_hdr = kmemdup(skb_network_header(skb), hlen, GFP_ATOMIC); |
620 | if (!tmp_hdr) { | 633 | if (!tmp_hdr) { |
621 | IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_FRAGFAILS); | 634 | IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_FRAGFAILS); |
622 | return -ENOMEM; | 635 | return -ENOMEM; |
@@ -624,8 +637,9 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | |||
624 | 637 | ||
625 | __skb_pull(skb, hlen); | 638 | __skb_pull(skb, hlen); |
626 | fh = (struct frag_hdr*)__skb_push(skb, sizeof(struct frag_hdr)); | 639 | fh = (struct frag_hdr*)__skb_push(skb, sizeof(struct frag_hdr)); |
627 | skb->nh.raw = __skb_push(skb, hlen); | 640 | __skb_push(skb, hlen); |
628 | memcpy(skb->nh.raw, tmp_hdr, hlen); | 641 | skb_reset_network_header(skb); |
642 | memcpy(skb_network_header(skb), tmp_hdr, hlen); | ||
629 | 643 | ||
630 | ipv6_select_ident(skb, fh); | 644 | ipv6_select_ident(skb, fh); |
631 | fh->nexthdr = nexthdr; | 645 | fh->nexthdr = nexthdr; |
@@ -636,7 +650,8 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | |||
636 | first_len = skb_pagelen(skb); | 650 | first_len = skb_pagelen(skb); |
637 | skb->data_len = first_len - skb_headlen(skb); | 651 | skb->data_len = first_len - skb_headlen(skb); |
638 | skb->len = first_len; | 652 | skb->len = first_len; |
639 | skb->nh.ipv6h->payload_len = htons(first_len - sizeof(struct ipv6hdr)); | 653 | ipv6_hdr(skb)->payload_len = htons(first_len - |
654 | sizeof(struct ipv6hdr)); | ||
640 | 655 | ||
641 | dst_hold(&rt->u.dst); | 656 | dst_hold(&rt->u.dst); |
642 | 657 | ||
@@ -645,10 +660,12 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | |||
645 | * before previous one went down. */ | 660 | * before previous one went down. */ |
646 | if (frag) { | 661 | if (frag) { |
647 | frag->ip_summed = CHECKSUM_NONE; | 662 | frag->ip_summed = CHECKSUM_NONE; |
648 | frag->h.raw = frag->data; | 663 | skb_reset_transport_header(frag); |
649 | fh = (struct frag_hdr*)__skb_push(frag, sizeof(struct frag_hdr)); | 664 | fh = (struct frag_hdr*)__skb_push(frag, sizeof(struct frag_hdr)); |
650 | frag->nh.raw = __skb_push(frag, hlen); | 665 | __skb_push(frag, hlen); |
651 | memcpy(frag->nh.raw, tmp_hdr, hlen); | 666 | skb_reset_network_header(frag); |
667 | memcpy(skb_network_header(frag), tmp_hdr, | ||
668 | hlen); | ||
652 | offset += skb->len - hlen - sizeof(struct frag_hdr); | 669 | offset += skb->len - hlen - sizeof(struct frag_hdr); |
653 | fh->nexthdr = nexthdr; | 670 | fh->nexthdr = nexthdr; |
654 | fh->reserved = 0; | 671 | fh->reserved = 0; |
@@ -656,7 +673,9 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | |||
656 | if (frag->next != NULL) | 673 | if (frag->next != NULL) |
657 | fh->frag_off |= htons(IP6_MF); | 674 | fh->frag_off |= htons(IP6_MF); |
658 | fh->identification = frag_id; | 675 | fh->identification = frag_id; |
659 | frag->nh.ipv6h->payload_len = htons(frag->len - sizeof(struct ipv6hdr)); | 676 | ipv6_hdr(frag)->payload_len = |
677 | htons(frag->len - | ||
678 | sizeof(struct ipv6hdr)); | ||
660 | ip6_copy_metadata(frag, skb); | 679 | ip6_copy_metadata(frag, skb); |
661 | } | 680 | } |
662 | 681 | ||
@@ -733,9 +752,10 @@ slow_path: | |||
733 | ip6_copy_metadata(frag, skb); | 752 | ip6_copy_metadata(frag, skb); |
734 | skb_reserve(frag, LL_RESERVED_SPACE(rt->u.dst.dev)); | 753 | skb_reserve(frag, LL_RESERVED_SPACE(rt->u.dst.dev)); |
735 | skb_put(frag, len + hlen + sizeof(struct frag_hdr)); | 754 | skb_put(frag, len + hlen + sizeof(struct frag_hdr)); |
736 | frag->nh.raw = frag->data; | 755 | skb_reset_network_header(frag); |
737 | fh = (struct frag_hdr*)(frag->data + hlen); | 756 | fh = (struct frag_hdr *)(skb_network_header(frag) + hlen); |
738 | frag->h.raw = frag->data + hlen + sizeof(struct frag_hdr); | 757 | frag->transport_header = (frag->network_header + hlen + |
758 | sizeof(struct frag_hdr)); | ||
739 | 759 | ||
740 | /* | 760 | /* |
741 | * Charge the memory for the fragment to any owner | 761 | * Charge the memory for the fragment to any owner |
@@ -747,7 +767,7 @@ slow_path: | |||
747 | /* | 767 | /* |
748 | * Copy the packet header into the new buffer. | 768 | * Copy the packet header into the new buffer. |
749 | */ | 769 | */ |
750 | memcpy(frag->nh.raw, skb->data, hlen); | 770 | skb_copy_from_linear_data(skb, skb_network_header(frag), hlen); |
751 | 771 | ||
752 | /* | 772 | /* |
753 | * Build fragment header. | 773 | * Build fragment header. |
@@ -763,14 +783,15 @@ slow_path: | |||
763 | /* | 783 | /* |
764 | * Copy a block of the IP datagram. | 784 | * Copy a block of the IP datagram. |
765 | */ | 785 | */ |
766 | if (skb_copy_bits(skb, ptr, frag->h.raw, len)) | 786 | if (skb_copy_bits(skb, ptr, skb_transport_header(skb), len)) |
767 | BUG(); | 787 | BUG(); |
768 | left -= len; | 788 | left -= len; |
769 | 789 | ||
770 | fh->frag_off = htons(offset); | 790 | fh->frag_off = htons(offset); |
771 | if (left > 0) | 791 | if (left > 0) |
772 | fh->frag_off |= htons(IP6_MF); | 792 | fh->frag_off |= htons(IP6_MF); |
773 | frag->nh.ipv6h->payload_len = htons(frag->len - sizeof(struct ipv6hdr)); | 793 | ipv6_hdr(frag)->payload_len = htons(frag->len - |
794 | sizeof(struct ipv6hdr)); | ||
774 | 795 | ||
775 | ptr += len; | 796 | ptr += len; |
776 | offset += len; | 797 | offset += len; |
@@ -861,6 +882,41 @@ static int ip6_dst_lookup_tail(struct sock *sk, | |||
861 | goto out_err_release; | 882 | goto out_err_release; |
862 | } | 883 | } |
863 | 884 | ||
885 | #ifdef CONFIG_IPV6_OPTIMISTIC_DAD | ||
886 | /* | ||
887 | * Here if the dst entry we've looked up | ||
888 | * has a neighbour entry that is in the INCOMPLETE | ||
889 | * state and the src address from the flow is | ||
890 | * marked as OPTIMISTIC, we release the found | ||
891 | * dst entry and replace it instead with the | ||
892 | * dst entry of the nexthop router | ||
893 | */ | ||
894 | if (!((*dst)->neighbour->nud_state & NUD_VALID)) { | ||
895 | struct inet6_ifaddr *ifp; | ||
896 | struct flowi fl_gw; | ||
897 | int redirect; | ||
898 | |||
899 | ifp = ipv6_get_ifaddr(&fl->fl6_src, (*dst)->dev, 1); | ||
900 | |||
901 | redirect = (ifp && ifp->flags & IFA_F_OPTIMISTIC); | ||
902 | if (ifp) | ||
903 | in6_ifa_put(ifp); | ||
904 | |||
905 | if (redirect) { | ||
906 | /* | ||
907 | * We need to get the dst entry for the | ||
908 | * default router instead | ||
909 | */ | ||
910 | dst_release(*dst); | ||
911 | memcpy(&fl_gw, fl, sizeof(struct flowi)); | ||
912 | memset(&fl_gw.fl6_dst, 0, sizeof(struct in6_addr)); | ||
913 | *dst = ip6_route_output(sk, &fl_gw); | ||
914 | if ((err = (*dst)->error)) | ||
915 | goto out_err_release; | ||
916 | } | ||
917 | } | ||
918 | #endif | ||
919 | |||
864 | return 0; | 920 | return 0; |
865 | 921 | ||
866 | out_err_release: | 922 | out_err_release: |
@@ -939,10 +995,10 @@ static inline int ip6_ufo_append_data(struct sock *sk, | |||
939 | skb_put(skb,fragheaderlen + transhdrlen); | 995 | skb_put(skb,fragheaderlen + transhdrlen); |
940 | 996 | ||
941 | /* initialize network header pointer */ | 997 | /* initialize network header pointer */ |
942 | skb->nh.raw = skb->data; | 998 | skb_reset_network_header(skb); |
943 | 999 | ||
944 | /* initialize protocol header pointer */ | 1000 | /* initialize protocol header pointer */ |
945 | skb->h.raw = skb->data + fragheaderlen; | 1001 | skb->transport_header = skb->network_header + fragheaderlen; |
946 | 1002 | ||
947 | skb->ip_summed = CHECKSUM_PARTIAL; | 1003 | skb->ip_summed = CHECKSUM_PARTIAL; |
948 | skb->csum = 0; | 1004 | skb->csum = 0; |
@@ -1015,7 +1071,8 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
1015 | inet->cork.fl = *fl; | 1071 | inet->cork.fl = *fl; |
1016 | np->cork.hop_limit = hlimit; | 1072 | np->cork.hop_limit = hlimit; |
1017 | np->cork.tclass = tclass; | 1073 | np->cork.tclass = tclass; |
1018 | mtu = dst_mtu(rt->u.dst.path); | 1074 | mtu = np->pmtudisc == IPV6_PMTUDISC_PROBE ? |
1075 | rt->u.dst.dev->mtu : dst_mtu(rt->u.dst.path); | ||
1019 | if (np->frag_size < mtu) { | 1076 | if (np->frag_size < mtu) { |
1020 | if (np->frag_size) | 1077 | if (np->frag_size) |
1021 | mtu = np->frag_size; | 1078 | mtu = np->frag_size; |
@@ -1162,10 +1219,10 @@ alloc_new_skb: | |||
1162 | * Find where to start putting bytes | 1219 | * Find where to start putting bytes |
1163 | */ | 1220 | */ |
1164 | data = skb_put(skb, fraglen); | 1221 | data = skb_put(skb, fraglen); |
1165 | skb->nh.raw = data + exthdrlen; | 1222 | skb_set_network_header(skb, exthdrlen); |
1166 | data += fragheaderlen; | 1223 | data += fragheaderlen; |
1167 | skb->h.raw = data + exthdrlen; | 1224 | skb->transport_header = (skb->network_header + |
1168 | 1225 | fragheaderlen); | |
1169 | if (fraggap) { | 1226 | if (fraggap) { |
1170 | skb->csum = skb_copy_and_csum_bits( | 1227 | skb->csum = skb_copy_and_csum_bits( |
1171 | skb_prev, maxfraglen, | 1228 | skb_prev, maxfraglen, |
@@ -1288,10 +1345,10 @@ int ip6_push_pending_frames(struct sock *sk) | |||
1288 | tail_skb = &(skb_shinfo(skb)->frag_list); | 1345 | tail_skb = &(skb_shinfo(skb)->frag_list); |
1289 | 1346 | ||
1290 | /* move skb->data to ip header from ext header */ | 1347 | /* move skb->data to ip header from ext header */ |
1291 | if (skb->data < skb->nh.raw) | 1348 | if (skb->data < skb_network_header(skb)) |
1292 | __skb_pull(skb, skb->nh.raw - skb->data); | 1349 | __skb_pull(skb, skb_network_offset(skb)); |
1293 | while ((tmp_skb = __skb_dequeue(&sk->sk_write_queue)) != NULL) { | 1350 | while ((tmp_skb = __skb_dequeue(&sk->sk_write_queue)) != NULL) { |
1294 | __skb_pull(tmp_skb, skb->h.raw - skb->nh.raw); | 1351 | __skb_pull(tmp_skb, skb_network_header_len(skb)); |
1295 | *tail_skb = tmp_skb; | 1352 | *tail_skb = tmp_skb; |
1296 | tail_skb = &(tmp_skb->next); | 1353 | tail_skb = &(tmp_skb->next); |
1297 | skb->len += tmp_skb->len; | 1354 | skb->len += tmp_skb->len; |
@@ -1303,13 +1360,15 @@ int ip6_push_pending_frames(struct sock *sk) | |||
1303 | } | 1360 | } |
1304 | 1361 | ||
1305 | ipv6_addr_copy(final_dst, &fl->fl6_dst); | 1362 | ipv6_addr_copy(final_dst, &fl->fl6_dst); |
1306 | __skb_pull(skb, skb->h.raw - skb->nh.raw); | 1363 | __skb_pull(skb, skb_network_header_len(skb)); |
1307 | if (opt && opt->opt_flen) | 1364 | if (opt && opt->opt_flen) |
1308 | ipv6_push_frag_opts(skb, opt, &proto); | 1365 | ipv6_push_frag_opts(skb, opt, &proto); |
1309 | if (opt && opt->opt_nflen) | 1366 | if (opt && opt->opt_nflen) |
1310 | ipv6_push_nfrag_opts(skb, opt, &proto, &final_dst); | 1367 | ipv6_push_nfrag_opts(skb, opt, &proto, &final_dst); |
1311 | 1368 | ||
1312 | skb->nh.ipv6h = hdr = (struct ipv6hdr*) skb_push(skb, sizeof(struct ipv6hdr)); | 1369 | skb_push(skb, sizeof(struct ipv6hdr)); |
1370 | skb_reset_network_header(skb); | ||
1371 | hdr = ipv6_hdr(skb); | ||
1313 | 1372 | ||
1314 | *(__be32*)hdr = fl->fl6_flowlabel | | 1373 | *(__be32*)hdr = fl->fl6_flowlabel | |
1315 | htonl(0x60000000 | ((int)np->cork.tclass << 20)); | 1374 | htonl(0x60000000 | ((int)np->cork.tclass << 20)); |