aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/ip_input.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/ip_input.c')
-rw-r--r--net/ipv4/ip_input.c35
1 files changed, 16 insertions, 19 deletions
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
index c29de9879fda..d859bcc26cb7 100644
--- a/net/ipv4/ip_input.c
+++ b/net/ipv4/ip_input.c
@@ -119,6 +119,7 @@
119#include <linux/kernel.h> 119#include <linux/kernel.h>
120#include <linux/string.h> 120#include <linux/string.h>
121#include <linux/errno.h> 121#include <linux/errno.h>
122#include <linux/slab.h>
122 123
123#include <linux/net.h> 124#include <linux/net.h>
124#include <linux/socket.h> 125#include <linux/socket.h>
@@ -145,7 +146,7 @@
145#include <linux/netlink.h> 146#include <linux/netlink.h>
146 147
147/* 148/*
148 * Process Router Attention IP option 149 * Process Router Attention IP option (RFC 2113)
149 */ 150 */
150int ip_call_ra_chain(struct sk_buff *skb) 151int ip_call_ra_chain(struct sk_buff *skb)
151{ 152{
@@ -154,8 +155,7 @@ int ip_call_ra_chain(struct sk_buff *skb)
154 struct sock *last = NULL; 155 struct sock *last = NULL;
155 struct net_device *dev = skb->dev; 156 struct net_device *dev = skb->dev;
156 157
157 read_lock(&ip_ra_lock); 158 for (ra = rcu_dereference(ip_ra_chain); ra; ra = rcu_dereference(ra->next)) {
158 for (ra = ip_ra_chain; ra; ra = ra->next) {
159 struct sock *sk = ra->sk; 159 struct sock *sk = ra->sk;
160 160
161 /* If socket is bound to an interface, only report 161 /* If socket is bound to an interface, only report
@@ -166,10 +166,8 @@ int ip_call_ra_chain(struct sk_buff *skb)
166 sk->sk_bound_dev_if == dev->ifindex) && 166 sk->sk_bound_dev_if == dev->ifindex) &&
167 net_eq(sock_net(sk), dev_net(dev))) { 167 net_eq(sock_net(sk), dev_net(dev))) {
168 if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) { 168 if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
169 if (ip_defrag(skb, IP_DEFRAG_CALL_RA_CHAIN)) { 169 if (ip_defrag(skb, IP_DEFRAG_CALL_RA_CHAIN))
170 read_unlock(&ip_ra_lock);
171 return 1; 170 return 1;
172 }
173 } 171 }
174 if (last) { 172 if (last) {
175 struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC); 173 struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
@@ -182,10 +180,8 @@ int ip_call_ra_chain(struct sk_buff *skb)
182 180
183 if (last) { 181 if (last) {
184 raw_rcv(last, skb); 182 raw_rcv(last, skb);
185 read_unlock(&ip_ra_lock);
186 return 1; 183 return 1;
187 } 184 }
188 read_unlock(&ip_ra_lock);
189 return 0; 185 return 0;
190} 186}
191 187
@@ -265,7 +261,7 @@ int ip_local_deliver(struct sk_buff *skb)
265 return 0; 261 return 0;
266 } 262 }
267 263
268 return NF_HOOK(PF_INET, NF_INET_LOCAL_IN, skb, skb->dev, NULL, 264 return NF_HOOK(NFPROTO_IPV4, NF_INET_LOCAL_IN, skb, skb->dev, NULL,
269 ip_local_deliver_finish); 265 ip_local_deliver_finish);
270} 266}
271 267
@@ -297,18 +293,16 @@ static inline int ip_rcv_options(struct sk_buff *skb)
297 } 293 }
298 294
299 if (unlikely(opt->srr)) { 295 if (unlikely(opt->srr)) {
300 struct in_device *in_dev = in_dev_get(dev); 296 struct in_device *in_dev = __in_dev_get_rcu(dev);
297
301 if (in_dev) { 298 if (in_dev) {
302 if (!IN_DEV_SOURCE_ROUTE(in_dev)) { 299 if (!IN_DEV_SOURCE_ROUTE(in_dev)) {
303 if (IN_DEV_LOG_MARTIANS(in_dev) && 300 if (IN_DEV_LOG_MARTIANS(in_dev) &&
304 net_ratelimit()) 301 net_ratelimit())
305 printk(KERN_INFO "source route option %pI4 -> %pI4\n", 302 printk(KERN_INFO "source route option %pI4 -> %pI4\n",
306 &iph->saddr, &iph->daddr); 303 &iph->saddr, &iph->daddr);
307 in_dev_put(in_dev);
308 goto drop; 304 goto drop;
309 } 305 }
310
311 in_dev_put(in_dev);
312 } 306 }
313 307
314 if (ip_options_rcv_srr(skb)) 308 if (ip_options_rcv_srr(skb))
@@ -330,8 +324,8 @@ static int ip_rcv_finish(struct sk_buff *skb)
330 * how the packet travels inside Linux networking. 324 * how the packet travels inside Linux networking.
331 */ 325 */
332 if (skb_dst(skb) == NULL) { 326 if (skb_dst(skb) == NULL) {
333 int err = ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, 327 int err = ip_route_input_noref(skb, iph->daddr, iph->saddr,
334 skb->dev); 328 iph->tos, skb->dev);
335 if (unlikely(err)) { 329 if (unlikely(err)) {
336 if (err == -EHOSTUNREACH) 330 if (err == -EHOSTUNREACH)
337 IP_INC_STATS_BH(dev_net(skb->dev), 331 IP_INC_STATS_BH(dev_net(skb->dev),
@@ -339,13 +333,16 @@ static int ip_rcv_finish(struct sk_buff *skb)
339 else if (err == -ENETUNREACH) 333 else if (err == -ENETUNREACH)
340 IP_INC_STATS_BH(dev_net(skb->dev), 334 IP_INC_STATS_BH(dev_net(skb->dev),
341 IPSTATS_MIB_INNOROUTES); 335 IPSTATS_MIB_INNOROUTES);
336 else if (err == -EXDEV)
337 NET_INC_STATS_BH(dev_net(skb->dev),
338 LINUX_MIB_IPRPFILTER);
342 goto drop; 339 goto drop;
343 } 340 }
344 } 341 }
345 342
346#ifdef CONFIG_NET_CLS_ROUTE 343#ifdef CONFIG_NET_CLS_ROUTE
347 if (unlikely(skb_dst(skb)->tclassid)) { 344 if (unlikely(skb_dst(skb)->tclassid)) {
348 struct ip_rt_acct *st = per_cpu_ptr(ip_rt_acct, smp_processor_id()); 345 struct ip_rt_acct *st = this_cpu_ptr(ip_rt_acct);
349 u32 idx = skb_dst(skb)->tclassid; 346 u32 idx = skb_dst(skb)->tclassid;
350 st[idx&0xFF].o_packets++; 347 st[idx&0xFF].o_packets++;
351 st[idx&0xFF].o_bytes += skb->len; 348 st[idx&0xFF].o_bytes += skb->len;
@@ -359,10 +356,10 @@ static int ip_rcv_finish(struct sk_buff *skb)
359 356
360 rt = skb_rtable(skb); 357 rt = skb_rtable(skb);
361 if (rt->rt_type == RTN_MULTICAST) { 358 if (rt->rt_type == RTN_MULTICAST) {
362 IP_UPD_PO_STATS_BH(dev_net(rt->u.dst.dev), IPSTATS_MIB_INMCAST, 359 IP_UPD_PO_STATS_BH(dev_net(rt->dst.dev), IPSTATS_MIB_INMCAST,
363 skb->len); 360 skb->len);
364 } else if (rt->rt_type == RTN_BROADCAST) 361 } else if (rt->rt_type == RTN_BROADCAST)
365 IP_UPD_PO_STATS_BH(dev_net(rt->u.dst.dev), IPSTATS_MIB_INBCAST, 362 IP_UPD_PO_STATS_BH(dev_net(rt->dst.dev), IPSTATS_MIB_INBCAST,
366 skb->len); 363 skb->len);
367 364
368 return dst_input(skb); 365 return dst_input(skb);
@@ -443,7 +440,7 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
443 /* Must drop socket now because of tproxy. */ 440 /* Must drop socket now because of tproxy. */
444 skb_orphan(skb); 441 skb_orphan(skb);
445 442
446 return NF_HOOK(PF_INET, NF_INET_PRE_ROUTING, skb, dev, NULL, 443 return NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING, skb, dev, NULL,
447 ip_rcv_finish); 444 ip_rcv_finish);
448 445
449inhdr_error: 446inhdr_error: