]> git.ipfire.org Git - thirdparty/hostap.git/blobdiff - wpa_supplicant/p2p_supplicant.c
tests: Additional eap_user_file parsing coverage
[thirdparty/hostap.git] / wpa_supplicant / p2p_supplicant.c
index 4f8e14ebf48851ac4df893e166524432c9da4901..55b3b08efe50b98c891916d25e56cf9e1b414325 100644 (file)
@@ -307,7 +307,14 @@ static void wpas_p2p_trigger_scan_cb(struct wpa_radio_work *work, int deinit)
                return;
        }
 
+       if (wpa_s->clear_driver_scan_cache) {
+               wpa_printf(MSG_DEBUG,
+                          "Request driver to clear scan cache due to local BSS flush");
+               params->only_new_results = 1;
+       }
        ret = wpa_drv_scan(wpa_s, params);
+       if (ret == 0)
+               wpa_s->curr_scan_cookie = params->scan_cookie;
        wpa_scan_free_params(params);
        work->ctx = NULL;
        if (ret) {
@@ -320,6 +327,7 @@ static void wpas_p2p_trigger_scan_cb(struct wpa_radio_work *work, int deinit)
        os_get_reltime(&wpa_s->scan_trigger_time);
        wpa_s->scan_res_handler = wpas_p2p_scan_res_handler;
        wpa_s->own_scan_requested = 1;
+       wpa_s->clear_driver_scan_cache = 0;
        wpa_s->p2p_scan_work = work;
 }
 
@@ -740,6 +748,7 @@ static u8 p2ps_group_capability(void *ctx, u8 incoming, u8 role,
                                conncap = P2PS_SETUP_GROUP_OWNER;
                                goto grp_owner;
                        }
+                       /* fall through */
 
                default:
                        return P2PS_SETUP_NONE;
