Disable per-BSSID authentication for RSN IBSS
[wpasupplicant] / wpa_supplicant / mlme.c
index 6cf51aa..964b8c0 100644 (file)
@@ -23,6 +23,7 @@
 #include "wpa.h"
 #include "drivers/driver.h"
 #include "ieee802_11_defs.h"
+#include "ieee802_11_common.h"
 #include "mlme.h"
 
 
@@ -95,169 +96,6 @@ static void ieee80211_sta_timer(void *eloop_ctx, void *timeout_ctx);
 static void ieee80211_sta_scan_timer(void *eloop_ctx, void *timeout_ctx);
 
 
-/* Parsed Information Elements */
-struct ieee802_11_elems {
-       u8 *ssid;
-       u8 ssid_len;
-       u8 *supp_rates;
-       u8 supp_rates_len;
-       u8 *fh_params;
-       u8 fh_params_len;
-       u8 *ds_params;
-       u8 ds_params_len;
-       u8 *cf_params;
-       u8 cf_params_len;
-       u8 *tim;
-       u8 tim_len;
-       u8 *ibss_params;
-       u8 ibss_params_len;
-       u8 *challenge;
-       u8 challenge_len;
-       u8 *wpa;
-       u8 wpa_len;
-       u8 *rsn;
-       u8 rsn_len;
-       u8 *erp_info;
-       u8 erp_info_len;
-       u8 *ext_supp_rates;
-       u8 ext_supp_rates_len;
-       u8 *wmm_info;
-       u8 wmm_info_len;
-       u8 *wmm_param;
-       u8 wmm_param_len;
-       u8 *mdie;
-       u8 mdie_len;
-       u8 *ftie;
-       u8 ftie_len;
-       u8 *assoc_comeback;
-       u8 assoc_comeback_len;
-};
-
-typedef enum { ParseOK = 0, ParseUnknown = 1, ParseFailed = -1 } ParseRes;
-
-
-static ParseRes ieee802_11_parse_elems(u8 *start, size_t len,
-                                      struct ieee802_11_elems *elems)
-{
-       size_t left = len;
-       u8 *pos = start;
-       int unknown = 0;
-
-       os_memset(elems, 0, sizeof(*elems));
-
-       while (left >= 2) {
-               u8 id, elen;
-
-               id = *pos++;
-               elen = *pos++;
-               left -= 2;
-
-               if (elen > left) {
-#if 0
-                       wpa_printf(MSG_MSGDUMP, "MLME: IEEE 802.11 element "
-                                  "parse failed (id=%d elen=%d left=%d)",
-                                  id, elen, left);
-#endif
-                       return ParseFailed;
-               }
-
-               switch (id) {
-               case WLAN_EID_SSID:
-                       elems->ssid = pos;
-                       elems->ssid_len = elen;
-                       break;
-               case WLAN_EID_SUPP_RATES:
-                       elems->supp_rates = pos;
-                       elems->supp_rates_len = elen;
-                       break;
-               case WLAN_EID_FH_PARAMS:
-                       elems->fh_params = pos;
-                       elems->fh_params_len = elen;
-                       break;
-               case WLAN_EID_DS_PARAMS:
-                       elems->ds_params = pos;
-                       elems->ds_params_len = elen;
-                       break;
-               case WLAN_EID_CF_PARAMS:
-                       elems->cf_params = pos;
-                       elems->cf_params_len = elen;
-                       break;
-               case WLAN_EID_TIM:
-                       elems->tim = pos;
-                       elems->tim_len = elen;
-                       break;
-               case WLAN_EID_IBSS_PARAMS:
-                       elems->ibss_params = pos;
-                       elems->ibss_params_len = elen;
-                       break;
-               case WLAN_EID_CHALLENGE:
-                       elems->challenge = pos;
-                       elems->challenge_len = elen;
-                       break;
-               case WLAN_EID_VENDOR_SPECIFIC:
-                       if (elen >= 4 && pos[0] == 0x00 && pos[1] == 0x50 &&
-                           pos[2] == 0xf2) {
-                               /* Microsoft OUI (00:50:F2) */
-                               if (pos[3] == 1) {
-                                       /* OUI Type 1 - WPA IE */
-                                       elems->wpa = pos;
-                                       elems->wpa_len = elen;
-                               } else if (elen >= 5 && pos[3] == 2) {
-                                       if (pos[4] == 0) {
-                                               elems->wmm_info = pos;
-                                               elems->wmm_info_len = elen;
-                                       } else if (pos[4] == 1) {
-                                               elems->wmm_param = pos;
-                                               elems->wmm_param_len = elen;
-                                       }
-                               }
-                       }
-                       break;
-               case WLAN_EID_RSN:
-                       elems->rsn = pos;
-                       elems->rsn_len = elen;
-                       break;
-               case WLAN_EID_ERP_INFO:
-                       elems->erp_info = pos;
-                       elems->erp_info_len = elen;
-                       break;
-               case WLAN_EID_EXT_SUPP_RATES:
-                       elems->ext_supp_rates = pos;
-                       elems->ext_supp_rates_len = elen;
-                       break;
-               case WLAN_EID_MOBILITY_DOMAIN:
-                       elems->mdie = pos;
-                       elems->mdie_len = elen;
-                       break;
-               case WLAN_EID_FAST_BSS_TRANSITION:
-                       elems->ftie = pos;
-                       elems->ftie_len = elen;
-                       break;
-               case WLAN_EID_ASSOC_COMEBACK_TIME:
-                       elems->assoc_comeback = pos;
-                       elems->assoc_comeback_len = elen;
-                       break;
-               default:
-#if 0
-                       wpa_printf(MSG_MSGDUMP "MLME: IEEE 802.11 element "
-                                  "parse ignored unknown element (id=%d "
-                                  "elen=%d)", id, elen);
-#endif
-                       unknown++;
-                       break;
-               }
-
-               left -= elen;
-               pos += elen;
-       }
-
-       if (left)
-               return ParseFailed;
-
-       return unknown ? ParseUnknown : ParseOK;
-}
-
-
 static int ieee80211_sta_set_channel(struct wpa_supplicant *wpa_s,
                                     wpa_hw_mode phymode, int chan,
                                     int freq)
