From 23318bea947a28c3d147ca4db98aba6aadd22afa Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 7 Sep 2013 15:44:29 -0700 Subject: [PATCH] P2P NFC: Optimize join-a-group operation based on NFC information When the NFC connection handover message received from a peer indicates that the peer is operating as a GO on a specific channel, use that information to avoid having to go through full scan. In addition, skip the separate join-a-group scan since we already know the operating channel, GO P2P Device Address, and SSID. Signed-hostap: Jouni Malinen --- src/p2p/p2p.c | 20 ++++++-- src/p2p/p2p.h | 4 ++ wpa_supplicant/ctrl_iface.c | 3 +- wpa_supplicant/p2p_supplicant.c | 82 +++++++++++++++++++++++---------- wpa_supplicant/wps_supplicant.c | 31 +++++++++---- wpa_supplicant/wps_supplicant.h | 3 +- 6 files changed, 101 insertions(+), 42 deletions(-) diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c index d82f76036..64dc8bd2c 100644 --- a/src/p2p/p2p.c +++ b/src/p2p/p2p.c @@ -4493,12 +4493,17 @@ int p2p_process_nfc_connection_handover(struct p2p_data *p2p, if (freq < 0) { p2p_dbg(p2p, "Unknown peer OOB GO Neg channel"); return -1; - } else { - p2p_dbg(p2p, "Peer OOB GO Neg channel: %u MHz", freq); - dev->oob_go_neg_freq = freq; } + role = msg.oob_go_neg_channel[5]; - if (!params->sel) { + if (role == P2P_GO_IN_A_GROUP) { + p2p_dbg(p2p, "Peer OOB GO operating channel: %u MHz", freq); + params->go_freq = freq; + } else + p2p_dbg(p2p, "Peer OOB GO Neg channel: %u MHz", freq); + dev->oob_go_neg_freq = freq; + + if (!params->sel && role != P2P_GO_IN_A_GROUP) { freq = p2p_channel_to_freq(p2p->cfg->reg_class, p2p->cfg->channel); if (freq < 0) { @@ -4509,7 +4514,12 @@ int p2p_process_nfc_connection_handover(struct p2p_data *p2p, dev->oob_go_neg_freq = freq; } - role = msg.oob_go_neg_channel[5]; + if (msg.group_id) { + os_memcpy(params->go_dev_addr, msg.group_id, ETH_ALEN); + params->go_ssid_len = msg.group_id_len - ETH_ALEN; + os_memcpy(params->go_ssid, msg.group_id + ETH_ALEN, + params->go_ssid_len); + } p2p_parse_free(&msg); diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h index 43b24c850..3831b1c23 100644 --- a/src/p2p/p2p.h +++ b/src/p2p/p2p.h @@ -1919,6 +1919,10 @@ struct p2p_nfc_params { u8 oob_dev_pw[WPS_OOB_PUBKEY_HASH_LEN + 2 + WPS_OOB_DEVICE_PASSWORD_LEN]; size_t oob_dev_pw_len; + int go_freq; + u8 go_dev_addr[ETH_ALEN]; + u8 go_ssid[32]; + size_t go_ssid_len; }; int p2p_process_nfc_connection_handover(struct p2p_data *p2p, diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index c34c7a8f3..670562377 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -813,7 +813,8 @@ static int wpa_supplicant_ctrl_iface_wps_nfc(struct wpa_supplicant *wpa_s, else if (hwaddr_aton(cmd, bssid)) return -1; - return wpas_wps_start_nfc(wpa_s, _bssid, NULL, 0, 0, NULL, NULL, 0); + return wpas_wps_start_nfc(wpa_s, NULL, _bssid, NULL, 0, 0, NULL, NULL, + 0); } diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index 586708719..9c815ae95 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -103,13 +103,15 @@ static void wpas_p2p_long_listen_timeout(void *eloop_ctx, void *timeout_ctx); static struct wpa_supplicant * 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); +static int wpas_p2p_join_start(struct wpa_supplicant *wpa_s, int freq, + const u8 *ssid, size_t ssid_len); 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); static int wpas_p2p_join(struct wpa_supplicant *wpa_s, const u8 *iface_addr, const u8 *dev_addr, enum p2p_wps_method wps_method, - int auto_join, const u8 *ssid, size_t ssid_len); + int auto_join, int freq, + const u8 *ssid, size_t ssid_len); static int wpas_p2p_create_iface(struct wpa_supplicant *wpa_s); static void wpas_p2p_cross_connect_setup(struct wpa_supplicant *wpa_s); static void wpas_p2p_group_idle_timeout(void *eloop_ctx, void *timeout_ctx); @@ -580,6 +582,10 @@ static int wpas_p2p_persistent_group(struct wpa_supplicant *wpa_s, bssid = wpa_s->bssid; bss = wpa_bss_get(wpa_s, bssid, ssid, ssid_len); + if (bss == NULL && wpa_s->go_params && + !is_zero_ether_addr(wpa_s->go_params->peer_device_addr)) + bss = wpa_bss_get_p2p_dev_addr( + wpa_s, wpa_s->go_params->peer_device_addr); if (bss == NULL) { u8 iface_addr[ETH_ALEN]; if (p2p_get_interface_addr(wpa_s->global->p2p, bssid, @@ -1101,8 +1107,10 @@ static int wpas_copy_go_neg_results(struct wpa_supplicant *wpa_s, static void wpas_start_wps_enrollee(struct wpa_supplicant *wpa_s, struct p2p_go_neg_results *res) { - wpa_printf(MSG_DEBUG, "P2P: Start WPS Enrollee for peer " MACSTR, - MAC2STR(res->peer_interface_addr)); + wpa_printf(MSG_DEBUG, "P2P: Start WPS Enrollee for peer " MACSTR + " dev_addr " MACSTR, + MAC2STR(res->peer_interface_addr), + MAC2STR(res->peer_device_addr)); wpa_hexdump_ascii(MSG_DEBUG, "P2P: Start WPS Enrollee for SSID", res->ssid, res->ssid_len); wpa_supplicant_ap_deinit(wpa_s); @@ -1111,7 +1119,8 @@ static void wpas_start_wps_enrollee(struct wpa_supplicant *wpa_s, wpas_wps_start_pbc(wpa_s, res->peer_interface_addr, 1); #ifdef CONFIG_WPS_NFC } else if (res->wps_method == WPS_NFC) { - wpas_wps_start_nfc(wpa_s, res->peer_interface_addr, + wpas_wps_start_nfc(wpa_s, res->peer_device_addr, + res->peer_interface_addr, wpa_s->parent->p2p_oob_dev_pw, wpa_s->parent->p2p_oob_dev_pw_id, 1, wpa_s->parent->p2p_oob_dev_pw_id == @@ -2821,7 +2830,7 @@ static void wpas_prov_disc_resp(void *ctx, const u8 *peer, u16 config_methods) wpa_s->pending_pd_before_join = 0; wpa_printf(MSG_DEBUG, "P2P: Starting pending " "join-existing-group operation"); - wpas_p2p_join_start(wpa_s); + wpas_p2p_join_start(wpa_s, 0, NULL, 0); return; } @@ -2865,7 +2874,7 @@ static void wpas_prov_disc_fail(void *ctx, const u8 *peer, wpa_printf(MSG_DEBUG, "P2P: Starting pending " "join-existing-group operation (no ACK for PD " "Req attempts)"); - wpas_p2p_join_start(wpa_s); + wpas_p2p_join_start(wpa_s, 0, NULL, 0); return; } @@ -3034,7 +3043,7 @@ static void wpas_invitation_received(void *ctx, const u8 *sa, const u8 *bssid, } else if (bssid) { wpa_s->user_initiated_pd = 0; wpas_p2p_join(wpa_s, bssid, go_dev_addr, - wpa_s->p2p_wps_method, 0, + wpa_s->p2p_wps_method, 0, op_freq, ssid, ssid_len); } return; @@ -4283,7 +4292,7 @@ static void wpas_p2p_scan_res_join(struct wpa_supplicant *wpa_s, start: /* Start join operation immediately */ - wpas_p2p_join_start(wpa_s); + wpas_p2p_join_start(wpa_s, 0, NULL, 0); } @@ -4384,11 +4393,12 @@ static void wpas_p2p_join_scan(void *eloop_ctx, void *timeout_ctx) static int wpas_p2p_join(struct wpa_supplicant *wpa_s, const u8 *iface_addr, const u8 *dev_addr, enum p2p_wps_method wps_method, - int auto_join, const u8 *ssid, size_t ssid_len) + int auto_join, int op_freq, + const u8 *ssid, size_t ssid_len) { wpa_printf(MSG_DEBUG, "P2P: Request to join existing group (iface " - MACSTR " dev " MACSTR ")%s", - MAC2STR(iface_addr), MAC2STR(dev_addr), + MACSTR " dev " MACSTR " op_freq=%d)%s", + MAC2STR(iface_addr), MAC2STR(dev_addr), op_freq, auto_join ? " (auto_join)" : ""); if (ssid && ssid_len) { wpa_printf(MSG_DEBUG, "P2P: Group SSID specified: %s", @@ -4405,12 +4415,13 @@ static int wpas_p2p_join(struct wpa_supplicant *wpa_s, const u8 *iface_addr, wpas_p2p_stop_find(wpa_s); wpa_s->p2p_join_scan_count = 0; - wpas_p2p_join_scan_req(wpa_s, 0, ssid, ssid_len); + wpas_p2p_join_scan_req(wpa_s, op_freq, ssid, ssid_len); return 0; } -static int wpas_p2p_join_start(struct wpa_supplicant *wpa_s) +static int wpas_p2p_join_start(struct wpa_supplicant *wpa_s, int freq, + const u8 *ssid, size_t ssid_len) { struct wpa_supplicant *group; struct p2p_go_neg_results res; @@ -4438,17 +4449,25 @@ static int wpas_p2p_join_start(struct wpa_supplicant *wpa_s) group->p2p_fallback_to_go_neg = wpa_s->p2p_fallback_to_go_neg; os_memset(&res, 0, sizeof(res)); + os_memcpy(res.peer_device_addr, wpa_s->pending_join_dev_addr, ETH_ALEN); os_memcpy(res.peer_interface_addr, wpa_s->pending_join_iface_addr, ETH_ALEN); res.wps_method = wpa_s->pending_join_wps_method; - bss = wpa_bss_get_bssid_latest(wpa_s, wpa_s->pending_join_iface_addr); - if (bss) { - res.freq = bss->freq; - res.ssid_len = bss->ssid_len; - os_memcpy(res.ssid, bss->ssid, bss->ssid_len); - wpa_printf(MSG_DEBUG, "P2P: Join target GO operating frequency " - "from BSS table: %d MHz (SSID %s)", bss->freq, - wpa_ssid_txt(bss->ssid, bss->ssid_len)); + if (freq && ssid && ssid_len) { + res.freq = freq; + res.ssid_len = ssid_len; + os_memcpy(res.ssid, ssid, ssid_len); + } else { + bss = wpa_bss_get_bssid_latest(wpa_s, + wpa_s->pending_join_iface_addr); + if (bss) { + res.freq = bss->freq; + res.ssid_len = bss->ssid_len; + os_memcpy(res.ssid, bss->ssid, bss->ssid_len); + wpa_printf(MSG_DEBUG, "P2P: Join target GO operating frequency from BSS table: %d MHz (SSID %s)", + bss->freq, + wpa_ssid_txt(bss->ssid, bss->ssid_len)); + } } if (wpa_s->off_channel_freq || wpa_s->roc_waiting_drv_freq) { @@ -4660,7 +4679,7 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr, } wpa_s->user_initiated_pd = 1; if (wpas_p2p_join(wpa_s, iface_addr, dev_addr, wps_method, - auto_join, NULL, 0) < 0) + auto_join, freq, NULL, 0) < 0) return -1; return ret; } @@ -7100,10 +7119,23 @@ static int wpas_p2p_nfc_join_group(struct wpa_supplicant *wpa_s, struct p2p_nfc_params *params) { wpa_printf(MSG_DEBUG, "P2P: Initiate join-group based on NFC " - "connection handover"); + "connection handover (freq=%d)", + params->go_freq); + + if (params->go_freq && params->go_ssid_len) { + wpa_s->p2p_wps_method = WPS_NFC; + wpa_s->pending_join_wps_method = WPS_NFC; + os_memset(wpa_s->pending_join_iface_addr, 0, ETH_ALEN); + os_memcpy(wpa_s->pending_join_dev_addr, params->go_dev_addr, + ETH_ALEN); + return wpas_p2p_join_start(wpa_s, params->go_freq, + params->go_ssid, + params->go_ssid_len); + } + return wpas_p2p_connect(wpa_s, params->peer->p2p_device_addr, NULL, WPS_NFC, 0, 0, 1, 0, wpa_s->conf->p2p_go_intent, - 0, -1, 0, 1, 1); + params->go_freq, -1, 0, 1, 1); } diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c index aaf563f59..1f6dd92ad 100644 --- a/wpa_supplicant/wps_supplicant.c +++ b/wpa_supplicant/wps_supplicant.c @@ -911,7 +911,8 @@ static void wpas_wps_timeout(void *eloop_ctx, void *timeout_ctx) static struct wpa_ssid * wpas_wps_add_network(struct wpa_supplicant *wpa_s, - int registrar, const u8 *bssid) + int registrar, const u8 *dev_addr, + const u8 *bssid) { struct wpa_ssid *ssid; @@ -931,6 +932,11 @@ static struct wpa_ssid * wpas_wps_add_network(struct wpa_supplicant *wpa_s, return NULL; } +#ifdef CONFIG_P2P + if (dev_addr) + os_memcpy(ssid->go_p2p_dev_addr, dev_addr, ETH_ALEN); +#endif /* CONFIG_P2P */ + if (bssid) { #ifndef CONFIG_P2P struct wpa_bss *bss; @@ -1044,7 +1050,7 @@ int wpas_wps_start_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid, { struct wpa_ssid *ssid; wpas_clear_wps(wpa_s); - ssid = wpas_wps_add_network(wpa_s, 0, bssid); + ssid = wpas_wps_add_network(wpa_s, 0, NULL, bssid); if (ssid == NULL) return -1; ssid->temporary = 1; @@ -1072,7 +1078,8 @@ int wpas_wps_start_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid, } -static int wpas_wps_start_dev_pw(struct wpa_supplicant *wpa_s, const u8 *bssid, +static int wpas_wps_start_dev_pw(struct wpa_supplicant *wpa_s, + const u8 *dev_addr, const u8 *bssid, const char *pin, int p2p_group, u16 dev_pw_id, const u8 *peer_pubkey_hash, const u8 *ssid_val, size_t ssid_len) @@ -1083,7 +1090,9 @@ static int wpas_wps_start_dev_pw(struct wpa_supplicant *wpa_s, const u8 *bssid, char hash[2 * WPS_OOB_PUBKEY_HASH_LEN + 10]; wpas_clear_wps(wpa_s); - ssid = wpas_wps_add_network(wpa_s, 0, bssid); + if (bssid && is_zero_ether_addr(bssid)) + bssid = NULL; + ssid = wpas_wps_add_network(wpa_s, 0, dev_addr, bssid); if (ssid == NULL) { wpa_printf(MSG_DEBUG, "WPS: Could not add network"); return -1; @@ -1145,8 +1154,8 @@ static int wpas_wps_start_dev_pw(struct wpa_supplicant *wpa_s, const u8 *bssid, int wpas_wps_start_pin(struct wpa_supplicant *wpa_s, const u8 *bssid, const char *pin, int p2p_group, u16 dev_pw_id) { - return wpas_wps_start_dev_pw(wpa_s, bssid, pin, p2p_group, dev_pw_id, - NULL, NULL, 0); + return wpas_wps_start_dev_pw(wpa_s, NULL, bssid, pin, p2p_group, + dev_pw_id, NULL, NULL, 0); } @@ -1196,7 +1205,7 @@ int wpas_wps_start_reg(struct wpa_supplicant *wpa_s, const u8 *bssid, if (!pin) return -1; wpas_clear_wps(wpa_s); - ssid = wpas_wps_add_network(wpa_s, 1, bssid); + ssid = wpas_wps_add_network(wpa_s, 1, NULL, bssid); if (ssid == NULL) return -1; ssid->temporary = 1; @@ -2118,7 +2127,8 @@ struct wpabuf * wpas_wps_nfc_token(struct wpa_supplicant *wpa_s, int ndef) } -int wpas_wps_start_nfc(struct wpa_supplicant *wpa_s, const u8 *bssid, +int wpas_wps_start_nfc(struct wpa_supplicant *wpa_s, const u8 *go_dev_addr, + const u8 *bssid, const struct wpabuf *dev_pw, u16 dev_pw_id, int p2p_group, const u8 *peer_pubkey_hash, const u8 *ssid, size_t ssid_len) @@ -2173,7 +2183,8 @@ int wpas_wps_start_nfc(struct wpa_supplicant *wpa_s, const u8 *bssid, wpabuf_head(dev_pw), wpabuf_len(dev_pw)); } - return wpas_wps_start_dev_pw(wpa_s, bssid, dev_pw ? pw : NULL, + return wpas_wps_start_dev_pw(wpa_s, go_dev_addr, bssid, + dev_pw ? pw : NULL, p2p_group, dev_pw_id, peer_pubkey_hash, ssid, ssid_len); } @@ -2484,7 +2495,7 @@ int wpas_wps_nfc_rx_handover_sel(struct wpa_supplicant *wpa_s, wpa_hexdump(MSG_DEBUG, "WPS: AP Public Key hash", attr.oob_dev_password, WPS_OOB_PUBKEY_HASH_LEN); - ret = wpas_wps_start_nfc(wpa_s, NULL, NULL, dev_pw_id, 0, + ret = wpas_wps_start_nfc(wpa_s, NULL, NULL, NULL, dev_pw_id, 0, attr.oob_dev_password, attr.ssid, attr.ssid_len); diff --git a/wpa_supplicant/wps_supplicant.h b/wpa_supplicant/wps_supplicant.h index f3c4f4dab..d7002dc57 100644 --- a/wpa_supplicant/wps_supplicant.h +++ b/wpa_supplicant/wps_supplicant.h @@ -64,7 +64,8 @@ void wpas_wps_update_config(struct wpa_supplicant *wpa_s); struct wpabuf * wpas_wps_nfc_config_token(struct wpa_supplicant *wpa_s, int ndef, const char *id_str); struct wpabuf * wpas_wps_nfc_token(struct wpa_supplicant *wpa_s, int ndef); -int wpas_wps_start_nfc(struct wpa_supplicant *wpa_s, const u8 *bssid, +int wpas_wps_start_nfc(struct wpa_supplicant *wpa_s, const u8 *dev_addr, + const u8 *bssid, const struct wpabuf *dev_pw, u16 dev_pw_id, int p2p_group, const u8 *peer_pubkey_hash, const u8 *ssid, size_t ssid_len);