Add wps_cancel for hostapd_cli
[mech_eap.git] / wpa_supplicant / ap.c
index 6e84a64..66b0e1f 100644 (file)
@@ -3,20 +3,15 @@
  * Copyright (c) 2003-2009, Jouni Malinen <j@w1.fi>
  * Copyright (c) 2009, Atheros Communications
  *
- * 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
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
  */
 
 #include "utils/includes.h"
 
 #include "utils/common.h"
 #include "utils/eloop.h"
+#include "utils/uuid.h"
 #include "common/ieee802_11_defs.h"
 #include "common/wpa_ctrl.h"
 #include "ap/hostapd.h"
@@ -29,9 +24,6 @@
 #include "ap/ieee802_1x.h"
 #include "ap/wps_hostapd.h"
 #include "ap/ctrl_iface_ap.h"
-#include "eap_common/eap_defs.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 "p2p_supplicant.h"
 #include "ap.h"
 #include "ap/sta_info.h"
+#include "notify.h"
 
 
+#ifdef CONFIG_WPS
 static void wpas_wps_ap_pin_timeout(void *eloop_data, void *user_ctx);
+#endif /* CONFIG_WPS */
 
 
 static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s,
@@ -74,9 +69,43 @@ static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s,
                return -1;
        }
 
-       /* TODO: enable HT if driver supports it;
+       /* TODO: enable HT40 if driver supports it;
         * drop to 11b if driver does not support 11g */
 
+#ifdef CONFIG_IEEE80211N
+       /*
+        * Enable HT20 if the driver supports it, by setting conf->ieee80211n
+        * and a mask of allowed capabilities within conf->ht_capab.
+        * Using default config settings for: conf->ht_op_mode_fixed,
+        * conf->secondary_channel, conf->require_ht
+        */
+       if (wpa_s->hw.modes) {
+               struct hostapd_hw_modes *mode = NULL;
+               int i;
+               for (i = 0; i < wpa_s->hw.num_modes; i++) {
+                       if (wpa_s->hw.modes[i].mode == conf->hw_mode) {
+                               mode = &wpa_s->hw.modes[i];
+                               break;
+                       }
+               }
+               if (mode && mode->ht_capab) {
+                       conf->ieee80211n = 1;
+
+                       /*
+                        * white-list capabilities that won't cause issues
+                        * to connecting stations, while leaving the current
+                        * capabilities intact (currently disabled SMPS).
+                        */
+                       conf->ht_capab |= mode->ht_capab &
+                               (HT_CAP_INFO_GREEN_FIELD |
+                                HT_CAP_INFO_SHORT_GI20MHZ |
+                                HT_CAP_INFO_SHORT_GI40MHZ |
+                                HT_CAP_INFO_RX_STBC_MASK |
+                                HT_CAP_INFO_MAX_AMSDU_SIZE);
+               }
+       }
+#endif /* CONFIG_IEEE80211N */
+
 #ifdef CONFIG_P2P
        if (conf->hw_mode == HOSTAPD_MODE_IEEE80211G) {
                /* Remove 802.11b rates from supported and basic rate sets */
@@ -103,6 +132,8 @@ static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s,
                }
                conf->supported_rates = list;
        }
+
+       bss->isolate = !wpa_s->conf->p2p_intra_bss;
 #endif /* CONFIG_P2P */
 
        if (ssid->ssid_len == 0) {
@@ -114,6 +145,11 @@ static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s,
        bss->ssid.ssid_len = ssid->ssid_len;
        bss->ssid.ssid_set = 1;
 
+       bss->ignore_broadcast_ssid = ssid->ignore_broadcast_ssid;
+
+       if (ssid->auth_alg)
+               bss->auth_algs = ssid->auth_alg;
+
        if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt))
                bss->wpa = ssid->proto;
        bss->wpa_key_mgmt = ssid->key_mgmt;
