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