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 <jouni@qca.qualcomm.com>
This commit is contained in:
parent
74df9ecd4a
commit
59b45d1afe
4 changed files with 109 additions and 60 deletions
|
@ -151,6 +151,8 @@ extern "C" {
|
||||||
#define P2P_EVENT_PERSISTENT_PSK_FAIL "P2P-PERSISTENT-PSK-FAIL id="
|
#define P2P_EVENT_PERSISTENT_PSK_FAIL "P2P-PERSISTENT-PSK-FAIL id="
|
||||||
#define P2P_EVENT_PRESENCE_RESPONSE "P2P-PRESENCE-RESPONSE "
|
#define P2P_EVENT_PRESENCE_RESPONSE "P2P-PRESENCE-RESPONSE "
|
||||||
#define P2P_EVENT_NFC_BOTH_GO "P2P-NFC-BOTH-GO "
|
#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: <PMF enabled> <timeout in ms> <Session Information URL> */
|
/* parameters: <PMF enabled> <timeout in ms> <Session Information URL> */
|
||||||
#define ESS_DISASSOC_IMMINENT "ESS-DISASSOC-IMMINENT "
|
#define ESS_DISASSOC_IMMINENT "ESS-DISASSOC-IMMINENT "
|
||||||
|
|
|
@ -4379,7 +4379,8 @@ void p2p_err(struct p2p_data *p2p, const char *fmt, ...)
|
||||||
|
|
||||||
#ifdef CONFIG_WPS_NFC
|
#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;
|
struct wpabuf *buf;
|
||||||
u8 op_class, channel;
|
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;
|
role = P2P_GO_IN_A_GROUP;
|
||||||
p2p_freq_to_channel(p2p_group_get_freq(p2p->groups[0]),
|
p2p_freq_to_channel(p2p_group_get_freq(p2p->groups[0]),
|
||||||
&op_class, &channel);
|
&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,
|
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_message msg;
|
||||||
struct p2p_device *dev;
|
struct p2p_device *dev;
|
||||||
const u8 *p2p_dev_addr;
|
const u8 *p2p_dev_addr;
|
||||||
int peer_go = 0;
|
int freq;
|
||||||
|
enum p2p_role_indication role;
|
||||||
|
|
||||||
params->next_step = NO_ACTION;
|
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);
|
dev->flags &= ~(P2P_DEV_PROBE_REQ_ONLY | P2P_DEV_GROUP_CLIENT_ONLY);
|
||||||
p2p_copy_wps_info(p2p, dev, 0, &msg);
|
p2p_copy_wps_info(p2p, dev, 0, &msg);
|
||||||
|
|
||||||
if (msg.oob_go_neg_channel) {
|
if (!msg.oob_go_neg_channel) {
|
||||||
int freq;
|
p2p_dbg(p2p, "OOB GO Negotiation Channel attribute not included");
|
||||||
if (msg.oob_go_neg_channel[3] == 0 &&
|
return -1;
|
||||||
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 (!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[5] == P2P_GO_IN_A_GROUP)
|
|
||||||
peer_go = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 (!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);
|
p2p_parse_free(&msg);
|
||||||
|
|
||||||
if (dev->flags & P2P_DEV_USER_REJECTED) {
|
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;
|
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;
|
params->next_step = BOTH_GO;
|
||||||
else if (peer_go)
|
else if (role == P2P_GO_IN_A_GROUP)
|
||||||
params->next_step = JOIN_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;
|
params->next_step = AUTH_JOIN;
|
||||||
else if (params->sel)
|
else if (params->sel)
|
||||||
params->next_step = INIT_GO_NEG;
|
params->next_step = INIT_GO_NEG;
|
||||||
|
|
|
@ -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);
|
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_req(struct p2p_data *p2p,
|
||||||
struct wpabuf * p2p_build_nfc_handover_sel(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 {
|
struct p2p_nfc_params {
|
||||||
int sel;
|
int sel;
|
||||||
|
@ -1911,7 +1913,7 @@ struct p2p_nfc_params {
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
NO_ACTION, JOIN_GROUP, AUTH_JOIN, INIT_GO_NEG, RESP_GO_NEG,
|
NO_ACTION, JOIN_GROUP, AUTH_JOIN, INIT_GO_NEG, RESP_GO_NEG,
|
||||||
BOTH_GO
|
BOTH_GO, PEER_CLIENT
|
||||||
} next_step;
|
} next_step;
|
||||||
struct p2p_peer_info *peer;
|
struct p2p_peer_info *peer;
|
||||||
u8 oob_dev_pw[WPS_OOB_PUBKEY_HASH_LEN + 2 +
|
u8 oob_dev_pw[WPS_OOB_PUBKEY_HASH_LEN + 2 +
|
||||||
|
|
|
@ -6975,11 +6975,7 @@ static struct wpabuf * wpas_p2p_nfc_handover(int ndef, struct wpabuf *wsc,
|
||||||
struct wpabuf *p2p)
|
struct wpabuf *p2p)
|
||||||
{
|
{
|
||||||
struct wpabuf *ret;
|
struct wpabuf *ret;
|
||||||
|
size_t wsc_len;
|
||||||
if (wsc == NULL) {
|
|
||||||
wpabuf_free(p2p);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p2p == NULL) {
|
if (p2p == NULL) {
|
||||||
wpabuf_free(wsc);
|
wpabuf_free(wsc);
|
||||||
|
@ -6987,15 +6983,17 @@ static struct wpabuf * wpas_p2p_nfc_handover(int ndef, struct wpabuf *wsc,
|
||||||
return NULL;
|
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) {
|
if (ret == NULL) {
|
||||||
wpabuf_free(wsc);
|
wpabuf_free(wsc);
|
||||||
wpabuf_free(p2p);
|
wpabuf_free(p2p);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
wpabuf_put_be16(ret, wpabuf_len(wsc));
|
wpabuf_put_be16(ret, wsc_len);
|
||||||
wpabuf_put_buf(ret, wsc);
|
if (wsc)
|
||||||
|
wpabuf_put_buf(ret, wsc);
|
||||||
wpabuf_put_be16(ret, wpabuf_len(p2p));
|
wpabuf_put_be16(ret, wpabuf_len(p2p));
|
||||||
wpabuf_put_buf(ret, 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,
|
struct wpabuf * wpas_p2p_nfc_handover_req(struct wpa_supplicant *wpa_s,
|
||||||
int ndef)
|
int ndef)
|
||||||
{
|
{
|
||||||
struct wpabuf *wsc, *p2p;
|
struct wpabuf *wsc, *p2p;
|
||||||
|
int cli_freq = wpas_p2p_cli_freq(wpa_s);
|
||||||
|
|
||||||
if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL) {
|
if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL) {
|
||||||
wpa_printf(MSG_DEBUG, "P2P: P2P disabled - cannot build handover request");
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
wsc = wps_build_nfc_handover_req_p2p(wpa_s->parent->wps,
|
if (cli_freq == 0) {
|
||||||
wpa_s->conf->wps_nfc_dh_pubkey);
|
wsc = wps_build_nfc_handover_req_p2p(
|
||||||
p2p = p2p_build_nfc_handover_req(wpa_s->global->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);
|
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)
|
int ndef, int tag)
|
||||||
{
|
{
|
||||||
struct wpabuf *wsc, *p2p;
|
struct wpabuf *wsc, *p2p;
|
||||||
|
int cli_freq = wpas_p2p_cli_freq(wpa_s);
|
||||||
|
|
||||||
if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
|
if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
|
||||||
return 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)
|
&wpa_s->conf->wps_nfc_dh_privkey) < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
wsc = wps_build_nfc_handover_sel_p2p(wpa_s->parent->wps,
|
if (cli_freq == 0) {
|
||||||
tag ?
|
wsc = wps_build_nfc_handover_sel_p2p(
|
||||||
wpa_s->conf->wps_nfc_dev_pw_id :
|
wpa_s->parent->wps,
|
||||||
DEV_PW_NFC_CONNECTION_HANDOVER,
|
tag ? wpa_s->conf->wps_nfc_dev_pw_id :
|
||||||
wpa_s->conf->wps_nfc_dh_pubkey,
|
DEV_PW_NFC_CONNECTION_HANDOVER,
|
||||||
tag ? wpa_s->conf->wps_nfc_dev_pw :
|
wpa_s->conf->wps_nfc_dh_pubkey,
|
||||||
NULL);
|
tag ? wpa_s->conf->wps_nfc_dev_pw : NULL);
|
||||||
p2p = p2p_build_nfc_handover_sel(wpa_s->global->p2p);
|
} else
|
||||||
|
wsc = NULL;
|
||||||
|
p2p = p2p_build_nfc_handover_sel(wpa_s->global->p2p, cli_freq);
|
||||||
|
|
||||||
return wpas_p2p_nfc_handover(ndef, wsc, p2p);
|
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;
|
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);
|
wpabuf_free(wpa_s->p2p_oob_dev_pw);
|
||||||
wpa_s->p2p_oob_dev_pw = NULL;
|
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) {
|
switch (params.next_step) {
|
||||||
case NO_ACTION:
|
case NO_ACTION:
|
||||||
case BOTH_GO:
|
case BOTH_GO:
|
||||||
|
case PEER_CLIENT:
|
||||||
/* already covered above */
|
/* already covered above */
|
||||||
return 0;
|
return 0;
|
||||||
case JOIN_GROUP:
|
case JOIN_GROUP:
|
||||||
|
|
Loading…
Reference in a new issue