@@ -127,8 +163,27 @@ static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s,
                        return -1;
                os_memcpy(bss->ssid.wpa_psk->psk, ssid->psk, PMK_LEN);
                bss->ssid.wpa_psk->group = 1;
+       } else if (ssid->wep_key_len[0] || ssid->wep_key_len[1] ||
+                  ssid->wep_key_len[2] || ssid->wep_key_len[3]) {
+               struct hostapd_wep_keys *wep = &bss->ssid.wep;
+               int i;
+               for (i = 0; i < NUM_WEP_KEYS; i++) {
+                       if (ssid->wep_key_len[i] == 0)
+                               continue;
+                       wep->key[i] = os_malloc(ssid->wep_key_len[i]);
+                       if (wep->key[i] == NULL)
+                               return -1;
+                       os_memcpy(wep->key[i], ssid->wep_key[i],
+                                 ssid->wep_key_len[i]);
+                       wep->len[i] = ssid->wep_key_len[i];
+               }
+               wep->idx = ssid->wep_tx_keyidx;
+               wep->keys_set = 1;
        }
 
+       if (ssid->ap_max_inactivity)
+               bss->ap_max_inactivity = ssid->ap_max_inactivity;
+
        /* Select group cipher based on the enabled pairwise cipher suites */
        pairwise = 0;
        if (bss->wpa & 1)
@@ -148,25 +203,55 @@ static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s,
        else if (bss->wpa)
                bss->ssid.security_policy = SECURITY_WPA_PSK;
        else if (bss->ieee802_1x) {
+               int cipher = WPA_CIPHER_NONE;
                bss->ssid.security_policy = SECURITY_IEEE_802_1X;
                bss->ssid.wep.default_len = bss->default_wep_key_len;
-       } else if (bss->ssid.wep.keys_set)
+               if (bss->default_wep_key_len)
+                       cipher = bss->default_wep_key_len >= 13 ?
+                               WPA_CIPHER_WEP104 : WPA_CIPHER_WEP40;
+               bss->wpa_group = cipher;
+               bss->wpa_pairwise = cipher;
+               bss->rsn_pairwise = cipher;
+       } else if (bss->ssid.wep.keys_set) {
+               int cipher = WPA_CIPHER_WEP40;
+               if (bss->ssid.wep.len[0] >= 13)
+                       cipher = WPA_CIPHER_WEP104;
                bss->ssid.security_policy = SECURITY_STATIC_WEP;
-       else
+               bss->wpa_group = cipher;
+               bss->wpa_pairwise = cipher;
+               bss->rsn_pairwise = cipher;
+       } else {
                bss->ssid.security_policy = SECURITY_PLAINTEXT;
+               bss->wpa_group = WPA_CIPHER_NONE;
+               bss->wpa_pairwise = WPA_CIPHER_NONE;
+               bss->rsn_pairwise = WPA_CIPHER_NONE;
+       }
 
 #ifdef CONFIG_WPS
        /*
-        * Enable WPS by default, but require user interaction to actually use
-        * it. Only the internal Registrar is supported.
+        * Enable WPS by default for open and WPA/WPA2-Personal network, but
+        * require user interaction to actually use it. Only the internal
+        * Registrar is supported.
         */
+       if (bss->ssid.security_policy != SECURITY_WPA_PSK &&
+           bss->ssid.security_policy != SECURITY_PLAINTEXT)
+               goto no_wps;
+#ifdef CONFIG_WPS2
+       if (bss->ssid.security_policy == SECURITY_WPA_PSK &&
+           (!(pairwise & WPA_CIPHER_CCMP) || !(bss->wpa & 2)))
+               goto no_wps; /* WPS2 does not allow WPA/TKIP-only
+                             * configuration */
+#endif /* CONFIG_WPS2 */
        bss->eap_server = 1;
-       bss->wps_state = 2;
+
+       if (!ssid->ignore_broadcast_ssid)
+               bss->wps_state = 2;
+
        bss->ap_setup_locked = 2;
        if (wpa_s->conf->config_methods)
                bss->config_methods = os_strdup(wpa_s->conf->config_methods);
