Parcourir la source

Fix CSA related IEs order

Fix the order of CSA, eCSA, Secondary Channel Offset, and Wide Bandwidth
Channel Switch Wrapper elements in Beacon and Probe Response frames.

Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
Andrei Otcheretianski il y a 9 ans
Parent
commit
38d9048fa8
3 fichiers modifiés avec 40 ajouts et 50 suppressions
  1. 36 48
      src/ap/beacon.c
  2. 2 1
      src/ap/ieee802_11_ht.c
  3. 2 1
      src/ap/ieee802_11_vht.c

+ 36 - 48
src/ap/beacon.c

@@ -326,51 +326,12 @@ static u8 * hostapd_eid_ecsa(struct hostapd_data *hapd, u8 *eid)
 }
 
 
-static u8 * hostapd_add_csa_elems(struct hostapd_data *hapd, u8 *pos,
-				  u8 *start, unsigned int *csa_counter_off,
-				  unsigned int *ecsa_counter_off)
-{
-	u8 *curr_pos = pos;
-	u8 *csa_pos = pos;
-
-	if (!csa_counter_off || !ecsa_counter_off)
-		return pos;
-
-	*csa_counter_off = 0;
-	*ecsa_counter_off = 0;
-
-	curr_pos = hostapd_eid_csa(hapd, curr_pos);
-
-	/* save an offset to the csa counter - should be last byte */
-	if (curr_pos != pos)
-		*csa_counter_off = curr_pos - start - 1;
-
-	csa_pos = curr_pos;
-	curr_pos = hostapd_eid_ecsa(hapd, curr_pos);
-
-	/* save an offset to the eCSA counter - should be last byte */
-	if (curr_pos != csa_pos)
-		*ecsa_counter_off = curr_pos - start - 1;
-
-	/* at least one of ies is added */
-	if (pos != curr_pos) {
-#ifdef CONFIG_IEEE80211N
-		curr_pos = hostapd_eid_secondary_channel(hapd, curr_pos);
-#endif /* CONFIG_IEEE80211N */
-#ifdef CONFIG_IEEE80211AC
-		curr_pos = hostapd_eid_wb_chsw_wrapper(hapd, curr_pos);
-#endif /* CONFIG_IEEE80211AC */
-	}
-	return curr_pos;
-}
-
-
 static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
 				   const struct ieee80211_mgmt *req,
 				   int is_p2p, size_t *resp_len)
 {
 	struct ieee80211_mgmt *resp;
-	u8 *pos, *epos;
+	u8 *pos, *epos, *csa_pos;
 	size_t buflen;
 
 #define MAX_PROBERESP_LEN 768
@@ -430,6 +391,12 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
 	/* Power Constraint element */
 	pos = hostapd_eid_pwr_constraint(hapd, pos);
 
+	/* CSA IE */
+	csa_pos = hostapd_eid_csa(hapd, pos);
+	if (csa_pos != pos)
+		hapd->cs_c_off_proberesp = csa_pos - (u8 *) resp - 1;
+	pos = csa_pos;
+
 	/* ERP Information element */
 	pos = hostapd_eid_erp_info(hapd, pos);
 
@@ -443,7 +410,17 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
 
 	pos = hostapd_eid_rm_enabled_capab(hapd, pos, epos - pos);
 
+	/* eCSA IE */
+	csa_pos = hostapd_eid_ecsa(hapd, pos);
+	if (csa_pos != pos)
+		hapd->cs_c_off_ecsa_proberesp = csa_pos - (u8 *) resp - 1;
+	pos = csa_pos;
+
 #ifdef CONFIG_IEEE80211N
+	/* Secondary Channel Offset element */
+	/* TODO: The standard doesn't specify a position for this element. */
+	pos = hostapd_eid_secondary_channel(hapd, pos);
+
 	pos = hostapd_eid_ht_capabilities(hapd, pos);
 	pos = hostapd_eid_ht_operation(hapd, pos);
 #endif /* CONFIG_IEEE80211N */
@@ -457,10 +434,6 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
 	pos = hostapd_eid_adv_proto(hapd, pos);
 	pos = hostapd_eid_roaming_consortium(hapd, pos);
 
-	pos = hostapd_add_csa_elems(hapd, pos, (u8 *)resp,
-				    &hapd->cs_c_off_proberesp,
-				    &hapd->cs_c_off_ecsa_proberesp);
-
 #ifdef CONFIG_FST
 	if (hapd->iface->fst_ies) {
 		os_memcpy(pos, wpabuf_head(hapd->iface->fst_ies),
@@ -473,6 +446,7 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
 	if (hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) {
 		pos = hostapd_eid_vht_capabilities(hapd, pos);
 		pos = hostapd_eid_vht_operation(hapd, pos);
+		pos = hostapd_eid_wb_chsw_wrapper(hapd, pos);
 	}
 	if (hapd->conf->vendor_vht)
 		pos = hostapd_eid_vendor_vht(hapd, pos);
@@ -913,7 +887,7 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
 	size_t resp_len = 0;
 #ifdef NEED_AP_MLME
 	u16 capab_info;
-	u8 *pos, *tailpos;
+	u8 *pos, *tailpos, *csa_pos;
 
 #define BEACON_HEAD_BUF_SIZE 256
 #define BEACON_TAIL_BUF_SIZE 512
@@ -994,6 +968,12 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
 	/* Power Constraint element */
 	tailpos = hostapd_eid_pwr_constraint(hapd, tailpos);
 
+	/* CSA IE */
+	csa_pos = hostapd_eid_csa(hapd, tailpos);
+	if (csa_pos != tailpos)
+		hapd->cs_c_off_beacon = csa_pos - tail - 1;
+	tailpos = csa_pos;
+
 	/* ERP Information element */
 	tailpos = hostapd_eid_erp_info(hapd, tailpos);
 
@@ -1011,7 +991,17 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
 	tailpos = hostapd_eid_bss_load(hapd, tailpos,
 				       tail + BEACON_TAIL_BUF_SIZE - tailpos);
 
+	/* eCSA IE */
+	csa_pos = hostapd_eid_ecsa(hapd, tailpos);
+	if (csa_pos != tailpos)
+		hapd->cs_c_off_ecsa_beacon = csa_pos - tail - 1;
+	tailpos = csa_pos;
+
 #ifdef CONFIG_IEEE80211N
+	/* Secondary Channel Offset element */
+	/* TODO: The standard doesn't specify a position for this element. */
+	tailpos = hostapd_eid_secondary_channel(hapd, tailpos);
+
 	tailpos = hostapd_eid_ht_capabilities(hapd, tailpos);
 	tailpos = hostapd_eid_ht_operation(hapd, tailpos);
 #endif /* CONFIG_IEEE80211N */
@@ -1027,9 +1017,6 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
 	tailpos = hostapd_eid_interworking(hapd, tailpos);
 	tailpos = hostapd_eid_adv_proto(hapd, tailpos);
 	tailpos = hostapd_eid_roaming_consortium(hapd, tailpos);
-	tailpos = hostapd_add_csa_elems(hapd, tailpos, tail,
-					&hapd->cs_c_off_beacon,
-					&hapd->cs_c_off_ecsa_beacon);
 
 #ifdef CONFIG_FST
 	if (hapd->iface->fst_ies) {
@@ -1043,6 +1030,7 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
 	if (hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) {
 		tailpos = hostapd_eid_vht_capabilities(hapd, tailpos);
 		tailpos = hostapd_eid_vht_operation(hapd, tailpos);
+		tailpos = hostapd_eid_wb_chsw_wrapper(hapd, tailpos);
 	}
 	if (hapd->conf->vendor_vht)
 		tailpos = hostapd_eid_vendor_vht(hapd, tailpos);

+ 2 - 1
src/ap/ieee802_11_ht.c

@@ -112,7 +112,8 @@ u8 * hostapd_eid_secondary_channel(struct hostapd_data *hapd, u8 *eid)
 {
 	u8 sec_ch;
 
-	if (!hapd->cs_freq_params.sec_channel_offset)
+	if (!hapd->cs_freq_params.channel ||
+	    !hapd->cs_freq_params.sec_channel_offset)
 		return eid;
 
 	if (hapd->cs_freq_params.sec_channel_offset == -1)

+ 2 - 1
src/ap/ieee802_11_vht.c

@@ -136,7 +136,8 @@ u8 * hostapd_eid_wb_chsw_wrapper(struct hostapd_data *hapd, u8 *eid)
 	u8 bw, chan1, chan2 = 0;
 	int freq1;
 
-	if (!hapd->cs_freq_params.vht_enabled)
+	if (!hapd->cs_freq_params.channel ||
+	    !hapd->cs_freq_params.vht_enabled)
 		return eid;
 
 	/* bandwidth: 0: 40, 1: 80, 2: 160, 3: 80+80 */