diff options
Diffstat (limited to 'net/ipv4/ip_input.c')
-rw-r--r-- | net/ipv4/ip_input.c | 26 |
1 files changed, 11 insertions, 15 deletions
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c index d930dc5e4d85..d859bcc26cb7 100644 --- a/net/ipv4/ip_input.c +++ b/net/ipv4/ip_input.c | |||
@@ -146,7 +146,7 @@ | |||
146 | #include <linux/netlink.h> | 146 | #include <linux/netlink.h> |
147 | 147 | ||
148 | /* | 148 | /* |
149 | * Process Router Attention IP option | 149 | * Process Router Attention IP option (RFC 2113) |
150 | */ | 150 | */ |
151 | int ip_call_ra_chain(struct sk_buff *skb) | 151 | int ip_call_ra_chain(struct sk_buff *skb) |
152 | { | 152 | { |
@@ -155,8 +155,7 @@ int ip_call_ra_chain(struct sk_buff *skb) | |||
155 | struct sock *last = NULL; | 155 | struct sock *last = NULL; |
156 | struct net_device *dev = skb->dev; | 156 | struct net_device *dev = skb->dev; |
157 | 157 | ||
158 | read_lock(&ip_ra_lock); | 158 | for (ra = rcu_dereference(ip_ra_chain); ra; ra = rcu_dereference(ra->next)) { |
159 | for (ra = ip_ra_chain; ra; ra = ra->next) { | ||
160 | struct sock *sk = ra->sk; | 159 | struct sock *sk = ra->sk; |
161 | 160 | ||
162 | /* If socket is bound to an interface, only report | 161 | /* If socket is bound to an interface, only report |
@@ -167,10 +166,8 @@ int ip_call_ra_chain(struct sk_buff *skb) | |||
167 | sk->sk_bound_dev_if == dev->ifindex) && | 166 | sk->sk_bound_dev_if == dev->ifindex) && |
168 | net_eq(sock_net(sk), dev_net(dev))) { | 167 | net_eq(sock_net(sk), dev_net(dev))) { |
169 | if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) { | 168 | if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) { |
170 | if (ip_defrag(skb, IP_DEFRAG_CALL_RA_CHAIN)) { | 169 | if (ip_defrag(skb, IP_DEFRAG_CALL_RA_CHAIN)) |
171 | read_unlock(&ip_ra_lock); | ||
172 | return 1; | 170 | return 1; |
173 | } | ||
174 | } | 171 | } |
175 | if (last) { | 172 | if (last) { |
176 | struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC); | 173 | struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC); |
@@ -183,10 +180,8 @@ int ip_call_ra_chain(struct sk_buff *skb) | |||
183 | 180 | ||
184 | if (last) { | 181 | if (last) { |
185 | raw_rcv(last, skb); | 182 | raw_rcv(last, skb); |
186 | read_unlock(&ip_ra_lock); | ||
187 | return 1; | 183 | return 1; |
188 | } | 184 | } |
189 | read_unlock(&ip_ra_lock); | ||
190 | return 0; | 185 | return 0; |
191 | } | 186 | } |
192 | 187 | ||
@@ -298,18 +293,16 @@ static inline int ip_rcv_options(struct sk_buff *skb) | |||
298 | } | 293 | } |
299 | 294 | ||
300 | if (unlikely(opt->srr)) { | 295 | if (unlikely(opt->srr)) { |
301 | struct in_device *in_dev = in_dev_get(dev); | 296 | struct in_device *in_dev = __in_dev_get_rcu(dev); |
297 | |||
302 | if (in_dev) { | 298 | if (in_dev) { |
303 | if (!IN_DEV_SOURCE_ROUTE(in_dev)) { | 299 | if (!IN_DEV_SOURCE_ROUTE(in_dev)) { |
304 | if (IN_DEV_LOG_MARTIANS(in_dev) && | 300 | if (IN_DEV_LOG_MARTIANS(in_dev) && |
305 | net_ratelimit()) | 301 | net_ratelimit()) |
306 | printk(KERN_INFO "source route option %pI4 -> %pI4\n", | 302 | printk(KERN_INFO "source route option %pI4 -> %pI4\n", |
307 | &iph->saddr, &iph->daddr); | 303 | &iph->saddr, &iph->daddr); |
308 | in_dev_put(in_dev); | ||
309 | goto drop; | 304 | goto drop; |
310 | } | 305 | } |
311 | |||
312 | in_dev_put(in_dev); | ||
313 | } | 306 | } |
314 | 307 | ||
315 | if (ip_options_rcv_srr(skb)) | 308 | if (ip_options_rcv_srr(skb)) |
@@ -340,13 +333,16 @@ static int ip_rcv_finish(struct sk_buff *skb) | |||
340 | else if (err == -ENETUNREACH) | 333 | else if (err == -ENETUNREACH) |
341 | IP_INC_STATS_BH(dev_net(skb->dev), | 334 | IP_INC_STATS_BH(dev_net(skb->dev), |
342 | 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); | ||
343 | goto drop; | 339 | goto drop; |
344 | } | 340 | } |
345 | } | 341 | } |
346 | 342 | ||
347 | #ifdef CONFIG_NET_CLS_ROUTE | 343 | #ifdef CONFIG_NET_CLS_ROUTE |
348 | if (unlikely(skb_dst(skb)->tclassid)) { | 344 | if (unlikely(skb_dst(skb)->tclassid)) { |
349 | 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); |
350 | u32 idx = skb_dst(skb)->tclassid; | 346 | u32 idx = skb_dst(skb)->tclassid; |
351 | st[idx&0xFF].o_packets++; | 347 | st[idx&0xFF].o_packets++; |
352 | st[idx&0xFF].o_bytes += skb->len; | 348 | st[idx&0xFF].o_bytes += skb->len; |
@@ -360,10 +356,10 @@ static int ip_rcv_finish(struct sk_buff *skb) | |||
360 | 356 | ||
361 | rt = skb_rtable(skb); | 357 | rt = skb_rtable(skb); |
362 | if (rt->rt_type == RTN_MULTICAST) { | 358 | if (rt->rt_type == RTN_MULTICAST) { |
363 | 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, |
364 | skb->len); | 360 | skb->len); |
365 | } else if (rt->rt_type == RTN_BROADCAST) | 361 | } else if (rt->rt_type == RTN_BROADCAST) |
366 | 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, |
367 | skb->len); | 363 | skb->len); |
368 | 364 | ||
369 | return dst_input(skb); | 365 | return dst_input(skb); |