P2P: Add more debug prints for Action frame TX clearing steps
[mech_eap.git] / wpa_supplicant / p2p_supplicant.c
index 371b6e0..7d78623 100644 (file)
@@ -124,6 +124,10 @@ wpas_p2p_get_group_iface(struct wpa_supplicant *wpa_s, int addr_allocated,
                         int go);
 static int wpas_p2p_join_start(struct wpa_supplicant *wpa_s, int freq,
                               const u8 *ssid, size_t ssid_len);
+static int wpas_p2p_setup_freqs(struct wpa_supplicant *wpa_s, int freq,
+                               int *force_freq, int *pref_freq, int go,
+                               unsigned int *pref_freq_list,
+                               unsigned int *num_pref_freq);
 static void wpas_p2p_join_scan_req(struct wpa_supplicant *wpa_s, int freq,
                                   const u8 *ssid, size_t ssid_len);
 static void wpas_p2p_join_scan(void *eloop_ctx, void *timeout_ctx);
@@ -585,17 +589,23 @@ wpas_p2p_get_go_group(struct wpa_supplicant *wpa_s)
 }
 
 
-/* Find an active P2P group where we are the GO */
-static struct wpa_ssid * wpas_p2p_group_go_ssid(struct wpa_supplicant *wpa_s,
-                                               u8 *bssid)
+static unsigned int p2p_is_active_persistent_cli(struct wpa_supplicant *wpa_s)
 {
-       struct wpa_supplicant *go = wpas_p2p_get_go_group(wpa_s);
+       return p2p_is_active_persistent_group(wpa_s) &&
+               wpa_s->current_ssid->mode == WPAS_MODE_INFRA;
+}
 
-       if (!go)
-               return NULL;
 
-       os_memcpy(bssid, go->own_addr, ETH_ALEN);
-       return go->current_ssid;
+/* Find an interface for a P2P group where we are the P2P Client */
+static struct wpa_supplicant *
+wpas_p2p_get_cli_group(struct wpa_supplicant *wpa_s)
+{
+       for (wpa_s = wpa_s->global->ifaces; wpa_s; wpa_s = wpa_s->next) {
+               if (p2p_is_active_persistent_cli(wpa_s))
+                       return wpa_s;
+       }
+
+       return NULL;
 }
 
 
@@ -614,20 +624,34 @@ wpas_p2p_get_persistent_go(struct wpa_supplicant *wpa_s)
 }
 
 