-       if (wpa_s->conf->device_type)
-               bss->device_type = os_strdup(wpa_s->conf->device_type);
+       os_memcpy(bss->device_type, wpa_s->conf->device_type,
+                 WPS_DEV_TYPE_LEN);
        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);
@@ -179,8 +264,12 @@ static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s,
                bss->model_number = os_strdup(wpa_s->conf->model_number);
        if (wpa_s->conf->serial_number)
                bss->serial_number = os_strdup(wpa_s->conf->serial_number);
-       os_memcpy(bss->uuid, wpa_s->conf->uuid, WPS_UUID_LEN);
+       if (is_nil_uuid(wpa_s->conf->uuid))
+               os_memcpy(bss->uuid, wpa_s->wps->uuid, WPS_UUID_LEN);
+       else
+               os_memcpy(bss->uuid, wpa_s->conf->uuid, WPS_UUID_LEN);
        os_memcpy(bss->os_version, wpa_s->conf->os_version, 4);
+no_wps:
 #endif /* CONFIG_WPS */
 
        if (wpa_s->max_stations &&
@@ -189,6 +278,8 @@ static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s,
        else
                bss->max_num_sta = wpa_s->conf->max_num_sta;
 
+       bss->disassoc_low_ack = wpa_s->conf->disassoc_low_ack;
+
        return 0;
 }
 
@@ -218,23 +309,33 @@ static void ap_wps_event_cb(void *ctx, enum wps_event event,
 #ifdef CONFIG_P2P
        struct wpa_supplicant *wpa_s = ctx;
 
-       if (event == WPS_EV_FAIL && wpa_s->parent && wpa_s->parent != wpa_s &&
-           wpa_s == wpa_s->global->p2p_group_formation) {
+       if (event == WPS_EV_FAIL) {
                struct wps_event_fail *fail = &data->fail;
 
-               /*
-                * src/ap/wps_hostapd.c has already sent this on the main
-                * interface, so only send on the parent interface here if
-                * needed.
-                */
-               wpa_msg(wpa_s->parent, MSG_INFO, WPS_EVENT_FAIL
-                       "msg=%d config_error=%d",
-                       fail->msg, fail->config_error);
+               if (wpa_s->parent && wpa_s->parent != wpa_s &&
+                   wpa_s == wpa_s->global->p2p_group_formation) {
+                       /*
+                        * src/ap/wps_hostapd.c has already sent this on the
+                        * main interface, so only send on the parent interface
+                        * here if needed.
+                        */
+                       wpa_msg(wpa_s->parent, MSG_INFO, WPS_EVENT_FAIL
+                               "msg=%d config_error=%d",
+                               fail->msg, fail->config_error);
+               }
+               wpas_p2p_wps_failed(wpa_s, fail);
        }
 #endif /* CONFIG_P2P */
 }
 
 
+static void ap_sta_authorized_cb(void *ctx, const u8 *mac_addr,
+                                int authorized, const u8 *p2p_dev_addr)
+{
+       wpas_notify_sta_authorized(ctx, mac_addr, authorized, p2p_dev_addr);
+}
+
+
 static int ap_vendor_action_rx(void *ctx, const u8 *buf, size_t len, int freq)
 {
 #ifdef CONFIG_P2P
@@ -255,12 +356,12 @@ static int ap_vendor_action_rx(void *ctx, const u8 *buf, size_t len, int freq)
 }
 
 
-static int ap_probe_req_rx(void *ctx, const u8 *addr, const u8 *ie,
-                          size_t ie_len)
+static int ap_probe_req_rx(void *ctx, const u8 *sa, const u8 *da,
+                          const u8 *bssid, 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);
+       return wpas_p2p_probe_req_rx(wpa_s, sa, da, bssid, ie, ie_len);
 #else /* CONFIG_P2P */
        return 0;
 #endif /* CONFIG_P2P */
@@ -277,6 +378,18 @@ static void ap_wps_reg_success_cb(void *ctx, const u8 *mac_addr,
 }
 
 
+static void wpas_ap_configured_cb(void *ctx)
+{
+       struct wpa_supplicant *wpa_s = ctx;
+
+       wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
+
+       if (wpa_s->ap_configured_cb)
+               wpa_s->ap_configured_cb(wpa_s->ap_configured_cb_ctx,
+                                       wpa_s->ap_configured_cb_data);
+}
+
+
 int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s,
                             struct wpa_ssid *ssid)
 {
@@ -313,6 +426,7 @@ int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s,
        }
        params.freq = ssid->frequency;
 
