diff options
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/devinet.c | 2 | ||||
-rw-r--r-- | net/ipv4/fib_semantics.c | 2 | ||||
-rw-r--r-- | net/ipv4/icmp.c | 2 | ||||
-rw-r--r-- | net/ipv4/ip_gre.c | 3 | ||||
-rw-r--r-- | net/ipv4/ip_output.c | 16 | ||||
-rw-r--r-- | net/ipv4/ipip.c | 3 | ||||
-rw-r--r-- | net/ipv4/netfilter.c | 41 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_nat_core.c | 18 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_nat_standalone.c | 22 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 5 | ||||
-rw-r--r-- | net/ipv4/tcp_input.c | 3 | ||||
-rw-r--r-- | net/ipv4/xfrm4_output.c | 13 |
12 files changed, 87 insertions, 43 deletions
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 95b9d81ac488..3ffa60dadc0c 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c | |||
@@ -1135,7 +1135,7 @@ static void rtmsg_ifa(int event, struct in_ifaddr* ifa) | |||
1135 | 1135 | ||
1136 | if (!skb) | 1136 | if (!skb) |
1137 | netlink_set_err(rtnl, 0, RTNLGRP_IPV4_IFADDR, ENOBUFS); | 1137 | netlink_set_err(rtnl, 0, RTNLGRP_IPV4_IFADDR, ENOBUFS); |
1138 | else if (inet_fill_ifaddr(skb, ifa, current->pid, 0, event, 0) < 0) { | 1138 | else if (inet_fill_ifaddr(skb, ifa, 0, 0, event, 0) < 0) { |
1139 | kfree_skb(skb); | 1139 | kfree_skb(skb); |
1140 | netlink_set_err(rtnl, 0, RTNLGRP_IPV4_IFADDR, EINVAL); | 1140 | netlink_set_err(rtnl, 0, RTNLGRP_IPV4_IFADDR, EINVAL); |
1141 | } else { | 1141 | } else { |
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index ef4724de7350..0f4145babb14 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c | |||
@@ -1045,7 +1045,7 @@ fib_convert_rtentry(int cmd, struct nlmsghdr *nl, struct rtmsg *rtm, | |||
1045 | } | 1045 | } |
1046 | 1046 | ||
1047 | nl->nlmsg_flags = NLM_F_REQUEST; | 1047 | nl->nlmsg_flags = NLM_F_REQUEST; |
1048 | nl->nlmsg_pid = current->pid; | 1048 | nl->nlmsg_pid = 0; |
1049 | nl->nlmsg_seq = 0; | 1049 | nl->nlmsg_seq = 0; |
1050 | nl->nlmsg_len = NLMSG_LENGTH(sizeof(*rtm)); | 1050 | nl->nlmsg_len = NLMSG_LENGTH(sizeof(*rtm)); |
1051 | if (cmd == SIOCDELRT) { | 1051 | if (cmd == SIOCDELRT) { |
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 4d1c40972a4b..e7bbff4340bb 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c | |||
@@ -192,7 +192,7 @@ int sysctl_icmp_echo_ignore_all; | |||
192 | int sysctl_icmp_echo_ignore_broadcasts = 1; | 192 | int sysctl_icmp_echo_ignore_broadcasts = 1; |
193 | 193 | ||
194 | /* Control parameter - ignore bogus broadcast responses? */ | 194 | /* Control parameter - ignore bogus broadcast responses? */ |
195 | int sysctl_icmp_ignore_bogus_error_responses; | 195 | int sysctl_icmp_ignore_bogus_error_responses = 1; |
196 | 196 | ||
197 | /* | 197 | /* |
198 | * Configurable global rate limit. | 198 | * Configurable global rate limit. |
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index abe23923e4e7..9981dcd68f11 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c | |||
@@ -830,7 +830,8 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
830 | skb->h.raw = skb->nh.raw; | 830 | skb->h.raw = skb->nh.raw; |
831 | skb->nh.raw = skb_push(skb, gre_hlen); | 831 | skb->nh.raw = skb_push(skb, gre_hlen); |
832 | memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); | 832 | memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); |
833 | IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE|IPSKB_XFRM_TRANSFORMED); | 833 | IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED | |
834 | IPSKB_REROUTED); | ||
834 | dst_release(skb->dst); | 835 | dst_release(skb->dst); |
835 | skb->dst = &rt->u.dst; | 836 | skb->dst = &rt->u.dst; |
836 | 837 | ||
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 3324fbfe528a..57d290d89ec2 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
@@ -207,8 +207,10 @@ static inline int ip_finish_output(struct sk_buff *skb) | |||
207 | { | 207 | { |
208 | #if defined(CONFIG_NETFILTER) && defined(CONFIG_XFRM) | 208 | #if defined(CONFIG_NETFILTER) && defined(CONFIG_XFRM) |
209 | /* Policy lookup after SNAT yielded a new policy */ | 209 | /* Policy lookup after SNAT yielded a new policy */ |
210 | if (skb->dst->xfrm != NULL) | 210 | if (skb->dst->xfrm != NULL) { |
211 | return xfrm4_output_finish(skb); | 211 | IPCB(skb)->flags |= IPSKB_REROUTED; |
212 | return dst_output(skb); | ||
213 | } | ||
212 | #endif | 214 | #endif |
213 | if (skb->len > dst_mtu(skb->dst) && | 215 | if (skb->len > dst_mtu(skb->dst) && |
214 | !(skb_shinfo(skb)->ufo_size || skb_shinfo(skb)->tso_size)) | 216 | !(skb_shinfo(skb)->ufo_size || skb_shinfo(skb)->tso_size)) |
@@ -271,8 +273,9 @@ int ip_mc_output(struct sk_buff *skb) | |||
271 | newskb->dev, ip_dev_loopback_xmit); | 273 | newskb->dev, ip_dev_loopback_xmit); |
272 | } | 274 | } |
273 | 275 | ||
274 | return NF_HOOK(PF_INET, NF_IP_POST_ROUTING, skb, NULL, skb->dev, | 276 | return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL, skb->dev, |
275 | ip_finish_output); | 277 | ip_finish_output, |
278 | !(IPCB(skb)->flags & IPSKB_REROUTED)); | ||
276 | } | 279 | } |
277 | 280 | ||
278 | int ip_output(struct sk_buff *skb) | 281 | int ip_output(struct sk_buff *skb) |
@@ -284,8 +287,9 @@ int ip_output(struct sk_buff *skb) | |||
284 | skb->dev = dev; | 287 | skb->dev = dev; |
285 | skb->protocol = htons(ETH_P_IP); | 288 | skb->protocol = htons(ETH_P_IP); |
286 | 289 | ||
287 | return NF_HOOK(PF_INET, NF_IP_POST_ROUTING, skb, NULL, dev, | 290 | return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL, dev, |
288 | ip_finish_output); | 291 | ip_finish_output, |
292 | !(IPCB(skb)->flags & IPSKB_REROUTED)); | ||
289 | } | 293 | } |
290 | 294 | ||
291 | int ip_queue_xmit(struct sk_buff *skb, int ipfragok) | 295 | int ip_queue_xmit(struct sk_buff *skb, int ipfragok) |
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index e5cbe72c6b80..03d13742a4b8 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c | |||
@@ -622,7 +622,8 @@ static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
622 | skb->h.raw = skb->nh.raw; | 622 | skb->h.raw = skb->nh.raw; |
623 | skb->nh.raw = skb_push(skb, sizeof(struct iphdr)); | 623 | skb->nh.raw = skb_push(skb, sizeof(struct iphdr)); |
624 | memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); | 624 | memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); |
625 | IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE|IPSKB_XFRM_TRANSFORMED); | 625 | IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED | |
626 | IPSKB_REROUTED); | ||
626 | dst_release(skb->dst); | 627 | dst_release(skb->dst); |
627 | skb->dst = &rt->u.dst; | 628 | skb->dst = &rt->u.dst; |
628 | 629 | ||
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c index 52a3d7c57907..ed42cdc57cd9 100644 --- a/net/ipv4/netfilter.c +++ b/net/ipv4/netfilter.c | |||
@@ -78,6 +78,47 @@ int ip_route_me_harder(struct sk_buff **pskb) | |||
78 | } | 78 | } |
79 | EXPORT_SYMBOL(ip_route_me_harder); | 79 | EXPORT_SYMBOL(ip_route_me_harder); |
80 | 80 | ||
81 | #ifdef CONFIG_XFRM | ||
82 | int ip_xfrm_me_harder(struct sk_buff **pskb) | ||
83 | { | ||
84 | struct flowi fl; | ||
85 | unsigned int hh_len; | ||
86 | struct dst_entry *dst; | ||
87 | |||
88 | if (IPCB(*pskb)->flags & IPSKB_XFRM_TRANSFORMED) | ||
89 | return 0; | ||
90 | if (xfrm_decode_session(*pskb, &fl, AF_INET) < 0) | ||
91 | return -1; | ||
92 | |||
93 | dst = (*pskb)->dst; | ||
94 | if (dst->xfrm) | ||
95 | dst = ((struct xfrm_dst *)dst)->route; | ||
96 | dst_hold(dst); | ||
97 | |||
98 | if (xfrm_lookup(&dst, &fl, (*pskb)->sk, 0) < 0) | ||
99 | return -1; | ||
100 | |||
101 | dst_release((*pskb)->dst); | ||
102 | (*pskb)->dst = dst; | ||
103 | |||
104 | /* Change in oif may mean change in hh_len. */ | ||
105 | hh_len = (*pskb)->dst->dev->hard_header_len; | ||
106 | if (skb_headroom(*pskb) < hh_len) { | ||
107 | struct sk_buff *nskb; | ||
108 | |||
109 | nskb = skb_realloc_headroom(*pskb, hh_len); | ||
110 | if (!nskb) | ||
111 | return -1; | ||
112 | if ((*pskb)->sk) | ||
113 | skb_set_owner_w(nskb, (*pskb)->sk); | ||
114 | kfree_skb(*pskb); | ||
115 | *pskb = nskb; | ||
116 | } | ||
117 | return 0; | ||
118 | } | ||
119 | EXPORT_SYMBOL(ip_xfrm_me_harder); | ||
120 | #endif | ||
121 | |||
81 | void (*ip_nat_decode_session)(struct sk_buff *, struct flowi *); | 122 | void (*ip_nat_decode_session)(struct sk_buff *, struct flowi *); |
82 | EXPORT_SYMBOL(ip_nat_decode_session); | 123 | EXPORT_SYMBOL(ip_nat_decode_session); |
83 | 124 | ||
diff --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c index c1a61462507f..1741d555ad0d 100644 --- a/net/ipv4/netfilter/ip_nat_core.c +++ b/net/ipv4/netfilter/ip_nat_core.c | |||
@@ -434,6 +434,7 @@ int ip_nat_icmp_reply_translation(struct sk_buff **pskb, | |||
434 | } *inside; | 434 | } *inside; |
435 | struct ip_conntrack_tuple inner, target; | 435 | struct ip_conntrack_tuple inner, target; |
436 | int hdrlen = (*pskb)->nh.iph->ihl * 4; | 436 | int hdrlen = (*pskb)->nh.iph->ihl * 4; |
437 | unsigned long statusbit; | ||
437 | 438 | ||
438 | if (!skb_make_writable(pskb, hdrlen + sizeof(*inside))) | 439 | if (!skb_make_writable(pskb, hdrlen + sizeof(*inside))) |
439 | return 0; | 440 | return 0; |
@@ -495,17 +496,16 @@ int ip_nat_icmp_reply_translation(struct sk_buff **pskb, | |||
495 | 496 | ||
496 | /* Change outer to look the reply to an incoming packet | 497 | /* Change outer to look the reply to an incoming packet |
497 | * (proto 0 means don't invert per-proto part). */ | 498 | * (proto 0 means don't invert per-proto part). */ |
499 | if (manip == IP_NAT_MANIP_SRC) | ||
500 | statusbit = IPS_SRC_NAT; | ||
501 | else | ||
502 | statusbit = IPS_DST_NAT; | ||
498 | 503 | ||
499 | /* Obviously, we need to NAT destination IP, but source IP | 504 | /* Invert if this is reply dir. */ |
500 | should be NAT'ed only if it is from a NAT'd host. | 505 | if (dir == IP_CT_DIR_REPLY) |
506 | statusbit ^= IPS_NAT_MASK; | ||
501 | 507 | ||
502 | Explanation: some people use NAT for anonymizing. Also, | 508 | if (ct->status & statusbit) { |
503 | CERT recommends dropping all packets from private IP | ||
504 | addresses (although ICMP errors from internal links with | ||
505 | such addresses are not too uncommon, as Alan Cox points | ||
506 | out) */ | ||
507 | if (manip != IP_NAT_MANIP_SRC | ||
508 | || ((*pskb)->nh.iph->saddr == ct->tuplehash[dir].tuple.src.ip)) { | ||
509 | invert_tuplepr(&target, &ct->tuplehash[!dir].tuple); | 509 | invert_tuplepr(&target, &ct->tuplehash[!dir].tuple); |
510 | if (!manip_pkt(0, pskb, 0, &target, manip)) | 510 | if (!manip_pkt(0, pskb, 0, &target, manip)) |
511 | return 0; | 511 | return 0; |
diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c index 92c54999a19d..ab1f88fa21ec 100644 --- a/net/ipv4/netfilter/ip_nat_standalone.c +++ b/net/ipv4/netfilter/ip_nat_standalone.c | |||
@@ -200,20 +200,14 @@ ip_nat_in(unsigned int hooknum, | |||
200 | const struct net_device *out, | 200 | const struct net_device *out, |
201 | int (*okfn)(struct sk_buff *)) | 201 | int (*okfn)(struct sk_buff *)) |
202 | { | 202 | { |
203 | struct ip_conntrack *ct; | ||
204 | enum ip_conntrack_info ctinfo; | ||
205 | unsigned int ret; | 203 | unsigned int ret; |
204 | u_int32_t daddr = (*pskb)->nh.iph->daddr; | ||
206 | 205 | ||
207 | ret = ip_nat_fn(hooknum, pskb, in, out, okfn); | 206 | ret = ip_nat_fn(hooknum, pskb, in, out, okfn); |
208 | if (ret != NF_DROP && ret != NF_STOLEN | 207 | if (ret != NF_DROP && ret != NF_STOLEN |
209 | && (ct = ip_conntrack_get(*pskb, &ctinfo)) != NULL) { | 208 | && daddr != (*pskb)->nh.iph->daddr) { |
210 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); | 209 | dst_release((*pskb)->dst); |
211 | 210 | (*pskb)->dst = NULL; | |
212 | if (ct->tuplehash[dir].tuple.dst.ip != | ||
213 | ct->tuplehash[!dir].tuple.src.ip) { | ||
214 | dst_release((*pskb)->dst); | ||
215 | (*pskb)->dst = NULL; | ||
216 | } | ||
217 | } | 211 | } |
218 | return ret; | 212 | return ret; |
219 | } | 213 | } |
@@ -235,19 +229,19 @@ ip_nat_out(unsigned int hooknum, | |||
235 | return NF_ACCEPT; | 229 | return NF_ACCEPT; |
236 | 230 | ||
237 | ret = ip_nat_fn(hooknum, pskb, in, out, okfn); | 231 | ret = ip_nat_fn(hooknum, pskb, in, out, okfn); |
232 | #ifdef CONFIG_XFRM | ||
238 | if (ret != NF_DROP && ret != NF_STOLEN | 233 | if (ret != NF_DROP && ret != NF_STOLEN |
239 | && (ct = ip_conntrack_get(*pskb, &ctinfo)) != NULL) { | 234 | && (ct = ip_conntrack_get(*pskb, &ctinfo)) != NULL) { |
240 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); | 235 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); |
241 | 236 | ||
242 | if (ct->tuplehash[dir].tuple.src.ip != | 237 | if (ct->tuplehash[dir].tuple.src.ip != |
243 | ct->tuplehash[!dir].tuple.dst.ip | 238 | ct->tuplehash[!dir].tuple.dst.ip |
244 | #ifdef CONFIG_XFRM | ||
245 | || ct->tuplehash[dir].tuple.src.u.all != | 239 | || ct->tuplehash[dir].tuple.src.u.all != |
246 | ct->tuplehash[!dir].tuple.dst.u.all | 240 | ct->tuplehash[!dir].tuple.dst.u.all |
247 | #endif | ||
248 | ) | 241 | ) |
249 | return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP; | 242 | return ip_xfrm_me_harder(pskb) == 0 ? ret : NF_DROP; |
250 | } | 243 | } |
244 | #endif | ||
251 | return ret; | 245 | return ret; |
252 | } | 246 | } |
253 | 247 | ||
@@ -276,7 +270,7 @@ ip_nat_local_fn(unsigned int hooknum, | |||
276 | ct->tuplehash[!dir].tuple.src.ip | 270 | ct->tuplehash[!dir].tuple.src.ip |
277 | #ifdef CONFIG_XFRM | 271 | #ifdef CONFIG_XFRM |
278 | || ct->tuplehash[dir].tuple.dst.u.all != | 272 | || ct->tuplehash[dir].tuple.dst.u.all != |
279 | ct->tuplehash[dir].tuple.src.u.all | 273 | ct->tuplehash[!dir].tuple.src.u.all |
280 | #endif | 274 | #endif |
281 | ) | 275 | ) |
282 | return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP; | 276 | return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP; |
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index 167619f638c6..6c8624a54933 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | |||
@@ -529,15 +529,10 @@ static int init_or_cleanup(int init) | |||
529 | goto cleanup_localinops; | 529 | goto cleanup_localinops; |
530 | } | 530 | } |
531 | #endif | 531 | #endif |
532 | |||
533 | /* For use by REJECT target */ | ||
534 | ip_ct_attach = __nf_conntrack_attach; | ||
535 | |||
536 | return ret; | 532 | return ret; |
537 | 533 | ||
538 | cleanup: | 534 | cleanup: |
539 | synchronize_net(); | 535 | synchronize_net(); |
540 | ip_ct_attach = NULL; | ||
541 | #ifdef CONFIG_SYSCTL | 536 | #ifdef CONFIG_SYSCTL |
542 | unregister_sysctl_table(nf_ct_ipv4_sysctl_header); | 537 | unregister_sysctl_table(nf_ct_ipv4_sysctl_header); |
543 | cleanup_localinops: | 538 | cleanup_localinops: |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index a97ed5416c28..e9a54ae7d690 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -456,7 +456,8 @@ void tcp_rcv_space_adjust(struct sock *sk) | |||
456 | 456 | ||
457 | tp->rcvq_space.space = space; | 457 | tp->rcvq_space.space = space; |
458 | 458 | ||
459 | if (sysctl_tcp_moderate_rcvbuf) { | 459 | if (sysctl_tcp_moderate_rcvbuf && |
460 | !(sk->sk_userlocks & SOCK_RCVBUF_LOCK)) { | ||
460 | int new_clamp = space; | 461 | int new_clamp = space; |
461 | 462 | ||
462 | /* Receive space grows, normalize in order to | 463 | /* Receive space grows, normalize in order to |
diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c index d4df0ddd424b..32ad229b4fed 100644 --- a/net/ipv4/xfrm4_output.c +++ b/net/ipv4/xfrm4_output.c | |||
@@ -152,10 +152,16 @@ error_nolock: | |||
152 | goto out_exit; | 152 | goto out_exit; |
153 | } | 153 | } |
154 | 154 | ||
155 | int xfrm4_output_finish(struct sk_buff *skb) | 155 | static int xfrm4_output_finish(struct sk_buff *skb) |
156 | { | 156 | { |
157 | int err; | 157 | int err; |
158 | 158 | ||
159 | #ifdef CONFIG_NETFILTER | ||
160 | if (!skb->dst->xfrm) { | ||
161 | IPCB(skb)->flags |= IPSKB_REROUTED; | ||
162 | return dst_output(skb); | ||
163 | } | ||
164 | #endif | ||
159 | while (likely((err = xfrm4_output_one(skb)) == 0)) { | 165 | while (likely((err = xfrm4_output_one(skb)) == 0)) { |
160 | nf_reset(skb); | 166 | nf_reset(skb); |
161 | 167 | ||
@@ -178,6 +184,7 @@ int xfrm4_output_finish(struct sk_buff *skb) | |||
178 | 184 | ||
179 | int xfrm4_output(struct sk_buff *skb) | 185 | int xfrm4_output(struct sk_buff *skb) |
180 | { | 186 | { |
181 | return NF_HOOK(PF_INET, NF_IP_POST_ROUTING, skb, NULL, skb->dst->dev, | 187 | return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL, skb->dst->dev, |
182 | xfrm4_output_finish); | 188 | xfrm4_output_finish, |
189 | !(IPCB(skb)->flags & IPSKB_REROUTED)); | ||
183 | } | 190 | } |