P2P: Extend P2P manager functionality to work with driver MLME
[libeap.git] / src / ap / ap_drv_ops.c
index b7298dc..3fd2761 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
 
 #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"
 #include "ap_config.h"
+#include "p2p_hostapd.h"
 #include "ap_drv_ops.h"
 
 
@@ -38,14 +41,119 @@ 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_P2P_MANAGER
+       if (hapd->conf->p2p & P2P_MANAGE) {
+               struct wpabuf *a;
+
+               a = wpabuf_alloc(100 + (beacon ? wpabuf_len(beacon) : 0));
+               if (a) {
+                       u8 *start, *p;
+                       if (beacon)
+                               wpabuf_put_buf(a, beacon);
+                       if (beacon != hapd->wps_beacon_ie)
+                               wpabuf_free(beacon);
+                       start = wpabuf_put(a, 0);
+                       p = hostapd_eid_p2p_manage(hapd, start);
+                       wpabuf_put(a, p - start);
+                       beacon = a;
+               }
+
+               a = wpabuf_alloc(100 + (proberesp ? wpabuf_len(proberesp) :
+                                       0));
+               if (a) {
+                       u8 *start, *p;
+                       if (proberesp)
+                               wpabuf_put_buf(a, proberesp);
+                       if (proberesp != hapd->wps_probe_resp_ie)
+                               wpabuf_free(proberesp);
+                       start = wpabuf_put(a, 0);
+                       p = hostapd_eid_p2p_manage(hapd, start);
+                       wpabuf_put(a, p - start);
+                       proberesp = a;
+               }
+       }
+#endif /* CONFIG_P2P_MANAGER */
+
+#ifdef CONFIG_WPS2
+       if (hapd->conf->wps_state)
+               assocresp = wps_build_assoc_resp_ie();
+#endif /* CONFIG_WPS2 */
+
+#ifdef CONFIG_P2P_MANAGER
+       if (hapd->conf->p2p & P2P_MANAGE) {
+               struct wpabuf *a;
+               a = wpabuf_alloc(100 + (assocresp ? wpabuf_len(assocresp) :
+                                       0));
+               if (a) {
+                       u8 *start, *p;
+                       start = wpabuf_put(a, 0);
+                       p = hostapd_eid_p2p_manage(hapd, start);
+                       wpabuf_put(a, p - start);
+                       if (assocresp) {
+                               wpabuf_put_buf(a, assocresp);
+                               wpabuf_free(assocresp);
+                       }
+                       assocresp = a;
+               }
+       }
+#endif /* CONFIG_P2P_MANAGER */
+
+       ret = hapd->driver->set_ap_wps_ie(hapd->drv_priv, beacon, proberesp,
+                                         assocresp);
+
+       if (beacon != hapd->wps_beacon_ie)
+               wpabuf_free(beacon);
+       if (proberesp != hapd->wps_probe_resp_ie)
+               wpabuf_free(proberesp);
+       wpabuf_free(assocresp);
+
+       return ret;
 }
 
 
