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