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