dbus: Do not deinitialize new D-Bus API if it is not initialized
[hostap-gosc2009.git] / wpa_supplicant / dbus / dbus_new.c
blob3817e6e26ace481b8627877e4a593a1a73ea6b91
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
55 * Notify listeners about event related with interface
57 static void wpas_dbus_signal_interface(struct wpa_supplicant *wpa_s,
58 const char *sig_name)
60 struct wpas_dbus_priv *iface;
61 DBusMessage *_signal;
62 const char *path;
64 iface = wpa_s->global->dbus;
66 /* Do nothing if the control interface is not turned on */
67 if (iface == NULL)
68 return;
70 path = wpas_dbus_get_path(wpa_s);
71 if (path == NULL) {
72 wpa_printf(MSG_ERROR, "wpas_dbus_signal_interface[dbus]: "
73 "Interface doesn't have a dbus path. "
74 "Can't send signal.");
75 return;
77 _signal = dbus_message_new_signal(WPAS_DBUS_NEW_PATH,
78 WPAS_DBUS_NEW_INTERFACE, sig_name);
79 if (_signal == NULL) {
80 wpa_printf(MSG_ERROR, "wpas_dbus_signal_interface[dbus]: "
81 "enough memory to send scan results signal.");
82 return;
85 if (dbus_message_append_args(_signal, DBUS_TYPE_OBJECT_PATH, &path,
86 DBUS_TYPE_INVALID)) {
87 dbus_connection_send(iface->con, _signal, NULL);
88 } else {
89 wpa_printf(MSG_ERROR, "wpas_dbus_signal_interface[dbus]: "
90 "not enough memory to construct signal.");
92 dbus_message_unref(_signal);
96 /**
97 * wpas_dbus_signal_interface_created - Send a interface created signal
98 * @wpa_s: %wpa_supplicant network interface data
100 * Notify listeners about creating new interface
102 static void wpas_dbus_signal_interface_created(struct wpa_supplicant *wpa_s)
104 wpas_dbus_signal_interface(wpa_s, "InterfaceCreated");
109 * wpas_dbus_signal_interface_removed - Send a interface removed signal
110 * @wpa_s: %wpa_supplicant network interface data
112 * Notify listeners about removing interface
114 static void wpas_dbus_signal_interface_removed(struct wpa_supplicant *wpa_s)
116 wpas_dbus_signal_interface(wpa_s, "InterfaceRemoved");
122 * wpas_dbus_signal_scan_done - send scan done signal
123 * @wpa_s: %wpa_supplicant network interface data
124 * @success: indicates if scanning succeed or failed
126 * Notify listeners about finishing a scan
128 static void wpas_dbus_signal_scan_done(struct wpa_supplicant *wpa_s,
129 int success)
131 struct wpas_dbus_priv *iface;
132 DBusMessage *_signal;
133 const char *path;
134 dbus_bool_t succ;
136 iface = wpa_s->global->dbus;
138 /* Do nothing if the control interface is not turned on */
139 if (iface == NULL)
140 return;
142 path = wpas_dbus_get_path(wpa_s);
143 if (path == NULL) {
144 wpa_printf(MSG_ERROR, "wpas_dbus_signal_scan_done[dbus]: "
145 "Interface doesn't have a dbus path. "
146 "Can't send signal.");
147 return;
149 _signal = dbus_message_new_signal(path, WPAS_DBUS_NEW_IFACE_INTERFACE,
150 "ScanDone");
151 if (_signal == NULL) {
152 wpa_printf(MSG_ERROR, "wpas_dbus_signal_scan_done[dbus]: "
153 "enough memory to send signal.");
154 return;
157 succ = success ? TRUE : FALSE;
158 if (dbus_message_append_args(_signal, DBUS_TYPE_BOOLEAN, &succ,
159 DBUS_TYPE_INVALID)) {
160 dbus_connection_send(iface->con, _signal, NULL);
161 } else {
162 wpa_printf(MSG_ERROR, "wpas_dbus_signal_scan_done[dbus]: "
163 "not enough memory to construct signal.");
165 dbus_message_unref(_signal);
170 * wpas_dbus_signal_blob - Send a BSS related event signal
171 * @wpa_s: %wpa_supplicant network interface data
172 * @bss_obj_path: BSS object path
173 * @sig_name: signal name - BSSAdded or BSSRemoved
175 * Notify listeners about event related with BSS
177 static void wpas_dbus_signal_bss(struct wpa_supplicant *wpa_s,
178 const char *bss_obj_path,
179 const char *sig_name)
181 struct wpas_dbus_priv *iface;
182 DBusMessage *_signal;
183 const char *path;
185 iface = wpa_s->global->dbus;
187 /* Do nothing if the control interface is not turned on */
188 if (iface == NULL)
189 return;
191 path = wpas_dbus_get_path(wpa_s);
192 if (path == NULL) {
193 wpa_printf(MSG_ERROR, "wpas_dbus_signal_bss[dbus]: "
194 "Interface doesn't have a dbus path. "
195 "Can't send signal.");
196 return;
198 _signal = dbus_message_new_signal(path, WPAS_DBUS_NEW_IFACE_INTERFACE,
199 sig_name);
200 if (_signal == NULL) {
201 wpa_printf(MSG_ERROR, "wpas_dbus_signal_bss[dbus]: "
202 "enough memory to send signal.");
203 return;
206 if (dbus_message_append_args(_signal, DBUS_TYPE_OBJECT_PATH,
207 &bss_obj_path, DBUS_TYPE_INVALID)) {
208 dbus_connection_send(iface->con, _signal, NULL);
209 } else {
210 wpa_printf(MSG_ERROR, "wpas_dbus_signal_bss[dbus]: "
211 "not enough memory to construct signal.");
213 dbus_message_unref(_signal);
218 * wpas_dbus_signal_bss_added - Send a BSS added signal
219 * @wpa_s: %wpa_supplicant network interface data
220 * @bss_obj_path: new BSS object path
222 * Notify listeners about adding new BSS
224 static void wpas_dbus_signal_bss_added(struct wpa_supplicant *wpa_s,
225 const char *bss_obj_path)
227 wpas_dbus_signal_bss(wpa_s, bss_obj_path, "BSSAdded");
232 * wpas_dbus_signal_bss_removed - Send a BSS removed signal
233 * @wpa_s: %wpa_supplicant network interface data
234 * @bss_obj_path: BSS object path
236 * Notify listeners about removing BSS
238 static void wpas_dbus_signal_bss_removed(struct wpa_supplicant *wpa_s,
239 const char *bss_obj_path)
241 wpas_dbus_signal_bss(wpa_s, bss_obj_path, "BSSRemoved");
246 * wpas_dbus_signal_blob - Send a blob related event signal
247 * @wpa_s: %wpa_supplicant network interface data
248 * @name: blob name
249 * @sig_name: signal name - BlobAdded or BlobRemoved
251 * Notify listeners about event related with blob
253 static void wpas_dbus_signal_blob(struct wpa_supplicant *wpa_s,
254 const char *name, const char *sig_name)
256 struct wpas_dbus_priv *iface;
257 DBusMessage *_signal;
258 const char *path;
260 iface = wpa_s->global->dbus;
262 /* Do nothing if the control interface is not turned on */
263 if (iface == NULL)
264 return;
266 path = wpas_dbus_get_path(wpa_s);
267 if (path == NULL) {
268 wpa_printf(MSG_ERROR, "wpas_dbus_signal_blob[dbus]: "
269 "Interface doesn't have a dbus path. "
270 "Can't send signal.");
271 return;
273 _signal = dbus_message_new_signal(path, WPAS_DBUS_NEW_IFACE_INTERFACE,
274 sig_name);
275 if (_signal == NULL) {
276 wpa_printf(MSG_ERROR, "wpas_dbus_signal_blob[dbus]: "
277 "enough memory to send signal.");
278 return;
281 if (dbus_message_append_args(_signal, DBUS_TYPE_STRING, &name,
282 DBUS_TYPE_INVALID)) {
283 dbus_connection_send(iface->con, _signal, NULL);
284 } else {
285 wpa_printf(MSG_ERROR, "wpas_dbus_signal_blob[dbus]: "
286 "not enough memory to construct signal.");
288 dbus_message_unref(_signal);
293 * wpas_dbus_signal_blob_added - Send a blob added signal
294 * @wpa_s: %wpa_supplicant network interface data
295 * @name: blob name
297 * Notify listeners about adding a new blob
299 static void wpas_dbus_signal_blob_added(struct wpa_supplicant *wpa_s,
300 const char *name)
302 wpas_dbus_signal_blob(wpa_s, name, "BlobAdded");
307 * wpas_dbus_signal_blob_removed - Send a blob removed signal
308 * @wpa_s: %wpa_supplicant network interface data
309 * @name: blob name
311 * Notify listeners about removing blob
313 static void wpas_dbus_signal_blob_removed(struct wpa_supplicant *wpa_s,
314 const char *name)
316 wpas_dbus_signal_blob(wpa_s, name, "BlobRemoved");
321 * wpas_dbus_signal_network - Send a network related event signal
322 * @wpa_s: %wpa_supplicant network interface data
323 * @id: new network id
324 * @sig_name: signal name - NetworkAdded, NetworkRemoved or NetworkSelected
326 * Notify listeners about event related with configured network
328 static void wpas_dbus_signal_network(struct wpa_supplicant *wpa_s,
329 int id, const char *sig_name)
331 struct wpas_dbus_priv *iface;
332 DBusMessage *_signal;
333 const char *path;
334 char *net_obj_path;
336 iface = wpa_s->global->dbus;
338 /* Do nothing if the control interface is not turned on */
339 if (iface == NULL)
340 return;
342 path = wpas_dbus_get_path(wpa_s);
343 if (path == NULL) {
344 wpa_printf(MSG_ERROR, "wpas_dbus_signal_network[dbus]: "
345 "Interface doesn't have a dbus path. "
346 "Can't send signal.");
347 return;
350 net_obj_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
351 if (net_obj_path == NULL)
352 return;
353 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
354 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u", path, id);
356 _signal = dbus_message_new_signal(path, WPAS_DBUS_NEW_IFACE_INTERFACE,
357 sig_name);
358 if (_signal == NULL) {
359 wpa_printf(MSG_ERROR, "wpas_dbus_signal_network[dbus]: "
360 "enough memory to send signal.");
361 os_free(net_obj_path);
362 return;
365 if (dbus_message_append_args(_signal, DBUS_TYPE_OBJECT_PATH,
366 &net_obj_path, DBUS_TYPE_INVALID)) {
367 dbus_connection_send(iface->con, _signal, NULL);
368 } else {
369 wpa_printf(MSG_ERROR, "wpas_dbus_signal_network[dbus]: "
370 "not enough memory to construct signal.");
373 os_free(net_obj_path);
374 dbus_message_unref(_signal);
379 * wpas_dbus_signal_network_added - Send a network added signal
380 * @wpa_s: %wpa_supplicant network interface data
381 * @id: new network id
383 * Notify listeners about adding new network
385 static void wpas_dbus_signal_network_added(struct wpa_supplicant *wpa_s,
386 int id)
388 wpas_dbus_signal_network(wpa_s, id, "NetworkAdded");
393 * wpas_dbus_signal_network_removed - Send a network removed signal
394 * @wpa_s: %wpa_supplicant network interface data
395 * @id: network id
397 * Notify listeners about removing a network
399 static void wpas_dbus_signal_network_removed(struct wpa_supplicant *wpa_s,
400 int id)
402 wpas_dbus_signal_network(wpa_s, id, "NetworkRemoved");
407 * wpas_dbus_signal_network_selected - Send a network selected signal
408 * @wpa_s: %wpa_supplicant network interface data
409 * @id: network id
411 * Notify listeners about selecting a network
413 static void wpas_dbus_signal_network_selected(struct wpa_supplicant *wpa_s,
414 int id)
416 wpas_dbus_signal_network(wpa_s, id, "NetworkSelected");
421 * wpas_dbus_signal_state_changed - Send a state changed signal
422 * @wpa_s: %wpa_supplicant network interface data
423 * @new_state: new state wpa_supplicant is entering
424 * @old_state: old state wpa_supplicant is leaving
426 * Notify listeners that wpa_supplicant has changed state
428 static void wpas_dbus_signal_state_changed(struct wpa_supplicant *wpa_s,
429 enum wpa_states new_state,
430 enum wpa_states old_state)
432 struct wpas_dbus_priv *iface;
433 DBusMessage *_signal = NULL;
434 const char *path;
435 char *new_state_str, *old_state_str;
436 char *tmp;
438 /* Do nothing if the control interface is not turned on */
439 if (wpa_s->global == NULL)
440 return;
441 iface = wpa_s->global->dbus;
442 if (iface == NULL)
443 return;
445 /* Only send signal if state really changed */
446 if (new_state == old_state)
447 return;
449 path = wpas_dbus_get_path(wpa_s);
450 if (path == NULL) {
451 perror("wpas_dbus_signal_state_changed[dbus]: "
452 "interface didn't have a dbus path");
453 wpa_printf(MSG_ERROR,
454 "wpas_dbus_signal_state_changed[dbus]: "
455 "interface didn't have a dbus path; can't send "
456 "signal.");
457 return;
459 _signal = dbus_message_new_signal(path, WPAS_DBUS_NEW_IFACE_INTERFACE,
460 "StateChanged");
461 if (_signal == NULL) {
462 perror("wpas_dbus_signal_state_changed[dbus]: "
463 "couldn't create dbus signal; likely out of memory");
464 wpa_printf(MSG_ERROR,
465 "wpas_dbus_signal_state_changed[dbus]: "
466 "couldn't create dbus signal; likely out of "
467 "memory.");
468 return;
471 new_state_str = os_strdup(wpa_supplicant_state_txt(new_state));
472 old_state_str = os_strdup(wpa_supplicant_state_txt(old_state));
473 if (new_state_str == NULL || old_state_str == NULL) {
474 perror("wpas_dbus_signal_state_changed[dbus]: "
475 "couldn't convert state strings");
476 wpa_printf(MSG_ERROR,
477 "wpas_dbus_signal_state_changed[dbus]: "
478 "couldn't convert state strings.");
479 goto out;
482 /* make state string lowercase to fit new DBus API convention */
483 tmp = new_state_str;
484 while (*tmp) {
485 *tmp = tolower(*tmp);
486 tmp++;
488 tmp = old_state_str;
489 while (*tmp) {
490 *tmp = tolower(*tmp);
491 tmp++;
494 if (!dbus_message_append_args(_signal,
495 DBUS_TYPE_STRING, &new_state_str,
496 DBUS_TYPE_STRING, &old_state_str,
497 DBUS_TYPE_INVALID)) {
498 perror("wpas_dbus_signal_state_changed[dbus]: "
499 "not enough memory to construct state change signal.");
500 wpa_printf(MSG_ERROR,
501 "wpas_dbus_signal_state_changed[dbus]: "
502 "not enough memory to construct state change "
503 "signal.");
504 goto out;
507 dbus_connection_send(iface->con, _signal, NULL);
509 out:
510 dbus_message_unref(_signal);
511 os_free(new_state_str);
512 os_free(old_state_str);
517 * wpas_dbus_signal_network_enabled_changed - Signals Enabled property changes
518 * @wpa_s: %wpa_supplicant network interface data
519 * @ssid: configured network which Enabled property has changed
521 * Sends PropertyChanged signals containing new value of Enabled property
522 * for specified network
524 static void wpas_dbus_signal_network_enabled_changed(
525 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
528 struct network_handler_args args = {wpa_s, ssid};
530 char path[WPAS_DBUS_OBJECT_PATH_MAX];
531 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
532 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
533 wpas_dbus_get_path(wpa_s), ssid->id);
535 wpa_dbus_signal_property_changed(wpa_s->global->dbus,
536 (WPADBusPropertyAccessor)
537 wpas_dbus_getter_enabled, &args,
538 path, WPAS_DBUS_NEW_IFACE_NETWORK,
539 "Enabled");
543 #ifdef CONFIG_WPS
546 * wpas_dbus_signal_wps_event_success - Signals Success WPS event
547 * @wpa_s: %wpa_supplicant network interface data
549 * Sends Event dbus signal with name "success" and empty dict as arguments
551 static void wpas_dbus_signal_wps_event_success(struct wpa_supplicant *wpa_s)
554 DBusMessage *_signal = NULL;
555 DBusMessageIter iter, dict_iter;
556 struct wpas_dbus_priv *iface;
557 char *key = "success";
558 const char *path;
560 iface = wpa_s->global->dbus;
562 /* Do nothing if the control interface is not turned on */
563 if (iface == NULL)
564 return;
566 path = wpas_dbus_get_path(wpa_s);
567 if (!path) {
568 wpa_printf(MSG_ERROR, "wpas_dbus_signal_wps_event_success"
569 "[dbus]: interface has no dbus path set");
570 return;
573 _signal = dbus_message_new_signal(path, WPAS_DBUS_NEW_IFACE_WPS,
574 "Event");
575 if (!_signal) {
576 wpa_printf(MSG_ERROR, "wpas_dbus_signal_wps_event_success"
577 "[dbus]: out of memory when creating a signal");
578 return;
581 dbus_message_iter_init_append(_signal, &iter);
583 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
584 !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
585 !wpa_dbus_dict_close_write(&iter, &dict_iter)) {
586 wpa_printf(MSG_ERROR, "wpas_dbus_signal_wps_event_success"
587 "[dbus]: out of memory");
588 goto out;
591 dbus_connection_send(iface->con, _signal, NULL);
592 out:
593 dbus_message_unref(_signal);
598 * wpas_dbus_signal_wps_event_fail - Signals Fail WPS event
599 * @wpa_s: %wpa_supplicant network interface data
601 * Sends Event dbus signal with name "fail" and dictionary containing
602 * "msg field with fail message number (int32) as arguments
604 static void wpas_dbus_signal_wps_event_fail(struct wpa_supplicant *wpa_s,
605 struct wps_event_fail *fail)
608 DBusMessage *_signal = NULL;
609 DBusMessageIter iter, dict_iter;
610 struct wpas_dbus_priv *iface;
611 char *key = "fail";
612 const char *path;
614 iface = wpa_s->global->dbus;
616 /* Do nothing if the control interface is not turned on */
617 if (iface == NULL)
618 return;
620 path = wpas_dbus_get_path(wpa_s);
621 if (!path) {
622 wpa_printf(MSG_ERROR, "wpas_dbus_signal_wps_event_fail[dbus]: "
623 "interface has no dbus path set");
624 return;
627 _signal = dbus_message_new_signal(path, WPAS_DBUS_NEW_IFACE_WPS,
628 "Event");
629 if (!_signal) {
630 wpa_printf(MSG_ERROR, "wpas_dbus_signal_wps_event_fail[dbus]: "
631 "out of memory when creating a signal");
632 return;
635 dbus_message_iter_init_append(_signal, &iter);
637 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
638 !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
639 !wpa_dbus_dict_append_int32(&dict_iter, "msg", fail->msg) ||
640 !wpa_dbus_dict_close_write(&iter, &dict_iter)) {
641 wpa_printf(MSG_ERROR, "wpas_dbus_signal_wps_event_fail[dbus]: "
642 "out of memory");
643 goto out;
646 dbus_connection_send(iface->con, _signal, NULL);
647 out:
648 dbus_message_unref(_signal);
653 * wpas_dbus_signal_wps_event_m2d - Signals M2D WPS event
654 * @wpa_s: %wpa_supplicant network interface data
656 * Sends Event dbus signal with name "m2d" and dictionary containing
657 * fields of wps_event_m2d structure.
659 static void wpas_dbus_signal_wps_event_m2d(struct wpa_supplicant *wpa_s,
660 struct wps_event_m2d *m2d)
663 DBusMessage *_signal = NULL;
664 DBusMessageIter iter, dict_iter;
665 struct wpas_dbus_priv *iface;
666 char *key = "m2d";
667 const char *path;
669 iface = wpa_s->global->dbus;
671 /* Do nothing if the control interface is not turned on */
672 if (iface == NULL)
673 return;
675 path = wpas_dbus_get_path(wpa_s);
676 if (!path) {
677 wpa_printf(MSG_ERROR, "wpas_dbus_signal_wps_event_m2d[dbus]: "
678 "interface has no dbus path set");
679 return;
682 _signal = dbus_message_new_signal(path, WPAS_DBUS_NEW_IFACE_WPS,
683 "Event");
684 if (!_signal) {
685 wpa_printf(MSG_ERROR, "wpas_dbus_signal_wps_event_m2d[dbus]: "
686 "out of memory when creating a signal");
687 return;
690 dbus_message_iter_init_append(_signal, &iter);
692 if (!(dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) &&
693 wpa_dbus_dict_open_write(&iter, &dict_iter) &&
694 wpa_dbus_dict_append_uint16(&dict_iter, "config_methods",
695 m2d->config_methods) &&
696 wpa_dbus_dict_append_byte_array(&dict_iter, "manufacturer",
697 (const char *) m2d->manufacturer,
698 m2d->manufacturer_len) &&
699 wpa_dbus_dict_append_byte_array(&dict_iter, "model_name",
700 (const char *) m2d->model_name,
701 m2d->model_name_len) &&
702 wpa_dbus_dict_append_byte_array(&dict_iter, "model_number",
703 (const char *) m2d->model_number,
704 m2d->model_number_len) &&
705 wpa_dbus_dict_append_byte_array(&dict_iter, "serial_number",
706 (const char *)
707 m2d->serial_number,
708 m2d->serial_number_len) &&
709 wpa_dbus_dict_append_byte_array(&dict_iter, "dev_name",
710 (const char *) m2d->dev_name,
711 m2d->dev_name_len) &&
712 wpa_dbus_dict_append_byte_array(&dict_iter, "primary_dev_type",
713 (const char *)
714 m2d->primary_dev_type, 8) &&
715 wpa_dbus_dict_append_uint16(&dict_iter, "config_error",
716 m2d->config_error) &&
717 wpa_dbus_dict_append_uint16(&dict_iter, "dev_password_id",
718 m2d->dev_password_id) &&
719 wpa_dbus_dict_close_write(&iter, &dict_iter))) {
720 wpa_printf(MSG_ERROR, "wpas_dbus_signal_wps_event_m2d[dbus]: "
721 "out of memory");
722 goto out;
725 dbus_connection_send(iface->con, _signal, NULL);
726 out:
727 dbus_message_unref(_signal);
732 * wpas_dbus_signal_wps_cred - Signals new credentials
733 * @wpa_s: %wpa_supplicant network interface data
735 * Sends signal with credentials in directory argument
737 static void wpas_dbus_signal_wps_cred(struct wpa_supplicant *wpa_s,
738 const struct wps_credential *cred)
740 DBusMessage *_signal = NULL;
741 DBusMessageIter iter, dict_iter;
742 struct wpas_dbus_priv *iface;
743 const char *path;
744 char *auth_type[6]; /* we have six possible authorization types */
745 int at_num = 0;
746 char *encr_type[4]; /* we have four possible encryption types */
747 int et_num = 0;
749 iface = wpa_s->global->dbus;
751 /* Do nothing if the control interface is not turned on */
752 if (iface == NULL)
753 return;
755 path = wpas_dbus_get_path(wpa_s);
756 if (!path) {
757 wpa_printf(MSG_ERROR, "wpas_dbus_signal_wps_cred[dbus]: "
758 "interface has no dbus path set");
759 return;
762 _signal = dbus_message_new_signal(path, WPAS_DBUS_NEW_IFACE_WPS,
763 "Credentials");
764 if (!_signal) {
765 wpa_printf(MSG_ERROR, "wpas_dbus_signal_wps_cred[dbus]: "
766 "out of memory when creating a signal");
767 return;
770 dbus_message_iter_init_append(_signal, &iter);
772 if (!wpa_dbus_dict_open_write(&iter, &dict_iter)) {
773 perror("wpas_dbus_signal_wps_cred[dbus]: out of memory "
774 "when opening a dictionary");
775 goto nomem;
778 if (cred->auth_type & WPS_AUTH_OPEN)
779 auth_type[at_num++] = "open";
780 if (cred->auth_type & WPS_AUTH_WPAPSK)
781 auth_type[at_num++] = "wpa-psk";
782 if (cred->auth_type & WPS_AUTH_SHARED)
783 auth_type[at_num++] = "shared";
784 if (cred->auth_type & WPS_AUTH_WPA)
785 auth_type[at_num++] = "wpa-eap";
786 if (cred->auth_type & WPS_AUTH_WPA2)
787 auth_type[at_num++] = "wpa2-eap";
788 if (cred->auth_type & WPS_AUTH_WPA2PSK)
789 auth_type[at_num++] =
790 "wpa2-psk";
792 if (cred->encr_type & WPS_ENCR_NONE)
793 encr_type[et_num++] = "none";
794 if (cred->encr_type & WPS_ENCR_WEP)
795 encr_type[et_num++] = "wep";
796 if (cred->encr_type & WPS_ENCR_TKIP)
797 encr_type[et_num++] = "tkip";
798 if (cred->encr_type & WPS_ENCR_AES)
799 encr_type[et_num++] = "aes";
801 if (wpa_s->current_ssid) {
802 if (!wpa_dbus_dict_append_byte_array(
803 &dict_iter, "BSSID",
804 (const char *) wpa_s->current_ssid->bssid,
805 ETH_ALEN)) {
806 perror("wpas_dbus_signal_wps_cred[dbus]: out of "
807 "memory when appending bssid to dictionary");
808 goto nomem;
812 if (!(wpa_dbus_dict_append_byte_array(&dict_iter, "SSID",
813 (const char *) cred->ssid,
814 cred->ssid_len) &&
815 wpa_dbus_dict_append_string_array(&dict_iter, "AuthType",
816 (const char **) auth_type,
817 at_num) &&
818 wpa_dbus_dict_append_string_array(&dict_iter, "EncrType",
819 (const char **) encr_type,
820 et_num) &&
821 wpa_dbus_dict_append_byte_array(&dict_iter, "Key",
822 (const char *) cred->key,
823 cred->key_len) &&
824 wpa_dbus_dict_append_uint32(&dict_iter, "KeyIndex",
825 cred->key_idx))) {
826 perror("wpas_dbus_signal_wps_cred[dbus]: out of memory "
827 "when appending to dictionary");
828 goto nomem;
831 if (!wpa_dbus_dict_close_write(&iter, &dict_iter)) {
832 perror("wpas_dbus_signal_wps_cred[dbus]: out of memory "
833 "when closing a dictionary");
834 goto nomem;
837 dbus_connection_send(iface->con, _signal, NULL);
839 nomem:
840 dbus_message_unref(_signal);
843 #endif /* CONFIG_WPS */
847 * wpas_dbus_signal_prop_changed - Signals change of property
848 * @wpa_s: %wpa_supplicant network interface data
849 * @property: indicates which property has changed
851 * Sends ProertyChanged signals with path, interface and arguments
852 * depending on which property has changed.
854 static void wpas_dbus_signal_prop_changed(struct wpa_supplicant *wpa_s,
855 enum wpas_dbus_prop property)
857 WPADBusPropertyAccessor getter;
858 char *iface;
859 char *prop;
860 void *arg;
862 switch (property) {
863 case WPAS_DBUS_PROP_AP_SCAN:
864 getter = (WPADBusPropertyAccessor) wpas_dbus_getter_ap_scan;
865 arg = wpa_s;
866 iface = WPAS_DBUS_NEW_IFACE_INTERFACE;
867 prop = "ApScan";
868 break;
869 case WPAS_DBUS_PROP_SCANNING:
870 getter = (WPADBusPropertyAccessor) wpas_dbus_getter_scanning;
871 arg = wpa_s;
872 iface = WPAS_DBUS_NEW_IFACE_INTERFACE;
873 prop = "Scanning";
874 break;
875 case WPAS_DBUS_PROP_CURRENT_BSS:
876 getter = (WPADBusPropertyAccessor)
877 wpas_dbus_getter_current_bss;
878 arg = wpa_s;
879 iface = WPAS_DBUS_NEW_IFACE_INTERFACE;
880 prop = "CurrentBSS";
881 break;
882 case WPAS_DBUS_PROP_CURRENT_NETWORK:
883 getter = (WPADBusPropertyAccessor)
884 wpas_dbus_getter_current_network;
885 arg = wpa_s;
886 iface = WPAS_DBUS_NEW_IFACE_INTERFACE;
887 prop = "CurrentNetwork";
888 break;
889 default:
890 wpa_printf(MSG_ERROR, "wpas_dbus_signal_prop_changed[dbus]: "
891 "Unknown Property enum value %d", property);
892 return;
895 wpa_dbus_signal_property_changed(wpa_s->global->dbus,
896 getter, arg,
897 wpas_dbus_get_path(wpa_s), iface,
898 prop);
903 * wpas_dbus_signal_debug_params_changed - Signals change of debug params
904 * @global: wpa_global structure
906 * Sends ProertyChanged signals informing that debug params has changed.
908 static void wpas_dbus_signal_debug_params_changed(struct wpa_global *global)
911 wpa_dbus_signal_property_changed(global->dbus,
912 (WPADBusPropertyAccessor)
913 wpas_dbus_getter_debug_params,
914 global, WPAS_DBUS_NEW_PATH,
915 WPAS_DBUS_NEW_INTERFACE,
916 "DebugParams");
920 struct wpas_dbus_method {
921 const char *name;
922 const char *iface;
923 WPADBusMethodHandler handler;
924 struct wpa_dbus_argument args[3];
927 struct wpas_dbus_property {
928 const char *name;
929 const char *iface;
930 const char *type;
931 WPADBusPropertyAccessor getter;
932 WPADBusPropertyAccessor setter;
933 enum dbus_prop_access _access;
936 struct wpas_dbus_signal {
937 const char *name;
938 const char *iface;
939 struct wpa_dbus_argument args[3];
943 static void wpas_dbus_register(struct wpa_dbus_object_desc *obj_desc,
944 void *priv,
945 const struct wpas_dbus_method *methods,
946 const struct wpas_dbus_property *properties,
947 const struct wpas_dbus_signal *signals)
949 int i;
951 for (i = 0; methods && methods[i].name; i++) {
952 wpa_dbus_method_register(obj_desc, methods[i].iface,
953 methods[i].name, methods[i].handler,
954 priv, NULL, methods[i].args);
957 for (i = 0; properties && properties[i].name; i++) {
958 wpa_dbus_property_register(obj_desc, properties[i].iface,
959 properties[i].name,
960 properties[i].type,
961 properties[i].getter,
962 properties[i].setter,
963 priv, NULL, properties[i]._access);
966 for (i = 0; signals && signals[i].name; i++) {
967 wpa_dbus_signal_register(obj_desc, signals[i].iface,
968 signals[i].name, signals[i].args);
973 static const struct wpas_dbus_method wpas_dbus_global_methods[] = {
974 { "CreateInterface", WPAS_DBUS_NEW_INTERFACE,
975 (WPADBusMethodHandler) &wpas_dbus_handler_create_interface,
977 { "args", "a{sv}", ARG_IN },
978 { "path", "o", ARG_OUT },
979 END_ARGS
982 { "RemoveInterface", WPAS_DBUS_NEW_INTERFACE,
983 (WPADBusMethodHandler) &wpas_dbus_handler_remove_interface,
985 { "path", "o", ARG_IN },
986 END_ARGS
989 { "GetInterface", WPAS_DBUS_NEW_INTERFACE,
990 (WPADBusMethodHandler) &wpas_dbus_handler_get_interface,
992 { "ifname", "s", ARG_IN },
993 { "path", "o", ARG_OUT },
994 END_ARGS
997 { NULL, NULL, NULL, { END_ARGS } }
1000 static const struct wpas_dbus_property wpas_dbus_global_properties[] = {
1001 { "DebugParams", WPAS_DBUS_NEW_INTERFACE, "(ibb)",
1002 (WPADBusPropertyAccessor) &wpas_dbus_getter_debug_params,
1003 (WPADBusPropertyAccessor) &wpas_dbus_setter_debug_params,
1006 { "Interfaces", WPAS_DBUS_NEW_INTERFACE, "ao",
1007 (WPADBusPropertyAccessor) &wpas_dbus_getter_interfaces,
1008 NULL,
1011 { "EapMethods", WPAS_DBUS_NEW_INTERFACE, "as",
1012 wpas_dbus_getter_eap_methods,
1013 NULL,
1016 { NULL, NULL, NULL, NULL, NULL, 0 }
1019 static const struct wpas_dbus_signal wpas_dbus_global_signals[] = {
1020 { "InterfaceAdded", WPAS_DBUS_NEW_INTERFACE,
1022 { "path", "o", ARG_OUT },
1023 END_ARGS
1026 { "InterfaceRemoved", WPAS_DBUS_NEW_INTERFACE,
1028 { "path", "o", ARG_OUT },
1029 END_ARGS
1032 { "PropertiesChanged", WPAS_DBUS_NEW_INTERFACE,
1034 { "properties", "a{sv}", ARG_OUT },
1035 END_ARGS
1038 { NULL, NULL, { END_ARGS } }
1043 * wpas_dbus_ctrl_iface_init - Initialize dbus control interface
1044 * @global: Pointer to global data from wpa_supplicant_init()
1045 * Returns: 0 on success or -1 on failure
1047 * Initialize the dbus control interface for wpa_supplicantand and start
1048 * receiving commands from external programs over the bus.
1050 int wpas_dbus_ctrl_iface_init(struct wpas_dbus_priv *priv)
1052 struct wpa_dbus_object_desc *obj_desc;
1053 int ret;
1055 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
1056 if (!obj_desc) {
1057 wpa_printf(MSG_ERROR, "Not enough memory "
1058 "to create object description");
1059 return -1;
1062 wpas_dbus_register(obj_desc, priv->global, wpas_dbus_global_methods,
1063 wpas_dbus_global_properties,
1064 wpas_dbus_global_signals);
1066 wpa_printf(MSG_DEBUG, "dbus: Register D-Bus object '%s'",
1067 WPAS_DBUS_NEW_PATH);
1068 ret = wpa_dbus_ctrl_iface_init(priv, WPAS_DBUS_NEW_PATH,
1069 WPAS_DBUS_NEW_SERVICE,
1070 obj_desc);
1071 if (ret < 0)
1072 free_dbus_object_desc(obj_desc);
1073 else
1074 priv->dbus_new_initialized = 1;
1076 return ret;
1081 * wpas_dbus_ctrl_iface_deinit - Deinitialize dbus ctrl interface for
1082 * wpa_supplicant
1083 * @iface: Pointer to dbus private data from wpas_dbus_init()
1085 * Deinitialize the dbus control interface that was initialized with
1086 * wpas_dbus_ctrl_iface_init().
1088 void wpas_dbus_ctrl_iface_deinit(struct wpas_dbus_priv *iface)
1090 if (!iface->dbus_new_initialized)
1091 return;
1092 wpa_printf(MSG_DEBUG, "dbus: Unregister D-Bus object '%s'",
1093 WPAS_DBUS_NEW_PATH);
1094 dbus_connection_unregister_object_path(iface->con,
1095 WPAS_DBUS_NEW_PATH);
1099 static void wpa_dbus_free(void *ptr)
1101 os_free(ptr);
1106 * wpas_dbus_register_network - Register a configured network with dbus
1107 * @wpa_s: wpa_supplicant interface structure
1108 * @ssid: network configuration data
1109 * Returns: 0 on success, -1 on failure
1111 * Registers network representing object with dbus
1113 static int wpas_dbus_register_network(struct wpa_supplicant *wpa_s,
1114 struct wpa_ssid *ssid)
1116 struct wpas_dbus_priv *ctrl_iface;
1117 struct wpa_dbus_object_desc *obj_desc;
1119 struct network_handler_args *arg1 = NULL;
1120 struct network_handler_args *arg2 = NULL;
1122 char *net_obj_path;
1124 struct wpa_dbus_argument sargs[] = {
1125 { "properties", "a{sv}", ARG_OUT },
1126 END_ARGS
1129 /* Do nothing if the control interface is not turned on */
1130 if (wpa_s == NULL || wpa_s->global == NULL)
1131 return 0;
1132 ctrl_iface = wpa_s->global->dbus;
1133 if (ctrl_iface == NULL)
1134 return 0;
1136 net_obj_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1137 if (net_obj_path == NULL)
1138 return -1;
1139 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1140 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
1141 wpas_dbus_get_path(wpa_s), ssid->id);
1143 wpa_printf(MSG_DEBUG, "dbus: Register network object '%s'",
1144 net_obj_path);
1145 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
1146 if (!obj_desc) {
1147 wpa_printf(MSG_ERROR, "Not enough memory "
1148 "to create object description");
1149 goto err;
1152 /* allocate memory for handlers arguments */
1153 arg1 = os_zalloc(sizeof(struct network_handler_args));
1154 if (!arg1) {
1155 wpa_printf(MSG_ERROR, "Not enough memory "
1156 "to create arguments for method");
1157 goto err;
1159 arg2 = os_zalloc(sizeof(struct network_handler_args));
1160 if (!arg2) {
1161 wpa_printf(MSG_ERROR, "Not enough memory "
1162 "to create arguments for method");
1163 goto err;
1166 arg1->wpa_s = wpa_s;
1167 arg1->ssid = ssid;
1168 arg2->wpa_s = wpa_s;
1169 arg2->ssid = ssid;
1171 /* Enabled property */
1172 wpa_dbus_property_register(obj_desc, WPAS_DBUS_NEW_IFACE_NETWORK,
1173 "Enabled", "b",
1174 (WPADBusPropertyAccessor)
1175 wpas_dbus_getter_enabled,
1176 (WPADBusPropertyAccessor)
1177 wpas_dbus_setter_enabled,
1178 arg1, wpa_dbus_free, RW);
1180 /* Properties property */
1181 wpa_dbus_property_register(obj_desc, WPAS_DBUS_NEW_IFACE_NETWORK,
1182 "Properties", "a{sv}",
1183 (WPADBusPropertyAccessor)
1184 wpas_dbus_getter_network_properties,
1185 (WPADBusPropertyAccessor)
1186 wpas_dbus_setter_network_properties,
1187 arg2, wpa_dbus_free, RW);
1189 /* PropertiesChanged signal */
1190 wpa_dbus_signal_register(obj_desc, WPAS_DBUS_NEW_IFACE_NETWORK,
1191 "PropertiesChanged", sargs);
1193 if (wpa_dbus_register_object_per_iface(ctrl_iface, net_obj_path,
1194 wpa_s->ifname, obj_desc))
1195 goto err;
1197 wpas_dbus_signal_network_added(wpa_s, ssid->id);
1199 os_free(net_obj_path);
1200 return 0;
1202 err:
1203 os_free(net_obj_path);
1204 os_free(obj_desc);
1205 os_free(arg1);
1206 os_free(arg2);
1207 return -1;
1212 * wpas_dbus_unregister_network - Unregister a configured network from dbus
1213 * @wpa_s: wpa_supplicant interface structure
1214 * @nid: network id
1215 * Returns: 0 on success, -1 on failure
1217 * Unregisters network representing object from dbus
1219 static int wpas_dbus_unregister_network(struct wpa_supplicant *wpa_s, int nid)
1221 struct wpas_dbus_priv *ctrl_iface;
1222 char *net_obj_path;
1223 int ret;
1225 /* Do nothing if the control interface is not turned on */
1226 if (wpa_s == NULL || wpa_s->global == NULL)
1227 return 0;
1228 ctrl_iface = wpa_s->global->dbus;
1229 if (ctrl_iface == NULL)
1230 return 0;
1232 net_obj_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1233 if (net_obj_path == NULL)
1234 return -1;
1235 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1236 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
1237 wpas_dbus_get_path(wpa_s), nid);
1239 wpa_printf(MSG_DEBUG, "dbus: Unregister network object '%s'",
1240 net_obj_path);
1241 ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, net_obj_path);
1243 if (!ret)
1244 wpas_dbus_signal_network_removed(wpa_s, nid);
1246 os_free(net_obj_path);
1247 return ret;
1252 * wpas_dbus_unregister_bss - Unregister a scanned BSS from dbus
1253 * @wpa_s: wpa_supplicant interface structure
1254 * @bssid: scanned network bssid
1255 * @id: unique BSS identifier
1256 * Returns: 0 on success, -1 on failure
1258 * Unregisters BSS representing object from dbus
1260 static int wpas_dbus_unregister_bss(struct wpa_supplicant *wpa_s,
1261 u8 bssid[ETH_ALEN], unsigned int id)
1263 struct wpas_dbus_priv *ctrl_iface;
1264 char *bss_obj_path;
1266 /* Do nothing if the control interface is not turned on */
1267 if (wpa_s == NULL || wpa_s->global == NULL)
1268 return 0;
1269 ctrl_iface = wpa_s->global->dbus;
1270 if (ctrl_iface == NULL)
1271 return 0;
1273 bss_obj_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1274 if (bss_obj_path == NULL)
1275 return -1;
1277 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1278 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
1279 wpas_dbus_get_path(wpa_s), id);
1281 wpa_printf(MSG_DEBUG, "dbus: Unregister BSS object '%s'",
1282 bss_obj_path);
1283 if (wpa_dbus_unregister_object_per_iface(ctrl_iface, bss_obj_path)) {
1284 wpa_printf(MSG_ERROR,
1285 "Cannot unregister BSSID dbus object %s.",
1286 bss_obj_path);
1287 os_free(bss_obj_path);
1288 return -1;
1291 wpas_dbus_signal_bss_removed(wpa_s, bss_obj_path);
1293 os_free(bss_obj_path);
1294 return 0;
1299 * wpas_dbus_register_bss - Register a scanned BSS with dbus
1300 * @wpa_s: wpa_supplicant interface structure
1301 * @bssid: scanned network bssid
1302 * @id: unique BSS identifier
1303 * Returns: 0 on success, -1 on failure
1305 * Registers BSS representing object with dbus
1307 static int wpas_dbus_register_bss(struct wpa_supplicant *wpa_s,
1308 u8 bssid[ETH_ALEN], unsigned int id)
1310 struct wpas_dbus_priv *ctrl_iface;
1311 struct wpa_dbus_object_desc *obj_desc;
1312 char *bss_obj_path;
1314 struct bss_handler_args *arg = NULL;
1316 /* Do nothing if the control interface is not turned on */
1317 if (wpa_s == NULL || wpa_s->global == NULL)
1318 return 0;
1319 ctrl_iface = wpa_s->global->dbus;
1320 if (ctrl_iface == NULL)
1321 return 0;
1323 bss_obj_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1324 if (bss_obj_path == NULL)
1325 return -1;
1327 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1328 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
1329 wpas_dbus_get_path(wpa_s), id);
1331 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
1332 if (!obj_desc) {
1333 wpa_printf(MSG_ERROR, "Not enough memory "
1334 "to create object description");
1335 goto err;
1338 arg = os_zalloc(sizeof(struct bss_handler_args));
1339 if (!arg) {
1340 wpa_printf(MSG_ERROR, "Not enough memory "
1341 "to create arguments for handler");
1342 goto err;
1344 arg->wpa_s = wpa_s;
1345 arg->id = id;
1347 /* Properties property */
1348 wpa_dbus_property_register(obj_desc, WPAS_DBUS_NEW_IFACE_BSSID,
1349 "Properties", "a{sv}",
1350 (WPADBusPropertyAccessor)
1351 wpas_dbus_getter_bss_properties, NULL,
1352 arg, wpa_dbus_free, R);
1354 wpa_printf(MSG_DEBUG, "dbus: Register BSS object '%s'",
1355 bss_obj_path);
1356 if (wpa_dbus_register_object_per_iface(ctrl_iface, bss_obj_path,
1357 wpa_s->ifname, obj_desc)) {
1358 wpa_printf(MSG_ERROR,
1359 "Cannot register BSSID dbus object %s.",
1360 bss_obj_path);
1361 goto err;
1364 wpas_dbus_signal_bss_added(wpa_s, bss_obj_path);
1366 os_free(bss_obj_path);
1367 return 0;
1369 err:
1370 os_free(bss_obj_path);
1371 os_free(obj_desc);
1372 os_free(arg);
1373 return -1;
1377 static const struct wpas_dbus_method wpas_dbus_interface_methods[] = {
1378 { "Scan", WPAS_DBUS_NEW_IFACE_INTERFACE,
1379 (WPADBusMethodHandler) &wpas_dbus_handler_scan,
1381 { "args", "a{sv}", ARG_IN },
1382 END_ARGS
1385 { "Disconnect", WPAS_DBUS_NEW_IFACE_INTERFACE,
1386 (WPADBusMethodHandler) &wpas_dbus_handler_disconnect,
1388 END_ARGS
1391 { "AddNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
1392 (WPADBusMethodHandler) &wpas_dbus_handler_add_network,
1394 { "args", "a{sv}", ARG_IN },
1395 { "path", "o", ARG_OUT },
1396 END_ARGS
1399 { "RemoveNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
1400 (WPADBusMethodHandler) &wpas_dbus_handler_remove_network,
1402 { "path", "o", ARG_IN },
1403 END_ARGS
1406 { "SelectNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
1407 (WPADBusMethodHandler) &wpas_dbus_handler_select_network,
1409 { "path", "o", ARG_IN },
1410 END_ARGS
1413 { "AddBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
1414 (WPADBusMethodHandler) &wpas_dbus_handler_add_blob,
1416 { "name", "s", ARG_IN },
1417 { "data", "ay", ARG_IN },
1418 END_ARGS
1421 { "GetBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
1422 (WPADBusMethodHandler) &wpas_dbus_handler_get_blob,
1424 { "name", "s", ARG_IN },
1425 { "data", "ay", ARG_OUT },
1426 END_ARGS
1429 { "RemoveBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
1430 (WPADBusMethodHandler) &wpas_dbus_handler_remove_blob,
1432 { "name", "s", ARG_IN },
1433 END_ARGS
1436 #ifdef CONFIG_WPS
1437 { "Start", WPAS_DBUS_NEW_IFACE_WPS,
1438 (WPADBusMethodHandler) &wpas_dbus_handler_wps_start,
1440 { "args", "a{sv}", ARG_IN },
1441 { "output", "a{sv}", ARG_OUT },
1442 END_ARGS
1445 #endif /* CONFIG_WPS */
1446 { NULL, NULL, NULL, { END_ARGS } }
1449 static const struct wpas_dbus_property wpas_dbus_interface_properties[] = {
1450 { "Capabilities", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{sv}",
1451 (WPADBusPropertyAccessor) wpas_dbus_getter_capabilities,
1452 NULL, R
1454 { "State", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
1455 (WPADBusPropertyAccessor) wpas_dbus_getter_state,
1456 NULL, R
1458 { "Scanning", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
1459 (WPADBusPropertyAccessor) wpas_dbus_getter_scanning,
1460 NULL, R
1462 { "ApScan", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
1463 (WPADBusPropertyAccessor) wpas_dbus_getter_ap_scan,
1464 (WPADBusPropertyAccessor) wpas_dbus_setter_ap_scan,
1467 { "Ifname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
1468 (WPADBusPropertyAccessor) wpas_dbus_getter_ifname,
1469 NULL, R
1471 { "Driver", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
1472 (WPADBusPropertyAccessor) wpas_dbus_getter_driver,
1473 NULL, R
1475 { "BridgeIfname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
1476 (WPADBusPropertyAccessor) wpas_dbus_getter_bridge_ifname,
1477 NULL, R
1479 { "CurrentBSS", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
1480 (WPADBusPropertyAccessor) wpas_dbus_getter_current_bss,
1481 NULL, R
1483 { "CurrentNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
1484 (WPADBusPropertyAccessor) wpas_dbus_getter_current_network,
1485 NULL, R
1487 { "Blobs", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{say}",
1488 (WPADBusPropertyAccessor) wpas_dbus_getter_blobs,
1489 NULL, R
1491 { "BSSs", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
1492 (WPADBusPropertyAccessor) wpas_dbus_getter_bsss,
1493 NULL, R
1495 { "Networks", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
1496 (WPADBusPropertyAccessor) wpas_dbus_getter_networks,
1497 NULL, R
1499 #ifdef CONFIG_WPS
1500 { "ProcessCredentials", WPAS_DBUS_NEW_IFACE_WPS, "b",
1501 (WPADBusPropertyAccessor) wpas_dbus_getter_process_credentials,
1502 (WPADBusPropertyAccessor) wpas_dbus_setter_process_credentials,
1505 #endif /* CONFIG_WPS */
1506 { NULL, NULL, NULL, NULL, NULL, 0 }
1509 static const struct wpas_dbus_signal wpas_dbus_interface_signals[] = {
1510 { "ScanDone", WPAS_DBUS_NEW_IFACE_INTERFACE,
1512 { "success", "b", ARG_OUT },
1513 END_ARGS
1516 { "StateChanged", WPAS_DBUS_NEW_IFACE_INTERFACE,
1518 { "newState", "s", ARG_OUT },
1519 { "oldState", "s", ARG_OUT },
1520 END_ARGS
1523 { "BSSAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
1525 { "path", "o", ARG_OUT },
1526 END_ARGS
1529 { "BSSRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
1531 { "path", "o", ARG_OUT },
1532 END_ARGS
1535 { "BlobAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
1537 { "name", "s", ARG_OUT },
1538 END_ARGS
1541 { "BlobRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
1543 { "name", "s", ARG_OUT },
1544 END_ARGS
1547 { "NetworkAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
1549 { "path", "o", ARG_OUT },
1550 END_ARGS
1553 { "NetworkRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
1555 { "path", "o", ARG_OUT },
1556 END_ARGS
1559 { "NetworkSelected", WPAS_DBUS_NEW_IFACE_INTERFACE,
1561 { "path", "o", ARG_OUT },
1562 END_ARGS
1565 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_INTERFACE,
1567 { "properties", "a{sv}", ARG_OUT },
1568 END_ARGS
1571 #ifdef CONFIG_WPS
1572 { "Event", WPAS_DBUS_NEW_IFACE_WPS,
1574 { "name", "s", ARG_OUT },
1575 { "args", "a{sv}", ARG_OUT },
1576 END_ARGS
1579 { "Credentials", WPAS_DBUS_NEW_IFACE_WPS,
1581 { "credentials", "a{sv}", ARG_OUT },
1582 END_ARGS
1585 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_WPS,
1587 { "properties", "a{sv}", ARG_OUT },
1588 END_ARGS
1591 #endif /* CONFIG_WPS */
1592 { NULL, NULL, { END_ARGS } }
1596 static int wpas_dbus_register_interface(struct wpa_supplicant *wpa_s)
1599 struct wpa_dbus_object_desc *obj_desc = NULL;
1600 char *path;
1601 struct wpas_dbus_priv *ctrl_iface = wpa_s->global->dbus;
1602 int next;
1604 /* Do nothing if the control interface is not turned on */
1605 if (ctrl_iface == NULL)
1606 return 0;
1608 /* Create and set the interface's object path */
1609 path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1610 if (path == NULL)
1611 return -1;
1612 next = ctrl_iface->next_objid++;
1613 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
1614 WPAS_DBUS_NEW_PATH_INTERFACES "/%u",
1615 next);
1616 if (wpas_dbus_set_path(wpa_s, path)) {
1617 wpa_printf(MSG_DEBUG,
1618 "Failed to set dbus path for interface %s",
1619 wpa_s->ifname);
1620 goto err;
1623 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
1624 if (!obj_desc) {
1625 wpa_printf(MSG_ERROR, "Not enough memory "
1626 "to create object description");
1627 goto err;
1630 wpas_dbus_register(obj_desc, wpa_s, wpas_dbus_interface_methods,
1631 wpas_dbus_interface_properties,
1632 wpas_dbus_interface_signals);
1634 wpa_printf(MSG_DEBUG, "dbus: Register interface object '%s'", path);
1635 if (wpa_dbus_register_object_per_iface(ctrl_iface, path, wpa_s->ifname,
1636 obj_desc))
1637 goto err;
1639 wpas_dbus_signal_interface_created(wpa_s);
1641 os_free(path);
1642 return 0;
1644 err:
1645 os_free(obj_desc);
1646 os_free(path);
1647 return -1;
1651 static int wpas_dbus_unregister_interface(struct wpa_supplicant *wpa_s)
1653 struct wpas_dbus_priv *ctrl_iface;
1655 /* Do nothing if the control interface is not turned on */
1656 if (wpa_s == NULL || wpa_s->global == NULL)
1657 return 0;
1658 ctrl_iface = wpa_s->global->dbus;
1659 if (ctrl_iface == NULL)
1660 return 0;
1662 wpa_printf(MSG_DEBUG, "dbus: Unregister interface object '%s'",
1663 wpas_dbus_get_path(wpa_s));
1664 if (wpa_dbus_unregister_object_per_iface(ctrl_iface,
1665 wpas_dbus_get_path(wpa_s)))
1666 return -1;
1668 wpas_dbus_signal_interface_removed(wpa_s);
1670 os_free(wpa_s->dbus_new_path);
1671 wpa_s->dbus_new_path = NULL;
1673 return 0;
1677 static struct wpas_dbus_callbacks callbacks =
1679 .signal_interface_created = wpas_dbus_signal_interface_created,
1680 .signal_interface_removed = wpas_dbus_signal_interface_removed,
1682 .register_interface = wpas_dbus_register_interface,
1683 .unregister_interface = wpas_dbus_unregister_interface,
1685 .signal_scan_done = wpas_dbus_signal_scan_done,
1687 .signal_blob_added = wpas_dbus_signal_blob_added,
1688 .signal_blob_removed = wpas_dbus_signal_blob_removed,
1690 .signal_network_selected = wpas_dbus_signal_network_selected,
1692 .signal_state_changed = wpas_dbus_signal_state_changed,
1693 .register_network = wpas_dbus_register_network,
1694 .unregister_network = wpas_dbus_unregister_network,
1696 .signal_network_enabled_changed =
1697 wpas_dbus_signal_network_enabled_changed,
1699 .register_bss = wpas_dbus_register_bss,
1700 .unregister_bss = wpas_dbus_unregister_bss,
1702 .signal_prop_changed = wpas_dbus_signal_prop_changed,
1703 .signal_debug_params_changed = wpas_dbus_signal_debug_params_changed,
1705 #ifdef CONFIG_WPS
1706 .signal_wps_event_success = wpas_dbus_signal_wps_event_success,
1707 .signal_wps_event_fail = wpas_dbus_signal_wps_event_fail,
1708 .signal_wps_event_m2d = wpas_dbus_signal_wps_event_m2d,
1709 .signal_wps_credentials = wpas_dbus_signal_wps_cred,
1710 #endif /* CONFIG_WPS */
1714 struct wpas_dbus_callbacks * wpas_dbus_get_callbacks(void)
1716 return &callbacks;
1721 * wpas_dbus_get_path - Get an interface's dbus path
1722 * @wpa_s: %wpa_supplicant interface structure
1723 * Returns: Interface's dbus object path, or %NULL on error
1725 const char * wpas_dbus_get_path(struct wpa_supplicant *wpa_s)
1727 return wpa_s->dbus_new_path;