aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/arp.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/arp.c')
-rw-r--r--net/ipv4/arp.c65
1 files changed, 55 insertions, 10 deletions
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index 4e80f336c0cf..80769f1f9fab 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -70,6 +70,7 @@
70 * bonding can change the skb before 70 * bonding can change the skb before
71 * sending (e.g. insert 8021q tag). 71 * sending (e.g. insert 8021q tag).
72 * Harald Welte : convert to make use of jenkins hash 72 * Harald Welte : convert to make use of jenkins hash
73 * Jesper D. Brouer: Proxy ARP PVLAN RFC 3069 support.
73 */ 74 */
74 75
75#include <linux/module.h> 76#include <linux/module.h>
@@ -97,6 +98,7 @@
97#include <linux/net.h> 98#include <linux/net.h>
98#include <linux/rcupdate.h> 99#include <linux/rcupdate.h>
99#include <linux/jhash.h> 100#include <linux/jhash.h>
101#include <linux/slab.h>
100#ifdef CONFIG_SYSCTL 102#ifdef CONFIG_SYSCTL
101#include <linux/sysctl.h> 103#include <linux/sysctl.h>
102#endif 104#endif
@@ -524,12 +526,15 @@ int arp_bind_neighbour(struct dst_entry *dst)
524/* 526/*
525 * Check if we can use proxy ARP for this path 527 * Check if we can use proxy ARP for this path
526 */ 528 */
527 529static inline int arp_fwd_proxy(struct in_device *in_dev,
528static inline int arp_fwd_proxy(struct in_device *in_dev, struct rtable *rt) 530 struct net_device *dev, struct rtable *rt)
529{ 531{
530 struct in_device *out_dev; 532 struct in_device *out_dev;
531 int imi, omi = -1; 533 int imi, omi = -1;
532 534
535 if (rt->u.dst.dev == dev)
536 return 0;
537
533 if (!IN_DEV_PROXY_ARP(in_dev)) 538 if (!IN_DEV_PROXY_ARP(in_dev))
534 return 0; 539 return 0;
535 540
@@ -548,6 +553,43 @@ static inline int arp_fwd_proxy(struct in_device *in_dev, struct rtable *rt)
548} 553}
549 554
550/* 555/*
556 * Check for RFC3069 proxy arp private VLAN (allow to send back to same dev)
557 *
558 * RFC3069 supports proxy arp replies back to the same interface. This
559 * is done to support (ethernet) switch features, like RFC 3069, where
560 * the individual ports are not allowed to communicate with each
561 * other, BUT they are allowed to talk to the upstream router. As
562 * described in RFC 3069, it is possible to allow these hosts to
563 * communicate through the upstream router, by proxy_arp'ing.
564 *
565 * RFC 3069: "VLAN Aggregation for Efficient IP Address Allocation"
566 *
567 * This technology is known by different names:
568 * In RFC 3069 it is called VLAN Aggregation.
569 * Cisco and Allied Telesyn call it Private VLAN.
570 * Hewlett-Packard call it Source-Port filtering or port-isolation.
571 * Ericsson call it MAC-Forced Forwarding (RFC Draft).
572 *
573 */
574static inline int arp_fwd_pvlan(struct in_device *in_dev,
575 struct net_device *dev, struct rtable *rt,
576 __be32 sip, __be32 tip)
577{
578 /* Private VLAN is only concerned about the same ethernet segment */
579 if (rt->u.dst.dev != dev)
580 return 0;
581
582 /* Don't reply on self probes (often done by windowz boxes)*/
583 if (sip == tip)
584 return 0;
585
586 if (IN_DEV_PROXY_ARP_PVLAN(in_dev))
587 return 1;
588 else
589 return 0;
590}
591
592/*
551 * Interface to link layer: send routine and receive handler. 593 * Interface to link layer: send routine and receive handler.
552 */ 594 */
553 595
@@ -619,13 +661,13 @@ struct sk_buff *arp_create(int type, int ptype, __be32 dest_ip,
619#endif 661#endif
620#endif 662#endif
621 663
622#ifdef CONFIG_FDDI 664#if defined(CONFIG_FDDI) || defined(CONFIG_FDDI_MODULE)
623 case ARPHRD_FDDI: 665 case ARPHRD_FDDI:
624 arp->ar_hrd = htons(ARPHRD_ETHER); 666 arp->ar_hrd = htons(ARPHRD_ETHER);
625 arp->ar_pro = htons(ETH_P_IP); 667 arp->ar_pro = htons(ETH_P_IP);
626 break; 668 break;
627#endif 669#endif
628#ifdef CONFIG_TR 670#if defined(CONFIG_TR) || defined(CONFIG_TR_MODULE)
629 case ARPHRD_IEEE802_TR: 671 case ARPHRD_IEEE802_TR:
630 arp->ar_hrd = htons(ARPHRD_IEEE802); 672 arp->ar_hrd = htons(ARPHRD_IEEE802);
631 arp->ar_pro = htons(ETH_P_IP); 673 arp->ar_pro = htons(ETH_P_IP);
@@ -833,8 +875,11 @@ static int arp_process(struct sk_buff *skb)
833 } 875 }
834 goto out; 876 goto out;
835 } else if (IN_DEV_FORWARD(in_dev)) { 877 } else if (IN_DEV_FORWARD(in_dev)) {
836 if (addr_type == RTN_UNICAST && rt->u.dst.dev != dev && 878 if (addr_type == RTN_UNICAST &&
837 (arp_fwd_proxy(in_dev, rt) || pneigh_lookup(&arp_tbl, net, &tip, dev, 0))) { 879 (arp_fwd_proxy(in_dev, dev, rt) ||
880 arp_fwd_pvlan(in_dev, dev, rt, sip, tip) ||
881 pneigh_lookup(&arp_tbl, net, &tip, dev, 0)))
882 {
838 n = neigh_event_ns(&arp_tbl, sha, &sip, dev); 883 n = neigh_event_ns(&arp_tbl, sha, &sip, dev);
839 if (n) 884 if (n)
840 neigh_release(n); 885 neigh_release(n);
@@ -863,7 +908,8 @@ static int arp_process(struct sk_buff *skb)
863 devices (strip is candidate) 908 devices (strip is candidate)
864 */ 909 */
865 if (n == NULL && 910 if (n == NULL &&
866 arp->ar_op == htons(ARPOP_REPLY) && 911 (arp->ar_op == htons(ARPOP_REPLY) ||
912 (arp->ar_op == htons(ARPOP_REQUEST) && tip == sip)) &&
867 inet_addr_type(net, sip) == RTN_UNICAST) 913 inet_addr_type(net, sip) == RTN_UNICAST)
868 n = __neigh_lookup(&arp_tbl, &sip, dev, 1); 914 n = __neigh_lookup(&arp_tbl, &sip, dev, 1);
869 } 915 }
@@ -1005,7 +1051,7 @@ static int arp_req_set(struct net *net, struct arpreq *r,
1005 return -EINVAL; 1051 return -EINVAL;
1006 } 1052 }
1007 switch (dev->type) { 1053 switch (dev->type) {
1008#ifdef CONFIG_FDDI 1054#if defined(CONFIG_FDDI) || defined(CONFIG_FDDI_MODULE)
1009 case ARPHRD_FDDI: 1055 case ARPHRD_FDDI:
1010 /* 1056 /*
1011 * According to RFC 1390, FDDI devices should accept ARP 1057 * According to RFC 1390, FDDI devices should accept ARP
@@ -1239,8 +1285,7 @@ void __init arp_init(void)
1239 dev_add_pack(&arp_packet_type); 1285 dev_add_pack(&arp_packet_type);
1240 arp_proc_init(); 1286 arp_proc_init();
1241#ifdef CONFIG_SYSCTL 1287#ifdef CONFIG_SYSCTL
1242 neigh_sysctl_register(NULL, &arp_tbl.parms, NET_IPV4, 1288 neigh_sysctl_register(NULL, &arp_tbl.parms, "ipv4", NULL);
1243 NET_IPV4_NEIGH, "ipv4", NULL, NULL);
1244#endif 1289#endif
1245 register_netdevice_notifier(&arp_netdev_notifier); 1290 register_netdevice_notifier(&arp_netdev_notifier);
1246} 1291}