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