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