+       params.wpa_proto = ssid->proto;
        if (ssid->key_mgmt & WPA_KEY_MGMT_PSK)
                wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
        else
@@ -337,7 +451,6 @@ int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s,
        if (ssid->mode == WPAS_MODE_P2P_GO ||
            ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
                params.p2p = 1;
-       wpa_drv_set_intra_bss(wpa_s, wpa_s->conf->p2p_intra_bss);
 #endif /* CONFIG_P2P */
 
        if (wpa_s->parent->set_ap_uapsd)
@@ -354,6 +467,8 @@ int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s,
        if (hapd_iface == NULL)
                return -1;
        hapd_iface->owner = wpa_s;
+       hapd_iface->drv_flags = wpa_s->drv_flags;
+       hapd_iface->probe_resp_offloads = wpa_s->probe_resp_offloads;
 
        wpa_s->ap_iface->conf = conf = hostapd_config_defaults();
        if (conf == NULL) {
@@ -361,6 +476,11 @@ int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s,
                return -1;
        }
 
+       if (params.uapsd > 0) {
+               conf->bss->wmm_enabled = 1;
+               conf->bss->wmm_uapsd = 1;
+       }
+
        if (wpa_supplicant_conf_ap(wpa_s, ssid, conf)) {
                wpa_printf(MSG_ERROR, "Failed to create AP configuration");
                wpa_supplicant_ap_deinit(wpa_s);
@@ -393,6 +513,7 @@ int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s,
                }
 
                hapd_iface->bss[i]->msg_ctx = wpa_s;
+               hapd_iface->bss[i]->msg_ctx_parent = wpa_s->parent;
                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;
@@ -403,45 +524,48 @@ int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s,
                hapd_iface->bss[i]->wps_reg_success_cb_ctx = wpa_s;
                hapd_iface->bss[i]->wps_event_cb = ap_wps_event_cb;
                hapd_iface->bss[i]->wps_event_cb_ctx = wpa_s;
+               hapd_iface->bss[i]->sta_authorized_cb = ap_sta_authorized_cb;
+               hapd_iface->bss[i]->sta_authorized_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 */
+               hapd_iface->bss[i]->setup_complete_cb = wpas_ap_configured_cb;
+               hapd_iface->bss[i]->setup_complete_cb_ctx = wpa_s;
        }
 
        os_memcpy(hapd_iface->bss[0]->own_addr, wpa_s->own_addr, ETH_ALEN);
        hapd_iface->bss[0]->driver = wpa_s->driver;
        hapd_iface->bss[0]->drv_priv = wpa_s->drv_priv;
 
+       wpa_s->current_ssid = ssid;
+       os_memcpy(wpa_s->bssid, wpa_s->own_addr, ETH_ALEN);
+       wpa_s->assoc_freq = ssid->frequency;
+
        if (hostapd_setup_interface(wpa_s->ap_iface)) {
                wpa_printf(MSG_ERROR, "Failed to initialize AP interface");
                wpa_supplicant_ap_deinit(wpa_s);
                return -1;
        }
 
