Interworking: Add support for QoS Mapping functionality for the STA
authorJouni Malinen <jouni@qca.qualcomm.com>
Wed, 24 Jul 2013 10:17:56 +0000 (13:17 +0300)
committerJouni Malinen <j@w1.fi>
Fri, 18 Oct 2013 11:13:45 +0000 (14:13 +0300)
Indicate support for QoS Mapping and configure driver to update the QoS
Map if QoS Map Set elements is received from the AP either in
(Re)Association Response or QoS Map Configure frame.

This commit adds support for receiving the frames with nl80211 drivers,
but the actual QoS Map configuration command is still missing.

Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>

src/common/ieee802_11_common.c
src/common/ieee802_11_common.h
src/drivers/driver_nl80211.c
wpa_supplicant/driver_i.h
wpa_supplicant/events.c
wpa_supplicant/wpa_supplicant.c

index aab8ac6..304dfc6 100644 (file)
@@ -276,6 +276,12 @@ ParseRes ieee802_11_parse_elems(const u8 *start, size_t len,
                        elems->interworking = pos;
                        elems->interworking_len = elen;
                        break;
+               case WLAN_EID_QOS_MAP_SET:
+                       if (elen < 16)
+                               break;
+                       elems->qos_map_set = pos;
+                       elems->qos_map_set_len = elen;
+                       break;
                case WLAN_EID_EXT_CAPAB:
                        elems->ext_capab = pos;
                        elems->ext_capab_len = elen;
index 68c6b96..c4618b2 100644 (file)
@@ -40,6 +40,7 @@ struct ieee802_11_elems {
        const u8 *wfd;
        const u8 *link_id;
        const u8 *interworking;
+       const u8 *qos_map_set;
        const u8 *hs20;
        const u8 *ext_capab;
        const u8 *bss_max_idle_period;
@@ -73,6 +74,7 @@ struct ieee802_11_elems {
        u8 p2p_len;
        u8 wfd_len;
        u8 interworking_len;
+       u8 qos_map_set_len;
        u8 hs20_len;
        u8 ext_capab_len;
        u8 ssid_list_len;
index 8688ea1..80673fa 100644 (file)
@@ -3805,6 +3805,11 @@ static int nl80211_mgmt_subscribe_non_ap(struct i802_bss *bss)
        wpa_printf(MSG_DEBUG, "nl80211: Subscribe to mgmt frames with non-AP "
                   "handle %p", bss->nl_mgmt);
 
+#ifdef CONFIG_INTERWORKING
+       /* QoS Map Configure */
+       if (nl80211_register_action_frame(bss, (u8 *) "\x01\x04", 2) < 0)
+               return -1;
+#endif /* CONFIG_INTERWORKING */
 #if defined(CONFIG_P2P) || defined(CONFIG_INTERWORKING)
        /* GAS Initial Request */
        if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0a", 2) < 0)
index 461b472..c391680 100644 (file)
@@ -708,4 +708,13 @@ static inline int wpa_drv_status(struct wpa_supplicant *wpa_s,
        return wpa_s->driver->status(wpa_s->drv_priv, buf, buflen);
 }
 
+static inline int wpa_drv_set_qos_map(struct wpa_supplicant *wpa_s,
+                                     const u8 *qos_map_set, u8 qos_map_set_len)
+{
+       if (!wpa_s->driver->set_qos_map)
+               return -1;
+       return wpa_s->driver->set_qos_map(wpa_s->drv_priv, qos_map_set,
+                                         qos_map_set_len);
+}
+
 #endif /* DRIVER_I_H */
index 8284b4f..9c77ade 100644 (file)
@@ -1503,6 +1503,43 @@ void wnm_bss_keep_alive_deinit(struct wpa_supplicant *wpa_s)
 }
 
 
+#ifdef CONFIG_INTERWORKING
+
+static int wpas_qos_map_set(struct wpa_supplicant *wpa_s, const u8 *qos_map,
+                           size_t len)
+{
+       int res;
+
+       wpa_hexdump(MSG_DEBUG, "Interworking: QoS Map Set", qos_map, len);
+       res = wpa_drv_set_qos_map(wpa_s, qos_map, len);
+       if (res) {
+               wpa_printf(MSG_DEBUG, "Interworking: Failed to configure QoS Map Set to the driver");
+       }
+
+       return res;
+}
+
+
+static void interworking_process_assoc_resp(struct wpa_supplicant *wpa_s,
+                                           const u8 *ies, size_t ies_len)
+{
+       struct ieee802_11_elems elems;
+
+       if (ies == NULL)
+               return;
+
+       if (ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed)
+               return;
+
+       if (elems.qos_map_set) {
+               wpas_qos_map_set(wpa_s, elems.qos_map_set,
+                                elems.qos_map_set_len);
+       }
+}
+
+#endif /* CONFIG_INTERWORKING */
+
+
 static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s,
                                          union wpa_event_data *data)
 {
@@ -1527,6 +1564,10 @@ static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s,
                wnm_process_assoc_resp(wpa_s, data->assoc_info.resp_ies,
                                       data->assoc_info.resp_ies_len);
 #endif /* CONFIG_WNM */
+#ifdef CONFIG_INTERWORKING
+               interworking_process_assoc_resp(wpa_s, data->assoc_info.resp_ies,
+                                               data->assoc_info.resp_ies_len);
+#endif /* CONFIG_INTERWORKING */
        }
        if (data->assoc_info.beacon_ies)
                wpa_hexdump(MSG_DEBUG, "beacon_ies",
@@ -2906,6 +2947,19 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
                        break;
                }
 #endif /* CONFIG_TDLS */
+#ifdef CONFIG_INTERWORKING
+               if (data->rx_action.category == WLAN_ACTION_QOS &&
+                   data->rx_action.len >= 1 &&
+                   data->rx_action.data[0] == QOS_QOS_MAP_CONFIG) {
+                       wpa_dbg(wpa_s, MSG_DEBUG, "Interworking: Received QoS Map Configure frame from "
+                               MACSTR, MAC2STR(data->rx_action.sa));
+                       if (os_memcmp(data->rx_action.sa, wpa_s->bssid, ETH_ALEN)
+                           == 0)
+                               wpas_qos_map_set(wpa_s, data->rx_action.data + 1,
+                                                data->rx_action.len - 1);
+                       break;
+               }
+#endif /* CONFIG_INTERWORKING */
 #ifdef CONFIG_P2P
                wpas_p2p_rx_action(wpa_s, data->rx_action.da,
                                   data->rx_action.sa,
index 99e48eb..06ba2c7 100644 (file)
@@ -1219,6 +1219,9 @@ static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
 #endif /* CONFIG_INTERWORKING */
                break;
        case 4: /* Bits 32-39 */
+#ifdef CONFIG_INTERWORKING
+               *pos |= 0x01; /* Bit 32 - QoS Map */
+#endif /* CONFIG_INTERWORKING */
                break;
        case 5: /* Bits 40-47 */
                break;