P2P2: Refactor provision discovery request/response processing

Parse the P2P IEs in functions that handle provision discovery request
and response. Process the frames based on the IEs received in the PD
frames. This makes it easier to extend PD for P2P2 cases.

Signed-off-by: Shivani Baranwal <quic_shivbara@quicinc.com>
This commit is contained in:
Shivani Baranwal 2024-08-05 15:03:06 +05:30 committed by Jouni Malinen
parent b4f9742ee2
commit 6aa9ad8f8f
3 changed files with 193 additions and 185 deletions

View file

@ -1924,10 +1924,10 @@ static void p2p_rx_p2p_action(struct p2p_data *p2p, const u8 *sa,
p2p_process_invitation_resp(p2p, sa, data + 1, len - 1);
break;
case P2P_PROV_DISC_REQ:
p2p_process_prov_disc_req(p2p, sa, data + 1, len - 1, rx_freq);
p2p_handle_prov_disc_req(p2p, sa, data + 1, len - 1, rx_freq);
break;
case P2P_PROV_DISC_RESP:
p2p_process_prov_disc_resp(p2p, sa, data + 1, len - 1);
p2p_handle_prov_disc_resp(p2p, sa, data + 1, len - 1);
break;
case P2P_DEV_DISC_REQ:
p2p_process_dev_disc_req(p2p, sa, data + 1, len - 1, rx_freq);

View file

@ -873,10 +873,10 @@ void p2p_check_pref_chan(struct p2p_data *p2p, int go,
struct p2p_device *dev, struct p2p_message *msg);
/* p2p_pd.c */
void p2p_process_prov_disc_req(struct p2p_data *p2p, const u8 *sa,
const u8 *data, size_t len, int rx_freq);
void p2p_process_prov_disc_resp(struct p2p_data *p2p, const u8 *sa,
const u8 *data, size_t len);
void p2p_handle_prov_disc_req(struct p2p_data *p2p, const u8 *sa,
const u8 *data, size_t len, int rx_freq);
void p2p_handle_prov_disc_resp(struct p2p_data *p2p, const u8 *sa,
const u8 *data, size_t len);
int p2p_send_prov_disc_req(struct p2p_data *p2p, struct p2p_device *dev,
int join, int force_freq);
void p2p_reset_pending_pd(struct p2p_data *p2p);

View file

@ -614,10 +614,10 @@ void p2p_process_pcea(struct p2p_data *p2p, struct p2p_message *msg,
}
void p2p_process_prov_disc_req(struct p2p_data *p2p, const u8 *sa,
const u8 *data, size_t len, int rx_freq)
static void p2p_process_prov_disc_req(struct p2p_data *p2p,
struct p2p_message *msg, const u8 *sa,
const u8 *data, size_t len, int rx_freq)
{
struct p2p_message msg;
struct p2p_device *dev;
int freq;
enum p2p_status_code reject = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
@ -638,21 +638,17 @@ void p2p_process_prov_disc_req(struct p2p_data *p2p, const u8 *sa,
u8 remote_conncap;
u16 method;
if (p2p_parse(data, len, &msg))
return;
p2p_dbg(p2p, "Received Provision Discovery Request from " MACSTR
" with config methods 0x%x (freq=%d)",
MAC2STR(sa), msg.wps_config_methods, rx_freq);
group_mac = msg.intended_addr;
MAC2STR(sa), msg->wps_config_methods, rx_freq);
group_mac = msg->intended_addr;
dev = p2p_get_device(p2p, sa);
if (dev == NULL || (dev->flags & P2P_DEV_PROBE_REQ_ONLY)) {
p2p_dbg(p2p, "Provision Discovery Request from unknown peer "
MACSTR, MAC2STR(sa));
if (p2p_add_device(p2p, sa, rx_freq, NULL, 0, data + 1, len - 1,
0)) {
if (p2p_add_device(p2p, sa, rx_freq, NULL, 0, data, len, 0)) {
p2p_dbg(p2p, "Provision Discovery Request add device failed "
MACSTR, MAC2STR(sa));
goto out;
@ -665,29 +661,29 @@ void p2p_process_prov_disc_req(struct p2p_data *p2p, const u8 *sa,
MACSTR, MAC2STR(sa));
goto out;
}
} else if (msg.wfd_subelems) {
} else if (msg->wfd_subelems) {
wpabuf_free(dev->info.wfd_subelems);
dev->info.wfd_subelems = wpabuf_dup(msg.wfd_subelems);
dev->info.wfd_subelems = wpabuf_dup(msg->wfd_subelems);
}
p2p_update_peer_6ghz_capab(dev, &msg);
p2p_update_peer_6ghz_capab(dev, msg);
if (!msg.adv_id) {
if (!msg->adv_id) {
allowed_config_methods |= WPS_CONFIG_PUSHBUTTON;
if (!(msg.wps_config_methods & allowed_config_methods)) {
if (!(msg->wps_config_methods & allowed_config_methods)) {
p2p_dbg(p2p,
"Unsupported Config Methods in Provision Discovery Request");
goto out;
}
/* Legacy (non-P2PS) - Unknown groups allowed for P2PS */
if (msg.group_id) {
if (msg->group_id) {
size_t i;
for (i = 0; i < p2p->num_groups; i++) {
if (p2p_group_is_group_id_match(
p2p->groups[i],
msg.group_id, msg.group_id_len))
msg->group_id, msg->group_id_len))
break;
}
if (i == p2p->num_groups) {
@ -703,29 +699,29 @@ void p2p_process_prov_disc_req(struct p2p_data *p2p, const u8 *sa,
* Set adv_id here, so in case of an error, a P2PS PD Response
* will be sent.
*/
adv_id = WPA_GET_LE32(msg.adv_id);
if (p2ps_validate_pd_req(p2p, &msg, sa) < 0) {
adv_id = WPA_GET_LE32(msg->adv_id);
if (p2ps_validate_pd_req(p2p, msg, sa) < 0) {
reject = P2P_SC_FAIL_INVALID_PARAMS;
goto out;
}
req_fcap = (struct p2ps_feature_capab *) msg.feature_cap;
req_fcap = (struct p2ps_feature_capab *) msg->feature_cap;
os_memcpy(session_mac, msg.session_mac, ETH_ALEN);
os_memcpy(adv_mac, msg.adv_mac, ETH_ALEN);
os_memcpy(session_mac, msg->session_mac, ETH_ALEN);
os_memcpy(adv_mac, msg->adv_mac, ETH_ALEN);
session_id = WPA_GET_LE32(msg.session_id);
session_id = WPA_GET_LE32(msg->session_id);
if (msg.conn_cap)
conncap = *msg.conn_cap;
if (msg->conn_cap)
conncap = *msg->conn_cap;
/*
* We need to verify a P2PS config methog in an initial PD
* request or in a follow-on PD request with the status
* SUCCESS_DEFERRED.
*/
if ((!msg.status || *msg.status == P2P_SC_SUCCESS_DEFERRED) &&
!(msg.wps_config_methods & allowed_config_methods)) {
if ((!msg->status || *msg->status == P2P_SC_SUCCESS_DEFERRED) &&
!(msg->wps_config_methods & allowed_config_methods)) {
p2p_dbg(p2p,
"Unsupported Config Methods in Provision Discovery Request");
goto out;
@ -741,18 +737,18 @@ void p2p_process_prov_disc_req(struct p2p_data *p2p, const u8 *sa,
P2P_DEV_PD_PEER_KEYPAD |
P2P_DEV_PD_PEER_P2PS);
if (msg.wps_config_methods & WPS_CONFIG_DISPLAY) {
if (msg->wps_config_methods & WPS_CONFIG_DISPLAY) {
p2p_dbg(p2p, "Peer " MACSTR
" requested us to show a PIN on display", MAC2STR(sa));
dev->flags |= P2P_DEV_PD_PEER_KEYPAD;
passwd_id = DEV_PW_USER_SPECIFIED;
} else if (msg.wps_config_methods & WPS_CONFIG_KEYPAD) {
} else if (msg->wps_config_methods & WPS_CONFIG_KEYPAD) {
p2p_dbg(p2p, "Peer " MACSTR
" requested us to write its PIN using keypad",
MAC2STR(sa));
dev->flags |= P2P_DEV_PD_PEER_DISPLAY;
passwd_id = DEV_PW_REGISTRAR_SPECIFIED;
} else if (msg.wps_config_methods & WPS_CONFIG_P2PS) {
} else if (msg->wps_config_methods & WPS_CONFIG_P2PS) {
p2p_dbg(p2p, "Peer " MACSTR " requesting P2PS PIN",
MAC2STR(sa));
dev->flags |= P2P_DEV_PD_PEER_P2PS;
@ -763,8 +759,8 @@ void p2p_process_prov_disc_req(struct p2p_data *p2p, const u8 *sa,
if (p2p->cfg->remove_stale_groups) {
p2p->cfg->remove_stale_groups(
p2p->cfg->cb_ctx, dev->info.p2p_device_addr,
msg.persistent_dev,
msg.persistent_ssid, msg.persistent_ssid_len);
msg->persistent_dev,
msg->persistent_ssid, msg->persistent_ssid_len);
}
reject = P2P_SC_SUCCESS;
@ -773,15 +769,15 @@ void p2p_process_prov_disc_req(struct p2p_data *p2p, const u8 *sa,
* End of a legacy P2P PD Request processing, from this point continue
* with P2PS one.
*/
if (!msg.adv_id)
if (!msg->adv_id)
goto out;
remote_conncap = conncap;
if (!msg.status) {
if (!msg->status) {
unsigned int forced_freq, pref_freq;
if (!ether_addr_equal(p2p->cfg->dev_addr, msg.adv_mac)) {
if (!ether_addr_equal(p2p->cfg->dev_addr, msg->adv_mac)) {
p2p_dbg(p2p,
"P2PS PD adv mac does not match the local one");
reject = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
@ -818,12 +814,12 @@ void p2p_process_prov_disc_req(struct p2p_data *p2p, const u8 *sa,
"Incompatible P2PS feature capability CPT bitmask");
reject = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
} else if (p2ps_adv->config_methods &&
!(msg.wps_config_methods &
!(msg->wps_config_methods &
p2ps_adv->config_methods)) {
p2p_dbg(p2p,
"Unsupported config methods in Provision Discovery Request (own=0x%x peer=0x%x)",
p2ps_adv->config_methods,
msg.wps_config_methods);
msg->wps_config_methods);
reject = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
} else if (!p2ps_adv->state) {
p2p_dbg(p2p, "P2PS state unavailable");
@ -833,24 +829,24 @@ void p2p_process_prov_disc_req(struct p2p_data *p2p, const u8 *sa,
reject = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
}
if (msg.wps_config_methods & WPS_CONFIG_KEYPAD) {
if (msg->wps_config_methods & WPS_CONFIG_KEYPAD) {
p2p_dbg(p2p, "Keypad - always defer");
auto_accept = 0;
}
if ((remote_conncap & (P2PS_SETUP_NEW | P2PS_SETUP_CLIENT) ||
msg.persistent_dev) && conncap != P2PS_SETUP_NEW &&
msg.channel_list && msg.channel_list_len &&
msg->persistent_dev) && conncap != P2PS_SETUP_NEW &&
msg->channel_list && msg->channel_list_len &&
p2p_peer_channels_check(p2p, &p2p->channels, dev,
msg.channel_list,
msg.channel_list_len) < 0) {
msg->channel_list,
msg->channel_list_len) < 0) {
p2p_dbg(p2p,
"No common channels - force deferred flow");
auto_accept = 0;
}
if (((remote_conncap & P2PS_SETUP_GROUP_OWNER) ||
msg.persistent_dev) && msg.operating_channel) {
msg->persistent_dev) && msg->operating_channel) {
struct p2p_channels intersect;
/*
@ -861,15 +857,15 @@ void p2p_process_prov_disc_req(struct p2p_data *p2p, const u8 *sa,
*/
if (dev->channels.reg_classes == 0 ||
!p2p_channels_includes(&dev->channels,
msg.operating_channel[3],
msg.operating_channel[4])) {
msg->operating_channel[3],
msg->operating_channel[4])) {
struct p2p_channels *ch = &dev->channels;
os_memset(ch, 0, sizeof(*ch));
ch->reg_class[0].reg_class =
msg.operating_channel[3];
msg->operating_channel[3];
ch->reg_class[0].channel[0] =
msg.operating_channel[4];
msg->operating_channel[4];
ch->reg_class[0].channels = 1;
ch->reg_classes = 1;
}
@ -888,7 +884,7 @@ void p2p_process_prov_disc_req(struct p2p_data *p2p, const u8 *sa,
struct p2ps_provision *tmp;
if (p2ps_setup_p2ps_prov(p2p, adv_id, session_id,
msg.wps_config_methods,
msg->wps_config_methods,
session_mac, adv_mac) < 0) {
reject = P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE;
goto out;
@ -910,7 +906,7 @@ void p2p_process_prov_disc_req(struct p2p_data *p2p, const u8 *sa,
}
}
if (!msg.status && !auto_accept &&
if (!msg->status && !auto_accept &&
(!p2p->p2ps_prov || p2p->p2ps_prov->adv_id != adv_id)) {
struct p2ps_provision *tmp;
@ -920,7 +916,7 @@ void p2p_process_prov_disc_req(struct p2p_data *p2p, const u8 *sa,
}
if (p2ps_setup_p2ps_prov(p2p, adv_id, session_id,
msg.wps_config_methods,
msg->wps_config_methods,
session_mac, adv_mac) < 0) {
reject = P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE;
goto out;
@ -931,26 +927,26 @@ void p2p_process_prov_disc_req(struct p2p_data *p2p, const u8 *sa,
}
/* Not a P2PS Follow-on PD */
if (!msg.status)
if (!msg->status)
goto out;
if (*msg.status && *msg.status != P2P_SC_SUCCESS_DEFERRED) {
reject = *msg.status;
if (*msg->status && *msg->status != P2P_SC_SUCCESS_DEFERRED) {
reject = *msg->status;
goto out;
}
if (*msg.status != P2P_SC_SUCCESS_DEFERRED || !p2p->p2ps_prov)
if (*msg->status != P2P_SC_SUCCESS_DEFERRED || !p2p->p2ps_prov)
goto out;
if (p2p->p2ps_prov->adv_id != adv_id ||
!ether_addr_equal(p2p->p2ps_prov->adv_mac, msg.adv_mac)) {
!ether_addr_equal(p2p->p2ps_prov->adv_mac, msg->adv_mac)) {
p2p_dbg(p2p,
"P2PS Follow-on PD with mismatch Advertisement ID/MAC");
goto out;
}
if (p2p->p2ps_prov->session_id != session_id ||
!ether_addr_equal(p2p->p2ps_prov->session_mac, msg.session_mac)) {
!ether_addr_equal(p2p->p2ps_prov->session_mac, msg->session_mac)) {
p2p_dbg(p2p, "P2PS Follow-on PD with mismatch Session ID/MAC");
goto out;
}
@ -981,7 +977,7 @@ void p2p_process_prov_disc_req(struct p2p_data *p2p, const u8 *sa,
else if (method & WPS_CONFIG_KEYPAD)
method = WPS_CONFIG_DISPLAY;
if (!conncap || !(msg.wps_config_methods & method)) {
if (!conncap || !(msg->wps_config_methods & method)) {
/*
* Reject this "Deferred Accept*
* if incompatible conncap or method
@ -992,11 +988,11 @@ void p2p_process_prov_disc_req(struct p2p_data *p2p, const u8 *sa,
"Incompatible P2PS feature capability CPT bitmask");
reject = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
} else if ((remote_conncap & (P2PS_SETUP_NEW | P2PS_SETUP_CLIENT) ||
msg.persistent_dev) && conncap != P2PS_SETUP_NEW &&
msg.channel_list && msg.channel_list_len &&
msg->persistent_dev) && conncap != P2PS_SETUP_NEW &&
msg->channel_list && msg->channel_list_len &&
p2p_peer_channels_check(p2p, &p2p->channels, dev,
msg.channel_list,
msg.channel_list_len) < 0) {
msg->channel_list,
msg->channel_list_len) < 0) {
p2p_dbg(p2p,
"No common channels in Follow-On Provision Discovery Request");
reject = P2P_SC_FAIL_NO_COMMON_CHANNELS;
@ -1008,10 +1004,10 @@ void p2p_process_prov_disc_req(struct p2p_data *p2p, const u8 *sa,
if (reject == P2P_SC_SUCCESS || reject == P2P_SC_SUCCESS_DEFERRED) {
u8 tmp;
if (msg.operating_channel)
if (msg->operating_channel)
dev->oper_freq =
p2p_channel_to_freq(msg.operating_channel[3],
msg.operating_channel[4]);
p2p_channel_to_freq(msg->operating_channel[3],
msg->operating_channel[4]);
if ((conncap & P2PS_SETUP_GROUP_OWNER) &&
p2p_go_select_channel(p2p, dev, &tmp) < 0)
@ -1024,7 +1020,7 @@ void p2p_process_prov_disc_req(struct p2p_data *p2p, const u8 *sa,
out:
if (reject == P2P_SC_SUCCESS ||
reject == P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE)
config_methods = msg.wps_config_methods;
config_methods = msg->wps_config_methods;
else
config_methods = 0;
@ -1032,18 +1028,18 @@ out:
* Send PD Response for an initial PD Request or for follow-on
* PD Request with P2P_SC_SUCCESS_DEFERRED status.
*/
if (!msg.status || *msg.status == P2P_SC_SUCCESS_DEFERRED) {
resp = p2p_build_prov_disc_resp(p2p, dev, msg.dialog_token,
if (!msg->status || *msg->status == P2P_SC_SUCCESS_DEFERRED) {
resp = p2p_build_prov_disc_resp(p2p, dev, msg->dialog_token,
reject, config_methods, adv_id,
msg.group_id, msg.group_id_len,
msg.persistent_ssid,
msg.persistent_ssid_len,
msg->group_id,
msg->group_id_len,
msg->persistent_ssid,
msg->persistent_ssid_len,
(const u8 *) &resp_fcap,
sizeof(resp_fcap));
if (!resp) {
p2p_parse_free(&msg);
if (!resp)
return;
}
p2p_dbg(p2p, "Sending Provision Discovery Response");
if (rx_freq > 0)
freq = rx_freq;
@ -1053,7 +1049,6 @@ out:
if (freq < 0) {
p2p_dbg(p2p, "Unknown regulatory class/channel");
wpabuf_free(resp);
p2p_parse_free(&msg);
return;
}
p2p->pending_action_state = P2P_PENDING_PD_RESPONSE;
@ -1068,10 +1063,8 @@ out:
wpabuf_free(resp);
}
if (!dev) {
p2p_parse_free(&msg);
if (!dev)
return;
}
freq = 0;
if (reject == P2P_SC_SUCCESS && conncap == P2PS_SETUP_GROUP_OWNER) {
@ -1083,17 +1076,17 @@ out:
if (!p2p->cfg->p2ps_prov_complete) {
/* Don't emit anything */
} else if (msg.status && *msg.status != P2P_SC_SUCCESS &&
*msg.status != P2P_SC_SUCCESS_DEFERRED) {
reject = *msg.status;
} else if (msg->status && *msg->status != P2P_SC_SUCCESS &&
*msg->status != P2P_SC_SUCCESS_DEFERRED) {
reject = *msg->status;
p2p->cfg->p2ps_prov_complete(p2p->cfg->cb_ctx, reject,
sa, adv_mac, session_mac,
NULL, adv_id, session_id,
0, 0, msg.persistent_ssid,
msg.persistent_ssid_len,
0, 0, msg->persistent_ssid,
msg->persistent_ssid_len,
0, 0, NULL, NULL, 0, freq,
NULL, 0);
} else if (msg.status && *msg.status == P2P_SC_SUCCESS_DEFERRED &&
} else if (msg->status && *msg->status == P2P_SC_SUCCESS_DEFERRED &&
p2p->p2ps_prov) {
p2p->p2ps_prov->status = reject;
p2p->p2ps_prov->conncap = conncap;
@ -1103,77 +1096,77 @@ out:
sa, adv_mac, session_mac,
NULL, adv_id,
session_id, conncap, 0,
msg.persistent_ssid,
msg.persistent_ssid_len, 0,
0, NULL, NULL, 0, freq,
msg->persistent_ssid,
msg->persistent_ssid_len,
0, 0, NULL, NULL, 0, freq,
NULL, 0);
else
p2p->cfg->p2ps_prov_complete(p2p->cfg->cb_ctx,
*msg.status,
*msg->status,
sa, adv_mac, session_mac,
group_mac, adv_id,
session_id, conncap,
passwd_id,
msg.persistent_ssid,
msg.persistent_ssid_len, 0,
0, NULL,
msg->persistent_ssid,
msg->persistent_ssid_len,
0, 0, NULL,
(const u8 *) &resp_fcap,
sizeof(resp_fcap), freq,
NULL, 0);
} else if (msg.status && p2p->p2ps_prov) {
} else if (msg->status && p2p->p2ps_prov) {
p2p->p2ps_prov->status = P2P_SC_SUCCESS;
p2p->cfg->p2ps_prov_complete(p2p->cfg->cb_ctx, *msg.status, sa,
p2p->cfg->p2ps_prov_complete(p2p->cfg->cb_ctx, *msg->status, sa,
adv_mac, session_mac, group_mac,
adv_id, session_id, conncap,
passwd_id,
msg.persistent_ssid,
msg.persistent_ssid_len,
msg->persistent_ssid,
msg->persistent_ssid_len,
0, 0, NULL,
(const u8 *) &resp_fcap,
sizeof(resp_fcap), freq, NULL, 0);
} else if (msg.status) {
} else if (msg->status) {
} else if (auto_accept && reject == P2P_SC_SUCCESS) {
p2p->cfg->p2ps_prov_complete(p2p->cfg->cb_ctx, P2P_SC_SUCCESS,
sa, adv_mac, session_mac,
group_mac, adv_id, session_id,
conncap, passwd_id,
msg.persistent_ssid,
msg.persistent_ssid_len,
msg->persistent_ssid,
msg->persistent_ssid_len,
0, 0, NULL,
(const u8 *) &resp_fcap,
sizeof(resp_fcap), freq,
msg.group_id ?
msg.group_id + ETH_ALEN : NULL,
msg.group_id ?
msg.group_id_len - ETH_ALEN : 0);
msg->group_id ?
msg->group_id + ETH_ALEN : NULL,
msg->group_id ?
msg->group_id_len - ETH_ALEN : 0);
} else if (reject == P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE &&
(!msg.session_info || !msg.session_info_len)) {
p2p->p2ps_prov->method = msg.wps_config_methods;
(!msg->session_info || !msg->session_info_len)) {
p2p->p2ps_prov->method = msg->wps_config_methods;
p2p->cfg->p2ps_prov_complete(p2p->cfg->cb_ctx, P2P_SC_SUCCESS,
sa, adv_mac, session_mac,
group_mac, adv_id, session_id,
conncap, passwd_id,
msg.persistent_ssid,
msg.persistent_ssid_len,
msg->persistent_ssid,
msg->persistent_ssid_len,
0, 1, NULL,
(const u8 *) &resp_fcap,
sizeof(resp_fcap), freq, NULL, 0);
} else if (reject == P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE) {
size_t buf_len = msg.session_info_len;
size_t buf_len = msg->session_info_len;
char *buf = os_malloc(2 * buf_len + 1);
if (buf) {
p2p->p2ps_prov->method = msg.wps_config_methods;
p2p->p2ps_prov->method = msg->wps_config_methods;
utf8_escape((char *) msg.session_info, buf_len,
utf8_escape((char *) msg->session_info, buf_len,
buf, 2 * buf_len + 1);
p2p->cfg->p2ps_prov_complete(
p2p->cfg->cb_ctx, P2P_SC_SUCCESS, sa,
adv_mac, session_mac, group_mac, adv_id,
session_id, conncap, passwd_id,
msg.persistent_ssid, msg.persistent_ssid_len,
msg->persistent_ssid, msg->persistent_ssid_len,
0, 1, buf,
(const u8 *) &resp_fcap, sizeof(resp_fcap),
freq, NULL, 0);
@ -1201,29 +1194,30 @@ out:
* seeker: KEYPAD, response status: SUCCESS
*/
if (p2p->cfg->prov_disc_req &&
((reject == P2P_SC_SUCCESS && !msg.adv_id) ||
(!msg.status &&
((reject == P2P_SC_SUCCESS && !msg->adv_id) ||
(!msg->status &&
(reject == P2P_SC_SUCCESS ||
reject == P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE) &&
passwd_id == DEV_PW_USER_SPECIFIED) ||
(!msg.status &&
(!msg->status &&
reject == P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE &&
passwd_id == DEV_PW_REGISTRAR_SPECIFIED) ||
(reject == P2P_SC_SUCCESS &&
msg.status && *msg.status == P2P_SC_SUCCESS_DEFERRED &&
msg->status && *msg->status == P2P_SC_SUCCESS_DEFERRED &&
passwd_id == DEV_PW_REGISTRAR_SPECIFIED))) {
const u8 *dev_addr = sa;
if (msg.p2p_device_addr)
dev_addr = msg.p2p_device_addr;
if (msg->p2p_device_addr)
dev_addr = msg->p2p_device_addr;
p2p->cfg->prov_disc_req(p2p->cfg->cb_ctx, sa,
msg.wps_config_methods,
dev_addr, msg.pri_dev_type,
msg.device_name, msg.config_methods,
msg.capability ? msg.capability[0] : 0,
msg.capability ? msg.capability[1] :
msg->wps_config_methods,
dev_addr, msg->pri_dev_type,
msg->device_name, msg->config_methods,
msg->capability ? msg->capability[0] :
0,
msg.group_id, msg.group_id_len);
msg->capability ? msg->capability[1] :
0,
msg->group_id, msg->group_id_len);
}
if (reject != P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE)
@ -1248,10 +1242,22 @@ out:
break;
}
if (msg.intended_addr)
os_memcpy(dev->interface_addr, msg.intended_addr,
if (msg->intended_addr)
os_memcpy(dev->interface_addr, msg->intended_addr,
ETH_ALEN);
}
}
void p2p_handle_prov_disc_req(struct p2p_data *p2p, const u8 *sa,
const u8 *data, size_t len, int rx_freq)
{
struct p2p_message msg;
if (p2p_parse(data, len, &msg))
return;
p2p_process_prov_disc_req(p2p, &msg, sa, data + 1, len - 1, rx_freq);
p2p_parse_free(&msg);
}
@ -1354,10 +1360,10 @@ static int p2p_validate_p2ps_pd_resp(struct p2p_data *p2p,
}
void p2p_process_prov_disc_resp(struct p2p_data *p2p, const u8 *sa,
const u8 *data, size_t len)
static void p2p_process_prov_disc_resp(struct p2p_data *p2p,
struct p2p_message *msg, const u8 *sa,
const u8 *data, size_t len)
{
struct p2p_message msg;
struct p2p_device *dev;
u16 report_config_methods = 0, req_config_methods;
u8 status = P2P_SC_SUCCESS;
@ -1368,30 +1374,25 @@ void p2p_process_prov_disc_resp(struct p2p_data *p2p, const u8 *sa,
int passwd_id = DEV_PW_DEFAULT;
int p2ps_seeker;
if (p2p_parse(data, len, &msg))
if (p2p->p2ps_prov && p2p_validate_p2ps_pd_resp(p2p, msg))
return;
if (p2p->p2ps_prov && p2p_validate_p2ps_pd_resp(p2p, &msg)) {
p2p_parse_free(&msg);
return;
}
/* Parse the P2PS members present */
if (msg.status)
status = *msg.status;
if (msg->status)
status = *msg->status;
group_mac = msg.intended_addr;
group_mac = msg->intended_addr;
if (msg.adv_mac)
os_memcpy(adv_mac, msg.adv_mac, 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->adv_id)
adv_id = WPA_GET_LE32(msg->adv_id);
if (msg.conn_cap) {
conncap = *msg.conn_cap;
if (msg->conn_cap) {
conncap = *msg->conn_cap;
/* Switch bits to local relative */
switch (conncap) {
@ -1406,25 +1407,23 @@ void p2p_process_prov_disc_resp(struct p2p_data *p2p, const u8 *sa,
p2p_dbg(p2p, "Received Provision Discovery Response from " MACSTR
" with config methods 0x%x",
MAC2STR(sa), msg.wps_config_methods);
MAC2STR(sa), msg->wps_config_methods);
dev = p2p_get_device(p2p, sa);
if (dev == NULL || !dev->req_config_methods) {
p2p_dbg(p2p, "Ignore Provision Discovery Response from " MACSTR
" with no pending request", MAC2STR(sa));
p2p_parse_free(&msg);
return;
} else if (msg.wfd_subelems) {
} else if (msg->wfd_subelems) {
wpabuf_free(dev->info.wfd_subelems);
dev->info.wfd_subelems = wpabuf_dup(msg.wfd_subelems);
dev->info.wfd_subelems = wpabuf_dup(msg->wfd_subelems);
}
p2p_update_peer_6ghz_capab(dev, &msg);
p2p_update_peer_6ghz_capab(dev, msg);
if (dev->dialog_token != msg.dialog_token) {
if (dev->dialog_token != msg->dialog_token) {
p2p_dbg(p2p, "Ignore Provision Discovery Response with unexpected Dialog Token %u (expected %u)",
msg.dialog_token, dev->dialog_token);
p2p_parse_free(&msg);
msg->dialog_token, dev->dialog_token);
return;
}
@ -1449,14 +1448,13 @@ void p2p_process_prov_disc_resp(struct p2p_data *p2p, const u8 *sa,
ether_addr_equal(p2p->pending_pd_devaddr, sa))
p2p_reset_pending_pd(p2p);
if (msg.wps_config_methods != req_config_methods) {
if (msg->wps_config_methods != req_config_methods) {
p2p_dbg(p2p, "Peer rejected our Provision Discovery Request (received config_methods 0x%x expected 0x%x",
msg.wps_config_methods, req_config_methods);
msg->wps_config_methods, req_config_methods);
if (p2p->cfg->prov_disc_fail)
p2p->cfg->prov_disc_fail(p2p->cfg->cb_ctx, sa,
P2P_PROV_DISC_REJECTED,
adv_id, adv_mac, NULL);
p2p_parse_free(&msg);
p2ps_prov_free(p2p);
goto out;
}
@ -1470,13 +1468,13 @@ void p2p_process_prov_disc_resp(struct p2p_data *p2p, const u8 *sa,
" accepted to show a PIN on display", MAC2STR(sa));
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
" accepted to write our PIN using keypad",
MAC2STR(sa));
dev->flags |= P2P_DEV_PD_PEER_KEYPAD;
passwd_id = DEV_PW_USER_SPECIFIED;
} else if (msg.wps_config_methods & WPS_CONFIG_P2PS) {
} 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;
@ -1495,23 +1493,23 @@ void p2p_process_prov_disc_resp(struct p2p_data *p2p, const u8 *sa,
* fails the flow would continue, although it would probably
* fail. Same is true for the operating channel.
*/
if (msg.channel_list && msg.channel_list_len &&
if (msg->channel_list && msg->channel_list_len &&
p2p_peer_channels_check(p2p, &p2p->channels, dev,
msg.channel_list,
msg.channel_list_len) < 0)
msg->channel_list,
msg->channel_list_len) < 0)
p2p_dbg(p2p, "P2PS PD Response - no common channels");
if (msg.operating_channel) {
if (msg->operating_channel) {
if (p2p_channels_includes(&p2p->channels,
msg.operating_channel[3],
msg.operating_channel[4]) &&
msg->operating_channel[3],
msg->operating_channel[4]) &&
p2p_channels_includes(&dev->channels,
msg.operating_channel[3],
msg.operating_channel[4])) {
msg->operating_channel[3],
msg->operating_channel[4])) {
dev->oper_freq =
p2p_channel_to_freq(
msg.operating_channel[3],
msg.operating_channel[4]);
msg->operating_channel[3],
msg->operating_channel[4]);
} else {
p2p_dbg(p2p,
"P2PS PD Response - invalid operating channel");
@ -1543,11 +1541,12 @@ void p2p_process_prov_disc_resp(struct p2p_data *p2p, const u8 *sa,
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,
msg.feature_cap, msg.feature_cap_len, freq,
msg.group_id ? msg.group_id + ETH_ALEN : NULL,
msg.group_id ? msg.group_id_len - ETH_ALEN : 0);
conncap, passwd_id, msg->persistent_ssid,
msg->persistent_ssid_len, 1, 0, NULL,
msg->feature_cap, msg->feature_cap_len, freq,
msg->group_id ? msg->group_id + ETH_ALEN : NULL,
msg->group_id ? msg->group_id_len - ETH_ALEN :
0);
}
p2ps_prov_free(p2p);
} else if (status != P2P_SC_SUCCESS &&
@ -1569,16 +1568,15 @@ void p2p_process_prov_disc_resp(struct p2p_data *p2p, const u8 *sa,
NULL, NULL, 0);
}
if (msg.session_info && msg.session_info_len) {
size_t info_len = msg.session_info_len;
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);
p2ps_prov_free(p2p);
goto out;
}
utf8_escape((char *) msg.session_info, info_len,
utf8_escape((char *) msg->session_info, info_len,
deferred_sess_resp, 2 * info_len + 1);
if (p2p->cfg->prov_disc_fail)
@ -1600,17 +1598,14 @@ void p2p_process_prov_disc_resp(struct p2p_data *p2p, const u8 *sa,
p2p->cfg->prov_disc_fail(p2p->cfg->cb_ctx, sa,
P2P_PROV_DISC_REJECTED,
adv_id, adv_mac, NULL);
p2p_parse_free(&msg);
p2ps_prov_free(p2p);
goto out;
}
/* Store the provisioning info */
dev->wps_prov_info = msg.wps_config_methods;
if (msg.intended_addr)
os_memcpy(dev->interface_addr, msg.intended_addr, ETH_ALEN);
p2p_parse_free(&msg);
dev->wps_prov_info = msg->wps_config_methods;
if (msg->intended_addr)
os_memcpy(dev->interface_addr, msg->intended_addr, ETH_ALEN);
out:
dev->req_config_methods = 0;
@ -1654,6 +1649,19 @@ out:
}
void p2p_handle_prov_disc_resp(struct p2p_data *p2p, const u8 *sa,
const u8 *data, size_t len)
{
struct p2p_message msg;
if (p2p_parse(data, len, &msg))
return;
p2p_process_prov_disc_resp(p2p, &msg, sa, data + 1, len - 1);
p2p_parse_free(&msg);
}
int p2p_send_prov_disc_req(struct p2p_data *p2p, struct p2p_device *dev,
int join, int force_freq)
{