aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/ip.h2
-rw-r--r--include/net/ipip.h5
-rw-r--r--net/ipv4/igmp.c12
-rw-r--r--net/ipv4/ip_output.c39
-rw-r--r--net/ipv4/ipvs/ip_vs_xmit.c6
-rw-r--r--net/ipv4/netfilter/ipt_REJECT.c8
-rw-r--r--net/ipv4/xfrm4_output.c8
7 files changed, 35 insertions, 45 deletions
diff --git a/include/net/ip.h b/include/net/ip.h
index 50c8889b1b8d..66d51616ade8 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -102,6 +102,8 @@ extern int ip_mc_output(struct sk_buff *skb);
102extern int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)); 102extern int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *));
103extern int ip_do_nat(struct sk_buff *skb); 103extern int ip_do_nat(struct sk_buff *skb);
104extern void ip_send_check(struct iphdr *ip); 104extern void ip_send_check(struct iphdr *ip);
105extern int __ip_local_out(struct sk_buff *skb);
106extern int ip_local_out(struct sk_buff *skb);
105extern int ip_queue_xmit(struct sk_buff *skb, int ipfragok); 107extern int ip_queue_xmit(struct sk_buff *skb, int ipfragok);
106extern void ip_init(void); 108extern void ip_init(void);
107extern int ip_append_data(struct sock *sk, 109extern int ip_append_data(struct sock *sk,
diff --git a/include/net/ipip.h b/include/net/ipip.h
index 7cdc914322f0..549e132bca9c 100644
--- a/include/net/ipip.h
+++ b/include/net/ipip.h
@@ -2,6 +2,7 @@
2#define __NET_IPIP_H 1 2#define __NET_IPIP_H 1
3 3
4#include <linux/if_tunnel.h> 4#include <linux/if_tunnel.h>
5#include <net/ip.h>
5 6
6/* Keep error state on tunnel for 30 sec */ 7/* Keep error state on tunnel for 30 sec */
7#define IPTUNNEL_ERR_TIMEO (30*HZ) 8#define IPTUNNEL_ERR_TIMEO (30*HZ)
@@ -30,11 +31,9 @@ struct ip_tunnel
30 int pkt_len = skb->len; \ 31 int pkt_len = skb->len; \
31 \ 32 \
32 skb->ip_summed = CHECKSUM_NONE; \ 33 skb->ip_summed = CHECKSUM_NONE; \
33 iph->tot_len = htons(skb->len); \
34 ip_select_ident(iph, &rt->u.dst, NULL); \ 34 ip_select_ident(iph, &rt->u.dst, NULL); \
35 ip_send_check(iph); \
36 \ 35 \
37 err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev, dst_output);\ 36 err = ip_local_out(skb); \
38 if (net_xmit_eval(err) == 0) { \ 37 if (net_xmit_eval(err) == 0) { \
39 stats->tx_bytes += pkt_len; \ 38 stats->tx_bytes += pkt_len; \
40 stats->tx_packets++; \ 39 stats->tx_packets++; \
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index 701558564e96..c560a9392b1d 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -349,17 +349,12 @@ static struct sk_buff *igmpv3_newpack(struct net_device *dev, int size)
349 349
350static int igmpv3_sendpack(struct sk_buff *skb) 350static int igmpv3_sendpack(struct sk_buff *skb)
351{ 351{
352 struct iphdr *pip = ip_hdr(skb);
353 struct igmphdr *pig = igmp_hdr(skb); 352 struct igmphdr *pig = igmp_hdr(skb);
354 const int iplen = skb->tail - skb->network_header;
355 const int igmplen = skb->tail - skb->transport_header; 353 const int igmplen = skb->tail - skb->transport_header;
356 354
357 pip->tot_len = htons(iplen);
358 ip_send_check(pip);
359 pig->csum = ip_compute_csum(igmp_hdr(skb), igmplen); 355 pig->csum = ip_compute_csum(igmp_hdr(skb), igmplen);
360 356
361 return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, skb->dev, 357 return ip_local_out(skb);
362 dst_output);
363} 358}
364 359
365static int grec_size(struct ip_mc_list *pmc, int type, int gdel, int sdel) 360static int grec_size(struct ip_mc_list *pmc, int type, int gdel, int sdel)
@@ -680,13 +675,11 @@ static int igmp_send_report(struct in_device *in_dev, struct ip_mc_list *pmc,
680 iph->daddr = dst; 675 iph->daddr = dst;
681 iph->saddr = rt->rt_src; 676 iph->saddr = rt->rt_src;
682 iph->protocol = IPPROTO_IGMP; 677 iph->protocol = IPPROTO_IGMP;
683 iph->tot_len = htons(IGMP_SIZE);
684 ip_select_ident(iph, &rt->u.dst, NULL); 678 ip_select_ident(iph, &rt->u.dst, NULL);
685 ((u8*)&iph[1])[0] = IPOPT_RA; 679 ((u8*)&iph[1])[0] = IPOPT_RA;
686 ((u8*)&iph[1])[1] = 4; 680 ((u8*)&iph[1])[1] = 4;
687 ((u8*)&iph[1])[2] = 0; 681 ((u8*)&iph[1])[2] = 0;
688 ((u8*)&iph[1])[3] = 0; 682 ((u8*)&iph[1])[3] = 0;
689 ip_send_check(iph);
690 683
691 ih = (struct igmphdr *)skb_put(skb, sizeof(struct igmphdr)); 684 ih = (struct igmphdr *)skb_put(skb, sizeof(struct igmphdr));
692 ih->type=type; 685 ih->type=type;
@@ -695,8 +688,7 @@ static int igmp_send_report(struct in_device *in_dev, struct ip_mc_list *pmc,
695 ih->group=group; 688 ih->group=group;
696 ih->csum=ip_compute_csum((void *)ih, sizeof(struct igmphdr)); 689 ih->csum=ip_compute_csum((void *)ih, sizeof(struct igmphdr));
697 690
698 return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev, 691 return ip_local_out(skb);
699 dst_output);
700} 692}
701 693
702static void igmp_gq_timer_expire(unsigned long data) 694static void igmp_gq_timer_expire(unsigned long data)
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;
diff --git a/net/ipv4/ipvs/ip_vs_xmit.c b/net/ipv4/ipvs/ip_vs_xmit.c
index 7c074e386c17..66775ad9e328 100644
--- a/net/ipv4/ipvs/ip_vs_xmit.c
+++ b/net/ipv4/ipvs/ip_vs_xmit.c
@@ -16,8 +16,8 @@
16 */ 16 */
17 17
18#include <linux/kernel.h> 18#include <linux/kernel.h>
19#include <linux/ip.h>
20#include <linux/tcp.h> /* for tcphdr */ 19#include <linux/tcp.h> /* for tcphdr */
20#include <net/ip.h>
21#include <net/tcp.h> /* for csum_tcpudp_magic */ 21#include <net/tcp.h> /* for csum_tcpudp_magic */
22#include <net/udp.h> 22#include <net/udp.h>
23#include <net/icmp.h> /* for icmp_send */ 23#include <net/icmp.h> /* for icmp_send */
@@ -406,14 +406,12 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
406 iph->daddr = rt->rt_dst; 406 iph->daddr = rt->rt_dst;
407 iph->saddr = rt->rt_src; 407 iph->saddr = rt->rt_src;
408 iph->ttl = old_iph->ttl; 408 iph->ttl = old_iph->ttl;
409 iph->tot_len = htons(skb->len);
410 ip_select_ident(iph, &rt->u.dst, NULL); 409 ip_select_ident(iph, &rt->u.dst, NULL);
411 ip_send_check(iph);
412 410
413 /* Another hack: avoid icmp_send in ip_fragment */ 411 /* Another hack: avoid icmp_send in ip_fragment */
414 skb->local_df = 1; 412 skb->local_df = 1;
415 413
416 IP_VS_XMIT(skb, rt); 414 ip_local_out(skb);
417 415
418 LeaveFunction(10); 416 LeaveFunction(10);
419 417
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c
index dcf4d21d5116..ccb2a03dcd5a 100644
--- a/net/ipv4/netfilter/ipt_REJECT.c
+++ b/net/ipv4/netfilter/ipt_REJECT.c
@@ -90,7 +90,6 @@ static void send_reset(struct sk_buff *oldskb, int hook)
90 /* Truncate to length (no data) */ 90 /* Truncate to length (no data) */
91 tcph->doff = sizeof(struct tcphdr)/4; 91 tcph->doff = sizeof(struct tcphdr)/4;
92 skb_trim(nskb, ip_hdrlen(nskb) + sizeof(struct tcphdr)); 92 skb_trim(nskb, ip_hdrlen(nskb) + sizeof(struct tcphdr));
93 niph->tot_len = htons(nskb->len);
94 93
95 if (tcph->ack) { 94 if (tcph->ack) {
96 needs_ack = 0; 95 needs_ack = 0;
@@ -139,18 +138,13 @@ static void send_reset(struct sk_buff *oldskb, int hook)
139 /* Adjust IP TTL */ 138 /* Adjust IP TTL */
140 niph->ttl = dst_metric(nskb->dst, RTAX_HOPLIMIT); 139 niph->ttl = dst_metric(nskb->dst, RTAX_HOPLIMIT);
141 140
142 /* Adjust IP checksum */
143 niph->check = 0;
144 niph->check = ip_fast_csum(skb_network_header(nskb), niph->ihl);
145
146 /* "Never happens" */ 141 /* "Never happens" */
147 if (nskb->len > dst_mtu(nskb->dst)) 142 if (nskb->len > dst_mtu(nskb->dst))
148 goto free_nskb; 143 goto free_nskb;
149 144
150 nf_ct_attach(nskb, oldskb); 145 nf_ct_attach(nskb, oldskb);
151 146
152 NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, nskb, NULL, nskb->dst->dev, 147 ip_local_out(nskb);
153 dst_output);
154 return; 148 return;
155 149
156 free_nskb: 150 free_nskb:
diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c
index 13fd11335e28..0ffc3d078489 100644
--- a/net/ipv4/xfrm4_output.c
+++ b/net/ipv4/xfrm4_output.c
@@ -69,17 +69,12 @@ EXPORT_SYMBOL(xfrm4_prepare_output);
69 69
70static inline int xfrm4_output_one(struct sk_buff *skb) 70static inline int xfrm4_output_one(struct sk_buff *skb)
71{ 71{
72 struct iphdr *iph;
73 int err; 72 int err;
74 73
75 err = xfrm_output(skb); 74 err = xfrm_output(skb);
76 if (err) 75 if (err)
77 goto error_nolock; 76 goto error_nolock;
78 77
79 iph = ip_hdr(skb);
80 iph->tot_len = htons(skb->len);
81 ip_send_check(iph);
82
83 IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED; 78 IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
84 err = 0; 79 err = 0;
85 80
@@ -97,8 +92,7 @@ static int xfrm4_output_finish2(struct sk_buff *skb)
97 while (likely((err = xfrm4_output_one(skb)) == 0)) { 92 while (likely((err = xfrm4_output_one(skb)) == 0)) {
98 nf_reset(skb); 93 nf_reset(skb);
99 94
100 err = nf_hook(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, 95 err = __ip_local_out(skb);
101 skb->dst->dev, dst_output);
102 if (unlikely(err != 1)) 96 if (unlikely(err != 1))
103 break; 97 break;
104 98