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