diff options
Diffstat (limited to 'net/ipv4/arp.c')
-rw-r--r-- | net/ipv4/arp.c | 65 |
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 | 529 | 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) | 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 | */ | ||
574 | static 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 | } |