-static u8 p2ps_group_capability(void *ctx, u8 incoming, u8 role)
+static u8 p2ps_group_capability(void *ctx, u8 incoming, u8 role,
+                               unsigned int *force_freq,
+                               unsigned int *pref_freq)
 {
-       struct wpa_supplicant *wpa_s = ctx, *tmp_wpa_s;
+       struct wpa_supplicant *wpa_s = ctx;
        struct wpa_ssid *s;
        u8 conncap = P2PS_SETUP_NONE;
        unsigned int owned_members = 0;
-       unsigned int owner = 0;
-       unsigned int client = 0;
-       struct wpa_supplicant *go_wpa_s;
+       struct wpa_supplicant *go_wpa_s, *cli_wpa_s;
        struct wpa_ssid *persistent_go;
        int p2p_no_group_iface;
+       unsigned int pref_freq_list[P2P_MAX_PREF_CHANNELS], size;
 
        wpa_printf(MSG_DEBUG, "P2P: Conncap - in:%d role:%d", incoming, role);
 
+       if (force_freq)
+               *force_freq = 0;
+       if (pref_freq)
+               *pref_freq = 0;
+
+       size = P2P_MAX_PREF_CHANNELS;
+       if (force_freq && pref_freq &&
+           !wpas_p2p_setup_freqs(wpa_s, 0, (int *) force_freq,
+                                 (int *) pref_freq, 0, pref_freq_list, &size))
+               wpas_p2p_set_own_freq_preference(wpa_s,
+                                                *force_freq ? *force_freq :
+                                                *pref_freq);
+
        /*
         * For non-concurrent capable devices:
         * If persistent_go, then no new.
@@ -635,36 +659,21 @@ static u8 p2ps_group_capability(void *ctx, u8 incoming, u8 role)
         * If client, then no GO.
         */
        go_wpa_s = wpas_p2p_get_go_group(wpa_s);
+       if (go_wpa_s)
+               owned_members = p2p_get_group_num_members(go_wpa_s->p2p_group);
        persistent_go = wpas_p2p_get_persistent_go(wpa_s);
        p2p_no_group_iface = !wpas_p2p_create_iface(wpa_s);
+       cli_wpa_s = wpas_p2p_get_cli_group(wpa_s);
 
-       wpa_printf(MSG_DEBUG, "P2P: GO(iface)=%p persistent(ssid)=%p",
-                  go_wpa_s, persistent_go);
-
-       for (tmp_wpa_s = wpa_s->global->ifaces; tmp_wpa_s;
-            tmp_wpa_s = tmp_wpa_s->next) {
-               for (s = tmp_wpa_s->conf->ssid; s; s = s->next) {
-                       wpa_printf(MSG_DEBUG,
-                                  "P2P: sup:%p ssid:%p disabled:%d p2p:%d mode:%d",
-                                  tmp_wpa_s, s, s->disabled,
-                                  s->p2p_group, s->mode);
-                       if (!s->disabled && s->p2p_group) {
-                               if (s->mode == WPAS_MODE_P2P_GO) {
-                                       owned_members +=
-                                               p2p_get_group_num_members(
-                                                       tmp_wpa_s->p2p_group);
-                                       owner++;
-                               } else
-                                       client++;
-                       }
-               }
-       }
+       wpa_printf(MSG_DEBUG,
+                  "P2P: GO(iface)=%p members=%u CLI(iface)=%p persistent(ssid)=%p",
+                  go_wpa_s, owned_members, cli_wpa_s, persistent_go);
 
        /* If not concurrent, restrict our choices */
        if (p2p_no_group_iface) {
                wpa_printf(MSG_DEBUG, "P2P: p2p_no_group_iface");
 
-               if (client)
+               if (cli_wpa_s)
                        return P2PS_SETUP_NONE;
 
                if (go_wpa_s) {
@@ -696,10 +705,20 @@ static u8 p2ps_group_capability(void *ctx, u8 incoming, u8 role)
        /* If a required role has been specified, handle it here */
        if (role && role != P2PS_SETUP_NEW) {
                switch (incoming) {
+               case P2PS_SETUP_GROUP_OWNER | P2PS_SETUP_NEW:
+               case P2PS_SETUP_GROUP_OWNER | P2PS_SETUP_CLIENT:
+                       /*
+                        * Peer has an active GO, so if the role allows it and
+                        * we do not have any active roles, become client.
+                        */
+                       if ((role & P2PS_SETUP_CLIENT) && !go_wpa_s &&
+                           !cli_wpa_s)
+                               return P2PS_SETUP_CLIENT;
+
+                       /* fall through */
+
                case P2PS_SETUP_NONE:
                case P2PS_SETUP_NEW:
-               case P2PS_SETUP_GROUP_OWNER | P2PS_SETUP_CLIENT:
-               case P2PS_SETUP_GROUP_OWNER | P2PS_SETUP_NEW:
                        conncap = role;
                        goto grp_owner;
 
@@ -708,7 +727,7 @@ static u8 p2ps_group_capability(void *ctx, u8 incoming, u8 role)
                         * Must be a complimentary role - cannot be a client to
                         * more than one peer.
                         */
-                       if (incoming == role || client)
+                       if (incoming == role || cli_wpa_s)
                                return P2PS_SETUP_NONE;
 
                        return P2PS_SETUP_CLIENT;
@@ -734,7 +753,7 @@ static u8 p2ps_group_capability(void *ctx, u8 incoming, u8 role)
        switch (incoming) {
        case P2PS_SETUP_NONE:
        case P2PS_SETUP_NEW:
-               if (client)
+               if (cli_wpa_s)
                        conncap = P2PS_SETUP_GROUP_OWNER;
                else if (!owned_members)
                        conncap = P2PS_SETUP_NEW;
@@ -749,13 +768,20 @@ static u8 p2ps_group_capability(void *ctx, u8 incoming, u8 role)
                break;
 
        case P2PS_SETUP_GROUP_OWNER:
-               if (!client)
+               if (!cli_wpa_s)
                        conncap = P2PS_SETUP_CLIENT;
                break;
 
        case P2PS_SETUP_GROUP_OWNER | P2PS_SETUP_NEW:
        case P2PS_SETUP_GROUP_OWNER | P2PS_SETUP_CLIENT:
-               if (client)
+               /*
+                * Peer has an active GO, so if the role allows it and
+                * we do not have any active roles, become client.
+                */
+               if ((role & P2PS_SETUP_CLIENT) && !go_wpa_s && !cli_wpa_s)
+                       return P2PS_SETUP_CLIENT;
+
+               if (cli_wpa_s)
                        conncap = P2PS_SETUP_GROUP_OWNER;
                else {
                        u8 r;
@@ -777,15 +803,12 @@ grp_owner:
            (!incoming && (conncap & P2PS_SETUP_NEW))) {
                if (go_wpa_s && p2p_client_limit_reached(go_wpa_s->p2p_group))
                        conncap &= ~P2PS_SETUP_GROUP_OWNER;
-               wpa_printf(MSG_DEBUG, "P2P: GOs:%d members:%d conncap:%d",
-                          owner, owned_members, conncap);
 
                s = wpas_p2p_get_persistent_go(wpa_s);
-
-               if (!s && !owner && p2p_no_group_iface) {
+               if (!s && !go_wpa_s && p2p_no_group_iface) {
                        p2p_set_intended_addr(wpa_s->global->p2p,
                                              wpa_s->own_addr);
-               } else if (!s && !owner) {
+               } else if (!s && !go_wpa_s) {
                        if (wpas_p2p_add_group_interface(wpa_s,
                                                         WPA_IF_P2P_GO) < 0) {
                                wpa_printf(MSG_ERROR,
@@ -1375,6 +1398,25 @@ struct send_action_work {
 };
 
 
+static void wpas_p2p_free_send_action_work(struct wpa_supplicant *wpa_s)
+{
+       struct send_action_work *awork = wpa_s->p2p_send_action_work->ctx;
+
+       wpa_printf(MSG_DEBUG,
+                  "P2P: Free Action frame radio work @%p (freq=%u dst="
+                  MACSTR " src=" MACSTR " bssid=" MACSTR " wait_time=%u)",
+                  wpa_s->p2p_send_action_work, awork->freq,
+                  MAC2STR(awork->dst), MAC2STR(awork->src),
+                  MAC2STR(awork->bssid), awork->wait_time);
+       wpa_hexdump(MSG_DEBUG, "P2P: Freeing pending Action frame",
+                   awork->buf, awork->len);
+       os_free(awork);
+       wpa_s->p2p_send_action_work->ctx = NULL;
+       radio_work_done(wpa_s->p2p_send_action_work);
+       wpa_s->p2p_send_action_work = NULL;
+}
+
+
 static void wpas_p2p_send_action_work_timeout(void *eloop_ctx,
                                              void *timeout_ctx)
 {
@@ -1384,9 +1426,7 @@ static void wpas_p2p_send_action_work_timeout(void *eloop_ctx,
                return;
 
        wpa_printf(MSG_DEBUG, "P2P: Send Action frame radio work timed out");
-       os_free(wpa_s->p2p_send_action_work->ctx);
-       radio_work_done(wpa_s->p2p_send_action_work);
-       wpa_s->p2p_send_action_work = NULL;
+       wpas_p2p_free_send_action_work(wpa_s);
 }
 
 
@@ -1394,11 +1434,13 @@ static void wpas_p2p_action_tx_clear(struct wpa_supplicant *wpa_s)
 {
        if (wpa_s->p2p_send_action_work) {
                struct send_action_work *awork;
+
                awork = wpa_s->p2p_send_action_work->ctx;
+               wpa_printf(MSG_DEBUG,
+                          "P2P: Clear Action TX work @%p (wait_time=%u)",
+                          wpa_s->p2p_send_action_work, awork->wait_time);
                if (awork->wait_time == 0) {
-                       os_free(awork);
-                       radio_work_done(wpa_s->p2p_send_action_work);
-                       wpa_s->p2p_send_action_work = NULL;
+                       wpas_p2p_free_send_action_work(wpa_s);
                } else {
                        /*
                         * In theory, this should not be needed, but number of
@@ -3668,11 +3710,12 @@ static int wpas_get_persistent_group(void *ctx, const u8 *addr, const u8 *ssid,
 
 
 static int wpas_get_go_info(void *ctx, u8 *intended_addr,
-                           u8 *ssid, size_t *ssid_len, int *group_iface)
+                           u8 *ssid, size_t *ssid_len, int *group_iface,
+                           unsigned int *freq)
 {
        struct wpa_supplicant *wpa_s = ctx;
+       struct wpa_supplicant *go;
        struct wpa_ssid *s;
-       u8 bssid[ETH_ALEN];
 
        /*
         * group_iface will be set to 1 only if a dedicated interface for P2P
@@ -3682,17 +3725,25 @@ static int wpas_get_go_info(void *ctx, u8 *intended_addr,
         * that the pending interface should be used.
         */
        *group_iface = 0;
-       s = wpas_p2p_group_go_ssid(wpa_s, bssid);
-       if (!s) {
+
+       if (freq)
+               *freq = 0;
+
+       go = wpas_p2p_get_go_group(wpa_s);
+       if (!go) {
                s = wpas_p2p_get_persistent_go(wpa_s);
                *group_iface = wpas_p2p_create_iface(wpa_s);
                if (s)
-                       os_memcpy(bssid, s->bssid, ETH_ALEN);
+                       os_memcpy(intended_addr, s->bssid, ETH_ALEN);
                else
                        return 0;
+       } else {
+               s = go->current_ssid;
+               os_memcpy(intended_addr, go->own_addr, ETH_ALEN);
+               if (freq)
+                       *freq = go->assoc_freq;
        }
 
-       os_memcpy(intended_addr, bssid, ETH_ALEN);
        os_memcpy(ssid, s->ssid, s->ssid_len);
        *ssid_len = s->ssid_len;
 
@@ -3780,11 +3831,12 @@ static void wpas_p2ps_prov_complete(void *ctx, u8 status, const u8 *dev,
                                    const u8 *persist_ssid,
                                    size_t persist_ssid_size, int response_done,
                                    int prov_start, const char *session_info,
-                                   const u8 *feat_cap, size_t feat_cap_len)
+                                   const u8 *feat_cap, size_t feat_cap_len,
+                                   unsigned int freq)
 {
        struct wpa_supplicant *wpa_s = ctx;
        u8 mac[ETH_ALEN];
-       struct wpa_ssid *persistent_go, *stale, *s;
+       struct wpa_ssid *persistent_go, *stale, *s = NULL;
        int save_config = 0;
        struct wpa_supplicant *go_wpa_s;
        char feat_cap_str[256];
@@ -3855,8 +3907,9 @@ static void wpas_p2ps_prov_complete(void *ctx, u8 status, const u8 *dev,
        }
 
        /* Clean up stale persistent groups with this device */
-       s = wpas_p2p_get_persistent(wpa_s, dev, persist_ssid,
-                                   persist_ssid_size);
+       if (persist_ssid && persist_ssid_size)
+               s = wpas_p2p_get_persistent(wpa_s, dev, persist_ssid,
+                                           persist_ssid_size);
 
        if (persist_ssid && s && s->mode != WPAS_MODE_P2P_GO &&
            is_zero_ether_addr(grp_mac)) {
@@ -3938,6 +3991,7 @@ 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 (!wpas_p2p_create_iface(wpa_s))
                                os_memcpy(go_ifname, wpa_s->ifname,
@@ -3952,7 +4006,7 @@ static void wpas_p2ps_prov_complete(void *ctx, u8 status, const u8 *dev,
                                        wpa_s, P2P_SC_FAIL_UNKNOWN_GROUP,
                                        dev, adv_mac, ses_mac,
                                        grp_mac, adv_id, ses_id, 0, 0,
-                                       NULL, 0, 0, 0, NULL, NULL, 0);
+                                       NULL, 0, 0, 0, NULL, NULL, 0, 0);
                                return;
                        }
 
@@ -3960,13 +4014,13 @@ 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, 0, 0, 0, NULL,
+                                       0, 0, freq, 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, 0, 0, 0);
+                               wpas_p2p_group_add(wpa_s, 1, freq, 0, 0);
                        }
 
                        if (passwd_id == DEV_PW_P2PS_DEFAULT) {
@@ -4055,10 +4109,13 @@ static int wpas_prov_disc_resp_cb(void *ctx)
 {
        struct wpa_supplicant *wpa_s = ctx;
        struct wpa_ssid *persistent_go;
+       unsigned int freq;
 
        if (!wpa_s->global->pending_p2ps_group)
                return 0;
 
+       freq = wpa_s->global->pending_p2ps_group_freq;
+       wpa_s->global->pending_p2ps_group_freq = 0;
        wpa_s->global->pending_p2ps_group = 0;
 
        if (wpas_p2p_get_go_group(wpa_s))
@@ -4071,7 +4128,7 @@ static int wpas_prov_disc_resp_cb(void *ctx)
                        persistent_go->mode == WPAS_MODE_P2P_GO ?
                        P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE : 0, 0);
        } else {
-               wpas_p2p_group_add(wpa_s, 1, 0, 0, 0);
+               wpas_p2p_group_add(wpa_s, 1, freq, 0, 0);
        }
 
        return 1;
@@ -5135,6 +5192,7 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
 
        wpa_s->global->p2p_fail_on_wps_complete = 0;
        wpa_s->global->pending_p2ps_group = 0;
+       wpa_s->global->pending_p2ps_group_freq = 0;
        wpa_s->p2ps_method_config_any = 0;
 
        if (go_intent < 0)
@@ -6214,11 +6272,14 @@ int wpas_p2p_prov_disc(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
        u16 config_methods;
 
        wpa_s->global->pending_p2ps_group = 0;
+       wpa_s->global->pending_p2ps_group_freq = 0;
        wpa_s->p2p_fallback_to_go_neg = 0;
        wpa_s->pending_pd_use = NORMAL_PD;
        if (p2ps_prov && use == WPAS_P2P_PD_FOR_ASP) {
                p2ps_prov->conncap = p2ps_group_capability(
-                       wpa_s, P2PS_SETUP_NONE, p2ps_prov->role);
+                       wpa_s, P2PS_SETUP_NONE, p2ps_prov->role,
+                       &p2ps_prov->force_freq, &p2ps_prov->pref_freq);
+
                wpa_printf(MSG_DEBUG,
                           "P2P: %s conncap: %d - ASP parsed: %x %x %d %s",
                           __func__, p2ps_prov->conncap,