OSDN Git Service

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