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

Generated by: LCOV version 1.10