]> git.ipfire.org Git - thirdparty/hostap.git/blob - wpa_supplicant/dbus/dbus_new.c
dbus: Rename InterfaceCreated to InterfaceAdded
[thirdparty/hostap.git] / wpa_supplicant / dbus / dbus_new.c
1 /*
2 * WPA Supplicant / dbus-based control interface
3 * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
4 * Copyright (c) 2009, Witold Sowa <witold.sowa@gmail.com>
5 * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 * Alternatively, this software may be distributed under the terms of BSD
12 * license.
13 *
14 * See README and COPYING for more details.
15 */
16
17 #include "includes.h"
18
19 #include "common.h"
20 #include "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"
30
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
36 */
37 static int wpas_dbus_set_path(struct wpa_supplicant *wpa_s,
38 const char *path)
39 {
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;
47 }
48
49
50 /**
51 * wpas_dbus_signal_interface - Send a interface related event signal
52 * @wpa_s: %wpa_supplicant network interface data
53 * @sig_name: signal name - InterfaceAdded or InterfaceRemoved
54 * @properties: determines if add second argument with object properties
55 *
56 * Notify listeners about event related with interface
57 */
58 static void wpas_dbus_signal_interface(struct wpa_supplicant *wpa_s,
59 const char *sig_name, int properties)
60 {
61 struct wpas_dbus_priv *iface;
62 DBusMessage *_signal;
63 DBusMessageIter iter, iter_dict;
64 const char *path;
65
66 iface = wpa_s->global->dbus;
67
68 /* Do nothing if the control interface is not turned on */
69 if (iface == NULL)
70 return;
71
72 path = wpas_dbus_get_path(wpa_s);
73 if (path == NULL) {
74 wpa_printf(MSG_ERROR, "wpas_dbus_signal_interface[dbus]: "
75 "Interface doesn't have a dbus path. "
76 "Can't send signal.");
77 return;
78 }
79 _signal = dbus_message_new_signal(WPAS_DBUS_NEW_PATH,
80 WPAS_DBUS_NEW_INTERFACE, sig_name);
81 if (_signal == NULL) {
82 wpa_printf(MSG_ERROR, "wpas_dbus_signal_interface[dbus]: "
83 "enough memory to send scan results signal.");
84 return;
85 }
86
87 dbus_message_iter_init_append(_signal, &iter);
88
89 if(!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
90 &path))
91 goto err;
92
93 if (properties) {
94 if (!wpa_dbus_dict_open_write(&iter, &iter_dict))
95 goto err;
96
97 wpa_dbus_get_object_properties(iface, path,
98 WPAS_DBUS_NEW_IFACE_INTERFACE,
99 &iter_dict);
100
101 if (!wpa_dbus_dict_close_write(&iter, &iter_dict))
102 goto err;
103 }
104
105 dbus_connection_send(iface->con, _signal, NULL);
106
107 dbus_message_unref(_signal);
108 return;
109
110 err:
111 wpa_printf(MSG_ERROR, "wpas_dbus_signal_interface[dbus]: "
112 "not enough memory to construct signal.");
113 dbus_message_unref(_signal);
114 }
115
116
117 /**
118 * wpas_dbus_signal_interface_added - Send a interface created signal
119 * @wpa_s: %wpa_supplicant network interface data
120 *
121 * Notify listeners about creating new interface
122 */
123 static void wpas_dbus_signal_interface_added(struct wpa_supplicant *wpa_s)
124 {
125 wpas_dbus_signal_interface(wpa_s, "InterfaceAdded", TRUE);
126 }
127
128
129 /**
130 * wpas_dbus_signal_interface_removed - Send a interface removed signal
131 * @wpa_s: %wpa_supplicant network interface data
132 *
133 * Notify listeners about removing interface
134 */
135 static void wpas_dbus_signal_interface_removed(struct wpa_supplicant *wpa_s)
136 {
137 wpas_dbus_signal_interface(wpa_s, "InterfaceRemoved", FALSE);
138
139 }
140
141
142 /**
143 * wpas_dbus_signal_scan_done - send scan done signal
144 * @wpa_s: %wpa_supplicant network interface data
145 * @success: indicates if scanning succeed or failed
146 *
147 * Notify listeners about finishing a scan
148 */
149 static void wpas_dbus_signal_scan_done(struct wpa_supplicant *wpa_s,
150 int success)
151 {
152 struct wpas_dbus_priv *iface;
153 DBusMessage *_signal;
154 const char *path;
155 dbus_bool_t succ;
156
157 iface = wpa_s->global->dbus;
158
159 /* Do nothing if the control interface is not turned on */
160 if (iface == NULL)
161 return;
162
163 path = wpas_dbus_get_path(wpa_s);
164 if (path == NULL) {
165 wpa_printf(MSG_ERROR, "wpas_dbus_signal_scan_done[dbus]: "
166 "Interface doesn't have a dbus path. "
167 "Can't send signal.");
168 return;
169 }
170 _signal = dbus_message_new_signal(path, WPAS_DBUS_NEW_IFACE_INTERFACE,
171 "ScanDone");
172 if (_signal == NULL) {
173 wpa_printf(MSG_ERROR, "wpas_dbus_signal_scan_done[dbus]: "
174 "enough memory to send signal.");
175 return;
176 }
177
178 succ = success ? TRUE : FALSE;
179 if (dbus_message_append_args(_signal, DBUS_TYPE_BOOLEAN, &succ,
180 DBUS_TYPE_INVALID)) {
181 dbus_connection_send(iface->con, _signal, NULL);
182 } else {
183 wpa_printf(MSG_ERROR, "wpas_dbus_signal_scan_done[dbus]: "
184 "not enough memory to construct signal.");
185 }
186 dbus_message_unref(_signal);
187 }
188
189
190 /**
191 * wpas_dbus_signal_blob - Send a BSS related event signal
192 * @wpa_s: %wpa_supplicant network interface data
193 * @bss_obj_path: BSS object path
194 * @sig_name: signal name - BSSAdded or BSSRemoved
195 * @properties: determines if add second argument with object properties
196 *
197 * Notify listeners about event related with BSS
198 */
199 static void wpas_dbus_signal_bss(struct wpa_supplicant *wpa_s,
200 const char *bss_obj_path,
201 const char *sig_name, int properties)
202 {
203 struct wpas_dbus_priv *iface;
204 DBusMessage *_signal;
205 DBusMessageIter iter, iter_dict;
206 const char *path;
207
208 iface = wpa_s->global->dbus;
209
210 /* Do nothing if the control interface is not turned on */
211 if (iface == NULL)
212 return;
213
214 path = wpas_dbus_get_path(wpa_s);
215 if (path == NULL) {
216 wpa_printf(MSG_ERROR, "wpas_dbus_signal_bss[dbus]: "
217 "Interface doesn't have a dbus path. "
218 "Can't send signal.");
219 return;
220 }
221 _signal = dbus_message_new_signal(path, WPAS_DBUS_NEW_IFACE_INTERFACE,
222 sig_name);
223 if (_signal == NULL) {
224 wpa_printf(MSG_ERROR, "wpas_dbus_signal_bss[dbus]: "
225 "enough memory to send signal.");
226 return;
227 }
228
229 dbus_message_iter_init_append(_signal, &iter);
230
231 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
232 &bss_obj_path))
233 goto err;
234
235 if (properties) {
236 if (!wpa_dbus_dict_open_write(&iter, &iter_dict))
237 goto err;
238
239 wpa_dbus_get_object_properties(iface, bss_obj_path,
240 WPAS_DBUS_NEW_IFACE_BSSID,
241 &iter_dict);
242
243 if (!wpa_dbus_dict_close_write(&iter, &iter_dict))
244 goto err;
245 }
246
247 dbus_connection_send(iface->con, _signal, NULL);
248
249 dbus_message_unref(_signal);
250 return;
251
252 err:
253 wpa_printf(MSG_ERROR, "wpas_dbus_signal_bss[dbus]: "
254 "not enough memory to construct signal.");
255 dbus_message_unref(_signal);
256 }
257
258
259 /**
260 * wpas_dbus_signal_bss_added - Send a BSS added signal
261 * @wpa_s: %wpa_supplicant network interface data
262 * @bss_obj_path: new BSS object path
263 *
264 * Notify listeners about adding new BSS
265 */
266 static void wpas_dbus_signal_bss_added(struct wpa_supplicant *wpa_s,
267 const char *bss_obj_path)
268 {
269 wpas_dbus_signal_bss(wpa_s, bss_obj_path, "BSSAdded", TRUE);
270 }
271
272
273 /**
274 * wpas_dbus_signal_bss_removed - Send a BSS removed signal
275 * @wpa_s: %wpa_supplicant network interface data
276 * @bss_obj_path: BSS object path
277 *
278 * Notify listeners about removing BSS
279 */
280 static void wpas_dbus_signal_bss_removed(struct wpa_supplicant *wpa_s,
281 const char *bss_obj_path)
282 {
283 wpas_dbus_signal_bss(wpa_s, bss_obj_path, "BSSRemoved", FALSE);
284 }
285
286
287 /**
288 * wpas_dbus_signal_blob - Send a blob related event signal
289 * @wpa_s: %wpa_supplicant network interface data
290 * @name: blob name
291 * @sig_name: signal name - BlobAdded or BlobRemoved
292 *
293 * Notify listeners about event related with blob
294 */
295 static void wpas_dbus_signal_blob(struct wpa_supplicant *wpa_s,
296 const char *name, const char *sig_name)
297 {
298 struct wpas_dbus_priv *iface;
299 DBusMessage *_signal;
300 const char *path;
301
302 iface = wpa_s->global->dbus;
303
304 /* Do nothing if the control interface is not turned on */
305 if (iface == NULL)
306 return;
307
308 path = wpas_dbus_get_path(wpa_s);
309 if (path == NULL) {
310 wpa_printf(MSG_ERROR, "wpas_dbus_signal_blob[dbus]: "
311 "Interface doesn't have a dbus path. "
312 "Can't send signal.");
313 return;
314 }
315 _signal = dbus_message_new_signal(path, WPAS_DBUS_NEW_IFACE_INTERFACE,
316 sig_name);
317 if (_signal == NULL) {
318 wpa_printf(MSG_ERROR, "wpas_dbus_signal_blob[dbus]: "
319 "enough memory to send signal.");
320 return;
321 }
322
323 if (dbus_message_append_args(_signal, DBUS_TYPE_STRING, &name,
324 DBUS_TYPE_INVALID)) {
325 dbus_connection_send(iface->con, _signal, NULL);
326 } else {
327 wpa_printf(MSG_ERROR, "wpas_dbus_signal_blob[dbus]: "
328 "not enough memory to construct signal.");
329 }
330 dbus_message_unref(_signal);
331 }
332
333
334 /**
335 * wpas_dbus_signal_blob_added - Send a blob added signal
336 * @wpa_s: %wpa_supplicant network interface data
337 * @name: blob name
338 *
339 * Notify listeners about adding a new blob
340 */
341 static void wpas_dbus_signal_blob_added(struct wpa_supplicant *wpa_s,
342 const char *name)
343 {
344 wpas_dbus_signal_blob(wpa_s, name, "BlobAdded");
345 }
346
347
348 /**
349 * wpas_dbus_signal_blob_removed - Send a blob removed signal
350 * @wpa_s: %wpa_supplicant network interface data
351 * @name: blob name
352 *
353 * Notify listeners about removing blob
354 */
355 static void wpas_dbus_signal_blob_removed(struct wpa_supplicant *wpa_s,
356 const char *name)
357 {
358 wpas_dbus_signal_blob(wpa_s, name, "BlobRemoved");
359 }
360
361
362 /**
363 * wpas_dbus_signal_network - Send a network related event signal
364 * @wpa_s: %wpa_supplicant network interface data
365 * @id: new network id
366 * @sig_name: signal name - NetworkAdded, NetworkRemoved or NetworkSelected
367 * @properties: determines if add second argument with object properties
368 *
369 * Notify listeners about event related with configured network
370 */
371 static void wpas_dbus_signal_network(struct wpa_supplicant *wpa_s,
372 int id, const char *sig_name,
373 int properties)
374 {
375 struct wpas_dbus_priv *iface;
376 DBusMessage *_signal;
377 DBusMessageIter iter, iter_dict;
378 const char *path;
379 char *net_obj_path;
380
381 iface = wpa_s->global->dbus;
382
383 /* Do nothing if the control interface is not turned on */
384 if (iface == NULL)
385 return;
386
387 path = wpas_dbus_get_path(wpa_s);
388 if (path == NULL) {
389 wpa_printf(MSG_ERROR, "wpas_dbus_signal_network[dbus]: "
390 "Interface doesn't have a dbus path. "
391 "Can't send signal.");
392 return;
393 }
394
395 net_obj_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
396 if (net_obj_path == NULL)
397 return;
398 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
399 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u", path, id);
400
401 _signal = dbus_message_new_signal(path, WPAS_DBUS_NEW_IFACE_INTERFACE,
402 sig_name);
403 if (_signal == NULL) {
404 wpa_printf(MSG_ERROR, "wpas_dbus_signal_network[dbus]: "
405 "enough memory to send signal.");
406 os_free(net_obj_path);
407 return;
408 }
409
410 dbus_message_iter_init_append(_signal, &iter);
411
412 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
413 &net_obj_path))
414 goto err;
415
416 if (properties) {
417 if (!wpa_dbus_dict_open_write(&iter, &iter_dict))
418 goto err;
419
420 wpa_dbus_get_object_properties(iface, net_obj_path,
421 WPAS_DBUS_NEW_IFACE_NETWORK,
422 &iter_dict);
423
424 if (!wpa_dbus_dict_close_write(&iter, &iter_dict))
425 goto err;
426 }
427
428 dbus_connection_send(iface->con, _signal, NULL);
429
430 os_free(net_obj_path);
431 dbus_message_unref(_signal);
432 return;
433
434 err:
435 wpa_printf(MSG_ERROR, "wpas_dbus_signal_network[dbus]: "
436 "not enough memory to construct signal.");
437 os_free(net_obj_path);
438 dbus_message_unref(_signal);
439 }
440
441
442 /**
443 * wpas_dbus_signal_network_added - Send a network added signal
444 * @wpa_s: %wpa_supplicant network interface data
445 * @id: new network id
446 *
447 * Notify listeners about adding new network
448 */
449 static void wpas_dbus_signal_network_added(struct wpa_supplicant *wpa_s,
450 int id)
451 {
452 wpas_dbus_signal_network(wpa_s, id, "NetworkAdded", TRUE);
453 }
454
455
456 /**
457 * wpas_dbus_signal_network_removed - Send a network removed signal
458 * @wpa_s: %wpa_supplicant network interface data
459 * @id: network id
460 *
461 * Notify listeners about removing a network
462 */
463 static void wpas_dbus_signal_network_removed(struct wpa_supplicant *wpa_s,
464 int id)
465 {
466 wpas_dbus_signal_network(wpa_s, id, "NetworkRemoved", FALSE);
467 }
468
469
470 /**
471 * wpas_dbus_signal_network_selected - Send a network selected signal
472 * @wpa_s: %wpa_supplicant network interface data
473 * @id: network id
474 *
475 * Notify listeners about selecting a network
476 */
477 static void wpas_dbus_signal_network_selected(struct wpa_supplicant *wpa_s,
478 int id)
479 {
480 wpas_dbus_signal_network(wpa_s, id, "NetworkSelected", FALSE);
481 }
482
483
484 /**
485 * wpas_dbus_signal_state_changed - Send a state changed signal
486 * @wpa_s: %wpa_supplicant network interface data
487 * @new_state: new state wpa_supplicant is entering
488 * @old_state: old state wpa_supplicant is leaving
489 *
490 * Notify listeners that wpa_supplicant has changed state
491 */
492 static void wpas_dbus_signal_state_changed(struct wpa_supplicant *wpa_s,
493 enum wpa_states new_state,
494 enum wpa_states old_state)
495 {
496 struct wpas_dbus_priv *iface;
497 DBusMessage *_signal = NULL;
498 const char *path;
499 char *new_state_str, *old_state_str;
500 char *tmp;
501
502 /* Do nothing if the control interface is not turned on */
503 if (wpa_s->global == NULL)
504 return;
505 iface = wpa_s->global->dbus;
506 if (iface == NULL)
507 return;
508
509 /* Only send signal if state really changed */
510 if (new_state == old_state)
511 return;
512
513 path = wpas_dbus_get_path(wpa_s);
514 if (path == NULL) {
515 perror("wpas_dbus_signal_state_changed[dbus]: "
516 "interface didn't have a dbus path");
517 wpa_printf(MSG_ERROR,
518 "wpas_dbus_signal_state_changed[dbus]: "
519 "interface didn't have a dbus path; can't send "
520 "signal.");
521 return;
522 }
523 _signal = dbus_message_new_signal(path, WPAS_DBUS_NEW_IFACE_INTERFACE,
524 "StateChanged");
525 if (_signal == NULL) {
526 perror("wpas_dbus_signal_state_changed[dbus]: "
527 "couldn't create dbus signal; likely out of memory");
528 wpa_printf(MSG_ERROR,
529 "wpas_dbus_signal_state_changed[dbus]: "
530 "couldn't create dbus signal; likely out of "
531 "memory.");
532 return;
533 }
534
535 new_state_str = os_strdup(wpa_supplicant_state_txt(new_state));
536 old_state_str = os_strdup(wpa_supplicant_state_txt(old_state));
537 if (new_state_str == NULL || old_state_str == NULL) {
538 perror("wpas_dbus_signal_state_changed[dbus]: "
539 "couldn't convert state strings");
540 wpa_printf(MSG_ERROR,
541 "wpas_dbus_signal_state_changed[dbus]: "
542 "couldn't convert state strings.");
543 goto out;
544 }
545
546 /* make state string lowercase to fit new DBus API convention */
547 tmp = new_state_str;
548 while (*tmp) {
549 *tmp = tolower(*tmp);
550 tmp++;
551 }
552 tmp = old_state_str;
553 while (*tmp) {
554 *tmp = tolower(*tmp);
555 tmp++;
556 }
557
558 if (!dbus_message_append_args(_signal,
559 DBUS_TYPE_STRING, &new_state_str,
560 DBUS_TYPE_STRING, &old_state_str,
561 DBUS_TYPE_INVALID)) {
562 perror("wpas_dbus_signal_state_changed[dbus]: "
563 "not enough memory to construct state change signal.");
564 wpa_printf(MSG_ERROR,
565 "wpas_dbus_signal_state_changed[dbus]: "
566 "not enough memory to construct state change "
567 "signal.");
568 goto out;
569 }
570
571 dbus_connection_send(iface->con, _signal, NULL);
572
573 out:
574 dbus_message_unref(_signal);
575 os_free(new_state_str);
576 os_free(old_state_str);
577 }
578
579
580 /**
581 * wpas_dbus_signal_network_enabled_changed - Signals Enabled property changes
582 * @wpa_s: %wpa_supplicant network interface data
583 * @ssid: configured network which Enabled property has changed
584 *
585 * Sends PropertyChanged signals containing new value of Enabled property
586 * for specified network
587 */
588 static void wpas_dbus_signal_network_enabled_changed(
589 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
590 {
591
592 struct network_handler_args args = {wpa_s, ssid};
593
594 char path[WPAS_DBUS_OBJECT_PATH_MAX];
595 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
596 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
597 wpas_dbus_get_path(wpa_s), ssid->id);
598
599 wpa_dbus_signal_property_changed(wpa_s->global->dbus,
600 (WPADBusPropertyAccessor)
601 wpas_dbus_getter_enabled, &args,
602 path, WPAS_DBUS_NEW_IFACE_NETWORK,
603 "Enabled");
604 }
605
606
607 #ifdef CONFIG_WPS
608
609 /**
610 * wpas_dbus_signal_wps_event_success - Signals Success WPS event
611 * @wpa_s: %wpa_supplicant network interface data
612 *
613 * Sends Event dbus signal with name "success" and empty dict as arguments
614 */
615 static void wpas_dbus_signal_wps_event_success(struct wpa_supplicant *wpa_s)
616 {
617
618 DBusMessage *_signal = NULL;
619 DBusMessageIter iter, dict_iter;
620 struct wpas_dbus_priv *iface;
621 char *key = "success";
622 const char *path;
623
624 iface = wpa_s->global->dbus;
625
626 /* Do nothing if the control interface is not turned on */
627 if (iface == NULL)
628 return;
629
630 path = wpas_dbus_get_path(wpa_s);
631 if (!path) {
632 wpa_printf(MSG_ERROR, "wpas_dbus_signal_wps_event_success"
633 "[dbus]: interface has no dbus path set");
634 return;
635 }
636
637 _signal = dbus_message_new_signal(path, WPAS_DBUS_NEW_IFACE_WPS,
638 "Event");
639 if (!_signal) {
640 wpa_printf(MSG_ERROR, "wpas_dbus_signal_wps_event_success"
641 "[dbus]: out of memory when creating a signal");
642 return;
643 }
644
645 dbus_message_iter_init_append(_signal, &iter);
646
647 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
648 !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
649 !wpa_dbus_dict_close_write(&iter, &dict_iter)) {
650 wpa_printf(MSG_ERROR, "wpas_dbus_signal_wps_event_success"
651 "[dbus]: out of memory");
652 goto out;
653 }
654
655 dbus_connection_send(iface->con, _signal, NULL);
656 out:
657 dbus_message_unref(_signal);
658 }
659
660
661 /**
662 * wpas_dbus_signal_wps_event_fail - Signals Fail WPS event
663 * @wpa_s: %wpa_supplicant network interface data
664 *
665 * Sends Event dbus signal with name "fail" and dictionary containing
666 * "msg field with fail message number (int32) as arguments
667 */
668 static void wpas_dbus_signal_wps_event_fail(struct wpa_supplicant *wpa_s,
669 struct wps_event_fail *fail)
670 {
671
672 DBusMessage *_signal = NULL;
673 DBusMessageIter iter, dict_iter;
674 struct wpas_dbus_priv *iface;
675 char *key = "fail";
676 const char *path;
677
678 iface = wpa_s->global->dbus;
679
680 /* Do nothing if the control interface is not turned on */
681 if (iface == NULL)
682 return;
683
684 path = wpas_dbus_get_path(wpa_s);
685 if (!path) {
686 wpa_printf(MSG_ERROR, "wpas_dbus_signal_wps_event_fail[dbus]: "
687 "interface has no dbus path set");
688 return;
689 }
690
691 _signal = dbus_message_new_signal(path, WPAS_DBUS_NEW_IFACE_WPS,
692 "Event");
693 if (!_signal) {
694 wpa_printf(MSG_ERROR, "wpas_dbus_signal_wps_event_fail[dbus]: "
695 "out of memory when creating a signal");
696 return;
697 }
698
699 dbus_message_iter_init_append(_signal, &iter);
700
701 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
702 !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
703 !wpa_dbus_dict_append_int32(&dict_iter, "msg", fail->msg) ||
704 !wpa_dbus_dict_close_write(&iter, &dict_iter)) {
705 wpa_printf(MSG_ERROR, "wpas_dbus_signal_wps_event_fail[dbus]: "
706 "out of memory");
707 goto out;
708 }
709
710 dbus_connection_send(iface->con, _signal, NULL);
711 out:
712 dbus_message_unref(_signal);
713 }
714
715
716 /**
717 * wpas_dbus_signal_wps_event_m2d - Signals M2D WPS event
718 * @wpa_s: %wpa_supplicant network interface data
719 *
720 * Sends Event dbus signal with name "m2d" and dictionary containing
721 * fields of wps_event_m2d structure.
722 */
723 static void wpas_dbus_signal_wps_event_m2d(struct wpa_supplicant *wpa_s,
724 struct wps_event_m2d *m2d)
725 {
726
727 DBusMessage *_signal = NULL;
728 DBusMessageIter iter, dict_iter;
729 struct wpas_dbus_priv *iface;
730 char *key = "m2d";
731 const char *path;
732
733 iface = wpa_s->global->dbus;
734
735 /* Do nothing if the control interface is not turned on */
736 if (iface == NULL)
737 return;
738
739 path = wpas_dbus_get_path(wpa_s);
740 if (!path) {
741 wpa_printf(MSG_ERROR, "wpas_dbus_signal_wps_event_m2d[dbus]: "
742 "interface has no dbus path set");
743 return;
744 }
745
746 _signal = dbus_message_new_signal(path, WPAS_DBUS_NEW_IFACE_WPS,
747 "Event");
748 if (!_signal) {
749 wpa_printf(MSG_ERROR, "wpas_dbus_signal_wps_event_m2d[dbus]: "
750 "out of memory when creating a signal");
751 return;
752 }
753
754 dbus_message_iter_init_append(_signal, &iter);
755
756 if (!(dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) &&
757 wpa_dbus_dict_open_write(&iter, &dict_iter) &&
758 wpa_dbus_dict_append_uint16(&dict_iter, "config_methods",
759 m2d->config_methods) &&
760 wpa_dbus_dict_append_byte_array(&dict_iter, "manufacturer",
761 (const char *) m2d->manufacturer,
762 m2d->manufacturer_len) &&
763 wpa_dbus_dict_append_byte_array(&dict_iter, "model_name",
764 (const char *) m2d->model_name,
765 m2d->model_name_len) &&
766 wpa_dbus_dict_append_byte_array(&dict_iter, "model_number",
767 (const char *) m2d->model_number,
768 m2d->model_number_len) &&
769 wpa_dbus_dict_append_byte_array(&dict_iter, "serial_number",
770 (const char *)
771 m2d->serial_number,
772 m2d->serial_number_len) &&
773 wpa_dbus_dict_append_byte_array(&dict_iter, "dev_name",
774 (const char *) m2d->dev_name,
775 m2d->dev_name_len) &&
776 wpa_dbus_dict_append_byte_array(&dict_iter, "primary_dev_type",
777 (const char *)
778 m2d->primary_dev_type, 8) &&
779 wpa_dbus_dict_append_uint16(&dict_iter, "config_error",
780 m2d->config_error) &&
781 wpa_dbus_dict_append_uint16(&dict_iter, "dev_password_id",
782 m2d->dev_password_id) &&
783 wpa_dbus_dict_close_write(&iter, &dict_iter))) {
784 wpa_printf(MSG_ERROR, "wpas_dbus_signal_wps_event_m2d[dbus]: "
785 "out of memory");
786 goto out;
787 }
788
789 dbus_connection_send(iface->con, _signal, NULL);
790 out:
791 dbus_message_unref(_signal);
792 }
793
794
795 /**
796 * wpas_dbus_signal_wps_cred - Signals new credentials
797 * @wpa_s: %wpa_supplicant network interface data
798 *
799 * Sends signal with credentials in directory argument
800 */
801 static void wpas_dbus_signal_wps_cred(struct wpa_supplicant *wpa_s,
802 const struct wps_credential *cred)
803 {
804 DBusMessage *_signal = NULL;
805 DBusMessageIter iter, dict_iter;
806 struct wpas_dbus_priv *iface;
807 const char *path;
808 char *auth_type[6]; /* we have six possible authorization types */
809 int at_num = 0;
810 char *encr_type[4]; /* we have four possible encryption types */
811 int et_num = 0;
812
813 iface = wpa_s->global->dbus;
814
815 /* Do nothing if the control interface is not turned on */
816 if (iface == NULL)
817 return;
818
819 path = wpas_dbus_get_path(wpa_s);
820 if (!path) {
821 wpa_printf(MSG_ERROR, "wpas_dbus_signal_wps_cred[dbus]: "
822 "interface has no dbus path set");
823 return;
824 }
825
826 _signal = dbus_message_new_signal(path, WPAS_DBUS_NEW_IFACE_WPS,
827 "Credentials");
828 if (!_signal) {
829 wpa_printf(MSG_ERROR, "wpas_dbus_signal_wps_cred[dbus]: "
830 "out of memory when creating a signal");
831 return;
832 }
833
834 dbus_message_iter_init_append(_signal, &iter);
835
836 if (!wpa_dbus_dict_open_write(&iter, &dict_iter)) {
837 perror("wpas_dbus_signal_wps_cred[dbus]: out of memory "
838 "when opening a dictionary");
839 goto nomem;
840 }
841
842 if (cred->auth_type & WPS_AUTH_OPEN)
843 auth_type[at_num++] = "open";
844 if (cred->auth_type & WPS_AUTH_WPAPSK)
845 auth_type[at_num++] = "wpa-psk";
846 if (cred->auth_type & WPS_AUTH_SHARED)
847 auth_type[at_num++] = "shared";
848 if (cred->auth_type & WPS_AUTH_WPA)
849 auth_type[at_num++] = "wpa-eap";
850 if (cred->auth_type & WPS_AUTH_WPA2)
851 auth_type[at_num++] = "wpa2-eap";
852 if (cred->auth_type & WPS_AUTH_WPA2PSK)
853 auth_type[at_num++] =
854 "wpa2-psk";
855
856 if (cred->encr_type & WPS_ENCR_NONE)
857 encr_type[et_num++] = "none";
858 if (cred->encr_type & WPS_ENCR_WEP)
859 encr_type[et_num++] = "wep";
860 if (cred->encr_type & WPS_ENCR_TKIP)
861 encr_type[et_num++] = "tkip";
862 if (cred->encr_type & WPS_ENCR_AES)
863 encr_type[et_num++] = "aes";
864
865 if (wpa_s->current_ssid) {
866 if (!wpa_dbus_dict_append_byte_array(
867 &dict_iter, "BSSID",
868 (const char *) wpa_s->current_ssid->bssid,
869 ETH_ALEN)) {
870 perror("wpas_dbus_signal_wps_cred[dbus]: out of "
871 "memory when appending bssid to dictionary");
872 goto nomem;
873 }
874 }
875
876 if (!(wpa_dbus_dict_append_byte_array(&dict_iter, "SSID",
877 (const char *) cred->ssid,
878 cred->ssid_len) &&
879 wpa_dbus_dict_append_string_array(&dict_iter, "AuthType",
880 (const char **) auth_type,
881 at_num) &&
882 wpa_dbus_dict_append_string_array(&dict_iter, "EncrType",
883 (const char **) encr_type,
884 et_num) &&
885 wpa_dbus_dict_append_byte_array(&dict_iter, "Key",
886 (const char *) cred->key,
887 cred->key_len) &&
888 wpa_dbus_dict_append_uint32(&dict_iter, "KeyIndex",
889 cred->key_idx))) {
890 perror("wpas_dbus_signal_wps_cred[dbus]: out of memory "
891 "when appending to dictionary");
892 goto nomem;
893 }
894
895 if (!wpa_dbus_dict_close_write(&iter, &dict_iter)) {
896 perror("wpas_dbus_signal_wps_cred[dbus]: out of memory "
897 "when closing a dictionary");
898 goto nomem;
899 }
900
901 dbus_connection_send(iface->con, _signal, NULL);
902
903 nomem:
904 dbus_message_unref(_signal);
905 }
906
907 #endif /* CONFIG_WPS */
908
909
910 /**
911 * wpas_dbus_signal_prop_changed - Signals change of property
912 * @wpa_s: %wpa_supplicant network interface data
913 * @property: indicates which property has changed
914 *
915 * Sends ProertyChanged signals with path, interface and arguments
916 * depending on which property has changed.
917 */
918 static void wpas_dbus_signal_prop_changed(struct wpa_supplicant *wpa_s,
919 enum wpas_dbus_prop property)
920 {
921 WPADBusPropertyAccessor getter;
922 char *iface;
923 char *prop;
924 void *arg;
925
926 switch (property) {
927 case WPAS_DBUS_PROP_AP_SCAN:
928 getter = (WPADBusPropertyAccessor) wpas_dbus_getter_ap_scan;
929 arg = wpa_s;
930 iface = WPAS_DBUS_NEW_IFACE_INTERFACE;
931 prop = "ApScan";
932 break;
933 case WPAS_DBUS_PROP_SCANNING:
934 getter = (WPADBusPropertyAccessor) wpas_dbus_getter_scanning;
935 arg = wpa_s;
936 iface = WPAS_DBUS_NEW_IFACE_INTERFACE;
937 prop = "Scanning";
938 break;
939 case WPAS_DBUS_PROP_CURRENT_BSS:
940 getter = (WPADBusPropertyAccessor)
941 wpas_dbus_getter_current_bss;
942 arg = wpa_s;
943 iface = WPAS_DBUS_NEW_IFACE_INTERFACE;
944 prop = "CurrentBSS";
945 break;
946 case WPAS_DBUS_PROP_CURRENT_NETWORK:
947 getter = (WPADBusPropertyAccessor)
948 wpas_dbus_getter_current_network;
949 arg = wpa_s;
950 iface = WPAS_DBUS_NEW_IFACE_INTERFACE;
951 prop = "CurrentNetwork";
952 break;
953 default:
954 wpa_printf(MSG_ERROR, "wpas_dbus_signal_prop_changed[dbus]: "
955 "Unknown Property enum value %d", property);
956 return;
957 }
958
959 wpa_dbus_signal_property_changed(wpa_s->global->dbus,
960 getter, arg,
961 wpas_dbus_get_path(wpa_s), iface,
962 prop);
963 }
964
965
966 /**
967 * wpas_dbus_signal_debug_params_changed - Signals change of debug params
968 * @global: wpa_global structure
969 *
970 * Sends ProertyChanged signals informing that debug params has changed.
971 */
972 static void wpas_dbus_signal_debug_params_changed(struct wpa_global *global)
973 {
974
975 wpa_dbus_signal_property_changed(global->dbus,
976 (WPADBusPropertyAccessor)
977 wpas_dbus_getter_debug_params,
978 global, WPAS_DBUS_NEW_PATH,
979 WPAS_DBUS_NEW_INTERFACE,
980 "DebugParams");
981 }
982
983
984 struct wpas_dbus_method {
985 const char *name;
986 const char *iface;
987 WPADBusMethodHandler handler;
988 struct wpa_dbus_argument args[3];
989 };
990
991 struct wpas_dbus_property {
992 const char *name;
993 const char *iface;
994 const char *type;
995 WPADBusPropertyAccessor getter;
996 WPADBusPropertyAccessor setter;
997 enum dbus_prop_access _access;
998 };
999
1000 struct wpas_dbus_signal {
1001 const char *name;
1002 const char *iface;
1003 struct wpa_dbus_argument args[3];
1004 };
1005
1006
1007 static void wpas_dbus_register(struct wpa_dbus_object_desc *obj_desc,
1008 void *priv,
1009 WPADBusArgumentFreeFunction priv_free,
1010 const struct wpas_dbus_method *methods,
1011 const struct wpas_dbus_property *properties,
1012 const struct wpas_dbus_signal *signals)
1013 {
1014 int i;
1015
1016 obj_desc->user_data = priv;
1017 obj_desc->user_data_free_func = priv_free;
1018
1019 for (i = 0; methods && methods[i].name; i++) {
1020 wpa_dbus_method_register(obj_desc, methods[i].iface,
1021 methods[i].name, methods[i].handler,
1022 methods[i].args);
1023 }
1024
1025 for (i = 0; properties && properties[i].name; i++) {
1026 wpa_dbus_property_register(obj_desc, properties[i].iface,
1027 properties[i].name,
1028 properties[i].type,
1029 properties[i].getter,
1030 properties[i].setter,
1031 properties[i]._access);
1032 }
1033
1034 for (i = 0; signals && signals[i].name; i++) {
1035 wpa_dbus_signal_register(obj_desc, signals[i].iface,
1036 signals[i].name, signals[i].args);
1037 }
1038 }
1039
1040
1041 static const struct wpas_dbus_method wpas_dbus_global_methods[] = {
1042 { "CreateInterface", WPAS_DBUS_NEW_INTERFACE,
1043 (WPADBusMethodHandler) &wpas_dbus_handler_create_interface,
1044 {
1045 { "args", "a{sv}", ARG_IN },
1046 { "path", "o", ARG_OUT },
1047 END_ARGS
1048 }
1049 },
1050 { "RemoveInterface", WPAS_DBUS_NEW_INTERFACE,
1051 (WPADBusMethodHandler) &wpas_dbus_handler_remove_interface,
1052 {
1053 { "path", "o", ARG_IN },
1054 END_ARGS
1055 }
1056 },
1057 { "GetInterface", WPAS_DBUS_NEW_INTERFACE,
1058 (WPADBusMethodHandler) &wpas_dbus_handler_get_interface,
1059 {
1060 { "ifname", "s", ARG_IN },
1061 { "path", "o", ARG_OUT },
1062 END_ARGS
1063 }
1064 },
1065 { NULL, NULL, NULL, { END_ARGS } }
1066 };
1067
1068 static const struct wpas_dbus_property wpas_dbus_global_properties[] = {
1069 { "DebugParams", WPAS_DBUS_NEW_INTERFACE, "(ibb)",
1070 (WPADBusPropertyAccessor) &wpas_dbus_getter_debug_params,
1071 (WPADBusPropertyAccessor) &wpas_dbus_setter_debug_params,
1072 RW
1073 },
1074 { "Interfaces", WPAS_DBUS_NEW_INTERFACE, "ao",
1075 (WPADBusPropertyAccessor) &wpas_dbus_getter_interfaces,
1076 NULL,
1077 R
1078 },
1079 { "EapMethods", WPAS_DBUS_NEW_INTERFACE, "as",
1080 (WPADBusPropertyAccessor) wpas_dbus_getter_eap_methods,
1081 NULL,
1082 R
1083 },
1084 { NULL, NULL, NULL, NULL, NULL, 0 }
1085 };
1086
1087 static const struct wpas_dbus_signal wpas_dbus_global_signals[] = {
1088 { "InterfaceAdded", WPAS_DBUS_NEW_INTERFACE,
1089 {
1090 { "path", "o", ARG_OUT },
1091 { "properties", "a{sv}", ARG_OUT },
1092 END_ARGS
1093 }
1094 },
1095 { "InterfaceRemoved", WPAS_DBUS_NEW_INTERFACE,
1096 {
1097 { "path", "o", ARG_OUT },
1098 END_ARGS
1099 }
1100 },
1101 { "PropertiesChanged", WPAS_DBUS_NEW_INTERFACE,
1102 {
1103 { "properties", "a{sv}", ARG_OUT },
1104 END_ARGS
1105 }
1106 },
1107 { NULL, NULL, { END_ARGS } }
1108 };
1109
1110
1111 /**
1112 * wpas_dbus_ctrl_iface_init - Initialize dbus control interface
1113 * @global: Pointer to global data from wpa_supplicant_init()
1114 * Returns: 0 on success or -1 on failure
1115 *
1116 * Initialize the dbus control interface for wpa_supplicantand and start
1117 * receiving commands from external programs over the bus.
1118 */
1119 int wpas_dbus_ctrl_iface_init(struct wpas_dbus_priv *priv)
1120 {
1121 struct wpa_dbus_object_desc *obj_desc;
1122 int ret;
1123
1124 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
1125 if (!obj_desc) {
1126 wpa_printf(MSG_ERROR, "Not enough memory "
1127 "to create object description");
1128 return -1;
1129 }
1130
1131 wpas_dbus_register(obj_desc, priv->global, NULL,
1132 wpas_dbus_global_methods,
1133 wpas_dbus_global_properties,
1134 wpas_dbus_global_signals);
1135
1136 wpa_printf(MSG_DEBUG, "dbus: Register D-Bus object '%s'",
1137 WPAS_DBUS_NEW_PATH);
1138 ret = wpa_dbus_ctrl_iface_init(priv, WPAS_DBUS_NEW_PATH,
1139 WPAS_DBUS_NEW_SERVICE,
1140 obj_desc);
1141 if (ret < 0)
1142 free_dbus_object_desc(obj_desc);
1143 else
1144 priv->dbus_new_initialized = 1;
1145
1146 return ret;
1147 }
1148
1149
1150 /**
1151 * wpas_dbus_ctrl_iface_deinit - Deinitialize dbus ctrl interface for
1152 * wpa_supplicant
1153 * @iface: Pointer to dbus private data from wpas_dbus_init()
1154 *
1155 * Deinitialize the dbus control interface that was initialized with
1156 * wpas_dbus_ctrl_iface_init().
1157 */
1158 void wpas_dbus_ctrl_iface_deinit(struct wpas_dbus_priv *iface)
1159 {
1160 if (!iface->dbus_new_initialized)
1161 return;
1162 wpa_printf(MSG_DEBUG, "dbus: Unregister D-Bus object '%s'",
1163 WPAS_DBUS_NEW_PATH);
1164 dbus_connection_unregister_object_path(iface->con,
1165 WPAS_DBUS_NEW_PATH);
1166 }
1167
1168
1169 static void wpa_dbus_free(void *ptr)
1170 {
1171 os_free(ptr);
1172 }
1173
1174
1175 static const struct wpas_dbus_property wpas_dbus_network_properties[] = {
1176 { "Properties", WPAS_DBUS_NEW_IFACE_NETWORK, "a{sv}",
1177 (WPADBusPropertyAccessor) wpas_dbus_getter_network_properties,
1178 (WPADBusPropertyAccessor) wpas_dbus_setter_network_properties,
1179 RW
1180 },
1181 { "Enabled", WPAS_DBUS_NEW_IFACE_NETWORK, "b",
1182 (WPADBusPropertyAccessor) wpas_dbus_getter_enabled,
1183 (WPADBusPropertyAccessor) wpas_dbus_setter_enabled,
1184 RW
1185 },
1186 { NULL, NULL, NULL, NULL, NULL, 0 }
1187 };
1188
1189
1190 static const struct wpas_dbus_signal wpas_dbus_network_signals[] = {
1191 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_NETWORK,
1192 {
1193 { "properties", "a{sv}", ARG_OUT },
1194 END_ARGS
1195 }
1196 },
1197 { NULL, NULL, { END_ARGS } }
1198 };
1199
1200
1201 /**
1202 * wpas_dbus_register_network - Register a configured network with dbus
1203 * @wpa_s: wpa_supplicant interface structure
1204 * @ssid: network configuration data
1205 * Returns: 0 on success, -1 on failure
1206 *
1207 * Registers network representing object with dbus
1208 */
1209 static int wpas_dbus_register_network(struct wpa_supplicant *wpa_s,
1210 struct wpa_ssid *ssid)
1211 {
1212 struct wpas_dbus_priv *ctrl_iface;
1213 struct wpa_dbus_object_desc *obj_desc;
1214
1215 struct network_handler_args *arg = NULL;
1216
1217 char *net_obj_path;
1218
1219 /* Do nothing if the control interface is not turned on */
1220 if (wpa_s == NULL || wpa_s->global == NULL)
1221 return 0;
1222 ctrl_iface = wpa_s->global->dbus;
1223 if (ctrl_iface == NULL)
1224 return 0;
1225
1226 net_obj_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1227 if (net_obj_path == NULL)
1228 return -1;
1229 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1230 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
1231 wpas_dbus_get_path(wpa_s), ssid->id);
1232
1233 wpa_printf(MSG_DEBUG, "dbus: Register network object '%s'",
1234 net_obj_path);
1235 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
1236 if (!obj_desc) {
1237 wpa_printf(MSG_ERROR, "Not enough memory "
1238 "to create object description");
1239 goto err;
1240 }
1241
1242 /* allocate memory for handlers arguments */
1243 arg = os_zalloc(sizeof(struct network_handler_args));
1244 if (!arg) {
1245 wpa_printf(MSG_ERROR, "Not enough memory "
1246 "to create arguments for method");
1247 goto err;
1248 }
1249
1250 arg->wpa_s = wpa_s;
1251 arg->ssid = ssid;
1252
1253 wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
1254 wpas_dbus_network_properties,
1255 wpas_dbus_network_signals);
1256
1257 if (wpa_dbus_register_object_per_iface(ctrl_iface, net_obj_path,
1258 wpa_s->ifname, obj_desc))
1259 goto err;
1260
1261 wpas_dbus_signal_network_added(wpa_s, ssid->id);
1262
1263 os_free(net_obj_path);
1264 return 0;
1265
1266 err:
1267 os_free(net_obj_path);
1268 os_free(obj_desc);
1269 os_free(arg);
1270 return -1;
1271 }
1272
1273
1274 /**
1275 * wpas_dbus_unregister_network - Unregister a configured network from dbus
1276 * @wpa_s: wpa_supplicant interface structure
1277 * @nid: network id
1278 * Returns: 0 on success, -1 on failure
1279 *
1280 * Unregisters network representing object from dbus
1281 */
1282 static int wpas_dbus_unregister_network(struct wpa_supplicant *wpa_s, int nid)
1283 {
1284 struct wpas_dbus_priv *ctrl_iface;
1285 char *net_obj_path;
1286 int ret;
1287
1288 /* Do nothing if the control interface is not turned on */
1289 if (wpa_s == NULL || wpa_s->global == NULL)
1290 return 0;
1291 ctrl_iface = wpa_s->global->dbus;
1292 if (ctrl_iface == NULL)
1293 return 0;
1294
1295 net_obj_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1296 if (net_obj_path == NULL)
1297 return -1;
1298 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1299 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
1300 wpas_dbus_get_path(wpa_s), nid);
1301
1302 wpa_printf(MSG_DEBUG, "dbus: Unregister network object '%s'",
1303 net_obj_path);
1304 ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, net_obj_path);
1305
1306 if (!ret)
1307 wpas_dbus_signal_network_removed(wpa_s, nid);
1308
1309 os_free(net_obj_path);
1310 return ret;
1311 }
1312
1313
1314 static const struct wpas_dbus_property wpas_dbus_bss_properties[] = {
1315 { "SSID", WPAS_DBUS_NEW_IFACE_BSSID, "ay",
1316 (WPADBusPropertyAccessor) wpas_dbus_getter_bss_ssid,
1317 NULL,
1318 R
1319 },
1320 { "BSSID", WPAS_DBUS_NEW_IFACE_BSSID, "ay",
1321 (WPADBusPropertyAccessor) wpas_dbus_getter_bss_bssid,
1322 NULL,
1323 R
1324 },
1325 { "Privacy", WPAS_DBUS_NEW_IFACE_BSSID, "b",
1326 (WPADBusPropertyAccessor) wpas_dbus_getter_bss_privacy,
1327 NULL,
1328 R
1329 },
1330 { "Mode", WPAS_DBUS_NEW_IFACE_BSSID, "s",
1331 (WPADBusPropertyAccessor) wpas_dbus_getter_bss_mode,
1332 NULL,
1333 R
1334 },
1335 { "Signal", WPAS_DBUS_NEW_IFACE_BSSID, "n",
1336 (WPADBusPropertyAccessor) wpas_dbus_getter_bss_signal,
1337 NULL,
1338 R
1339 },
1340 { "Frequency", WPAS_DBUS_NEW_IFACE_BSSID, "q",
1341 (WPADBusPropertyAccessor) wpas_dbus_getter_bss_frequency,
1342 NULL,
1343 R
1344 },
1345 { "MaxRate", WPAS_DBUS_NEW_IFACE_BSSID, "q",
1346 (WPADBusPropertyAccessor) wpas_dbus_getter_bss_max_rate,
1347 NULL,
1348 R
1349 },
1350 { "WPAIE", WPAS_DBUS_NEW_IFACE_BSSID, "ay",
1351 (WPADBusPropertyAccessor) wpas_dbus_getter_bss_wpaie,
1352 NULL,
1353 R
1354 },
1355 { "RSNIE", WPAS_DBUS_NEW_IFACE_BSSID, "ay",
1356 (WPADBusPropertyAccessor) wpas_dbus_getter_bss_rsnie,
1357 NULL,
1358 R
1359 },
1360 { "WPSIE", WPAS_DBUS_NEW_IFACE_BSSID, "ay",
1361 (WPADBusPropertyAccessor) wpas_dbus_getter_bss_wpsie,
1362 NULL,
1363 R
1364 },
1365 { NULL, NULL, NULL, NULL, NULL, 0 }
1366 };
1367
1368
1369 static const struct wpas_dbus_signal wpas_dbus_bss_signals[] = {
1370 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_BSSID,
1371 {
1372 { "properties", "a{sv}", ARG_OUT },
1373 END_ARGS
1374 }
1375 },
1376 { NULL, NULL, { END_ARGS } }
1377 };
1378
1379
1380 /**
1381 * wpas_dbus_unregister_bss - Unregister a scanned BSS from dbus
1382 * @wpa_s: wpa_supplicant interface structure
1383 * @bssid: scanned network bssid
1384 * @id: unique BSS identifier
1385 * Returns: 0 on success, -1 on failure
1386 *
1387 * Unregisters BSS representing object from dbus
1388 */
1389 static int wpas_dbus_unregister_bss(struct wpa_supplicant *wpa_s,
1390 u8 bssid[ETH_ALEN], unsigned int id)
1391 {
1392 struct wpas_dbus_priv *ctrl_iface;
1393 char *bss_obj_path;
1394
1395 /* Do nothing if the control interface is not turned on */
1396 if (wpa_s == NULL || wpa_s->global == NULL)
1397 return 0;
1398 ctrl_iface = wpa_s->global->dbus;
1399 if (ctrl_iface == NULL)
1400 return 0;
1401
1402 bss_obj_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1403 if (bss_obj_path == NULL)
1404 return -1;
1405
1406 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1407 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
1408 wpas_dbus_get_path(wpa_s), id);
1409
1410 wpa_printf(MSG_DEBUG, "dbus: Unregister BSS object '%s'",
1411 bss_obj_path);
1412 if (wpa_dbus_unregister_object_per_iface(ctrl_iface, bss_obj_path)) {
1413 wpa_printf(MSG_ERROR,
1414 "Cannot unregister BSSID dbus object %s.",
1415 bss_obj_path);
1416 os_free(bss_obj_path);
1417 return -1;
1418 }
1419
1420 wpas_dbus_signal_bss_removed(wpa_s, bss_obj_path);
1421
1422 os_free(bss_obj_path);
1423 return 0;
1424 }
1425
1426
1427 /**
1428 * wpas_dbus_register_bss - Register a scanned BSS with dbus
1429 * @wpa_s: wpa_supplicant interface structure
1430 * @bssid: scanned network bssid
1431 * @id: unique BSS identifier
1432 * Returns: 0 on success, -1 on failure
1433 *
1434 * Registers BSS representing object with dbus
1435 */
1436 static int wpas_dbus_register_bss(struct wpa_supplicant *wpa_s,
1437 u8 bssid[ETH_ALEN], unsigned int id)
1438 {
1439 struct wpas_dbus_priv *ctrl_iface;
1440 struct wpa_dbus_object_desc *obj_desc;
1441 char *bss_obj_path;
1442
1443 struct bss_handler_args *arg = NULL;
1444
1445 /* Do nothing if the control interface is not turned on */
1446 if (wpa_s == NULL || wpa_s->global == NULL)
1447 return 0;
1448 ctrl_iface = wpa_s->global->dbus;
1449 if (ctrl_iface == NULL)
1450 return 0;
1451
1452 bss_obj_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1453 if (bss_obj_path == NULL)
1454 return -1;
1455
1456 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1457 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
1458 wpas_dbus_get_path(wpa_s), id);
1459
1460 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
1461 if (!obj_desc) {
1462 wpa_printf(MSG_ERROR, "Not enough memory "
1463 "to create object description");
1464 goto err;
1465 }
1466
1467 arg = os_zalloc(sizeof(struct bss_handler_args));
1468 if (!arg) {
1469 wpa_printf(MSG_ERROR, "Not enough memory "
1470 "to create arguments for handler");
1471 goto err;
1472 }
1473 arg->wpa_s = wpa_s;
1474 arg->id = id;
1475
1476 wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
1477 wpas_dbus_bss_properties,
1478 wpas_dbus_bss_signals);
1479
1480 wpa_printf(MSG_DEBUG, "dbus: Register BSS object '%s'",
1481 bss_obj_path);
1482 if (wpa_dbus_register_object_per_iface(ctrl_iface, bss_obj_path,
1483 wpa_s->ifname, obj_desc)) {
1484 wpa_printf(MSG_ERROR,
1485 "Cannot register BSSID dbus object %s.",
1486 bss_obj_path);
1487 goto err;
1488 }
1489
1490 wpas_dbus_signal_bss_added(wpa_s, bss_obj_path);
1491
1492 os_free(bss_obj_path);
1493 return 0;
1494
1495 err:
1496 os_free(bss_obj_path);
1497 os_free(obj_desc);
1498 os_free(arg);
1499 return -1;
1500 }
1501
1502
1503 static const struct wpas_dbus_method wpas_dbus_interface_methods[] = {
1504 { "Scan", WPAS_DBUS_NEW_IFACE_INTERFACE,
1505 (WPADBusMethodHandler) &wpas_dbus_handler_scan,
1506 {
1507 { "args", "a{sv}", ARG_IN },
1508 END_ARGS
1509 }
1510 },
1511 { "Disconnect", WPAS_DBUS_NEW_IFACE_INTERFACE,
1512 (WPADBusMethodHandler) &wpas_dbus_handler_disconnect,
1513 {
1514 END_ARGS
1515 }
1516 },
1517 { "AddNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
1518 (WPADBusMethodHandler) &wpas_dbus_handler_add_network,
1519 {
1520 { "args", "a{sv}", ARG_IN },
1521 { "path", "o", ARG_OUT },
1522 END_ARGS
1523 }
1524 },
1525 { "RemoveNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
1526 (WPADBusMethodHandler) &wpas_dbus_handler_remove_network,
1527 {
1528 { "path", "o", ARG_IN },
1529 END_ARGS
1530 }
1531 },
1532 { "SelectNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
1533 (WPADBusMethodHandler) &wpas_dbus_handler_select_network,
1534 {
1535 { "path", "o", ARG_IN },
1536 END_ARGS
1537 }
1538 },
1539 { "AddBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
1540 (WPADBusMethodHandler) &wpas_dbus_handler_add_blob,
1541 {
1542 { "name", "s", ARG_IN },
1543 { "data", "ay", ARG_IN },
1544 END_ARGS
1545 }
1546 },
1547 { "GetBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
1548 (WPADBusMethodHandler) &wpas_dbus_handler_get_blob,
1549 {
1550 { "name", "s", ARG_IN },
1551 { "data", "ay", ARG_OUT },
1552 END_ARGS
1553 }
1554 },
1555 { "RemoveBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
1556 (WPADBusMethodHandler) &wpas_dbus_handler_remove_blob,
1557 {
1558 { "name", "s", ARG_IN },
1559 END_ARGS
1560 }
1561 },
1562 #ifdef CONFIG_WPS
1563 { "Start", WPAS_DBUS_NEW_IFACE_WPS,
1564 (WPADBusMethodHandler) &wpas_dbus_handler_wps_start,
1565 {
1566 { "args", "a{sv}", ARG_IN },
1567 { "output", "a{sv}", ARG_OUT },
1568 END_ARGS
1569 }
1570 },
1571 #endif /* CONFIG_WPS */
1572 { NULL, NULL, NULL, { END_ARGS } }
1573 };
1574
1575 static const struct wpas_dbus_property wpas_dbus_interface_properties[] = {
1576 { "Capabilities", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{sv}",
1577 (WPADBusPropertyAccessor) wpas_dbus_getter_capabilities,
1578 NULL, R
1579 },
1580 { "State", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
1581 (WPADBusPropertyAccessor) wpas_dbus_getter_state,
1582 NULL, R
1583 },
1584 { "Scanning", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
1585 (WPADBusPropertyAccessor) wpas_dbus_getter_scanning,
1586 NULL, R
1587 },
1588 { "ApScan", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
1589 (WPADBusPropertyAccessor) wpas_dbus_getter_ap_scan,
1590 (WPADBusPropertyAccessor) wpas_dbus_setter_ap_scan,
1591 RW
1592 },
1593 { "Ifname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
1594 (WPADBusPropertyAccessor) wpas_dbus_getter_ifname,
1595 NULL, R
1596 },
1597 { "Driver", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
1598 (WPADBusPropertyAccessor) wpas_dbus_getter_driver,
1599 NULL, R
1600 },
1601 { "BridgeIfname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
1602 (WPADBusPropertyAccessor) wpas_dbus_getter_bridge_ifname,
1603 NULL, R
1604 },
1605 { "CurrentBSS", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
1606 (WPADBusPropertyAccessor) wpas_dbus_getter_current_bss,
1607 NULL, R
1608 },
1609 { "CurrentNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
1610 (WPADBusPropertyAccessor) wpas_dbus_getter_current_network,
1611 NULL, R
1612 },
1613 { "Blobs", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{say}",
1614 (WPADBusPropertyAccessor) wpas_dbus_getter_blobs,
1615 NULL, R
1616 },
1617 { "BSSs", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
1618 (WPADBusPropertyAccessor) wpas_dbus_getter_bsss,
1619 NULL, R
1620 },
1621 { "Networks", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
1622 (WPADBusPropertyAccessor) wpas_dbus_getter_networks,
1623 NULL, R
1624 },
1625 #ifdef CONFIG_WPS
1626 { "ProcessCredentials", WPAS_DBUS_NEW_IFACE_WPS, "b",
1627 (WPADBusPropertyAccessor) wpas_dbus_getter_process_credentials,
1628 (WPADBusPropertyAccessor) wpas_dbus_setter_process_credentials,
1629 RW
1630 },
1631 #endif /* CONFIG_WPS */
1632 { NULL, NULL, NULL, NULL, NULL, 0 }
1633 };
1634
1635 static const struct wpas_dbus_signal wpas_dbus_interface_signals[] = {
1636 { "ScanDone", WPAS_DBUS_NEW_IFACE_INTERFACE,
1637 {
1638 { "success", "b", ARG_OUT },
1639 END_ARGS
1640 }
1641 },
1642 { "StateChanged", WPAS_DBUS_NEW_IFACE_INTERFACE,
1643 {
1644 { "newState", "s", ARG_OUT },
1645 { "oldState", "s", ARG_OUT },
1646 END_ARGS
1647 }
1648 },
1649 { "BSSAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
1650 {
1651 { "path", "o", ARG_OUT },
1652 { "properties", "a{sv}", ARG_OUT },
1653 END_ARGS
1654 }
1655 },
1656 { "BSSRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
1657 {
1658 { "path", "o", ARG_OUT },
1659 END_ARGS
1660 }
1661 },
1662 { "BlobAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
1663 {
1664 { "name", "s", ARG_OUT },
1665 END_ARGS
1666 }
1667 },
1668 { "BlobRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
1669 {
1670 { "name", "s", ARG_OUT },
1671 END_ARGS
1672 }
1673 },
1674 { "NetworkAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
1675 {
1676 { "path", "o", ARG_OUT },
1677 { "properties", "a{sv}", ARG_OUT },
1678 END_ARGS
1679 }
1680 },
1681 { "NetworkRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
1682 {
1683 { "path", "o", ARG_OUT },
1684 END_ARGS
1685 }
1686 },
1687 { "NetworkSelected", WPAS_DBUS_NEW_IFACE_INTERFACE,
1688 {
1689 { "path", "o", ARG_OUT },
1690 END_ARGS
1691 }
1692 },
1693 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_INTERFACE,
1694 {
1695 { "properties", "a{sv}", ARG_OUT },
1696 END_ARGS
1697 }
1698 },
1699 #ifdef CONFIG_WPS
1700 { "Event", WPAS_DBUS_NEW_IFACE_WPS,
1701 {
1702 { "name", "s", ARG_OUT },
1703 { "args", "a{sv}", ARG_OUT },
1704 END_ARGS
1705 }
1706 },
1707 { "Credentials", WPAS_DBUS_NEW_IFACE_WPS,
1708 {
1709 { "credentials", "a{sv}", ARG_OUT },
1710 END_ARGS
1711 }
1712 },
1713 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_WPS,
1714 {
1715 { "properties", "a{sv}", ARG_OUT },
1716 END_ARGS
1717 }
1718 },
1719 #endif /* CONFIG_WPS */
1720 { NULL, NULL, { END_ARGS } }
1721 };
1722
1723
1724 static int wpas_dbus_register_interface(struct wpa_supplicant *wpa_s)
1725 {
1726
1727 struct wpa_dbus_object_desc *obj_desc = NULL;
1728 char *path;
1729 struct wpas_dbus_priv *ctrl_iface = wpa_s->global->dbus;
1730 int next;
1731
1732 /* Do nothing if the control interface is not turned on */
1733 if (ctrl_iface == NULL)
1734 return 0;
1735
1736 /* Create and set the interface's object path */
1737 path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1738 if (path == NULL)
1739 return -1;
1740 next = ctrl_iface->next_objid++;
1741 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
1742 WPAS_DBUS_NEW_PATH_INTERFACES "/%u",
1743 next);
1744 if (wpas_dbus_set_path(wpa_s, path)) {
1745 wpa_printf(MSG_DEBUG,
1746 "Failed to set dbus path for interface %s",
1747 wpa_s->ifname);
1748 goto err;
1749 }
1750
1751 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
1752 if (!obj_desc) {
1753 wpa_printf(MSG_ERROR, "Not enough memory "
1754 "to create object description");
1755 goto err;
1756 }
1757
1758 wpas_dbus_register(obj_desc, wpa_s, NULL, wpas_dbus_interface_methods,
1759 wpas_dbus_interface_properties,
1760 wpas_dbus_interface_signals);
1761
1762 wpa_printf(MSG_DEBUG, "dbus: Register interface object '%s'", path);
1763 if (wpa_dbus_register_object_per_iface(ctrl_iface, path, wpa_s->ifname,
1764 obj_desc))
1765 goto err;
1766
1767 wpas_dbus_signal_interface_added(wpa_s);
1768
1769 os_free(path);
1770 return 0;
1771
1772 err:
1773 os_free(obj_desc);
1774 os_free(path);
1775 return -1;
1776 }
1777
1778
1779 static int wpas_dbus_unregister_interface(struct wpa_supplicant *wpa_s)
1780 {
1781 struct wpas_dbus_priv *ctrl_iface;
1782
1783 /* Do nothing if the control interface is not turned on */
1784 if (wpa_s == NULL || wpa_s->global == NULL)
1785 return 0;
1786 ctrl_iface = wpa_s->global->dbus;
1787 if (ctrl_iface == NULL)
1788 return 0;
1789
1790 wpa_printf(MSG_DEBUG, "dbus: Unregister interface object '%s'",
1791 wpas_dbus_get_path(wpa_s));
1792 if (wpa_dbus_unregister_object_per_iface(ctrl_iface,
1793 wpas_dbus_get_path(wpa_s)))
1794 return -1;
1795
1796 wpas_dbus_signal_interface_removed(wpa_s);
1797
1798 os_free(wpa_s->dbus_new_path);
1799 wpa_s->dbus_new_path = NULL;
1800
1801 return 0;
1802 }
1803
1804
1805 static struct wpas_dbus_callbacks callbacks =
1806 {
1807 .signal_interface_added = wpas_dbus_signal_interface_added,
1808 .signal_interface_removed = wpas_dbus_signal_interface_removed,
1809
1810 .register_interface = wpas_dbus_register_interface,
1811 .unregister_interface = wpas_dbus_unregister_interface,
1812
1813 .signal_scan_done = wpas_dbus_signal_scan_done,
1814
1815 .signal_blob_added = wpas_dbus_signal_blob_added,
1816 .signal_blob_removed = wpas_dbus_signal_blob_removed,
1817
1818 .signal_network_selected = wpas_dbus_signal_network_selected,
1819
1820 .signal_state_changed = wpas_dbus_signal_state_changed,
1821 .register_network = wpas_dbus_register_network,
1822 .unregister_network = wpas_dbus_unregister_network,
1823
1824 .signal_network_enabled_changed =
1825 wpas_dbus_signal_network_enabled_changed,
1826
1827 .register_bss = wpas_dbus_register_bss,
1828 .unregister_bss = wpas_dbus_unregister_bss,
1829
1830 .signal_prop_changed = wpas_dbus_signal_prop_changed,
1831 .signal_debug_params_changed = wpas_dbus_signal_debug_params_changed,
1832
1833 #ifdef CONFIG_WPS
1834 .signal_wps_event_success = wpas_dbus_signal_wps_event_success,
1835 .signal_wps_event_fail = wpas_dbus_signal_wps_event_fail,
1836 .signal_wps_event_m2d = wpas_dbus_signal_wps_event_m2d,
1837 .signal_wps_credentials = wpas_dbus_signal_wps_cred,
1838 #endif /* CONFIG_WPS */
1839 };
1840
1841
1842 struct wpas_dbus_callbacks * wpas_dbus_get_callbacks(void)
1843 {
1844 return &callbacks;
1845 }
1846
1847
1848 /**
1849 * wpas_dbus_get_path - Get an interface's dbus path
1850 * @wpa_s: %wpa_supplicant interface structure
1851 * Returns: Interface's dbus object path, or %NULL on error
1852 */
1853 const char * wpas_dbus_get_path(struct wpa_supplicant *wpa_s)
1854 {
1855 return wpa_s->dbus_new_path;
1856 }