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