]> git.ipfire.org Git - thirdparty/hostap.git/blob - wpa_supplicant/dbus/dbus_new.c
Clean up: Replace standard lib methods with os.h ones
[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-2010, Witold Sowa <witold.sowa@gmail.com>
5 * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 * Alternatively, this software may be distributed under the terms of BSD
12 * license.
13 *
14 * See README and COPYING for more details.
15 */
16
17 #include "includes.h"
18
19 #include "common.h"
20 #include "common/ieee802_11_defs.h"
21 #include "wps/wps.h"
22 #include "../config.h"
23 #include "../wpa_supplicant_i.h"
24 #include "../bss.h"
25 #include "../wpas_glue.h"
26 #include "dbus_new_helpers.h"
27 #include "dbus_dict_helpers.h"
28 #include "dbus_new.h"
29 #include "dbus_new_handlers.h"
30 #include "dbus_common_i.h"
31 #include "dbus_new_handlers_p2p.h"
32 #include "p2p/p2p.h"
33
34
35 /**
36 * wpas_dbus_signal_interface - Send a interface related event signal
37 * @wpa_s: %wpa_supplicant network interface data
38 * @sig_name: signal name - InterfaceAdded or InterfaceRemoved
39 * @properties: Whether to add second argument with object properties
40 *
41 * Notify listeners about event related with interface
42 */
43 static void wpas_dbus_signal_interface(struct wpa_supplicant *wpa_s,
44 const char *sig_name, int properties)
45 {
46 struct wpas_dbus_priv *iface;
47 DBusMessage *msg;
48 DBusMessageIter iter;
49
50 iface = wpa_s->global->dbus;
51
52 /* Do nothing if the control interface is not turned on */
53 if (iface == NULL)
54 return;
55
56 msg = dbus_message_new_signal(WPAS_DBUS_NEW_PATH,
57 WPAS_DBUS_NEW_INTERFACE, sig_name);
58 if (msg == NULL)
59 return;
60
61 dbus_message_iter_init_append(msg, &iter);
62 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
63 &wpa_s->dbus_new_path))
64 goto err;
65
66 if (properties) {
67 if (!wpa_dbus_get_object_properties(
68 iface, wpa_s->dbus_new_path,
69 WPAS_DBUS_NEW_IFACE_INTERFACE, &iter))
70 goto err;
71 }
72
73 dbus_connection_send(iface->con, msg, NULL);
74 dbus_message_unref(msg);
75 return;
76
77 err:
78 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
79 dbus_message_unref(msg);
80 }
81
82
83 /**
84 * wpas_dbus_signal_interface_added - Send a interface created signal
85 * @wpa_s: %wpa_supplicant network interface data
86 *
87 * Notify listeners about creating new interface
88 */
89 static void wpas_dbus_signal_interface_added(struct wpa_supplicant *wpa_s)
90 {
91 wpas_dbus_signal_interface(wpa_s, "InterfaceAdded", TRUE);
92 }
93
94
95 /**
96 * wpas_dbus_signal_interface_removed - Send a interface removed signal
97 * @wpa_s: %wpa_supplicant network interface data
98 *
99 * Notify listeners about removing interface
100 */
101 static void wpas_dbus_signal_interface_removed(struct wpa_supplicant *wpa_s)
102 {
103 wpas_dbus_signal_interface(wpa_s, "InterfaceRemoved", FALSE);
104
105 }
106
107
108 /**
109 * wpas_dbus_signal_scan_done - send scan done signal
110 * @wpa_s: %wpa_supplicant network interface data
111 * @success: indicates if scanning succeed or failed
112 *
113 * Notify listeners about finishing a scan
114 */
115 void wpas_dbus_signal_scan_done(struct wpa_supplicant *wpa_s, int success)
116 {
117 struct wpas_dbus_priv *iface;
118 DBusMessage *msg;
119 dbus_bool_t succ;
120
121 iface = wpa_s->global->dbus;
122
123 /* Do nothing if the control interface is not turned on */
124 if (iface == NULL)
125 return;
126
127 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
128 WPAS_DBUS_NEW_IFACE_INTERFACE,
129 "ScanDone");
130 if (msg == NULL)
131 return;
132
133 succ = success ? TRUE : FALSE;
134 if (dbus_message_append_args(msg, DBUS_TYPE_BOOLEAN, &succ,
135 DBUS_TYPE_INVALID))
136 dbus_connection_send(iface->con, msg, NULL);
137 else
138 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
139 dbus_message_unref(msg);
140 }
141
142
143 /**
144 * wpas_dbus_signal_blob - Send a BSS related event signal
145 * @wpa_s: %wpa_supplicant network interface data
146 * @bss_obj_path: BSS object path
147 * @sig_name: signal name - BSSAdded or BSSRemoved
148 * @properties: Whether to add second argument with object properties
149 *
150 * Notify listeners about event related with BSS
151 */
152 static void wpas_dbus_signal_bss(struct wpa_supplicant *wpa_s,
153 const char *bss_obj_path,
154 const char *sig_name, int properties)
155 {
156 struct wpas_dbus_priv *iface;
157 DBusMessage *msg;
158 DBusMessageIter iter;
159
160 iface = wpa_s->global->dbus;
161
162 /* Do nothing if the control interface is not turned on */
163 if (iface == NULL)
164 return;
165
166 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
167 WPAS_DBUS_NEW_IFACE_INTERFACE,
168 sig_name);
169 if (msg == NULL)
170 return;
171
172 dbus_message_iter_init_append(msg, &iter);
173 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
174 &bss_obj_path))
175 goto err;
176
177 if (properties) {
178 if (!wpa_dbus_get_object_properties(iface, bss_obj_path,
179 WPAS_DBUS_NEW_IFACE_BSS,
180 &iter))
181 goto err;
182 }
183
184 dbus_connection_send(iface->con, msg, NULL);
185 dbus_message_unref(msg);
186 return;
187
188 err:
189 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
190 dbus_message_unref(msg);
191 }
192
193
194 /**
195 * wpas_dbus_signal_bss_added - Send a BSS added signal
196 * @wpa_s: %wpa_supplicant network interface data
197 * @bss_obj_path: new BSS object path
198 *
199 * Notify listeners about adding new BSS
200 */
201 static void wpas_dbus_signal_bss_added(struct wpa_supplicant *wpa_s,
202 const char *bss_obj_path)
203 {
204 wpas_dbus_signal_bss(wpa_s, bss_obj_path, "BSSAdded", TRUE);
205 }
206
207
208 /**
209 * wpas_dbus_signal_bss_removed - Send a BSS removed signal
210 * @wpa_s: %wpa_supplicant network interface data
211 * @bss_obj_path: BSS object path
212 *
213 * Notify listeners about removing BSS
214 */
215 static void wpas_dbus_signal_bss_removed(struct wpa_supplicant *wpa_s,
216 const char *bss_obj_path)
217 {
218 wpas_dbus_signal_bss(wpa_s, bss_obj_path, "BSSRemoved", FALSE);
219 }
220
221
222 /**
223 * wpas_dbus_signal_blob - Send a blob related event signal
224 * @wpa_s: %wpa_supplicant network interface data
225 * @name: blob name
226 * @sig_name: signal name - BlobAdded or BlobRemoved
227 *
228 * Notify listeners about event related with blob
229 */
230 static void wpas_dbus_signal_blob(struct wpa_supplicant *wpa_s,
231 const char *name, const char *sig_name)
232 {
233 struct wpas_dbus_priv *iface;
234 DBusMessage *msg;
235
236 iface = wpa_s->global->dbus;
237
238 /* Do nothing if the control interface is not turned on */
239 if (iface == NULL)
240 return;
241
242 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
243 WPAS_DBUS_NEW_IFACE_INTERFACE,
244 sig_name);
245 if (msg == NULL)
246 return;
247
248 if (dbus_message_append_args(msg, DBUS_TYPE_STRING, &name,
249 DBUS_TYPE_INVALID))
250 dbus_connection_send(iface->con, msg, NULL);
251 else
252 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
253 dbus_message_unref(msg);
254 }
255
256
257 /**
258 * wpas_dbus_signal_blob_added - Send a blob added signal
259 * @wpa_s: %wpa_supplicant network interface data
260 * @name: blob name
261 *
262 * Notify listeners about adding a new blob
263 */
264 void wpas_dbus_signal_blob_added(struct wpa_supplicant *wpa_s,
265 const char *name)
266 {
267 wpas_dbus_signal_blob(wpa_s, name, "BlobAdded");
268 }
269
270
271 /**
272 * wpas_dbus_signal_blob_removed - Send a blob removed signal
273 * @wpa_s: %wpa_supplicant network interface data
274 * @name: blob name
275 *
276 * Notify listeners about removing blob
277 */
278 void wpas_dbus_signal_blob_removed(struct wpa_supplicant *wpa_s,
279 const char *name)
280 {
281 wpas_dbus_signal_blob(wpa_s, name, "BlobRemoved");
282 }
283
284
285 /**
286 * wpas_dbus_signal_network - Send a network related event signal
287 * @wpa_s: %wpa_supplicant network interface data
288 * @id: new network id
289 * @sig_name: signal name - NetworkAdded, NetworkRemoved or NetworkSelected
290 * @properties: determines if add second argument with object properties
291 *
292 * Notify listeners about event related with configured network
293 */
294 static void wpas_dbus_signal_network(struct wpa_supplicant *wpa_s,
295 int id, const char *sig_name,
296 int properties)
297 {
298 struct wpas_dbus_priv *iface;
299 DBusMessage *msg;
300 DBusMessageIter iter;
301 char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
302
303 iface = wpa_s->global->dbus;
304
305 /* Do nothing if the control interface is not turned on */
306 if (iface == NULL)
307 return;
308
309 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
310 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
311 wpa_s->dbus_new_path, id);
312
313 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
314 WPAS_DBUS_NEW_IFACE_INTERFACE,
315 sig_name);
316 if (msg == NULL)
317 return;
318
319 dbus_message_iter_init_append(msg, &iter);
320 path = net_obj_path;
321 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
322 &path))
323 goto err;
324
325 if (properties) {
326 if (!wpa_dbus_get_object_properties(
327 iface, net_obj_path, WPAS_DBUS_NEW_IFACE_NETWORK,
328 &iter))
329 goto err;
330 }
331
332 dbus_connection_send(iface->con, msg, NULL);
333
334 dbus_message_unref(msg);
335 return;
336
337 err:
338 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
339 dbus_message_unref(msg);
340 }
341
342
343 /**
344 * wpas_dbus_signal_network_added - Send a network added signal
345 * @wpa_s: %wpa_supplicant network interface data
346 * @id: new network id
347 *
348 * Notify listeners about adding new network
349 */
350 static void wpas_dbus_signal_network_added(struct wpa_supplicant *wpa_s,
351 int id)
352 {
353 wpas_dbus_signal_network(wpa_s, id, "NetworkAdded", TRUE);
354 }
355
356
357 /**
358 * wpas_dbus_signal_network_removed - Send a network removed signal
359 * @wpa_s: %wpa_supplicant network interface data
360 * @id: network id
361 *
362 * Notify listeners about removing a network
363 */
364 static void wpas_dbus_signal_network_removed(struct wpa_supplicant *wpa_s,
365 int id)
366 {
367 wpas_dbus_signal_network(wpa_s, id, "NetworkRemoved", FALSE);
368 }
369
370
371 /**
372 * wpas_dbus_signal_network_selected - Send a network selected signal
373 * @wpa_s: %wpa_supplicant network interface data
374 * @id: network id
375 *
376 * Notify listeners about selecting a network
377 */
378 void wpas_dbus_signal_network_selected(struct wpa_supplicant *wpa_s, int id)
379 {
380 wpas_dbus_signal_network(wpa_s, id, "NetworkSelected", FALSE);
381 }
382
383
384 /**
385 * wpas_dbus_signal_network_request - Indicate that additional information
386 * (EAP password, etc.) is required to complete the association to this SSID
387 * @wpa_s: %wpa_supplicant network interface data
388 * @rtype: The specific additional information required
389 * @default_text: Optional description of required information
390 *
391 * Request additional information or passwords to complete an association
392 * request.
393 */
394 void wpas_dbus_signal_network_request(struct wpa_supplicant *wpa_s,
395 struct wpa_ssid *ssid,
396 enum wpa_ctrl_req_type rtype,
397 const char *default_txt)
398 {
399 struct wpas_dbus_priv *iface;
400 DBusMessage *msg;
401 DBusMessageIter iter;
402 char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
403 const char *field, *txt = NULL, *net_ptr;
404
405 iface = wpa_s->global->dbus;
406
407 /* Do nothing if the control interface is not turned on */
408 if (iface == NULL)
409 return;
410
411 field = wpa_supplicant_ctrl_req_to_string(rtype, default_txt, &txt);
412 if (field == NULL)
413 return;
414
415 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
416 WPAS_DBUS_NEW_IFACE_INTERFACE,
417 "NetworkRequest");
418 if (msg == NULL)
419 return;
420
421 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
422 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
423 wpa_s->dbus_new_path, ssid->id);
424 net_ptr = &net_obj_path[0];
425
426 dbus_message_iter_init_append(msg, &iter);
427 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
428 &net_ptr))
429 goto err;
430 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &field))
431 goto err;
432 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &txt))
433 goto err;
434
435 dbus_connection_send(iface->con, msg, NULL);
436 dbus_message_unref(msg);
437 return;
438
439 err:
440 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
441 dbus_message_unref(msg);
442 }
443
444
445 /**
446 * wpas_dbus_signal_network_enabled_changed - Signals Enabled property changes
447 * @wpa_s: %wpa_supplicant network interface data
448 * @ssid: configured network which Enabled property has changed
449 *
450 * Sends PropertyChanged signals containing new value of Enabled property
451 * for specified network
452 */
453 void wpas_dbus_signal_network_enabled_changed(struct wpa_supplicant *wpa_s,
454 struct wpa_ssid *ssid)
455 {
456
457 char path[WPAS_DBUS_OBJECT_PATH_MAX];
458 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
459 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
460 wpa_s->dbus_new_path, ssid->id);
461
462 wpa_dbus_mark_property_changed(wpa_s->global->dbus, path,
463 WPAS_DBUS_NEW_IFACE_NETWORK, "Enabled");
464 }
465
466
467 #ifdef CONFIG_WPS
468
469 /**
470 * wpas_dbus_signal_wps_event_success - Signals Success WPS event
471 * @wpa_s: %wpa_supplicant network interface data
472 *
473 * Sends Event dbus signal with name "success" and empty dict as arguments
474 */
475 void wpas_dbus_signal_wps_event_success(struct wpa_supplicant *wpa_s)
476 {
477
478 DBusMessage *msg;
479 DBusMessageIter iter, dict_iter;
480 struct wpas_dbus_priv *iface;
481 char *key = "success";
482
483 iface = wpa_s->global->dbus;
484
485 /* Do nothing if the control interface is not turned on */
486 if (iface == NULL)
487 return;
488
489 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
490 WPAS_DBUS_NEW_IFACE_WPS, "Event");
491 if (msg == NULL)
492 return;
493
494 dbus_message_iter_init_append(msg, &iter);
495
496 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
497 !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
498 !wpa_dbus_dict_close_write(&iter, &dict_iter))
499 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
500 else
501 dbus_connection_send(iface->con, msg, NULL);
502
503 dbus_message_unref(msg);
504 }
505
506
507 /**
508 * wpas_dbus_signal_wps_event_fail - Signals Fail WPS event
509 * @wpa_s: %wpa_supplicant network interface data
510 *
511 * Sends Event dbus signal with name "fail" and dictionary containing
512 * "msg field with fail message number (int32) as arguments
513 */
514 void wpas_dbus_signal_wps_event_fail(struct wpa_supplicant *wpa_s,
515 struct wps_event_fail *fail)
516 {
517
518 DBusMessage *msg;
519 DBusMessageIter iter, dict_iter;
520 struct wpas_dbus_priv *iface;
521 char *key = "fail";
522
523 iface = wpa_s->global->dbus;
524
525 /* Do nothing if the control interface is not turned on */
526 if (iface == NULL)
527 return;
528
529 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
530 WPAS_DBUS_NEW_IFACE_WPS, "Event");
531 if (msg == NULL)
532 return;
533
534 dbus_message_iter_init_append(msg, &iter);
535
536 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
537 !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
538 !wpa_dbus_dict_append_int32(&dict_iter, "msg", fail->msg) ||
539 !wpa_dbus_dict_close_write(&iter, &dict_iter))
540 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
541 else
542 dbus_connection_send(iface->con, msg, NULL);
543
544 dbus_message_unref(msg);
545 }
546
547
548 /**
549 * wpas_dbus_signal_wps_event_m2d - Signals M2D WPS event
550 * @wpa_s: %wpa_supplicant network interface data
551 *
552 * Sends Event dbus signal with name "m2d" and dictionary containing
553 * fields of wps_event_m2d structure.
554 */
555 void wpas_dbus_signal_wps_event_m2d(struct wpa_supplicant *wpa_s,
556 struct wps_event_m2d *m2d)
557 {
558
559 DBusMessage *msg;
560 DBusMessageIter iter, dict_iter;
561 struct wpas_dbus_priv *iface;
562 char *key = "m2d";
563
564 iface = wpa_s->global->dbus;
565
566 /* Do nothing if the control interface is not turned on */
567 if (iface == NULL)
568 return;
569
570 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
571 WPAS_DBUS_NEW_IFACE_WPS, "Event");
572 if (msg == NULL)
573 return;
574
575 dbus_message_iter_init_append(msg, &iter);
576
577 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
578 !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
579 !wpa_dbus_dict_append_uint16(&dict_iter, "config_methods",
580 m2d->config_methods) ||
581 !wpa_dbus_dict_append_byte_array(&dict_iter, "manufacturer",
582 (const char *) m2d->manufacturer,
583 m2d->manufacturer_len) ||
584 !wpa_dbus_dict_append_byte_array(&dict_iter, "model_name",
585 (const char *) m2d->model_name,
586 m2d->model_name_len) ||
587 !wpa_dbus_dict_append_byte_array(&dict_iter, "model_number",
588 (const char *) m2d->model_number,
589 m2d->model_number_len) ||
590 !wpa_dbus_dict_append_byte_array(&dict_iter, "serial_number",
591 (const char *)
592 m2d->serial_number,
593 m2d->serial_number_len) ||
594 !wpa_dbus_dict_append_byte_array(&dict_iter, "dev_name",
595 (const char *) m2d->dev_name,
596 m2d->dev_name_len) ||
597 !wpa_dbus_dict_append_byte_array(&dict_iter, "primary_dev_type",
598 (const char *)
599 m2d->primary_dev_type, 8) ||
600 !wpa_dbus_dict_append_uint16(&dict_iter, "config_error",
601 m2d->config_error) ||
602 !wpa_dbus_dict_append_uint16(&dict_iter, "dev_password_id",
603 m2d->dev_password_id) ||
604 !wpa_dbus_dict_close_write(&iter, &dict_iter))
605 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
606 else
607 dbus_connection_send(iface->con, msg, NULL);
608
609 dbus_message_unref(msg);
610 }
611
612
613 /**
614 * wpas_dbus_signal_wps_cred - Signals new credentials
615 * @wpa_s: %wpa_supplicant network interface data
616 *
617 * Sends signal with credentials in directory argument
618 */
619 void wpas_dbus_signal_wps_cred(struct wpa_supplicant *wpa_s,
620 const struct wps_credential *cred)
621 {
622 DBusMessage *msg;
623 DBusMessageIter iter, dict_iter;
624 struct wpas_dbus_priv *iface;
625 char *auth_type[6]; /* we have six possible authorization types */
626 int at_num = 0;
627 char *encr_type[4]; /* we have four possible encryption types */
628 int et_num = 0;
629
630 iface = wpa_s->global->dbus;
631
632 /* Do nothing if the control interface is not turned on */
633 if (iface == NULL)
634 return;
635
636 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
637 WPAS_DBUS_NEW_IFACE_WPS,
638 "Credentials");
639 if (msg == NULL)
640 return;
641
642 dbus_message_iter_init_append(msg, &iter);
643 if (!wpa_dbus_dict_open_write(&iter, &dict_iter))
644 goto nomem;
645
646 if (cred->auth_type & WPS_AUTH_OPEN)
647 auth_type[at_num++] = "open";
648 if (cred->auth_type & WPS_AUTH_WPAPSK)
649 auth_type[at_num++] = "wpa-psk";
650 if (cred->auth_type & WPS_AUTH_SHARED)
651 auth_type[at_num++] = "shared";
652 if (cred->auth_type & WPS_AUTH_WPA)
653 auth_type[at_num++] = "wpa-eap";
654 if (cred->auth_type & WPS_AUTH_WPA2)
655 auth_type[at_num++] = "wpa2-eap";
656 if (cred->auth_type & WPS_AUTH_WPA2PSK)
657 auth_type[at_num++] =
658 "wpa2-psk";
659
660 if (cred->encr_type & WPS_ENCR_NONE)
661 encr_type[et_num++] = "none";
662 if (cred->encr_type & WPS_ENCR_WEP)
663 encr_type[et_num++] = "wep";
664 if (cred->encr_type & WPS_ENCR_TKIP)
665 encr_type[et_num++] = "tkip";
666 if (cred->encr_type & WPS_ENCR_AES)
667 encr_type[et_num++] = "aes";
668
669 if (wpa_s->current_ssid) {
670 if (!wpa_dbus_dict_append_byte_array(
671 &dict_iter, "BSSID",
672 (const char *) wpa_s->current_ssid->bssid,
673 ETH_ALEN))
674 goto nomem;
675 }
676
677 if (!wpa_dbus_dict_append_byte_array(&dict_iter, "SSID",
678 (const char *) cred->ssid,
679 cred->ssid_len) ||
680 !wpa_dbus_dict_append_string_array(&dict_iter, "AuthType",
681 (const char **) auth_type,
682 at_num) ||
683 !wpa_dbus_dict_append_string_array(&dict_iter, "EncrType",
684 (const char **) encr_type,
685 et_num) ||
686 !wpa_dbus_dict_append_byte_array(&dict_iter, "Key",
687 (const char *) cred->key,
688 cred->key_len) ||
689 !wpa_dbus_dict_append_uint32(&dict_iter, "KeyIndex",
690 cred->key_idx) ||
691 !wpa_dbus_dict_close_write(&iter, &dict_iter))
692 goto nomem;
693
694 dbus_connection_send(iface->con, msg, NULL);
695
696 nomem:
697 dbus_message_unref(msg);
698 }
699
700 #endif /* CONFIG_WPS */
701
702 void wpas_dbus_signal_certification(struct wpa_supplicant *wpa_s,
703 int depth, const char *subject,
704 const char *cert_hash,
705 const struct wpabuf *cert)
706 {
707 struct wpas_dbus_priv *iface;
708 DBusMessage *msg;
709 DBusMessageIter iter, dict_iter;
710
711 iface = wpa_s->global->dbus;
712
713 /* Do nothing if the control interface is not turned on */
714 if (iface == NULL)
715 return;
716
717 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
718 WPAS_DBUS_NEW_IFACE_INTERFACE,
719 "Certification");
720 if (msg == NULL)
721 return;
722
723 dbus_message_iter_init_append(msg, &iter);
724 if (!wpa_dbus_dict_open_write(&iter, &dict_iter))
725 goto nomem;
726
727 if (!wpa_dbus_dict_append_uint32(&dict_iter, "depth", depth) ||
728 !wpa_dbus_dict_append_string(&dict_iter, "subject", subject))
729 goto nomem;
730
731 if (cert_hash &&
732 !wpa_dbus_dict_append_string(&dict_iter, "cert_hash", cert_hash))
733 goto nomem;
734
735 if (cert &&
736 !wpa_dbus_dict_append_byte_array(&dict_iter, "cert",
737 wpabuf_head(cert),
738 wpabuf_len(cert)))
739 goto nomem;
740
741 if (!wpa_dbus_dict_close_write(&iter, &dict_iter))
742 goto nomem;
743
744 dbus_connection_send(iface->con, msg, NULL);
745
746 nomem:
747 dbus_message_unref(msg);
748 }
749
750 #ifdef CONFIG_P2P
751
752 /**
753 * wpas_dbus_signal_p2p_group_removed - Signals P2P group was removed
754 * @wpa_s: %wpa_supplicant network interface data
755 * @role: role of this device (client or GO)
756 * Sends signal with i/f name and role as string arguments
757 */
758 void wpas_dbus_signal_p2p_group_removed(struct wpa_supplicant *wpa_s,
759 const char *role)
760 {
761
762 DBusMessage *msg;
763 DBusMessageIter iter;
764 struct wpas_dbus_priv *iface = wpa_s->global->dbus;
765 char *ifname = wpa_s->ifname;
766
767 /* Do nothing if the control interface is not turned on */
768 if (iface == NULL)
769 return;
770
771 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
772 WPAS_DBUS_NEW_IFACE_P2PDEVICE,
773 "GroupFinished");
774 if (msg == NULL)
775 return;
776
777 dbus_message_iter_init_append(msg, &iter);
778
779 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &ifname)) {
780 wpa_printf(MSG_ERROR, "dbus: Failed to construct GroupFinished"
781 "signal -not enough memory for ifname ");
782 goto err;
783 }
784
785 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &role))
786 wpa_printf(MSG_ERROR, "dbus: Failed to construct GroupFinished"
787 "signal -not enough memory for role ");
788 else
789 dbus_connection_send(iface->con, msg, NULL);
790
791 err:
792 dbus_message_unref(msg);
793 }
794
795
796 /**
797 * wpas_dbus_signal_p2p_provision_discovery - Signals various PD events
798 *
799 * @dev_addr - who sent the request or responded to our request.
800 * @request - Will be 1 if request, 0 for response.
801 * @status - valid only in case of response
802 * @config_methods - wps config methods
803 * @generated_pin - pin to be displayed in case of WPS_CONFIG_DISPLAY method
804 *
805 * Sends following provision discovery related events:
806 * ProvisionDiscoveryRequestDisplayPin
807 * ProvisionDiscoveryResponseDisplayPin
808 * ProvisionDiscoveryRequestEnterPin
809 * ProvisionDiscoveryResponseEnterPin
810 * ProvisionDiscoveryPBCRequest
811 * ProvisionDiscoveryPBCResponse
812 *
813 * TODO::
814 * ProvisionDiscoveryFailure (timeout case)
815 */
816 void wpas_dbus_signal_p2p_provision_discovery(struct wpa_supplicant *wpa_s,
817 const u8 *dev_addr, int request,
818 enum p2p_prov_disc_status status,
819 u16 config_methods,
820 unsigned int generated_pin)
821 {
822 DBusMessage *msg;
823 DBusMessageIter iter;
824 struct wpas_dbus_priv *iface;
825 char *_signal;
826 int add_pin = 0;
827 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
828 int error_ret = 1;
829 char pin[9], *p_pin = NULL;
830
831 iface = wpa_s->global->dbus;
832
833 /* Do nothing if the control interface is not turned on */
834 if (iface == NULL)
835 return;
836
837 if (request || !status) {
838 if (config_methods & WPS_CONFIG_DISPLAY)
839 _signal = request ?
840 "ProvisionDiscoveryRequestDisplayPin" :
841 "ProvisionDiscoveryResponseEnterPin";
842 else if (config_methods & WPS_CONFIG_KEYPAD)
843 _signal = request ?
844 "ProvisionDiscoveryRequestEnterPin" :
845 "ProvisionDiscoveryResponseDisplayPin";
846 else if (config_methods & WPS_CONFIG_PUSHBUTTON)
847 _signal = request ? "ProvisionDiscoveryPBCRequest" :
848 "ProvisionDiscoveryPBCResponse";
849 else
850 return; /* Unknown or un-supported method */
851 } else if (!request && status)
852 /* Explicit check for failure response */
853 _signal = "ProvisionDiscoveryFailure";
854
855 add_pin = ((request && (config_methods & WPS_CONFIG_DISPLAY)) ||
856 (!request && !status &&
857 (config_methods & WPS_CONFIG_KEYPAD)));
858
859 if (add_pin) {
860 os_snprintf(pin, sizeof(pin), "%08d", generated_pin);
861 p_pin = pin;
862 }
863
864 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
865 WPAS_DBUS_NEW_IFACE_P2PDEVICE, _signal);
866 if (msg == NULL)
867 return;
868
869 /* Check if this is a known peer */
870 if (!p2p_peer_known(wpa_s->global->p2p, dev_addr))
871 goto error;
872
873 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
874 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
875 COMPACT_MACSTR,
876 wpa_s->dbus_new_path, MAC2STR(dev_addr));
877
878 path = peer_obj_path;
879
880 dbus_message_iter_init_append(msg, &iter);
881
882 if (!dbus_message_iter_append_basic(&iter,
883 DBUS_TYPE_OBJECT_PATH,
884 &path))
885 goto error;
886
887 if (!request && status)
888 /* Attach status to ProvisionDiscoveryFailure */
889 error_ret = !dbus_message_iter_append_basic(&iter,
890 DBUS_TYPE_INT32,
891 &status);
892 else
893 error_ret = (add_pin &&
894 !dbus_message_iter_append_basic(&iter,
895 DBUS_TYPE_STRING,
896 &p_pin));
897
898 error:
899 if (!error_ret)
900 dbus_connection_send(iface->con, msg, NULL);
901 else
902 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
903
904 dbus_message_unref(msg);
905 }
906
907
908 void wpas_dbus_signal_p2p_go_neg_req(struct wpa_supplicant *wpa_s,
909 const u8 *src, u16 dev_passwd_id)
910 {
911 DBusMessage *msg;
912 DBusMessageIter iter;
913 struct wpas_dbus_priv *iface;
914 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
915
916 iface = wpa_s->global->dbus;
917
918 /* Do nothing if the control interface is not turned on */
919 if (iface == NULL)
920 return;
921
922 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
923 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
924 wpa_s->dbus_new_path, MAC2STR(src));
925 path = peer_obj_path;
926
927 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
928 WPAS_DBUS_NEW_IFACE_P2PDEVICE,
929 "GONegotiationRequest");
930 if (msg == NULL)
931 return;
932
933 dbus_message_iter_init_append(msg, &iter);
934
935 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
936 &path) ||
937 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT16,
938 &dev_passwd_id))
939 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
940 else
941 dbus_connection_send(iface->con, msg, NULL);
942
943 dbus_message_unref(msg);
944 }
945
946
947 static int wpas_dbus_get_group_obj_path(struct wpa_supplicant *wpa_s,
948 const struct wpa_ssid *ssid,
949 char *group_obj_path)
950 {
951 char group_name[3];
952
953 if (os_memcmp(ssid->ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN))
954 return -1;
955
956 os_memcpy(group_name, ssid->ssid + P2P_WILDCARD_SSID_LEN, 2);
957 group_name[2] = '\0';
958
959 os_snprintf(group_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
960 "%s/" WPAS_DBUS_NEW_P2P_GROUPS_PART "/%s",
961 wpa_s->dbus_new_path, group_name);
962
963 return 0;
964 }
965
966
967 /**
968 * wpas_dbus_signal_p2p_group_started - Signals P2P group has
969 * started. Emitted when a group is successfully started
970 * irrespective of the role (client/GO) of the current device
971 *
972 * @wpa_s: %wpa_supplicant network interface data
973 * @ssid: SSID object
974 * @client: this device is P2P client
975 * @network_id: network id of the group started, use instead of ssid->id
976 * to account for persistent groups
977 */
978 void wpas_dbus_signal_p2p_group_started(struct wpa_supplicant *wpa_s,
979 const struct wpa_ssid *ssid,
980 int client, int network_id)
981 {
982 DBusMessage *msg;
983 DBusMessageIter iter, dict_iter;
984 struct wpas_dbus_priv *iface;
985 char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
986 char group_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
987
988 iface = wpa_s->parent->global->dbus;
989
990 /* Do nothing if the control interface is not turned on */
991 if (iface == NULL)
992 return;
993
994 if (wpas_dbus_get_group_obj_path(wpa_s, ssid, group_obj_path) < 0)
995 return;
996
997 /* New interface has been created for this group */
998 msg = dbus_message_new_signal(wpa_s->parent->dbus_new_path,
999 WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1000 "GroupStarted");
1001
1002 if (msg == NULL)
1003 return;
1004
1005 dbus_message_iter_init_append(msg, &iter);
1006 if (!wpa_dbus_dict_open_write(&iter, &dict_iter))
1007 goto nomem;
1008
1009 /*
1010 * In case the device supports creating a separate interface the
1011 * DBus client will need to know the object path for the interface
1012 * object this group was created on, so include it here.
1013 */
1014 if (!wpa_dbus_dict_append_object_path(&dict_iter,
1015 "interface_object",
1016 wpa_s->dbus_new_path))
1017 goto nomem;
1018
1019 if (!wpa_dbus_dict_append_string(&dict_iter, "role",
1020 client ? "client" : "GO"))
1021 goto nomem;
1022
1023 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1024 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
1025 wpa_s->parent->dbus_new_path, network_id);
1026
1027 if (!wpa_dbus_dict_append_object_path(&dict_iter, "group_object",
1028 group_obj_path) ||
1029 !wpa_dbus_dict_append_object_path(&dict_iter, "network_object",
1030 net_obj_path) ||
1031 !wpa_dbus_dict_close_write(&iter, &dict_iter))
1032 goto nomem;
1033
1034 dbus_connection_send(iface->con, msg, NULL);
1035
1036 nomem:
1037 dbus_message_unref(msg);
1038 }
1039
1040
1041 /**
1042 *
1043 * Method to emit GONeogtiation Success or Failure signals based
1044 * on status.
1045 * @status: Status of the GO neg request. 0 for success, other for errors.
1046 */
1047 void wpas_dbus_signal_p2p_go_neg_resp(struct wpa_supplicant *wpa_s,
1048 struct p2p_go_neg_results *res)
1049 {
1050 DBusMessage *msg;
1051 DBusMessageIter iter, dict_iter;
1052 DBusMessageIter iter_dict_entry, iter_dict_val, iter_dict_array;
1053 struct wpas_dbus_priv *iface;
1054 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1055 dbus_int32_t freqs[P2P_MAX_CHANNELS];
1056 dbus_int32_t *f_array = freqs;
1057
1058
1059 iface = wpa_s->global->dbus;
1060
1061 os_memset(freqs, 0, sizeof(freqs));
1062 /* Do nothing if the control interface is not turned on */
1063 if (iface == NULL)
1064 return;
1065
1066 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1067 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
1068 wpa_s->dbus_new_path, MAC2STR(res->peer_device_addr));
1069 path = peer_obj_path;
1070
1071 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1072 WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1073 res->status ? "GONegotiationFailure" :
1074 "GONegotiationSuccess");
1075 if (msg == NULL)
1076 return;
1077
1078 dbus_message_iter_init_append(msg, &iter);
1079 if (!wpa_dbus_dict_open_write(&iter, &dict_iter))
1080 goto err;
1081 if (!wpa_dbus_dict_append_object_path(&dict_iter, "peer_object",
1082 path) ||
1083 !wpa_dbus_dict_append_int32(&dict_iter, "status", res->status))
1084 goto err;
1085
1086 if (!res->status) {
1087 int i = 0;
1088 int freq_list_num = 0;
1089
1090 if (res->role_go) {
1091 if (!wpa_dbus_dict_append_byte_array(
1092 &dict_iter, "passphrase",
1093 (const char *) res->passphrase,
1094 sizeof(res->passphrase)))
1095 goto err;
1096 }
1097
1098 if (!wpa_dbus_dict_append_string(&dict_iter, "role_go",
1099 res->role_go ? "GO" :
1100 "client") ||
1101 !wpa_dbus_dict_append_int32(&dict_iter, "frequency",
1102 res->freq) ||
1103 !wpa_dbus_dict_append_byte_array(&dict_iter, "ssid",
1104 (const char *) res->ssid,
1105 res->ssid_len) ||
1106 !wpa_dbus_dict_append_byte_array(&dict_iter,
1107 "peer_device_addr",
1108 (const char *)
1109 res->peer_device_addr,
1110 ETH_ALEN) ||
1111 !wpa_dbus_dict_append_byte_array(&dict_iter,
1112 "peer_interface_addr",
1113 (const char *)
1114 res->peer_interface_addr,
1115 ETH_ALEN) ||
1116 !wpa_dbus_dict_append_string(&dict_iter, "wps_method",
1117 p2p_wps_method_text(
1118 res->wps_method)))
1119 goto err;
1120
1121 for (i = 0; i < P2P_MAX_CHANNELS; i++) {
1122 if (res->freq_list[i]) {
1123 freqs[i] = res->freq_list[i];
1124 freq_list_num++;
1125 }
1126 }
1127
1128 if (!wpa_dbus_dict_begin_array(&dict_iter,
1129 "frequency_list",
1130 DBUS_TYPE_INT32_AS_STRING,
1131 &iter_dict_entry,
1132 &iter_dict_val,
1133 &iter_dict_array))
1134 goto err;
1135
1136 if (!dbus_message_iter_append_fixed_array(&iter_dict_array,
1137 DBUS_TYPE_INT32,
1138 &f_array,
1139 freq_list_num))
1140 goto err;
1141
1142 if (!wpa_dbus_dict_end_array(&dict_iter,
1143 &iter_dict_entry,
1144 &iter_dict_val,
1145 &iter_dict_array))
1146 goto err;
1147
1148 if (!wpa_dbus_dict_append_int32(&dict_iter, "persistent_group",
1149 res->persistent_group) ||
1150 !wpa_dbus_dict_append_uint32(&dict_iter,
1151 "peer_config_timeout",
1152 res->peer_config_timeout))
1153 goto err;
1154 }
1155
1156 if (!wpa_dbus_dict_close_write(&iter, &dict_iter))
1157 goto err;
1158
1159 dbus_connection_send(iface->con, msg, NULL);
1160 err:
1161 dbus_message_unref(msg);
1162 }
1163
1164
1165 /**
1166 *
1167 * Method to emit Invitation Result signal based on status and
1168 * bssid
1169 * @status: Status of the Invite request. 0 for success, other
1170 * for errors
1171 * @bssid : Basic Service Set Identifier
1172 */
1173 void wpas_dbus_signal_p2p_invitation_result(struct wpa_supplicant *wpa_s,
1174 int status, const u8 *bssid)
1175 {
1176 DBusMessage *msg;
1177 DBusMessageIter iter, dict_iter;
1178 struct wpas_dbus_priv *iface;
1179
1180 wpa_printf(MSG_INFO, "%s\n", __func__);
1181
1182 iface = wpa_s->global->dbus;
1183 /* Do nothing if the control interface is not turned on */
1184 if (iface == NULL)
1185 return;
1186
1187 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1188 WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1189 "InvitationResult");
1190
1191 if (msg == NULL)
1192 return;
1193
1194 dbus_message_iter_init_append(msg, &iter);
1195 if (!wpa_dbus_dict_open_write(&iter, &dict_iter))
1196 goto nomem;
1197
1198 if (!wpa_dbus_dict_append_int32(&dict_iter, "status", status))
1199 goto nomem;
1200 if (bssid) {
1201 if (!wpa_dbus_dict_append_byte_array(&dict_iter, "BSSID",
1202 (const char *) bssid,
1203 ETH_ALEN))
1204 goto nomem;
1205 }
1206 if (!wpa_dbus_dict_close_write(&iter, &dict_iter))
1207 goto nomem;
1208
1209 dbus_connection_send(iface->con, msg, NULL);
1210
1211 nomem:
1212 dbus_message_unref(msg);
1213 }
1214
1215
1216 /**
1217 *
1218 * Method to emit a signal for a peer joining the group.
1219 * The signal will carry path to the group member object
1220 * constructed using p2p i/f addr used for connecting.
1221 *
1222 * @wpa_s: %wpa_supplicant network interface data
1223 * @member_addr: addr (p2p i/f) of the peer joining the group
1224 */
1225 void wpas_dbus_signal_p2p_peer_joined(struct wpa_supplicant *wpa_s,
1226 const u8 *member)
1227 {
1228 struct wpas_dbus_priv *iface;
1229 DBusMessage *msg;
1230 DBusMessageIter iter;
1231 char groupmember_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1232
1233 iface = wpa_s->global->dbus;
1234
1235 /* Do nothing if the control interface is not turned on */
1236 if (iface == NULL)
1237 return;
1238
1239 if (!wpa_s->dbus_groupobj_path)
1240 return;
1241
1242 os_snprintf(groupmember_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1243 "%s/" WPAS_DBUS_NEW_P2P_GROUPMEMBERS_PART "/"
1244 COMPACT_MACSTR,
1245 wpa_s->dbus_groupobj_path, MAC2STR(member));
1246
1247 msg = dbus_message_new_signal(wpa_s->dbus_groupobj_path,
1248 WPAS_DBUS_NEW_IFACE_P2P_GROUP,
1249 "PeerJoined");
1250 if (msg == NULL)
1251 return;
1252
1253 dbus_message_iter_init_append(msg, &iter);
1254 path = groupmember_obj_path;
1255 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
1256 &path))
1257 goto err;
1258
1259 dbus_connection_send(iface->con, msg, NULL);
1260
1261 dbus_message_unref(msg);
1262 return;
1263
1264 err:
1265 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1266 dbus_message_unref(msg);
1267 }
1268
1269
1270 /**
1271 *
1272 * Method to emit a signal for a peer disconnecting the group.
1273 * The signal will carry path to the group member object
1274 * constructed using p2p i/f addr used for connecting.
1275 *
1276 * @wpa_s: %wpa_supplicant network interface data
1277 * @member_addr: addr (p2p i/f) of the peer joining the group
1278 */
1279 void wpas_dbus_signal_p2p_peer_disconnected(struct wpa_supplicant *wpa_s,
1280 const u8 *member)
1281 {
1282 struct wpas_dbus_priv *iface;
1283 DBusMessage *msg;
1284 DBusMessageIter iter;
1285 char groupmember_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1286
1287 iface = wpa_s->global->dbus;
1288
1289 /* Do nothing if the control interface is not turned on */
1290 if (iface == NULL)
1291 return;
1292
1293 if (!wpa_s->dbus_groupobj_path)
1294 return;
1295
1296 os_snprintf(groupmember_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1297 "%s/" WPAS_DBUS_NEW_P2P_GROUPMEMBERS_PART "/"
1298 COMPACT_MACSTR,
1299 wpa_s->dbus_groupobj_path, MAC2STR(member));
1300
1301 msg = dbus_message_new_signal(wpa_s->dbus_groupobj_path,
1302 WPAS_DBUS_NEW_IFACE_P2P_GROUP,
1303 "PeerDisconnected");
1304 if (msg == NULL)
1305 return;
1306
1307 dbus_message_iter_init_append(msg, &iter);
1308 path = groupmember_obj_path;
1309 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
1310 &path))
1311 goto err;
1312
1313 dbus_connection_send(iface->con, msg, NULL);
1314
1315 dbus_message_unref(msg);
1316 return;
1317
1318 err:
1319 wpa_printf(MSG_ERROR, "dbus: Failed to construct PeerDisconnected "
1320 "signal");
1321 dbus_message_unref(msg);
1322 }
1323
1324
1325 /**
1326 *
1327 * Method to emit a signal for a service discovery request.
1328 * The signal will carry station address, frequency, dialog token,
1329 * update indicator and it tlvs
1330 *
1331 * @wpa_s: %wpa_supplicant network interface data
1332 * @sa: station addr (p2p i/f) of the peer
1333 * @dialog_token: service discovery request dialog token
1334 * @update_indic: service discovery request update indicator
1335 * @tlvs: service discovery request genrated byte array of tlvs
1336 * @tlvs_len: service discovery request tlvs length
1337 */
1338 void wpas_dbus_signal_p2p_sd_request(struct wpa_supplicant *wpa_s,
1339 int freq, const u8 *sa, u8 dialog_token,
1340 u16 update_indic, const u8 *tlvs,
1341 size_t tlvs_len)
1342 {
1343 DBusMessage *msg;
1344 DBusMessageIter iter, dict_iter;
1345 struct wpas_dbus_priv *iface;
1346 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1347 iface = wpa_s->global->dbus;
1348
1349 /* Do nothing if the control interface is not turned on */
1350 if (iface == NULL)
1351 return;
1352
1353 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1354 WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1355 "ServiceDiscoveryRequest");
1356 if (msg == NULL)
1357 return;
1358
1359 /* Check if this is a known peer */
1360 if (!p2p_peer_known(wpa_s->global->p2p, sa))
1361 goto error;
1362
1363 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1364 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
1365 COMPACT_MACSTR, wpa_s->dbus_new_path, MAC2STR(sa));
1366
1367 path = peer_obj_path;
1368
1369 dbus_message_iter_init_append(msg, &iter);
1370 if (!wpa_dbus_dict_open_write(&iter, &dict_iter))
1371 goto error;
1372
1373
1374 if (!wpa_dbus_dict_append_object_path(&dict_iter, "peer_object",
1375 path) ||
1376 !wpa_dbus_dict_append_int32(&dict_iter, "frequency", freq) ||
1377 !wpa_dbus_dict_append_int32(&dict_iter, "dialog_token",
1378 dialog_token) ||
1379 !wpa_dbus_dict_append_uint16(&dict_iter, "update_indicator",
1380 update_indic) ||
1381 !wpa_dbus_dict_append_byte_array(&dict_iter, "tlvs",
1382 (const char *) tlvs,
1383 tlvs_len) ||
1384 !wpa_dbus_dict_close_write(&iter, &dict_iter))
1385 goto error;
1386
1387 dbus_connection_send(iface->con, msg, NULL);
1388 dbus_message_unref(msg);
1389 return;
1390 error:
1391 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1392 dbus_message_unref(msg);
1393 }
1394
1395
1396 /**
1397 *
1398 * Method to emit a signal for a service discovery response.
1399 * The signal will carry station address, update indicator and it
1400 * tlvs
1401 *
1402 * @wpa_s: %wpa_supplicant network interface data
1403 * @sa: station addr (p2p i/f) of the peer
1404 * @update_indic: service discovery request update indicator
1405 * @tlvs: service discovery request genrated byte array of tlvs
1406 * @tlvs_len: service discovery request tlvs length
1407 */
1408 void wpas_dbus_signal_p2p_sd_response(struct wpa_supplicant *wpa_s,
1409 const u8 *sa, u16 update_indic,
1410 const u8 *tlvs, size_t tlvs_len)
1411 {
1412 DBusMessage *msg;
1413 DBusMessageIter iter, dict_iter;
1414 struct wpas_dbus_priv *iface;
1415 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1416 iface = wpa_s->global->dbus;
1417
1418 /* Do nothing if the control interface is not turned on */
1419 if (iface == NULL)
1420 return;
1421
1422 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1423 WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1424 "ServiceDiscoveryResponse");
1425 if (msg == NULL)
1426 return;
1427
1428 /* Check if this is a known peer */
1429 if (!p2p_peer_known(wpa_s->global->p2p, sa))
1430 goto error;
1431
1432 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1433 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
1434 COMPACT_MACSTR, wpa_s->dbus_new_path, MAC2STR(sa));
1435
1436 path = peer_obj_path;
1437
1438 dbus_message_iter_init_append(msg, &iter);
1439 if (!wpa_dbus_dict_open_write(&iter, &dict_iter))
1440 goto error;
1441
1442 if (!wpa_dbus_dict_append_object_path(&dict_iter, "peer_object",
1443 path) ||
1444 !wpa_dbus_dict_append_uint16(&dict_iter, "update_indicator",
1445 update_indic) ||
1446 !wpa_dbus_dict_append_byte_array(&dict_iter, "tlvs",
1447 (const char *) tlvs,
1448 tlvs_len) ||
1449 !wpa_dbus_dict_close_write(&iter, &dict_iter))
1450 goto error;
1451
1452
1453 dbus_connection_send(iface->con, msg, NULL);
1454 dbus_message_unref(msg);
1455 return;
1456 error:
1457 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1458 dbus_message_unref(msg);
1459 }
1460
1461 /**
1462 * wpas_dbus_signal_persistent_group - Send a persistent group related
1463 * event signal
1464 * @wpa_s: %wpa_supplicant network interface data
1465 * @id: new persistent group id
1466 * @sig_name: signal name - PersistentGroupAdded, PersistentGroupRemoved
1467 * @properties: determines if add second argument with object properties
1468 *
1469 * Notify listeners about an event related to persistent groups.
1470 */
1471 static void wpas_dbus_signal_persistent_group(struct wpa_supplicant *wpa_s,
1472 int id, const char *sig_name,
1473 int properties)
1474 {
1475 struct wpas_dbus_priv *iface;
1476 DBusMessage *msg;
1477 DBusMessageIter iter;
1478 char pgrp_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1479
1480 iface = wpa_s->global->dbus;
1481
1482 /* Do nothing if the control interface is not turned on */
1483 if (iface == NULL)
1484 return;
1485
1486 os_snprintf(pgrp_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1487 "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%u",
1488 wpa_s->dbus_new_path, id);
1489
1490 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1491 WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1492 sig_name);
1493 if (msg == NULL)
1494 return;
1495
1496 dbus_message_iter_init_append(msg, &iter);
1497 path = pgrp_obj_path;
1498 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
1499 &path))
1500 goto err;
1501
1502 if (properties) {
1503 if (!wpa_dbus_get_object_properties(
1504 iface, pgrp_obj_path,
1505 WPAS_DBUS_NEW_IFACE_PERSISTENT_GROUP, &iter))
1506 goto err;
1507 }
1508
1509 dbus_connection_send(iface->con, msg, NULL);
1510
1511 dbus_message_unref(msg);
1512 return;
1513
1514 err:
1515 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1516 dbus_message_unref(msg);
1517 }
1518
1519
1520 /**
1521 * wpas_dbus_signal_persistent_group_added - Send a persistent_group
1522 * added signal
1523 * @wpa_s: %wpa_supplicant network interface data
1524 * @id: new persistent group id
1525 *
1526 * Notify listeners about addition of a new persistent group.
1527 */
1528 static void wpas_dbus_signal_persistent_group_added(
1529 struct wpa_supplicant *wpa_s, int id)
1530 {
1531 wpas_dbus_signal_persistent_group(wpa_s, id, "PersistentGroupAdded",
1532 TRUE);
1533 }
1534
1535
1536 /**
1537 * wpas_dbus_signal_persistent_group_removed - Send a persistent_group
1538 * removed signal
1539 * @wpa_s: %wpa_supplicant network interface data
1540 * @id: persistent group id
1541 *
1542 * Notify listeners about removal of a persistent group.
1543 */
1544 static void wpas_dbus_signal_persistent_group_removed(
1545 struct wpa_supplicant *wpa_s, int id)
1546 {
1547 wpas_dbus_signal_persistent_group(wpa_s, id, "PersistentGroupRemoved",
1548 FALSE);
1549 }
1550
1551
1552 /**
1553 * wpas_dbus_signal_p2p_wps_failed - Signals WpsFailed event
1554 * @wpa_s: %wpa_supplicant network interface data
1555 *
1556 * Sends Event dbus signal with name "fail" and dictionary containing
1557 * "msg" field with fail message number (int32) as arguments
1558 */
1559 void wpas_dbus_signal_p2p_wps_failed(struct wpa_supplicant *wpa_s,
1560 struct wps_event_fail *fail)
1561 {
1562
1563 DBusMessage *msg;
1564 DBusMessageIter iter, dict_iter;
1565 struct wpas_dbus_priv *iface;
1566 char *key = "fail";
1567
1568 iface = wpa_s->global->dbus;
1569
1570 /* Do nothing if the control interface is not turned on */
1571 if (iface == NULL)
1572 return;
1573
1574 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1575 WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1576 "WpsFailed");
1577 if (msg == NULL)
1578 return;
1579
1580 dbus_message_iter_init_append(msg, &iter);
1581
1582 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
1583 !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
1584 !wpa_dbus_dict_append_int32(&dict_iter, "msg", fail->msg) ||
1585 !wpa_dbus_dict_append_int16(&dict_iter, "config_error",
1586 fail->config_error) ||
1587 !wpa_dbus_dict_close_write(&iter, &dict_iter))
1588 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1589 else
1590 dbus_connection_send(iface->con, msg, NULL);
1591
1592 dbus_message_unref(msg);
1593 }
1594
1595 #endif /*CONFIG_P2P*/
1596
1597
1598 /**
1599 * wpas_dbus_signal_prop_changed - Signals change of property
1600 * @wpa_s: %wpa_supplicant network interface data
1601 * @property: indicates which property has changed
1602 *
1603 * Sends PropertyChanged signals with path, interface and arguments
1604 * depending on which property has changed.
1605 */
1606 void wpas_dbus_signal_prop_changed(struct wpa_supplicant *wpa_s,
1607 enum wpas_dbus_prop property)
1608 {
1609 char *prop;
1610
1611 if (wpa_s->dbus_new_path == NULL)
1612 return; /* Skip signal since D-Bus setup is not yet ready */
1613
1614 switch (property) {
1615 case WPAS_DBUS_PROP_AP_SCAN:
1616 prop = "ApScan";
1617 break;
1618 case WPAS_DBUS_PROP_SCANNING:
1619 prop = "Scanning";
1620 break;
1621 case WPAS_DBUS_PROP_STATE:
1622 prop = "State";
1623 break;
1624 case WPAS_DBUS_PROP_CURRENT_BSS:
1625 prop = "CurrentBSS";
1626 break;
1627 case WPAS_DBUS_PROP_CURRENT_NETWORK:
1628 prop = "CurrentNetwork";
1629 break;
1630 case WPAS_DBUS_PROP_BSSS:
1631 prop = "BSSs";
1632 break;
1633 case WPAS_DBUS_PROP_CURRENT_AUTH_MODE:
1634 prop = "CurrentAuthMode";
1635 break;
1636 default:
1637 wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d",
1638 __func__, property);
1639 return;
1640 }
1641
1642 wpa_dbus_mark_property_changed(wpa_s->global->dbus,
1643 wpa_s->dbus_new_path,
1644 WPAS_DBUS_NEW_IFACE_INTERFACE, prop);
1645 }
1646
1647
1648 /**
1649 * wpas_dbus_bss_signal_prop_changed - Signals change of BSS property
1650 * @wpa_s: %wpa_supplicant network interface data
1651 * @property: indicates which property has changed
1652 * @id: unique BSS identifier
1653 *
1654 * Sends PropertyChanged signals with path, interface, and arguments depending
1655 * on which property has changed.
1656 */
1657 void wpas_dbus_bss_signal_prop_changed(struct wpa_supplicant *wpa_s,
1658 enum wpas_dbus_bss_prop property,
1659 unsigned int id)
1660 {
1661 char path[WPAS_DBUS_OBJECT_PATH_MAX];
1662 char *prop;
1663
1664 switch (property) {
1665 case WPAS_DBUS_BSS_PROP_SIGNAL:
1666 prop = "Signal";
1667 break;
1668 case WPAS_DBUS_BSS_PROP_FREQ:
1669 prop = "Frequency";
1670 break;
1671 case WPAS_DBUS_BSS_PROP_MODE:
1672 prop = "Mode";
1673 break;
1674 case WPAS_DBUS_BSS_PROP_PRIVACY:
1675 prop = "Privacy";
1676 break;
1677 case WPAS_DBUS_BSS_PROP_RATES:
1678 prop = "Rates";
1679 break;
1680 case WPAS_DBUS_BSS_PROP_WPA:
1681 prop = "WPA";
1682 break;
1683 case WPAS_DBUS_BSS_PROP_RSN:
1684 prop = "RSN";
1685 break;
1686 case WPAS_DBUS_BSS_PROP_IES:
1687 prop = "IEs";
1688 break;
1689 default:
1690 wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d",
1691 __func__, property);
1692 return;
1693 }
1694
1695 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
1696 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
1697 wpa_s->dbus_new_path, id);
1698
1699 wpa_dbus_mark_property_changed(wpa_s->global->dbus, path,
1700 WPAS_DBUS_NEW_IFACE_BSS, prop);
1701 }
1702
1703
1704 /**
1705 * wpas_dbus_signal_debug_level_changed - Signals change of debug param
1706 * @global: wpa_global structure
1707 *
1708 * Sends PropertyChanged signals informing that debug level has changed.
1709 */
1710 void wpas_dbus_signal_debug_level_changed(struct wpa_global *global)
1711 {
1712 wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
1713 WPAS_DBUS_NEW_INTERFACE,
1714 "DebugLevel");
1715 }
1716
1717
1718 /**
1719 * wpas_dbus_signal_debug_timestamp_changed - Signals change of debug param
1720 * @global: wpa_global structure
1721 *
1722 * Sends PropertyChanged signals informing that debug timestamp has changed.
1723 */
1724 void wpas_dbus_signal_debug_timestamp_changed(struct wpa_global *global)
1725 {
1726 wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
1727 WPAS_DBUS_NEW_INTERFACE,
1728 "DebugTimestamp");
1729 }
1730
1731
1732 /**
1733 * wpas_dbus_signal_debug_show_keys_changed - Signals change of debug param
1734 * @global: wpa_global structure
1735 *
1736 * Sends PropertyChanged signals informing that debug show_keys has changed.
1737 */
1738 void wpas_dbus_signal_debug_show_keys_changed(struct wpa_global *global)
1739 {
1740 wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
1741 WPAS_DBUS_NEW_INTERFACE,
1742 "DebugShowKeys");
1743 }
1744
1745
1746 static void wpas_dbus_register(struct wpa_dbus_object_desc *obj_desc,
1747 void *priv,
1748 WPADBusArgumentFreeFunction priv_free,
1749 const struct wpa_dbus_method_desc *methods,
1750 const struct wpa_dbus_property_desc *properties,
1751 const struct wpa_dbus_signal_desc *signals)
1752 {
1753 int n;
1754
1755 obj_desc->user_data = priv;
1756 obj_desc->user_data_free_func = priv_free;
1757 obj_desc->methods = methods;
1758 obj_desc->properties = properties;
1759 obj_desc->signals = signals;
1760
1761 for (n = 0; properties && properties->dbus_property; properties++)
1762 n++;
1763
1764 obj_desc->prop_changed_flags = os_zalloc(n);
1765 if (!obj_desc->prop_changed_flags)
1766 wpa_printf(MSG_DEBUG, "dbus: %s: can't register handlers",
1767 __func__);
1768 }
1769
1770
1771 static const struct wpa_dbus_method_desc wpas_dbus_global_methods[] = {
1772 { "CreateInterface", WPAS_DBUS_NEW_INTERFACE,
1773 (WPADBusMethodHandler) &wpas_dbus_handler_create_interface,
1774 {
1775 { "args", "a{sv}", ARG_IN },
1776 { "path", "o", ARG_OUT },
1777 END_ARGS
1778 }
1779 },
1780 { "RemoveInterface", WPAS_DBUS_NEW_INTERFACE,
1781 (WPADBusMethodHandler) &wpas_dbus_handler_remove_interface,
1782 {
1783 { "path", "o", ARG_IN },
1784 END_ARGS
1785 }
1786 },
1787 { "GetInterface", WPAS_DBUS_NEW_INTERFACE,
1788 (WPADBusMethodHandler) &wpas_dbus_handler_get_interface,
1789 {
1790 { "ifname", "s", ARG_IN },
1791 { "path", "o", ARG_OUT },
1792 END_ARGS
1793 }
1794 },
1795 { NULL, NULL, NULL, { END_ARGS } }
1796 };
1797
1798 static const struct wpa_dbus_property_desc wpas_dbus_global_properties[] = {
1799 { "DebugLevel", WPAS_DBUS_NEW_INTERFACE, "s",
1800 wpas_dbus_getter_debug_level,
1801 wpas_dbus_setter_debug_level
1802 },
1803 { "DebugTimestamp", WPAS_DBUS_NEW_INTERFACE, "b",
1804 wpas_dbus_getter_debug_timestamp,
1805 wpas_dbus_setter_debug_timestamp
1806 },
1807 { "DebugShowKeys", WPAS_DBUS_NEW_INTERFACE, "b",
1808 wpas_dbus_getter_debug_show_keys,
1809 wpas_dbus_setter_debug_show_keys
1810 },
1811 { "Interfaces", WPAS_DBUS_NEW_INTERFACE, "ao",
1812 wpas_dbus_getter_interfaces,
1813 NULL
1814 },
1815 { "EapMethods", WPAS_DBUS_NEW_INTERFACE, "as",
1816 wpas_dbus_getter_eap_methods,
1817 NULL
1818 },
1819 { NULL, NULL, NULL, NULL, NULL }
1820 };
1821
1822 static const struct wpa_dbus_signal_desc wpas_dbus_global_signals[] = {
1823 { "InterfaceAdded", WPAS_DBUS_NEW_INTERFACE,
1824 {
1825 { "path", "o", ARG_OUT },
1826 { "properties", "a{sv}", ARG_OUT },
1827 END_ARGS
1828 }
1829 },
1830 { "InterfaceRemoved", WPAS_DBUS_NEW_INTERFACE,
1831 {
1832 { "path", "o", ARG_OUT },
1833 END_ARGS
1834 }
1835 },
1836 { "NetworkRequest", WPAS_DBUS_NEW_IFACE_INTERFACE,
1837 {
1838 { "path", "o", ARG_OUT },
1839 { "field", "s", ARG_OUT },
1840 { "text", "s", ARG_OUT },
1841 END_ARGS
1842 }
1843 },
1844 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
1845 { "PropertiesChanged", WPAS_DBUS_NEW_INTERFACE,
1846 {
1847 { "properties", "a{sv}", ARG_OUT },
1848 END_ARGS
1849 }
1850 },
1851 { NULL, NULL, { END_ARGS } }
1852 };
1853
1854
1855 /**
1856 * wpas_dbus_ctrl_iface_init - Initialize dbus control interface
1857 * @global: Pointer to global data from wpa_supplicant_init()
1858 * Returns: 0 on success or -1 on failure
1859 *
1860 * Initialize the dbus control interface for wpa_supplicantand and start
1861 * receiving commands from external programs over the bus.
1862 */
1863 int wpas_dbus_ctrl_iface_init(struct wpas_dbus_priv *priv)
1864 {
1865 struct wpa_dbus_object_desc *obj_desc;
1866 int ret;
1867
1868 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
1869 if (!obj_desc) {
1870 wpa_printf(MSG_ERROR, "Not enough memory "
1871 "to create object description");
1872 return -1;
1873 }
1874
1875 wpas_dbus_register(obj_desc, priv->global, NULL,
1876 wpas_dbus_global_methods,
1877 wpas_dbus_global_properties,
1878 wpas_dbus_global_signals);
1879
1880 wpa_printf(MSG_DEBUG, "dbus: Register D-Bus object '%s'",
1881 WPAS_DBUS_NEW_PATH);
1882 ret = wpa_dbus_ctrl_iface_init(priv, WPAS_DBUS_NEW_PATH,
1883 WPAS_DBUS_NEW_SERVICE,
1884 obj_desc);
1885 if (ret < 0)
1886 free_dbus_object_desc(obj_desc);
1887 else
1888 priv->dbus_new_initialized = 1;
1889
1890 return ret;
1891 }
1892
1893
1894 /**
1895 * wpas_dbus_ctrl_iface_deinit - Deinitialize dbus ctrl interface for
1896 * wpa_supplicant
1897 * @iface: Pointer to dbus private data from wpas_dbus_init()
1898 *
1899 * Deinitialize the dbus control interface that was initialized with
1900 * wpas_dbus_ctrl_iface_init().
1901 */
1902 void wpas_dbus_ctrl_iface_deinit(struct wpas_dbus_priv *iface)
1903 {
1904 if (!iface->dbus_new_initialized)
1905 return;
1906 wpa_printf(MSG_DEBUG, "dbus: Unregister D-Bus object '%s'",
1907 WPAS_DBUS_NEW_PATH);
1908 dbus_connection_unregister_object_path(iface->con,
1909 WPAS_DBUS_NEW_PATH);
1910 }
1911
1912
1913 static void wpa_dbus_free(void *ptr)
1914 {
1915 os_free(ptr);
1916 }
1917
1918
1919 static const struct wpa_dbus_property_desc wpas_dbus_network_properties[] = {
1920 { "Properties", WPAS_DBUS_NEW_IFACE_NETWORK, "a{sv}",
1921 wpas_dbus_getter_network_properties,
1922 wpas_dbus_setter_network_properties
1923 },
1924 { "Enabled", WPAS_DBUS_NEW_IFACE_NETWORK, "b",
1925 wpas_dbus_getter_enabled,
1926 wpas_dbus_setter_enabled
1927 },
1928 { NULL, NULL, NULL, NULL, NULL }
1929 };
1930
1931
1932 static const struct wpa_dbus_signal_desc wpas_dbus_network_signals[] = {
1933 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
1934 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_NETWORK,
1935 {
1936 { "properties", "a{sv}", ARG_OUT },
1937 END_ARGS
1938 }
1939 },
1940 { NULL, NULL, { END_ARGS } }
1941 };
1942
1943
1944 /**
1945 * wpas_dbus_register_network - Register a configured network with dbus
1946 * @wpa_s: wpa_supplicant interface structure
1947 * @ssid: network configuration data
1948 * Returns: 0 on success, -1 on failure
1949 *
1950 * Registers network representing object with dbus
1951 */
1952 int wpas_dbus_register_network(struct wpa_supplicant *wpa_s,
1953 struct wpa_ssid *ssid)
1954 {
1955 struct wpas_dbus_priv *ctrl_iface;
1956 struct wpa_dbus_object_desc *obj_desc;
1957 struct network_handler_args *arg;
1958 char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
1959
1960 #ifdef CONFIG_P2P
1961 /*
1962 * If it is a persistent group register it as such.
1963 * This is to handle cases where an interface is being initialized
1964 * with a list of networks read from config.
1965 */
1966 if (network_is_persistent_group(ssid))
1967 return wpas_dbus_register_persistent_group(wpa_s, ssid);
1968 #endif /* CONFIG_P2P */
1969
1970 /* Do nothing if the control interface is not turned on */
1971 if (wpa_s == NULL || wpa_s->global == NULL)
1972 return 0;
1973 ctrl_iface = wpa_s->global->dbus;
1974 if (ctrl_iface == NULL)
1975 return 0;
1976
1977 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1978 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
1979 wpa_s->dbus_new_path, ssid->id);
1980
1981 wpa_printf(MSG_DEBUG, "dbus: Register network object '%s'",
1982 net_obj_path);
1983 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
1984 if (!obj_desc) {
1985 wpa_printf(MSG_ERROR, "Not enough memory "
1986 "to create object description");
1987 goto err;
1988 }
1989
1990 /* allocate memory for handlers arguments */
1991 arg = os_zalloc(sizeof(struct network_handler_args));
1992 if (!arg) {
1993 wpa_printf(MSG_ERROR, "Not enough memory "
1994 "to create arguments for method");
1995 goto err;
1996 }
1997
1998 arg->wpa_s = wpa_s;
1999 arg->ssid = ssid;
2000
2001 wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
2002 wpas_dbus_network_properties,
2003 wpas_dbus_network_signals);
2004
2005 if (wpa_dbus_register_object_per_iface(ctrl_iface, net_obj_path,
2006 wpa_s->ifname, obj_desc))
2007 goto err;
2008
2009 wpas_dbus_signal_network_added(wpa_s, ssid->id);
2010
2011 return 0;
2012
2013 err:
2014 free_dbus_object_desc(obj_desc);
2015 return -1;
2016 }
2017
2018
2019 /**
2020 * wpas_dbus_unregister_network - Unregister a configured network from dbus
2021 * @wpa_s: wpa_supplicant interface structure
2022 * @nid: network id
2023 * Returns: 0 on success, -1 on failure
2024 *
2025 * Unregisters network representing object from dbus
2026 */
2027 int wpas_dbus_unregister_network(struct wpa_supplicant *wpa_s, int nid)
2028 {
2029 struct wpas_dbus_priv *ctrl_iface;
2030 char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
2031 int ret;
2032 struct wpa_ssid *ssid;
2033
2034 ssid = wpa_config_get_network(wpa_s->conf, nid);
2035
2036 #ifdef CONFIG_P2P
2037 /* If it is a persistent group unregister it as such */
2038 if (ssid && network_is_persistent_group(ssid))
2039 return wpas_dbus_unregister_persistent_group(wpa_s, nid);
2040 #endif /* CONFIG_P2P */
2041
2042 /* Do nothing if the control interface is not turned on */
2043 if (wpa_s->global == NULL || wpa_s->dbus_new_path == NULL)
2044 return 0;
2045 ctrl_iface = wpa_s->global->dbus;
2046 if (ctrl_iface == NULL)
2047 return 0;
2048
2049 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2050 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
2051 wpa_s->dbus_new_path, nid);
2052
2053 wpa_printf(MSG_DEBUG, "dbus: Unregister network object '%s'",
2054 net_obj_path);
2055 ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, net_obj_path);
2056
2057 if (!ret)
2058 wpas_dbus_signal_network_removed(wpa_s, nid);
2059
2060 return ret;
2061 }
2062
2063
2064 static const struct wpa_dbus_property_desc wpas_dbus_bss_properties[] = {
2065 { "SSID", WPAS_DBUS_NEW_IFACE_BSS, "ay",
2066 wpas_dbus_getter_bss_ssid,
2067 NULL
2068 },
2069 { "BSSID", WPAS_DBUS_NEW_IFACE_BSS, "ay",
2070 wpas_dbus_getter_bss_bssid,
2071 NULL
2072 },
2073 { "Privacy", WPAS_DBUS_NEW_IFACE_BSS, "b",
2074 wpas_dbus_getter_bss_privacy,
2075 NULL
2076 },
2077 { "Mode", WPAS_DBUS_NEW_IFACE_BSS, "s",
2078 wpas_dbus_getter_bss_mode,
2079 NULL
2080 },
2081 { "Signal", WPAS_DBUS_NEW_IFACE_BSS, "n",
2082 wpas_dbus_getter_bss_signal,
2083 NULL
2084 },
2085 { "Frequency", WPAS_DBUS_NEW_IFACE_BSS, "q",
2086 wpas_dbus_getter_bss_frequency,
2087 NULL
2088 },
2089 { "Rates", WPAS_DBUS_NEW_IFACE_BSS, "au",
2090 wpas_dbus_getter_bss_rates,
2091 NULL
2092 },
2093 { "WPA", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
2094 wpas_dbus_getter_bss_wpa,
2095 NULL
2096 },
2097 { "RSN", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
2098 wpas_dbus_getter_bss_rsn,
2099 NULL
2100 },
2101 { "IEs", WPAS_DBUS_NEW_IFACE_BSS, "ay",
2102 wpas_dbus_getter_bss_ies,
2103 NULL
2104 },
2105 { NULL, NULL, NULL, NULL, NULL }
2106 };
2107
2108
2109 static const struct wpa_dbus_signal_desc wpas_dbus_bss_signals[] = {
2110 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
2111 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_BSS,
2112 {
2113 { "properties", "a{sv}", ARG_OUT },
2114 END_ARGS
2115 }
2116 },
2117 { NULL, NULL, { END_ARGS } }
2118 };
2119
2120
2121 /**
2122 * wpas_dbus_unregister_bss - Unregister a scanned BSS from dbus
2123 * @wpa_s: wpa_supplicant interface structure
2124 * @bssid: scanned network bssid
2125 * @id: unique BSS identifier
2126 * Returns: 0 on success, -1 on failure
2127 *
2128 * Unregisters BSS representing object from dbus
2129 */
2130 int wpas_dbus_unregister_bss(struct wpa_supplicant *wpa_s,
2131 u8 bssid[ETH_ALEN], unsigned int id)
2132 {
2133 struct wpas_dbus_priv *ctrl_iface;
2134 char bss_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
2135
2136 /* Do nothing if the control interface is not turned on */
2137 if (wpa_s == NULL || wpa_s->global == NULL)
2138 return 0;
2139 ctrl_iface = wpa_s->global->dbus;
2140 if (ctrl_iface == NULL)
2141 return 0;
2142
2143 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2144 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
2145 wpa_s->dbus_new_path, id);
2146
2147 wpa_printf(MSG_DEBUG, "dbus: Unregister BSS object '%s'",
2148 bss_obj_path);
2149 if (wpa_dbus_unregister_object_per_iface(ctrl_iface, bss_obj_path)) {
2150 wpa_printf(MSG_ERROR, "dbus: Cannot unregister BSS object %s",
2151 bss_obj_path);
2152 return -1;
2153 }
2154
2155 wpas_dbus_signal_bss_removed(wpa_s, bss_obj_path);
2156 wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_BSSS);
2157
2158 return 0;
2159 }
2160
2161
2162 /**
2163 * wpas_dbus_register_bss - Register a scanned BSS with dbus
2164 * @wpa_s: wpa_supplicant interface structure
2165 * @bssid: scanned network bssid
2166 * @id: unique BSS identifier
2167 * Returns: 0 on success, -1 on failure
2168 *
2169 * Registers BSS representing object with dbus
2170 */
2171 int wpas_dbus_register_bss(struct wpa_supplicant *wpa_s,
2172 u8 bssid[ETH_ALEN], unsigned int id)
2173 {
2174 struct wpas_dbus_priv *ctrl_iface;
2175 struct wpa_dbus_object_desc *obj_desc;
2176 char bss_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
2177 struct bss_handler_args *arg;
2178
2179 /* Do nothing if the control interface is not turned on */
2180 if (wpa_s == NULL || wpa_s->global == NULL)
2181 return 0;
2182 ctrl_iface = wpa_s->global->dbus;
2183 if (ctrl_iface == NULL)
2184 return 0;
2185
2186 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2187 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
2188 wpa_s->dbus_new_path, id);
2189
2190 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
2191 if (!obj_desc) {
2192 wpa_printf(MSG_ERROR, "Not enough memory "
2193 "to create object description");
2194 goto err;
2195 }
2196
2197 arg = os_zalloc(sizeof(struct bss_handler_args));
2198 if (!arg) {
2199 wpa_printf(MSG_ERROR, "Not enough memory "
2200 "to create arguments for handler");
2201 goto err;
2202 }
2203 arg->wpa_s = wpa_s;
2204 arg->id = id;
2205
2206 wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
2207 wpas_dbus_bss_properties,
2208 wpas_dbus_bss_signals);
2209
2210 wpa_printf(MSG_DEBUG, "dbus: Register BSS object '%s'",
2211 bss_obj_path);
2212 if (wpa_dbus_register_object_per_iface(ctrl_iface, bss_obj_path,
2213 wpa_s->ifname, obj_desc)) {
2214 wpa_printf(MSG_ERROR,
2215 "Cannot register BSSID dbus object %s.",
2216 bss_obj_path);
2217 goto err;
2218 }
2219
2220 wpas_dbus_signal_bss_added(wpa_s, bss_obj_path);
2221 wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_BSSS);
2222
2223 return 0;
2224
2225 err:
2226 free_dbus_object_desc(obj_desc);
2227 return -1;
2228 }
2229
2230
2231 static const struct wpa_dbus_method_desc wpas_dbus_interface_methods[] = {
2232 { "Scan", WPAS_DBUS_NEW_IFACE_INTERFACE,
2233 (WPADBusMethodHandler) &wpas_dbus_handler_scan,
2234 {
2235 { "args", "a{sv}", ARG_IN },
2236 END_ARGS
2237 }
2238 },
2239 { "Disconnect", WPAS_DBUS_NEW_IFACE_INTERFACE,
2240 (WPADBusMethodHandler) &wpas_dbus_handler_disconnect,
2241 {
2242 END_ARGS
2243 }
2244 },
2245 { "AddNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
2246 (WPADBusMethodHandler) &wpas_dbus_handler_add_network,
2247 {
2248 { "args", "a{sv}", ARG_IN },
2249 { "path", "o", ARG_OUT },
2250 END_ARGS
2251 }
2252 },
2253 { "RemoveNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
2254 (WPADBusMethodHandler) &wpas_dbus_handler_remove_network,
2255 {
2256 { "path", "o", ARG_IN },
2257 END_ARGS
2258 }
2259 },
2260 { "RemoveAllNetworks", WPAS_DBUS_NEW_IFACE_INTERFACE,
2261 (WPADBusMethodHandler) &wpas_dbus_handler_remove_all_networks,
2262 {
2263 END_ARGS
2264 }
2265 },
2266 { "SelectNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
2267 (WPADBusMethodHandler) &wpas_dbus_handler_select_network,
2268 {
2269 { "path", "o", ARG_IN },
2270 END_ARGS
2271 }
2272 },
2273 { "NetworkReply", WPAS_DBUS_NEW_IFACE_INTERFACE,
2274 (WPADBusMethodHandler) &wpas_dbus_handler_network_reply,
2275 {
2276 { "path", "o", ARG_IN },
2277 { "field", "s", ARG_IN },
2278 { "value", "s", ARG_IN },
2279 END_ARGS
2280 }
2281 },
2282 { "AddBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
2283 (WPADBusMethodHandler) &wpas_dbus_handler_add_blob,
2284 {
2285 { "name", "s", ARG_IN },
2286 { "data", "ay", ARG_IN },
2287 END_ARGS
2288 }
2289 },
2290 { "GetBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
2291 (WPADBusMethodHandler) &wpas_dbus_handler_get_blob,
2292 {
2293 { "name", "s", ARG_IN },
2294 { "data", "ay", ARG_OUT },
2295 END_ARGS
2296 }
2297 },
2298 { "RemoveBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
2299 (WPADBusMethodHandler) &wpas_dbus_handler_remove_blob,
2300 {
2301 { "name", "s", ARG_IN },
2302 END_ARGS
2303 }
2304 },
2305 #ifdef CONFIG_WPS
2306 { "Start", WPAS_DBUS_NEW_IFACE_WPS,
2307 (WPADBusMethodHandler) &wpas_dbus_handler_wps_start,
2308 {
2309 { "args", "a{sv}", ARG_IN },
2310 { "output", "a{sv}", ARG_OUT },
2311 END_ARGS
2312 }
2313 },
2314 #endif /* CONFIG_WPS */
2315 #ifdef CONFIG_P2P
2316 { "Find", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2317 (WPADBusMethodHandler)wpas_dbus_handler_p2p_find,
2318 {
2319 { "args", "a{sv}", ARG_IN },
2320 END_ARGS
2321 }
2322 },
2323 { "StopFind", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2324 (WPADBusMethodHandler)wpas_dbus_handler_p2p_stop_find,
2325 {
2326 END_ARGS
2327 }
2328 },
2329 { "Listen", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2330 (WPADBusMethodHandler)wpas_dbus_handler_p2p_listen,
2331 {
2332 { "timeout", "i", ARG_IN },
2333 END_ARGS
2334 }
2335 },
2336 { "ExtendedListen", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2337 (WPADBusMethodHandler)wpas_dbus_handler_p2p_extendedlisten,
2338 {
2339 { "args", "a{sv}", ARG_IN },
2340 END_ARGS
2341 }
2342 },
2343 { "PresenceRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2344 (WPADBusMethodHandler)wpas_dbus_handler_p2p_presence_request,
2345 {
2346 { "args", "a{sv}", ARG_IN },
2347 END_ARGS
2348 }
2349 },
2350 { "ProvisionDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2351 (WPADBusMethodHandler)wpas_dbus_handler_p2p_prov_disc_req,
2352 {
2353 { "peer", "o", ARG_IN },
2354 { "config_method", "s", ARG_IN },
2355 END_ARGS
2356 }
2357 },
2358 { "Connect", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2359 (WPADBusMethodHandler)wpas_dbus_handler_p2p_connect,
2360 {
2361 { "args", "a{sv}", ARG_IN },
2362 { "generated_pin", "s", ARG_OUT },
2363 END_ARGS
2364 }
2365 },
2366 { "GroupAdd", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2367 (WPADBusMethodHandler)wpas_dbus_handler_p2p_group_add,
2368 {
2369 { "args", "a{sv}", ARG_IN },
2370 END_ARGS
2371 }
2372 },
2373 { "Invite", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2374 (WPADBusMethodHandler)wpas_dbus_handler_p2p_invite,
2375 {
2376 { "args", "a{sv}", ARG_IN },
2377 END_ARGS
2378 }
2379 },
2380 { "Disconnect", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2381 (WPADBusMethodHandler)wpas_dbus_handler_p2p_disconnect,
2382 {
2383 END_ARGS
2384 }
2385 },
2386 { "RejectPeer", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2387 (WPADBusMethodHandler)wpas_dbus_handler_p2p_rejectpeer,
2388 {
2389 { "peer", "o", ARG_IN },
2390 END_ARGS
2391 }
2392 },
2393 { "Flush", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2394 (WPADBusMethodHandler)wpas_dbus_handler_p2p_flush,
2395 {
2396 END_ARGS
2397 }
2398 },
2399 { "AddService", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2400 (WPADBusMethodHandler)wpas_dbus_handler_p2p_add_service,
2401 {
2402 { "args", "a{sv}", ARG_IN },
2403 END_ARGS
2404 }
2405 },
2406 { "DeleteService", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2407 (WPADBusMethodHandler)wpas_dbus_handler_p2p_delete_service,
2408 {
2409 { "args", "a{sv}", ARG_IN },
2410 END_ARGS
2411 }
2412 },
2413 { "FlushService", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2414 (WPADBusMethodHandler)wpas_dbus_handler_p2p_flush_service,
2415 {
2416 END_ARGS
2417 }
2418 },
2419 { "ServiceDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2420 (WPADBusMethodHandler)wpas_dbus_handler_p2p_service_sd_req,
2421 {
2422 { "args", "a{sv}", ARG_IN },
2423 END_ARGS
2424 }
2425 },
2426 { "ServiceDiscoveryResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2427 (WPADBusMethodHandler)wpas_dbus_handler_p2p_service_sd_res,
2428 {
2429 { "args", "a{sv}", ARG_IN },
2430 END_ARGS
2431 }
2432 },
2433 { "ServiceDiscoveryCancelRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2434 (WPADBusMethodHandler)wpas_dbus_handler_p2p_service_sd_cancel_req,
2435 {
2436 { "args", "t", ARG_IN },
2437 END_ARGS
2438 }
2439 },
2440 { "ServiceUpdate", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2441 (WPADBusMethodHandler)wpas_dbus_handler_p2p_service_update,
2442 {
2443 END_ARGS
2444 }
2445 },
2446 { "ServiceDiscoveryExternal", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2447 (WPADBusMethodHandler)wpas_dbus_handler_p2p_serv_disc_external,
2448 {
2449 { "arg", "i", ARG_IN },
2450 END_ARGS
2451 }
2452 },
2453 { "ServiceDiscoveryExternal", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2454 (WPADBusMethodHandler)wpas_dbus_handler_p2p_serv_disc_external,
2455 {
2456 { "arg", "i", ARG_IN },
2457 END_ARGS
2458 }
2459 },
2460 { "AddPersistentGroup", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2461 (WPADBusMethodHandler) wpas_dbus_handler_add_persistent_group,
2462 {
2463 { "args", "a{sv}", ARG_IN },
2464 { "path", "o", ARG_OUT },
2465 END_ARGS
2466 }
2467 },
2468 { "RemovePersistentGroup", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2469 (WPADBusMethodHandler) wpas_dbus_handler_remove_persistent_group,
2470 {
2471 { "path", "o", ARG_IN },
2472 END_ARGS
2473 }
2474 },
2475 { "RemoveAllPersistentGroups", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2476 (WPADBusMethodHandler)
2477 wpas_dbus_handler_remove_all_persistent_groups,
2478 {
2479 END_ARGS
2480 }
2481 },
2482 #endif /* CONFIG_P2P */
2483 { "FlushBSS", WPAS_DBUS_NEW_IFACE_INTERFACE,
2484 (WPADBusMethodHandler) &wpas_dbus_handler_flush_bss,
2485 {
2486 { "age", "u", ARG_IN },
2487 END_ARGS
2488 }
2489 },
2490 { NULL, NULL, NULL, { END_ARGS } }
2491 };
2492
2493 static const struct wpa_dbus_property_desc wpas_dbus_interface_properties[] = {
2494 { "Capabilities", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{sv}",
2495 wpas_dbus_getter_capabilities,
2496 NULL
2497 },
2498 { "State", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
2499 wpas_dbus_getter_state,
2500 NULL
2501 },
2502 { "Scanning", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
2503 wpas_dbus_getter_scanning,
2504 NULL
2505 },
2506 { "ApScan", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
2507 wpas_dbus_getter_ap_scan,
2508 wpas_dbus_setter_ap_scan
2509 },
2510 { "BSSExpireAge", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
2511 wpas_dbus_getter_bss_expire_age,
2512 wpas_dbus_setter_bss_expire_age
2513 },
2514 { "BSSExpireCount", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
2515 wpas_dbus_getter_bss_expire_count,
2516 wpas_dbus_setter_bss_expire_count
2517 },
2518 { "Country", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
2519 wpas_dbus_getter_country,
2520 wpas_dbus_setter_country
2521 },
2522 { "Ifname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
2523 wpas_dbus_getter_ifname,
2524 NULL
2525 },
2526 { "Driver", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
2527 wpas_dbus_getter_driver,
2528 NULL
2529 },
2530 { "BridgeIfname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
2531 wpas_dbus_getter_bridge_ifname,
2532 NULL
2533 },
2534 { "CurrentBSS", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
2535 wpas_dbus_getter_current_bss,
2536 NULL
2537 },
2538 { "CurrentNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
2539 wpas_dbus_getter_current_network,
2540 NULL
2541 },
2542 { "CurrentAuthMode", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
2543 wpas_dbus_getter_current_auth_mode,
2544 NULL
2545 },
2546 { "Blobs", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{say}",
2547 wpas_dbus_getter_blobs,
2548 NULL
2549 },
2550 { "BSSs", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
2551 wpas_dbus_getter_bsss,
2552 NULL
2553 },
2554 { "Networks", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
2555 wpas_dbus_getter_networks,
2556 NULL
2557 },
2558 { "FastReauth", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
2559 wpas_dbus_getter_fast_reauth,
2560 wpas_dbus_setter_fast_reauth
2561 },
2562 #ifdef CONFIG_WPS
2563 { "ProcessCredentials", WPAS_DBUS_NEW_IFACE_WPS, "b",
2564 wpas_dbus_getter_process_credentials,
2565 wpas_dbus_setter_process_credentials
2566 },
2567 #endif /* CONFIG_WPS */
2568 #ifdef CONFIG_P2P
2569 { "P2PDeviceProperties", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "a{sv}",
2570 wpas_dbus_getter_p2p_device_properties,
2571 wpas_dbus_setter_p2p_device_properties
2572 },
2573 { "Peers", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "ao",
2574 wpas_dbus_getter_p2p_peers,
2575 NULL
2576 },
2577 { "Role", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "s",
2578 wpas_dbus_getter_p2p_role,
2579 NULL
2580 },
2581 { "Group", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "o",
2582 wpas_dbus_getter_p2p_group,
2583 NULL
2584 },
2585 { "PeerGO", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "o",
2586 wpas_dbus_getter_p2p_peergo,
2587 NULL
2588 },
2589 { "PersistentGroups", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "ao",
2590 wpas_dbus_getter_persistent_groups,
2591 NULL
2592 },
2593 #endif /* CONFIG_P2P */
2594 { NULL, NULL, NULL, NULL, NULL }
2595 };
2596
2597 static const struct wpa_dbus_signal_desc wpas_dbus_interface_signals[] = {
2598 { "ScanDone", WPAS_DBUS_NEW_IFACE_INTERFACE,
2599 {
2600 { "success", "b", ARG_OUT },
2601 END_ARGS
2602 }
2603 },
2604 { "BSSAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
2605 {
2606 { "path", "o", ARG_OUT },
2607 { "properties", "a{sv}", ARG_OUT },
2608 END_ARGS
2609 }
2610 },
2611 { "BSSRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
2612 {
2613 { "path", "o", ARG_OUT },
2614 END_ARGS
2615 }
2616 },
2617 { "BlobAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
2618 {
2619 { "name", "s", ARG_OUT },
2620 END_ARGS
2621 }
2622 },
2623 { "BlobRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
2624 {
2625 { "name", "s", ARG_OUT },
2626 END_ARGS
2627 }
2628 },
2629 { "NetworkAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
2630 {
2631 { "path", "o", ARG_OUT },
2632 { "properties", "a{sv}", ARG_OUT },
2633 END_ARGS
2634 }
2635 },
2636 { "NetworkRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
2637 {
2638 { "path", "o", ARG_OUT },
2639 END_ARGS
2640 }
2641 },
2642 { "NetworkSelected", WPAS_DBUS_NEW_IFACE_INTERFACE,
2643 {
2644 { "path", "o", ARG_OUT },
2645 END_ARGS
2646 }
2647 },
2648 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
2649 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_INTERFACE,
2650 {
2651 { "properties", "a{sv}", ARG_OUT },
2652 END_ARGS
2653 }
2654 },
2655 #ifdef CONFIG_WPS
2656 { "Event", WPAS_DBUS_NEW_IFACE_WPS,
2657 {
2658 { "name", "s", ARG_OUT },
2659 { "args", "a{sv}", ARG_OUT },
2660 END_ARGS
2661 }
2662 },
2663 { "Credentials", WPAS_DBUS_NEW_IFACE_WPS,
2664 {
2665 { "credentials", "a{sv}", ARG_OUT },
2666 END_ARGS
2667 }
2668 },
2669 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
2670 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_WPS,
2671 {
2672 { "properties", "a{sv}", ARG_OUT },
2673 END_ARGS
2674 }
2675 },
2676 #endif /* CONFIG_WPS */
2677 #ifdef CONFIG_P2P
2678 { "P2PStateChanged", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2679 {
2680 { "states", "a{ss}", ARG_OUT },
2681 END_ARGS
2682 }
2683 },
2684 { "DeviceFound", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2685 {
2686 { "path", "o", ARG_OUT },
2687 { "properties", "a{sv}", ARG_OUT },
2688 END_ARGS
2689 }
2690 },
2691 { "DeviceLost", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2692 {
2693 { "path", "o", ARG_OUT },
2694 END_ARGS
2695 }
2696 },
2697 { "ProvisionDiscoveryRequestDisplayPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2698 {
2699 { "peer_object", "o", ARG_OUT },
2700 { "pin", "s", ARG_OUT },
2701 END_ARGS
2702 }
2703 },
2704 { "ProvisionDiscoveryResponseDisplayPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2705 {
2706 { "peer_object", "o", ARG_OUT },
2707 { "pin", "s", ARG_OUT },
2708 END_ARGS
2709 }
2710 },
2711 { "ProvisionDiscoveryRequestEnterPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2712 {
2713 { "peer_object", "o", ARG_OUT },
2714 END_ARGS
2715 }
2716 },
2717 { "ProvisionDiscoveryResponseEnterPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2718 {
2719 { "peer_object", "o", ARG_OUT },
2720 END_ARGS
2721 }
2722 },
2723 { "ProvisionDiscoveryPBCRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2724 {
2725 { "peer_object", "o", ARG_OUT },
2726 END_ARGS
2727 }
2728 },
2729 { "ProvisionDiscoveryPBCResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2730 {
2731 { "peer_object", "o", ARG_OUT },
2732 END_ARGS
2733 }
2734 },
2735 { "ProvisionDiscoveryFailure", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2736 {
2737 { "peer_object", "o", ARG_OUT },
2738 { "status", "i", ARG_OUT },
2739 END_ARGS
2740 }
2741 },
2742 { "GroupStarted", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2743 {
2744 { "properties", "a{sv}", ARG_OUT },
2745 END_ARGS
2746 }
2747 },
2748 { "GONegotiationSuccess", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2749 {
2750 END_ARGS
2751 }
2752 },
2753 { "GONegotiationFailure", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2754 {
2755 { "status", "i", ARG_OUT },
2756 END_ARGS
2757 }
2758 },
2759 { "GONegotiationRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2760 {
2761 { "path", "o", ARG_OUT },
2762 { "dev_passwd_id", "i", ARG_OUT },
2763 END_ARGS
2764 }
2765 },
2766 { "InvitationResult", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2767 {
2768 { "invite_result", "a{sv}", ARG_OUT },
2769 END_ARGS
2770 }
2771 },
2772 { "GroupFinished", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2773 {
2774 { "ifname", "s", ARG_OUT },
2775 { "role", "s", ARG_OUT },
2776 END_ARGS
2777 }
2778 },
2779 { "ServiceDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2780 {
2781 { "sd_request", "a{sv}", ARG_OUT },
2782 END_ARGS
2783 }
2784 },
2785 { "ServiceDiscoveryResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2786 {
2787 { "sd_response", "a{sv}", ARG_OUT },
2788 END_ARGS
2789 }
2790 },
2791 { "PersistentGroupAdded", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2792 {
2793 { "path", "o", ARG_OUT },
2794 { "properties", "a{sv}", ARG_OUT },
2795 END_ARGS
2796 }
2797 },
2798 { "PersistentGroupRemoved", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2799 {
2800 { "path", "o", ARG_OUT },
2801 END_ARGS
2802 }
2803 },
2804 { "WpsFailed", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2805 {
2806 { "name", "s", ARG_OUT },
2807 { "args", "a{sv}", ARG_OUT },
2808 END_ARGS
2809 }
2810 },
2811 #endif /* CONFIG_P2P */
2812 { "Certification", WPAS_DBUS_NEW_IFACE_INTERFACE,
2813 {
2814 { "certification", "a{sv}", ARG_OUT },
2815 END_ARGS
2816 }
2817 },
2818 { NULL, NULL, { END_ARGS } }
2819 };
2820
2821
2822 int wpas_dbus_register_interface(struct wpa_supplicant *wpa_s)
2823 {
2824
2825 struct wpa_dbus_object_desc *obj_desc = NULL;
2826 struct wpas_dbus_priv *ctrl_iface = wpa_s->global->dbus;
2827 int next;
2828
2829 /* Do nothing if the control interface is not turned on */
2830 if (ctrl_iface == NULL)
2831 return 0;
2832
2833 /* Create and set the interface's object path */
2834 wpa_s->dbus_new_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
2835 if (wpa_s->dbus_new_path == NULL)
2836 return -1;
2837 next = ctrl_iface->next_objid++;
2838 os_snprintf(wpa_s->dbus_new_path, WPAS_DBUS_OBJECT_PATH_MAX,
2839 WPAS_DBUS_NEW_PATH_INTERFACES "/%u",
2840 next);
2841
2842 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
2843 if (!obj_desc) {
2844 wpa_printf(MSG_ERROR, "Not enough memory "
2845 "to create object description");
2846 goto err;
2847 }
2848
2849 wpas_dbus_register(obj_desc, wpa_s, NULL, wpas_dbus_interface_methods,
2850 wpas_dbus_interface_properties,
2851 wpas_dbus_interface_signals);
2852
2853 wpa_printf(MSG_DEBUG, "dbus: Register interface object '%s'",
2854 wpa_s->dbus_new_path);
2855 if (wpa_dbus_register_object_per_iface(ctrl_iface,
2856 wpa_s->dbus_new_path,
2857 wpa_s->ifname, obj_desc))
2858 goto err;
2859
2860 wpas_dbus_signal_interface_added(wpa_s);
2861
2862 return 0;
2863
2864 err:
2865 os_free(wpa_s->dbus_new_path);
2866 wpa_s->dbus_new_path = NULL;
2867 free_dbus_object_desc(obj_desc);
2868 return -1;
2869 }
2870
2871
2872 int wpas_dbus_unregister_interface(struct wpa_supplicant *wpa_s)
2873 {
2874 struct wpas_dbus_priv *ctrl_iface;
2875
2876 /* Do nothing if the control interface is not turned on */
2877 if (wpa_s == NULL || wpa_s->global == NULL)
2878 return 0;
2879 ctrl_iface = wpa_s->global->dbus;
2880 if (ctrl_iface == NULL)
2881 return 0;
2882
2883 wpa_printf(MSG_DEBUG, "dbus: Unregister interface object '%s'",
2884 wpa_s->dbus_new_path);
2885 if (wpa_dbus_unregister_object_per_iface(ctrl_iface,
2886 wpa_s->dbus_new_path))
2887 return -1;
2888
2889 wpas_dbus_signal_interface_removed(wpa_s);
2890
2891 os_free(wpa_s->dbus_new_path);
2892 wpa_s->dbus_new_path = NULL;
2893
2894 return 0;
2895 }
2896
2897 #ifdef CONFIG_P2P
2898
2899 static const struct wpa_dbus_property_desc wpas_dbus_p2p_peer_properties[] = {
2900 { "DeviceName", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
2901 wpas_dbus_getter_p2p_peer_device_name,
2902 NULL
2903 },
2904 { "PrimaryDeviceType", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
2905 wpas_dbus_getter_p2p_peer_primary_device_type,
2906 NULL
2907 },
2908 { "config_method", WPAS_DBUS_NEW_IFACE_P2P_PEER, "q",
2909 wpas_dbus_getter_p2p_peer_config_method,
2910 NULL
2911 },
2912 { "level", WPAS_DBUS_NEW_IFACE_P2P_PEER, "i",
2913 wpas_dbus_getter_p2p_peer_level,
2914 NULL
2915 },
2916 { "devicecapability", WPAS_DBUS_NEW_IFACE_P2P_PEER, "y",
2917 wpas_dbus_getter_p2p_peer_device_capability,
2918 NULL
2919 },
2920 { "groupcapability", WPAS_DBUS_NEW_IFACE_P2P_PEER, "y",
2921 wpas_dbus_getter_p2p_peer_group_capability,
2922 NULL
2923 },
2924 { "SecondaryDeviceTypes", WPAS_DBUS_NEW_IFACE_P2P_PEER, "aay",
2925 wpas_dbus_getter_p2p_peer_secondary_device_types,
2926 NULL
2927 },
2928 { "VendorExtension", WPAS_DBUS_NEW_IFACE_P2P_PEER, "aay",
2929 wpas_dbus_getter_p2p_peer_vendor_extension,
2930 NULL
2931 },
2932 { "IEs", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
2933 wpas_dbus_getter_p2p_peer_ies,
2934 NULL
2935 },
2936 { NULL, NULL, NULL, NULL, NULL }
2937 };
2938
2939 static const struct wpa_dbus_signal_desc wpas_dbus_p2p_peer_signals[] = {
2940
2941 { NULL, NULL, { END_ARGS } }
2942 };
2943
2944 /**
2945 * wpas_dbus_signal_peer - Send a peer related event signal
2946 * @wpa_s: %wpa_supplicant network interface data
2947 * @dev: peer device object
2948 * @interface: name of the interface emitting this signal.
2949 * In case of peer objects, it would be emitted by either
2950 * the "interface object" or by "peer objects"
2951 * @sig_name: signal name - DeviceFound
2952 *
2953 * Notify listeners about event related with newly found p2p peer device
2954 */
2955 static void wpas_dbus_signal_peer(struct wpa_supplicant *wpa_s,
2956 const u8 *dev_addr, const char *interface,
2957 const char *sig_name)
2958 {
2959 struct wpas_dbus_priv *iface;
2960 DBusMessage *msg;
2961 DBusMessageIter iter;
2962 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
2963
2964 iface = wpa_s->global->dbus;
2965
2966 /* Do nothing if the control interface is not turned on */
2967 if (iface == NULL)
2968 return;
2969
2970 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2971 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
2972 wpa_s->dbus_new_path, MAC2STR(dev_addr));
2973
2974 msg = dbus_message_new_signal(wpa_s->dbus_new_path, interface,
2975 sig_name);
2976 if (msg == NULL)
2977 return;
2978
2979 dbus_message_iter_init_append(msg, &iter);
2980 path = peer_obj_path;
2981 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
2982 &path))
2983 goto err;
2984
2985 dbus_connection_send(iface->con, msg, NULL);
2986
2987 dbus_message_unref(msg);
2988 return;
2989
2990 err:
2991 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
2992 dbus_message_unref(msg);
2993 }
2994
2995
2996 /**
2997 * wpas_dbus_signal_peer_found - Send a peer found signal
2998 * @wpa_s: %wpa_supplicant network interface data
2999 * @dev: peer device object
3000 *
3001 * Notify listeners about find a p2p peer device found
3002 */
3003 void wpas_dbus_signal_peer_device_found(struct wpa_supplicant *wpa_s,
3004 const u8 *dev_addr)
3005 {
3006 wpas_dbus_signal_peer(wpa_s, dev_addr,
3007 WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3008 "DeviceFound");
3009 }
3010
3011 /**
3012 * wpas_dbus_signal_peer_lost - Send a peer lost signal
3013 * @wpa_s: %wpa_supplicant network interface data
3014 * @dev: peer device object
3015 *
3016 * Notify listeners about lost a p2p peer device
3017 */
3018 void wpas_dbus_signal_peer_device_lost(struct wpa_supplicant *wpa_s,
3019 const u8 *dev_addr)
3020 {
3021 wpas_dbus_signal_peer(wpa_s, dev_addr,
3022 WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3023 "DeviceLost");
3024 }
3025
3026 /**
3027 * wpas_dbus_register_peer - Register a discovered peer object with dbus
3028 * @wpa_s: wpa_supplicant interface structure
3029 * @ssid: network configuration data
3030 * Returns: 0 on success, -1 on failure
3031 *
3032 * Registers network representing object with dbus
3033 */
3034 int wpas_dbus_register_peer(struct wpa_supplicant *wpa_s, const u8 *dev_addr)
3035 {
3036 struct wpas_dbus_priv *ctrl_iface;
3037 struct wpa_dbus_object_desc *obj_desc;
3038 struct peer_handler_args *arg;
3039 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3040
3041 /* Do nothing if the control interface is not turned on */
3042 if (wpa_s == NULL || wpa_s->global == NULL)
3043 return 0;
3044
3045 ctrl_iface = wpa_s->global->dbus;
3046 if (ctrl_iface == NULL)
3047 return 0;
3048
3049 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3050 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
3051 wpa_s->dbus_new_path, MAC2STR(dev_addr));
3052
3053 wpa_printf(MSG_INFO, "dbus: Register peer object '%s'",
3054 peer_obj_path);
3055 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
3056 if (!obj_desc) {
3057 wpa_printf(MSG_ERROR, "Not enough memory "
3058 "to create object description");
3059 goto err;
3060 }
3061
3062 /* allocate memory for handlers arguments */
3063 arg = os_zalloc(sizeof(struct peer_handler_args));
3064 if (!arg) {
3065 wpa_printf(MSG_ERROR, "Not enough memory "
3066 "to create arguments for method");
3067 goto err;
3068 }
3069
3070 arg->wpa_s = wpa_s;
3071 os_memcpy(arg->p2p_device_addr, dev_addr, ETH_ALEN);
3072
3073 wpas_dbus_register(obj_desc, arg, wpa_dbus_free,
3074 NULL,
3075 wpas_dbus_p2p_peer_properties,
3076 wpas_dbus_p2p_peer_signals);
3077
3078 if (wpa_dbus_register_object_per_iface(ctrl_iface, peer_obj_path,
3079 wpa_s->ifname, obj_desc))
3080 goto err;
3081
3082 return 0;
3083
3084 err:
3085 free_dbus_object_desc(obj_desc);
3086 return -1;
3087 }
3088
3089 /**
3090 * wpas_dbus_unregister_peer - Unregister a peer object with dbus
3091 * @wpa_s: wpa_supplicant interface structure
3092 * @dev_addr: p2p device addr
3093 * Returns: 0 on success, -1 on failure
3094 *
3095 * Registers network representing object with dbus
3096 */
3097 int wpas_dbus_unregister_peer(struct wpa_supplicant *wpa_s,
3098 const u8 *dev_addr)
3099 {
3100 struct wpas_dbus_priv *ctrl_iface;
3101 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3102 int ret;
3103
3104 /* Do nothing if the control interface is not turned on */
3105 if (wpa_s == NULL || wpa_s->global == NULL ||
3106 wpa_s->dbus_new_path == NULL)
3107 return 0;
3108 ctrl_iface = wpa_s->global->dbus;
3109 if (ctrl_iface == NULL)
3110 return 0;
3111
3112 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3113 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
3114 wpa_s->dbus_new_path, MAC2STR(dev_addr));
3115
3116 wpa_printf(MSG_INFO, "dbus: Unregister peer object '%s'",
3117 peer_obj_path);
3118 ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, peer_obj_path);
3119
3120 return ret;
3121 }
3122
3123
3124 static const struct wpa_dbus_property_desc wpas_dbus_p2p_group_properties[] = {
3125 { "Members", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ao",
3126 wpas_dbus_getter_p2p_group_members,
3127 NULL
3128 },
3129 { "Group", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "o",
3130 wpas_dbus_getter_p2p_group,
3131 NULL
3132 },
3133 { "Role", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "s",
3134 wpas_dbus_getter_p2p_role,
3135 NULL
3136 },
3137 { "SSID", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay",
3138 wpas_dbus_getter_p2p_group_ssid,
3139 NULL
3140 },
3141 { "BSSID", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay",
3142 wpas_dbus_getter_p2p_group_bssid,
3143 NULL
3144 },
3145 { "Frequency", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "q",
3146 wpas_dbus_getter_p2p_group_frequency,
3147 NULL
3148 },
3149 { "Passphrase", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "s",
3150 wpas_dbus_getter_p2p_group_passphrase,
3151 NULL
3152 },
3153 { "PSK", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay",
3154 wpas_dbus_getter_p2p_group_psk,
3155 NULL
3156 },
3157 { "WPSVendorExtensions", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "aay",
3158 wpas_dbus_getter_p2p_group_vendor_ext,
3159 wpas_dbus_setter_p2p_group_vendor_ext
3160 },
3161 { NULL, NULL, NULL, NULL, NULL }
3162 };
3163
3164 static const struct wpa_dbus_signal_desc wpas_dbus_p2p_group_signals[] = {
3165 { "PeerJoined", WPAS_DBUS_NEW_IFACE_P2P_GROUP,
3166 {
3167 { "peer", "o", ARG_OUT },
3168 END_ARGS
3169 }
3170 },
3171 { "PeerDisconnected", WPAS_DBUS_NEW_IFACE_P2P_GROUP,
3172 {
3173 { "peer", "o", ARG_OUT },
3174 END_ARGS
3175 }
3176 },
3177 { NULL, NULL, { END_ARGS } }
3178 };
3179
3180 /**
3181 * wpas_dbus_register_p2p_group - Register a p2p group object with dbus
3182 * @wpa_s: wpa_supplicant interface structure
3183 * @ssid: SSID struct
3184 * Returns: 0 on success, -1 on failure
3185 *
3186 * Registers p2p group representing object with dbus
3187 */
3188 void wpas_dbus_register_p2p_group(struct wpa_supplicant *wpa_s,
3189 struct wpa_ssid *ssid)
3190 {
3191 struct wpas_dbus_priv *ctrl_iface;
3192 struct wpa_dbus_object_desc *obj_desc;
3193 char group_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3194
3195 /* Do nothing if the control interface is not turned on */
3196 if (wpa_s == NULL || wpa_s->global == NULL)
3197 return;
3198
3199 ctrl_iface = wpa_s->global->dbus;
3200 if (ctrl_iface == NULL)
3201 return;
3202
3203 if (wpa_s->dbus_groupobj_path) {
3204 wpa_printf(MSG_INFO, "%s: Group object '%s' already exists",
3205 __func__, wpa_s->dbus_groupobj_path);
3206 return;
3207 }
3208
3209 if (wpas_dbus_get_group_obj_path(wpa_s, ssid, group_obj_path) < 0)
3210 return;
3211
3212 wpa_s->dbus_groupobj_path = os_strdup(group_obj_path);
3213 if (wpa_s->dbus_groupobj_path == NULL)
3214 return;
3215
3216 wpa_printf(MSG_INFO, "dbus: Register group object '%s'",
3217 group_obj_path);
3218 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
3219 if (!obj_desc) {
3220 wpa_printf(MSG_ERROR, "Not enough memory "
3221 "to create object description");
3222 goto err;
3223 }
3224
3225 wpas_dbus_register(obj_desc, wpa_s, NULL, NULL,
3226 wpas_dbus_p2p_group_properties,
3227 wpas_dbus_p2p_group_signals);
3228
3229 if (wpa_dbus_register_object_per_iface(ctrl_iface, group_obj_path,
3230 wpa_s->ifname, obj_desc))
3231 goto err;
3232
3233 return;
3234
3235 err:
3236 if (wpa_s->dbus_groupobj_path) {
3237 os_free(wpa_s->dbus_groupobj_path);
3238 wpa_s->dbus_groupobj_path = NULL;
3239 }
3240
3241 free_dbus_object_desc(obj_desc);
3242 }
3243
3244 /**
3245 * wpas_dbus_unregister_p2p_group - Unregister a p2p group object from dbus
3246 * @wpa_s: wpa_supplicant interface structure
3247 * @ssid: network name of the p2p group started
3248 */
3249 void wpas_dbus_unregister_p2p_group(struct wpa_supplicant *wpa_s,
3250 const struct wpa_ssid *ssid)
3251 {
3252 struct wpas_dbus_priv *ctrl_iface;
3253
3254 /* Do nothing if the control interface is not turned on */
3255 if (wpa_s == NULL || wpa_s->global == NULL)
3256 return;
3257
3258 ctrl_iface = wpa_s->global->dbus;
3259 if (ctrl_iface == NULL)
3260 return;
3261
3262 if (!wpa_s->dbus_groupobj_path) {
3263 wpa_printf(MSG_DEBUG,
3264 "%s: Group object '%s' already unregistered",
3265 __func__, wpa_s->dbus_groupobj_path);
3266 return;
3267 }
3268
3269 wpa_printf(MSG_DEBUG, "dbus: Unregister group object '%s'",
3270 wpa_s->dbus_groupobj_path);
3271
3272 wpa_dbus_unregister_object_per_iface(ctrl_iface,
3273 wpa_s->dbus_groupobj_path);
3274
3275 os_free(wpa_s->dbus_groupobj_path);
3276 wpa_s->dbus_groupobj_path = NULL;
3277 }
3278
3279 static const struct wpa_dbus_property_desc
3280 wpas_dbus_p2p_groupmember_properties[] = {
3281 { NULL, NULL, NULL, NULL, NULL }
3282 };
3283
3284 /**
3285 * wpas_dbus_register_p2p_groupmember - Register a p2p groupmember
3286 * object with dbus
3287 * @wpa_s: wpa_supplicant interface structure
3288 * @p2p_if_addr: i/f addr of the device joining this group
3289 *
3290 * Registers p2p groupmember representing object with dbus
3291 */
3292 void wpas_dbus_register_p2p_groupmember(struct wpa_supplicant *wpa_s,
3293 const u8 *p2p_if_addr)
3294 {
3295 struct wpas_dbus_priv *ctrl_iface;
3296 struct wpa_dbus_object_desc *obj_desc = NULL;
3297 struct groupmember_handler_args *arg;
3298 char groupmember_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3299
3300 /* Do nothing if the control interface is not turned on */
3301 if (wpa_s == NULL || wpa_s->global == NULL)
3302 return;
3303
3304 ctrl_iface = wpa_s->global->dbus;
3305 if (ctrl_iface == NULL)
3306 return;
3307
3308 if (!wpa_s->dbus_groupobj_path)
3309 return;
3310
3311 os_snprintf(groupmember_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3312 "%s/" WPAS_DBUS_NEW_P2P_GROUPMEMBERS_PART "/" COMPACT_MACSTR,
3313 wpa_s->dbus_groupobj_path, MAC2STR(p2p_if_addr));
3314
3315 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
3316 if (!obj_desc) {
3317 wpa_printf(MSG_ERROR, "Not enough memory "
3318 "to create object description");
3319 goto err;
3320 }
3321
3322 /* allocate memory for handlers arguments */
3323 arg = os_zalloc(sizeof(struct groupmember_handler_args));
3324 if (!arg) {
3325 wpa_printf(MSG_ERROR, "Not enough memory "
3326 "to create arguments for method");
3327 goto err;
3328 }
3329
3330 arg->wpa_s = wpa_s;
3331 os_memcpy(arg->member_addr, p2p_if_addr, ETH_ALEN);
3332
3333 wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
3334 wpas_dbus_p2p_groupmember_properties, NULL);
3335
3336 if (wpa_dbus_register_object_per_iface(ctrl_iface, groupmember_obj_path,
3337 wpa_s->ifname, obj_desc))
3338 goto err;
3339
3340 wpa_printf(MSG_INFO,
3341 "dbus: Registered group member object '%s' successfully",
3342 groupmember_obj_path);
3343 return;
3344
3345 err:
3346 free_dbus_object_desc(obj_desc);
3347 }
3348
3349 /**
3350 * wpas_dbus_unregister_p2p_groupmember - Unregister a p2p groupmember
3351 * object with dbus
3352 * @wpa_s: wpa_supplicant interface structure
3353 * @p2p_if_addr: i/f addr of the device joining this group
3354 *
3355 * Unregisters p2p groupmember representing object with dbus
3356 */
3357 void wpas_dbus_unregister_p2p_groupmember(struct wpa_supplicant *wpa_s,
3358 const u8 *p2p_if_addr)
3359 {
3360 struct wpas_dbus_priv *ctrl_iface;
3361 char groupmember_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3362
3363 /* Do nothing if the control interface is not turned on */
3364 if (wpa_s == NULL || wpa_s->global == NULL)
3365 return;
3366
3367 ctrl_iface = wpa_s->global->dbus;
3368 if (ctrl_iface == NULL)
3369 return;
3370
3371 if (!wpa_s->dbus_groupobj_path)
3372 return;
3373
3374 os_snprintf(groupmember_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3375 "%s/" WPAS_DBUS_NEW_P2P_GROUPMEMBERS_PART "/" COMPACT_MACSTR,
3376 wpa_s->dbus_groupobj_path, MAC2STR(p2p_if_addr));
3377
3378 wpa_dbus_unregister_object_per_iface(ctrl_iface, groupmember_obj_path);
3379 }
3380
3381
3382 static const struct wpa_dbus_property_desc
3383 wpas_dbus_persistent_group_properties[] = {
3384 { "Properties", WPAS_DBUS_NEW_IFACE_PERSISTENT_GROUP, "a{sv}",
3385 wpas_dbus_getter_persistent_group_properties,
3386 wpas_dbus_setter_persistent_group_properties
3387 },
3388 { NULL, NULL, NULL, NULL, NULL }
3389 };
3390
3391 /* No signals intended for persistent group objects */
3392
3393 /**
3394 * wpas_dbus_register_persistent_group - Register a configured(saved)
3395 * persistent group with dbus
3396 * @wpa_s: wpa_supplicant interface structure
3397 * @ssid: persistent group (still represented as a network within wpa)
3398 * configuration data
3399 * Returns: 0 on success, -1 on failure
3400 *
3401 * Registers a persistent group representing object with dbus.
3402 */
3403 int wpas_dbus_register_persistent_group(struct wpa_supplicant *wpa_s,
3404 struct wpa_ssid *ssid)
3405 {
3406 struct wpas_dbus_priv *ctrl_iface;
3407 struct wpa_dbus_object_desc *obj_desc;
3408 struct network_handler_args *arg;
3409 char pgrp_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3410
3411 /* Do nothing if the control interface is not turned on */
3412 if (wpa_s == NULL || wpa_s->global == NULL)
3413 return 0;
3414
3415 /* Make sure ssid is a persistent group */
3416 if (ssid->disabled != 2 && !ssid->p2p_persistent_group)
3417 return -1; /* should we return w/o complaining? */
3418
3419 ctrl_iface = wpa_s->global->dbus;
3420 if (ctrl_iface == NULL)
3421 return 0;
3422
3423 /*
3424 * Intentionally not coming up with different numbering scheme
3425 * for persistent groups.
3426 */
3427 os_snprintf(pgrp_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3428 "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%u",
3429 wpa_s->dbus_new_path, ssid->id);
3430
3431 wpa_printf(MSG_DEBUG, "dbus: Register persistent group object '%s'",
3432 pgrp_obj_path);
3433 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
3434 if (!obj_desc) {
3435 wpa_printf(MSG_ERROR, "dbus: Not enough memory to create "
3436 "object description");
3437 goto err;
3438 }
3439
3440 /*
3441 * Reusing the same context structure as that for networks
3442 * since these are represented using same data structure.
3443 */
3444 /* allocate memory for handlers arguments */
3445 arg = os_zalloc(sizeof(struct network_handler_args));
3446 if (!arg) {
3447 wpa_printf(MSG_ERROR, "dbus: Not enough memory to create "
3448 "arguments for method");
3449 goto err;
3450 }
3451
3452 arg->wpa_s = wpa_s;
3453 arg->ssid = ssid;
3454
3455 wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
3456 wpas_dbus_persistent_group_properties,
3457 NULL);
3458
3459 if (wpa_dbus_register_object_per_iface(ctrl_iface, pgrp_obj_path,
3460 wpa_s->ifname, obj_desc))
3461 goto err;
3462
3463 wpas_dbus_signal_persistent_group_added(wpa_s, ssid->id);
3464
3465 return 0;
3466
3467 err:
3468 free_dbus_object_desc(obj_desc);
3469 return -1;
3470 }
3471
3472
3473 /**
3474 * wpas_dbus_unregister_persistent_group - Unregister a persistent_group
3475 * from dbus
3476 * @wpa_s: wpa_supplicant interface structure
3477 * @nid: network id
3478 * Returns: 0 on success, -1 on failure
3479 *
3480 * Unregisters persistent group representing object from dbus
3481 *
3482 * NOTE: There is a slight issue with the semantics here. While the
3483 * implementation simply means the persistent group is unloaded from memory,
3484 * it should not get interpreted as the group is actually being erased/removed
3485 * from persistent storage as well.
3486 */
3487 int wpas_dbus_unregister_persistent_group(struct wpa_supplicant *wpa_s,
3488 int nid)
3489 {
3490 struct wpas_dbus_priv *ctrl_iface;
3491 char pgrp_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3492 int ret;
3493
3494 /* Do nothing if the control interface is not turned on */
3495 if (wpa_s == NULL || wpa_s->global == NULL ||
3496 wpa_s->dbus_new_path == NULL)
3497 return 0;
3498 ctrl_iface = wpa_s->global->dbus;
3499 if (ctrl_iface == NULL)
3500 return 0;
3501
3502 os_snprintf(pgrp_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3503 "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%u",
3504 wpa_s->dbus_new_path, nid);
3505
3506 wpa_printf(MSG_DEBUG, "dbus: Unregister persistent group object '%s'",
3507 pgrp_obj_path);
3508 ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, pgrp_obj_path);
3509
3510 if (!ret)
3511 wpas_dbus_signal_persistent_group_removed(wpa_s, nid);
3512
3513 return ret;
3514 }
3515
3516 #endif /* CONFIG_P2P */