LCOV - code coverage report
Current view: top level - src/p2p - p2p_pd.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1443382998 Lines: 614 755 81.3 %
Date: 2015-09-27 Functions: 14 14 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Wi-Fi Direct - P2P provision discovery
       3             :  * Copyright (c) 2009-2010, Atheros Communications
       4             :  *
       5             :  * This software may be distributed under the terms of the BSD license.
       6             :  * See README for more details.
       7             :  */
       8             : 
       9             : #include "includes.h"
      10             : 
      11             : #include "common.h"
      12             : #include "common/ieee802_11_defs.h"
      13             : #include "common/wpa_ctrl.h"
      14             : #include "wps/wps_defs.h"
      15             : #include "p2p_i.h"
      16             : #include "p2p.h"
      17             : 
      18             : 
      19             : /*
      20             :  * Number of retries to attempt for provision discovery requests
      21             :  * in case the peer is not listening.
      22             :  */
      23             : #define MAX_PROV_DISC_REQ_RETRIES 120
      24             : 
      25             : 
      26         337 : static void p2p_build_wps_ie_config_methods(struct wpabuf *buf,
      27             :                                             u16 config_methods)
      28             : {
      29             :         u8 *len;
      30         337 :         wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
      31         337 :         len = wpabuf_put(buf, 1);
      32         337 :         wpabuf_put_be32(buf, WPS_DEV_OUI_WFA);
      33             : 
      34             :         /* Config Methods */
      35         337 :         wpabuf_put_be16(buf, ATTR_CONFIG_METHODS);
      36         337 :         wpabuf_put_be16(buf, 2);
      37         337 :         wpabuf_put_be16(buf, config_methods);
      38             : 
      39         337 :         p2p_buf_update_ie_hdr(buf, len);
      40         337 : }
      41             : 
      42             : 
      43          42 : static void p2ps_add_new_group_info(struct p2p_data *p2p, struct wpabuf *buf)
      44             : {
      45             :         int found;
      46             :         u8 intended_addr[ETH_ALEN];
      47             :         u8 ssid[SSID_MAX_LEN];
      48             :         size_t ssid_len;
      49             :         int group_iface;
      50             : 
      51          42 :         if (!p2p->cfg->get_go_info)
      52          42 :                 return;
      53             : 
      54          84 :         found = p2p->cfg->get_go_info(
      55          42 :                 p2p->cfg->cb_ctx, intended_addr, ssid,
      56             :                 &ssid_len, &group_iface);
      57          42 :         if (found) {
      58           0 :                 p2p_buf_add_group_id(buf, p2p->cfg->dev_addr,
      59             :                                      ssid, ssid_len);
      60             : 
      61           0 :                 if (group_iface)
      62           0 :                         p2p_buf_add_intended_addr(buf, p2p->intended_addr);
      63             :                 else
      64           0 :                         p2p_buf_add_intended_addr(buf, intended_addr);
      65             :         } else {
      66          42 :                 if (!p2p->ssid_set) {
      67          36 :                         p2p_build_ssid(p2p, p2p->ssid, &p2p->ssid_len);
      68          36 :                         p2p->ssid_set = 1;
      69             :                 }
      70             : 
      71             :                 /* Add pre-composed P2P Group ID */
      72          84 :                 p2p_buf_add_group_id(buf, p2p->cfg->dev_addr,
      73          42 :                                      p2p->ssid, p2p->ssid_len);
      74             : 
      75          42 :                 if (group_iface)
      76           4 :                         p2p_buf_add_intended_addr(
      77           4 :                                 buf, p2p->intended_addr);
      78             :                 else
      79          38 :                         p2p_buf_add_intended_addr(
      80          38 :                                 buf, p2p->cfg->dev_addr);
      81             :         }
      82             : }
      83             : 
      84             : 
      85          37 : static void p2ps_add_pd_req_attrs(struct p2p_data *p2p, struct p2p_device *dev,
      86             :                                   struct wpabuf *buf, u16 config_methods)
      87             : {
      88          37 :         struct p2ps_provision *prov = p2p->p2ps_prov;
      89          37 :         struct p2ps_feature_capab fcap = { prov->cpt_mask, 0 };
      90          37 :         int shared_group = 0;
      91             :         u8 ssid[SSID_MAX_LEN];
      92             :         size_t ssid_len;
      93             :         u8 go_dev_addr[ETH_ALEN];
      94             :         u8 intended_addr[ETH_ALEN];
      95             : 
      96             :         /* If we might be explicite group owner, add GO details */
      97          37 :         if (prov->conncap & (P2PS_SETUP_GROUP_OWNER |
      98             :                              P2PS_SETUP_NEW))
      99          37 :                 p2ps_add_new_group_info(p2p, buf);
     100             : 
     101          37 :         if (prov->status >= 0)
     102          13 :                 p2p_buf_add_status(buf, (u8) prov->status);
     103             :         else
     104          24 :                 prov->method = config_methods;
     105             : 
     106          37 :         if (p2p->cfg->get_persistent_group) {
     107          74 :                 shared_group = p2p->cfg->get_persistent_group(
     108          37 :                         p2p->cfg->cb_ctx, dev->info.p2p_device_addr, NULL, 0,
     109             :                         go_dev_addr, ssid, &ssid_len, intended_addr);
     110             :         }
     111             : 
     112             :         /* Add Operating Channel if conncap includes GO */
     113          73 :         if (shared_group ||
     114          36 :             (prov->conncap & (P2PS_SETUP_GROUP_OWNER |
     115             :                               P2PS_SETUP_NEW))) {
     116             :                 u8 tmp;
     117             : 
     118          37 :                 p2p_go_select_channel(p2p, dev, &tmp);
     119             : 
     120          37 :                 if (p2p->op_reg_class && p2p->op_channel)
     121          74 :                         p2p_buf_add_operating_channel(buf, p2p->cfg->country,
     122          37 :                                                       p2p->op_reg_class,
     123          37 :                                                       p2p->op_channel);
     124             :                 else
     125           0 :                         p2p_buf_add_operating_channel(buf, p2p->cfg->country,
     126           0 :                                                       p2p->cfg->op_reg_class,
     127           0 :                                                       p2p->cfg->op_channel);
     128             :         }
     129             : 
     130          37 :         p2p_buf_add_channel_list(buf, p2p->cfg->country, &p2p->cfg->channels);
     131             : 
     132          37 :         if (prov->info[0])
     133           0 :                 p2p_buf_add_session_info(buf, prov->info);
     134             : 
     135          37 :         p2p_buf_add_connection_capability(buf, prov->conncap);
     136             : 
     137          37 :         p2p_buf_add_advertisement_id(buf, prov->adv_id, prov->adv_mac);
     138             : 
     139          37 :         if (shared_group || prov->conncap == P2PS_SETUP_NEW ||
     140           0 :             prov->conncap ==
     141           0 :             (P2PS_SETUP_GROUP_OWNER | P2PS_SETUP_NEW) ||
     142           0 :             prov->conncap ==
     143             :             (P2PS_SETUP_GROUP_OWNER | P2PS_SETUP_CLIENT)) {
     144             :                 /* Add Config Timeout */
     145          37 :                 p2p_buf_add_config_timeout(buf, p2p->go_timeout,
     146          37 :                                            p2p->client_timeout);
     147             :         }
     148             : 
     149          37 :         p2p_buf_add_listen_channel(buf, p2p->cfg->country, p2p->cfg->reg_class,
     150          37 :                                    p2p->cfg->channel);
     151             : 
     152          37 :         p2p_buf_add_session_id(buf, prov->session_id, prov->session_mac);
     153             : 
     154          37 :         p2p_buf_add_feature_capability(buf, sizeof(fcap), (const u8 *) &fcap);
     155             : 
     156          37 :         if (shared_group) {
     157           1 :                 p2p_buf_add_persistent_group_info(buf, go_dev_addr,
     158             :                                                   ssid, ssid_len);
     159             :                 /* Add intended interface address if it is not added yet */
     160           2 :                 if ((prov->conncap == P2PS_SETUP_NONE ||
     161           1 :                      prov->conncap == P2PS_SETUP_CLIENT) &&
     162           0 :                     !is_zero_ether_addr(intended_addr))
     163           0 :                         p2p_buf_add_intended_addr(buf, intended_addr);
     164             :         }
     165          37 : }
     166             : 
     167             : 
     168         229 : static struct wpabuf * p2p_build_prov_disc_req(struct p2p_data *p2p,
     169             :                                                struct p2p_device *dev,
     170             :                                                int join)
     171             : {
     172             :         struct wpabuf *buf;
     173             :         u8 *len;
     174         229 :         size_t extra = 0;
     175         229 :         u8 dialog_token = dev->dialog_token;
     176         229 :         u16 config_methods = dev->req_config_methods;
     177         229 :         struct p2p_device *go = join ? dev : NULL;
     178             :         u8 group_capab;
     179             : 
     180             : #ifdef CONFIG_WIFI_DISPLAY
     181         229 :         if (p2p->wfd_ie_prov_disc_req)
     182           3 :                 extra = wpabuf_len(p2p->wfd_ie_prov_disc_req);
     183             : #endif /* CONFIG_WIFI_DISPLAY */
     184             : 
     185         229 :         if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_PD_REQ])
     186           1 :                 extra += wpabuf_len(p2p->vendor_elem[VENDOR_ELEM_P2P_PD_REQ]);
     187             : 
     188         229 :         if (p2p->p2ps_prov)
     189          37 :                 extra += os_strlen(p2p->p2ps_prov->info) + 1 +
     190             :                         sizeof(struct p2ps_provision);
     191             : 
     192         229 :         buf = wpabuf_alloc(1000 + extra);
     193         229 :         if (buf == NULL)
     194           0 :                 return NULL;
     195             : 
     196         229 :         p2p_buf_add_public_action_hdr(buf, P2P_PROV_DISC_REQ, dialog_token);
     197             : 
     198         229 :         len = p2p_buf_add_ie_hdr(buf);
     199             : 
     200         229 :         group_capab = 0;
     201         229 :         if (p2p->p2ps_prov) {
     202          37 :                 group_capab |= P2P_GROUP_CAPAB_PERSISTENT_GROUP;
     203          37 :                 group_capab |= P2P_GROUP_CAPAB_PERSISTENT_RECONN;
     204          37 :                 if (p2p->cross_connect)
     205           0 :                         group_capab |= P2P_GROUP_CAPAB_CROSS_CONN;
     206          37 :                 if (p2p->cfg->p2p_intra_bss)
     207          37 :                         group_capab |= P2P_GROUP_CAPAB_INTRA_BSS_DIST;
     208             :         }
     209         229 :         p2p_buf_add_capability(buf, p2p->dev_capab &
     210             :                                ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY,
     211             :                                group_capab);
     212         229 :         p2p_buf_add_device_info(buf, p2p, NULL);
     213         229 :         if (p2p->p2ps_prov) {
     214          37 :                 p2ps_add_pd_req_attrs(p2p, dev, buf, config_methods);
     215         192 :         } else if (go) {
     216         118 :                 p2p_buf_add_group_id(buf, go->info.p2p_device_addr,
     217          59 :                                      go->oper_ssid, go->oper_ssid_len);
     218             :         }
     219         229 :         p2p_buf_update_ie_hdr(buf, len);
     220             : 
     221             :         /* WPS IE with Config Methods attribute */
     222         229 :         p2p_build_wps_ie_config_methods(buf, config_methods);
     223             : 
     224             : #ifdef CONFIG_WIFI_DISPLAY
     225         229 :         if (p2p->wfd_ie_prov_disc_req)
     226           3 :                 wpabuf_put_buf(buf, p2p->wfd_ie_prov_disc_req);
     227             : #endif /* CONFIG_WIFI_DISPLAY */
     228             : 
     229         229 :         if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_PD_REQ])
     230           1 :                 wpabuf_put_buf(buf, p2p->vendor_elem[VENDOR_ELEM_P2P_PD_REQ]);
     231             : 
     232         229 :         return buf;
     233             : }
     234             : 
     235             : 
     236         108 : static struct wpabuf * p2p_build_prov_disc_resp(struct p2p_data *p2p,
     237             :                                                 struct p2p_device *dev,
     238             :                                                 u8 dialog_token,
     239             :                                                 enum p2p_status_code status,
     240             :                                                 u16 config_methods,
     241             :                                                 u32 adv_id,
     242             :                                                 const u8 *group_id,
     243             :                                                 size_t group_id_len,
     244             :                                                 const u8 *persist_ssid,
     245             :                                                 size_t persist_ssid_len,
     246             :                                                 const u8 *fcap,
     247             :                                                 u16 fcap_len)
     248             : {
     249             :         struct wpabuf *buf;
     250         108 :         size_t extra = 0;
     251         108 :         int persist = 0;
     252             : 
     253             : #ifdef CONFIG_WIFI_DISPLAY
     254         108 :         struct wpabuf *wfd_ie = p2p->wfd_ie_prov_disc_resp;
     255         108 :         if (wfd_ie && group_id) {
     256             :                 size_t i;
     257           3 :                 for (i = 0; i < p2p->num_groups; i++) {
     258           3 :                         struct p2p_group *g = p2p->groups[i];
     259             :                         struct wpabuf *ie;
     260           3 :                         if (!p2p_group_is_group_id_match(g, group_id,
     261             :                                                          group_id_len))
     262           0 :                                 continue;
     263           3 :                         ie = p2p_group_get_wfd_ie(g);
     264           3 :                         if (ie) {
     265           3 :                                 wfd_ie = ie;
     266           3 :                                 break;
     267             :                         }
     268             :                 }
     269             :         }
     270         108 :         if (wfd_ie)
     271           4 :                 extra = wpabuf_len(wfd_ie);
     272             : #endif /* CONFIG_WIFI_DISPLAY */
     273             : 
     274         108 :         if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_PD_RESP])
     275           1 :                 extra += wpabuf_len(p2p->vendor_elem[VENDOR_ELEM_P2P_PD_RESP]);
     276             : 
     277         108 :         buf = wpabuf_alloc(1000 + extra);
     278         108 :         if (buf == NULL)
     279           0 :                 return NULL;
     280             : 
     281         108 :         p2p_buf_add_public_action_hdr(buf, P2P_PROV_DISC_RESP, dialog_token);
     282             : 
     283             :         /* Add P2P IE for P2PS */
     284         143 :         if (p2p->p2ps_prov && p2p->p2ps_prov->adv_id == adv_id) {
     285          35 :                 u8 *len = p2p_buf_add_ie_hdr(buf);
     286          35 :                 struct p2ps_provision *prov = p2p->p2ps_prov;
     287             :                 u8 group_capab;
     288             : 
     289          35 :                 if (!status && prov->status != -1)
     290          28 :                         status = prov->status;
     291             : 
     292          35 :                 p2p_buf_add_status(buf, status);
     293          35 :                 group_capab = P2P_GROUP_CAPAB_PERSISTENT_GROUP |
     294             :                         P2P_GROUP_CAPAB_PERSISTENT_RECONN;
     295          35 :                 if (p2p->cross_connect)
     296           0 :                         group_capab |= P2P_GROUP_CAPAB_CROSS_CONN;
     297          35 :                 if (p2p->cfg->p2p_intra_bss)
     298          35 :                         group_capab |= P2P_GROUP_CAPAB_INTRA_BSS_DIST;
     299          35 :                 p2p_buf_add_capability(buf, p2p->dev_capab &
     300             :                                        ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY,
     301             :                                        group_capab);
     302          35 :                 p2p_buf_add_device_info(buf, p2p, NULL);
     303             : 
     304          35 :                 if (persist_ssid && p2p->cfg->get_persistent_group &&
     305           0 :                     (status == P2P_SC_SUCCESS ||
     306             :                      status == P2P_SC_SUCCESS_DEFERRED)) {
     307             :                         u8 ssid[SSID_MAX_LEN];
     308             :                         size_t ssid_len;
     309             :                         u8 go_dev_addr[ETH_ALEN];
     310             :                         u8 intended_addr[ETH_ALEN];
     311             : 
     312           2 :                         persist = p2p->cfg->get_persistent_group(
     313           1 :                                 p2p->cfg->cb_ctx,
     314           1 :                                 dev->info.p2p_device_addr,
     315             :                                 persist_ssid, persist_ssid_len, go_dev_addr,
     316             :                                 ssid, &ssid_len, intended_addr);
     317           1 :                         if (persist) {
     318           1 :                                 p2p_buf_add_persistent_group_info(
     319             :                                         buf, go_dev_addr, ssid, ssid_len);
     320           1 :                                 if (!is_zero_ether_addr(intended_addr))
     321           1 :                                         p2p_buf_add_intended_addr(
     322             :                                                 buf, intended_addr);
     323             :                         }
     324             :                 }
     325             : 
     326          35 :                 if (!persist && (prov->conncap & P2PS_SETUP_GROUP_OWNER))
     327           5 :                         p2ps_add_new_group_info(p2p, buf);
     328             : 
     329             :                 /* Add Operating Channel if conncap indicates GO */
     330          35 :                 if (persist || (prov->conncap & P2PS_SETUP_GROUP_OWNER)) {
     331             :                         u8 tmp;
     332             : 
     333           6 :                         if (dev)
     334           6 :                                 p2p_go_select_channel(p2p, dev, &tmp);
     335             : 
     336           6 :                         if (p2p->op_reg_class && p2p->op_channel)
     337          18 :                                 p2p_buf_add_operating_channel(
     338           6 :                                         buf, p2p->cfg->country,
     339           6 :                                         p2p->op_reg_class,
     340           6 :                                         p2p->op_channel);
     341             :                         else
     342           0 :                                 p2p_buf_add_operating_channel(
     343           0 :                                         buf, p2p->cfg->country,
     344           0 :                                         p2p->cfg->op_reg_class,
     345           0 :                                         p2p->cfg->op_channel);
     346             :                 }
     347             : 
     348          35 :                 p2p_buf_add_channel_list(buf, p2p->cfg->country,
     349          35 :                                          &p2p->cfg->channels);
     350             : 
     351          35 :                 if (!persist && (status == P2P_SC_SUCCESS ||
     352             :                                  status == P2P_SC_SUCCESS_DEFERRED))
     353          27 :                         p2p_buf_add_connection_capability(buf, prov->conncap);
     354             : 
     355          35 :                 p2p_buf_add_advertisement_id(buf, adv_id, prov->adv_mac);
     356             : 
     357          35 :                 p2p_buf_add_config_timeout(buf, p2p->go_timeout,
     358          35 :                                            p2p->client_timeout);
     359             : 
     360          35 :                 p2p_buf_add_session_id(buf, prov->session_id,
     361          35 :                                        prov->session_mac);
     362             : 
     363          35 :                 p2p_buf_add_feature_capability(buf, fcap_len, fcap);
     364          35 :                 p2p_buf_update_ie_hdr(buf, len);
     365          73 :         } else if (status != P2P_SC_SUCCESS || adv_id) {
     366           3 :                 u8 *len = p2p_buf_add_ie_hdr(buf);
     367             : 
     368           3 :                 p2p_buf_add_status(buf, status);
     369             : 
     370           3 :                 if (p2p->p2ps_prov)
     371           0 :                         p2p_buf_add_advertisement_id(buf, adv_id,
     372           0 :                                                      p2p->p2ps_prov->adv_mac);
     373             : 
     374           3 :                 p2p_buf_update_ie_hdr(buf, len);
     375             :         }
     376             : 
     377             :         /* WPS IE with Config Methods attribute */
     378         108 :         p2p_build_wps_ie_config_methods(buf, config_methods);
     379             : 
     380             : #ifdef CONFIG_WIFI_DISPLAY
     381         108 :         if (wfd_ie)
     382           4 :                 wpabuf_put_buf(buf, wfd_ie);
     383             : #endif /* CONFIG_WIFI_DISPLAY */
     384             : 
     385         108 :         if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_PD_RESP])
     386           1 :                 wpabuf_put_buf(buf, p2p->vendor_elem[VENDOR_ELEM_P2P_PD_RESP]);
     387             : 
     388         108 :         return buf;
     389             : }
     390             : 
     391             : 
     392          24 : static int p2ps_setup_p2ps_prov(struct p2p_data *p2p, u32 adv_id,
     393             :                                 u32 session_id, u16 method,
     394             :                                 const u8 *session_mac, const u8 *adv_mac)
     395             : {
     396             :         struct p2ps_provision *tmp;
     397             : 
     398          24 :         if (!p2p->p2ps_prov) {
     399          11 :                 p2p->p2ps_prov = os_zalloc(sizeof(struct p2ps_provision) + 1);
     400          11 :                 if (!p2p->p2ps_prov)
     401           0 :                         return -1;
     402             :         } else {
     403          13 :                 os_memset(p2p->p2ps_prov, 0, sizeof(struct p2ps_provision) + 1);
     404             :         }
     405             : 
     406          24 :         tmp = p2p->p2ps_prov;
     407          24 :         tmp->adv_id = adv_id;
     408          24 :         tmp->session_id = session_id;
     409          24 :         tmp->method = method;
     410          24 :         os_memcpy(tmp->session_mac, session_mac, ETH_ALEN);
     411          24 :         os_memcpy(tmp->adv_mac, adv_mac, ETH_ALEN);
     412          24 :         tmp->info[0] = '\0';
     413             : 
     414          24 :         return 0;
     415             : }
     416             : 
     417             : 
     418          35 : static u8 p2ps_own_preferred_cpt(const u8 *cpt_priority, u8 req_cpt_mask)
     419             : {
     420             :         int i;
     421             : 
     422          36 :         for (i = 0; cpt_priority[i]; i++)
     423          36 :                 if (req_cpt_mask & cpt_priority[i])
     424          35 :                         return cpt_priority[i];
     425             : 
     426           0 :         return 0;
     427             : }
     428             : 
     429             : 
     430         109 : void p2p_process_prov_disc_req(struct p2p_data *p2p, const u8 *sa,
     431             :                                const u8 *data, size_t len, int rx_freq)
     432             : {
     433             :         struct p2p_message msg;
     434             :         struct p2p_device *dev;
     435             :         int freq;
     436         109 :         enum p2p_status_code reject = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
     437             :         struct wpabuf *resp;
     438         109 :         u32 adv_id = 0;
     439         109 :         struct p2ps_advertisement *p2ps_adv = NULL;
     440         109 :         u8 conncap = P2PS_SETUP_NEW;
     441         109 :         u8 auto_accept = 0;
     442         109 :         u32 session_id = 0;
     443             :         u8 session_mac[ETH_ALEN];
     444             :         u8 adv_mac[ETH_ALEN];
     445             :         const u8 *group_mac;
     446         109 :         int passwd_id = DEV_PW_DEFAULT;
     447             :         u16 config_methods;
     448         109 :         u16 allowed_config_methods = WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD;
     449         109 :         struct p2ps_feature_capab resp_fcap = { 0, 0 };
     450             :         struct p2ps_feature_capab *req_fcap;
     451             : 
     452         109 :         if (p2p_parse(data, len, &msg))
     453           2 :                 return;
     454             : 
     455         756 :         p2p_dbg(p2p, "Received Provision Discovery Request from " MACSTR
     456             :                 " with config methods 0x%x (freq=%d)",
     457         756 :                 MAC2STR(sa), msg.wps_config_methods, rx_freq);
     458         108 :         group_mac = msg.intended_addr;
     459             : 
     460         108 :         dev = p2p_get_device(p2p, sa);
     461         108 :         if (dev == NULL || (dev->flags & P2P_DEV_PROBE_REQ_ONLY)) {
     462         522 :                 p2p_dbg(p2p, "Provision Discovery Request from unknown peer "
     463         522 :                         MACSTR, MAC2STR(sa));
     464             : 
     465         174 :                 if (p2p_add_device(p2p, sa, rx_freq, NULL, 0, data + 1, len - 1,
     466             :                                    0)) {
     467           6 :                         p2p_dbg(p2p, "Provision Discovery Request add device failed "
     468           6 :                                 MACSTR, MAC2STR(sa));
     469             :                 }
     470          21 :         } else if (msg.wfd_subelems) {
     471           1 :                 wpabuf_free(dev->info.wfd_subelems);
     472           1 :                 dev->info.wfd_subelems = wpabuf_dup(msg.wfd_subelems);
     473             :         }
     474             : 
     475         108 :         if (msg.adv_id)
     476          35 :                 allowed_config_methods |= WPS_CONFIG_P2PS;
     477             :         else
     478          73 :                 allowed_config_methods |= WPS_CONFIG_PUSHBUTTON;
     479             : 
     480         108 :         if (!(msg.wps_config_methods & allowed_config_methods)) {
     481           1 :                 p2p_dbg(p2p, "Unsupported Config Methods in Provision Discovery Request");
     482           1 :                 goto out;
     483             :         }
     484             : 
     485             :         /* Legacy (non-P2PS) - Unknown groups allowed for P2PS */
     486         107 :         if (!msg.adv_id && msg.group_id) {
     487             :                 size_t i;
     488          60 :                 for (i = 0; i < p2p->num_groups; i++) {
     489          58 :                         if (p2p_group_is_group_id_match(p2p->groups[i],
     490             :                                                         msg.group_id,
     491             :                                                         msg.group_id_len))
     492          58 :                                 break;
     493             :                 }
     494          60 :                 if (i == p2p->num_groups) {
     495           2 :                         p2p_dbg(p2p, "PD request for unknown P2P Group ID - reject");
     496           2 :                         goto out;
     497             :                 }
     498             :         }
     499             : 
     500         105 :         if (dev) {
     501         103 :                 dev->flags &= ~(P2P_DEV_PD_PEER_DISPLAY |
     502             :                                 P2P_DEV_PD_PEER_KEYPAD |
     503             :                                 P2P_DEV_PD_PEER_P2PS);
     504             : 
     505             :                 /* Remove stale persistent groups */
     506         103 :                 if (p2p->cfg->remove_stale_groups) {
     507         206 :                         p2p->cfg->remove_stale_groups(
     508         103 :                                 p2p->cfg->cb_ctx, dev->info.p2p_device_addr,
     509             :                                 msg.persistent_dev,
     510             :                                 msg.persistent_ssid, msg.persistent_ssid_len);
     511             :                 }
     512             :         }
     513         105 :         if (msg.wps_config_methods & WPS_CONFIG_DISPLAY) {
     514         432 :                 p2p_dbg(p2p, "Peer " MACSTR
     515         432 :                         " requested us to show a PIN on display", MAC2STR(sa));
     516          72 :                 if (dev)
     517          70 :                         dev->flags |= P2P_DEV_PD_PEER_KEYPAD;
     518          72 :                 passwd_id = DEV_PW_USER_SPECIFIED;
     519          33 :         } else if (msg.wps_config_methods & WPS_CONFIG_KEYPAD) {
     520          66 :                 p2p_dbg(p2p, "Peer " MACSTR
     521             :                         " requested us to write its PIN using keypad",
     522          66 :                         MAC2STR(sa));
     523          11 :                 if (dev)
     524          11 :                         dev->flags |= P2P_DEV_PD_PEER_DISPLAY;
     525          11 :                 passwd_id = DEV_PW_REGISTRAR_SPECIFIED;
     526          22 :         } else if (msg.wps_config_methods & WPS_CONFIG_P2PS) {
     527          84 :                 p2p_dbg(p2p, "Peer " MACSTR " requesting P2PS PIN",
     528          84 :                         MAC2STR(sa));
     529          14 :                 if (dev)
     530          14 :                         dev->flags |= P2P_DEV_PD_PEER_P2PS;
     531          14 :                 passwd_id = DEV_PW_P2PS_DEFAULT;
     532             :         }
     533             : 
     534         105 :         reject = P2P_SC_SUCCESS;
     535             : 
     536         105 :         os_memset(session_mac, 0, ETH_ALEN);
     537         105 :         os_memset(adv_mac, 0, ETH_ALEN);
     538             : 
     539             :         /* Note 1: A feature capability attribute structure can be changed
     540             :          * in the future. The assumption is that such modifications are
     541             :          * backwards compatible, therefore we allow processing of
     542             :          * msg.feature_cap exceeding the size of the p2ps_feature_capab
     543             :          * structure.
     544             :          * Note 2: Vverification of msg.feature_cap_len below has to be changed
     545             :          * to allow 2 byte feature capability processing if struct
     546             :          * p2ps_feature_capab is extended to include additional fields and it
     547             :          * affects the structure size.
     548             :          */
     549         140 :         if (msg.adv_id && msg.session_id && msg.session_mac && msg.adv_mac &&
     550         105 :             msg.feature_cap && msg.feature_cap_len >= sizeof(*req_fcap) &&
     551          59 :             (msg.status || msg.conn_cap)) {
     552             :                 u8 remote_conncap;
     553             : 
     554          35 :                 req_fcap = (struct p2ps_feature_capab *) msg.feature_cap;
     555             : 
     556          35 :                 os_memcpy(session_mac, msg.session_mac, ETH_ALEN);
     557          35 :                 os_memcpy(adv_mac, msg.adv_mac, ETH_ALEN);
     558             : 
     559          35 :                 session_id = WPA_GET_LE32(msg.session_id);
     560          35 :                 adv_id = WPA_GET_LE32(msg.adv_id);
     561             : 
     562          35 :                 if (!msg.status)
     563          24 :                         p2ps_adv = p2p_service_p2ps_id(p2p, adv_id);
     564             : 
     565          35 :                 p2p_dbg(p2p, "adv_id: %x - p2ps_adv - %p", adv_id, p2ps_adv);
     566             : 
     567          35 :                 if (msg.conn_cap)
     568          35 :                         conncap = *msg.conn_cap;
     569          35 :                 remote_conncap = conncap;
     570             : 
     571          35 :                 if (p2ps_adv) {
     572          24 :                         auto_accept = p2ps_adv->auto_accept;
     573          48 :                         conncap = p2p->cfg->p2ps_group_capability(
     574          24 :                                 p2p->cfg->cb_ctx, conncap, auto_accept);
     575             : 
     576          24 :                         p2p_dbg(p2p, "Conncap: local:%d remote:%d result:%d",
     577             :                                 auto_accept, remote_conncap, conncap);
     578             : 
     579          24 :                         resp_fcap.cpt =
     580          24 :                                 p2ps_own_preferred_cpt(p2ps_adv->cpt_priority,
     581          24 :                                                        req_fcap->cpt);
     582             : 
     583          72 :                         p2p_dbg(p2p,
     584             :                                 "cpt: service:0x%x remote:0x%x result:0x%x",
     585          48 :                                 p2ps_adv->cpt_mask, req_fcap->cpt,
     586          24 :                                 resp_fcap.cpt);
     587             : 
     588          24 :                         if (!resp_fcap.cpt) {
     589           0 :                                 p2p_dbg(p2p,
     590             :                                         "Incompatible P2PS feature capability CPT bitmask");
     591           0 :                                 reject = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
     592          48 :                         } else if (p2ps_adv->config_methods &&
     593          48 :                                    !(msg.wps_config_methods &
     594          24 :                                    p2ps_adv->config_methods)) {
     595           0 :                                 p2p_dbg(p2p,
     596             :                                         "Unsupported config methods in Provision Discovery Request (own=0x%x peer=0x%x)",
     597           0 :                                         p2ps_adv->config_methods,
     598           0 :                                         msg.wps_config_methods);
     599           0 :                                 reject = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
     600          24 :                         } else if (!p2ps_adv->state) {
     601           0 :                                 p2p_dbg(p2p, "P2PS state unavailable");
     602           0 :                                 reject = P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE;
     603          24 :                         } else if (!conncap) {
     604           0 :                                 p2p_dbg(p2p, "Conncap resolution failed");
     605           0 :                                 reject = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
     606             :                         }
     607             : 
     608          24 :                         if (msg.wps_config_methods & WPS_CONFIG_KEYPAD) {
     609           2 :                                 p2p_dbg(p2p, "Keypad - always defer");
     610           2 :                                 auto_accept = 0;
     611             :                         }
     612             : 
     613          24 :                         if (auto_accept || reject != P2P_SC_SUCCESS) {
     614             :                                 struct p2ps_provision *tmp;
     615             : 
     616          17 :                                 if (reject == P2P_SC_SUCCESS && !conncap) {
     617           0 :                                         reject =
     618             :                                                 P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
     619             :                                 }
     620             : 
     621          17 :                                 if (p2ps_setup_p2ps_prov(
     622             :                                             p2p, adv_id, session_id,
     623          17 :                                             msg.wps_config_methods,
     624             :                                             session_mac, adv_mac) < 0) {
     625           0 :                                         reject = P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE;
     626           0 :                                         goto out;
     627             :                                 }
     628             : 
     629          17 :                                 tmp = p2p->p2ps_prov;
     630          17 :                                 if (conncap) {
     631          17 :                                         tmp->conncap = conncap;
     632          17 :                                         tmp->status = P2P_SC_SUCCESS;
     633             :                                 } else {
     634           0 :                                         tmp->conncap = auto_accept;
     635           0 :                                         tmp->status = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
     636             :                                 }
     637             : 
     638          17 :                                 if (reject != P2P_SC_SUCCESS)
     639           0 :                                         goto out;
     640             :                         }
     641          11 :                 } else if (!msg.status) {
     642           0 :                         reject = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
     643           0 :                         goto out;
     644             :                 }
     645             : 
     646          42 :                 if (!msg.status && !auto_accept &&
     647          11 :                     (!p2p->p2ps_prov || p2p->p2ps_prov->adv_id != adv_id)) {
     648             :                         struct p2ps_provision *tmp;
     649             : 
     650           7 :                         if (!conncap) {
     651           0 :                                 reject = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
     652           0 :                                 goto out;
     653             :                         }
     654             : 
     655           7 :                         if (p2ps_setup_p2ps_prov(p2p, adv_id, session_id,
     656           7 :                                                  msg.wps_config_methods,
     657             :                                                  session_mac, adv_mac) < 0) {
     658           0 :                                 reject = P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE;
     659           0 :                                 goto out;
     660             :                         }
     661           7 :                         tmp = p2p->p2ps_prov;
     662           7 :                         reject = P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE;
     663           7 :                         tmp->status = reject;
     664             :                 }
     665             : 
     666          35 :                 if (msg.status) {
     667          22 :                         if (*msg.status &&
     668          11 :                             *msg.status != P2P_SC_SUCCESS_DEFERRED) {
     669           0 :                                 reject = *msg.status;
     670          22 :                         } else if (*msg.status == P2P_SC_SUCCESS_DEFERRED &&
     671          11 :                                    p2p->p2ps_prov) {
     672          11 :                                 u16 method = p2p->p2ps_prov->method;
     673             : 
     674          33 :                                 conncap = p2p->cfg->p2ps_group_capability(
     675          11 :                                         p2p->cfg->cb_ctx, remote_conncap,
     676          11 :                                         p2p->p2ps_prov->conncap);
     677             : 
     678          22 :                                 p2p_dbg(p2p,
     679             :                                         "Conncap: local:%d remote:%d result:%d",
     680          11 :                                         p2p->p2ps_prov->conncap,
     681             :                                         remote_conncap, conncap);
     682             : 
     683          22 :                                 resp_fcap.cpt = p2ps_own_preferred_cpt(
     684          11 :                                         p2p->p2ps_prov->cpt_priority,
     685          11 :                                         req_fcap->cpt);
     686             : 
     687          33 :                                 p2p_dbg(p2p,
     688             :                                         "cpt: local:0x%x remote:0x%x result:0x%x",
     689          11 :                                         p2p->p2ps_prov->cpt_mask,
     690          22 :                                         req_fcap->cpt, resp_fcap.cpt);
     691             : 
     692             :                                 /*
     693             :                                  * Ensure that if we asked for PIN originally,
     694             :                                  * our method is consistent with original
     695             :                                  * request.
     696             :                                  */
     697          11 :                                 if (method & WPS_CONFIG_DISPLAY)
     698           6 :                                         method = WPS_CONFIG_KEYPAD;
     699           5 :                                 else if (method & WPS_CONFIG_KEYPAD)
     700           2 :                                         method = WPS_CONFIG_DISPLAY;
     701             : 
     702          22 :                                 if (!conncap ||
     703          11 :                                     !(msg.wps_config_methods & method)) {
     704             :                                         /*
     705             :                                          * Reject this "Deferred Accept*
     706             :                                          * if incompatible conncap or method
     707             :                                          */
     708           0 :                                         reject =
     709             :                                                 P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
     710          11 :                                 } else if (!resp_fcap.cpt) {
     711           0 :                                         p2p_dbg(p2p,
     712             :                                                 "Incompatible P2PS feature capability CPT bitmask");
     713           0 :                                         reject =
     714             :                                                 P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
     715             :                                 } else {
     716          11 :                                         reject = P2P_SC_SUCCESS;
     717             :                                 }
     718             : 
     719          11 :                                 p2p->p2ps_prov->status = reject;
     720          11 :                                 p2p->p2ps_prov->conncap = conncap;
     721             :                         }
     722             :                 }
     723             :         }
     724             : 
     725             : out:
     726         108 :         if (reject == P2P_SC_SUCCESS ||
     727             :             reject == P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE)
     728         105 :                 config_methods = msg.wps_config_methods;
     729             :         else
     730           3 :                 config_methods = 0;
     731         108 :         resp = p2p_build_prov_disc_resp(p2p, dev, msg.dialog_token, reject,
     732             :                                         config_methods, adv_id,
     733             :                                         msg.group_id, msg.group_id_len,
     734             :                                         msg.persistent_ssid,
     735             :                                         msg.persistent_ssid_len,
     736             :                                         (const u8 *) &resp_fcap,
     737             :                                         sizeof(resp_fcap));
     738         108 :         if (resp == NULL) {
     739           0 :                 p2p_parse_free(&msg);
     740           0 :                 return;
     741             :         }
     742         108 :         p2p_dbg(p2p, "Sending Provision Discovery Response");
     743         108 :         if (rx_freq > 0)
     744         108 :                 freq = rx_freq;
     745             :         else
     746           0 :                 freq = p2p_channel_to_freq(p2p->cfg->reg_class,
     747           0 :                                            p2p->cfg->channel);
     748         108 :         if (freq < 0) {
     749           0 :                 p2p_dbg(p2p, "Unknown regulatory class/channel");
     750           0 :                 wpabuf_free(resp);
     751           0 :                 p2p_parse_free(&msg);
     752           0 :                 return;
     753             :         }
     754         108 :         p2p->pending_action_state = P2P_PENDING_PD_RESPONSE;
     755         216 :         if (p2p_send_action(p2p, freq, sa, p2p->cfg->dev_addr,
     756         108 :                             p2p->cfg->dev_addr,
     757         108 :                             wpabuf_head(resp), wpabuf_len(resp), 200) < 0) {
     758           0 :                 p2p_dbg(p2p, "Failed to send Action frame");
     759             :         } else
     760         108 :                 p2p->send_action_in_progress = 1;
     761             : 
     762         108 :         wpabuf_free(resp);
     763             : 
     764         108 :         if (!p2p->cfg->p2ps_prov_complete) {
     765             :                 /* Don't emit anything */
     766         119 :         } else if (msg.status && *msg.status != P2P_SC_SUCCESS &&
     767          11 :                    *msg.status != P2P_SC_SUCCESS_DEFERRED) {
     768           0 :                 reject = *msg.status;
     769           0 :                 p2p->cfg->p2ps_prov_complete(p2p->cfg->cb_ctx, reject,
     770             :                                              sa, adv_mac, session_mac,
     771             :                                              NULL, adv_id, session_id,
     772             :                                              0, 0, msg.persistent_ssid,
     773             :                                              msg.persistent_ssid_len,
     774             :                                              0, 0, NULL, NULL, 0);
     775         119 :         } else if (msg.status && *msg.status == P2P_SC_SUCCESS_DEFERRED &&
     776          11 :                    p2p->p2ps_prov) {
     777          11 :                 p2p->p2ps_prov->status = reject;
     778          11 :                 p2p->p2ps_prov->conncap = conncap;
     779             : 
     780          22 :                 if (reject != P2P_SC_SUCCESS)
     781           0 :                         p2p->cfg->p2ps_prov_complete(p2p->cfg->cb_ctx, reject,
     782             :                                                      sa, adv_mac, session_mac,
     783             :                                                      NULL, adv_id,
     784             :                                                      session_id, conncap, 0,
     785             :                                                      msg.persistent_ssid,
     786             :                                                      msg.persistent_ssid_len, 0,
     787             :                                                      0, NULL, NULL, 0);
     788             :                 else
     789          22 :                         p2p->cfg->p2ps_prov_complete(p2p->cfg->cb_ctx,
     790          11 :                                                      *msg.status,
     791             :                                                      sa, adv_mac, session_mac,
     792             :                                                      group_mac, adv_id,
     793             :                                                      session_id, conncap,
     794             :                                                      passwd_id,
     795             :                                                      msg.persistent_ssid,
     796             :                                                      msg.persistent_ssid_len, 0,
     797             :                                                      0, NULL,
     798             :                                                      (const u8 *) &resp_fcap,
     799             :                                                      sizeof(resp_fcap));
     800          97 :         } else if (msg.status && p2p->p2ps_prov) {
     801           0 :                 p2p->p2ps_prov->status = P2P_SC_SUCCESS;
     802           0 :                 p2p->cfg->p2ps_prov_complete(p2p->cfg->cb_ctx, *msg.status, sa,
     803             :                                              adv_mac, session_mac, group_mac,
     804             :                                              adv_id, session_id, conncap,
     805             :                                              passwd_id,
     806             :                                              msg.persistent_ssid,
     807             :                                              msg.persistent_ssid_len,
     808             :                                              0, 0, NULL,
     809             :                                              (const u8 *) &resp_fcap,
     810             :                                              sizeof(resp_fcap));
     811          97 :         } else if (msg.status) {
     812          97 :         } else if (auto_accept && reject == P2P_SC_SUCCESS) {
     813          17 :                 p2p->cfg->p2ps_prov_complete(p2p->cfg->cb_ctx, P2P_SC_SUCCESS,
     814             :                                              sa, adv_mac, session_mac,
     815             :                                              group_mac, adv_id, session_id,
     816             :                                              conncap, passwd_id,
     817             :                                              msg.persistent_ssid,
     818             :                                              msg.persistent_ssid_len,
     819             :                                              0, 0, NULL,
     820             :                                              (const u8 *) &resp_fcap,
     821             :                                              sizeof(resp_fcap));
     822          87 :         } else if (reject == P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE &&
     823           7 :                    (!msg.session_info || !msg.session_info_len)) {
     824           7 :                 p2p->p2ps_prov->method = msg.wps_config_methods;
     825             : 
     826           7 :                 p2p->cfg->p2ps_prov_complete(p2p->cfg->cb_ctx, P2P_SC_SUCCESS,
     827             :                                              sa, adv_mac, session_mac,
     828             :                                              group_mac, adv_id, session_id,
     829             :                                              conncap, passwd_id,
     830             :                                              msg.persistent_ssid,
     831             :                                              msg.persistent_ssid_len,
     832             :                                              0, 1, NULL,
     833             :                                              (const u8 *) &resp_fcap,
     834             :                                              sizeof(resp_fcap));
     835          73 :         } else if (reject == P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE) {
     836           0 :                 size_t buf_len = msg.session_info_len;
     837           0 :                 char *buf = os_malloc(2 * buf_len + 1);
     838             : 
     839           0 :                 if (buf) {
     840           0 :                         p2p->p2ps_prov->method = msg.wps_config_methods;
     841             : 
     842           0 :                         utf8_escape((char *) msg.session_info, buf_len,
     843           0 :                                     buf, 2 * buf_len + 1);
     844             : 
     845           0 :                         p2p->cfg->p2ps_prov_complete(
     846           0 :                                 p2p->cfg->cb_ctx, P2P_SC_SUCCESS, sa,
     847             :                                 adv_mac, session_mac, group_mac, adv_id,
     848             :                                 session_id, conncap, passwd_id,
     849             :                                 msg.persistent_ssid, msg.persistent_ssid_len,
     850             :                                 0, 1, buf,
     851             :                                 (const u8 *) &resp_fcap, sizeof(resp_fcap));
     852             : 
     853           0 :                         os_free(buf);
     854             :                 }
     855             :         }
     856             : 
     857             :         /*
     858             :          * prov_disc_req callback is used to generate P2P-PROV-DISC-ENTER-PIN,
     859             :          * P2P-PROV-DISC-SHOW-PIN, and P2P-PROV-DISC-PBC-REQ events.
     860             :          * Call it either on legacy P2P PD or on P2PS PD only if we need to
     861             :          * enter/show PIN.
     862             :          *
     863             :          * The callback is called in the following cases:
     864             :          * 1. Legacy P2P PD request, response status SUCCESS
     865             :          * 2. P2PS advertiser, method: DISPLAY, autoaccept: TRUE,
     866             :          *    response status: SUCCESS
     867             :          * 3. P2PS advertiser, method  DISPLAY, autoaccept: FALSE,
     868             :          *    response status: INFO_CURRENTLY_UNAVAILABLE
     869             :          * 4. P2PS advertiser, method: KEYPAD, autoaccept==any,
     870             :          *    response status: INFO_CURRENTLY_UNAVAILABLE
     871             :          * 5. P2PS follow-on with SUCCESS_DEFERRED,
     872             :          *    advertiser role: DISPLAY, autoaccept: FALSE,
     873             :          *    seeker: KEYPAD, response status: SUCCESS
     874             :          */
     875         108 :         if (p2p->cfg->prov_disc_req &&
     876         136 :             ((reject == P2P_SC_SUCCESS && !msg.adv_id) ||
     877          65 :              (!msg.status &&
     878          10 :              (reject == P2P_SC_SUCCESS ||
     879          24 :               reject == P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE) &&
     880          27 :               passwd_id == DEV_PW_USER_SPECIFIED) ||
     881          43 :              (!msg.status &&
     882           3 :               reject == P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE &&
     883          25 :               passwd_id == DEV_PW_REGISTRAR_SPECIFIED) ||
     884          21 :              (reject == P2P_SC_SUCCESS &&
     885          32 :               msg.status && *msg.status == P2P_SC_SUCCESS_DEFERRED &&
     886             :                passwd_id == DEV_PW_REGISTRAR_SPECIFIED))) {
     887          89 :                 const u8 *dev_addr = sa;
     888             : 
     889          89 :                 if (msg.p2p_device_addr)
     890          89 :                         dev_addr = msg.p2p_device_addr;
     891         623 :                 p2p->cfg->prov_disc_req(p2p->cfg->cb_ctx, sa,
     892          89 :                                         msg.wps_config_methods,
     893             :                                         dev_addr, msg.pri_dev_type,
     894          89 :                                         msg.device_name, msg.config_methods,
     895         178 :                                         msg.capability ? msg.capability[0] : 0,
     896         178 :                                         msg.capability ? msg.capability[1] :
     897             :                                         0,
     898             :                                         msg.group_id, msg.group_id_len);
     899             :         }
     900             : 
     901         108 :         if (dev && reject == P2P_SC_SUCCESS) {
     902          96 :                 switch (config_methods) {
     903             :                 case WPS_CONFIG_DISPLAY:
     904          65 :                         dev->wps_prov_info = WPS_CONFIG_KEYPAD;
     905          65 :                         break;
     906             :                 case WPS_CONFIG_KEYPAD:
     907           9 :                         dev->wps_prov_info = WPS_CONFIG_DISPLAY;
     908           9 :                         break;
     909             :                 case WPS_CONFIG_PUSHBUTTON:
     910           8 :                         dev->wps_prov_info = WPS_CONFIG_PUSHBUTTON;
     911           8 :                         break;
     912             :                 case WPS_CONFIG_P2PS:
     913          13 :                         dev->wps_prov_info = WPS_CONFIG_P2PS;
     914          13 :                         break;
     915             :                 default:
     916           1 :                         dev->wps_prov_info = 0;
     917           1 :                         break;
     918             :                 }
     919             : 
     920          96 :                 if (msg.intended_addr)
     921          28 :                         os_memcpy(dev->interface_addr, msg.intended_addr,
     922             :                                   ETH_ALEN);
     923             :         }
     924         108 :         p2p_parse_free(&msg);
     925             : }
     926             : 
     927             : 
     928          31 : static int p2p_validate_p2ps_pd_resp(struct p2p_data *p2p,
     929             :                                      struct p2p_message *msg)
     930             : {
     931          31 :         u8 conn_cap_go = 0;
     932          31 :         u8 conn_cap_cli = 0;
     933             :         u32 session_id;
     934             :         u32 adv_id;
     935             : 
     936             : #define P2PS_PD_RESP_CHECK(_val, _attr) \
     937             :         do { \
     938             :                 if ((_val) && !msg->_attr) { \
     939             :                         p2p_dbg(p2p, "P2PS PD Response missing " #_attr); \
     940             :                         return -1; \
     941             :                 } \
     942             :         } while (0)
     943             : 
     944          31 :         P2PS_PD_RESP_CHECK(1, status);
     945          31 :         P2PS_PD_RESP_CHECK(1, adv_id);
     946          31 :         P2PS_PD_RESP_CHECK(1, adv_mac);
     947          31 :         P2PS_PD_RESP_CHECK(1, capability);
     948          31 :         P2PS_PD_RESP_CHECK(1, p2p_device_info);
     949          31 :         P2PS_PD_RESP_CHECK(1, session_id);
     950          31 :         P2PS_PD_RESP_CHECK(1, session_mac);
     951          31 :         P2PS_PD_RESP_CHECK(1, feature_cap);
     952             : 
     953          31 :         session_id = WPA_GET_LE32(msg->session_id);
     954          31 :         adv_id = WPA_GET_LE32(msg->adv_id);
     955             : 
     956          31 :         if (p2p->p2ps_prov->session_id != session_id) {
     957           0 :                 p2p_dbg(p2p,
     958             :                         "Ignore PD Response with unexpected Session ID");
     959           0 :                 return -1;
     960             :         }
     961             : 
     962          31 :         if (os_memcmp(p2p->p2ps_prov->session_mac, msg->session_mac,
     963             :                       ETH_ALEN)) {
     964           0 :                 p2p_dbg(p2p,
     965             :                         "Ignore PD Response with unexpected Session MAC");
     966           0 :                 return -1;
     967             :         }
     968             : 
     969          31 :         if (p2p->p2ps_prov->adv_id != adv_id) {
     970           0 :                 p2p_dbg(p2p,
     971             :                         "Ignore PD Response with unexpected Advertisement ID");
     972           0 :                 return -1;
     973             :         }
     974             : 
     975          31 :         if (os_memcmp(p2p->p2ps_prov->adv_mac, msg->adv_mac, ETH_ALEN) != 0) {
     976           0 :                 p2p_dbg(p2p,
     977             :                         "Ignore PD Response with unexpected Advertisement MAC");
     978           0 :                 return -1;
     979             :         }
     980             : 
     981          31 :         if (msg->listen_channel) {
     982           0 :                 p2p_dbg(p2p,
     983             :                         "Ignore malformed PD Response - unexpected Listen Channel");
     984           0 :                 return -1;
     985             :         }
     986             : 
     987          55 :         if (*msg->status == P2P_SC_SUCCESS &&
     988          24 :             !(!!msg->conn_cap ^ !!msg->persistent_dev)) {
     989           0 :                 p2p_dbg(p2p,
     990             :                         "Ignore malformed PD Response - either conn_cap or persistent group should be present");
     991           0 :                 return -1;
     992             :         }
     993             : 
     994          31 :         if (msg->persistent_dev && *msg->status != P2P_SC_SUCCESS) {
     995           0 :                 p2p_dbg(p2p,
     996             :                         "Ignore malformed PD Response - persistent group is present, but the status isn't success");
     997           0 :                 return -1;
     998             :         }
     999             : 
    1000          31 :         if (msg->conn_cap) {
    1001          23 :                 conn_cap_go = *msg->conn_cap == P2PS_SETUP_GROUP_OWNER;
    1002          23 :                 conn_cap_cli = *msg->conn_cap == P2PS_SETUP_CLIENT;
    1003             :         }
    1004             : 
    1005          31 :         P2PS_PD_RESP_CHECK(msg->persistent_dev || conn_cap_go || conn_cap_cli,
    1006             :                            channel_list);
    1007          31 :         P2PS_PD_RESP_CHECK(msg->persistent_dev || conn_cap_go || conn_cap_cli,
    1008             :                            config_timeout);
    1009             : 
    1010          31 :         P2PS_PD_RESP_CHECK(conn_cap_go, group_id);
    1011          31 :         P2PS_PD_RESP_CHECK(conn_cap_go, intended_addr);
    1012          31 :         P2PS_PD_RESP_CHECK(conn_cap_go, operating_channel);
    1013             :         /*
    1014             :          * TODO: Also validate that operating channel is present if the device
    1015             :          * is a GO in a persistent group. We can't do it here since we don't
    1016             :          * know what is the role of the peer. It should be probably done in
    1017             :          * p2ps_prov_complete callback, but currently operating channel isn't
    1018             :          * passed to it.
    1019             :          */
    1020             : 
    1021             : #undef P2PS_PD_RESP_CHECK
    1022             : 
    1023          31 :         return 0;
    1024             : }
    1025             : 
    1026             : 
    1027         104 : void p2p_process_prov_disc_resp(struct p2p_data *p2p, const u8 *sa,
    1028             :                                 const u8 *data, size_t len)
    1029             : {
    1030             :         struct p2p_message msg;
    1031             :         struct p2p_device *dev;
    1032         104 :         u16 report_config_methods = 0, req_config_methods;
    1033         104 :         u8 status = P2P_SC_SUCCESS;
    1034         104 :         u32 adv_id = 0;
    1035         104 :         u8 conncap = P2PS_SETUP_NEW;
    1036             :         u8 adv_mac[ETH_ALEN];
    1037             :         const u8 *group_mac;
    1038         104 :         int passwd_id = DEV_PW_DEFAULT;
    1039             :         int p2ps_seeker;
    1040             : 
    1041         104 :         if (p2p_parse(data, len, &msg))
    1042           6 :                 return;
    1043             : 
    1044         104 :         if (p2p->p2ps_prov && p2p_validate_p2ps_pd_resp(p2p, &msg)) {
    1045           0 :                 p2p_parse_free(&msg);
    1046           0 :                 return;
    1047             :         }
    1048             : 
    1049             :         /* Parse the P2PS members present */
    1050         104 :         if (msg.status)
    1051          34 :                 status = *msg.status;
    1052             : 
    1053         104 :         group_mac = msg.intended_addr;
    1054             : 
    1055         104 :         if (msg.adv_mac)
    1056          33 :                 os_memcpy(adv_mac, msg.adv_mac, ETH_ALEN);
    1057             :         else
    1058          71 :                 os_memset(adv_mac, 0, ETH_ALEN);
    1059             : 
    1060         104 :         if (msg.adv_id)
    1061          33 :                 adv_id = WPA_GET_LE32(msg.adv_id);
    1062             : 
    1063         104 :         if (msg.conn_cap) {
    1064          25 :                 conncap = *msg.conn_cap;
    1065             : 
    1066             :                 /* Switch bits to local relative */
    1067          25 :                 switch (conncap) {
    1068             :                 case P2PS_SETUP_GROUP_OWNER:
    1069           5 :                         conncap = P2PS_SETUP_CLIENT;
    1070           5 :                         break;
    1071             :                 case P2PS_SETUP_CLIENT:
    1072           9 :                         conncap = P2PS_SETUP_GROUP_OWNER;
    1073           9 :                         break;
    1074             :                 }
    1075             :         }
    1076             : 
    1077         728 :         p2p_dbg(p2p, "Received Provision Discovery Response from " MACSTR
    1078             :                 " with config methods 0x%x",
    1079         728 :                 MAC2STR(sa), msg.wps_config_methods);
    1080             : 
    1081         104 :         dev = p2p_get_device(p2p, sa);
    1082         104 :         if (dev == NULL || !dev->req_config_methods) {
    1083          18 :                 p2p_dbg(p2p, "Ignore Provision Discovery Response from " MACSTR
    1084          18 :                         " with no pending request", MAC2STR(sa));
    1085           3 :                 p2p_parse_free(&msg);
    1086           3 :                 return;
    1087             :         }
    1088             : 
    1089         101 :         if (dev->dialog_token != msg.dialog_token) {
    1090           2 :                 p2p_dbg(p2p, "Ignore Provision Discovery Response with unexpected Dialog Token %u (expected %u)",
    1091           2 :                         msg.dialog_token, dev->dialog_token);
    1092           1 :                 p2p_parse_free(&msg);
    1093           1 :                 return;
    1094             :         }
    1095             : 
    1096         100 :         if (p2p->pending_action_state == P2P_PENDING_PD) {
    1097          96 :                 os_memset(p2p->pending_pd_devaddr, 0, ETH_ALEN);
    1098          96 :                 p2p->pending_action_state = P2P_NO_PENDING_ACTION;
    1099             :         }
    1100             : 
    1101         100 :         p2ps_seeker = p2p->p2ps_prov && p2p->p2ps_prov->pd_seeker;
    1102             : 
    1103             :         /*
    1104             :          * Use a local copy of the requested config methods since
    1105             :          * p2p_reset_pending_pd() can clear this in the peer entry.
    1106             :          */
    1107         100 :         req_config_methods = dev->req_config_methods;
    1108             : 
    1109             :         /*
    1110             :          * If the response is from the peer to whom a user initiated request
    1111             :          * was sent earlier, we reset that state info here.
    1112             :          */
    1113         196 :         if (p2p->user_initiated_pd &&
    1114          96 :             os_memcmp(p2p->pending_pd_devaddr, sa, ETH_ALEN) == 0)
    1115           0 :                 p2p_reset_pending_pd(p2p);
    1116             : 
    1117         100 :         if (msg.wps_config_methods != req_config_methods) {
    1118           4 :                 p2p_dbg(p2p, "Peer rejected our Provision Discovery Request (received config_methods 0x%x expected 0x%x",
    1119           2 :                         msg.wps_config_methods, req_config_methods);
    1120           2 :                 if (p2p->cfg->prov_disc_fail)
    1121           2 :                         p2p->cfg->prov_disc_fail(p2p->cfg->cb_ctx, sa,
    1122             :                                                  P2P_PROV_DISC_REJECTED,
    1123             :                                                  adv_id, adv_mac, NULL);
    1124           2 :                 p2p_parse_free(&msg);
    1125           2 :                 p2ps_prov_free(p2p);
    1126           2 :                 goto out;
    1127             :         }
    1128             : 
    1129          98 :         report_config_methods = req_config_methods;
    1130          98 :         dev->flags &= ~(P2P_DEV_PD_PEER_DISPLAY |
    1131             :                         P2P_DEV_PD_PEER_KEYPAD |
    1132             :                         P2P_DEV_PD_PEER_P2PS);
    1133          98 :         if (req_config_methods & WPS_CONFIG_DISPLAY) {
    1134         414 :                 p2p_dbg(p2p, "Peer " MACSTR
    1135         414 :                         " accepted to show a PIN on display", MAC2STR(sa));
    1136          69 :                 dev->flags |= P2P_DEV_PD_PEER_DISPLAY;
    1137          69 :                 passwd_id = DEV_PW_REGISTRAR_SPECIFIED;
    1138          29 :         } else if (msg.wps_config_methods & WPS_CONFIG_KEYPAD) {
    1139          54 :                 p2p_dbg(p2p, "Peer " MACSTR
    1140             :                         " accepted to write our PIN using keypad",
    1141          54 :                         MAC2STR(sa));
    1142           9 :                 dev->flags |= P2P_DEV_PD_PEER_KEYPAD;
    1143           9 :                 passwd_id = DEV_PW_USER_SPECIFIED;
    1144          20 :         } else if (msg.wps_config_methods & WPS_CONFIG_P2PS) {
    1145          72 :                 p2p_dbg(p2p, "Peer " MACSTR " accepted P2PS PIN",
    1146          72 :                         MAC2STR(sa));
    1147          12 :                 dev->flags |= P2P_DEV_PD_PEER_P2PS;
    1148          12 :                 passwd_id = DEV_PW_P2PS_DEFAULT;
    1149             :         }
    1150             : 
    1151          98 :         if ((msg.conn_cap || msg.persistent_dev) &&
    1152          24 :             (status == P2P_SC_SUCCESS || status == P2P_SC_SUCCESS_DEFERRED) &&
    1153          24 :             p2p->p2ps_prov) {
    1154          24 :                 if (p2p->cfg->p2ps_prov_complete) {
    1155          96 :                         p2p->cfg->p2ps_prov_complete(
    1156          24 :                                 p2p->cfg->cb_ctx, status, sa, adv_mac,
    1157          24 :                                 p2p->p2ps_prov->session_mac,
    1158          24 :                                 group_mac, adv_id, p2p->p2ps_prov->session_id,
    1159             :                                 conncap, passwd_id, msg.persistent_ssid,
    1160             :                                 msg.persistent_ssid_len, 1, 0, NULL,
    1161             :                                 msg.feature_cap, msg.feature_cap_len);
    1162             :                 }
    1163          24 :                 p2ps_prov_free(p2p);
    1164          74 :         } else if (status != P2P_SC_SUCCESS &&
    1165           0 :                    status != P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE &&
    1166           0 :                    status != P2P_SC_SUCCESS_DEFERRED && p2p->p2ps_prov) {
    1167           0 :                 if (p2p->cfg->p2ps_prov_complete)
    1168           0 :                         p2p->cfg->p2ps_prov_complete(
    1169           0 :                                 p2p->cfg->cb_ctx, status, sa, adv_mac,
    1170           0 :                                 p2p->p2ps_prov->session_mac,
    1171           0 :                                 group_mac, adv_id, p2p->p2ps_prov->session_id,
    1172             :                                 0, 0, NULL, 0, 1, 0, NULL, NULL, 0);
    1173           0 :                 p2ps_prov_free(p2p);
    1174             :         }
    1175             : 
    1176          98 :         if (status == P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE) {
    1177           7 :                 if (p2p->cfg->remove_stale_groups) {
    1178          14 :                         p2p->cfg->remove_stale_groups(p2p->cfg->cb_ctx,
    1179           7 :                                                       dev->info.p2p_device_addr,
    1180             :                                                       NULL, NULL, 0);
    1181             :                 }
    1182             : 
    1183           7 :                 if (msg.session_info && msg.session_info_len) {
    1184           0 :                         size_t info_len = msg.session_info_len;
    1185           0 :                         char *deferred_sess_resp = os_malloc(2 * info_len + 1);
    1186             : 
    1187           0 :                         if (!deferred_sess_resp) {
    1188           0 :                                 p2p_parse_free(&msg);
    1189           0 :                                 p2ps_prov_free(p2p);
    1190           0 :                                 goto out;
    1191             :                         }
    1192           0 :                         utf8_escape((char *) msg.session_info, info_len,
    1193           0 :                                     deferred_sess_resp, 2 * info_len + 1);
    1194             : 
    1195           0 :                         if (p2p->cfg->prov_disc_fail)
    1196           0 :                                 p2p->cfg->prov_disc_fail(
    1197           0 :                                         p2p->cfg->cb_ctx, sa,
    1198             :                                         P2P_PROV_DISC_INFO_UNAVAILABLE,
    1199             :                                         adv_id, adv_mac,
    1200             :                                         deferred_sess_resp);
    1201           0 :                         os_free(deferred_sess_resp);
    1202             :                 } else
    1203           7 :                         if (p2p->cfg->prov_disc_fail)
    1204          14 :                                 p2p->cfg->prov_disc_fail(
    1205           7 :                                         p2p->cfg->cb_ctx, sa,
    1206             :                                         P2P_PROV_DISC_INFO_UNAVAILABLE,
    1207             :                                         adv_id, adv_mac, NULL);
    1208          91 :         } else if (status != P2P_SC_SUCCESS) {
    1209           0 :                 p2p_dbg(p2p, "Peer rejected our Provision Discovery Request");
    1210           0 :                 if (p2p->cfg->prov_disc_fail)
    1211           0 :                         p2p->cfg->prov_disc_fail(p2p->cfg->cb_ctx, sa,
    1212             :                                                  P2P_PROV_DISC_REJECTED,
    1213             :                                                  adv_id, adv_mac, NULL);
    1214           0 :                 p2p_parse_free(&msg);
    1215           0 :                 p2ps_prov_free(p2p);
    1216           0 :                 goto out;
    1217             :         }
    1218             : 
    1219             :         /* Store the provisioning info */
    1220          98 :         dev->wps_prov_info = msg.wps_config_methods;
    1221          98 :         if (msg.intended_addr)
    1222           6 :                 os_memcpy(dev->interface_addr, msg.intended_addr, ETH_ALEN);
    1223             : 
    1224          98 :         p2p_parse_free(&msg);
    1225             : 
    1226             : out:
    1227         100 :         dev->req_config_methods = 0;
    1228         100 :         p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
    1229         100 :         if (dev->flags & P2P_DEV_PD_BEFORE_GO_NEG) {
    1230          12 :                 p2p_dbg(p2p, "Start GO Neg after the PD-before-GO-Neg workaround with "
    1231          12 :                         MACSTR, MAC2STR(dev->info.p2p_device_addr));
    1232           2 :                 dev->flags &= ~P2P_DEV_PD_BEFORE_GO_NEG;
    1233           2 :                 p2p_connect_send(p2p, dev);
    1234           2 :                 return;
    1235             :         }
    1236             : 
    1237             :         /*
    1238             :          * prov_disc_resp callback is used to generate P2P-PROV-DISC-ENTER-PIN,
    1239             :          * P2P-PROV-DISC-SHOW-PIN, and P2P-PROV-DISC-PBC-REQ events.
    1240             :          * Call it only for a legacy P2P PD or for P2PS PD scenarios where
    1241             :          * show/enter PIN events are needed.
    1242             :          *
    1243             :          * The callback is called in the following cases:
    1244             :          * 1. Legacy P2P PD response with a status SUCCESS
    1245             :          * 2. P2PS, advertiser method: DISPLAY, autoaccept: true,
    1246             :          *    response status: SUCCESS, local method KEYPAD
    1247             :          * 3. P2PS, advertiser method: KEYPAD,Seeker side,
    1248             :          *    response status: INFO_CURRENTLY_UNAVAILABLE,
    1249             :          *    local method: DISPLAY
    1250             :          */
    1251          98 :         if (p2p->cfg->prov_disc_resp &&
    1252          90 :             ((status == P2P_SC_SUCCESS && !adv_id) ||
    1253          24 :              (p2ps_seeker && status == P2P_SC_SUCCESS &&
    1254          25 :               passwd_id == DEV_PW_REGISTRAR_SPECIFIED) ||
    1255          17 :              (p2ps_seeker &&
    1256           7 :               status == P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE &&
    1257             :               passwd_id == DEV_PW_USER_SPECIFIED)))
    1258          75 :                 p2p->cfg->prov_disc_resp(p2p->cfg->cb_ctx, sa,
    1259             :                                          report_config_methods);
    1260             : 
    1261          98 :         if (p2p->state == P2P_PD_DURING_FIND) {
    1262          19 :                 p2p_clear_timeout(p2p);
    1263          19 :                 p2p_continue_find(p2p);
    1264             :         }
    1265             : }
    1266             : 
    1267             : 
    1268         230 : int p2p_send_prov_disc_req(struct p2p_data *p2p, struct p2p_device *dev,
    1269             :                            int join, int force_freq)
    1270             : {
    1271             :         struct wpabuf *req;
    1272             :         int freq;
    1273             : 
    1274         230 :         if (force_freq > 0)
    1275          57 :                 freq = force_freq;
    1276             :         else
    1277         173 :                 freq = dev->listen_freq > 0 ? dev->listen_freq :
    1278             :                         dev->oper_freq;
    1279         230 :         if (freq <= 0) {
    1280           6 :                 p2p_dbg(p2p, "No Listen/Operating frequency known for the peer "
    1281             :                         MACSTR " to send Provision Discovery Request",
    1282           6 :                         MAC2STR(dev->info.p2p_device_addr));
    1283           1 :                 return -1;
    1284             :         }
    1285             : 
    1286         229 :         if (dev->flags & P2P_DEV_GROUP_CLIENT_ONLY) {
    1287           0 :                 if (!(dev->info.dev_capab &
    1288             :                       P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY)) {
    1289           0 :                         p2p_dbg(p2p, "Cannot use PD with P2P Device " MACSTR
    1290             :                                 " that is in a group and is not discoverable",
    1291           0 :                                 MAC2STR(dev->info.p2p_device_addr));
    1292           0 :                         return -1;
    1293             :                 }
    1294             :                 /* TODO: use device discoverability request through GO */
    1295             :         }
    1296             : 
    1297         229 :         if (p2p->p2ps_prov) {
    1298          37 :                 if (p2p->p2ps_prov->status == P2P_SC_SUCCESS_DEFERRED) {
    1299          13 :                         if (p2p->p2ps_prov->method == WPS_CONFIG_DISPLAY)
    1300           7 :                                 dev->req_config_methods = WPS_CONFIG_KEYPAD;
    1301           6 :                         else if (p2p->p2ps_prov->method == WPS_CONFIG_KEYPAD)
    1302           2 :                                 dev->req_config_methods = WPS_CONFIG_DISPLAY;
    1303             :                         else
    1304           4 :                                 dev->req_config_methods = WPS_CONFIG_P2PS;
    1305             :                 } else {
    1306             :                         /* Order of preference, based on peer's capabilities */
    1307          24 :                         if (p2p->p2ps_prov->method)
    1308          24 :                                 dev->req_config_methods =
    1309          24 :                                         p2p->p2ps_prov->method;
    1310           0 :                         else if (dev->info.config_methods & WPS_CONFIG_P2PS)
    1311           0 :                                 dev->req_config_methods = WPS_CONFIG_P2PS;
    1312           0 :                         else if (dev->info.config_methods & WPS_CONFIG_DISPLAY)
    1313           0 :                                 dev->req_config_methods = WPS_CONFIG_DISPLAY;
    1314             :                         else
    1315           0 :                                 dev->req_config_methods = WPS_CONFIG_KEYPAD;
    1316             :                 }
    1317         111 :                 p2p_dbg(p2p,
    1318             :                         "Building PD Request based on P2PS config method 0x%x status %d --> req_config_methods 0x%x",
    1319          74 :                         p2p->p2ps_prov->method, p2p->p2ps_prov->status,
    1320          37 :                         dev->req_config_methods);
    1321             :         }
    1322             : 
    1323         229 :         req = p2p_build_prov_disc_req(p2p, dev, join);
    1324         229 :         if (req == NULL)
    1325           0 :                 return -1;
    1326             : 
    1327         229 :         if (p2p->state != P2P_IDLE)
    1328          43 :                 p2p_stop_listen_for_freq(p2p, freq);
    1329         229 :         p2p->pending_action_state = P2P_PENDING_PD;
    1330         458 :         if (p2p_send_action(p2p, freq, dev->info.p2p_device_addr,
    1331         229 :                             p2p->cfg->dev_addr, dev->info.p2p_device_addr,
    1332         229 :                             wpabuf_head(req), wpabuf_len(req), 200) < 0) {
    1333           0 :                 p2p_dbg(p2p, "Failed to send Action frame");
    1334           0 :                 wpabuf_free(req);
    1335           0 :                 return -1;
    1336             :         }
    1337             : 
    1338         229 :         os_memcpy(p2p->pending_pd_devaddr, dev->info.p2p_device_addr, ETH_ALEN);
    1339             : 
    1340         229 :         wpabuf_free(req);
    1341         229 :         return 0;
    1342             : }
    1343             : 
    1344             : 
    1345         110 : int p2p_prov_disc_req(struct p2p_data *p2p, const u8 *peer_addr,
    1346             :                       struct p2ps_provision *p2ps_prov,
    1347             :                       u16 config_methods, int join, int force_freq,
    1348             :                       int user_initiated_pd)
    1349             : {
    1350             :         struct p2p_device *dev;
    1351             : 
    1352         110 :         dev = p2p_get_device(p2p, peer_addr);
    1353         110 :         if (dev == NULL)
    1354           6 :                 dev = p2p_get_device_interface(p2p, peer_addr);
    1355         110 :         if (dev == NULL || (dev->flags & P2P_DEV_PROBE_REQ_ONLY)) {
    1356          36 :                 p2p_dbg(p2p, "Provision Discovery Request destination " MACSTR
    1357          36 :                         " not yet known", MAC2STR(peer_addr));
    1358           6 :                 os_free(p2ps_prov);
    1359           6 :                 return -1;
    1360             :         }
    1361             : 
    1362         728 :         p2p_dbg(p2p, "Provision Discovery Request with " MACSTR
    1363             :                 " (config methods 0x%x)",
    1364         624 :                 MAC2STR(peer_addr), config_methods);
    1365         104 :         if (config_methods == 0 && !p2ps_prov) {
    1366           0 :                 os_free(p2ps_prov);
    1367           0 :                 return -1;
    1368             :         }
    1369             : 
    1370         111 :         if (p2ps_prov && p2ps_prov->status == P2P_SC_SUCCESS_DEFERRED &&
    1371           7 :             p2p->p2ps_prov) {
    1372             :                 /* Use cached method from deferred provisioning */
    1373           7 :                 p2ps_prov->method = p2p->p2ps_prov->method;
    1374             :         }
    1375             : 
    1376             :         /* Reset provisioning info */
    1377         104 :         dev->wps_prov_info = 0;
    1378         104 :         p2ps_prov_free(p2p);
    1379         104 :         p2p->p2ps_prov = p2ps_prov;
    1380             : 
    1381         104 :         dev->req_config_methods = config_methods;
    1382         104 :         if (join)
    1383          59 :                 dev->flags |= P2P_DEV_PD_FOR_JOIN;
    1384             :         else
    1385          45 :                 dev->flags &= ~P2P_DEV_PD_FOR_JOIN;
    1386             : 
    1387         114 :         if (p2p->state != P2P_IDLE && p2p->state != P2P_SEARCH &&
    1388          10 :             p2p->state != P2P_LISTEN_ONLY) {
    1389           0 :                 p2p_dbg(p2p, "Busy with other operations; postpone Provision Discovery Request with "
    1390             :                         MACSTR " (config methods 0x%x)",
    1391           0 :                         MAC2STR(peer_addr), config_methods);
    1392           0 :                 return 0;
    1393             :         }
    1394             : 
    1395         104 :         p2p->user_initiated_pd = user_initiated_pd;
    1396         104 :         p2p->pd_force_freq = force_freq;
    1397             : 
    1398         104 :         if (p2p->user_initiated_pd)
    1399         100 :                 p2p->pd_retries = MAX_PROV_DISC_REQ_RETRIES;
    1400             : 
    1401             :         /*
    1402             :          * Assign dialog token here to use the same value in each retry within
    1403             :          * the same PD exchange.
    1404             :          */
    1405         104 :         dev->dialog_token++;
    1406         104 :         if (dev->dialog_token == 0)
    1407           0 :                 dev->dialog_token = 1;
    1408             : 
    1409         104 :         return p2p_send_prov_disc_req(p2p, dev, join, force_freq);
    1410             : }
    1411             : 
    1412             : 
    1413           1 : void p2p_reset_pending_pd(struct p2p_data *p2p)
    1414             : {
    1415             :         struct p2p_device *dev;
    1416             : 
    1417           2 :         dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
    1418           1 :                 if (os_memcmp(p2p->pending_pd_devaddr,
    1419             :                               dev->info.p2p_device_addr, ETH_ALEN))
    1420           0 :                         continue;
    1421           1 :                 if (!dev->req_config_methods)
    1422           0 :                         continue;
    1423           1 :                 if (dev->flags & P2P_DEV_PD_FOR_JOIN)
    1424           0 :                         continue;
    1425             :                 /* Reset the config methods of the device */
    1426           1 :                 dev->req_config_methods = 0;
    1427             :         }
    1428             : 
    1429           1 :         p2p->user_initiated_pd = 0;
    1430           1 :         os_memset(p2p->pending_pd_devaddr, 0, ETH_ALEN);
    1431           1 :         p2p->pd_retries = 0;
    1432           1 :         p2p->pd_force_freq = 0;
    1433           1 : }
    1434             : 
    1435             : 
    1436         369 : void p2ps_prov_free(struct p2p_data *p2p)
    1437             : {
    1438         369 :         os_free(p2p->p2ps_prov);
    1439         369 :         p2p->p2ps_prov = NULL;
    1440         369 : }

Generated by: LCOV version 1.10