From 91c40cdce17424d9a4718876becf0b7811cf68f2 Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Tue, 25 Sep 2012 14:23:53 -0700 Subject: [PATCH] wpa_supplicant: P2P-related fixes - P2P: Show own channel list in debug log - P2P: Allow peer to propose channel in invitation process - P2P: Clear sta_scan_pending on group removal - P2P: Fix ignoring of PD Response due to dialog token mismatch BUG: 7226065, 7231289 Change-Id: Iacb0f85d80f63bcdf311ccc0d29d0c282a0c0576 Signed-off-by: Dmitry Shmidt --- src/p2p/p2p_build.c | 3 +- src/p2p/p2p_go_neg.c | 4 +- src/p2p/p2p_i.h | 2 + src/p2p/p2p_invitation.c | 81 +++++++++++++++++++++++++++++++++++++---- src/p2p/p2p_pd.c | 10 ++--- wpa_supplicant/p2p_supplicant.c | 4 +- 6 files changed, 88 insertions(+), 16 deletions(-) diff --git a/src/p2p/p2p_build.c b/src/p2p/p2p_build.c index bbe2002..7f4d295 100644 --- a/src/p2p/p2p_build.c +++ b/src/p2p/p2p_build.c @@ -132,7 +132,8 @@ void p2p_buf_add_channel_list(struct wpabuf *buf, const char *country, /* Update attribute length */ WPA_PUT_LE16(len, (u8 *) wpabuf_put(buf, 0) - len - 2); - wpa_printf(MSG_DEBUG, "P2P: * Channel List"); + wpa_hexdump(MSG_DEBUG, "P2P: * Channel List", + len + 2, (u8 *) wpabuf_put(buf, 0) - len - 2); } #ifdef ANDROID_P2P diff --git a/src/p2p/p2p_go_neg.c b/src/p2p/p2p_go_neg.c index b0b53fe..9c287b6 100644 --- a/src/p2p/p2p_go_neg.c +++ b/src/p2p/p2p_go_neg.c @@ -368,8 +368,8 @@ static struct wpabuf * p2p_build_go_neg_resp(struct p2p_data *p2p, } -static void p2p_reselect_channel(struct p2p_data *p2p, - struct p2p_channels *intersection) +void p2p_reselect_channel(struct p2p_data *p2p, + struct p2p_channels *intersection) { struct p2p_reg_class *cl; int freq; diff --git a/src/p2p/p2p_i.h b/src/p2p/p2p_i.h index bf55015..673c4c1 100644 --- a/src/p2p/p2p_i.h +++ b/src/p2p/p2p_i.h @@ -655,6 +655,8 @@ void p2p_process_go_neg_conf(struct p2p_data *p2p, const u8 *sa, const u8 *data, size_t len); int p2p_connect_send(struct p2p_data *p2p, struct p2p_device *dev); u16 p2p_wps_method_pw_id(enum p2p_wps_method wps_method); +void p2p_reselect_channel(struct p2p_data *p2p, + struct p2p_channels *intersection); /* p2p_pd.c */ void p2p_process_prov_disc_req(struct p2p_data *p2p, const u8 *sa, diff --git a/src/p2p/p2p_invitation.c b/src/p2p/p2p_invitation.c index 785200c..7d6dd11 100644 --- a/src/p2p/p2p_invitation.c +++ b/src/p2p/p2p_invitation.c @@ -253,6 +253,8 @@ void p2p_process_invitation_req(struct p2p_data *p2p, const u8 *sa, } if (op_freq) { + wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Invitation " + "processing forced frequency %d MHz", op_freq); if (p2p_freq_to_channel(p2p->cfg->country, op_freq, ®_class, &channel) < 0) { wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, @@ -276,24 +278,89 @@ void p2p_process_invitation_req(struct p2p_data *p2p, const u8 *sa, if (status == P2P_SC_SUCCESS) channels = &intersection; } else { + wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, + "P2P: No forced channel from invitation processing - " + "figure out best one to use"); + + p2p_channels_intersect(&p2p->cfg->channels, &dev->channels, + &intersection); + /* Default to own configuration as a starting point */ + p2p->op_reg_class = p2p->cfg->op_reg_class; + p2p->op_channel = p2p->cfg->op_channel; + wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Own default " + "op_class %d channel %d", + p2p->op_reg_class, p2p->op_channel); + + /* Use peer preference if specified and compatible */ + if (msg.operating_channel) { + int req_freq; + req_freq = p2p_channel_to_freq( + (const char *) msg.operating_channel, + msg.operating_channel[3], + msg.operating_channel[4]); + wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer " + "operating channel preference: %d MHz", + req_freq); + if (req_freq > 0 && + p2p_channels_includes(&intersection, + msg.operating_channel[3], + msg.operating_channel[4])) { + p2p->op_reg_class = msg.operating_channel[3]; + p2p->op_channel = msg.operating_channel[4]; + wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, + "P2P: Use peer preference op_class %d " + "channel %d", + p2p->op_reg_class, p2p->op_channel); + } else { + wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, + "P2P: Cannot use peer channel " + "preference"); + } + } + + if (!p2p_channels_includes(&intersection, p2p->op_reg_class, + p2p->op_channel)) { + wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, + "P2P: Initially selected channel (op_class %d " + "channel %d) not in channel intersection - try " + "to reselect", + p2p->op_reg_class, p2p->op_channel); + p2p_reselect_channel(p2p, &intersection); + wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, + "P2P: Re-selection result: op_class %d " + "channel %d", + p2p->op_reg_class, p2p->op_channel); + if (!p2p_channels_includes(&intersection, + p2p->op_reg_class, + p2p->op_channel)) { + wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, + "P2P: Peer does not support selected " + "operating channel (reg_class=%u " + "channel=%u)", + p2p->op_reg_class, p2p->op_channel); + status = P2P_SC_FAIL_NO_COMMON_CHANNELS; + goto fail; + } + } + op_freq = p2p_channel_to_freq(p2p->cfg->country, - p2p->cfg->op_reg_class, - p2p->cfg->op_channel); + p2p->op_reg_class, + p2p->op_channel); if (op_freq < 0) { wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Unknown operational channel " "(country=%c%c reg_class=%u channel=%u)", p2p->cfg->country[0], p2p->cfg->country[1], - p2p->cfg->op_reg_class, p2p->cfg->op_channel); + p2p->op_reg_class, p2p->op_channel); status = P2P_SC_FAIL_NO_COMMON_CHANNELS; goto fail; } + wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Selected operating " + "channel - %d MHz", op_freq); - p2p_channels_intersect(&p2p->cfg->channels, &dev->channels, - &intersection); if (status == P2P_SC_SUCCESS) { - reg_class = p2p->cfg->op_reg_class; - channel = p2p->cfg->op_channel; + reg_class = p2p->op_reg_class; + channel = p2p->op_channel; channels = &intersection; } } diff --git a/src/p2p/p2p_pd.c b/src/p2p/p2p_pd.c index a2d5aee..42447e5 100644 --- a/src/p2p/p2p_pd.c +++ b/src/p2p/p2p_pd.c @@ -278,11 +278,6 @@ void p2p_process_prov_disc_resp(struct p2p_data *p2p, const u8 *sa, return; } - if (p2p->pending_action_state == P2P_PENDING_PD) { - os_memset(p2p->pending_pd_devaddr, 0, ETH_ALEN); - p2p->pending_action_state = P2P_NO_PENDING_ACTION; - } - if (dev->dialog_token != msg.dialog_token) { wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Ignore Provision Discovery Response with " @@ -292,6 +287,11 @@ void p2p_process_prov_disc_resp(struct p2p_data *p2p, const u8 *sa, return; } + if (p2p->pending_action_state == P2P_PENDING_PD) { + os_memset(p2p->pending_pd_devaddr, 0, ETH_ALEN); + p2p->pending_action_state = P2P_NO_PENDING_ACTION; + } + /* * If the response is from the peer to whom a user initiated request * was sent earlier, we reset that state info here. diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index cf8f935..c721a29 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -377,6 +377,7 @@ static int wpas_p2p_group_delete(struct wpa_supplicant *wpa_s, wpa_config_remove_network(wpa_s->conf, id); wpa_supplicant_clear_status(wpa_s); wpa_supplicant_cancel_sched_scan(wpa_s); + wpa_s->sta_scan_pending = 0; } else { wpa_printf(MSG_DEBUG, "P2P: Temporary group network not " "found"); @@ -2322,8 +2323,9 @@ static void wpas_invitation_received(void *ctx, const u8 *sa, const u8 *bssid, " was accepted; op_freq=%d MHz", MAC2STR(sa), op_freq); if (s) { + int go = s->mode == WPAS_MODE_P2P_GO; wpas_p2p_group_add_persistent( - wpa_s, s, s->mode == WPAS_MODE_P2P_GO, 0, 0); + wpa_s, s, go, go ? op_freq : 0, 0); } else if (bssid) { wpas_p2p_join(wpa_s, bssid, go_dev_addr, wpa_s->p2p_wps_method, 0); -- 2.11.0