dbus: Get rid of unnecessary string duplication in dbus_path
[hostap-gosc2009.git] / wpa_supplicant / dbus / dbus_new.c
blob294156730d97abdb63cee664b248c9220935f50e
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"
32 /**
33 * wpas_dbus_signal_interface - Send a interface related event signal
34 * @wpa_s: %wpa_supplicant network interface data
35 * @sig_name: signal name - InterfaceAdded or InterfaceRemoved
36 * @properties: determines if add second argument with object properties
38 * Notify listeners about event related with interface
40 static void wpas_dbus_signal_interface(struct wpa_supplicant *wpa_s,
41 const char *sig_name, int properties)
43 struct wpas_dbus_priv *iface;
44 DBusMessage *_signal;
45 DBusMessageIter iter, iter_dict;
46 const char *path;
48 iface = wpa_s->global->dbus;
50 /* Do nothing if the control interface is not turned on */
51 if (iface == NULL)
52 return;
54 path = wpas_dbus_get_path(wpa_s);
55 if (path == NULL) {
56 wpa_printf(MSG_ERROR, "wpas_dbus_signal_interface[dbus]: "
57 "Interface doesn't have a dbus path. "
58 "Can't send signal.");
59 return;
61 _signal = dbus_message_new_signal(WPAS_DBUS_NEW_PATH,
62 WPAS_DBUS_NEW_INTERFACE, sig_name);
63 if (_signal == NULL) {
64 wpa_printf(MSG_ERROR, "wpas_dbus_signal_interface[dbus]: "
65 "enough memory to send scan results signal.");
66 return;
69 dbus_message_iter_init_append(_signal, &iter);
71 if(!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
72 &path))
73 goto err;
75 if (properties) {
76 if (!wpa_dbus_dict_open_write(&iter, &iter_dict))
77 goto err;
79 wpa_dbus_get_object_properties(iface, path,
80 WPAS_DBUS_NEW_IFACE_INTERFACE,
81 &iter_dict);
83 if (!wpa_dbus_dict_close_write(&iter, &iter_dict))
84 goto err;
87 dbus_connection_send(iface->con, _signal, NULL);
89 dbus_message_unref(_signal);
90 return;
92 err:
93 wpa_printf(MSG_ERROR, "wpas_dbus_signal_interface[dbus]: "
94 "not enough memory to construct signal.");
95 dbus_message_unref(_signal);
99 /**
100 * wpas_dbus_signal_interface_added - Send a interface created signal
101 * @wpa_s: %wpa_supplicant network interface data
103 * Notify listeners about creating new interface
105 static void wpas_dbus_signal_interface_added(struct wpa_supplicant *wpa_s)
107 wpas_dbus_signal_interface(wpa_s, "InterfaceAdded", TRUE);
112 * wpas_dbus_signal_interface_removed - Send a interface removed signal
113 * @wpa_s: %wpa_supplicant network interface data
115 * Notify listeners about removing interface
117 static void wpas_dbus_signal_interface_removed(struct wpa_supplicant *wpa_s)
119 wpas_dbus_signal_interface(wpa_s, "InterfaceRemoved", FALSE);
125 * wpas_dbus_signal_scan_done - send scan done signal
126 * @wpa_s: %wpa_supplicant network interface data
127 * @success: indicates if scanning succeed or failed
129 * Notify listeners about finishing a scan
131 void wpas_dbus_signal_scan_done(struct wpa_supplicant *wpa_s, int success)
133 struct wpas_dbus_priv *iface;
134 DBusMessage *_signal;
135 const char *path;
136 dbus_bool_t succ;
138 iface = wpa_s->global->dbus;
140 /* Do nothing if the control interface is not turned on */
141 if (iface == NULL)
142 return;
144 path = wpas_dbus_get_path(wpa_s);
145 if (path == NULL) {
146 wpa_printf(MSG_ERROR, "wpas_dbus_signal_scan_done[dbus]: "
147 "Interface doesn't have a dbus path. "
148 "Can't send signal.");
149 return;
151 _signal = dbus_message_new_signal(path, WPAS_DBUS_NEW_IFACE_INTERFACE,
152 "ScanDone");
153 if (_signal == NULL) {
154 wpa_printf(MSG_ERROR, "wpas_dbus_signal_scan_done[dbus]: "
155 "enough memory to send signal.");
156 return;
159 succ = success ? TRUE : FALSE;
160 if (dbus_message_append_args(_signal, DBUS_TYPE_BOOLEAN, &succ,
161 DBUS_TYPE_INVALID)) {
162 dbus_connection_send(iface->con, _signal, NULL);
163 } else {
164 wpa_printf(MSG_ERROR, "wpas_dbus_signal_scan_done[dbus]: "
165 "not enough memory to construct signal.");
167 dbus_message_unref(_signal);
172 * wpas_dbus_signal_blob - Send a BSS related event signal
173 * @wpa_s: %wpa_supplicant network interface data
174 * @bss_obj_path: BSS object path
175 * @sig_name: signal name - BSSAdded or BSSRemoved
176 * @properties: determines if add second argument with object properties
178 * Notify listeners about event related with BSS
180 static void wpas_dbus_signal_bss(struct wpa_supplicant *wpa_s,
181 const char *bss_obj_path,
182 const char *sig_name, int properties)
184 struct wpas_dbus_priv *iface;
185 DBusMessage *_signal;
186 DBusMessageIter iter, iter_dict;
187 const char *path;
189 iface = wpa_s->global->dbus;
191 /* Do nothing if the control interface is not turned on */
192 if (iface == NULL)
193 return;
195 path = wpas_dbus_get_path(wpa_s);
196 if (path == NULL) {
197 wpa_printf(MSG_ERROR, "wpas_dbus_signal_bss[dbus]: "
198 "Interface doesn't have a dbus path. "
199 "Can't send signal.");
200 return;
202 _signal = dbus_message_new_signal(path, WPAS_DBUS_NEW_IFACE_INTERFACE,
203 sig_name);
204 if (_signal == NULL) {
205 wpa_printf(MSG_ERROR, "wpas_dbus_signal_bss[dbus]: "
206 "enough memory to send signal.");
207 return;
210 dbus_message_iter_init_append(_signal, &iter);
212 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
213 &bss_obj_path))
214 goto err;
216 if (properties) {
217 if (!wpa_dbus_dict_open_write(&iter, &iter_dict))
218 goto err;
220 wpa_dbus_get_object_properties(iface, bss_obj_path,
221 WPAS_DBUS_NEW_IFACE_BSSID,
222 &iter_dict);
224 if (!wpa_dbus_dict_close_write(&iter, &iter_dict))
225 goto err;
228 dbus_connection_send(iface->con, _signal, NULL);
230 dbus_message_unref(_signal);
231 return;
233 err:
234 wpa_printf(MSG_ERROR, "wpas_dbus_signal_bss[dbus]: "
235 "not enough memory to construct signal.");
236 dbus_message_unref(_signal);
241 * wpas_dbus_signal_bss_added - Send a BSS added signal
242 * @wpa_s: %wpa_supplicant network interface data
243 * @bss_obj_path: new BSS object path
245 * Notify listeners about adding new BSS
247 static void wpas_dbus_signal_bss_added(struct wpa_supplicant *wpa_s,
248 const char *bss_obj_path)
250 wpas_dbus_signal_bss(wpa_s, bss_obj_path, "BSSAdded", TRUE);
255 * wpas_dbus_signal_bss_removed - Send a BSS removed signal
256 * @wpa_s: %wpa_supplicant network interface data
257 * @bss_obj_path: BSS object path
259 * Notify listeners about removing BSS
261 static void wpas_dbus_signal_bss_removed(struct wpa_supplicant *wpa_s,
262 const char *bss_obj_path)
264 wpas_dbus_signal_bss(wpa_s, bss_obj_path, "BSSRemoved", FALSE);
269 * wpas_dbus_signal_blob - Send a blob related event signal
270 * @wpa_s: %wpa_supplicant network interface data
271 * @name: blob name
272 * @sig_name: signal name - BlobAdded or BlobRemoved
274 * Notify listeners about event related with blob
276 static void wpas_dbus_signal_blob(struct wpa_supplicant *wpa_s,
277 const char *name, const char *sig_name)
279 struct wpas_dbus_priv *iface;
280 DBusMessage *_signal;
281 const char *path;
283 iface = wpa_s->global->dbus;
285 /* Do nothing if the control interface is not turned on */
286 if (iface == NULL)
287 return;
289 path = wpas_dbus_get_path(wpa_s);
290 if (path == NULL) {
291 wpa_printf(MSG_ERROR, "wpas_dbus_signal_blob[dbus]: "
292 "Interface doesn't have a dbus path. "
293 "Can't send signal.");
294 return;
296 _signal = dbus_message_new_signal(path, WPAS_DBUS_NEW_IFACE_INTERFACE,
297 sig_name);
298 if (_signal == NULL) {
299 wpa_printf(MSG_ERROR, "wpas_dbus_signal_blob[dbus]: "
300 "enough memory to send signal.");
301 return;
304 if (dbus_message_append_args(_signal, DBUS_TYPE_STRING, &name,
305 DBUS_TYPE_INVALID)) {
306 dbus_connection_send(iface->con, _signal, NULL);
307 } else {
308 wpa_printf(MSG_ERROR, "wpas_dbus_signal_blob[dbus]: "
309 "not enough memory to construct signal.");
311 dbus_message_unref(_signal);
316 * wpas_dbus_signal_blob_added - Send a blob added signal
317 * @wpa_s: %wpa_supplicant network interface data
318 * @name: blob name
320 * Notify listeners about adding a new blob
322 void wpas_dbus_signal_blob_added(struct wpa_supplicant *wpa_s,
323 const char *name)
325 wpas_dbus_signal_blob(wpa_s, name, "BlobAdded");
330 * wpas_dbus_signal_blob_removed - Send a blob removed signal
331 * @wpa_s: %wpa_supplicant network interface data
332 * @name: blob name
334 * Notify listeners about removing blob
336 void wpas_dbus_signal_blob_removed(struct wpa_supplicant *wpa_s,
337 const char *name)
339 wpas_dbus_signal_blob(wpa_s, name, "BlobRemoved");
344 * wpas_dbus_signal_network - Send a network related event signal
345 * @wpa_s: %wpa_supplicant network interface data
346 * @id: new network id
347 * @sig_name: signal name - NetworkAdded, NetworkRemoved or NetworkSelected
348 * @properties: determines if add second argument with object properties
350 * Notify listeners about event related with configured network
352 static void wpas_dbus_signal_network(struct wpa_supplicant *wpa_s,
353 int id, const char *sig_name,
354 int properties)
356 struct wpas_dbus_priv *iface;
357 DBusMessage *_signal;
358 DBusMessageIter iter, iter_dict;
359 const char *path;
360 char *net_obj_path;
362 iface = wpa_s->global->dbus;
364 /* Do nothing if the control interface is not turned on */
365 if (iface == NULL)
366 return;
368 path = wpas_dbus_get_path(wpa_s);
369 if (path == NULL) {
370 wpa_printf(MSG_ERROR, "wpas_dbus_signal_network[dbus]: "
371 "Interface doesn't have a dbus path. "
372 "Can't send signal.");
373 return;
376 net_obj_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
377 if (net_obj_path == NULL)
378 return;
379 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
380 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u", path, id);
382 _signal = dbus_message_new_signal(path, WPAS_DBUS_NEW_IFACE_INTERFACE,
383 sig_name);
384 if (_signal == NULL) {
385 wpa_printf(MSG_ERROR, "wpas_dbus_signal_network[dbus]: "
386 "enough memory to send signal.");
387 os_free(net_obj_path);
388 return;
391 dbus_message_iter_init_append(_signal, &iter);
393 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
394 &net_obj_path))
395 goto err;
397 if (properties) {
398 if (!wpa_dbus_dict_open_write(&iter, &iter_dict))
399 goto err;
401 wpa_dbus_get_object_properties(iface, net_obj_path,
402 WPAS_DBUS_NEW_IFACE_NETWORK,
403 &iter_dict);
405 if (!wpa_dbus_dict_close_write(&iter, &iter_dict))
406 goto err;
409 dbus_connection_send(iface->con, _signal, NULL);
411 os_free(net_obj_path);
412 dbus_message_unref(_signal);
413 return;
415 err:
416 wpa_printf(MSG_ERROR, "wpas_dbus_signal_network[dbus]: "
417 "not enough memory to construct signal.");
418 os_free(net_obj_path);
419 dbus_message_unref(_signal);
424 * wpas_dbus_signal_network_added - Send a network added signal
425 * @wpa_s: %wpa_supplicant network interface data
426 * @id: new network id
428 * Notify listeners about adding new network
430 static void wpas_dbus_signal_network_added(struct wpa_supplicant *wpa_s,
431 int id)
433 wpas_dbus_signal_network(wpa_s, id, "NetworkAdded", TRUE);
438 * wpas_dbus_signal_network_removed - Send a network removed signal
439 * @wpa_s: %wpa_supplicant network interface data
440 * @id: network id
442 * Notify listeners about removing a network
444 static void wpas_dbus_signal_network_removed(struct wpa_supplicant *wpa_s,
445 int id)
447 wpas_dbus_signal_network(wpa_s, id, "NetworkRemoved", FALSE);
452 * wpas_dbus_signal_network_selected - Send a network selected signal
453 * @wpa_s: %wpa_supplicant network interface data
454 * @id: network id
456 * Notify listeners about selecting a network
458 void wpas_dbus_signal_network_selected(struct wpa_supplicant *wpa_s, int id)
460 wpas_dbus_signal_network(wpa_s, id, "NetworkSelected", FALSE);
465 * wpas_dbus_signal_state_changed - Send a state changed signal
466 * @wpa_s: %wpa_supplicant network interface data
467 * @new_state: new state wpa_supplicant is entering
468 * @old_state: old state wpa_supplicant is leaving
470 * Notify listeners that wpa_supplicant has changed state
472 void wpas_dbus_signal_state_changed(struct wpa_supplicant *wpa_s,
473 enum wpa_states new_state,
474 enum wpa_states old_state)
476 struct wpas_dbus_priv *iface;
477 DBusMessage *_signal = NULL;
478 const char *path;
479 char *new_state_str, *old_state_str;
480 char *tmp;
482 /* Do nothing if the control interface is not turned on */
483 if (wpa_s->global == NULL)
484 return;
485 iface = wpa_s->global->dbus;
486 if (iface == NULL)
487 return;
489 /* Only send signal if state really changed */
490 if (new_state == old_state)
491 return;
493 path = wpas_dbus_get_path(wpa_s);
494 if (path == NULL) {
495 perror("wpas_dbus_signal_state_changed[dbus]: "
496 "interface didn't have a dbus path");
497 wpa_printf(MSG_ERROR,
498 "wpas_dbus_signal_state_changed[dbus]: "
499 "interface didn't have a dbus path; can't send "
500 "signal.");
501 return;
503 _signal = dbus_message_new_signal(path, WPAS_DBUS_NEW_IFACE_INTERFACE,
504 "StateChanged");
505 if (_signal == NULL) {
506 perror("wpas_dbus_signal_state_changed[dbus]: "
507 "couldn't create dbus signal; likely out of memory");
508 wpa_printf(MSG_ERROR,
509 "wpas_dbus_signal_state_changed[dbus]: "
510 "couldn't create dbus signal; likely out of "
511 "memory.");
512 return;
515 new_state_str = os_strdup(wpa_supplicant_state_txt(new_state));
516 old_state_str = os_strdup(wpa_supplicant_state_txt(old_state));
517 if (new_state_str == NULL || old_state_str == NULL) {
518 perror("wpas_dbus_signal_state_changed[dbus]: "
519 "couldn't convert state strings");
520 wpa_printf(MSG_ERROR,
521 "wpas_dbus_signal_state_changed[dbus]: "
522 "couldn't convert state strings.");
523 goto out;
526 /* make state string lowercase to fit new DBus API convention */
527 tmp = new_state_str;
528 while (*tmp) {
529 *tmp = tolower(*tmp);
530 tmp++;
532 tmp = old_state_str;
533 while (*tmp) {
534 *tmp = tolower(*tmp);
535 tmp++;
538 if (!dbus_message_append_args(_signal,
539 DBUS_TYPE_STRING, &new_state_str,
540 DBUS_TYPE_STRING, &old_state_str,
541 DBUS_TYPE_INVALID)) {
542 perror("wpas_dbus_signal_state_changed[dbus]: "
543 "not enough memory to construct state change signal.");
544 wpa_printf(MSG_ERROR,
545 "wpas_dbus_signal_state_changed[dbus]: "
546 "not enough memory to construct state change "
547 "signal.");
548 goto out;
551 dbus_connection_send(iface->con, _signal, NULL);
553 out:
554 dbus_message_unref(_signal);
555 os_free(new_state_str);
556 os_free(old_state_str);
561 * wpas_dbus_signal_network_enabled_changed - Signals Enabled property changes
562 * @wpa_s: %wpa_supplicant network interface data
563 * @ssid: configured network which Enabled property has changed
565 * Sends PropertyChanged signals containing new value of Enabled property
566 * for specified network
568 void wpas_dbus_signal_network_enabled_changed(struct wpa_supplicant *wpa_s,
569 struct wpa_ssid *ssid)
572 struct network_handler_args args = {wpa_s, ssid};
574 char path[WPAS_DBUS_OBJECT_PATH_MAX];
575 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
576 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
577 wpas_dbus_get_path(wpa_s), ssid->id);
579 wpa_dbus_signal_property_changed(wpa_s->global->dbus,
580 (WPADBusPropertyAccessor)
581 wpas_dbus_getter_enabled, &args,
582 path, WPAS_DBUS_NEW_IFACE_NETWORK,
583 "Enabled");
587 #ifdef CONFIG_WPS
590 * wpas_dbus_signal_wps_event_success - Signals Success WPS event
591 * @wpa_s: %wpa_supplicant network interface data
593 * Sends Event dbus signal with name "success" and empty dict as arguments
595 void wpas_dbus_signal_wps_event_success(struct wpa_supplicant *wpa_s)
598 DBusMessage *_signal = NULL;
599 DBusMessageIter iter, dict_iter;
600 struct wpas_dbus_priv *iface;
601 char *key = "success";
602 const char *path;
604 iface = wpa_s->global->dbus;
606 /* Do nothing if the control interface is not turned on */
607 if (iface == NULL)
608 return;
610 path = wpas_dbus_get_path(wpa_s);
611 if (!path) {
612 wpa_printf(MSG_ERROR, "wpas_dbus_signal_wps_event_success"
613 "[dbus]: interface has no dbus path set");
614 return;
617 _signal = dbus_message_new_signal(path, WPAS_DBUS_NEW_IFACE_WPS,
618 "Event");
619 if (!_signal) {
620 wpa_printf(MSG_ERROR, "wpas_dbus_signal_wps_event_success"
621 "[dbus]: out of memory when creating a signal");
622 return;
625 dbus_message_iter_init_append(_signal, &iter);
627 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
628 !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
629 !wpa_dbus_dict_close_write(&iter, &dict_iter)) {
630 wpa_printf(MSG_ERROR, "wpas_dbus_signal_wps_event_success"
631 "[dbus]: out of memory");
632 goto out;
635 dbus_connection_send(iface->con, _signal, NULL);
636 out:
637 dbus_message_unref(_signal);
642 * wpas_dbus_signal_wps_event_fail - Signals Fail WPS event
643 * @wpa_s: %wpa_supplicant network interface data
645 * Sends Event dbus signal with name "fail" and dictionary containing
646 * "msg field with fail message number (int32) as arguments
648 void wpas_dbus_signal_wps_event_fail(struct wpa_supplicant *wpa_s,
649 struct wps_event_fail *fail)
652 DBusMessage *_signal = NULL;
653 DBusMessageIter iter, dict_iter;
654 struct wpas_dbus_priv *iface;
655 char *key = "fail";
656 const char *path;
658 iface = wpa_s->global->dbus;
660 /* Do nothing if the control interface is not turned on */
661 if (iface == NULL)
662 return;
664 path = wpas_dbus_get_path(wpa_s);
665 if (!path) {
666 wpa_printf(MSG_ERROR, "wpas_dbus_signal_wps_event_fail[dbus]: "
667 "interface has no dbus path set");
668 return;
671 _signal = dbus_message_new_signal(path, WPAS_DBUS_NEW_IFACE_WPS,
672 "Event");
673 if (!_signal) {
674 wpa_printf(MSG_ERROR, "wpas_dbus_signal_wps_event_fail[dbus]: "
675 "out of memory when creating a signal");
676 return;
679 dbus_message_iter_init_append(_signal, &iter);
681 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
682 !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
683 !wpa_dbus_dict_append_int32(&dict_iter, "msg", fail->msg) ||
684 !wpa_dbus_dict_close_write(&iter, &dict_iter)) {
685 wpa_printf(MSG_ERROR, "wpas_dbus_signal_wps_event_fail[dbus]: "
686 "out of memory");
687 goto out;
690 dbus_connection_send(iface->con, _signal, NULL);
691 out:
692 dbus_message_unref(_signal);
697 * wpas_dbus_signal_wps_event_m2d - Signals M2D WPS event
698 * @wpa_s: %wpa_supplicant network interface data
700 * Sends Event dbus signal with name "m2d" and dictionary containing
701 * fields of wps_event_m2d structure.
703 void wpas_dbus_signal_wps_event_m2d(struct wpa_supplicant *wpa_s,
704 struct wps_event_m2d *m2d)
707 DBusMessage *_signal = NULL;
708 DBusMessageIter iter, dict_iter;
709 struct wpas_dbus_priv *iface;
710 char *key = "m2d";
711 const char *path;
713 iface = wpa_s->global->dbus;
715 /* Do nothing if the control interface is not turned on */
716 if (iface == NULL)
717 return;
719 path = wpas_dbus_get_path(wpa_s);
720 if (!path) {
721 wpa_printf(MSG_ERROR, "wpas_dbus_signal_wps_event_m2d[dbus]: "
722 "interface has no dbus path set");
723 return;
726 _signal = dbus_message_new_signal(path, WPAS_DBUS_NEW_IFACE_WPS,
727 "Event");
728 if (!_signal) {
729 wpa_printf(MSG_ERROR, "wpas_dbus_signal_wps_event_m2d[dbus]: "
730 "out of memory when creating a signal");
731 return;
734 dbus_message_iter_init_append(_signal, &iter);
736 if (!(dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) &&
737 wpa_dbus_dict_open_write(&iter, &dict_iter) &&
738 wpa_dbus_dict_append_uint16(&dict_iter, "config_methods",
739 m2d->config_methods) &&
740 wpa_dbus_dict_append_byte_array(&dict_iter, "manufacturer",
741 (const char *) m2d->manufacturer,
742 m2d->manufacturer_len) &&
743 wpa_dbus_dict_append_byte_array(&dict_iter, "model_name",
744 (const char *) m2d->model_name,
745 m2d->model_name_len) &&
746 wpa_dbus_dict_append_byte_array(&dict_iter, "model_number",
747 (const char *) m2d->model_number,
748 m2d->model_number_len) &&
749 wpa_dbus_dict_append_byte_array(&dict_iter, "serial_number",
750 (const char *)
751 m2d->serial_number,
752 m2d->serial_number_len) &&
753 wpa_dbus_dict_append_byte_array(&dict_iter, "dev_name",
754 (const char *) m2d->dev_name,
755 m2d->dev_name_len) &&
756 wpa_dbus_dict_append_byte_array(&dict_iter, "primary_dev_type",
757 (const char *)
758 m2d->primary_dev_type, 8) &&
759 wpa_dbus_dict_append_uint16(&dict_iter, "config_error",
760 m2d->config_error) &&
761 wpa_dbus_dict_append_uint16(&dict_iter, "dev_password_id",
762 m2d->dev_password_id) &&
763 wpa_dbus_dict_close_write(&iter, &dict_iter))) {
764 wpa_printf(MSG_ERROR, "wpas_dbus_signal_wps_event_m2d[dbus]: "
765 "out of memory");
766 goto out;
769 dbus_connection_send(iface->con, _signal, NULL);
770 out:
771 dbus_message_unref(_signal);
776 * wpas_dbus_signal_wps_cred - Signals new credentials
777 * @wpa_s: %wpa_supplicant network interface data
779 * Sends signal with credentials in directory argument
781 void wpas_dbus_signal_wps_cred(struct wpa_supplicant *wpa_s,
782 const struct wps_credential *cred)
784 DBusMessage *_signal = NULL;
785 DBusMessageIter iter, dict_iter;
786 struct wpas_dbus_priv *iface;
787 const char *path;
788 char *auth_type[6]; /* we have six possible authorization types */
789 int at_num = 0;
790 char *encr_type[4]; /* we have four possible encryption types */
791 int et_num = 0;
793 iface = wpa_s->global->dbus;
795 /* Do nothing if the control interface is not turned on */
796 if (iface == NULL)
797 return;
799 path = wpas_dbus_get_path(wpa_s);
800 if (!path) {
801 wpa_printf(MSG_ERROR, "wpas_dbus_signal_wps_cred[dbus]: "
802 "interface has no dbus path set");
803 return;
806 _signal = dbus_message_new_signal(path, WPAS_DBUS_NEW_IFACE_WPS,
807 "Credentials");
808 if (!_signal) {
809 wpa_printf(MSG_ERROR, "wpas_dbus_signal_wps_cred[dbus]: "
810 "out of memory when creating a signal");
811 return;
814 dbus_message_iter_init_append(_signal, &iter);
816 if (!wpa_dbus_dict_open_write(&iter, &dict_iter)) {
817 perror("wpas_dbus_signal_wps_cred[dbus]: out of memory "
818 "when opening a dictionary");
819 goto nomem;
822 if (cred->auth_type & WPS_AUTH_OPEN)
823 auth_type[at_num++] = "open";
824 if (cred->auth_type & WPS_AUTH_WPAPSK)
825 auth_type[at_num++] = "wpa-psk";
826 if (cred->auth_type & WPS_AUTH_SHARED)
827 auth_type[at_num++] = "shared";
828 if (cred->auth_type & WPS_AUTH_WPA)
829 auth_type[at_num++] = "wpa-eap";
830 if (cred->auth_type & WPS_AUTH_WPA2)
831 auth_type[at_num++] = "wpa2-eap";
832 if (cred->auth_type & WPS_AUTH_WPA2PSK)
833 auth_type[at_num++] =
834 "wpa2-psk";
836 if (cred->encr_type & WPS_ENCR_NONE)
837 encr_type[et_num++] = "none";
838 if (cred->encr_type & WPS_ENCR_WEP)
839 encr_type[et_num++] = "wep";
840 if (cred->encr_type & WPS_ENCR_TKIP)
841 encr_type[et_num++] = "tkip";
842 if (cred->encr_type & WPS_ENCR_AES)
843 encr_type[et_num++] = "aes";
845 if (wpa_s->current_ssid) {
846 if (!wpa_dbus_dict_append_byte_array(
847 &dict_iter, "BSSID",
848 (const char *) wpa_s->current_ssid->bssid,
849 ETH_ALEN)) {
850 perror("wpas_dbus_signal_wps_cred[dbus]: out of "
851 "memory when appending bssid to dictionary");
852 goto nomem;
856 if (!(wpa_dbus_dict_append_byte_array(&dict_iter, "SSID",
857 (const char *) cred->ssid,
858 cred->ssid_len) &&
859 wpa_dbus_dict_append_string_array(&dict_iter, "AuthType",
860 (const char **) auth_type,
861 at_num) &&
862 wpa_dbus_dict_append_string_array(&dict_iter, "EncrType",
863 (const char **) encr_type,
864 et_num) &&
865 wpa_dbus_dict_append_byte_array(&dict_iter, "Key",
866 (const char *) cred->key,
867 cred->key_len) &&
868 wpa_dbus_dict_append_uint32(&dict_iter, "KeyIndex",
869 cred->key_idx))) {
870 perror("wpas_dbus_signal_wps_cred[dbus]: out of memory "
871 "when appending to dictionary");
872 goto nomem;
875 if (!wpa_dbus_dict_close_write(&iter, &dict_iter)) {
876 perror("wpas_dbus_signal_wps_cred[dbus]: out of memory "
877 "when closing a dictionary");
878 goto nomem;
881 dbus_connection_send(iface->con, _signal, NULL);
883 nomem:
884 dbus_message_unref(_signal);
887 #endif /* CONFIG_WPS */
891 * wpas_dbus_signal_prop_changed - Signals change of property
892 * @wpa_s: %wpa_supplicant network interface data
893 * @property: indicates which property has changed
895 * Sends ProertyChanged signals with path, interface and arguments
896 * depending on which property has changed.
898 void wpas_dbus_signal_prop_changed(struct wpa_supplicant *wpa_s,
899 enum wpas_dbus_prop property)
901 WPADBusPropertyAccessor getter;
902 char *iface;
903 char *prop;
904 void *arg;
906 switch (property) {
907 case WPAS_DBUS_PROP_AP_SCAN:
908 getter = (WPADBusPropertyAccessor) wpas_dbus_getter_ap_scan;
909 arg = wpa_s;
910 iface = WPAS_DBUS_NEW_IFACE_INTERFACE;
911 prop = "ApScan";
912 break;
913 case WPAS_DBUS_PROP_SCANNING:
914 getter = (WPADBusPropertyAccessor) wpas_dbus_getter_scanning;
915 arg = wpa_s;
916 iface = WPAS_DBUS_NEW_IFACE_INTERFACE;
917 prop = "Scanning";
918 break;
919 case WPAS_DBUS_PROP_CURRENT_BSS:
920 getter = (WPADBusPropertyAccessor)
921 wpas_dbus_getter_current_bss;
922 arg = wpa_s;
923 iface = WPAS_DBUS_NEW_IFACE_INTERFACE;
924 prop = "CurrentBSS";
925 break;
926 case WPAS_DBUS_PROP_CURRENT_NETWORK:
927 getter = (WPADBusPropertyAccessor)
928 wpas_dbus_getter_current_network;
929 arg = wpa_s;
930 iface = WPAS_DBUS_NEW_IFACE_INTERFACE;
931 prop = "CurrentNetwork";
932 break;
933 default:
934 wpa_printf(MSG_ERROR, "wpas_dbus_signal_prop_changed[dbus]: "
935 "Unknown Property enum value %d", property);
936 return;
939 wpa_dbus_signal_property_changed(wpa_s->global->dbus,
940 getter, arg,
941 wpas_dbus_get_path(wpa_s), iface,
942 prop);
947 * wpas_dbus_signal_debug_level_changed - Signals change of debug param
948 * @global: wpa_global structure
950 * Sends ProertyChanged signals informing that debug level has changed.
952 void wpas_dbus_signal_debug_level_changed(struct wpa_global *global)
954 wpa_dbus_signal_property_changed(global->dbus,
955 (WPADBusPropertyAccessor)
956 wpas_dbus_getter_debug_level,
957 global, WPAS_DBUS_NEW_PATH,
958 WPAS_DBUS_NEW_INTERFACE,
959 "DebugLevel");
964 * wpas_dbus_signal_debug_timestamp_changed - Signals change of debug param
965 * @global: wpa_global structure
967 * Sends ProertyChanged signals informing that debug timestamp has changed.
969 void wpas_dbus_signal_debug_timestamp_changed(struct wpa_global *global)
971 wpa_dbus_signal_property_changed(global->dbus,
972 (WPADBusPropertyAccessor)
973 wpas_dbus_getter_debug_timestamp,
974 global, WPAS_DBUS_NEW_PATH,
975 WPAS_DBUS_NEW_INTERFACE,
976 "DebugTimestamp");
981 * wpas_dbus_signal_debug_show_keys_changed - Signals change of debug param
982 * @global: wpa_global structure
984 * Sends ProertyChanged signals informing that debug show_keys has changed.
986 void wpas_dbus_signal_debug_show_keys_changed(struct wpa_global *global)
988 wpa_dbus_signal_property_changed(global->dbus,
989 (WPADBusPropertyAccessor)
990 wpas_dbus_getter_debug_show_keys,
991 global, WPAS_DBUS_NEW_PATH,
992 WPAS_DBUS_NEW_INTERFACE,
993 "DebugShowKeys");
997 struct wpas_dbus_method {
998 const char *name;
999 const char *iface;
1000 WPADBusMethodHandler handler;
1001 struct wpa_dbus_argument args[3];
1004 struct wpas_dbus_property {
1005 const char *name;
1006 const char *iface;
1007 const char *type;
1008 WPADBusPropertyAccessor getter;
1009 WPADBusPropertyAccessor setter;
1010 enum dbus_prop_access _access;
1013 struct wpas_dbus_signal {
1014 const char *name;
1015 const char *iface;
1016 struct wpa_dbus_argument args[3];
1020 static void wpas_dbus_register(struct wpa_dbus_object_desc *obj_desc,
1021 void *priv,
1022 WPADBusArgumentFreeFunction priv_free,
1023 const struct wpas_dbus_method *methods,
1024 const struct wpas_dbus_property *properties,
1025 const struct wpas_dbus_signal *signals)
1027 int i;
1029 obj_desc->user_data = priv;
1030 obj_desc->user_data_free_func = priv_free;
1032 for (i = 0; methods && methods[i].name; i++) {
1033 wpa_dbus_method_register(obj_desc, methods[i].iface,
1034 methods[i].name, methods[i].handler,
1035 methods[i].args);
1038 for (i = 0; properties && properties[i].name; i++) {
1039 wpa_dbus_property_register(obj_desc, properties[i].iface,
1040 properties[i].name,
1041 properties[i].type,
1042 properties[i].getter,
1043 properties[i].setter,
1044 properties[i]._access);
1047 for (i = 0; signals && signals[i].name; i++) {
1048 wpa_dbus_signal_register(obj_desc, signals[i].iface,
1049 signals[i].name, signals[i].args);
1054 static const struct wpas_dbus_method wpas_dbus_global_methods[] = {
1055 { "CreateInterface", WPAS_DBUS_NEW_INTERFACE,
1056 (WPADBusMethodHandler) &wpas_dbus_handler_create_interface,
1058 { "args", "a{sv}", ARG_IN },
1059 { "path", "o", ARG_OUT },
1060 END_ARGS
1063 { "RemoveInterface", WPAS_DBUS_NEW_INTERFACE,
1064 (WPADBusMethodHandler) &wpas_dbus_handler_remove_interface,
1066 { "path", "o", ARG_IN },
1067 END_ARGS
1070 { "GetInterface", WPAS_DBUS_NEW_INTERFACE,
1071 (WPADBusMethodHandler) &wpas_dbus_handler_get_interface,
1073 { "ifname", "s", ARG_IN },
1074 { "path", "o", ARG_OUT },
1075 END_ARGS
1078 { NULL, NULL, NULL, { END_ARGS } }
1081 static const struct wpas_dbus_property wpas_dbus_global_properties[] = {
1082 { "DebugLevel", WPAS_DBUS_NEW_INTERFACE, "y",
1083 (WPADBusPropertyAccessor) wpas_dbus_getter_debug_level,
1084 (WPADBusPropertyAccessor) wpas_dbus_setter_debug_level,
1087 { "DebugTimestamp", WPAS_DBUS_NEW_INTERFACE, "b",
1088 (WPADBusPropertyAccessor) wpas_dbus_getter_debug_timestamp,
1089 (WPADBusPropertyAccessor) wpas_dbus_setter_debug_timestamp,
1092 { "DebugShowKeys", WPAS_DBUS_NEW_INTERFACE, "b",
1093 (WPADBusPropertyAccessor) wpas_dbus_getter_debug_show_keys,
1094 (WPADBusPropertyAccessor) wpas_dbus_setter_debug_show_keys,
1097 { "Interfaces", WPAS_DBUS_NEW_INTERFACE, "ao",
1098 (WPADBusPropertyAccessor) &wpas_dbus_getter_interfaces,
1099 NULL,
1102 { "EapMethods", WPAS_DBUS_NEW_INTERFACE, "as",
1103 (WPADBusPropertyAccessor) wpas_dbus_getter_eap_methods,
1104 NULL,
1107 { NULL, NULL, NULL, NULL, NULL, 0 }
1110 static const struct wpas_dbus_signal wpas_dbus_global_signals[] = {
1111 { "InterfaceAdded", WPAS_DBUS_NEW_INTERFACE,
1113 { "path", "o", ARG_OUT },
1114 { "properties", "a{sv}", ARG_OUT },
1115 END_ARGS
1118 { "InterfaceRemoved", WPAS_DBUS_NEW_INTERFACE,
1120 { "path", "o", ARG_OUT },
1121 END_ARGS
1124 { "PropertiesChanged", WPAS_DBUS_NEW_INTERFACE,
1126 { "properties", "a{sv}", ARG_OUT },
1127 END_ARGS
1130 { NULL, NULL, { END_ARGS } }
1135 * wpas_dbus_ctrl_iface_init - Initialize dbus control interface
1136 * @global: Pointer to global data from wpa_supplicant_init()
1137 * Returns: 0 on success or -1 on failure
1139 * Initialize the dbus control interface for wpa_supplicantand and start
1140 * receiving commands from external programs over the bus.
1142 int wpas_dbus_ctrl_iface_init(struct wpas_dbus_priv *priv)
1144 struct wpa_dbus_object_desc *obj_desc;
1145 int ret;
1147 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
1148 if (!obj_desc) {
1149 wpa_printf(MSG_ERROR, "Not enough memory "
1150 "to create object description");
1151 return -1;
1154 wpas_dbus_register(obj_desc, priv->global, NULL,
1155 wpas_dbus_global_methods,
1156 wpas_dbus_global_properties,
1157 wpas_dbus_global_signals);
1159 wpa_printf(MSG_DEBUG, "dbus: Register D-Bus object '%s'",
1160 WPAS_DBUS_NEW_PATH);
1161 ret = wpa_dbus_ctrl_iface_init(priv, WPAS_DBUS_NEW_PATH,
1162 WPAS_DBUS_NEW_SERVICE,
1163 obj_desc);
1164 if (ret < 0)
1165 free_dbus_object_desc(obj_desc);
1166 else
1167 priv->dbus_new_initialized = 1;
1169 return ret;
1174 * wpas_dbus_ctrl_iface_deinit - Deinitialize dbus ctrl interface for
1175 * wpa_supplicant
1176 * @iface: Pointer to dbus private data from wpas_dbus_init()
1178 * Deinitialize the dbus control interface that was initialized with
1179 * wpas_dbus_ctrl_iface_init().
1181 void wpas_dbus_ctrl_iface_deinit(struct wpas_dbus_priv *iface)
1183 if (!iface->dbus_new_initialized)
1184 return;
1185 wpa_printf(MSG_DEBUG, "dbus: Unregister D-Bus object '%s'",
1186 WPAS_DBUS_NEW_PATH);
1187 dbus_connection_unregister_object_path(iface->con,
1188 WPAS_DBUS_NEW_PATH);
1192 static void wpa_dbus_free(void *ptr)
1194 os_free(ptr);
1198 static const struct wpas_dbus_property wpas_dbus_network_properties[] = {
1199 { "Properties", WPAS_DBUS_NEW_IFACE_NETWORK, "a{sv}",
1200 (WPADBusPropertyAccessor) wpas_dbus_getter_network_properties,
1201 (WPADBusPropertyAccessor) wpas_dbus_setter_network_properties,
1204 { "Enabled", WPAS_DBUS_NEW_IFACE_NETWORK, "b",
1205 (WPADBusPropertyAccessor) wpas_dbus_getter_enabled,
1206 (WPADBusPropertyAccessor) wpas_dbus_setter_enabled,
1209 { NULL, NULL, NULL, NULL, NULL, 0 }
1213 static const struct wpas_dbus_signal wpas_dbus_network_signals[] = {
1214 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_NETWORK,
1216 { "properties", "a{sv}", ARG_OUT },
1217 END_ARGS
1220 { NULL, NULL, { END_ARGS } }
1225 * wpas_dbus_register_network - Register a configured network with dbus
1226 * @wpa_s: wpa_supplicant interface structure
1227 * @ssid: network configuration data
1228 * Returns: 0 on success, -1 on failure
1230 * Registers network representing object with dbus
1232 int wpas_dbus_register_network(struct wpa_supplicant *wpa_s,
1233 struct wpa_ssid *ssid)
1235 struct wpas_dbus_priv *ctrl_iface;
1236 struct wpa_dbus_object_desc *obj_desc;
1238 struct network_handler_args *arg = NULL;
1240 char *net_obj_path;
1242 /* Do nothing if the control interface is not turned on */
1243 if (wpa_s == NULL || wpa_s->global == NULL)
1244 return 0;
1245 ctrl_iface = wpa_s->global->dbus;
1246 if (ctrl_iface == NULL)
1247 return 0;
1249 net_obj_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1250 if (net_obj_path == NULL)
1251 return -1;
1252 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1253 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
1254 wpas_dbus_get_path(wpa_s), ssid->id);
1256 wpa_printf(MSG_DEBUG, "dbus: Register network object '%s'",
1257 net_obj_path);
1258 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
1259 if (!obj_desc) {
1260 wpa_printf(MSG_ERROR, "Not enough memory "
1261 "to create object description");
1262 goto err;
1265 /* allocate memory for handlers arguments */
1266 arg = os_zalloc(sizeof(struct network_handler_args));
1267 if (!arg) {
1268 wpa_printf(MSG_ERROR, "Not enough memory "
1269 "to create arguments for method");
1270 goto err;
1273 arg->wpa_s = wpa_s;
1274 arg->ssid = ssid;
1276 wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
1277 wpas_dbus_network_properties,
1278 wpas_dbus_network_signals);
1280 if (wpa_dbus_register_object_per_iface(ctrl_iface, net_obj_path,
1281 wpa_s->ifname, obj_desc))
1282 goto err;
1284 wpas_dbus_signal_network_added(wpa_s, ssid->id);
1286 os_free(net_obj_path);
1287 return 0;
1289 err:
1290 os_free(net_obj_path);
1291 os_free(obj_desc);
1292 os_free(arg);
1293 return -1;
1298 * wpas_dbus_unregister_network - Unregister a configured network from dbus
1299 * @wpa_s: wpa_supplicant interface structure
1300 * @nid: network id
1301 * Returns: 0 on success, -1 on failure
1303 * Unregisters network representing object from dbus
1305 int wpas_dbus_unregister_network(struct wpa_supplicant *wpa_s, int nid)
1307 struct wpas_dbus_priv *ctrl_iface;
1308 char *net_obj_path;
1309 int ret;
1311 /* Do nothing if the control interface is not turned on */
1312 if (wpa_s == NULL || wpa_s->global == NULL)
1313 return 0;
1314 ctrl_iface = wpa_s->global->dbus;
1315 if (ctrl_iface == NULL)
1316 return 0;
1318 net_obj_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1319 if (net_obj_path == NULL)
1320 return -1;
1321 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1322 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
1323 wpas_dbus_get_path(wpa_s), nid);
1325 wpa_printf(MSG_DEBUG, "dbus: Unregister network object '%s'",
1326 net_obj_path);
1327 ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, net_obj_path);
1329 if (!ret)
1330 wpas_dbus_signal_network_removed(wpa_s, nid);
1332 os_free(net_obj_path);
1333 return ret;
1337 static const struct wpas_dbus_property wpas_dbus_bss_properties[] = {
1338 { "SSID", WPAS_DBUS_NEW_IFACE_BSSID, "ay",
1339 (WPADBusPropertyAccessor) wpas_dbus_getter_bss_ssid,
1340 NULL,
1343 { "BSSID", WPAS_DBUS_NEW_IFACE_BSSID, "ay",
1344 (WPADBusPropertyAccessor) wpas_dbus_getter_bss_bssid,
1345 NULL,
1348 { "Privacy", WPAS_DBUS_NEW_IFACE_BSSID, "b",
1349 (WPADBusPropertyAccessor) wpas_dbus_getter_bss_privacy,
1350 NULL,
1353 { "Mode", WPAS_DBUS_NEW_IFACE_BSSID, "s",
1354 (WPADBusPropertyAccessor) wpas_dbus_getter_bss_mode,
1355 NULL,
1358 { "Signal", WPAS_DBUS_NEW_IFACE_BSSID, "n",
1359 (WPADBusPropertyAccessor) wpas_dbus_getter_bss_signal,
1360 NULL,
1363 { "Frequency", WPAS_DBUS_NEW_IFACE_BSSID, "q",
1364 (WPADBusPropertyAccessor) wpas_dbus_getter_bss_frequency,
1365 NULL,
1368 { "MaxRate", WPAS_DBUS_NEW_IFACE_BSSID, "q",
1369 (WPADBusPropertyAccessor) wpas_dbus_getter_bss_max_rate,
1370 NULL,
1373 { "WPAIE", WPAS_DBUS_NEW_IFACE_BSSID, "ay",
1374 (WPADBusPropertyAccessor) wpas_dbus_getter_bss_wpaie,
1375 NULL,
1378 { "RSNIE", WPAS_DBUS_NEW_IFACE_BSSID, "ay",
1379 (WPADBusPropertyAccessor) wpas_dbus_getter_bss_rsnie,
1380 NULL,
1383 { "WPSIE", WPAS_DBUS_NEW_IFACE_BSSID, "ay",
1384 (WPADBusPropertyAccessor) wpas_dbus_getter_bss_wpsie,
1385 NULL,
1388 { NULL, NULL, NULL, NULL, NULL, 0 }
1392 static const struct wpas_dbus_signal wpas_dbus_bss_signals[] = {
1393 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_BSSID,
1395 { "properties", "a{sv}", ARG_OUT },
1396 END_ARGS
1399 { NULL, NULL, { END_ARGS } }
1404 * wpas_dbus_unregister_bss - Unregister a scanned BSS from dbus
1405 * @wpa_s: wpa_supplicant interface structure
1406 * @bssid: scanned network bssid
1407 * @id: unique BSS identifier
1408 * Returns: 0 on success, -1 on failure
1410 * Unregisters BSS representing object from dbus
1412 int wpas_dbus_unregister_bss(struct wpa_supplicant *wpa_s,
1413 u8 bssid[ETH_ALEN], unsigned int id)
1415 struct wpas_dbus_priv *ctrl_iface;
1416 char *bss_obj_path;
1418 /* Do nothing if the control interface is not turned on */
1419 if (wpa_s == NULL || wpa_s->global == NULL)
1420 return 0;
1421 ctrl_iface = wpa_s->global->dbus;
1422 if (ctrl_iface == NULL)
1423 return 0;
1425 bss_obj_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1426 if (bss_obj_path == NULL)
1427 return -1;
1429 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1430 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
1431 wpas_dbus_get_path(wpa_s), id);
1433 wpa_printf(MSG_DEBUG, "dbus: Unregister BSS object '%s'",
1434 bss_obj_path);
1435 if (wpa_dbus_unregister_object_per_iface(ctrl_iface, bss_obj_path)) {
1436 wpa_printf(MSG_ERROR,
1437 "Cannot unregister BSSID dbus object %s.",
1438 bss_obj_path);
1439 os_free(bss_obj_path);
1440 return -1;
1443 wpas_dbus_signal_bss_removed(wpa_s, bss_obj_path);
1445 os_free(bss_obj_path);
1446 return 0;
1451 * wpas_dbus_register_bss - Register a scanned BSS with dbus
1452 * @wpa_s: wpa_supplicant interface structure
1453 * @bssid: scanned network bssid
1454 * @id: unique BSS identifier
1455 * Returns: 0 on success, -1 on failure
1457 * Registers BSS representing object with dbus
1459 int wpas_dbus_register_bss(struct wpa_supplicant *wpa_s,
1460 u8 bssid[ETH_ALEN], unsigned int id)
1462 struct wpas_dbus_priv *ctrl_iface;
1463 struct wpa_dbus_object_desc *obj_desc;
1464 char *bss_obj_path;
1466 struct bss_handler_args *arg = NULL;
1468 /* Do nothing if the control interface is not turned on */
1469 if (wpa_s == NULL || wpa_s->global == NULL)
1470 return 0;
1471 ctrl_iface = wpa_s->global->dbus;
1472 if (ctrl_iface == NULL)
1473 return 0;
1475 bss_obj_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1476 if (bss_obj_path == NULL)
1477 return -1;
1479 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1480 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
1481 wpas_dbus_get_path(wpa_s), id);
1483 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
1484 if (!obj_desc) {
1485 wpa_printf(MSG_ERROR, "Not enough memory "
1486 "to create object description");
1487 goto err;
1490 arg = os_zalloc(sizeof(struct bss_handler_args));
1491 if (!arg) {
1492 wpa_printf(MSG_ERROR, "Not enough memory "
1493 "to create arguments for handler");
1494 goto err;
1496 arg->wpa_s = wpa_s;
1497 arg->id = id;
1499 wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
1500 wpas_dbus_bss_properties,
1501 wpas_dbus_bss_signals);
1503 wpa_printf(MSG_DEBUG, "dbus: Register BSS object '%s'",
1504 bss_obj_path);
1505 if (wpa_dbus_register_object_per_iface(ctrl_iface, bss_obj_path,
1506 wpa_s->ifname, obj_desc)) {
1507 wpa_printf(MSG_ERROR,
1508 "Cannot register BSSID dbus object %s.",
1509 bss_obj_path);
1510 goto err;
1513 wpas_dbus_signal_bss_added(wpa_s, bss_obj_path);
1515 os_free(bss_obj_path);
1516 return 0;
1518 err:
1519 os_free(bss_obj_path);
1520 os_free(obj_desc);
1521 os_free(arg);
1522 return -1;
1526 static const struct wpas_dbus_method wpas_dbus_interface_methods[] = {
1527 { "Scan", WPAS_DBUS_NEW_IFACE_INTERFACE,
1528 (WPADBusMethodHandler) &wpas_dbus_handler_scan,
1530 { "args", "a{sv}", ARG_IN },
1531 END_ARGS
1534 { "Disconnect", WPAS_DBUS_NEW_IFACE_INTERFACE,
1535 (WPADBusMethodHandler) &wpas_dbus_handler_disconnect,
1537 END_ARGS
1540 { "AddNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
1541 (WPADBusMethodHandler) &wpas_dbus_handler_add_network,
1543 { "args", "a{sv}", ARG_IN },
1544 { "path", "o", ARG_OUT },
1545 END_ARGS
1548 { "RemoveNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
1549 (WPADBusMethodHandler) &wpas_dbus_handler_remove_network,
1551 { "path", "o", ARG_IN },
1552 END_ARGS
1555 { "SelectNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
1556 (WPADBusMethodHandler) &wpas_dbus_handler_select_network,
1558 { "path", "o", ARG_IN },
1559 END_ARGS
1562 { "AddBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
1563 (WPADBusMethodHandler) &wpas_dbus_handler_add_blob,
1565 { "name", "s", ARG_IN },
1566 { "data", "ay", ARG_IN },
1567 END_ARGS
1570 { "GetBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
1571 (WPADBusMethodHandler) &wpas_dbus_handler_get_blob,
1573 { "name", "s", ARG_IN },
1574 { "data", "ay", ARG_OUT },
1575 END_ARGS
1578 { "RemoveBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
1579 (WPADBusMethodHandler) &wpas_dbus_handler_remove_blob,
1581 { "name", "s", ARG_IN },
1582 END_ARGS
1585 #ifdef CONFIG_WPS
1586 { "Start", WPAS_DBUS_NEW_IFACE_WPS,
1587 (WPADBusMethodHandler) &wpas_dbus_handler_wps_start,
1589 { "args", "a{sv}", ARG_IN },
1590 { "output", "a{sv}", ARG_OUT },
1591 END_ARGS
1594 #endif /* CONFIG_WPS */
1595 { NULL, NULL, NULL, { END_ARGS } }
1598 static const struct wpas_dbus_property wpas_dbus_interface_properties[] = {
1599 { "Capabilities", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{sv}",
1600 (WPADBusPropertyAccessor) wpas_dbus_getter_capabilities,
1601 NULL, R
1603 { "State", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
1604 (WPADBusPropertyAccessor) wpas_dbus_getter_state,
1605 NULL, R
1607 { "Scanning", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
1608 (WPADBusPropertyAccessor) wpas_dbus_getter_scanning,
1609 NULL, R
1611 { "ApScan", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
1612 (WPADBusPropertyAccessor) wpas_dbus_getter_ap_scan,
1613 (WPADBusPropertyAccessor) wpas_dbus_setter_ap_scan,
1616 { "Ifname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
1617 (WPADBusPropertyAccessor) wpas_dbus_getter_ifname,
1618 NULL, R
1620 { "Driver", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
1621 (WPADBusPropertyAccessor) wpas_dbus_getter_driver,
1622 NULL, R
1624 { "BridgeIfname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
1625 (WPADBusPropertyAccessor) wpas_dbus_getter_bridge_ifname,
1626 NULL, R
1628 { "CurrentBSS", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
1629 (WPADBusPropertyAccessor) wpas_dbus_getter_current_bss,
1630 NULL, R
1632 { "CurrentNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
1633 (WPADBusPropertyAccessor) wpas_dbus_getter_current_network,
1634 NULL, R
1636 { "Blobs", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{say}",
1637 (WPADBusPropertyAccessor) wpas_dbus_getter_blobs,
1638 NULL, R
1640 { "BSSs", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
1641 (WPADBusPropertyAccessor) wpas_dbus_getter_bsss,
1642 NULL, R
1644 { "Networks", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
1645 (WPADBusPropertyAccessor) wpas_dbus_getter_networks,
1646 NULL, R
1648 #ifdef CONFIG_WPS
1649 { "ProcessCredentials", WPAS_DBUS_NEW_IFACE_WPS, "b",
1650 (WPADBusPropertyAccessor) wpas_dbus_getter_process_credentials,
1651 (WPADBusPropertyAccessor) wpas_dbus_setter_process_credentials,
1654 #endif /* CONFIG_WPS */
1655 { NULL, NULL, NULL, NULL, NULL, 0 }
1658 static const struct wpas_dbus_signal wpas_dbus_interface_signals[] = {
1659 { "ScanDone", WPAS_DBUS_NEW_IFACE_INTERFACE,
1661 { "success", "b", ARG_OUT },
1662 END_ARGS
1665 { "StateChanged", WPAS_DBUS_NEW_IFACE_INTERFACE,
1667 { "newState", "s", ARG_OUT },
1668 { "oldState", "s", ARG_OUT },
1669 END_ARGS
1672 { "BSSAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
1674 { "path", "o", ARG_OUT },
1675 { "properties", "a{sv}", ARG_OUT },
1676 END_ARGS
1679 { "BSSRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
1681 { "path", "o", ARG_OUT },
1682 END_ARGS
1685 { "BlobAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
1687 { "name", "s", ARG_OUT },
1688 END_ARGS
1691 { "BlobRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
1693 { "name", "s", ARG_OUT },
1694 END_ARGS
1697 { "NetworkAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
1699 { "path", "o", ARG_OUT },
1700 { "properties", "a{sv}", ARG_OUT },
1701 END_ARGS
1704 { "NetworkRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
1706 { "path", "o", ARG_OUT },
1707 END_ARGS
1710 { "NetworkSelected", WPAS_DBUS_NEW_IFACE_INTERFACE,
1712 { "path", "o", ARG_OUT },
1713 END_ARGS
1716 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_INTERFACE,
1718 { "properties", "a{sv}", ARG_OUT },
1719 END_ARGS
1722 #ifdef CONFIG_WPS
1723 { "Event", WPAS_DBUS_NEW_IFACE_WPS,
1725 { "name", "s", ARG_OUT },
1726 { "args", "a{sv}", ARG_OUT },
1727 END_ARGS
1730 { "Credentials", WPAS_DBUS_NEW_IFACE_WPS,
1732 { "credentials", "a{sv}", ARG_OUT },
1733 END_ARGS
1736 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_WPS,
1738 { "properties", "a{sv}", ARG_OUT },
1739 END_ARGS
1742 #endif /* CONFIG_WPS */
1743 { NULL, NULL, { END_ARGS } }
1747 int wpas_dbus_register_interface(struct wpa_supplicant *wpa_s)
1750 struct wpa_dbus_object_desc *obj_desc = NULL;
1751 struct wpas_dbus_priv *ctrl_iface = wpa_s->global->dbus;
1752 int next;
1754 /* Do nothing if the control interface is not turned on */
1755 if (ctrl_iface == NULL)
1756 return 0;
1758 /* Create and set the interface's object path */
1759 wpa_s->dbus_new_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1760 if (wpa_s->dbus_new_path == NULL)
1761 return -1;
1762 next = ctrl_iface->next_objid++;
1763 os_snprintf(wpa_s->dbus_new_path, WPAS_DBUS_OBJECT_PATH_MAX,
1764 WPAS_DBUS_NEW_PATH_INTERFACES "/%u",
1765 next);
1767 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
1768 if (!obj_desc) {
1769 wpa_printf(MSG_ERROR, "Not enough memory "
1770 "to create object description");
1771 goto err;
1774 wpas_dbus_register(obj_desc, wpa_s, NULL, wpas_dbus_interface_methods,
1775 wpas_dbus_interface_properties,
1776 wpas_dbus_interface_signals);
1778 wpa_printf(MSG_DEBUG, "dbus: Register interface object '%s'",
1779 wpa_s->dbus_new_path);
1780 if (wpa_dbus_register_object_per_iface(ctrl_iface,
1781 wpa_s->dbus_new_path,
1782 wpa_s->ifname, obj_desc))
1783 goto err;
1785 wpas_dbus_signal_interface_added(wpa_s);
1787 return 0;
1789 err:
1790 os_free(wpa_s->dbus_new_path);
1791 wpa_s->dbus_new_path = NULL;
1792 os_free(obj_desc);
1793 return -1;
1797 int wpas_dbus_unregister_interface(struct wpa_supplicant *wpa_s)
1799 struct wpas_dbus_priv *ctrl_iface;
1801 /* Do nothing if the control interface is not turned on */
1802 if (wpa_s == NULL || wpa_s->global == NULL)
1803 return 0;
1804 ctrl_iface = wpa_s->global->dbus;
1805 if (ctrl_iface == NULL)
1806 return 0;
1808 wpa_printf(MSG_DEBUG, "dbus: Unregister interface object '%s'",
1809 wpas_dbus_get_path(wpa_s));
1810 if (wpa_dbus_unregister_object_per_iface(ctrl_iface,
1811 wpas_dbus_get_path(wpa_s)))
1812 return -1;
1814 wpas_dbus_signal_interface_removed(wpa_s);
1816 os_free(wpa_s->dbus_new_path);
1817 wpa_s->dbus_new_path = NULL;
1819 return 0;
1824 * wpas_dbus_get_path - Get an interface's dbus path
1825 * @wpa_s: %wpa_supplicant interface structure
1826 * Returns: Interface's dbus object path, or %NULL on error
1828 const char * wpas_dbus_get_path(struct wpa_supplicant *wpa_s)
1830 return wpa_s->dbus_new_path;