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