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