D-Bus: Fix WPS.Start method in AP/P2P GO mode
[mech_eap.git] / wpa_supplicant / dbus / dbus_new_handlers.c
1 /*
2  * WPA Supplicant / dbus-based control interface
3  * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
4  * Copyright (c) 2009-2010, Witold Sowa <witold.sowa@gmail.com>
5  * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
6  *
7  * This software may be distributed under the terms of the BSD license.
8  * See README for more details.
9  */
10
11 #include "includes.h"
12
13 #include "common.h"
14 #include "common/ieee802_11_defs.h"
15 #include "eap_peer/eap_methods.h"
16 #include "eapol_supp/eapol_supp_sm.h"
17 #include "rsn_supp/wpa.h"
18 #include "../config.h"
19 #include "../wpa_supplicant_i.h"
20 #include "../driver_i.h"
21 #include "../notify.h"
22 #include "../bss.h"
23 #include "../scan.h"
24 #include "../autoscan.h"
25 #include "dbus_new_helpers.h"
26 #include "dbus_new.h"
27 #include "dbus_new_handlers.h"
28 #include "dbus_dict_helpers.h"
29 #include "dbus_common_i.h"
30 #include "drivers/driver.h"
31
32 static const char * const debug_strings[] = {
33         "excessive", "msgdump", "debug", "info", "warning", "error", NULL
34 };
35
36
37 /**
38  * wpas_dbus_error_unknown_error - Return a new UnknownError error message
39  * @message: Pointer to incoming dbus message this error refers to
40  * @arg: Optional string appended to error message
41  * Returns: a dbus error message
42  *
43  * Convenience function to create and return an UnknownError
44  */
45 DBusMessage * wpas_dbus_error_unknown_error(DBusMessage *message,
46                                             const char *arg)
47 {
48         return dbus_message_new_error(message, WPAS_DBUS_ERROR_UNKNOWN_ERROR,
49                                       arg);
50 }
51
52
53 /**
54  * wpas_dbus_error_iface_unknown - Return a new invalid interface error message
55  * @message: Pointer to incoming dbus message this error refers to
56  * Returns: A dbus error message
57  *
58  * Convenience function to create and return an invalid interface error
59  */
60 static DBusMessage * wpas_dbus_error_iface_unknown(DBusMessage *message)
61 {
62         return dbus_message_new_error(
63                 message, WPAS_DBUS_ERROR_IFACE_UNKNOWN,
64                 "wpa_supplicant knows nothing about this interface.");
65 }
66
67
68 /**
69  * wpas_dbus_error_network_unknown - Return a new NetworkUnknown error message
70  * @message: Pointer to incoming dbus message this error refers to
71  * Returns: a dbus error message
72  *
73  * Convenience function to create and return an invalid network error
74  */
75 static DBusMessage * wpas_dbus_error_network_unknown(DBusMessage *message)
76 {
77         return dbus_message_new_error(
78                 message, WPAS_DBUS_ERROR_NETWORK_UNKNOWN,
79                 "There is no such a network in this interface.");
80 }
81
82
83 /**
84  * wpas_dbus_error_invalid_args - Return a new InvalidArgs error message
85  * @message: Pointer to incoming dbus message this error refers to
86  * Returns: a dbus error message
87  *
88  * Convenience function to create and return an invalid options error
89  */
90 DBusMessage * wpas_dbus_error_invalid_args(DBusMessage *message,
91                                           const char *arg)
92 {
93         DBusMessage *reply;
94
95         reply = dbus_message_new_error(
96                 message, WPAS_DBUS_ERROR_INVALID_ARGS,
97                 "Did not receive correct message arguments.");
98         if (arg != NULL)
99                 dbus_message_append_args(reply, DBUS_TYPE_STRING, &arg,
100                                          DBUS_TYPE_INVALID);
101
102         return reply;
103 }
104
105
106 /**
107  * wpas_dbus_error_scan_error - Return a new ScanError error message
108  * @message: Pointer to incoming dbus message this error refers to
109  * @error: Optional string to be used as the error message
110  * Returns: a dbus error message
111  *
112  * Convenience function to create and return a scan error
113  */
114 static DBusMessage * wpas_dbus_error_scan_error(DBusMessage *message,
115                                                 const char *error)
116 {
117         return dbus_message_new_error(message,
118                                       WPAS_DBUS_ERROR_IFACE_SCAN_ERROR,
119                                       error);
120 }
121
122
123 DBusMessage * wpas_dbus_error_no_memory(DBusMessage *message)
124 {
125         wpa_printf(MSG_DEBUG, "dbus: Failed to allocate memory");
126         return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, NULL);
127 }
128
129
130 static const char * const dont_quote[] = {
131         "key_mgmt", "proto", "pairwise", "auth_alg", "group", "eap",
132         "opensc_engine_path", "pkcs11_engine_path", "pkcs11_module_path",
133         "bssid", "scan_freq", "freq_list", NULL
134 };
135
136 static dbus_bool_t should_quote_opt(const char *key)
137 {
138         int i = 0;
139
140         while (dont_quote[i] != NULL) {
141                 if (os_strcmp(key, dont_quote[i]) == 0)
142                         return FALSE;
143                 i++;
144         }
145         return TRUE;
146 }
147
148 /**
149  * get_iface_by_dbus_path - Get a new network interface
150  * @global: Pointer to global data from wpa_supplicant_init()
151  * @path: Pointer to a dbus object path representing an interface
152  * Returns: Pointer to the interface or %NULL if not found
153  */
154 static struct wpa_supplicant * get_iface_by_dbus_path(
155         struct wpa_global *global, const char *path)
156 {
157         struct wpa_supplicant *wpa_s;
158
159         for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
160                 if (os_strcmp(wpa_s->dbus_new_path, path) == 0)
161                         return wpa_s;
162         }
163         return NULL;
164 }
165
166
167 /**
168  * set_network_properties - Set properties of a configured network
169  * @wpa_s: wpa_supplicant structure for a network interface
170  * @ssid: wpa_ssid structure for a configured network
171  * @iter: DBus message iterator containing dictionary of network
172  * properties to set.
173  * @error: On failure, an error describing the failure
174  * Returns: TRUE if the request succeeds, FALSE if it failed
175  *
176  * Sets network configuration with parameters given id DBus dictionary
177  */
178 dbus_bool_t set_network_properties(struct wpa_supplicant *wpa_s,
179                                    struct wpa_ssid *ssid,
180                                    DBusMessageIter *iter,
181                                    DBusError *error)
182 {
183         struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
184         DBusMessageIter iter_dict;
185         char *value = NULL;
186
187         if (!wpa_dbus_dict_open_read(iter, &iter_dict, error))
188                 return FALSE;
189
190         while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
191                 size_t size = 50;
192                 int ret;
193
194                 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
195                         goto error;
196
197                 value = NULL;
198                 if (entry.type == DBUS_TYPE_ARRAY &&
199                     entry.array_type == DBUS_TYPE_BYTE) {
200                         if (entry.array_len <= 0)
201                                 goto error;
202
203                         size = entry.array_len * 2 + 1;
204                         value = os_zalloc(size);
205                         if (value == NULL)
206                                 goto error;
207
208                         ret = wpa_snprintf_hex(value, size,
209                                                (u8 *) entry.bytearray_value,
210                                                entry.array_len);
211                         if (ret <= 0)
212                                 goto error;
213                 } else if (entry.type == DBUS_TYPE_STRING) {
214                         if (should_quote_opt(entry.key)) {
215                                 size = os_strlen(entry.str_value);
216                                 if (size <= 0)
217                                         goto error;
218
219                                 size += 3;
220                                 value = os_zalloc(size);
221                                 if (value == NULL)
222                                         goto error;
223
224                                 ret = os_snprintf(value, size, "\"%s\"",
225                                                   entry.str_value);
226                                 if (os_snprintf_error(size, ret))
227                                         goto error;
228                         } else {
229                                 value = os_strdup(entry.str_value);
230                                 if (value == NULL)
231                                         goto error;
232                         }
233                 } else if (entry.type == DBUS_TYPE_UINT32) {
234                         value = os_zalloc(size);
235                         if (value == NULL)
236                                 goto error;
237
238                         ret = os_snprintf(value, size, "%u",
239                                           entry.uint32_value);
240                         if (os_snprintf_error(size, ret))
241                                 goto error;
242                 } else if (entry.type == DBUS_TYPE_INT32) {
243                         value = os_zalloc(size);
244                         if (value == NULL)
245                                 goto error;
246
247                         ret = os_snprintf(value, size, "%d",
248                                           entry.int32_value);
249                         if (os_snprintf_error(size, ret))
250                                 goto error;
251                 } else
252                         goto error;
253
254                 if (wpa_config_set(ssid, entry.key, value, 0) < 0)
255                         goto error;
256
257                 if ((os_strcmp(entry.key, "psk") == 0 &&
258                      value[0] == '"' && ssid->ssid_len) ||
259                     (os_strcmp(entry.key, "ssid") == 0 && ssid->passphrase))
260                         wpa_config_update_psk(ssid);
261                 else if (os_strcmp(entry.key, "priority") == 0)
262                         wpa_config_update_prio_list(wpa_s->conf);
263
264                 os_free(value);
265                 value = NULL;
266                 wpa_dbus_dict_entry_clear(&entry);
267         }
268
269         return TRUE;
270
271 error:
272         os_free(value);
273         wpa_dbus_dict_entry_clear(&entry);
274         dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
275                              "invalid message format");
276         return FALSE;
277 }
278
279
280 /**
281  * wpas_dbus_simple_property_getter - Get basic type property
282  * @iter: Message iter to use when appending arguments
283  * @type: DBus type of property (must be basic type)
284  * @val: pointer to place holding property value
285  * @error: On failure an error describing the failure
286  * Returns: TRUE if the request was successful, FALSE if it failed
287  *
288  * Generic getter for basic type properties. Type is required to be basic.
289  */
290 dbus_bool_t wpas_dbus_simple_property_getter(DBusMessageIter *iter,
291                                              const int type,
292                                              const void *val,
293                                              DBusError *error)
294 {
295         DBusMessageIter variant_iter;
296
297         if (!dbus_type_is_basic(type)) {
298                 dbus_set_error(error, DBUS_ERROR_FAILED,
299                                "%s: given type is not basic", __func__);
300                 return FALSE;
301         }
302
303         if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
304                                               wpa_dbus_type_as_string(type),
305                                               &variant_iter) ||
306             !dbus_message_iter_append_basic(&variant_iter, type, val) ||
307             !dbus_message_iter_close_container(iter, &variant_iter)) {
308                 dbus_set_error(error, DBUS_ERROR_FAILED,
309                                "%s: error constructing reply", __func__);
310                 return FALSE;
311         }
312
313         return TRUE;
314 }
315
316
317 /**
318  * wpas_dbus_simple_property_setter - Set basic type property
319  * @message: Pointer to incoming dbus message
320  * @type: DBus type of property (must be basic type)
321  * @val: pointer to place where value being set will be stored
322  * Returns: TRUE if the request was successful, FALSE if it failed
323  *
324  * Generic setter for basic type properties. Type is required to be basic.
325  */
326 dbus_bool_t wpas_dbus_simple_property_setter(DBusMessageIter *iter,
327                                              DBusError *error,
328                                              const int type, void *val)
329 {
330         DBusMessageIter variant_iter;
331
332         if (!dbus_type_is_basic(type)) {
333                 dbus_set_error(error, DBUS_ERROR_FAILED,
334                                "%s: given type is not basic", __func__);
335                 return FALSE;
336         }
337
338         /* Look at the new value */
339         dbus_message_iter_recurse(iter, &variant_iter);
340         if (dbus_message_iter_get_arg_type(&variant_iter) != type) {
341                 dbus_set_error_const(error, DBUS_ERROR_FAILED,
342                                      "wrong property type");
343                 return FALSE;
344         }
345         dbus_message_iter_get_basic(&variant_iter, val);
346
347         return TRUE;
348 }
349
350
351 /**
352  * wpas_dbus_simple_array_property_getter - Get array type property
353  * @iter: Pointer to incoming dbus message iterator
354  * @type: DBus type of property array elements (must be basic type)
355  * @array: pointer to array of elements to put into response message
356  * @array_len: length of above array
357  * @error: a pointer to an error to fill on failure
358  * Returns: TRUE if the request succeeded, FALSE if it failed
359  *
360  * Generic getter for array type properties. Array elements type is
361  * required to be basic.
362  */
363 dbus_bool_t wpas_dbus_simple_array_property_getter(DBusMessageIter *iter,
364                                                    const int type,
365                                                    const void *array,
366                                                    size_t array_len,
367                                                    DBusError *error)
368 {
369         DBusMessageIter variant_iter, array_iter;
370         char type_str[] = "a?"; /* ? will be replaced with subtype letter; */
371         const char *sub_type_str;
372         size_t element_size, i;
373
374         if (!dbus_type_is_basic(type)) {
375                 dbus_set_error(error, DBUS_ERROR_FAILED,
376                                "%s: given type is not basic", __func__);
377                 return FALSE;
378         }
379
380         sub_type_str = wpa_dbus_type_as_string(type);
381         type_str[1] = sub_type_str[0];
382
383         if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
384                                               type_str, &variant_iter) ||
385             !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
386                                               sub_type_str, &array_iter)) {
387                 dbus_set_error(error, DBUS_ERROR_FAILED,
388                                "%s: failed to construct message", __func__);
389                 return FALSE;
390         }
391
392         switch (type) {
393         case DBUS_TYPE_BYTE:
394         case DBUS_TYPE_BOOLEAN:
395                 element_size = 1;
396                 break;
397         case DBUS_TYPE_INT16:
398         case DBUS_TYPE_UINT16:
399                 element_size = sizeof(uint16_t);
400                 break;
401         case DBUS_TYPE_INT32:
402         case DBUS_TYPE_UINT32:
403                 element_size = sizeof(uint32_t);
404                 break;
405         case DBUS_TYPE_INT64:
406         case DBUS_TYPE_UINT64:
407                 element_size = sizeof(uint64_t);
408                 break;
409         case DBUS_TYPE_DOUBLE:
410                 element_size = sizeof(double);
411                 break;
412         case DBUS_TYPE_STRING:
413         case DBUS_TYPE_OBJECT_PATH:
414                 element_size = sizeof(char *);
415                 break;
416         default:
417                 dbus_set_error(error, DBUS_ERROR_FAILED,
418                                "%s: unknown element type %d", __func__, type);
419                 return FALSE;
420         }
421
422         for (i = 0; i < array_len; i++) {
423                 if (!dbus_message_iter_append_basic(&array_iter, type,
424                                                     array + i * element_size)) {
425                         dbus_set_error(error, DBUS_ERROR_FAILED,
426                                        "%s: failed to construct message 2.5",
427                                        __func__);
428                         return FALSE;
429                 }
430         }
431
432         if (!dbus_message_iter_close_container(&variant_iter, &array_iter) ||
433             !dbus_message_iter_close_container(iter, &variant_iter)) {
434                 dbus_set_error(error, DBUS_ERROR_FAILED,
435                                "%s: failed to construct message 3", __func__);
436                 return FALSE;
437         }
438
439         return TRUE;
440 }
441
442
443 /**
444  * wpas_dbus_simple_array_array_property_getter - Get array array type property
445  * @iter: Pointer to incoming dbus message iterator
446  * @type: DBus type of property array elements (must be basic type)
447  * @array: pointer to array of elements to put into response message
448  * @array_len: length of above array
449  * @error: a pointer to an error to fill on failure
450  * Returns: TRUE if the request succeeded, FALSE if it failed
451  *
452  * Generic getter for array type properties. Array elements type is
453  * required to be basic.
454  */
455 dbus_bool_t wpas_dbus_simple_array_array_property_getter(DBusMessageIter *iter,
456                                                          const int type,
457                                                          struct wpabuf **array,
458                                                          size_t array_len,
459                                                          DBusError *error)
460 {
461         DBusMessageIter variant_iter, array_iter;
462         char type_str[] = "aa?";
463         char inner_type_str[] = "a?";
464         const char *sub_type_str;
465         size_t i;
466
467         if (!dbus_type_is_basic(type)) {
468                 dbus_set_error(error, DBUS_ERROR_FAILED,
469                                "%s: given type is not basic", __func__);
470                 return FALSE;
471         }
472
473         sub_type_str = wpa_dbus_type_as_string(type);
474         type_str[2] = sub_type_str[0];
475         inner_type_str[1] = sub_type_str[0];
476
477         if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
478                                               type_str, &variant_iter) ||
479             !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
480                                               inner_type_str, &array_iter)) {
481                 dbus_set_error(error, DBUS_ERROR_FAILED,
482                                "%s: failed to construct message", __func__);
483                 return FALSE;
484         }
485
486         for (i = 0; i < array_len && array[i]; i++) {
487                 wpa_dbus_dict_bin_array_add_element(&array_iter,
488                                                     wpabuf_head(array[i]),
489                                                     wpabuf_len(array[i]));
490
491         }
492
493         if (!dbus_message_iter_close_container(&variant_iter, &array_iter) ||
494             !dbus_message_iter_close_container(iter, &variant_iter)) {
495                 dbus_set_error(error, DBUS_ERROR_FAILED,
496                                "%s: failed to close message", __func__);
497                 return FALSE;
498         }
499
500         return TRUE;
501 }
502
503
504 /**
505  * wpas_dbus_handler_create_interface - Request registration of a network iface
506  * @message: Pointer to incoming dbus message
507  * @global: %wpa_supplicant global data structure
508  * Returns: The object path of the new interface object,
509  *          or a dbus error message with more information
510  *
511  * Handler function for "CreateInterface" method call. Handles requests
512  * by dbus clients to register a network interface that wpa_supplicant
513  * will manage.
514  */
515 DBusMessage * wpas_dbus_handler_create_interface(DBusMessage *message,
516                                                  struct wpa_global *global)
517 {
518         DBusMessageIter iter_dict;
519         DBusMessage *reply = NULL;
520         DBusMessageIter iter;
521         struct wpa_dbus_dict_entry entry;
522         char *driver = NULL;
523         char *ifname = NULL;
524         char *confname = NULL;
525         char *bridge_ifname = NULL;
526
527         dbus_message_iter_init(message, &iter);
528
529         if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
530                 goto error;
531         while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
532                 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
533                         goto error;
534                 if (os_strcmp(entry.key, "Driver") == 0 &&
535                     entry.type == DBUS_TYPE_STRING) {
536                         os_free(driver);
537                         driver = os_strdup(entry.str_value);
538                         wpa_dbus_dict_entry_clear(&entry);
539                         if (driver == NULL)
540                                 goto error;
541                 } else if (os_strcmp(entry.key, "Ifname") == 0 &&
542                            entry.type == DBUS_TYPE_STRING) {
543                         os_free(ifname);
544                         ifname = os_strdup(entry.str_value);
545                         wpa_dbus_dict_entry_clear(&entry);
546                         if (ifname == NULL)
547                                 goto error;
548                 } else if (os_strcmp(entry.key, "ConfigFile") == 0 &&
549                            entry.type == DBUS_TYPE_STRING) {
550                         os_free(confname);
551                         confname = os_strdup(entry.str_value);
552                         wpa_dbus_dict_entry_clear(&entry);
553                         if (confname == NULL)
554                                 goto error;
555                 } else if (os_strcmp(entry.key, "BridgeIfname") == 0 &&
556                            entry.type == DBUS_TYPE_STRING) {
557                         os_free(bridge_ifname);
558                         bridge_ifname = os_strdup(entry.str_value);
559                         wpa_dbus_dict_entry_clear(&entry);
560                         if (bridge_ifname == NULL)
561                                 goto error;
562                 } else {
563                         wpa_dbus_dict_entry_clear(&entry);
564                         goto error;
565                 }
566         }
567
568         if (ifname == NULL)
569                 goto error; /* Required Ifname argument missing */
570
571         /*
572          * Try to get the wpa_supplicant record for this iface, return
573          * an error if we already control it.
574          */
575         if (wpa_supplicant_get_iface(global, ifname) != NULL) {
576                 reply = dbus_message_new_error(
577                         message, WPAS_DBUS_ERROR_IFACE_EXISTS,
578                         "wpa_supplicant already controls this interface.");
579         } else {
580                 struct wpa_supplicant *wpa_s;
581                 struct wpa_interface iface;
582
583                 os_memset(&iface, 0, sizeof(iface));
584                 iface.driver = driver;
585                 iface.ifname = ifname;
586                 iface.confname = confname;
587                 iface.bridge_ifname = bridge_ifname;
588                 /* Otherwise, have wpa_supplicant attach to it. */
589                 wpa_s = wpa_supplicant_add_iface(global, &iface);
590                 if (wpa_s) {
591                         const char *path = wpa_s->dbus_new_path;
592
593                         reply = dbus_message_new_method_return(message);
594                         dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH,
595                                                  &path, DBUS_TYPE_INVALID);
596                 } else {
597                         reply = wpas_dbus_error_unknown_error(
598                                 message,
599                                 "wpa_supplicant couldn't grab this interface.");
600                 }
601         }
602
603 out:
604         os_free(driver);
605         os_free(ifname);
606         os_free(confname);
607         os_free(bridge_ifname);
608         return reply;
609
610 error:
611         reply = wpas_dbus_error_invalid_args(message, NULL);
612         goto out;
613 }
614
615
616 /**
617  * wpas_dbus_handler_remove_interface - Request deregistration of an interface
618  * @message: Pointer to incoming dbus message
619  * @global: wpa_supplicant global data structure
620  * Returns: a dbus message containing a UINT32 indicating success (1) or
621  *          failure (0), or returns a dbus error message with more information
622  *
623  * Handler function for "removeInterface" method call.  Handles requests
624  * by dbus clients to deregister a network interface that wpa_supplicant
625  * currently manages.
626  */
627 DBusMessage * wpas_dbus_handler_remove_interface(DBusMessage *message,
628                                                  struct wpa_global *global)
629 {
630         struct wpa_supplicant *wpa_s;
631         char *path;
632         DBusMessage *reply = NULL;
633
634         dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path,
635                               DBUS_TYPE_INVALID);
636
637         wpa_s = get_iface_by_dbus_path(global, path);
638         if (wpa_s == NULL)
639                 reply = wpas_dbus_error_iface_unknown(message);
640         else if (wpa_supplicant_remove_iface(global, wpa_s, 0)) {
641                 reply = wpas_dbus_error_unknown_error(
642                         message,
643                         "wpa_supplicant couldn't remove this interface.");
644         }
645
646         return reply;
647 }
648
649
650 /**
651  * wpas_dbus_handler_get_interface - Get the object path for an interface name
652  * @message: Pointer to incoming dbus message
653  * @global: %wpa_supplicant global data structure
654  * Returns: The object path of the interface object,
655  *          or a dbus error message with more information
656  *
657  * Handler function for "getInterface" method call.
658  */
659 DBusMessage * wpas_dbus_handler_get_interface(DBusMessage *message,
660                                               struct wpa_global *global)
661 {
662         DBusMessage *reply = NULL;
663         const char *ifname;
664         const char *path;
665         struct wpa_supplicant *wpa_s;
666
667         dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &ifname,
668                               DBUS_TYPE_INVALID);
669
670         wpa_s = wpa_supplicant_get_iface(global, ifname);
671         if (wpa_s == NULL)
672                 return wpas_dbus_error_iface_unknown(message);
673
674         path = wpa_s->dbus_new_path;
675         reply = dbus_message_new_method_return(message);
676         if (reply == NULL)
677                 return wpas_dbus_error_no_memory(message);
678         if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
679                                       DBUS_TYPE_INVALID)) {
680                 dbus_message_unref(reply);
681                 return wpas_dbus_error_no_memory(message);
682         }
683
684         return reply;
685 }
686
687
688 /**
689  * wpas_dbus_getter_debug_level - Get debug level
690  * @iter: Pointer to incoming dbus message iter
691  * @error: Location to store error on failure
692  * @user_data: Function specific data
693  * Returns: TRUE on success, FALSE on failure
694  *
695  * Getter for "DebugLevel" property.
696  */
697 dbus_bool_t wpas_dbus_getter_debug_level(DBusMessageIter *iter,
698                                          DBusError *error,
699                                          void *user_data)
700 {
701         const char *str;
702         int idx = wpa_debug_level;
703
704         if (idx < 0)
705                 idx = 0;
706         if (idx > 5)
707                 idx = 5;
708         str = debug_strings[idx];
709         return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
710                                                 &str, error);
711 }
712
713
714 /**
715  * wpas_dbus_getter_debug_timestamp - Get debug timestamp
716  * @iter: Pointer to incoming dbus message iter
717  * @error: Location to store error on failure
718  * @user_data: Function specific data
719  * Returns: TRUE on success, FALSE on failure
720  *
721  * Getter for "DebugTimestamp" property.
722  */
723 dbus_bool_t wpas_dbus_getter_debug_timestamp(DBusMessageIter *iter,
724                                              DBusError *error,
725                                              void *user_data)
726 {
727         return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
728                                                 &wpa_debug_timestamp, error);
729
730 }
731
732
733 /**
734  * wpas_dbus_getter_debug_show_keys - Get debug show keys
735  * @iter: Pointer to incoming dbus message iter
736  * @error: Location to store error on failure
737  * @user_data: Function specific data
738  * Returns: TRUE on success, FALSE on failure
739  *
740  * Getter for "DebugShowKeys" property.
741  */
742 dbus_bool_t wpas_dbus_getter_debug_show_keys(DBusMessageIter *iter,
743                                              DBusError *error,
744                                              void *user_data)
745 {
746         return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
747                                                 &wpa_debug_show_keys, error);
748
749 }
750
751 /**
752  * wpas_dbus_setter_debug_level - Set debug level
753  * @iter: Pointer to incoming dbus message iter
754  * @error: Location to store error on failure
755  * @user_data: Function specific data
756  * Returns: TRUE on success, FALSE on failure
757  *
758  * Setter for "DebugLevel" property.
759  */
760 dbus_bool_t wpas_dbus_setter_debug_level(DBusMessageIter *iter,
761                                          DBusError *error, void *user_data)
762 {
763         struct wpa_global *global = user_data;
764         const char *str = NULL;
765         int i, val = -1;
766
767         if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
768                                               &str))
769                 return FALSE;
770
771         for (i = 0; debug_strings[i]; i++)
772                 if (os_strcmp(debug_strings[i], str) == 0) {
773                         val = i;
774                         break;
775                 }
776
777         if (val < 0 ||
778             wpa_supplicant_set_debug_params(global, val, wpa_debug_timestamp,
779                                             wpa_debug_show_keys)) {
780                 dbus_set_error_const(error, DBUS_ERROR_FAILED,
781                                      "wrong debug level value");
782                 return FALSE;
783         }
784
785         return TRUE;
786 }
787
788
789 /**
790  * wpas_dbus_setter_debug_timestamp - Set debug timestamp
791  * @iter: Pointer to incoming dbus message iter
792  * @error: Location to store error on failure
793  * @user_data: Function specific data
794  * Returns: TRUE on success, FALSE on failure
795  *
796  * Setter for "DebugTimestamp" property.
797  */
798 dbus_bool_t wpas_dbus_setter_debug_timestamp(DBusMessageIter *iter,
799                                              DBusError *error,
800                                              void *user_data)
801 {
802         struct wpa_global *global = user_data;
803         dbus_bool_t val;
804
805         if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
806                                               &val))
807                 return FALSE;
808
809         wpa_supplicant_set_debug_params(global, wpa_debug_level, val ? 1 : 0,
810                                         wpa_debug_show_keys);
811         return TRUE;
812 }
813
814
815 /**
816  * wpas_dbus_setter_debug_show_keys - Set debug show keys
817  * @iter: Pointer to incoming dbus message iter
818  * @error: Location to store error on failure
819  * @user_data: Function specific data
820  * Returns: TRUE on success, FALSE on failure
821  *
822  * Setter for "DebugShowKeys" property.
823  */
824 dbus_bool_t wpas_dbus_setter_debug_show_keys(DBusMessageIter *iter,
825                                              DBusError *error,
826                                              void *user_data)
827 {
828         struct wpa_global *global = user_data;
829         dbus_bool_t val;
830
831         if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
832                                               &val))
833                 return FALSE;
834
835         wpa_supplicant_set_debug_params(global, wpa_debug_level,
836                                         wpa_debug_timestamp,
837                                         val ? 1 : 0);
838         return TRUE;
839 }
840
841
842 /**
843  * wpas_dbus_getter_interfaces - Request registered interfaces list
844  * @iter: Pointer to incoming dbus message iter
845  * @error: Location to store error on failure
846  * @user_data: Function specific data
847  * Returns: TRUE on success, FALSE on failure
848  *
849  * Getter for "Interfaces" property. Handles requests
850  * by dbus clients to return list of registered interfaces objects
851  * paths
852  */
853 dbus_bool_t wpas_dbus_getter_interfaces(DBusMessageIter *iter,
854                                         DBusError *error,
855                                         void *user_data)
856 {
857         struct wpa_global *global = user_data;
858         struct wpa_supplicant *wpa_s;
859         const char **paths;
860         unsigned int i = 0, num = 0;
861         dbus_bool_t success;
862
863         for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
864                 num++;
865
866         paths = os_calloc(num, sizeof(char *));
867         if (!paths) {
868                 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
869                 return FALSE;
870         }
871
872         for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
873                 paths[i++] = wpa_s->dbus_new_path;
874
875         success = wpas_dbus_simple_array_property_getter(iter,
876                                                          DBUS_TYPE_OBJECT_PATH,
877                                                          paths, num, error);
878
879         os_free(paths);
880         return success;
881 }
882
883
884 /**
885  * wpas_dbus_getter_eap_methods - Request supported EAP methods list
886  * @iter: Pointer to incoming dbus message iter
887  * @error: Location to store error on failure
888  * @user_data: Function specific data
889  * Returns: TRUE on success, FALSE on failure
890  *
891  * Getter for "EapMethods" property. Handles requests
892  * by dbus clients to return list of strings with supported EAP methods
893  */
894 dbus_bool_t wpas_dbus_getter_eap_methods(DBusMessageIter *iter,
895                                          DBusError *error, void *user_data)
896 {
897         char **eap_methods;
898         size_t num_items = 0;
899         dbus_bool_t success;
900
901         eap_methods = eap_get_names_as_string_array(&num_items);
902         if (!eap_methods) {
903                 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
904                 return FALSE;
905         }
906
907         success = wpas_dbus_simple_array_property_getter(iter,
908                                                          DBUS_TYPE_STRING,
909                                                          eap_methods,
910                                                          num_items, error);
911
912         while (num_items)
913                 os_free(eap_methods[--num_items]);
914         os_free(eap_methods);
915         return success;
916 }
917
918
919 /**
920  * wpas_dbus_getter_global_capabilities - Request supported global capabilities
921  * @iter: Pointer to incoming dbus message iter
922  * @error: Location to store error on failure
923  * @user_data: Function specific data
924  * Returns: TRUE on success, FALSE on failure
925  *
926  * Getter for "Capabilities" property. Handles requests by dbus clients to
927  * return a list of strings with supported capabilities like AP, RSN IBSS,
928  * and P2P that are determined at compile time.
929  */
930 dbus_bool_t wpas_dbus_getter_global_capabilities(DBusMessageIter *iter,
931                                                  DBusError *error,
932                                                  void *user_data)
933 {
934         const char *capabilities[5] = { NULL, NULL, NULL, NULL, NULL };
935         size_t num_items = 0;
936
937 #ifdef CONFIG_AP
938         capabilities[num_items++] = "ap";
939 #endif /* CONFIG_AP */
940 #ifdef CONFIG_IBSS_RSN
941         capabilities[num_items++] = "ibss-rsn";
942 #endif /* CONFIG_IBSS_RSN */
943 #ifdef CONFIG_P2P
944         capabilities[num_items++] = "p2p";
945 #endif /* CONFIG_P2P */
946 #ifdef CONFIG_INTERWORKING
947         capabilities[num_items++] = "interworking";
948 #endif /* CONFIG_INTERWORKING */
949
950         return wpas_dbus_simple_array_property_getter(iter,
951                                                       DBUS_TYPE_STRING,
952                                                       capabilities,
953                                                       num_items, error);
954 }
955
956
957 static int wpas_dbus_get_scan_type(DBusMessage *message, DBusMessageIter *var,
958                                    char **type, DBusMessage **reply)
959 {
960         if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_STRING) {
961                 wpa_printf(MSG_DEBUG, "%s[dbus]: Type must be a string",
962                            __func__);
963                 *reply = wpas_dbus_error_invalid_args(
964                         message, "Wrong Type value type. String required");
965                 return -1;
966         }
967         dbus_message_iter_get_basic(var, type);
968         return 0;
969 }
970
971
972 static int wpas_dbus_get_scan_ssids(DBusMessage *message, DBusMessageIter *var,
973                                     struct wpa_driver_scan_params *params,
974                                     DBusMessage **reply)
975 {
976         struct wpa_driver_scan_ssid *ssids = params->ssids;
977         size_t ssids_num = 0;
978         u8 *ssid;
979         DBusMessageIter array_iter, sub_array_iter;
980         char *val;
981         int len;
982
983         if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
984                 wpa_printf(MSG_DEBUG,
985                            "%s[dbus]: ssids must be an array of arrays of bytes",
986                            __func__);
987                 *reply = wpas_dbus_error_invalid_args(
988                         message,
989                         "Wrong SSIDs value type. Array of arrays of bytes required");
990                 return -1;
991         }
992
993         dbus_message_iter_recurse(var, &array_iter);
994
995         if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY ||
996             dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_BYTE) {
997                 wpa_printf(MSG_DEBUG,
998                            "%s[dbus]: ssids must be an array of arrays of bytes",
999                            __func__);
1000                 *reply = wpas_dbus_error_invalid_args(
1001                         message,
1002                         "Wrong SSIDs value type. Array of arrays of bytes required");
1003                 return -1;
1004         }
1005
1006         while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_ARRAY) {
1007                 if (ssids_num >= WPAS_MAX_SCAN_SSIDS) {
1008                         wpa_printf(MSG_DEBUG,
1009                                    "%s[dbus]: Too many ssids specified on scan dbus call",
1010                                    __func__);
1011                         *reply = wpas_dbus_error_invalid_args(
1012                                 message,
1013                                 "Too many ssids specified. Specify at most four");
1014                         return -1;
1015                 }
1016
1017                 dbus_message_iter_recurse(&array_iter, &sub_array_iter);
1018
1019                 dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len);
1020
1021                 if (len > MAX_SSID_LEN) {
1022                         wpa_printf(MSG_DEBUG,
1023                                    "%s[dbus]: SSID too long (len=%d max_len=%d)",
1024                                    __func__, len, MAX_SSID_LEN);
1025                         *reply = wpas_dbus_error_invalid_args(
1026                                 message, "Invalid SSID: too long");
1027                         return -1;
1028                 }
1029
1030                 if (len != 0) {
1031                         ssid = os_malloc(len);
1032                         if (ssid == NULL) {
1033                                 *reply = wpas_dbus_error_no_memory(message);
1034                                 return -1;
1035                         }
1036                         os_memcpy(ssid, val, len);
1037                 } else {
1038                         /* Allow zero-length SSIDs */
1039                         ssid = NULL;
1040                 }
1041
1042                 ssids[ssids_num].ssid = ssid;
1043                 ssids[ssids_num].ssid_len = len;
1044
1045                 dbus_message_iter_next(&array_iter);
1046                 ssids_num++;
1047         }
1048
1049         params->num_ssids = ssids_num;
1050         return 0;
1051 }
1052
1053
1054 static int wpas_dbus_get_scan_ies(DBusMessage *message, DBusMessageIter *var,
1055                                   struct wpa_driver_scan_params *params,
1056                                   DBusMessage **reply)
1057 {
1058         u8 *ies = NULL, *nies;
1059         int ies_len = 0;
1060         DBusMessageIter array_iter, sub_array_iter;
1061         char *val;
1062         int len;
1063
1064         if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
1065                 wpa_printf(MSG_DEBUG,
1066                            "%s[dbus]: ies must be an array of arrays of bytes",
1067                            __func__);
1068                 *reply = wpas_dbus_error_invalid_args(
1069                         message,
1070                         "Wrong IEs value type. Array of arrays of bytes required");
1071                 return -1;
1072         }
1073
1074         dbus_message_iter_recurse(var, &array_iter);
1075
1076         if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY ||
1077             dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_BYTE) {
1078                 wpa_printf(MSG_DEBUG,
1079                            "%s[dbus]: ies must be an array of arrays of bytes",
1080                            __func__);
1081                 *reply = wpas_dbus_error_invalid_args(
1082                         message, "Wrong IEs value type. Array required");
1083                 return -1;
1084         }
1085
1086         while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_ARRAY) {
1087                 dbus_message_iter_recurse(&array_iter, &sub_array_iter);
1088
1089                 dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len);
1090                 if (len == 0) {
1091                         dbus_message_iter_next(&array_iter);
1092                         continue;
1093                 }
1094
1095                 nies = os_realloc(ies, ies_len + len);
1096                 if (nies == NULL) {
1097                         os_free(ies);
1098                         *reply = wpas_dbus_error_no_memory(message);
1099                         return -1;
1100                 }
1101                 ies = nies;
1102                 os_memcpy(ies + ies_len, val, len);
1103                 ies_len += len;
1104
1105                 dbus_message_iter_next(&array_iter);
1106         }
1107
1108         params->extra_ies = ies;
1109         params->extra_ies_len = ies_len;
1110         return 0;
1111 }
1112
1113
1114 static int wpas_dbus_get_scan_channels(DBusMessage *message,
1115                                        DBusMessageIter *var,
1116                                        struct wpa_driver_scan_params *params,
1117                                        DBusMessage **reply)
1118 {
1119         DBusMessageIter array_iter, sub_array_iter;
1120         int *freqs = NULL, *nfreqs;
1121         int freqs_num = 0;
1122
1123         if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
1124                 wpa_printf(MSG_DEBUG,
1125                            "%s[dbus]: Channels must be an array of structs",
1126                            __func__);
1127                 *reply = wpas_dbus_error_invalid_args(
1128                         message,
1129                         "Wrong Channels value type. Array of structs required");
1130                 return -1;
1131         }
1132
1133         dbus_message_iter_recurse(var, &array_iter);
1134
1135         if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_STRUCT) {
1136                 wpa_printf(MSG_DEBUG,
1137                            "%s[dbus]: Channels must be an array of structs",
1138                            __func__);
1139                 *reply = wpas_dbus_error_invalid_args(
1140                         message,
1141                         "Wrong Channels value type. Array of structs required");
1142                 return -1;
1143         }
1144
1145         while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_STRUCT)
1146         {
1147                 int freq, width;
1148
1149                 dbus_message_iter_recurse(&array_iter, &sub_array_iter);
1150
1151                 if (dbus_message_iter_get_arg_type(&sub_array_iter) !=
1152                     DBUS_TYPE_UINT32) {
1153                         wpa_printf(MSG_DEBUG,
1154                                    "%s[dbus]: Channel must by specified by struct of two UINT32s %c",
1155                                    __func__,
1156                                    dbus_message_iter_get_arg_type(
1157                                            &sub_array_iter));
1158                         *reply = wpas_dbus_error_invalid_args(
1159                                 message,
1160                                 "Wrong Channel struct. Two UINT32s required");
1161                         os_free(freqs);
1162                         return -1;
1163                 }
1164                 dbus_message_iter_get_basic(&sub_array_iter, &freq);
1165
1166                 if (!dbus_message_iter_next(&sub_array_iter) ||
1167                     dbus_message_iter_get_arg_type(&sub_array_iter) !=
1168                     DBUS_TYPE_UINT32) {
1169                         wpa_printf(MSG_DEBUG,
1170                                    "%s[dbus]: Channel must by specified by struct of two UINT32s",
1171                                    __func__);
1172                         *reply = wpas_dbus_error_invalid_args(
1173                                 message,
1174                                 "Wrong Channel struct. Two UINT32s required");
1175                         os_free(freqs);
1176                         return -1;
1177                 }
1178
1179                 dbus_message_iter_get_basic(&sub_array_iter, &width);
1180
1181 #define FREQS_ALLOC_CHUNK 32
1182                 if (freqs_num % FREQS_ALLOC_CHUNK == 0) {
1183                         nfreqs = os_realloc_array(
1184                                 freqs, freqs_num + FREQS_ALLOC_CHUNK,
1185                                 sizeof(int));
1186                         if (nfreqs == NULL)
1187                                 os_free(freqs);
1188                         freqs = nfreqs;
1189                 }
1190                 if (freqs == NULL) {
1191                         *reply = wpas_dbus_error_no_memory(message);
1192                         return -1;
1193                 }
1194
1195                 freqs[freqs_num] = freq;
1196
1197                 freqs_num++;
1198                 dbus_message_iter_next(&array_iter);
1199         }
1200
1201         nfreqs = os_realloc_array(freqs, freqs_num + 1, sizeof(int));
1202         if (nfreqs == NULL)
1203                 os_free(freqs);
1204         freqs = nfreqs;
1205         if (freqs == NULL) {
1206                 *reply = wpas_dbus_error_no_memory(message);
1207                 return -1;
1208         }
1209         freqs[freqs_num] = 0;
1210
1211         params->freqs = freqs;
1212         return 0;
1213 }
1214
1215
1216 static int wpas_dbus_get_scan_allow_roam(DBusMessage *message,
1217                                          DBusMessageIter *var,
1218                                          dbus_bool_t *allow,
1219                                          DBusMessage **reply)
1220 {
1221         if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_BOOLEAN) {
1222                 wpa_printf(MSG_DEBUG, "%s[dbus]: Type must be a boolean",
1223                            __func__);
1224                 *reply = wpas_dbus_error_invalid_args(
1225                         message, "Wrong Type value type. Boolean required");
1226                 return -1;
1227         }
1228         dbus_message_iter_get_basic(var, allow);
1229         return 0;
1230 }
1231
1232
1233 /**
1234  * wpas_dbus_handler_scan - Request a wireless scan on an interface
1235  * @message: Pointer to incoming dbus message
1236  * @wpa_s: wpa_supplicant structure for a network interface
1237  * Returns: NULL indicating success or DBus error message on failure
1238  *
1239  * Handler function for "Scan" method call of a network device. Requests
1240  * that wpa_supplicant perform a wireless scan as soon as possible
1241  * on a particular wireless interface.
1242  */
1243 DBusMessage * wpas_dbus_handler_scan(DBusMessage *message,
1244                                      struct wpa_supplicant *wpa_s)
1245 {
1246         DBusMessage *reply = NULL;
1247         DBusMessageIter iter, dict_iter, entry_iter, variant_iter;
1248         char *key = NULL, *type = NULL;
1249         struct wpa_driver_scan_params params;
1250         size_t i;
1251         dbus_bool_t allow_roam = 1;
1252
1253         os_memset(&params, 0, sizeof(params));
1254
1255         dbus_message_iter_init(message, &iter);
1256
1257         dbus_message_iter_recurse(&iter, &dict_iter);
1258
1259         while (dbus_message_iter_get_arg_type(&dict_iter) ==
1260                DBUS_TYPE_DICT_ENTRY) {
1261                 dbus_message_iter_recurse(&dict_iter, &entry_iter);
1262                 dbus_message_iter_get_basic(&entry_iter, &key);
1263                 dbus_message_iter_next(&entry_iter);
1264                 dbus_message_iter_recurse(&entry_iter, &variant_iter);
1265
1266                 if (os_strcmp(key, "Type") == 0) {
1267                         if (wpas_dbus_get_scan_type(message, &variant_iter,
1268                                                     &type, &reply) < 0)
1269                                 goto out;
1270                 } else if (os_strcmp(key, "SSIDs") == 0) {
1271                         if (wpas_dbus_get_scan_ssids(message, &variant_iter,
1272                                                      &params, &reply) < 0)
1273                                 goto out;
1274                 } else if (os_strcmp(key, "IEs") == 0) {
1275                         if (wpas_dbus_get_scan_ies(message, &variant_iter,
1276                                                    &params, &reply) < 0)
1277                                 goto out;
1278                 } else if (os_strcmp(key, "Channels") == 0) {
1279                         if (wpas_dbus_get_scan_channels(message, &variant_iter,
1280                                                         &params, &reply) < 0)
1281                                 goto out;
1282                 } else if (os_strcmp(key, "AllowRoam") == 0) {
1283                         if (wpas_dbus_get_scan_allow_roam(message,
1284                                                           &variant_iter,
1285                                                           &allow_roam,
1286                                                           &reply) < 0)
1287                                 goto out;
1288                 } else {
1289                         wpa_printf(MSG_DEBUG, "%s[dbus]: Unknown argument %s",
1290                                    __func__, key);
1291                         reply = wpas_dbus_error_invalid_args(message, key);
1292                         goto out;
1293                 }
1294
1295                 dbus_message_iter_next(&dict_iter);
1296         }
1297
1298         if (!type) {
1299                 wpa_printf(MSG_DEBUG, "%s[dbus]: Scan type not specified",
1300                            __func__);
1301                 reply = wpas_dbus_error_invalid_args(message, key);
1302                 goto out;
1303         }
1304
1305         if (os_strcmp(type, "passive") == 0) {
1306                 if (params.num_ssids || params.extra_ies_len) {
1307                         wpa_printf(MSG_DEBUG,
1308                                    "%s[dbus]: SSIDs or IEs specified for passive scan.",
1309                                    __func__);
1310                         reply = wpas_dbus_error_invalid_args(
1311                                 message,
1312                                 "You can specify only Channels in passive scan");
1313                         goto out;
1314                 } else if (params.freqs && params.freqs[0]) {
1315                         if (wpa_supplicant_trigger_scan(wpa_s, &params)) {
1316                                 reply = wpas_dbus_error_scan_error(
1317                                         message, "Scan request rejected");
1318                         }
1319                 } else {
1320                         wpa_s->scan_req = MANUAL_SCAN_REQ;
1321                         wpa_supplicant_req_scan(wpa_s, 0, 0);
1322                 }
1323         } else if (os_strcmp(type, "active") == 0) {
1324                 if (!params.num_ssids) {
1325                         /* Add wildcard ssid */
1326                         params.num_ssids++;
1327                 }
1328 #ifdef CONFIG_AUTOSCAN
1329                 autoscan_deinit(wpa_s);
1330 #endif /* CONFIG_AUTOSCAN */
1331                 if (wpa_supplicant_trigger_scan(wpa_s, &params)) {
1332                         reply = wpas_dbus_error_scan_error(
1333                                 message, "Scan request rejected");
1334                 }
1335         } else {
1336                 wpa_printf(MSG_DEBUG, "%s[dbus]: Unknown scan type: %s",
1337                            __func__, type);
1338                 reply = wpas_dbus_error_invalid_args(message,
1339                                                      "Wrong scan type");
1340                 goto out;
1341         }
1342
1343         if (!allow_roam)
1344                 wpa_s->scan_res_handler = scan_only_handler;
1345
1346 out:
1347         for (i = 0; i < WPAS_MAX_SCAN_SSIDS; i++)
1348                 os_free((u8 *) params.ssids[i].ssid);
1349         os_free((u8 *) params.extra_ies);
1350         os_free(params.freqs);
1351         return reply;
1352 }
1353
1354
1355 /**
1356  * wpas_dbus_handler_signal_poll - Request immediate signal properties
1357  * @message: Pointer to incoming dbus message
1358  * @wpa_s: wpa_supplicant structure for a network interface
1359  * Returns: NULL indicating success or DBus error message on failure
1360  *
1361  * Handler function for "SignalPoll" method call of a network device. Requests
1362  * that wpa_supplicant read signal properties like RSSI, noise, and link
1363  * speed and return them.
1364  */
1365 DBusMessage * wpas_dbus_handler_signal_poll(DBusMessage *message,
1366                                             struct wpa_supplicant *wpa_s)
1367 {
1368         struct wpa_signal_info si;
1369         DBusMessage *reply = NULL;
1370         DBusMessageIter iter, iter_dict, variant_iter;
1371         int ret;
1372
1373         ret = wpa_drv_signal_poll(wpa_s, &si);
1374         if (ret) {
1375                 return dbus_message_new_error(message, DBUS_ERROR_FAILED,
1376                                               "Failed to read signal");
1377         }
1378
1379         reply = dbus_message_new_method_return(message);
1380         if (reply == NULL)
1381                 goto nomem;
1382
1383         dbus_message_iter_init_append(reply, &iter);
1384
1385         if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
1386                                               "a{sv}", &variant_iter) ||
1387             !wpa_dbus_dict_open_write(&variant_iter, &iter_dict) ||
1388             !wpa_dbus_dict_append_int32(&iter_dict, "rssi",
1389                                         si.current_signal) ||
1390             !wpa_dbus_dict_append_int32(&iter_dict, "linkspeed",
1391                                         si.current_txrate / 1000) ||
1392             !wpa_dbus_dict_append_int32(&iter_dict, "noise",
1393                                         si.current_noise) ||
1394             !wpa_dbus_dict_append_uint32(&iter_dict, "frequency",
1395                                          si.frequency) ||
1396             (si.chanwidth != CHAN_WIDTH_UNKNOWN &&
1397              !wpa_dbus_dict_append_string(
1398                      &iter_dict, "width",
1399                      channel_width_to_string(si.chanwidth))) ||
1400             (si.center_frq1 > 0 && si.center_frq2 > 0 &&
1401              (!wpa_dbus_dict_append_int32(&iter_dict, "center-frq1",
1402                                           si.center_frq1) ||
1403               !wpa_dbus_dict_append_int32(&iter_dict, "center-frq2",
1404                                           si.center_frq2))) ||
1405             (si.avg_signal &&
1406              !wpa_dbus_dict_append_int32(&iter_dict, "avg-rssi",
1407                                          si.avg_signal)) ||
1408             !wpa_dbus_dict_close_write(&variant_iter, &iter_dict) ||
1409             !dbus_message_iter_close_container(&iter, &variant_iter))
1410                 goto nomem;
1411
1412         return reply;
1413
1414 nomem:
1415         if (reply)
1416                 dbus_message_unref(reply);
1417         return wpas_dbus_error_no_memory(message);
1418 }
1419
1420
1421 /*
1422  * wpas_dbus_handler_disconnect - Terminate the current connection
1423  * @message: Pointer to incoming dbus message
1424  * @wpa_s: wpa_supplicant structure for a network interface
1425  * Returns: NotConnected DBus error message if already not connected
1426  * or NULL otherwise.
1427  *
1428  * Handler function for "Disconnect" method call of network interface.
1429  */
1430 DBusMessage * wpas_dbus_handler_disconnect(DBusMessage *message,
1431                                            struct wpa_supplicant *wpa_s)
1432 {
1433         if (wpa_s->current_ssid != NULL) {
1434                 wpa_s->disconnected = 1;
1435                 wpa_supplicant_deauthenticate(wpa_s,
1436                                               WLAN_REASON_DEAUTH_LEAVING);
1437
1438                 return NULL;
1439         }
1440
1441         return dbus_message_new_error(message, WPAS_DBUS_ERROR_NOT_CONNECTED,
1442                                       "This interface is not connected");
1443 }
1444
1445
1446 /**
1447  * wpas_dbus_new_iface_add_network - Add a new configured network
1448  * @message: Pointer to incoming dbus message
1449  * @wpa_s: wpa_supplicant structure for a network interface
1450  * Returns: A dbus message containing the object path of the new network
1451  *
1452  * Handler function for "AddNetwork" method call of a network interface.
1453  */
1454 DBusMessage * wpas_dbus_handler_add_network(DBusMessage *message,
1455                                             struct wpa_supplicant *wpa_s)
1456 {
1457         DBusMessage *reply = NULL;
1458         DBusMessageIter iter;
1459         struct wpa_ssid *ssid = NULL;
1460         char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf;
1461         DBusError error;
1462
1463         dbus_message_iter_init(message, &iter);
1464
1465         ssid = wpa_config_add_network(wpa_s->conf);
1466         if (ssid == NULL) {
1467                 wpa_printf(MSG_ERROR, "%s[dbus]: can't add new interface.",
1468                            __func__);
1469                 reply = wpas_dbus_error_unknown_error(
1470                         message,
1471                         "wpa_supplicant could not add a network on this interface.");
1472                 goto err;
1473         }
1474         wpas_notify_network_added(wpa_s, ssid);
1475         ssid->disabled = 1;
1476         wpa_config_set_network_defaults(ssid);
1477
1478         dbus_error_init(&error);
1479         if (!set_network_properties(wpa_s, ssid, &iter, &error)) {
1480                 wpa_printf(MSG_DEBUG,
1481                            "%s[dbus]: control interface couldn't set network properties",
1482                            __func__);
1483                 reply = wpas_dbus_reply_new_from_error(message, &error,
1484                                                        DBUS_ERROR_INVALID_ARGS,
1485                                                        "Failed to add network");
1486                 dbus_error_free(&error);
1487                 goto err;
1488         }
1489
1490         /* Construct the object path for this network. */
1491         os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
1492                     "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
1493                     wpa_s->dbus_new_path, ssid->id);
1494
1495         reply = dbus_message_new_method_return(message);
1496         if (reply == NULL) {
1497                 reply = wpas_dbus_error_no_memory(message);
1498                 goto err;
1499         }
1500         if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
1501                                       DBUS_TYPE_INVALID)) {
1502                 dbus_message_unref(reply);
1503                 reply = wpas_dbus_error_no_memory(message);
1504                 goto err;
1505         }
1506
1507         return reply;
1508
1509 err:
1510         if (ssid) {
1511                 wpas_notify_network_removed(wpa_s, ssid);
1512                 wpa_config_remove_network(wpa_s->conf, ssid->id);
1513         }
1514         return reply;
1515 }
1516
1517
1518 /**
1519  * wpas_dbus_handler_reassociate - Reassociate
1520  * @message: Pointer to incoming dbus message
1521  * @wpa_s: wpa_supplicant structure for a network interface
1522  * Returns: InterfaceDisabled DBus error message if disabled
1523  * or NULL otherwise.
1524  *
1525  * Handler function for "Reassociate" method call of network interface.
1526  */
1527 DBusMessage * wpas_dbus_handler_reassociate(DBusMessage *message,
1528                                             struct wpa_supplicant *wpa_s)
1529 {
1530         if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED) {
1531                 wpas_request_connection(wpa_s);
1532                 return NULL;
1533         }
1534
1535         return dbus_message_new_error(message, WPAS_DBUS_ERROR_IFACE_DISABLED,
1536                                       "This interface is disabled");
1537 }
1538
1539
1540 /**
1541  * wpas_dbus_handler_reattach - Reattach to current AP
1542  * @message: Pointer to incoming dbus message
1543  * @wpa_s: wpa_supplicant structure for a network interface
1544  * Returns: NotConnected DBus error message if not connected
1545  * or NULL otherwise.
1546  *
1547  * Handler function for "Reattach" method call of network interface.
1548  */
1549 DBusMessage * wpas_dbus_handler_reattach(DBusMessage *message,
1550                                          struct wpa_supplicant *wpa_s)
1551 {
1552         if (wpa_s->current_ssid != NULL) {
1553                 wpa_s->reattach = 1;
1554                 wpas_request_connection(wpa_s);
1555                 return NULL;
1556         }
1557
1558         return dbus_message_new_error(message, WPAS_DBUS_ERROR_NOT_CONNECTED,
1559                                       "This interface is not connected");
1560 }
1561
1562
1563 /**
1564  * wpas_dbus_handler_remove_network - Remove a configured network
1565  * @message: Pointer to incoming dbus message
1566  * @wpa_s: wpa_supplicant structure for a network interface
1567  * Returns: NULL on success or dbus error on failure
1568  *
1569  * Handler function for "RemoveNetwork" method call of a network interface.
1570  */
1571 DBusMessage * wpas_dbus_handler_remove_network(DBusMessage *message,
1572                                                struct wpa_supplicant *wpa_s)
1573 {
1574         DBusMessage *reply = NULL;
1575         const char *op;
1576         char *iface, *net_id;
1577         int id;
1578         struct wpa_ssid *ssid;
1579         int was_disabled;
1580
1581         dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
1582                               DBUS_TYPE_INVALID);
1583
1584         /* Extract the network ID and ensure the network */
1585         /* is actually a child of this interface */
1586         iface = wpas_dbus_new_decompose_object_path(op,
1587                                                     WPAS_DBUS_NEW_NETWORKS_PART,
1588                                                     &net_id);
1589         if (iface == NULL || net_id == NULL ||
1590             os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
1591                 reply = wpas_dbus_error_invalid_args(message, op);
1592                 goto out;
1593         }
1594
1595         errno = 0;
1596         id = strtoul(net_id, NULL, 10);
1597         if (errno != 0) {
1598                 reply = wpas_dbus_error_invalid_args(message, op);
1599                 goto out;
1600         }
1601
1602         ssid = wpa_config_get_network(wpa_s->conf, id);
1603         if (ssid == NULL) {
1604                 reply = wpas_dbus_error_network_unknown(message);
1605                 goto out;
1606         }
1607
1608         was_disabled = ssid->disabled;
1609
1610         wpas_notify_network_removed(wpa_s, ssid);
1611
1612         if (ssid == wpa_s->current_ssid)
1613                 wpa_supplicant_deauthenticate(wpa_s,
1614                                               WLAN_REASON_DEAUTH_LEAVING);
1615         else if (!was_disabled && wpa_s->sched_scanning) {
1616                 wpa_printf(MSG_DEBUG,
1617                            "Stop ongoing sched_scan to remove network from filters");
1618                 wpa_supplicant_cancel_sched_scan(wpa_s);
1619                 wpa_supplicant_req_scan(wpa_s, 0, 0);
1620         }
1621
1622         if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
1623                 wpa_printf(MSG_ERROR,
1624                            "%s[dbus]: error occurred when removing network %d",
1625                            __func__, id);
1626                 reply = wpas_dbus_error_unknown_error(
1627                         message,
1628                         "error removing the specified network on is interface.");
1629                 goto out;
1630         }
1631
1632 out:
1633         os_free(iface);
1634         return reply;
1635 }
1636
1637
1638 static void remove_network(void *arg, struct wpa_ssid *ssid)
1639 {
1640         struct wpa_supplicant *wpa_s = arg;
1641
1642         wpas_notify_network_removed(wpa_s, ssid);
1643
1644         if (wpa_config_remove_network(wpa_s->conf, ssid->id) < 0) {
1645                 wpa_printf(MSG_ERROR,
1646                            "%s[dbus]: error occurred when removing network %d",
1647                            __func__, ssid->id);
1648                 return;
1649         }
1650
1651         if (ssid == wpa_s->current_ssid)
1652                 wpa_supplicant_deauthenticate(wpa_s,
1653                                               WLAN_REASON_DEAUTH_LEAVING);
1654 }
1655
1656
1657 /**
1658  * wpas_dbus_handler_remove_all_networks - Remove all configured networks
1659  * @message: Pointer to incoming dbus message
1660  * @wpa_s: wpa_supplicant structure for a network interface
1661  * Returns: NULL on success or dbus error on failure
1662  *
1663  * Handler function for "RemoveAllNetworks" method call of a network interface.
1664  */
1665 DBusMessage * wpas_dbus_handler_remove_all_networks(
1666         DBusMessage *message, struct wpa_supplicant *wpa_s)
1667 {
1668         if (wpa_s->sched_scanning)
1669                 wpa_supplicant_cancel_sched_scan(wpa_s);
1670
1671         /* NB: could check for failure and return an error */
1672         wpa_config_foreach_network(wpa_s->conf, remove_network, wpa_s);
1673         return NULL;
1674 }
1675
1676
1677 /**
1678  * wpas_dbus_handler_select_network - Attempt association with a network
1679  * @message: Pointer to incoming dbus message
1680  * @wpa_s: wpa_supplicant structure for a network interface
1681  * Returns: NULL on success or dbus error on failure
1682  *
1683  * Handler function for "SelectNetwork" method call of network interface.
1684  */
1685 DBusMessage * wpas_dbus_handler_select_network(DBusMessage *message,
1686                                                struct wpa_supplicant *wpa_s)
1687 {
1688         DBusMessage *reply = NULL;
1689         const char *op;
1690         char *iface, *net_id;
1691         int id;
1692         struct wpa_ssid *ssid;
1693
1694         dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
1695                               DBUS_TYPE_INVALID);
1696
1697         /* Extract the network ID and ensure the network */
1698         /* is actually a child of this interface */
1699         iface = wpas_dbus_new_decompose_object_path(op,
1700                                                     WPAS_DBUS_NEW_NETWORKS_PART,
1701                                                     &net_id);
1702         if (iface == NULL || net_id == NULL ||
1703             os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
1704                 reply = wpas_dbus_error_invalid_args(message, op);
1705                 goto out;
1706         }
1707
1708         errno = 0;
1709         id = strtoul(net_id, NULL, 10);
1710         if (errno != 0) {
1711                 reply = wpas_dbus_error_invalid_args(message, op);
1712                 goto out;
1713         }
1714
1715         ssid = wpa_config_get_network(wpa_s->conf, id);
1716         if (ssid == NULL) {
1717                 reply = wpas_dbus_error_network_unknown(message);
1718                 goto out;
1719         }
1720
1721         /* Finally, associate with the network */
1722         wpa_supplicant_select_network(wpa_s, ssid);
1723
1724 out:
1725         os_free(iface);
1726         return reply;
1727 }
1728
1729
1730 /**
1731  * wpas_dbus_handler_network_reply - Reply to a NetworkRequest signal
1732  * @message: Pointer to incoming dbus message
1733  * @wpa_s: wpa_supplicant structure for a network interface
1734  * Returns: NULL on success or dbus error on failure
1735  *
1736  * Handler function for "NetworkReply" method call of network interface.
1737  */
1738 DBusMessage * wpas_dbus_handler_network_reply(DBusMessage *message,
1739                                               struct wpa_supplicant *wpa_s)
1740 {
1741 #ifdef IEEE8021X_EAPOL
1742         DBusMessage *reply = NULL;
1743         const char *op, *field, *value;
1744         char *iface, *net_id;
1745         int id;
1746         struct wpa_ssid *ssid;
1747
1748         if (!dbus_message_get_args(message, NULL,
1749                                    DBUS_TYPE_OBJECT_PATH, &op,
1750                                    DBUS_TYPE_STRING, &field,
1751                                    DBUS_TYPE_STRING, &value,
1752                                    DBUS_TYPE_INVALID))
1753                 return wpas_dbus_error_invalid_args(message, NULL);
1754
1755         /* Extract the network ID and ensure the network */
1756         /* is actually a child of this interface */
1757         iface = wpas_dbus_new_decompose_object_path(op,
1758                                                     WPAS_DBUS_NEW_NETWORKS_PART,
1759                                                     &net_id);
1760         if (iface == NULL || net_id == NULL ||
1761             os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
1762                 reply = wpas_dbus_error_invalid_args(message, op);
1763                 goto out;
1764         }
1765
1766         errno = 0;
1767         id = strtoul(net_id, NULL, 10);
1768         if (errno != 0) {
1769                 reply = wpas_dbus_error_invalid_args(message, net_id);
1770                 goto out;
1771         }
1772
1773         ssid = wpa_config_get_network(wpa_s->conf, id);
1774         if (ssid == NULL) {
1775                 reply = wpas_dbus_error_network_unknown(message);
1776                 goto out;
1777         }
1778
1779         if (wpa_supplicant_ctrl_iface_ctrl_rsp_handle(wpa_s, ssid,
1780                                                       field, value) < 0)
1781                 reply = wpas_dbus_error_invalid_args(message, field);
1782         else {
1783                 /* Tell EAP to retry immediately */
1784                 eapol_sm_notify_ctrl_response(wpa_s->eapol);
1785         }
1786
1787 out:
1788         os_free(iface);
1789         return reply;
1790 #else /* IEEE8021X_EAPOL */
1791         wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included");
1792         return wpas_dbus_error_unknown_error(message, "802.1X not included");
1793 #endif /* IEEE8021X_EAPOL */
1794 }
1795
1796
1797 #ifndef CONFIG_NO_CONFIG_BLOBS
1798
1799 /**
1800  * wpas_dbus_handler_add_blob - Store named binary blob (ie, for certificates)
1801  * @message: Pointer to incoming dbus message
1802  * @wpa_s: %wpa_supplicant data structure
1803  * Returns: A dbus message containing an error on failure or NULL on success
1804  *
1805  * Asks wpa_supplicant to internally store a binary blobs.
1806  */
1807 DBusMessage * wpas_dbus_handler_add_blob(DBusMessage *message,
1808                                          struct wpa_supplicant *wpa_s)
1809 {
1810         DBusMessage *reply = NULL;
1811         DBusMessageIter iter, array_iter;
1812
1813         char *blob_name;
1814         u8 *blob_data;
1815         int blob_len;
1816         struct wpa_config_blob *blob = NULL;
1817
1818         dbus_message_iter_init(message, &iter);
1819         dbus_message_iter_get_basic(&iter, &blob_name);
1820
1821         if (wpa_config_get_blob(wpa_s->conf, blob_name)) {
1822                 return dbus_message_new_error(message,
1823                                               WPAS_DBUS_ERROR_BLOB_EXISTS,
1824                                               NULL);
1825         }
1826
1827         dbus_message_iter_next(&iter);
1828         dbus_message_iter_recurse(&iter, &array_iter);
1829
1830         dbus_message_iter_get_fixed_array(&array_iter, &blob_data, &blob_len);
1831
1832         blob = os_zalloc(sizeof(*blob));
1833         if (!blob) {
1834                 reply = wpas_dbus_error_no_memory(message);
1835                 goto err;
1836         }
1837
1838         blob->data = os_malloc(blob_len);
1839         blob->name = os_strdup(blob_name);
1840         if (!blob->data || !blob->name) {
1841                 reply = wpas_dbus_error_no_memory(message);
1842                 goto err;
1843         }
1844         os_memcpy(blob->data, blob_data, blob_len);
1845         blob->len = blob_len;
1846
1847         wpa_config_set_blob(wpa_s->conf, blob);
1848         wpas_notify_blob_added(wpa_s, blob->name);
1849
1850         return reply;
1851
1852 err:
1853         if (blob) {
1854                 os_free(blob->name);
1855                 os_free(blob->data);
1856                 os_free(blob);
1857         }
1858         return reply;
1859 }
1860
1861
1862 /**
1863  * wpas_dbus_handler_get_blob - Get named binary blob (ie, for certificates)
1864  * @message: Pointer to incoming dbus message
1865  * @wpa_s: %wpa_supplicant data structure
1866  * Returns: A dbus message containing array of bytes (blob)
1867  *
1868  * Gets one wpa_supplicant's binary blobs.
1869  */
1870 DBusMessage * wpas_dbus_handler_get_blob(DBusMessage *message,
1871                                          struct wpa_supplicant *wpa_s)
1872 {
1873         DBusMessage *reply = NULL;
1874         DBusMessageIter iter, array_iter;
1875
1876         char *blob_name;
1877         const struct wpa_config_blob *blob;
1878
1879         dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &blob_name,
1880                               DBUS_TYPE_INVALID);
1881
1882         blob = wpa_config_get_blob(wpa_s->conf, blob_name);
1883         if (!blob) {
1884                 return dbus_message_new_error(message,
1885                                               WPAS_DBUS_ERROR_BLOB_UNKNOWN,
1886                                               "Blob id not set");
1887         }
1888
1889         reply = dbus_message_new_method_return(message);
1890         if (!reply)
1891                 return wpas_dbus_error_no_memory(message);
1892
1893         dbus_message_iter_init_append(reply, &iter);
1894
1895         if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
1896                                               DBUS_TYPE_BYTE_AS_STRING,
1897                                               &array_iter) ||
1898             !dbus_message_iter_append_fixed_array(&array_iter, DBUS_TYPE_BYTE,
1899                                                   &(blob->data), blob->len) ||
1900             !dbus_message_iter_close_container(&iter, &array_iter)) {
1901                 dbus_message_unref(reply);
1902                 reply = wpas_dbus_error_no_memory(message);
1903         }
1904
1905         return reply;
1906 }
1907
1908
1909 /**
1910  * wpas_remove_handler_remove_blob - Remove named binary blob
1911  * @message: Pointer to incoming dbus message
1912  * @wpa_s: %wpa_supplicant data structure
1913  * Returns: NULL on success or dbus error
1914  *
1915  * Asks wpa_supplicant to internally remove a binary blobs.
1916  */
1917 DBusMessage * wpas_dbus_handler_remove_blob(DBusMessage *message,
1918                                             struct wpa_supplicant *wpa_s)
1919 {
1920         DBusMessage *reply = NULL;
1921         char *blob_name;
1922
1923         dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &blob_name,
1924                               DBUS_TYPE_INVALID);
1925
1926         if (wpa_config_remove_blob(wpa_s->conf, blob_name)) {
1927                 return dbus_message_new_error(message,
1928                                               WPAS_DBUS_ERROR_BLOB_UNKNOWN,
1929                                               "Blob id not set");
1930         }
1931         wpas_notify_blob_removed(wpa_s, blob_name);
1932
1933         return reply;
1934
1935 }
1936
1937 #endif /* CONFIG_NO_CONFIG_BLOBS */
1938
1939
1940 /*
1941  * wpas_dbus_handler_flush_bss - Flush the BSS cache
1942  * @message: Pointer to incoming dbus message
1943  * @wpa_s: wpa_supplicant structure for a network interface
1944  * Returns: NULL
1945  *
1946  * Handler function for "FlushBSS" method call of network interface.
1947  */
1948 DBusMessage * wpas_dbus_handler_flush_bss(DBusMessage *message,
1949                                           struct wpa_supplicant *wpa_s)
1950 {
1951         dbus_uint32_t age;
1952
1953         dbus_message_get_args(message, NULL, DBUS_TYPE_UINT32, &age,
1954                               DBUS_TYPE_INVALID);
1955
1956         if (age == 0)
1957                 wpa_bss_flush(wpa_s);
1958         else
1959                 wpa_bss_flush_by_age(wpa_s, age);
1960
1961         return NULL;
1962 }
1963
1964
1965 #ifdef CONFIG_AUTOSCAN
1966 /**
1967  * wpas_dbus_handler_autoscan - Set autoscan parameters for the interface
1968  * @message: Pointer to incoming dbus message
1969  * @wpa_s: wpa_supplicant structure for a network interface
1970  * Returns: NULL
1971  *
1972  * Handler function for "AutoScan" method call of network interface.
1973  */
1974 DBusMessage * wpas_dbus_handler_autoscan(DBusMessage *message,
1975                                          struct wpa_supplicant *wpa_s)
1976 {
1977         DBusMessage *reply = NULL;
1978         enum wpa_states state = wpa_s->wpa_state;
1979         char *arg;
1980
1981         dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &arg,
1982                               DBUS_TYPE_INVALID);
1983
1984         if (arg != NULL && os_strlen(arg) > 0) {
1985                 char *tmp;
1986
1987                 tmp = os_strdup(arg);
1988                 if (tmp == NULL) {
1989                         reply = wpas_dbus_error_no_memory(message);
1990                 } else {
1991                         os_free(wpa_s->conf->autoscan);
1992                         wpa_s->conf->autoscan = tmp;
1993                         if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
1994                                 autoscan_init(wpa_s, 1);
1995                         else if (state == WPA_SCANNING)
1996                                 wpa_supplicant_reinit_autoscan(wpa_s);
1997                 }
1998         } else if (arg != NULL && os_strlen(arg) == 0) {
1999                 os_free(wpa_s->conf->autoscan);
2000                 wpa_s->conf->autoscan = NULL;
2001                 autoscan_deinit(wpa_s);
2002         } else
2003                 reply = dbus_message_new_error(message,
2004                                                DBUS_ERROR_INVALID_ARGS,
2005                                                NULL);
2006
2007         return reply;
2008 }
2009 #endif /* CONFIG_AUTOSCAN */
2010
2011
2012 /*
2013  * wpas_dbus_handler_eap_logoff - IEEE 802.1X EAPOL state machine logoff
2014  * @message: Pointer to incoming dbus message
2015  * @wpa_s: wpa_supplicant structure for a network interface
2016  * Returns: NULL
2017  *
2018  * Handler function for "EAPLogoff" method call of network interface.
2019  */
2020 DBusMessage * wpas_dbus_handler_eap_logoff(DBusMessage *message,
2021                                            struct wpa_supplicant *wpa_s)
2022 {
2023         eapol_sm_notify_logoff(wpa_s->eapol, TRUE);
2024         return NULL;
2025 }
2026
2027
2028 /*
2029  * wpas_dbus_handler_eap_logon - IEEE 802.1X EAPOL state machine logon
2030  * @message: Pointer to incoming dbus message
2031  * @wpa_s: wpa_supplicant structure for a network interface
2032  * Returns: NULL
2033  *
2034  * Handler function for "EAPLogin" method call of network interface.
2035  */
2036 DBusMessage * wpas_dbus_handler_eap_logon(DBusMessage *message,
2037                                           struct wpa_supplicant *wpa_s)
2038 {
2039         eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
2040         return NULL;
2041 }
2042
2043
2044 #ifdef CONFIG_TDLS
2045
2046 static int get_peer_hwaddr_helper(DBusMessage *message, const char *func_name,
2047                                   u8 *peer_address, DBusMessage **error)
2048 {
2049         const char *peer_string;
2050
2051         *error = NULL;
2052
2053         if (!dbus_message_get_args(message, NULL,
2054                                    DBUS_TYPE_STRING, &peer_string,
2055                                    DBUS_TYPE_INVALID)) {
2056                 *error = wpas_dbus_error_invalid_args(message, NULL);
2057                 return -1;
2058         }
2059
2060         if (hwaddr_aton(peer_string, peer_address)) {
2061                 wpa_printf(MSG_DEBUG, "%s: invalid address '%s'",
2062                            func_name, peer_string);
2063                 *error = wpas_dbus_error_invalid_args(
2064                         message, "Invalid hardware address format");
2065                 return -1;
2066         }
2067
2068         return 0;
2069 }
2070
2071
2072 /*
2073  * wpas_dbus_handler_tdls_discover - Discover TDLS peer
2074  * @message: Pointer to incoming dbus message
2075  * @wpa_s: wpa_supplicant structure for a network interface
2076  * Returns: NULL indicating success or DBus error message on failure
2077  *
2078  * Handler function for "TDLSDiscover" method call of network interface.
2079  */
2080 DBusMessage * wpas_dbus_handler_tdls_discover(DBusMessage *message,
2081                                               struct wpa_supplicant *wpa_s)
2082 {
2083         u8 peer[ETH_ALEN];
2084         DBusMessage *error_reply;
2085         int ret;
2086
2087         if (get_peer_hwaddr_helper(message, __func__, peer, &error_reply) < 0)
2088                 return error_reply;
2089
2090         wpa_printf(MSG_DEBUG, "DBUS TDLS_DISCOVER " MACSTR, MAC2STR(peer));
2091
2092         if (wpa_tdls_is_external_setup(wpa_s->wpa))
2093                 ret = wpa_tdls_send_discovery_request(wpa_s->wpa, peer);
2094         else
2095                 ret = wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer);
2096
2097         if (ret) {
2098                 return wpas_dbus_error_unknown_error(
2099                         message, "error performing TDLS discovery");
2100         }
2101
2102         return NULL;
2103 }
2104
2105
2106 /*
2107  * wpas_dbus_handler_tdls_setup - Setup TDLS session
2108  * @message: Pointer to incoming dbus message
2109  * @wpa_s: wpa_supplicant structure for a network interface
2110  * Returns: NULL indicating success or DBus error message on failure
2111  *
2112  * Handler function for "TDLSSetup" method call of network interface.
2113  */
2114 DBusMessage * wpas_dbus_handler_tdls_setup(DBusMessage *message,
2115                                            struct wpa_supplicant *wpa_s)
2116 {
2117         u8 peer[ETH_ALEN];
2118         DBusMessage *error_reply;
2119         int ret;
2120
2121         if (get_peer_hwaddr_helper(message, __func__, peer, &error_reply) < 0)
2122                 return error_reply;
2123
2124         wpa_printf(MSG_DEBUG, "DBUS TDLS_SETUP " MACSTR, MAC2STR(peer));
2125
2126         wpa_tdls_remove(wpa_s->wpa, peer);
2127         if (wpa_tdls_is_external_setup(wpa_s->wpa))
2128                 ret = wpa_tdls_start(wpa_s->wpa, peer);
2129         else
2130                 ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
2131
2132         if (ret) {
2133                 return wpas_dbus_error_unknown_error(
2134                         message, "error performing TDLS setup");
2135         }
2136
2137         return NULL;
2138 }
2139
2140
2141 /*
2142  * wpas_dbus_handler_tdls_status - Return TDLS session status
2143  * @message: Pointer to incoming dbus message
2144  * @wpa_s: wpa_supplicant structure for a network interface
2145  * Returns: A string representing the state of the link to this TDLS peer
2146  *
2147  * Handler function for "TDLSStatus" method call of network interface.
2148  */
2149 DBusMessage * wpas_dbus_handler_tdls_status(DBusMessage *message,
2150                                             struct wpa_supplicant *wpa_s)
2151 {
2152         u8 peer[ETH_ALEN];
2153         DBusMessage *reply;
2154         const char *tdls_status;
2155
2156         if (get_peer_hwaddr_helper(message, __func__, peer, &reply) < 0)
2157                 return reply;
2158
2159         wpa_printf(MSG_DEBUG, "DBUS TDLS_STATUS " MACSTR, MAC2STR(peer));
2160
2161         tdls_status = wpa_tdls_get_link_status(wpa_s->wpa, peer);
2162
2163         reply = dbus_message_new_method_return(message);
2164         dbus_message_append_args(reply, DBUS_TYPE_STRING,
2165                                  &tdls_status, DBUS_TYPE_INVALID);
2166         return reply;
2167 }
2168
2169
2170 /*
2171  * wpas_dbus_handler_tdls_teardown - Teardown TDLS session
2172  * @message: Pointer to incoming dbus message
2173  * @wpa_s: wpa_supplicant structure for a network interface
2174  * Returns: NULL indicating success or DBus error message on failure
2175  *
2176  * Handler function for "TDLSTeardown" method call of network interface.
2177  */
2178 DBusMessage * wpas_dbus_handler_tdls_teardown(DBusMessage *message,
2179                                               struct wpa_supplicant *wpa_s)
2180 {
2181         u8 peer[ETH_ALEN];
2182         DBusMessage *error_reply;
2183         int ret;
2184
2185         if (get_peer_hwaddr_helper(message, __func__, peer, &error_reply) < 0)
2186                 return error_reply;
2187
2188         wpa_printf(MSG_DEBUG, "DBUS TDLS_TEARDOWN " MACSTR, MAC2STR(peer));
2189
2190         if (wpa_tdls_is_external_setup(wpa_s->wpa))
2191                 ret = wpa_tdls_teardown_link(
2192                         wpa_s->wpa, peer,
2193                         WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
2194         else
2195                 ret = wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
2196
2197         if (ret) {
2198                 return wpas_dbus_error_unknown_error(
2199                         message, "error performing TDLS teardown");
2200         }
2201
2202         return NULL;
2203 }
2204
2205 #endif /* CONFIG_TDLS */
2206
2207
2208 /**
2209  * wpas_dbus_handler_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
2210  * @message: Pointer to incoming dbus message
2211  * @wpa_s: %wpa_supplicant data structure
2212  * Returns: A dbus message containing an error on failure or NULL on success
2213  *
2214  * Sets the PKCS #11 engine and module path.
2215  */
2216 DBusMessage * wpas_dbus_handler_set_pkcs11_engine_and_module_path(
2217         DBusMessage *message, struct wpa_supplicant *wpa_s)
2218 {
2219         DBusMessageIter iter;
2220         char *value = NULL;
2221         char *pkcs11_engine_path = NULL;
2222         char *pkcs11_module_path = NULL;
2223
2224         dbus_message_iter_init(message, &iter);
2225         dbus_message_iter_get_basic(&iter, &value);
2226         if (value == NULL) {
2227                 return dbus_message_new_error(
2228                         message, DBUS_ERROR_INVALID_ARGS,
2229                         "Invalid pkcs11_engine_path argument");
2230         }
2231         /* Empty path defaults to NULL */
2232         if (os_strlen(value))
2233                 pkcs11_engine_path = value;
2234
2235         dbus_message_iter_next(&iter);
2236         dbus_message_iter_get_basic(&iter, &value);
2237         if (value == NULL) {
2238                 os_free(pkcs11_engine_path);
2239                 return dbus_message_new_error(
2240                         message, DBUS_ERROR_INVALID_ARGS,
2241                         "Invalid pkcs11_module_path argument");
2242         }
2243         /* Empty path defaults to NULL */
2244         if (os_strlen(value))
2245                 pkcs11_module_path = value;
2246
2247         if (wpas_set_pkcs11_engine_and_module_path(wpa_s, pkcs11_engine_path,
2248                                                    pkcs11_module_path))
2249                 return dbus_message_new_error(
2250                         message, DBUS_ERROR_FAILED,
2251                         "Reinit of the EAPOL state machine with the new PKCS #11 engine and module path failed.");
2252
2253         wpa_dbus_mark_property_changed(
2254                 wpa_s->global->dbus, wpa_s->dbus_new_path,
2255                 WPAS_DBUS_NEW_IFACE_INTERFACE, "PKCS11EnginePath");
2256         wpa_dbus_mark_property_changed(
2257                 wpa_s->global->dbus, wpa_s->dbus_new_path,
2258                 WPAS_DBUS_NEW_IFACE_INTERFACE, "PKCS11ModulePath");
2259
2260         return NULL;
2261 }
2262
2263
2264 /**
2265  * wpas_dbus_getter_capabilities - Return interface capabilities
2266  * @iter: Pointer to incoming dbus message iter
2267  * @error: Location to store error on failure
2268  * @user_data: Function specific data
2269  * Returns: TRUE on success, FALSE on failure
2270  *
2271  * Getter for "Capabilities" property of an interface.
2272  */
2273 dbus_bool_t wpas_dbus_getter_capabilities(DBusMessageIter *iter,
2274                                           DBusError *error, void *user_data)
2275 {
2276         struct wpa_supplicant *wpa_s = user_data;
2277         struct wpa_driver_capa capa;
2278         int res;
2279         DBusMessageIter iter_dict, iter_dict_entry, iter_dict_val, iter_array,
2280                 variant_iter;
2281         const char *scans[] = { "active", "passive", "ssid" };
2282
2283         if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
2284                                               "a{sv}", &variant_iter) ||
2285             !wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
2286                 goto nomem;
2287
2288         res = wpa_drv_get_capa(wpa_s, &capa);
2289
2290         /***** pairwise cipher */
2291         if (res < 0) {
2292                 const char *args[] = {"ccmp", "tkip", "none"};
2293
2294                 if (!wpa_dbus_dict_append_string_array(
2295                             &iter_dict, "Pairwise", args,
2296                             ARRAY_SIZE(args)))
2297                         goto nomem;
2298         } else {
2299                 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Pairwise",
2300                                                       &iter_dict_entry,
2301                                                       &iter_dict_val,
2302                                                       &iter_array) ||
2303                     ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP_256) &&
2304                      !wpa_dbus_dict_string_array_add_element(
2305                              &iter_array, "ccmp-256")) ||
2306                     ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP_256) &&
2307                      !wpa_dbus_dict_string_array_add_element(
2308                              &iter_array, "gcmp-256")) ||
2309                     ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) &&
2310                      !wpa_dbus_dict_string_array_add_element(
2311                              &iter_array, "ccmp")) ||
2312                     ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP) &&
2313                      !wpa_dbus_dict_string_array_add_element(
2314                              &iter_array, "gcmp")) ||
2315                     ((capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) &&
2316                      !wpa_dbus_dict_string_array_add_element(
2317                              &iter_array, "tkip")) ||
2318                     ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) &&
2319                      !wpa_dbus_dict_string_array_add_element(
2320                              &iter_array, "none")) ||
2321                     !wpa_dbus_dict_end_string_array(&iter_dict,
2322                                                     &iter_dict_entry,
2323                                                     &iter_dict_val,
2324                                                     &iter_array))
2325                         goto nomem;
2326         }
2327
2328         /***** group cipher */
2329         if (res < 0) {
2330                 const char *args[] = {
2331                         "ccmp", "tkip", "wep104", "wep40"
2332                 };
2333
2334                 if (!wpa_dbus_dict_append_string_array(
2335                             &iter_dict, "Group", args,
2336                             ARRAY_SIZE(args)))
2337                         goto nomem;
2338         } else {
2339                 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Group",
2340                                                       &iter_dict_entry,
2341                                                       &iter_dict_val,
2342                                                       &iter_array) ||
2343                     ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP_256) &&
2344                      !wpa_dbus_dict_string_array_add_element(
2345                              &iter_array, "ccmp-256")) ||
2346                     ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP_256) &&
2347                      !wpa_dbus_dict_string_array_add_element(
2348                              &iter_array, "gcmp-256")) ||
2349                     ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) &&
2350                      !wpa_dbus_dict_string_array_add_element(
2351                              &iter_array, "ccmp")) ||
2352                     ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP) &&
2353                      !wpa_dbus_dict_string_array_add_element(
2354                              &iter_array, "gcmp")) ||
2355                     ((capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) &&
2356                      !wpa_dbus_dict_string_array_add_element(
2357                              &iter_array, "tkip")) ||
2358                     ((capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) &&
2359                      !wpa_dbus_dict_string_array_add_element(
2360                              &iter_array, "wep104")) ||
2361                     ((capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) &&
2362                      !wpa_dbus_dict_string_array_add_element(
2363                              &iter_array, "wep40")) ||
2364                     !wpa_dbus_dict_end_string_array(&iter_dict,
2365                                                     &iter_dict_entry,
2366                                                     &iter_dict_val,
2367                                                     &iter_array))
2368                         goto nomem;
2369         }
2370
2371         /***** key management */
2372         if (res < 0) {
2373                 const char *args[] = {
2374                         "wpa-psk", "wpa-eap", "ieee8021x", "wpa-none",
2375 #ifdef CONFIG_WPS
2376                         "wps",
2377 #endif /* CONFIG_WPS */
2378                         "none"
2379                 };
2380                 if (!wpa_dbus_dict_append_string_array(
2381                             &iter_dict, "KeyMgmt", args,
2382                             ARRAY_SIZE(args)))
2383                         goto nomem;
2384         } else {
2385                 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "KeyMgmt",
2386                                                       &iter_dict_entry,
2387                                                       &iter_dict_val,
2388                                                       &iter_array) ||
2389                     !wpa_dbus_dict_string_array_add_element(&iter_array,
2390                                                             "none") ||
2391                     !wpa_dbus_dict_string_array_add_element(&iter_array,
2392                                                             "ieee8021x"))
2393                         goto nomem;
2394
2395                 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
2396                                      WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
2397                         if (!wpa_dbus_dict_string_array_add_element(
2398                                     &iter_array, "wpa-eap") ||
2399                             ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT) &&
2400                              !wpa_dbus_dict_string_array_add_element(
2401                                      &iter_array, "wpa-ft-eap")))
2402                                 goto nomem;
2403
2404 /* TODO: Ensure that driver actually supports sha256 encryption. */
2405 #ifdef CONFIG_IEEE80211W
2406                         if (!wpa_dbus_dict_string_array_add_element(
2407                                     &iter_array, "wpa-eap-sha256"))
2408                                 goto nomem;
2409 #endif /* CONFIG_IEEE80211W */
2410                 }
2411
2412                 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
2413                                      WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
2414                         if (!wpa_dbus_dict_string_array_add_element(
2415                                     &iter_array, "wpa-psk") ||
2416                             ((capa.key_mgmt &
2417                               WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK) &&
2418                              !wpa_dbus_dict_string_array_add_element(
2419                                      &iter_array, "wpa-ft-psk")))
2420                                 goto nomem;
2421
2422 /* TODO: Ensure that driver actually supports sha256 encryption. */
2423 #ifdef CONFIG_IEEE80211W
2424                         if (!wpa_dbus_dict_string_array_add_element(
2425                                     &iter_array, "wpa-psk-sha256"))
2426                                 goto nomem;
2427 #endif /* CONFIG_IEEE80211W */
2428                 }
2429
2430                 if ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) &&
2431                     !wpa_dbus_dict_string_array_add_element(&iter_array,
2432                                                             "wpa-none"))
2433                         goto nomem;
2434
2435
2436 #ifdef CONFIG_WPS
2437                 if (!wpa_dbus_dict_string_array_add_element(&iter_array,
2438                                                             "wps"))
2439                         goto nomem;
2440 #endif /* CONFIG_WPS */
2441
2442                 if (!wpa_dbus_dict_end_string_array(&iter_dict,
2443                                                     &iter_dict_entry,
2444                                                     &iter_dict_val,
2445                                                     &iter_array))
2446                         goto nomem;
2447         }
2448
2449         /***** WPA protocol */
2450         if (res < 0) {
2451                 const char *args[] = { "rsn", "wpa" };
2452
2453                 if (!wpa_dbus_dict_append_string_array(
2454                             &iter_dict, "Protocol", args,
2455                             ARRAY_SIZE(args)))
2456                         goto nomem;
2457         } else {
2458                 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Protocol",
2459                                                       &iter_dict_entry,
2460                                                       &iter_dict_val,
2461                                                       &iter_array) ||
2462                     ((capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
2463                                        WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) &&
2464                      !wpa_dbus_dict_string_array_add_element(
2465                              &iter_array, "rsn")) ||
2466                     ((capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
2467                                        WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) &&
2468                      !wpa_dbus_dict_string_array_add_element(
2469                              &iter_array, "wpa")) ||
2470                     !wpa_dbus_dict_end_string_array(&iter_dict,
2471                                                     &iter_dict_entry,
2472                                                     &iter_dict_val,
2473                                                     &iter_array))
2474                         goto nomem;
2475         }
2476
2477         /***** auth alg */
2478         if (res < 0) {
2479                 const char *args[] = { "open", "shared", "leap" };
2480
2481                 if (!wpa_dbus_dict_append_string_array(
2482                             &iter_dict, "AuthAlg", args,
2483                             ARRAY_SIZE(args)))
2484                         goto nomem;
2485         } else {
2486                 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "AuthAlg",
2487                                                       &iter_dict_entry,
2488                                                       &iter_dict_val,
2489                                                       &iter_array))
2490                         goto nomem;
2491
2492                 if (((capa.auth & WPA_DRIVER_AUTH_OPEN) &&
2493                      !wpa_dbus_dict_string_array_add_element(
2494                              &iter_array, "open")) ||
2495                     ((capa.auth & WPA_DRIVER_AUTH_SHARED) &&
2496                      !wpa_dbus_dict_string_array_add_element(
2497                              &iter_array, "shared")) ||
2498                     ((capa.auth & WPA_DRIVER_AUTH_LEAP) &&
2499                      !wpa_dbus_dict_string_array_add_element(
2500                              &iter_array, "leap")) ||
2501                     !wpa_dbus_dict_end_string_array(&iter_dict,
2502                                                     &iter_dict_entry,
2503                                                     &iter_dict_val,
2504                                                     &iter_array))
2505                         goto nomem;
2506         }
2507
2508         /***** Scan */
2509         if (!wpa_dbus_dict_append_string_array(&iter_dict, "Scan", scans,
2510                                                ARRAY_SIZE(scans)))
2511                 goto nomem;
2512
2513         /***** Modes */
2514         if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Modes",
2515                                               &iter_dict_entry,
2516                                               &iter_dict_val,
2517                                               &iter_array) ||
2518             !wpa_dbus_dict_string_array_add_element(
2519                     &iter_array, "infrastructure") ||
2520             !wpa_dbus_dict_string_array_add_element(
2521                     &iter_array, "ad-hoc") ||
2522             (res >= 0 && (capa.flags & WPA_DRIVER_FLAGS_AP) &&
2523              !wpa_dbus_dict_string_array_add_element(
2524                      &iter_array, "ap")) ||
2525             (res >= 0 && (capa.flags & WPA_DRIVER_FLAGS_P2P_CAPABLE) &&
2526              !wpa_dbus_dict_string_array_add_element(
2527                      &iter_array, "p2p")) ||
2528             !wpa_dbus_dict_end_string_array(&iter_dict,
2529                                             &iter_dict_entry,
2530                                             &iter_dict_val,
2531                                             &iter_array))
2532                 goto nomem;
2533         /***** Modes end */
2534
2535         if (res >= 0) {
2536                 dbus_int32_t max_scan_ssid = capa.max_scan_ssids;
2537
2538                 if (!wpa_dbus_dict_append_int32(&iter_dict, "MaxScanSSID",
2539                                                 max_scan_ssid))
2540                         goto nomem;
2541         }
2542
2543         if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict) ||
2544             !dbus_message_iter_close_container(iter, &variant_iter))
2545                 goto nomem;
2546
2547         return TRUE;
2548
2549 nomem:
2550         dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
2551         return FALSE;
2552 }
2553
2554
2555 /**
2556  * wpas_dbus_getter_state - Get interface state
2557  * @iter: Pointer to incoming dbus message iter
2558  * @error: Location to store error on failure
2559  * @user_data: Function specific data
2560  * Returns: TRUE on success, FALSE on failure
2561  *
2562  * Getter for "State" property.
2563  */
2564 dbus_bool_t wpas_dbus_getter_state(DBusMessageIter *iter, DBusError *error,
2565                                    void *user_data)
2566 {
2567         struct wpa_supplicant *wpa_s = user_data;
2568         const char *str_state;
2569         char *state_ls, *tmp;
2570         dbus_bool_t success = FALSE;
2571
2572         str_state = wpa_supplicant_state_txt(wpa_s->wpa_state);
2573
2574         /* make state string lowercase to fit new DBus API convention
2575          */
2576         state_ls = tmp = os_strdup(str_state);
2577         if (!tmp) {
2578                 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
2579                 return FALSE;
2580         }
2581         while (*tmp) {
2582                 *tmp = tolower(*tmp);
2583                 tmp++;
2584         }
2585
2586         success = wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
2587                                                    &state_ls, error);
2588
2589         os_free(state_ls);
2590
2591         return success;
2592 }
2593
2594
2595 /**
2596  * wpas_dbus_new_iface_get_scanning - Get interface scanning state
2597  * @iter: Pointer to incoming dbus message iter
2598  * @error: Location to store error on failure
2599  * @user_data: Function specific data
2600  * Returns: TRUE on success, FALSE on failure
2601  *
2602  * Getter for "scanning" property.
2603  */
2604 dbus_bool_t wpas_dbus_getter_scanning(DBusMessageIter *iter, DBusError *error,
2605                                       void *user_data)
2606 {
2607         struct wpa_supplicant *wpa_s = user_data;
2608         dbus_bool_t scanning = wpa_s->scanning ? TRUE : FALSE;
2609
2610         return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
2611                                                 &scanning, error);
2612 }
2613
2614
2615 /**
2616  * wpas_dbus_getter_ap_scan - Control roaming mode
2617  * @iter: Pointer to incoming dbus message iter
2618  * @error: Location to store error on failure
2619  * @user_data: Function specific data
2620  * Returns: TRUE on success, FALSE on failure
2621  *
2622  * Getter function for "ApScan" property.
2623  */
2624 dbus_bool_t wpas_dbus_getter_ap_scan(DBusMessageIter *iter, DBusError *error,
2625                                      void *user_data)
2626 {
2627         struct wpa_supplicant *wpa_s = user_data;
2628         dbus_uint32_t ap_scan = wpa_s->conf->ap_scan;
2629
2630         return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
2631                                                 &ap_scan, error);
2632 }
2633
2634
2635 /**
2636  * wpas_dbus_setter_ap_scan - Control roaming mode
2637  * @iter: Pointer to incoming dbus message iter
2638  * @error: Location to store error on failure
2639  * @user_data: Function specific data
2640  * Returns: TRUE on success, FALSE on failure
2641  *
2642  * Setter function for "ApScan" property.
2643  */
2644 dbus_bool_t wpas_dbus_setter_ap_scan(DBusMessageIter *iter, DBusError *error,
2645                                      void *user_data)
2646 {
2647         struct wpa_supplicant *wpa_s = user_data;
2648         dbus_uint32_t ap_scan;
2649
2650         if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
2651                                               &ap_scan))
2652                 return FALSE;
2653
2654         if (wpa_supplicant_set_ap_scan(wpa_s, ap_scan)) {
2655                 dbus_set_error_const(error, DBUS_ERROR_FAILED,
2656                                      "ap_scan must be 0, 1, or 2");
2657                 return FALSE;
2658         }
2659         return TRUE;
2660 }
2661
2662
2663 /**
2664  * wpas_dbus_getter_fast_reauth - Control fast
2665  * reauthentication (TLS session resumption)
2666  * @iter: Pointer to incoming dbus message iter
2667  * @error: Location to store error on failure
2668  * @user_data: Function specific data
2669  * Returns: TRUE on success, FALSE on failure
2670  *
2671  * Getter function for "FastReauth" property.
2672  */
2673 dbus_bool_t wpas_dbus_getter_fast_reauth(DBusMessageIter *iter,
2674                                          DBusError *error,
2675                                          void *user_data)
2676 {
2677         struct wpa_supplicant *wpa_s = user_data;
2678         dbus_bool_t fast_reauth = wpa_s->conf->fast_reauth ? TRUE : FALSE;
2679
2680         return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
2681                                                 &fast_reauth, error);
2682 }
2683
2684
2685 /**
2686  * wpas_dbus_setter_fast_reauth - Control fast
2687  * reauthentication (TLS session resumption)
2688  * @iter: Pointer to incoming dbus message iter
2689  * @error: Location to store error on failure
2690  * @user_data: Function specific data
2691  * Returns: TRUE on success, FALSE on failure
2692  *
2693  * Setter function for "FastReauth" property.
2694  */
2695 dbus_bool_t wpas_dbus_setter_fast_reauth(DBusMessageIter *iter,
2696                                      DBusError *error,
2697                                      void *user_data)
2698 {
2699         struct wpa_supplicant *wpa_s = user_data;
2700         dbus_bool_t fast_reauth;
2701
2702         if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
2703                                               &fast_reauth))
2704                 return FALSE;
2705
2706         wpa_s->conf->fast_reauth = fast_reauth;
2707         return TRUE;
2708 }
2709
2710
2711 /**
2712  * wpas_dbus_getter_disconnect_reason - Get most recent reason for disconnect
2713  * @iter: Pointer to incoming dbus message iter
2714  * @error: Location to store error on failure
2715  * @user_data: Function specific data
2716  * Returns: TRUE on success, FALSE on failure
2717  *
2718  * Getter for "DisconnectReason" property.  The reason is negative if it is
2719  * locally generated.
2720  */
2721 dbus_bool_t wpas_dbus_getter_disconnect_reason(DBusMessageIter *iter,
2722                                                DBusError *error,
2723                                                void *user_data)
2724 {
2725         struct wpa_supplicant *wpa_s = user_data;
2726         dbus_int32_t reason = wpa_s->disconnect_reason;
2727
2728         return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
2729                                                 &reason, error);
2730 }
2731
2732
2733 /**
2734  * wpas_dbus_getter_bss_expire_age - Get BSS entry expiration age
2735  * @iter: Pointer to incoming dbus message iter
2736  * @error: Location to store error on failure
2737  * @user_data: Function specific data
2738  * Returns: TRUE on success, FALSE on failure
2739  *
2740  * Getter function for "BSSExpireAge" property.
2741  */
2742 dbus_bool_t wpas_dbus_getter_bss_expire_age(DBusMessageIter *iter,
2743                                             DBusError *error,
2744                                             void *user_data)
2745 {
2746         struct wpa_supplicant *wpa_s = user_data;
2747         dbus_uint32_t expire_age = wpa_s->conf->bss_expiration_age;
2748
2749         return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
2750                                                 &expire_age, error);
2751 }
2752
2753
2754 /**
2755  * wpas_dbus_setter_bss_expire_age - Control BSS entry expiration age
2756  * @iter: Pointer to incoming dbus message iter
2757  * @error: Location to store error on failure
2758  * @user_data: Function specific data
2759  * Returns: TRUE on success, FALSE on failure
2760  *
2761  * Setter function for "BSSExpireAge" property.
2762  */
2763 dbus_bool_t wpas_dbus_setter_bss_expire_age(DBusMessageIter *iter,
2764                                             DBusError *error,
2765                                             void *user_data)
2766 {
2767         struct wpa_supplicant *wpa_s = user_data;
2768         dbus_uint32_t expire_age;
2769
2770         if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
2771                                               &expire_age))
2772                 return FALSE;
2773
2774         if (wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age)) {
2775                 dbus_set_error_const(error, DBUS_ERROR_FAILED,
2776                                      "BSSExpireAge must be >= 10");
2777                 return FALSE;
2778         }
2779         return TRUE;
2780 }
2781
2782
2783 /**
2784  * wpas_dbus_getter_bss_expire_count - Get BSS entry expiration scan count
2785  * @iter: Pointer to incoming dbus message iter
2786  * @error: Location to store error on failure
2787  * @user_data: Function specific data
2788  * Returns: TRUE on success, FALSE on failure
2789  *
2790  * Getter function for "BSSExpireCount" property.
2791  */
2792 dbus_bool_t wpas_dbus_getter_bss_expire_count(DBusMessageIter *iter,
2793                                               DBusError *error,
2794                                               void *user_data)
2795 {
2796         struct wpa_supplicant *wpa_s = user_data;
2797         dbus_uint32_t expire_count = wpa_s->conf->bss_expiration_scan_count;
2798
2799         return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
2800                                                 &expire_count, error);
2801 }
2802
2803
2804 /**
2805  * wpas_dbus_setter_bss_expire_count - Control BSS entry expiration scan count
2806  * @iter: Pointer to incoming dbus message iter
2807  * @error: Location to store error on failure
2808  * @user_data: Function specific data
2809  * Returns: TRUE on success, FALSE on failure
2810  *
2811  * Setter function for "BSSExpireCount" property.
2812  */
2813 dbus_bool_t wpas_dbus_setter_bss_expire_count(DBusMessageIter *iter,
2814                                               DBusError *error,
2815                                               void *user_data)
2816 {
2817         struct wpa_supplicant *wpa_s = user_data;
2818         dbus_uint32_t expire_count;
2819
2820         if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
2821                                               &expire_count))
2822                 return FALSE;
2823
2824         if (wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count)) {
2825                 dbus_set_error_const(error, DBUS_ERROR_FAILED,
2826                                      "BSSExpireCount must be > 0");
2827                 return FALSE;
2828         }
2829         return TRUE;
2830 }
2831
2832
2833 /**
2834  * wpas_dbus_getter_country - Control country code
2835  * @iter: Pointer to incoming dbus message iter
2836  * @error: Location to store error on failure
2837  * @user_data: Function specific data
2838  * Returns: TRUE on success, FALSE on failure
2839  *
2840  * Getter function for "Country" property.
2841  */
2842 dbus_bool_t wpas_dbus_getter_country(DBusMessageIter *iter, DBusError *error,
2843                                      void *user_data)
2844 {
2845         struct wpa_supplicant *wpa_s = user_data;
2846         char country[3];
2847         char *str = country;
2848
2849         country[0] = wpa_s->conf->country[0];
2850         country[1] = wpa_s->conf->country[1];
2851         country[2] = '\0';
2852
2853         return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
2854                                                 &str, error);
2855 }
2856
2857
2858 /**
2859  * wpas_dbus_setter_country - Control country code
2860  * @iter: Pointer to incoming dbus message iter
2861  * @error: Location to store error on failure
2862  * @user_data: Function specific data
2863  * Returns: TRUE on success, FALSE on failure
2864  *
2865  * Setter function for "Country" property.
2866  */
2867 dbus_bool_t wpas_dbus_setter_country(DBusMessageIter *iter, DBusError *error,
2868                                      void *user_data)
2869 {
2870         struct wpa_supplicant *wpa_s = user_data;
2871         const char *country;
2872
2873         if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
2874                                               &country))
2875                 return FALSE;
2876
2877         if (!country[0] || !country[1]) {
2878                 dbus_set_error_const(error, DBUS_ERROR_FAILED,
2879                                      "invalid country code");
2880                 return FALSE;
2881         }
2882
2883         if (wpa_s->drv_priv != NULL && wpa_drv_set_country(wpa_s, country)) {
2884                 wpa_printf(MSG_DEBUG, "Failed to set country");
2885                 dbus_set_error_const(error, DBUS_ERROR_FAILED,
2886                                      "failed to set country code");
2887                 return FALSE;
2888         }
2889
2890         wpa_s->conf->country[0] = country[0];
2891         wpa_s->conf->country[1] = country[1];
2892         return TRUE;
2893 }
2894
2895
2896 /**
2897  * wpas_dbus_getter_scan_interval - Get scan interval
2898  * @iter: Pointer to incoming dbus message iter
2899  * @error: Location to store error on failure
2900  * @user_data: Function specific data
2901  * Returns: TRUE on success, FALSE on failure
2902  *
2903  * Getter function for "ScanInterval" property.
2904  */
2905 dbus_bool_t wpas_dbus_getter_scan_interval(DBusMessageIter *iter,
2906                                            DBusError *error,
2907                                            void *user_data)
2908 {
2909         struct wpa_supplicant *wpa_s = user_data;
2910         dbus_int32_t scan_interval = wpa_s->scan_interval;
2911
2912         return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
2913                                                 &scan_interval, error);
2914 }
2915
2916
2917 /**
2918  * wpas_dbus_setter_scan_interval - Control scan interval
2919  * @iter: Pointer to incoming dbus message iter
2920  * @error: Location to store error on failure
2921  * @user_data: Function specific data
2922  * Returns: TRUE on success, FALSE on failure
2923  *
2924  * Setter function for "ScanInterval" property.
2925  */
2926 dbus_bool_t wpas_dbus_setter_scan_interval(DBusMessageIter *iter,
2927                                            DBusError *error,
2928                                            void *user_data)
2929 {
2930         struct wpa_supplicant *wpa_s = user_data;
2931         dbus_int32_t scan_interval;
2932
2933         if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_INT32,
2934                                               &scan_interval))
2935                 return FALSE;
2936
2937         if (wpa_supplicant_set_scan_interval(wpa_s, scan_interval)) {
2938                 dbus_set_error_const(error, DBUS_ERROR_FAILED,
2939                                      "scan_interval must be >= 0");
2940                 return FALSE;
2941         }
2942         return TRUE;
2943 }
2944
2945
2946 /**
2947  * wpas_dbus_getter_ifname - Get interface name
2948  * @iter: Pointer to incoming dbus message iter
2949  * @error: Location to store error on failure
2950  * @user_data: Function specific data
2951  * Returns: TRUE on success, FALSE on failure
2952  *
2953  * Getter for "Ifname" property.
2954  */
2955 dbus_bool_t wpas_dbus_getter_ifname(DBusMessageIter *iter, DBusError *error,
2956                                     void *user_data)
2957 {
2958         struct wpa_supplicant *wpa_s = user_data;
2959         const char *ifname = wpa_s->ifname;
2960
2961         return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
2962                                                 &ifname, error);
2963 }
2964
2965
2966 /**
2967  * wpas_dbus_getter_driver - Get interface name
2968  * @iter: Pointer to incoming dbus message iter
2969  * @error: Location to store error on failure
2970  * @user_data: Function specific data
2971  * Returns: TRUE on success, FALSE on failure
2972  *
2973  * Getter for "Driver" property.
2974  */
2975 dbus_bool_t wpas_dbus_getter_driver(DBusMessageIter *iter, DBusError *error,
2976                                     void *user_data)
2977 {
2978         struct wpa_supplicant *wpa_s = user_data;
2979         const char *driver;
2980
2981         if (wpa_s->driver == NULL || wpa_s->driver->name == NULL) {
2982                 wpa_printf(MSG_DEBUG, "%s[dbus]: wpa_s has no driver set",
2983                            __func__);
2984                 dbus_set_error(error, DBUS_ERROR_FAILED, "%s: no driver set",
2985                                __func__);
2986                 return FALSE;
2987         }
2988
2989         driver = wpa_s->driver->name;
2990         return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
2991                                                 &driver, error);
2992 }
2993
2994
2995 /**
2996  * wpas_dbus_getter_current_bss - Get current bss object path
2997  * @iter: Pointer to incoming dbus message iter
2998  * @error: Location to store error on failure
2999  * @user_data: Function specific data
3000  * Returns: TRUE on success, FALSE on failure
3001  *
3002  * Getter for "CurrentBSS" property.
3003  */
3004 dbus_bool_t wpas_dbus_getter_current_bss(DBusMessageIter *iter,
3005                                          DBusError *error,
3006                                          void *user_data)
3007 {
3008         struct wpa_supplicant *wpa_s = user_data;
3009         char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *bss_obj_path = path_buf;
3010
3011         if (wpa_s->current_bss)
3012                 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3013                             "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
3014                             wpa_s->dbus_new_path, wpa_s->current_bss->id);
3015         else
3016                 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
3017
3018         return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
3019                                                 &bss_obj_path, error);
3020 }
3021
3022
3023 /**
3024  * wpas_dbus_getter_current_network - Get current network object path
3025  * @iter: Pointer to incoming dbus message iter
3026  * @error: Location to store error on failure
3027  * @user_data: Function specific data
3028  * Returns: TRUE on success, FALSE on failure
3029  *
3030  * Getter for "CurrentNetwork" property.
3031  */
3032 dbus_bool_t wpas_dbus_getter_current_network(DBusMessageIter *iter,
3033                                              DBusError *error,
3034                                              void *user_data)
3035 {
3036         struct wpa_supplicant *wpa_s = user_data;
3037         char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *net_obj_path = path_buf;
3038
3039         if (wpa_s->current_ssid)
3040                 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3041                             "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
3042                             wpa_s->dbus_new_path, wpa_s->current_ssid->id);
3043         else
3044                 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
3045
3046         return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
3047                                                 &net_obj_path, error);
3048 }
3049
3050
3051 /**
3052  * wpas_dbus_getter_current_auth_mode - Get current authentication type
3053  * @iter: Pointer to incoming dbus message iter
3054  * @error: Location to store error on failure
3055  * @user_data: Function specific data
3056  * Returns: TRUE on success, FALSE on failure
3057  *
3058  * Getter for "CurrentAuthMode" property.
3059  */
3060 dbus_bool_t wpas_dbus_getter_current_auth_mode(DBusMessageIter *iter,
3061                                                DBusError *error,
3062                                                void *user_data)
3063 {
3064         struct wpa_supplicant *wpa_s = user_data;
3065         const char *eap_mode;
3066         const char *auth_mode;
3067         char eap_mode_buf[WPAS_DBUS_AUTH_MODE_MAX];
3068
3069         if (wpa_s->wpa_state != WPA_COMPLETED) {
3070                 auth_mode = "INACTIVE";
3071         } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X ||
3072             wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3073                 eap_mode = wpa_supplicant_get_eap_mode(wpa_s);
3074                 os_snprintf(eap_mode_buf, WPAS_DBUS_AUTH_MODE_MAX,
3075                             "EAP-%s", eap_mode);
3076                 auth_mode = eap_mode_buf;
3077
3078         } else {
3079                 auth_mode = wpa_key_mgmt_txt(wpa_s->key_mgmt,
3080                                              wpa_s->current_ssid->proto);
3081         }
3082
3083         return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3084                                                 &auth_mode, error);
3085 }
3086
3087
3088 /**
3089  * wpas_dbus_getter_bridge_ifname - Get interface name
3090  * @iter: Pointer to incoming dbus message iter
3091  * @error: Location to store error on failure
3092  * @user_data: Function specific data
3093  * Returns: TRUE on success, FALSE on failure
3094  *
3095  * Getter for "BridgeIfname" property.
3096  */
3097 dbus_bool_t wpas_dbus_getter_bridge_ifname(DBusMessageIter *iter,
3098                                            DBusError *error,
3099                                            void *user_data)
3100 {
3101         struct wpa_supplicant *wpa_s = user_data;
3102         const char *bridge_ifname = wpa_s->bridge_ifname;
3103
3104         return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3105                                                 &bridge_ifname, error);
3106 }
3107
3108
3109 /**
3110  * wpas_dbus_getter_bsss - Get array of BSSs objects
3111  * @iter: Pointer to incoming dbus message iter
3112  * @error: Location to store error on failure
3113  * @user_data: Function specific data
3114  * Returns: TRUE on success, FALSE on failure
3115  *
3116  * Getter for "BSSs" property.
3117  */
3118 dbus_bool_t wpas_dbus_getter_bsss(DBusMessageIter *iter, DBusError *error,
3119                                   void *user_data)
3120 {
3121         struct wpa_supplicant *wpa_s = user_data;
3122         struct wpa_bss *bss;
3123         char **paths;
3124         unsigned int i = 0;
3125         dbus_bool_t success = FALSE;
3126
3127         paths = os_calloc(wpa_s->num_bss, sizeof(char *));
3128         if (!paths) {
3129                 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3130                 return FALSE;
3131         }
3132
3133         /* Loop through scan results and append each result's object path */
3134         dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
3135                 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
3136                 if (paths[i] == NULL) {
3137                         dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
3138                                              "no memory");
3139                         goto out;
3140                 }
3141                 /* Construct the object path for this BSS. */
3142                 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
3143                             "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
3144                             wpa_s->dbus_new_path, bss->id);
3145         }
3146
3147         success = wpas_dbus_simple_array_property_getter(iter,
3148                                                          DBUS_TYPE_OBJECT_PATH,
3149                                                          paths, wpa_s->num_bss,
3150                                                          error);
3151
3152 out:
3153         while (i)
3154                 os_free(paths[--i]);
3155         os_free(paths);
3156         return success;
3157 }
3158
3159
3160 /**
3161  * wpas_dbus_getter_networks - Get array of networks objects
3162  * @iter: Pointer to incoming dbus message iter
3163  * @error: Location to store error on failure
3164  * @user_data: Function specific data
3165  * Returns: TRUE on success, FALSE on failure
3166  *
3167  * Getter for "Networks" property.
3168  */
3169 dbus_bool_t wpas_dbus_getter_networks(DBusMessageIter *iter, DBusError *error,
3170                                       void *user_data)
3171 {
3172         struct wpa_supplicant *wpa_s = user_data;
3173         struct wpa_ssid *ssid;
3174         char **paths;
3175         unsigned int i = 0, num = 0;
3176         dbus_bool_t success = FALSE;
3177
3178         for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
3179                 if (!network_is_persistent_group(ssid))
3180                         num++;
3181
3182         paths = os_calloc(num, sizeof(char *));
3183         if (!paths) {
3184                 dbus_set_error(error, DBUS_ERROR_NO_MEMORY, "no memory");
3185                 return FALSE;
3186         }
3187
3188         /* Loop through configured networks and append object path of each */
3189         for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
3190                 if (network_is_persistent_group(ssid))
3191                         continue;
3192                 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
3193                 if (paths[i] == NULL) {
3194                         dbus_set_error(error, DBUS_ERROR_NO_MEMORY,
3195                                        "no memory");
3196                         goto out;
3197                 }
3198
3199                 /* Construct the object path for this network. */
3200                 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
3201                             "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
3202                             wpa_s->dbus_new_path, ssid->id);
3203         }
3204
3205         success = wpas_dbus_simple_array_property_getter(iter,
3206                                                          DBUS_TYPE_OBJECT_PATH,
3207                                                          paths, num, error);
3208
3209 out:
3210         while (i)
3211                 os_free(paths[--i]);
3212         os_free(paths);
3213         return success;
3214 }
3215
3216
3217 /**
3218  * wpas_dbus_getter_pkcs11_engine_path - Get PKCS #11 engine path
3219  * @iter: Pointer to incoming dbus message iter
3220  * @error: Location to store error on failure
3221  * @user_data: Function specific data
3222  * Returns: A dbus message containing the PKCS #11 engine path
3223  *
3224  * Getter for "PKCS11EnginePath" property.
3225  */
3226 dbus_bool_t wpas_dbus_getter_pkcs11_engine_path(DBusMessageIter *iter,
3227                                                 DBusError *error,
3228                                                 void *user_data)
3229 {
3230         struct wpa_supplicant *wpa_s = user_data;
3231         const char *pkcs11_engine_path;
3232
3233         if (wpa_s->conf->pkcs11_engine_path == NULL)
3234                 pkcs11_engine_path = "";
3235         else
3236                 pkcs11_engine_path = wpa_s->conf->pkcs11_engine_path;
3237         return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3238                                                 &pkcs11_engine_path, error);
3239 }
3240
3241
3242 /**
3243  * wpas_dbus_getter_pkcs11_module_path - Get PKCS #11 module path
3244  * @iter: Pointer to incoming dbus message iter
3245  * @error: Location to store error on failure
3246  * @user_data: Function specific data
3247  * Returns: A dbus message containing the PKCS #11 module path
3248  *
3249  * Getter for "PKCS11ModulePath" property.
3250  */
3251 dbus_bool_t wpas_dbus_getter_pkcs11_module_path(DBusMessageIter *iter,
3252                                                 DBusError *error,
3253                                                 void *user_data)
3254 {
3255         struct wpa_supplicant *wpa_s = user_data;
3256         const char *pkcs11_module_path;
3257
3258         if (wpa_s->conf->pkcs11_module_path == NULL)
3259                 pkcs11_module_path = "";
3260         else
3261                 pkcs11_module_path = wpa_s->conf->pkcs11_module_path;
3262         return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3263                                                 &pkcs11_module_path, error);
3264 }
3265
3266
3267 /**
3268  * wpas_dbus_getter_blobs - Get all blobs defined for this interface
3269  * @iter: Pointer to incoming dbus message iter
3270  * @error: Location to store error on failure
3271  * @user_data: Function specific data
3272  * Returns: TRUE on success, FALSE on failure
3273  *
3274  * Getter for "Blobs" property.
3275  */
3276 dbus_bool_t wpas_dbus_getter_blobs(DBusMessageIter *iter, DBusError *error,
3277                                    void *user_data)
3278 {
3279         struct wpa_supplicant *wpa_s = user_data;
3280         DBusMessageIter variant_iter, dict_iter, entry_iter, array_iter;
3281         struct wpa_config_blob *blob;
3282
3283         if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
3284                                               "a{say}", &variant_iter) ||
3285             !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
3286                                               "{say}", &dict_iter)) {
3287                 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3288                 return FALSE;
3289         }
3290
3291         blob = wpa_s->conf->blobs;
3292         while (blob) {
3293                 if (!dbus_message_iter_open_container(&dict_iter,
3294                                                       DBUS_TYPE_DICT_ENTRY,
3295                                                       NULL, &entry_iter) ||
3296                     !dbus_message_iter_append_basic(&entry_iter,
3297                                                     DBUS_TYPE_STRING,
3298                                                     &(blob->name)) ||
3299                     !dbus_message_iter_open_container(&entry_iter,
3300                                                       DBUS_TYPE_ARRAY,
3301                                                       DBUS_TYPE_BYTE_AS_STRING,
3302                                                       &array_iter) ||
3303                     !dbus_message_iter_append_fixed_array(&array_iter,
3304                                                           DBUS_TYPE_BYTE,
3305                                                           &(blob->data),
3306                                                           blob->len) ||
3307                     !dbus_message_iter_close_container(&entry_iter,
3308                                                        &array_iter) ||
3309                     !dbus_message_iter_close_container(&dict_iter,
3310                                                        &entry_iter)) {
3311                         dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
3312                                              "no memory");
3313                         return FALSE;
3314                 }
3315
3316                 blob = blob->next;
3317         }
3318
3319         if (!dbus_message_iter_close_container(&variant_iter, &dict_iter) ||
3320             !dbus_message_iter_close_container(iter, &variant_iter)) {
3321                 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3322                 return FALSE;
3323         }
3324
3325         return TRUE;
3326 }
3327
3328
3329 static struct wpa_bss * get_bss_helper(struct bss_handler_args *args,
3330                                        DBusError *error, const char *func_name)
3331 {
3332         struct wpa_bss *res = wpa_bss_get_id(args->wpa_s, args->id);
3333
3334         if (!res) {
3335                 wpa_printf(MSG_ERROR, "%s[dbus]: no bss with id %d found",
3336                            func_name, args->id);
3337                 dbus_set_error(error, DBUS_ERROR_FAILED,
3338                                "%s: BSS %d not found",
3339                                func_name, args->id);
3340         }
3341
3342         return res;
3343 }
3344
3345
3346 /**
3347  * wpas_dbus_getter_bss_bssid - Return the BSSID of a BSS
3348  * @iter: Pointer to incoming dbus message iter
3349  * @error: Location to store error on failure
3350  * @user_data: Function specific data
3351  * Returns: TRUE on success, FALSE on failure
3352  *
3353  * Getter for "BSSID" property.
3354  */
3355 dbus_bool_t wpas_dbus_getter_bss_bssid(DBusMessageIter *iter, DBusError *error,
3356                                        void *user_data)
3357 {
3358         struct bss_handler_args *args = user_data;
3359         struct wpa_bss *res;
3360
3361         res = get_bss_helper(args, error, __func__);
3362         if (!res)
3363                 return FALSE;
3364
3365         return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
3366                                                       res->bssid, ETH_ALEN,
3367                                                       error);
3368 }
3369
3370
3371 /**
3372  * wpas_dbus_getter_bss_ssid - Return the SSID of a BSS
3373  * @iter: Pointer to incoming dbus message iter
3374  * @error: Location to store error on failure
3375  * @user_data: Function specific data
3376  * Returns: TRUE on success, FALSE on failure
3377  *
3378  * Getter for "SSID" property.
3379  */
3380 dbus_bool_t wpas_dbus_getter_bss_ssid(DBusMessageIter *iter, DBusError *error,
3381                                       void *user_data)
3382 {
3383         struct bss_handler_args *args = user_data;
3384         struct wpa_bss *res;
3385
3386         res = get_bss_helper(args, error, __func__);
3387         if (!res)
3388                 return FALSE;
3389
3390         return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
3391                                                       res->ssid, res->ssid_len,
3392                                                       error);
3393 }
3394
3395
3396 /**
3397  * wpas_dbus_getter_bss_privacy - Return the privacy flag of a BSS
3398  * @iter: Pointer to incoming dbus message iter
3399  * @error: Location to store error on failure
3400  * @user_data: Function specific data
3401  * Returns: TRUE on success, FALSE on failure
3402  *
3403  * Getter for "Privacy" property.
3404  */
3405 dbus_bool_t wpas_dbus_getter_bss_privacy(DBusMessageIter *iter,
3406                                          DBusError *error, void *user_data)
3407 {
3408         struct bss_handler_args *args = user_data;
3409         struct wpa_bss *res;
3410         dbus_bool_t privacy;
3411
3412         res = get_bss_helper(args, error, __func__);
3413         if (!res)
3414                 return FALSE;
3415
3416         privacy = (res->caps & IEEE80211_CAP_PRIVACY) ? TRUE : FALSE;
3417         return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
3418                                                 &privacy, error);
3419 }
3420
3421
3422 /**
3423  * wpas_dbus_getter_bss_mode - Return the mode of a BSS
3424  * @iter: Pointer to incoming dbus message iter
3425  * @error: Location to store error on failure
3426  * @user_data: Function specific data
3427  * Returns: TRUE on success, FALSE on failure
3428  *
3429  * Getter for "Mode" property.
3430  */
3431 dbus_bool_t wpas_dbus_getter_bss_mode(DBusMessageIter *iter, DBusError *error,
3432                                       void *user_data)
3433 {
3434         struct bss_handler_args *args = user_data;
3435         struct wpa_bss *res;
3436         const char *mode;
3437
3438         res = get_bss_helper(args, error, __func__);
3439         if (!res)
3440                 return FALSE;
3441         if (bss_is_dmg(res)) {
3442                 switch (res->caps & IEEE80211_CAP_DMG_MASK) {
3443                 case IEEE80211_CAP_DMG_PBSS:
3444                 case IEEE80211_CAP_DMG_IBSS:
3445                         mode = "ad-hoc";
3446                         break;
3447                 case IEEE80211_CAP_DMG_AP:
3448                         mode = "infrastructure";
3449                         break;
3450                 }
3451         } else {
3452                 if (res->caps & IEEE80211_CAP_IBSS)
3453                         mode = "ad-hoc";
3454                 else
3455                         mode = "infrastructure";
3456         }
3457
3458         return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
3459                                                 &mode, error);
3460 }
3461
3462
3463 /**
3464  * wpas_dbus_getter_bss_level - Return the signal strength of a BSS
3465  * @iter: Pointer to incoming dbus message iter
3466  * @error: Location to store error on failure
3467  * @user_data: Function specific data
3468  * Returns: TRUE on success, FALSE on failure
3469  *
3470  * Getter for "Level" property.
3471  */
3472 dbus_bool_t wpas_dbus_getter_bss_signal(DBusMessageIter *iter,
3473                                         DBusError *error, void *user_data)
3474 {
3475         struct bss_handler_args *args = user_data;
3476         struct wpa_bss *res;
3477         s16 level;
3478
3479         res = get_bss_helper(args, error, __func__);
3480         if (!res)
3481                 return FALSE;
3482
3483         level = (s16) res->level;
3484         return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT16,
3485                                                 &level, error);
3486 }
3487
3488
3489 /**
3490  * wpas_dbus_getter_bss_frequency - Return the frequency of a BSS
3491  * @iter: Pointer to incoming dbus message iter
3492  * @error: Location to store error on failure
3493  * @user_data: Function specific data
3494  * Returns: TRUE on success, FALSE on failure
3495  *
3496  * Getter for "Frequency" property.
3497  */
3498 dbus_bool_t wpas_dbus_getter_bss_frequency(DBusMessageIter *iter,
3499                                            DBusError *error, void *user_data)
3500 {
3501         struct bss_handler_args *args = user_data;
3502         struct wpa_bss *res;
3503         u16 freq;
3504
3505         res = get_bss_helper(args, error, __func__);
3506         if (!res)
3507                 return FALSE;
3508
3509         freq = (u16) res->freq;
3510         return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
3511                                                 &freq, error);
3512 }
3513
3514
3515 static int cmp_u8s_desc(const void *a, const void *b)
3516 {
3517         return (*(u8 *) b - *(u8 *) a);
3518 }
3519
3520
3521 /**
3522  * wpas_dbus_getter_bss_rates - Return available bit rates of a BSS
3523  * @iter: Pointer to incoming dbus message iter
3524  * @error: Location to store error on failure
3525  * @user_data: Function specific data
3526  * Returns: TRUE on success, FALSE on failure
3527  *
3528  * Getter for "Rates" property.
3529  */
3530 dbus_bool_t wpas_dbus_getter_bss_rates(DBusMessageIter *iter,
3531                                        DBusError *error, void *user_data)
3532 {
3533         struct bss_handler_args *args = user_data;
3534         struct wpa_bss *res;
3535         u8 *ie_rates = NULL;
3536         u32 *real_rates;
3537         int rates_num, i;
3538         dbus_bool_t success = FALSE;
3539
3540         res = get_bss_helper(args, error, __func__);
3541         if (!res)
3542                 return FALSE;
3543
3544         rates_num = wpa_bss_get_bit_rates(res, &ie_rates);
3545         if (rates_num < 0)
3546                 return FALSE;
3547
3548         qsort(ie_rates, rates_num, 1, cmp_u8s_desc);
3549
3550         real_rates = os_malloc(sizeof(u32) * rates_num);
3551         if (!real_rates) {
3552                 os_free(ie_rates);
3553                 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3554                 return FALSE;
3555         }
3556
3557         for (i = 0; i < rates_num; i++)
3558                 real_rates[i] = ie_rates[i] * 500000;
3559
3560         success = wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_UINT32,
3561                                                          real_rates, rates_num,
3562                                                          error);
3563
3564         os_free(ie_rates);
3565         os_free(real_rates);
3566         return success;
3567 }
3568
3569
3570 static dbus_bool_t wpas_dbus_get_bss_security_prop(DBusMessageIter *iter,
3571                                                    struct wpa_ie_data *ie_data,
3572                                                    DBusError *error)
3573 {
3574         DBusMessageIter iter_dict, variant_iter;
3575         const char *group;
3576         const char *pairwise[5]; /* max 5 pairwise ciphers is supported */
3577         const char *key_mgmt[8]; /* max 8 key managements may be supported */
3578         int n;
3579
3580         if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
3581                                               "a{sv}", &variant_iter))
3582                 goto nomem;
3583
3584         if (!wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
3585                 goto nomem;
3586
3587         /* KeyMgmt */
3588         n = 0;
3589         if (ie_data->key_mgmt & WPA_KEY_MGMT_PSK)
3590                 key_mgmt[n++] = "wpa-psk";
3591         if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_PSK)
3592                 key_mgmt[n++] = "wpa-ft-psk";
3593         if (ie_data->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
3594                 key_mgmt[n++] = "wpa-psk-sha256";
3595         if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X)
3596                 key_mgmt[n++] = "wpa-eap";
3597         if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X)
3598                 key_mgmt[n++] = "wpa-ft-eap";
3599         if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256)
3600                 key_mgmt[n++] = "wpa-eap-sha256";
3601         if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B)
3602                 key_mgmt[n++] = "wpa-eap-suite-b";
3603         if (ie_data->key_mgmt & WPA_KEY_MGMT_NONE)
3604                 key_mgmt[n++] = "wpa-none";
3605
3606         if (!wpa_dbus_dict_append_string_array(&iter_dict, "KeyMgmt",
3607                                                key_mgmt, n))
3608                 goto nomem;
3609
3610         /* Group */
3611         switch (ie_data->group_cipher) {
3612         case WPA_CIPHER_WEP40:
3613                 group = "wep40";
3614                 break;
3615         case WPA_CIPHER_TKIP:
3616                 group = "tkip";
3617                 break;
3618         case WPA_CIPHER_CCMP:
3619                 group = "ccmp";
3620                 break;
3621         case WPA_CIPHER_GCMP:
3622                 group = "gcmp";
3623                 break;
3624         case WPA_CIPHER_WEP104:
3625                 group = "wep104";
3626                 break;
3627         case WPA_CIPHER_CCMP_256:
3628                 group = "ccmp-256";
3629                 break;
3630         case WPA_CIPHER_GCMP_256:
3631                 group = "gcmp-256";
3632                 break;
3633         default:
3634                 group = "";
3635                 break;
3636         }
3637
3638         if (!wpa_dbus_dict_append_string(&iter_dict, "Group", group))
3639                 goto nomem;
3640
3641         /* Pairwise */
3642         n = 0;
3643         if (ie_data->pairwise_cipher & WPA_CIPHER_TKIP)
3644                 pairwise[n++] = "tkip";
3645         if (ie_data->pairwise_cipher & WPA_CIPHER_CCMP)
3646                 pairwise[n++] = "ccmp";
3647         if (ie_data->pairwise_cipher & WPA_CIPHER_GCMP)
3648                 pairwise[n++] = "gcmp";
3649         if (ie_data->pairwise_cipher & WPA_CIPHER_CCMP_256)
3650                 pairwise[n++] = "ccmp-256";
3651         if (ie_data->pairwise_cipher & WPA_CIPHER_GCMP_256)
3652                 pairwise[n++] = "gcmp-256";
3653
3654         if (!wpa_dbus_dict_append_string_array(&iter_dict, "Pairwise",
3655                                                pairwise, n))
3656                 goto nomem;
3657
3658         /* Management group (RSN only) */
3659         if (ie_data->proto == WPA_PROTO_RSN) {
3660                 switch (ie_data->mgmt_group_cipher) {
3661 #ifdef CONFIG_IEEE80211W
3662                 case WPA_CIPHER_AES_128_CMAC:
3663                         group = "aes128cmac";
3664                         break;
3665 #endif /* CONFIG_IEEE80211W */
3666                 default:
3667                         group = "";
3668                         break;
3669                 }
3670
3671                 if (!wpa_dbus_dict_append_string(&iter_dict, "MgmtGroup",
3672                                                  group))
3673                         goto nomem;
3674         }
3675
3676         if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict) ||
3677             !dbus_message_iter_close_container(iter, &variant_iter))
3678                 goto nomem;
3679
3680         return TRUE;
3681
3682 nomem:
3683         dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3684         return FALSE;
3685 }
3686
3687
3688 /**
3689  * wpas_dbus_getter_bss_wpa - Return the WPA options of a BSS
3690  * @iter: Pointer to incoming dbus message iter
3691  * @error: Location to store error on failure
3692  * @user_data: Function specific data
3693  * Returns: TRUE on success, FALSE on failure
3694  *
3695  * Getter for "WPA" property.
3696  */
3697 dbus_bool_t wpas_dbus_getter_bss_wpa(DBusMessageIter *iter, DBusError *error,
3698                                      void *user_data)
3699 {
3700         struct bss_handler_args *args = user_data;
3701         struct wpa_bss *res;
3702         struct wpa_ie_data wpa_data;
3703         const u8 *ie;
3704
3705         res = get_bss_helper(args, error, __func__);
3706         if (!res)
3707                 return FALSE;
3708
3709         os_memset(&wpa_data, 0, sizeof(wpa_data));
3710         ie = wpa_bss_get_vendor_ie(res, WPA_IE_VENDOR_TYPE);
3711         if (ie && wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0) {
3712                 dbus_set_error_const(error, DBUS_ERROR_FAILED,
3713                                      "failed to parse WPA IE");
3714                 return FALSE;
3715         }
3716
3717         return wpas_dbus_get_bss_security_prop(iter, &wpa_data, error);
3718 }
3719
3720
3721 /**
3722  * wpas_dbus_getter_bss_rsn - Return the RSN options of a BSS
3723  * @iter: Pointer to incoming dbus message iter
3724  * @error: Location to store error on failure
3725  * @user_data: Function specific data
3726  * Returns: TRUE on success, FALSE on failure
3727  *
3728  * Getter for "RSN" property.
3729  */
3730 dbus_bool_t wpas_dbus_getter_bss_rsn(DBusMessageIter *iter, DBusError *error,
3731                                      void *user_data)
3732 {
3733         struct bss_handler_args *args = user_data;
3734         struct wpa_bss *res;
3735         struct wpa_ie_data wpa_data;
3736         const u8 *ie;
3737
3738         res = get_bss_helper(args, error, __func__);
3739         if (!res)
3740                 return FALSE;
3741
3742         os_memset(&wpa_data, 0, sizeof(wpa_data));
3743         ie = wpa_bss_get_ie(res, WLAN_EID_RSN);
3744         if (ie && wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0) {
3745                 dbus_set_error_const(error, DBUS_ERROR_FAILED,
3746                                      "failed to parse RSN IE");
3747                 return FALSE;
3748         }
3749
3750         return wpas_dbus_get_bss_security_prop(iter, &wpa_data, error);
3751 }
3752
3753
3754 /**
3755  * wpas_dbus_getter_bss_wps - Return the WPS options of a BSS
3756  * @iter: Pointer to incoming dbus message iter
3757  * @error: Location to store error on failure
3758  * @user_data: Function specific data
3759  * Returns: TRUE on success, FALSE on failure
3760  *
3761  * Getter for "WPS" property.
3762  */
3763 dbus_bool_t wpas_dbus_getter_bss_wps(DBusMessageIter *iter, DBusError *error,
3764                                      void *user_data)
3765 {
3766         struct bss_handler_args *args = user_data;
3767         struct wpa_bss *res;
3768 #ifdef CONFIG_WPS
3769         struct wpabuf *wps_ie;
3770 #endif /* CONFIG_WPS */
3771         DBusMessageIter iter_dict, variant_iter;
3772         const char *type = "";
3773
3774         res = get_bss_helper(args, error, __func__);
3775         if (!res)
3776                 return FALSE;
3777
3778         if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
3779                                               "a{sv}", &variant_iter) ||
3780             !wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
3781                 goto nomem;
3782
3783 #ifdef CONFIG_WPS
3784         wps_ie = wpa_bss_get_vendor_ie_multi(res, WPS_IE_VENDOR_TYPE);
3785         if (wps_ie) {
3786                 if (wps_is_selected_pbc_registrar(wps_ie))
3787                         type = "pbc";
3788                 else if (wps_is_selected_pin_registrar(wps_ie))
3789                         type = "pin";
3790
3791                 wpabuf_free(wps_ie);
3792         }
3793 #endif /* CONFIG_WPS */
3794
3795         if (!wpa_dbus_dict_append_string(&iter_dict, "Type", type) ||
3796             !wpa_dbus_dict_close_write(&variant_iter, &iter_dict) ||
3797             !dbus_message_iter_close_container(iter, &variant_iter))
3798                 goto nomem;
3799
3800         return TRUE;
3801
3802 nomem:
3803         dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3804         return FALSE;
3805 }
3806
3807
3808 /**
3809  * wpas_dbus_getter_bss_ies - Return all IEs of a BSS
3810  * @iter: Pointer to incoming dbus message iter
3811  * @error: Location to store error on failure
3812  * @user_data: Function specific data
3813  * Returns: TRUE on success, FALSE on failure
3814  *
3815  * Getter for "IEs" property.
3816  */
3817 dbus_bool_t wpas_dbus_getter_bss_ies(DBusMessageIter *iter, DBusError *error,
3818                                      void *user_data)
3819 {
3820         struct bss_handler_args *args = user_data;
3821         struct wpa_bss *res;
3822
3823         res = get_bss_helper(args, error, __func__);
3824         if (!res)
3825                 return FALSE;
3826
3827         return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
3828                                                       res + 1, res->ie_len,
3829                                                       error);
3830 }
3831
3832
3833 /**
3834  * wpas_dbus_getter_bss_age - Return time in seconds since BSS was last seen
3835  * @iter: Pointer to incoming dbus message iter
3836  * @error: Location to store error on failure
3837  * @user_data: Function specific data
3838  * Returns: TRUE on success, FALSE on failure
3839  *
3840  * Getter for BSS age
3841  */
3842 dbus_bool_t wpas_dbus_getter_bss_age(DBusMessageIter *iter, DBusError *error,
3843                                      void *user_data)
3844 {
3845         struct bss_handler_args *args = user_data;
3846         struct wpa_bss *res;
3847         struct os_reltime now, diff = { 0, 0 };
3848         u32 age;
3849
3850         res = get_bss_helper(args, error, __func__);
3851         if (!res)
3852                 return FALSE;
3853
3854         os_get_reltime(&now);
3855         os_reltime_sub(&now, &res->last_update, &diff);
3856         age = diff.sec > 0 ? diff.sec : 0;
3857         return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32, &age,
3858                                                 error);
3859 }
3860
3861
3862 /**
3863  * wpas_dbus_getter_enabled - Check whether network is enabled or disabled
3864  * @iter: Pointer to incoming dbus message iter
3865  * @error: Location to store error on failure
3866  * @user_data: Function specific data
3867  * Returns: TRUE on success, FALSE on failure
3868  *
3869  * Getter for "enabled" property of a configured network.
3870  */
3871 dbus_bool_t wpas_dbus_getter_enabled(DBusMessageIter *iter, DBusError *error,
3872                                      void *user_data)
3873 {
3874         struct network_handler_args *net = user_data;
3875         dbus_bool_t enabled = net->ssid->disabled ? FALSE : TRUE;
3876
3877         return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
3878                                                 &enabled, error);
3879 }
3880
3881
3882 /**
3883  * wpas_dbus_setter_enabled - Mark a configured network as enabled or disabled
3884  * @iter: Pointer to incoming dbus message iter
3885  * @error: Location to store error on failure
3886  * @user_data: Function specific data
3887  * Returns: TRUE on success, FALSE on failure
3888  *
3889  * Setter for "Enabled" property of a configured network.
3890  */
3891 dbus_bool_t wpas_dbus_setter_enabled(DBusMessageIter *iter, DBusError *error,
3892                                      void *user_data)
3893 {
3894         struct network_handler_args *net = user_data;
3895         struct wpa_supplicant *wpa_s;
3896         struct wpa_ssid *ssid;
3897         dbus_bool_t enable;
3898
3899         if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
3900                                               &enable))
3901                 return FALSE;
3902
3903         wpa_s = net->wpa_s;
3904         ssid = net->ssid;
3905
3906         if (enable)
3907                 wpa_supplicant_enable_network(wpa_s, ssid);
3908         else
3909                 wpa_supplicant_disable_network(wpa_s, ssid);
3910
3911         return TRUE;
3912 }
3913
3914
3915 /**
3916  * wpas_dbus_getter_network_properties - Get options for a configured network
3917  * @iter: Pointer to incoming dbus message iter
3918  * @error: Location to store error on failure
3919  * @user_data: Function specific data
3920  * Returns: TRUE on success, FALSE on failure
3921  *
3922  * Getter for "Properties" property of a configured network.
3923  */
3924 dbus_bool_t wpas_dbus_getter_network_properties(DBusMessageIter *iter,
3925                                                 DBusError *error,
3926                                                 void *user_data)
3927 {
3928         struct network_handler_args *net = user_data;
3929         DBusMessageIter variant_iter, dict_iter;
3930         char **iterator;
3931         char **props = wpa_config_get_all(net->ssid, 1);
3932         dbus_bool_t success = FALSE;
3933
3934         if (!props) {
3935                 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3936                 return FALSE;
3937         }
3938
3939         if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a{sv}",
3940                                               &variant_iter) ||
3941             !wpa_dbus_dict_open_write(&variant_iter, &dict_iter)) {
3942                 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3943                 goto out;
3944         }
3945
3946         iterator = props;
3947         while (*iterator) {
3948                 if (!wpa_dbus_dict_append_string(&dict_iter, *iterator,
3949                                                  *(iterator + 1))) {
3950                         dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
3951                                              "no memory");
3952                         goto out;
3953                 }
3954                 iterator += 2;
3955         }
3956
3957
3958         if (!wpa_dbus_dict_close_write(&variant_iter, &dict_iter) ||
3959             !dbus_message_iter_close_container(iter, &variant_iter)) {
3960                 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
3961                 goto out;
3962         }
3963
3964         success = TRUE;
3965
3966 out:
3967         iterator = props;
3968         while (*iterator) {
3969                 os_free(*iterator);
3970                 iterator++;
3971         }
3972         os_free(props);
3973         return success;
3974 }
3975
3976
3977 /**
3978  * wpas_dbus_setter_network_properties - Set options for a configured network
3979  * @iter: Pointer to incoming dbus message iter
3980  * @error: Location to store error on failure
3981  * @user_data: Function specific data
3982  * Returns: TRUE on success, FALSE on failure
3983  *
3984  * Setter for "Properties" property of a configured network.
3985  */
3986 dbus_bool_t wpas_dbus_setter_network_properties(DBusMessageIter *iter,
3987                                                 DBusError *error,
3988                                                 void *user_data)
3989 {
3990         struct network_handler_args *net = user_data;
3991         struct wpa_ssid *ssid = net->ssid;
3992         DBusMessageIter variant_iter;
3993
3994         dbus_message_iter_recurse(iter, &variant_iter);
3995         return set_network_properties(net->wpa_s, ssid, &variant_iter, error);
3996 }
3997
3998
3999 #ifdef CONFIG_AP
4000
4001 DBusMessage * wpas_dbus_handler_subscribe_preq(
4002         DBusMessage *message, struct wpa_supplicant *wpa_s)
4003 {
4004         struct wpas_dbus_priv *priv = wpa_s->global->dbus;
4005         char *name;
4006
4007         if (wpa_s->preq_notify_peer != NULL) {
4008                 if (os_strcmp(dbus_message_get_sender(message),
4009                               wpa_s->preq_notify_peer) == 0)
4010                         return NULL;
4011
4012                 return dbus_message_new_error(message,
4013                         WPAS_DBUS_ERROR_SUBSCRIPTION_IN_USE,
4014                         "Another application is already subscribed");
4015         }
4016
4017         name = os_strdup(dbus_message_get_sender(message));
4018         if (!name)
4019                 return wpas_dbus_error_no_memory(message);
4020
4021         wpa_s->preq_notify_peer = name;
4022
4023         /* Subscribe to clean up if application closes socket */
4024         wpas_dbus_subscribe_noc(priv);
4025
4026         /*
4027          * Double-check it's still alive to make sure that we didn't
4028          * miss the NameOwnerChanged signal, e.g. while strdup'ing.
4029          */
4030         if (!dbus_bus_name_has_owner(priv->con, name, NULL)) {
4031                 /*
4032                  * Application no longer exists, clean up.
4033                  * The return value is irrelevant now.
4034                  *
4035                  * Need to check if the NameOwnerChanged handling
4036                  * already cleaned up because we have processed
4037                  * DBus messages while checking if the name still
4038                  * has an owner.
4039                  */
4040                 if (!wpa_s->preq_notify_peer)
4041                         return NULL;
4042                 os_free(wpa_s->preq_notify_peer);
4043                 wpa_s->preq_notify_peer = NULL;
4044                 wpas_dbus_unsubscribe_noc(priv);
4045         }
4046
4047         return NULL;
4048 }
4049
4050
4051 DBusMessage * wpas_dbus_handler_unsubscribe_preq(
4052         DBusMessage *message, struct wpa_supplicant *wpa_s)
4053 {
4054         struct wpas_dbus_priv *priv = wpa_s->global->dbus;
4055
4056         if (!wpa_s->preq_notify_peer)
4057                 return dbus_message_new_error(message,
4058                         WPAS_DBUS_ERROR_NO_SUBSCRIPTION,
4059                         "Not subscribed");
4060
4061         if (os_strcmp(wpa_s->preq_notify_peer,
4062                       dbus_message_get_sender(message)))
4063                 return dbus_message_new_error(message,
4064                         WPAS_DBUS_ERROR_SUBSCRIPTION_EPERM,
4065                         "Can't unsubscribe others");
4066
4067         os_free(wpa_s->preq_notify_peer);
4068         wpa_s->preq_notify_peer = NULL;
4069         wpas_dbus_unsubscribe_noc(priv);
4070         return NULL;
4071 }
4072
4073
4074 void wpas_dbus_signal_preq(struct wpa_supplicant *wpa_s,
4075                            const u8 *addr, const u8 *dst, const u8 *bssid,
4076                            const u8 *ie, size_t ie_len, u32 ssi_signal)
4077 {
4078         DBusMessage *msg;
4079         DBusMessageIter iter, dict_iter;
4080         struct wpas_dbus_priv *priv = wpa_s->global->dbus;
4081
4082         /* Do nothing if the control interface is not turned on */
4083         if (priv == NULL)
4084                 return;
4085
4086         if (wpa_s->preq_notify_peer == NULL)
4087                 return;
4088
4089         msg = dbus_message_new_signal(wpa_s->dbus_new_path,
4090                                       WPAS_DBUS_NEW_IFACE_INTERFACE,
4091                                       "ProbeRequest");
4092         if (msg == NULL)
4093                 return;
4094
4095         dbus_message_set_destination(msg, wpa_s->preq_notify_peer);
4096
4097         dbus_message_iter_init_append(msg, &iter);
4098
4099         if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
4100             (addr && !wpa_dbus_dict_append_byte_array(&dict_iter, "addr",
4101                                                       (const char *) addr,
4102                                                       ETH_ALEN)) ||
4103             (dst && !wpa_dbus_dict_append_byte_array(&dict_iter, "dst",
4104                                                      (const char *) dst,
4105                                                      ETH_ALEN)) ||
4106             (bssid && !wpa_dbus_dict_append_byte_array(&dict_iter, "bssid",
4107                                                        (const char *) bssid,
4108                                                        ETH_ALEN)) ||
4109             (ie && ie_len && !wpa_dbus_dict_append_byte_array(&dict_iter, "ies",
4110                                                               (const char *) ie,
4111                                                               ie_len)) ||
4112             (ssi_signal && !wpa_dbus_dict_append_int32(&dict_iter, "signal",
4113                                                        ssi_signal)) ||
4114             !wpa_dbus_dict_close_write(&iter, &dict_iter))
4115                 goto fail;
4116
4117         dbus_connection_send(priv->con, msg, NULL);
4118         goto out;
4119 fail:
4120         wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
4121 out:
4122         dbus_message_unref(msg);
4123 }
4124
4125 #endif /* CONFIG_AP */