diff options
-rw-r--r-- | include/net/ip.h | 2 | ||||
-rw-r--r-- | include/net/ipip.h | 5 | ||||
-rw-r--r-- | net/ipv4/igmp.c | 12 | ||||
-rw-r--r-- | net/ipv4/ip_output.c | 39 | ||||
-rw-r--r-- | net/ipv4/ipvs/ip_vs_xmit.c | 6 | ||||
-rw-r--r-- | net/ipv4/netfilter/ipt_REJECT.c | 8 | ||||
-rw-r--r-- | net/ipv4/xfrm4_output.c | 8 |
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); | |||
102 | extern int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)); | 102 | extern int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)); |
103 | extern int ip_do_nat(struct sk_buff *skb); | 103 | extern int ip_do_nat(struct sk_buff *skb); |
104 | extern void ip_send_check(struct iphdr *ip); | 104 | extern void ip_send_check(struct iphdr *ip); |
105 | extern int __ip_local_out(struct sk_buff *skb); | ||
106 | extern int ip_local_out(struct sk_buff *skb); | ||
105 | extern int ip_queue_xmit(struct sk_buff *skb, int ipfragok); | 107 | extern int ip_queue_xmit(struct sk_buff *skb, int ipfragok); |
106 | extern void ip_init(void); | 108 | extern void ip_init(void); |
107 | extern int ip_append_data(struct sock *sk, | 109 | extern 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 | ||
350 | static int igmpv3_sendpack(struct sk_buff *skb) | 350 | static 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 | ||
365 | static int grec_size(struct ip_mc_list *pmc, int type, int gdel, int sdel) | 360 | static 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 | ||
702 | static void igmp_gq_timer_expire(unsigned long data) | 694 | static 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 | ||
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; |
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 | ||
70 | static inline int xfrm4_output_one(struct sk_buff *skb) | 70 | static 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 | ||