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