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

Generated by: LCOV version 1.10