]> git.ipfire.org Git - thirdparty/hostap.git/blob - wpa_supplicant/dbus/dbus_new.c
dbus: Replace BSS 'Properties' property with separate properties
[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 *
55 * Notify listeners about event related with interface
56 */
57 static void wpas_dbus_signal_interface(struct wpa_supplicant *wpa_s,
58 const char *sig_name)
59 {
60 struct wpas_dbus_priv *iface;
61 DBusMessage *_signal;
62 const char *path;
63
64 iface = wpa_s->global->dbus;
65
66 /* Do nothing if the control interface is not turned on */
67 if (iface == NULL)
68 return;
69
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;
76 }
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;
83 }
84
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.");
91 }
92 dbus_message_unref(_signal);
93 }
94
95
96 /**
97 * wpas_dbus_signal_interface_created - Send a interface created signal
98 * @wpa_s: %wpa_supplicant network interface data
99 *
100 * Notify listeners about creating new interface
101 */
102 static void wpas_dbus_signal_interface_created(struct wpa_supplicant *wpa_s)
103 {
104 wpas_dbus_signal_interface(wpa_s, "InterfaceCreated");
105 }
106
107
108 /**
109 * wpas_dbus_signal_interface_removed - Send a interface removed signal
110 * @wpa_s: %wpa_supplicant network interface data
111 *
112 * Notify listeners about removing interface
113 */
114 static void wpas_dbus_signal_interface_removed(struct wpa_supplicant *wpa_s)
115 {
116 wpas_dbus_signal_interface(wpa_s, "InterfaceRemoved");
117
118 }
119
120
121 /**
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
125 *
126 * Notify listeners about finishing a scan
127 */
128 static void wpas_dbus_signal_scan_done(struct wpa_supplicant *wpa_s,
129 int success)
130 {
131 struct wpas_dbus_priv *iface;
132 DBusMessage *_signal;
133 const char *path;
134 dbus_bool_t succ;
135
136 iface = wpa_s->global->dbus;
137
138 /* Do nothing if the control interface is not turned on */
139 if (iface == NULL)
140 return;
141
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;
148 }
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;
155 }
156
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.");
164 }
165 dbus_message_unref(_signal);
166 }
167
168
169 /**
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
174 *
175 * Notify listeners about event related with BSS
176 */
177 static void wpas_dbus_signal_bss(struct wpa_supplicant *wpa_s,
178 const char *bss_obj_path,
179 const char *sig_name)
180 {
181 struct wpas_dbus_priv *iface;
182 DBusMessage *_signal;
183 const char *path;
184
185 iface = wpa_s->global->dbus;
186
187 /* Do nothing if the control interface is not turned on */
188 if (iface == NULL)
189 return;
190
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;
197 }
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;
204 }
205
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.");
212 }
213 dbus_message_unref(_signal);
214 }
215
216
217 /**
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
221 *
222 * Notify listeners about adding new BSS
223 */
224 static void wpas_dbus_signal_bss_added(struct wpa_supplicant *wpa_s,
225 const char *bss_obj_path)
226 {
227 wpas_dbus_signal_bss(wpa_s, bss_obj_path, "BSSAdded");
228 }
229
230
231 /**
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
235 *
236 * Notify listeners about removing BSS
237 */
238 static void wpas_dbus_signal_bss_removed(struct wpa_supplicant *wpa_s,
239 const char *bss_obj_path)
240 {
241 wpas_dbus_signal_bss(wpa_s, bss_obj_path, "BSSRemoved");
242 }
243
244
245 /**
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
250 *
251 * Notify listeners about event related with blob
252 */
253 static void wpas_dbus_signal_blob(struct wpa_supplicant *wpa_s,
254 const char *name, const char *sig_name)
255 {
256 struct wpas_dbus_priv *iface;
257 DBusMessage *_signal;
258 const char *path;
259
260 iface = wpa_s->global->dbus;
261
262 /* Do nothing if the control interface is not turned on */
263 if (iface == NULL)
264 return;
265
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;
272 }
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;
279 }
280
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.");
287 }
288 dbus_message_unref(_signal);
289 }
290
291
292 /**
293 * wpas_dbus_signal_blob_added - Send a blob added signal
294 * @wpa_s: %wpa_supplicant network interface data
295 * @name: blob name
296 *
297 * Notify listeners about adding a new blob
298 */
299 static void wpas_dbus_signal_blob_added(struct wpa_supplicant *wpa_s,
300 const char *name)
301 {
302 wpas_dbus_signal_blob(wpa_s, name, "BlobAdded");
303 }
304
305
306 /**
307 * wpas_dbus_signal_blob_removed - Send a blob removed signal
308 * @wpa_s: %wpa_supplicant network interface data
309 * @name: blob name
310 *
311 * Notify listeners about removing blob
312 */
313 static void wpas_dbus_signal_blob_removed(struct wpa_supplicant *wpa_s,
314 const char *name)
315 {
316 wpas_dbus_signal_blob(wpa_s, name, "BlobRemoved");
317 }
318
319
320 /**
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
325 *
326 * Notify listeners about event related with configured network
327 */
328 static void wpas_dbus_signal_network(struct wpa_supplicant *wpa_s,
329 int id, const char *sig_name)
330 {
331 struct wpas_dbus_priv *iface;
332 DBusMessage *_signal;
333 const char *path;
334 char *net_obj_path;
335
336 iface = wpa_s->global->dbus;
337
338 /* Do nothing if the control interface is not turned on */
339 if (iface == NULL)
340 return;
341
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;
348 }
349
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);
355
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;
363 }
364
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.");
371 }
372
373 os_free(net_obj_path);
374 dbus_message_unref(_signal);
375 }
376
377
378 /**
379 * wpas_dbus_signal_network_added - Send a network added signal
380 * @wpa_s: %wpa_supplicant network interface data
381 * @id: new network id
382 *
383 * Notify listeners about adding new network
384 */
385 static void wpas_dbus_signal_network_added(struct wpa_supplicant *wpa_s,
386 int id)
387 {
388 wpas_dbus_signal_network(wpa_s, id, "NetworkAdded");
389 }
390
391
392 /**
393 * wpas_dbus_signal_network_removed - Send a network removed signal
394 * @wpa_s: %wpa_supplicant network interface data
395 * @id: network id
396 *
397 * Notify listeners about removing a network
398 */
399 static void wpas_dbus_signal_network_removed(struct wpa_supplicant *wpa_s,
400 int id)
401 {
402 wpas_dbus_signal_network(wpa_s, id, "NetworkRemoved");
403 }
404
405
406 /**
407 * wpas_dbus_signal_network_selected - Send a network selected signal
408 * @wpa_s: %wpa_supplicant network interface data
409 * @id: network id
410 *
411 * Notify listeners about selecting a network
412 */
413 static void wpas_dbus_signal_network_selected(struct wpa_supplicant *wpa_s,
414 int id)
415 {
416 wpas_dbus_signal_network(wpa_s, id, "NetworkSelected");
417 }
418
419
420 /**
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
425 *
426 * Notify listeners that wpa_supplicant has changed state
427 */
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)
431 {
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;
437
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;
444
445 /* Only send signal if state really changed */
446 if (new_state == old_state)
447 return;
448
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;
458 }
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;
469 }
470
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;
480 }
481
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++;
487 }
488 tmp = old_state_str;
489 while (*tmp) {
490 *tmp = tolower(*tmp);
491 tmp++;
492 }
493
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;
505 }
506
507 dbus_connection_send(iface->con, _signal, NULL);
508
509 out:
510 dbus_message_unref(_signal);
511 os_free(new_state_str);
512 os_free(old_state_str);
513 }
514
515
516 /**
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
520 *
521 * Sends PropertyChanged signals containing new value of Enabled property
522 * for specified network
523 */
524 static void wpas_dbus_signal_network_enabled_changed(
525 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
526 {
527
528 struct network_handler_args args = {wpa_s, ssid};
529
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);
534
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");
540 }
541
542
543 #ifdef CONFIG_WPS
544
545 /**
546 * wpas_dbus_signal_wps_event_success - Signals Success WPS event
547 * @wpa_s: %wpa_supplicant network interface data
548 *
549 * Sends Event dbus signal with name "success" and empty dict as arguments
550 */
551 static void wpas_dbus_signal_wps_event_success(struct wpa_supplicant *wpa_s)
552 {
553
554 DBusMessage *_signal = NULL;
555 DBusMessageIter iter, dict_iter;
556 struct wpas_dbus_priv *iface;
557 char *key = "success";
558 const char *path;
559
560 iface = wpa_s->global->dbus;
561
562 /* Do nothing if the control interface is not turned on */
563 if (iface == NULL)
564 return;
565
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;
571 }
572
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;
579 }
580
581 dbus_message_iter_init_append(_signal, &iter);
582
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;
589 }
590
591 dbus_connection_send(iface->con, _signal, NULL);
592 out:
593 dbus_message_unref(_signal);
594 }
595
596
597 /**
598 * wpas_dbus_signal_wps_event_fail - Signals Fail WPS event
599 * @wpa_s: %wpa_supplicant network interface data
600 *
601 * Sends Event dbus signal with name "fail" and dictionary containing
602 * "msg field with fail message number (int32) as arguments
603 */
604 static void wpas_dbus_signal_wps_event_fail(struct wpa_supplicant *wpa_s,
605 struct wps_event_fail *fail)
606 {
607
608 DBusMessage *_signal = NULL;
609 DBusMessageIter iter, dict_iter;
610 struct wpas_dbus_priv *iface;
611 char *key = "fail";
612 const char *path;
613
614 iface = wpa_s->global->dbus;
615
616 /* Do nothing if the control interface is not turned on */
617 if (iface == NULL)
618 return;
619
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;
625 }
626
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;
633 }
634
635 dbus_message_iter_init_append(_signal, &iter);
636
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;
644 }
645
646 dbus_connection_send(iface->con, _signal, NULL);
647 out:
648 dbus_message_unref(_signal);
649 }
650
651
652 /**
653 * wpas_dbus_signal_wps_event_m2d - Signals M2D WPS event
654 * @wpa_s: %wpa_supplicant network interface data
655 *
656 * Sends Event dbus signal with name "m2d" and dictionary containing
657 * fields of wps_event_m2d structure.
658 */
659 static void wpas_dbus_signal_wps_event_m2d(struct wpa_supplicant *wpa_s,
660 struct wps_event_m2d *m2d)
661 {
662
663 DBusMessage *_signal = NULL;
664 DBusMessageIter iter, dict_iter;
665 struct wpas_dbus_priv *iface;
666 char *key = "m2d";
667 const char *path;
668
669 iface = wpa_s->global->dbus;
670
671 /* Do nothing if the control interface is not turned on */
672 if (iface == NULL)
673 return;
674
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;
680 }
681
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;
688 }
689
690 dbus_message_iter_init_append(_signal, &iter);
691
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;
723 }
724
725 dbus_connection_send(iface->con, _signal, NULL);
726 out:
727 dbus_message_unref(_signal);
728 }
729
730
731 /**
732 * wpas_dbus_signal_wps_cred - Signals new credentials
733 * @wpa_s: %wpa_supplicant network interface data
734 *
735 * Sends signal with credentials in directory argument
736 */
737 static void wpas_dbus_signal_wps_cred(struct wpa_supplicant *wpa_s,
738 const struct wps_credential *cred)
739 {
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;
748
749 iface = wpa_s->global->dbus;
750
751 /* Do nothing if the control interface is not turned on */
752 if (iface == NULL)
753 return;
754
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;
760 }
761
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;
768 }
769
770 dbus_message_iter_init_append(_signal, &iter);
771
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;
776 }
777
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";
791
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";
800
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;
809 }
810 }
811
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;
829 }
830
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;
835 }
836
837 dbus_connection_send(iface->con, _signal, NULL);
838
839 nomem:
840 dbus_message_unref(_signal);
841 }
842
843 #endif /* CONFIG_WPS */
844
845
846 /**
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
850 *
851 * Sends ProertyChanged signals with path, interface and arguments
852 * depending on which property has changed.
853 */
854 static void wpas_dbus_signal_prop_changed(struct wpa_supplicant *wpa_s,
855 enum wpas_dbus_prop property)
856 {
857 WPADBusPropertyAccessor getter;
858 char *iface;
859 char *prop;
860 void *arg;
861
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;
893 }
894
895 wpa_dbus_signal_property_changed(wpa_s->global->dbus,
896 getter, arg,
897 wpas_dbus_get_path(wpa_s), iface,
898 prop);
899 }
900
901
902 /**
903 * wpas_dbus_signal_debug_params_changed - Signals change of debug params
904 * @global: wpa_global structure
905 *
906 * Sends ProertyChanged signals informing that debug params has changed.
907 */
908 static void wpas_dbus_signal_debug_params_changed(struct wpa_global *global)
909 {
910
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");
917 }
918
919
920 struct wpas_dbus_method {
921 const char *name;
922 const char *iface;
923 WPADBusMethodHandler handler;
924 struct wpa_dbus_argument args[3];
925 };
926
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;
934 };
935
936 struct wpas_dbus_signal {
937 const char *name;
938 const char *iface;
939 struct wpa_dbus_argument args[3];
940 };
941
942
943 static void wpas_dbus_register(struct wpa_dbus_object_desc *obj_desc,
944 void *priv,
945 WPADBusArgumentFreeFunction priv_free,
946 const struct wpas_dbus_method *methods,
947 const struct wpas_dbus_property *properties,
948 const struct wpas_dbus_signal *signals)
949 {
950 int i;
951
952 obj_desc->user_data = priv;
953 obj_desc->user_data_free_func = priv_free;
954
955 for (i = 0; methods && methods[i].name; i++) {
956 wpa_dbus_method_register(obj_desc, methods[i].iface,
957 methods[i].name, methods[i].handler,
958 methods[i].args);
959 }
960
961 for (i = 0; properties && properties[i].name; i++) {
962 wpa_dbus_property_register(obj_desc, properties[i].iface,
963 properties[i].name,
964 properties[i].type,
965 properties[i].getter,
966 properties[i].setter,
967 properties[i]._access);
968 }
969
970 for (i = 0; signals && signals[i].name; i++) {
971 wpa_dbus_signal_register(obj_desc, signals[i].iface,
972 signals[i].name, signals[i].args);
973 }
974 }
975
976
977 static const struct wpas_dbus_method wpas_dbus_global_methods[] = {
978 { "CreateInterface", WPAS_DBUS_NEW_INTERFACE,
979 (WPADBusMethodHandler) &wpas_dbus_handler_create_interface,
980 {
981 { "args", "a{sv}", ARG_IN },
982 { "path", "o", ARG_OUT },
983 END_ARGS
984 }
985 },
986 { "RemoveInterface", WPAS_DBUS_NEW_INTERFACE,
987 (WPADBusMethodHandler) &wpas_dbus_handler_remove_interface,
988 {
989 { "path", "o", ARG_IN },
990 END_ARGS
991 }
992 },
993 { "GetInterface", WPAS_DBUS_NEW_INTERFACE,
994 (WPADBusMethodHandler) &wpas_dbus_handler_get_interface,
995 {
996 { "ifname", "s", ARG_IN },
997 { "path", "o", ARG_OUT },
998 END_ARGS
999 }
1000 },
1001 { NULL, NULL, NULL, { END_ARGS } }
1002 };
1003
1004 static const struct wpas_dbus_property wpas_dbus_global_properties[] = {
1005 { "DebugParams", WPAS_DBUS_NEW_INTERFACE, "(ibb)",
1006 (WPADBusPropertyAccessor) &wpas_dbus_getter_debug_params,
1007 (WPADBusPropertyAccessor) &wpas_dbus_setter_debug_params,
1008 RW
1009 },
1010 { "Interfaces", WPAS_DBUS_NEW_INTERFACE, "ao",
1011 (WPADBusPropertyAccessor) &wpas_dbus_getter_interfaces,
1012 NULL,
1013 R
1014 },
1015 { "EapMethods", WPAS_DBUS_NEW_INTERFACE, "as",
1016 wpas_dbus_getter_eap_methods,
1017 NULL,
1018 R
1019 },
1020 { NULL, NULL, NULL, NULL, NULL, 0 }
1021 };
1022
1023 static const struct wpas_dbus_signal wpas_dbus_global_signals[] = {
1024 { "InterfaceAdded", WPAS_DBUS_NEW_INTERFACE,
1025 {
1026 { "path", "o", ARG_OUT },
1027 END_ARGS
1028 }
1029 },
1030 { "InterfaceRemoved", WPAS_DBUS_NEW_INTERFACE,
1031 {
1032 { "path", "o", ARG_OUT },
1033 END_ARGS
1034 }
1035 },
1036 { "PropertiesChanged", WPAS_DBUS_NEW_INTERFACE,
1037 {
1038 { "properties", "a{sv}", ARG_OUT },
1039 END_ARGS
1040 }
1041 },
1042 { NULL, NULL, { END_ARGS } }
1043 };
1044
1045
1046 /**
1047 * wpas_dbus_ctrl_iface_init - Initialize dbus control interface
1048 * @global: Pointer to global data from wpa_supplicant_init()
1049 * Returns: 0 on success or -1 on failure
1050 *
1051 * Initialize the dbus control interface for wpa_supplicantand and start
1052 * receiving commands from external programs over the bus.
1053 */
1054 int wpas_dbus_ctrl_iface_init(struct wpas_dbus_priv *priv)
1055 {
1056 struct wpa_dbus_object_desc *obj_desc;
1057 int ret;
1058
1059 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
1060 if (!obj_desc) {
1061 wpa_printf(MSG_ERROR, "Not enough memory "
1062 "to create object description");
1063 return -1;
1064 }
1065
1066 wpas_dbus_register(obj_desc, priv->global, NULL,
1067 wpas_dbus_global_methods,
1068 wpas_dbus_global_properties,
1069 wpas_dbus_global_signals);
1070
1071 wpa_printf(MSG_DEBUG, "dbus: Register D-Bus object '%s'",
1072 WPAS_DBUS_NEW_PATH);
1073 ret = wpa_dbus_ctrl_iface_init(priv, WPAS_DBUS_NEW_PATH,
1074 WPAS_DBUS_NEW_SERVICE,
1075 obj_desc);
1076 if (ret < 0)
1077 free_dbus_object_desc(obj_desc);
1078 else
1079 priv->dbus_new_initialized = 1;
1080
1081 return ret;
1082 }
1083
1084
1085 /**
1086 * wpas_dbus_ctrl_iface_deinit - Deinitialize dbus ctrl interface for
1087 * wpa_supplicant
1088 * @iface: Pointer to dbus private data from wpas_dbus_init()
1089 *
1090 * Deinitialize the dbus control interface that was initialized with
1091 * wpas_dbus_ctrl_iface_init().
1092 */
1093 void wpas_dbus_ctrl_iface_deinit(struct wpas_dbus_priv *iface)
1094 {
1095 if (!iface->dbus_new_initialized)
1096 return;
1097 wpa_printf(MSG_DEBUG, "dbus: Unregister D-Bus object '%s'",
1098 WPAS_DBUS_NEW_PATH);
1099 dbus_connection_unregister_object_path(iface->con,
1100 WPAS_DBUS_NEW_PATH);
1101 }
1102
1103
1104 static void wpa_dbus_free(void *ptr)
1105 {
1106 os_free(ptr);
1107 }
1108
1109
1110 static const struct wpas_dbus_property wpas_dbus_network_properties[] = {
1111 { "Properties", WPAS_DBUS_NEW_IFACE_NETWORK, "a{sv}",
1112 (WPADBusPropertyAccessor) wpas_dbus_getter_network_properties,
1113 (WPADBusPropertyAccessor) wpas_dbus_setter_network_properties,
1114 RW
1115 },
1116 { "Enabled", WPAS_DBUS_NEW_IFACE_NETWORK, "b",
1117 (WPADBusPropertyAccessor) wpas_dbus_getter_enabled,
1118 (WPADBusPropertyAccessor) wpas_dbus_setter_enabled,
1119 RW
1120 },
1121 { NULL, NULL, NULL, NULL, NULL, 0 }
1122 };
1123
1124
1125 static const struct wpas_dbus_signal wpas_dbus_network_signals[] = {
1126 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_NETWORK,
1127 {
1128 { "properties", "a{sv}", ARG_OUT },
1129 END_ARGS
1130 }
1131 },
1132 { NULL, NULL, { END_ARGS } }
1133 };
1134
1135
1136 /**
1137 * wpas_dbus_register_network - Register a configured network with dbus
1138 * @wpa_s: wpa_supplicant interface structure
1139 * @ssid: network configuration data
1140 * Returns: 0 on success, -1 on failure
1141 *
1142 * Registers network representing object with dbus
1143 */
1144 static int wpas_dbus_register_network(struct wpa_supplicant *wpa_s,
1145 struct wpa_ssid *ssid)
1146 {
1147 struct wpas_dbus_priv *ctrl_iface;
1148 struct wpa_dbus_object_desc *obj_desc;
1149
1150 struct network_handler_args *arg = NULL;
1151
1152 char *net_obj_path;
1153
1154 /* Do nothing if the control interface is not turned on */
1155 if (wpa_s == NULL || wpa_s->global == NULL)
1156 return 0;
1157 ctrl_iface = wpa_s->global->dbus;
1158 if (ctrl_iface == NULL)
1159 return 0;
1160
1161 net_obj_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1162 if (net_obj_path == NULL)
1163 return -1;
1164 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1165 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
1166 wpas_dbus_get_path(wpa_s), ssid->id);
1167
1168 wpa_printf(MSG_DEBUG, "dbus: Register network object '%s'",
1169 net_obj_path);
1170 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
1171 if (!obj_desc) {
1172 wpa_printf(MSG_ERROR, "Not enough memory "
1173 "to create object description");
1174 goto err;
1175 }
1176
1177 /* allocate memory for handlers arguments */
1178 arg = os_zalloc(sizeof(struct network_handler_args));
1179 if (!arg) {
1180 wpa_printf(MSG_ERROR, "Not enough memory "
1181 "to create arguments for method");
1182 goto err;
1183 }
1184
1185 arg->wpa_s = wpa_s;
1186 arg->ssid = ssid;
1187
1188 wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
1189 wpas_dbus_network_properties,
1190 wpas_dbus_network_signals);
1191
1192 if (wpa_dbus_register_object_per_iface(ctrl_iface, net_obj_path,
1193 wpa_s->ifname, obj_desc))
1194 goto err;
1195
1196 wpas_dbus_signal_network_added(wpa_s, ssid->id);
1197
1198 os_free(net_obj_path);
1199 return 0;
1200
1201 err:
1202 os_free(net_obj_path);
1203 os_free(obj_desc);
1204 os_free(arg);
1205 return -1;
1206 }
1207
1208
1209 /**
1210 * wpas_dbus_unregister_network - Unregister a configured network from dbus
1211 * @wpa_s: wpa_supplicant interface structure
1212 * @nid: network id
1213 * Returns: 0 on success, -1 on failure
1214 *
1215 * Unregisters network representing object from dbus
1216 */
1217 static int wpas_dbus_unregister_network(struct wpa_supplicant *wpa_s, int nid)
1218 {
1219 struct wpas_dbus_priv *ctrl_iface;
1220 char *net_obj_path;
1221 int ret;
1222
1223 /* Do nothing if the control interface is not turned on */
1224 if (wpa_s == NULL || wpa_s->global == NULL)
1225 return 0;
1226 ctrl_iface = wpa_s->global->dbus;
1227 if (ctrl_iface == NULL)
1228 return 0;
1229
1230 net_obj_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1231 if (net_obj_path == NULL)
1232 return -1;
1233 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1234 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
1235 wpas_dbus_get_path(wpa_s), nid);
1236
1237 wpa_printf(MSG_DEBUG, "dbus: Unregister network object '%s'",
1238 net_obj_path);
1239 ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, net_obj_path);
1240
1241 if (!ret)
1242 wpas_dbus_signal_network_removed(wpa_s, nid);
1243
1244 os_free(net_obj_path);
1245 return ret;
1246 }
1247
1248
1249 static const struct wpas_dbus_property wpas_dbus_bss_properties[] = {
1250 { "SSID", WPAS_DBUS_NEW_IFACE_BSSID, "ay",
1251 (WPADBusPropertyAccessor) wpas_dbus_getter_bss_ssid,
1252 NULL,
1253 R
1254 },
1255 { "BSSID", WPAS_DBUS_NEW_IFACE_BSSID, "ay",
1256 (WPADBusPropertyAccessor) wpas_dbus_getter_bss_bssid,
1257 NULL,
1258 R
1259 },
1260 { "Privacy", WPAS_DBUS_NEW_IFACE_BSSID, "b",
1261 (WPADBusPropertyAccessor) wpas_dbus_getter_bss_privacy,
1262 NULL,
1263 R
1264 },
1265 { "Mode", WPAS_DBUS_NEW_IFACE_BSSID, "s",
1266 (WPADBusPropertyAccessor) wpas_dbus_getter_bss_mode,
1267 NULL,
1268 R
1269 },
1270 { "Signal", WPAS_DBUS_NEW_IFACE_BSSID, "n",
1271 (WPADBusPropertyAccessor) wpas_dbus_getter_bss_signal,
1272 NULL,
1273 R
1274 },
1275 { "Frequency", WPAS_DBUS_NEW_IFACE_BSSID, "q",
1276 (WPADBusPropertyAccessor) wpas_dbus_getter_bss_frequency,
1277 NULL,
1278 R
1279 },
1280 { "MaxRate", WPAS_DBUS_NEW_IFACE_BSSID, "q",
1281 (WPADBusPropertyAccessor) wpas_dbus_getter_bss_max_rate,
1282 NULL,
1283 R
1284 },
1285 { "WPAIE", WPAS_DBUS_NEW_IFACE_BSSID, "ay",
1286 (WPADBusPropertyAccessor) wpas_dbus_getter_bss_wpaie,
1287 NULL,
1288 R
1289 },
1290 { "RSNIE", WPAS_DBUS_NEW_IFACE_BSSID, "ay",
1291 (WPADBusPropertyAccessor) wpas_dbus_getter_bss_rsnie,
1292 NULL,
1293 R
1294 },
1295 { "WPSIE", WPAS_DBUS_NEW_IFACE_BSSID, "ay",
1296 (WPADBusPropertyAccessor) wpas_dbus_getter_bss_wpsie,
1297 NULL,
1298 R
1299 },
1300 { NULL, NULL, NULL, NULL, NULL, 0 }
1301 };
1302
1303
1304 static const struct wpas_dbus_signal wpas_dbus_bss_signals[] = {
1305 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_BSSID,
1306 {
1307 { "properties", "a{sv}", ARG_OUT },
1308 END_ARGS
1309 }
1310 },
1311 { NULL, NULL, { END_ARGS } }
1312 };
1313
1314
1315 /**
1316 * wpas_dbus_unregister_bss - Unregister a scanned BSS from dbus
1317 * @wpa_s: wpa_supplicant interface structure
1318 * @bssid: scanned network bssid
1319 * @id: unique BSS identifier
1320 * Returns: 0 on success, -1 on failure
1321 *
1322 * Unregisters BSS representing object from dbus
1323 */
1324 static int wpas_dbus_unregister_bss(struct wpa_supplicant *wpa_s,
1325 u8 bssid[ETH_ALEN], unsigned int id)
1326 {
1327 struct wpas_dbus_priv *ctrl_iface;
1328 char *bss_obj_path;
1329
1330 /* Do nothing if the control interface is not turned on */
1331 if (wpa_s == NULL || wpa_s->global == NULL)
1332 return 0;
1333 ctrl_iface = wpa_s->global->dbus;
1334 if (ctrl_iface == NULL)
1335 return 0;
1336
1337 bss_obj_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1338 if (bss_obj_path == NULL)
1339 return -1;
1340
1341 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1342 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
1343 wpas_dbus_get_path(wpa_s), id);
1344
1345 wpa_printf(MSG_DEBUG, "dbus: Unregister BSS object '%s'",
1346 bss_obj_path);
1347 if (wpa_dbus_unregister_object_per_iface(ctrl_iface, bss_obj_path)) {
1348 wpa_printf(MSG_ERROR,
1349 "Cannot unregister BSSID dbus object %s.",
1350 bss_obj_path);
1351 os_free(bss_obj_path);
1352 return -1;
1353 }
1354
1355 wpas_dbus_signal_bss_removed(wpa_s, bss_obj_path);
1356
1357 os_free(bss_obj_path);
1358 return 0;
1359 }
1360
1361
1362 /**
1363 * wpas_dbus_register_bss - Register a scanned BSS with dbus
1364 * @wpa_s: wpa_supplicant interface structure
1365 * @bssid: scanned network bssid
1366 * @id: unique BSS identifier
1367 * Returns: 0 on success, -1 on failure
1368 *
1369 * Registers BSS representing object with dbus
1370 */
1371 static int wpas_dbus_register_bss(struct wpa_supplicant *wpa_s,
1372 u8 bssid[ETH_ALEN], unsigned int id)
1373 {
1374 struct wpas_dbus_priv *ctrl_iface;
1375 struct wpa_dbus_object_desc *obj_desc;
1376 char *bss_obj_path;
1377
1378 struct bss_handler_args *arg = NULL;
1379
1380 /* Do nothing if the control interface is not turned on */
1381 if (wpa_s == NULL || wpa_s->global == NULL)
1382 return 0;
1383 ctrl_iface = wpa_s->global->dbus;
1384 if (ctrl_iface == NULL)
1385 return 0;
1386
1387 bss_obj_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1388 if (bss_obj_path == NULL)
1389 return -1;
1390
1391 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1392 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
1393 wpas_dbus_get_path(wpa_s), id);
1394
1395 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
1396 if (!obj_desc) {
1397 wpa_printf(MSG_ERROR, "Not enough memory "
1398 "to create object description");
1399 goto err;
1400 }
1401
1402 arg = os_zalloc(sizeof(struct bss_handler_args));
1403 if (!arg) {
1404 wpa_printf(MSG_ERROR, "Not enough memory "
1405 "to create arguments for handler");
1406 goto err;
1407 }
1408 arg->wpa_s = wpa_s;
1409 arg->id = id;
1410
1411 wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
1412 wpas_dbus_bss_properties,
1413 wpas_dbus_bss_signals);
1414
1415 wpa_printf(MSG_DEBUG, "dbus: Register BSS object '%s'",
1416 bss_obj_path);
1417 if (wpa_dbus_register_object_per_iface(ctrl_iface, bss_obj_path,
1418 wpa_s->ifname, obj_desc)) {
1419 wpa_printf(MSG_ERROR,
1420 "Cannot register BSSID dbus object %s.",
1421 bss_obj_path);
1422 goto err;
1423 }
1424
1425 wpas_dbus_signal_bss_added(wpa_s, bss_obj_path);
1426
1427 os_free(bss_obj_path);
1428 return 0;
1429
1430 err:
1431 os_free(bss_obj_path);
1432 os_free(obj_desc);
1433 os_free(arg);
1434 return -1;
1435 }
1436
1437
1438 static const struct wpas_dbus_method wpas_dbus_interface_methods[] = {
1439 { "Scan", WPAS_DBUS_NEW_IFACE_INTERFACE,
1440 (WPADBusMethodHandler) &wpas_dbus_handler_scan,
1441 {
1442 { "args", "a{sv}", ARG_IN },
1443 END_ARGS
1444 }
1445 },
1446 { "Disconnect", WPAS_DBUS_NEW_IFACE_INTERFACE,
1447 (WPADBusMethodHandler) &wpas_dbus_handler_disconnect,
1448 {
1449 END_ARGS
1450 }
1451 },
1452 { "AddNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
1453 (WPADBusMethodHandler) &wpas_dbus_handler_add_network,
1454 {
1455 { "args", "a{sv}", ARG_IN },
1456 { "path", "o", ARG_OUT },
1457 END_ARGS
1458 }
1459 },
1460 { "RemoveNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
1461 (WPADBusMethodHandler) &wpas_dbus_handler_remove_network,
1462 {
1463 { "path", "o", ARG_IN },
1464 END_ARGS
1465 }
1466 },
1467 { "SelectNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
1468 (WPADBusMethodHandler) &wpas_dbus_handler_select_network,
1469 {
1470 { "path", "o", ARG_IN },
1471 END_ARGS
1472 }
1473 },
1474 { "AddBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
1475 (WPADBusMethodHandler) &wpas_dbus_handler_add_blob,
1476 {
1477 { "name", "s", ARG_IN },
1478 { "data", "ay", ARG_IN },
1479 END_ARGS
1480 }
1481 },
1482 { "GetBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
1483 (WPADBusMethodHandler) &wpas_dbus_handler_get_blob,
1484 {
1485 { "name", "s", ARG_IN },
1486 { "data", "ay", ARG_OUT },
1487 END_ARGS
1488 }
1489 },
1490 { "RemoveBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
1491 (WPADBusMethodHandler) &wpas_dbus_handler_remove_blob,
1492 {
1493 { "name", "s", ARG_IN },
1494 END_ARGS
1495 }
1496 },
1497 #ifdef CONFIG_WPS
1498 { "Start", WPAS_DBUS_NEW_IFACE_WPS,
1499 (WPADBusMethodHandler) &wpas_dbus_handler_wps_start,
1500 {
1501 { "args", "a{sv}", ARG_IN },
1502 { "output", "a{sv}", ARG_OUT },
1503 END_ARGS
1504 }
1505 },
1506 #endif /* CONFIG_WPS */
1507 { NULL, NULL, NULL, { END_ARGS } }
1508 };
1509
1510 static const struct wpas_dbus_property wpas_dbus_interface_properties[] = {
1511 { "Capabilities", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{sv}",
1512 (WPADBusPropertyAccessor) wpas_dbus_getter_capabilities,
1513 NULL, R
1514 },
1515 { "State", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
1516 (WPADBusPropertyAccessor) wpas_dbus_getter_state,
1517 NULL, R
1518 },
1519 { "Scanning", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
1520 (WPADBusPropertyAccessor) wpas_dbus_getter_scanning,
1521 NULL, R
1522 },
1523 { "ApScan", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
1524 (WPADBusPropertyAccessor) wpas_dbus_getter_ap_scan,
1525 (WPADBusPropertyAccessor) wpas_dbus_setter_ap_scan,
1526 RW
1527 },
1528 { "Ifname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
1529 (WPADBusPropertyAccessor) wpas_dbus_getter_ifname,
1530 NULL, R
1531 },
1532 { "Driver", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
1533 (WPADBusPropertyAccessor) wpas_dbus_getter_driver,
1534 NULL, R
1535 },
1536 { "BridgeIfname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
1537 (WPADBusPropertyAccessor) wpas_dbus_getter_bridge_ifname,
1538 NULL, R
1539 },
1540 { "CurrentBSS", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
1541 (WPADBusPropertyAccessor) wpas_dbus_getter_current_bss,
1542 NULL, R
1543 },
1544 { "CurrentNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
1545 (WPADBusPropertyAccessor) wpas_dbus_getter_current_network,
1546 NULL, R
1547 },
1548 { "Blobs", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{say}",
1549 (WPADBusPropertyAccessor) wpas_dbus_getter_blobs,
1550 NULL, R
1551 },
1552 { "BSSs", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
1553 (WPADBusPropertyAccessor) wpas_dbus_getter_bsss,
1554 NULL, R
1555 },
1556 { "Networks", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
1557 (WPADBusPropertyAccessor) wpas_dbus_getter_networks,
1558 NULL, R
1559 },
1560 #ifdef CONFIG_WPS
1561 { "ProcessCredentials", WPAS_DBUS_NEW_IFACE_WPS, "b",
1562 (WPADBusPropertyAccessor) wpas_dbus_getter_process_credentials,
1563 (WPADBusPropertyAccessor) wpas_dbus_setter_process_credentials,
1564 RW
1565 },
1566 #endif /* CONFIG_WPS */
1567 { NULL, NULL, NULL, NULL, NULL, 0 }
1568 };
1569
1570 static const struct wpas_dbus_signal wpas_dbus_interface_signals[] = {
1571 { "ScanDone", WPAS_DBUS_NEW_IFACE_INTERFACE,
1572 {
1573 { "success", "b", ARG_OUT },
1574 END_ARGS
1575 }
1576 },
1577 { "StateChanged", WPAS_DBUS_NEW_IFACE_INTERFACE,
1578 {
1579 { "newState", "s", ARG_OUT },
1580 { "oldState", "s", ARG_OUT },
1581 END_ARGS
1582 }
1583 },
1584 { "BSSAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
1585 {
1586 { "path", "o", ARG_OUT },
1587 END_ARGS
1588 }
1589 },
1590 { "BSSRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
1591 {
1592 { "path", "o", ARG_OUT },
1593 END_ARGS
1594 }
1595 },
1596 { "BlobAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
1597 {
1598 { "name", "s", ARG_OUT },
1599 END_ARGS
1600 }
1601 },
1602 { "BlobRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
1603 {
1604 { "name", "s", ARG_OUT },
1605 END_ARGS
1606 }
1607 },
1608 { "NetworkAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
1609 {
1610 { "path", "o", ARG_OUT },
1611 END_ARGS
1612 }
1613 },
1614 { "NetworkRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
1615 {
1616 { "path", "o", ARG_OUT },
1617 END_ARGS
1618 }
1619 },
1620 { "NetworkSelected", WPAS_DBUS_NEW_IFACE_INTERFACE,
1621 {
1622 { "path", "o", ARG_OUT },
1623 END_ARGS
1624 }
1625 },
1626 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_INTERFACE,
1627 {
1628 { "properties", "a{sv}", ARG_OUT },
1629 END_ARGS
1630 }
1631 },
1632 #ifdef CONFIG_WPS
1633 { "Event", WPAS_DBUS_NEW_IFACE_WPS,
1634 {
1635 { "name", "s", ARG_OUT },
1636 { "args", "a{sv}", ARG_OUT },
1637 END_ARGS
1638 }
1639 },
1640 { "Credentials", WPAS_DBUS_NEW_IFACE_WPS,
1641 {
1642 { "credentials", "a{sv}", ARG_OUT },
1643 END_ARGS
1644 }
1645 },
1646 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_WPS,
1647 {
1648 { "properties", "a{sv}", ARG_OUT },
1649 END_ARGS
1650 }
1651 },
1652 #endif /* CONFIG_WPS */
1653 { NULL, NULL, { END_ARGS } }
1654 };
1655
1656
1657 static int wpas_dbus_register_interface(struct wpa_supplicant *wpa_s)
1658 {
1659
1660 struct wpa_dbus_object_desc *obj_desc = NULL;
1661 char *path;
1662 struct wpas_dbus_priv *ctrl_iface = wpa_s->global->dbus;
1663 int next;
1664
1665 /* Do nothing if the control interface is not turned on */
1666 if (ctrl_iface == NULL)
1667 return 0;
1668
1669 /* Create and set the interface's object path */
1670 path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1671 if (path == NULL)
1672 return -1;
1673 next = ctrl_iface->next_objid++;
1674 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
1675 WPAS_DBUS_NEW_PATH_INTERFACES "/%u",
1676 next);
1677 if (wpas_dbus_set_path(wpa_s, path)) {
1678 wpa_printf(MSG_DEBUG,
1679 "Failed to set dbus path for interface %s",
1680 wpa_s->ifname);
1681 goto err;
1682 }
1683
1684 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
1685 if (!obj_desc) {
1686 wpa_printf(MSG_ERROR, "Not enough memory "
1687 "to create object description");
1688 goto err;
1689 }
1690
1691 wpas_dbus_register(obj_desc, wpa_s, NULL, wpas_dbus_interface_methods,
1692 wpas_dbus_interface_properties,
1693 wpas_dbus_interface_signals);
1694
1695 wpa_printf(MSG_DEBUG, "dbus: Register interface object '%s'", path);
1696 if (wpa_dbus_register_object_per_iface(ctrl_iface, path, wpa_s->ifname,
1697 obj_desc))
1698 goto err;
1699
1700 wpas_dbus_signal_interface_created(wpa_s);
1701
1702 os_free(path);
1703 return 0;
1704
1705 err:
1706 os_free(obj_desc);
1707 os_free(path);
1708 return -1;
1709 }
1710
1711
1712 static int wpas_dbus_unregister_interface(struct wpa_supplicant *wpa_s)
1713 {
1714 struct wpas_dbus_priv *ctrl_iface;
1715
1716 /* Do nothing if the control interface is not turned on */
1717 if (wpa_s == NULL || wpa_s->global == NULL)
1718 return 0;
1719 ctrl_iface = wpa_s->global->dbus;
1720 if (ctrl_iface == NULL)
1721 return 0;
1722
1723 wpa_printf(MSG_DEBUG, "dbus: Unregister interface object '%s'",
1724 wpas_dbus_get_path(wpa_s));
1725 if (wpa_dbus_unregister_object_per_iface(ctrl_iface,
1726 wpas_dbus_get_path(wpa_s)))
1727 return -1;
1728
1729 wpas_dbus_signal_interface_removed(wpa_s);
1730
1731 os_free(wpa_s->dbus_new_path);
1732 wpa_s->dbus_new_path = NULL;
1733
1734 return 0;
1735 }
1736
1737
1738 static struct wpas_dbus_callbacks callbacks =
1739 {
1740 .signal_interface_created = wpas_dbus_signal_interface_created,
1741 .signal_interface_removed = wpas_dbus_signal_interface_removed,
1742
1743 .register_interface = wpas_dbus_register_interface,
1744 .unregister_interface = wpas_dbus_unregister_interface,
1745
1746 .signal_scan_done = wpas_dbus_signal_scan_done,
1747
1748 .signal_blob_added = wpas_dbus_signal_blob_added,
1749 .signal_blob_removed = wpas_dbus_signal_blob_removed,
1750
1751 .signal_network_selected = wpas_dbus_signal_network_selected,
1752
1753 .signal_state_changed = wpas_dbus_signal_state_changed,
1754 .register_network = wpas_dbus_register_network,
1755 .unregister_network = wpas_dbus_unregister_network,
1756
1757 .signal_network_enabled_changed =
1758 wpas_dbus_signal_network_enabled_changed,
1759
1760 .register_bss = wpas_dbus_register_bss,
1761 .unregister_bss = wpas_dbus_unregister_bss,
1762
1763 .signal_prop_changed = wpas_dbus_signal_prop_changed,
1764 .signal_debug_params_changed = wpas_dbus_signal_debug_params_changed,
1765
1766 #ifdef CONFIG_WPS
1767 .signal_wps_event_success = wpas_dbus_signal_wps_event_success,
1768 .signal_wps_event_fail = wpas_dbus_signal_wps_event_fail,
1769 .signal_wps_event_m2d = wpas_dbus_signal_wps_event_m2d,
1770 .signal_wps_credentials = wpas_dbus_signal_wps_cred,
1771 #endif /* CONFIG_WPS */
1772 };
1773
1774
1775 struct wpas_dbus_callbacks * wpas_dbus_get_callbacks(void)
1776 {
1777 return &callbacks;
1778 }
1779
1780
1781 /**
1782 * wpas_dbus_get_path - Get an interface's dbus path
1783 * @wpa_s: %wpa_supplicant interface structure
1784 * Returns: Interface's dbus object path, or %NULL on error
1785 */
1786 const char * wpas_dbus_get_path(struct wpa_supplicant *wpa_s)
1787 {
1788 return wpa_s->dbus_new_path;
1789 }