From 59b45d1afe9270b424d0a42f81e5fb1e1857b1b4 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 4 Apr 2013 16:18:46 +0300 Subject: [PATCH] P2P NFC: Add processing of P2P client while NFC handover case Instead of automatically triggering a connection, provide an indication of one of the devices being a P2P client to upper layers to allow user to determine what to do next. Signed-hostap: Jouni Malinen --- src/common/wpa_ctrl.h | 2 + src/p2p/p2p.c | 83 +++++++++++++++++++++++------------------ src/p2p/p2p.h | 8 ++-- wpa_supplicant/p2p_supplicant.c | 72 +++++++++++++++++++++++++---------- 4 files changed, 107 insertions(+), 58 deletions(-) diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h index 5948ca7..759cee4 100644 --- a/src/common/wpa_ctrl.h +++ b/src/common/wpa_ctrl.h @@ -151,6 +151,8 @@ extern "C" { #define P2P_EVENT_PERSISTENT_PSK_FAIL "P2P-PERSISTENT-PSK-FAIL id=" #define P2P_EVENT_PRESENCE_RESPONSE "P2P-PRESENCE-RESPONSE " #define P2P_EVENT_NFC_BOTH_GO "P2P-NFC-BOTH-GO " +#define P2P_EVENT_NFC_PEER_CLIENT "P2P-NFC-PEER-CLIENT " +#define P2P_EVENT_NFC_WHILE_CLIENT "P2P-NFC-WHILE-CLIENT " /* parameters: */ #define ESS_DISASSOC_IMMINENT "ESS-DISASSOC-IMMINENT " diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c index 3e9bc19..d82f760 100644 --- a/src/p2p/p2p.c +++ b/src/p2p/p2p.c @@ -4379,7 +4379,8 @@ void p2p_err(struct p2p_data *p2p, const char *fmt, ...) #ifdef CONFIG_WPS_NFC -static struct wpabuf * p2p_build_nfc_handover(struct p2p_data *p2p) +static struct wpabuf * p2p_build_nfc_handover(struct p2p_data *p2p, + int client_freq) { struct wpabuf *buf; u8 op_class, channel; @@ -4400,6 +4401,9 @@ static struct wpabuf * p2p_build_nfc_handover(struct p2p_data *p2p) role = P2P_GO_IN_A_GROUP; p2p_freq_to_channel(p2p_group_get_freq(p2p->groups[0]), &op_class, &channel); + } else if (client_freq > 0) { + role = P2P_CLIENT_IN_A_GROUP; + p2p_freq_to_channel(client_freq, &op_class, &channel); } p2p_buf_add_oob_go_neg_channel(buf, p2p->cfg->country, op_class, @@ -4415,15 +4419,17 @@ static struct wpabuf * p2p_build_nfc_handover(struct p2p_data *p2p) } -struct wpabuf * p2p_build_nfc_handover_req(struct p2p_data *p2p) +struct wpabuf * p2p_build_nfc_handover_req(struct p2p_data *p2p, + int client_freq) { - return p2p_build_nfc_handover(p2p); + return p2p_build_nfc_handover(p2p, client_freq); } -struct wpabuf * p2p_build_nfc_handover_sel(struct p2p_data *p2p) +struct wpabuf * p2p_build_nfc_handover_sel(struct p2p_data *p2p, + int client_freq) { - return p2p_build_nfc_handover(p2p); + return p2p_build_nfc_handover(p2p, client_freq); } @@ -4433,7 +4439,8 @@ int p2p_process_nfc_connection_handover(struct p2p_data *p2p, struct p2p_message msg; struct p2p_device *dev; const u8 *p2p_dev_addr; - int peer_go = 0; + int freq; + enum p2p_role_indication role; params->next_step = NO_ACTION; @@ -4472,37 +4479,38 @@ int p2p_process_nfc_connection_handover(struct p2p_data *p2p, dev->flags &= ~(P2P_DEV_PROBE_REQ_ONLY | P2P_DEV_GROUP_CLIENT_ONLY); p2p_copy_wps_info(p2p, dev, 0, &msg); - if (msg.oob_go_neg_channel) { - int freq; - if (msg.oob_go_neg_channel[3] == 0 && - msg.oob_go_neg_channel[4] == 0) - freq = 0; - else - freq = p2p_channel_to_freq(msg.oob_go_neg_channel[3], - msg.oob_go_neg_channel[4]); - if (freq < 0) { - p2p_dbg(p2p, "Unknown peer OOB GO Neg channel"); - } else { - p2p_dbg(p2p, "Peer OOB GO Neg channel: %u MHz", freq); - dev->oob_go_neg_freq = freq; - } + if (!msg.oob_go_neg_channel) { + p2p_dbg(p2p, "OOB GO Negotiation Channel attribute not included"); + return -1; + } - if (!params->sel) { - freq = p2p_channel_to_freq(p2p->cfg->reg_class, - p2p->cfg->channel); - if (freq < 0) { - p2p_dbg(p2p, "Own listen channel not known"); - return -1; - } - p2p_dbg(p2p, "Use own Listen channel as OOB GO Neg channel: %u MHz", - freq); - dev->oob_go_neg_freq = freq; - } + if (msg.oob_go_neg_channel[3] == 0 && + msg.oob_go_neg_channel[4] == 0) + freq = 0; + else + freq = p2p_channel_to_freq(msg.oob_go_neg_channel[3], + msg.oob_go_neg_channel[4]); + 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; + } - if (msg.oob_go_neg_channel[5] == P2P_GO_IN_A_GROUP) - peer_go = 1; + if (!params->sel) { + freq = p2p_channel_to_freq(p2p->cfg->reg_class, + p2p->cfg->channel); + if (freq < 0) { + p2p_dbg(p2p, "Own listen channel not known"); + return -1; + } + p2p_dbg(p2p, "Use own Listen channel as OOB GO Neg channel: %u MHz", freq); + dev->oob_go_neg_freq = freq; } + role = msg.oob_go_neg_channel[5]; + p2p_parse_free(&msg); if (dev->flags & P2P_DEV_USER_REJECTED) { @@ -4516,11 +4524,14 @@ int p2p_process_nfc_connection_handover(struct p2p_data *p2p, dev->flags |= P2P_DEV_REPORTED | P2P_DEV_REPORTED_ONCE; } - if (peer_go && p2p->num_groups > 0) + if (role == P2P_GO_IN_A_GROUP && p2p->num_groups > 0) params->next_step = BOTH_GO; - else if (peer_go) + else if (role == P2P_GO_IN_A_GROUP) params->next_step = JOIN_GROUP; - else if (p2p->num_groups > 0) + else if (role == P2P_CLIENT_IN_A_GROUP) { + dev->flags |= P2P_DEV_GROUP_CLIENT_ONLY; + params->next_step = PEER_CLIENT; + } else if (p2p->num_groups > 0) params->next_step = AUTH_JOIN; else if (params->sel) params->next_step = INIT_GO_NEG; diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h index d5432c0..43b24c8 100644 --- a/src/p2p/p2p.h +++ b/src/p2p/p2p.h @@ -1899,8 +1899,10 @@ int p2p_set_disc_int(struct p2p_data *p2p, int min_disc_int, int max_disc_int, */ const char * p2p_get_state_txt(struct p2p_data *p2p); -struct wpabuf * p2p_build_nfc_handover_req(struct p2p_data *p2p); -struct wpabuf * p2p_build_nfc_handover_sel(struct p2p_data *p2p); +struct wpabuf * p2p_build_nfc_handover_req(struct p2p_data *p2p, + int client_freq); +struct wpabuf * p2p_build_nfc_handover_sel(struct p2p_data *p2p, + int client_freq); struct p2p_nfc_params { int sel; @@ -1911,7 +1913,7 @@ struct p2p_nfc_params { enum { NO_ACTION, JOIN_GROUP, AUTH_JOIN, INIT_GO_NEG, RESP_GO_NEG, - BOTH_GO + BOTH_GO, PEER_CLIENT } next_step; struct p2p_peer_info *peer; u8 oob_dev_pw[WPS_OOB_PUBKEY_HASH_LEN + 2 + diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index fa8c648..254314d 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -6975,11 +6975,7 @@ static struct wpabuf * wpas_p2p_nfc_handover(int ndef, struct wpabuf *wsc, struct wpabuf *p2p) { struct wpabuf *ret; - - if (wsc == NULL) { - wpabuf_free(p2p); - return NULL; - } + size_t wsc_len; if (p2p == NULL) { wpabuf_free(wsc); @@ -6987,15 +6983,17 @@ static struct wpabuf * wpas_p2p_nfc_handover(int ndef, struct wpabuf *wsc, return NULL; } - ret = wpabuf_alloc(2 + wpabuf_len(wsc) + 2 + wpabuf_len(p2p)); + wsc_len = wsc ? wpabuf_len(wsc) : 0; + ret = wpabuf_alloc(2 + wsc_len + 2 + wpabuf_len(p2p)); if (ret == NULL) { wpabuf_free(wsc); wpabuf_free(p2p); return NULL; } - wpabuf_put_be16(ret, wpabuf_len(wsc)); - wpabuf_put_buf(ret, wsc); + wpabuf_put_be16(ret, wsc_len); + if (wsc) + wpabuf_put_buf(ret, wsc); wpabuf_put_be16(ret, wpabuf_len(p2p)); wpabuf_put_buf(ret, p2p); @@ -7019,10 +7017,27 @@ static struct wpabuf * wpas_p2p_nfc_handover(int ndef, struct wpabuf *wsc, } +static int wpas_p2p_cli_freq(struct wpa_supplicant *wpa_s) +{ + struct wpa_supplicant *iface; + + for (iface = wpa_s->global->ifaces; iface; iface = iface->next) { + if (iface->wpa_state < WPA_ASSOCIATING || + iface->current_ssid == NULL || iface->assoc_freq == 0 || + !iface->current_ssid->p2p_group || + iface->current_ssid->mode != WPAS_MODE_INFRA) + continue; + return iface->assoc_freq; + } + return 0; +} + + struct wpabuf * wpas_p2p_nfc_handover_req(struct wpa_supplicant *wpa_s, int ndef) { struct wpabuf *wsc, *p2p; + int cli_freq = wpas_p2p_cli_freq(wpa_s); if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL) { wpa_printf(MSG_DEBUG, "P2P: P2P disabled - cannot build handover request"); @@ -7036,9 +7051,12 @@ struct wpabuf * wpas_p2p_nfc_handover_req(struct wpa_supplicant *wpa_s, return NULL; } - wsc = wps_build_nfc_handover_req_p2p(wpa_s->parent->wps, - wpa_s->conf->wps_nfc_dh_pubkey); - p2p = p2p_build_nfc_handover_req(wpa_s->global->p2p); + if (cli_freq == 0) { + wsc = wps_build_nfc_handover_req_p2p( + wpa_s->parent->wps, wpa_s->conf->wps_nfc_dh_pubkey); + } else + wsc = NULL; + p2p = p2p_build_nfc_handover_req(wpa_s->global->p2p, cli_freq); return wpas_p2p_nfc_handover(ndef, wsc, p2p); } @@ -7048,6 +7066,7 @@ struct wpabuf * wpas_p2p_nfc_handover_sel(struct wpa_supplicant *wpa_s, int ndef, int tag) { struct wpabuf *wsc, *p2p; + int cli_freq = wpas_p2p_cli_freq(wpa_s); if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL) return NULL; @@ -7057,14 +7076,16 @@ struct wpabuf * wpas_p2p_nfc_handover_sel(struct wpa_supplicant *wpa_s, &wpa_s->conf->wps_nfc_dh_privkey) < 0) return NULL; - wsc = wps_build_nfc_handover_sel_p2p(wpa_s->parent->wps, - tag ? - wpa_s->conf->wps_nfc_dev_pw_id : - DEV_PW_NFC_CONNECTION_HANDOVER, - wpa_s->conf->wps_nfc_dh_pubkey, - tag ? wpa_s->conf->wps_nfc_dev_pw : - NULL); - p2p = p2p_build_nfc_handover_sel(wpa_s->global->p2p); + if (cli_freq == 0) { + wsc = wps_build_nfc_handover_sel_p2p( + wpa_s->parent->wps, + tag ? wpa_s->conf->wps_nfc_dev_pw_id : + DEV_PW_NFC_CONNECTION_HANDOVER, + wpa_s->conf->wps_nfc_dh_pubkey, + tag ? wpa_s->conf->wps_nfc_dev_pw : NULL); + } else + wsc = NULL; + p2p = p2p_build_nfc_handover_sel(wpa_s->global->p2p, cli_freq); return wpas_p2p_nfc_handover(ndef, wsc, p2p); } @@ -7221,6 +7242,18 @@ static int wpas_p2p_nfc_connection_handover(struct wpa_supplicant *wpa_s, return 0; } + if (params.next_step == PEER_CLIENT) { + wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_NFC_PEER_CLIENT "peer=" + MACSTR, MAC2STR(params.peer->p2p_device_addr)); + return 0; + } + + if (wpas_p2p_cli_freq(wpa_s)) { + wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_NFC_WHILE_CLIENT "peer=" + MACSTR, MAC2STR(params.peer->p2p_device_addr)); + return 0; + } + wpabuf_free(wpa_s->p2p_oob_dev_pw); wpa_s->p2p_oob_dev_pw = NULL; @@ -7271,6 +7304,7 @@ static int wpas_p2p_nfc_connection_handover(struct wpa_supplicant *wpa_s, switch (params.next_step) { case NO_ACTION: case BOTH_GO: + case PEER_CLIENT: /* already covered above */ return 0; case JOIN_GROUP: -- 2.1.4