diff options
Diffstat (limited to 'net/ipv4/ip_input.c')
| -rw-r--r-- | net/ipv4/ip_input.c | 35 |
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 | */ |
| 150 | int ip_call_ra_chain(struct sk_buff *skb) | 151 | int 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 | ||
| 449 | inhdr_error: | 446 | inhdr_error: |
