P2P: Set Device Password ID in WPS M1/M2 per new rules
[libeap.git] / wpa_supplicant / ap.c
index e2be10c..3087542 100644 (file)
@@ -22,6 +22,7 @@
 #ifdef NEED_AP_MLME
 #include "ap/ieee802_11.h"
 #endif /* NEED_AP_MLME */
+#include "ap/beacon.h"
 #include "ap/ieee802_1x.h"
 #include "ap/wps_hostapd.h"
 #include "ap/ctrl_iface_ap.h"
 #include "eap_server/eap_methods.h"
 #include "eap_common/eap_wsc_common.h"
 #include "wps/wps.h"
+#include "common/ieee802_11_defs.h"
 #include "config_ssid.h"
 #include "config.h"
 #include "wpa_supplicant_i.h"
 #include "driver_i.h"
+#include "p2p_supplicant.h"
 #include "ap.h"
 
 
@@ -67,6 +70,34 @@ static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s,
        /* TODO: enable HT if driver supports it;
         * drop to 11b if driver does not support 11g */
 
+#ifdef CONFIG_P2P
+       if (conf->hw_mode == HOSTAPD_MODE_IEEE80211G) {
+               /* Remove 802.11b rates from supported and basic rate sets */
+               int *list = os_malloc(4 * sizeof(int));
+               if (list) {
+                       list[0] = 60;
+                       list[1] = 120;
+                       list[2] = 240;
+                       list[3] = -1;
+               }
+               conf->basic_rates = list;
+
+               list = os_malloc(9 * sizeof(int));
+               if (list) {
+                       list[0] = 60;
+                       list[1] = 90;
+                       list[2] = 120;
+                       list[3] = 180;
+                       list[4] = 240;
+                       list[5] = 360;
+                       list[6] = 480;
+                       list[7] = 540;
+                       list[8] = -1;
+               }
+               conf->supported_rates = list;
+       }
+#endif /* CONFIG_P2P */
+
        if (ssid->ssid_len == 0) {
                wpa_printf(MSG_ERROR, "No SSID configured for AP mode");
                return -1;
@@ -131,25 +162,75 @@ static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s,
                bss->device_type = os_strdup(wpa_s->conf->device_type);
 #endif /* CONFIG_WPS */
 
+#ifdef CONFIG_P2P
+       if (wpa_s->conf->device_name) {
+               bss->device_name = os_strdup(wpa_s->conf->device_name);
+               bss->friendly_name = os_strdup(wpa_s->conf->device_name);
+       }
+#endif /* CONFIG_P2P */
+
        return 0;
 }
 
 
 static void ap_public_action_rx(void *ctx, const u8 *buf, size_t len, int freq)
 {
+#ifdef CONFIG_P2P
+       struct wpa_supplicant *wpa_s = ctx;
+       const struct ieee80211_mgmt *mgmt;
+       size_t hdr_len;
+
+       mgmt = (const struct ieee80211_mgmt *) buf;
+       hdr_len = (const u8 *) &mgmt->u.action.u.vs_public_action.action - buf;
+       if (hdr_len > len)
+               return;
+       wpas_p2p_rx_action(wpa_s, mgmt->da, mgmt->sa, mgmt->bssid,
+                          mgmt->u.action.category,
+                          &mgmt->u.action.u.vs_public_action.action,
+                          len - hdr_len, freq);
+#endif /* CONFIG_P2P */
+}
+
+
+static int ap_vendor_action_rx(void *ctx, const u8 *buf, size_t len, int freq)
+{
+#ifdef CONFIG_P2P
+       struct wpa_supplicant *wpa_s = ctx;
+       const struct ieee80211_mgmt *mgmt;
+       size_t hdr_len;
+
+       mgmt = (const struct ieee80211_mgmt *) buf;
+       hdr_len = (const u8 *) &mgmt->u.action.u.vs_public_action.action - buf;
+       if (hdr_len > len)
+               return -1;
+       wpas_p2p_rx_action(wpa_s, mgmt->da, mgmt->sa, mgmt->bssid,
+                          mgmt->u.action.category,
+                          &mgmt->u.action.u.vs_public_action.action,
+                          len - hdr_len, freq);
+#endif /* CONFIG_P2P */
+       return 0;
 }
 
 
 static int ap_probe_req_rx(void *ctx, const u8 *addr, const u8 *ie,
                           size_t ie_len)
 {
+#ifdef CONFIG_P2P
+       struct wpa_supplicant *wpa_s = ctx;
+       return wpas_p2p_probe_req_rx(wpa_s, addr, ie, ie_len);
+#else /* CONFIG_P2P */
        return 0;
+#endif /* CONFIG_P2P */
 }
 
 
 static void ap_wps_reg_success_cb(void *ctx, const u8 *mac_addr,
                                  const u8 *uuid_e)
 {
+#ifdef CONFIG_P2P
+       struct wpa_supplicant *wpa_s = ctx;
+       wpas_p2p_wps_success(wpa_s, mac_addr, 1);
+#endif /* CONFIG_P2P */
 }
 
 
