diff mbox

[19/24] P2P: Disallow legacy client connection on indoor channel

Message ID 1400483181-10284-20-git-send-email-ilan.peer@intel.com
State Changes Requested
Headers show

Commit Message

Peer, Ilan May 19, 2014, 7:06 a.m. UTC
In order to prevent daisy chain scenario, a GO should not allow
legacy clients to connect to it if the GO is operating on
an INDOOR only channel.

Add the support to determine if the given operating frequency of
the GO is associated with a channel for which only indoor operation
is allowed and disallow legacy client connection in such cases.

Signed-off-by: Ilan Peer <ilan.peer@intel.com>
---
 src/ap/drv_callbacks.c |    9 +++++++++
 src/ap/hostapd.c       |   13 +++++++++++++
 src/ap/hostapd.h       |    1 +
 src/ap/hw_features.c   |   34 ++++++++++++++++++++++++++++++++++
 src/ap/hw_features.h   |    9 +++++++++
 src/ap/ieee802_11.c    |    9 +++++++++
 6 files changed, 75 insertions(+)
diff mbox

Patch

diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index fb095ef..fa33e37 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -496,6 +496,15 @@  void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
 		wpa_msg(hapd->msg_ctx, MSG_INFO, AP_CSA_FINISHED "freq=%d",
 			freq);
 	}
+
+#ifdef CONFIG_P2P
+	hapd->disallow_legacy_clients = hapd->p2p &&
+		hostapd_freq_flags(hapd->iface,
+				   hapd->iface->freq,
+				   HOSTAPD_CHAN_INDOOR_ONLY);
+
+	/* TODO: need to deauth legacy clients */
+#endif /* CONFIG_P2P */
 #endif /* NEED_AP_MLME */
 }
 
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index 147635f..7d8d1a8 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -1147,6 +1147,9 @@  int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err)
 	struct hostapd_data *hapd = iface->bss[0];
 	size_t j;
 	u8 *prev_addr;
+#ifdef CONFIG_P2P
+	int disallow_legacy_clients;
+#endif /* CONFIG_P2P */
 
 	if (err)
 		goto fail;
@@ -1214,6 +1217,12 @@  int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err)
 
 	prev_addr = hapd->own_addr;
 
+#ifdef CONFIG_P2P
+	disallow_legacy_clients =
+		hostapd_freq_flags(iface, iface->freq,
+				   HOSTAPD_CHAN_INDOOR_ONLY);
+#endif /* CONFIG_P2P */
+
 	for (j = 0; j < iface->num_bss; j++) {
 		hapd = iface->bss[j];
 		if (j)
@@ -1222,6 +1231,10 @@  int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err)
 			goto fail;
 		if (hostapd_mac_comp_empty(hapd->conf->bssid) == 0)
 			prev_addr = hapd->own_addr;
+#ifdef CONFIG_P2P
+		if (hapd->p2p)
+			hapd->disallow_legacy_clients = disallow_legacy_clients;
+#endif /* CONFIG_P2P */
 	}
 	hapd = iface->bss[0];
 
diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
index 25c2d4f..687dbaa 100644
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -223,6 +223,7 @@  struct hostapd_data {
 	int noa_enabled;
 	int noa_start;
 	int noa_duration;
+	unsigned int disallow_legacy_clients;
 #endif /* CONFIG_P2P */
 #ifdef CONFIG_INTERWORKING
 	size_t gas_frag_limit;
diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c
index 2d01d1d..8d1029d 100644
--- a/src/ap/hw_features.c
+++ b/src/ap/hw_features.c
@@ -1128,3 +1128,37 @@  int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq)
 
 	return 0;
 }
+
+
+/*
+ * hostapd_channel_flags - check if the given flags are set for the given freq
+ * @iface: Pointer to hostapd interface
+ * @freq: the freq to check
+ * @flags: the flags to verify
+ *
+ * The function determines if the given flags are set for the given freq in one
+ * of the supported hw_modes.
+ * Returns 1 if there is a matching channel which is enabled and on which the
+ * give flags are set. Otherwise returns 0.
+ */
+int hostapd_freq_flags(struct hostapd_iface *iface, int freq,
+		       unsigned int flags)
+{
+	struct hostapd_hw_modes *mode;
+	u16 i;
+
+	for (i = 0; i < iface->num_hw_features; i++) {
+		int j;
+
+		mode = &iface->hw_features[i];
+		for (j = 0; j < mode->num_channels; j++) {
+			if (mode->channels[j].flag & HOSTAPD_CHAN_DISABLED ||
+			    mode->channels[j].freq != freq)
+				continue;
+
+			if ((mode->channels[j].flag & flags) == flags)
+				return 1;
+		}
+	}
+	return 0;
+}
diff --git a/src/ap/hw_features.h b/src/ap/hw_features.h
index 0f67ab8..6844af9 100644
--- a/src/ap/hw_features.h
+++ b/src/ap/hw_features.h
@@ -24,6 +24,9 @@  int hostapd_check_ht_capab(struct hostapd_iface *iface);
 int hostapd_prepare_rates(struct hostapd_iface *iface,
 			  struct hostapd_hw_modes *mode);
 void hostapd_stop_setup_timers(struct hostapd_iface *iface);
+int hostapd_freq_flags(struct hostapd_iface *iface, int freq,
+		       unsigned int flags);
+
 #else /* NEED_AP_MLME */
 static inline void
 hostapd_free_hw_features(struct hostapd_hw_modes *hw_features,
@@ -66,6 +69,12 @@  static inline void hostapd_stop_setup_timers(struct hostapd_iface *iface)
 {
 }
 
+static inline int hostapd_freq_flags(struct hostapd_iface *iface, int freq,
+				     unsigned int flags)
+{
+	return 0;
+}
+
 #endif /* NEED_AP_MLME */
 
 #endif /* HW_FEATURES_H */
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index ca8db8f..3ddb1ee 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -943,6 +943,15 @@  static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
 	} else {
 		wpabuf_free(sta->p2p_ie);
 		sta->p2p_ie = NULL;
+
+		if (hapd->disallow_legacy_clients) {
+			hostapd_logger(hapd, sta->addr,
+				       HOSTAPD_MODULE_IEEE80211,
+				       HOSTAPD_LEVEL_INFO,
+				       "Station is a legacy client and "
+				       "connection to P2P GO is not allowed");
+			return WLAN_STATUS_UNSPECIFIED_FAILURE;
+		}
 	}
 #endif /* CONFIG_P2P */