Patchwork [18/23] P2P: Disallow legacy client connection on indoor channel

login
register
mail settings
Submitter Ilan Peer
Date July 7, 2014, 11:21 a.m.
Message ID <1404732076-32252-19-git-send-email-ilan.peer@intel.com>
Download mbox | patch
Permalink /patch/367521/
State New
Headers show

Comments

Ilan Peer - July 7, 2014, 11:21 a.m.
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(+)

Patch

diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index 93804de..33b6bb5 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -497,6 +497,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 d0a837b..c974dfe 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -1165,6 +1165,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;
@@ -1232,6 +1235,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)
@@ -1246,6 +1255,10 @@  int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err)
 		}
 		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 4190956..29b0713 100644
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -231,6 +231,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 23f0eae..7e62769 100644
--- a/src/ap/hw_features.c
+++ b/src/ap/hw_features.c
@@ -1166,3 +1166,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 de1ee5e..f15dc58 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -944,6 +944,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 */