P2PS: PD Response processing

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
Krishna Vamsi 2014-12-10 17:23:00 +05:30 committed by Jouni Malinen
parent ab8ee776b9
commit 9e96e46456
2 changed files with 125 additions and 2 deletions

View file

@ -348,6 +348,7 @@ enum p2p_prov_disc_status {
P2P_PROV_DISC_TIMEOUT, P2P_PROV_DISC_TIMEOUT,
P2P_PROV_DISC_REJECTED, P2P_PROV_DISC_REJECTED,
P2P_PROV_DISC_TIMEOUT_JOIN, P2P_PROV_DISC_TIMEOUT_JOIN,
P2P_PROV_DISC_INFO_UNAVAILABLE,
}; };
struct p2p_channel { struct p2p_channel {

View file

@ -793,11 +793,48 @@ void p2p_process_prov_disc_resp(struct p2p_data *p2p, const u8 *sa,
struct p2p_message msg; struct p2p_message msg;
struct p2p_device *dev; struct p2p_device *dev;
u16 report_config_methods = 0, req_config_methods; u16 report_config_methods = 0, req_config_methods;
u8 status = P2P_SC_SUCCESS;
int success = 0; int success = 0;
u32 adv_id = 0;
u8 conncap = P2PS_SETUP_NEW;
u8 adv_mac[ETH_ALEN];
u8 group_mac[ETH_ALEN];
int passwd_id = DEV_PW_DEFAULT;
if (p2p_parse(data, len, &msg)) if (p2p_parse(data, len, &msg))
return; return;
/* Parse the P2PS members present */
if (msg.status)
status = *msg.status;
if (msg.intended_addr)
os_memcpy(group_mac, msg.intended_addr, ETH_ALEN);
else
os_memset(group_mac, 0, ETH_ALEN);
if (msg.adv_mac)
os_memcpy(adv_mac, msg.adv_mac, ETH_ALEN);
else
os_memset(adv_mac, 0, ETH_ALEN);
if (msg.adv_id)
adv_id = WPA_GET_LE32(msg.adv_id);
if (msg.conn_cap) {
conncap = *msg.conn_cap;
/* Switch bits to local relative */
switch (conncap) {
case P2PS_SETUP_GROUP_OWNER:
conncap = P2PS_SETUP_CLIENT;
break;
case P2PS_SETUP_CLIENT:
conncap = P2PS_SETUP_GROUP_OWNER;
break;
}
}
p2p_dbg(p2p, "Received Provision Discovery Response from " MACSTR p2p_dbg(p2p, "Received Provision Discovery Response from " MACSTR
" with config methods 0x%x", " with config methods 0x%x",
MAC2STR(sa), msg.wps_config_methods); MAC2STR(sa), msg.wps_config_methods);
@ -842,23 +879,108 @@ void p2p_process_prov_disc_resp(struct p2p_data *p2p, const u8 *sa,
if (p2p->cfg->prov_disc_fail) if (p2p->cfg->prov_disc_fail)
p2p->cfg->prov_disc_fail(p2p->cfg->cb_ctx, sa, p2p->cfg->prov_disc_fail(p2p->cfg->cb_ctx, sa,
P2P_PROV_DISC_REJECTED, P2P_PROV_DISC_REJECTED,
0, NULL, NULL); adv_id, adv_mac, NULL);
p2p_parse_free(&msg); p2p_parse_free(&msg);
os_free(p2p->p2ps_prov);
p2p->p2ps_prov = NULL;
goto out; goto out;
} }
report_config_methods = req_config_methods; report_config_methods = req_config_methods;
dev->flags &= ~(P2P_DEV_PD_PEER_DISPLAY | dev->flags &= ~(P2P_DEV_PD_PEER_DISPLAY |
P2P_DEV_PD_PEER_KEYPAD); P2P_DEV_PD_PEER_KEYPAD |
P2P_DEV_PD_PEER_P2PS);
if (req_config_methods & WPS_CONFIG_DISPLAY) { if (req_config_methods & WPS_CONFIG_DISPLAY) {
p2p_dbg(p2p, "Peer " MACSTR p2p_dbg(p2p, "Peer " MACSTR
" accepted to show a PIN on display", MAC2STR(sa)); " accepted to show a PIN on display", MAC2STR(sa));
dev->flags |= P2P_DEV_PD_PEER_DISPLAY; dev->flags |= P2P_DEV_PD_PEER_DISPLAY;
passwd_id = DEV_PW_REGISTRAR_SPECIFIED;
} else if (msg.wps_config_methods & WPS_CONFIG_KEYPAD) { } else if (msg.wps_config_methods & WPS_CONFIG_KEYPAD) {
p2p_dbg(p2p, "Peer " MACSTR p2p_dbg(p2p, "Peer " MACSTR
" accepted to write our PIN using keypad", " accepted to write our PIN using keypad",
MAC2STR(sa)); MAC2STR(sa));
dev->flags |= P2P_DEV_PD_PEER_KEYPAD; dev->flags |= P2P_DEV_PD_PEER_KEYPAD;
passwd_id = DEV_PW_USER_SPECIFIED;
} else if (msg.wps_config_methods & WPS_CONFIG_P2PS) {
p2p_dbg(p2p, "Peer " MACSTR " accepted P2PS PIN",
MAC2STR(sa));
dev->flags |= P2P_DEV_PD_PEER_P2PS;
passwd_id = DEV_PW_P2PS_DEFAULT;
}
if ((msg.conn_cap || msg.persistent_dev) &&
msg.adv_id &&
(status == P2P_SC_SUCCESS || status == P2P_SC_SUCCESS_DEFERRED) &&
p2p->p2ps_prov) {
if (p2p->cfg->p2ps_prov_complete) {
p2p->cfg->p2ps_prov_complete(
p2p->cfg->cb_ctx, status, sa, adv_mac,
p2p->p2ps_prov->session_mac,
group_mac, adv_id, p2p->p2ps_prov->session_id,
conncap, passwd_id, msg.persistent_ssid,
msg.persistent_ssid_len, 1, 0, NULL);
}
os_free(p2p->p2ps_prov);
p2p->p2ps_prov = NULL;
}
if (status != P2P_SC_SUCCESS &&
status != P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE &&
status != P2P_SC_SUCCESS_DEFERRED && p2p->p2ps_prov) {
if (p2p->cfg->p2ps_prov_complete)
p2p->cfg->p2ps_prov_complete(
p2p->cfg->cb_ctx, status, sa, adv_mac,
p2p->p2ps_prov->session_mac,
group_mac, adv_id, p2p->p2ps_prov->session_id,
0, 0, NULL, 0, 1, 0, NULL);
os_free(p2p->p2ps_prov);
p2p->p2ps_prov = NULL;
}
if (status == P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE) {
if (p2p->cfg->remove_stale_groups) {
p2p->cfg->remove_stale_groups(p2p->cfg->cb_ctx,
dev->info.p2p_device_addr,
NULL, NULL, 0);
}
if (msg.session_info && msg.session_info_len) {
size_t info_len = msg.session_info_len;
char *deferred_sess_resp = os_malloc(2 * info_len + 1);
if (!deferred_sess_resp) {
p2p_parse_free(&msg);
os_free(p2p->p2ps_prov);
p2p->p2ps_prov = NULL;
goto out;
}
utf8_escape((char *) msg.session_info, info_len,
deferred_sess_resp, 2 * info_len + 1);
if (p2p->cfg->prov_disc_fail)
p2p->cfg->prov_disc_fail(
p2p->cfg->cb_ctx, sa,
P2P_PROV_DISC_INFO_UNAVAILABLE,
adv_id, adv_mac,
deferred_sess_resp);
os_free(deferred_sess_resp);
} else
if (p2p->cfg->prov_disc_fail)
p2p->cfg->prov_disc_fail(
p2p->cfg->cb_ctx, sa,
P2P_PROV_DISC_INFO_UNAVAILABLE,
adv_id, adv_mac, NULL);
} else if (msg.wps_config_methods != dev->req_config_methods ||
status != P2P_SC_SUCCESS) {
p2p_dbg(p2p, "Peer rejected our Provision Discovery Request");
if (p2p->cfg->prov_disc_fail)
p2p->cfg->prov_disc_fail(p2p->cfg->cb_ctx, sa,
P2P_PROV_DISC_REJECTED, 0,
NULL, NULL);
p2p_parse_free(&msg);
os_free(p2p->p2ps_prov);
p2p->p2ps_prov = NULL;
goto out;
} }
/* Store the provisioning info */ /* Store the provisioning info */