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