@@ -807,7 +816,7 @@ grp_owner:
                                              wpa_s->own_addr);
                } else if (!s && !go_wpa_s) {
                        if (wpas_p2p_add_group_interface(wpa_s,
-                                                        WPA_IF_P2P_GO) < 0) {
+                                                        WPA_IF_P2P_GROUP) < 0) {
                                wpa_printf(MSG_ERROR,
                                           "P2P: Failed to allocate a new interface for the group");
                                return P2PS_SETUP_NONE;
@@ -971,6 +980,7 @@ static int wpas_p2p_group_delete(struct wpa_supplicant *wpa_s,
        os_free(wpa_s->p2p_group_common_freqs);
        wpa_s->p2p_group_common_freqs = NULL;
        wpa_s->p2p_group_common_freqs_num = 0;
+       wpa_s->p2p_go_do_acs = 0;
 
        wpa_s->waiting_presence_resp = 0;
 
@@ -1076,7 +1086,7 @@ static int wpas_p2p_persistent_group(struct wpa_supplicant *wpa_s,
                   "go_dev_addr=" MACSTR,
                   MAC2STR(bssid), group_capab, MAC2STR(go_dev_addr));
 
-       return group_capab & P2P_GROUP_CAPAB_PERSISTENT_GROUP;
+       return !!(group_capab & P2P_GROUP_CAPAB_PERSISTENT_GROUP);
 }
 
 
@@ -1301,7 +1311,6 @@ static void wpas_group_formation_completed(struct wpa_supplicant *wpa_s,
        int client;
        int persistent;
        u8 go_dev_addr[ETH_ALEN];
-       int network_id = -1;
 
        /*
         * This callback is likely called for the main interface. Update wpa_s
@@ -1313,6 +1322,10 @@ static void wpas_group_formation_completed(struct wpa_supplicant *wpa_s,
        if (wpa_s->p2p_go_group_formation_completed) {
                wpa_s->global->p2p_group_formation = NULL;
                wpa_s->p2p_in_provisioning = 0;
+       } else if (wpa_s->p2p_in_provisioning && !success) {
+               wpa_msg(wpa_s, MSG_DEBUG,
+                       "P2P: Stop provisioning state due to failure");
+               wpa_s->p2p_in_provisioning = 0;
        }
        wpa_s->p2p_in_invitation = 0;
        wpa_s->group_formation_reported = 1;
@@ -1376,16 +1389,15 @@ static void wpas_group_formation_completed(struct wpa_supplicant *wpa_s,
        }
 
        if (persistent)
-               network_id = wpas_p2p_store_persistent_group(wpa_s->p2pdev,
-                                                            ssid, go_dev_addr);
+               wpas_p2p_store_persistent_group(wpa_s->p2pdev,
+                                               ssid, go_dev_addr);
        else {
                os_free(wpa_s->global->add_psk);
                wpa_s->global->add_psk = NULL;
        }
-       if (network_id < 0 && ssid)
-               network_id = ssid->id;
+
        if (!client) {
-               wpas_notify_p2p_group_started(wpa_s, ssid, network_id, 0);
+               wpas_notify_p2p_group_started(wpa_s, ssid, persistent, 0, NULL);
                os_get_reltime(&wpa_s->global->p2p_go_wait_client);
        }
 }
@@ -1544,7 +1556,7 @@ static int wpas_send_action_work(struct wpa_supplicant *wpa_s,
 {
        struct send_action_work *awork;
 
-       if (wpa_s->p2p_send_action_work) {
+       if (radio_work_pending(wpa_s, "p2p-send-action")) {
                wpa_printf(MSG_DEBUG, "P2P: Cannot schedule new p2p-send-action work since one is already pending");
                return -1;
        }
@@ -1561,7 +1573,7 @@ static int wpas_send_action_work(struct wpa_supplicant *wpa_s,
        awork->wait_time = wait_time;
        os_memcpy(awork->buf, buf, len);
 
-       if (radio_add_work(wpa_s, freq, "p2p-send-action", 0,
+       if (radio_add_work(wpa_s, freq, "p2p-send-action", 1,
                           wpas_send_action_cb, awork) < 0) {
                os_free(awork);
                return -1;
@@ -1573,20 +1585,27 @@ static int wpas_send_action_work(struct wpa_supplicant *wpa_s,
 
 static int wpas_send_action(void *ctx, unsigned int freq, const u8 *dst,
                            const u8 *src, const u8 *bssid, const u8 *buf,
-                           size_t len, unsigned int wait_time)
+                           size_t len, unsigned int wait_time, int *scheduled)
 {
        struct wpa_supplicant *wpa_s = ctx;
        int listen_freq = -1, send_freq = -1;
 
+       if (scheduled)
+               *scheduled = 0;
        if (wpa_s->p2p_listen_work)
                listen_freq = wpa_s->p2p_listen_work->freq;
        if (wpa_s->p2p_send_action_work)
                send_freq = wpa_s->p2p_send_action_work->freq;
        if (listen_freq != (int) freq && send_freq != (int) freq) {
-               wpa_printf(MSG_DEBUG, "P2P: Schedule new radio work for Action frame TX (listen_freq=%d send_freq=%d)",
-                          listen_freq, send_freq);
-               return wpas_send_action_work(wpa_s, freq, dst, src, bssid, buf,
-                                            len, wait_time);
+               int res;
+
+               wpa_printf(MSG_DEBUG, "P2P: Schedule new radio work for Action frame TX (listen_freq=%d send_freq=%d freq=%u)",
+                          listen_freq, send_freq, freq);
+               res = wpas_send_action_work(wpa_s, freq, dst, src, bssid, buf,
+                                           len, wait_time);
+               if (res == 0 && scheduled)
+                       *scheduled = 1;
+               return res;
        }
 
        wpa_printf(MSG_DEBUG, "P2P: Use ongoing radio work for Action frame TX");
@@ -1638,7 +1657,7 @@ static void wpas_start_wps_enrollee(struct wpa_supplicant *wpa_s,
        wpa_supplicant_ap_deinit(wpa_s);
        wpas_copy_go_neg_results(wpa_s, res);
        if (res->wps_method == WPS_PBC) {
-               wpas_wps_start_pbc(wpa_s, res->peer_interface_addr, 1);
+               wpas_wps_start_pbc(wpa_s, res->peer_interface_addr, 1, 0);
 #ifdef CONFIG_WPS_NFC
        } else if (res->wps_method == WPS_NFC) {
                wpas_wps_start_nfc(wpa_s, res->peer_device_addr,
@@ -1703,14 +1722,23 @@ static void wpas_p2p_add_psk_list(struct wpa_supplicant *wpa_s,
 
 static void p2p_go_dump_common_freqs(struct wpa_supplicant *wpa_s)
 {
+       char buf[20 + P2P_MAX_CHANNELS * 6];
+       char *pos, *end;
        unsigned int i;
+       int res;
 
-       wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Common group frequencies (len=%u):",
-               wpa_s->p2p_group_common_freqs_num);
+       pos = buf;
+       end = pos + sizeof(buf);
+       for (i = 0; i < wpa_s->p2p_group_common_freqs_num; i++) {
+               res = os_snprintf(pos, end - pos, " %d",
+                                 wpa_s->p2p_group_common_freqs[i]);
+               if (os_snprintf_error(end - pos, res))
+                       break;
+               pos += res;
+       }
+       *pos = '\0';
 
-       for (i = 0; i < wpa_s->p2p_group_common_freqs_num; i++)
-               wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d",
-                       i, wpa_s->p2p_group_common_freqs[i]);
+       wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Common group frequencies:%s", buf);
 }
 
 
@@ -1750,7 +1778,6 @@ static void p2p_go_configured(void *ctx, void *data)
        struct wpa_supplicant *wpa_s = ctx;
        struct p2p_go_neg_results *params = data;
        struct wpa_ssid *ssid;
-       int network_id = -1;
 
        wpa_s->ap_configured_cb = NULL;
        wpa_s->ap_configured_cb_ctx = NULL;
@@ -1797,14 +1824,15 @@ static void p2p_go_configured(void *ctx, void *data)
 
                os_get_reltime(&wpa_s->global->p2p_go_wait_client);
                if (params->persistent_group) {
-                       network_id = wpas_p2p_store_persistent_group(
+                       wpas_p2p_store_persistent_group(
                                wpa_s->p2pdev, ssid,
                                wpa_s->global->p2p_dev_addr);
                        wpas_p2p_add_psk_list(wpa_s, ssid);
                }
-               if (network_id < 0)
-                       network_id = ssid->id;
-               wpas_notify_p2p_group_started(wpa_s, ssid, network_id, 0);
+
+               wpas_notify_p2p_group_started(wpa_s, ssid,
+                                             params->persistent_group, 0,
+                                             NULL);
                wpas_p2p_cross_connect_setup(wpa_s);
                wpas_p2p_set_group_idle_timeout(wpa_s);
 
@@ -1884,7 +1912,7 @@ static void wpas_start_wps_go(struct wpa_supplicant *wpa_s,
        wpa_config_set_network_defaults(ssid);
        ssid->temporary = 1;
        ssid->p2p_group = 1;
-       ssid->p2p_persistent_group = params->persistent_group;
+       ssid->p2p_persistent_group = !!params->persistent_group;
        ssid->mode = group_formation ? WPAS_MODE_P2P_GROUP_FORMATION :
                WPAS_MODE_P2P_GO;
        ssid->frequency = params->freq;
@@ -1892,6 +1920,7 @@ static void wpas_start_wps_go(struct wpa_supplicant *wpa_s,
        ssid->vht = params->vht;
        ssid->max_oper_chwidth = params->max_oper_chwidth;
        ssid->vht_center_freq2 = params->vht_center_freq2;
+       ssid->he = params->he;
        ssid->ssid = os_zalloc(params->ssid_len + 1);
        if (ssid->ssid) {
                os_memcpy(ssid->ssid, params->ssid, params->ssid_len);
@@ -1951,7 +1980,12 @@ static void wpas_p2p_clone_config(struct wpa_supplicant *dst,
        d = dst->conf;
        s = src->conf;
 
-#define C(n) if (s->n) d->n = os_strdup(s->n)
+#define C(n)                            \
+do {                                    \
+       if (s->n && !d->n)              \
+               d->n = os_strdup(s->n); \
+} while (0)
+
        C(device_name);
        C(manufacturer);
        C(model_name);
@@ -1979,28 +2013,19 @@ static void wpas_p2p_clone_config(struct wpa_supplicant *dst,
        d->disable_scan_offload = s->disable_scan_offload;
        d->passive_scan = s->passive_scan;
 
-       if (s->wps_nfc_dh_privkey && s->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);
-       }
-       d->p2p_cli_probe = s->p2p_cli_probe;
-}
-
-
-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_pw_from_config) {
+               wpabuf_free(d->wps_nfc_dh_privkey);
+               wpabuf_free(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);
        }
+       d->p2p_cli_probe = s->p2p_cli_probe;
+       d->go_interworking = s->go_interworking;
+       d->go_access_network_type = s->go_access_network_type;
+       d->go_internet = s->go_internet;
+       d->go_venue_group = s->go_venue_group;
+       d->go_venue_type = s->go_venue_type;
 }
 
 
@@ -2059,6 +2084,13 @@ static int wpas_p2p_add_group_interface(struct wpa_supplicant *wpa_s,
                return -1;
        }
 
+       if (wpa_s->conf->p2p_interface_random_mac_addr) {
+               random_mac_addr(wpa_s->pending_interface_addr);
+               wpa_printf(MSG_DEBUG, "P2P: Generate random MAC address " MACSTR
+                          " for the group",
+                          MAC2STR(wpa_s->pending_interface_addr));
+       }
+
        if (force_ifname[0]) {
                wpa_printf(MSG_DEBUG, "P2P: Driver forced interface name %s",
                           force_ifname);
@@ -2137,6 +2169,29 @@ wpas_p2p_init_group_interface(struct wpa_supplicant *wpa_s, int go)
 
        wpas_p2p_clone_config(group_wpa_s, wpa_s);
 
+       if (wpa_s->conf->p2p_interface_random_mac_addr) {
+               if (wpa_drv_set_mac_addr(group_wpa_s,
+                                        wpa_s->pending_interface_addr) < 0) {
+                       wpa_msg(group_wpa_s, MSG_INFO,
+                               "Failed to set random MAC address");
+                       wpa_supplicant_remove_iface(wpa_s->global, group_wpa_s,
+                                                   0);
+                       return NULL;
+               }
+
+               if (wpa_supplicant_update_mac_addr(group_wpa_s) < 0) {
+                       wpa_msg(group_wpa_s, MSG_INFO,
+                               "Could not update MAC address information");
+                       wpa_supplicant_remove_iface(wpa_s->global, group_wpa_s,
+                                                   0);
+                       return NULL;
+               }
+
+               wpa_printf(MSG_DEBUG, "P2P: Using random MAC address " MACSTR
+                          " for the group",
+                          MAC2STR(wpa_s->pending_interface_addr));
+       }
+
        return group_wpa_s;
 }
 
@@ -2213,6 +2268,8 @@ static void wpas_go_neg_completed(void *ctx, struct p2p_go_neg_results *res)
                res->ht40 = 1;
        if (wpa_s->p2p_go_vht)
                res->vht = 1;
+       if (wpa_s->p2p_go_he)
+               res->he = 1;
        res->max_oper_chwidth = wpa_s->p2p_go_max_oper_chwidth;
        res->vht_center_freq2 = wpa_s->p2p_go_vht_center_freq2;
 
@@ -2255,7 +2312,7 @@ static void wpas_go_neg_completed(void *ctx, struct p2p_go_neg_results *res)
                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);
+                       wpas_p2p_clone_config(group_wpa_s, wpa_s);
        }
 
        group_wpa_s->p2p_in_provisioning = 1;
@@ -3032,7 +3089,7 @@ static void wpas_invitation_received(void *ctx, const u8 *sa, const u8 *bssid,
                                               MAC2STR(sa), s->id);
                        }
                        wpas_p2p_group_add_persistent(
-                               wpa_s, s, go, 0, op_freq, 0, 0, 0, 0, NULL,
+                               wpa_s, s, go, 0, op_freq, 0, 0, 0, 0, 0, NULL,
                                go ? P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE : 0,
                                1);
                } else if (bssid) {
@@ -3258,6 +3315,7 @@ static void wpas_invitation_result(void *ctx, int status, const u8 *bssid,
                                      wpa_s->p2p_go_vht_center_freq2,
                                      wpa_s->p2p_go_ht40, wpa_s->p2p_go_vht,
                                      wpa_s->p2p_go_max_oper_chwidth,
+                                     wpa_s->p2p_go_he,
                                      channels,
                                      ssid->mode == WPAS_MODE_P2P_GO ?
                                      P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE :
@@ -3343,10 +3401,6 @@ static int wpas_p2p_default_channels(struct wpa_supplicant *wpa_s,
 }
 
 
-enum chan_allowed {
-       NOT_ALLOWED, NO_IR, ALLOWED
-};
-
 static int has_channel(struct wpa_global *global,
                       struct hostapd_hw_modes *mode, u8 chan, int *flags)
 {
@@ -3381,7 +3435,7 @@ static int wpas_p2p_get_center_80mhz(struct wpa_supplicant *wpa_s,
                                     u8 channel)
 {
        u8 center_channels[] = { 42, 58, 106, 122, 138, 155 };
-       unsigned int i;
+       size_t i;
 
        if (mode->mode != HOSTAPD_MODE_IEEE80211A)
                return 0;
@@ -3906,6 +3960,10 @@ static int wpas_remove_stale_groups(void *ctx, const u8 *peer, const u8 *go,
 
                /* Remove stale persistent group */
                if (s->mode != WPAS_MODE_P2P_GO || s->num_p2p_clients <= 1) {
+                       wpa_dbg(wpa_s, MSG_DEBUG,
+                               "P2P: Remove stale persistent group id=%d",
+                               s->id);
+                       wpas_notify_persistent_group_removed(wpa_s, s);
                        wpa_config_remove_network(wpa_s->conf, s->id);
                        save_config = 1;
                        continue;
@@ -4029,6 +4087,11 @@ static void wpas_p2ps_prov_complete(void *ctx, u8 status, const u8 *dev,
 
                if (persistent_go && !persistent_go->num_p2p_clients) {
                        /* remove empty persistent GO */
+                       wpa_dbg(wpa_s, MSG_DEBUG,
+                               "P2P: Remove empty persistent group id=%d",
+                               persistent_go->id);
+                       wpas_notify_persistent_group_removed(wpa_s,
+                                                            persistent_go);
                        wpa_config_remove_network(wpa_s->conf,
                                                  persistent_go->id);
                }
@@ -4069,6 +4132,10 @@ static void wpas_p2ps_prov_complete(void *ctx, u8 status, const u8 *dev,
                /* Remove stale persistent group */
                if (stale->mode != WPAS_MODE_P2P_GO ||
                    stale->num_p2p_clients <= 1) {
+                       wpa_dbg(wpa_s, MSG_DEBUG,
+                               "P2P: Remove stale persistent group id=%d",
+                               stale->id);
+                       wpas_notify_persistent_group_removed(wpa_s, stale);
                        wpa_config_remove_network(wpa_s->conf, stale->id);
                } else {
                        size_t i;
@@ -4101,6 +4168,11 @@ static void wpas_p2ps_prov_complete(void *ctx, u8 status, const u8 *dev,
                if (persistent_go && s != persistent_go &&
                    !persistent_go->num_p2p_clients) {
                        /* remove empty persistent GO */
+                       wpa_dbg(wpa_s, MSG_DEBUG,
+                               "P2P: Remove empty persistent group id=%d",
+                               persistent_go->id);
+                       wpas_notify_persistent_group_removed(wpa_s,
+                                                            persistent_go);
                        wpa_config_remove_network(wpa_s->conf,
                                                  persistent_go->id);
                        /* Save config */
@@ -4118,6 +4190,9 @@ static void wpas_p2ps_prov_complete(void *ctx, u8 status, const u8 *dev,
                return;
        }
 
+       wpa_s->global->pending_p2ps_group = 0;
+       wpa_s->global->pending_p2ps_group_freq = 0;
+
        if (conncap == P2PS_SETUP_GROUP_OWNER) {
                /*
                 * We need to copy the interface name. Simply saving a
@@ -4128,8 +4203,10 @@ static void wpas_p2ps_prov_complete(void *ctx, u8 status, const u8 *dev,
 
                go_ifname[0] = '\0';
                if (!go_wpa_s) {
-                       wpa_s->global->pending_p2ps_group = 1;
-                       wpa_s->global->pending_p2ps_group_freq = freq;
+                       if (!response_done) {
+                               wpa_s->global->pending_p2ps_group = 1;
+                               wpa_s->global->pending_p2ps_group_freq = freq;
+                       }
 
                        if (!wpas_p2p_create_iface(wpa_s))
                                os_memcpy(go_ifname, wpa_s->ifname,
@@ -4153,13 +4230,14 @@ static void wpas_p2ps_prov_complete(void *ctx, u8 status, const u8 *dev,
                        if (response_done && persistent_go) {
                                wpas_p2p_group_add_persistent(
                                        wpa_s, persistent_go,
-                                       0, 0, freq, 0, 0, 0, 0, NULL,
+                                       0, 0, freq, 0, 0, 0, 0, 0, NULL,
                                        persistent_go->mode ==
                                        WPAS_MODE_P2P_GO ?
                                        P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE :
                                        0, 0);
                        } else if (response_done) {
-                               wpas_p2p_group_add(wpa_s, 1, freq, 0, 0, 0, 0);
+                               wpas_p2p_group_add(wpa_s, 1, freq,
+                                                  0, 0, 0, 0, 0);
                        }
 
                        if (passwd_id == DEV_PW_P2PS_DEFAULT) {
@@ -4208,6 +4286,10 @@ static void wpas_p2ps_prov_complete(void *ctx, u8 status, const u8 *dev,
 
        if (persistent_go && !persistent_go->num_p2p_clients) {
                /* remove empty persistent GO */
+               wpa_dbg(wpa_s, MSG_DEBUG,
+                       "P2P: Remove empty persistent group id=%d",
+                       persistent_go->id);
+               wpas_notify_persistent_group_removed(wpa_s, persistent_go);
                wpa_config_remove_network(wpa_s->conf, persistent_go->id);
        }
 
@@ -4271,11 +4353,11 @@ static int wpas_prov_disc_resp_cb(void *ctx)
 
        if (persistent_go) {
                wpas_p2p_group_add_persistent(
-                       wpa_s, persistent_go, 0, 0, 0, 0, 0, 0, 0, NULL,
+                       wpa_s, persistent_go, 0, 0, 0, 0, 0, 0, 0, 0, NULL,
                        persistent_go->mode == WPAS_MODE_P2P_GO ?
                        P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE : 0, 0);
        } else {
-               wpas_p2p_group_add(wpa_s, 1, freq, 0, 0, 0, 0);
+               wpas_p2p_group_add(wpa_s, 1, freq, 0, 0, 0, 0, 0);
        }
 
        return 1;
@@ -4293,6 +4375,54 @@ static int wpas_p2p_get_pref_freq_list(void *ctx, int go,
 }
 
 
+int wpas_p2p_mac_setup(struct wpa_supplicant *wpa_s)
+{
+       u8 addr[ETH_ALEN] = {0};
+
+       if (wpa_s->conf->p2p_device_random_mac_addr == 0)
+               return 0;
+
+       if (!wpa_s->conf->ssid) {
+               if (random_mac_addr(addr) < 0) {
+                       wpa_msg(wpa_s, MSG_INFO,
+                               "Failed to generate random MAC address");
+                       return -EINVAL;
+               }
+
+               /* Store generated MAC address. */
+               os_memcpy(wpa_s->conf->p2p_device_persistent_mac_addr, addr,
+                         ETH_ALEN);
+       } else {
+               /* If there are existing saved groups, restore last MAC address.
+                * if there is no last used MAC address, the last one is
+                * factory MAC. */
+               if (is_zero_ether_addr(
+                           wpa_s->conf->p2p_device_persistent_mac_addr))
+                       return 0;
+               os_memcpy(addr, wpa_s->conf->p2p_device_persistent_mac_addr,
+                         ETH_ALEN);
+               wpa_msg(wpa_s, MSG_DEBUG, "Restore last used MAC address.");
+       }
+
+       if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
+               wpa_msg(wpa_s, MSG_INFO,
+                       "Failed to set random MAC address");
+               return -EINVAL;
+       }
+
+       if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
+               wpa_msg(wpa_s, MSG_INFO,
+                       "Could not update MAC address information");
+               return -EINVAL;
+       }
+
+       wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
+               MAC2STR(addr));
+
+       return 0;
+}
+
+
 /**
  * wpas_p2p_init - Initialize P2P module for %wpa_supplicant
  * @global: Pointer to global data from wpa_supplicant_init()
@@ -4313,6 +4443,12 @@ int wpas_p2p_init(struct wpa_global *global, struct wpa_supplicant *wpa_s)
        if (global->p2p)
                return 0;
 
+       if (wpas_p2p_mac_setup(wpa_s) < 0) {
+               wpa_msg(wpa_s, MSG_ERROR,
+                       "Failed to initialize P2P random MAC address.");
+               return -1;
+       }
+
        os_memset(&p2p, 0, sizeof(p2p));
        p2p.cb_ctx = wpa_s;
        p2p.debug_print = wpas_p2p_debug_print;
@@ -4377,7 +4513,10 @@ int wpas_p2p_init(struct wpa_global *global, struct wpa_supplicant *wpa_s)
                 * channel.
                 */
                if (p2p_config_get_random_social(&p2p, &p2p.reg_class,
-                                                &p2p.channel) != 0) {
+                                                &p2p.channel,
+                                                &global->p2p_go_avoid_freq,
+                                                &global->p2p_disallow_freq) !=
+                   0) {
                        wpa_printf(MSG_INFO,
                                   "P2P: No social channels supported by the driver - do not enable P2P");
                        return 0;
@@ -4402,10 +4541,14 @@ int wpas_p2p_init(struct wpa_global *global, struct wpa_supplicant *wpa_s)
                 * other preference is indicated.
                 */
                if (p2p_config_get_random_social(&p2p, &p2p.op_reg_class,
-                                                &p2p.op_channel) != 0) {
-                       wpa_printf(MSG_ERROR,
+                                                &p2p.op_channel, NULL,
+                                                NULL) != 0) {
+                       wpa_printf(MSG_INFO,
                                   "P2P: Failed to select random social channel as operation channel");
-                       return -1;
+                       p2p.op_reg_class = 0;
+                       p2p.op_channel = 0;
+                       /* This will be overridden during group setup in
+                        * p2p_prepare_channel(), so allow setup to continue. */
                }
                p2p.cfg_op_channel = 0;
                wpa_printf(MSG_DEBUG, "P2P: Random operating channel: "
@@ -4798,6 +4941,7 @@ static void wpas_p2p_scan_res_join(struct wpa_supplicant *wpa_s,
                                         wpa_s->p2p_go_ht40,
                                         wpa_s->p2p_go_vht,
                                         wpa_s->p2p_go_max_oper_chwidth,
+                                        wpa_s->p2p_go_he,
                                         NULL, 0);
                        return;
                }
@@ -5015,6 +5159,12 @@ static void wpas_p2p_join_scan_req(struct wpa_supplicant *wpa_s, int freq,
        params.extra_ies = wpabuf_head(ies);
        params.extra_ies_len = wpabuf_len(ies);
 
+       if (wpa_s->clear_driver_scan_cache) {
+               wpa_printf(MSG_DEBUG,
+                          "Request driver to clear scan cache due to local BSS flush");
+               params.only_new_results = 1;
+       }
+
        /*
         * Run a scan to update BSS table and start Provision Discovery once
         * the new scan results become available.
@@ -5024,6 +5174,7 @@ static void wpas_p2p_join_scan_req(struct wpa_supplicant *wpa_s, int freq,
                os_get_reltime(&wpa_s->scan_trigger_time);
                wpa_s->scan_res_handler = wpas_p2p_scan_res_join;
                wpa_s->own_scan_requested = 1;
+               wpa_s->clear_driver_scan_cache = 0;
        }
 
        wpabuf_free(ies);
@@ -5088,17 +5239,18 @@ static int wpas_p2p_join_start(struct wpa_supplicant *wpa_s, int freq,
                os_memcpy(group->p2p_pin, wpa_s->p2p_pin,
                          sizeof(group->p2p_pin));
                group->p2p_wps_method = wpa_s->p2p_wps_method;
-       } else {
-               /*
-                * Need to mark the current interface for p2p_group_formation
-                * when a separate group interface is not used. This is needed
-                * to allow p2p_cancel stop a pending p2p_connect-join.
-                * wpas_p2p_init_group_interface() addresses this for the case
-                * where a separate group interface is used.
-                */
-               wpa_s->global->p2p_group_formation = wpa_s;
        }
 
+       /*
+        * Need to mark the current interface for p2p_group_formation
+        * when a separate group interface is not used. This is needed
+        * to allow p2p_cancel stop a pending p2p_connect-join.
+        * wpas_p2p_init_group_interface() addresses this for the case
+        * where a separate group interface is used.
+        */
+       if (group == wpa_s->parent)
+               wpa_s->global->p2p_group_formation = group;
+
        group->p2p_in_provisioning = 1;
        group->p2p_fallback_to_go_neg = wpa_s->p2p_fallback_to_go_neg;
 
@@ -5195,7 +5347,8 @@ static int wpas_p2p_setup_freqs(struct wpa_supplicant *wpa_s, int freq,
                        ret = p2p_supported_freq_cli(wpa_s->global->p2p, freq);
                if (!ret) {
                        if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) &&
-                           ieee80211_is_dfs(freq)) {
+                           ieee80211_is_dfs(freq, wpa_s->hw.modes,
+                                            wpa_s->hw.num_modes)) {
                                /*
                                 * If freq is a DFS channel and DFS is offloaded
                                 * to the driver, allow P2P GO to use it.
@@ -5248,9 +5401,11 @@ static int wpas_p2p_setup_freqs(struct wpa_supplicant *wpa_s, int freq,
                if (!res && max_pref_freq > 0) {
                        *num_pref_freq = max_pref_freq;
                        i = 0;
-                       while (wpas_p2p_disallowed_freq(wpa_s->global,
-                                                       pref_freq_list[i]) &&
-                              i < *num_pref_freq) {
+                       while (i < *num_pref_freq &&
+                              (!p2p_supported_freq(wpa_s->global->p2p,
+                                                   pref_freq_list[i]) ||
+                               wpas_p2p_disallowed_freq(wpa_s->global,
+                                                        pref_freq_list[i]))) {
                                wpa_printf(MSG_DEBUG,
                                           "P2P: preferred_freq_list[%d]=%d is disallowed",
                                           i, pref_freq_list[i]);
@@ -5323,7 +5478,7 @@ exit_free:
  * @ht40: Start GO with 40 MHz channel width
  * @vht:  Start GO with VHT support
  * @vht_chwidth: Channel width supported by GO operating with VHT support
- *     (VHT_CHANWIDTH_*).
+ *     (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
@@ -5335,7 +5490,7 @@ 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, const u8 *group_ssid,
+                    unsigned int vht_chwidth, int he, const u8 *group_ssid,
                     size_t group_ssid_len)
 {
        int force_freq = 0, pref_freq = 0;
@@ -5380,6 +5535,7 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
        wpa_s->p2p_go_vht = !!vht;
        wpa_s->p2p_go_vht_center_freq2 = vht_center_freq2;
        wpa_s->p2p_go_max_oper_chwidth = vht_chwidth;
+       wpa_s->p2p_go_he = !!he;
 
        if (pin)
                os_strlcpy(wpa_s->p2p_pin, pin, sizeof(wpa_s->p2p_pin));
@@ -5392,6 +5548,9 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
                        wpa_s->p2p_pin[sizeof(wpa_s->p2p_pin) - 1] = '\0';
                wpa_printf(MSG_DEBUG, "P2P: Randomly generated PIN: %s",
                           wpa_s->p2p_pin);
+       } else if (wps_method == WPS_P2PS) {
+               /* Force the P2Ps default PIN to be used */
+               os_strlcpy(wpa_s->p2p_pin, "12345670", sizeof(wpa_s->p2p_pin));
        } else
                wpa_s->p2p_pin[0] = '\0';
 
@@ -5610,9 +5769,11 @@ static int wpas_p2p_select_go_freq(struct wpa_supplicant *wpa_s, int freq)
                                                 &size, pref_freq_list);
                if (!res && size > 0) {
                        i = 0;
-                       while (wpas_p2p_disallowed_freq(wpa_s->global,
-                                                       pref_freq_list[i]) &&
-                              i < size) {
+                       while (i < size &&
+                              (!p2p_supported_freq(wpa_s->global->p2p,
+                                                   pref_freq_list[i]) ||
+                               wpas_p2p_disallowed_freq(wpa_s->global,
+                                                        pref_freq_list[i]))) {
                                wpa_printf(MSG_DEBUG,
                                           "P2P: preferred_freq_list[%d]=%d is disallowed",
                                           i, pref_freq_list[i]);
@@ -5676,7 +5837,8 @@ static int wpas_p2p_select_go_freq(struct wpa_supplicant *wpa_s, int freq)
 
        if (freq > 0 && !p2p_supported_freq_go(wpa_s->global->p2p, freq)) {
                if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) &&
-                   ieee80211_is_dfs(freq)) {
+                   ieee80211_is_dfs(freq, wpa_s->hw.modes,
+                                    wpa_s->hw.num_modes)) {
                        /*
                         * If freq is a DFS channel and DFS is offloaded to the
                         * driver, allow P2P GO to use it.
@@ -5714,30 +5876,6 @@ static void wpas_p2p_select_go_freq_no_pref(struct wpa_supplicant *wpa_s,
 {
        unsigned int i, r;
 
-       /* first try some random selection of the social channels */
-       if (os_get_random((u8 *) &r, sizeof(r)) < 0)
-               return;
-
-       for (i = 0; i < 3; i++) {
-               params->freq = 2412 + ((r + i) % 3) * 25;
-               if (wpas_p2p_supported_freq_go(wpa_s, channels, params->freq))
-                       goto out;
-       }
-
-       /* try all other channels in operating class 81 */
-       for (i = 0; i < 11; i++) {
-               params->freq = 2412 + i * 5;
-
-               /* skip social channels; covered in the previous loop */
-               if (params->freq == 2412 ||
-                   params->freq == 2437 ||
-                   params->freq == 2462)
-                       continue;
-
-               if (wpas_p2p_supported_freq_go(wpa_s, channels, params->freq))
-                       goto out;
-       }
-
        /* try all channels in operating class 115 */
        for (i = 0; i < 4; i++) {
                params->freq = 5180 + i * 20;
@@ -5772,6 +5910,30 @@ static void wpas_p2p_select_go_freq_no_pref(struct wpa_supplicant *wpa_s,
                        goto out;
        }
 
+       /* try some random selection of the social channels */
+       if (os_get_random((u8 *) &r, sizeof(r)) < 0)
+               return;
+
+       for (i = 0; i < 3; i++) {
+               params->freq = 2412 + ((r + i) % 3) * 25;
+               if (wpas_p2p_supported_freq_go(wpa_s, channels, params->freq))
+                       goto out;
+       }
+
+       /* try all other channels in operating class 81 */
+       for (i = 0; i < 11; i++) {
+               params->freq = 2412 + i * 5;
+
+               /* skip social channels; covered in the previous loop */
+               if (params->freq == 2412 ||
+                   params->freq == 2437 ||
+                   params->freq == 2462)
+                       continue;
+
+               if (wpas_p2p_supported_freq_go(wpa_s, channels, params->freq))
+                       goto out;
+       }
+
        params->freq = 0;
        wpa_printf(MSG_DEBUG, "P2P: No 2.4, 5, or 60 GHz channel allowed");
        return;
@@ -5781,10 +5943,23 @@ out:
 }
 
 
+static int wpas_same_band(int freq1, int freq2)
+{
+       enum hostapd_hw_mode mode1, mode2;
+       u8 chan1, chan2;
+
+       mode1 = ieee80211_freq_to_chan(freq1, &chan1);
+       mode2 = ieee80211_freq_to_chan(freq2, &chan2);
+       if (mode1 == NUM_HOSTAPD_MODES)
+               return 0;
+       return mode1 == mode2;
+}
+
+
 static int wpas_p2p_init_go_params(struct wpa_supplicant *wpa_s,
                                   struct p2p_go_neg_results *params,
                                   int freq, int vht_center_freq2, int ht40,
-                                  int vht, int max_oper_chwidth,
+                                  int vht, int max_oper_chwidth, int he,
                                   const struct p2p_channels *channels)
 {
        struct wpa_used_freq_data *freqs;
@@ -5797,6 +5972,7 @@ static int wpas_p2p_init_go_params(struct wpa_supplicant *wpa_s,
        params->role_go = 1;
        params->ht40 = ht40;
        params->vht = vht;
+       params->he = he;
        params->max_oper_chwidth = max_oper_chwidth;
        params->vht_center_freq2 = vht_center_freq2;
 
@@ -5831,12 +6007,31 @@ static int wpas_p2p_init_go_params(struct wpa_supplicant *wpa_s,
 
        /* try using the forced freq */
        if (freq) {
-               if (!wpas_p2p_supported_freq_go(wpa_s, channels, freq)) {
+               if (wpas_p2p_disallowed_freq(wpa_s->global, freq) ||
+                   !freq_included(wpa_s, channels, freq)) {
                        wpa_printf(MSG_DEBUG,
-                                  "P2P: Forced GO freq %d MHz not accepted",
+                                  "P2P: Forced GO freq %d MHz disallowed",
                                   freq);
                        goto fail;
                }
+               if (!p2p_supported_freq_go(wpa_s->global->p2p, freq)) {
+                       if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) &&
+                           ieee80211_is_dfs(freq, wpa_s->hw.modes,
+                                            wpa_s->hw.num_modes)) {
+                               /*
+                                * If freq is a DFS channel and DFS is offloaded
+                                * to the driver, allow P2P GO to use it.
+                                */
+                               wpa_printf(MSG_DEBUG,
+                                          "P2P: %s: The forced channel for GO (%u MHz) requires DFS and DFS is offloaded",
+                                          __func__, freq);
+                       } else {
+                               wpa_printf(MSG_DEBUG,
+                                          "P2P: The forced channel for GO (%u MHz) is not supported for P2P uses",
+                                          freq);
+                               goto fail;
+                       }
+               }
 
                for (i = 0; i < num; i++) {
                        if (freqs[i].freq == freq) {
@@ -5962,6 +6157,80 @@ static int wpas_p2p_init_go_params(struct wpa_supplicant *wpa_s,
                goto success;
        }
 
+       /* Try using a channel that allows VHT to be used with 80 MHz */
+       if (wpa_s->hw.modes && wpa_s->p2p_group_common_freqs) {
+               for (i = 0; i < wpa_s->p2p_group_common_freqs_num; i++) {
+                       enum hostapd_hw_mode mode;
+                       struct hostapd_hw_modes *hwmode;
+                       u8 chan;
+
+                       cand = wpa_s->p2p_group_common_freqs[i];
+                       mode = ieee80211_freq_to_chan(cand, &chan);
+                       hwmode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
+                                         mode);
+                       if (!hwmode ||
+                           wpas_p2p_verify_channel(wpa_s, hwmode, chan,
+                                                   BW80) != ALLOWED)
+                               continue;
+                       if (wpas_p2p_supported_freq_go(wpa_s, channels, cand)) {
+                               params->freq = cand;
+                               wpa_printf(MSG_DEBUG,
+                                          "P2P: Use freq %d MHz common with the peer and allowing VHT80",
+                                          params->freq);
+                               goto success;
+                       }
+               }
+       }
+
+       /* Try using a channel that allows HT to be used with 40 MHz on the same
+        * band so that CSA can be used */
+       if (wpa_s->current_ssid && wpa_s->hw.modes &&
+           wpa_s->p2p_group_common_freqs) {
+               for (i = 0; i < wpa_s->p2p_group_common_freqs_num; i++) {
+                       enum hostapd_hw_mode mode;
+                       struct hostapd_hw_modes *hwmode;
+                       u8 chan;
+
+                       cand = wpa_s->p2p_group_common_freqs[i];
+                       mode = ieee80211_freq_to_chan(cand, &chan);
+                       hwmode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
+                                         mode);
+                       if (!wpas_same_band(wpa_s->current_ssid->frequency,
+                                           cand) ||
+                           !hwmode ||
+                           (wpas_p2p_verify_channel(wpa_s, hwmode, chan,
+                                                    BW40MINUS) != ALLOWED &&
+                            wpas_p2p_verify_channel(wpa_s, hwmode, chan,
+                                                    BW40PLUS) != ALLOWED))
+                               continue;
+                       if (wpas_p2p_supported_freq_go(wpa_s, channels, cand)) {
+                               params->freq = cand;
+                               wpa_printf(MSG_DEBUG,
+                                          "P2P: Use freq %d MHz common with the peer, allowing HT40, and maintaining same band",
+                                          params->freq);
+                               goto success;
+                       }
+               }
+       }
+
+       /* Try using one of the group common freqs on the same band so that CSA
+        * can be used */
+       if (wpa_s->current_ssid && wpa_s->p2p_group_common_freqs) {
+               for (i = 0; i < wpa_s->p2p_group_common_freqs_num; i++) {
+                       cand = wpa_s->p2p_group_common_freqs[i];
+                       if (!wpas_same_band(wpa_s->current_ssid->frequency,
+                                           cand))
+                               continue;
+                       if (wpas_p2p_supported_freq_go(wpa_s, channels, cand)) {
+                               params->freq = cand;
+                               wpa_printf(MSG_DEBUG,
+                                          "P2P: Use freq %d MHz common with the peer and maintaining same band",
+                                          params->freq);
+                               goto success;
+                       }
+               }
+       }
+
        /* Try using one of the group common freqs */
        if (wpa_s->p2p_group_common_freqs) {
                for (i = 0; i < wpa_s->p2p_group_common_freqs_num; i++) {
@@ -6013,7 +6282,7 @@ wpas_p2p_get_group_iface(struct wpa_supplicant *wpa_s, int addr_allocated,
                        "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);
+                       wpas_p2p_clone_config(wpa_s, wpa_s->p2pdev);
                return wpa_s;
        }
 
@@ -6031,6 +6300,12 @@ wpas_p2p_get_group_iface(struct wpa_supplicant *wpa_s, int addr_allocated,
                return NULL;
        }
 
+       if (go && wpa_s->p2p_go_do_acs) {
+               group_wpa_s->p2p_go_do_acs = wpa_s->p2p_go_do_acs;
+               group_wpa_s->p2p_go_acs_band = wpa_s->p2p_go_acs_band;
+               wpa_s->p2p_go_do_acs = 0;
+       }
+
        wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Use separate group interface %s",
                group_wpa_s->ifname);
        group_wpa_s->p2p_first_connection_timeout = 0;
@@ -6054,7 +6329,7 @@ wpas_p2p_get_group_iface(struct wpa_supplicant *wpa_s, int addr_allocated,
  */
 int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group,
                       int freq, int vht_center_freq2, int ht40, int vht,
-                      int max_oper_chwidth)
+                      int max_oper_chwidth, int he)
 {
        struct p2p_go_neg_results params;
 
@@ -6068,31 +6343,16 @@ int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group,
        wpa_printf(MSG_DEBUG, "P2P: Stop any on-going P2P FIND");
        wpas_p2p_stop_find_oper(wpa_s);
 
-       freq = wpas_p2p_select_go_freq(wpa_s, freq);
-       if (freq < 0)
-               return -1;
+       if (!wpa_s->p2p_go_do_acs) {
+               freq = wpas_p2p_select_go_freq(wpa_s, freq);
+               if (freq < 0)
+                       return -1;
+       }
 
        if (wpas_p2p_init_go_params(wpa_s, &params, freq, vht_center_freq2,
-                                   ht40, vht, max_oper_chwidth, NULL))
+                                   ht40, vht, max_oper_chwidth, he, NULL))
                return -1;
-       if (params.freq &&
-           !p2p_supported_freq_go(wpa_s->global->p2p, params.freq)) {
-               if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) &&
-                   ieee80211_is_dfs(params.freq)) {
-                       /*
-                        * If freq is a DFS channel and DFS is offloaded to the
-                        * driver, allow P2P GO to use it.
-                        */
-                       wpa_printf(MSG_DEBUG,
-                                  "P2P: %s: The forced channel for GO (%u MHz) is DFS, and DFS is offloaded to driver",
-                               __func__, params.freq);
-               } else {
-                       wpa_printf(MSG_DEBUG,
-                                  "P2P: The selected channel for GO (%u MHz) is not supported for P2P uses",
-                                  params.freq);
-                       return -1;
-               }
-       }
+
        p2p_go_params(wpa_s->global->p2p, &params);
        params.persistent_group = persistent_group;
 
@@ -6169,7 +6429,7 @@ int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s,
                                  struct wpa_ssid *ssid, int addr_allocated,
                                  int force_freq, int neg_freq,
                                  int vht_center_freq2, int ht40,
-                                 int vht, int max_oper_chwidth,
+                                 int vht, int max_oper_chwidth, int he,
                                  const struct p2p_channels *channels,
                                  int connection_timeout, int force_scan)
 {
@@ -6245,7 +6505,7 @@ int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s,
        }
 
        if (wpas_p2p_init_go_params(wpa_s, &params, freq, vht_center_freq2,
-                                   ht40, vht, max_oper_chwidth, channels))
+                                   ht40, vht, max_oper_chwidth, he, channels))
                return -1;
 
        params.role_go = 1;
@@ -6327,7 +6587,8 @@ struct p2p_group * wpas_p2p_group_init(struct wpa_supplicant *wpa_s,
        struct p2p_group *group;
        struct p2p_group_config *cfg;
 
-       if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
+       if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL ||
+           !ssid->p2p_group)
                return NULL;
 
        cfg = os_zalloc(sizeof(*cfg));
@@ -6567,8 +6828,14 @@ int wpas_p2p_find(struct wpa_supplicant *wpa_s, unsigned int timeout,
        wpa_s->p2p_long_listen = 0;
 
        if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL ||
-           wpa_s->p2p_in_provisioning)
+           wpa_s->p2p_in_provisioning) {
+               wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Reject p2p_find operation%s%s",
+                       (wpa_s->global->p2p_disabled || !wpa_s->global->p2p) ?
+                       " (P2P disabled)" : "",
+                       wpa_s->p2p_in_provisioning ?
+                       " (p2p_in_provisioning)" : "");
                return -1;
+       }
 
        wpa_supplicant_cancel_sched_scan(wpa_s);
 
@@ -6640,6 +6907,12 @@ int wpas_p2p_listen(struct wpa_supplicant *wpa_s, unsigned int timeout)
        if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
                return -1;
 
+       if (wpa_s->p2p_lo_started) {
+               wpa_printf(MSG_DEBUG,
+                       "P2P: Cannot start P2P listen, it is offloaded");
+               return -1;
+       }
+
        wpa_supplicant_cancel_sched_scan(wpa_s);
        wpas_p2p_clear_pending_action_tx(wpa_s);
 
@@ -6713,7 +6986,7 @@ int wpas_p2p_probe_req_rx(struct wpa_supplicant *wpa_s, const u8 *addr,
                return 0;
 
        switch (p2p_probe_req_rx(wpa_s->global->p2p, addr, dst, bssid,
-                                ie, ie_len, rx_freq)) {
+                                ie, ie_len, rx_freq, wpa_s->p2p_lo_started)) {
        case P2P_PREQ_NOT_P2P:
                wpas_notify_preq(wpa_s, addr, dst, bssid, ie, ie_len,
                                 ssi_signal);
@@ -6784,7 +7057,7 @@ int wpas_p2p_reject(struct wpa_supplicant *wpa_s, const u8 *addr)
 int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
                    struct wpa_ssid *ssid, const u8 *go_dev_addr, int freq,
                    int vht_center_freq2, int ht40, int vht, int max_chwidth,
-                   int pref_freq)
+                   int pref_freq, int he)
 {
        enum p2p_invite_role role;
        u8 *bssid = NULL;
@@ -6802,6 +7075,7 @@ int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
        wpa_s->p2p_persistent_go_freq = freq;
        wpa_s->p2p_go_ht40 = !!ht40;
        wpa_s->p2p_go_vht = !!vht;
+       wpa_s->p2p_go_he = !!he;
        wpa_s->p2p_go_max_oper_chwidth = max_chwidth;
        wpa_s->p2p_go_vht_center_freq2 = vht_center_freq2;
        if (ssid->mode == WPAS_MODE_P2P_GO) {
@@ -6946,10 +7220,9 @@ void wpas_p2p_completed(struct wpa_supplicant *wpa_s)
 {
        struct wpa_ssid *ssid = wpa_s->current_ssid;
        u8 go_dev_addr[ETH_ALEN];
-       int network_id = -1;
        int persistent;
        int freq;
-       u8 ip[3 * 4];
+       u8 ip[3 * 4], *ip_ptr = NULL;
        char ip_addr[100];
 
        if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GROUP_FORMATION) {
@@ -6996,6 +7269,7 @@ void wpas_p2p_completed(struct wpa_supplicant *wpa_s)
                                  ip[8], ip[9], ip[10], ip[11]);
                if (os_snprintf_error(sizeof(ip_addr), res))
                        ip_addr[0] = '\0';
+               ip_ptr = ip;
        }
 
        wpas_p2p_group_started(wpa_s, 0, ssid, freq,
@@ -7005,11 +7279,10 @@ void wpas_p2p_completed(struct wpa_supplicant *wpa_s)
                               ip_addr);
 
        if (persistent)
-               network_id = wpas_p2p_store_persistent_group(wpa_s->p2pdev,
-                                                            ssid, go_dev_addr);
-       if (network_id < 0)
-               network_id = ssid->id;
-       wpas_notify_p2p_group_started(wpa_s, ssid, network_id, 1);
+               wpas_p2p_store_persistent_group(wpa_s->p2pdev,
+                                               ssid, go_dev_addr);
+
+       wpas_notify_p2p_group_started(wpa_s, ssid, persistent, 1, ip_ptr);
 }
 
 
@@ -7826,7 +8099,8 @@ 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, NULL, 0);
+                        wpa_s->p2p_go_max_oper_chwidth,
+                        wpa_s->p2p_go_he, NULL, 0);
        return ret;
 }
 
