diff options
Diffstat (limited to 'net/ipv4/arp.c')
-rw-r--r-- | net/ipv4/arp.c | 51 |
1 files changed, 23 insertions, 28 deletions
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index f094b75810db..96c1955b3e2f 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c | |||
@@ -116,6 +116,7 @@ | |||
116 | #if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE) | 116 | #if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE) |
117 | #include <net/atmclip.h> | 117 | #include <net/atmclip.h> |
118 | struct neigh_table *clip_tbl_hook; | 118 | struct neigh_table *clip_tbl_hook; |
119 | EXPORT_SYMBOL(clip_tbl_hook); | ||
119 | #endif | 120 | #endif |
120 | 121 | ||
121 | #include <asm/system.h> | 122 | #include <asm/system.h> |
@@ -169,6 +170,7 @@ const struct neigh_ops arp_broken_ops = { | |||
169 | .hh_output = dev_queue_xmit, | 170 | .hh_output = dev_queue_xmit, |
170 | .queue_xmit = dev_queue_xmit, | 171 | .queue_xmit = dev_queue_xmit, |
171 | }; | 172 | }; |
173 | EXPORT_SYMBOL(arp_broken_ops); | ||
172 | 174 | ||
173 | struct neigh_table arp_tbl = { | 175 | struct neigh_table arp_tbl = { |
174 | .family = AF_INET, | 176 | .family = AF_INET, |
@@ -198,6 +200,7 @@ struct neigh_table arp_tbl = { | |||
198 | .gc_thresh2 = 512, | 200 | .gc_thresh2 = 512, |
199 | .gc_thresh3 = 1024, | 201 | .gc_thresh3 = 1024, |
200 | }; | 202 | }; |
203 | EXPORT_SYMBOL(arp_tbl); | ||
201 | 204 | ||
202 | int arp_mc_map(__be32 addr, u8 *haddr, struct net_device *dev, int dir) | 205 | int arp_mc_map(__be32 addr, u8 *haddr, struct net_device *dev, int dir) |
203 | { | 206 | { |
@@ -333,11 +336,14 @@ static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb) | |||
333 | struct net_device *dev = neigh->dev; | 336 | struct net_device *dev = neigh->dev; |
334 | __be32 target = *(__be32*)neigh->primary_key; | 337 | __be32 target = *(__be32*)neigh->primary_key; |
335 | int probes = atomic_read(&neigh->probes); | 338 | int probes = atomic_read(&neigh->probes); |
336 | struct in_device *in_dev = in_dev_get(dev); | 339 | struct in_device *in_dev; |
337 | 340 | ||
338 | if (!in_dev) | 341 | rcu_read_lock(); |
342 | in_dev = __in_dev_get_rcu(dev); | ||
343 | if (!in_dev) { | ||
344 | rcu_read_unlock(); | ||
339 | return; | 345 | return; |
340 | 346 | } | |
341 | switch (IN_DEV_ARP_ANNOUNCE(in_dev)) { | 347 | switch (IN_DEV_ARP_ANNOUNCE(in_dev)) { |
342 | default: | 348 | default: |
343 | case 0: /* By default announce any local IP */ | 349 | case 0: /* By default announce any local IP */ |
@@ -358,9 +364,8 @@ static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb) | |||
358 | case 2: /* Avoid secondary IPs, get a primary/preferred one */ | 364 | case 2: /* Avoid secondary IPs, get a primary/preferred one */ |
359 | break; | 365 | break; |
360 | } | 366 | } |
367 | rcu_read_unlock(); | ||
361 | 368 | ||
362 | if (in_dev) | ||
363 | in_dev_put(in_dev); | ||
364 | if (!saddr) | 369 | if (!saddr) |
365 | saddr = inet_select_addr(dev, target, RT_SCOPE_LINK); | 370 | saddr = inet_select_addr(dev, target, RT_SCOPE_LINK); |
366 | 371 | ||
@@ -427,7 +432,7 @@ static int arp_filter(__be32 sip, __be32 tip, struct net_device *dev) | |||
427 | 432 | ||
428 | if (ip_route_output_key(net, &rt, &fl) < 0) | 433 | if (ip_route_output_key(net, &rt, &fl) < 0) |
429 | return 1; | 434 | return 1; |
430 | if (rt->u.dst.dev != dev) { | 435 | if (rt->dst.dev != dev) { |
431 | NET_INC_STATS_BH(net, LINUX_MIB_ARPFILTER); | 436 | NET_INC_STATS_BH(net, LINUX_MIB_ARPFILTER); |
432 | flag = 1; | 437 | flag = 1; |
433 | } | 438 | } |
@@ -497,6 +502,7 @@ int arp_find(unsigned char *haddr, struct sk_buff *skb) | |||
497 | kfree_skb(skb); | 502 | kfree_skb(skb); |
498 | return 1; | 503 | return 1; |
499 | } | 504 | } |
505 | EXPORT_SYMBOL(arp_find); | ||
500 | 506 | ||
501 | /* END OF OBSOLETE FUNCTIONS */ | 507 | /* END OF OBSOLETE FUNCTIONS */ |
502 | 508 | ||
@@ -532,7 +538,7 @@ static inline int arp_fwd_proxy(struct in_device *in_dev, | |||
532 | struct in_device *out_dev; | 538 | struct in_device *out_dev; |
533 | int imi, omi = -1; | 539 | int imi, omi = -1; |
534 | 540 | ||
535 | if (rt->u.dst.dev == dev) | 541 | if (rt->dst.dev == dev) |
536 | return 0; | 542 | return 0; |
537 | 543 | ||
538 | if (!IN_DEV_PROXY_ARP(in_dev)) | 544 | if (!IN_DEV_PROXY_ARP(in_dev)) |
@@ -545,10 +551,10 @@ static inline int arp_fwd_proxy(struct in_device *in_dev, | |||
545 | 551 | ||
546 | /* place to check for proxy_arp for routes */ | 552 | /* place to check for proxy_arp for routes */ |
547 | 553 | ||
548 | if ((out_dev = in_dev_get(rt->u.dst.dev)) != NULL) { | 554 | out_dev = __in_dev_get_rcu(rt->dst.dev); |
555 | if (out_dev) | ||
549 | omi = IN_DEV_MEDIUM_ID(out_dev); | 556 | omi = IN_DEV_MEDIUM_ID(out_dev); |
550 | in_dev_put(out_dev); | 557 | |
551 | } | ||
552 | return (omi != imi && omi != -1); | 558 | return (omi != imi && omi != -1); |
553 | } | 559 | } |
554 | 560 | ||
@@ -576,7 +582,7 @@ static inline int arp_fwd_pvlan(struct in_device *in_dev, | |||
576 | __be32 sip, __be32 tip) | 582 | __be32 sip, __be32 tip) |
577 | { | 583 | { |
578 | /* Private VLAN is only concerned about the same ethernet segment */ | 584 | /* Private VLAN is only concerned about the same ethernet segment */ |
579 | if (rt->u.dst.dev != dev) | 585 | if (rt->dst.dev != dev) |
580 | return 0; | 586 | return 0; |
581 | 587 | ||
582 | /* Don't reply on self probes (often done by windowz boxes)*/ | 588 | /* Don't reply on self probes (often done by windowz boxes)*/ |
@@ -698,6 +704,7 @@ out: | |||
698 | kfree_skb(skb); | 704 | kfree_skb(skb); |
699 | return NULL; | 705 | return NULL; |
700 | } | 706 | } |
707 | EXPORT_SYMBOL(arp_create); | ||
701 | 708 | ||
702 | /* | 709 | /* |
703 | * Send an arp packet. | 710 | * Send an arp packet. |
@@ -707,6 +714,7 @@ void arp_xmit(struct sk_buff *skb) | |||
707 | /* Send it off, maybe filter it using firewalling first. */ | 714 | /* Send it off, maybe filter it using firewalling first. */ |
708 | NF_HOOK(NFPROTO_ARP, NF_ARP_OUT, skb, NULL, skb->dev, dev_queue_xmit); | 715 | NF_HOOK(NFPROTO_ARP, NF_ARP_OUT, skb, NULL, skb->dev, dev_queue_xmit); |
709 | } | 716 | } |
717 | EXPORT_SYMBOL(arp_xmit); | ||
710 | 718 | ||
711 | /* | 719 | /* |
712 | * Create and send an arp packet. | 720 | * Create and send an arp packet. |
@@ -733,6 +741,7 @@ void arp_send(int type, int ptype, __be32 dest_ip, | |||
733 | 741 | ||
734 | arp_xmit(skb); | 742 | arp_xmit(skb); |
735 | } | 743 | } |
744 | EXPORT_SYMBOL(arp_send); | ||
736 | 745 | ||
737 | /* | 746 | /* |
738 | * Process an arp request. | 747 | * Process an arp request. |
@@ -741,7 +750,7 @@ void arp_send(int type, int ptype, __be32 dest_ip, | |||
741 | static int arp_process(struct sk_buff *skb) | 750 | static int arp_process(struct sk_buff *skb) |
742 | { | 751 | { |
743 | struct net_device *dev = skb->dev; | 752 | struct net_device *dev = skb->dev; |
744 | struct in_device *in_dev = in_dev_get(dev); | 753 | struct in_device *in_dev = __in_dev_get_rcu(dev); |
745 | struct arphdr *arp; | 754 | struct arphdr *arp; |
746 | unsigned char *arp_ptr; | 755 | unsigned char *arp_ptr; |
747 | struct rtable *rt; | 756 | struct rtable *rt; |
@@ -890,7 +899,6 @@ static int arp_process(struct sk_buff *skb) | |||
890 | arp_send(ARPOP_REPLY,ETH_P_ARP,sip,dev,tip,sha,dev->dev_addr,sha); | 899 | arp_send(ARPOP_REPLY,ETH_P_ARP,sip,dev,tip,sha,dev->dev_addr,sha); |
891 | } else { | 900 | } else { |
892 | pneigh_enqueue(&arp_tbl, in_dev->arp_parms, skb); | 901 | pneigh_enqueue(&arp_tbl, in_dev->arp_parms, skb); |
893 | in_dev_put(in_dev); | ||
894 | return 0; | 902 | return 0; |
895 | } | 903 | } |
896 | goto out; | 904 | goto out; |
@@ -936,8 +944,6 @@ static int arp_process(struct sk_buff *skb) | |||
936 | } | 944 | } |
937 | 945 | ||
938 | out: | 946 | out: |
939 | if (in_dev) | ||
940 | in_dev_put(in_dev); | ||
941 | consume_skb(skb); | 947 | consume_skb(skb); |
942 | return 0; | 948 | return 0; |
943 | } | 949 | } |
@@ -1045,7 +1051,7 @@ static int arp_req_set(struct net *net, struct arpreq *r, | |||
1045 | struct rtable * rt; | 1051 | struct rtable * rt; |
1046 | if ((err = ip_route_output_key(net, &rt, &fl)) != 0) | 1052 | if ((err = ip_route_output_key(net, &rt, &fl)) != 0) |
1047 | return err; | 1053 | return err; |
1048 | dev = rt->u.dst.dev; | 1054 | dev = rt->dst.dev; |
1049 | ip_rt_put(rt); | 1055 | ip_rt_put(rt); |
1050 | if (!dev) | 1056 | if (!dev) |
1051 | return -EINVAL; | 1057 | return -EINVAL; |
@@ -1152,7 +1158,7 @@ static int arp_req_delete(struct net *net, struct arpreq *r, | |||
1152 | struct rtable * rt; | 1158 | struct rtable * rt; |
1153 | if ((err = ip_route_output_key(net, &rt, &fl)) != 0) | 1159 | if ((err = ip_route_output_key(net, &rt, &fl)) != 0) |
1154 | return err; | 1160 | return err; |
1155 | dev = rt->u.dst.dev; | 1161 | dev = rt->dst.dev; |
1156 | ip_rt_put(rt); | 1162 | ip_rt_put(rt); |
1157 | if (!dev) | 1163 | if (!dev) |
1158 | return -EINVAL; | 1164 | return -EINVAL; |
@@ -1453,14 +1459,3 @@ static int __init arp_proc_init(void) | |||
1453 | } | 1459 | } |
1454 | 1460 | ||
1455 | #endif /* CONFIG_PROC_FS */ | 1461 | #endif /* CONFIG_PROC_FS */ |
1456 | |||
1457 | EXPORT_SYMBOL(arp_broken_ops); | ||
1458 | EXPORT_SYMBOL(arp_find); | ||
1459 | EXPORT_SYMBOL(arp_create); | ||
1460 | EXPORT_SYMBOL(arp_xmit); | ||
1461 | EXPORT_SYMBOL(arp_send); | ||
1462 | EXPORT_SYMBOL(arp_tbl); | ||
1463 | |||
1464 | #if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE) | ||
1465 | EXPORT_SYMBOL(clip_tbl_hook); | ||
1466 | #endif | ||