aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/ip_output.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/ip_output.c')
-rw-r--r--net/ipv4/ip_output.c39
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
94int __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
104int 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}
114EXPORT_SYMBOL_GPL(ip_local_out);
115
94/* dev_loopback_xmit for use with netfilter. */ 116/* dev_loopback_xmit for use with netfilter. */
95static int ip_dev_loopback_xmit(struct sk_buff *newskb) 117static 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
157EXPORT_SYMBOL_GPL(ip_build_and_send_pkt); 176EXPORT_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
377no_route: 391no_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;