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