-       wpa_s->current_ssid = ssid;
-       os_memcpy(wpa_s->bssid, wpa_s->own_addr, ETH_ALEN);
-       wpa_s->assoc_freq = ssid->frequency;
-       wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
-
-       if (wpa_s->ap_configured_cb)
-               wpa_s->ap_configured_cb(wpa_s->ap_configured_cb_ctx,
-                                       wpa_s->ap_configured_cb_data);
-
        return 0;
 }
 
 
 void wpa_supplicant_ap_deinit(struct wpa_supplicant *wpa_s)
 {
+#ifdef CONFIG_WPS
        eloop_cancel_timeout(wpas_wps_ap_pin_timeout, wpa_s, NULL);
+#endif /* CONFIG_WPS */
 
        if (wpa_s->ap_iface == NULL)
                return;
 
        wpa_s->current_ssid = NULL;
+       wpa_s->assoc_freq = 0;
+       wpa_s->reassociated_connection = 0;
 #ifdef CONFIG_P2P
        if (wpa_s->ap_iface->bss)
                wpa_s->ap_iface->bss[0]->p2p_group = NULL;
@@ -464,16 +588,31 @@ void ap_tx_status(void *ctx, const u8 *addr,
 }
 
 
-void ap_rx_from_unknown_sta(void *ctx, const u8 *frame, size_t len)
+void ap_eapol_tx_status(void *ctx, const u8 *dst,
+                       const u8 *data, size_t len, int ack)
+{
+#ifdef NEED_AP_MLME
+       struct wpa_supplicant *wpa_s = ctx;
+       hostapd_tx_status(wpa_s->ap_iface->bss[0], dst, data, len, ack);
+#endif /* NEED_AP_MLME */
+}
+
+
+void ap_client_poll_ok(void *ctx, const u8 *addr)
+{
+#ifdef NEED_AP_MLME
+       struct wpa_supplicant *wpa_s = ctx;
+       if (wpa_s->ap_iface)
+               hostapd_client_poll_ok(wpa_s->ap_iface->bss[0], addr);
+#endif /* NEED_AP_MLME */
+}
+
+
+void ap_rx_from_unknown_sta(void *ctx, const u8 *addr, int wds)
 {
 #ifdef NEED_AP_MLME
        struct wpa_supplicant *wpa_s = ctx;
-       const struct ieee80211_hdr *hdr =
-               (const struct ieee80211_hdr *) frame;
-       u16 fc = le_to_host16(hdr->frame_control);
-       ieee802_11_rx_from_unknown(wpa_s->ap_iface->bss[0], hdr->addr2,
-                                  (fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) ==
-                                  (WLAN_FC_TODS | WLAN_FC_FROMDS));
+       ieee802_11_rx_from_unknown(wpa_s->ap_iface->bss[0], addr, wds);
 #endif /* NEED_AP_MLME */
 }
 
@@ -510,26 +649,13 @@ void wpa_supplicant_ap_rx_eapol(struct wpa_supplicant *wpa_s,
 
 #ifdef CONFIG_WPS
 
-int wpa_supplicant_ap_wps_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid)
+int wpa_supplicant_ap_wps_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid,
+                             const u8 *p2p_dev_addr)
 {
        if (!wpa_s->ap_iface)
                return -1;
-       return hostapd_wps_button_pushed(wpa_s->ap_iface->bss[0]);
-}
-
-
-static int wpa_supplicant_ap_wps_sta_cancel(struct hostapd_data *hapd,
-                                           struct sta_info *sta, void *ctx)
-{
-       if (sta && (sta->flags & WLAN_STA_WPS)) {
-               ap_sta_deauthenticate(hapd, sta,
-                                     WLAN_REASON_PREV_AUTH_NOT_VALID);
-               wpa_printf(MSG_DEBUG, "WPS: %s: Deauth sta=" MACSTR,
-                          __func__, MAC2STR(sta->addr));
-               return 1;
-       }
-
-       return 0;
+       return hostapd_wps_button_pushed(wpa_s->ap_iface->bss[0],
+                                        p2p_dev_addr);
 }
 
 
