]> git.ipfire.org Git - thirdparty/hostap.git/blobdiff - wpa_supplicant/p2p_supplicant.c
P2P: Pass HE flag to GO negotiation result
[thirdparty/hostap.git] / wpa_supplicant / p2p_supplicant.c
index 570c09b59d5055dd21bee927f402fc436e637b28..55b3b08efe50b98c891916d25e56cf9e1b414325 100644 (file)
@@ -980,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;
 
@@ -1555,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;
        }
@@ -1572,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;
@@ -1584,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");
@@ -1649,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,
@@ -2076,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);
@@ -2154,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;
 }
 
@@ -2230,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;
 
@@ -4150,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
@@ -4160,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,
@@ -4330,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()
@@ -4350,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;
@@ -4414,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;
@@ -4439,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: "
@@ -5372,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
@@ -7116,7 +7222,7 @@ void wpas_p2p_completed(struct wpa_supplicant *wpa_s)
        u8 go_dev_addr[ETH_ALEN];
        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) {
@@ -7163,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,
@@ -7175,7 +7282,7 @@ void wpas_p2p_completed(struct wpa_supplicant *wpa_s)
                wpas_p2p_store_persistent_group(wpa_s->p2pdev,
                                                ssid, go_dev_addr);
 
-       wpas_notify_p2p_group_started(wpa_s, ssid, persistent, 1, ip);
+       wpas_notify_p2p_group_started(wpa_s, ssid, persistent, 1, ip_ptr);
 }
 
 
@@ -9088,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;
                }