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