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