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