@@ -122,7 +230,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;
@@ -186,8 +295,7 @@ static int hostapd_set_bss_params(struct hostapd_data *hapd,
        ht_oper = pos;
        pos = hostapd_eid_ht_operation(hapd, pos);
        if (pos > ht_oper && ht_oper > ht_capab &&
-           hostapd_set_ht_params(hapd->conf->iface, hapd,
-                                 ht_capab + 2, ht_capab[1],
+           hostapd_set_ht_params(hapd, ht_capab + 2, ht_capab[1],
                                  ht_oper + 2, ht_oper[1])) {
                wpa_printf(MSG_ERROR, "Could not set HT capabilities "
                           "for kernel driver");
@@ -242,7 +350,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,
@@ -299,7 +410,7 @@ static int hostapd_sta_disassoc(struct hostapd_data *hapd, const u8 *addr,
 }
 
 
-static int hostapd_sta_add(const char *ifname, struct hostapd_data *hapd,
+static int hostapd_sta_add(struct hostapd_data *hapd,
                           const u8 *addr, u16 aid, u16 capability,
                           const u8 *supp_rates, size_t supp_rates_len,
                           u16 listen_interval,
@@ -320,7 +431,7 @@ static int hostapd_sta_add(const char *ifname, struct hostapd_data *hapd,
        params.supp_rates_len = supp_rates_len;
        params.listen_interval = listen_interval;
        params.ht_capabilities = ht_capab;
-       return hapd->driver->sta_add(ifname, hapd->drv_priv, &params);
+       return hapd->driver->sta_add(hapd->drv_priv, &params);
 }
 
 
@@ -373,8 +484,7 @@ int hostapd_set_privacy(struct hostapd_data *hapd, int enabled)
 {
        if (hapd->driver == NULL || hapd->driver->set_privacy == NULL)
                return 0;
-       return hapd->driver->set_privacy(hapd->conf->iface, hapd->drv_priv,
-                                        enabled);
+       return hapd->driver->set_privacy(hapd->drv_priv, enabled);
 }
 
 
@@ -383,8 +493,7 @@ int hostapd_set_generic_elem(struct hostapd_data *hapd, const u8 *elem,
 {
        if (hapd->driver == NULL || hapd->driver->set_generic_elem == NULL)
                return 0;
-       return hapd->driver->set_generic_elem(hapd->conf->iface,
-                                             hapd->drv_priv, elem, elem_len);
+       return hapd->driver->set_generic_elem(hapd->drv_priv, elem, elem_len);
 }
 
 
@@ -392,8 +501,7 @@ int hostapd_get_ssid(struct hostapd_data *hapd, u8 *buf, size_t len)
 {
        if (hapd->driver == NULL || hapd->driver->hapd_get_ssid == NULL)
                return 0;
-       return hapd->driver->hapd_get_ssid(hapd->conf->iface, hapd->drv_priv,
-                                          buf, len);
+       return hapd->driver->hapd_get_ssid(hapd->drv_priv, buf, len);
 }
 
 
@@ -401,19 +509,18 @@ int hostapd_set_ssid(struct hostapd_data *hapd, const u8 *buf, size_t len)
 {
        if (hapd->driver == NULL || hapd->driver->hapd_set_ssid == NULL)
                return 0;
-       return hapd->driver->hapd_set_ssid(hapd->conf->iface, hapd->drv_priv,
-                                          buf, len);
+       return hapd->driver->hapd_set_ssid(hapd->drv_priv, buf, 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->conf->iface, hapd->drv_priv, type,
-                                   ifname, addr, bss_ctx, drv_priv);
+       return hapd->driver->if_add(hapd->drv_priv, type, ifname, addr,
+                                   bss_ctx, drv_priv, force_ifname, if_addr);
 }
 
 
@@ -491,7 +598,7 @@ int hostapd_sta_set_flags(struct hostapd_data *hapd, u8 *addr,
 {
        if (hapd->driver == NULL || hapd->driver->sta_set_flags == NULL)
                return 0;
-       return hapd->driver->sta_set_flags(hapd->conf->iface, hapd->drv_priv, addr, total_flags,
+       return hapd->driver->sta_set_flags(hapd->drv_priv, addr, total_flags,
                                           flags_or, flags_and);
 }
 
@@ -578,16 +685,16 @@ int hostapd_driver_commit(struct hostapd_data *hapd)
 }
 
 
-int hostapd_set_ht_params(const char *ifname, struct hostapd_data *hapd,
+int hostapd_set_ht_params(struct hostapd_data *hapd,
                          const u8 *ht_capab, size_t ht_capab_len,
                          const u8 *ht_oper, size_t ht_oper_len)
 {
        if (hapd->driver == NULL || hapd->driver->set_ht_params == NULL ||
            ht_capab == NULL || ht_oper == NULL)
                return 0;
-       return hapd->driver->set_ht_params(
-               ifname, hapd->drv_priv, ht_capab, ht_capab_len,
-               ht_oper, ht_oper_len);
+       return hapd->driver->set_ht_params(hapd->drv_priv,
+                                          ht_capab, ht_capab_len,
+                                          ht_oper, ht_oper_len);
 }
 
 
@@ -613,3 +720,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;
+}