]> git.ipfire.org Git - thirdparty/hostap.git/blame - wpa_supplicant/dbus/dbus_new.c
dbus: Add example script for fetching all properties with Getall
[thirdparty/hostap.git] / wpa_supplicant / dbus / dbus_new.c
CommitLineData
8fc2fb56
WS
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>
ccd286d0 5 * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
8fc2fb56
WS
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"
8fc2fb56 20#include "wps/wps.h"
a206a29a
JM
21#include "../config.h"
22#include "../wpa_supplicant_i.h"
ccd286d0 23#include "../bss.h"
a206a29a 24#include "dbus_new_helpers.h"
8fc2fb56 25#include "dbus_dict_helpers.h"
a206a29a
JM
26#include "dbus_new.h"
27#include "dbus_new_handlers.h"
8ddef94b
JM
28#include "dbus_common.h"
29#include "dbus_common_i.h"
8fc2fb56
WS
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
17efbfac 35 * Returns: 0 on success, -1 on error
8fc2fb56
WS
36 */
37static 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 */
57static void wpas_dbus_signal_interface(struct wpa_supplicant *wpa_s,
58 const char *sig_name)
59{
8ddef94b 60 struct wpas_dbus_priv *iface;
8fc2fb56
WS
61 DBusMessage *_signal;
62 const char *path;
63
8ddef94b 64 iface = wpa_s->global->dbus;
8fc2fb56
WS
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 */
102static 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 */
114static 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 */
128static void wpas_dbus_signal_scan_done(struct wpa_supplicant *wpa_s,
129 int success)
130{
8ddef94b 131 struct wpas_dbus_priv *iface;
8fc2fb56
WS
132 DBusMessage *_signal;
133 const char *path;
134 dbus_bool_t succ;
135
8ddef94b 136 iface = wpa_s->global->dbus;
8fc2fb56
WS
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 */
177static void wpas_dbus_signal_bss(struct wpa_supplicant *wpa_s,
178 const char *bss_obj_path,
179 const char *sig_name)
180{
8ddef94b 181 struct wpas_dbus_priv *iface;
8fc2fb56
WS
182 DBusMessage *_signal;
183 const char *path;
184
8ddef94b 185 iface = wpa_s->global->dbus;
8fc2fb56
WS
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 */
224static 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 */
238static 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 */
253static void wpas_dbus_signal_blob(struct wpa_supplicant *wpa_s,
254 const char *name, const char *sig_name)
255{
8ddef94b 256 struct wpas_dbus_priv *iface;
8fc2fb56
WS
257 DBusMessage *_signal;
258 const char *path;
259
8ddef94b 260 iface = wpa_s->global->dbus;
8fc2fb56
WS
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 */
299static 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 */
313static 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 */
328static void wpas_dbus_signal_network(struct wpa_supplicant *wpa_s,
329 int id, const char *sig_name)
330{
8ddef94b 331 struct wpas_dbus_priv *iface;
8fc2fb56
WS
332 DBusMessage *_signal;
333 const char *path;
334 char *net_obj_path;
335
8ddef94b 336 iface = wpa_s->global->dbus;
8fc2fb56
WS
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 */
385static 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/**
17efbfac 393 * wpas_dbus_signal_network_removed - Send a network removed signal
8fc2fb56
WS
394 * @wpa_s: %wpa_supplicant network interface data
395 * @id: network id
396 *
397 * Notify listeners about removing a network
398 */
399static 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 */
413static 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 */
428static void wpas_dbus_signal_state_changed(struct wpa_supplicant *wpa_s,
71934751
JM
429 enum wpa_states new_state,
430 enum wpa_states old_state)
8fc2fb56 431{
8ddef94b 432 struct wpas_dbus_priv *iface;
8fc2fb56
WS
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;
8ddef94b 441 iface = wpa_s->global->dbus;
8fc2fb56
WS
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
509out:
510 dbus_message_unref(_signal);
511 os_free(new_state_str);
512 os_free(old_state_str);
513}
514
515
516/**
17efbfac 517 * wpas_dbus_signal_network_enabled_changed - Signals Enabled property changes
8fc2fb56
WS
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 */
524static 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
8ddef94b 535 wpa_dbus_signal_property_changed(wpa_s->global->dbus,
8fc2fb56
WS
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 */
551static void wpas_dbus_signal_wps_event_success(struct wpa_supplicant *wpa_s)
552{
553
3864e6ea 554 DBusMessage *_signal = NULL;
8fc2fb56 555 DBusMessageIter iter, dict_iter;
8ddef94b 556 struct wpas_dbus_priv *iface;
8fc2fb56 557 char *key = "success";
3864e6ea 558 const char *path;
8fc2fb56 559
8ddef94b 560 iface = wpa_s->global->dbus;
8fc2fb56
WS
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);
592out:
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 */
604static void wpas_dbus_signal_wps_event_fail(struct wpa_supplicant *wpa_s,
605 struct wps_event_fail *fail)
606{
607
3864e6ea 608 DBusMessage *_signal = NULL;
8fc2fb56 609 DBusMessageIter iter, dict_iter;
8ddef94b 610 struct wpas_dbus_priv *iface;
3864e6ea
JM
611 char *key = "fail";
612 const char *path;
8fc2fb56 613
8ddef94b 614 iface = wpa_s->global->dbus;
8fc2fb56
WS
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);
647out:
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 */
659static void wpas_dbus_signal_wps_event_m2d(struct wpa_supplicant *wpa_s,
660 struct wps_event_m2d *m2d)
661{
662
3864e6ea 663 DBusMessage *_signal = NULL;
8fc2fb56 664 DBusMessageIter iter, dict_iter;
8ddef94b 665 struct wpas_dbus_priv *iface;
3864e6ea
JM
666 char *key = "m2d";
667 const char *path;
8fc2fb56 668
8ddef94b 669 iface = wpa_s->global->dbus;
8fc2fb56
WS
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);
726out:
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 */
737static 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;
8ddef94b 742 struct wpas_dbus_priv *iface;
8fc2fb56
WS
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
8ddef94b 749 iface = wpa_s->global->dbus;
8fc2fb56
WS
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
839nomem:
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 */
854static 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
8ddef94b 895 wpa_dbus_signal_property_changed(wpa_s->global->dbus,
8fc2fb56
WS
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 */
908static void wpas_dbus_signal_debug_params_changed(struct wpa_global *global)
909{
910
8ddef94b 911 wpa_dbus_signal_property_changed(global->dbus,
8fc2fb56
WS
912 (WPADBusPropertyAccessor)
913 wpas_dbus_getter_debug_params,
914 global, WPAS_DBUS_NEW_PATH,
915 WPAS_DBUS_NEW_INTERFACE,
916 "DebugParams");
917}
918
919
9b61515c
JM
920struct wpas_dbus_method {
921 const char *name;
922 const char *iface;
923 WPADBusMethodHandler handler;
924 struct wpa_dbus_argument args[3];
925};
926
927struct 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
936struct wpas_dbus_signal {
937 const char *name;
938 const char *iface;
939 struct wpa_dbus_argument args[3];
940};
941
942
943static void wpas_dbus_register(struct wpa_dbus_object_desc *obj_desc,
944 void *priv,
945 const struct wpas_dbus_method *methods,
946 const struct wpas_dbus_property *properties,
947 const struct wpas_dbus_signal *signals)
7ae7b192 948{
9b61515c 949 int i;
7ae7b192 950
9b61515c
JM
951 for (i = 0; methods && methods[i].name; i++) {
952 wpa_dbus_method_register(obj_desc, methods[i].iface,
953 methods[i].name, methods[i].handler,
954 priv, NULL, methods[i].args);
955 }
7ae7b192 956
9b61515c
JM
957 for (i = 0; properties && properties[i].name; i++) {
958 wpa_dbus_property_register(obj_desc, properties[i].iface,
959 properties[i].name,
960 properties[i].type,
961 properties[i].getter,
962 properties[i].setter,
963 priv, NULL, properties[i]._access);
964 }
7ae7b192 965
9b61515c
JM
966 for (i = 0; signals && signals[i].name; i++) {
967 wpa_dbus_signal_register(obj_desc, signals[i].iface,
968 signals[i].name, signals[i].args);
969 }
7ae7b192
JM
970}
971
972
9b61515c
JM
973static const struct wpas_dbus_method wpas_dbus_global_methods[] = {
974 { "CreateInterface", WPAS_DBUS_NEW_INTERFACE,
975 (WPADBusMethodHandler) &wpas_dbus_handler_create_interface,
976 {
977 { "args", "a{sv}", ARG_IN },
978 { "path", "o", ARG_OUT },
979 END_ARGS
980 }
981 },
982 { "RemoveInterface", WPAS_DBUS_NEW_INTERFACE,
983 (WPADBusMethodHandler) &wpas_dbus_handler_remove_interface,
984 {
985 { "path", "o", ARG_IN },
986 END_ARGS
987 }
988 },
989 { "GetInterface", WPAS_DBUS_NEW_INTERFACE,
990 (WPADBusMethodHandler) &wpas_dbus_handler_get_interface,
991 {
992 { "ifname", "s", ARG_IN },
993 { "path", "o", ARG_OUT },
994 END_ARGS
995 }
996 },
997 { NULL, NULL, NULL, { END_ARGS } }
998};
999
1000static const struct wpas_dbus_property wpas_dbus_global_properties[] = {
1001 { "DebugParams", WPAS_DBUS_NEW_INTERFACE, "(ibb)",
1002 (WPADBusPropertyAccessor) &wpas_dbus_getter_debug_params,
1003 (WPADBusPropertyAccessor) &wpas_dbus_setter_debug_params,
1004 RW
1005 },
1006 { "Interfaces", WPAS_DBUS_NEW_INTERFACE, "ao",
1007 (WPADBusPropertyAccessor) &wpas_dbus_getter_interfaces,
1008 NULL,
1009 R
1010 },
1011 { "EapMethods", WPAS_DBUS_NEW_INTERFACE, "as",
1012 wpas_dbus_getter_eap_methods,
1013 NULL,
1014 R
1015 },
1016 { NULL, NULL, NULL, NULL, NULL, 0 }
1017};
1018
1019static const struct wpas_dbus_signal wpas_dbus_global_signals[] = {
1020 { "InterfaceAdded", WPAS_DBUS_NEW_INTERFACE,
1021 {
1022 { "path", "o", ARG_OUT },
1023 END_ARGS
1024 }
1025 },
1026 { "InterfaceRemoved", WPAS_DBUS_NEW_INTERFACE,
1027 {
1028 { "path", "o", ARG_OUT },
1029 END_ARGS
1030 }
1031 },
1032 { "PropertiesChanged", WPAS_DBUS_NEW_INTERFACE,
1033 {
1034 { "properties", "a{sv}", ARG_OUT },
1035 END_ARGS
1036 }
1037 },
1038 { NULL, NULL, { END_ARGS } }
1039};
7ae7b192
JM
1040
1041
1042/**
1043 * wpas_dbus_ctrl_iface_init - Initialize dbus control interface
1044 * @global: Pointer to global data from wpa_supplicant_init()
8ddef94b 1045 * Returns: 0 on success or -1 on failure
7ae7b192
JM
1046 *
1047 * Initialize the dbus control interface for wpa_supplicantand and start
1048 * receiving commands from external programs over the bus.
1049 */
8ddef94b 1050int wpas_dbus_ctrl_iface_init(struct wpas_dbus_priv *priv)
7ae7b192 1051{
7ae7b192 1052 struct wpa_dbus_object_desc *obj_desc;
8ddef94b 1053 int ret;
8fc2fb56
WS
1054
1055 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
1056 if (!obj_desc) {
1057 wpa_printf(MSG_ERROR, "Not enough memory "
1058 "to create object description");
8ddef94b 1059 return -1;
8fc2fb56
WS
1060 }
1061
8ddef94b 1062 wpas_dbus_register(obj_desc, priv->global, wpas_dbus_global_methods,
9b61515c
JM
1063 wpas_dbus_global_properties,
1064 wpas_dbus_global_signals);
8fc2fb56 1065
8e56d189
JM
1066 wpa_printf(MSG_DEBUG, "dbus: Register D-Bus object '%s'",
1067 WPAS_DBUS_NEW_PATH);
8ddef94b
JM
1068 ret = wpa_dbus_ctrl_iface_init(priv, WPAS_DBUS_NEW_PATH,
1069 WPAS_DBUS_NEW_SERVICE,
1070 obj_desc);
1071 if (ret < 0)
8fc2fb56 1072 free_dbus_object_desc(obj_desc);
26e054ce
JM
1073 else
1074 priv->dbus_new_initialized = 1;
8fc2fb56 1075
8ddef94b 1076 return ret;
8fc2fb56
WS
1077}
1078
1079
1080/**
1081 * wpas_dbus_ctrl_iface_deinit - Deinitialize dbus ctrl interface for
1082 * wpa_supplicant
8ddef94b 1083 * @iface: Pointer to dbus private data from wpas_dbus_init()
8fc2fb56
WS
1084 *
1085 * Deinitialize the dbus control interface that was initialized with
1086 * wpas_dbus_ctrl_iface_init().
1087 */
8ddef94b 1088void wpas_dbus_ctrl_iface_deinit(struct wpas_dbus_priv *iface)
8fc2fb56 1089{
26e054ce
JM
1090 if (!iface->dbus_new_initialized)
1091 return;
8ddef94b
JM
1092 wpa_printf(MSG_DEBUG, "dbus: Unregister D-Bus object '%s'",
1093 WPAS_DBUS_NEW_PATH);
1094 dbus_connection_unregister_object_path(iface->con,
1095 WPAS_DBUS_NEW_PATH);
8fc2fb56
WS
1096}
1097
1098
d114fcab
JM
1099static void wpa_dbus_free(void *ptr)
1100{
1101 os_free(ptr);
1102}
1103
1104
8fc2fb56
WS
1105/**
1106 * wpas_dbus_register_network - Register a configured network with dbus
1107 * @wpa_s: wpa_supplicant interface structure
1108 * @ssid: network configuration data
1109 * Returns: 0 on success, -1 on failure
1110 *
1111 * Registers network representing object with dbus
1112 */
1113static int wpas_dbus_register_network(struct wpa_supplicant *wpa_s,
1114 struct wpa_ssid *ssid)
1115{
8ddef94b 1116 struct wpas_dbus_priv *ctrl_iface;
8fc2fb56
WS
1117 struct wpa_dbus_object_desc *obj_desc;
1118
1119 struct network_handler_args *arg1 = NULL;
1120 struct network_handler_args *arg2 = NULL;
8fc2fb56 1121
8fc2fb56
WS
1122 char *net_obj_path;
1123
1124 struct wpa_dbus_argument sargs[] = {
1125 { "properties", "a{sv}", ARG_OUT },
1126 END_ARGS
1127 };
1128
1129 /* Do nothing if the control interface is not turned on */
1130 if (wpa_s == NULL || wpa_s->global == NULL)
1131 return 0;
8ddef94b 1132 ctrl_iface = wpa_s->global->dbus;
8fc2fb56
WS
1133 if (ctrl_iface == NULL)
1134 return 0;
1135
1136 net_obj_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1137 if (net_obj_path == NULL)
1138 return -1;
1139 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
d69780dc
JM
1140 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
1141 wpas_dbus_get_path(wpa_s), ssid->id);
8fc2fb56 1142
8e56d189
JM
1143 wpa_printf(MSG_DEBUG, "dbus: Register network object '%s'",
1144 net_obj_path);
8fc2fb56
WS
1145 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
1146 if (!obj_desc) {
1147 wpa_printf(MSG_ERROR, "Not enough memory "
1148 "to create object description");
1149 goto err;
1150 }
1151
1152 /* allocate memory for handlers arguments */
1153 arg1 = os_zalloc(sizeof(struct network_handler_args));
1154 if (!arg1) {
1155 wpa_printf(MSG_ERROR, "Not enough memory "
1156 "to create arguments for method");
1157 goto err;
1158 }
1159 arg2 = os_zalloc(sizeof(struct network_handler_args));
1160 if (!arg2) {
1161 wpa_printf(MSG_ERROR, "Not enough memory "
1162 "to create arguments for method");
1163 goto err;
1164 }
1165
1166 arg1->wpa_s = wpa_s;
1167 arg1->ssid = ssid;
1168 arg2->wpa_s = wpa_s;
1169 arg2->ssid = ssid;
1170
1171 /* Enabled property */
485ec2ae
JM
1172 wpa_dbus_property_register(obj_desc, WPAS_DBUS_NEW_IFACE_NETWORK,
1173 "Enabled", "b",
1174 (WPADBusPropertyAccessor)
1175 wpas_dbus_getter_enabled,
1176 (WPADBusPropertyAccessor)
1177 wpas_dbus_setter_enabled,
d114fcab 1178 arg1, wpa_dbus_free, RW);
8fc2fb56
WS
1179
1180 /* Properties property */
485ec2ae
JM
1181 wpa_dbus_property_register(obj_desc, WPAS_DBUS_NEW_IFACE_NETWORK,
1182 "Properties", "a{sv}",
1183 (WPADBusPropertyAccessor)
1184 wpas_dbus_getter_network_properties,
1185 (WPADBusPropertyAccessor)
1186 wpas_dbus_setter_network_properties,
d114fcab 1187 arg2, wpa_dbus_free, RW);
8fc2fb56
WS
1188
1189 /* PropertiesChanged signal */
485ec2ae
JM
1190 wpa_dbus_signal_register(obj_desc, WPAS_DBUS_NEW_IFACE_NETWORK,
1191 "PropertiesChanged", sargs);
8fc2fb56
WS
1192
1193 if (wpa_dbus_register_object_per_iface(ctrl_iface, net_obj_path,
1194 wpa_s->ifname, obj_desc))
1195 goto err;
1196
1197 wpas_dbus_signal_network_added(wpa_s, ssid->id);
1198
1199 os_free(net_obj_path);
1200 return 0;
1201
1202err:
1203 os_free(net_obj_path);
1204 os_free(obj_desc);
1205 os_free(arg1);
1206 os_free(arg2);
8fc2fb56
WS
1207 return -1;
1208}
1209
1210
1211/**
1212 * wpas_dbus_unregister_network - Unregister a configured network from dbus
1213 * @wpa_s: wpa_supplicant interface structure
1214 * @nid: network id
1215 * Returns: 0 on success, -1 on failure
1216 *
1217 * Unregisters network representing object from dbus
1218 */
1219static int wpas_dbus_unregister_network(struct wpa_supplicant *wpa_s, int nid)
1220{
8ddef94b 1221 struct wpas_dbus_priv *ctrl_iface;
8fc2fb56
WS
1222 char *net_obj_path;
1223 int ret;
1224
1225 /* Do nothing if the control interface is not turned on */
1226 if (wpa_s == NULL || wpa_s->global == NULL)
1227 return 0;
8ddef94b 1228 ctrl_iface = wpa_s->global->dbus;
8fc2fb56
WS
1229 if (ctrl_iface == NULL)
1230 return 0;
1231
1232 net_obj_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1233 if (net_obj_path == NULL)
1234 return -1;
1235 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
d69780dc
JM
1236 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
1237 wpas_dbus_get_path(wpa_s), nid);
8fc2fb56 1238
8e56d189
JM
1239 wpa_printf(MSG_DEBUG, "dbus: Unregister network object '%s'",
1240 net_obj_path);
8fc2fb56
WS
1241 ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, net_obj_path);
1242
1243 if (!ret)
1244 wpas_dbus_signal_network_removed(wpa_s, nid);
1245
1246 os_free(net_obj_path);
1247 return ret;
1248}
1249
1250
1251/**
17efbfac 1252 * wpas_dbus_unregister_bss - Unregister a scanned BSS from dbus
8fc2fb56
WS
1253 * @wpa_s: wpa_supplicant interface structure
1254 * @bssid: scanned network bssid
ccd286d0 1255 * @id: unique BSS identifier
8fc2fb56
WS
1256 * Returns: 0 on success, -1 on failure
1257 *
17efbfac 1258 * Unregisters BSS representing object from dbus
8fc2fb56
WS
1259 */
1260static int wpas_dbus_unregister_bss(struct wpa_supplicant *wpa_s,
ccd286d0 1261 u8 bssid[ETH_ALEN], unsigned int id)
8fc2fb56 1262{
8ddef94b 1263 struct wpas_dbus_priv *ctrl_iface;
8fc2fb56
WS
1264 char *bss_obj_path;
1265
1266 /* Do nothing if the control interface is not turned on */
1267 if (wpa_s == NULL || wpa_s->global == NULL)
1268 return 0;
8ddef94b 1269 ctrl_iface = wpa_s->global->dbus;
8fc2fb56
WS
1270 if (ctrl_iface == NULL)
1271 return 0;
1272
1273 bss_obj_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1274 if (bss_obj_path == NULL)
1275 return -1;
1276
1277 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
ccd286d0
JM
1278 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
1279 wpas_dbus_get_path(wpa_s), id);
8fc2fb56 1280
8e56d189
JM
1281 wpa_printf(MSG_DEBUG, "dbus: Unregister BSS object '%s'",
1282 bss_obj_path);
8fc2fb56
WS
1283 if (wpa_dbus_unregister_object_per_iface(ctrl_iface, bss_obj_path)) {
1284 wpa_printf(MSG_ERROR,
1285 "Cannot unregister BSSID dbus object %s.",
1286 bss_obj_path);
1287 os_free(bss_obj_path);
1288 return -1;
1289 }
1290
1291 wpas_dbus_signal_bss_removed(wpa_s, bss_obj_path);
1292
1293 os_free(bss_obj_path);
1294 return 0;
1295}
1296
1297
17efbfac
JM
1298/**
1299 * wpas_dbus_register_bss - Register a scanned BSS with dbus
1300 * @wpa_s: wpa_supplicant interface structure
1301 * @bssid: scanned network bssid
ccd286d0 1302 * @id: unique BSS identifier
17efbfac
JM
1303 * Returns: 0 on success, -1 on failure
1304 *
1305 * Registers BSS representing object with dbus
1306 */
8fc2fb56 1307static int wpas_dbus_register_bss(struct wpa_supplicant *wpa_s,
ccd286d0 1308 u8 bssid[ETH_ALEN], unsigned int id)
8fc2fb56 1309{
8ddef94b 1310 struct wpas_dbus_priv *ctrl_iface;
8fc2fb56 1311 struct wpa_dbus_object_desc *obj_desc;
8fc2fb56
WS
1312 char *bss_obj_path;
1313
1314 struct bss_handler_args *arg = NULL;
1315
1316 /* Do nothing if the control interface is not turned on */
1317 if (wpa_s == NULL || wpa_s->global == NULL)
1318 return 0;
8ddef94b 1319 ctrl_iface = wpa_s->global->dbus;
8fc2fb56
WS
1320 if (ctrl_iface == NULL)
1321 return 0;
1322
1323 bss_obj_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1324 if (bss_obj_path == NULL)
1325 return -1;
1326
1327 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
ccd286d0
JM
1328 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
1329 wpas_dbus_get_path(wpa_s), id);
8fc2fb56
WS
1330
1331 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
1332 if (!obj_desc) {
1333 wpa_printf(MSG_ERROR, "Not enough memory "
1334 "to create object description");
1335 goto err;
1336 }
1337
1338 arg = os_zalloc(sizeof(struct bss_handler_args));
1339 if (!arg) {
1340 wpa_printf(MSG_ERROR, "Not enough memory "
1341 "to create arguments for handler");
1342 goto err;
1343 }
1344 arg->wpa_s = wpa_s;
ccd286d0 1345 arg->id = id;
8fc2fb56
WS
1346
1347 /* Properties property */
485ec2ae
JM
1348 wpa_dbus_property_register(obj_desc, WPAS_DBUS_NEW_IFACE_BSSID,
1349 "Properties", "a{sv}",
1350 (WPADBusPropertyAccessor)
1351 wpas_dbus_getter_bss_properties, NULL,
d114fcab 1352 arg, wpa_dbus_free, R);
8fc2fb56 1353
8e56d189
JM
1354 wpa_printf(MSG_DEBUG, "dbus: Register BSS object '%s'",
1355 bss_obj_path);
8fc2fb56
WS
1356 if (wpa_dbus_register_object_per_iface(ctrl_iface, bss_obj_path,
1357 wpa_s->ifname, obj_desc)) {
1358 wpa_printf(MSG_ERROR,
1359 "Cannot register BSSID dbus object %s.",
1360 bss_obj_path);
1361 goto err;
1362 }
1363
1364 wpas_dbus_signal_bss_added(wpa_s, bss_obj_path);
1365
1366 os_free(bss_obj_path);
1367 return 0;
1368
1369err:
1370 os_free(bss_obj_path);
1371 os_free(obj_desc);
1372 os_free(arg);
1373 return -1;
1374}
1375
1376
9b61515c
JM
1377static const struct wpas_dbus_method wpas_dbus_interface_methods[] = {
1378 { "Scan", WPAS_DBUS_NEW_IFACE_INTERFACE,
1379 (WPADBusMethodHandler) &wpas_dbus_handler_scan,
1380 {
1381 { "args", "a{sv}", ARG_IN },
1382 END_ARGS
1383 }
1384 },
1385 { "Disconnect", WPAS_DBUS_NEW_IFACE_INTERFACE,
1386 (WPADBusMethodHandler) &wpas_dbus_handler_disconnect,
1387 {
1388 END_ARGS
1389 }
1390 },
1391 { "AddNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
1392 (WPADBusMethodHandler) &wpas_dbus_handler_add_network,
1393 {
1394 { "args", "a{sv}", ARG_IN },
1395 { "path", "o", ARG_OUT },
1396 END_ARGS
1397 }
1398 },
1399 { "RemoveNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
1400 (WPADBusMethodHandler) &wpas_dbus_handler_remove_network,
1401 {
1402 { "path", "o", ARG_IN },
1403 END_ARGS
1404 }
1405 },
1406 { "SelectNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
1407 (WPADBusMethodHandler) &wpas_dbus_handler_select_network,
1408 {
1409 { "path", "o", ARG_IN },
1410 END_ARGS
1411 }
1412 },
1413 { "AddBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
1414 (WPADBusMethodHandler) &wpas_dbus_handler_add_blob,
1415 {
1416 { "name", "s", ARG_IN },
1417 { "data", "ay", ARG_IN },
1418 END_ARGS
1419 }
1420 },
1421 { "GetBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
1422 (WPADBusMethodHandler) &wpas_dbus_handler_get_blob,
1423 {
1424 { "name", "s", ARG_IN },
1425 { "data", "ay", ARG_OUT },
1426 END_ARGS
1427 }
1428 },
1429 { "RemoveBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
1430 (WPADBusMethodHandler) &wpas_dbus_handler_remove_blob,
1431 {
1432 { "name", "s", ARG_IN },
1433 END_ARGS
1434 }
1435 },
1436#ifdef CONFIG_WPS
1437 { "Start", WPAS_DBUS_NEW_IFACE_WPS,
1438 (WPADBusMethodHandler) &wpas_dbus_handler_wps_start,
1439 {
1440 { "args", "a{sv}", ARG_IN },
1441 { "output", "a{sv}", ARG_OUT },
1442 END_ARGS
1443 }
1444 },
1445#endif /* CONFIG_WPS */
1446 { NULL, NULL, NULL, { END_ARGS } }
1447};
1448
1449static const struct wpas_dbus_property wpas_dbus_interface_properties[] = {
1450 { "Capabilities", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{sv}",
1451 (WPADBusPropertyAccessor) wpas_dbus_getter_capabilities,
1452 NULL, R
1453 },
1454 { "State", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
1455 (WPADBusPropertyAccessor) wpas_dbus_getter_state,
1456 NULL, R
1457 },
1458 { "Scanning", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
1459 (WPADBusPropertyAccessor) wpas_dbus_getter_scanning,
1460 NULL, R
1461 },
1462 { "ApScan", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
1463 (WPADBusPropertyAccessor) wpas_dbus_getter_ap_scan,
1464 (WPADBusPropertyAccessor) wpas_dbus_setter_ap_scan,
1465 RW
1466 },
1467 { "Ifname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
1468 (WPADBusPropertyAccessor) wpas_dbus_getter_ifname,
1469 NULL, R
1470 },
1471 { "Driver", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
1472 (WPADBusPropertyAccessor) wpas_dbus_getter_driver,
1473 NULL, R
1474 },
1475 { "BridgeIfname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
1476 (WPADBusPropertyAccessor) wpas_dbus_getter_bridge_ifname,
1477 NULL, R
1478 },
1479 { "CurrentBSS", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
1480 (WPADBusPropertyAccessor) wpas_dbus_getter_current_bss,
1481 NULL, R
1482 },
1483 { "CurrentNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
1484 (WPADBusPropertyAccessor) wpas_dbus_getter_current_network,
1485 NULL, R
1486 },
1487 { "Blobs", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{say}",
1488 (WPADBusPropertyAccessor) wpas_dbus_getter_blobs,
1489 NULL, R
1490 },
1491 { "BSSs", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
1492 (WPADBusPropertyAccessor) wpas_dbus_getter_bsss,
1493 NULL, R
1494 },
1495 { "Networks", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
1496 (WPADBusPropertyAccessor) wpas_dbus_getter_networks,
1497 NULL, R
1498 },
1499#ifdef CONFIG_WPS
1500 { "ProcessCredentials", WPAS_DBUS_NEW_IFACE_WPS, "b",
1501 (WPADBusPropertyAccessor) wpas_dbus_getter_process_credentials,
1502 (WPADBusPropertyAccessor) wpas_dbus_setter_process_credentials,
1503 RW
1504 },
1505#endif /* CONFIG_WPS */
1506 { NULL, NULL, NULL, NULL, NULL, 0 }
1507};
1508
1509static const struct wpas_dbus_signal wpas_dbus_interface_signals[] = {
1510 { "ScanDone", WPAS_DBUS_NEW_IFACE_INTERFACE,
1511 {
1512 { "success", "b", ARG_OUT },
1513 END_ARGS
1514 }
1515 },
1516 { "StateChanged", WPAS_DBUS_NEW_IFACE_INTERFACE,
1517 {
1518 { "newState", "s", ARG_OUT },
1519 { "oldState", "s", ARG_OUT },
1520 END_ARGS
1521 }
1522 },
1523 { "BSSAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
1524 {
1525 { "path", "o", ARG_OUT },
1526 END_ARGS
1527 }
1528 },
1529 { "BSSRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
1530 {
1531 { "path", "o", ARG_OUT },
1532 END_ARGS
1533 }
1534 },
1535 { "BlobAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
1536 {
1537 { "name", "s", ARG_OUT },
1538 END_ARGS
1539 }
1540 },
1541 { "BlobRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
1542 {
1543 { "name", "s", ARG_OUT },
1544 END_ARGS
1545 }
1546 },
1547 { "NetworkAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
1548 {
1549 { "path", "o", ARG_OUT },
1550 END_ARGS
1551 }
1552 },
1553 { "NetworkRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
1554 {
1555 { "path", "o", ARG_OUT },
1556 END_ARGS
1557 }
1558 },
1559 { "NetworkSelected", WPAS_DBUS_NEW_IFACE_INTERFACE,
1560 {
1561 { "path", "o", ARG_OUT },
1562 END_ARGS
1563 }
1564 },
1565 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_INTERFACE,
1566 {
1567 { "properties", "a{sv}", ARG_OUT },
1568 END_ARGS
1569 }
1570 },
1571#ifdef CONFIG_WPS
1572 { "Event", WPAS_DBUS_NEW_IFACE_WPS,
1573 {
1574 { "name", "s", ARG_OUT },
1575 { "args", "a{sv}", ARG_OUT },
1576 END_ARGS
1577 }
1578 },
1579 { "Credentials", WPAS_DBUS_NEW_IFACE_WPS,
1580 {
1581 { "credentials", "a{sv}", ARG_OUT },
1582 END_ARGS
1583 }
1584 },
1585 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_WPS,
1586 {
1587 { "properties", "a{sv}", ARG_OUT },
1588 END_ARGS
1589 }
1590 },
1591#endif /* CONFIG_WPS */
1592 { NULL, NULL, { END_ARGS } }
1593};
1594
1595
8fc2fb56
WS
1596static int wpas_dbus_register_interface(struct wpa_supplicant *wpa_s)
1597{
1598
1599 struct wpa_dbus_object_desc *obj_desc = NULL;
1600 char *path;
8ddef94b 1601 struct wpas_dbus_priv *ctrl_iface = wpa_s->global->dbus;
8fc2fb56
WS
1602 int next;
1603
8fc2fb56
WS
1604 /* Do nothing if the control interface is not turned on */
1605 if (ctrl_iface == NULL)
1606 return 0;
1607
1608 /* Create and set the interface's object path */
1609 path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1610 if (path == NULL)
1611 return -1;
8ddef94b 1612 next = ctrl_iface->next_objid++;
8fc2fb56
WS
1613 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
1614 WPAS_DBUS_NEW_PATH_INTERFACES "/%u",
1615 next);
1616 if (wpas_dbus_set_path(wpa_s, path)) {
1617 wpa_printf(MSG_DEBUG,
1618 "Failed to set dbus path for interface %s",
1619 wpa_s->ifname);
1620 goto err;
1621 }
1622
1623 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
1624 if (!obj_desc) {
1625 wpa_printf(MSG_ERROR, "Not enough memory "
1626 "to create object description");
1627 goto err;
1628 }
1629
9b61515c
JM
1630 wpas_dbus_register(obj_desc, wpa_s, wpas_dbus_interface_methods,
1631 wpas_dbus_interface_properties,
1632 wpas_dbus_interface_signals);
8fc2fb56 1633
8e56d189 1634 wpa_printf(MSG_DEBUG, "dbus: Register interface object '%s'", path);
8fc2fb56
WS
1635 if (wpa_dbus_register_object_per_iface(ctrl_iface, path, wpa_s->ifname,
1636 obj_desc))
1637 goto err;
1638
1639 wpas_dbus_signal_interface_created(wpa_s);
1640
1641 os_free(path);
1642 return 0;
1643
1644err:
1645 os_free(obj_desc);
1646 os_free(path);
1647 return -1;
1648}
1649
1650
1651static int wpas_dbus_unregister_interface(struct wpa_supplicant *wpa_s)
1652{
8ddef94b 1653 struct wpas_dbus_priv *ctrl_iface;
8fc2fb56
WS
1654
1655 /* Do nothing if the control interface is not turned on */
1656 if (wpa_s == NULL || wpa_s->global == NULL)
1657 return 0;
8ddef94b 1658 ctrl_iface = wpa_s->global->dbus;
8fc2fb56
WS
1659 if (ctrl_iface == NULL)
1660 return 0;
1661
8e56d189
JM
1662 wpa_printf(MSG_DEBUG, "dbus: Unregister interface object '%s'",
1663 wpas_dbus_get_path(wpa_s));
d69780dc
JM
1664 if (wpa_dbus_unregister_object_per_iface(ctrl_iface,
1665 wpas_dbus_get_path(wpa_s)))
8fc2fb56
WS
1666 return -1;
1667
1668 wpas_dbus_signal_interface_removed(wpa_s);
1669
1670 os_free(wpa_s->dbus_new_path);
1671 wpa_s->dbus_new_path = NULL;
1672
1673 return 0;
1674}
1675
1676
1677static struct wpas_dbus_callbacks callbacks =
1678{
8fc2fb56
WS
1679 .signal_interface_created = wpas_dbus_signal_interface_created,
1680 .signal_interface_removed = wpas_dbus_signal_interface_removed,
1681
1682 .register_interface = wpas_dbus_register_interface,
1683 .unregister_interface = wpas_dbus_unregister_interface,
1684
1685 .signal_scan_done = wpas_dbus_signal_scan_done,
1686
1687 .signal_blob_added = wpas_dbus_signal_blob_added,
1688 .signal_blob_removed = wpas_dbus_signal_blob_removed,
1689
1690 .signal_network_selected = wpas_dbus_signal_network_selected,
1691
1692 .signal_state_changed = wpas_dbus_signal_state_changed,
1693 .register_network = wpas_dbus_register_network,
1694 .unregister_network = wpas_dbus_unregister_network,
1695
1696 .signal_network_enabled_changed =
1697 wpas_dbus_signal_network_enabled_changed,
1698
1699 .register_bss = wpas_dbus_register_bss,
1700 .unregister_bss = wpas_dbus_unregister_bss,
1701
1702 .signal_prop_changed = wpas_dbus_signal_prop_changed,
1703 .signal_debug_params_changed = wpas_dbus_signal_debug_params_changed,
1704
1705#ifdef CONFIG_WPS
1706 .signal_wps_event_success = wpas_dbus_signal_wps_event_success,
1707 .signal_wps_event_fail = wpas_dbus_signal_wps_event_fail,
1708 .signal_wps_event_m2d = wpas_dbus_signal_wps_event_m2d,
1709 .signal_wps_credentials = wpas_dbus_signal_wps_cred,
1710#endif /* CONFIG_WPS */
1711};
1712
1713
1714struct wpas_dbus_callbacks * wpas_dbus_get_callbacks(void)
1715{
1716 return &callbacks;
1717}
1718
1719
1720/**
1721 * wpas_dbus_get_path - Get an interface's dbus path
1722 * @wpa_s: %wpa_supplicant interface structure
1723 * Returns: Interface's dbus object path, or %NULL on error
1724 */
1725const char * wpas_dbus_get_path(struct wpa_supplicant *wpa_s)
1726{
1727 return wpa_s->dbus_new_path;
1728}