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