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