@@ -906,7 +744,7 @@ static void ieee80211_auth_challenge(struct wpa_supplicant *wpa_s,
 
        wpa_printf(MSG_DEBUG, "MLME: replying to auth challenge");
        pos = mgmt->u.auth.variable;
-       if (ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems)
+       if (ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems, 0)
            == ParseFailed) {
                wpa_printf(MSG_DEBUG, "MLME: failed to parse Auth(challenge)");
                return;
@@ -1238,7 +1076,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct wpa_supplicant *wpa_s,
                   capab_info, status_code, aid);
 
        pos = mgmt->u.assoc_resp.variable;
-       if (ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems)
+       if (ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems, 0)
            == ParseFailed) {
                wpa_printf(MSG_DEBUG, "MLME: failed to parse AssocResp");
                return;
@@ -1336,10 +1174,9 @@ static void ieee80211_rx_mgmt_assoc_resp(struct wpa_supplicant *wpa_s,
 #if 0 /* FIX? */
        sta->assoc_ap = 1;
 
-       if (elems.wmm_param && wpa_s->mlme.wmm_enabled) {
+       if (elems.wme && wpa_s->mlme.wmm_enabled) {
                sta->flags |= WLAN_STA_WME;
-               ieee80211_sta_wmm_params(wpa_s, elems.wmm_param,
-                                        elems.wmm_param_len);
+               ieee80211_sta_wmm_params(wpa_s, elems.wme, elems.wme_len);
        }
 #endif
 
@@ -1492,7 +1329,7 @@ static void ieee80211_bss_info(struct wpa_supplicant *wpa_s,
 
        ie_pos = mgmt->u.beacon.variable;
        ie_len = len - baselen;
-       if (ieee802_11_parse_elems(ie_pos, ie_len, &elems) == ParseFailed)
+       if (ieee802_11_parse_elems(ie_pos, ie_len, &elems, 0) == ParseFailed)
                invalid = 1;
 
 #if 0 /* FIX */
@@ -1616,52 +1453,52 @@ static void ieee80211_bss_info(struct wpa_supplicant *wpa_s,
                bss->supp_rates_len += clen;
        }
 
-       if (elems.wpa &&
-           (bss->wpa_ie == NULL || bss->wpa_ie_len != elems.wpa_len ||
-            os_memcmp(bss->wpa_ie, elems.wpa, elems.wpa_len))) {
+       if (elems.wpa_ie &&
+           (bss->wpa_ie == NULL || bss->wpa_ie_len != elems.wpa_ie_len ||
+            os_memcmp(bss->wpa_ie, elems.wpa_ie, elems.wpa_ie_len))) {
                os_free(bss->wpa_ie);
-               bss->wpa_ie = os_malloc(elems.wpa_len + 2);
+               bss->wpa_ie = os_malloc(elems.wpa_ie_len + 2);
                if (bss->wpa_ie) {
-                       os_memcpy(bss->wpa_ie, elems.wpa - 2,
-                                 elems.wpa_len + 2);
-                       bss->wpa_ie_len = elems.wpa_len + 2;
+                       os_memcpy(bss->wpa_ie, elems.wpa_ie - 2,
+                                 elems.wpa_ie_len + 2);
+                       bss->wpa_ie_len = elems.wpa_ie_len + 2;
                } else
                        bss->wpa_ie_len = 0;
-       } else if (!elems.wpa && bss->wpa_ie) {
+       } else if (!elems.wpa_ie && bss->wpa_ie) {
                os_free(bss->wpa_ie);
                bss->wpa_ie = NULL;
                bss->wpa_ie_len = 0;
        }
 
-       if (elems.rsn &&
-           (bss->rsn_ie == NULL || bss->rsn_ie_len != elems.rsn_len ||
-            os_memcmp(bss->rsn_ie, elems.rsn, elems.rsn_len))) {
+       if (elems.rsn_ie &&
+           (bss->rsn_ie == NULL || bss->rsn_ie_len != elems.rsn_ie_len ||
+            os_memcmp(bss->rsn_ie, elems.rsn_ie, elems.rsn_ie_len))) {
                os_free(bss->rsn_ie);
-               bss->rsn_ie = os_malloc(elems.rsn_len + 2);
+               bss->rsn_ie = os_malloc(elems.rsn_ie_len + 2);
                if (bss->rsn_ie) {
-                       os_memcpy(bss->rsn_ie, elems.rsn - 2,
-                                 elems.rsn_len + 2);
-                       bss->rsn_ie_len = elems.rsn_len + 2;
+                       os_memcpy(bss->rsn_ie, elems.rsn_ie - 2,
+                                 elems.rsn_ie_len + 2);
+                       bss->rsn_ie_len = elems.rsn_ie_len + 2;
                } else
                        bss->rsn_ie_len = 0;
-       } else if (!elems.rsn && bss->rsn_ie) {
+       } else if (!elems.rsn_ie && bss->rsn_ie) {
                os_free(bss->rsn_ie);
                bss->rsn_ie = NULL;
                bss->rsn_ie_len = 0;
        }
 
-       if (elems.wmm_param &&
-           (bss->wmm_ie == NULL || bss->wmm_ie_len != elems.wmm_param_len ||
-            os_memcmp(bss->wmm_ie, elems.wmm_param, elems.wmm_param_len))) {
+       if (elems.wme &&
+           (bss->wmm_ie == NULL || bss->wmm_ie_len != elems.wme_len ||
+            os_memcmp(bss->wmm_ie, elems.wme, elems.wme_len))) {
                os_free(bss->wmm_ie);
-               bss->wmm_ie = os_malloc(elems.wmm_param_len + 2);
+               bss->wmm_ie = os_malloc(elems.wme_len + 2);
                if (bss->wmm_ie) {
-                       os_memcpy(bss->wmm_ie, elems.wmm_param - 2,
-                                 elems.wmm_param_len + 2);
-                       bss->wmm_ie_len = elems.wmm_param_len + 2;
+                       os_memcpy(bss->wmm_ie, elems.wme - 2,
+                                 elems.wme_len + 2);
+                       bss->wmm_ie_len = elems.wme_len + 2;
                } else
                        bss->wmm_ie_len = 0;
-       } else if (!elems.wmm_param && bss->wmm_ie) {
+       } else if (!elems.wme && bss->wmm_ie) {
                os_free(bss->wmm_ie);
                bss->wmm_ie = NULL;
                bss->wmm_ie_len = 0;
@@ -1739,7 +1576,7 @@ static void ieee80211_rx_mgmt_beacon(struct wpa_supplicant *wpa_s,
                return;
 
        if (ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen,
-                                  &elems) == ParseFailed)
+                                  &elems, 0) == ParseFailed)
                return;
 
        use_protection = 0;
@@ -1757,9 +1594,9 @@ static void ieee80211_rx_mgmt_beacon(struct wpa_supplicant *wpa_s,
                wpa_s->mlme.cts_protect_erp_frames = use_protection;
        }
 
-       if (elems.wmm_param && wpa_s->mlme.wmm_enabled) {
-               ieee80211_sta_wmm_params(wpa_s, elems.wmm_param,
-                                        elems.wmm_param_len);
+       if (elems.wme && wpa_s->mlme.wmm_enabled) {
+               ieee80211_sta_wmm_params(wpa_s, elems.wme,
+                                        elems.wme_len);
        }
 }
 
@@ -1901,9 +1738,9 @@ static void ieee80211_rx_mgmt_ft_action(struct wpa_supplicant *wpa_s,
 
 #ifdef CONFIG_IEEE80211W
 
-/* MLME-PING.response */
-static int ieee80211_sta_send_ping_resp(struct wpa_supplicant *wpa_s,
-                                       const u8 *addr, const u8 *trans_id)
+/* MLME-SAQuery.response */
+static int ieee80211_sta_send_sa_query_resp(struct wpa_supplicant *wpa_s,
+                                           const u8 *addr, const u8 *trans_id)
 {
        struct ieee80211_mgmt *mgmt;
        int res;
@@ -1912,7 +1749,7 @@ static int ieee80211_sta_send_ping_resp(struct wpa_supplicant *wpa_s,
        mgmt = os_zalloc(sizeof(*mgmt));
        if (mgmt == NULL) {
                wpa_printf(MSG_DEBUG, "MLME: Failed to allocate buffer for "
-                          "ping action frame");
+                          "SA Query action frame");
                return -1;
        }
 
@@ -1922,11 +1759,11 @@ static int ieee80211_sta_send_ping_resp(struct wpa_supplicant *wpa_s,
        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_PING;
-       mgmt->u.action.u.ping_resp.action = WLAN_PING_RESPONSE;
-       os_memcpy(mgmt->u.action.u.ping_resp.trans_id, trans_id,
-                 WLAN_PING_TRANS_ID_LEN);
-       len += 1 + sizeof(mgmt->u.action.u.ping_resp);
+       mgmt->u.action.category = WLAN_ACTION_SA_QUERY;
+       mgmt->u.action.u.sa_query_resp.action = WLAN_SA_QUERY_RESPONSE;
+       os_memcpy(mgmt->u.action.u.sa_query_resp.trans_id, trans_id,
+                 WLAN_SA_QUERY_TR_ID_LEN);
+       len += 1 + sizeof(mgmt->u.action.u.sa_query_resp);
 
        res = ieee80211_sta_tx(wpa_s, (u8 *) mgmt, len);
        os_free(mgmt);
@@ -1935,36 +1772,36 @@ static int ieee80211_sta_send_ping_resp(struct wpa_supplicant *wpa_s,
 }
 
 
-static void ieee80211_rx_mgmt_ping_action(
+static void ieee80211_rx_mgmt_sa_query_action(
        struct wpa_supplicant *wpa_s, struct ieee80211_mgmt *mgmt, size_t len,
        struct ieee80211_rx_status *rx_status)
 {
-       if (len < 24 + 1 + sizeof(mgmt->u.action.u.ping_req)) {
-               wpa_printf(MSG_DEBUG, "MLME: Too short Ping Action frame");
+       if (len < 24 + 1 + sizeof(mgmt->u.action.u.sa_query_req)) {
+               wpa_printf(MSG_DEBUG, "MLME: Too short SA Query Action frame");
                return;
        }
 
-       if (mgmt->u.action.u.ping_req.action != WLAN_PING_REQUEST) {
-               wpa_printf(MSG_DEBUG, "MLME: Unexpected Ping Action %d",
-                          mgmt->u.action.u.ping_req.action);
+       if (mgmt->u.action.u.sa_query_req.action != WLAN_SA_QUERY_REQUEST) {
+               wpa_printf(MSG_DEBUG, "MLME: Unexpected SA Query Action %d",
+                          mgmt->u.action.u.sa_query_req.action);
                return;
        }
 
        if (os_memcmp(mgmt->sa, wpa_s->bssid, ETH_ALEN) != 0) {
-               wpa_printf(MSG_DEBUG, "MLME: Ignore ping from unknown source "
-                          MACSTR, MAC2STR(mgmt->sa));
+               wpa_printf(MSG_DEBUG, "MLME: Ignore SA Query from unknown "
+                          "source " MACSTR, MAC2STR(mgmt->sa));
                return;
        }
 
        if (wpa_s->mlme.state == IEEE80211_ASSOCIATE) {
-               wpa_printf(MSG_DEBUG, "MLME: Ignore ping request during "
+               wpa_printf(MSG_DEBUG, "MLME: Ignore SA query request during "
                           "association process");
                return;
        }
 
-       wpa_printf(MSG_DEBUG, "MLME: Replying to ping request");
-       ieee80211_sta_send_ping_resp(wpa_s, mgmt->sa,
-                                    mgmt->u.action.u.ping_req.trans_id);
+       wpa_printf(MSG_DEBUG, "MLME: Replying to SA Query request");
+       ieee80211_sta_send_sa_query_resp(wpa_s, mgmt->sa, mgmt->u.action.u.
+                                        sa_query_req.trans_id);
 }
 
 #endif /* CONFIG_IEEE80211W */
@@ -1987,8 +1824,8 @@ static void ieee80211_rx_mgmt_action(struct wpa_supplicant *wpa_s,
                break;
 #endif /* CONFIG_IEEE80211R */
 #ifdef CONFIG_IEEE80211W
-       case WLAN_ACTION_PING:
-               ieee80211_rx_mgmt_ping_action(wpa_s, mgmt, len, rx_status);
+       case WLAN_ACTION_SA_QUERY:
+               ieee80211_rx_mgmt_sa_query_action(wpa_s, mgmt, len, rx_status);
                break;
 #endif /* CONFIG_IEEE80211W */
        default:
@@ -3123,8 +2960,8 @@ int ieee80211_sta_send_ft_action(struct wpa_supplicant *wpa_s, u8 action,
        len += 1 + sizeof(mgmt->u.action.u.ft_action_req) + ies_len;
 
        wpa_printf(MSG_DEBUG, "MLME: Send FT Action Frame: Action=%d "
-                  "Target AP=" MACSTR " body_len=%d",
-                  action, MAC2STR(target_ap), ies_len);
+                  "Target AP=" MACSTR " body_len=%lu",
+                  action, MAC2STR(target_ap), (unsigned long) ies_len);
 
        res = ieee80211_sta_tx(wpa_s, buf, len);
        os_free(buf);