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