LCOV - code coverage report
Current view: top level - wpa_supplicant/dbus - dbus_new_handlers_p2p.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1475438200 Lines: 1263 1480 85.3 %
Date: 2016-10-02 Functions: 65 65 100.0 %

          Line data    Source code
       1             : /*
       2             :  * WPA Supplicant / dbus-based control interface (P2P)
       3             :  * Copyright (c) 2011-2012, Intel Corporation
       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 "utils/includes.h"
      12             : #include "common.h"
      13             : #include "../config.h"
      14             : #include "../wpa_supplicant_i.h"
      15             : #include "../wps_supplicant.h"
      16             : #include "../notify.h"
      17             : #include "dbus_new_helpers.h"
      18             : #include "dbus_new.h"
      19             : #include "dbus_new_handlers.h"
      20             : #include "dbus_new_handlers_p2p.h"
      21             : #include "dbus_dict_helpers.h"
      22             : #include "p2p/p2p.h"
      23             : #include "common/ieee802_11_defs.h"
      24             : #include "ap/hostapd.h"
      25             : #include "ap/ap_config.h"
      26             : #include "ap/wps_hostapd.h"
      27             : 
      28             : #include "../p2p_supplicant.h"
      29             : #include "../wifi_display.h"
      30             : 
      31             : /**
      32             :  * Parses out the mac address from the peer object path.
      33             :  * @peer_path - object path of the form
      34             :  *      /fi/w1/wpa_supplicant1/Interfaces/n/Peers/00112233445566 (no colons)
      35             :  * @addr - out param must be of ETH_ALEN size
      36             :  * Returns 0 if valid (including MAC), -1 otherwise
      37             :  */
      38          31 : static int parse_peer_object_path(const char *peer_path, u8 addr[ETH_ALEN])
      39             : {
      40             :         const char *p;
      41             : 
      42          31 :         if (!peer_path)
      43           1 :                 return -1;
      44          30 :         p = os_strrchr(peer_path, '/');
      45          30 :         if (!p)
      46           0 :                 return -1;
      47          30 :         p++;
      48          30 :         return hwaddr_compact_aton(p, addr);
      49             : }
      50             : 
      51             : 
      52             : /**
      53             :  * wpas_dbus_error_persistent_group_unknown - Return a new PersistentGroupUnknown
      54             :  * error message
      55             :  * @message: Pointer to incoming dbus message this error refers to
      56             :  * Returns: a dbus error message
      57             :  *
      58             :  * Convenience function to create and return an invalid persistent group error.
      59             :  */
      60             : static DBusMessage *
      61           1 : wpas_dbus_error_persistent_group_unknown(DBusMessage *message)
      62             : {
      63           1 :         return dbus_message_new_error(
      64             :                 message, WPAS_DBUS_ERROR_NETWORK_UNKNOWN,
      65             :                 "There is no such persistent group in this P2P device.");
      66             : }
      67             : 
      68             : 
      69          33 : DBusMessage * wpas_dbus_handler_p2p_find(DBusMessage *message,
      70             :                                          struct wpa_supplicant *wpa_s)
      71             : {
      72             :         struct wpa_dbus_dict_entry entry;
      73          33 :         DBusMessage *reply = NULL;
      74             :         DBusMessageIter iter;
      75             :         DBusMessageIter iter_dict;
      76          33 :         unsigned int timeout = 0;
      77          33 :         enum p2p_discovery_type type = P2P_FIND_START_WITH_FULL;
      78          33 :         int num_req_dev_types = 0;
      79             :         unsigned int i;
      80          33 :         u8 *req_dev_types = NULL;
      81             : 
      82          33 :         dbus_message_iter_init(message, &iter);
      83          33 :         entry.key = NULL;
      84             : 
      85          33 :         if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
      86           0 :                 goto error;
      87             : 
      88          80 :         while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
      89          37 :                 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
      90          10 :                         goto error;
      91             : 
      92          30 :                 if (os_strcmp(entry.key, "Timeout") == 0 &&
      93           3 :                     entry.type == DBUS_TYPE_INT32) {
      94           3 :                         timeout = entry.uint32_value;
      95          24 :                 } else if (os_strcmp(entry.key, "RequestedDeviceTypes") == 0) {
      96          11 :                         if (entry.type != DBUS_TYPE_ARRAY ||
      97           5 :                             entry.array_type != WPAS_DBUS_TYPE_BINARRAY)
      98             :                                 goto error_clear;
      99             : 
     100           2 :                         os_free(req_dev_types);
     101           2 :                         req_dev_types =
     102           2 :                                 os_malloc(WPS_DEV_TYPE_LEN * entry.array_len);
     103           2 :                         if (!req_dev_types)
     104           0 :                                 goto error_clear;
     105             : 
     106           4 :                         for (i = 0; i < entry.array_len; i++) {
     107           3 :                                 if (wpabuf_len(entry.binarray_value[i]) !=
     108             :                                     WPS_DEV_TYPE_LEN)
     109           1 :                                         goto error_clear;
     110           2 :                                 os_memcpy(req_dev_types + i * WPS_DEV_TYPE_LEN,
     111             :                                           wpabuf_head(entry.binarray_value[i]),
     112             :                                           WPS_DEV_TYPE_LEN);
     113             :                         }
     114           1 :                         num_req_dev_types = entry.array_len;
     115          29 :                 } else if (os_strcmp(entry.key, "DiscoveryType") == 0 &&
     116          11 :                            entry.type == DBUS_TYPE_STRING) {
     117          11 :                         if (os_strcmp(entry.str_value, "start_with_full") == 0)
     118           0 :                                 type = P2P_FIND_START_WITH_FULL;
     119          11 :                         else if (os_strcmp(entry.str_value, "social") == 0)
     120          10 :                                 type = P2P_FIND_ONLY_SOCIAL;
     121           1 :                         else if (os_strcmp(entry.str_value, "progressive") == 0)
     122           0 :                                 type = P2P_FIND_PROGRESSIVE;
     123             :                         else
     124           1 :                                 goto error_clear;
     125             :                 } else
     126             :                         goto error_clear;
     127          14 :                 wpa_dbus_dict_entry_clear(&entry);
     128             :         }
     129             : 
     130          10 :         wpa_s = wpa_s->global->p2p_init_wpa_s;
     131             : 
     132          10 :         wpas_p2p_find(wpa_s, timeout, type, num_req_dev_types, req_dev_types,
     133             :                       NULL, 0, 0, NULL, 0);
     134          10 :         os_free(req_dev_types);
     135          10 :         return reply;
     136             : 
     137             : error_clear:
     138          13 :         wpa_dbus_dict_entry_clear(&entry);
     139             : error:
     140          23 :         os_free(req_dev_types);
     141          23 :         reply = wpas_dbus_error_invalid_args(message, entry.key);
     142          23 :         return reply;
     143             : }
     144             : 
     145             : 
     146           6 : DBusMessage * wpas_dbus_handler_p2p_stop_find(DBusMessage *message,
     147             :                                               struct wpa_supplicant *wpa_s)
     148             : {
     149           6 :         wpas_p2p_stop_find(wpa_s->global->p2p_init_wpa_s);
     150           6 :         return NULL;
     151             : }
     152             : 
     153             : 
     154           4 : DBusMessage * wpas_dbus_handler_p2p_rejectpeer(DBusMessage *message,
     155             :                                                struct wpa_supplicant *wpa_s)
     156             : {
     157             :         DBusMessageIter iter;
     158           4 :         char *peer_object_path = NULL;
     159             :         u8 peer_addr[ETH_ALEN];
     160             : 
     161           4 :         dbus_message_iter_init(message, &iter);
     162           4 :         dbus_message_iter_get_basic(&iter, &peer_object_path);
     163             : 
     164           4 :         if (parse_peer_object_path(peer_object_path, peer_addr) < 0)
     165           1 :                 return wpas_dbus_error_invalid_args(message, NULL);
     166             : 
     167           3 :         wpa_s = wpa_s->global->p2p_init_wpa_s;
     168             : 
     169           3 :         if (wpas_p2p_reject(wpa_s, peer_addr) < 0)
     170           2 :                 return wpas_dbus_error_unknown_error(message,
     171             :                                 "Failed to call wpas_p2p_reject method.");
     172             : 
     173           1 :         return NULL;
     174             : }
     175             : 
     176             : 
     177           6 : DBusMessage * wpas_dbus_handler_p2p_listen(DBusMessage *message,
     178             :                                            struct wpa_supplicant *wpa_s)
     179             : {
     180           6 :         dbus_int32_t timeout = 0;
     181             : 
     182           6 :         if (!dbus_message_get_args(message, NULL, DBUS_TYPE_INT32, &timeout,
     183             :                                    DBUS_TYPE_INVALID))
     184           0 :                 return wpas_dbus_error_no_memory(message);
     185             : 
     186           6 :         wpa_s = wpa_s->global->p2p_init_wpa_s;
     187             : 
     188           6 :         if (wpas_p2p_listen(wpa_s, (unsigned int) timeout)) {
     189           1 :                 return dbus_message_new_error(message,
     190             :                                               WPAS_DBUS_ERROR_UNKNOWN_ERROR,
     191             :                                               "Could not start P2P listen");
     192             :         }
     193             : 
     194           5 :         return NULL;
     195             : }
     196             : 
     197             : 
     198           4 : DBusMessage * wpas_dbus_handler_p2p_extendedlisten(
     199             :         DBusMessage *message, struct wpa_supplicant *wpa_s)
     200             : {
     201           4 :         unsigned int period = 0, interval = 0;
     202             :         struct wpa_dbus_dict_entry entry;
     203             :         DBusMessageIter iter;
     204             :         DBusMessageIter iter_dict;
     205             : 
     206           4 :         dbus_message_iter_init(message, &iter);
     207           4 :         entry.key = NULL;
     208             : 
     209           4 :         if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
     210           0 :                 goto error;
     211             : 
     212          10 :         while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
     213           3 :                 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
     214           0 :                         goto error;
     215             : 
     216           4 :                 if (os_strcmp(entry.key, "period") == 0 &&
     217           1 :                     entry.type == DBUS_TYPE_INT32)
     218           1 :                         period = entry.uint32_value;
     219           3 :                 else if (os_strcmp(entry.key, "interval") == 0 &&
     220           1 :                          entry.type == DBUS_TYPE_INT32)
     221           1 :                         interval = entry.uint32_value;
     222             :                 else
     223             :                         goto error_clear;
     224           2 :                 wpa_dbus_dict_entry_clear(&entry);
     225             :         }
     226             : 
     227           3 :         wpa_s = wpa_s->global->p2p_init_wpa_s;
     228             : 
     229           3 :         if (wpas_p2p_ext_listen(wpa_s, period, interval))
     230           1 :                 return wpas_dbus_error_unknown_error(
     231             :                         message, "failed to initiate a p2p_ext_listen.");
     232             : 
     233           2 :         return NULL;
     234             : 
     235             : error_clear:
     236           1 :         wpa_dbus_dict_entry_clear(&entry);
     237             : error:
     238           1 :         return wpas_dbus_error_invalid_args(message, entry.key);
     239             : }
     240             : 
     241             : 
     242           2 : DBusMessage * wpas_dbus_handler_p2p_presence_request(
     243             :         DBusMessage *message, struct wpa_supplicant *wpa_s)
     244             : {
     245           2 :         unsigned int dur1 = 0, int1 = 0, dur2 = 0, int2 = 0;
     246             :         struct wpa_dbus_dict_entry entry;
     247             :         DBusMessageIter iter;
     248             :         DBusMessageIter iter_dict;
     249             : 
     250           2 :         dbus_message_iter_init(message, &iter);
     251           2 :         entry.key = NULL;
     252             : 
     253           2 :         if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
     254           0 :                 goto error;
     255             : 
     256          12 :         while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
     257           8 :                 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
     258           0 :                         goto error;
     259             : 
     260          10 :                 if (os_strcmp(entry.key, "duration1") == 0 &&
     261           2 :                     entry.type == DBUS_TYPE_INT32)
     262           2 :                         dur1 = entry.uint32_value;
     263           8 :                 else if (os_strcmp(entry.key, "interval1") == 0 &&
     264           2 :                          entry.type == DBUS_TYPE_INT32)
     265           2 :                         int1 = entry.uint32_value;
     266           6 :                 else if (os_strcmp(entry.key, "duration2") == 0 &&
     267           2 :                          entry.type == DBUS_TYPE_INT32)
     268           2 :                         dur2 = entry.uint32_value;
     269           4 :                 else if (os_strcmp(entry.key, "interval2") == 0 &&
     270           2 :                          entry.type == DBUS_TYPE_INT32)
     271           2 :                         int2 = entry.uint32_value;
     272             :                 else
     273             :                         goto error_clear;
     274             : 
     275           8 :                 wpa_dbus_dict_entry_clear(&entry);
     276             :         }
     277             : 
     278           2 :         if (wpas_p2p_presence_req(wpa_s, dur1, int1, dur2, int2) < 0)
     279           1 :                 return wpas_dbus_error_unknown_error(message,
     280             :                                 "Failed to invoke presence request.");
     281             : 
     282           1 :         return NULL;
     283             : 
     284             : error_clear:
     285           0 :         wpa_dbus_dict_entry_clear(&entry);
     286             : error:
     287           0 :         return wpas_dbus_error_invalid_args(message, entry.key);
     288             : }
     289             : 
     290             : 
     291          11 : DBusMessage * wpas_dbus_handler_p2p_group_add(DBusMessage *message,
     292             :                                               struct wpa_supplicant *wpa_s)
     293             : {
     294             :         DBusMessageIter iter_dict;
     295          11 :         DBusMessage *reply = NULL;
     296             :         DBusMessageIter iter;
     297             :         struct wpa_dbus_dict_entry entry;
     298          11 :         char *pg_object_path = NULL;
     299          11 :         int persistent_group = 0;
     300          11 :         int freq = 0;
     301          11 :         char *iface = NULL;
     302          11 :         unsigned int group_id = 0;
     303             :         struct wpa_ssid *ssid;
     304             : 
     305          11 :         dbus_message_iter_init(message, &iter);
     306             : 
     307          11 :         if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
     308           0 :                 goto inv_args;
     309             : 
     310          37 :         while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
     311          16 :                 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
     312           0 :                         goto inv_args;
     313             : 
     314          19 :                 if (os_strcmp(entry.key, "persistent") == 0 &&
     315           3 :                     entry.type == DBUS_TYPE_BOOLEAN) {
     316           3 :                         persistent_group = entry.bool_value;
     317          24 :                 } else if (os_strcmp(entry.key, "frequency") == 0 &&
     318          11 :                            entry.type == DBUS_TYPE_INT32) {
     319          11 :                         freq = entry.int32_value;
     320          21 :                         if (freq <= 0)
     321           1 :                                 goto inv_args_clear;
     322           2 :                 } else if (os_strcmp(entry.key, "persistent_group_object") ==
     323           2 :                            0 &&
     324           2 :                            entry.type == DBUS_TYPE_OBJECT_PATH)
     325           2 :                         pg_object_path = os_strdup(entry.str_value);
     326             :                 else
     327             :                         goto inv_args_clear;
     328             : 
     329          15 :                 wpa_dbus_dict_entry_clear(&entry);
     330             :         }
     331             : 
     332          10 :         wpa_s = wpa_s->global->p2p_init_wpa_s;
     333             : 
     334          10 :         if (pg_object_path != NULL) {
     335             :                 char *net_id_str;
     336             : 
     337             :                 /*
     338             :                  * A persistent group Object Path is defined meaning we want
     339             :                  * to re-invoke a persistent group.
     340             :                  */
     341             : 
     342           2 :                 iface = wpas_dbus_new_decompose_object_path(
     343             :                         pg_object_path, WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART,
     344             :                         &net_id_str);
     345           3 :                 if (iface == NULL || net_id_str == NULL ||
     346           2 :                     !wpa_s->parent->dbus_new_path ||
     347           1 :                     os_strcmp(iface, wpa_s->parent->dbus_new_path) != 0) {
     348           1 :                         reply =
     349             :                             wpas_dbus_error_invalid_args(message,
     350             :                                                          pg_object_path);
     351           1 :                         goto out;
     352             :                 }
     353             : 
     354           1 :                 group_id = strtoul(net_id_str, NULL, 10);
     355           1 :                 if (errno == EINVAL) {
     356           0 :                         reply = wpas_dbus_error_invalid_args(
     357             :                                                 message, pg_object_path);
     358           0 :                         goto out;
     359             :                 }
     360             : 
     361             :                 /* Get the SSID structure from the persistent group id */
     362           1 :                 ssid = wpa_config_get_network(wpa_s->conf, group_id);
     363           1 :                 if (ssid == NULL || ssid->disabled != 2)
     364             :                         goto inv_args;
     365             : 
     366           1 :                 if (wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 0, 0, 0,
     367             :                                                   0, 0, NULL, 0, 0)) {
     368           0 :                         reply = wpas_dbus_error_unknown_error(
     369             :                                 message,
     370             :                                 "Failed to reinvoke a persistent group");
     371           0 :                         goto out;
     372             :                 }
     373           8 :         } else if (wpas_p2p_group_add(wpa_s, persistent_group, freq, 0, 0, 0,
     374             :                                       0))
     375           0 :                 goto inv_args;
     376             : 
     377             : out:
     378          11 :         os_free(pg_object_path);
     379          11 :         os_free(iface);
     380          22 :         return reply;
     381             : inv_args_clear:
     382           1 :         wpa_dbus_dict_entry_clear(&entry);
     383             : inv_args:
     384           1 :         reply = wpas_dbus_error_invalid_args(message, NULL);
     385           1 :         goto out;
     386             : }
     387             : 
     388             : 
     389          14 : DBusMessage * wpas_dbus_handler_p2p_disconnect(DBusMessage *message,
     390             :                                                struct wpa_supplicant *wpa_s)
     391             : {
     392          14 :         if (wpas_p2p_disconnect(wpa_s))
     393           1 :                 return wpas_dbus_error_unknown_error(message,
     394             :                                                 "failed to disconnect");
     395             : 
     396          13 :         return NULL;
     397             : }
     398             : 
     399             : 
     400        1556 : static dbus_bool_t wpa_dbus_p2p_check_enabled(struct wpa_supplicant *wpa_s,
     401             :                                               DBusMessage *message,
     402             :                                               DBusMessage **out_reply,
     403             :                                               DBusError *error)
     404             : {
     405             :         /* Return an error message or an error if P2P isn't available */
     406        1556 :         if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL) {
     407           6 :                 if (out_reply) {
     408           3 :                         *out_reply = dbus_message_new_error(
     409             :                                 message, DBUS_ERROR_FAILED,
     410             :                                 "P2P is not available for this interface");
     411             :                 }
     412           6 :                 dbus_set_error_const(error, DBUS_ERROR_FAILED,
     413             :                                      "P2P is not available for this interface");
     414           6 :                 return FALSE;
     415             :         }
     416        1550 :         return TRUE;
     417             : }
     418             : 
     419             : 
     420           6 : DBusMessage * wpas_dbus_handler_p2p_remove_client(DBusMessage *message,
     421             :                                                   struct wpa_supplicant *wpa_s)
     422             : {
     423             :         DBusMessageIter iter_dict;
     424           6 :         DBusMessage *reply = NULL;
     425             :         DBusMessageIter iter;
     426             :         struct wpa_dbus_dict_entry entry;
     427           6 :         char *peer_object_path = NULL;
     428           6 :         char *interface_addr = NULL;
     429             :         u8 peer_addr[ETH_ALEN];
     430             : 
     431           6 :         if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL))
     432           0 :                 return reply;
     433             : 
     434           6 :         dbus_message_iter_init(message, &iter);
     435             : 
     436           6 :         if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
     437           0 :                 goto err;
     438             : 
     439          14 :         while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
     440           5 :                 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
     441           0 :                         goto err;
     442             : 
     443           7 :                 if (os_strcmp(entry.key, "peer") == 0 &&
     444           2 :                     entry.type == DBUS_TYPE_OBJECT_PATH) {
     445           1 :                         os_free(peer_object_path);
     446           1 :                         peer_object_path = os_strdup(entry.str_value);
     447           1 :                         wpa_dbus_dict_entry_clear(&entry);
     448           6 :                 } else if (os_strcmp(entry.key, "iface") == 0 &&
     449           2 :                            entry.type == DBUS_TYPE_STRING) {
     450           1 :                         os_free(interface_addr);
     451           1 :                         interface_addr = os_strdup(entry.str_value);
     452           1 :                         wpa_dbus_dict_entry_clear(&entry);
     453             :                 } else {
     454           3 :                         wpa_dbus_dict_entry_clear(&entry);
     455           3 :                         goto err;
     456             :                 }
     457             :         }
     458             : 
     459           3 :         if ((!peer_object_path && !interface_addr) ||
     460           1 :             (peer_object_path &&
     461           2 :              (parse_peer_object_path(peer_object_path, peer_addr) < 0 ||
     462           3 :               !p2p_peer_known(wpa_s->global->p2p, peer_addr))) ||
     463           1 :             (interface_addr && hwaddr_aton(interface_addr, peer_addr) < 0))
     464             :                 goto err;
     465             : 
     466           1 :         wpas_p2p_remove_client(wpa_s, peer_addr, interface_addr != NULL);
     467           1 :         reply = NULL;
     468             : out:
     469           6 :         os_free(peer_object_path);
     470           6 :         os_free(interface_addr);
     471           6 :         return reply;
     472             : err:
     473           5 :         reply = wpas_dbus_error_invalid_args(message, "Invalid address format");
     474           5 :         goto out;
     475             : }
     476             : 
     477             : 
     478           2 : DBusMessage * wpas_dbus_handler_p2p_flush(DBusMessage *message,
     479             :                                           struct wpa_supplicant *wpa_s)
     480             : {
     481           2 :         DBusMessage *reply = NULL;
     482             : 
     483           2 :         if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL))
     484           1 :                 return reply;
     485             : 
     486           1 :         wpa_s = wpa_s->global->p2p_init_wpa_s;
     487             : 
     488           1 :         os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
     489           1 :         wpa_s->force_long_sd = 0;
     490           1 :         p2p_flush(wpa_s->global->p2p);
     491             : 
     492           1 :         return NULL;
     493             : }
     494             : 
     495             : 
     496          15 : DBusMessage * wpas_dbus_handler_p2p_connect(DBusMessage *message,
     497             :                                             struct wpa_supplicant *wpa_s)
     498             : {
     499             :         DBusMessageIter iter_dict;
     500          15 :         DBusMessage *reply = NULL;
     501             :         DBusMessageIter iter;
     502             :         struct wpa_dbus_dict_entry entry;
     503          15 :         char *peer_object_path = NULL;
     504          15 :         int persistent_group = 0;
     505          15 :         int join = 0;
     506          15 :         int authorize_only = 0;
     507          15 :         int go_intent = -1;
     508          15 :         int freq = 0;
     509             :         u8 addr[ETH_ALEN];
     510          15 :         char *pin = NULL;
     511          15 :         enum p2p_wps_method wps_method = WPS_NOT_READY;
     512             :         int new_pin;
     513          15 :         char *err_msg = NULL;
     514          15 :         char *iface = NULL;
     515             : 
     516          15 :         if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL))
     517           1 :                 return reply;
     518             : 
     519          14 :         dbus_message_iter_init(message, &iter);
     520             : 
     521          14 :         if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
     522           0 :                 goto inv_args;
     523             : 
     524          78 :         while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
     525          52 :                 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
     526           0 :                         goto inv_args;
     527             : 
     528          63 :                 if (os_strcmp(entry.key, "peer") == 0 &&
     529          11 :                     entry.type == DBUS_TYPE_OBJECT_PATH) {
     530          11 :                         peer_object_path = os_strdup(entry.str_value);
     531          43 :                 } else if (os_strcmp(entry.key, "persistent") == 0 &&
     532           2 :                            entry.type == DBUS_TYPE_BOOLEAN) {
     533           2 :                         persistent_group = entry.bool_value;
     534          41 :                 } else if (os_strcmp(entry.key, "join") == 0 &&
     535           2 :                            entry.type == DBUS_TYPE_BOOLEAN) {
     536           2 :                         join = entry.bool_value;
     537          39 :                 } else if (os_strcmp(entry.key, "authorize_only") == 0 &&
     538           2 :                            entry.type == DBUS_TYPE_BOOLEAN) {
     539           2 :                         authorize_only = entry.bool_value;
     540          39 :                 } else if (os_strcmp(entry.key, "frequency") == 0 &&
     541           4 :                            entry.type == DBUS_TYPE_INT32) {
     542           4 :                         freq = entry.int32_value;
     543           7 :                         if (freq <= 0)
     544           1 :                                 goto inv_args_clear;
     545          40 :                 } else if (os_strcmp(entry.key, "go_intent") == 0 &&
     546           9 :                            entry.type == DBUS_TYPE_INT32) {
     547           9 :                         go_intent = entry.int32_value;
     548           9 :                         if ((go_intent < 0) || (go_intent > 15))
     549             :                                 goto inv_args_clear;
     550          35 :                 } else if (os_strcmp(entry.key, "wps_method") == 0 &&
     551          13 :                            entry.type == DBUS_TYPE_STRING) {
     552          25 :                         if (os_strcmp(entry.str_value, "pbc") == 0)
     553           1 :                                 wps_method = WPS_PBC;
     554          12 :                         else if (os_strcmp(entry.str_value, "pin") == 0)
     555           2 :                                 wps_method = WPS_PIN_DISPLAY;
     556          10 :                         else if (os_strcmp(entry.str_value, "display") == 0)
     557           3 :                                 wps_method = WPS_PIN_DISPLAY;
     558           7 :                         else if (os_strcmp(entry.str_value, "keypad") == 0)
     559           6 :                                 wps_method = WPS_PIN_KEYPAD;
     560             :                         else
     561           1 :                                 goto inv_args_clear;
     562          18 :                 } else if (os_strcmp(entry.key, "pin") == 0 &&
     563           9 :                            entry.type == DBUS_TYPE_STRING) {
     564           9 :                         pin = os_strdup(entry.str_value);
     565             :                 } else
     566             :                         goto inv_args_clear;
     567             : 
     568          50 :                 wpa_dbus_dict_entry_clear(&entry);
     569             :         }
     570             : 
     571          24 :         if (wps_method == WPS_NOT_READY ||
     572          23 :             parse_peer_object_path(peer_object_path, addr) < 0 ||
     573          11 :             !p2p_peer_known(wpa_s->global->p2p, addr))
     574             :                 goto inv_args;
     575             : 
     576             :         /*
     577             :          * Validate the wps_method specified and the pin value.
     578             :          */
     579          11 :         if ((!pin || !pin[0]) && wps_method == WPS_PIN_KEYPAD)
     580           1 :                 goto inv_args;
     581             : 
     582          10 :         wpa_s = wpa_s->global->p2p_init_wpa_s;
     583             : 
     584          10 :         new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
     585             :                                    persistent_group, 0, join, authorize_only,
     586             :                                    go_intent, freq, 0, -1, 0, 0, 0, 0, NULL, 0);
     587             : 
     588          10 :         if (new_pin >= 0) {
     589             :                 char npin[9];
     590             :                 char *generated_pin;
     591             : 
     592           9 :                 os_snprintf(npin, sizeof(npin), "%08d", new_pin);
     593           9 :                 generated_pin = npin;
     594           9 :                 reply = dbus_message_new_method_return(message);
     595           9 :                 dbus_message_append_args(reply, DBUS_TYPE_STRING,
     596             :                                          &generated_pin, DBUS_TYPE_INVALID);
     597             :         } else {
     598           1 :                 switch (new_pin) {
     599             :                 case -2:
     600           0 :                         err_msg =
     601             :                                 "connect failed due to channel unavailability.";
     602           0 :                         iface = WPAS_DBUS_ERROR_CONNECT_CHANNEL_UNAVAILABLE;
     603           0 :                         break;
     604             : 
     605             :                 case -3:
     606           1 :                         err_msg = "connect failed due to unsupported channel.";
     607           1 :                         iface = WPAS_DBUS_ERROR_CONNECT_CHANNEL_UNSUPPORTED;
     608           1 :                         break;
     609             : 
     610             :                 default:
     611           0 :                         err_msg = "connect failed due to unspecified error.";
     612           0 :                         iface = WPAS_DBUS_ERROR_CONNECT_UNSPECIFIED_ERROR;
     613           0 :                         break;
     614             :                 }
     615             : 
     616             :                 /*
     617             :                  * TODO:
     618             :                  * Do we need specialized errors corresponding to above
     619             :                  * error conditions as against just returning a different
     620             :                  * error message?
     621             :                  */
     622           1 :                 reply = dbus_message_new_error(message, iface, err_msg);
     623             :         }
     624             : 
     625             : out:
     626          14 :         os_free(peer_object_path);
     627          14 :         os_free(pin);
     628          14 :         return reply;
     629             : inv_args_clear:
     630           2 :         wpa_dbus_dict_entry_clear(&entry);
     631             : inv_args:
     632           4 :         reply = wpas_dbus_error_invalid_args(message, NULL);
     633           4 :         goto out;
     634             : }
     635             : 
     636             : 
     637             : /**
     638             :  * wpas_dbus_handler_p2p_cancel - Cancel P2P group formation
     639             :  * @message: Pointer to incoming dbus message
     640             :  * @wpa_s: %wpa_supplicant data structure
     641             :  * Returns: NULL on success or DBus error on failure
     642             :  *
     643             :  * Handler for "Cancel" method call. Returns NULL if P2P cancel succeeds or DBus
     644             :  * error on P2P cancel failure
     645             :  */
     646           2 : DBusMessage * wpas_dbus_handler_p2p_cancel(DBusMessage *message,
     647             :                                            struct wpa_supplicant *wpa_s)
     648             : {
     649           2 :         if (wpas_p2p_cancel(wpa_s))
     650           1 :                 return wpas_dbus_error_unknown_error(message,
     651             :                                                      "P2P cancel failed");
     652             : 
     653           1 :         return NULL;
     654             : }
     655             : 
     656             : 
     657           5 : DBusMessage * wpas_dbus_handler_p2p_invite(DBusMessage *message,
     658             :                                            struct wpa_supplicant *wpa_s)
     659             : {
     660             :         DBusMessageIter iter_dict;
     661           5 :         DBusMessage *reply = NULL;
     662             :         DBusMessageIter iter;
     663             :         struct wpa_dbus_dict_entry entry;
     664           5 :         char *peer_object_path = NULL;
     665           5 :         char *pg_object_path = NULL;
     666           5 :         char *iface = NULL;
     667             :         u8 peer_addr[ETH_ALEN];
     668           5 :         unsigned int group_id = 0;
     669           5 :         int persistent = 0;
     670             :         struct wpa_ssid *ssid;
     671             : 
     672           5 :         if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL))
     673           1 :                 return reply;
     674             : 
     675           4 :         dbus_message_iter_init(message, &iter);
     676             : 
     677           4 :         if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
     678           0 :                 goto err;
     679             : 
     680          13 :         while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
     681           6 :                 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
     682           0 :                         goto err;
     683             : 
     684           9 :                 if (os_strcmp(entry.key, "peer") == 0 &&
     685           3 :                     entry.type == DBUS_TYPE_OBJECT_PATH) {
     686           3 :                         peer_object_path = os_strdup(entry.str_value);
     687           3 :                         wpa_dbus_dict_entry_clear(&entry);
     688           3 :                 } else if (os_strcmp(entry.key, "persistent_group_object") ==
     689           2 :                            0 &&
     690           2 :                            entry.type == DBUS_TYPE_OBJECT_PATH) {
     691           2 :                         pg_object_path = os_strdup(entry.str_value);
     692           2 :                         persistent = 1;
     693           2 :                         wpa_dbus_dict_entry_clear(&entry);
     694             :                 } else {
     695           1 :                         wpa_dbus_dict_entry_clear(&entry);
     696           1 :                         goto err;
     697             :                 }
     698             :         }
     699             : 
     700           6 :         if (parse_peer_object_path(peer_object_path, peer_addr) < 0 ||
     701           3 :             !p2p_peer_known(wpa_s->global->p2p, peer_addr))
     702             :                 goto err;
     703             : 
     704           3 :         wpa_s = wpa_s->global->p2p_init_wpa_s;
     705             : 
     706           3 :         if (persistent) {
     707             :                 char *net_id_str;
     708             :                 /*
     709             :                  * A group ID is defined meaning we want to re-invoke a
     710             :                  * persistent group
     711             :                  */
     712             : 
     713           2 :                 iface = wpas_dbus_new_decompose_object_path(
     714             :                         pg_object_path,
     715             :                         WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART,
     716             :                         &net_id_str);
     717           3 :                 if (iface == NULL || net_id_str == NULL ||
     718           2 :                     !wpa_s->parent->dbus_new_path ||
     719           1 :                     os_strcmp(iface, wpa_s->parent->dbus_new_path) != 0) {
     720           1 :                         reply = wpas_dbus_error_invalid_args(message,
     721             :                                                              pg_object_path);
     722           2 :                         goto out;
     723             :                 }
     724             : 
     725           1 :                 group_id = strtoul(net_id_str, NULL, 10);
     726           1 :                 if (errno == EINVAL) {
     727           0 :                         reply = wpas_dbus_error_invalid_args(
     728             :                                 message, pg_object_path);
     729           0 :                         goto out;
     730             :                 }
     731             : 
     732             :                 /* Get the SSID structure from the persistent group id */
     733           1 :                 ssid = wpa_config_get_network(wpa_s->conf, group_id);
     734           1 :                 if (ssid == NULL || ssid->disabled != 2)
     735             :                         goto err;
     736             : 
     737           1 :                 if (wpas_p2p_invite(wpa_s, peer_addr, ssid, NULL, 0, 0, 0, 0, 0,
     738             :                                     0) < 0) {
     739           0 :                         reply = wpas_dbus_error_unknown_error(
     740             :                                 message,
     741             :                                 "Failed to reinvoke a persistent group");
     742           0 :                         goto out;
     743             :                 }
     744             :         } else {
     745             :                 /*
     746             :                  * No group ID means propose to a peer to join my active group
     747             :                  */
     748           1 :                 if (wpas_p2p_invite_group(wpa_s, wpa_s->ifname,
     749             :                                           peer_addr, NULL)) {
     750           0 :                         reply = wpas_dbus_error_unknown_error(
     751             :                                 message, "Failed to join to an active group");
     752           0 :                         goto out;
     753             :                 }
     754             :         }
     755             : 
     756             : out:
     757           4 :         os_free(iface);
     758           4 :         os_free(pg_object_path);
     759           4 :         os_free(peer_object_path);
     760           4 :         return reply;
     761             : 
     762             : err:
     763           1 :         reply = wpas_dbus_error_invalid_args(message, NULL);
     764           1 :         goto out;
     765             : }
     766             : 
     767             : 
     768           7 : DBusMessage * wpas_dbus_handler_p2p_prov_disc_req(DBusMessage *message,
     769             :                                                   struct wpa_supplicant *wpa_s)
     770             : {
     771             :         DBusMessageIter iter;
     772           7 :         char *peer_object_path = NULL;
     773           7 :         char *config_method = NULL;
     774             :         u8 peer_addr[ETH_ALEN];
     775             : 
     776           7 :         dbus_message_iter_init(message, &iter);
     777           7 :         dbus_message_iter_get_basic(&iter, &peer_object_path);
     778             : 
     779           7 :         if (parse_peer_object_path(peer_object_path, peer_addr) < 0)
     780           1 :                 return wpas_dbus_error_invalid_args(message, NULL);
     781             : 
     782           6 :         dbus_message_iter_next(&iter);
     783           6 :         dbus_message_iter_get_basic(&iter, &config_method);
     784             : 
     785             :         /*
     786             :          * Validation checks on config_method are being duplicated here
     787             :          * to be able to return invalid args reply since the error code
     788             :          * from p2p module are not granular enough (yet).
     789             :          */
     790          10 :         if (os_strcmp(config_method, "display") &&
     791           7 :             os_strcmp(config_method, "keypad") &&
     792           5 :             os_strcmp(config_method, "pbc") &&
     793           2 :             os_strcmp(config_method, "pushbutton"))
     794           1 :                 return wpas_dbus_error_invalid_args(message, NULL);
     795             : 
     796           5 :         wpa_s = wpa_s->global->p2p_init_wpa_s;
     797             : 
     798           5 :         if (wpas_p2p_prov_disc(wpa_s, peer_addr, config_method,
     799             :                                WPAS_P2P_PD_FOR_GO_NEG, NULL) < 0)
     800           4 :                 return wpas_dbus_error_unknown_error(message,
     801             :                                 "Failed to send provision discovery request");
     802             : 
     803           1 :         return NULL;
     804             : }
     805             : 
     806             : 
     807             : /*
     808             :  * P2P Device property accessor methods.
     809             :  */
     810             : 
     811           9 : dbus_bool_t wpas_dbus_getter_p2p_device_config(
     812             :         const struct wpa_dbus_property_desc *property_desc,
     813             :         DBusMessageIter *iter, DBusError *error, void *user_data)
     814             : {
     815           9 :         struct wpa_supplicant *wpa_s = user_data;
     816             :         DBusMessageIter variant_iter, dict_iter;
     817             :         DBusMessageIter iter_secdev_dict_entry, iter_secdev_dict_val,
     818             :                 iter_secdev_dict_array;
     819             :         const char *dev_name;
     820           9 :         int num_vendor_extensions = 0;
     821             :         int i;
     822             :         const struct wpabuf *vendor_ext[P2P_MAX_WPS_VENDOR_EXT];
     823             : 
     824           9 :         if (!wpa_dbus_p2p_check_enabled(wpa_s, NULL, NULL, error))
     825           1 :                 return FALSE;
     826             : 
     827           8 :         wpa_s = wpa_s->global->p2p_init_wpa_s;
     828             : 
     829           8 :         if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
     830           8 :                                               "a{sv}", &variant_iter) ||
     831           8 :             !wpa_dbus_dict_open_write(&variant_iter, &dict_iter))
     832             :                 goto err_no_mem;
     833             : 
     834             :         /* DeviceName */
     835           8 :         dev_name = wpa_s->conf->device_name;
     836          16 :         if (dev_name &&
     837           8 :             !wpa_dbus_dict_append_string(&dict_iter, "DeviceName", dev_name))
     838           0 :                 goto err_no_mem;
     839             : 
     840             :         /* Primary device type */
     841           8 :         if (!wpa_dbus_dict_append_byte_array(&dict_iter, "PrimaryDeviceType",
     842           8 :                                              (char *) wpa_s->conf->device_type,
     843             :                                              WPS_DEV_TYPE_LEN))
     844           0 :                 goto err_no_mem;
     845             : 
     846             :         /* Secondary device types */
     847           8 :         if (wpa_s->conf->num_sec_device_types) {
     848           1 :                 if (!wpa_dbus_dict_begin_array(&dict_iter,
     849             :                                                "SecondaryDeviceTypes",
     850             :                                                DBUS_TYPE_ARRAY_AS_STRING
     851             :                                                DBUS_TYPE_BYTE_AS_STRING,
     852             :                                                &iter_secdev_dict_entry,
     853             :                                                &iter_secdev_dict_val,
     854             :                                                &iter_secdev_dict_array))
     855           0 :                         goto err_no_mem;
     856             : 
     857           2 :                 for (i = 0; i < wpa_s->conf->num_sec_device_types; i++)
     858           1 :                         wpa_dbus_dict_bin_array_add_element(
     859             :                                 &iter_secdev_dict_array,
     860           1 :                                 wpa_s->conf->sec_device_type[i],
     861             :                                 WPS_DEV_TYPE_LEN);
     862             : 
     863           1 :                 if (!wpa_dbus_dict_end_array(&dict_iter,
     864             :                                              &iter_secdev_dict_entry,
     865             :                                              &iter_secdev_dict_val,
     866             :                                              &iter_secdev_dict_array))
     867           0 :                         goto err_no_mem;
     868             :         }
     869             : 
     870             :         /* Vendor Extensions */
     871          88 :         for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
     872          80 :                 if (wpa_s->conf->wps_vendor_ext[i] == NULL)
     873          79 :                         continue;
     874           2 :                 vendor_ext[num_vendor_extensions++] =
     875           1 :                         wpa_s->conf->wps_vendor_ext[i];
     876             :         }
     877             : 
     878           9 :         if ((num_vendor_extensions &&
     879           1 :              !wpa_dbus_dict_append_wpabuf_array(&dict_iter,
     880             :                                                 "VendorExtension",
     881             :                                                 vendor_ext,
     882           8 :                                                 num_vendor_extensions)) ||
     883           8 :             !wpa_dbus_dict_append_uint32(&dict_iter, "GOIntent",
     884          16 :                                          wpa_s->conf->p2p_go_intent) ||
     885           8 :             !wpa_dbus_dict_append_bool(&dict_iter, "PersistentReconnect",
     886          16 :                                        wpa_s->conf->persistent_reconnect) ||
     887           8 :             !wpa_dbus_dict_append_uint32(&dict_iter, "ListenRegClass",
     888          16 :                                          wpa_s->conf->p2p_listen_reg_class) ||
     889           8 :             !wpa_dbus_dict_append_uint32(&dict_iter, "ListenChannel",
     890          16 :                                          wpa_s->conf->p2p_listen_channel) ||
     891           8 :             !wpa_dbus_dict_append_uint32(&dict_iter, "OperRegClass",
     892          16 :                                          wpa_s->conf->p2p_oper_reg_class) ||
     893           8 :             !wpa_dbus_dict_append_uint32(&dict_iter, "OperChannel",
     894          16 :                                          wpa_s->conf->p2p_oper_channel) ||
     895          10 :             (wpa_s->conf->p2p_ssid_postfix &&
     896           2 :              !wpa_dbus_dict_append_string(&dict_iter, "SsidPostfix",
     897          10 :                                           wpa_s->conf->p2p_ssid_postfix)) ||
     898           8 :             !wpa_dbus_dict_append_bool(&dict_iter, "IntraBss",
     899          16 :                                        wpa_s->conf->p2p_intra_bss) ||
     900           8 :             !wpa_dbus_dict_append_uint32(&dict_iter, "GroupIdle",
     901          16 :                                          wpa_s->conf->p2p_group_idle) ||
     902           8 :             !wpa_dbus_dict_append_uint32(&dict_iter, "disassoc_low_ack",
     903          16 :                                          wpa_s->conf->disassoc_low_ack) ||
     904           8 :             !wpa_dbus_dict_append_bool(&dict_iter, "NoGroupIface",
     905          16 :                                        wpa_s->conf->p2p_no_group_iface) ||
     906           8 :             !wpa_dbus_dict_append_uint32(&dict_iter, "p2p_search_delay",
     907          16 :                                          wpa_s->conf->p2p_search_delay) ||
     908          16 :             !wpa_dbus_dict_close_write(&variant_iter, &dict_iter) ||
     909           8 :             !dbus_message_iter_close_container(iter, &variant_iter))
     910             :                 goto err_no_mem;
     911             : 
     912           8 :         return TRUE;
     913             : 
     914             : err_no_mem:
     915           0 :         dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
     916           0 :         return FALSE;
     917             : }
     918             : 
     919             : 
     920           7 : dbus_bool_t wpas_dbus_setter_p2p_device_config(
     921             :         const struct wpa_dbus_property_desc *property_desc,
     922             :         DBusMessageIter *iter, DBusError *error, void *user_data)
     923             : {
     924           7 :         struct wpa_supplicant *wpa_s = user_data;
     925             :         DBusMessageIter variant_iter, iter_dict;
     926           7 :         struct wpa_dbus_dict_entry entry = {.type = DBUS_TYPE_STRING };
     927             :         unsigned int i;
     928             : 
     929           7 :         if (!wpa_dbus_p2p_check_enabled(wpa_s, NULL, NULL, error))
     930           1 :                 return FALSE;
     931             : 
     932           6 :         wpa_s = wpa_s->global->p2p_init_wpa_s;
     933             : 
     934           6 :         dbus_message_iter_recurse(iter, &variant_iter);
     935           6 :         if (!wpa_dbus_dict_open_read(&variant_iter, &iter_dict, error))
     936           0 :                 return FALSE;
     937             : 
     938          31 :         while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
     939          22 :                 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) {
     940           0 :                         dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
     941             :                                              "invalid message format");
     942           0 :                         return FALSE;
     943             :                 }
     944             : 
     945          22 :                 if (os_strcmp(entry.key, "DeviceName") == 0) {
     946             :                         char *devname;
     947             : 
     948           3 :                         if (entry.type != DBUS_TYPE_STRING ||
     949           1 :                             os_strlen(entry.str_value) > WPS_DEV_NAME_MAX_LEN)
     950             :                                 goto error;
     951             : 
     952           1 :                         devname = os_strdup(entry.str_value);
     953           1 :                         if (devname == NULL)
     954           0 :                                 goto err_no_mem_clear;
     955             : 
     956           1 :                         os_free(wpa_s->conf->device_name);
     957           1 :                         wpa_s->conf->device_name = devname;
     958             : 
     959           1 :                         wpa_s->conf->changed_parameters |=
     960             :                                 CFG_CHANGED_DEVICE_NAME;
     961          20 :                 } else if (os_strcmp(entry.key, "PrimaryDeviceType") == 0) {
     962           2 :                         if (entry.type != DBUS_TYPE_ARRAY ||
     963           2 :                             entry.array_type != DBUS_TYPE_BYTE ||
     964           1 :                             entry.array_len != WPS_DEV_TYPE_LEN)
     965             :                                 goto error;
     966             : 
     967           1 :                         os_memcpy(wpa_s->conf->device_type,
     968             :                                   entry.bytearray_value,
     969             :                                   WPS_DEV_TYPE_LEN);
     970           1 :                         wpa_s->conf->changed_parameters |=
     971             :                                 CFG_CHANGED_DEVICE_TYPE;
     972          19 :                 } else if (os_strcmp(entry.key, "SecondaryDeviceTypes") == 0) {
     973           4 :                         if (entry.type != DBUS_TYPE_ARRAY ||
     974           4 :                             entry.array_type != WPAS_DBUS_TYPE_BINARRAY ||
     975           2 :                             entry.array_len > MAX_SEC_DEVICE_TYPES)
     976             :                                 goto error;
     977             : 
     978           3 :                         for (i = 0; i < entry.array_len; i++)
     979           1 :                                 if (wpabuf_len(entry.binarray_value[i]) !=
     980             :                                     WPS_DEV_TYPE_LEN)
     981           0 :                                         goto err_no_mem_clear;
     982           3 :                         for (i = 0; i < entry.array_len; i++)
     983           1 :                                 os_memcpy(wpa_s->conf->sec_device_type[i],
     984             :                                           wpabuf_head(entry.binarray_value[i]),
     985             :                                           WPS_DEV_TYPE_LEN);
     986           2 :                         wpa_s->conf->num_sec_device_types = entry.array_len;
     987           2 :                         wpa_s->conf->changed_parameters |=
     988             :                                         CFG_CHANGED_SEC_DEVICE_TYPE;
     989          17 :                 } else if (os_strcmp(entry.key, "VendorExtension") == 0) {
     990           4 :                         if (entry.type != DBUS_TYPE_ARRAY ||
     991           4 :                             entry.array_type != WPAS_DBUS_TYPE_BINARRAY ||
     992           2 :                             (entry.array_len > P2P_MAX_WPS_VENDOR_EXT))
     993             :                                 goto error;
     994             : 
     995           2 :                         wpa_s->conf->changed_parameters |=
     996             :                                 CFG_CHANGED_VENDOR_EXTENSION;
     997             : 
     998          22 :                         for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
     999          20 :                                 wpabuf_free(wpa_s->conf->wps_vendor_ext[i]);
    1000          20 :                                 if (i < entry.array_len) {
    1001           2 :                                         wpa_s->conf->wps_vendor_ext[i] =
    1002           1 :                                                 entry.binarray_value[i];
    1003           1 :                                         entry.binarray_value[i] = NULL;
    1004             :                                 } else
    1005          19 :                                         wpa_s->conf->wps_vendor_ext[i] = NULL;
    1006             :                         }
    1007          16 :                 } else if (os_strcmp(entry.key, "GOIntent") == 0 &&
    1008           2 :                            entry.type == DBUS_TYPE_UINT32 &&
    1009           1 :                            (entry.uint32_value <= 15))
    1010           1 :                         wpa_s->conf->p2p_go_intent = entry.uint32_value;
    1011          15 :                 else if (os_strcmp(entry.key, "PersistentReconnect") == 0 &&
    1012           1 :                          entry.type == DBUS_TYPE_BOOLEAN)
    1013           1 :                         wpa_s->conf->persistent_reconnect = entry.bool_value;
    1014          14 :                 else if (os_strcmp(entry.key, "ListenRegClass") == 0 &&
    1015           1 :                          entry.type == DBUS_TYPE_UINT32) {
    1016           1 :                         wpa_s->conf->p2p_listen_reg_class = entry.uint32_value;
    1017           1 :                         wpa_s->conf->changed_parameters |=
    1018             :                                 CFG_CHANGED_P2P_LISTEN_CHANNEL;
    1019          13 :                 } else if (os_strcmp(entry.key, "ListenChannel") == 0 &&
    1020           1 :                            entry.type == DBUS_TYPE_UINT32) {
    1021           1 :                         wpa_s->conf->p2p_listen_channel = entry.uint32_value;
    1022           1 :                         wpa_s->conf->changed_parameters |=
    1023             :                                 CFG_CHANGED_P2P_LISTEN_CHANNEL;
    1024          12 :                 } else if (os_strcmp(entry.key, "OperRegClass") == 0 &&
    1025           1 :                            entry.type == DBUS_TYPE_UINT32) {
    1026           1 :                         wpa_s->conf->p2p_oper_reg_class = entry.uint32_value;
    1027           1 :                         wpa_s->conf->changed_parameters |=
    1028             :                                 CFG_CHANGED_P2P_OPER_CHANNEL;
    1029          11 :                 } else if (os_strcmp(entry.key, "OperChannel") == 0 &&
    1030           1 :                            entry.type == DBUS_TYPE_UINT32) {
    1031           1 :                         wpa_s->conf->p2p_oper_channel = entry.uint32_value;
    1032           1 :                         wpa_s->conf->changed_parameters |=
    1033             :                                 CFG_CHANGED_P2P_OPER_CHANNEL;
    1034           9 :                 } else if (os_strcmp(entry.key, "SsidPostfix") == 0) {
    1035             :                         char *postfix;
    1036             : 
    1037           3 :                         if (entry.type != DBUS_TYPE_STRING)
    1038           1 :                                 goto error;
    1039             : 
    1040           2 :                         postfix = os_strdup(entry.str_value);
    1041           2 :                         if (!postfix)
    1042           0 :                                 goto err_no_mem_clear;
    1043             : 
    1044           2 :                         os_free(wpa_s->conf->p2p_ssid_postfix);
    1045           2 :                         wpa_s->conf->p2p_ssid_postfix = postfix;
    1046             : 
    1047           2 :                         wpa_s->conf->changed_parameters |=
    1048             :                                         CFG_CHANGED_P2P_SSID_POSTFIX;
    1049           7 :                 } else if (os_strcmp(entry.key, "IntraBss") == 0 &&
    1050           1 :                            entry.type == DBUS_TYPE_BOOLEAN) {
    1051           1 :                         wpa_s->conf->p2p_intra_bss = entry.bool_value;
    1052           1 :                         wpa_s->conf->changed_parameters |=
    1053             :                                 CFG_CHANGED_P2P_INTRA_BSS;
    1054           6 :                 } else if (os_strcmp(entry.key, "GroupIdle") == 0 &&
    1055           1 :                            entry.type == DBUS_TYPE_UINT32)
    1056           1 :                         wpa_s->conf->p2p_group_idle = entry.uint32_value;
    1057           5 :                 else if (os_strcmp(entry.key, "disassoc_low_ack") == 0 &&
    1058           1 :                          entry.type == DBUS_TYPE_UINT32)
    1059           1 :                         wpa_s->conf->disassoc_low_ack = entry.uint32_value;
    1060           4 :                 else if (os_strcmp(entry.key, "NoGroupIface") == 0 &&
    1061           1 :                          entry.type == DBUS_TYPE_BOOLEAN)
    1062           1 :                         wpa_s->conf->p2p_no_group_iface = entry.bool_value;
    1063           3 :                 else if (os_strcmp(entry.key, "p2p_search_delay") == 0 &&
    1064           1 :                          entry.type == DBUS_TYPE_UINT32)
    1065           1 :                         wpa_s->conf->p2p_search_delay = entry.uint32_value;
    1066             :                 else
    1067             :                         goto error;
    1068             : 
    1069          19 :                 wpa_dbus_dict_entry_clear(&entry);
    1070             :         }
    1071             : 
    1072           3 :         if (wpa_s->conf->changed_parameters) {
    1073             :                 /* Some changed parameters requires to update config*/
    1074           3 :                 wpa_supplicant_update_config(wpa_s);
    1075             :         }
    1076             : 
    1077           3 :         return TRUE;
    1078             : 
    1079             :  error:
    1080           3 :         dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
    1081             :                              "invalid message format");
    1082           3 :         wpa_dbus_dict_entry_clear(&entry);
    1083           3 :         return FALSE;
    1084             : 
    1085             :  err_no_mem_clear:
    1086           0 :         dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
    1087           0 :         wpa_dbus_dict_entry_clear(&entry);
    1088           0 :         return FALSE;
    1089             : }
    1090             : 
    1091             : 
    1092           7 : dbus_bool_t wpas_dbus_getter_p2p_peers(
    1093             :         const struct wpa_dbus_property_desc *property_desc,
    1094             :         DBusMessageIter *iter, DBusError *error, void *user_data)
    1095             : {
    1096           7 :         struct wpa_supplicant *wpa_s = user_data;
    1097           7 :         struct p2p_data *p2p = wpa_s->global->p2p;
    1098           7 :         int next = 0, i = 0;
    1099           7 :         int num = 0, out_of_mem = 0;
    1100             :         const u8 *addr;
    1101           7 :         const struct p2p_peer_info *peer_info = NULL;
    1102           7 :         dbus_bool_t success = FALSE;
    1103             : 
    1104             :         struct dl_list peer_objpath_list;
    1105             :         struct peer_objpath_node {
    1106             :                 struct dl_list list;
    1107             :                 char path[WPAS_DBUS_OBJECT_PATH_MAX];
    1108             :         } *node, *tmp;
    1109             : 
    1110           7 :         char **peer_obj_paths = NULL;
    1111             : 
    1112          13 :         if (!wpa_dbus_p2p_check_enabled(wpa_s, NULL, NULL, error) ||
    1113           6 :             !wpa_s->parent->parent->dbus_new_path)
    1114           1 :                 return FALSE;
    1115             : 
    1116           6 :         dl_list_init(&peer_objpath_list);
    1117             : 
    1118             :         /* Get the first peer info */
    1119           6 :         peer_info = p2p_get_peer_found(p2p, NULL, next);
    1120             : 
    1121             :         /* Get next and accumulate them */
    1122           6 :         next = 1;
    1123          20 :         while (peer_info != NULL) {
    1124           8 :                 node = os_zalloc(sizeof(struct peer_objpath_node));
    1125           8 :                 if (!node) {
    1126           0 :                         out_of_mem = 1;
    1127           0 :                         goto error;
    1128             :                 }
    1129             : 
    1130           8 :                 addr = peer_info->p2p_device_addr;
    1131          56 :                 os_snprintf(node->path, WPAS_DBUS_OBJECT_PATH_MAX,
    1132             :                             "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART
    1133             :                             "/" COMPACT_MACSTR,
    1134           8 :                             wpa_s->parent->parent->dbus_new_path,
    1135          48 :                             MAC2STR(addr));
    1136           8 :                 dl_list_add_tail(&peer_objpath_list, &node->list);
    1137           8 :                 num++;
    1138             : 
    1139           8 :                 peer_info = p2p_get_peer_found(p2p, addr, next);
    1140             :         }
    1141             : 
    1142             :         /*
    1143             :          * Now construct the peer object paths in a form suitable for
    1144             :          * array_property_getter helper below.
    1145             :          */
    1146           6 :         peer_obj_paths = os_calloc(num, sizeof(char *));
    1147             : 
    1148           6 :         if (!peer_obj_paths) {
    1149           0 :                 out_of_mem = 1;
    1150           0 :                 goto error;
    1151             :         }
    1152             : 
    1153          14 :         dl_list_for_each_safe(node, tmp, &peer_objpath_list,
    1154             :                               struct peer_objpath_node, list)
    1155           8 :                 peer_obj_paths[i++] = node->path;
    1156             : 
    1157           6 :         success = wpas_dbus_simple_array_property_getter(iter,
    1158             :                                                          DBUS_TYPE_OBJECT_PATH,
    1159             :                                                          peer_obj_paths, num,
    1160             :                                                          error);
    1161             : 
    1162             : error:
    1163           6 :         if (peer_obj_paths)
    1164           6 :                 os_free(peer_obj_paths);
    1165             : 
    1166          14 :         dl_list_for_each_safe(node, tmp, &peer_objpath_list,
    1167             :                               struct peer_objpath_node, list) {
    1168           8 :                 dl_list_del(&node->list);
    1169           8 :                 os_free(node);
    1170             :         }
    1171           6 :         if (out_of_mem)
    1172           0 :                 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
    1173             : 
    1174           6 :         return success;
    1175             : }
    1176             : 
    1177             : 
    1178             : enum wpas_p2p_role {
    1179             :         WPAS_P2P_ROLE_DEVICE,
    1180             :         WPAS_P2P_ROLE_GO,
    1181             :         WPAS_P2P_ROLE_CLIENT,
    1182             : };
    1183             : 
    1184          63 : static enum wpas_p2p_role wpas_get_p2p_role(struct wpa_supplicant *wpa_s)
    1185             : {
    1186          63 :         struct wpa_ssid *ssid = wpa_s->current_ssid;
    1187             : 
    1188          63 :         if (!ssid)
    1189           8 :                 return WPAS_P2P_ROLE_DEVICE;
    1190          55 :         if (wpa_s->wpa_state != WPA_COMPLETED)
    1191           0 :                 return WPAS_P2P_ROLE_DEVICE;
    1192             : 
    1193          55 :         switch (ssid->mode) {
    1194             :         case WPAS_MODE_P2P_GO:
    1195             :         case WPAS_MODE_P2P_GROUP_FORMATION:
    1196          37 :                 return WPAS_P2P_ROLE_GO;
    1197             :         case WPAS_MODE_INFRA:
    1198          18 :                 if (ssid->p2p_group)
    1199          18 :                         return WPAS_P2P_ROLE_CLIENT;
    1200           0 :                 return WPAS_P2P_ROLE_DEVICE;
    1201             :         default:
    1202           0 :                 return WPAS_P2P_ROLE_DEVICE;
    1203             :         }
    1204             : }
    1205             : 
    1206             : 
    1207          15 : dbus_bool_t wpas_dbus_getter_p2p_role(
    1208             :         const struct wpa_dbus_property_desc *property_desc,
    1209             :         DBusMessageIter *iter, DBusError *error, void *user_data)
    1210             : {
    1211          15 :         struct wpa_supplicant *wpa_s = user_data;
    1212             :         char *str;
    1213             : 
    1214          15 :         switch (wpas_get_p2p_role(wpa_s)) {
    1215             :         case WPAS_P2P_ROLE_GO:
    1216           7 :                 str = "GO";
    1217           7 :                 break;
    1218             :         case WPAS_P2P_ROLE_CLIENT:
    1219           4 :                 str = "client";
    1220           4 :                 break;
    1221             :         default:
    1222           4 :                 str = "device";
    1223           4 :                 break;
    1224             :         }
    1225             : 
    1226          15 :         return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &str,
    1227             :                                                 error);
    1228             : }
    1229             : 
    1230             : 
    1231          15 : dbus_bool_t wpas_dbus_getter_p2p_group(
    1232             :         const struct wpa_dbus_property_desc *property_desc,
    1233             :         DBusMessageIter *iter, DBusError *error, void *user_data)
    1234             : {
    1235          15 :         struct wpa_supplicant *wpa_s = user_data;
    1236             :         char path_buf[WPAS_DBUS_OBJECT_PATH_MAX];
    1237          15 :         char *dbus_groupobj_path = path_buf;
    1238             : 
    1239          15 :         if (wpa_s->dbus_groupobj_path == NULL)
    1240           4 :                 os_snprintf(dbus_groupobj_path, WPAS_DBUS_OBJECT_PATH_MAX,
    1241             :                             "/");
    1242             :         else
    1243          11 :                 os_snprintf(dbus_groupobj_path, WPAS_DBUS_OBJECT_PATH_MAX,
    1244             :                             "%s", wpa_s->dbus_groupobj_path);
    1245             : 
    1246          15 :         return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
    1247             :                                                 &dbus_groupobj_path, error);
    1248             : }
    1249             : 
    1250             : 
    1251           7 : dbus_bool_t wpas_dbus_getter_p2p_peergo(
    1252             :         const struct wpa_dbus_property_desc *property_desc,
    1253             :         DBusMessageIter *iter, DBusError *error, void *user_data)
    1254             : {
    1255           7 :         struct wpa_supplicant *wpa_s = user_data;
    1256             :         char go_peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
    1257             : 
    1258           7 :         if (!wpa_s->parent->parent->dbus_new_path)
    1259           0 :                 return FALSE;
    1260             : 
    1261           7 :         if (wpas_get_p2p_role(wpa_s) != WPAS_P2P_ROLE_CLIENT)
    1262           6 :                 os_snprintf(go_peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
    1263             :         else
    1264           7 :                 os_snprintf(go_peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
    1265             :                             "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
    1266             :                             COMPACT_MACSTR,
    1267           1 :                             wpa_s->parent->parent->dbus_new_path,
    1268           6 :                             MAC2STR(wpa_s->go_dev_addr));
    1269             : 
    1270           7 :         path = go_peer_obj_path;
    1271           7 :         return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
    1272             :                                                 &path, error);
    1273             : }
    1274             : 
    1275             : 
    1276             : /*
    1277             :  * Peer object properties accessor methods
    1278             :  */
    1279             : 
    1280         301 : dbus_bool_t wpas_dbus_getter_p2p_peer_device_name(
    1281             :         const struct wpa_dbus_property_desc *property_desc,
    1282             :         DBusMessageIter *iter, DBusError *error, void *user_data)
    1283             : {
    1284         301 :         struct peer_handler_args *peer_args = user_data;
    1285             :         const struct p2p_peer_info *info;
    1286             :         char *tmp;
    1287             : 
    1288         301 :         if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error))
    1289           0 :                 return FALSE;
    1290             : 
    1291             :         /* get the peer info */
    1292         301 :         info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
    1293         301 :                                   peer_args->p2p_device_addr, 0);
    1294         301 :         if (info == NULL) {
    1295           0 :                 dbus_set_error(error, DBUS_ERROR_FAILED,
    1296             :                                "failed to find peer");
    1297           0 :                 return FALSE;
    1298             :         }
    1299             : 
    1300         301 :         tmp = os_strdup(info->device_name);
    1301         301 :         if (!tmp) {
    1302           0 :                 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
    1303           0 :                 return FALSE;
    1304             :         }
    1305             : 
    1306         301 :         if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp,
    1307             :                                               error)) {
    1308           0 :                 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
    1309           0 :                 os_free(tmp);
    1310           0 :                 return FALSE;
    1311             :         }
    1312             : 
    1313         301 :         os_free(tmp);
    1314         301 :         return TRUE;
    1315             : }
    1316             : 
    1317             : 
    1318         301 : dbus_bool_t wpas_dbus_getter_p2p_peer_manufacturer(
    1319             :         const struct wpa_dbus_property_desc *property_desc,
    1320             :         DBusMessageIter *iter, DBusError *error, void *user_data)
    1321             : {
    1322         301 :         struct peer_handler_args *peer_args = user_data;
    1323             :         const struct p2p_peer_info *info;
    1324             :         char *tmp;
    1325             : 
    1326         301 :         if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error))
    1327           0 :                 return FALSE;
    1328             : 
    1329             :         /* get the peer info */
    1330         301 :         info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
    1331         301 :                                   peer_args->p2p_device_addr, 0);
    1332         301 :         if (info == NULL) {
    1333           0 :                 dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer");
    1334           0 :                 return FALSE;
    1335             :         }
    1336             : 
    1337         301 :         tmp = os_strdup(info->manufacturer);
    1338         301 :         if (!tmp) {
    1339           0 :                 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
    1340           0 :                 return FALSE;
    1341             :         }
    1342             : 
    1343         301 :         if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp,
    1344             :                                               error)) {
    1345           0 :                 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
    1346           0 :                 os_free(tmp);
    1347           0 :                 return FALSE;
    1348             :         }
    1349             : 
    1350         301 :         os_free(tmp);
    1351         301 :         return TRUE;
    1352             : }
    1353             : 
    1354             : 
    1355         301 : dbus_bool_t wpas_dbus_getter_p2p_peer_modelname(
    1356             :         const struct wpa_dbus_property_desc *property_desc,
    1357             :         DBusMessageIter *iter, DBusError *error, void *user_data)
    1358             : {
    1359         301 :         struct peer_handler_args *peer_args = user_data;
    1360             :         const struct p2p_peer_info *info;
    1361             :         char *tmp;
    1362             : 
    1363         301 :         if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error))
    1364           0 :                 return FALSE;
    1365             : 
    1366             :         /* get the peer info */
    1367         301 :         info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
    1368         301 :                                   peer_args->p2p_device_addr, 0);
    1369         301 :         if (info == NULL) {
    1370           0 :                 dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer");
    1371           0 :                 return FALSE;
    1372             :         }
    1373             : 
    1374         301 :         tmp = os_strdup(info->model_name);
    1375         301 :         if (!tmp) {
    1376           0 :                 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
    1377           0 :                 return FALSE;
    1378             :         }
    1379             : 
    1380         301 :         if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp,
    1381             :                                               error)) {
    1382           0 :                 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
    1383           0 :                 os_free(tmp);
    1384           0 :                 return FALSE;
    1385             :         }
    1386             : 
    1387         301 :         os_free(tmp);
    1388         301 :         return TRUE;
    1389             : }
    1390             : 
    1391             : 
    1392         301 : dbus_bool_t wpas_dbus_getter_p2p_peer_modelnumber(
    1393             :         const struct wpa_dbus_property_desc *property_desc,
    1394             :         DBusMessageIter *iter, DBusError *error, void *user_data)
    1395             : {
    1396         301 :         struct peer_handler_args *peer_args = user_data;
    1397             :         const struct p2p_peer_info *info;
    1398             :         char *tmp;
    1399             : 
    1400         301 :         if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error))
    1401           0 :                 return FALSE;
    1402             : 
    1403             :         /* get the peer info */
    1404         301 :         info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
    1405         301 :                                   peer_args->p2p_device_addr, 0);
    1406         301 :         if (info == NULL) {
    1407           0 :                 dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer");
    1408           0 :                 return FALSE;
    1409             :         }
    1410             : 
    1411         301 :         tmp = os_strdup(info->model_number);
    1412         301 :         if (!tmp) {
    1413           0 :                 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
    1414           0 :                 return FALSE;
    1415             :         }
    1416             : 
    1417         301 :         if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp,
    1418             :                                               error)) {
    1419           0 :                 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
    1420           0 :                 os_free(tmp);
    1421           0 :                 return FALSE;
    1422             :         }
    1423             : 
    1424         301 :         os_free(tmp);
    1425         301 :         return TRUE;
    1426             : }
    1427             : 
    1428             : 
    1429         301 : dbus_bool_t wpas_dbus_getter_p2p_peer_serialnumber(
    1430             :         const struct wpa_dbus_property_desc *property_desc,
    1431             :         DBusMessageIter *iter, DBusError *error, void *user_data)
    1432             : {
    1433         301 :         struct peer_handler_args *peer_args = user_data;
    1434             :         const struct p2p_peer_info *info;
    1435             :         char *tmp;
    1436             : 
    1437         301 :         if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error))
    1438           0 :                 return FALSE;
    1439             : 
    1440             :         /* get the peer info */
    1441         301 :         info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
    1442         301 :                                   peer_args->p2p_device_addr, 0);
    1443         301 :         if (info == NULL) {
    1444           0 :                 dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer");
    1445           0 :                 return FALSE;
    1446             :         }
    1447             : 
    1448         301 :         tmp = os_strdup(info->serial_number);
    1449         301 :         if (!tmp) {
    1450           0 :                 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
    1451           0 :                 return FALSE;
    1452             :         }
    1453             : 
    1454         301 :         if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp,
    1455             :                                               error)) {
    1456           0 :                 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
    1457           0 :                 os_free(tmp);
    1458           0 :                 return FALSE;
    1459             :         }
    1460             : 
    1461         301 :         os_free(tmp);
    1462         301 :         return TRUE;
    1463             : }
    1464             : 
    1465             : 
    1466         301 : dbus_bool_t wpas_dbus_getter_p2p_peer_primary_device_type(
    1467             :         const struct wpa_dbus_property_desc *property_desc,
    1468             :         DBusMessageIter *iter, DBusError *error, void *user_data)
    1469             : {
    1470         301 :         struct peer_handler_args *peer_args = user_data;
    1471             :         const struct p2p_peer_info *info;
    1472             : 
    1473         301 :         info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
    1474         301 :                                   peer_args->p2p_device_addr, 0);
    1475         301 :         if (info == NULL) {
    1476           0 :                 dbus_set_error(error, DBUS_ERROR_FAILED,
    1477             :                                "failed to find peer");
    1478           0 :                 return FALSE;
    1479             :         }
    1480             : 
    1481         301 :         if (!wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
    1482             :                                                     (char *)
    1483         301 :                                                     info->pri_dev_type,
    1484             :                                                     WPS_DEV_TYPE_LEN, error)) {
    1485           0 :                 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
    1486           0 :                 return FALSE;
    1487             :         }
    1488             : 
    1489         301 :         return TRUE;
    1490             : }
    1491             : 
    1492             : 
    1493         301 : dbus_bool_t wpas_dbus_getter_p2p_peer_config_method(
    1494             :         const struct wpa_dbus_property_desc *property_desc,
    1495             :         DBusMessageIter *iter, DBusError *error, void *user_data)
    1496             : {
    1497         301 :         struct peer_handler_args *peer_args = user_data;
    1498             :         const struct p2p_peer_info *info;
    1499             : 
    1500         301 :         info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
    1501         301 :                                   peer_args->p2p_device_addr, 0);
    1502         301 :         if (info == NULL) {
    1503           0 :                 dbus_set_error(error, DBUS_ERROR_FAILED,
    1504             :                                "failed to find peer");
    1505           0 :                 return FALSE;
    1506             :         }
    1507             : 
    1508         301 :         if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
    1509         301 :                                               &info->config_methods, error)) {
    1510           0 :                 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
    1511           0 :                 return FALSE;
    1512             :         }
    1513             : 
    1514         301 :         return TRUE;
    1515             : }
    1516             : 
    1517             : 
    1518         301 : dbus_bool_t wpas_dbus_getter_p2p_peer_level(
    1519             :         const struct wpa_dbus_property_desc *property_desc,
    1520             :         DBusMessageIter *iter, DBusError *error, void *user_data)
    1521             : {
    1522         301 :         struct peer_handler_args *peer_args = user_data;
    1523             :         const struct p2p_peer_info *info;
    1524             : 
    1525         301 :         info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
    1526         301 :                                   peer_args->p2p_device_addr, 0);
    1527         301 :         if (info == NULL) {
    1528           0 :                 dbus_set_error(error, DBUS_ERROR_FAILED,
    1529             :                                "failed to find peer");
    1530           0 :                 return FALSE;
    1531             :         }
    1532             : 
    1533         301 :         if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
    1534         301 :                                               &info->level, error)) {
    1535           0 :                 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
    1536           0 :                 return FALSE;
    1537             :         }
    1538             : 
    1539         301 :         return TRUE;
    1540             : }
    1541             : 
    1542             : 
    1543         301 : dbus_bool_t wpas_dbus_getter_p2p_peer_device_capability(
    1544             :         const struct wpa_dbus_property_desc *property_desc,
    1545             :         DBusMessageIter *iter, DBusError *error, void *user_data)
    1546             : {
    1547         301 :         struct peer_handler_args *peer_args = user_data;
    1548             :         const struct p2p_peer_info *info;
    1549             : 
    1550         301 :         info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
    1551         301 :                                   peer_args->p2p_device_addr, 0);
    1552         301 :         if (info == NULL) {
    1553           0 :                 dbus_set_error(error, DBUS_ERROR_FAILED,
    1554             :                                "failed to find peer");
    1555           0 :                 return FALSE;
    1556             :         }
    1557             : 
    1558         301 :         if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BYTE,
    1559         301 :                                               &info->dev_capab, error)) {
    1560           0 :                 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
    1561           0 :                 return FALSE;
    1562             :         }
    1563             : 
    1564         301 :         return TRUE;
    1565             : }
    1566             : 
    1567             : 
    1568         301 : dbus_bool_t wpas_dbus_getter_p2p_peer_group_capability(
    1569             :         const struct wpa_dbus_property_desc *property_desc,
    1570             :         DBusMessageIter *iter, DBusError *error, void *user_data)
    1571             : {
    1572         301 :         struct peer_handler_args *peer_args = user_data;
    1573             :         const struct p2p_peer_info *info;
    1574             : 
    1575         301 :         info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
    1576         301 :                                   peer_args->p2p_device_addr, 0);
    1577         301 :         if (info == NULL) {
    1578           0 :                 dbus_set_error(error, DBUS_ERROR_FAILED,
    1579             :                                "failed to find peer");
    1580           0 :                 return FALSE;
    1581             :         }
    1582             : 
    1583         301 :         if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BYTE,
    1584         301 :                                               &info->group_capab, error)) {
    1585           0 :                 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
    1586           0 :                 return FALSE;
    1587             :         }
    1588             : 
    1589         301 :         return TRUE;
    1590             : }
    1591             : 
    1592             : 
    1593         301 : dbus_bool_t wpas_dbus_getter_p2p_peer_secondary_device_types(
    1594             :         const struct wpa_dbus_property_desc *property_desc,
    1595             :         DBusMessageIter *iter, DBusError *error, void *user_data)
    1596             : {
    1597         301 :         struct peer_handler_args *peer_args = user_data;
    1598             :         const struct p2p_peer_info *info;
    1599             :         DBusMessageIter variant_iter, array_iter;
    1600             : 
    1601         301 :         info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
    1602         301 :                                   peer_args->p2p_device_addr, 0);
    1603         301 :         if (info == NULL) {
    1604           0 :                 dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer");
    1605           0 :                 return FALSE;
    1606             :         }
    1607             : 
    1608         301 :         if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
    1609             :                                               DBUS_TYPE_ARRAY_AS_STRING
    1610             :                                               DBUS_TYPE_ARRAY_AS_STRING
    1611             :                                               DBUS_TYPE_BYTE_AS_STRING,
    1612         301 :                                               &variant_iter) ||
    1613         301 :             !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
    1614             :                                               DBUS_TYPE_ARRAY_AS_STRING
    1615             :                                               DBUS_TYPE_BYTE_AS_STRING,
    1616             :                                               &array_iter)) {
    1617           0 :                 dbus_set_error(error, DBUS_ERROR_FAILED,
    1618             :                                "%s: failed to construct message 1", __func__);
    1619           0 :                 return FALSE;
    1620             :         }
    1621             : 
    1622         301 :         if (info->wps_sec_dev_type_list_len) {
    1623          25 :                 const u8 *sec_dev_type_list = info->wps_sec_dev_type_list;
    1624          25 :                 int num_sec_device_types =
    1625          25 :                         info->wps_sec_dev_type_list_len / WPS_DEV_TYPE_LEN;
    1626             :                 int i;
    1627             :                 DBusMessageIter inner_array_iter;
    1628             : 
    1629          54 :                 for (i = 0; i < num_sec_device_types; i++) {
    1630          29 :                         if (!dbus_message_iter_open_container(
    1631             :                                     &array_iter, DBUS_TYPE_ARRAY,
    1632             :                                     DBUS_TYPE_BYTE_AS_STRING,
    1633          29 :                                     &inner_array_iter) ||
    1634          29 :                             !dbus_message_iter_append_fixed_array(
    1635             :                                     &inner_array_iter, DBUS_TYPE_BYTE,
    1636          29 :                                     &sec_dev_type_list, WPS_DEV_TYPE_LEN) ||
    1637          29 :                             !dbus_message_iter_close_container(
    1638             :                                     &array_iter, &inner_array_iter)) {
    1639           0 :                                 dbus_set_error(error, DBUS_ERROR_FAILED,
    1640             :                                                "%s: failed to construct message 2 (%d)",
    1641             :                                                __func__, i);
    1642           0 :                                 return FALSE;
    1643             :                         }
    1644             : 
    1645          29 :                         sec_dev_type_list += WPS_DEV_TYPE_LEN;
    1646             :                 }
    1647             :         }
    1648             : 
    1649         602 :         if (!dbus_message_iter_close_container(&variant_iter, &array_iter) ||
    1650         301 :             !dbus_message_iter_close_container(iter, &variant_iter)) {
    1651           0 :                 dbus_set_error(error, DBUS_ERROR_FAILED,
    1652             :                                "%s: failed to construct message 3", __func__);
    1653           0 :                 return FALSE;
    1654             :         }
    1655             : 
    1656         301 :         return TRUE;
    1657             : }
    1658             : 
    1659             : 
    1660         301 : dbus_bool_t wpas_dbus_getter_p2p_peer_vendor_extension(
    1661             :         const struct wpa_dbus_property_desc *property_desc,
    1662             :         DBusMessageIter *iter, DBusError *error, void *user_data)
    1663             : {
    1664             :         struct wpabuf *vendor_extension[P2P_MAX_WPS_VENDOR_EXT];
    1665         301 :         unsigned int i, num = 0;
    1666         301 :         struct peer_handler_args *peer_args = user_data;
    1667             :         const struct p2p_peer_info *info;
    1668             : 
    1669         301 :         info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
    1670         301 :                                   peer_args->p2p_device_addr, 0);
    1671         301 :         if (info == NULL) {
    1672           0 :                 dbus_set_error(error, DBUS_ERROR_FAILED,
    1673             :                                "failed to find peer");
    1674           0 :                 return FALSE;
    1675             :         }
    1676             : 
    1677             :         /* Add WPS vendor extensions attribute */
    1678         301 :         os_memset(vendor_extension, 0, sizeof(vendor_extension));
    1679        3311 :         for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
    1680        3010 :                 if (info->wps_vendor_ext[i] == NULL)
    1681        3008 :                         continue;
    1682           2 :                 vendor_extension[num] = info->wps_vendor_ext[i];
    1683           2 :                 num++;
    1684             :         }
    1685             : 
    1686         301 :         if (!wpas_dbus_simple_array_array_property_getter(iter, DBUS_TYPE_BYTE,
    1687             :                                                           vendor_extension,
    1688             :                                                           num, error))
    1689           0 :                 return FALSE;
    1690             : 
    1691         301 :         return TRUE;
    1692             : }
    1693             : 
    1694             : 
    1695         301 : dbus_bool_t wpas_dbus_getter_p2p_peer_ies(
    1696             :         const struct wpa_dbus_property_desc *property_desc,
    1697             :         DBusMessageIter *iter, DBusError *error, void *user_data)
    1698             : {
    1699         301 :         struct peer_handler_args *peer_args = user_data;
    1700             :         const struct p2p_peer_info *info;
    1701             : 
    1702         301 :         info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
    1703         301 :                                   peer_args->p2p_device_addr, 0);
    1704         301 :         if (info == NULL) {
    1705           0 :                 dbus_set_error(error, DBUS_ERROR_FAILED,
    1706             :                                "failed to find peer");
    1707           0 :                 return FALSE;
    1708             :         }
    1709             : 
    1710         301 :         if (info->wfd_subelems == NULL)
    1711         291 :                 return wpas_dbus_simple_array_property_getter(iter,
    1712             :                                                               DBUS_TYPE_BYTE,
    1713             :                                                               NULL, 0, error);
    1714             : 
    1715          20 :         return wpas_dbus_simple_array_property_getter(
    1716          10 :                 iter, DBUS_TYPE_BYTE, (char *) info->wfd_subelems->buf,
    1717          10 :                 info->wfd_subelems->used, error);
    1718             : }
    1719             : 
    1720             : 
    1721         301 : dbus_bool_t wpas_dbus_getter_p2p_peer_device_address(
    1722             :         const struct wpa_dbus_property_desc *property_desc,
    1723             :         DBusMessageIter *iter, DBusError *error, void *user_data)
    1724             : {
    1725         301 :         struct peer_handler_args *peer_args = user_data;
    1726             :         const struct p2p_peer_info *info;
    1727             : 
    1728         301 :         info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
    1729         301 :                                   peer_args->p2p_device_addr, 0);
    1730         301 :         if (info == NULL) {
    1731           0 :                 dbus_set_error(error, DBUS_ERROR_FAILED,
    1732             :                                "failed to find peer");
    1733           0 :                 return FALSE;
    1734             :         }
    1735             : 
    1736         301 :         return wpas_dbus_simple_array_property_getter(
    1737         301 :                 iter, DBUS_TYPE_BYTE, (char *) info->p2p_device_addr,
    1738             :                 ETH_ALEN, error);
    1739             : }
    1740             : 
    1741             : 
    1742             : struct peer_group_data {
    1743             :         struct wpa_supplicant *wpa_s;
    1744             :         const struct p2p_peer_info *info;
    1745             :         char **paths;
    1746             :         unsigned int nb_paths;
    1747             :         int error;
    1748             : };
    1749             : 
    1750             : 
    1751         531 : static int match_group_where_peer_is_client(struct p2p_group *group,
    1752             :                                             void *user_data)
    1753             : {
    1754         531 :         struct peer_group_data *data = user_data;
    1755             :         const struct p2p_group_config *cfg;
    1756             :         struct wpa_supplicant *wpa_s_go;
    1757             :         char **paths;
    1758             : 
    1759         531 :         if (!p2p_group_is_client_connected(group, data->info->p2p_device_addr))
    1760         112 :                 return 1;
    1761             : 
    1762         419 :         cfg = p2p_group_get_config(group);
    1763             : 
    1764         419 :         wpa_s_go = wpas_get_p2p_go_iface(data->wpa_s, cfg->ssid,
    1765             :                                          cfg->ssid_len);
    1766         419 :         if (wpa_s_go == NULL)
    1767           0 :                 return 1;
    1768             : 
    1769         419 :         paths = os_realloc_array(data->paths, data->nb_paths + 1,
    1770             :                                  sizeof(char *));
    1771         419 :         if (paths == NULL)
    1772           0 :                 goto out_of_memory;
    1773             : 
    1774         419 :         data->paths = paths;
    1775         419 :         data->paths[data->nb_paths] = wpa_s_go->dbus_groupobj_path;
    1776         419 :         data->nb_paths++;
    1777             : 
    1778         419 :         return 1;
    1779             : 
    1780             : out_of_memory:
    1781           0 :         data->error = ENOMEM;
    1782           0 :         return 0;
    1783             : }
    1784             : 
    1785             : 
    1786        1295 : dbus_bool_t wpas_dbus_getter_p2p_peer_groups(
    1787             :         const struct wpa_dbus_property_desc *property_desc,
    1788             :         DBusMessageIter *iter, DBusError *error, void *user_data)
    1789             : {
    1790        1295 :         struct peer_handler_args *peer_args = user_data;
    1791             :         const struct p2p_peer_info *info;
    1792             :         struct peer_group_data data;
    1793             :         struct wpa_supplicant *wpa_s, *wpa_s_go;
    1794        1295 :         dbus_bool_t success = FALSE;
    1795             : 
    1796        1295 :         info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
    1797        1295 :                                   peer_args->p2p_device_addr, 0);
    1798        1295 :         if (info == NULL) {
    1799           0 :                 dbus_set_error(error, DBUS_ERROR_FAILED,
    1800             :                                "failed to find peer");
    1801           0 :                 return FALSE;
    1802             :         }
    1803             : 
    1804        1295 :         os_memset(&data, 0, sizeof(data));
    1805             : 
    1806        1295 :         wpa_s = peer_args->wpa_s;
    1807        1295 :         wpa_s = wpa_s->global->p2p_init_wpa_s;
    1808             : 
    1809        1295 :         wpa_s_go = wpas_get_p2p_client_iface(wpa_s, info->p2p_device_addr);
    1810        1295 :         if (wpa_s_go) {
    1811         120 :                 data.paths = os_calloc(1, sizeof(char *));
    1812         120 :                 if (data.paths == NULL)
    1813           0 :                         goto out_of_memory;
    1814         120 :                 data.paths[0] = wpa_s_go->dbus_groupobj_path;
    1815         120 :                 data.nb_paths = 1;
    1816             :         }
    1817             : 
    1818        1295 :         data.wpa_s = peer_args->wpa_s;
    1819        1295 :         data.info = info;
    1820             : 
    1821        1295 :         p2p_loop_on_all_groups(peer_args->wpa_s->global->p2p,
    1822             :                                match_group_where_peer_is_client, &data);
    1823        1295 :         if (data.error)
    1824           0 :                 goto out_of_memory;
    1825             : 
    1826        1295 :         if (data.paths == NULL) {
    1827         756 :                 return wpas_dbus_simple_array_property_getter(
    1828             :                         iter, DBUS_TYPE_OBJECT_PATH, NULL, 0, error);
    1829             :         }
    1830             : 
    1831        1078 :         success = wpas_dbus_simple_array_property_getter(iter,
    1832             :                                                          DBUS_TYPE_OBJECT_PATH,
    1833         539 :                                                          data.paths,
    1834         539 :                                                          data.nb_paths, error);
    1835         539 :         goto out;
    1836             : 
    1837             : out_of_memory:
    1838           0 :         dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
    1839             : out:
    1840         539 :         os_free(data.paths);
    1841         539 :         return success;
    1842             : }
    1843             : 
    1844             : 
    1845             : /**
    1846             :  * wpas_dbus_getter_persistent_groups - Get array of persistent group objects
    1847             :  * @iter: Pointer to incoming dbus message iter
    1848             :  * @error: Location to store error on failure
    1849             :  * @user_data: Function specific data
    1850             :  * Returns: TRUE on success, FALSE on failure
    1851             :  *
    1852             :  * Getter for "PersistentGroups" property.
    1853             :  */
    1854           6 : dbus_bool_t wpas_dbus_getter_persistent_groups(
    1855             :         const struct wpa_dbus_property_desc *property_desc,
    1856             :         DBusMessageIter *iter, DBusError *error, void *user_data)
    1857             : {
    1858           6 :         struct wpa_supplicant *wpa_s = user_data;
    1859             :         struct wpa_ssid *ssid;
    1860             :         char **paths;
    1861           6 :         unsigned int i = 0, num = 0;
    1862           6 :         dbus_bool_t success = FALSE;
    1863             : 
    1864           6 :         wpa_s = wpa_s->global->p2p_init_wpa_s;
    1865           6 :         if (!wpa_s->parent->dbus_new_path)
    1866           0 :                 return FALSE;
    1867             : 
    1868           8 :         for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
    1869           2 :                 if (network_is_persistent_group(ssid))
    1870           2 :                         num++;
    1871             : 
    1872           6 :         paths = os_calloc(num, sizeof(char *));
    1873           6 :         if (!paths) {
    1874           0 :                 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
    1875           0 :                 return FALSE;
    1876             :         }
    1877             : 
    1878             :         /* Loop through configured networks and append object path of each */
    1879           8 :         for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
    1880           2 :                 if (!network_is_persistent_group(ssid))
    1881           0 :                         continue;
    1882           2 :                 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
    1883           2 :                 if (paths[i] == NULL) {
    1884           0 :                         dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
    1885             :                                              "no memory");
    1886           0 :                         goto out;
    1887             :                 }
    1888             :                 /* Construct the object path for this network. */
    1889           4 :                 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
    1890             :                             "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%d",
    1891           2 :                             wpa_s->parent->dbus_new_path, ssid->id);
    1892             :         }
    1893             : 
    1894           6 :         success = wpas_dbus_simple_array_property_getter(iter,
    1895             :                                                          DBUS_TYPE_OBJECT_PATH,
    1896             :                                                          paths, num, error);
    1897             : 
    1898             : out:
    1899          14 :         while (i)
    1900           2 :                 os_free(paths[--i]);
    1901           6 :         os_free(paths);
    1902           6 :         return success;
    1903             : }
    1904             : 
    1905             : 
    1906             : /**
    1907             :  * wpas_dbus_getter_persistent_group_properties - Get options for a persistent
    1908             :  *      group
    1909             :  * @iter: Pointer to incoming dbus message iter
    1910             :  * @error: Location to store error on failure
    1911             :  * @user_data: Function specific data
    1912             :  * Returns: TRUE on success, FALSE on failure
    1913             :  *
    1914             :  * Getter for "Properties" property of a persistent group.
    1915             :  */
    1916          79 : dbus_bool_t wpas_dbus_getter_persistent_group_properties(
    1917             :         const struct wpa_dbus_property_desc *property_desc,
    1918             :         DBusMessageIter *iter, DBusError *error, void *user_data)
    1919             : {
    1920          79 :         struct network_handler_args *net = user_data;
    1921             : 
    1922             :         /* Leveraging the fact that persistent group object is still
    1923             :          * represented in same manner as network within.
    1924             :          */
    1925          79 :         return wpas_dbus_getter_network_properties(property_desc, iter, error, net);
    1926             : }
    1927             : 
    1928             : 
    1929             : /**
    1930             :  * wpas_dbus_setter_persistent_group_properties - Set options for a persistent
    1931             :  *      group
    1932             :  * @iter: Pointer to incoming dbus message iter
    1933             :  * @error: Location to store error on failure
    1934             :  * @user_data: Function specific data
    1935             :  * Returns: TRUE on success, FALSE on failure
    1936             :  *
    1937             :  * Setter for "Properties" property of a persistent group.
    1938             :  */
    1939           1 : dbus_bool_t wpas_dbus_setter_persistent_group_properties(
    1940             :         const struct wpa_dbus_property_desc *property_desc,
    1941             :         DBusMessageIter *iter, DBusError *error, void *user_data)
    1942             : {
    1943           1 :         struct network_handler_args *net = user_data;
    1944           1 :         struct wpa_ssid *ssid = net->ssid;
    1945             :         DBusMessageIter variant_iter;
    1946             : 
    1947             :         /*
    1948             :          * Leveraging the fact that persistent group object is still
    1949             :          * represented in same manner as network within.
    1950             :          */
    1951           1 :         dbus_message_iter_recurse(iter, &variant_iter);
    1952           1 :         return set_network_properties(net->wpa_s, ssid, &variant_iter, error);
    1953             : }
    1954             : 
    1955             : 
    1956             : /**
    1957             :  * wpas_dbus_new_iface_add_persistent_group - Add a new configured
    1958             :  *      persistent_group
    1959             :  * @message: Pointer to incoming dbus message
    1960             :  * @wpa_s: wpa_supplicant structure for a network interface
    1961             :  * Returns: A dbus message containing the object path of the new
    1962             :  * persistent group
    1963             :  *
    1964             :  * Handler function for "AddPersistentGroup" method call of a P2P Device
    1965             :  * interface.
    1966             :  */
    1967           1 : DBusMessage * wpas_dbus_handler_add_persistent_group(
    1968             :         DBusMessage *message, struct wpa_supplicant *wpa_s)
    1969             : {
    1970           1 :         DBusMessage *reply = NULL;
    1971             :         DBusMessageIter iter;
    1972           1 :         struct wpa_ssid *ssid = NULL;
    1973           1 :         char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf;
    1974             :         DBusError error;
    1975             : 
    1976           1 :         dbus_message_iter_init(message, &iter);
    1977             : 
    1978           1 :         wpa_s = wpa_s->global->p2p_init_wpa_s;
    1979           1 :         if (wpa_s->parent->dbus_new_path)
    1980           1 :                 ssid = wpa_config_add_network(wpa_s->conf);
    1981           1 :         if (ssid == NULL) {
    1982           0 :                 wpa_printf(MSG_ERROR,
    1983             :                            "dbus: %s: Cannot add new persistent group",
    1984             :                            __func__);
    1985           0 :                 reply = wpas_dbus_error_unknown_error(
    1986             :                         message,
    1987             :                         "wpa_supplicant could not add a persistent group on this interface.");
    1988           0 :                 goto err;
    1989             :         }
    1990             : 
    1991             :         /* Mark the ssid as being a persistent group before the notification */
    1992           1 :         ssid->disabled = 2;
    1993           1 :         ssid->p2p_persistent_group = 1;
    1994           1 :         wpas_notify_persistent_group_added(wpa_s, ssid);
    1995             : 
    1996           1 :         wpa_config_set_network_defaults(ssid);
    1997             : 
    1998           1 :         dbus_error_init(&error);
    1999           1 :         if (!set_network_properties(wpa_s, ssid, &iter, &error)) {
    2000           0 :                 wpa_printf(MSG_DEBUG,
    2001             :                            "dbus: %s: Control interface could not set persistent group properties",
    2002             :                            __func__);
    2003           0 :                 reply = wpas_dbus_reply_new_from_error(
    2004             :                         message, &error, DBUS_ERROR_INVALID_ARGS,
    2005             :                         "Failed to set network properties");
    2006           0 :                 dbus_error_free(&error);
    2007           0 :                 goto err;
    2008             :         }
    2009             : 
    2010             :         /* Construct the object path for this network. */
    2011           2 :         os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
    2012             :                     "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%d",
    2013           1 :                     wpa_s->parent->dbus_new_path, ssid->id);
    2014             : 
    2015           1 :         reply = dbus_message_new_method_return(message);
    2016           1 :         if (reply == NULL) {
    2017           0 :                 reply = wpas_dbus_error_no_memory(message);
    2018           0 :                 goto err;
    2019             :         }
    2020           1 :         if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
    2021             :                                       DBUS_TYPE_INVALID)) {
    2022           0 :                 dbus_message_unref(reply);
    2023           0 :                 reply = wpas_dbus_error_no_memory(message);
    2024           0 :                 goto err;
    2025             :         }
    2026             : 
    2027           1 :         return reply;
    2028             : 
    2029             : err:
    2030           0 :         if (ssid) {
    2031           0 :                 wpas_notify_persistent_group_removed(wpa_s, ssid);
    2032           0 :                 wpa_config_remove_network(wpa_s->conf, ssid->id);
    2033             :         }
    2034           0 :         return reply;
    2035             : }
    2036             : 
    2037             : 
    2038             : /**
    2039             :  * wpas_dbus_handler_remove_persistent_group - Remove a configured persistent
    2040             :  *      group
    2041             :  * @message: Pointer to incoming dbus message
    2042             :  * @wpa_s: wpa_supplicant structure for a network interface
    2043             :  * Returns: NULL on success or dbus error on failure
    2044             :  *
    2045             :  * Handler function for "RemovePersistentGroup" method call of a P2P Device
    2046             :  * interface.
    2047             :  */
    2048           5 : DBusMessage * wpas_dbus_handler_remove_persistent_group(
    2049             :         DBusMessage *message, struct wpa_supplicant *wpa_s)
    2050             : {
    2051           5 :         DBusMessage *reply = NULL;
    2052             :         const char *op;
    2053           5 :         char *iface = NULL, *persistent_group_id;
    2054             :         int id;
    2055             :         struct wpa_ssid *ssid;
    2056             : 
    2057           5 :         dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
    2058             :                               DBUS_TYPE_INVALID);
    2059             : 
    2060           5 :         wpa_s = wpa_s->global->p2p_init_wpa_s;
    2061             : 
    2062             :         /*
    2063             :          * Extract the network ID and ensure the network is actually a child of
    2064             :          * this interface.
    2065             :          */
    2066           5 :         iface = wpas_dbus_new_decompose_object_path(
    2067             :                 op, WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART,
    2068             :                 &persistent_group_id);
    2069           7 :         if (iface == NULL || persistent_group_id == NULL ||
    2070           4 :             !wpa_s->parent->dbus_new_path ||
    2071           2 :             os_strcmp(iface, wpa_s->parent->dbus_new_path) != 0) {
    2072           3 :                 reply = wpas_dbus_error_invalid_args(message, op);
    2073           3 :                 goto out;
    2074             :         }
    2075             : 
    2076           2 :         id = strtoul(persistent_group_id, NULL, 10);
    2077           2 :         if (errno == EINVAL) {
    2078           0 :                 reply = wpas_dbus_error_invalid_args(message, op);
    2079           0 :                 goto out;
    2080             :         }
    2081             : 
    2082           2 :         ssid = wpa_config_get_network(wpa_s->conf, id);
    2083           2 :         if (ssid == NULL) {
    2084           1 :                 reply = wpas_dbus_error_persistent_group_unknown(message);
    2085           1 :                 goto out;
    2086             :         }
    2087             : 
    2088           1 :         wpas_notify_persistent_group_removed(wpa_s, ssid);
    2089             : 
    2090           1 :         if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
    2091           0 :                 wpa_printf(MSG_ERROR,
    2092             :                            "dbus: %s: error occurred when removing persistent group %d",
    2093             :                            __func__, id);
    2094           0 :                 reply = wpas_dbus_error_unknown_error(
    2095             :                         message,
    2096             :                         "error removing the specified persistent group on this interface.");
    2097           0 :                 goto out;
    2098             :         }
    2099             : 
    2100             : out:
    2101           5 :         os_free(iface);
    2102           5 :         return reply;
    2103             : }
    2104             : 
    2105             : 
    2106           2 : static void remove_persistent_group(struct wpa_supplicant *wpa_s,
    2107             :                                     struct wpa_ssid *ssid)
    2108             : {
    2109           2 :         wpas_notify_persistent_group_removed(wpa_s, ssid);
    2110             : 
    2111           2 :         if (wpa_config_remove_network(wpa_s->conf, ssid->id) < 0) {
    2112           0 :                 wpa_printf(MSG_ERROR,
    2113             :                            "dbus: %s: error occurred when removing persistent group %d",
    2114             :                            __func__, ssid->id);
    2115           0 :                 return;
    2116             :         }
    2117             : }
    2118             : 
    2119             : 
    2120             : /**
    2121             :  * wpas_dbus_handler_remove_all_persistent_groups - Remove all configured
    2122             :  * persistent groups
    2123             :  * @message: Pointer to incoming dbus message
    2124             :  * @wpa_s: wpa_supplicant structure for a network interface
    2125             :  * Returns: NULL on success or dbus error on failure
    2126             :  *
    2127             :  * Handler function for "RemoveAllPersistentGroups" method call of a
    2128             :  * P2P Device interface.
    2129             :  */
    2130           1 : DBusMessage * wpas_dbus_handler_remove_all_persistent_groups(
    2131             :         DBusMessage *message, struct wpa_supplicant *wpa_s)
    2132             : {
    2133             :         struct wpa_ssid *ssid, *next;
    2134             :         struct wpa_config *config;
    2135             : 
    2136           1 :         wpa_s = wpa_s->global->p2p_init_wpa_s;
    2137             : 
    2138           1 :         config = wpa_s->conf;
    2139           1 :         ssid = config->ssid;
    2140           4 :         while (ssid) {
    2141           2 :                 next = ssid->next;
    2142           2 :                 if (network_is_persistent_group(ssid))
    2143           2 :                         remove_persistent_group(wpa_s, ssid);
    2144           2 :                 ssid = next;
    2145             :         }
    2146           1 :         return NULL;
    2147             : }
    2148             : 
    2149             : 
    2150             : /*
    2151             :  * Group object properties accessor methods
    2152             :  */
    2153             : 
    2154           8 : dbus_bool_t wpas_dbus_getter_p2p_group_members(
    2155             :         const struct wpa_dbus_property_desc *property_desc,
    2156             :         DBusMessageIter *iter, DBusError *error, void *user_data)
    2157             : {
    2158           8 :         struct wpa_supplicant *wpa_s = user_data;
    2159             :         struct wpa_ssid *ssid;
    2160             :         unsigned int num_members;
    2161             :         char **paths;
    2162             :         unsigned int i;
    2163           8 :         void *next = NULL;
    2164             :         const u8 *addr;
    2165           8 :         dbus_bool_t success = FALSE;
    2166             : 
    2167           8 :         if (!wpa_s->parent->parent->dbus_new_path)
    2168           0 :                 return FALSE;
    2169             : 
    2170             :         /* Verify correct role for this property */
    2171           8 :         if (wpas_get_p2p_role(wpa_s) != WPAS_P2P_ROLE_GO) {
    2172           3 :                 return wpas_dbus_simple_array_property_getter(
    2173             :                         iter, DBUS_TYPE_OBJECT_PATH, NULL, 0, error);
    2174             :         }
    2175             : 
    2176           5 :         ssid = wpa_s->conf->ssid;
    2177             :         /* At present WPAS P2P_GO mode only applicable for p2p_go */
    2178           5 :         if (ssid->mode != WPAS_MODE_P2P_GO &&
    2179           0 :             ssid->mode != WPAS_MODE_AP &&
    2180           0 :             ssid->mode != WPAS_MODE_P2P_GROUP_FORMATION)
    2181           0 :                 return FALSE;
    2182             : 
    2183           5 :         num_members = p2p_get_group_num_members(wpa_s->p2p_group);
    2184             : 
    2185           5 :         paths = os_calloc(num_members, sizeof(char *));
    2186           5 :         if (!paths)
    2187           0 :                 goto out_of_memory;
    2188             : 
    2189           5 :         i = 0;
    2190          12 :         while ((addr = p2p_iterate_group_members(wpa_s->p2p_group, &next))) {
    2191           2 :                 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
    2192           2 :                 if (!paths[i])
    2193           0 :                         goto out_of_memory;
    2194          14 :                 os_snprintf(paths[i], WPAS_DBUS_OBJECT_PATH_MAX,
    2195             :                             "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART
    2196             :                             "/" COMPACT_MACSTR,
    2197           2 :                             wpa_s->parent->parent->dbus_new_path,
    2198          12 :                             MAC2STR(addr));
    2199           2 :                 i++;
    2200             :         }
    2201             : 
    2202           5 :         success = wpas_dbus_simple_array_property_getter(iter,
    2203             :                                                          DBUS_TYPE_OBJECT_PATH,
    2204             :                                                          paths, num_members,
    2205             :                                                          error);
    2206             : 
    2207           7 :         for (i = 0; i < num_members; i++)
    2208           2 :                 os_free(paths[i]);
    2209           5 :         os_free(paths);
    2210           5 :         return success;
    2211             : 
    2212             : out_of_memory:
    2213           0 :         dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
    2214           0 :         if (paths) {
    2215           0 :                 for (i = 0; i < num_members; i++)
    2216           0 :                         os_free(paths[i]);
    2217           0 :                 os_free(paths);
    2218             :         }
    2219           0 :         return FALSE;
    2220             : }
    2221             : 
    2222             : 
    2223           8 : dbus_bool_t wpas_dbus_getter_p2p_group_ssid(
    2224             :         const struct wpa_dbus_property_desc *property_desc,
    2225             :         DBusMessageIter *iter, DBusError *error, void *user_data)
    2226             : {
    2227           8 :         struct wpa_supplicant *wpa_s = user_data;
    2228             : 
    2229           8 :         if (wpa_s->current_ssid == NULL)
    2230           0 :                 return FALSE;
    2231          16 :         return wpas_dbus_simple_array_property_getter(
    2232           8 :                 iter, DBUS_TYPE_BYTE, wpa_s->current_ssid->ssid,
    2233           8 :                 wpa_s->current_ssid->ssid_len, error);
    2234             : }
    2235             : 
    2236             : 
    2237           8 : dbus_bool_t wpas_dbus_getter_p2p_group_bssid(
    2238             :         const struct wpa_dbus_property_desc *property_desc,
    2239             :         DBusMessageIter *iter, DBusError *error, void *user_data)
    2240             : {
    2241           8 :         struct wpa_supplicant *wpa_s = user_data;
    2242           8 :         u8 role = wpas_get_p2p_role(wpa_s);
    2243             :         u8 *p_bssid;
    2244             : 
    2245           8 :         if (role == WPAS_P2P_ROLE_CLIENT) {
    2246           3 :                 if (wpa_s->current_ssid == NULL)
    2247           0 :                         return FALSE;
    2248           3 :                 p_bssid = wpa_s->current_ssid->bssid;
    2249             :         } else {
    2250           5 :                 if (wpa_s->ap_iface == NULL)
    2251           0 :                         return FALSE;
    2252           5 :                 p_bssid = wpa_s->ap_iface->bss[0]->own_addr;
    2253             :         }
    2254             : 
    2255           8 :         return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
    2256             :                                                       p_bssid, ETH_ALEN,
    2257             :                                                       error);
    2258             : }
    2259             : 
    2260             : 
    2261           8 : dbus_bool_t wpas_dbus_getter_p2p_group_frequency(
    2262             :         const struct wpa_dbus_property_desc *property_desc,
    2263             :         DBusMessageIter *iter, DBusError *error, void *user_data)
    2264             : {
    2265           8 :         struct wpa_supplicant *wpa_s = user_data;
    2266             :         u16 op_freq;
    2267           8 :         u8 role = wpas_get_p2p_role(wpa_s);
    2268             : 
    2269           8 :         if (role == WPAS_P2P_ROLE_CLIENT) {
    2270           3 :                 if (wpa_s->go_params == NULL)
    2271           0 :                         return FALSE;
    2272           3 :                 op_freq = wpa_s->go_params->freq;
    2273             :         } else {
    2274           5 :                 if (wpa_s->ap_iface == NULL)
    2275           0 :                         return FALSE;
    2276           5 :                 op_freq = wpa_s->ap_iface->freq;
    2277             :         }
    2278             : 
    2279           8 :         return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
    2280             :                                                 &op_freq, error);
    2281             : }
    2282             : 
    2283             : 
    2284           8 : dbus_bool_t wpas_dbus_getter_p2p_group_passphrase(
    2285             :         const struct wpa_dbus_property_desc *property_desc,
    2286             :         DBusMessageIter *iter, DBusError *error, void *user_data)
    2287             : {
    2288           8 :         struct wpa_supplicant *wpa_s = user_data;
    2289             :         char *p_pass;
    2290           8 :         struct wpa_ssid *ssid = wpa_s->current_ssid;
    2291             : 
    2292           8 :         if (ssid == NULL)
    2293           0 :                 return FALSE;
    2294             : 
    2295           8 :         p_pass = ssid->passphrase;
    2296           8 :         if (!p_pass)
    2297           3 :                 p_pass = "";
    2298             : 
    2299           8 :         return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
    2300             :                                                 &p_pass, error);
    2301             : 
    2302             : }
    2303             : 
    2304             : 
    2305           8 : dbus_bool_t wpas_dbus_getter_p2p_group_psk(
    2306             :         const struct wpa_dbus_property_desc *property_desc,
    2307             :         DBusMessageIter *iter, DBusError *error, void *user_data)
    2308             : {
    2309           8 :         struct wpa_supplicant *wpa_s = user_data;
    2310           8 :         u8 *p_psk = NULL;
    2311           8 :         u8 psk_len = 0;
    2312           8 :         struct wpa_ssid *ssid = wpa_s->current_ssid;
    2313             : 
    2314           8 :         if (ssid == NULL)
    2315           0 :                 return FALSE;
    2316             : 
    2317           8 :         if (ssid->psk_set) {
    2318           8 :                 p_psk = ssid->psk;
    2319           8 :                 psk_len = sizeof(ssid->psk);
    2320             :         }
    2321             : 
    2322           8 :         return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
    2323             :                                                       p_psk, psk_len, error);
    2324             : }
    2325             : 
    2326             : 
    2327          10 : dbus_bool_t wpas_dbus_getter_p2p_group_vendor_ext(
    2328             :         const struct wpa_dbus_property_desc *property_desc,
    2329             :         DBusMessageIter *iter, DBusError *error, void *user_data)
    2330             : {
    2331          10 :         struct wpa_supplicant *wpa_s = user_data;
    2332             :         struct hostapd_data *hapd;
    2333             :         struct wpabuf *vendor_ext[MAX_WPS_VENDOR_EXTENSIONS];
    2334          10 :         unsigned int i, num_vendor_ext = 0;
    2335             : 
    2336          10 :         os_memset(vendor_ext, 0, sizeof(vendor_ext));
    2337             : 
    2338             :         /* Verify correct role for this property */
    2339          10 :         if (wpas_get_p2p_role(wpa_s) == WPAS_P2P_ROLE_GO) {
    2340           7 :                 if (wpa_s->ap_iface == NULL)
    2341           0 :                         return FALSE;
    2342           7 :                 hapd = wpa_s->ap_iface->bss[0];
    2343             : 
    2344             :                 /* Parse WPS Vendor Extensions sent in Beacon/Probe Response */
    2345          77 :                 for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
    2346          70 :                         if (hapd->conf->wps_vendor_ext[i] == NULL)
    2347          67 :                                 continue;
    2348           6 :                         vendor_ext[num_vendor_ext++] =
    2349           3 :                                 hapd->conf->wps_vendor_ext[i];
    2350             :                 }
    2351             :         }
    2352             : 
    2353             :         /* Return vendor extensions or no data */
    2354          10 :         return wpas_dbus_simple_array_array_property_getter(iter,
    2355             :                                                             DBUS_TYPE_BYTE,
    2356             :                                                             vendor_ext,
    2357             :                                                             num_vendor_ext,
    2358             :                                                             error);
    2359             : }
    2360             : 
    2361             : 
    2362           7 : dbus_bool_t wpas_dbus_setter_p2p_group_vendor_ext(
    2363             :         const struct wpa_dbus_property_desc *property_desc,
    2364             :         DBusMessageIter *iter, DBusError *error, void *user_data)
    2365             : {
    2366           7 :         struct wpa_supplicant *wpa_s = user_data;
    2367             :         DBusMessageIter variant_iter, iter_dict, array_iter, sub;
    2368           7 :         struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
    2369             :         unsigned int i;
    2370           7 :         struct hostapd_data *hapd = NULL;
    2371             : 
    2372          13 :         if (wpas_get_p2p_role(wpa_s) == WPAS_P2P_ROLE_GO &&
    2373           6 :             wpa_s->ap_iface != NULL)
    2374           6 :                 hapd = wpa_s->ap_iface->bss[0];
    2375             :         else
    2376           1 :                 return FALSE;
    2377             : 
    2378           6 :         dbus_message_iter_recurse(iter, &variant_iter);
    2379           6 :         if (dbus_message_iter_get_arg_type(&variant_iter) != DBUS_TYPE_ARRAY)
    2380           0 :                 return FALSE;
    2381             : 
    2382             :         /*
    2383             :          * This is supposed to be array of bytearrays (aay), but the earlier
    2384             :          * implementation used a dict with "WPSVendorExtensions" as the key in
    2385             :          * this setter function which does not match the format used by the
    2386             :          * getter function. For backwards compatibility, allow both formats to
    2387             :          * be used in the setter.
    2388             :          */
    2389           6 :         if (dbus_message_iter_get_element_type(&variant_iter) ==
    2390             :             DBUS_TYPE_ARRAY) {
    2391             :                 /* This is the proper format matching the getter */
    2392             :                 struct wpabuf *vals[MAX_WPS_VENDOR_EXTENSIONS];
    2393             : 
    2394           3 :                 dbus_message_iter_recurse(&variant_iter, &array_iter);
    2395             : 
    2396           3 :                 if (dbus_message_iter_get_arg_type(&array_iter) !=
    2397           3 :                     DBUS_TYPE_ARRAY ||
    2398           3 :                     dbus_message_iter_get_element_type(&array_iter) !=
    2399             :                     DBUS_TYPE_BYTE) {
    2400           1 :                         wpa_printf(MSG_DEBUG,
    2401             :                                    "dbus: Not an array of array of bytes");
    2402           1 :                         return FALSE;
    2403             :                 }
    2404             : 
    2405           2 :                 i = 0;
    2406           2 :                 os_memset(vals, 0, sizeof(vals));
    2407             : 
    2408          16 :                 while (dbus_message_iter_get_arg_type(&array_iter) ==
    2409             :                        DBUS_TYPE_ARRAY) {
    2410             :                         char *val;
    2411             :                         int len;
    2412             : 
    2413          13 :                         if (i == MAX_WPS_VENDOR_EXTENSIONS) {
    2414           1 :                                 wpa_printf(MSG_DEBUG,
    2415             :                                            "dbus: Too many WPSVendorExtensions values");
    2416           1 :                                 i = MAX_WPS_VENDOR_EXTENSIONS + 1;
    2417           2 :                                 break;
    2418             :                         }
    2419             : 
    2420          12 :                         dbus_message_iter_recurse(&array_iter, &sub);
    2421          12 :                         dbus_message_iter_get_fixed_array(&sub, &val, &len);
    2422          12 :                         wpa_hexdump(MSG_DEBUG, "dbus: WPSVendorExtentions[]",
    2423             :                                     val, len);
    2424          12 :                         vals[i] = wpabuf_alloc_copy(val, len);
    2425          12 :                         if (vals[i] == NULL) {
    2426           0 :                                 i = MAX_WPS_VENDOR_EXTENSIONS + 1;
    2427           0 :                                 break;
    2428             :                         }
    2429          12 :                         i++;
    2430          12 :                         dbus_message_iter_next(&array_iter);
    2431             :                 }
    2432             : 
    2433           2 :                 if (i > MAX_WPS_VENDOR_EXTENSIONS) {
    2434          11 :                         for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++)
    2435          10 :                                 wpabuf_free(vals[i]);
    2436           1 :                         return FALSE;
    2437             :                 }
    2438             : 
    2439          11 :                 for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
    2440          10 :                         wpabuf_free(hapd->conf->wps_vendor_ext[i]);
    2441          10 :                         hapd->conf->wps_vendor_ext[i] = vals[i];
    2442             :                 }
    2443             : 
    2444           1 :                 hostapd_update_wps(hapd);
    2445             : 
    2446           1 :                 return TRUE;
    2447             :         }
    2448             : 
    2449           3 :         if (dbus_message_iter_get_element_type(&variant_iter) !=
    2450             :             DBUS_TYPE_DICT_ENTRY)
    2451           1 :                 return FALSE;
    2452             : 
    2453           2 :         wpa_printf(MSG_DEBUG,
    2454             :                    "dbus: Try to use backwards compatibility version of WPSVendorExtensions setter");
    2455           2 :         if (!wpa_dbus_dict_open_read(&variant_iter, &iter_dict, error))
    2456           0 :                 return FALSE;
    2457             : 
    2458           5 :         while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
    2459           2 :                 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) {
    2460           0 :                         dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
    2461             :                                              "invalid message format");
    2462           0 :                         return FALSE;
    2463             :                 }
    2464             : 
    2465           2 :                 if (os_strcmp(entry.key, "WPSVendorExtensions") == 0) {
    2466           2 :                         if (entry.type != DBUS_TYPE_ARRAY ||
    2467           2 :                             entry.array_type != WPAS_DBUS_TYPE_BINARRAY ||
    2468           1 :                             entry.array_len > MAX_WPS_VENDOR_EXTENSIONS)
    2469             :                                 goto error;
    2470             : 
    2471          11 :                         for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
    2472          10 :                                 wpabuf_free(hapd->conf->wps_vendor_ext[i]);
    2473          10 :                                 if (i < entry.array_len) {
    2474           2 :                                         hapd->conf->wps_vendor_ext[i] =
    2475           1 :                                                 entry.binarray_value[i];
    2476           1 :                                         entry.binarray_value[i] = NULL;
    2477             :                                 } else
    2478           9 :                                         hapd->conf->wps_vendor_ext[i] = NULL;
    2479             :                         }
    2480             : 
    2481           1 :                         hostapd_update_wps(hapd);
    2482             :                 } else
    2483           1 :                         goto error;
    2484             : 
    2485           1 :                 wpa_dbus_dict_entry_clear(&entry);
    2486             :         }
    2487             : 
    2488           1 :         return TRUE;
    2489             : 
    2490             : error:
    2491           1 :         wpa_dbus_dict_entry_clear(&entry);
    2492           1 :         dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
    2493             :                              "invalid message format");
    2494           1 :         return FALSE;
    2495             : }
    2496             : 
    2497             : 
    2498          18 : DBusMessage * wpas_dbus_handler_p2p_add_service(DBusMessage *message,
    2499             :                                                 struct wpa_supplicant *wpa_s)
    2500             : {
    2501             :         DBusMessageIter iter_dict;
    2502          18 :         DBusMessage *reply = NULL;
    2503             :         DBusMessageIter iter;
    2504             :         struct wpa_dbus_dict_entry entry;
    2505          18 :         int upnp = 0;
    2506          18 :         int bonjour = 0;
    2507          18 :         char *service = NULL;
    2508          18 :         struct wpabuf *query = NULL;
    2509          18 :         struct wpabuf *resp = NULL;
    2510          18 :         u8 version = 0;
    2511             : 
    2512          18 :         dbus_message_iter_init(message, &iter);
    2513             : 
    2514          18 :         if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
    2515           0 :                 goto error;
    2516             : 
    2517          67 :         while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
    2518          36 :                 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
    2519           2 :                         goto error;
    2520             : 
    2521          51 :                 if (os_strcmp(entry.key, "service_type") == 0 &&
    2522          17 :                     entry.type == DBUS_TYPE_STRING) {
    2523          33 :                         if (os_strcmp(entry.str_value, "upnp") == 0)
    2524           5 :                                 upnp = 1;
    2525          12 :                         else if (os_strcmp(entry.str_value, "bonjour") == 0)
    2526          11 :                                 bonjour = 1;
    2527             :                         else
    2528           1 :                                 goto error_clear;
    2529          20 :                 } else if (os_strcmp(entry.key, "version") == 0 &&
    2530           3 :                            entry.type == DBUS_TYPE_INT32) {
    2531           3 :                         version = entry.uint32_value;
    2532          17 :                 } else if (os_strcmp(entry.key, "service") == 0 &&
    2533           3 :                            entry.type == DBUS_TYPE_STRING) {
    2534           3 :                         os_free(service);
    2535           3 :                         service = os_strdup(entry.str_value);
    2536          11 :                 } else if (os_strcmp(entry.key, "query") == 0) {
    2537           9 :                         if (entry.type != DBUS_TYPE_ARRAY ||
    2538           4 :                             entry.array_type != DBUS_TYPE_BYTE)
    2539             :                                 goto error_clear;
    2540           8 :                         query = wpabuf_alloc_copy(
    2541           4 :                                 entry.bytearray_value,
    2542           4 :                                 entry.array_len);
    2543           6 :                 } else if (os_strcmp(entry.key, "response") == 0) {
    2544           7 :                         if (entry.type != DBUS_TYPE_ARRAY ||
    2545           3 :                             entry.array_type != DBUS_TYPE_BYTE)
    2546             :                                 goto error_clear;
    2547           3 :                         resp = wpabuf_alloc_copy(entry.bytearray_value,
    2548           3 :                                                  entry.array_len);
    2549             :                 }
    2550          31 :                 wpa_dbus_dict_entry_clear(&entry);
    2551             :         }
    2552             : 
    2553          13 :         if (upnp == 1) {
    2554           5 :                 if (version <= 0 || service == NULL)
    2555             :                         goto error;
    2556             : 
    2557           1 :                 if (wpas_p2p_service_add_upnp(wpa_s, version, service) != 0)
    2558           0 :                         goto error;
    2559             : 
    2560           8 :         } else if (bonjour == 1) {
    2561           7 :                 if (query == NULL || resp == NULL)
    2562             :                         goto error;
    2563             : 
    2564           2 :                 if (wpas_p2p_service_add_bonjour(wpa_s, query, resp) < 0)
    2565           0 :                         goto error;
    2566           2 :                 query = NULL;
    2567           2 :                 resp = NULL;
    2568             :         } else
    2569           1 :                 goto error;
    2570             : 
    2571           3 :         os_free(service);
    2572           3 :         return reply;
    2573             : error_clear:
    2574           3 :         wpa_dbus_dict_entry_clear(&entry);
    2575             : error:
    2576          15 :         os_free(service);
    2577          15 :         wpabuf_free(query);
    2578          15 :         wpabuf_free(resp);
    2579          15 :         return wpas_dbus_error_invalid_args(message, NULL);
    2580             : }
    2581             : 
    2582             : 
    2583          15 : DBusMessage * wpas_dbus_handler_p2p_delete_service(
    2584             :         DBusMessage *message, struct wpa_supplicant *wpa_s)
    2585             : {
    2586             :         DBusMessageIter iter_dict;
    2587          15 :         DBusMessage *reply = NULL;
    2588             :         DBusMessageIter iter;
    2589             :         struct wpa_dbus_dict_entry entry;
    2590          15 :         int upnp = 0;
    2591          15 :         int bonjour = 0;
    2592          15 :         int ret = 0;
    2593          15 :         char *service = NULL;
    2594          15 :         struct wpabuf *query = NULL;
    2595          15 :         u8 version = 0;
    2596             : 
    2597          15 :         dbus_message_iter_init(message, &iter);
    2598             : 
    2599          15 :         if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
    2600           0 :                 goto error;
    2601             : 
    2602          15 :         if (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
    2603          15 :                 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
    2604           0 :                         goto error;
    2605             : 
    2606          29 :                 if (os_strcmp(entry.key, "service_type") == 0 &&
    2607          14 :                     entry.type == DBUS_TYPE_STRING) {
    2608          14 :                         if (os_strcmp(entry.str_value, "upnp") == 0)
    2609           6 :                                 upnp = 1;
    2610           8 :                         else if (os_strcmp(entry.str_value, "bonjour") == 0)
    2611           6 :                                 bonjour = 1;
    2612             :                         else
    2613           2 :                                 goto error_clear;
    2614          12 :                         wpa_dbus_dict_entry_clear(&entry);
    2615             :                 }
    2616             :         }
    2617          13 :         if (upnp == 1) {
    2618          18 :                 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
    2619           7 :                         if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
    2620           0 :                                 goto error;
    2621          10 :                         if (os_strcmp(entry.key, "version") == 0 &&
    2622           3 :                             entry.type == DBUS_TYPE_INT32)
    2623           3 :                                 version = entry.uint32_value;
    2624           7 :                         else if (os_strcmp(entry.key, "service") == 0 &&
    2625           3 :                                  entry.type == DBUS_TYPE_STRING) {
    2626           3 :                                 os_free(service);
    2627           3 :                                 service = os_strdup(entry.str_value);
    2628             :                         } else
    2629             :                                 goto error_clear;
    2630             : 
    2631           6 :                         wpa_dbus_dict_entry_clear(&entry);
    2632             :                 }
    2633             : 
    2634           5 :                 if (version <= 0 || service == NULL)
    2635             :                         goto error;
    2636             : 
    2637           2 :                 ret = wpas_p2p_service_del_upnp(wpa_s, version, service);
    2638           2 :                 if (ret != 0)
    2639           1 :                         goto error;
    2640           7 :         } else if (bonjour == 1) {
    2641          15 :                 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
    2642           6 :                         if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
    2643           0 :                                 goto error;
    2644             : 
    2645           6 :                         if (os_strcmp(entry.key, "query") == 0) {
    2646           7 :                                 if (entry.type != DBUS_TYPE_ARRAY ||
    2647           3 :                                     entry.array_type != DBUS_TYPE_BYTE)
    2648             :                                         goto error_clear;
    2649           3 :                                 wpabuf_free(query);
    2650           6 :                                 query = wpabuf_alloc_copy(
    2651           3 :                                         entry.bytearray_value,
    2652           3 :                                         entry.array_len);
    2653             :                         } else
    2654           2 :                                 goto error_clear;
    2655             : 
    2656           3 :                         wpa_dbus_dict_entry_clear(&entry);
    2657             :                 }
    2658             : 
    2659           3 :                 if (query == NULL)
    2660           1 :                         goto error;
    2661             : 
    2662           2 :                 ret = wpas_p2p_service_del_bonjour(wpa_s, query);
    2663           2 :                 if (ret != 0)
    2664           1 :                         goto error;
    2665             :         } else
    2666           1 :                 goto error;
    2667             : 
    2668           2 :         wpabuf_free(query);
    2669           2 :         os_free(service);
    2670           2 :         return reply;
    2671             : error_clear:
    2672           6 :         wpa_dbus_dict_entry_clear(&entry);
    2673             : error:
    2674          13 :         wpabuf_free(query);
    2675          13 :         os_free(service);
    2676          13 :         return wpas_dbus_error_invalid_args(message, NULL);
    2677             : }
    2678             : 
    2679             : 
    2680           1 : DBusMessage * wpas_dbus_handler_p2p_flush_service(DBusMessage *message,
    2681             :                                                   struct wpa_supplicant *wpa_s)
    2682             : {
    2683           1 :         wpas_p2p_service_flush(wpa_s);
    2684           1 :         return NULL;
    2685             : }
    2686             : 
    2687             : 
    2688          13 : DBusMessage * wpas_dbus_handler_p2p_service_sd_req(
    2689             :         DBusMessage *message, struct wpa_supplicant *wpa_s)
    2690             : {
    2691             :         DBusMessageIter iter_dict;
    2692          13 :         DBusMessage *reply = NULL;
    2693             :         DBusMessageIter iter;
    2694             :         struct wpa_dbus_dict_entry entry;
    2695          13 :         int upnp = 0;
    2696          13 :         char *service = NULL;
    2697          13 :         char *peer_object_path = NULL;
    2698          13 :         struct wpabuf *tlv = NULL;
    2699          13 :         u8 version = 0;
    2700          13 :         u64 ref = 0;
    2701             :         u8 addr_buf[ETH_ALEN], *addr;
    2702             : 
    2703          13 :         dbus_message_iter_init(message, &iter);
    2704             : 
    2705          13 :         if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
    2706           0 :                 goto error;
    2707             : 
    2708          46 :         while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
    2709          24 :                 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
    2710           0 :                         goto error;
    2711          28 :                 if (os_strcmp(entry.key, "peer_object") == 0 &&
    2712           4 :                     entry.type == DBUS_TYPE_OBJECT_PATH) {
    2713           3 :                         peer_object_path = os_strdup(entry.str_value);
    2714          28 :                 } else if (os_strcmp(entry.key, "service_type") == 0 &&
    2715           7 :                            entry.type == DBUS_TYPE_STRING) {
    2716          13 :                         if (os_strcmp(entry.str_value, "upnp") == 0)
    2717           6 :                                 upnp = 1;
    2718             :                         else
    2719           1 :                                 goto error_clear;
    2720          19 :                 } else if (os_strcmp(entry.key, "version") == 0 &&
    2721           5 :                            entry.type == DBUS_TYPE_INT32) {
    2722           5 :                         version = entry.uint32_value;
    2723          13 :                 } else if (os_strcmp(entry.key, "service") == 0 &&
    2724           4 :                            entry.type == DBUS_TYPE_STRING) {
    2725           4 :                         service = os_strdup(entry.str_value);
    2726           5 :                 } else if (os_strcmp(entry.key, "tlv") == 0) {
    2727           5 :                         if (entry.type != DBUS_TYPE_ARRAY ||
    2728           2 :                             entry.array_type != DBUS_TYPE_BYTE)
    2729             :                                 goto error_clear;
    2730           2 :                         tlv = wpabuf_alloc_copy(entry.bytearray_value,
    2731           2 :                                                 entry.array_len);
    2732             :                 } else
    2733           2 :                         goto error_clear;
    2734             : 
    2735          20 :                 wpa_dbus_dict_entry_clear(&entry);
    2736             :         }
    2737             : 
    2738           9 :         if (!peer_object_path) {
    2739           6 :                 addr = NULL;
    2740             :         } else {
    2741           5 :                 if (parse_peer_object_path(peer_object_path, addr_buf) < 0 ||
    2742           2 :                     !p2p_peer_known(wpa_s->global->p2p, addr_buf))
    2743             :                         goto error;
    2744             : 
    2745           1 :                 addr = addr_buf;
    2746             :         }
    2747             : 
    2748           7 :         if (upnp == 1) {
    2749           3 :                 if (version <= 0 || service == NULL)
    2750             :                         goto error;
    2751             : 
    2752           1 :                 ref = wpas_p2p_sd_request_upnp(wpa_s, addr, version, service);
    2753             :         } else {
    2754           4 :                 if (tlv == NULL)
    2755           2 :                         goto error;
    2756           2 :                 ref = wpas_p2p_sd_request(wpa_s, addr, tlv);
    2757           2 :                 wpabuf_free(tlv);
    2758             :         }
    2759             : 
    2760           3 :         if (ref != 0) {
    2761           3 :                 reply = dbus_message_new_method_return(message);
    2762           3 :                 dbus_message_append_args(reply, DBUS_TYPE_UINT64,
    2763             :                                          &ref, DBUS_TYPE_INVALID);
    2764             :         } else {
    2765           0 :                 reply = wpas_dbus_error_unknown_error(
    2766             :                         message, "Unable to send SD request");
    2767             :         }
    2768             : out:
    2769          13 :         os_free(service);
    2770          13 :         os_free(peer_object_path);
    2771          26 :         return reply;
    2772             : error_clear:
    2773           4 :         wpa_dbus_dict_entry_clear(&entry);
    2774             : error:
    2775          10 :         if (tlv)
    2776           0 :                 wpabuf_free(tlv);
    2777          10 :         reply = wpas_dbus_error_invalid_args(message, NULL);
    2778          10 :         goto out;
    2779             : }
    2780             : 
    2781             : 
    2782           2 : DBusMessage * wpas_dbus_handler_p2p_service_sd_res(
    2783             :         DBusMessage *message, struct wpa_supplicant *wpa_s)
    2784             : {
    2785             :         DBusMessageIter iter_dict;
    2786           2 :         DBusMessage *reply = NULL;
    2787             :         DBusMessageIter iter;
    2788             :         struct wpa_dbus_dict_entry entry;
    2789           2 :         char *peer_object_path = NULL;
    2790           2 :         struct wpabuf *tlv = NULL;
    2791           2 :         int freq = 0;
    2792           2 :         int dlg_tok = 0;
    2793             :         u8 addr[ETH_ALEN];
    2794             : 
    2795           2 :         dbus_message_iter_init(message, &iter);
    2796             : 
    2797           2 :         if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
    2798           0 :                 goto error;
    2799             : 
    2800           8 :         while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
    2801           5 :                 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
    2802           0 :                         goto error;
    2803             : 
    2804           6 :                 if (os_strcmp(entry.key, "peer_object") == 0 &&
    2805           1 :                     entry.type == DBUS_TYPE_OBJECT_PATH) {
    2806           1 :                         peer_object_path = os_strdup(entry.str_value);
    2807           5 :                 } else if (os_strcmp(entry.key, "frequency") == 0 &&
    2808           1 :                            entry.type == DBUS_TYPE_INT32) {
    2809           1 :                         freq = entry.uint32_value;
    2810           4 :                 } else if (os_strcmp(entry.key, "dialog_token") == 0 &&
    2811           2 :                            (entry.type == DBUS_TYPE_UINT32 ||
    2812           1 :                             entry.type == DBUS_TYPE_INT32)) {
    2813           1 :                         dlg_tok = entry.uint32_value;
    2814           2 :                 } else if (os_strcmp(entry.key, "tlvs") == 0) {
    2815           2 :                         if (entry.type != DBUS_TYPE_ARRAY ||
    2816           1 :                             entry.array_type != DBUS_TYPE_BYTE)
    2817             :                                 goto error_clear;
    2818           1 :                         tlv = wpabuf_alloc_copy(entry.bytearray_value,
    2819           1 :                                                 entry.array_len);
    2820             :                 } else
    2821           1 :                         goto error_clear;
    2822             : 
    2823           4 :                 wpa_dbus_dict_entry_clear(&entry);
    2824             :         }
    2825           2 :         if (parse_peer_object_path(peer_object_path, addr) < 0 ||
    2826           2 :             !p2p_peer_known(wpa_s->global->p2p, addr) ||
    2827             :             tlv == NULL)
    2828             :                 goto error;
    2829             : 
    2830           1 :         wpas_p2p_sd_response(wpa_s, freq, addr, (u8) dlg_tok, tlv);
    2831           1 :         wpabuf_free(tlv);
    2832             : out:
    2833           2 :         os_free(peer_object_path);
    2834           4 :         return reply;
    2835             : error_clear:
    2836           1 :         wpa_dbus_dict_entry_clear(&entry);
    2837             : error:
    2838           1 :         reply = wpas_dbus_error_invalid_args(message, NULL);
    2839           1 :         goto out;
    2840             : }
    2841             : 
    2842             : 
    2843           4 : DBusMessage * wpas_dbus_handler_p2p_service_sd_cancel_req(
    2844             :         DBusMessage *message, struct wpa_supplicant *wpa_s)
    2845             : {
    2846             :         DBusMessageIter iter;
    2847           4 :         u64 req = 0;
    2848             : 
    2849           4 :         dbus_message_iter_init(message, &iter);
    2850           4 :         dbus_message_iter_get_basic(&iter, &req);
    2851             : 
    2852           4 :         if (req == 0)
    2853           1 :                 goto error;
    2854             : 
    2855           3 :         if (wpas_p2p_sd_cancel_request(wpa_s, req) < 0)
    2856           1 :                 goto error;
    2857             : 
    2858           2 :         return NULL;
    2859             : error:
    2860           2 :         return wpas_dbus_error_invalid_args(message, NULL);
    2861             : }
    2862             : 
    2863             : 
    2864           1 : DBusMessage * wpas_dbus_handler_p2p_service_update(
    2865             :         DBusMessage *message, struct wpa_supplicant *wpa_s)
    2866             : {
    2867           1 :         wpas_p2p_sd_service_update(wpa_s);
    2868           1 :         return NULL;
    2869             : }
    2870             : 
    2871             : 
    2872           2 : DBusMessage * wpas_dbus_handler_p2p_serv_disc_external(
    2873             :         DBusMessage *message, struct wpa_supplicant *wpa_s)
    2874             : {
    2875             :         DBusMessageIter iter;
    2876           2 :         int ext = 0;
    2877             : 
    2878           2 :         dbus_message_iter_init(message, &iter);
    2879           2 :         dbus_message_iter_get_basic(&iter, &ext);
    2880             : 
    2881           2 :         wpa_s->p2p_sd_over_ctrl_iface = ext;
    2882             : 
    2883           2 :         return NULL;
    2884             : 
    2885             : }
    2886             : 
    2887             : 
    2888             : #ifdef CONFIG_WIFI_DISPLAY
    2889             : 
    2890           4 : dbus_bool_t wpas_dbus_getter_global_wfd_ies(
    2891             :         const struct wpa_dbus_property_desc *property_desc,
    2892             :         DBusMessageIter *iter, DBusError *error, void *user_data)
    2893             : {
    2894           4 :         struct wpa_global *global = user_data;
    2895             :         struct wpabuf *ie;
    2896             :         dbus_bool_t ret;
    2897             : 
    2898           4 :         ie = wifi_display_get_wfd_ie(global);
    2899           4 :         if (ie == NULL)
    2900           0 :                 return wpas_dbus_simple_array_property_getter(iter,
    2901             :                                                               DBUS_TYPE_BYTE,
    2902             :                                                               NULL, 0, error);
    2903             : 
    2904           4 :         ret = wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
    2905             :                                                      wpabuf_head(ie),
    2906             :                                                      wpabuf_len(ie), error);
    2907           4 :         wpabuf_free(ie);
    2908             : 
    2909           4 :         return ret;
    2910             : }
    2911             : 
    2912             : 
    2913           6 : dbus_bool_t wpas_dbus_setter_global_wfd_ies(
    2914             :         const struct wpa_dbus_property_desc *property_desc,
    2915             :         DBusMessageIter *iter, DBusError *error, void *user_data)
    2916             : {
    2917           6 :         struct wpa_global *global = user_data;
    2918             :         DBusMessageIter variant, array;
    2919           6 :         struct wpabuf *ie = NULL;
    2920             :         const u8 *data;
    2921             :         int len;
    2922             : 
    2923           6 :         if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_VARIANT)
    2924           0 :                 goto err;
    2925             : 
    2926           6 :         dbus_message_iter_recurse(iter, &variant);
    2927           6 :         if (dbus_message_iter_get_arg_type(&variant) != DBUS_TYPE_ARRAY)
    2928           1 :                 goto err;
    2929             : 
    2930           5 :         dbus_message_iter_recurse(&variant, &array);
    2931           5 :         dbus_message_iter_get_fixed_array(&array, &data, &len);
    2932           5 :         if (len == 0) {
    2933           2 :                 wifi_display_enable(global, 0);
    2934           2 :                 wifi_display_deinit(global);
    2935             : 
    2936           2 :                 return TRUE;
    2937             :         }
    2938             : 
    2939           3 :         ie = wpabuf_alloc(len);
    2940           3 :         if (ie == NULL)
    2941           0 :                 goto err;
    2942             : 
    2943           3 :         wpabuf_put_data(ie, data, len);
    2944           3 :         if (wifi_display_subelem_set_from_ies(global, ie) != 0)
    2945           1 :                 goto err;
    2946             : 
    2947           2 :         if (global->wifi_display == 0)
    2948           1 :                 wifi_display_enable(global, 1);
    2949             : 
    2950           2 :         wpabuf_free(ie);
    2951             : 
    2952           2 :         return TRUE;
    2953             : err:
    2954           2 :         wpabuf_free(ie);
    2955             : 
    2956           2 :         dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
    2957             :                              "invalid message format");
    2958           2 :         return FALSE;
    2959             : }
    2960             : 
    2961             : #endif /* CONFIG_WIFI_DISPLAY */

Generated by: LCOV version 1.10