dbus: Change BSS property MaxRate to Rates
[libeap.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, Witold Sowa <witold.sowa@gmail.com>
5  * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2 as
9  * published by the Free Software Foundation.
10  *
11  * Alternatively, this software may be distributed under the terms of BSD
12  * license.
13  *
14  * See README and COPYING for more details.
15  */
16
17 #include "includes.h"
18
19 #include "common.h"
20 #include "common/ieee802_11_defs.h"
21 #include "eap_peer/eap_methods.h"
22 #include "eapol_supp/eapol_supp_sm.h"
23 #include "../config.h"
24 #include "../wpa_supplicant_i.h"
25 #include "../driver_i.h"
26 #include "../notify.h"
27 #include "../wpas_glue.h"
28 #include "../bss.h"
29 #include "../scan.h"
30 #include "dbus_new_helpers.h"
31 #include "dbus_new.h"
32 #include "dbus_new_handlers.h"
33 #include "dbus_dict_helpers.h"
34
35 extern int wpa_debug_level;
36 extern int wpa_debug_show_keys;
37 extern int wpa_debug_timestamp;
38
39 static const char *debug_strings[] = {
40         "msgdump", "debug", "info", "warning", "error", NULL
41 };
42
43
44 /**
45  * wpas_dbus_new_decompose_object_path - Decompose an interface object path into parts
46  * @path: The dbus object path
47  * @network: (out) the configured network this object path refers to, if any
48  * @bssid: (out) the scanned bssid this object path refers to, if any
49  * Returns: The object path of the network interface this path refers to
50  *
51  * For a given object path, decomposes the object path into object id, network,
52  * and BSSID parts, if those parts exist.
53  */
54 static char * wpas_dbus_new_decompose_object_path(const char *path,
55                                                   char **network,
56                                                   char **bssid)
57 {
58         const unsigned int dev_path_prefix_len =
59                 strlen(WPAS_DBUS_NEW_PATH_INTERFACES "/");
60         char *obj_path_only;
61         char *next_sep;
62
63         /* Be a bit paranoid about path */
64         if (!path || os_strncmp(path, WPAS_DBUS_NEW_PATH_INTERFACES "/",
65                                 dev_path_prefix_len))
66                 return NULL;
67
68         /* Ensure there's something at the end of the path */
69         if ((path + dev_path_prefix_len)[0] == '\0')
70                 return NULL;
71
72         obj_path_only = os_strdup(path);
73         if (obj_path_only == NULL)
74                 return NULL;
75
76         next_sep = os_strchr(obj_path_only + dev_path_prefix_len, '/');
77         if (next_sep != NULL) {
78                 const char *net_part = os_strstr(
79                         next_sep, WPAS_DBUS_NEW_NETWORKS_PART "/");
80                 const char *bssid_part = os_strstr(
81                         next_sep, WPAS_DBUS_NEW_BSSIDS_PART "/");
82
83                 if (network && net_part) {
84                         /* Deal with a request for a configured network */
85                         const char *net_name = net_part +
86                                 os_strlen(WPAS_DBUS_NEW_NETWORKS_PART "/");
87                         *network = NULL;
88                         if (os_strlen(net_name))
89                                 *network = os_strdup(net_name);
90                 } else if (bssid && bssid_part) {
91                         /* Deal with a request for a scanned BSSID */
92                         const char *bssid_name = bssid_part +
93                                 os_strlen(WPAS_DBUS_NEW_BSSIDS_PART "/");
94                         if (strlen(bssid_name))
95                                 *bssid = os_strdup(bssid_name);
96                         else
97                                 *bssid = NULL;
98                 }
99
100                 /* Cut off interface object path before "/" */
101                 *next_sep = '\0';
102         }
103
104         return obj_path_only;
105 }
106
107
108 /**
109  * wpas_dbus_error_unknown_error - Return a new InvalidArgs error message
110  * @message: Pointer to incoming dbus message this error refers to
111  * @arg: Optional string appended to error message
112  * Returns: a dbus error message
113  *
114  * Convenience function to create and return an UnknownError
115  */
116 DBusMessage * wpas_dbus_error_unknown_error(DBusMessage *message,
117                                             const char *arg)
118 {
119         return dbus_message_new_error(message, WPAS_DBUS_ERROR_UNKNOWN_ERROR,
120                                       arg);
121 }
122
123
124 /**
125  * wpas_dbus_error_iface_unknown - Return a new invalid interface error message
126  * @message: Pointer to incoming dbus message this error refers to
127  * Returns: A dbus error message
128  *
129  * Convenience function to create and return an invalid interface error
130  */
131 static DBusMessage * wpas_dbus_error_iface_unknown(DBusMessage *message)
132 {
133         return dbus_message_new_error(message, WPAS_DBUS_ERROR_IFACE_UNKNOWN,
134                                       "wpa_supplicant knows nothing about "
135                                       "this interface.");
136 }
137
138
139 /**
140  * wpas_dbus_error_network_unknown - Return a new NetworkUnknown error message
141  * @message: Pointer to incoming dbus message this error refers to
142  * Returns: a dbus error message
143  *
144  * Convenience function to create and return an invalid network error
145  */
146 static DBusMessage * wpas_dbus_error_network_unknown(DBusMessage *message)
147 {
148         return dbus_message_new_error(message, WPAS_DBUS_ERROR_NETWORK_UNKNOWN,
149                                       "There is no such a network in this "
150                                       "interface.");
151 }
152
153
154 /**
155  * wpas_dbus_error_invalid_args - Return a new InvalidArgs error message
156  * @message: Pointer to incoming dbus message this error refers to
157  * Returns: a dbus error message
158  *
159  * Convenience function to create and return an invalid options error
160  */
161 DBusMessage * wpas_dbus_error_invalid_args(DBusMessage *message,
162                                           const char *arg)
163 {
164         DBusMessage *reply;
165
166         reply = dbus_message_new_error(message, WPAS_DBUS_ERROR_INVALID_ARGS,
167                                        "Did not receive correct message "
168                                        "arguments.");
169         if (arg != NULL)
170                 dbus_message_append_args(reply, DBUS_TYPE_STRING, &arg,
171                                          DBUS_TYPE_INVALID);
172
173         return reply;
174 }
175
176
177 static const char *dont_quote[] = {
178         "key_mgmt", "proto", "pairwise", "auth_alg", "group", "eap",
179         "opensc_engine_path", "pkcs11_engine_path", "pkcs11_module_path",
180         "bssid", NULL
181 };
182
183 static dbus_bool_t should_quote_opt(const char *key)
184 {
185         int i = 0;
186         while (dont_quote[i] != NULL) {
187                 if (os_strcmp(key, dont_quote[i]) == 0)
188                         return FALSE;
189                 i++;
190         }
191         return TRUE;
192 }
193
194 /**
195  * get_iface_by_dbus_path - Get a new network interface
196  * @global: Pointer to global data from wpa_supplicant_init()
197  * @path: Pointer to a dbus object path representing an interface
198  * Returns: Pointer to the interface or %NULL if not found
199  */
200 static struct wpa_supplicant * get_iface_by_dbus_path(
201         struct wpa_global *global, const char *path)
202 {
203         struct wpa_supplicant *wpa_s;
204
205         for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
206                 if (os_strcmp(wpa_s->dbus_new_path, path) == 0)
207                         return wpa_s;
208         }
209         return NULL;
210 }
211
212
213 /**
214  * set_network_properties - Set properties of a configured network
215  * @message: Pointer to incoming dbus message
216  * @ssid: wpa_ssid structure for a configured network
217  * @iter: DBus message iterator containing dictionary of network
218  * properties to set.
219  * Returns: NULL when succeed or DBus error on failure
220  *
221  * Sets network configuration with parameters given id DBus dictionary
222  */
223 static DBusMessage * set_network_properties(DBusMessage *message,
224                                             struct wpa_ssid *ssid,
225                                             DBusMessageIter *iter)
226 {
227
228         struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
229         DBusMessage *reply = NULL;
230         DBusMessageIter iter_dict;
231
232         if (!wpa_dbus_dict_open_read(iter, &iter_dict))
233                 return wpas_dbus_error_invalid_args(message, NULL);
234
235         while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
236                 char *value = NULL;
237                 size_t size = 50;
238                 int ret;
239                 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) {
240                         reply = wpas_dbus_error_invalid_args(message, NULL);
241                         break;
242                 }
243                 if (entry.type == DBUS_TYPE_ARRAY &&
244                     entry.array_type == DBUS_TYPE_BYTE) {
245                         if (entry.array_len <= 0)
246                                 goto error;
247
248                         size = entry.array_len * 2 + 1;
249                         value = os_zalloc(size);
250                         if (value == NULL)
251                                 goto error;
252
253                         ret = wpa_snprintf_hex(value, size,
254                                                (u8 *) entry.bytearray_value,
255                                                entry.array_len);
256                         if (ret <= 0)
257                                 goto error;
258                 } else if (entry.type == DBUS_TYPE_STRING) {
259                         if (should_quote_opt(entry.key)) {
260                                 size = os_strlen(entry.str_value);
261                                 if (size <= 0)
262                                         goto error;
263
264                                 size += 3;
265                                 value = os_zalloc(size);
266                                 if (value == NULL)
267                                         goto error;
268
269                                 ret = os_snprintf(value, size, "\"%s\"",
270                                                   entry.str_value);
271                                 if (ret < 0 || (size_t) ret != (size - 1))
272                                         goto error;
273                         } else {
274                                 value = os_strdup(entry.str_value);
275                                 if (value == NULL)
276                                         goto error;
277                         }
278                 } else if (entry.type == DBUS_TYPE_UINT32) {
279                         value = os_zalloc(size);
280                         if (value == NULL)
281                                 goto error;
282
283                         ret = os_snprintf(value, size, "%u",
284                                           entry.uint32_value);
285                         if (ret <= 0)
286                                 goto error;
287                 } else if (entry.type == DBUS_TYPE_INT32) {
288                         value = os_zalloc(size);
289                         if (value == NULL)
290                                 goto error;
291
292                         ret = os_snprintf(value, size, "%d",
293                                           entry.int32_value);
294                         if (ret <= 0)
295                                 goto error;
296                 } else
297                         goto error;
298
299                 if (wpa_config_set(ssid, entry.key, value, 0) < 0)
300                         goto error;
301
302                 if ((os_strcmp(entry.key, "psk") == 0 &&
303                      value[0] == '"' && ssid->ssid_len) ||
304                     (strcmp(entry.key, "ssid") == 0 && ssid->passphrase))
305                         wpa_config_update_psk(ssid);
306
307                 os_free(value);
308                 wpa_dbus_dict_entry_clear(&entry);
309                 continue;
310
311         error:
312                 os_free(value);
313                 reply = wpas_dbus_error_invalid_args(message, entry.key);
314                 wpa_dbus_dict_entry_clear(&entry);
315                 break;
316         }
317
318         return reply;
319 }
320
321
322 /**
323  * wpas_dbus_simple_property_getter - Get basic type property
324  * @message: Pointer to incoming dbus message
325  * @type: DBus type of property (must be basic type)
326  * @val: pointer to place holding property value
327  * Returns: The DBus message containing response for Properties.Get call
328  * or DBus error message if error occurred.
329  *
330  * Generic getter for basic type properties. Type is required to be basic.
331  */
332 DBusMessage * wpas_dbus_simple_property_getter(DBusMessage *message,
333                                                const int type, const void *val)
334 {
335         DBusMessage *reply = NULL;
336         DBusMessageIter iter, variant_iter;
337
338         if (!dbus_type_is_basic(type)) {
339                 wpa_printf(MSG_ERROR, "dbus: wpas_dbus_simple_property_getter:"
340                            " given type is not basic");
341                 return wpas_dbus_error_unknown_error(message, NULL);
342         }
343
344         if (message == NULL)
345                 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
346         else
347                 reply = dbus_message_new_method_return(message);
348
349         if (reply != NULL) {
350                 dbus_message_iter_init_append(reply, &iter);
351                 if (!dbus_message_iter_open_container(
352                             &iter, DBUS_TYPE_VARIANT,
353                             wpa_dbus_type_as_string(type), &variant_iter) ||
354                     !dbus_message_iter_append_basic(&variant_iter, type,
355                                                     val) ||
356                     !dbus_message_iter_close_container(&iter, &variant_iter)) {
357                         wpa_printf(MSG_ERROR, "dbus: "
358                                    "wpas_dbus_simple_property_getter: out of "
359                                    "memory to put property value into "
360                                    "message");
361                         dbus_message_unref(reply);
362                         reply = dbus_message_new_error(message,
363                                                        DBUS_ERROR_NO_MEMORY,
364                                                        NULL);
365                 }
366         } else {
367                 wpa_printf(MSG_ERROR, "dbus: wpas_dbus_simple_property_getter:"
368                            " out of memory to return property value");
369                 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
370                                                NULL);
371         }
372
373         return reply;
374 }
375
376
377 /**
378  * wpas_dbus_simple_property_setter - Set basic type property
379  * @message: Pointer to incoming dbus message
380  * @type: DBus type of property (must be basic type)
381  * @val: pointer to place where value being set will be stored
382  * Returns: NULL or DBus error message if error occurred.
383  *
384  * Generic setter for basic type properties. Type is required to be basic.
385  */
386 DBusMessage * wpas_dbus_simple_property_setter(DBusMessage *message,
387                                                const int type, void *val)
388 {
389         DBusMessageIter iter, variant_iter;
390
391         if (!dbus_type_is_basic(type)) {
392                 wpa_printf(MSG_ERROR, "dbus: wpas_dbus_simple_property_setter:"
393                            " given type is not basic");
394                 return wpas_dbus_error_unknown_error(message, NULL);
395         }
396
397         if (!dbus_message_iter_init(message, &iter)) {
398                 wpa_printf(MSG_ERROR, "dbus: wpas_dbus_simple_property_setter:"
399                            " out of memory to return scanning state");
400                 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
401                                               NULL);
402         }
403
404         /* omit first and second argument and get value from third */
405         dbus_message_iter_next(&iter);
406         dbus_message_iter_next(&iter);
407         dbus_message_iter_recurse(&iter, &variant_iter);
408
409         if (dbus_message_iter_get_arg_type(&variant_iter) != type) {
410                 wpa_printf(MSG_DEBUG, "dbus: wpas_dbus_simple_property_setter:"
411                            " wrong property type");
412                 return wpas_dbus_error_invalid_args(message,
413                                                     "wrong property type");
414         }
415         dbus_message_iter_get_basic(&variant_iter, val);
416
417         return NULL;
418 }
419
420
421 /**
422  * wpas_dbus_simple_array_property_getter - Get array type property
423  * @message: Pointer to incoming dbus message
424  * @type: DBus type of property array elements (must be basic type)
425  * @array: pointer to array of elements to put into response message
426  * @array_len: length of above array
427  * Returns: The DBus message containing response for Properties.Get call
428  * or DBus error message if error occurred.
429  *
430  * Generic getter for array type properties. Array elements type is
431  * required to be basic.
432  */
433 DBusMessage * wpas_dbus_simple_array_property_getter(DBusMessage *message,
434                                                      const int type,
435                                                      const void *array,
436                                                      size_t array_len)
437 {
438         DBusMessage *reply = NULL;
439         DBusMessageIter iter, variant_iter, array_iter;
440         char type_str[] = "a?"; /* ? will be replaced with subtype letter; */
441         const char *sub_type_str;
442         size_t element_size, i;
443
444         if (!dbus_type_is_basic(type)) {
445                 wpa_printf(MSG_ERROR, "dbus: "
446                            "wpas_dbus_simple_array_property_getter: given "
447                            "type is not basic");
448                 return wpas_dbus_error_unknown_error(message, NULL);
449         }
450
451         sub_type_str = wpa_dbus_type_as_string(type);
452         type_str[1] = sub_type_str[0];
453
454         if (message == NULL)
455                 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
456         else
457                 reply = dbus_message_new_method_return(message);
458         if (reply == NULL) {
459                 wpa_printf(MSG_ERROR, "dbus: "
460                            "wpas_dbus_simple_array_property_getter: out of "
461                            "memory to create return message");
462                 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
463                                               NULL);
464         }
465
466         dbus_message_iter_init_append(reply, &iter);
467
468         if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
469                                               type_str, &variant_iter) ||
470             !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
471                                               sub_type_str, &array_iter)) {
472                 wpa_printf(MSG_ERROR, "dbus: "
473                            "wpas_dbus_simple_array_property_getter: out of "
474                            "memory to open container");
475                 dbus_message_unref(reply);
476                 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
477                                               NULL);
478         }
479
480         switch(type) {
481         case DBUS_TYPE_BYTE:
482         case DBUS_TYPE_BOOLEAN:
483                 element_size = 1;
484                 break;
485         case DBUS_TYPE_INT16:
486         case DBUS_TYPE_UINT16:
487                 element_size = sizeof(uint16_t);
488                 break;
489         case DBUS_TYPE_INT32:
490         case DBUS_TYPE_UINT32:
491                 element_size = sizeof(uint32_t);
492                 break;
493         case DBUS_TYPE_INT64:
494         case DBUS_TYPE_UINT64:
495                 element_size = sizeof(uint64_t);
496                 break;
497         case DBUS_TYPE_DOUBLE:
498                 element_size = sizeof(double);
499                 break;
500         case DBUS_TYPE_STRING:
501         case DBUS_TYPE_OBJECT_PATH:
502                 element_size = sizeof(char *);
503                 break;
504         default:
505                 wpa_printf(MSG_ERROR, "dbus: "
506                            "wpas_dbus_simple_array_property_getter: "
507                            "fatal: unknown element type");
508                 element_size = 1;
509                 break;
510         }
511
512         for (i = 0; i < array_len; i++) {
513                 dbus_message_iter_append_basic(&array_iter, type,
514                                                array + i * element_size);
515         }
516
517         if (!dbus_message_iter_close_container(&variant_iter, &array_iter) ||
518             !dbus_message_iter_close_container(&iter, &variant_iter)) {
519                 wpa_printf(MSG_ERROR, "dbus: "
520                            "wpas_dbus_simple_array_property_getter: out of "
521                            "memory to close container");
522                 dbus_message_unref(reply);
523                 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
524                                               NULL);
525         }
526
527         return reply;
528 }
529
530
531 /**
532  * wpas_dbus_handler_create_interface - Request registration of a network iface
533  * @message: Pointer to incoming dbus message
534  * @global: %wpa_supplicant global data structure
535  * Returns: The object path of the new interface object,
536  *          or a dbus error message with more information
537  *
538  * Handler function for "CreateInterface" method call. Handles requests
539  * by dbus clients to register a network interface that wpa_supplicant
540  * will manage.
541  */
542 DBusMessage * wpas_dbus_handler_create_interface(DBusMessage *message,
543                                                  struct wpa_global *global)
544 {
545         DBusMessageIter iter_dict;
546         DBusMessage *reply = NULL;
547         DBusMessageIter iter;
548         struct wpa_dbus_dict_entry entry;
549         char *driver = NULL;
550         char *ifname = NULL;
551         char *bridge_ifname = NULL;
552
553         dbus_message_iter_init(message, &iter);
554
555         if (!wpa_dbus_dict_open_read(&iter, &iter_dict))
556                 goto error;
557         while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
558                 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
559                         goto error;
560                 if (!strcmp(entry.key, "Driver") &&
561                     (entry.type == DBUS_TYPE_STRING)) {
562                         driver = os_strdup(entry.str_value);
563                         wpa_dbus_dict_entry_clear(&entry);
564                         if (driver == NULL)
565                                 goto error;
566                 } else if (!strcmp(entry.key, "Ifname") &&
567                            (entry.type == DBUS_TYPE_STRING)) {
568                         ifname = os_strdup(entry.str_value);
569                         wpa_dbus_dict_entry_clear(&entry);
570                         if (ifname == NULL)
571                                 goto error;
572                 } else if (!strcmp(entry.key, "BridgeIfname") &&
573                            (entry.type == DBUS_TYPE_STRING)) {
574                         bridge_ifname = os_strdup(entry.str_value);
575                         wpa_dbus_dict_entry_clear(&entry);
576                         if (bridge_ifname == NULL)
577                                 goto error;
578                 } else {
579                         wpa_dbus_dict_entry_clear(&entry);
580                         goto error;
581                 }
582         }
583
584         if (ifname == NULL)
585                 goto error; /* Required Ifname argument missing */
586
587         /*
588          * Try to get the wpa_supplicant record for this iface, return
589          * an error if we already control it.
590          */
591         if (wpa_supplicant_get_iface(global, ifname) != NULL) {
592                 reply = dbus_message_new_error(message,
593                                                WPAS_DBUS_ERROR_IFACE_EXISTS,
594                                                "wpa_supplicant already "
595                                                "controls this interface.");
596         } else {
597                 struct wpa_supplicant *wpa_s;
598                 struct wpa_interface iface;
599                 os_memset(&iface, 0, sizeof(iface));
600                 iface.driver = driver;
601                 iface.ifname = ifname;
602                 iface.bridge_ifname = bridge_ifname;
603                 /* Otherwise, have wpa_supplicant attach to it. */
604                 if ((wpa_s = wpa_supplicant_add_iface(global, &iface))) {
605                         const char *path = wpa_s->dbus_new_path;
606                         reply = dbus_message_new_method_return(message);
607                         dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH,
608                                                  &path, DBUS_TYPE_INVALID);
609                 } else {
610                         reply = wpas_dbus_error_unknown_error(
611                                 message, "wpa_supplicant couldn't grab this "
612                                 "interface.");
613                 }
614         }
615
616 out:
617         os_free(driver);
618         os_free(ifname);
619         os_free(bridge_ifname);
620         return reply;
621
622 error:
623         reply = wpas_dbus_error_invalid_args(message, NULL);
624         goto out;
625 }
626
627
628 /**
629  * wpas_dbus_handler_remove_interface - Request deregistration of an interface
630  * @message: Pointer to incoming dbus message
631  * @global: wpa_supplicant global data structure
632  * Returns: a dbus message containing a UINT32 indicating success (1) or
633  *          failure (0), or returns a dbus error message with more information
634  *
635  * Handler function for "removeInterface" method call.  Handles requests
636  * by dbus clients to deregister a network interface that wpa_supplicant
637  * currently manages.
638  */
639 DBusMessage * wpas_dbus_handler_remove_interface(DBusMessage *message,
640                                                  struct wpa_global *global)
641 {
642         struct wpa_supplicant *wpa_s;
643         char *path;
644         DBusMessage *reply = NULL;
645
646         dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path,
647                               DBUS_TYPE_INVALID);
648
649         wpa_s = get_iface_by_dbus_path(global, path);
650         if (wpa_s == NULL)
651                 reply = wpas_dbus_error_iface_unknown(message);
652         else if (wpa_supplicant_remove_iface(global, wpa_s)) {
653                 reply = wpas_dbus_error_unknown_error(
654                         message, "wpa_supplicant couldn't remove this "
655                         "interface.");
656         }
657
658         return reply;
659 }
660
661
662 /**
663  * wpas_dbus_handler_get_interface - Get the object path for an interface name
664  * @message: Pointer to incoming dbus message
665  * @global: %wpa_supplicant global data structure
666  * Returns: The object path of the interface object,
667  *          or a dbus error message with more information
668  *
669  * Handler function for "getInterface" method call.
670  */
671 DBusMessage * wpas_dbus_handler_get_interface(DBusMessage *message,
672                                               struct wpa_global *global)
673 {
674         DBusMessage *reply = NULL;
675         const char *ifname;
676         const char *path;
677         struct wpa_supplicant *wpa_s;
678
679         dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &ifname,
680                               DBUS_TYPE_INVALID);
681
682         wpa_s = wpa_supplicant_get_iface(global, ifname);
683         if (wpa_s == NULL)
684                 return wpas_dbus_error_iface_unknown(message);
685
686         path = wpa_s->dbus_new_path;
687         reply = dbus_message_new_method_return(message);
688         if (reply == NULL)
689                 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
690                                               NULL);
691         if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
692                                       DBUS_TYPE_INVALID)) {
693                 dbus_message_unref(reply);
694                 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
695                                               NULL);
696         }
697
698         return reply;
699 }
700
701
702 /**
703  * wpas_dbus_getter_debug_level - Get debug level
704  * @message: Pointer to incoming dbus message
705  * @global: %wpa_supplicant global data structure
706  * Returns: DBus message with value of debug level
707  *
708  * Getter for "DebugLevel" property.
709  */
710 DBusMessage * wpas_dbus_getter_debug_level(DBusMessage *message,
711                                            struct wpa_global *global)
712 {
713         const char *str;
714         int idx = wpa_debug_level;
715         if (idx < 0)
716                 idx = 0;
717         if (idx > 4)
718                 idx = 4;
719         str = debug_strings[idx];
720         return wpas_dbus_simple_property_getter(message, DBUS_TYPE_STRING,
721                                                 &str);
722 }
723
724
725 /**
726  * wpas_dbus_getter_debug_timestamp - Get debug timestamp
727  * @message: Pointer to incoming dbus message
728  * @global: %wpa_supplicant global data structure
729  * Returns: DBus message with value of debug timestamp
730  *
731  * Getter for "DebugTimestamp" property.
732  */
733 DBusMessage * wpas_dbus_getter_debug_timestamp(DBusMessage *message,
734                                                struct wpa_global *global)
735 {
736         return wpas_dbus_simple_property_getter(message, DBUS_TYPE_BOOLEAN,
737                                                 &wpa_debug_timestamp);
738
739 }
740
741
742 /**
743  * wpas_dbus_getter_debug_show_keys - Get debug show keys
744  * @message: Pointer to incoming dbus message
745  * @global: %wpa_supplicant global data structure
746  * Returns: DBus message with value of debug show_keys
747  *
748  * Getter for "DebugShowKeys" property.
749  */
750 DBusMessage * wpas_dbus_getter_debug_show_keys(DBusMessage *message,
751                                                struct wpa_global *global)
752 {
753         return wpas_dbus_simple_property_getter(message, DBUS_TYPE_BOOLEAN,
754                                                 &wpa_debug_show_keys);
755
756 }
757
758 /**
759  * wpas_dbus_setter_debug_level - Set debug level
760  * @message: Pointer to incoming dbus message
761  * @global: %wpa_supplicant global data structure
762  * Returns: %NULL or DBus error message
763  *
764  * Setter for "DebugLevel" property.
765  */
766 DBusMessage * wpas_dbus_setter_debug_level(DBusMessage *message,
767                                            struct wpa_global *global)
768 {
769         DBusMessage *reply;
770         const char *str = NULL;
771         int i, val = -1;
772
773         reply = wpas_dbus_simple_property_setter(message, DBUS_TYPE_STRING,
774                                                  &str);
775         if (reply)
776                 return reply;
777
778         for (i = 0; debug_strings[i]; i++)
779                 if (os_strcmp(debug_strings[i], str) == 0) {
780                         val = i;
781                         break;
782                 }
783
784         if (val < 0 ||
785             wpa_supplicant_set_debug_params(global, val, wpa_debug_timestamp,
786                                             wpa_debug_show_keys)) {
787                 dbus_message_unref(reply);
788                 return wpas_dbus_error_invalid_args(
789                         message, "Wrong debug level value");
790         }
791
792         return NULL;
793 }
794
795
796 /**
797  * wpas_dbus_setter_debug_timestamp - Set debug timestamp
798  * @message: Pointer to incoming dbus message
799  * @global: %wpa_supplicant global data structure
800  * Returns: %NULL or DBus error message
801  *
802  * Setter for "DebugTimestamp" property.
803  */
804 DBusMessage * wpas_dbus_setter_debug_timestamp(DBusMessage *message,
805                                                struct wpa_global *global)
806 {
807         DBusMessage *reply;
808         dbus_bool_t val;
809
810         reply = wpas_dbus_simple_property_setter(message, DBUS_TYPE_BOOLEAN,
811                                                  &val);
812         if (reply)
813                 return reply;
814
815         wpa_supplicant_set_debug_params(global, wpa_debug_level, val ? 1 : 0,
816                                         wpa_debug_show_keys);
817
818         return NULL;
819 }
820
821
822 /**
823  * wpas_dbus_setter_debug_show_keys - Set debug show keys
824  * @message: Pointer to incoming dbus message
825  * @global: %wpa_supplicant global data structure
826  * Returns: %NULL or DBus error message
827  *
828  * Setter for "DebugShowKeys" property.
829  */
830 DBusMessage * wpas_dbus_setter_debug_show_keys(DBusMessage *message,
831                                                struct wpa_global *global)
832 {
833         DBusMessage *reply;
834         dbus_bool_t val;
835
836         reply = wpas_dbus_simple_property_setter(message, DBUS_TYPE_BOOLEAN,
837                                                  &val);
838         if (reply)
839                 return reply;
840
841         wpa_supplicant_set_debug_params(global, wpa_debug_level,
842                                         wpa_debug_timestamp,
843                                         val ? 1 : 0);
844
845         return NULL;
846 }
847
848
849 /**
850  * wpas_dbus_getter_interfaces - Request registered interfaces list
851  * @message: Pointer to incoming dbus message
852  * @global: %wpa_supplicant global data structure
853  * Returns: The object paths array containing registered interfaces
854  * objects paths or DBus error on failure
855  *
856  * Getter for "Interfaces" property. Handles requests
857  * by dbus clients to return list of registered interfaces objects
858  * paths
859  */
860 DBusMessage * wpas_dbus_getter_interfaces(DBusMessage *message,
861                                           struct wpa_global *global)
862 {
863         DBusMessage *reply = NULL;
864         struct wpa_supplicant *wpa_s;
865         const char **paths;
866         unsigned int i = 0, num = 0;
867
868         for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
869                 num++;
870
871         paths = os_zalloc(num * sizeof(char*));
872         if (!paths) {
873                 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
874                                               NULL);
875         }
876
877         for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
878                 paths[i] = wpa_s->dbus_new_path;
879
880         reply = wpas_dbus_simple_array_property_getter(message,
881                                                        DBUS_TYPE_OBJECT_PATH,
882                                                        paths, num);
883
884         os_free(paths);
885         return reply;
886 }
887
888
889 /**
890  * wpas_dbus_getter_eap_methods - Request supported EAP methods list
891  * @message: Pointer to incoming dbus message
892  * @nothing: not used argument. may be NULL or anything else
893  * Returns: The object paths array containing supported EAP methods
894  * represented by strings or DBus error on failure
895  *
896  * Getter for "EapMethods" property. Handles requests
897  * by dbus clients to return list of strings with supported EAP methods
898  */
899 DBusMessage * wpas_dbus_getter_eap_methods(DBusMessage *message, void *nothing)
900 {
901         DBusMessage *reply = NULL;
902         char **eap_methods;
903         size_t num_items = 0;
904
905         eap_methods = eap_get_names_as_string_array(&num_items);
906         if (!eap_methods) {
907                 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
908                                               NULL);
909         }
910
911         reply = wpas_dbus_simple_array_property_getter(message,
912                                                        DBUS_TYPE_STRING,
913                                                        eap_methods, num_items);
914
915         while (num_items)
916                 os_free(eap_methods[--num_items]);
917         os_free(eap_methods);
918         return reply;
919 }
920
921
922 static int wpas_dbus_get_scan_type(DBusMessage *message, DBusMessageIter *var,
923                                    char **type, DBusMessage **reply)
924 {
925         if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_STRING) {
926                 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
927                            "Type must be a string");
928                 *reply = wpas_dbus_error_invalid_args(
929                         message, "Wrong Type value type. String required");
930                 return -1;
931         }
932         dbus_message_iter_get_basic(var, type);
933         return 0;
934 }
935
936
937 static int wpas_dbus_get_scan_ssids(DBusMessage *message, DBusMessageIter *var,
938                                     struct wpa_driver_scan_params *params,
939                                     DBusMessage **reply)
940 {
941         struct wpa_driver_scan_ssid *ssids = params->ssids;
942         size_t ssids_num = 0;
943         u8 *ssid;
944         DBusMessageIter array_iter, sub_array_iter;
945         char *val;
946         int len;
947
948         if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
949                 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: ssids "
950                            "must be an array of arrays of bytes");
951                 *reply = wpas_dbus_error_invalid_args(
952                         message, "Wrong SSIDs value type. Array of arrays of "
953                         "bytes required");
954                 return -1;
955         }
956
957         dbus_message_iter_recurse(var, &array_iter);
958
959         if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY ||
960             dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_BYTE)
961         {
962                 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: ssids "
963                            "must be an array of arrays of bytes");
964                 *reply = wpas_dbus_error_invalid_args(
965                         message, "Wrong SSIDs value type. Array of arrays of "
966                         "bytes required");
967                 return -1;
968         }
969
970         while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_ARRAY)
971         {
972                 if (ssids_num >= WPAS_MAX_SCAN_SSIDS) {
973                         wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
974                                    "Too many ssids specified on scan dbus "
975                                    "call");
976                         *reply = wpas_dbus_error_invalid_args(
977                                 message, "Too many ssids specified. Specify "
978                                 "at most four");
979                         return -1;
980                 }
981
982                 dbus_message_iter_recurse(&array_iter, &sub_array_iter);
983
984                 dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len);
985                 if (len == 0) {
986                         dbus_message_iter_next(&array_iter);
987                         continue;
988                 }
989
990                 ssid = os_malloc(len);
991                 if (ssid == NULL) {
992                         wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
993                                    "out of memory. Cannot allocate memory for "
994                                    "SSID");
995                         *reply = dbus_message_new_error(
996                                 message, DBUS_ERROR_NO_MEMORY, NULL);
997                         return -1;
998                 }
999                 os_memcpy(ssid, val, len);
1000                 ssids[ssids_num].ssid = ssid;
1001                 ssids[ssids_num].ssid_len = len;
1002
1003                 dbus_message_iter_next(&array_iter);
1004                 ssids_num++;
1005         }
1006
1007         params->num_ssids = ssids_num;
1008         return 0;
1009 }
1010
1011
1012 static int wpas_dbus_get_scan_ies(DBusMessage *message, DBusMessageIter *var,
1013                                   struct wpa_driver_scan_params *params,
1014                                   DBusMessage **reply)
1015 {
1016         u8 *ies = NULL, *nies;
1017         int ies_len = 0;
1018         DBusMessageIter array_iter, sub_array_iter;
1019         char *val;
1020         int len;
1021
1022         if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
1023                 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: ies must "
1024                            "be an array of arrays of bytes");
1025                 *reply = wpas_dbus_error_invalid_args(
1026                         message, "Wrong IEs value type. Array of arrays of "
1027                         "bytes required");
1028                 return -1;
1029         }
1030
1031         dbus_message_iter_recurse(var, &array_iter);
1032
1033         if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY ||
1034             dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_BYTE)
1035         {
1036                 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: ies must "
1037                            "be an array of arrays of bytes");
1038                 *reply = wpas_dbus_error_invalid_args(
1039                         message, "Wrong IEs value type. Array required");
1040                 return -1;
1041         }
1042
1043         while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_ARRAY)
1044         {
1045                 dbus_message_iter_recurse(&array_iter, &sub_array_iter);
1046
1047                 dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len);
1048                 if (len == 0) {
1049                         dbus_message_iter_next(&array_iter);
1050                         continue;
1051                 }
1052
1053                 nies = os_realloc(ies, ies_len + len);
1054                 if (nies == NULL) {
1055                         wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1056                                    "out of memory. Cannot allocate memory for "
1057                                    "IE");
1058                         os_free(ies);
1059                         *reply = dbus_message_new_error(
1060                                 message, DBUS_ERROR_NO_MEMORY, NULL);
1061                         return -1;
1062                 }
1063                 ies = nies;
1064                 os_memcpy(ies + ies_len, val, len);
1065                 ies_len += len;
1066
1067                 dbus_message_iter_next(&array_iter);
1068         }
1069
1070         params->extra_ies = ies;
1071         params->extra_ies_len = ies_len;
1072         return 0;
1073 }
1074
1075
1076 static int wpas_dbus_get_scan_channels(DBusMessage *message,
1077                                        DBusMessageIter *var,
1078                                        struct wpa_driver_scan_params *params,
1079                                        DBusMessage **reply)
1080 {
1081         DBusMessageIter array_iter, sub_array_iter;
1082         int *freqs = NULL, *nfreqs;
1083         int freqs_num = 0;
1084
1085         if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
1086                 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1087                            "Channels must be an array of structs");
1088                 *reply = wpas_dbus_error_invalid_args(
1089                         message, "Wrong Channels value type. Array of structs "
1090                         "required");
1091                 return -1;
1092         }
1093
1094         dbus_message_iter_recurse(var, &array_iter);
1095
1096         if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_STRUCT) {
1097                 wpa_printf(MSG_DEBUG,
1098                            "wpas_dbus_handler_scan[dbus]: Channels must be an "
1099                            "array of structs");
1100                 *reply = wpas_dbus_error_invalid_args(
1101                         message, "Wrong Channels value type. Array of structs "
1102                         "required");
1103                 return -1;
1104         }
1105
1106         while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_STRUCT)
1107         {
1108                 int freq, width;
1109
1110                 dbus_message_iter_recurse(&array_iter, &sub_array_iter);
1111
1112                 if (dbus_message_iter_get_arg_type(&sub_array_iter) !=
1113                     DBUS_TYPE_UINT32) {
1114                         wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1115                                    "Channel must by specified by struct of "
1116                                    "two UINT32s %c",
1117                                    dbus_message_iter_get_arg_type(
1118                                            &sub_array_iter));
1119                         *reply = wpas_dbus_error_invalid_args(
1120                                 message, "Wrong Channel struct. Two UINT32s "
1121                                 "required");
1122                         os_free(freqs);
1123                         return -1;
1124                 }
1125                 dbus_message_iter_get_basic(&sub_array_iter, &freq);
1126
1127                 if (!dbus_message_iter_next(&sub_array_iter) ||
1128                     dbus_message_iter_get_arg_type(&sub_array_iter) !=
1129                     DBUS_TYPE_UINT32) {
1130                         wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1131                                    "Channel must by specified by struct of "
1132                                    "two UINT32s");
1133                         *reply = wpas_dbus_error_invalid_args(
1134                                 message,
1135                                 "Wrong Channel struct. Two UINT32s required");
1136                         os_free(freqs);
1137                         return -1;
1138                 }
1139
1140                 dbus_message_iter_get_basic(&sub_array_iter, &width);
1141
1142 #define FREQS_ALLOC_CHUNK 32
1143                 if (freqs_num % FREQS_ALLOC_CHUNK == 0) {
1144                         nfreqs = os_realloc(freqs, sizeof(int) *
1145                                             (freqs_num + FREQS_ALLOC_CHUNK));
1146                         if (nfreqs == NULL)
1147                                 os_free(freqs);
1148                         freqs = nfreqs;
1149                 }
1150                 if (freqs == NULL) {
1151                         wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1152                                    "out of memory. can't allocate memory for "
1153                                    "freqs");
1154                         *reply = dbus_message_new_error(
1155                                 message, DBUS_ERROR_NO_MEMORY, NULL);
1156                         return -1;
1157                 }
1158
1159                 freqs[freqs_num] = freq;
1160
1161                 freqs_num++;
1162                 dbus_message_iter_next(&array_iter);
1163         }
1164
1165         nfreqs = os_realloc(freqs,
1166                             sizeof(int) * (freqs_num + 1));
1167         if (nfreqs == NULL)
1168                 os_free(freqs);
1169         freqs = nfreqs;
1170         if (freqs == NULL) {
1171                 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1172                            "out of memory. Can't allocate memory for freqs");
1173                 *reply = dbus_message_new_error(
1174                         message, DBUS_ERROR_NO_MEMORY, NULL);
1175                 return -1;
1176         }
1177         freqs[freqs_num] = 0;
1178
1179         params->freqs = freqs;
1180         return 0;
1181 }
1182
1183
1184 /**
1185  * wpas_dbus_handler_scan - Request a wireless scan on an interface
1186  * @message: Pointer to incoming dbus message
1187  * @wpa_s: wpa_supplicant structure for a network interface
1188  * Returns: NULL indicating success or DBus error message on failure
1189  *
1190  * Handler function for "Scan" method call of a network device. Requests
1191  * that wpa_supplicant perform a wireless scan as soon as possible
1192  * on a particular wireless interface.
1193  */
1194 DBusMessage * wpas_dbus_handler_scan(DBusMessage *message,
1195                                      struct wpa_supplicant *wpa_s)
1196 {
1197         DBusMessage *reply = NULL;
1198         DBusMessageIter iter, dict_iter, entry_iter, variant_iter;
1199         char *key = NULL, *type = NULL;
1200         struct wpa_driver_scan_params params;
1201         size_t i;
1202
1203         os_memset(&params, 0, sizeof(params));
1204
1205         dbus_message_iter_init(message, &iter);
1206
1207         dbus_message_iter_recurse(&iter, &dict_iter);
1208
1209         while (dbus_message_iter_get_arg_type(&dict_iter) ==
1210                         DBUS_TYPE_DICT_ENTRY) {
1211                 dbus_message_iter_recurse(&dict_iter, &entry_iter);
1212                 dbus_message_iter_get_basic(&entry_iter, &key);
1213                 dbus_message_iter_next(&entry_iter);
1214                 dbus_message_iter_recurse(&entry_iter, &variant_iter);
1215
1216                 if (os_strcmp(key, "Type") == 0) {
1217                         if (wpas_dbus_get_scan_type(message, &variant_iter,
1218                                                     &type, &reply) < 0)
1219                                 goto out;
1220                 } else if (os_strcmp(key, "SSIDs") == 0) {
1221                         if (wpas_dbus_get_scan_ssids(message, &variant_iter,
1222                                                      &params, &reply) < 0)
1223                                 goto out;
1224                 } else if (os_strcmp(key, "IEs") == 0) {
1225                         if (wpas_dbus_get_scan_ies(message, &variant_iter,
1226                                                    &params, &reply) < 0)
1227                                 goto out;
1228                 } else if (os_strcmp(key, "Channels") == 0) {
1229                         if (wpas_dbus_get_scan_channels(message, &variant_iter,
1230                                                         &params, &reply) < 0)
1231                                 goto out;
1232                 } else {
1233                         wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1234                                    "Unknown argument %s", key);
1235                         reply = wpas_dbus_error_invalid_args(message, key);
1236                         goto out;
1237                 }
1238
1239                 dbus_message_iter_next(&dict_iter);
1240         }
1241
1242         if (!type) {
1243                 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1244                            "Scan type not specified");
1245                 reply = wpas_dbus_error_invalid_args(message, key);
1246                 goto out;
1247         }
1248
1249         if (!os_strcmp(type, "passive")) {
1250                 if (params.num_ssids || params.extra_ies_len) {
1251                         wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1252                                    "SSIDs or IEs specified for passive scan.");
1253                         reply = wpas_dbus_error_invalid_args(
1254                                 message, "You can specify only Channels in "
1255                                 "passive scan");
1256                         goto out;
1257                 } else if (params.freqs && params.freqs[0]) {
1258                         /* wildcard ssid */
1259                         params.num_ssids++;
1260                         wpa_supplicant_trigger_scan(wpa_s, &params);
1261                 } else {
1262                         wpa_s->scan_req = 2;
1263                         wpa_supplicant_req_scan(wpa_s, 0, 0);
1264                 }
1265         } else if (!os_strcmp(type, "active")) {
1266                 wpa_supplicant_trigger_scan(wpa_s, &params);
1267         } else {
1268                 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
1269                            "Unknown scan type: %s", type);
1270                 reply = wpas_dbus_error_invalid_args(message,
1271                                                      "Wrong scan type");
1272                 goto out;
1273         }
1274
1275 out:
1276         for (i = 0; i < WPAS_MAX_SCAN_SSIDS; i++)
1277                 os_free((u8 *) params.ssids[i].ssid);
1278         os_free((u8 *) params.extra_ies);
1279         os_free(params.freqs);
1280         return reply;
1281 }
1282
1283
1284 /*
1285  * wpas_dbus_handler_disconnect - Terminate the current connection
1286  * @message: Pointer to incoming dbus message
1287  * @wpa_s: wpa_supplicant structure for a network interface
1288  * Returns: NotConnected DBus error message if already not connected
1289  * or NULL otherwise.
1290  *
1291  * Handler function for "Disconnect" method call of network interface.
1292  */
1293 DBusMessage * wpas_dbus_handler_disconnect(DBusMessage *message,
1294                                            struct wpa_supplicant *wpa_s)
1295 {
1296         if (wpa_s->current_ssid != NULL) {
1297                 wpa_s->disconnected = 1;
1298                 wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1299
1300                 return NULL;
1301         }
1302
1303         return dbus_message_new_error(message, WPAS_DBUS_ERROR_NOT_CONNECTED,
1304                                       "This interface is not connected");
1305 }
1306
1307
1308 /**
1309  * wpas_dbus_new_iface_add_network - Add a new configured network
1310  * @message: Pointer to incoming dbus message
1311  * @wpa_s: wpa_supplicant structure for a network interface
1312  * Returns: A dbus message containing the object path of the new network
1313  *
1314  * Handler function for "AddNetwork" method call of a network interface.
1315  */
1316 DBusMessage * wpas_dbus_handler_add_network(DBusMessage *message,
1317                                             struct wpa_supplicant *wpa_s)
1318 {
1319         DBusMessage *reply = NULL;
1320         DBusMessageIter iter;
1321         struct wpa_ssid *ssid = NULL;
1322         char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf;
1323
1324         dbus_message_iter_init(message, &iter);
1325
1326         ssid = wpa_config_add_network(wpa_s->conf);
1327         if (ssid == NULL) {
1328                 wpa_printf(MSG_ERROR, "wpas_dbus_handler_add_network[dbus]: "
1329                            "can't add new interface.");
1330                 reply = wpas_dbus_error_unknown_error(
1331                         message,
1332                         "wpa_supplicant could not add "
1333                         "a network on this interface.");
1334                 goto err;
1335         }
1336         wpas_notify_network_added(wpa_s, ssid);
1337         ssid->disabled = 1;
1338         wpa_config_set_network_defaults(ssid);
1339
1340         reply = set_network_properties(message, ssid, &iter);
1341         if (reply) {
1342                 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_add_network[dbus]:"
1343                            "control interface couldn't set network "
1344                            "properties");
1345                 goto err;
1346         }
1347
1348         /* Construct the object path for this network. */
1349         os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
1350                     "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
1351                     wpa_s->dbus_new_path, ssid->id);
1352
1353         reply = dbus_message_new_method_return(message);
1354         if (reply == NULL) {
1355                 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1356                                                NULL);
1357                 goto err;
1358         }
1359         if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
1360                                       DBUS_TYPE_INVALID)) {
1361                 dbus_message_unref(reply);
1362                 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1363                                                NULL);
1364                 goto err;
1365         }
1366
1367         return reply;
1368
1369 err:
1370         if (ssid) {
1371                 wpas_notify_network_removed(wpa_s, ssid);
1372                 wpa_config_remove_network(wpa_s->conf, ssid->id);
1373         }
1374         return reply;
1375 }
1376
1377
1378 /**
1379  * wpas_dbus_handler_remove_network - Remove a configured network
1380  * @message: Pointer to incoming dbus message
1381  * @wpa_s: wpa_supplicant structure for a network interface
1382  * Returns: NULL on success or dbus error on failure
1383  *
1384  * Handler function for "RemoveNetwork" method call of a network interface.
1385  */
1386 DBusMessage * wpas_dbus_handler_remove_network(DBusMessage *message,
1387                                                struct wpa_supplicant *wpa_s)
1388 {
1389         DBusMessage *reply = NULL;
1390         const char *op;
1391         char *iface = NULL, *net_id = NULL;
1392         int id;
1393         struct wpa_ssid *ssid;
1394
1395         dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
1396                               DBUS_TYPE_INVALID);
1397
1398         /* Extract the network ID and ensure the network */
1399         /* is actually a child of this interface */
1400         iface = wpas_dbus_new_decompose_object_path(op, &net_id, NULL);
1401         if (iface == NULL || os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
1402                 reply = wpas_dbus_error_invalid_args(message, op);
1403                 goto out;
1404         }
1405
1406         id = strtoul(net_id, NULL, 10);
1407         if (errno == EINVAL) {
1408                 reply = wpas_dbus_error_invalid_args(message, op);
1409                 goto out;
1410         }
1411
1412         ssid = wpa_config_get_network(wpa_s->conf, id);
1413         if (ssid == NULL) {
1414                 reply = wpas_dbus_error_network_unknown(message);
1415                 goto out;
1416         }
1417
1418         wpas_notify_network_removed(wpa_s, ssid);
1419
1420         if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
1421                 wpa_printf(MSG_ERROR,
1422                            "wpas_dbus_handler_remove_network[dbus]: "
1423                            "error occurred when removing network %d", id);
1424                 reply = wpas_dbus_error_unknown_error(
1425                         message, "error removing the specified network on "
1426                         "this interface.");
1427                 goto out;
1428         }
1429
1430         if (ssid == wpa_s->current_ssid)
1431                 wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1432
1433 out:
1434         os_free(iface);
1435         os_free(net_id);
1436         return reply;
1437 }
1438
1439
1440 /**
1441  * wpas_dbus_handler_select_network - Attempt association with a network
1442  * @message: Pointer to incoming dbus message
1443  * @wpa_s: wpa_supplicant structure for a network interface
1444  * Returns: NULL on success or dbus error on failure
1445  *
1446  * Handler function for "SelectNetwork" method call of network interface.
1447  */
1448 DBusMessage * wpas_dbus_handler_select_network(DBusMessage *message,
1449                                                struct wpa_supplicant *wpa_s)
1450 {
1451         DBusMessage *reply = NULL;
1452         const char *op;
1453         char *iface = NULL, *net_id = NULL;
1454         int id;
1455         struct wpa_ssid *ssid;
1456
1457         dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
1458                               DBUS_TYPE_INVALID);
1459
1460         /* Extract the network ID and ensure the network */
1461         /* is actually a child of this interface */
1462         iface = wpas_dbus_new_decompose_object_path(op, &net_id, NULL);
1463         if (iface == NULL || os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
1464                 reply = wpas_dbus_error_invalid_args(message, op);
1465                 goto out;
1466         }
1467
1468         id = strtoul(net_id, NULL, 10);
1469         if (errno == EINVAL) {
1470                 reply = wpas_dbus_error_invalid_args(message, op);
1471                 goto out;
1472         }
1473
1474         ssid = wpa_config_get_network(wpa_s->conf, id);
1475         if (ssid == NULL) {
1476                 reply = wpas_dbus_error_network_unknown(message);
1477                 goto out;
1478         }
1479
1480         /* Finally, associate with the network */
1481         wpa_supplicant_select_network(wpa_s, ssid);
1482
1483 out:
1484         os_free(iface);
1485         os_free(net_id);
1486         return reply;
1487 }
1488
1489
1490 /**
1491  * wpas_dbus_handler_add_blob - Store named binary blob (ie, for certificates)
1492  * @message: Pointer to incoming dbus message
1493  * @wpa_s: %wpa_supplicant data structure
1494  * Returns: A dbus message containing an error on failure or NULL on success
1495  *
1496  * Asks wpa_supplicant to internally store a binary blobs.
1497  */
1498 DBusMessage * wpas_dbus_handler_add_blob(DBusMessage *message,
1499                                          struct wpa_supplicant *wpa_s)
1500 {
1501         DBusMessage *reply = NULL;
1502         DBusMessageIter iter, array_iter;
1503
1504         char *blob_name;
1505         u8 *blob_data;
1506         int blob_len;
1507         struct wpa_config_blob *blob = NULL;
1508
1509         dbus_message_iter_init(message, &iter);
1510         dbus_message_iter_get_basic(&iter, &blob_name);
1511
1512         if (wpa_config_get_blob(wpa_s->conf, blob_name)) {
1513                 return dbus_message_new_error(message,
1514                                               WPAS_DBUS_ERROR_BLOB_EXISTS,
1515                                               NULL);
1516         }
1517
1518         dbus_message_iter_next(&iter);
1519         dbus_message_iter_recurse(&iter, &array_iter);
1520
1521         dbus_message_iter_get_fixed_array(&array_iter, &blob_data, &blob_len);
1522
1523         blob = os_zalloc(sizeof(*blob));
1524         if (!blob) {
1525                 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1526                                                NULL);
1527                 goto err;
1528         }
1529
1530         blob->data = os_malloc(blob_len);
1531         if (!blob->data) {
1532                 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1533                                                NULL);
1534                 goto err;
1535         }
1536         os_memcpy(blob->data, blob_data, blob_len);
1537
1538         blob->len = blob_len;
1539         blob->name = os_strdup(blob_name);
1540         if (!blob->name) {
1541                 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1542                                                NULL);
1543                 goto err;
1544         }
1545
1546         wpa_config_set_blob(wpa_s->conf, blob);
1547         wpas_notify_blob_added(wpa_s, blob->name);
1548
1549         return reply;
1550
1551 err:
1552         if (blob) {
1553                 os_free(blob->name);
1554                 os_free(blob->data);
1555                 os_free(blob);
1556         }
1557         return reply;
1558 }
1559
1560
1561 /**
1562  * wpas_dbus_handler_get_blob - Get named binary blob (ie, for certificates)
1563  * @message: Pointer to incoming dbus message
1564  * @wpa_s: %wpa_supplicant data structure
1565  * Returns: A dbus message containing array of bytes (blob)
1566  *
1567  * Gets one wpa_supplicant's binary blobs.
1568  */
1569 DBusMessage * wpas_dbus_handler_get_blob(DBusMessage *message,
1570                                          struct wpa_supplicant *wpa_s)
1571 {
1572         DBusMessage *reply = NULL;
1573         DBusMessageIter iter, array_iter;
1574
1575         char *blob_name;
1576         const struct wpa_config_blob *blob;
1577
1578         dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &blob_name,
1579                               DBUS_TYPE_INVALID);
1580
1581         blob = wpa_config_get_blob(wpa_s->conf, blob_name);
1582         if (!blob) {
1583                 return dbus_message_new_error(message,
1584                                               WPAS_DBUS_ERROR_BLOB_UNKNOWN,
1585                                               "Blob id not set");
1586         }
1587
1588         reply = dbus_message_new_method_return(message);
1589         if (!reply) {
1590                 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1591                                                NULL);
1592                 goto out;
1593         }
1594
1595         dbus_message_iter_init_append(reply, &iter);
1596
1597         if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
1598                                               DBUS_TYPE_BYTE_AS_STRING,
1599                                               &array_iter)) {
1600                 dbus_message_unref(reply);
1601                 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1602                                                NULL);
1603                 goto out;
1604         }
1605
1606         if (!dbus_message_iter_append_fixed_array(&array_iter, DBUS_TYPE_BYTE,
1607                                                   &(blob->data), blob->len)) {
1608                 dbus_message_unref(reply);
1609                 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1610                                                NULL);
1611                 goto out;
1612         }
1613
1614         if (!dbus_message_iter_close_container(&iter, &array_iter)) {
1615                 dbus_message_unref(reply);
1616                 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1617                                                NULL);
1618                 goto out;
1619         }
1620
1621 out:
1622         return reply;
1623 }
1624
1625
1626 /**
1627  * wpas_remove_handler_remove_blob - Remove named binary blob
1628  * @message: Pointer to incoming dbus message
1629  * @wpa_s: %wpa_supplicant data structure
1630  * Returns: NULL on success or dbus error
1631  *
1632  * Asks wpa_supplicant to internally remove a binary blobs.
1633  */
1634 DBusMessage * wpas_dbus_handler_remove_blob(DBusMessage *message,
1635                                             struct wpa_supplicant *wpa_s)
1636 {
1637         DBusMessage *reply = NULL;
1638         char *blob_name;
1639
1640         dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &blob_name,
1641                               DBUS_TYPE_INVALID);
1642
1643         if (wpa_config_remove_blob(wpa_s->conf, blob_name)) {
1644                 return dbus_message_new_error(message,
1645                                               WPAS_DBUS_ERROR_BLOB_UNKNOWN,
1646                                               "Blob id not set");
1647         }
1648         wpas_notify_blob_removed(wpa_s, blob_name);
1649
1650         return reply;
1651
1652 }
1653
1654
1655 /**
1656  * wpas_dbus_getter_capabilities - Return interface capabilities
1657  * @message: Pointer to incoming dbus message
1658  * @wpa_s: wpa_supplicant structure for a network interface
1659  * Returns: A dbus message containing a dict of strings
1660  *
1661  * Getter for "Capabilities" property of an interface.
1662  */
1663 DBusMessage * wpas_dbus_getter_capabilities(DBusMessage *message,
1664                                             struct wpa_supplicant *wpa_s)
1665 {
1666         DBusMessage *reply = NULL;
1667         struct wpa_driver_capa capa;
1668         int res;
1669         DBusMessageIter iter, iter_dict;
1670         DBusMessageIter iter_dict_entry, iter_dict_val, iter_array,
1671                 variant_iter;
1672         const char *scans[] = { "active", "passive", "ssid" };
1673         const char *modes[] = { "infrastructure", "ad-hoc", "ap" };
1674         int n = sizeof(modes) / sizeof(char *);
1675
1676         if (message == NULL)
1677                 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
1678         else
1679                 reply = dbus_message_new_method_return(message);
1680         if (!reply)
1681                 goto nomem;
1682
1683         dbus_message_iter_init_append(reply, &iter);
1684         if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
1685                                               "a{sv}", &variant_iter))
1686                 goto nomem;
1687
1688         if (!wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
1689                 goto nomem;
1690
1691         res = wpa_drv_get_capa(wpa_s, &capa);
1692
1693         /***** pairwise cipher */
1694         if (res < 0) {
1695                 const char *args[] = {"ccmp", "tkip", "none"};
1696                 if (!wpa_dbus_dict_append_string_array(
1697                             &iter_dict, "Pairwise", args,
1698                             sizeof(args) / sizeof(char*)))
1699                         goto nomem;
1700         } else {
1701                 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Pairwise",
1702                                                       &iter_dict_entry,
1703                                                       &iter_dict_val,
1704                                                       &iter_array))
1705                         goto nomem;
1706
1707                 if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
1708                         if (!wpa_dbus_dict_string_array_add_element(
1709                                     &iter_array, "ccmp"))
1710                                 goto nomem;
1711                 }
1712
1713                 if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
1714                         if (!wpa_dbus_dict_string_array_add_element(
1715                                     &iter_array, "tkip"))
1716                                 goto nomem;
1717                 }
1718
1719                 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
1720                         if (!wpa_dbus_dict_string_array_add_element(
1721                                     &iter_array, "none"))
1722                                 goto nomem;
1723                 }
1724
1725                 if (!wpa_dbus_dict_end_string_array(&iter_dict,
1726                                                     &iter_dict_entry,
1727                                                     &iter_dict_val,
1728                                                     &iter_array))
1729                         goto nomem;
1730         }
1731
1732         /***** group cipher */
1733         if (res < 0) {
1734                 const char *args[] = {
1735                         "ccmp", "tkip", "wep104", "wep40"
1736                 };
1737                 if (!wpa_dbus_dict_append_string_array(
1738                             &iter_dict, "Group", args,
1739                             sizeof(args) / sizeof(char*)))
1740                         goto nomem;
1741         } else {
1742                 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Group",
1743                                                       &iter_dict_entry,
1744                                                       &iter_dict_val,
1745                                                       &iter_array))
1746                         goto nomem;
1747
1748                 if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
1749                         if (!wpa_dbus_dict_string_array_add_element(
1750                                     &iter_array, "ccmp"))
1751                                 goto nomem;
1752                 }
1753
1754                 if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
1755                         if (!wpa_dbus_dict_string_array_add_element(
1756                                     &iter_array, "tkip"))
1757                                 goto nomem;
1758                 }
1759
1760                 if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) {
1761                         if (!wpa_dbus_dict_string_array_add_element(
1762                                     &iter_array, "wep104"))
1763                                 goto nomem;
1764                 }
1765
1766                 if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) {
1767                         if (!wpa_dbus_dict_string_array_add_element(
1768                                     &iter_array, "wep40"))
1769                                 goto nomem;
1770                 }
1771
1772                 if (!wpa_dbus_dict_end_string_array(&iter_dict,
1773                                                     &iter_dict_entry,
1774                                                     &iter_dict_val,
1775                                                     &iter_array))
1776                         goto nomem;
1777         }
1778
1779         /***** key management */
1780         if (res < 0) {
1781                 const char *args[] = {
1782                         "wpa-psk", "wpa-eap", "ieee8021x", "wpa-none",
1783 #ifdef CONFIG_WPS
1784                         "wps",
1785 #endif /* CONFIG_WPS */
1786                         "none"
1787                 };
1788                 if (!wpa_dbus_dict_append_string_array(
1789                             &iter_dict, "KeyMgmt", args,
1790                             sizeof(args) / sizeof(char*)))
1791                         goto nomem;
1792         } else {
1793                 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "KeyMgmt",
1794                                                       &iter_dict_entry,
1795                                                       &iter_dict_val,
1796                                                       &iter_array))
1797                         goto nomem;
1798
1799                 if (!wpa_dbus_dict_string_array_add_element(&iter_array,
1800                                                             "none"))
1801                         goto nomem;
1802
1803                 if (!wpa_dbus_dict_string_array_add_element(&iter_array,
1804                                                             "ieee8021x"))
1805                         goto nomem;
1806
1807                 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
1808                                      WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
1809                         if (!wpa_dbus_dict_string_array_add_element(
1810                                     &iter_array, "wpa-eap"))
1811                                 goto nomem;
1812                 }
1813
1814                 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
1815                                      WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
1816                         if (!wpa_dbus_dict_string_array_add_element(
1817                                     &iter_array, "wpa-psk"))
1818                                 goto nomem;
1819                 }
1820
1821                 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
1822                         if (!wpa_dbus_dict_string_array_add_element(
1823                                     &iter_array, "wpa-none"))
1824                                 goto nomem;
1825                 }
1826
1827
1828 #ifdef CONFIG_WPS
1829                 if (!wpa_dbus_dict_string_array_add_element(&iter_array,
1830                                                             "wps"))
1831                         goto nomem;
1832 #endif /* CONFIG_WPS */
1833
1834                 if (!wpa_dbus_dict_end_string_array(&iter_dict,
1835                                                     &iter_dict_entry,
1836                                                     &iter_dict_val,
1837                                                     &iter_array))
1838                         goto nomem;
1839         }
1840
1841         /***** WPA protocol */
1842         if (res < 0) {
1843                 const char *args[] = { "rsn", "wpa" };
1844                 if (!wpa_dbus_dict_append_string_array(
1845                             &iter_dict, "Protocol", args,
1846                             sizeof(args) / sizeof(char*)))
1847                         goto nomem;
1848         } else {
1849                 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Protocol",
1850                                                       &iter_dict_entry,
1851                                                       &iter_dict_val,
1852                                                       &iter_array))
1853                         goto nomem;
1854
1855                 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
1856                                      WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
1857                         if (!wpa_dbus_dict_string_array_add_element(
1858                                     &iter_array, "rsn"))
1859                                 goto nomem;
1860                 }
1861
1862                 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
1863                                      WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
1864                         if (!wpa_dbus_dict_string_array_add_element(
1865                                     &iter_array, "wpa"))
1866                                 goto nomem;
1867                 }
1868
1869                 if (!wpa_dbus_dict_end_string_array(&iter_dict,
1870                                                     &iter_dict_entry,
1871                                                     &iter_dict_val,
1872                                                     &iter_array))
1873                         goto nomem;
1874         }
1875
1876         /***** auth alg */
1877         if (res < 0) {
1878                 const char *args[] = { "open", "shared", "leap" };
1879                 if (!wpa_dbus_dict_append_string_array(
1880                             &iter_dict, "AuthAlg", args,
1881                             sizeof(args) / sizeof(char*)))
1882                         goto nomem;
1883         } else {
1884                 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "AuthAlg",
1885                                                       &iter_dict_entry,
1886                                                       &iter_dict_val,
1887                                                       &iter_array))
1888                         goto nomem;
1889
1890                 if (capa.auth & (WPA_DRIVER_AUTH_OPEN)) {
1891                         if (!wpa_dbus_dict_string_array_add_element(
1892                                     &iter_array, "open"))
1893                                 goto nomem;
1894                 }
1895
1896                 if (capa.auth & (WPA_DRIVER_AUTH_SHARED)) {
1897                         if (!wpa_dbus_dict_string_array_add_element(
1898                                     &iter_array, "shared"))
1899                                 goto nomem;
1900                 }
1901
1902                 if (capa.auth & (WPA_DRIVER_AUTH_LEAP)) {
1903                         if (!wpa_dbus_dict_string_array_add_element(
1904                                     &iter_array, "leap"))
1905                                 goto nomem;
1906                 }
1907
1908                 if (!wpa_dbus_dict_end_string_array(&iter_dict,
1909                                                     &iter_dict_entry,
1910                                                     &iter_dict_val,
1911                                                     &iter_array))
1912                         goto nomem;
1913         }
1914
1915         /***** Scan */
1916         if (!wpa_dbus_dict_append_string_array(&iter_dict, "Scan", scans,
1917                                                sizeof(scans) / sizeof(char *)))
1918                 goto nomem;
1919
1920         /***** Modes */
1921         if (res < 0 || !(capa.flags & WPA_DRIVER_FLAGS_AP))
1922                 n--; /* exclude ap mode if it is not supported by the driver */
1923         if (!wpa_dbus_dict_append_string_array(&iter_dict, "Modes", modes, n))
1924                 goto nomem;
1925
1926         if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict))
1927                 goto nomem;
1928         if (!dbus_message_iter_close_container(&iter, &variant_iter))
1929                 goto nomem;
1930
1931         return reply;
1932
1933 nomem:
1934         if (reply)
1935                 dbus_message_unref(reply);
1936
1937         return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, NULL);
1938 }
1939
1940
1941 /**
1942  * wpas_dbus_getter_state - Get interface state
1943  * @message: Pointer to incoming dbus message
1944  * @wpa_s: wpa_supplicant structure for a network interface
1945  * Returns: A dbus message containing a STRING representing the current
1946  *          interface state
1947  *
1948  * Getter for "State" property.
1949  */
1950 DBusMessage * wpas_dbus_getter_state(DBusMessage *message,
1951                                      struct wpa_supplicant *wpa_s)
1952 {
1953         DBusMessage *reply = NULL;
1954         const char *str_state;
1955         char *state_ls, *tmp;
1956
1957         str_state = wpa_supplicant_state_txt(wpa_s->wpa_state);
1958
1959         /* make state string lowercase to fit new DBus API convention
1960          */
1961         state_ls = tmp = os_strdup(str_state);
1962         if (!tmp) {
1963                 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
1964                                               NULL);
1965         }
1966         while (*tmp) {
1967                 *tmp = tolower(*tmp);
1968                 tmp++;
1969         }
1970
1971         reply = wpas_dbus_simple_property_getter(message, DBUS_TYPE_STRING,
1972                                                  &state_ls);
1973
1974         os_free(state_ls);
1975
1976         return reply;
1977 }
1978
1979
1980 /**
1981  * wpas_dbus_new_iface_get_scanning - Get interface scanning state
1982  * @message: Pointer to incoming dbus message
1983  * @wpa_s: wpa_supplicant structure for a network interface
1984  * Returns: A dbus message containing whether the interface is scanning
1985  *
1986  * Getter for "scanning" property.
1987  */
1988 DBusMessage * wpas_dbus_getter_scanning(DBusMessage *message,
1989                                         struct wpa_supplicant *wpa_s)
1990 {
1991         dbus_bool_t scanning = wpa_s->scanning ? TRUE : FALSE;
1992         return wpas_dbus_simple_property_getter(message, DBUS_TYPE_BOOLEAN,
1993                                                 &scanning);
1994 }
1995
1996
1997 /**
1998  * wpas_dbus_getter_ap_scan - Control roaming mode
1999  * @message: Pointer to incoming dbus message
2000  * @wpa_s: wpa_supplicant structure for a network interface
2001  * Returns: A message containong value of ap_scan variable
2002  *
2003  * Getter function for "ApScan" property.
2004  */
2005 DBusMessage * wpas_dbus_getter_ap_scan(DBusMessage *message,
2006                                        struct wpa_supplicant *wpa_s)
2007 {
2008         dbus_uint32_t ap_scan = wpa_s->conf->ap_scan;
2009         return wpas_dbus_simple_property_getter(message, DBUS_TYPE_UINT32,
2010                                                 &ap_scan);
2011 }
2012
2013
2014 /**
2015  * wpas_dbus_setter_ap_scan - Control roaming mode
2016  * @message: Pointer to incoming dbus message
2017  * @wpa_s: wpa_supplicant structure for a network interface
2018  * Returns: NULL
2019  *
2020  * Setter function for "ApScan" property.
2021  */
2022 DBusMessage * wpas_dbus_setter_ap_scan(DBusMessage *message,
2023                                        struct wpa_supplicant *wpa_s)
2024 {
2025         DBusMessage *reply = NULL;
2026         dbus_uint32_t ap_scan;
2027
2028         reply = wpas_dbus_simple_property_setter(message, DBUS_TYPE_UINT32,
2029                                                  &ap_scan);
2030         if (reply)
2031                 return reply;
2032
2033         if (wpa_supplicant_set_ap_scan(wpa_s, ap_scan)) {
2034                 return wpas_dbus_error_invalid_args(
2035                         message, "ap_scan must equal 0, 1 or 2");
2036         }
2037         return NULL;
2038 }
2039
2040
2041 /**
2042  * wpas_dbus_getter_ifname - Get interface name
2043  * @message: Pointer to incoming dbus message
2044  * @wpa_s: wpa_supplicant structure for a network interface
2045  * Returns: A dbus message containing a name of network interface
2046  * associated with with wpa_s
2047  *
2048  * Getter for "Ifname" property.
2049  */
2050 DBusMessage * wpas_dbus_getter_ifname(DBusMessage *message,
2051                                       struct wpa_supplicant *wpa_s)
2052 {
2053         const char *ifname = wpa_s->ifname;
2054         return wpas_dbus_simple_property_getter(message, DBUS_TYPE_STRING,
2055                                                 &ifname);
2056 }
2057
2058
2059 /**
2060  * wpas_dbus_getter_driver - Get interface name
2061  * @message: Pointer to incoming dbus message
2062  * @wpa_s: wpa_supplicant structure for a network interface
2063  * Returns: A dbus message containing a name of network interface
2064  * driver associated with with wpa_s
2065  *
2066  * Getter for "Driver" property.
2067  */
2068 DBusMessage * wpas_dbus_getter_driver(DBusMessage *message,
2069                                       struct wpa_supplicant *wpa_s)
2070 {
2071         const char *driver;
2072
2073         if (wpa_s->driver == NULL || wpa_s->driver->name == NULL) {
2074                 wpa_printf(MSG_DEBUG, "wpas_dbus_getter_driver[dbus]: "
2075                            "wpa_s has no driver set");
2076                 return wpas_dbus_error_unknown_error(message, NULL);
2077         }
2078
2079         driver = wpa_s->driver->name;
2080         return wpas_dbus_simple_property_getter(message, DBUS_TYPE_STRING,
2081                                                 &driver);
2082 }
2083
2084
2085 /**
2086  * wpas_dbus_getter_current_bss - Get current bss object path
2087  * @message: Pointer to incoming dbus message
2088  * @wpa_s: wpa_supplicant structure for a network interface
2089  * Returns: A dbus message containing a DBus object path to
2090  * current BSS
2091  *
2092  * Getter for "CurrentBSS" property.
2093  */
2094 DBusMessage * wpas_dbus_getter_current_bss(DBusMessage *message,
2095                                            struct wpa_supplicant *wpa_s)
2096 {
2097         DBusMessage *reply;
2098         char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *bss_obj_path = path_buf;
2099
2100         if (wpa_s->current_bss)
2101                 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2102                             "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
2103                             wpa_s->dbus_new_path, wpa_s->current_bss->id);
2104         else
2105                 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
2106
2107         reply = wpas_dbus_simple_property_getter(message,
2108                                                  DBUS_TYPE_OBJECT_PATH,
2109                                                  &bss_obj_path);
2110
2111         return reply;
2112 }
2113
2114
2115 /**
2116  * wpas_dbus_getter_current_network - Get current network object path
2117  * @message: Pointer to incoming dbus message
2118  * @wpa_s: wpa_supplicant structure for a network interface
2119  * Returns: A dbus message containing a DBus object path to
2120  * current network
2121  *
2122  * Getter for "CurrentNetwork" property.
2123  */
2124 DBusMessage * wpas_dbus_getter_current_network(DBusMessage *message,
2125                                                struct wpa_supplicant *wpa_s)
2126 {
2127         DBusMessage *reply;
2128         char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *net_obj_path = path_buf;
2129
2130         if (wpa_s->current_ssid)
2131                 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2132                             "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
2133                             wpa_s->dbus_new_path, wpa_s->current_ssid->id);
2134         else
2135                 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
2136
2137         reply = wpas_dbus_simple_property_getter(message,
2138                                                  DBUS_TYPE_OBJECT_PATH,
2139                                                  &net_obj_path);
2140
2141         return reply;
2142 }
2143
2144
2145 /**
2146  * wpas_dbus_getter_bridge_ifname - Get interface name
2147  * @message: Pointer to incoming dbus message
2148  * @wpa_s: wpa_supplicant structure for a network interface
2149  * Returns: A dbus message containing a name of bridge network
2150  * interface associated with with wpa_s
2151  *
2152  * Getter for "BridgeIfname" property.
2153  */
2154 DBusMessage * wpas_dbus_getter_bridge_ifname(DBusMessage *message,
2155                                              struct wpa_supplicant *wpa_s)
2156 {
2157         const char *bridge_ifname = NULL;
2158
2159         bridge_ifname = wpa_s->bridge_ifname;
2160         if (bridge_ifname == NULL) {
2161                 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bridge_ifname[dbus]: "
2162                            "wpa_s has no bridge interface name set");
2163                 return wpas_dbus_error_unknown_error(message, NULL);
2164         }
2165
2166         return wpas_dbus_simple_property_getter(message, DBUS_TYPE_STRING,
2167                                                 &bridge_ifname);
2168 }
2169
2170
2171 /**
2172  * wpas_dbus_getter_bsss - Get array of BSSs objects
2173  * @message: Pointer to incoming dbus message
2174  * @wpa_s: wpa_supplicant structure for a network interface
2175  * Returns: a dbus message containing an array of all known BSS objects
2176  * dbus paths
2177  *
2178  * Getter for "BSSs" property.
2179  */
2180 DBusMessage * wpas_dbus_getter_bsss(DBusMessage *message,
2181                                     struct wpa_supplicant *wpa_s)
2182 {
2183         DBusMessage *reply = NULL;
2184         struct wpa_bss *bss;
2185         char **paths;
2186         unsigned int i = 0;
2187
2188         paths = os_zalloc(wpa_s->num_bss * sizeof(char *));
2189         if (!paths) {
2190                 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2191                                               NULL);
2192         }
2193
2194         /* Loop through scan results and append each result's object path */
2195         dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
2196                 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
2197                 if (paths[i] == NULL) {
2198                         reply = dbus_message_new_error(message,
2199                                                        DBUS_ERROR_NO_MEMORY,
2200                                                        NULL);
2201                         goto out;
2202                 }
2203                 /* Construct the object path for this BSS. */
2204                 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
2205                             "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
2206                             wpa_s->dbus_new_path, bss->id);
2207         }
2208
2209         reply = wpas_dbus_simple_array_property_getter(message,
2210                                                        DBUS_TYPE_OBJECT_PATH,
2211                                                        paths, wpa_s->num_bss);
2212
2213 out:
2214         while (i)
2215                 os_free(paths[--i]);
2216         os_free(paths);
2217         return reply;
2218 }
2219
2220
2221 /**
2222  * wpas_dbus_getter_networks - Get array of networks objects
2223  * @message: Pointer to incoming dbus message
2224  * @wpa_s: wpa_supplicant structure for a network interface
2225  * Returns: a dbus message containing an array of all configured
2226  * networks dbus object paths.
2227  *
2228  * Getter for "Networks" property.
2229  */
2230 DBusMessage * wpas_dbus_getter_networks(DBusMessage *message,
2231                                         struct wpa_supplicant *wpa_s)
2232 {
2233         DBusMessage *reply = NULL;
2234         struct wpa_ssid *ssid;
2235         char **paths;
2236         unsigned int i = 0, num = 0;
2237
2238         if (wpa_s->conf == NULL) {
2239                 wpa_printf(MSG_ERROR, "wpas_dbus_getter_networks[dbus]: "
2240                            "An error occurred getting networks list.");
2241                 return wpas_dbus_error_unknown_error(message, NULL);
2242         }
2243
2244         for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
2245                 num++;
2246
2247         paths = os_zalloc(num * sizeof(char *));
2248         if (!paths) {
2249                 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2250                                               NULL);
2251         }
2252
2253         /* Loop through configured networks and append object path of each */
2254         for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2255                 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
2256                 if (paths[i] == NULL) {
2257                         reply = dbus_message_new_error(message,
2258                                                        DBUS_ERROR_NO_MEMORY,
2259                                                        NULL);
2260                         goto out;
2261                 }
2262
2263                 /* Construct the object path for this network. */
2264                 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
2265                             "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
2266                             wpa_s->dbus_new_path, ssid->id);
2267         }
2268
2269         reply = wpas_dbus_simple_array_property_getter(message,
2270                                                        DBUS_TYPE_OBJECT_PATH,
2271                                                        paths, num);
2272
2273 out:
2274         while (i)
2275                 os_free(paths[--i]);
2276         os_free(paths);
2277         return reply;
2278 }
2279
2280
2281 /**
2282  * wpas_dbus_getter_blobs - Get all blobs defined for this interface
2283  * @message: Pointer to incoming dbus message
2284  * @wpa_s: wpa_supplicant structure for a network interface
2285  * Returns: a dbus message containing a dictionary of pairs (blob_name, blob)
2286  *
2287  * Getter for "Blobs" property.
2288  */
2289 DBusMessage * wpas_dbus_getter_blobs(DBusMessage *message,
2290                                      struct wpa_supplicant *wpa_s)
2291 {
2292         DBusMessage *reply = NULL;
2293         DBusMessageIter iter, variant_iter, dict_iter, entry_iter, array_iter;
2294         struct wpa_config_blob *blob;
2295
2296         if (message == NULL)
2297                 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
2298         else
2299                 reply = dbus_message_new_method_return(message);
2300         if (!reply)
2301                 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2302                                               NULL);
2303
2304         dbus_message_iter_init_append(reply, &iter);
2305
2306         if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
2307                                               "a{say}", &variant_iter) ||
2308             !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
2309                                               "{say}", &dict_iter)) {
2310                 dbus_message_unref(reply);
2311                 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2312                                               NULL);
2313         }
2314
2315         blob = wpa_s->conf->blobs;
2316         while (blob) {
2317                 if (!dbus_message_iter_open_container(&dict_iter,
2318                                                       DBUS_TYPE_DICT_ENTRY,
2319                                                       NULL, &entry_iter) ||
2320                     !dbus_message_iter_append_basic(&entry_iter,
2321                                                     DBUS_TYPE_STRING,
2322                                                     &(blob->name)) ||
2323                     !dbus_message_iter_open_container(&entry_iter,
2324                                                       DBUS_TYPE_ARRAY,
2325                                                       DBUS_TYPE_BYTE_AS_STRING,
2326                                                       &array_iter) ||
2327                     !dbus_message_iter_append_fixed_array(&array_iter,
2328                                                           DBUS_TYPE_BYTE,
2329                                                           &(blob->data),
2330                                                           blob->len) ||
2331                     !dbus_message_iter_close_container(&entry_iter,
2332                                                        &array_iter) ||
2333                     !dbus_message_iter_close_container(&dict_iter,
2334                                                        &entry_iter)) {
2335                         dbus_message_unref(reply);
2336                         return dbus_message_new_error(message,
2337                                                       DBUS_ERROR_NO_MEMORY,
2338                                                       NULL);
2339                 }
2340
2341                 blob = blob->next;
2342         }
2343
2344         if (!dbus_message_iter_close_container(&variant_iter, &dict_iter) ||
2345             !dbus_message_iter_close_container(&iter, &variant_iter)) {
2346                 dbus_message_unref(reply);
2347                 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2348                                               NULL);
2349         }
2350
2351         return reply;
2352 }
2353
2354
2355 /**
2356  * wpas_dbus_getter_bss_bssid - Return the BSSID of a BSS
2357  * @message: Pointer to incoming dbus message
2358  * @bss: a pair of interface describing structure and bss's id
2359  * Returns: a dbus message containing the bssid for the requested bss
2360  *
2361  * Getter for "BSSID" property.
2362  */
2363 DBusMessage * wpas_dbus_getter_bss_bssid(DBusMessage *message,
2364                                          struct bss_handler_args *bss)
2365 {
2366         struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id);
2367
2368         if (!res) {
2369                 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_bssid[dbus]: no "
2370                            "bss with id %d found", bss->id);
2371                 return NULL;
2372         }
2373
2374         return wpas_dbus_simple_array_property_getter(message, DBUS_TYPE_BYTE,
2375                                                       res->bssid, ETH_ALEN);
2376 }
2377
2378
2379 /**
2380  * wpas_dbus_getter_bss_ssid - Return the SSID of a BSS
2381  * @message: Pointer to incoming dbus message
2382  * @bss: a pair of interface describing structure and bss's id
2383  * Returns: a dbus message containing the ssid for the requested bss
2384  *
2385  * Getter for "SSID" property.
2386  */
2387 DBusMessage * wpas_dbus_getter_bss_ssid(DBusMessage *message,
2388                                               struct bss_handler_args *bss)
2389 {
2390         struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id);
2391
2392         if (!res) {
2393                 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_ssid[dbus]: no "
2394                            "bss with id %d found", bss->id);
2395                 return NULL;
2396         }
2397
2398         return wpas_dbus_simple_array_property_getter(message, DBUS_TYPE_BYTE,
2399                                                       res->ssid,
2400                                                       res->ssid_len);
2401 }
2402
2403
2404 /**
2405  * wpas_dbus_getter_bss_privacy - Return the privacy flag of a BSS
2406  * @message: Pointer to incoming dbus message
2407  * @bss: a pair of interface describing structure and bss's id
2408  * Returns: a dbus message containing the privacy flag value of requested bss
2409  *
2410  * Getter for "Privacy" property.
2411  */
2412 DBusMessage * wpas_dbus_getter_bss_privacy(DBusMessage *message,
2413                                            struct bss_handler_args *bss)
2414 {
2415         struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id);
2416         dbus_bool_t privacy;
2417
2418         if (!res) {
2419                 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_privacy[dbus]: no "
2420                            "bss with id %d found", bss->id);
2421                 return NULL;
2422         }
2423
2424         privacy = res->caps && IEEE80211_CAP_PRIVACY ? TRUE : FALSE;
2425         return wpas_dbus_simple_property_getter(message, DBUS_TYPE_BOOLEAN,
2426                                                 &privacy);
2427 }
2428
2429
2430 /**
2431  * wpas_dbus_getter_bss_mode - Return the mode of a BSS
2432  * @message: Pointer to incoming dbus message
2433  * @bss: a pair of interface describing structure and bss's id
2434  * Returns: a dbus message containing the mode of requested bss
2435  *
2436  * Getter for "Mode" property.
2437  */
2438 DBusMessage * wpas_dbus_getter_bss_mode(DBusMessage *message,
2439                                         struct bss_handler_args *bss)
2440 {
2441         struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id);
2442         const char *mode;
2443
2444         if (!res) {
2445                 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_mode[dbus]: no "
2446                            "bss with id %d found", bss->id);
2447                 return NULL;
2448         }
2449
2450         if (res->caps & IEEE80211_CAP_IBSS)
2451                 mode = "ad-hoc";
2452         else
2453                 mode = "infrastructure";
2454
2455         return wpas_dbus_simple_property_getter(message, DBUS_TYPE_STRING,
2456                                                 &mode);
2457 }
2458
2459
2460 /**
2461  * wpas_dbus_getter_bss_level - Return the signal strength of a BSS
2462  * @message: Pointer to incoming dbus message
2463  * @bss: a pair of interface describing structure and bss's id
2464  * Returns: a dbus message containing the signal strength of requested bss
2465  *
2466  * Getter for "Level" property.
2467  */
2468 DBusMessage * wpas_dbus_getter_bss_signal(DBusMessage *message,
2469                                           struct bss_handler_args *bss)
2470 {
2471         struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id);
2472
2473         if (!res) {
2474                 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_signal[dbus]: no "
2475                            "bss with id %d found", bss->id);
2476                 return NULL;
2477         }
2478
2479         return wpas_dbus_simple_property_getter(message, DBUS_TYPE_INT16,
2480                                                 &res->level);
2481 }
2482
2483
2484 /**
2485  * wpas_dbus_getter_bss_frequency - Return the frequency of a BSS
2486  * @message: Pointer to incoming dbus message
2487  * @bss: a pair of interface describing structure and bss's id
2488  * Returns: a dbus message containing the frequency of requested bss
2489  *
2490  * Getter for "Frequency" property.
2491  */
2492 DBusMessage * wpas_dbus_getter_bss_frequency(DBusMessage *message,
2493                                              struct bss_handler_args *bss)
2494 {
2495         struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id);
2496
2497         if (!res) {
2498                 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_frequency[dbus]: "
2499                            "no bss with id %d found", bss->id);
2500                 return NULL;
2501         }
2502
2503         return wpas_dbus_simple_property_getter(message, DBUS_TYPE_UINT16,
2504                                                 &res->freq);
2505 }
2506
2507
2508 static int cmp_u8s_desc(const void *a, const void *b)
2509 {
2510         return (*(u8 *) b - *(u8 *) a);
2511 }
2512
2513
2514 /**
2515  * wpas_dbus_getter_bss_rates - Return available bit rates of a BSS
2516  * @message: Pointer to incoming dbus message
2517  * @bss: a pair of interface describing structure and bss's id
2518  * Returns: a dbus message containing sorted array of bit rates
2519  *
2520  * Getter for "Rates" property.
2521  */
2522 DBusMessage * wpas_dbus_getter_bss_rates(DBusMessage *message,
2523                                             struct bss_handler_args *bss)
2524 {
2525         DBusMessage *reply;
2526         struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id);
2527         u8 *ie_rates = NULL;
2528         u32 *real_rates;
2529         int rates_num, i;
2530
2531         if (!res) {
2532                 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_rates[dbus]: "
2533                            "no bss with id %d found", bss->id);
2534                 return NULL;
2535         }
2536
2537         rates_num = wpa_bss_get_bit_rates(res, &ie_rates);
2538         if (rates_num < 0)
2539                 return NULL;
2540
2541         qsort(ie_rates, rates_num, 1, cmp_u8s_desc);
2542
2543         real_rates = os_malloc(sizeof(u32) * rates_num);
2544         if (!real_rates) {
2545                 os_free(ie_rates);
2546                 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2547                                               NULL);
2548         }
2549
2550         for (i = 0; i < rates_num; i++)
2551                 real_rates[i] = ie_rates[i] * 500000;
2552
2553         reply = wpas_dbus_simple_array_property_getter(message,
2554                                                        DBUS_TYPE_UINT32,
2555                                                        real_rates, rates_num);
2556
2557         os_free(ie_rates);
2558         os_free(real_rates);
2559         return reply;
2560 }
2561
2562
2563 /**
2564  * wpas_dbus_getter_bss_wpaie - Return the WPA IE of a BSS
2565  * @message: Pointer to incoming dbus message
2566  * @bss: a pair of interface describing structure and bss's id
2567  * Returns: a dbus message containing the WPA information elements
2568  * of requested bss
2569  *
2570  * Getter for "WPAIE" property.
2571  */
2572 DBusMessage * wpas_dbus_getter_bss_wpaie(DBusMessage *message,
2573                                          struct bss_handler_args *bss)
2574 {
2575         struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id);
2576         const u8 *ie;
2577
2578         if (!res) {
2579                 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_wpaie[dbus]: no "
2580                            "bss with id %d found", bss->id);
2581                 return NULL;
2582         }
2583
2584         ie = wpa_bss_get_vendor_ie(res, WPA_IE_VENDOR_TYPE);
2585         if (!ie)
2586                 return NULL;
2587         return wpas_dbus_simple_array_property_getter(message, DBUS_TYPE_BYTE,
2588                                                       ie, ie[1] + 2);
2589 }
2590
2591
2592 /**
2593  * wpas_dbus_getter_bss_rsnie - Return the RSN IE of a BSS
2594  * @message: Pointer to incoming dbus message
2595  * @bss: a pair of interface describing structure and bss's id
2596  * Returns: a dbus message containing the RSN information elements
2597  * of requested bss
2598  *
2599  * Getter for "RSNIE" property.
2600  */
2601 DBusMessage * wpas_dbus_getter_bss_rsnie(DBusMessage *message,
2602                                          struct bss_handler_args *bss)
2603 {
2604         struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id);
2605         const u8 *ie;
2606
2607         if (!res) {
2608                 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_rsnie[dbus]: no "
2609                            "bss with id %d found", bss->id);
2610                 return NULL;
2611         }
2612
2613         ie = wpa_bss_get_ie(res, WLAN_EID_RSN);
2614         if (!ie)
2615                 return NULL;
2616         return wpas_dbus_simple_array_property_getter(message, DBUS_TYPE_BYTE,
2617                                                       ie, ie[1] + 2);
2618 }
2619
2620
2621 /**
2622  * wpas_dbus_getter_bss_wpsie - Return the WPS IE of a BSS
2623  * @message: Pointer to incoming dbus message
2624  * @bss: a pair of interface describing structure and bss's id
2625  * Returns: a dbus message containing the WPS information elements
2626  * of requested bss
2627  *
2628  * Getter for "WPSIE" property.
2629  */
2630 DBusMessage * wpas_dbus_getter_bss_wpsie(DBusMessage *message,
2631                                          struct bss_handler_args *bss)
2632 {
2633         struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id);
2634         const u8 *ie;
2635
2636         if (!res) {
2637                 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_wpsie[dbus]: no "
2638                            "bss with id %d found", bss->id);
2639                 return NULL;
2640         }
2641
2642         ie = wpa_bss_get_vendor_ie(res, WPS_IE_VENDOR_TYPE);
2643         if (!ie)
2644                 return NULL;
2645         return wpas_dbus_simple_array_property_getter(message, DBUS_TYPE_BYTE,
2646                                                       ie, ie[1] + 2);
2647 }
2648
2649
2650 /**
2651  * wpas_dbus_getter_enabled - Check whether network is enabled or disabled
2652  * @message: Pointer to incoming dbus message
2653  * @wpas_dbus_setter_enabled: wpa_supplicant structure for a network interface
2654  * and wpa_ssid structure for a configured network
2655  * Returns: DBus message with boolean indicating state of configured network
2656  * or DBus error on failure
2657  *
2658  * Getter for "enabled" property of a configured network.
2659  */
2660 DBusMessage * wpas_dbus_getter_enabled(DBusMessage *message,
2661                                        struct network_handler_args *net)
2662 {
2663         dbus_bool_t enabled = net->ssid->disabled ? FALSE : TRUE;
2664         return wpas_dbus_simple_property_getter(message, DBUS_TYPE_BOOLEAN,
2665                                                 &enabled);
2666 }
2667
2668
2669 /**
2670  * wpas_dbus_setter_enabled - Mark a configured network as enabled or disabled
2671  * @message: Pointer to incoming dbus message
2672  * @wpas_dbus_setter_enabled: wpa_supplicant structure for a network interface
2673  * and wpa_ssid structure for a configured network
2674  * Returns: NULL indicating success or DBus error on failure
2675  *
2676  * Setter for "Enabled" property of a configured network.
2677  */
2678 DBusMessage * wpas_dbus_setter_enabled(DBusMessage *message,
2679                                        struct network_handler_args *net)
2680 {
2681         DBusMessage *reply = NULL;
2682
2683         struct wpa_supplicant *wpa_s;
2684         struct wpa_ssid *ssid;
2685
2686         dbus_bool_t enable;
2687
2688         reply = wpas_dbus_simple_property_setter(message, DBUS_TYPE_BOOLEAN,
2689                                                  &enable);
2690
2691         if (reply)
2692                 return reply;
2693
2694         wpa_s = net->wpa_s;
2695         ssid = net->ssid;
2696
2697         if (enable)
2698                 wpa_supplicant_enable_network(wpa_s, ssid);
2699         else
2700                 wpa_supplicant_disable_network(wpa_s, ssid);
2701
2702         return NULL;
2703 }
2704
2705
2706 /**
2707  * wpas_dbus_getter_network_properties - Get options for a configured network
2708  * @message: Pointer to incoming dbus message
2709  * @net: wpa_supplicant structure for a network interface and
2710  * wpa_ssid structure for a configured network
2711  * Returns: DBus message with network properties or DBus error on failure
2712  *
2713  * Getter for "Properties" property of a configured network.
2714  */
2715 DBusMessage * wpas_dbus_getter_network_properties(
2716         DBusMessage *message, struct network_handler_args *net)
2717 {
2718         DBusMessage *reply = NULL;
2719         DBusMessageIter iter, variant_iter, dict_iter;
2720         char **iterator;
2721         char **props = wpa_config_get_all(net->ssid, 0);
2722         if (!props)
2723                 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2724                                               NULL);
2725
2726         if (message == NULL)
2727                 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
2728         else
2729                 reply = dbus_message_new_method_return(message);
2730         if (!reply) {
2731                 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2732                                                NULL);
2733                 goto out;
2734         }
2735
2736         dbus_message_iter_init_append(reply, &iter);
2737
2738         if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
2739                         "a{sv}", &variant_iter) ||
2740             !wpa_dbus_dict_open_write(&variant_iter, &dict_iter)) {
2741                 dbus_message_unref(reply);
2742                 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2743                                                NULL);
2744                 goto out;
2745         }
2746
2747         iterator = props;
2748         while (*iterator) {
2749                 if (!wpa_dbus_dict_append_string(&dict_iter, *iterator,
2750                                                  *(iterator + 1))) {
2751                         dbus_message_unref(reply);
2752                         reply = dbus_message_new_error(message,
2753                                                        DBUS_ERROR_NO_MEMORY,
2754                                                        NULL);
2755                         goto out;
2756                 }
2757                 iterator += 2;
2758         }
2759
2760
2761         if (!wpa_dbus_dict_close_write(&variant_iter, &dict_iter) ||
2762             !dbus_message_iter_close_container(&iter, &variant_iter)) {
2763                 dbus_message_unref(reply);
2764                 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
2765                                                NULL);
2766                 goto out;
2767         }
2768
2769 out:
2770         iterator = props;
2771         while (*iterator) {
2772                 os_free(*iterator);
2773                 iterator++;
2774         }
2775         os_free(props);
2776         return reply;
2777 }
2778
2779
2780 /**
2781  * wpas_dbus_setter_network_properties - Set options for a configured network
2782  * @message: Pointer to incoming dbus message
2783  * @net: wpa_supplicant structure for a network interface and
2784  * wpa_ssid structure for a configured network
2785  * Returns: NULL indicating success or DBus error on failure
2786  *
2787  * Setter for "Properties" property of a configured network.
2788  */
2789 DBusMessage * wpas_dbus_setter_network_properties(
2790         DBusMessage *message, struct network_handler_args *net)
2791 {
2792         struct wpa_ssid *ssid = net->ssid;
2793
2794         DBusMessage *reply = NULL;
2795         DBusMessageIter iter, variant_iter;
2796
2797         dbus_message_iter_init(message, &iter);
2798
2799         dbus_message_iter_next(&iter);
2800         dbus_message_iter_next(&iter);
2801
2802         dbus_message_iter_recurse(&iter, &variant_iter);
2803
2804         reply = set_network_properties(message, ssid, &variant_iter);
2805         if (reply)
2806                 wpa_printf(MSG_DEBUG, "dbus control interface couldn't set "
2807                            "network properties");
2808
2809         return reply;
2810 }