diff options
Diffstat (limited to 'net/ipv4/ip_output.c')
-rw-r--r-- | net/ipv4/ip_output.c | 453 |
1 files changed, 266 insertions, 187 deletions
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 04c7b3ba6b39..98af3697c718 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
@@ -140,14 +140,14 @@ static inline int ip_select_ttl(struct inet_sock *inet, struct dst_entry *dst) | |||
140 | * | 140 | * |
141 | */ | 141 | */ |
142 | int ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk, | 142 | int ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk, |
143 | __be32 saddr, __be32 daddr, struct ip_options *opt) | 143 | __be32 saddr, __be32 daddr, struct ip_options_rcu *opt) |
144 | { | 144 | { |
145 | struct inet_sock *inet = inet_sk(sk); | 145 | struct inet_sock *inet = inet_sk(sk); |
146 | struct rtable *rt = skb_rtable(skb); | 146 | struct rtable *rt = skb_rtable(skb); |
147 | struct iphdr *iph; | 147 | struct iphdr *iph; |
148 | 148 | ||
149 | /* Build the IP header. */ | 149 | /* Build the IP header. */ |
150 | skb_push(skb, sizeof(struct iphdr) + (opt ? opt->optlen : 0)); | 150 | skb_push(skb, sizeof(struct iphdr) + (opt ? opt->opt.optlen : 0)); |
151 | skb_reset_network_header(skb); | 151 | skb_reset_network_header(skb); |
152 | iph = ip_hdr(skb); | 152 | iph = ip_hdr(skb); |
153 | iph->version = 4; | 153 | iph->version = 4; |
@@ -158,14 +158,14 @@ int ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk, | |||
158 | else | 158 | else |
159 | iph->frag_off = 0; | 159 | iph->frag_off = 0; |
160 | iph->ttl = ip_select_ttl(inet, &rt->dst); | 160 | iph->ttl = ip_select_ttl(inet, &rt->dst); |
161 | iph->daddr = rt->rt_dst; | 161 | iph->daddr = (opt && opt->opt.srr ? opt->opt.faddr : daddr); |
162 | iph->saddr = rt->rt_src; | 162 | iph->saddr = saddr; |
163 | iph->protocol = sk->sk_protocol; | 163 | iph->protocol = sk->sk_protocol; |
164 | ip_select_ident(iph, &rt->dst, sk); | 164 | ip_select_ident(iph, &rt->dst, sk); |
165 | 165 | ||
166 | if (opt && opt->optlen) { | 166 | if (opt && opt->opt.optlen) { |
167 | iph->ihl += opt->optlen>>2; | 167 | iph->ihl += opt->opt.optlen>>2; |
168 | ip_options_build(skb, opt, daddr, rt, 0); | 168 | ip_options_build(skb, &opt->opt, daddr, rt, 0); |
169 | } | 169 | } |
170 | 170 | ||
171 | skb->priority = sk->sk_priority; | 171 | skb->priority = sk->sk_priority; |
@@ -312,11 +312,12 @@ int ip_output(struct sk_buff *skb) | |||
312 | !(IPCB(skb)->flags & IPSKB_REROUTED)); | 312 | !(IPCB(skb)->flags & IPSKB_REROUTED)); |
313 | } | 313 | } |
314 | 314 | ||
315 | int ip_queue_xmit(struct sk_buff *skb) | 315 | int ip_queue_xmit(struct sk_buff *skb, struct flowi *fl) |
316 | { | 316 | { |
317 | struct sock *sk = skb->sk; | 317 | struct sock *sk = skb->sk; |
318 | struct inet_sock *inet = inet_sk(sk); | 318 | struct inet_sock *inet = inet_sk(sk); |
319 | struct ip_options *opt = inet->opt; | 319 | struct ip_options_rcu *inet_opt; |
320 | struct flowi4 *fl4; | ||
320 | struct rtable *rt; | 321 | struct rtable *rt; |
321 | struct iphdr *iph; | 322 | struct iphdr *iph; |
322 | int res; | 323 | int res; |
@@ -325,6 +326,8 @@ int ip_queue_xmit(struct sk_buff *skb) | |||
325 | * f.e. by something like SCTP. | 326 | * f.e. by something like SCTP. |
326 | */ | 327 | */ |
327 | rcu_read_lock(); | 328 | rcu_read_lock(); |
329 | inet_opt = rcu_dereference(inet->inet_opt); | ||
330 | fl4 = &fl->u.ip4; | ||
328 | rt = skb_rtable(skb); | 331 | rt = skb_rtable(skb); |
329 | if (rt != NULL) | 332 | if (rt != NULL) |
330 | goto packet_routed; | 333 | goto packet_routed; |
@@ -336,38 +339,32 @@ int ip_queue_xmit(struct sk_buff *skb) | |||
336 | 339 | ||
337 | /* Use correct destination address if we have options. */ | 340 | /* Use correct destination address if we have options. */ |
338 | daddr = inet->inet_daddr; | 341 | daddr = inet->inet_daddr; |
339 | if(opt && opt->srr) | 342 | if (inet_opt && inet_opt->opt.srr) |
340 | daddr = opt->faddr; | 343 | daddr = inet_opt->opt.faddr; |
341 | 344 | ||
342 | { | 345 | /* If this fails, retransmit mechanism of transport layer will |
343 | struct flowi fl = { .oif = sk->sk_bound_dev_if, | 346 | * keep trying until route appears or the connection times |
344 | .mark = sk->sk_mark, | 347 | * itself out. |
345 | .fl4_dst = daddr, | 348 | */ |
346 | .fl4_src = inet->inet_saddr, | 349 | rt = ip_route_output_ports(sock_net(sk), fl4, sk, |
347 | .fl4_tos = RT_CONN_FLAGS(sk), | 350 | daddr, inet->inet_saddr, |
348 | .proto = sk->sk_protocol, | 351 | inet->inet_dport, |
349 | .flags = inet_sk_flowi_flags(sk), | 352 | inet->inet_sport, |
350 | .fl_ip_sport = inet->inet_sport, | 353 | sk->sk_protocol, |
351 | .fl_ip_dport = inet->inet_dport }; | 354 | RT_CONN_FLAGS(sk), |
352 | 355 | sk->sk_bound_dev_if); | |
353 | /* If this fails, retransmit mechanism of transport layer will | 356 | if (IS_ERR(rt)) |
354 | * keep trying until route appears or the connection times | 357 | goto no_route; |
355 | * itself out. | ||
356 | */ | ||
357 | security_sk_classify_flow(sk, &fl); | ||
358 | if (ip_route_output_flow(sock_net(sk), &rt, &fl, sk, 0)) | ||
359 | goto no_route; | ||
360 | } | ||
361 | sk_setup_caps(sk, &rt->dst); | 358 | sk_setup_caps(sk, &rt->dst); |
362 | } | 359 | } |
363 | skb_dst_set_noref(skb, &rt->dst); | 360 | skb_dst_set_noref(skb, &rt->dst); |
364 | 361 | ||
365 | packet_routed: | 362 | packet_routed: |
366 | if (opt && opt->is_strictroute && rt->rt_dst != rt->rt_gateway) | 363 | if (inet_opt && inet_opt->opt.is_strictroute && fl4->daddr != rt->rt_gateway) |
367 | goto no_route; | 364 | goto no_route; |
368 | 365 | ||
369 | /* OK, we know where to send it, allocate and build IP header. */ | 366 | /* OK, we know where to send it, allocate and build IP header. */ |
370 | skb_push(skb, sizeof(struct iphdr) + (opt ? opt->optlen : 0)); | 367 | skb_push(skb, sizeof(struct iphdr) + (inet_opt ? inet_opt->opt.optlen : 0)); |
371 | skb_reset_network_header(skb); | 368 | skb_reset_network_header(skb); |
372 | iph = ip_hdr(skb); | 369 | iph = ip_hdr(skb); |
373 | *((__be16 *)iph) = htons((4 << 12) | (5 << 8) | (inet->tos & 0xff)); | 370 | *((__be16 *)iph) = htons((4 << 12) | (5 << 8) | (inet->tos & 0xff)); |
@@ -377,13 +374,13 @@ packet_routed: | |||
377 | iph->frag_off = 0; | 374 | iph->frag_off = 0; |
378 | iph->ttl = ip_select_ttl(inet, &rt->dst); | 375 | iph->ttl = ip_select_ttl(inet, &rt->dst); |
379 | iph->protocol = sk->sk_protocol; | 376 | iph->protocol = sk->sk_protocol; |
380 | iph->saddr = rt->rt_src; | 377 | iph->saddr = fl4->saddr; |
381 | iph->daddr = rt->rt_dst; | 378 | iph->daddr = fl4->daddr; |
382 | /* Transport layer set skb->h.foo itself. */ | 379 | /* Transport layer set skb->h.foo itself. */ |
383 | 380 | ||
384 | if (opt && opt->optlen) { | 381 | if (inet_opt && inet_opt->opt.optlen) { |
385 | iph->ihl += opt->optlen >> 2; | 382 | iph->ihl += inet_opt->opt.optlen >> 2; |
386 | ip_options_build(skb, opt, inet->inet_daddr, rt, 0); | 383 | ip_options_build(skb, &inet_opt->opt, inet->inet_daddr, rt, 0); |
387 | } | 384 | } |
388 | 385 | ||
389 | ip_select_ident_more(iph, &rt->dst, sk, | 386 | ip_select_ident_more(iph, &rt->dst, sk, |
@@ -609,7 +606,7 @@ slow_path: | |||
609 | /* IF: it doesn't fit, use 'mtu' - the data space left */ | 606 | /* IF: it doesn't fit, use 'mtu' - the data space left */ |
610 | if (len > mtu) | 607 | if (len > mtu) |
611 | len = mtu; | 608 | len = mtu; |
612 | /* IF: we are not sending upto and including the packet end | 609 | /* IF: we are not sending up to and including the packet end |
613 | then align the next start on an eight byte boundary */ | 610 | then align the next start on an eight byte boundary */ |
614 | if (len < left) { | 611 | if (len < left) { |
615 | len &= ~7; | 612 | len &= ~7; |
@@ -733,6 +730,7 @@ csum_page(struct page *page, int offset, int copy) | |||
733 | } | 730 | } |
734 | 731 | ||
735 | static inline int ip_ufo_append_data(struct sock *sk, | 732 | static inline int ip_ufo_append_data(struct sock *sk, |
733 | struct sk_buff_head *queue, | ||
736 | int getfrag(void *from, char *to, int offset, int len, | 734 | int getfrag(void *from, char *to, int offset, int len, |
737 | int odd, struct sk_buff *skb), | 735 | int odd, struct sk_buff *skb), |
738 | void *from, int length, int hh_len, int fragheaderlen, | 736 | void *from, int length, int hh_len, int fragheaderlen, |
@@ -745,7 +743,7 @@ static inline int ip_ufo_append_data(struct sock *sk, | |||
745 | * device, so create one single skb packet containing complete | 743 | * device, so create one single skb packet containing complete |
746 | * udp datagram | 744 | * udp datagram |
747 | */ | 745 | */ |
748 | if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL) { | 746 | if ((skb = skb_peek_tail(queue)) == NULL) { |
749 | skb = sock_alloc_send_skb(sk, | 747 | skb = sock_alloc_send_skb(sk, |
750 | hh_len + fragheaderlen + transhdrlen + 20, | 748 | hh_len + fragheaderlen + transhdrlen + 20, |
751 | (flags & MSG_DONTWAIT), &err); | 749 | (flags & MSG_DONTWAIT), &err); |
@@ -767,40 +765,30 @@ static inline int ip_ufo_append_data(struct sock *sk, | |||
767 | 765 | ||
768 | skb->ip_summed = CHECKSUM_PARTIAL; | 766 | skb->ip_summed = CHECKSUM_PARTIAL; |
769 | skb->csum = 0; | 767 | skb->csum = 0; |
770 | sk->sk_sndmsg_off = 0; | ||
771 | 768 | ||
772 | /* specify the length of each IP datagram fragment */ | 769 | /* specify the length of each IP datagram fragment */ |
773 | skb_shinfo(skb)->gso_size = mtu - fragheaderlen; | 770 | skb_shinfo(skb)->gso_size = mtu - fragheaderlen; |
774 | skb_shinfo(skb)->gso_type = SKB_GSO_UDP; | 771 | skb_shinfo(skb)->gso_type = SKB_GSO_UDP; |
775 | __skb_queue_tail(&sk->sk_write_queue, skb); | 772 | __skb_queue_tail(queue, skb); |
776 | } | 773 | } |
777 | 774 | ||
778 | return skb_append_datato_frags(sk, skb, getfrag, from, | 775 | return skb_append_datato_frags(sk, skb, getfrag, from, |
779 | (length - transhdrlen)); | 776 | (length - transhdrlen)); |
780 | } | 777 | } |
781 | 778 | ||
782 | /* | 779 | static int __ip_append_data(struct sock *sk, |
783 | * ip_append_data() and ip_append_page() can make one large IP datagram | 780 | struct flowi4 *fl4, |
784 | * from many pieces of data. Each pieces will be holded on the socket | 781 | struct sk_buff_head *queue, |
785 | * until ip_push_pending_frames() is called. Each piece can be a page | 782 | struct inet_cork *cork, |
786 | * or non-page data. | 783 | int getfrag(void *from, char *to, int offset, |
787 | * | 784 | int len, int odd, struct sk_buff *skb), |
788 | * Not only UDP, other transport protocols - e.g. raw sockets - can use | 785 | void *from, int length, int transhdrlen, |
789 | * this interface potentially. | 786 | unsigned int flags) |
790 | * | ||
791 | * LATER: length must be adjusted by pad at tail, when it is required. | ||
792 | */ | ||
793 | int ip_append_data(struct sock *sk, | ||
794 | int getfrag(void *from, char *to, int offset, int len, | ||
795 | int odd, struct sk_buff *skb), | ||
796 | void *from, int length, int transhdrlen, | ||
797 | struct ipcm_cookie *ipc, struct rtable **rtp, | ||
798 | unsigned int flags) | ||
799 | { | 787 | { |
800 | struct inet_sock *inet = inet_sk(sk); | 788 | struct inet_sock *inet = inet_sk(sk); |
801 | struct sk_buff *skb; | 789 | struct sk_buff *skb; |
802 | 790 | ||
803 | struct ip_options *opt = NULL; | 791 | struct ip_options *opt = cork->opt; |
804 | int hh_len; | 792 | int hh_len; |
805 | int exthdrlen; | 793 | int exthdrlen; |
806 | int mtu; | 794 | int mtu; |
@@ -809,59 +797,20 @@ int ip_append_data(struct sock *sk, | |||
809 | int offset = 0; | 797 | int offset = 0; |
810 | unsigned int maxfraglen, fragheaderlen; | 798 | unsigned int maxfraglen, fragheaderlen; |
811 | int csummode = CHECKSUM_NONE; | 799 | int csummode = CHECKSUM_NONE; |
812 | struct rtable *rt; | 800 | struct rtable *rt = (struct rtable *)cork->dst; |
813 | |||
814 | if (flags&MSG_PROBE) | ||
815 | return 0; | ||
816 | 801 | ||
817 | if (skb_queue_empty(&sk->sk_write_queue)) { | 802 | exthdrlen = transhdrlen ? rt->dst.header_len : 0; |
818 | /* | 803 | length += exthdrlen; |
819 | * setup for corking. | 804 | transhdrlen += exthdrlen; |
820 | */ | 805 | mtu = cork->fragsize; |
821 | opt = ipc->opt; | ||
822 | if (opt) { | ||
823 | if (inet->cork.opt == NULL) { | ||
824 | inet->cork.opt = kmalloc(sizeof(struct ip_options) + 40, sk->sk_allocation); | ||
825 | if (unlikely(inet->cork.opt == NULL)) | ||
826 | return -ENOBUFS; | ||
827 | } | ||
828 | memcpy(inet->cork.opt, opt, sizeof(struct ip_options)+opt->optlen); | ||
829 | inet->cork.flags |= IPCORK_OPT; | ||
830 | inet->cork.addr = ipc->addr; | ||
831 | } | ||
832 | rt = *rtp; | ||
833 | if (unlikely(!rt)) | ||
834 | return -EFAULT; | ||
835 | /* | ||
836 | * We steal reference to this route, caller should not release it | ||
837 | */ | ||
838 | *rtp = NULL; | ||
839 | inet->cork.fragsize = mtu = inet->pmtudisc == IP_PMTUDISC_PROBE ? | ||
840 | rt->dst.dev->mtu : | ||
841 | dst_mtu(rt->dst.path); | ||
842 | inet->cork.dst = &rt->dst; | ||
843 | inet->cork.length = 0; | ||
844 | sk->sk_sndmsg_page = NULL; | ||
845 | sk->sk_sndmsg_off = 0; | ||
846 | exthdrlen = rt->dst.header_len; | ||
847 | length += exthdrlen; | ||
848 | transhdrlen += exthdrlen; | ||
849 | } else { | ||
850 | rt = (struct rtable *)inet->cork.dst; | ||
851 | if (inet->cork.flags & IPCORK_OPT) | ||
852 | opt = inet->cork.opt; | ||
853 | 806 | ||
854 | transhdrlen = 0; | ||
855 | exthdrlen = 0; | ||
856 | mtu = inet->cork.fragsize; | ||
857 | } | ||
858 | hh_len = LL_RESERVED_SPACE(rt->dst.dev); | 807 | hh_len = LL_RESERVED_SPACE(rt->dst.dev); |
859 | 808 | ||
860 | fragheaderlen = sizeof(struct iphdr) + (opt ? opt->optlen : 0); | 809 | fragheaderlen = sizeof(struct iphdr) + (opt ? opt->optlen : 0); |
861 | maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen; | 810 | maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen; |
862 | 811 | ||
863 | if (inet->cork.length + length > 0xFFFF - fragheaderlen) { | 812 | if (cork->length + length > 0xFFFF - fragheaderlen) { |
864 | ip_local_error(sk, EMSGSIZE, rt->rt_dst, inet->inet_dport, | 813 | ip_local_error(sk, EMSGSIZE, fl4->daddr, inet->inet_dport, |
865 | mtu-exthdrlen); | 814 | mtu-exthdrlen); |
866 | return -EMSGSIZE; | 815 | return -EMSGSIZE; |
867 | } | 816 | } |
@@ -876,15 +825,15 @@ int ip_append_data(struct sock *sk, | |||
876 | !exthdrlen) | 825 | !exthdrlen) |
877 | csummode = CHECKSUM_PARTIAL; | 826 | csummode = CHECKSUM_PARTIAL; |
878 | 827 | ||
879 | skb = skb_peek_tail(&sk->sk_write_queue); | 828 | skb = skb_peek_tail(queue); |
880 | 829 | ||
881 | inet->cork.length += length; | 830 | cork->length += length; |
882 | if (((length > mtu) || (skb && skb_is_gso(skb))) && | 831 | if (((length > mtu) || (skb && skb_is_gso(skb))) && |
883 | (sk->sk_protocol == IPPROTO_UDP) && | 832 | (sk->sk_protocol == IPPROTO_UDP) && |
884 | (rt->dst.dev->features & NETIF_F_UFO)) { | 833 | (rt->dst.dev->features & NETIF_F_UFO)) { |
885 | err = ip_ufo_append_data(sk, getfrag, from, length, hh_len, | 834 | err = ip_ufo_append_data(sk, queue, getfrag, from, length, |
886 | fragheaderlen, transhdrlen, mtu, | 835 | hh_len, fragheaderlen, transhdrlen, |
887 | flags); | 836 | mtu, flags); |
888 | if (err) | 837 | if (err) |
889 | goto error; | 838 | goto error; |
890 | return 0; | 839 | return 0; |
@@ -961,7 +910,7 @@ alloc_new_skb: | |||
961 | else | 910 | else |
962 | /* only the initial fragment is | 911 | /* only the initial fragment is |
963 | time stamped */ | 912 | time stamped */ |
964 | ipc->tx_flags = 0; | 913 | cork->tx_flags = 0; |
965 | } | 914 | } |
966 | if (skb == NULL) | 915 | if (skb == NULL) |
967 | goto error; | 916 | goto error; |
@@ -972,7 +921,7 @@ alloc_new_skb: | |||
972 | skb->ip_summed = csummode; | 921 | skb->ip_summed = csummode; |
973 | skb->csum = 0; | 922 | skb->csum = 0; |
974 | skb_reserve(skb, hh_len); | 923 | skb_reserve(skb, hh_len); |
975 | skb_shinfo(skb)->tx_flags = ipc->tx_flags; | 924 | skb_shinfo(skb)->tx_flags = cork->tx_flags; |
976 | 925 | ||
977 | /* | 926 | /* |
978 | * Find where to start putting bytes. | 927 | * Find where to start putting bytes. |
@@ -1009,7 +958,7 @@ alloc_new_skb: | |||
1009 | /* | 958 | /* |
1010 | * Put the packet on the pending queue. | 959 | * Put the packet on the pending queue. |
1011 | */ | 960 | */ |
1012 | __skb_queue_tail(&sk->sk_write_queue, skb); | 961 | __skb_queue_tail(queue, skb); |
1013 | continue; | 962 | continue; |
1014 | } | 963 | } |
1015 | 964 | ||
@@ -1029,8 +978,8 @@ alloc_new_skb: | |||
1029 | } else { | 978 | } else { |
1030 | int i = skb_shinfo(skb)->nr_frags; | 979 | int i = skb_shinfo(skb)->nr_frags; |
1031 | skb_frag_t *frag = &skb_shinfo(skb)->frags[i-1]; | 980 | skb_frag_t *frag = &skb_shinfo(skb)->frags[i-1]; |
1032 | struct page *page = sk->sk_sndmsg_page; | 981 | struct page *page = cork->page; |
1033 | int off = sk->sk_sndmsg_off; | 982 | int off = cork->off; |
1034 | unsigned int left; | 983 | unsigned int left; |
1035 | 984 | ||
1036 | if (page && (left = PAGE_SIZE - off) > 0) { | 985 | if (page && (left = PAGE_SIZE - off) > 0) { |
@@ -1042,7 +991,7 @@ alloc_new_skb: | |||
1042 | goto error; | 991 | goto error; |
1043 | } | 992 | } |
1044 | get_page(page); | 993 | get_page(page); |
1045 | skb_fill_page_desc(skb, i, page, sk->sk_sndmsg_off, 0); | 994 | skb_fill_page_desc(skb, i, page, off, 0); |
1046 | frag = &skb_shinfo(skb)->frags[i]; | 995 | frag = &skb_shinfo(skb)->frags[i]; |
1047 | } | 996 | } |
1048 | } else if (i < MAX_SKB_FRAGS) { | 997 | } else if (i < MAX_SKB_FRAGS) { |
@@ -1053,8 +1002,8 @@ alloc_new_skb: | |||
1053 | err = -ENOMEM; | 1002 | err = -ENOMEM; |
1054 | goto error; | 1003 | goto error; |
1055 | } | 1004 | } |
1056 | sk->sk_sndmsg_page = page; | 1005 | cork->page = page; |
1057 | sk->sk_sndmsg_off = 0; | 1006 | cork->off = 0; |
1058 | 1007 | ||
1059 | skb_fill_page_desc(skb, i, page, 0, 0); | 1008 | skb_fill_page_desc(skb, i, page, 0, 0); |
1060 | frag = &skb_shinfo(skb)->frags[i]; | 1009 | frag = &skb_shinfo(skb)->frags[i]; |
@@ -1066,7 +1015,7 @@ alloc_new_skb: | |||
1066 | err = -EFAULT; | 1015 | err = -EFAULT; |
1067 | goto error; | 1016 | goto error; |
1068 | } | 1017 | } |
1069 | sk->sk_sndmsg_off += copy; | 1018 | cork->off += copy; |
1070 | frag->size += copy; | 1019 | frag->size += copy; |
1071 | skb->len += copy; | 1020 | skb->len += copy; |
1072 | skb->data_len += copy; | 1021 | skb->data_len += copy; |
@@ -1080,18 +1029,95 @@ alloc_new_skb: | |||
1080 | return 0; | 1029 | return 0; |
1081 | 1030 | ||
1082 | error: | 1031 | error: |
1083 | inet->cork.length -= length; | 1032 | cork->length -= length; |
1084 | IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTDISCARDS); | 1033 | IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTDISCARDS); |
1085 | return err; | 1034 | return err; |
1086 | } | 1035 | } |
1087 | 1036 | ||
1088 | ssize_t ip_append_page(struct sock *sk, struct page *page, | 1037 | static int ip_setup_cork(struct sock *sk, struct inet_cork *cork, |
1038 | struct ipcm_cookie *ipc, struct rtable **rtp) | ||
1039 | { | ||
1040 | struct inet_sock *inet = inet_sk(sk); | ||
1041 | struct ip_options_rcu *opt; | ||
1042 | struct rtable *rt; | ||
1043 | |||
1044 | /* | ||
1045 | * setup for corking. | ||
1046 | */ | ||
1047 | opt = ipc->opt; | ||
1048 | if (opt) { | ||
1049 | if (cork->opt == NULL) { | ||
1050 | cork->opt = kmalloc(sizeof(struct ip_options) + 40, | ||
1051 | sk->sk_allocation); | ||
1052 | if (unlikely(cork->opt == NULL)) | ||
1053 | return -ENOBUFS; | ||
1054 | } | ||
1055 | memcpy(cork->opt, &opt->opt, sizeof(struct ip_options) + opt->opt.optlen); | ||
1056 | cork->flags |= IPCORK_OPT; | ||
1057 | cork->addr = ipc->addr; | ||
1058 | } | ||
1059 | rt = *rtp; | ||
1060 | if (unlikely(!rt)) | ||
1061 | return -EFAULT; | ||
1062 | /* | ||
1063 | * We steal reference to this route, caller should not release it | ||
1064 | */ | ||
1065 | *rtp = NULL; | ||
1066 | cork->fragsize = inet->pmtudisc == IP_PMTUDISC_PROBE ? | ||
1067 | rt->dst.dev->mtu : dst_mtu(rt->dst.path); | ||
1068 | cork->dst = &rt->dst; | ||
1069 | cork->length = 0; | ||
1070 | cork->tx_flags = ipc->tx_flags; | ||
1071 | cork->page = NULL; | ||
1072 | cork->off = 0; | ||
1073 | |||
1074 | return 0; | ||
1075 | } | ||
1076 | |||
1077 | /* | ||
1078 | * ip_append_data() and ip_append_page() can make one large IP datagram | ||
1079 | * from many pieces of data. Each pieces will be holded on the socket | ||
1080 | * until ip_push_pending_frames() is called. Each piece can be a page | ||
1081 | * or non-page data. | ||
1082 | * | ||
1083 | * Not only UDP, other transport protocols - e.g. raw sockets - can use | ||
1084 | * this interface potentially. | ||
1085 | * | ||
1086 | * LATER: length must be adjusted by pad at tail, when it is required. | ||
1087 | */ | ||
1088 | int ip_append_data(struct sock *sk, struct flowi4 *fl4, | ||
1089 | int getfrag(void *from, char *to, int offset, int len, | ||
1090 | int odd, struct sk_buff *skb), | ||
1091 | void *from, int length, int transhdrlen, | ||
1092 | struct ipcm_cookie *ipc, struct rtable **rtp, | ||
1093 | unsigned int flags) | ||
1094 | { | ||
1095 | struct inet_sock *inet = inet_sk(sk); | ||
1096 | int err; | ||
1097 | |||
1098 | if (flags&MSG_PROBE) | ||
1099 | return 0; | ||
1100 | |||
1101 | if (skb_queue_empty(&sk->sk_write_queue)) { | ||
1102 | err = ip_setup_cork(sk, &inet->cork.base, ipc, rtp); | ||
1103 | if (err) | ||
1104 | return err; | ||
1105 | } else { | ||
1106 | transhdrlen = 0; | ||
1107 | } | ||
1108 | |||
1109 | return __ip_append_data(sk, fl4, &sk->sk_write_queue, &inet->cork.base, getfrag, | ||
1110 | from, length, transhdrlen, flags); | ||
1111 | } | ||
1112 | |||
1113 | ssize_t ip_append_page(struct sock *sk, struct flowi4 *fl4, struct page *page, | ||
1089 | int offset, size_t size, int flags) | 1114 | int offset, size_t size, int flags) |
1090 | { | 1115 | { |
1091 | struct inet_sock *inet = inet_sk(sk); | 1116 | struct inet_sock *inet = inet_sk(sk); |
1092 | struct sk_buff *skb; | 1117 | struct sk_buff *skb; |
1093 | struct rtable *rt; | 1118 | struct rtable *rt; |
1094 | struct ip_options *opt = NULL; | 1119 | struct ip_options *opt = NULL; |
1120 | struct inet_cork *cork; | ||
1095 | int hh_len; | 1121 | int hh_len; |
1096 | int mtu; | 1122 | int mtu; |
1097 | int len; | 1123 | int len; |
@@ -1107,28 +1133,29 @@ ssize_t ip_append_page(struct sock *sk, struct page *page, | |||
1107 | if (skb_queue_empty(&sk->sk_write_queue)) | 1133 | if (skb_queue_empty(&sk->sk_write_queue)) |
1108 | return -EINVAL; | 1134 | return -EINVAL; |
1109 | 1135 | ||
1110 | rt = (struct rtable *)inet->cork.dst; | 1136 | cork = &inet->cork.base; |
1111 | if (inet->cork.flags & IPCORK_OPT) | 1137 | rt = (struct rtable *)cork->dst; |
1112 | opt = inet->cork.opt; | 1138 | if (cork->flags & IPCORK_OPT) |
1139 | opt = cork->opt; | ||
1113 | 1140 | ||
1114 | if (!(rt->dst.dev->features&NETIF_F_SG)) | 1141 | if (!(rt->dst.dev->features&NETIF_F_SG)) |
1115 | return -EOPNOTSUPP; | 1142 | return -EOPNOTSUPP; |
1116 | 1143 | ||
1117 | hh_len = LL_RESERVED_SPACE(rt->dst.dev); | 1144 | hh_len = LL_RESERVED_SPACE(rt->dst.dev); |
1118 | mtu = inet->cork.fragsize; | 1145 | mtu = cork->fragsize; |
1119 | 1146 | ||
1120 | fragheaderlen = sizeof(struct iphdr) + (opt ? opt->optlen : 0); | 1147 | fragheaderlen = sizeof(struct iphdr) + (opt ? opt->optlen : 0); |
1121 | maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen; | 1148 | maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen; |
1122 | 1149 | ||
1123 | if (inet->cork.length + size > 0xFFFF - fragheaderlen) { | 1150 | if (cork->length + size > 0xFFFF - fragheaderlen) { |
1124 | ip_local_error(sk, EMSGSIZE, rt->rt_dst, inet->inet_dport, mtu); | 1151 | ip_local_error(sk, EMSGSIZE, fl4->daddr, inet->inet_dport, mtu); |
1125 | return -EMSGSIZE; | 1152 | return -EMSGSIZE; |
1126 | } | 1153 | } |
1127 | 1154 | ||
1128 | if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL) | 1155 | if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL) |
1129 | return -EINVAL; | 1156 | return -EINVAL; |
1130 | 1157 | ||
1131 | inet->cork.length += size; | 1158 | cork->length += size; |
1132 | if ((size + skb->len > mtu) && | 1159 | if ((size + skb->len > mtu) && |
1133 | (sk->sk_protocol == IPPROTO_UDP) && | 1160 | (sk->sk_protocol == IPPROTO_UDP) && |
1134 | (rt->dst.dev->features & NETIF_F_UFO)) { | 1161 | (rt->dst.dev->features & NETIF_F_UFO)) { |
@@ -1223,45 +1250,47 @@ ssize_t ip_append_page(struct sock *sk, struct page *page, | |||
1223 | return 0; | 1250 | return 0; |
1224 | 1251 | ||
1225 | error: | 1252 | error: |
1226 | inet->cork.length -= size; | 1253 | cork->length -= size; |
1227 | IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTDISCARDS); | 1254 | IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTDISCARDS); |
1228 | return err; | 1255 | return err; |
1229 | } | 1256 | } |
1230 | 1257 | ||
1231 | static void ip_cork_release(struct inet_sock *inet) | 1258 | static void ip_cork_release(struct inet_cork *cork) |
1232 | { | 1259 | { |
1233 | inet->cork.flags &= ~IPCORK_OPT; | 1260 | cork->flags &= ~IPCORK_OPT; |
1234 | kfree(inet->cork.opt); | 1261 | kfree(cork->opt); |
1235 | inet->cork.opt = NULL; | 1262 | cork->opt = NULL; |
1236 | dst_release(inet->cork.dst); | 1263 | dst_release(cork->dst); |
1237 | inet->cork.dst = NULL; | 1264 | cork->dst = NULL; |
1238 | } | 1265 | } |
1239 | 1266 | ||
1240 | /* | 1267 | /* |
1241 | * Combined all pending IP fragments on the socket as one IP datagram | 1268 | * Combined all pending IP fragments on the socket as one IP datagram |
1242 | * and push them out. | 1269 | * and push them out. |
1243 | */ | 1270 | */ |
1244 | int ip_push_pending_frames(struct sock *sk) | 1271 | struct sk_buff *__ip_make_skb(struct sock *sk, |
1272 | struct flowi4 *fl4, | ||
1273 | struct sk_buff_head *queue, | ||
1274 | struct inet_cork *cork) | ||
1245 | { | 1275 | { |
1246 | struct sk_buff *skb, *tmp_skb; | 1276 | struct sk_buff *skb, *tmp_skb; |
1247 | struct sk_buff **tail_skb; | 1277 | struct sk_buff **tail_skb; |
1248 | struct inet_sock *inet = inet_sk(sk); | 1278 | struct inet_sock *inet = inet_sk(sk); |
1249 | struct net *net = sock_net(sk); | 1279 | struct net *net = sock_net(sk); |
1250 | struct ip_options *opt = NULL; | 1280 | struct ip_options *opt = NULL; |
1251 | struct rtable *rt = (struct rtable *)inet->cork.dst; | 1281 | struct rtable *rt = (struct rtable *)cork->dst; |
1252 | struct iphdr *iph; | 1282 | struct iphdr *iph; |
1253 | __be16 df = 0; | 1283 | __be16 df = 0; |
1254 | __u8 ttl; | 1284 | __u8 ttl; |
1255 | int err = 0; | ||
1256 | 1285 | ||
1257 | if ((skb = __skb_dequeue(&sk->sk_write_queue)) == NULL) | 1286 | if ((skb = __skb_dequeue(queue)) == NULL) |
1258 | goto out; | 1287 | goto out; |
1259 | tail_skb = &(skb_shinfo(skb)->frag_list); | 1288 | tail_skb = &(skb_shinfo(skb)->frag_list); |
1260 | 1289 | ||
1261 | /* move skb->data to ip header from ext header */ | 1290 | /* move skb->data to ip header from ext header */ |
1262 | if (skb->data < skb_network_header(skb)) | 1291 | if (skb->data < skb_network_header(skb)) |
1263 | __skb_pull(skb, skb_network_offset(skb)); | 1292 | __skb_pull(skb, skb_network_offset(skb)); |
1264 | while ((tmp_skb = __skb_dequeue(&sk->sk_write_queue)) != NULL) { | 1293 | while ((tmp_skb = __skb_dequeue(queue)) != NULL) { |
1265 | __skb_pull(tmp_skb, skb_network_header_len(skb)); | 1294 | __skb_pull(tmp_skb, skb_network_header_len(skb)); |
1266 | *tail_skb = tmp_skb; | 1295 | *tail_skb = tmp_skb; |
1267 | tail_skb = &(tmp_skb->next); | 1296 | tail_skb = &(tmp_skb->next); |
@@ -1287,8 +1316,8 @@ int ip_push_pending_frames(struct sock *sk) | |||
1287 | ip_dont_fragment(sk, &rt->dst))) | 1316 | ip_dont_fragment(sk, &rt->dst))) |
1288 | df = htons(IP_DF); | 1317 | df = htons(IP_DF); |
1289 | 1318 | ||
1290 | if (inet->cork.flags & IPCORK_OPT) | 1319 | if (cork->flags & IPCORK_OPT) |
1291 | opt = inet->cork.opt; | 1320 | opt = cork->opt; |
1292 | 1321 | ||
1293 | if (rt->rt_type == RTN_MULTICAST) | 1322 | if (rt->rt_type == RTN_MULTICAST) |
1294 | ttl = inet->mc_ttl; | 1323 | ttl = inet->mc_ttl; |
@@ -1298,17 +1327,18 @@ int ip_push_pending_frames(struct sock *sk) | |||
1298 | iph = (struct iphdr *)skb->data; | 1327 | iph = (struct iphdr *)skb->data; |
1299 | iph->version = 4; | 1328 | iph->version = 4; |
1300 | iph->ihl = 5; | 1329 | iph->ihl = 5; |
1301 | if (opt) { | ||
1302 | iph->ihl += opt->optlen>>2; | ||
1303 | ip_options_build(skb, opt, inet->cork.addr, rt, 0); | ||
1304 | } | ||
1305 | iph->tos = inet->tos; | 1330 | iph->tos = inet->tos; |
1306 | iph->frag_off = df; | 1331 | iph->frag_off = df; |
1307 | ip_select_ident(iph, &rt->dst, sk); | 1332 | ip_select_ident(iph, &rt->dst, sk); |
1308 | iph->ttl = ttl; | 1333 | iph->ttl = ttl; |
1309 | iph->protocol = sk->sk_protocol; | 1334 | iph->protocol = sk->sk_protocol; |
1310 | iph->saddr = rt->rt_src; | 1335 | iph->saddr = fl4->saddr; |
1311 | iph->daddr = rt->rt_dst; | 1336 | iph->daddr = fl4->daddr; |
1337 | |||
1338 | if (opt) { | ||
1339 | iph->ihl += opt->optlen>>2; | ||
1340 | ip_options_build(skb, opt, cork->addr, rt, 0); | ||
1341 | } | ||
1312 | 1342 | ||
1313 | skb->priority = sk->sk_priority; | 1343 | skb->priority = sk->sk_priority; |
1314 | skb->mark = sk->sk_mark; | 1344 | skb->mark = sk->sk_mark; |
@@ -1316,44 +1346,99 @@ int ip_push_pending_frames(struct sock *sk) | |||
1316 | * Steal rt from cork.dst to avoid a pair of atomic_inc/atomic_dec | 1346 | * Steal rt from cork.dst to avoid a pair of atomic_inc/atomic_dec |
1317 | * on dst refcount | 1347 | * on dst refcount |
1318 | */ | 1348 | */ |
1319 | inet->cork.dst = NULL; | 1349 | cork->dst = NULL; |
1320 | skb_dst_set(skb, &rt->dst); | 1350 | skb_dst_set(skb, &rt->dst); |
1321 | 1351 | ||
1322 | if (iph->protocol == IPPROTO_ICMP) | 1352 | if (iph->protocol == IPPROTO_ICMP) |
1323 | icmp_out_count(net, ((struct icmphdr *) | 1353 | icmp_out_count(net, ((struct icmphdr *) |
1324 | skb_transport_header(skb))->type); | 1354 | skb_transport_header(skb))->type); |
1325 | 1355 | ||
1326 | /* Netfilter gets whole the not fragmented skb. */ | 1356 | ip_cork_release(cork); |
1357 | out: | ||
1358 | return skb; | ||
1359 | } | ||
1360 | |||
1361 | int ip_send_skb(struct sk_buff *skb) | ||
1362 | { | ||
1363 | struct net *net = sock_net(skb->sk); | ||
1364 | int err; | ||
1365 | |||
1327 | err = ip_local_out(skb); | 1366 | err = ip_local_out(skb); |
1328 | if (err) { | 1367 | if (err) { |
1329 | if (err > 0) | 1368 | if (err > 0) |
1330 | err = net_xmit_errno(err); | 1369 | err = net_xmit_errno(err); |
1331 | if (err) | 1370 | if (err) |
1332 | goto error; | 1371 | IP_INC_STATS(net, IPSTATS_MIB_OUTDISCARDS); |
1333 | } | 1372 | } |
1334 | 1373 | ||
1335 | out: | ||
1336 | ip_cork_release(inet); | ||
1337 | return err; | 1374 | return err; |
1375 | } | ||
1338 | 1376 | ||
1339 | error: | 1377 | int ip_push_pending_frames(struct sock *sk, struct flowi4 *fl4) |
1340 | IP_INC_STATS(net, IPSTATS_MIB_OUTDISCARDS); | 1378 | { |
1341 | goto out; | 1379 | struct sk_buff *skb; |
1380 | |||
1381 | skb = ip_finish_skb(sk, fl4); | ||
1382 | if (!skb) | ||
1383 | return 0; | ||
1384 | |||
1385 | /* Netfilter gets whole the not fragmented skb. */ | ||
1386 | return ip_send_skb(skb); | ||
1342 | } | 1387 | } |
1343 | 1388 | ||
1344 | /* | 1389 | /* |
1345 | * Throw away all pending data on the socket. | 1390 | * Throw away all pending data on the socket. |
1346 | */ | 1391 | */ |
1347 | void ip_flush_pending_frames(struct sock *sk) | 1392 | static void __ip_flush_pending_frames(struct sock *sk, |
1393 | struct sk_buff_head *queue, | ||
1394 | struct inet_cork *cork) | ||
1348 | { | 1395 | { |
1349 | struct sk_buff *skb; | 1396 | struct sk_buff *skb; |
1350 | 1397 | ||
1351 | while ((skb = __skb_dequeue_tail(&sk->sk_write_queue)) != NULL) | 1398 | while ((skb = __skb_dequeue_tail(queue)) != NULL) |
1352 | kfree_skb(skb); | 1399 | kfree_skb(skb); |
1353 | 1400 | ||
1354 | ip_cork_release(inet_sk(sk)); | 1401 | ip_cork_release(cork); |
1355 | } | 1402 | } |
1356 | 1403 | ||
1404 | void ip_flush_pending_frames(struct sock *sk) | ||
1405 | { | ||
1406 | __ip_flush_pending_frames(sk, &sk->sk_write_queue, &inet_sk(sk)->cork.base); | ||
1407 | } | ||
1408 | |||
1409 | struct sk_buff *ip_make_skb(struct sock *sk, | ||
1410 | struct flowi4 *fl4, | ||
1411 | int getfrag(void *from, char *to, int offset, | ||
1412 | int len, int odd, struct sk_buff *skb), | ||
1413 | void *from, int length, int transhdrlen, | ||
1414 | struct ipcm_cookie *ipc, struct rtable **rtp, | ||
1415 | unsigned int flags) | ||
1416 | { | ||
1417 | struct inet_cork cork; | ||
1418 | struct sk_buff_head queue; | ||
1419 | int err; | ||
1420 | |||
1421 | if (flags & MSG_PROBE) | ||
1422 | return NULL; | ||
1423 | |||
1424 | __skb_queue_head_init(&queue); | ||
1425 | |||
1426 | cork.flags = 0; | ||
1427 | cork.addr = 0; | ||
1428 | cork.opt = NULL; | ||
1429 | err = ip_setup_cork(sk, &cork, ipc, rtp); | ||
1430 | if (err) | ||
1431 | return ERR_PTR(err); | ||
1432 | |||
1433 | err = __ip_append_data(sk, fl4, &queue, &cork, getfrag, | ||
1434 | from, length, transhdrlen, flags); | ||
1435 | if (err) { | ||
1436 | __ip_flush_pending_frames(sk, &queue, &cork); | ||
1437 | return ERR_PTR(err); | ||
1438 | } | ||
1439 | |||
1440 | return __ip_make_skb(sk, fl4, &queue, &cork); | ||
1441 | } | ||
1357 | 1442 | ||
1358 | /* | 1443 | /* |
1359 | * Fetch data from kernel space and fill in checksum if needed. | 1444 | * Fetch data from kernel space and fill in checksum if needed. |
@@ -1375,45 +1460,39 @@ static int ip_reply_glue_bits(void *dptr, char *to, int offset, | |||
1375 | * Should run single threaded per socket because it uses the sock | 1460 | * Should run single threaded per socket because it uses the sock |
1376 | * structure to pass arguments. | 1461 | * structure to pass arguments. |
1377 | */ | 1462 | */ |
1378 | void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *arg, | 1463 | void ip_send_reply(struct sock *sk, struct sk_buff *skb, __be32 daddr, |
1379 | unsigned int len) | 1464 | struct ip_reply_arg *arg, unsigned int len) |
1380 | { | 1465 | { |
1381 | struct inet_sock *inet = inet_sk(sk); | 1466 | struct inet_sock *inet = inet_sk(sk); |
1382 | struct { | 1467 | struct ip_options_data replyopts; |
1383 | struct ip_options opt; | ||
1384 | char data[40]; | ||
1385 | } replyopts; | ||
1386 | struct ipcm_cookie ipc; | 1468 | struct ipcm_cookie ipc; |
1387 | __be32 daddr; | 1469 | struct flowi4 fl4; |
1388 | struct rtable *rt = skb_rtable(skb); | 1470 | struct rtable *rt = skb_rtable(skb); |
1389 | 1471 | ||
1390 | if (ip_options_echo(&replyopts.opt, skb)) | 1472 | if (ip_options_echo(&replyopts.opt.opt, skb)) |
1391 | return; | 1473 | return; |
1392 | 1474 | ||
1393 | daddr = ipc.addr = rt->rt_src; | 1475 | ipc.addr = daddr; |
1394 | ipc.opt = NULL; | 1476 | ipc.opt = NULL; |
1395 | ipc.tx_flags = 0; | 1477 | ipc.tx_flags = 0; |
1396 | 1478 | ||
1397 | if (replyopts.opt.optlen) { | 1479 | if (replyopts.opt.opt.optlen) { |
1398 | ipc.opt = &replyopts.opt; | 1480 | ipc.opt = &replyopts.opt; |
1399 | 1481 | ||
1400 | if (ipc.opt->srr) | 1482 | if (replyopts.opt.opt.srr) |
1401 | daddr = replyopts.opt.faddr; | 1483 | daddr = replyopts.opt.opt.faddr; |
1402 | } | 1484 | } |
1403 | 1485 | ||
1404 | { | 1486 | flowi4_init_output(&fl4, arg->bound_dev_if, 0, |
1405 | struct flowi fl = { .oif = arg->bound_dev_if, | 1487 | RT_TOS(ip_hdr(skb)->tos), |
1406 | .fl4_dst = daddr, | 1488 | RT_SCOPE_UNIVERSE, sk->sk_protocol, |
1407 | .fl4_src = rt->rt_spec_dst, | 1489 | ip_reply_arg_flowi_flags(arg), |
1408 | .fl4_tos = RT_TOS(ip_hdr(skb)->tos), | 1490 | daddr, rt->rt_spec_dst, |
1409 | .fl_ip_sport = tcp_hdr(skb)->dest, | 1491 | tcp_hdr(skb)->source, tcp_hdr(skb)->dest); |
1410 | .fl_ip_dport = tcp_hdr(skb)->source, | 1492 | security_skb_classify_flow(skb, flowi4_to_flowi(&fl4)); |
1411 | .proto = sk->sk_protocol, | 1493 | rt = ip_route_output_key(sock_net(sk), &fl4); |
1412 | .flags = ip_reply_arg_flowi_flags(arg) }; | 1494 | if (IS_ERR(rt)) |
1413 | security_skb_classify_flow(skb, &fl); | 1495 | return; |
1414 | if (ip_route_output_key(sock_net(sk), &rt, &fl)) | ||
1415 | return; | ||
1416 | } | ||
1417 | 1496 | ||
1418 | /* And let IP do all the hard work. | 1497 | /* And let IP do all the hard work. |
1419 | 1498 | ||
@@ -1426,7 +1505,7 @@ void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *ar | |||
1426 | sk->sk_priority = skb->priority; | 1505 | sk->sk_priority = skb->priority; |
1427 | sk->sk_protocol = ip_hdr(skb)->protocol; | 1506 | sk->sk_protocol = ip_hdr(skb)->protocol; |
1428 | sk->sk_bound_dev_if = arg->bound_dev_if; | 1507 | sk->sk_bound_dev_if = arg->bound_dev_if; |
1429 | ip_append_data(sk, ip_reply_glue_bits, arg->iov->iov_base, len, 0, | 1508 | ip_append_data(sk, &fl4, ip_reply_glue_bits, arg->iov->iov_base, len, 0, |
1430 | &ipc, &rt, MSG_DONTWAIT); | 1509 | &ipc, &rt, MSG_DONTWAIT); |
1431 | if ((skb = skb_peek(&sk->sk_write_queue)) != NULL) { | 1510 | if ((skb = skb_peek(&sk->sk_write_queue)) != NULL) { |
1432 | if (arg->csumoffset >= 0) | 1511 | if (arg->csumoffset >= 0) |
@@ -1434,7 +1513,7 @@ void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *ar | |||
1434 | arg->csumoffset) = csum_fold(csum_add(skb->csum, | 1513 | arg->csumoffset) = csum_fold(csum_add(skb->csum, |
1435 | arg->csum)); | 1514 | arg->csum)); |
1436 | skb->ip_summed = CHECKSUM_NONE; | 1515 | skb->ip_summed = CHECKSUM_NONE; |
1437 | ip_push_pending_frames(sk); | 1516 | ip_push_pending_frames(sk, &fl4); |
1438 | } | 1517 | } |
1439 | 1518 | ||
1440 | bh_unlock_sock(sk); | 1519 | bh_unlock_sock(sk); |