dbus: Use strdup instead of malloc+strncpy
[hostap-gosc2009.git] / wpa_supplicant / dbus / dbus_new.c
blobde31c94d495be3e741af7216e5256939b7fce204
1 /*
2 * WPA Supplicant / dbus-based control interface
3 * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
4 * Copyright (c) 2009, Witold Sowa <witold.sowa@gmail.com>
5 * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * Alternatively, this software may be distributed under the terms of BSD
12 * license.
14 * See README and COPYING for more details.
17 #include "includes.h"
19 #include "common.h"
20 #include "wps/wps.h"
21 #include "../config.h"
22 #include "../wpa_supplicant_i.h"
23 #include "../bss.h"
24 #include "dbus_new_helpers.h"
25 #include "dbus_dict_helpers.h"
26 #include "dbus_new.h"
27 #include "dbus_new_handlers.h"
28 #include "dbus_common.h"
29 #include "dbus_common_i.h"
31 /**
32 * wpas_dbus_set_path - Assign a dbus path to an interface
33 * @wpa_s: wpa_supplicant interface structure
34 * @path: dbus path to set on the interface
35 * Returns: 0 on success, -1 on error
37 static int wpas_dbus_set_path(struct wpa_supplicant *wpa_s,
38 const char *path)
40 u32 len = os_strlen(path);
41 if (len >= WPAS_DBUS_OBJECT_PATH_MAX)
42 return -1;
43 if (wpa_s->dbus_new_path)
44 return -1;
45 wpa_s->dbus_new_path = os_strdup(path);
46 return 0;
50 /**
51 * wpas_dbus_signal_interface - Send a interface related event signal
52 * @wpa_s: %wpa_supplicant network interface data
53 * @sig_name: signal name - InterfaceAdded or InterfaceRemoved
54 * @properties: determines if add second argument with object properties
56 * Notify listeners about event related with interface
58 static void wpas_dbus_signal_interface(struct wpa_supplicant *wpa_s,
59 const char *sig_name, int properties)
61 struct wpas_dbus_priv *iface;
62 DBusMessage *_signal;
63 DBusMessageIter iter, iter_dict;
64 const char *path;
66 iface = wpa_s->global->dbus;
68 /* Do nothing if the control interface is not turned on */
69 if (iface == NULL)
70 return;
72 path = wpas_dbus_get_path(wpa_s);
73 if (path == NULL) {
74 wpa_printf(MSG_ERROR, "wpas_dbus_signal_interface[dbus]: "
75 "Interface doesn't have a dbus path. "
76 "Can't send signal.");
77 return;
79 _signal = dbus_message_new_signal(WPAS_DBUS_NEW_PATH,
80 WPAS_DBUS_NEW_INTERFACE, sig_name);
81 if (_signal == NULL) {
82 wpa_printf(MSG_ERROR, "wpas_dbus_signal_interface[dbus]: "
83 "enough memory to send scan results signal.");
84 return;
87 dbus_message_iter_init_append(_signal, &iter);
89 if(!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
90 &path))
91 goto err;
93 if (properties) {
94 if (!wpa_dbus_dict_open_write(&iter, &iter_dict))
95 goto err;
97 wpa_dbus_get_object_properties(iface, path,
98 WPAS_DBUS_NEW_IFACE_INTERFACE,
99 &iter_dict);
101 if (!wpa_dbus_dict_close_write(&iter, &iter_dict))
102 goto err;
105 dbus_connection_send(iface->con, _signal, NULL);
107 dbus_message_unref(_signal);
108 return;
110 err:
111 wpa_printf(MSG_ERROR, "wpas_dbus_signal_interface[dbus]: "
112 "not enough memory to construct signal.");
113 dbus_message_unref(_signal);
118 * wpas_dbus_signal_interface_added - Send a interface created signal
119 * @wpa_s: %wpa_supplicant network interface data
121 * Notify listeners about creating new interface
123 static void wpas_dbus_signal_interface_added(struct wpa_supplicant *wpa_s)
125 wpas_dbus_signal_interface(wpa_s, "InterfaceAdded", TRUE);
130 * wpas_dbus_signal_interface_removed - Send a interface removed signal
131 * @wpa_s: %wpa_supplicant network interface data
133 * Notify listeners about removing interface
135 static void wpas_dbus_signal_interface_removed(struct wpa_supplicant *wpa_s)
137 wpas_dbus_signal_interface(wpa_s, "InterfaceRemoved", FALSE);
143 * wpas_dbus_signal_scan_done - send scan done signal
144 * @wpa_s: %wpa_supplicant network interface data
145 * @success: indicates if scanning succeed or failed
147 * Notify listeners about finishing a scan
149 static void wpas_dbus_signal_scan_done(struct wpa_supplicant *wpa_s,
150 int success)
152 struct wpas_dbus_priv *iface;
153 DBusMessage *_signal;
154 const char *path;
155 dbus_bool_t succ;
157 iface = wpa_s->global->dbus;
159 /* Do nothing if the control interface is not turned on */
160 if (iface == NULL)
161 return;
163 path = wpas_dbus_get_path(wpa_s);
164 if (path == NULL) {
165 wpa_printf(MSG_ERROR, "wpas_dbus_signal_scan_done[dbus]: "
166 "Interface doesn't have a dbus path. "
167 "Can't send signal.");
168 return;
170 _signal = dbus_message_new_signal(path, WPAS_DBUS_NEW_IFACE_INTERFACE,
171 "ScanDone");
172 if (_signal == NULL) {
173 wpa_printf(MSG_ERROR, "wpas_dbus_signal_scan_done[dbus]: "
174 "enough memory to send signal.");
175 return;
178 succ = success ? TRUE : FALSE;
179 if (dbus_message_append_args(_signal, DBUS_TYPE_BOOLEAN, &succ,
180 DBUS_TYPE_INVALID)) {
181 dbus_connection_send(iface->con, _signal, NULL);
182 } else {
183 wpa_printf(MSG_ERROR, "wpas_dbus_signal_scan_done[dbus]: "
184 "not enough memory to construct signal.");
186 dbus_message_unref(_signal);
191 * wpas_dbus_signal_blob - Send a BSS related event signal
192 * @wpa_s: %wpa_supplicant network interface data
193 * @bss_obj_path: BSS object path
194 * @sig_name: signal name - BSSAdded or BSSRemoved
195 * @properties: determines if add second argument with object properties
197 * Notify listeners about event related with BSS
199 static void wpas_dbus_signal_bss(struct wpa_supplicant *wpa_s,
200 const char *bss_obj_path,
201 const char *sig_name, int properties)
203 struct wpas_dbus_priv *iface;
204 DBusMessage *_signal;
205 DBusMessageIter iter, iter_dict;
206 const char *path;
208 iface = wpa_s->global->dbus;
210 /* Do nothing if the control interface is not turned on */
211 if (iface == NULL)
212 return;
214 path = wpas_dbus_get_path(wpa_s);
215 if (path == NULL) {
216 wpa_printf(MSG_ERROR, "wpas_dbus_signal_bss[dbus]: "
217 "Interface doesn't have a dbus path. "
218 "Can't send signal.");
219 return;
221 _signal = dbus_message_new_signal(path, WPAS_DBUS_NEW_IFACE_INTERFACE,
222 sig_name);
223 if (_signal == NULL) {
224 wpa_printf(MSG_ERROR, "wpas_dbus_signal_bss[dbus]: "
225 "enough memory to send signal.");
226 return;
229 dbus_message_iter_init_append(_signal, &iter);
231 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
232 &bss_obj_path))
233 goto err;
235 if (properties) {
236 if (!wpa_dbus_dict_open_write(&iter, &iter_dict))
237 goto err;
239 wpa_dbus_get_object_properties(iface, bss_obj_path,
240 WPAS_DBUS_NEW_IFACE_BSSID,
241 &iter_dict);
243 if (!wpa_dbus_dict_close_write(&iter, &iter_dict))
244 goto err;
247 dbus_connection_send(iface->con, _signal, NULL);
249 dbus_message_unref(_signal);
250 return;
252 err:
253 wpa_printf(MSG_ERROR, "wpas_dbus_signal_bss[dbus]: "
254 "not enough memory to construct signal.");
255 dbus_message_unref(_signal);
260 * wpas_dbus_signal_bss_added - Send a BSS added signal
261 * @wpa_s: %wpa_supplicant network interface data
262 * @bss_obj_path: new BSS object path
264 * Notify listeners about adding new BSS
266 static void wpas_dbus_signal_bss_added(struct wpa_supplicant *wpa_s,
267 const char *bss_obj_path)
269 wpas_dbus_signal_bss(wpa_s, bss_obj_path, "BSSAdded", TRUE);
274 * wpas_dbus_signal_bss_removed - Send a BSS removed signal
275 * @wpa_s: %wpa_supplicant network interface data
276 * @bss_obj_path: BSS object path
278 * Notify listeners about removing BSS
280 static void wpas_dbus_signal_bss_removed(struct wpa_supplicant *wpa_s,
281 const char *bss_obj_path)
283 wpas_dbus_signal_bss(wpa_s, bss_obj_path, "BSSRemoved", FALSE);
288 * wpas_dbus_signal_blob - Send a blob related event signal
289 * @wpa_s: %wpa_supplicant network interface data
290 * @name: blob name
291 * @sig_name: signal name - BlobAdded or BlobRemoved
293 * Notify listeners about event related with blob
295 static void wpas_dbus_signal_blob(struct wpa_supplicant *wpa_s,
296 const char *name, const char *sig_name)
298 struct wpas_dbus_priv *iface;
299 DBusMessage *_signal;
300 const char *path;
302 iface = wpa_s->global->dbus;
304 /* Do nothing if the control interface is not turned on */
305 if (iface == NULL)
306 return;
308 path = wpas_dbus_get_path(wpa_s);
309 if (path == NULL) {
310 wpa_printf(MSG_ERROR, "wpas_dbus_signal_blob[dbus]: "
311 "Interface doesn't have a dbus path. "
312 "Can't send signal.");
313 return;
315 _signal = dbus_message_new_signal(path, WPAS_DBUS_NEW_IFACE_INTERFACE,
316 sig_name);
317 if (_signal == NULL) {
318 wpa_printf(MSG_ERROR, "wpas_dbus_signal_blob[dbus]: "
319 "enough memory to send signal.");
320 return;
323 if (dbus_message_append_args(_signal, DBUS_TYPE_STRING, &name,
324 DBUS_TYPE_INVALID)) {
325 dbus_connection_send(iface->con, _signal, NULL);
326 } else {
327 wpa_printf(MSG_ERROR, "wpas_dbus_signal_blob[dbus]: "
328 "not enough memory to construct signal.");
330 dbus_message_unref(_signal);
335 * wpas_dbus_signal_blob_added - Send a blob added signal
336 * @wpa_s: %wpa_supplicant network interface data
337 * @name: blob name
339 * Notify listeners about adding a new blob
341 static void wpas_dbus_signal_blob_added(struct wpa_supplicant *wpa_s,
342 const char *name)
344 wpas_dbus_signal_blob(wpa_s, name, "BlobAdded");
349 * wpas_dbus_signal_blob_removed - Send a blob removed signal
350 * @wpa_s: %wpa_supplicant network interface data
351 * @name: blob name
353 * Notify listeners about removing blob
355 static void wpas_dbus_signal_blob_removed(struct wpa_supplicant *wpa_s,
356 const char *name)
358 wpas_dbus_signal_blob(wpa_s, name, "BlobRemoved");
363 * wpas_dbus_signal_network - Send a network related event signal
364 * @wpa_s: %wpa_supplicant network interface data
365 * @id: new network id
366 * @sig_name: signal name - NetworkAdded, NetworkRemoved or NetworkSelected
367 * @properties: determines if add second argument with object properties
369 * Notify listeners about event related with configured network
371 static void wpas_dbus_signal_network(struct wpa_supplicant *wpa_s,
372 int id, const char *sig_name,
373 int properties)
375 struct wpas_dbus_priv *iface;
376 DBusMessage *_signal;
377 DBusMessageIter iter, iter_dict;
378 const char *path;
379 char *net_obj_path;
381 iface = wpa_s->global->dbus;
383 /* Do nothing if the control interface is not turned on */
384 if (iface == NULL)
385 return;
387 path = wpas_dbus_get_path(wpa_s);
388 if (path == NULL) {
389 wpa_printf(MSG_ERROR, "wpas_dbus_signal_network[dbus]: "
390 "Interface doesn't have a dbus path. "
391 "Can't send signal.");
392 return;
395 net_obj_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
396 if (net_obj_path == NULL)
397 return;
398 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
399 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u", path, id);
401 _signal = dbus_message_new_signal(path, WPAS_DBUS_NEW_IFACE_INTERFACE,
402 sig_name);
403 if (_signal == NULL) {
404 wpa_printf(MSG_ERROR, "wpas_dbus_signal_network[dbus]: "
405 "enough memory to send signal.");
406 os_free(net_obj_path);
407 return;
410 dbus_message_iter_init_append(_signal, &iter);
412 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
413 &net_obj_path))
414 goto err;
416 if (properties) {
417 if (!wpa_dbus_dict_open_write(&iter, &iter_dict))
418 goto err;
420 wpa_dbus_get_object_properties(iface, net_obj_path,
421 WPAS_DBUS_NEW_IFACE_NETWORK,
422 &iter_dict);
424 if (!wpa_dbus_dict_close_write(&iter, &iter_dict))
425 goto err;
428 dbus_connection_send(iface->con, _signal, NULL);
430 os_free(net_obj_path);
431 dbus_message_unref(_signal);
432 return;
434 err:
435 wpa_printf(MSG_ERROR, "wpas_dbus_signal_network[dbus]: "
436 "not enough memory to construct signal.");
437 os_free(net_obj_path);
438 dbus_message_unref(_signal);
443 * wpas_dbus_signal_network_added - Send a network added signal
444 * @wpa_s: %wpa_supplicant network interface data
445 * @id: new network id
447 * Notify listeners about adding new network
449 static void wpas_dbus_signal_network_added(struct wpa_supplicant *wpa_s,
450 int id)
452 wpas_dbus_signal_network(wpa_s, id, "NetworkAdded", TRUE);
457 * wpas_dbus_signal_network_removed - Send a network removed signal
458 * @wpa_s: %wpa_supplicant network interface data
459 * @id: network id
461 * Notify listeners about removing a network
463 static void wpas_dbus_signal_network_removed(struct wpa_supplicant *wpa_s,
464 int id)
466 wpas_dbus_signal_network(wpa_s, id, "NetworkRemoved", FALSE);
471 * wpas_dbus_signal_network_selected - Send a network selected signal
472 * @wpa_s: %wpa_supplicant network interface data
473 * @id: network id
475 * Notify listeners about selecting a network
477 static void wpas_dbus_signal_network_selected(struct wpa_supplicant *wpa_s,
478 int id)
480 wpas_dbus_signal_network(wpa_s, id, "NetworkSelected", FALSE);
485 * wpas_dbus_signal_state_changed - Send a state changed signal
486 * @wpa_s: %wpa_supplicant network interface data
487 * @new_state: new state wpa_supplicant is entering
488 * @old_state: old state wpa_supplicant is leaving
490 * Notify listeners that wpa_supplicant has changed state
492 static void wpas_dbus_signal_state_changed(struct wpa_supplicant *wpa_s,
493 enum wpa_states new_state,
494 enum wpa_states old_state)
496 struct wpas_dbus_priv *iface;
497 DBusMessage *_signal = NULL;
498 const char *path;
499 char *new_state_str, *old_state_str;
500 char *tmp;
502 /* Do nothing if the control interface is not turned on */
503 if (wpa_s->global == NULL)
504 return;
505 iface = wpa_s->global->dbus;
506 if (iface == NULL)
507 return;
509 /* Only send signal if state really changed */
510 if (new_state == old_state)
511 return;
513 path = wpas_dbus_get_path(wpa_s);
514 if (path == NULL) {
515 perror("wpas_dbus_signal_state_changed[dbus]: "
516 "interface didn't have a dbus path");
517 wpa_printf(MSG_ERROR,
518 "wpas_dbus_signal_state_changed[dbus]: "
519 "interface didn't have a dbus path; can't send "
520 "signal.");
521 return;
523 _signal = dbus_message_new_signal(path, WPAS_DBUS_NEW_IFACE_INTERFACE,
524 "StateChanged");
525 if (_signal == NULL) {
526 perror("wpas_dbus_signal_state_changed[dbus]: "
527 "couldn't create dbus signal; likely out of memory");
528 wpa_printf(MSG_ERROR,
529 "wpas_dbus_signal_state_changed[dbus]: "
530 "couldn't create dbus signal; likely out of "
531 "memory.");
532 return;
535 new_state_str = os_strdup(wpa_supplicant_state_txt(new_state));
536 old_state_str = os_strdup(wpa_supplicant_state_txt(old_state));
537 if (new_state_str == NULL || old_state_str == NULL) {
538 perror("wpas_dbus_signal_state_changed[dbus]: "
539 "couldn't convert state strings");
540 wpa_printf(MSG_ERROR,
541 "wpas_dbus_signal_state_changed[dbus]: "
542 "couldn't convert state strings.");
543 goto out;
546 /* make state string lowercase to fit new DBus API convention */
547 tmp = new_state_str;
548 while (*tmp) {
549 *tmp = tolower(*tmp);
550 tmp++;
552 tmp = old_state_str;
553 while (*tmp) {
554 *tmp = tolower(*tmp);
555 tmp++;
558 if (!dbus_message_append_args(_signal,
559 DBUS_TYPE_STRING, &new_state_str,
560 DBUS_TYPE_STRING, &old_state_str,
561 DBUS_TYPE_INVALID)) {
562 perror("wpas_dbus_signal_state_changed[dbus]: "
563 "not enough memory to construct state change signal.");
564 wpa_printf(MSG_ERROR,
565 "wpas_dbus_signal_state_changed[dbus]: "
566 "not enough memory to construct state change "
567 "signal.");
568 goto out;
571 dbus_connection_send(iface->con, _signal, NULL);
573 out:
574 dbus_message_unref(_signal);
575 os_free(new_state_str);
576 os_free(old_state_str);
581 * wpas_dbus_signal_network_enabled_changed - Signals Enabled property changes
582 * @wpa_s: %wpa_supplicant network interface data
583 * @ssid: configured network which Enabled property has changed
585 * Sends PropertyChanged signals containing new value of Enabled property
586 * for specified network
588 static void wpas_dbus_signal_network_enabled_changed(
589 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
592 struct network_handler_args args = {wpa_s, ssid};
594 char path[WPAS_DBUS_OBJECT_PATH_MAX];
595 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
596 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
597 wpas_dbus_get_path(wpa_s), ssid->id);
599 wpa_dbus_signal_property_changed(wpa_s->global->dbus,
600 (WPADBusPropertyAccessor)
601 wpas_dbus_getter_enabled, &args,
602 path, WPAS_DBUS_NEW_IFACE_NETWORK,
603 "Enabled");
607 #ifdef CONFIG_WPS
610 * wpas_dbus_signal_wps_event_success - Signals Success WPS event
611 * @wpa_s: %wpa_supplicant network interface data
613 * Sends Event dbus signal with name "success" and empty dict as arguments
615 static void wpas_dbus_signal_wps_event_success(struct wpa_supplicant *wpa_s)
618 DBusMessage *_signal = NULL;
619 DBusMessageIter iter, dict_iter;
620 struct wpas_dbus_priv *iface;
621 char *key = "success";
622 const char *path;
624 iface = wpa_s->global->dbus;
626 /* Do nothing if the control interface is not turned on */
627 if (iface == NULL)
628 return;
630 path = wpas_dbus_get_path(wpa_s);
631 if (!path) {
632 wpa_printf(MSG_ERROR, "wpas_dbus_signal_wps_event_success"
633 "[dbus]: interface has no dbus path set");
634 return;
637 _signal = dbus_message_new_signal(path, WPAS_DBUS_NEW_IFACE_WPS,
638 "Event");
639 if (!_signal) {
640 wpa_printf(MSG_ERROR, "wpas_dbus_signal_wps_event_success"
641 "[dbus]: out of memory when creating a signal");
642 return;
645 dbus_message_iter_init_append(_signal, &iter);
647 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
648 !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
649 !wpa_dbus_dict_close_write(&iter, &dict_iter)) {
650 wpa_printf(MSG_ERROR, "wpas_dbus_signal_wps_event_success"
651 "[dbus]: out of memory");
652 goto out;
655 dbus_connection_send(iface->con, _signal, NULL);
656 out:
657 dbus_message_unref(_signal);
662 * wpas_dbus_signal_wps_event_fail - Signals Fail WPS event
663 * @wpa_s: %wpa_supplicant network interface data
665 * Sends Event dbus signal with name "fail" and dictionary containing
666 * "msg field with fail message number (int32) as arguments
668 static void wpas_dbus_signal_wps_event_fail(struct wpa_supplicant *wpa_s,
669 struct wps_event_fail *fail)
672 DBusMessage *_signal = NULL;
673 DBusMessageIter iter, dict_iter;
674 struct wpas_dbus_priv *iface;
675 char *key = "fail";
676 const char *path;
678 iface = wpa_s->global->dbus;
680 /* Do nothing if the control interface is not turned on */
681 if (iface == NULL)
682 return;
684 path = wpas_dbus_get_path(wpa_s);
685 if (!path) {
686 wpa_printf(MSG_ERROR, "wpas_dbus_signal_wps_event_fail[dbus]: "
687 "interface has no dbus path set");
688 return;
691 _signal = dbus_message_new_signal(path, WPAS_DBUS_NEW_IFACE_WPS,
692 "Event");
693 if (!_signal) {
694 wpa_printf(MSG_ERROR, "wpas_dbus_signal_wps_event_fail[dbus]: "
695 "out of memory when creating a signal");
696 return;
699 dbus_message_iter_init_append(_signal, &iter);
701 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
702 !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
703 !wpa_dbus_dict_append_int32(&dict_iter, "msg", fail->msg) ||
704 !wpa_dbus_dict_close_write(&iter, &dict_iter)) {
705 wpa_printf(MSG_ERROR, "wpas_dbus_signal_wps_event_fail[dbus]: "
706 "out of memory");
707 goto out;
710 dbus_connection_send(iface->con, _signal, NULL);
711 out:
712 dbus_message_unref(_signal);
717 * wpas_dbus_signal_wps_event_m2d - Signals M2D WPS event
718 * @wpa_s: %wpa_supplicant network interface data
720 * Sends Event dbus signal with name "m2d" and dictionary containing
721 * fields of wps_event_m2d structure.
723 static void wpas_dbus_signal_wps_event_m2d(struct wpa_supplicant *wpa_s,
724 struct wps_event_m2d *m2d)
727 DBusMessage *_signal = NULL;
728 DBusMessageIter iter, dict_iter;
729 struct wpas_dbus_priv *iface;
730 char *key = "m2d";
731 const char *path;
733 iface = wpa_s->global->dbus;
735 /* Do nothing if the control interface is not turned on */
736 if (iface == NULL)
737 return;
739 path = wpas_dbus_get_path(wpa_s);
740 if (!path) {
741 wpa_printf(MSG_ERROR, "wpas_dbus_signal_wps_event_m2d[dbus]: "
742 "interface has no dbus path set");
743 return;
746 _signal = dbus_message_new_signal(path, WPAS_DBUS_NEW_IFACE_WPS,
747 "Event");
748 if (!_signal) {
749 wpa_printf(MSG_ERROR, "wpas_dbus_signal_wps_event_m2d[dbus]: "
750 "out of memory when creating a signal");
751 return;
754 dbus_message_iter_init_append(_signal, &iter);
756 if (!(dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) &&
757 wpa_dbus_dict_open_write(&iter, &dict_iter) &&
758 wpa_dbus_dict_append_uint16(&dict_iter, "config_methods",
759 m2d->config_methods) &&
760 wpa_dbus_dict_append_byte_array(&dict_iter, "manufacturer",
761 (const char *) m2d->manufacturer,
762 m2d->manufacturer_len) &&
763 wpa_dbus_dict_append_byte_array(&dict_iter, "model_name",
764 (const char *) m2d->model_name,
765 m2d->model_name_len) &&
766 wpa_dbus_dict_append_byte_array(&dict_iter, "model_number",
767 (const char *) m2d->model_number,
768 m2d->model_number_len) &&
769 wpa_dbus_dict_append_byte_array(&dict_iter, "serial_number",
770 (const char *)
771 m2d->serial_number,
772 m2d->serial_number_len) &&
773 wpa_dbus_dict_append_byte_array(&dict_iter, "dev_name",
774 (const char *) m2d->dev_name,
775 m2d->dev_name_len) &&
776 wpa_dbus_dict_append_byte_array(&dict_iter, "primary_dev_type",
777 (const char *)
778 m2d->primary_dev_type, 8) &&
779 wpa_dbus_dict_append_uint16(&dict_iter, "config_error",
780 m2d->config_error) &&
781 wpa_dbus_dict_append_uint16(&dict_iter, "dev_password_id",
782 m2d->dev_password_id) &&
783 wpa_dbus_dict_close_write(&iter, &dict_iter))) {
784 wpa_printf(MSG_ERROR, "wpas_dbus_signal_wps_event_m2d[dbus]: "
785 "out of memory");
786 goto out;
789 dbus_connection_send(iface->con, _signal, NULL);
790 out:
791 dbus_message_unref(_signal);
796 * wpas_dbus_signal_wps_cred - Signals new credentials
797 * @wpa_s: %wpa_supplicant network interface data
799 * Sends signal with credentials in directory argument
801 static void wpas_dbus_signal_wps_cred(struct wpa_supplicant *wpa_s,
802 const struct wps_credential *cred)
804 DBusMessage *_signal = NULL;
805 DBusMessageIter iter, dict_iter;
806 struct wpas_dbus_priv *iface;
807 const char *path;
808 char *auth_type[6]; /* we have six possible authorization types */
809 int at_num = 0;
810 char *encr_type[4]; /* we have four possible encryption types */
811 int et_num = 0;
813 iface = wpa_s->global->dbus;
815 /* Do nothing if the control interface is not turned on */
816 if (iface == NULL)
817 return;
819 path = wpas_dbus_get_path(wpa_s);
820 if (!path) {
821 wpa_printf(MSG_ERROR, "wpas_dbus_signal_wps_cred[dbus]: "
822 "interface has no dbus path set");
823 return;
826 _signal = dbus_message_new_signal(path, WPAS_DBUS_NEW_IFACE_WPS,
827 "Credentials");
828 if (!_signal) {
829 wpa_printf(MSG_ERROR, "wpas_dbus_signal_wps_cred[dbus]: "
830 "out of memory when creating a signal");
831 return;
834 dbus_message_iter_init_append(_signal, &iter);
836 if (!wpa_dbus_dict_open_write(&iter, &dict_iter)) {
837 perror("wpas_dbus_signal_wps_cred[dbus]: out of memory "
838 "when opening a dictionary");
839 goto nomem;
842 if (cred->auth_type & WPS_AUTH_OPEN)
843 auth_type[at_num++] = "open";
844 if (cred->auth_type & WPS_AUTH_WPAPSK)
845 auth_type[at_num++] = "wpa-psk";
846 if (cred->auth_type & WPS_AUTH_SHARED)
847 auth_type[at_num++] = "shared";
848 if (cred->auth_type & WPS_AUTH_WPA)
849 auth_type[at_num++] = "wpa-eap";
850 if (cred->auth_type & WPS_AUTH_WPA2)
851 auth_type[at_num++] = "wpa2-eap";
852 if (cred->auth_type & WPS_AUTH_WPA2PSK)
853 auth_type[at_num++] =
854 "wpa2-psk";
856 if (cred->encr_type & WPS_ENCR_NONE)
857 encr_type[et_num++] = "none";
858 if (cred->encr_type & WPS_ENCR_WEP)
859 encr_type[et_num++] = "wep";
860 if (cred->encr_type & WPS_ENCR_TKIP)
861 encr_type[et_num++] = "tkip";
862 if (cred->encr_type & WPS_ENCR_AES)
863 encr_type[et_num++] = "aes";
865 if (wpa_s->current_ssid) {
866 if (!wpa_dbus_dict_append_byte_array(
867 &dict_iter, "BSSID",
868 (const char *) wpa_s->current_ssid->bssid,
869 ETH_ALEN)) {
870 perror("wpas_dbus_signal_wps_cred[dbus]: out of "
871 "memory when appending bssid to dictionary");
872 goto nomem;
876 if (!(wpa_dbus_dict_append_byte_array(&dict_iter, "SSID",
877 (const char *) cred->ssid,
878 cred->ssid_len) &&
879 wpa_dbus_dict_append_string_array(&dict_iter, "AuthType",
880 (const char **) auth_type,
881 at_num) &&
882 wpa_dbus_dict_append_string_array(&dict_iter, "EncrType",
883 (const char **) encr_type,
884 et_num) &&
885 wpa_dbus_dict_append_byte_array(&dict_iter, "Key",
886 (const char *) cred->key,
887 cred->key_len) &&
888 wpa_dbus_dict_append_uint32(&dict_iter, "KeyIndex",
889 cred->key_idx))) {
890 perror("wpas_dbus_signal_wps_cred[dbus]: out of memory "
891 "when appending to dictionary");
892 goto nomem;
895 if (!wpa_dbus_dict_close_write(&iter, &dict_iter)) {
896 perror("wpas_dbus_signal_wps_cred[dbus]: out of memory "
897 "when closing a dictionary");
898 goto nomem;
901 dbus_connection_send(iface->con, _signal, NULL);
903 nomem:
904 dbus_message_unref(_signal);
907 #endif /* CONFIG_WPS */
911 * wpas_dbus_signal_prop_changed - Signals change of property
912 * @wpa_s: %wpa_supplicant network interface data
913 * @property: indicates which property has changed
915 * Sends ProertyChanged signals with path, interface and arguments
916 * depending on which property has changed.
918 static void wpas_dbus_signal_prop_changed(struct wpa_supplicant *wpa_s,
919 enum wpas_dbus_prop property)
921 WPADBusPropertyAccessor getter;
922 char *iface;
923 char *prop;
924 void *arg;
926 switch (property) {
927 case WPAS_DBUS_PROP_AP_SCAN:
928 getter = (WPADBusPropertyAccessor) wpas_dbus_getter_ap_scan;
929 arg = wpa_s;
930 iface = WPAS_DBUS_NEW_IFACE_INTERFACE;
931 prop = "ApScan";
932 break;
933 case WPAS_DBUS_PROP_SCANNING:
934 getter = (WPADBusPropertyAccessor) wpas_dbus_getter_scanning;
935 arg = wpa_s;
936 iface = WPAS_DBUS_NEW_IFACE_INTERFACE;
937 prop = "Scanning";
938 break;
939 case WPAS_DBUS_PROP_CURRENT_BSS:
940 getter = (WPADBusPropertyAccessor)
941 wpas_dbus_getter_current_bss;
942 arg = wpa_s;
943 iface = WPAS_DBUS_NEW_IFACE_INTERFACE;
944 prop = "CurrentBSS";
945 break;
946 case WPAS_DBUS_PROP_CURRENT_NETWORK:
947 getter = (WPADBusPropertyAccessor)
948 wpas_dbus_getter_current_network;
949 arg = wpa_s;
950 iface = WPAS_DBUS_NEW_IFACE_INTERFACE;
951 prop = "CurrentNetwork";
952 break;
953 default:
954 wpa_printf(MSG_ERROR, "wpas_dbus_signal_prop_changed[dbus]: "
955 "Unknown Property enum value %d", property);
956 return;
959 wpa_dbus_signal_property_changed(wpa_s->global->dbus,
960 getter, arg,
961 wpas_dbus_get_path(wpa_s), iface,
962 prop);
967 * wpas_dbus_signal_debug_level_changed - Signals change of debug param
968 * @global: wpa_global structure
970 * Sends ProertyChanged signals informing that debug level has changed.
972 static void wpas_dbus_signal_debug_level_changed(struct wpa_global *global)
974 wpa_dbus_signal_property_changed(global->dbus,
975 (WPADBusPropertyAccessor)
976 wpas_dbus_getter_debug_level,
977 global, WPAS_DBUS_NEW_PATH,
978 WPAS_DBUS_NEW_INTERFACE,
979 "DebugLevel");
984 * wpas_dbus_signal_debug_timestamp_changed - Signals change of debug param
985 * @global: wpa_global structure
987 * Sends ProertyChanged signals informing that debug timestamp has changed.
989 static void wpas_dbus_signal_debug_timestamp_changed(struct wpa_global *global)
991 wpa_dbus_signal_property_changed(global->dbus,
992 (WPADBusPropertyAccessor)
993 wpas_dbus_getter_debug_timestamp,
994 global, WPAS_DBUS_NEW_PATH,
995 WPAS_DBUS_NEW_INTERFACE,
996 "DebugTimestamp");
1001 * wpas_dbus_signal_debug_show_keys_changed - Signals change of debug param
1002 * @global: wpa_global structure
1004 * Sends ProertyChanged signals informing that debug show_keys has changed.
1006 static void wpas_dbus_signal_debug_show_keys_changed(struct wpa_global *global)
1008 wpa_dbus_signal_property_changed(global->dbus,
1009 (WPADBusPropertyAccessor)
1010 wpas_dbus_getter_debug_show_keys,
1011 global, WPAS_DBUS_NEW_PATH,
1012 WPAS_DBUS_NEW_INTERFACE,
1013 "DebugShowKeys");
1017 struct wpas_dbus_method {
1018 const char *name;
1019 const char *iface;
1020 WPADBusMethodHandler handler;
1021 struct wpa_dbus_argument args[3];
1024 struct wpas_dbus_property {
1025 const char *name;
1026 const char *iface;
1027 const char *type;
1028 WPADBusPropertyAccessor getter;
1029 WPADBusPropertyAccessor setter;
1030 enum dbus_prop_access _access;
1033 struct wpas_dbus_signal {
1034 const char *name;
1035 const char *iface;
1036 struct wpa_dbus_argument args[3];
1040 static void wpas_dbus_register(struct wpa_dbus_object_desc *obj_desc,
1041 void *priv,
1042 WPADBusArgumentFreeFunction priv_free,
1043 const struct wpas_dbus_method *methods,
1044 const struct wpas_dbus_property *properties,
1045 const struct wpas_dbus_signal *signals)
1047 int i;
1049 obj_desc->user_data = priv;
1050 obj_desc->user_data_free_func = priv_free;
1052 for (i = 0; methods && methods[i].name; i++) {
1053 wpa_dbus_method_register(obj_desc, methods[i].iface,
1054 methods[i].name, methods[i].handler,
1055 methods[i].args);
1058 for (i = 0; properties && properties[i].name; i++) {
1059 wpa_dbus_property_register(obj_desc, properties[i].iface,
1060 properties[i].name,
1061 properties[i].type,
1062 properties[i].getter,
1063 properties[i].setter,
1064 properties[i]._access);
1067 for (i = 0; signals && signals[i].name; i++) {
1068 wpa_dbus_signal_register(obj_desc, signals[i].iface,
1069 signals[i].name, signals[i].args);
1074 static const struct wpas_dbus_method wpas_dbus_global_methods[] = {
1075 { "CreateInterface", WPAS_DBUS_NEW_INTERFACE,
1076 (WPADBusMethodHandler) &wpas_dbus_handler_create_interface,
1078 { "args", "a{sv}", ARG_IN },
1079 { "path", "o", ARG_OUT },
1080 END_ARGS
1083 { "RemoveInterface", WPAS_DBUS_NEW_INTERFACE,
1084 (WPADBusMethodHandler) &wpas_dbus_handler_remove_interface,
1086 { "path", "o", ARG_IN },
1087 END_ARGS
1090 { "GetInterface", WPAS_DBUS_NEW_INTERFACE,
1091 (WPADBusMethodHandler) &wpas_dbus_handler_get_interface,
1093 { "ifname", "s", ARG_IN },
1094 { "path", "o", ARG_OUT },
1095 END_ARGS
1098 { NULL, NULL, NULL, { END_ARGS } }
1101 static const struct wpas_dbus_property wpas_dbus_global_properties[] = {
1102 { "DebugLevel", WPAS_DBUS_NEW_INTERFACE, "y",
1103 (WPADBusPropertyAccessor) wpas_dbus_getter_debug_level,
1104 (WPADBusPropertyAccessor) wpas_dbus_setter_debug_level,
1107 { "DebugTimestamp", WPAS_DBUS_NEW_INTERFACE, "b",
1108 (WPADBusPropertyAccessor) wpas_dbus_getter_debug_timestamp,
1109 (WPADBusPropertyAccessor) wpas_dbus_setter_debug_timestamp,
1112 { "DebugShowKeys", WPAS_DBUS_NEW_INTERFACE, "b",
1113 (WPADBusPropertyAccessor) wpas_dbus_getter_debug_show_keys,
1114 (WPADBusPropertyAccessor) wpas_dbus_setter_debug_show_keys,
1117 { "Interfaces", WPAS_DBUS_NEW_INTERFACE, "ao",
1118 (WPADBusPropertyAccessor) &wpas_dbus_getter_interfaces,
1119 NULL,
1122 { "EapMethods", WPAS_DBUS_NEW_INTERFACE, "as",
1123 (WPADBusPropertyAccessor) wpas_dbus_getter_eap_methods,
1124 NULL,
1127 { NULL, NULL, NULL, NULL, NULL, 0 }
1130 static const struct wpas_dbus_signal wpas_dbus_global_signals[] = {
1131 { "InterfaceAdded", WPAS_DBUS_NEW_INTERFACE,
1133 { "path", "o", ARG_OUT },
1134 { "properties", "a{sv}", ARG_OUT },
1135 END_ARGS
1138 { "InterfaceRemoved", WPAS_DBUS_NEW_INTERFACE,
1140 { "path", "o", ARG_OUT },
1141 END_ARGS
1144 { "PropertiesChanged", WPAS_DBUS_NEW_INTERFACE,
1146 { "properties", "a{sv}", ARG_OUT },
1147 END_ARGS
1150 { NULL, NULL, { END_ARGS } }
1155 * wpas_dbus_ctrl_iface_init - Initialize dbus control interface
1156 * @global: Pointer to global data from wpa_supplicant_init()
1157 * Returns: 0 on success or -1 on failure
1159 * Initialize the dbus control interface for wpa_supplicantand and start
1160 * receiving commands from external programs over the bus.
1162 int wpas_dbus_ctrl_iface_init(struct wpas_dbus_priv *priv)
1164 struct wpa_dbus_object_desc *obj_desc;
1165 int ret;
1167 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
1168 if (!obj_desc) {
1169 wpa_printf(MSG_ERROR, "Not enough memory "
1170 "to create object description");
1171 return -1;
1174 wpas_dbus_register(obj_desc, priv->global, NULL,
1175 wpas_dbus_global_methods,
1176 wpas_dbus_global_properties,
1177 wpas_dbus_global_signals);
1179 wpa_printf(MSG_DEBUG, "dbus: Register D-Bus object '%s'",
1180 WPAS_DBUS_NEW_PATH);
1181 ret = wpa_dbus_ctrl_iface_init(priv, WPAS_DBUS_NEW_PATH,
1182 WPAS_DBUS_NEW_SERVICE,
1183 obj_desc);
1184 if (ret < 0)
1185 free_dbus_object_desc(obj_desc);
1186 else
1187 priv->dbus_new_initialized = 1;
1189 return ret;
1194 * wpas_dbus_ctrl_iface_deinit - Deinitialize dbus ctrl interface for
1195 * wpa_supplicant
1196 * @iface: Pointer to dbus private data from wpas_dbus_init()
1198 * Deinitialize the dbus control interface that was initialized with
1199 * wpas_dbus_ctrl_iface_init().
1201 void wpas_dbus_ctrl_iface_deinit(struct wpas_dbus_priv *iface)
1203 if (!iface->dbus_new_initialized)
1204 return;
1205 wpa_printf(MSG_DEBUG, "dbus: Unregister D-Bus object '%s'",
1206 WPAS_DBUS_NEW_PATH);
1207 dbus_connection_unregister_object_path(iface->con,
1208 WPAS_DBUS_NEW_PATH);
1212 static void wpa_dbus_free(void *ptr)
1214 os_free(ptr);
1218 static const struct wpas_dbus_property wpas_dbus_network_properties[] = {
1219 { "Properties", WPAS_DBUS_NEW_IFACE_NETWORK, "a{sv}",
1220 (WPADBusPropertyAccessor) wpas_dbus_getter_network_properties,
1221 (WPADBusPropertyAccessor) wpas_dbus_setter_network_properties,
1224 { "Enabled", WPAS_DBUS_NEW_IFACE_NETWORK, "b",
1225 (WPADBusPropertyAccessor) wpas_dbus_getter_enabled,
1226 (WPADBusPropertyAccessor) wpas_dbus_setter_enabled,
1229 { NULL, NULL, NULL, NULL, NULL, 0 }
1233 static const struct wpas_dbus_signal wpas_dbus_network_signals[] = {
1234 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_NETWORK,
1236 { "properties", "a{sv}", ARG_OUT },
1237 END_ARGS
1240 { NULL, NULL, { END_ARGS } }
1245 * wpas_dbus_register_network - Register a configured network with dbus
1246 * @wpa_s: wpa_supplicant interface structure
1247 * @ssid: network configuration data
1248 * Returns: 0 on success, -1 on failure
1250 * Registers network representing object with dbus
1252 static int wpas_dbus_register_network(struct wpa_supplicant *wpa_s,
1253 struct wpa_ssid *ssid)
1255 struct wpas_dbus_priv *ctrl_iface;
1256 struct wpa_dbus_object_desc *obj_desc;
1258 struct network_handler_args *arg = NULL;
1260 char *net_obj_path;
1262 /* Do nothing if the control interface is not turned on */
1263 if (wpa_s == NULL || wpa_s->global == NULL)
1264 return 0;
1265 ctrl_iface = wpa_s->global->dbus;
1266 if (ctrl_iface == NULL)
1267 return 0;
1269 net_obj_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1270 if (net_obj_path == NULL)
1271 return -1;
1272 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1273 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
1274 wpas_dbus_get_path(wpa_s), ssid->id);
1276 wpa_printf(MSG_DEBUG, "dbus: Register network object '%s'",
1277 net_obj_path);
1278 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
1279 if (!obj_desc) {
1280 wpa_printf(MSG_ERROR, "Not enough memory "
1281 "to create object description");
1282 goto err;
1285 /* allocate memory for handlers arguments */
1286 arg = os_zalloc(sizeof(struct network_handler_args));
1287 if (!arg) {
1288 wpa_printf(MSG_ERROR, "Not enough memory "
1289 "to create arguments for method");
1290 goto err;
1293 arg->wpa_s = wpa_s;
1294 arg->ssid = ssid;
1296 wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
1297 wpas_dbus_network_properties,
1298 wpas_dbus_network_signals);
1300 if (wpa_dbus_register_object_per_iface(ctrl_iface, net_obj_path,
1301 wpa_s->ifname, obj_desc))
1302 goto err;
1304 wpas_dbus_signal_network_added(wpa_s, ssid->id);
1306 os_free(net_obj_path);
1307 return 0;
1309 err:
1310 os_free(net_obj_path);
1311 os_free(obj_desc);
1312 os_free(arg);
1313 return -1;
1318 * wpas_dbus_unregister_network - Unregister a configured network from dbus
1319 * @wpa_s: wpa_supplicant interface structure
1320 * @nid: network id
1321 * Returns: 0 on success, -1 on failure
1323 * Unregisters network representing object from dbus
1325 static int wpas_dbus_unregister_network(struct wpa_supplicant *wpa_s, int nid)
1327 struct wpas_dbus_priv *ctrl_iface;
1328 char *net_obj_path;
1329 int ret;
1331 /* Do nothing if the control interface is not turned on */
1332 if (wpa_s == NULL || wpa_s->global == NULL)
1333 return 0;
1334 ctrl_iface = wpa_s->global->dbus;
1335 if (ctrl_iface == NULL)
1336 return 0;
1338 net_obj_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1339 if (net_obj_path == NULL)
1340 return -1;
1341 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1342 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
1343 wpas_dbus_get_path(wpa_s), nid);
1345 wpa_printf(MSG_DEBUG, "dbus: Unregister network object '%s'",
1346 net_obj_path);
1347 ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, net_obj_path);
1349 if (!ret)
1350 wpas_dbus_signal_network_removed(wpa_s, nid);
1352 os_free(net_obj_path);
1353 return ret;
1357 static const struct wpas_dbus_property wpas_dbus_bss_properties[] = {
1358 { "SSID", WPAS_DBUS_NEW_IFACE_BSSID, "ay",
1359 (WPADBusPropertyAccessor) wpas_dbus_getter_bss_ssid,
1360 NULL,
1363 { "BSSID", WPAS_DBUS_NEW_IFACE_BSSID, "ay",
1364 (WPADBusPropertyAccessor) wpas_dbus_getter_bss_bssid,
1365 NULL,
1368 { "Privacy", WPAS_DBUS_NEW_IFACE_BSSID, "b",
1369 (WPADBusPropertyAccessor) wpas_dbus_getter_bss_privacy,
1370 NULL,
1373 { "Mode", WPAS_DBUS_NEW_IFACE_BSSID, "s",
1374 (WPADBusPropertyAccessor) wpas_dbus_getter_bss_mode,
1375 NULL,
1378 { "Signal", WPAS_DBUS_NEW_IFACE_BSSID, "n",
1379 (WPADBusPropertyAccessor) wpas_dbus_getter_bss_signal,
1380 NULL,
1383 { "Frequency", WPAS_DBUS_NEW_IFACE_BSSID, "q",
1384 (WPADBusPropertyAccessor) wpas_dbus_getter_bss_frequency,
1385 NULL,
1388 { "MaxRate", WPAS_DBUS_NEW_IFACE_BSSID, "q",
1389 (WPADBusPropertyAccessor) wpas_dbus_getter_bss_max_rate,
1390 NULL,
1393 { "WPAIE", WPAS_DBUS_NEW_IFACE_BSSID, "ay",
1394 (WPADBusPropertyAccessor) wpas_dbus_getter_bss_wpaie,
1395 NULL,
1398 { "RSNIE", WPAS_DBUS_NEW_IFACE_BSSID, "ay",
1399 (WPADBusPropertyAccessor) wpas_dbus_getter_bss_rsnie,
1400 NULL,
1403 { "WPSIE", WPAS_DBUS_NEW_IFACE_BSSID, "ay",
1404 (WPADBusPropertyAccessor) wpas_dbus_getter_bss_wpsie,
1405 NULL,
1408 { NULL, NULL, NULL, NULL, NULL, 0 }
1412 static const struct wpas_dbus_signal wpas_dbus_bss_signals[] = {
1413 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_BSSID,
1415 { "properties", "a{sv}", ARG_OUT },
1416 END_ARGS
1419 { NULL, NULL, { END_ARGS } }
1424 * wpas_dbus_unregister_bss - Unregister a scanned BSS from dbus
1425 * @wpa_s: wpa_supplicant interface structure
1426 * @bssid: scanned network bssid
1427 * @id: unique BSS identifier
1428 * Returns: 0 on success, -1 on failure
1430 * Unregisters BSS representing object from dbus
1432 static int wpas_dbus_unregister_bss(struct wpa_supplicant *wpa_s,
1433 u8 bssid[ETH_ALEN], unsigned int id)
1435 struct wpas_dbus_priv *ctrl_iface;
1436 char *bss_obj_path;
1438 /* Do nothing if the control interface is not turned on */
1439 if (wpa_s == NULL || wpa_s->global == NULL)
1440 return 0;
1441 ctrl_iface = wpa_s->global->dbus;
1442 if (ctrl_iface == NULL)
1443 return 0;
1445 bss_obj_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1446 if (bss_obj_path == NULL)
1447 return -1;
1449 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1450 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
1451 wpas_dbus_get_path(wpa_s), id);
1453 wpa_printf(MSG_DEBUG, "dbus: Unregister BSS object '%s'",
1454 bss_obj_path);
1455 if (wpa_dbus_unregister_object_per_iface(ctrl_iface, bss_obj_path)) {
1456 wpa_printf(MSG_ERROR,
1457 "Cannot unregister BSSID dbus object %s.",
1458 bss_obj_path);
1459 os_free(bss_obj_path);
1460 return -1;
1463 wpas_dbus_signal_bss_removed(wpa_s, bss_obj_path);
1465 os_free(bss_obj_path);
1466 return 0;
1471 * wpas_dbus_register_bss - Register a scanned BSS with dbus
1472 * @wpa_s: wpa_supplicant interface structure
1473 * @bssid: scanned network bssid
1474 * @id: unique BSS identifier
1475 * Returns: 0 on success, -1 on failure
1477 * Registers BSS representing object with dbus
1479 static int wpas_dbus_register_bss(struct wpa_supplicant *wpa_s,
1480 u8 bssid[ETH_ALEN], unsigned int id)
1482 struct wpas_dbus_priv *ctrl_iface;
1483 struct wpa_dbus_object_desc *obj_desc;
1484 char *bss_obj_path;
1486 struct bss_handler_args *arg = NULL;
1488 /* Do nothing if the control interface is not turned on */
1489 if (wpa_s == NULL || wpa_s->global == NULL)
1490 return 0;
1491 ctrl_iface = wpa_s->global->dbus;
1492 if (ctrl_iface == NULL)
1493 return 0;
1495 bss_obj_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1496 if (bss_obj_path == NULL)
1497 return -1;
1499 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1500 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
1501 wpas_dbus_get_path(wpa_s), id);
1503 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
1504 if (!obj_desc) {
1505 wpa_printf(MSG_ERROR, "Not enough memory "
1506 "to create object description");
1507 goto err;
1510 arg = os_zalloc(sizeof(struct bss_handler_args));
1511 if (!arg) {
1512 wpa_printf(MSG_ERROR, "Not enough memory "
1513 "to create arguments for handler");
1514 goto err;
1516 arg->wpa_s = wpa_s;
1517 arg->id = id;
1519 wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
1520 wpas_dbus_bss_properties,
1521 wpas_dbus_bss_signals);
1523 wpa_printf(MSG_DEBUG, "dbus: Register BSS object '%s'",
1524 bss_obj_path);
1525 if (wpa_dbus_register_object_per_iface(ctrl_iface, bss_obj_path,
1526 wpa_s->ifname, obj_desc)) {
1527 wpa_printf(MSG_ERROR,
1528 "Cannot register BSSID dbus object %s.",
1529 bss_obj_path);
1530 goto err;
1533 wpas_dbus_signal_bss_added(wpa_s, bss_obj_path);
1535 os_free(bss_obj_path);
1536 return 0;
1538 err:
1539 os_free(bss_obj_path);
1540 os_free(obj_desc);
1541 os_free(arg);
1542 return -1;
1546 static const struct wpas_dbus_method wpas_dbus_interface_methods[] = {
1547 { "Scan", WPAS_DBUS_NEW_IFACE_INTERFACE,
1548 (WPADBusMethodHandler) &wpas_dbus_handler_scan,
1550 { "args", "a{sv}", ARG_IN },
1551 END_ARGS
1554 { "Disconnect", WPAS_DBUS_NEW_IFACE_INTERFACE,
1555 (WPADBusMethodHandler) &wpas_dbus_handler_disconnect,
1557 END_ARGS
1560 { "AddNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
1561 (WPADBusMethodHandler) &wpas_dbus_handler_add_network,
1563 { "args", "a{sv}", ARG_IN },
1564 { "path", "o", ARG_OUT },
1565 END_ARGS
1568 { "RemoveNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
1569 (WPADBusMethodHandler) &wpas_dbus_handler_remove_network,
1571 { "path", "o", ARG_IN },
1572 END_ARGS
1575 { "SelectNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
1576 (WPADBusMethodHandler) &wpas_dbus_handler_select_network,
1578 { "path", "o", ARG_IN },
1579 END_ARGS
1582 { "AddBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
1583 (WPADBusMethodHandler) &wpas_dbus_handler_add_blob,
1585 { "name", "s", ARG_IN },
1586 { "data", "ay", ARG_IN },
1587 END_ARGS
1590 { "GetBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
1591 (WPADBusMethodHandler) &wpas_dbus_handler_get_blob,
1593 { "name", "s", ARG_IN },
1594 { "data", "ay", ARG_OUT },
1595 END_ARGS
1598 { "RemoveBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
1599 (WPADBusMethodHandler) &wpas_dbus_handler_remove_blob,
1601 { "name", "s", ARG_IN },
1602 END_ARGS
1605 #ifdef CONFIG_WPS
1606 { "Start", WPAS_DBUS_NEW_IFACE_WPS,
1607 (WPADBusMethodHandler) &wpas_dbus_handler_wps_start,
1609 { "args", "a{sv}", ARG_IN },
1610 { "output", "a{sv}", ARG_OUT },
1611 END_ARGS
1614 #endif /* CONFIG_WPS */
1615 { NULL, NULL, NULL, { END_ARGS } }
1618 static const struct wpas_dbus_property wpas_dbus_interface_properties[] = {
1619 { "Capabilities", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{sv}",
1620 (WPADBusPropertyAccessor) wpas_dbus_getter_capabilities,
1621 NULL, R
1623 { "State", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
1624 (WPADBusPropertyAccessor) wpas_dbus_getter_state,
1625 NULL, R
1627 { "Scanning", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
1628 (WPADBusPropertyAccessor) wpas_dbus_getter_scanning,
1629 NULL, R
1631 { "ApScan", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
1632 (WPADBusPropertyAccessor) wpas_dbus_getter_ap_scan,
1633 (WPADBusPropertyAccessor) wpas_dbus_setter_ap_scan,
1636 { "Ifname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
1637 (WPADBusPropertyAccessor) wpas_dbus_getter_ifname,
1638 NULL, R
1640 { "Driver", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
1641 (WPADBusPropertyAccessor) wpas_dbus_getter_driver,
1642 NULL, R
1644 { "BridgeIfname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
1645 (WPADBusPropertyAccessor) wpas_dbus_getter_bridge_ifname,
1646 NULL, R
1648 { "CurrentBSS", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
1649 (WPADBusPropertyAccessor) wpas_dbus_getter_current_bss,
1650 NULL, R
1652 { "CurrentNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
1653 (WPADBusPropertyAccessor) wpas_dbus_getter_current_network,
1654 NULL, R
1656 { "Blobs", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{say}",
1657 (WPADBusPropertyAccessor) wpas_dbus_getter_blobs,
1658 NULL, R
1660 { "BSSs", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
1661 (WPADBusPropertyAccessor) wpas_dbus_getter_bsss,
1662 NULL, R
1664 { "Networks", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
1665 (WPADBusPropertyAccessor) wpas_dbus_getter_networks,
1666 NULL, R
1668 #ifdef CONFIG_WPS
1669 { "ProcessCredentials", WPAS_DBUS_NEW_IFACE_WPS, "b",
1670 (WPADBusPropertyAccessor) wpas_dbus_getter_process_credentials,
1671 (WPADBusPropertyAccessor) wpas_dbus_setter_process_credentials,
1674 #endif /* CONFIG_WPS */
1675 { NULL, NULL, NULL, NULL, NULL, 0 }
1678 static const struct wpas_dbus_signal wpas_dbus_interface_signals[] = {
1679 { "ScanDone", WPAS_DBUS_NEW_IFACE_INTERFACE,
1681 { "success", "b", ARG_OUT },
1682 END_ARGS
1685 { "StateChanged", WPAS_DBUS_NEW_IFACE_INTERFACE,
1687 { "newState", "s", ARG_OUT },
1688 { "oldState", "s", ARG_OUT },
1689 END_ARGS
1692 { "BSSAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
1694 { "path", "o", ARG_OUT },
1695 { "properties", "a{sv}", ARG_OUT },
1696 END_ARGS
1699 { "BSSRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
1701 { "path", "o", ARG_OUT },
1702 END_ARGS
1705 { "BlobAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
1707 { "name", "s", ARG_OUT },
1708 END_ARGS
1711 { "BlobRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
1713 { "name", "s", ARG_OUT },
1714 END_ARGS
1717 { "NetworkAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
1719 { "path", "o", ARG_OUT },
1720 { "properties", "a{sv}", ARG_OUT },
1721 END_ARGS
1724 { "NetworkRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
1726 { "path", "o", ARG_OUT },
1727 END_ARGS
1730 { "NetworkSelected", WPAS_DBUS_NEW_IFACE_INTERFACE,
1732 { "path", "o", ARG_OUT },
1733 END_ARGS
1736 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_INTERFACE,
1738 { "properties", "a{sv}", ARG_OUT },
1739 END_ARGS
1742 #ifdef CONFIG_WPS
1743 { "Event", WPAS_DBUS_NEW_IFACE_WPS,
1745 { "name", "s", ARG_OUT },
1746 { "args", "a{sv}", ARG_OUT },
1747 END_ARGS
1750 { "Credentials", WPAS_DBUS_NEW_IFACE_WPS,
1752 { "credentials", "a{sv}", ARG_OUT },
1753 END_ARGS
1756 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_WPS,
1758 { "properties", "a{sv}", ARG_OUT },
1759 END_ARGS
1762 #endif /* CONFIG_WPS */
1763 { NULL, NULL, { END_ARGS } }
1767 static int wpas_dbus_register_interface(struct wpa_supplicant *wpa_s)
1770 struct wpa_dbus_object_desc *obj_desc = NULL;
1771 char *path;
1772 struct wpas_dbus_priv *ctrl_iface = wpa_s->global->dbus;
1773 int next;
1775 /* Do nothing if the control interface is not turned on */
1776 if (ctrl_iface == NULL)
1777 return 0;
1779 /* Create and set the interface's object path */
1780 path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1781 if (path == NULL)
1782 return -1;
1783 next = ctrl_iface->next_objid++;
1784 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
1785 WPAS_DBUS_NEW_PATH_INTERFACES "/%u",
1786 next);
1787 if (wpas_dbus_set_path(wpa_s, path)) {
1788 wpa_printf(MSG_DEBUG,
1789 "Failed to set dbus path for interface %s",
1790 wpa_s->ifname);
1791 goto err;
1794 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
1795 if (!obj_desc) {
1796 wpa_printf(MSG_ERROR, "Not enough memory "
1797 "to create object description");
1798 goto err;
1801 wpas_dbus_register(obj_desc, wpa_s, NULL, wpas_dbus_interface_methods,
1802 wpas_dbus_interface_properties,
1803 wpas_dbus_interface_signals);
1805 wpa_printf(MSG_DEBUG, "dbus: Register interface object '%s'", path);
1806 if (wpa_dbus_register_object_per_iface(ctrl_iface, path, wpa_s->ifname,
1807 obj_desc))
1808 goto err;
1810 wpas_dbus_signal_interface_added(wpa_s);
1812 os_free(path);
1813 return 0;
1815 err:
1816 os_free(obj_desc);
1817 os_free(path);
1818 return -1;
1822 static int wpas_dbus_unregister_interface(struct wpa_supplicant *wpa_s)
1824 struct wpas_dbus_priv *ctrl_iface;
1826 /* Do nothing if the control interface is not turned on */
1827 if (wpa_s == NULL || wpa_s->global == NULL)
1828 return 0;
1829 ctrl_iface = wpa_s->global->dbus;
1830 if (ctrl_iface == NULL)
1831 return 0;
1833 wpa_printf(MSG_DEBUG, "dbus: Unregister interface object '%s'",
1834 wpas_dbus_get_path(wpa_s));
1835 if (wpa_dbus_unregister_object_per_iface(ctrl_iface,
1836 wpas_dbus_get_path(wpa_s)))
1837 return -1;
1839 wpas_dbus_signal_interface_removed(wpa_s);
1841 os_free(wpa_s->dbus_new_path);
1842 wpa_s->dbus_new_path = NULL;
1844 return 0;
1848 static struct wpas_dbus_callbacks callbacks =
1850 .signal_interface_added = wpas_dbus_signal_interface_added,
1851 .signal_interface_removed = wpas_dbus_signal_interface_removed,
1853 .register_interface = wpas_dbus_register_interface,
1854 .unregister_interface = wpas_dbus_unregister_interface,
1856 .signal_scan_done = wpas_dbus_signal_scan_done,
1858 .signal_blob_added = wpas_dbus_signal_blob_added,
1859 .signal_blob_removed = wpas_dbus_signal_blob_removed,
1861 .signal_network_selected = wpas_dbus_signal_network_selected,
1863 .signal_state_changed = wpas_dbus_signal_state_changed,
1864 .register_network = wpas_dbus_register_network,
1865 .unregister_network = wpas_dbus_unregister_network,
1867 .signal_network_enabled_changed =
1868 wpas_dbus_signal_network_enabled_changed,
1870 .register_bss = wpas_dbus_register_bss,
1871 .unregister_bss = wpas_dbus_unregister_bss,
1873 .signal_prop_changed = wpas_dbus_signal_prop_changed,
1875 .signal_debug_level_changed = wpas_dbus_signal_debug_level_changed,
1876 .signal_debug_timestamp_changed =
1877 wpas_dbus_signal_debug_timestamp_changed,
1878 .signal_debug_show_keys_changed =
1879 wpas_dbus_signal_debug_show_keys_changed,
1881 #ifdef CONFIG_WPS
1882 .signal_wps_event_success = wpas_dbus_signal_wps_event_success,
1883 .signal_wps_event_fail = wpas_dbus_signal_wps_event_fail,
1884 .signal_wps_event_m2d = wpas_dbus_signal_wps_event_m2d,
1885 .signal_wps_credentials = wpas_dbus_signal_wps_cred,
1886 #endif /* CONFIG_WPS */
1890 struct wpas_dbus_callbacks * wpas_dbus_get_callbacks(void)
1892 return &callbacks;
1897 * wpas_dbus_get_path - Get an interface's dbus path
1898 * @wpa_s: %wpa_supplicant interface structure
1899 * Returns: Interface's dbus object path, or %NULL on error
1901 const char * wpas_dbus_get_path(struct wpa_supplicant *wpa_s)
1903 return wpa_s->dbus_new_path;