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