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