P2P: Support dedicated P2P_DEVICE without separate group interface
[mech_eap.git] / wpa_supplicant / p2p_supplicant.c
index a456d3e..ff52098 100644 (file)
@@ -800,6 +800,8 @@ grp_owner:
                s = wpas_p2p_get_persistent_go(wpa_s);
                if (!s && !go_wpa_s && p2p_no_group_iface) {
                        p2p_set_intended_addr(wpa_s->global->p2p,
+                                             wpa_s->p2p_mgmt ?
+                                             wpa_s->parent->own_addr :
                                              wpa_s->own_addr);
                } else if (!s && !go_wpa_s) {
                        if (wpas_p2p_add_group_interface(wpa_s,
@@ -873,7 +875,7 @@ static int wpas_p2p_group_delete(struct wpa_supplicant *wpa_s,
 
        if (wpa_s->cross_connect_in_use) {
                wpa_s->cross_connect_in_use = 0;
-               wpa_msg_global(wpa_s->parent, MSG_INFO,
+               wpa_msg_global(wpa_s->p2pdev, MSG_INFO,
                               P2P_EVENT_CROSS_CONNECT_DISABLE "%s %s",
                               wpa_s->ifname, wpa_s->cross_connect_uplink);
        }
@@ -904,7 +906,7 @@ static int wpas_p2p_group_delete(struct wpa_supplicant *wpa_s,
                break;
        }
        if (removal_reason != P2P_GROUP_REMOVAL_SILENT) {
-               wpa_msg_global(wpa_s->parent, MSG_INFO,
+               wpa_msg_global(wpa_s->p2pdev, MSG_INFO,
                               P2P_EVENT_GROUP_REMOVED "%s %s%s",
                               wpa_s->ifname, gtype, reason);
        }
@@ -914,7 +916,7 @@ static int wpas_p2p_group_delete(struct wpa_supplicant *wpa_s,
        if (eloop_cancel_timeout(wpas_p2p_group_idle_timeout, wpa_s, NULL) > 0)
                wpa_printf(MSG_DEBUG, "P2P: Cancelled P2P group idle timeout");
        if (eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
-                                wpa_s->parent, NULL) > 0) {
+                                wpa_s->p2pdev, NULL) > 0) {
                wpa_printf(MSG_DEBUG, "P2P: Cancelled P2P group formation "
                           "timeout");
                wpa_s->p2p_in_provisioning = 0;
@@ -949,6 +951,12 @@ static int wpas_p2p_group_delete(struct wpa_supplicant *wpa_s,
                return 1;
        }
 
+       /*
+        * The primary interface was used for P2P group operations, so
+        * need to reset its p2pdev.
+        */
+       wpa_s->p2pdev = wpa_s->parent;
+
        if (!wpa_s->p2p_go_group_formation_completed) {
                wpa_s->global->p2p_group_formation = NULL;
                wpa_s->p2p_in_provisioning = 0;
@@ -1264,7 +1272,7 @@ static void wpas_p2p_group_started(struct wpa_supplicant *wpa_s,
         * Include PSK/passphrase only in the control interface message and
         * leave it out from the debug log entry.
         */
-       wpa_msg_global_ctrl(wpa_s->parent, MSG_INFO,
+       wpa_msg_global_ctrl(wpa_s->p2pdev, MSG_INFO,
                            P2P_EVENT_GROUP_STARTED
                            "%s %s ssid=\"%s\" freq=%d%s%s%s%s%s go_dev_addr="
                            MACSTR "%s%s",
@@ -1307,7 +1315,7 @@ static void wpas_group_formation_completed(struct wpa_supplicant *wpa_s,
        wpa_s->group_formation_reported = 1;
 
        if (!success) {
-               wpa_msg_global(wpa_s->parent, MSG_INFO,
+               wpa_msg_global(wpa_s->p2pdev, MSG_INFO,
                               P2P_EVENT_GROUP_FORMATION_FAILURE);
                wpas_notify_p2p_group_formation_failure(wpa_s, "");
                if (already_deleted)
@@ -1317,7 +1325,7 @@ static void wpas_group_formation_completed(struct wpa_supplicant *wpa_s,
                return;
        }
 
-       wpa_msg_global(wpa_s->parent, MSG_INFO,
+       wpa_msg_global(wpa_s->p2pdev, MSG_INFO,
                       P2P_EVENT_GROUP_FORMATION_SUCCESS);
 
        ssid = wpa_s->current_ssid;
@@ -1365,7 +1373,7 @@ static void wpas_group_formation_completed(struct wpa_supplicant *wpa_s,
        }
 
        if (persistent)
-               network_id = wpas_p2p_store_persistent_group(wpa_s->parent,
+               network_id = wpas_p2p_store_persistent_group(wpa_s->p2pdev,
                                                             ssid, go_dev_addr);
        else {
                os_free(wpa_s->global->add_psk);
@@ -1489,7 +1497,7 @@ static void wpas_p2p_send_action_tx_status(struct wpa_supplicant *wpa_s,
                wpa_s->pending_pd_before_join = 0;
                wpa_dbg(wpa_s, MSG_DEBUG, "P2P: No ACK for PD Req "
                        "during p2p_connect-auto");
-               wpa_msg_global(wpa_s->parent, MSG_INFO,
+               wpa_msg_global(wpa_s->p2pdev, MSG_INFO,
                               P2P_EVENT_FALLBACK_TO_GO_NEG
                               "reason=no-ACK-to-PD-Req");
                wpas_p2p_fallback_to_go_neg(wpa_s, 0);
@@ -1632,11 +1640,11 @@ static void wpas_start_wps_enrollee(struct wpa_supplicant *wpa_s,
        } else if (res->wps_method == WPS_NFC) {
                wpas_wps_start_nfc(wpa_s, res->peer_device_addr,
                                   res->peer_interface_addr,
-                                  wpa_s->parent->p2p_oob_dev_pw,
-                                  wpa_s->parent->p2p_oob_dev_pw_id, 1,
-                                  wpa_s->parent->p2p_oob_dev_pw_id ==
+                                  wpa_s->p2pdev->p2p_oob_dev_pw,
+                                  wpa_s->p2pdev->p2p_oob_dev_pw_id, 1,
+                                  wpa_s->p2pdev->p2p_oob_dev_pw_id ==
                                   DEV_PW_NFC_CONNECTION_HANDOVER ?
-                                  wpa_s->parent->p2p_peer_oob_pubkey_hash :
+                                  wpa_s->p2pdev->p2p_peer_oob_pubkey_hash :
                                   NULL,
                                   NULL, 0, 0);
 #endif /* CONFIG_WPS_NFC */
@@ -1662,7 +1670,7 @@ static void wpas_p2p_add_psk_list(struct wpa_supplicant *wpa_s,
        if (!wpa_s->ap_iface)
                return;
 
-       persistent = wpas_p2p_get_persistent(wpa_s->parent, NULL, ssid->ssid,
+       persistent = wpas_p2p_get_persistent(wpa_s->p2pdev, NULL, ssid->ssid,
                                             ssid->ssid_len);
        if (persistent == NULL)
                return;
@@ -1727,8 +1735,8 @@ static void p2p_go_save_group_common_freqs(struct wpa_supplicant *wpa_s,
 static void p2p_config_write(struct wpa_supplicant *wpa_s)
 {
 #ifndef CONFIG_NO_CONFIG_WRITE
-       if (wpa_s->parent->conf->update_config &&
-           wpa_config_write(wpa_s->parent->confname, wpa_s->parent->conf))
+       if (wpa_s->p2pdev->conf->update_config &&
+           wpa_config_write(wpa_s->p2pdev->confname, wpa_s->p2pdev->conf))
                wpa_printf(MSG_DEBUG, "P2P: Failed to update configuration");
 #endif /* CONFIG_NO_CONFIG_WRITE */
 }
@@ -1766,8 +1774,8 @@ static void p2p_go_configured(void *ctx, void *data)
                                       params->persistent_group, "");
                wpa_s->group_formation_reported = 1;
 
-               if (wpa_s->parent->p2ps_method_config_any) {
-                       if (is_zero_ether_addr(wpa_s->parent->p2ps_join_addr)) {
+               if (wpa_s->p2pdev->p2ps_method_config_any) {
+                       if (is_zero_ether_addr(wpa_s->p2pdev->p2ps_join_addr)) {
                                wpa_dbg(wpa_s, MSG_DEBUG,
                                        "P2PS: Setting default PIN for ANY");
                                wpa_supplicant_ap_wps_pin(wpa_s, NULL,
@@ -1776,18 +1784,18 @@ static void p2p_go_configured(void *ctx, void *data)
                        } else {
                                wpa_dbg(wpa_s, MSG_DEBUG,
                                        "P2PS: Setting default PIN for " MACSTR,
-                                       MAC2STR(wpa_s->parent->p2ps_join_addr));
+                                       MAC2STR(wpa_s->p2pdev->p2ps_join_addr));
                                wpa_supplicant_ap_wps_pin(
-                                       wpa_s, wpa_s->parent->p2ps_join_addr,
+                                       wpa_s, wpa_s->p2pdev->p2ps_join_addr,
                                        "12345670", NULL, 0, 0);
                        }
-                       wpa_s->parent->p2ps_method_config_any = 0;
+                       wpa_s->p2pdev->p2ps_method_config_any = 0;
                }
 
                os_get_reltime(&wpa_s->global->p2p_go_wait_client);
                if (params->persistent_group) {
                        network_id = wpas_p2p_store_persistent_group(
-                               wpa_s->parent, ssid,
+                               wpa_s->p2pdev, ssid,
                                wpa_s->global->p2p_dev_addr);
                        wpas_p2p_add_psk_list(wpa_s, ssid);
                }
@@ -1804,11 +1812,11 @@ static void p2p_go_configured(void *ctx, void *data)
                        wpa_s->p2p_go_group_formation_completed = 0;
                        wpa_s->global->p2p_group_formation = wpa_s;
                        eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
-                                            wpa_s->parent, NULL);
+                                            wpa_s->p2pdev, NULL);
                        eloop_register_timeout(
                                wpa_s->p2p_first_connection_timeout, 0,
                                wpas_p2p_group_formation_timeout,
-                               wpa_s->parent, NULL);
+                               wpa_s->p2pdev, NULL);
                }
 
                return;
@@ -1826,17 +1834,17 @@ static void p2p_go_configured(void *ctx, void *data)
                                          params->peer_device_addr);
 #ifdef CONFIG_WPS_NFC
        } else if (params->wps_method == WPS_NFC) {
-               if (wpa_s->parent->p2p_oob_dev_pw_id !=
+               if (wpa_s->p2pdev->p2p_oob_dev_pw_id !=
                    DEV_PW_NFC_CONNECTION_HANDOVER &&
-                   !wpa_s->parent->p2p_oob_dev_pw) {
+                   !wpa_s->p2pdev->p2p_oob_dev_pw) {
                        wpa_printf(MSG_DEBUG, "P2P: No NFC Dev Pw known");
                        return;
                }
                wpas_ap_wps_add_nfc_pw(
-                       wpa_s, wpa_s->parent->p2p_oob_dev_pw_id,
-                       wpa_s->parent->p2p_oob_dev_pw,
-                       wpa_s->parent->p2p_peer_oob_pk_hash_known ?
-                       wpa_s->parent->p2p_peer_oob_pubkey_hash : NULL);
+                       wpa_s, wpa_s->p2pdev->p2p_oob_dev_pw_id,
+                       wpa_s->p2pdev->p2p_oob_dev_pw,
+                       wpa_s->p2pdev->p2p_peer_oob_pk_hash_known ?
+                       wpa_s->p2pdev->p2p_peer_oob_pubkey_hash : NULL);
 #endif /* CONFIG_WPS_NFC */
        } else if (wpa_s->p2p_pin[0])
                wpa_supplicant_ap_wps_pin(wpa_s, params->peer_interface_addr,
@@ -1898,6 +1906,8 @@ static void wpas_start_wps_go(struct wpa_supplicant *wpa_s,
                 */
                ssid->pairwise_cipher = WPA_CIPHER_GCMP;
                ssid->group_cipher = WPA_CIPHER_GCMP;
+               /* P2P GO in 60 GHz is always a PCP (PBSS) */
+               ssid->pbss = 1;
        }
        if (os_strlen(params->passphrase) > 0) {
                ssid->passphrase = os_strdup(params->passphrase);
@@ -1914,7 +1924,7 @@ static void wpas_start_wps_go(struct wpa_supplicant *wpa_s,
                os_memcpy(ssid->psk, params->psk, sizeof(ssid->psk));
        else if (ssid->passphrase)
                wpa_config_update_psk(ssid);
-       ssid->ap_max_inactivity = wpa_s->parent->conf->p2p_go_max_inactivity;
+       ssid->ap_max_inactivity = wpa_s->p2pdev->conf->p2p_go_max_inactivity;
 
        wpa_s->ap_configured_cb = p2p_go_configured;
        wpa_s->ap_configured_cb_ctx = wpa_s;
@@ -1974,6 +1984,23 @@ static void wpas_p2p_clone_config(struct wpa_supplicant *dst,
 }
 
 
+static void wpas_p2p_clone_config_dh(struct wpa_supplicant *dst,
+                                    const struct wpa_supplicant *src)
+{
+       struct wpa_config *d;
+       const struct wpa_config *s;
+
+       d = dst->conf;
+       s = src->conf;
+
+       if (s->wps_nfc_dh_privkey && s->wps_nfc_dh_pubkey &&
+           !d->wps_nfc_dh_privkey && !d->wps_nfc_dh_pubkey) {
+               d->wps_nfc_dh_privkey = wpabuf_dup(s->wps_nfc_dh_privkey);
+               d->wps_nfc_dh_pubkey = wpabuf_dup(s->wps_nfc_dh_pubkey);
+       }
+}
+
+
 static void wpas_p2p_get_group_ifname(struct wpa_supplicant *wpa_s,
                                      char *ifname, size_t len)
 {
@@ -2124,7 +2151,7 @@ static void wpas_p2p_group_formation_failed(struct wpa_supplicant *wpa_s,
                                            int already_deleted)
 {
        eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
-                            wpa_s->parent, NULL);
+                            wpa_s->p2pdev, NULL);
        if (wpa_s->global->p2p)
                p2p_group_formation_failed(wpa_s->global->p2p);
        wpas_group_formation_completed(wpa_s, 0, already_deleted);
@@ -2135,9 +2162,9 @@ static void wpas_p2p_grpform_fail_after_wps(struct wpa_supplicant *wpa_s)
 {
        wpa_printf(MSG_DEBUG, "P2P: Reject group formation due to WPS provisioning failure");
        eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
-                            wpa_s->parent, NULL);
+                            wpa_s->p2pdev, NULL);
        eloop_register_timeout(0, 0, wpas_p2p_group_formation_timeout,
-                              wpa_s->parent, NULL);
+                              wpa_s->p2pdev, NULL);
        wpa_s->global->p2p_fail_on_wps_complete = 0;
 }
 
@@ -2148,15 +2175,16 @@ void wpas_p2p_ap_setup_failed(struct wpa_supplicant *wpa_s)
                return;
        /* Speed up group formation timeout since this cannot succeed */
        eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
-                            wpa_s->parent, NULL);
+                            wpa_s->p2pdev, NULL);
        eloop_register_timeout(0, 0, wpas_p2p_group_formation_timeout,
-                              wpa_s->parent, NULL);
+                              wpa_s->p2pdev, NULL);
 }
 
 
 static void wpas_go_neg_completed(void *ctx, struct p2p_go_neg_results *res)
 {
        struct wpa_supplicant *wpa_s = ctx;
+       struct wpa_supplicant *group_wpa_s;
 
        if (wpa_s->off_channel_freq || wpa_s->roc_waiting_drv_freq) {
                wpa_drv_cancel_remain_on_channel(wpa_s);
@@ -2209,7 +2237,7 @@ static void wpas_go_neg_completed(void *ctx, struct p2p_go_neg_results *res)
        }
 
        if (wpa_s->create_p2p_iface) {
-               struct wpa_supplicant *group_wpa_s =
+               group_wpa_s =
                        wpas_p2p_init_group_interface(wpa_s, res->role_go);
                if (group_wpa_s == NULL) {
                        wpas_p2p_remove_pending_group_interface(wpa_s);
@@ -2218,31 +2246,27 @@ static void wpas_go_neg_completed(void *ctx, struct p2p_go_neg_results *res)
                        wpas_p2p_group_formation_failed(wpa_s, 1);
                        return;
                }
-               if (group_wpa_s != wpa_s) {
-                       os_memcpy(group_wpa_s->p2p_pin, wpa_s->p2p_pin,
-                                 sizeof(group_wpa_s->p2p_pin));
-                       group_wpa_s->p2p_wps_method = wpa_s->p2p_wps_method;
-               }
                os_memset(wpa_s->pending_interface_addr, 0, ETH_ALEN);
                wpa_s->pending_interface_name[0] = '\0';
-               group_wpa_s->p2p_in_provisioning = 1;
-
-               if (res->role_go) {
-                       wpas_start_wps_go(group_wpa_s, res, 1);
-               } else {
-                       os_get_reltime(&group_wpa_s->scan_min_time);
-                       wpas_start_wps_enrollee(group_wpa_s, res);
-               }
        } else {
-               wpa_s->p2p_in_provisioning = 1;
-               wpa_s->global->p2p_group_formation = wpa_s;
+               group_wpa_s = wpa_s->parent;
+               wpa_s->global->p2p_group_formation = group_wpa_s;
+               if (group_wpa_s != wpa_s)
+                       wpas_p2p_clone_config_dh(group_wpa_s, wpa_s);
+       }
 
-               if (res->role_go) {
-                       wpas_start_wps_go(wpa_s, res, 1);
-               } else {
-                       os_get_reltime(&wpa_s->scan_min_time);
-                       wpas_start_wps_enrollee(ctx, res);
-               }
+       group_wpa_s->p2p_in_provisioning = 1;
+       group_wpa_s->p2pdev = wpa_s;
+       if (group_wpa_s != wpa_s) {
+               os_memcpy(group_wpa_s->p2p_pin, wpa_s->p2p_pin,
+                         sizeof(group_wpa_s->p2p_pin));
+               group_wpa_s->p2p_wps_method = wpa_s->p2p_wps_method;
+       }
+       if (res->role_go) {
+               wpas_start_wps_go(group_wpa_s, res, 1);
+       } else {
+               os_get_reltime(&group_wpa_s->scan_min_time);
+               wpas_start_wps_enrollee(group_wpa_s, res);
        }
 
        wpa_s->p2p_long_listen = 0;
@@ -2576,7 +2600,13 @@ static void wpas_prov_disc_req(void *ctx, const u8 *peer, u16 config_methods,
        params[sizeof(params) - 1] = '\0';
 
        if (config_methods & WPS_CONFIG_DISPLAY) {
-               generated_pin = wps_generate_pin();
+               if (wps_generate_pin(&generated_pin) < 0) {
+                       wpa_printf(MSG_DEBUG, "P2P: Could not generate PIN");
+                       wpas_notify_p2p_provision_discovery(
+                               wpa_s, peer, 0 /* response */,
+                               P2P_PROV_DISC_INFO_UNAVAILABLE, 0, 0);
+                       return;
+               }
                wpas_prov_disc_local_display(wpa_s, peer, params,
                                             generated_pin);
        } else if (config_methods & WPS_CONFIG_KEYPAD)
@@ -2621,7 +2651,13 @@ static void wpas_prov_disc_resp(void *ctx, const u8 *peer, u16 config_methods)
        if (config_methods & WPS_CONFIG_DISPLAY)
                wpas_prov_disc_local_keypad(wpa_s, peer, params);
        else if (config_methods & WPS_CONFIG_KEYPAD) {
-               generated_pin = wps_generate_pin();
+               if (wps_generate_pin(&generated_pin) < 0) {
+                       wpa_printf(MSG_DEBUG, "P2P: Could not generate PIN");
+                       wpas_notify_p2p_provision_discovery(
+                               wpa_s, peer, 0 /* response */,
+                               P2P_PROV_DISC_INFO_UNAVAILABLE, 0, 0);
+                       return;
+               }
                wpas_prov_disc_local_display(wpa_s, peer, params,
                                             generated_pin);
        } else if (config_methods & WPS_CONFIG_PUSHBUTTON)
@@ -2644,7 +2680,7 @@ static void wpas_prov_disc_fail(void *ctx, const u8 *peer,
        if (wpa_s->p2p_fallback_to_go_neg) {
                wpa_dbg(wpa_s, MSG_DEBUG, "P2P: PD for p2p_connect-auto "
                        "failed - fall back to GO Negotiation");
-               wpa_msg_global(wpa_s->parent, MSG_INFO,
+               wpa_msg_global(wpa_s->p2pdev, MSG_INFO,
                               P2P_EVENT_FALLBACK_TO_GO_NEG
                               "reason=PD-failed");
                wpas_p2p_fallback_to_go_neg(wpa_s, 0);
@@ -2889,7 +2925,11 @@ static u8 wpas_invitation_process(void *ctx, const u8 *sa, const u8 *bssid,
                                   "invitation");
                        return P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE;
                }
-               os_memcpy(group_bssid, wpa_s->own_addr, ETH_ALEN);
+               if (wpa_s->p2p_mgmt)
+                       os_memcpy(group_bssid, wpa_s->parent->own_addr,
+                                 ETH_ALEN);
+               else
+                       os_memcpy(group_bssid, wpa_s->own_addr, ETH_ALEN);
        } else if (s->mode == WPAS_MODE_P2P_GO) {
                *go = 1;
                if (wpas_p2p_add_group_interface(wpa_s, WPA_IF_P2P_GO) < 0)
@@ -3077,7 +3117,7 @@ static void wpas_remove_persistent_client(struct wpa_supplicant *wpa_s,
        if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GO ||
            !ssid->p2p_persistent_group)
                return; /* Not operating as a GO in persistent group */
-       ssid = wpas_p2p_get_persistent(wpa_s->parent, peer,
+       ssid = wpas_p2p_get_persistent(wpa_s->p2pdev, peer,
                                       ssid->ssid, ssid->ssid_len);
        wpas_remove_persistent_peer(wpa_s, ssid, peer, 1);
 }
@@ -3277,21 +3317,6 @@ static int wpas_p2p_default_channels(struct wpa_supplicant *wpa_s,
 }
 
 
-static struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
-                                         u16 num_modes,
-                                         enum hostapd_hw_mode mode)
-{
-       u16 i;
-
-       for (i = 0; i < num_modes; i++) {
-               if (modes[i].mode == mode)
-                       return &modes[i];
-       }
-
-       return NULL;
-}
-
-
 enum chan_allowed {
        NOT_ALLOWED, NO_IR, ALLOWED
 };
@@ -3325,45 +3350,6 @@ static int has_channel(struct wpa_global *global,
 }
 
 
-struct p2p_oper_class_map {
-       enum hostapd_hw_mode mode;
-       u8 op_class;
-       u8 min_chan;
-       u8 max_chan;
-       u8 inc;
-       enum { BW20, BW40PLUS, BW40MINUS, BW80, BW2160, BW160, BW80P80 } bw;
-};
-
-static const struct p2p_oper_class_map op_class[] = {
-       { HOSTAPD_MODE_IEEE80211G, 81, 1, 13, 1, BW20 },
-#if 0 /* Do not enable HT40 on 2 GHz for now */
-       { HOSTAPD_MODE_IEEE80211G, 83, 1, 9, 1, BW40PLUS },
-       { HOSTAPD_MODE_IEEE80211G, 84, 5, 13, 1, BW40MINUS },
-#endif
-       { HOSTAPD_MODE_IEEE80211A, 115, 36, 48, 4, BW20 },
-       { HOSTAPD_MODE_IEEE80211A, 124, 149, 161, 4, BW20 },
-       { HOSTAPD_MODE_IEEE80211A, 125, 149, 169, 4, BW20 },
-       { HOSTAPD_MODE_IEEE80211A, 116, 36, 44, 8, BW40PLUS },
-       { HOSTAPD_MODE_IEEE80211A, 117, 40, 48, 8, BW40MINUS },
-       { HOSTAPD_MODE_IEEE80211A, 126, 149, 157, 8, BW40PLUS },
-       { HOSTAPD_MODE_IEEE80211A, 127, 153, 161, 8, BW40MINUS },
-
-       /*
-        * IEEE P802.11ac/D7.0 Table E-4 actually talks about channel center
-        * frequency index 42, 58, 106, 122, 138, 155 with channel spacing of
-        * 80 MHz, but currently use the following definition for simplicity
-        * (these center frequencies are not actual channels, which makes
-        * has_channel() fail). wpas_p2p_verify_80mhz() should take care of
-        * removing invalid channels.
-        */
-       { HOSTAPD_MODE_IEEE80211A, 128, 36, 161, 4, BW80 },
-       { HOSTAPD_MODE_IEEE80211A, 130, 36, 161, 4, BW80P80 },
-       { HOSTAPD_MODE_IEEE80211A, 129, 50, 114, 16, BW160 },
-       { HOSTAPD_MODE_IEEE80211AD, 180, 1, 4, 1, BW2160 },
-       { -1, 0, 0, 0, 0, BW20 }
-};
-
-
 static int wpas_p2p_get_center_80mhz(struct wpa_supplicant *wpa_s,
                                     struct hostapd_hw_modes *mode,
                                     u8 channel)
@@ -3540,11 +3526,14 @@ static int wpas_p2p_setup_channels(struct wpa_supplicant *wpa_s,
 
        cla = cli_cla = 0;
 
-       for (op = 0; op_class[op].op_class; op++) {
-               const struct p2p_oper_class_map *o = &op_class[op];
+       for (op = 0; global_op_class[op].op_class; op++) {
+               const struct oper_class_map *o = &global_op_class[op];
                u8 ch;
                struct p2p_reg_class *reg = NULL, *cli_reg = NULL;
 
+               if (o->p2p == NO_P2P_SUPP)
+                       continue;
+
                mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, o->mode);
                if (mode == NULL)
                        continue;
@@ -3599,10 +3588,13 @@ int wpas_p2p_get_ht40_mode(struct wpa_supplicant *wpa_s,
        int op;
        enum chan_allowed ret;
 
-       for (op = 0; op_class[op].op_class; op++) {
-               const struct p2p_oper_class_map *o = &op_class[op];
+       for (op = 0; global_op_class[op].op_class; op++) {
+               const struct oper_class_map *o = &global_op_class[op];
                u8 ch;
 
+               if (o->p2p == NO_P2P_SUPP)
+                       continue;
+
                for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) {
                        if (o->mode != HOSTAPD_MODE_IEEE80211A ||
                            (o->bw != BW40PLUS && o->bw != BW40MINUS) ||
@@ -3767,6 +3759,7 @@ int wpas_p2p_add_p2pdev_interface(struct wpa_supplicant *wpa_s,
                return -1;
        }
 
+       p2pdev_wpa_s->p2pdev = p2pdev_wpa_s;
        wpa_s->pending_interface_name[0] = '\0';
        return 0;
 }
@@ -4548,8 +4541,7 @@ static void wpas_p2p_deinit_global(struct wpa_global *global)
 
 static int wpas_p2p_create_iface(struct wpa_supplicant *wpa_s)
 {
-       if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
-           wpa_s->conf->p2p_no_group_iface)
+       if (wpa_s->conf->p2p_no_group_iface)
                return 0; /* separate interface disabled per configuration */
        if (wpa_s->drv_flags &
            (WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE |
@@ -4630,7 +4622,7 @@ static void wpas_p2p_check_join_scan_limit(struct wpa_supplicant *wpa_s)
                                       MAC2STR(wpa_s->pending_join_dev_addr));
                        return;
                }
-               wpa_msg_global(wpa_s->parent, MSG_INFO,
+               wpa_msg_global(wpa_s->p2pdev, MSG_INFO,
                               P2P_EVENT_GROUP_FORMATION_FAILURE);
                wpas_notify_p2p_group_formation_failure(wpa_s, "");
        }
@@ -4766,7 +4758,7 @@ static void wpas_p2p_scan_res_join(struct wpa_supplicant *wpa_s,
                if (join < 0) {
                        wpa_printf(MSG_DEBUG, "P2P: Peer was not found to be "
                                   "running a GO -> use GO Negotiation");
-                       wpa_msg_global(wpa_s->parent, MSG_INFO,
+                       wpa_msg_global(wpa_s->p2pdev, MSG_INFO,
                                       P2P_EVENT_FALLBACK_TO_GO_NEG
                                       "reason=peer-not-running-GO");
                        wpas_p2p_connect(wpa_s, wpa_s->pending_join_dev_addr,
@@ -4779,7 +4771,8 @@ static void wpas_p2p_scan_res_join(struct wpa_supplicant *wpa_s,
                                         wpa_s->p2p_pd_before_go_neg,
                                         wpa_s->p2p_go_ht40,
                                         wpa_s->p2p_go_vht,
-                                        wpa_s->p2p_go_max_oper_chwidth);
+                                        wpa_s->p2p_go_max_oper_chwidth,
+                                        NULL, 0);
                        return;
                }
 
@@ -4787,7 +4780,7 @@ static void wpas_p2p_scan_res_join(struct wpa_supplicant *wpa_s,
                           "try to join the group", join ? "" :
                           " in older scan");
                if (!join) {
-                       wpa_msg_global(wpa_s->parent, MSG_INFO,
+                       wpa_msg_global(wpa_s->p2pdev, MSG_INFO,
                                       P2P_EVENT_FALLBACK_TO_GO_NEG_ENABLED);
                        wpa_s->p2p_fallback_to_go_neg = 1;
                }
@@ -4825,8 +4818,7 @@ static void wpas_p2p_scan_res_join(struct wpa_supplicant *wpa_s,
                bss = wpa_bss_get(wpa_s, wpa_s->pending_join_iface_addr,
                                  wpa_s->p2p_join_ssid,
                                  wpa_s->p2p_join_ssid_len);
-       }
-       if (!bss) {
+       } else if (!bss) {
                wpa_printf(MSG_DEBUG, "P2P: Trying to find target GO BSS entry based on BSSID "
                           MACSTR, MAC2STR(wpa_s->pending_join_iface_addr));
                bss = wpa_bss_get_bssid_latest(wpa_s,
@@ -4857,7 +4849,7 @@ static void wpas_p2p_scan_res_join(struct wpa_supplicant *wpa_s,
                u16 method;
 
                if (wpas_check_freq_conflict(wpa_s, freq) > 0) {
-                       wpa_msg_global(wpa_s->parent, MSG_INFO,
+                       wpa_msg_global(wpa_s->p2pdev, MSG_INFO,
                                       P2P_EVENT_GROUP_FORMATION_FAILURE
                                       "reason=FREQ_CONFLICT");
                        wpas_notify_p2p_group_formation_failure(
@@ -5304,6 +5296,8 @@ exit_free:
  * @vht:  Start GO with VHT support
  * @vht_chwidth: Channel width supported by GO operating with VHT support
  *     (VHT_CHANWIDTH_*).
+ * @group_ssid: Specific Group SSID for join or %NULL if not set
+ * @group_ssid_len: Length of @group_ssid in octets
  * Returns: 0 or new PIN (if pin was %NULL) on success, -1 on unspecified
  *     failure, -2 on failure due to channel not currently available,
  *     -3 if forced channel is not supported
@@ -5313,7 +5307,8 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
                     int persistent_group, int auto_join, int join, int auth,
                     int go_intent, int freq, unsigned int vht_center_freq2,
                     int persistent_id, int pd, int ht40, int vht,
-                    unsigned int vht_chwidth)
+                    unsigned int vht_chwidth, const u8 *group_ssid,
+                    size_t group_ssid_len)
 {
        int force_freq = 0, pref_freq = 0;
        int ret = 0, res;
@@ -5361,7 +5356,8 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
        if (pin)
                os_strlcpy(wpa_s->p2p_pin, pin, sizeof(wpa_s->p2p_pin));
        else if (wps_method == WPS_PIN_DISPLAY) {
-               ret = wps_generate_pin();
+               if (wps_generate_pin((unsigned int *) &ret) < 0)
+                       return -1;
                res = os_snprintf(wpa_s->p2p_pin, sizeof(wpa_s->p2p_pin),
                                  "%08d", ret);
                if (os_snprintf_error(sizeof(wpa_s->p2p_pin), res))
@@ -5396,7 +5392,8 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
                }
                wpa_s->user_initiated_pd = 1;
                if (wpas_p2p_join(wpa_s, iface_addr, dev_addr, wps_method,
-                                 auto_join, freq, NULL, 0) < 0)
+                                 auto_join, freq,
+                                 group_ssid, group_ssid_len) < 0)
                        return -1;
                return ret;
        }
@@ -5426,7 +5423,10 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
 
                if_addr = wpa_s->pending_interface_addr;
        } else {
-               if_addr = wpa_s->own_addr;
+               if (wpa_s->p2p_mgmt)
+                       if_addr = wpa_s->parent->own_addr;
+               else
+                       if_addr = wpa_s->own_addr;
                os_memset(wpa_s->go_dev_addr, 0, ETH_ALEN);
        }
 
@@ -5972,9 +5972,20 @@ wpas_p2p_get_group_iface(struct wpa_supplicant *wpa_s, int addr_allocated,
        struct wpa_supplicant *group_wpa_s;
 
        if (!wpas_p2p_create_iface(wpa_s)) {
-               wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Use same interface for group "
-                       "operations");
+               if (wpa_s->p2p_mgmt) {
+                       /*
+                        * We may be called on the p2p_dev interface which
+                        * cannot be used for group operations, so always use
+                        * the primary interface.
+                        */
+                       wpa_s->parent->p2pdev = wpa_s;
+                       wpa_s = wpa_s->parent;
+               }
+               wpa_dbg(wpa_s, MSG_DEBUG,
+                       "P2P: Use primary interface for group operations");
                wpa_s->p2p_first_connection_timeout = 0;
+               if (wpa_s != wpa_s->p2pdev)
+                       wpas_p2p_clone_config_dh(wpa_s, wpa_s->p2pdev);
                return wpa_s;
        }
 
@@ -6113,11 +6124,11 @@ static int wpas_start_p2p_client(struct wpa_supplicant *wpa_s,
        wpa_s->p2p_go_group_formation_completed = 0;
        wpa_s->global->p2p_group_formation = wpa_s;
 
-       eloop_cancel_timeout(wpas_p2p_group_formation_timeout, wpa_s->parent,
+       eloop_cancel_timeout(wpas_p2p_group_formation_timeout, wpa_s->p2pdev,
                             NULL);
        eloop_register_timeout(P2P_MAX_INITIAL_CONN_WAIT, 0,
                               wpas_p2p_group_formation_timeout,
-                              wpa_s->parent, NULL);
+                              wpa_s->p2pdev, NULL);
        wpa_supplicant_select_network(wpa_s, ssid);
 
        return 0;
@@ -6144,7 +6155,7 @@ int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s,
                           "already running");
                if (go == 0 &&
                    eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
-                                        wpa_s->parent, NULL)) {
+                                        wpa_s->p2pdev, NULL)) {
                        /*
                         * This can happen if Invitation Response frame was lost
                         * and the peer (GO of a persistent group) tries to
@@ -6157,7 +6168,7 @@ int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s,
                                   "P2P: Reschedule group formation timeout since peer is still trying to invite us");
                        eloop_register_timeout(P2P_MAX_INITIAL_CONN_WAIT, 0,
                                               wpas_p2p_group_formation_timeout,
-                                              wpa_s->parent, NULL);
+                                              wpa_s->p2pdev, NULL);
                }
                return 0;
        }
@@ -6340,7 +6351,7 @@ void wpas_p2p_wps_success(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
                p2p_clear_provisioning_info(wpa_s->global->p2p, go_dev_addr);
        }
 
-       eloop_cancel_timeout(wpas_p2p_group_formation_timeout, wpa_s->parent,
+       eloop_cancel_timeout(wpas_p2p_group_formation_timeout, wpa_s->p2pdev,
                             NULL);
        wpa_s->p2p_go_group_formation_completed = 1;
        if (ssid && ssid->mode == WPAS_MODE_INFRA) {
@@ -6355,7 +6366,7 @@ void wpas_p2p_wps_success(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
                        P2P_MAX_INITIAL_CONN_WAIT);
                eloop_register_timeout(P2P_MAX_INITIAL_CONN_WAIT, 0,
                                       wpas_p2p_group_formation_timeout,
-                                      wpa_s->parent, NULL);
+                                      wpa_s->p2pdev, NULL);
                /* Complete group formation on successful data connection. */
                wpa_s->p2p_go_group_formation_completed = 0;
        } else if (ssid) {
@@ -6369,7 +6380,7 @@ void wpas_p2p_wps_success(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
                        P2P_MAX_INITIAL_CONN_WAIT_GO);
                eloop_register_timeout(P2P_MAX_INITIAL_CONN_WAIT_GO, 0,
                                       wpas_p2p_group_formation_timeout,
-                                      wpa_s->parent, NULL);
+                                      wpa_s->p2pdev, NULL);
                /*
                 * Complete group formation on first successful data connection
                 */
@@ -6408,7 +6419,7 @@ void wpas_p2p_wps_failed(struct wpa_supplicant *wpa_s,
                wpa_s->global->p2p_fail_on_wps_complete = 1;
                eloop_deplete_timeout(0, 50000,
                                      wpas_p2p_group_formation_timeout,
-                                     wpa_s->parent, NULL);
+                                     wpa_s->p2pdev, NULL);
        }
 }
 
@@ -6501,8 +6512,12 @@ static void wpas_p2p_clear_pending_action_tx(struct wpa_supplicant *wpa_s)
        if (!offchannel_pending_action_tx(wpa_s))
                return;
 
-       if (wpa_s->p2p_send_action_work)
+       if (wpa_s->p2p_send_action_work) {
                wpas_p2p_free_send_action_work(wpa_s);
+               eloop_cancel_timeout(wpas_p2p_send_action_work_timeout,
+                                    wpa_s, NULL);
+               offchannel_send_action_done(wpa_s);
+       }
 
        wpa_printf(MSG_DEBUG, "P2P: Drop pending Action TX due to new "
                   "operation request");
@@ -6770,7 +6785,9 @@ int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
                                return -1;
                        }
                        bssid = wpa_s->pending_interface_addr;
-               } else
+               } else if (wpa_s->p2p_mgmt)
+                       bssid = wpa_s->parent->own_addr;
+               else
                        bssid = wpa_s->own_addr;
        } else {
                role = P2P_INVITE_ROLE_CLIENT;
@@ -6848,7 +6865,7 @@ int wpas_p2p_invite_group(struct wpa_supplicant *wpa_s, const char *ifname,
 
        wpa_s->global->p2p_invite_group = wpa_s;
        persistent = ssid->p2p_persistent_group &&
-               wpas_p2p_get_persistent(wpa_s->parent, peer_addr,
+               wpas_p2p_get_persistent(wpa_s->p2pdev, peer_addr,
                                        ssid->ssid, ssid->ssid_len);
 
        if (ssid->mode == WPAS_MODE_P2P_GO) {
@@ -6871,7 +6888,7 @@ int wpas_p2p_invite_group(struct wpa_supplicant *wpa_s, const char *ifname,
                freq = wpa_s->current_bss ? wpa_s->current_bss->freq :
                        (int) wpa_s->assoc_freq;
        }
-       wpa_s->parent->pending_invite_ssid_id = -1;
+       wpa_s->p2pdev->pending_invite_ssid_id = -1;
 
        if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
                return -1;
@@ -6902,7 +6919,7 @@ void wpas_p2p_completed(struct wpa_supplicant *wpa_s)
 
        if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GROUP_FORMATION) {
                eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
-                                    wpa_s->parent, NULL);
+                                    wpa_s->p2pdev, NULL);
        }
 
        if (!wpa_s->show_group_started || !ssid)
@@ -6953,7 +6970,7 @@ void wpas_p2p_completed(struct wpa_supplicant *wpa_s)
                               ip_addr);
 
        if (persistent)
-               network_id = wpas_p2p_store_persistent_group(wpa_s->parent,
+               network_id = wpas_p2p_store_persistent_group(wpa_s->p2pdev,
                                                             ssid, go_dev_addr);
        if (network_id < 0)
                network_id = ssid->id;
@@ -7290,7 +7307,7 @@ int wpas_p2p_set_cross_connect(struct wpa_supplicant *wpa_s, int enabled)
 
                        iface->cross_connect_enabled = 0;
                        iface->cross_connect_in_use = 0;
-                       wpa_msg_global(iface->parent, MSG_INFO,
+                       wpa_msg_global(iface->p2pdev, MSG_INFO,
                                       P2P_EVENT_CROSS_CONNECT_DISABLE "%s %s",
                                       iface->ifname,
                                       iface->cross_connect_uplink);
@@ -7320,7 +7337,7 @@ static void wpas_p2p_enable_cross_connect(struct wpa_supplicant *uplink)
                        continue;
 
                iface->cross_connect_in_use = 1;
-               wpa_msg_global(iface->parent, MSG_INFO,
+               wpa_msg_global(iface->p2pdev, MSG_INFO,
                               P2P_EVENT_CROSS_CONNECT_ENABLE "%s %s",
                               iface->ifname, iface->cross_connect_uplink);
        }
@@ -7340,7 +7357,7 @@ static void wpas_p2p_disable_cross_connect(struct wpa_supplicant *uplink)
                if (!iface->cross_connect_in_use)
                        continue;
 
-               wpa_msg_global(iface->parent, MSG_INFO,
+               wpa_msg_global(iface->p2pdev, MSG_INFO,
                               P2P_EVENT_CROSS_CONNECT_DISABLE "%s %s",
                               iface->ifname, iface->cross_connect_uplink);
                iface->cross_connect_in_use = 0;
@@ -7403,7 +7420,7 @@ static void wpas_p2p_cross_connect_setup(struct wpa_supplicant *wpa_s)
                        break;
 
                wpa_s->cross_connect_in_use = 1;
-               wpa_msg_global(wpa_s->parent, MSG_INFO,
+               wpa_msg_global(wpa_s->p2pdev, MSG_INFO,
                               P2P_EVENT_CROSS_CONNECT_ENABLE "%s %s",
                               wpa_s->ifname, wpa_s->cross_connect_uplink);
                break;
@@ -7419,8 +7436,8 @@ int wpas_p2p_notif_pbc_overlap(struct wpa_supplicant *wpa_s)
 
        wpa_printf(MSG_DEBUG, "P2P: Terminate connection due to WPS PBC "
                   "session overlap");
-       if (wpa_s != wpa_s->parent)
-               wpa_msg_ctrl(wpa_s->parent, MSG_INFO, WPS_EVENT_OVERLAP);
+       if (wpa_s != wpa_s->p2pdev)
+               wpa_msg_ctrl(wpa_s->p2pdev, MSG_INFO, WPS_EVENT_OVERLAP);
        wpas_p2p_group_formation_failed(wpa_s, 0);
        return 1;
 }
@@ -7527,7 +7544,7 @@ int wpas_p2p_cancel(struct wpa_supplicant *wpa_s)
                                   wpa_s->ifname);
                        found = 1;
                        eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
-                                            wpa_s->parent, NULL);
+                                            wpa_s->p2pdev, NULL);
                        if (wpa_s->p2p_in_provisioning) {
                                wpas_group_formation_completed(wpa_s, 0, 0);
                                break;
@@ -7657,7 +7674,7 @@ void wpas_p2p_network_removed(struct wpa_supplicant *wpa_s,
 {
        if (wpa_s->p2p_in_provisioning && ssid->p2p_group &&
            eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
-                                wpa_s->parent, NULL) > 0) {
+                                wpa_s->p2pdev, NULL) > 0) {
                /**
                 * Remove the network by scheduling the group formation
                 * timeout to happen immediately. The teardown code
@@ -7669,7 +7686,7 @@ void wpas_p2p_network_removed(struct wpa_supplicant *wpa_s,
                wpa_printf(MSG_DEBUG, "P2P: Canceled group formation due to "
                           "P2P group network getting removed");
                eloop_register_timeout(0, 0, wpas_p2p_group_formation_timeout,
-                                      wpa_s->parent, NULL);
+                                      wpa_s->p2pdev, NULL);
        }
 }
 
@@ -7713,7 +7730,7 @@ void wpas_p2p_notify_ap_sta_authorized(struct wpa_supplicant *wpa_s,
                                       const u8 *addr)
 {
        if (eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
-                                wpa_s->parent, NULL) > 0) {
+                                wpa_s->p2pdev, NULL) > 0) {
                /*
                 * This can happen if WPS provisioning step is not terminated
                 * cleanly (e.g., P2P Client does not send WSC_Done). Since the
@@ -7774,7 +7791,7 @@ static int wpas_p2p_fallback_to_go_neg(struct wpa_supplicant *wpa_s,
                         wpa_s->p2p_pd_before_go_neg,
                         wpa_s->p2p_go_ht40,
                         wpa_s->p2p_go_vht,
-                        wpa_s->p2p_go_max_oper_chwidth);
+                        wpa_s->p2p_go_max_oper_chwidth, NULL, 0);
        return ret;
 }
 
@@ -7792,7 +7809,7 @@ int wpas_p2p_scan_no_go_seen(struct wpa_supplicant *wpa_s)
 
        wpa_dbg(wpa_s, MSG_DEBUG, "P2P: GO not found for p2p_connect-auto - "
                "fallback to GO Negotiation");
-       wpa_msg_global(wpa_s->parent, MSG_INFO, P2P_EVENT_FALLBACK_TO_GO_NEG
+       wpa_msg_global(wpa_s->p2pdev, MSG_INFO, P2P_EVENT_FALLBACK_TO_GO_NEG
                       "reason=GO-not-found");
        res = wpas_p2p_fallback_to_go_neg(wpa_s, 1);
 
@@ -7901,7 +7918,7 @@ void wpas_p2p_new_psk_cb(struct wpa_supplicant *wpa_s, const u8 *mac_addr,
                return;
        }
 
-       persistent = wpas_p2p_get_persistent(wpa_s->parent, NULL, ssid->ssid,
+       persistent = wpas_p2p_get_persistent(wpa_s->p2pdev, NULL, ssid->ssid,
                                             ssid->ssid_len);
        if (!persistent) {
                wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Could not find persistent group information to store the new PSK");
@@ -7930,7 +7947,7 @@ void wpas_p2p_new_psk_cb(struct wpa_supplicant *wpa_s, const u8 *mac_addr,
                os_free(last);
        }
 
-       wpas_p2p_remove_psk_entry(wpa_s->parent, persistent,
+       wpas_p2p_remove_psk_entry(wpa_s->p2pdev, persistent,
                                  p2p_dev_addr ? p2p_dev_addr : mac_addr,
                                  p2p_dev_addr == NULL);
        if (p2p_dev_addr) {
@@ -7942,8 +7959,8 @@ void wpas_p2p_new_psk_cb(struct wpa_supplicant *wpa_s, const u8 *mac_addr,
        }
        dl_list_add(&persistent->psk_list, &p->list);
 
-       if (wpa_s->parent->conf->update_config &&
-           wpa_config_write(wpa_s->parent->confname, wpa_s->parent->conf))
+       if (wpa_s->p2pdev->conf->update_config &&
+           wpa_config_write(wpa_s->p2pdev->confname, wpa_s->p2pdev->conf))
                wpa_printf(MSG_DEBUG, "P2P: Failed to update configuration");
 }
 
@@ -8122,14 +8139,14 @@ int wpas_p2p_4way_hs_failed(struct wpa_supplicant *wpa_s)
 
                wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Two 4-way handshake failures for a P2P group - go_dev_addr="
                        MACSTR, MAC2STR(go_dev_addr));
-               persistent = wpas_p2p_get_persistent(wpa_s->parent, go_dev_addr,
+               persistent = wpas_p2p_get_persistent(wpa_s->p2pdev, go_dev_addr,
                                                     ssid->ssid,
                                                     ssid->ssid_len);
                if (persistent == NULL || persistent->mode != WPAS_MODE_INFRA) {
                        wpa_dbg(wpa_s, MSG_DEBUG, "P2P: No matching persistent group stored");
                        goto disconnect;
                }
-               wpa_msg_global(wpa_s->parent, MSG_INFO,
+               wpa_msg_global(wpa_s->p2pdev, MSG_INFO,
                               P2P_EVENT_PERSISTENT_PSK_FAIL "%d",
                               persistent->id);
        disconnect:
@@ -8309,7 +8326,9 @@ static int wpas_p2p_nfc_join_group(struct wpa_supplicant *wpa_s,
        return wpas_p2p_connect(wpa_s, params->peer->p2p_device_addr, NULL,
                                WPS_NFC, 0, 0, 1, 0, wpa_s->conf->p2p_go_intent,
                                params->go_freq, wpa_s->p2p_go_vht_center_freq2,
-                               -1, 0, 1, 1, wpa_s->p2p_go_max_oper_chwidth);
+                               -1, 0, 1, 1, wpa_s->p2p_go_max_oper_chwidth,
+                               params->go_ssid_len ? params->go_ssid : NULL,
+                               params->go_ssid_len);
 }
 
 
@@ -8386,7 +8405,8 @@ static int wpas_p2p_nfc_init_go_neg(struct wpa_supplicant *wpa_s,
        return wpas_p2p_connect(wpa_s, params->peer->p2p_device_addr, NULL,
                                WPS_NFC, 0, 0, 0, 0, wpa_s->conf->p2p_go_intent,
                                forced_freq, wpa_s->p2p_go_vht_center_freq2,
-                               -1, 0, 1, 1, wpa_s->p2p_go_max_oper_chwidth);
+                               -1, 0, 1, 1, wpa_s->p2p_go_max_oper_chwidth,
+                               NULL, 0);
 }
 
 
@@ -8401,7 +8421,8 @@ static int wpas_p2p_nfc_resp_go_neg(struct wpa_supplicant *wpa_s,
        res = wpas_p2p_connect(wpa_s, params->peer->p2p_device_addr, NULL,
                               WPS_NFC, 0, 0, 0, 1, wpa_s->conf->p2p_go_intent,
                               forced_freq, wpa_s->p2p_go_vht_center_freq2,
-                              -1, 0, 1, 1, wpa_s->p2p_go_max_oper_chwidth);
+                              -1, 0, 1, 1, wpa_s->p2p_go_max_oper_chwidth,
+                              NULL, 0);
        if (res)
                return res;
 
@@ -8692,7 +8713,9 @@ int wpas_p2p_nfc_tag_enabled(struct wpa_supplicant *wpa_s, int enabled)
                }
 
                if_addr = wpa_s->pending_interface_addr;
-       } else
+       } else if (wpa_s->p2p_mgmt)
+               if_addr = wpa_s->parent->own_addr;
+       else
                if_addr = wpa_s->own_addr;
 
        wpa_s->p2p_nfc_tag_enabled = enabled;