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

Generated by: LCOV version 1.10