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