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