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