nl80211: Share common interface processing code
[wpasupplicant] / wpa_supplicant / mlme.c
index 964b8c0..e894c46 100644 (file)
@@ -20,8 +20,8 @@
 #include "eloop.h"
 #include "config_ssid.h"
 #include "wpa_supplicant_i.h"
+#include "driver_i.h"
 #include "wpa.h"
-#include "drivers/driver.h"
 #include "ieee802_11_defs.h"
 #include "ieee802_11_common.h"
 #include "mlme.h"
@@ -94,14 +94,15 @@ static int ieee80211_sta_find_ibss(struct wpa_supplicant *wpa_s);
 static int ieee80211_sta_wep_configured(struct wpa_supplicant *wpa_s);
 static void ieee80211_sta_timer(void *eloop_ctx, void *timeout_ctx);
 static void ieee80211_sta_scan_timer(void *eloop_ctx, void *timeout_ctx);
+static void ieee80211_build_tspec(struct wpabuf *buf);
 
 
 static int ieee80211_sta_set_channel(struct wpa_supplicant *wpa_s,
-                                    wpa_hw_mode phymode, int chan,
+                                    hostapd_hw_mode phymode, int chan,
                                     int freq)
 {
        size_t i;
-       struct wpa_hw_modes *mode;
+       struct hostapd_hw_modes *mode;
 
        for (i = 0; i < wpa_s->mlme.num_modes; i++) {
                mode = &wpa_s->mlme.modes[i];
@@ -116,8 +117,6 @@ static int ieee80211_sta_set_channel(struct wpa_supplicant *wpa_s,
 }
 
 
-
-#if 0 /* FIX */
 static int ecw2cw(int ecw)
 {
        int cw = 1;
@@ -127,7 +126,6 @@ static int ecw2cw(int ecw)
        }
        return cw - 1;
 }
-#endif
 
 
 static void ieee80211_sta_wmm_params(struct wpa_supplicant *wpa_s,
@@ -136,6 +134,7 @@ static void ieee80211_sta_wmm_params(struct wpa_supplicant *wpa_s,
        size_t left;
        int count;
        u8 *pos;
+       u8 wmm_acm;
 
        if (wmm_param_len < 8 || wmm_param[5] /* version */ != 1)
                return;
@@ -147,54 +146,42 @@ static void ieee80211_sta_wmm_params(struct wpa_supplicant *wpa_s,
        pos = wmm_param + 8;
        left = wmm_param_len - 8;
 
-#if 0 /* FIX */
        wmm_acm = 0;
        for (; left >= 4; left -= 4, pos += 4) {
                int aci = (pos[0] >> 5) & 0x03;
                int acm = (pos[0] >> 4) & 0x01;
-               int queue;
+               int aifs, cw_max, cw_min, burst_time;
 
                switch (aci) {
-               case 1:
-                       queue = IEEE80211_TX_QUEUE_DATA3;
+               case 1: /* AC_BK */
                        if (acm)
-                               wmm_acm |= BIT(1) | BIT(2);
+                               wmm_acm |= BIT(1) | BIT(2); /* BK/- */
                        break;
-               case 2:
-                       queue = IEEE80211_TX_QUEUE_DATA1;
+               case 2: /* AC_VI */
                        if (acm)
-                               wmm_acm |= BIT(4) | BIT(5);
+                               wmm_acm |= BIT(4) | BIT(5); /* CL/VI */
                        break;
-               case 3:
-                       queue = IEEE80211_TX_QUEUE_DATA0;
+               case 3: /* AC_VO */
                        if (acm)
-                               wmm_acm |= BIT(6) | BIT(7);
+                               wmm_acm |= BIT(6) | BIT(7); /* VO/NC */
                        break;
-               case 0:
+               case 0: /* AC_BE */
                default:
-                       queue = IEEE80211_TX_QUEUE_DATA2;
                        if (acm)
-                               wpa_s->mlme.wmm_acm |= BIT(0) | BIT(3);
+                               wmm_acm |= BIT(0) | BIT(3); /* BE/EE */
                        break;
                }
 
-               params.aifs = pos[0] & 0x0f;
-               params.cw_max = ecw2cw((pos[1] & 0xf0) >> 4);
-               params.cw_min = ecw2cw(pos[1] & 0x0f);
+               aifs = pos[0] & 0x0f;
+               cw_max = ecw2cw((pos[1] & 0xf0) >> 4);
+               cw_min = ecw2cw(pos[1] & 0x0f);
                /* TXOP is in units of 32 usec; burst_time in 0.1 ms */
-               params.burst_time = (pos[2] | (pos[3] << 8)) * 32 / 100;
-               wpa_printf(MSG_DEBUG, "MLME: WMM queue=%d aci=%d acm=%d "
-                          "aifs=%d cWmin=%d cWmax=%d burst=%d",
-                          queue, aci, acm, params.aifs, params.cw_min,
-                          params.cw_max, params.burst_time);
-               /* TODO: handle ACM (block TX, fallback to next lowest allowed
-                * AC for now) */
-               if (local->hw->conf_tx(local->mdev, queue, &params)) {
-                       wpa_printf(MSG_DEBUG, "MLME: failed to set TX queue "
-                                  "parameters for queue %d", queue);
-               }
+               burst_time = (pos[2] | (pos[3] << 8)) * 32 / 100;
+               wpa_printf(MSG_DEBUG, "MLME: WMM aci=%d acm=%d aifs=%d "
+                          "cWmin=%d cWmax=%d burst=%d",
+                          aci, acm, aifs, cw_min, cw_max, burst_time);
+               /* TODO: driver configuration */
        }
-#endif
 }
 
 
@@ -352,7 +339,7 @@ static void ieee80211_send_assoc(struct wpa_supplicant *wpa_s)
        blen = 0;
 
        capab = wpa_s->mlme.capab;
-       if (wpa_s->mlme.phymode == WPA_MODE_IEEE80211G) {
+       if (wpa_s->mlme.phymode == HOSTAPD_MODE_IEEE80211G) {
                capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME |
                        WLAN_CAPABILITY_SHORT_PREAMBLE;
        }
@@ -459,9 +446,9 @@ static void ieee80211_send_assoc(struct wpa_supplicant *wpa_s)
                *pos++ = 0x00; /* Microsoft OUI 00:50:F2 */
                *pos++ = 0x50;
                *pos++ = 0xf2;
-               *pos++ = 2; /* WME */
-               *pos++ = 0; /* WME info */
-               *pos++ = 1; /* WME ver */
+               *pos++ = 2; /* WMM */
+               *pos++ = 0; /* WMM info */
+               *pos++ = 1; /* WMM ver */
                *pos++ = 0;
        }
 
@@ -683,7 +670,7 @@ static void ieee80211_send_probe_req(struct wpa_supplicant *wpa_s,
        supp_rates[0] = WLAN_EID_SUPP_RATES;
        supp_rates[1] = 0;
        for (i = 0; i < wpa_s->mlme.num_curr_rates; i++) {
-               struct wpa_rate_data *rate = &wpa_s->mlme.curr_rates[i];
+               struct hostapd_rate_data *rate = &wpa_s->mlme.curr_rates[i];
                if (esupp_rates) {
                        pos = buf + len;
                        len++;
@@ -890,12 +877,36 @@ static void ieee80211_rx_mgmt_auth(struct wpa_supplicant *wpa_s,
        case WLAN_AUTH_FT:
        {
                union wpa_event_data data;
+               struct wpabuf *ric = NULL;
                os_memset(&data, 0, sizeof(data));
                data.ft_ies.ies = mgmt->u.auth.variable;
                data.ft_ies.ies_len = len -
                        (mgmt->u.auth.variable - (u8 *) mgmt);
                os_memcpy(data.ft_ies.target_ap, wpa_s->bssid, ETH_ALEN);
+               if (os_strcmp(wpa_s->driver->name, "test") == 0 &&
+                   wpa_s->mlme.wmm_enabled) {
+                       ric = wpabuf_alloc(200);
+                       if (ric) {
+                               /* Build simple RIC-Request: RDIE | TSPEC */
+
+                               /* RIC Data (RDIE) */
+                               wpabuf_put_u8(ric, WLAN_EID_RIC_DATA);
+                               wpabuf_put_u8(ric, 4);
+                               wpabuf_put_u8(ric, 0); /* RDIE Identifier */
+                               wpabuf_put_u8(ric, 1); /* Resource Descriptor
+                                                       * Count */
+                               wpabuf_put_le16(ric, 0); /* Status Code */
+
+                               /* WMM TSPEC */
+                               ieee80211_build_tspec(ric);
+
+                               data.ft_ies.ric_ies = wpabuf_head(ric);
+                               data.ft_ies.ric_ies_len = wpabuf_len(ric);
+                       }
+               }
+
                wpa_supplicant_event(wpa_s, EVENT_FT_RESPONSE, &data);
+               wpabuf_free(ric);
                ieee80211_auth_completed(wpa_s);
                break;
        }
@@ -1026,6 +1037,66 @@ static int ieee80211_ft_assoc_resp(struct wpa_supplicant *wpa_s,
 }
 
 
+static void ieee80211_build_tspec(struct wpabuf *buf)
+{
+       struct wmm_tspec_element *tspec;
+       int tid, up;
+
+       tspec = wpabuf_put(buf, sizeof(*tspec));
+       tspec->eid = WLAN_EID_VENDOR_SPECIFIC;
+       tspec->length = sizeof(*tspec) - 2;
+       tspec->oui[0] = 0x00;
+       tspec->oui[1] = 0x50;
+       tspec->oui[2] = 0xf2;
+       tspec->oui_type = 2;
+       tspec->oui_subtype = 2;
+       tspec->version = 1;
+
+       tid = 1;
+       up = 6; /* Voice */
+       tspec->ts_info[0] = (tid << 1) |
+               (WMM_TSPEC_DIRECTION_BI_DIRECTIONAL << 5) |
+               BIT(7);
+       tspec->ts_info[1] = up << 3;
+       tspec->nominal_msdu_size = host_to_le16(1530);
+       tspec->mean_data_rate = host_to_le32(128000); /* bits per second */
+       tspec->minimum_phy_rate = host_to_le32(6000000);
+       tspec->surplus_bandwidth_allowance = host_to_le16(0x3000); /* 150% */
+}
+
+
+static void ieee80211_tx_addts(struct wpa_supplicant *wpa_s)
+{
+       struct wpabuf *buf;
+       struct ieee80211_mgmt *mgmt;
+       size_t alen;
+
+       wpa_printf(MSG_DEBUG, "MLME: Send ADDTS Request for Voice TSPEC");
+       mgmt = NULL;
+       alen = mgmt->u.action.u.wmm_action.variable - (u8 *) mgmt;
+
+       buf = wpabuf_alloc(alen + sizeof(struct wmm_tspec_element));
+       if (buf == NULL)
+               return;
+
+       mgmt = wpabuf_put(buf, alen);
+       os_memcpy(mgmt->da, wpa_s->bssid, ETH_ALEN);
+       os_memcpy(mgmt->sa, wpa_s->own_addr, ETH_ALEN);
+       os_memcpy(mgmt->bssid, wpa_s->bssid, ETH_ALEN);
+       mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
+                                          WLAN_FC_STYPE_ACTION);
+       mgmt->u.action.category = WLAN_ACTION_WMM;
+       mgmt->u.action.u.wmm_action.action_code = WMM_ACTION_CODE_ADDTS_REQ;
+       mgmt->u.action.u.wmm_action.dialog_token = 1;
+       mgmt->u.action.u.wmm_action.status_code = 0;
+
+       ieee80211_build_tspec(buf);
+
+       ieee80211_sta_tx(wpa_s, wpabuf_head(buf), wpabuf_len(buf));
+       wpabuf_free(buf);
+}
+
+
 static void ieee80211_rx_mgmt_assoc_resp(struct wpa_supplicant *wpa_s,
                                         struct ieee80211_mgmt *mgmt,
                                         size_t len,
@@ -1087,9 +1158,10 @@ static void ieee80211_rx_mgmt_assoc_resp(struct wpa_supplicant *wpa_s,
                           status_code);
 #ifdef CONFIG_IEEE80211W
                if (status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY &&
-                   elems.assoc_comeback && elems.assoc_comeback_len == 4) {
+                   elems.timeout_int && elems.timeout_int_len == 5 &&
+                   elems.timeout_int[0] == WLAN_TIMEOUT_ASSOC_COMEBACK) {
                        u32 tu, ms;
-                       tu = WPA_GET_LE32(elems.assoc_comeback);
+                       tu = WPA_GET_LE32(elems.timeout_int + 1);
                        ms = tu * 1024 / 1000;
                        wpa_printf(MSG_DEBUG, "MLME: AP rejected association "
                                   "temporarily; comeback duration %u TU "
@@ -1171,16 +1243,17 @@ static void ieee80211_rx_mgmt_assoc_resp(struct wpa_supplicant *wpa_s,
                           "netstack");
        }
 
-#if 0 /* FIX? */
-       sta->assoc_ap = 1;
-
-       if (elems.wme && wpa_s->mlme.wmm_enabled) {
-               sta->flags |= WLAN_STA_WME;
-               ieee80211_sta_wmm_params(wpa_s, elems.wme, elems.wme_len);
-       }
-#endif
+       if (elems.wmm && wpa_s->mlme.wmm_enabled)
+               ieee80211_sta_wmm_params(wpa_s, elems.wmm, elems.wmm_len);
 
        ieee80211_associated(wpa_s);
+
+       if (wpa_s->mlme.auth_alg != WLAN_AUTH_FT &&
+           os_strcmp(wpa_s->driver->name, "test") == 0 &&
+           elems.wmm && wpa_s->mlme.wmm_enabled) {
+               /* Test WMM-AC - send ADDTS for WMM TSPEC */
+               ieee80211_tx_addts(wpa_s);
+       }
 }
 
 
@@ -1487,18 +1560,18 @@ static void ieee80211_bss_info(struct wpa_supplicant *wpa_s,
                bss->rsn_ie_len = 0;
        }
 
-       if (elems.wme &&
-           (bss->wmm_ie == NULL || bss->wmm_ie_len != elems.wme_len ||
-            os_memcmp(bss->wmm_ie, elems.wme, elems.wme_len))) {
+       if (elems.wmm &&
+           (bss->wmm_ie == NULL || bss->wmm_ie_len != elems.wmm_len ||
+            os_memcmp(bss->wmm_ie, elems.wmm, elems.wmm_len))) {
                os_free(bss->wmm_ie);
-               bss->wmm_ie = os_malloc(elems.wme_len + 2);
+               bss->wmm_ie = os_malloc(elems.wmm_len + 2);
                if (bss->wmm_ie) {
-                       os_memcpy(bss->wmm_ie, elems.wme - 2,
-                                 elems.wme_len + 2);
-                       bss->wmm_ie_len = elems.wme_len + 2;
+                       os_memcpy(bss->wmm_ie, elems.wmm - 2,
+                                 elems.wmm_len + 2);
+                       bss->wmm_ie_len = elems.wmm_len + 2;
                } else
                        bss->wmm_ie_len = 0;
-       } else if (!elems.wme && bss->wmm_ie) {
+       } else if (!elems.wmm && bss->wmm_ie) {
                os_free(bss->wmm_ie);
                bss->wmm_ie = NULL;
                bss->wmm_ie_len = 0;
@@ -1527,8 +1600,8 @@ static void ieee80211_bss_info(struct wpa_supplicant *wpa_s,
        bss->channel = channel;
        bss->freq = wpa_s->mlme.freq;
        if (channel != wpa_s->mlme.channel &&
-           (wpa_s->mlme.phymode == WPA_MODE_IEEE80211G ||
-            wpa_s->mlme.phymode == WPA_MODE_IEEE80211B) &&
+           (wpa_s->mlme.phymode == HOSTAPD_MODE_IEEE80211G ||
+            wpa_s->mlme.phymode == HOSTAPD_MODE_IEEE80211B) &&
            channel >= 1 && channel <= 14) {
                static const int freq_list[] = {
                        2412, 2417, 2422, 2427, 2432, 2437, 2442,
@@ -1594,9 +1667,9 @@ static void ieee80211_rx_mgmt_beacon(struct wpa_supplicant *wpa_s,
                wpa_s->mlme.cts_protect_erp_frames = use_protection;
        }
 
-       if (elems.wme && wpa_s->mlme.wmm_enabled) {
-               ieee80211_sta_wmm_params(wpa_s, elems.wme,
-                                        elems.wme_len);
+       if (elems.wmm && wpa_s->mlme.wmm_enabled) {
+               ieee80211_sta_wmm_params(wpa_s, elems.wmm,
+                                        elems.wmm_len);
        }
 }
 
@@ -1807,6 +1880,119 @@ static void ieee80211_rx_mgmt_sa_query_action(
 #endif /* CONFIG_IEEE80211W */
 
 
+static void dump_tspec(struct wmm_tspec_element *tspec)
+{
+       int up, psb, dir, tid;
+       u16 val;
+
+       up = (tspec->ts_info[1] >> 3) & 0x07;
+       psb = (tspec->ts_info[1] >> 2) & 0x01;
+       dir = (tspec->ts_info[0] >> 5) & 0x03;
+       tid = (tspec->ts_info[0] >> 1) & 0x0f;
+       wpa_printf(MSG_DEBUG, "WMM: TS Info: UP=%d PSB=%d Direction=%d TID=%d",
+                  up, psb, dir, tid);
+       val = le_to_host16(tspec->nominal_msdu_size);
+       wpa_printf(MSG_DEBUG, "WMM: Nominal MSDU Size: %d%s",
+                  val & 0x7fff, val & 0x8000 ? " (fixed)" : "");
+       wpa_printf(MSG_DEBUG, "WMM: Mean Data Rate: %u bps",
+                  le_to_host32(tspec->mean_data_rate));
+       wpa_printf(MSG_DEBUG, "WMM: Minimum PHY Rate: %u bps",
+                  le_to_host32(tspec->minimum_phy_rate));
+       val = le_to_host16(tspec->surplus_bandwidth_allowance);
+       wpa_printf(MSG_DEBUG, "WMM: Surplus Bandwidth Allowance: %u.%04u",
+                  val >> 13, 10000 * (val & 0x1fff) / 0x2000);
+       val = le_to_host16(tspec->medium_time);
+       wpa_printf(MSG_DEBUG, "WMM: Medium Time: %u (= %u usec/sec)",
+                  val, 32 * val);
+}
+
+
+static int is_wmm_tspec(const u8 *ie, size_t len)
+{
+       const struct wmm_tspec_element *tspec;
+
+       if (len < sizeof(*tspec))
+               return 0;
+
+       tspec = (const struct wmm_tspec_element *) ie;
+       if (tspec->eid != WLAN_EID_VENDOR_SPECIFIC ||
+           tspec->length < sizeof(*tspec) - 2 ||
+           tspec->oui[0] != 0x00 || tspec->oui[1] != 0x50 ||
+           tspec->oui[2] != 0xf2 || tspec->oui_type != 2 ||
+           tspec->oui_subtype != 2 || tspec->version != 1)
+               return 0;
+
+       return 1;
+}
+
+
+static void ieee80211_rx_addts_resp(
+       struct wpa_supplicant *wpa_s, struct ieee80211_mgmt *mgmt, size_t len,
+       size_t var_len)
+{
+       struct wmm_tspec_element *tspec;
+
+       wpa_printf(MSG_DEBUG, "WMM: Received ADDTS Response");
+       wpa_hexdump(MSG_MSGDUMP, "WMM: ADDTS Response IE(s)",
+                   mgmt->u.action.u.wmm_action.variable, var_len);
+       if (!is_wmm_tspec(mgmt->u.action.u.wmm_action.variable, var_len))
+               return;
+       tspec = (struct wmm_tspec_element *)
+               mgmt->u.action.u.wmm_action.variable;
+       dump_tspec(tspec);
+}
+
+
+static void ieee80211_rx_delts(
+       struct wpa_supplicant *wpa_s, struct ieee80211_mgmt *mgmt, size_t len,
+       size_t var_len)
+{
+       struct wmm_tspec_element *tspec;
+
+       wpa_printf(MSG_DEBUG, "WMM: Received DELTS");
+       wpa_hexdump(MSG_MSGDUMP, "WMM: DELTS IE(s)",
+                   mgmt->u.action.u.wmm_action.variable, var_len);
+       if (!is_wmm_tspec(mgmt->u.action.u.wmm_action.variable, var_len))
+               return;
+       tspec = (struct wmm_tspec_element *)
+               mgmt->u.action.u.wmm_action.variable;
+       dump_tspec(tspec);
+}
+
+
+static void ieee80211_rx_mgmt_wmm_action(
+       struct wpa_supplicant *wpa_s, struct ieee80211_mgmt *mgmt, size_t len,
+       struct ieee80211_rx_status *rx_status)
+{
+       size_t alen;
+
+       alen = mgmt->u.action.u.wmm_action.variable - (u8 *) mgmt;
+       if (len < alen) {
+               wpa_printf(MSG_DEBUG, "WMM: Received Action frame too short");
+               return;
+       }
+
+       wpa_printf(MSG_DEBUG, "WMM: Received Action frame: Action Code %d, "
+                  "Dialog Token %d, Status Code %d",
+                  mgmt->u.action.u.wmm_action.action_code,
+                  mgmt->u.action.u.wmm_action.dialog_token,
+                  mgmt->u.action.u.wmm_action.status_code);
+
+       switch (mgmt->u.action.u.wmm_action.action_code) {
+       case WMM_ACTION_CODE_ADDTS_RESP:
+               ieee80211_rx_addts_resp(wpa_s, mgmt, len, len - alen);
+               break;
+       case WMM_ACTION_CODE_DELTS:
+               ieee80211_rx_delts(wpa_s, mgmt, len, len - alen);
+               break;
+       default:
+               wpa_printf(MSG_DEBUG, "WMM: Unsupported Action Code %d",
+                          mgmt->u.action.u.wmm_action.action_code);
+               break;
+       }
+}
+
+
 static void ieee80211_rx_mgmt_action(struct wpa_supplicant *wpa_s,
                                     struct ieee80211_mgmt *mgmt,
                                     size_t len,
@@ -1828,6 +2014,9 @@ static void ieee80211_rx_mgmt_action(struct wpa_supplicant *wpa_s,
                ieee80211_rx_mgmt_sa_query_action(wpa_s, mgmt, len, rx_status);
                break;
 #endif /* CONFIG_IEEE80211W */
+       case WLAN_ACTION_WMM:
+               ieee80211_rx_mgmt_wmm_action(wpa_s, mgmt, len, rx_status);
+               break;
        default:
                wpa_printf(MSG_DEBUG, "MLME: unknown Action Category %d",
                           mgmt->u.action.category);
@@ -2503,14 +2692,14 @@ static int ieee80211_active_scan(struct wpa_supplicant *wpa_s)
        int c;
 
        for (m = 0; m < wpa_s->mlme.num_modes; m++) {
-               struct wpa_hw_modes *mode = &wpa_s->mlme.modes[m];
+               struct hostapd_hw_modes *mode = &wpa_s->mlme.modes[m];
                if ((int) mode->mode != (int) wpa_s->mlme.phymode)
                        continue;
                for (c = 0; c < mode->num_channels; c++) {
-                       struct wpa_channel_data *chan = &mode->channels[c];
-                       if (chan->flag & WPA_CHAN_W_SCAN &&
+                       struct hostapd_channel_data *chan = &mode->channels[c];
+                       if (!(chan->flag & HOSTAPD_CHAN_DISABLED) &&
                            chan->chan == wpa_s->mlme.channel) {
-                               if (chan->flag & WPA_CHAN_W_ACTIVE_SCAN)
+                               if (!(chan->flag & HOSTAPD_CHAN_PASSIVE_SCAN))
                                        return 1;
                                break;
                        }
@@ -2524,8 +2713,8 @@ static int ieee80211_active_scan(struct wpa_supplicant *wpa_s)
 static void ieee80211_sta_scan_timer(void *eloop_ctx, void *timeout_ctx)
 {
        struct wpa_supplicant *wpa_s = eloop_ctx;
-       struct wpa_hw_modes *mode;
-       struct wpa_channel_data *chan;
+       struct hostapd_hw_modes *mode;
+       struct hostapd_channel_data *chan;
        int skip = 0;
        int timeout = 0;
        struct wpa_ssid *ssid = wpa_s->current_ssid;
@@ -2564,10 +2753,10 @@ static void ieee80211_sta_scan_timer(void *eloop_ctx, void *timeout_ctx)
                }
                skip = !(wpa_s->mlme.hw_modes & (1 << mode->mode));
                chan = &mode->channels[wpa_s->mlme.scan_channel_idx];
-               if (!(chan->flag & WPA_CHAN_W_SCAN) ||
-                   (adhoc && !(chan->flag & WPA_CHAN_W_IBSS)) ||
-                   (wpa_s->mlme.hw_modes & (1 << WPA_MODE_IEEE80211G) &&
-                    mode->mode == WPA_MODE_IEEE80211B &&
+               if ((chan->flag & HOSTAPD_CHAN_DISABLED) ||
+                   (adhoc && (chan->flag & HOSTAPD_CHAN_NO_IBSS)) ||
+                   (wpa_s->mlme.hw_modes & (1 << HOSTAPD_MODE_IEEE80211G) &&
+                    mode->mode == HOSTAPD_MODE_IEEE80211B &&
                     wpa_s->mlme.scan_skip_11b))
                        skip = 1;
 
@@ -2830,7 +3019,7 @@ void ieee80211_sta_rx(struct wpa_supplicant *wpa_s, const u8 *buf, size_t len,
 }
 
 
-void ieee80211_sta_free_hw_features(struct wpa_hw_modes *hw_features,
+void ieee80211_sta_free_hw_features(struct hostapd_hw_modes *hw_features,
                                    size_t num_hw_features)
 {
        size_t i;
@@ -2861,9 +3050,11 @@ int ieee80211_sta_init(struct wpa_supplicant *wpa_s)
 
        wpa_s->mlme.num_modes = num_modes;
 
-       wpa_s->mlme.hw_modes = 1 << WPA_MODE_IEEE80211A;
-       wpa_s->mlme.hw_modes |= 1 << WPA_MODE_IEEE80211B;
-       wpa_s->mlme.hw_modes |= 1 << WPA_MODE_IEEE80211G;
+       wpa_s->mlme.hw_modes = 1 << HOSTAPD_MODE_IEEE80211A;
+       wpa_s->mlme.hw_modes |= 1 << HOSTAPD_MODE_IEEE80211B;
+       wpa_s->mlme.hw_modes |= 1 << HOSTAPD_MODE_IEEE80211G;
+
+       wpa_s->mlme.wmm_enabled = 1;
 
        return 0;
 }