diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c index 676a45ce0..c9a462632 100644 --- a/src/p2p/p2p.c +++ b/src/p2p/p2p.c @@ -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); diff --git a/src/p2p/p2p_i.h b/src/p2p/p2p_i.h index c22630d51..344bece21 100644 --- a/src/p2p/p2p_i.h +++ b/src/p2p/p2p_i.h @@ -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); diff --git a/src/p2p/p2p_pd.c b/src/p2p/p2p_pd.c index 6c9ac194a..c34f69f7f 100644 --- a/src/p2p/p2p_pd.c +++ b/src/p2p/p2p_pd.c @@ -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) {