@@ -544,7 +670,7 @@ int wpa_supplicant_ap_wps_cancel(struct wpa_supplicant *wpa_s)
        reg = wpa_s->ap_iface->bss[0]->wps->registrar;
        reg_sel = wps_registrar_wps_cancel(reg);
        wps_sta = ap_for_each_sta(wpa_s->ap_iface->bss[0],
-                                 wpa_supplicant_ap_wps_sta_cancel, NULL);
+                                 ap_sta_wps_cancel, NULL);
 
        if (!reg_sel && !wps_sta) {
                wpa_printf(MSG_DEBUG, "No WPS operation in progress at this "
@@ -573,7 +699,7 @@ int wpa_supplicant_ap_wps_pin(struct wpa_supplicant *wpa_s, const u8 *bssid,
 
        if (pin == NULL) {
                unsigned int rpin = wps_generate_pin();
-               ret_len = os_snprintf(buf, buflen, "%d", rpin);
+               ret_len = os_snprintf(buf, buflen, "%08d", rpin);
                pin = buf;
        } else
                ret_len = os_snprintf(buf, buflen, "%s", pin);
@@ -634,7 +760,7 @@ const char * wpas_wps_ap_pin_random(struct wpa_supplicant *wpa_s, int timeout)
                return NULL;
        hapd = wpa_s->ap_iface->bss[0];
        pin = wps_generate_pin();
-       os_snprintf(pin_txt, sizeof(pin_txt), "%u", pin);
+       os_snprintf(pin_txt, sizeof(pin_txt), "%08u", pin);
        os_free(hapd->conf->ap_pin);
        hapd->conf->ap_pin = os_strdup(pin_txt);
        if (hapd->conf->ap_pin == NULL)
@@ -737,6 +863,26 @@ int ap_ctrl_iface_sta_next(struct wpa_supplicant *wpa_s, const char *txtaddr,
 }
 
 
+int ap_ctrl_iface_sta_disassociate(struct wpa_supplicant *wpa_s,
+                                  const char *txtaddr)
+{
+       if (wpa_s->ap_iface == NULL)
+               return -1;
+       return hostapd_ctrl_iface_disassociate(wpa_s->ap_iface->bss[0],
+                                              txtaddr);
+}
+
+
+int ap_ctrl_iface_sta_deauthenticate(struct wpa_supplicant *wpa_s,
+                                    const char *txtaddr)
+{
+       if (wpa_s->ap_iface == NULL)
+               return -1;
+       return hostapd_ctrl_iface_deauthenticate(wpa_s->ap_iface->bss[0],
+                                                txtaddr);
+}
+
+
 int ap_ctrl_iface_wpa_get_status(struct wpa_supplicant *wpa_s, char *buf,
                                 size_t buflen, int verbose)
 {
@@ -774,7 +920,9 @@ int wpa_supplicant_ap_update_beacon(struct wpa_supplicant *wpa_s)
        struct wpa_ssid *ssid = wpa_s->current_ssid;
        struct hostapd_data *hapd;
 
-       if (ssid == NULL || wpa_s->ap_iface == NULL)
+       if (ssid == NULL || wpa_s->ap_iface == NULL ||
+           ssid->mode == WPAS_MODE_INFRA ||
+           ssid->mode == WPAS_MODE_IBSS)
                return -1;
 
 #ifdef CONFIG_P2P
@@ -785,8 +933,10 @@ int wpa_supplicant_ap_update_beacon(struct wpa_supplicant *wpa_s)
                        P2P_GROUP_FORMATION;
 #endif /* CONFIG_P2P */
 
-       ieee802_11_set_beacons(iface);
        hapd = iface->bss[0];
+       if (hapd->drv_priv == NULL)
+               return -1;
+       ieee802_11_set_beacons(iface);
        hostapd_set_ap_wps_ie(hapd);
 
        return 0;