diff options
Diffstat (limited to 'net/ipv4/ip_output.c')
-rw-r--r-- | net/ipv4/ip_output.c | 39 |
1 files changed, 25 insertions, 14 deletions
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index bc9e57550e86..03b9b0600276 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
@@ -91,6 +91,28 @@ __inline__ void ip_send_check(struct iphdr *iph) | |||
91 | iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); | 91 | iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); |
92 | } | 92 | } |
93 | 93 | ||
94 | int __ip_local_out(struct sk_buff *skb) | ||
95 | { | ||
96 | struct iphdr *iph = ip_hdr(skb); | ||
97 | |||
98 | iph->tot_len = htons(skb->len); | ||
99 | ip_send_check(iph); | ||
100 | return nf_hook(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, skb->dst->dev, | ||
101 | dst_output); | ||
102 | } | ||
103 | |||
104 | int ip_local_out(struct sk_buff *skb) | ||
105 | { | ||
106 | int err; | ||
107 | |||
108 | err = __ip_local_out(skb); | ||
109 | if (likely(err == 1)) | ||
110 | err = dst_output(skb); | ||
111 | |||
112 | return err; | ||
113 | } | ||
114 | EXPORT_SYMBOL_GPL(ip_local_out); | ||
115 | |||
94 | /* dev_loopback_xmit for use with netfilter. */ | 116 | /* dev_loopback_xmit for use with netfilter. */ |
95 | static int ip_dev_loopback_xmit(struct sk_buff *newskb) | 117 | static int ip_dev_loopback_xmit(struct sk_buff *newskb) |
96 | { | 118 | { |
@@ -138,20 +160,17 @@ int ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk, | |||
138 | iph->daddr = rt->rt_dst; | 160 | iph->daddr = rt->rt_dst; |
139 | iph->saddr = rt->rt_src; | 161 | iph->saddr = rt->rt_src; |
140 | iph->protocol = sk->sk_protocol; | 162 | iph->protocol = sk->sk_protocol; |
141 | iph->tot_len = htons(skb->len); | ||
142 | ip_select_ident(iph, &rt->u.dst, sk); | 163 | ip_select_ident(iph, &rt->u.dst, sk); |
143 | 164 | ||
144 | if (opt && opt->optlen) { | 165 | if (opt && opt->optlen) { |
145 | iph->ihl += opt->optlen>>2; | 166 | iph->ihl += opt->optlen>>2; |
146 | ip_options_build(skb, opt, daddr, rt, 0); | 167 | ip_options_build(skb, opt, daddr, rt, 0); |
147 | } | 168 | } |
148 | ip_send_check(iph); | ||
149 | 169 | ||
150 | skb->priority = sk->sk_priority; | 170 | skb->priority = sk->sk_priority; |
151 | 171 | ||
152 | /* Send it out. */ | 172 | /* Send it out. */ |
153 | return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev, | 173 | return ip_local_out(skb); |
154 | dst_output); | ||
155 | } | 174 | } |
156 | 175 | ||
157 | EXPORT_SYMBOL_GPL(ip_build_and_send_pkt); | 176 | EXPORT_SYMBOL_GPL(ip_build_and_send_pkt); |
@@ -347,7 +366,6 @@ packet_routed: | |||
347 | skb_reset_network_header(skb); | 366 | skb_reset_network_header(skb); |
348 | iph = ip_hdr(skb); | 367 | iph = ip_hdr(skb); |
349 | *((__be16 *)iph) = htons((4 << 12) | (5 << 8) | (inet->tos & 0xff)); | 368 | *((__be16 *)iph) = htons((4 << 12) | (5 << 8) | (inet->tos & 0xff)); |
350 | iph->tot_len = htons(skb->len); | ||
351 | if (ip_dont_fragment(sk, &rt->u.dst) && !ipfragok) | 369 | if (ip_dont_fragment(sk, &rt->u.dst) && !ipfragok) |
352 | iph->frag_off = htons(IP_DF); | 370 | iph->frag_off = htons(IP_DF); |
353 | else | 371 | else |
@@ -366,13 +384,9 @@ packet_routed: | |||
366 | ip_select_ident_more(iph, &rt->u.dst, sk, | 384 | ip_select_ident_more(iph, &rt->u.dst, sk, |
367 | (skb_shinfo(skb)->gso_segs ?: 1) - 1); | 385 | (skb_shinfo(skb)->gso_segs ?: 1) - 1); |
368 | 386 | ||
369 | /* Add an IP checksum. */ | ||
370 | ip_send_check(iph); | ||
371 | |||
372 | skb->priority = sk->sk_priority; | 387 | skb->priority = sk->sk_priority; |
373 | 388 | ||
374 | return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev, | 389 | return ip_local_out(skb); |
375 | dst_output); | ||
376 | 390 | ||
377 | no_route: | 391 | no_route: |
378 | IP_INC_STATS(IPSTATS_MIB_OUTNOROUTES); | 392 | IP_INC_STATS(IPSTATS_MIB_OUTNOROUTES); |
@@ -1262,14 +1276,12 @@ int ip_push_pending_frames(struct sock *sk) | |||
1262 | ip_options_build(skb, opt, inet->cork.addr, rt, 0); | 1276 | ip_options_build(skb, opt, inet->cork.addr, rt, 0); |
1263 | } | 1277 | } |
1264 | iph->tos = inet->tos; | 1278 | iph->tos = inet->tos; |
1265 | iph->tot_len = htons(skb->len); | ||
1266 | iph->frag_off = df; | 1279 | iph->frag_off = df; |
1267 | ip_select_ident(iph, &rt->u.dst, sk); | 1280 | ip_select_ident(iph, &rt->u.dst, sk); |
1268 | iph->ttl = ttl; | 1281 | iph->ttl = ttl; |
1269 | iph->protocol = sk->sk_protocol; | 1282 | iph->protocol = sk->sk_protocol; |
1270 | iph->saddr = rt->rt_src; | 1283 | iph->saddr = rt->rt_src; |
1271 | iph->daddr = rt->rt_dst; | 1284 | iph->daddr = rt->rt_dst; |
1272 | ip_send_check(iph); | ||
1273 | 1285 | ||
1274 | skb->priority = sk->sk_priority; | 1286 | skb->priority = sk->sk_priority; |
1275 | skb->dst = dst_clone(&rt->u.dst); | 1287 | skb->dst = dst_clone(&rt->u.dst); |
@@ -1279,8 +1291,7 @@ int ip_push_pending_frames(struct sock *sk) | |||
1279 | skb_transport_header(skb))->type); | 1291 | skb_transport_header(skb))->type); |
1280 | 1292 | ||
1281 | /* Netfilter gets whole the not fragmented skb. */ | 1293 | /* Netfilter gets whole the not fragmented skb. */ |
1282 | err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, | 1294 | err = ip_local_out(skb); |
1283 | skb->dst->dev, dst_output); | ||
1284 | if (err) { | 1295 | if (err) { |
1285 | if (err > 0) | 1296 | if (err > 0) |
1286 | err = inet->recverr ? net_xmit_errno(err) : 0; | 1297 | err = inet->recverr ? net_xmit_errno(err) : 0; |