WPS 2.0: Provide (Re)Association Response WPS IE to driver
[libeap.git] / src / ap / ap_drv_ops.c
index d79c698..5aed879 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * hostapd - Driver operations
- * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2009-2010, Jouni Malinen <j@w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -16,6 +16,8 @@
 
 #include "utils/common.h"
 #include "drivers/driver.h"
+#include "common/ieee802_11_defs.h"
+#include "wps/wps.h"
 #include "hostapd.h"
 #include "ieee802_11.h"
 #include "sta_info.h"
@@ -38,14 +40,67 @@ static int hostapd_sta_flags_to_drv(int flags)
 }
 
 
-static int hostapd_set_ap_wps_ie(struct hostapd_data *hapd,
-                                const struct wpabuf *beacon,
-                                const struct wpabuf *proberesp)
+static int hostapd_set_ap_wps_ie(struct hostapd_data *hapd)
 {
+       struct wpabuf *beacon, *proberesp, *assocresp = NULL;
+       int ret;
+
        if (hapd->driver == NULL || hapd->driver->set_ap_wps_ie == NULL)
                return 0;
-       return hapd->driver->set_ap_wps_ie(hapd->conf->iface, hapd->drv_priv,
-                                          beacon, proberesp);
+
+       beacon = hapd->wps_beacon_ie;
+       proberesp = hapd->wps_probe_resp_ie;
+
+#ifdef CONFIG_P2P
+       if (hapd->wps_beacon_ie == NULL && hapd->p2p_beacon_ie == NULL)
+               beacon = NULL;
+       else {
+               beacon = wpabuf_alloc((hapd->wps_beacon_ie ?
+                                      wpabuf_len(hapd->wps_beacon_ie) : 0) +
+                                     (hapd->p2p_beacon_ie ?
+                                      wpabuf_len(hapd->p2p_beacon_ie) : 0));
+               if (beacon == NULL)
+                       return -1;
+               if (hapd->wps_beacon_ie)
+                       wpabuf_put_buf(beacon, hapd->wps_beacon_ie);
+               if (hapd->p2p_beacon_ie)
+                       wpabuf_put_buf(beacon, hapd->p2p_beacon_ie);
+       }
+
+       if (hapd->wps_probe_resp_ie == NULL && hapd->p2p_probe_resp_ie == NULL)
+               proberesp = NULL;
+       else {
+               proberesp = wpabuf_alloc(
+                       (hapd->wps_probe_resp_ie ?
+                        wpabuf_len(hapd->wps_probe_resp_ie) : 0) +
+                       (hapd->p2p_probe_resp_ie ?
+                        wpabuf_len(hapd->p2p_probe_resp_ie) : 0));
+               if (proberesp == NULL) {
+                       wpabuf_free(beacon);
+                       return -1;
+               }
+               if (hapd->wps_probe_resp_ie)
+                       wpabuf_put_buf(proberesp, hapd->wps_probe_resp_ie);
+               if (hapd->p2p_probe_resp_ie)
+                       wpabuf_put_buf(proberesp, hapd->p2p_probe_resp_ie);
+       }
+#endif /* CONFIG_P2P */
+
+#ifdef CONFIG_WPS2
+       if (hapd->conf->wps_state)
+               assocresp = wps_build_assoc_resp_ie();
+#endif /* CONFIG_WPS2 */
+
+       ret = hapd->driver->set_ap_wps_ie(hapd->drv_priv, beacon, proberesp,
+                                         assocresp);
+
+#ifdef CONFIG_P2P
+       wpabuf_free(beacon);
+       wpabuf_free(proberesp);
+#endif /* CONFIG_P2P */
+       wpabuf_free(assocresp);
+
+       return ret;
 }
 
 
@@ -122,7 +177,8 @@ static int hostapd_set_sta_flags(struct hostapd_data *hapd,
        int set_flags, total_flags, flags_and, flags_or;
        total_flags = hostapd_sta_flags_to_drv(sta->flags);
        set_flags = WPA_STA_SHORT_PREAMBLE | WPA_STA_WMM | WPA_STA_MFP;
-       if (!hapd->conf->ieee802_1x && !hapd->conf->wpa &&
+       if (((!hapd->conf->ieee802_1x && !hapd->conf->wpa) ||
+            sta->auth_alg == WLAN_AUTH_FT) &&
            sta->flags & WLAN_STA_AUTHORIZED)
                set_flags |= WPA_STA_AUTHORIZED;
        flags_or = total_flags & set_flags;
@@ -241,7 +297,10 @@ static int hostapd_set_beacon(struct hostapd_data *hapd,
 
 static int hostapd_vlan_if_add(struct hostapd_data *hapd, const char *ifname)
 {
-       return hostapd_if_add(hapd, WPA_IF_AP_VLAN, ifname, NULL, NULL, NULL);
+       char force_ifname[IFNAMSIZ];
+       u8 if_addr[ETH_ALEN];
+       return hostapd_if_add(hapd, WPA_IF_AP_VLAN, ifname, NULL, NULL, NULL,
+                             force_ifname, if_addr);
 }
 
 static int hostapd_vlan_if_remove(struct hostapd_data *hapd,
@@ -403,12 +462,12 @@ int hostapd_set_ssid(struct hostapd_data *hapd, const u8 *buf, size_t len)
 
 int hostapd_if_add(struct hostapd_data *hapd, enum wpa_driver_if_type type,
                   const char *ifname, const u8 *addr, void *bss_ctx,
-                  void **drv_priv)
+                  void **drv_priv, char *force_ifname, u8 *if_addr)
 {
        if (hapd->driver == NULL || hapd->driver->if_add == NULL)
                return -1;
        return hapd->driver->if_add(hapd->drv_priv, type, ifname, addr,
-                                   bss_ctx, drv_priv);
+                                   bss_ctx, drv_priv, force_ifname, if_addr);
 }
 
 
@@ -608,3 +667,13 @@ struct wpa_scan_results * hostapd_driver_get_scan_results(
                return hapd->driver->get_scan_results2(hapd->drv_priv);
        return NULL;
 }
+
+
+int hostapd_driver_set_noa(struct hostapd_data *hapd, u8 count, int start,
+                          int duration)
+{
+       if (hapd->driver && hapd->driver->set_noa)
+               return hapd->driver->set_noa(hapd->drv_priv, count, start,
+                                            duration);
+       return -1;
+}