@@ -182,6 +263,8 @@ int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s,
                params.mode = IEEE80211_MODE_IBSS;
                break;
        case WPAS_MODE_AP:
+       case WPAS_MODE_P2P_GO:
+       case WPAS_MODE_P2P_GROUP_FORMATION:
                params.mode = IEEE80211_MODE_AP;
                break;
        }
@@ -207,6 +290,12 @@ int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s,
        params.pairwise_suite = cipher_suite2driver(wpa_s->pairwise_cipher);
        params.group_suite = params.pairwise_suite;
 
+#ifdef CONFIG_P2P
+       if (ssid->mode == WPAS_MODE_P2P_GO ||
+           ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
+               params.p2p = 1;
+#endif /* CONFIG_P2P */
+
        if (wpa_drv_associate(wpa_s, &params) < 0) {
                wpa_msg(wpa_s, MSG_INFO, "Failed to start AP functionality");
                return -1;
@@ -229,6 +318,14 @@ int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s,
                return -1;
        }
 
+#ifdef CONFIG_P2P
+       if (ssid->mode == WPAS_MODE_P2P_GO)
+               conf->bss[0].p2p = P2P_ENABLED | P2P_GROUP_OWNER;
+       else if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
+               conf->bss[0].p2p = P2P_ENABLED | P2P_GROUP_OWNER |
+                       P2P_GROUP_FORMATION;
+#endif /* CONFIG_P2P */
+
        hapd_iface->num_bss = conf->num_bss;
        hapd_iface->bss = os_zalloc(conf->num_bss *
                                    sizeof(struct hostapd_data *));
@@ -249,10 +346,18 @@ int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s,
                hapd_iface->bss[i]->msg_ctx = wpa_s;
                hapd_iface->bss[i]->public_action_cb = ap_public_action_rx;
                hapd_iface->bss[i]->public_action_cb_ctx = wpa_s;
+               hapd_iface->bss[i]->vendor_action_cb = ap_vendor_action_rx;
+               hapd_iface->bss[i]->vendor_action_cb_ctx = wpa_s;
                hostapd_register_probereq_cb(hapd_iface->bss[i],
                                             ap_probe_req_rx, wpa_s);
                hapd_iface->bss[i]->wps_reg_success_cb = ap_wps_reg_success_cb;
                hapd_iface->bss[i]->wps_reg_success_cb_ctx = wpa_s;
+#ifdef CONFIG_P2P
+               hapd_iface->bss[i]->p2p = wpa_s->global->p2p;
+               hapd_iface->bss[i]->p2p_group = wpas_p2p_group_init(
+                       wpa_s, ssid->p2p_persistent_group,
+                       ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION);
+#endif /* CONFIG_P2P */
        }
 
        os_memcpy(hapd_iface->bss[0]->own_addr, wpa_s->own_addr, ETH_ALEN);
@@ -283,6 +388,10 @@ void wpa_supplicant_ap_deinit(struct wpa_supplicant *wpa_s)
                return;
 
        wpa_s->current_ssid = NULL;
+#ifdef CONFIG_P2P
+       wpa_s->ap_iface->bss[0]->p2p_group = NULL;
+       wpas_p2p_group_deinit(wpa_s);
+#endif /* CONFIG_P2P */
        hostapd_interface_deinit(wpa_s->ap_iface);
        hostapd_interface_free(wpa_s->ap_iface);
        wpa_s->ap_iface = NULL;
@@ -441,6 +550,31 @@ int ap_ctrl_iface_wpa_get_status(struct wpa_supplicant *wpa_s, char *buf,
 #endif /* CONFIG_CTRL_IFACE */
 
 
+int wpa_supplicant_ap_update_beacon(struct wpa_supplicant *wpa_s)
+{
+       struct hostapd_iface *iface = wpa_s->ap_iface;
+       struct wpa_ssid *ssid = wpa_s->current_ssid;
+       struct hostapd_data *hapd;
+
+       if (ssid == NULL || wpa_s->ap_iface == NULL)
+               return -1;
+
+#ifdef CONFIG_P2P
+       if (ssid->mode == WPAS_MODE_P2P_GO)
+               iface->conf->bss[0].p2p = P2P_ENABLED | P2P_GROUP_OWNER;
+       else if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
+               iface->conf->bss[0].p2p = P2P_ENABLED | P2P_GROUP_OWNER |
+                       P2P_GROUP_FORMATION;
+#endif /* CONFIG_P2P */
+
+       ieee802_11_set_beacons(iface);
+       hapd = iface->bss[0];
+       hapd->drv.set_ap_wps_ie(hapd);
+
+       return 0;
+}
+
+
 int wpa_supplicant_ap_mac_addr_filter(struct wpa_supplicant *wpa_s,
                                      const u8 *addr)
 {