summaryrefslogtreecommitdiffstats
path: root/net/bridge/br_input.c
diff options
context:
space:
mode:
authorJouni Malinen <jouni@codeaurora.org>2015-03-04 12:54:21 +0200
committerDavid S. Miller <davem@davemloft.net>2015-03-05 14:52:23 -0500
commit842a9ae08a25671db3d4f689eed68b4d64be15b5 (patch)
treee8159604c1e8cc0abb1868e21ba6f6a5cabad5f7 /net/bridge/br_input.c
parent787fb2bd42b9d798f4ed85b66e878222a9e28ae6 (diff)
downloadlinux-842a9ae08a25671db3d4f689eed68b4d64be15b5.tar.gz
linux-842a9ae08a25671db3d4f689eed68b4d64be15b5.tar.bz2
linux-842a9ae08a25671db3d4f689eed68b4d64be15b5.zip
bridge: Extend Proxy ARP design to allow optional rules for Wi-Fi
This extends the design in commit 958501163ddd ("bridge: Add support for IEEE 802.11 Proxy ARP") with optional set of rules that are needed to meet the IEEE 802.11 and Hotspot 2.0 requirements for ProxyARP. The previously added BR_PROXYARP behavior is left as-is and a new BR_PROXYARP_WIFI alternative is added so that this behavior can be configured from user space when required. In addition, this enables proxyarp functionality for unicast ARP requests for both BR_PROXYARP and BR_PROXYARP_WIFI since it is possible to use unicast as well as broadcast for these frames. The key differences in functionality: BR_PROXYARP: - uses the flag on the bridge port on which the request frame was received to determine whether to reply - block bridge port flooding completely on ports that enable proxy ARP BR_PROXYARP_WIFI: - uses the flag on the bridge port to which the target device of the request belongs - block bridge port flooding selectively based on whether the proxyarp functionality replied Signed-off-by: Jouni Malinen <jouni@codeaurora.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/bridge/br_input.c')
-rw-r--r--net/bridge/br_input.c17
1 files changed, 10 insertions, 7 deletions
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index e2aa7be3a847..052c5ebbc947 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -60,7 +60,7 @@ static int br_pass_frame_up(struct sk_buff *skb)
}
static void br_do_proxy_arp(struct sk_buff *skb, struct net_bridge *br,
- u16 vid)
+ u16 vid, struct net_bridge_port *p)
{
struct net_device *dev = br->dev;
struct neighbour *n;
@@ -68,6 +68,8 @@ static void br_do_proxy_arp(struct sk_buff *skb, struct net_bridge *br,
u8 *arpptr, *sha;
__be32 sip, tip;
+ BR_INPUT_SKB_CB(skb)->proxyarp_replied = false;
+
if (dev->flags & IFF_NOARP)
return;
@@ -105,9 +107,12 @@ static void br_do_proxy_arp(struct sk_buff *skb, struct net_bridge *br,
}
f = __br_fdb_get(br, n->ha, vid);
- if (f)
+ if (f && ((p->flags & BR_PROXYARP) ||
+ (f->dst && (f->dst->flags & BR_PROXYARP_WIFI)))) {
arp_send(ARPOP_REPLY, ETH_P_ARP, sip, skb->dev, tip,
sha, n->ha, sha);
+ BR_INPUT_SKB_CB(skb)->proxyarp_replied = true;
+ }
neigh_release(n);
}
@@ -153,12 +158,10 @@ int br_handle_frame_finish(struct sk_buff *skb)
dst = NULL;
- if (is_broadcast_ether_addr(dest)) {
- if (IS_ENABLED(CONFIG_INET) &&
- p->flags & BR_PROXYARP &&
- skb->protocol == htons(ETH_P_ARP))
- br_do_proxy_arp(skb, br, vid);
+ if (IS_ENABLED(CONFIG_INET) && skb->protocol == htons(ETH_P_ARP))
+ br_do_proxy_arp(skb, br, vid, p);
+ if (is_broadcast_ether_addr(dest)) {
skb2 = skb;
unicast = false;
} else if (is_multicast_ether_addr(dest)) {