WPS: Parse Request Type from WPS IE in (Re)AssocReq and derive mgmt keys
[wpasupplicant] / hostapd / driver_hostap.c
index 04b0b94..ceff099 100644 (file)
@@ -55,6 +55,8 @@ struct hostap_driver_data {
 
        u8 *generic_ie;
        size_t generic_ie_len;
+       u8 *wps_ie;
+       size_t wps_ie_len;
 };
 
 
@@ -770,7 +772,7 @@ static int hostapd_ioctl_set_generic_elem(struct hostap_driver_data *drv)
        int res;
        size_t blen, elem_len;
 
-       elem_len = drv->generic_ie_len;
+       elem_len = drv->generic_ie_len + drv->wps_ie_len;
        blen = PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN + elem_len;
        if (blen < sizeof(*param))
                blen = sizeof(*param);
@@ -785,6 +787,10 @@ static int hostapd_ioctl_set_generic_elem(struct hostap_driver_data *drv)
                os_memcpy(param->u.generic_elem.data, drv->generic_ie,
                          drv->generic_ie_len);
        }
+       if (drv->wps_ie) {
+               os_memcpy(&param->u.generic_elem.data[drv->generic_ie_len],
+                         drv->wps_ie, drv->wps_ie_len);
+       }
        wpa_hexdump(MSG_DEBUG, "hostap: Set generic IE",
                    param->u.generic_elem.data, elem_len);
        res = hostapd_ioctl(drv, param, blen);
@@ -815,6 +821,36 @@ static int hostap_set_generic_elem(const char *ifname, void *priv,
 }
 
 
+static int hostap_set_wps_beacon_ie(const char *ifname, void *priv,
+                                   const u8 *ie, size_t len)
+{
+       /* Host AP driver supports only one set of extra IEs, so we need to
+        * use the ProbeResp IEs also for Beacon frames since they include more
+        * information. */
+       return 0;
+}
+
+
+static int hostap_set_wps_probe_resp_ie(const char *ifname, void *priv,
+                                       const u8 *ie, size_t len)
+{
+       struct hostap_driver_data *drv = priv;
+
+       os_free(drv->wps_ie);
+       drv->wps_ie = NULL;
+       drv->wps_ie_len = 0;
+       if (ie) {
+               drv->wps_ie = os_malloc(len);
+               if (drv->wps_ie == NULL)
+                       return -1;
+               os_memcpy(drv->wps_ie, ie, len);
+               drv->wps_ie_len = len;
+       }
+
+       return hostapd_ioctl_set_generic_elem(drv);
+}
+
+
 static void
 hostapd_wireless_event_wireless_custom(struct hostap_driver_data *drv,
                                       char *custom)
@@ -1120,6 +1156,7 @@ static void hostap_driver_deinit(void *priv)
                close(drv->sock);
 
        os_free(drv->generic_ie);
+       os_free(drv->wps_ie);
 
        free(drv);
 }
@@ -1237,4 +1274,6 @@ const struct wpa_driver_ops wpa_driver_hostap_ops = {
        .get_inact_sec = hostap_get_inact_sec,
        .sta_clear_stats = hostap_sta_clear_stats,
        .get_hw_feature_data = hostap_get_hw_feature_data,
+       .set_wps_beacon_ie = hostap_set_wps_beacon_ie,
+       .set_wps_probe_resp_ie = hostap_set_wps_probe_resp_ie,
 };