aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/networking/ip-sysctl.txt19
-rw-r--r--include/linux/inetdevice.h1
-rw-r--r--include/linux/sysctl.h1
-rw-r--r--net/ipv4/arp.c52
-rw-r--r--net/ipv4/devinet.c1
-rw-r--r--net/ipv4/route.c7
6 files changed, 76 insertions, 5 deletions
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index 006b39dec87d..c532884f4fec 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -692,6 +692,25 @@ proxy_arp - BOOLEAN
692 conf/{all,interface}/proxy_arp is set to TRUE, 692 conf/{all,interface}/proxy_arp is set to TRUE,
693 it will be disabled otherwise 693 it will be disabled otherwise
694 694
695proxy_arp_pvlan - BOOLEAN
696 Private VLAN proxy arp.
697 Basically allow proxy arp replies back to the same interface
698 (from which the ARP request/solicitation was received).
699
700 This is done to support (ethernet) switch features, like RFC
701 3069, where the individual ports are NOT allowed to
702 communicate with each other, but they are allowed to talk to
703 the upstream router. As described in RFC 3069, it is possible
704 to allow these hosts to communicate through the upstream
705 router by proxy_arp'ing. Don't need to be used together with
706 proxy_arp.
707
708 This technology is known by different names:
709 In RFC 3069 it is called VLAN Aggregation.
710 Cisco and Allied Telesyn call it Private VLAN.
711 Hewlett-Packard call it Source-Port filtering or port-isolation.
712 Ericsson call it MAC-Forced Forwarding (RFC Draft).
713
695shared_media - BOOLEAN 714shared_media - BOOLEAN
696 Send(router) or accept(host) RFC1620 shared media redirects. 715 Send(router) or accept(host) RFC1620 shared media redirects.
697 Overrides ip_secure_redirects. 716 Overrides ip_secure_redirects.
diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h
index 699e85c01a4d..9a8c57467d3d 100644
--- a/include/linux/inetdevice.h
+++ b/include/linux/inetdevice.h
@@ -88,6 +88,7 @@ static inline void ipv4_devconf_setall(struct in_device *in_dev)
88 88
89#define IN_DEV_LOG_MARTIANS(in_dev) IN_DEV_ORCONF((in_dev), LOG_MARTIANS) 89#define IN_DEV_LOG_MARTIANS(in_dev) IN_DEV_ORCONF((in_dev), LOG_MARTIANS)
90#define IN_DEV_PROXY_ARP(in_dev) IN_DEV_ORCONF((in_dev), PROXY_ARP) 90#define IN_DEV_PROXY_ARP(in_dev) IN_DEV_ORCONF((in_dev), PROXY_ARP)
91#define IN_DEV_PROXY_ARP_PVLAN(in_dev) IN_DEV_CONF_GET(in_dev, PROXY_ARP_PVLAN)
91#define IN_DEV_SHARED_MEDIA(in_dev) IN_DEV_ORCONF((in_dev), SHARED_MEDIA) 92#define IN_DEV_SHARED_MEDIA(in_dev) IN_DEV_ORCONF((in_dev), SHARED_MEDIA)
92#define IN_DEV_TX_REDIRECTS(in_dev) IN_DEV_ORCONF((in_dev), SEND_REDIRECTS) 93#define IN_DEV_TX_REDIRECTS(in_dev) IN_DEV_ORCONF((in_dev), SEND_REDIRECTS)
93#define IN_DEV_SEC_REDIRECTS(in_dev) IN_DEV_ORCONF((in_dev), \ 94#define IN_DEV_SEC_REDIRECTS(in_dev) IN_DEV_ORCONF((in_dev), \
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index 877ba039e6a4..24ff7e3a0d59 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -482,6 +482,7 @@ enum
482 NET_IPV4_CONF_ARP_ACCEPT=21, 482 NET_IPV4_CONF_ARP_ACCEPT=21,
483 NET_IPV4_CONF_ARP_NOTIFY=22, 483 NET_IPV4_CONF_ARP_NOTIFY=22,
484 NET_IPV4_CONF_ACCEPT_LOCAL=23, 484 NET_IPV4_CONF_ACCEPT_LOCAL=23,
485 NET_IPV4_CONF_PROXY_ARP_PVLAN=24,
485 __NET_IPV4_CONF_MAX 486 __NET_IPV4_CONF_MAX
486}; 487};
487 488
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index c95cd93acf29..078709233bc4 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>
@@ -524,12 +525,15 @@ int arp_bind_neighbour(struct dst_entry *dst)
524/* 525/*
525 * Check if we can use proxy ARP for this path 526 * Check if we can use proxy ARP for this path
526 */ 527 */
527 528static inline int arp_fwd_proxy(struct in_device *in_dev,
528static inline int arp_fwd_proxy(struct in_device *in_dev, struct rtable *rt) 529 struct net_device *dev, struct rtable *rt)
529{ 530{
530 struct in_device *out_dev; 531 struct in_device *out_dev;
531 int imi, omi = -1; 532 int imi, omi = -1;
532 533
534 if (rt->u.dst.dev == dev)
535 return 0;
536
533 if (!IN_DEV_PROXY_ARP(in_dev)) 537 if (!IN_DEV_PROXY_ARP(in_dev))
534 return 0; 538 return 0;
535 539
@@ -548,6 +552,43 @@ static inline int arp_fwd_proxy(struct in_device *in_dev, struct rtable *rt)
548} 552}
549 553
550/* 554/*
555 * Check for RFC3069 proxy arp private VLAN (allow to send back to same dev)
556 *
557 * RFC3069 supports proxy arp replies back to the same interface. This
558 * is done to support (ethernet) switch features, like RFC 3069, where
559 * the individual ports are not allowed to communicate with each
560 * other, BUT they are allowed to talk to the upstream router. As
561 * described in RFC 3069, it is possible to allow these hosts to
562 * communicate through the upstream router, by proxy_arp'ing.
563 *
564 * RFC 3069: "VLAN Aggregation for Efficient IP Address Allocation"
565 *
566 * This technology is known by different names:
567 * In RFC 3069 it is called VLAN Aggregation.
568 * Cisco and Allied Telesyn call it Private VLAN.
569 * Hewlett-Packard call it Source-Port filtering or port-isolation.
570 * Ericsson call it MAC-Forced Forwarding (RFC Draft).
571 *
572 */
573static inline int arp_fwd_pvlan(struct in_device *in_dev,
574 struct net_device *dev, struct rtable *rt,
575 __be32 sip, __be32 tip)
576{
577 /* Private VLAN is only concerned about the same ethernet segment */
578 if (rt->u.dst.dev != dev)
579 return 0;
580
581 /* Don't reply on self probes (often done by windowz boxes)*/
582 if (sip == tip)
583 return 0;
584
585 if (IN_DEV_PROXY_ARP_PVLAN(in_dev))
586 return 1;
587 else
588 return 0;
589}
590
591/*
551 * Interface to link layer: send routine and receive handler. 592 * Interface to link layer: send routine and receive handler.
552 */ 593 */
553 594
@@ -833,8 +874,11 @@ static int arp_process(struct sk_buff *skb)
833 } 874 }
834 goto out; 875 goto out;
835 } else if (IN_DEV_FORWARD(in_dev)) { 876 } else if (IN_DEV_FORWARD(in_dev)) {
836 if (addr_type == RTN_UNICAST && rt->u.dst.dev != dev && 877 if (addr_type == RTN_UNICAST &&
837 (arp_fwd_proxy(in_dev, rt) || pneigh_lookup(&arp_tbl, net, &tip, dev, 0))) { 878 (arp_fwd_proxy(in_dev, dev, rt) ||
879 arp_fwd_pvlan(in_dev, dev, rt, sip, tip) ||
880 pneigh_lookup(&arp_tbl, net, &tip, dev, 0)))
881 {
838 n = neigh_event_ns(&arp_tbl, sha, &sip, dev); 882 n = neigh_event_ns(&arp_tbl, sha, &sip, dev);
839 if (n) 883 if (n)
840 neigh_release(n); 884 neigh_release(n);
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 5cdbc102a418..0715f4cac391 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -1407,6 +1407,7 @@ static struct devinet_sysctl_table {
1407 DEVINET_SYSCTL_RW_ENTRY(ARP_IGNORE, "arp_ignore"), 1407 DEVINET_SYSCTL_RW_ENTRY(ARP_IGNORE, "arp_ignore"),
1408 DEVINET_SYSCTL_RW_ENTRY(ARP_ACCEPT, "arp_accept"), 1408 DEVINET_SYSCTL_RW_ENTRY(ARP_ACCEPT, "arp_accept"),
1409 DEVINET_SYSCTL_RW_ENTRY(ARP_NOTIFY, "arp_notify"), 1409 DEVINET_SYSCTL_RW_ENTRY(ARP_NOTIFY, "arp_notify"),
1410 DEVINET_SYSCTL_RW_ENTRY(PROXY_ARP_PVLAN, "proxy_arp_pvlan"),
1410 1411
1411 DEVINET_SYSCTL_FLUSHING_ENTRY(NOXFRM, "disable_xfrm"), 1412 DEVINET_SYSCTL_FLUSHING_ENTRY(NOXFRM, "disable_xfrm"),
1412 DEVINET_SYSCTL_FLUSHING_ENTRY(NOPOLICY, "disable_policy"), 1413 DEVINET_SYSCTL_FLUSHING_ENTRY(NOPOLICY, "disable_policy"),
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index e446496f564f..1cc339441e7d 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -1988,8 +1988,13 @@ static int __mkroute_input(struct sk_buff *skb,
1988 if (skb->protocol != htons(ETH_P_IP)) { 1988 if (skb->protocol != htons(ETH_P_IP)) {
1989 /* Not IP (i.e. ARP). Do not create route, if it is 1989 /* Not IP (i.e. ARP). Do not create route, if it is
1990 * invalid for proxy arp. DNAT routes are always valid. 1990 * invalid for proxy arp. DNAT routes are always valid.
1991 *
1992 * Proxy arp feature have been extended to allow, ARP
1993 * replies back to the same interface, to support
1994 * Private VLAN switch technologies. See arp.c.
1991 */ 1995 */
1992 if (out_dev == in_dev) { 1996 if (out_dev == in_dev &&
1997 IN_DEV_PROXY_ARP_PVLAN(in_dev) == 0) {
1993 err = -EINVAL; 1998 err = -EINVAL;
1994 goto cleanup; 1999 goto cleanup;
1995 } 2000 }