@@ -8362,6 +8636,7 @@ static int wpas_p2p_nfc_join_group(struct wpa_supplicant *wpa_s,
                                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,
+                               wpa_s->p2p_go_he,
                                params->go_ssid_len ? params->go_ssid : NULL,
                                params->go_ssid_len);
 }
@@ -8441,7 +8716,7 @@ static int wpas_p2p_nfc_init_go_neg(struct wpa_supplicant *wpa_s,
                                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,
-                               NULL, 0);
+                               wpa_s->p2p_go_he, NULL, 0);
 }
 
 
@@ -8457,7 +8732,7 @@ static int wpas_p2p_nfc_resp_go_neg(struct wpa_supplicant *wpa_s,
                               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,
-                              NULL, 0);
+                              wpa_s->p2p_go_he, NULL, 0);
        if (res)
                return res;
 
@@ -8842,7 +9117,7 @@ static int wpas_p2p_move_go_csa(struct wpa_supplicant *wpa_s)
         * TODO: This function may not always work correctly. For example,
         * when we have a running GO and a BSS on a DFS channel.
         */
-       if (wpas_p2p_init_go_params(wpa_s, &params, 0, 0, 0, 0, 0, NULL)) {
+       if (wpas_p2p_init_go_params(wpa_s, &params, 0, 0, 0, 0, 0, 0, NULL)) {
                wpa_dbg(wpa_s, MSG_DEBUG,
                        "P2P CSA: Failed to select new frequency for GO");
                return -1;
@@ -8920,11 +9195,11 @@ static int wpas_p2p_move_go_csa(struct wpa_supplicant *wpa_s)
                csa_settings.freq_params.center_freq2 = freq2;
 
                switch (conf->vht_oper_chwidth) {
-               case VHT_CHANWIDTH_80MHZ:
-               case VHT_CHANWIDTH_80P80MHZ:
+               case CHANWIDTH_80MHZ:
+               case CHANWIDTH_80P80MHZ:
                        csa_settings.freq_params.bandwidth = 80;
                        break;
-               case VHT_CHANWIDTH_160MHZ:
+               case CHANWIDTH_160MHZ:
                        csa_settings.freq_params.bandwidth = 160;
                        break;
                }
@@ -8954,7 +9229,7 @@ static void wpas_p2p_move_go_no_csa(struct wpa_supplicant *wpa_s)
        wpa_supplicant_ap_deinit(wpa_s);
 
        /* Reselect the GO frequency */
-       if (wpas_p2p_init_go_params(wpa_s, &params, 0, 0, 0, 0, 0, NULL)) {
+       if (wpas_p2p_init_go_params(wpa_s, &params, 0, 0, 0, 0, 0, 0, NULL)) {
                wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Failed to reselect freq");
                wpas_p2p_group_delete(wpa_s,
                                      P2P_GROUP_REMOVAL_GO_LEAVE_CHANNEL);
@@ -9045,16 +9320,20 @@ static void wpas_p2p_consider_moving_one_go(struct wpa_supplicant *wpa_s,
        unsigned int i, invalid_freq = 0, policy_move = 0, flags = 0;
        unsigned int timeout;
        int freq;
+       int dfs_offload;
 
        wpas_p2p_go_update_common_freqs(wpa_s);
 
        freq = wpa_s->current_ssid->frequency;
+       dfs_offload = (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) &&
+               ieee80211_is_dfs(freq, wpa_s->hw.modes, wpa_s->hw.num_modes);
        for (i = 0, invalid_freq = 0; i < num; i++) {
                if (freqs[i].freq == freq) {
                        flags = freqs[i].flags;
 
                        /* The channel is invalid, must change it */
-                       if (!p2p_supported_freq_go(wpa_s->global->p2p, freq)) {
+                       if (!p2p_supported_freq_go(wpa_s->global->p2p, freq) &&
+                           !dfs_offload) {
                                wpa_dbg(wpa_s, MSG_DEBUG,
                                        "P2P: Freq=%d MHz no longer valid for GO",
                                        freq);
@@ -9064,7 +9343,7 @@ static void wpas_p2p_consider_moving_one_go(struct wpa_supplicant *wpa_s,
                        /* Freq is not used by any other station interface */
                        continue;
                } else if (!p2p_supported_freq(wpa_s->global->p2p,
-                                              freqs[i].freq)) {
+                                              freqs[i].freq) && !dfs_offload) {
                        /* Freq is not valid for P2P use cases */
                        continue;
                } else if (wpa_s->conf->p2p_go_freq_change_policy ==
@@ -9216,3 +9495,86 @@ void wpas_p2p_ap_deinit(struct wpa_supplicant *wpa_s)
                wpa_s->ap_iface->bss[0]->p2p_group = NULL;
        wpas_p2p_group_deinit(wpa_s);
 }
+
+
+int wpas_p2p_lo_start(struct wpa_supplicant *wpa_s, unsigned int freq,
+                     unsigned int period, unsigned int interval,
+                     unsigned int count)
+{
+       struct p2p_data *p2p = wpa_s->global->p2p;
+       u8 *device_types;
+       size_t dev_types_len;
+       struct wpabuf *buf;
+       int ret;
+
+       if (wpa_s->p2p_lo_started) {
+               wpa_dbg(wpa_s, MSG_DEBUG,
+                       "P2P Listen offload is already started");
+               return 0;
+       }
+
+       if (wpa_s->global->p2p == NULL ||
+           !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_LISTEN_OFFLOAD)) {
+               wpa_printf(MSG_DEBUG, "P2P: Listen offload not supported");
+               return -1;
+       }
+
+       if (!p2p_supported_freq(wpa_s->global->p2p, freq)) {
+               wpa_printf(MSG_ERROR, "P2P: Input channel not supported: %u",
+                          freq);
+               return -1;
+       }
+
+       /* Get device type */
+       dev_types_len = (wpa_s->conf->num_sec_device_types + 1) *
+               WPS_DEV_TYPE_LEN;
+       device_types = os_malloc(dev_types_len);
+       if (!device_types)
+               return -1;
+       os_memcpy(device_types, wpa_s->conf->device_type, WPS_DEV_TYPE_LEN);
+       os_memcpy(&device_types[WPS_DEV_TYPE_LEN], wpa_s->conf->sec_device_type,
+                 wpa_s->conf->num_sec_device_types * WPS_DEV_TYPE_LEN);
+
+       /* Get Probe Response IE(s) */
+       buf = p2p_build_probe_resp_template(p2p, freq);
+       if (!buf) {
+               os_free(device_types);
+               return -1;
+       }
+
+       ret = wpa_drv_p2p_lo_start(wpa_s, freq, period, interval, count,
+                                  device_types, dev_types_len,
+                                  wpabuf_mhead_u8(buf), wpabuf_len(buf));
+       if (ret < 0)
+               wpa_dbg(wpa_s, MSG_DEBUG,
+                       "P2P: Failed to start P2P listen offload");
+
+       os_free(device_types);
+       wpabuf_free(buf);
+
+       if (ret == 0) {
+               wpa_s->p2p_lo_started = 1;
+
+               /* Stop current P2P listen if any */
+               wpas_stop_listen(wpa_s);
+       }
+
+       return ret;
+}
+
+
+int wpas_p2p_lo_stop(struct wpa_supplicant *wpa_s)
+{
+       int ret;
+
+       if (!wpa_s->p2p_lo_started)
+               return 0;
+
+       ret = wpa_drv_p2p_lo_stop(wpa_s);
+       if (ret < 0)
+               wpa_dbg(wpa_s, MSG_DEBUG,
+                       "P2P: Failed to stop P2P listen offload");
+
+       wpa_s->p2p_lo_started = 0;
+       return ret;
+}