diff options
-rw-r--r-- | Documentation/networking/ip-sysctl.txt | 19 | ||||
-rw-r--r-- | include/linux/inetdevice.h | 1 | ||||
-rw-r--r-- | include/linux/sysctl.h | 1 | ||||
-rw-r--r-- | net/ipv4/arp.c | 52 | ||||
-rw-r--r-- | net/ipv4/devinet.c | 1 | ||||
-rw-r--r-- | net/ipv4/route.c | 7 |
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 | ||
695 | proxy_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 | |||
695 | shared_media - BOOLEAN | 714 | shared_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 | 528 | static inline int arp_fwd_proxy(struct in_device *in_dev, | |
528 | static 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 | */ | ||
573 | static 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 | } |