aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge/br_input.c
diff options
context:
space:
mode:
authorJouni Malinen <jouni@codeaurora.org>2015-03-04 05:54:21 -0500
committerDavid S. Miller <davem@davemloft.net>2015-03-05 14:52:23 -0500
commit842a9ae08a25671db3d4f689eed68b4d64be15b5 (patch)
treee8159604c1e8cc0abb1868e21ba6f6a5cabad5f7 /net/bridge/br_input.c
parent787fb2bd42b9d798f4ed85b66e878222a9e28ae6 (diff)
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)
60} 60}
61 61
62static void br_do_proxy_arp(struct sk_buff *skb, struct net_bridge *br, 62static void br_do_proxy_arp(struct sk_buff *skb, struct net_bridge *br,
63 u16 vid) 63 u16 vid, struct net_bridge_port *p)
64{ 64{
65 struct net_device *dev = br->dev; 65 struct net_device *dev = br->dev;
66 struct neighbour *n; 66 struct neighbour *n;
@@ -68,6 +68,8 @@ static void br_do_proxy_arp(struct sk_buff *skb, struct net_bridge *br,
68 u8 *arpptr, *sha; 68 u8 *arpptr, *sha;
69 __be32 sip, tip; 69 __be32 sip, tip;
70 70
71 BR_INPUT_SKB_CB(skb)->proxyarp_replied = false;
72
71 if (dev->flags & IFF_NOARP) 73 if (dev->flags & IFF_NOARP)
72 return; 74 return;
73 75
@@ -105,9 +107,12 @@ static void br_do_proxy_arp(struct sk_buff *skb, struct net_bridge *br,
105 } 107 }
106 108
107 f = __br_fdb_get(br, n->ha, vid); 109 f = __br_fdb_get(br, n->ha, vid);
108 if (f) 110 if (f && ((p->flags & BR_PROXYARP) ||
111 (f->dst && (f->dst->flags & BR_PROXYARP_WIFI)))) {
109 arp_send(ARPOP_REPLY, ETH_P_ARP, sip, skb->dev, tip, 112 arp_send(ARPOP_REPLY, ETH_P_ARP, sip, skb->dev, tip,
110 sha, n->ha, sha); 113 sha, n->ha, sha);
114 BR_INPUT_SKB_CB(skb)->proxyarp_replied = true;
115 }
111 116
112 neigh_release(n); 117 neigh_release(n);
113 } 118 }
@@ -153,12 +158,10 @@ int br_handle_frame_finish(struct sk_buff *skb)
153 158
154 dst = NULL; 159 dst = NULL;
155 160
156 if (is_broadcast_ether_addr(dest)) { 161 if (IS_ENABLED(CONFIG_INET) && skb->protocol == htons(ETH_P_ARP))
157 if (IS_ENABLED(CONFIG_INET) && 162 br_do_proxy_arp(skb, br, vid, p);
158 p->flags & BR_PROXYARP &&
159 skb->protocol == htons(ETH_P_ARP))
160 br_do_proxy_arp(skb, br, vid);
161 163
164 if (is_broadcast_ether_addr(dest)) {
162 skb2 = skb; 165 skb2 = skb;
163 unicast = false; 166 unicast = false;
164 } else if (is_multicast_ether_addr(dest)) { 167 } else if (is_multicast_ether_addr(dest)) {