aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/ip_output.c
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2008-01-11 22:14:00 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-28 17:53:47 -0500
commitc439cb2e4b13cf1cb2abcd006b906315a3381323 (patch)
tree7bb9d27214e010d37d6a715d0533a7148a8f429a /net/ipv4/ip_output.c
parent227620e295090629fcb2c46ad3828222ab65438d (diff)
[IPV4]: Add ip_local_out
Most callers of the LOCAL_OUT chain will set the IP packet length and header checksum before doing so. They also share the same output function dst_output. This patch creates a new function called ip_local_out which does all of that and converts the appropriate users over to it. Apart from removing duplicate code, it will also help in merging the IPsec output path once the same thing is done for IPv6. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
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;