1 /*
2 * WPA Supplicant / dbus-based control interface
3 * Copyright (c) 2006, Dan Williams <[email protected]> and Red Hat, Inc.
4 * Copyright (c) 2009-2010, Witold Sowa <[email protected]>
5 * Copyright (c) 2009, Jouni Malinen <[email protected]>
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 "ap/sta_info.h"
17 #include "../config.h"
18 #include "../wpa_supplicant_i.h"
19 #include "../bss.h"
20 #include "../wpas_glue.h"
21 #include "dbus_new_helpers.h"
22 #include "dbus_dict_helpers.h"
23 #include "dbus_new.h"
24 #include "dbus_new_handlers.h"
25 #include "dbus_common_i.h"
26 #include "dbus_new_handlers_p2p.h"
27 #include "p2p/p2p.h"
28 #include "../p2p_supplicant.h"
29
30 #ifdef CONFIG_AP /* until needed by something else */
31
32 /*
33 * NameOwnerChanged handling
34 *
35 * Some services we provide allow an application to register for
36 * a signal that it needs. While it can also unregister, we must
37 * be prepared for the case where the application simply crashes
38 * and thus doesn't clean up properly. The way to handle this in
39 * DBus is to register for the NameOwnerChanged signal which will
40 * signal an owner change to NULL if the peer closes the socket
41 * for whatever reason.
42 *
43 * Handle this signal via a filter function whenever necessary.
44 * The code below also handles refcounting in case in the future
45 * there will be multiple instances of this subscription scheme.
46 */
47 static const char wpas_dbus_noc_filter_str[] =
48 "interface=org.freedesktop.DBus,member=NameOwnerChanged";
49
50
noc_filter(DBusConnection * conn,DBusMessage * message,void * data)51 static DBusHandlerResult noc_filter(DBusConnection *conn,
52 DBusMessage *message, void *data)
53 {
54 struct wpas_dbus_priv *priv = data;
55
56 if (dbus_message_get_type(message) != DBUS_MESSAGE_TYPE_SIGNAL)
57 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
58
59 if (dbus_message_is_signal(message, DBUS_INTERFACE_DBUS,
60 "NameOwnerChanged")) {
61 const char *name;
62 const char *prev_owner;
63 const char *new_owner;
64 DBusError derr;
65 struct wpa_supplicant *wpa_s;
66
67 dbus_error_init(&derr);
68
69 if (!dbus_message_get_args(message, &derr,
70 DBUS_TYPE_STRING, &name,
71 DBUS_TYPE_STRING, &prev_owner,
72 DBUS_TYPE_STRING, &new_owner,
73 DBUS_TYPE_INVALID)) {
74 /* Ignore this error */
75 dbus_error_free(&derr);
76 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
77 }
78
79 for (wpa_s = priv->global->ifaces; wpa_s; wpa_s = wpa_s->next) {
80 if (wpa_s->preq_notify_peer != NULL &&
81 os_strcmp(name, wpa_s->preq_notify_peer) == 0 &&
82 (new_owner == NULL || os_strlen(new_owner) == 0)) {
83 /* probe request owner disconnected */
84 os_free(wpa_s->preq_notify_peer);
85 wpa_s->preq_notify_peer = NULL;
86 wpas_dbus_unsubscribe_noc(priv);
87 }
88 }
89 }
90
91 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
92 }
93
94
wpas_dbus_subscribe_noc(struct wpas_dbus_priv * priv)95 void wpas_dbus_subscribe_noc(struct wpas_dbus_priv *priv)
96 {
97 priv->dbus_noc_refcnt++;
98 if (priv->dbus_noc_refcnt > 1)
99 return;
100
101 if (!dbus_connection_add_filter(priv->con, noc_filter, priv, NULL)) {
102 wpa_printf(MSG_ERROR, "dbus: failed to add filter");
103 return;
104 }
105
106 dbus_bus_add_match(priv->con, wpas_dbus_noc_filter_str, NULL);
107 }
108
109
wpas_dbus_unsubscribe_noc(struct wpas_dbus_priv * priv)110 void wpas_dbus_unsubscribe_noc(struct wpas_dbus_priv *priv)
111 {
112 priv->dbus_noc_refcnt--;
113 if (priv->dbus_noc_refcnt > 0)
114 return;
115
116 dbus_bus_remove_match(priv->con, wpas_dbus_noc_filter_str, NULL);
117 dbus_connection_remove_filter(priv->con, noc_filter, priv);
118 }
119
120 #endif /* CONFIG_AP */
121
122
123 /**
124 * wpas_dbus_signal_interface - Send a interface related event signal
125 * @wpa_s: %wpa_supplicant network interface data
126 * @sig_name: signal name - InterfaceAdded or InterfaceRemoved
127 * @properties: Whether to add second argument with object properties
128 *
129 * Notify listeners about event related with interface
130 */
wpas_dbus_signal_interface(struct wpa_supplicant * wpa_s,const char * sig_name,dbus_bool_t properties)131 static void wpas_dbus_signal_interface(struct wpa_supplicant *wpa_s,
132 const char *sig_name,
133 dbus_bool_t properties)
134 {
135 struct wpas_dbus_priv *iface;
136 DBusMessage *msg;
137 DBusMessageIter iter;
138
139 iface = wpa_s->global->dbus;
140
141 /* Do nothing if the control interface is not turned on */
142 if (iface == NULL || !wpa_s->dbus_new_path)
143 return;
144
145 msg = dbus_message_new_signal(WPAS_DBUS_NEW_PATH,
146 WPAS_DBUS_NEW_INTERFACE, sig_name);
147 if (msg == NULL)
148 return;
149
150 dbus_message_iter_init_append(msg, &iter);
151 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
152 &wpa_s->dbus_new_path) ||
153 (properties &&
154 !wpa_dbus_get_object_properties(
155 iface, wpa_s->dbus_new_path,
156 WPAS_DBUS_NEW_IFACE_INTERFACE, &iter)))
157 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
158 else
159 dbus_connection_send(iface->con, msg, NULL);
160 dbus_message_unref(msg);
161 }
162
163
164 /**
165 * wpas_dbus_signal_interface_added - Send a interface created signal
166 * @wpa_s: %wpa_supplicant network interface data
167 *
168 * Notify listeners about creating new interface
169 */
wpas_dbus_signal_interface_added(struct wpa_supplicant * wpa_s)170 static void wpas_dbus_signal_interface_added(struct wpa_supplicant *wpa_s)
171 {
172 wpas_dbus_signal_interface(wpa_s, "InterfaceAdded", TRUE);
173 }
174
175
176 /**
177 * wpas_dbus_signal_interface_removed - Send a interface removed signal
178 * @wpa_s: %wpa_supplicant network interface data
179 *
180 * Notify listeners about removing interface
181 */
wpas_dbus_signal_interface_removed(struct wpa_supplicant * wpa_s)182 static void wpas_dbus_signal_interface_removed(struct wpa_supplicant *wpa_s)
183 {
184 wpas_dbus_signal_interface(wpa_s, "InterfaceRemoved", FALSE);
185
186 }
187
188
189 /**
190 * wpas_dbus_signal_scan_done - send scan done signal
191 * @wpa_s: %wpa_supplicant network interface data
192 * @success: indicates if scanning succeed or failed
193 *
194 * Notify listeners about finishing a scan
195 */
wpas_dbus_signal_scan_done(struct wpa_supplicant * wpa_s,int success)196 void wpas_dbus_signal_scan_done(struct wpa_supplicant *wpa_s, int success)
197 {
198 struct wpas_dbus_priv *iface;
199 DBusMessage *msg;
200 dbus_bool_t succ;
201
202 iface = wpa_s->global->dbus;
203
204 /* Do nothing if the control interface is not turned on */
205 if (iface == NULL || !wpa_s->dbus_new_path)
206 return;
207
208 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
209 WPAS_DBUS_NEW_IFACE_INTERFACE,
210 "ScanDone");
211 if (msg == NULL)
212 return;
213
214 succ = success ? TRUE : FALSE;
215 if (dbus_message_append_args(msg, DBUS_TYPE_BOOLEAN, &succ,
216 DBUS_TYPE_INVALID))
217 dbus_connection_send(iface->con, msg, NULL);
218 else
219 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
220 dbus_message_unref(msg);
221 }
222
223
224 /**
225 * wpas_dbus_signal_bss - Send a BSS related event signal
226 * @wpa_s: %wpa_supplicant network interface data
227 * @bss_obj_path: BSS object path
228 * @sig_name: signal name - BSSAdded or BSSRemoved
229 * @properties: Whether to add second argument with object properties
230 *
231 * Notify listeners about event related with BSS
232 */
wpas_dbus_signal_bss(struct wpa_supplicant * wpa_s,const char * bss_obj_path,const char * sig_name,dbus_bool_t properties)233 static void wpas_dbus_signal_bss(struct wpa_supplicant *wpa_s,
234 const char *bss_obj_path,
235 const char *sig_name, dbus_bool_t properties)
236 {
237 struct wpas_dbus_priv *iface;
238 DBusMessage *msg;
239 DBusMessageIter iter;
240
241 iface = wpa_s->global->dbus;
242
243 /* Do nothing if the control interface is not turned on */
244 if (iface == NULL || !wpa_s->dbus_new_path)
245 return;
246
247 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
248 WPAS_DBUS_NEW_IFACE_INTERFACE,
249 sig_name);
250 if (msg == NULL)
251 return;
252
253 dbus_message_iter_init_append(msg, &iter);
254 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
255 &bss_obj_path) ||
256 (properties &&
257 !wpa_dbus_get_object_properties(iface, bss_obj_path,
258 WPAS_DBUS_NEW_IFACE_BSS,
259 &iter)))
260 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
261 else
262 dbus_connection_send(iface->con, msg, NULL);
263 dbus_message_unref(msg);
264 }
265
266
267 /**
268 * wpas_dbus_signal_bss_added - Send a BSS added signal
269 * @wpa_s: %wpa_supplicant network interface data
270 * @bss_obj_path: new BSS object path
271 *
272 * Notify listeners about adding new BSS
273 */
wpas_dbus_signal_bss_added(struct wpa_supplicant * wpa_s,const char * bss_obj_path)274 static void wpas_dbus_signal_bss_added(struct wpa_supplicant *wpa_s,
275 const char *bss_obj_path)
276 {
277 wpas_dbus_signal_bss(wpa_s, bss_obj_path, "BSSAdded", TRUE);
278 }
279
280
281 /**
282 * wpas_dbus_signal_bss_removed - Send a BSS removed signal
283 * @wpa_s: %wpa_supplicant network interface data
284 * @bss_obj_path: BSS object path
285 *
286 * Notify listeners about removing BSS
287 */
wpas_dbus_signal_bss_removed(struct wpa_supplicant * wpa_s,const char * bss_obj_path)288 static void wpas_dbus_signal_bss_removed(struct wpa_supplicant *wpa_s,
289 const char *bss_obj_path)
290 {
291 wpas_dbus_signal_bss(wpa_s, bss_obj_path, "BSSRemoved", FALSE);
292 }
293
294
295 /**
296 * wpas_dbus_signal_blob - Send a blob related event signal
297 * @wpa_s: %wpa_supplicant network interface data
298 * @name: blob name
299 * @sig_name: signal name - BlobAdded or BlobRemoved
300 *
301 * Notify listeners about event related with blob
302 */
wpas_dbus_signal_blob(struct wpa_supplicant * wpa_s,const char * name,const char * sig_name)303 static void wpas_dbus_signal_blob(struct wpa_supplicant *wpa_s,
304 const char *name, const char *sig_name)
305 {
306 struct wpas_dbus_priv *iface;
307 DBusMessage *msg;
308
309 iface = wpa_s->global->dbus;
310
311 /* Do nothing if the control interface is not turned on */
312 if (iface == NULL || !wpa_s->dbus_new_path)
313 return;
314
315 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
316 WPAS_DBUS_NEW_IFACE_INTERFACE,
317 sig_name);
318 if (msg == NULL)
319 return;
320
321 if (dbus_message_append_args(msg, DBUS_TYPE_STRING, &name,
322 DBUS_TYPE_INVALID))
323 dbus_connection_send(iface->con, msg, NULL);
324 else
325 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
326 dbus_message_unref(msg);
327 }
328
329
330 /**
331 * wpas_dbus_signal_blob_added - Send a blob added signal
332 * @wpa_s: %wpa_supplicant network interface data
333 * @name: blob name
334 *
335 * Notify listeners about adding a new blob
336 */
wpas_dbus_signal_blob_added(struct wpa_supplicant * wpa_s,const char * name)337 void wpas_dbus_signal_blob_added(struct wpa_supplicant *wpa_s,
338 const char *name)
339 {
340 wpas_dbus_signal_blob(wpa_s, name, "BlobAdded");
341 }
342
343
344 /**
345 * wpas_dbus_signal_blob_removed - Send a blob removed signal
346 * @wpa_s: %wpa_supplicant network interface data
347 * @name: blob name
348 *
349 * Notify listeners about removing blob
350 */
wpas_dbus_signal_blob_removed(struct wpa_supplicant * wpa_s,const char * name)351 void wpas_dbus_signal_blob_removed(struct wpa_supplicant *wpa_s,
352 const char *name)
353 {
354 wpas_dbus_signal_blob(wpa_s, name, "BlobRemoved");
355 }
356
357
358 /**
359 * wpas_dbus_signal_network - Send a network related event signal
360 * @wpa_s: %wpa_supplicant network interface data
361 * @id: new network id
362 * @sig_name: signal name - NetworkAdded, NetworkRemoved or NetworkSelected
363 * @properties: determines if add second argument with object properties
364 *
365 * Notify listeners about event related with configured network
366 */
wpas_dbus_signal_network(struct wpa_supplicant * wpa_s,int id,const char * sig_name,dbus_bool_t properties)367 static void wpas_dbus_signal_network(struct wpa_supplicant *wpa_s,
368 int id, const char *sig_name,
369 dbus_bool_t properties)
370 {
371 struct wpas_dbus_priv *iface;
372 DBusMessage *msg;
373 DBusMessageIter iter;
374 char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
375
376 iface = wpa_s->global->dbus;
377
378 /* Do nothing if the control interface is not turned on */
379 if (iface == NULL || !wpa_s->dbus_new_path)
380 return;
381
382 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
383 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
384 wpa_s->dbus_new_path, id);
385
386 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
387 WPAS_DBUS_NEW_IFACE_INTERFACE,
388 sig_name);
389 if (msg == NULL)
390 return;
391
392 dbus_message_iter_init_append(msg, &iter);
393 path = net_obj_path;
394 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
395 &path) ||
396 (properties &&
397 !wpa_dbus_get_object_properties(
398 iface, net_obj_path, WPAS_DBUS_NEW_IFACE_NETWORK,
399 &iter)))
400 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
401 else
402 dbus_connection_send(iface->con, msg, NULL);
403 dbus_message_unref(msg);
404 }
405
406
407 /**
408 * wpas_dbus_signal_network_added - Send a network added signal
409 * @wpa_s: %wpa_supplicant network interface data
410 * @id: new network id
411 *
412 * Notify listeners about adding new network
413 */
wpas_dbus_signal_network_added(struct wpa_supplicant * wpa_s,int id)414 static void wpas_dbus_signal_network_added(struct wpa_supplicant *wpa_s,
415 int id)
416 {
417 wpas_dbus_signal_network(wpa_s, id, "NetworkAdded", TRUE);
418 }
419
420
421 /**
422 * wpas_dbus_signal_network_removed - Send a network removed signal
423 * @wpa_s: %wpa_supplicant network interface data
424 * @id: network id
425 *
426 * Notify listeners about removing a network
427 */
wpas_dbus_signal_network_removed(struct wpa_supplicant * wpa_s,int id)428 static void wpas_dbus_signal_network_removed(struct wpa_supplicant *wpa_s,
429 int id)
430 {
431 wpas_dbus_signal_network(wpa_s, id, "NetworkRemoved", FALSE);
432 }
433
434
435 /**
436 * wpas_dbus_signal_network_selected - Send a network selected signal
437 * @wpa_s: %wpa_supplicant network interface data
438 * @id: network id
439 *
440 * Notify listeners about selecting a network
441 */
wpas_dbus_signal_network_selected(struct wpa_supplicant * wpa_s,int id)442 void wpas_dbus_signal_network_selected(struct wpa_supplicant *wpa_s, int id)
443 {
444 wpas_dbus_signal_network(wpa_s, id, "NetworkSelected", FALSE);
445 }
446
447
448 /**
449 * wpas_dbus_signal_network_request - Indicate that additional information
450 * (EAP password, etc.) is required to complete the association to this SSID
451 * @wpa_s: %wpa_supplicant network interface data
452 * @rtype: The specific additional information required
453 * @default_text: Optional description of required information
454 *
455 * Request additional information or passwords to complete an association
456 * request.
457 */
wpas_dbus_signal_network_request(struct wpa_supplicant * wpa_s,struct wpa_ssid * ssid,enum wpa_ctrl_req_type rtype,const char * default_txt)458 void wpas_dbus_signal_network_request(struct wpa_supplicant *wpa_s,
459 struct wpa_ssid *ssid,
460 enum wpa_ctrl_req_type rtype,
461 const char *default_txt)
462 {
463 struct wpas_dbus_priv *iface;
464 DBusMessage *msg;
465 DBusMessageIter iter;
466 char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
467 const char *field, *txt = NULL, *net_ptr;
468
469 iface = wpa_s->global->dbus;
470
471 /* Do nothing if the control interface is not turned on */
472 if (iface == NULL || !wpa_s->dbus_new_path)
473 return;
474
475 field = wpa_supplicant_ctrl_req_to_string(rtype, default_txt, &txt);
476 if (field == NULL)
477 return;
478
479 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
480 WPAS_DBUS_NEW_IFACE_INTERFACE,
481 "NetworkRequest");
482 if (msg == NULL)
483 return;
484
485 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
486 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
487 wpa_s->dbus_new_path, ssid->id);
488 net_ptr = &net_obj_path[0];
489
490 dbus_message_iter_init_append(msg, &iter);
491 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
492 &net_ptr) ||
493 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &field) ||
494 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &txt))
495 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
496 else
497 dbus_connection_send(iface->con, msg, NULL);
498 dbus_message_unref(msg);
499 }
500
501
502 /**
503 * wpas_dbus_signal_network_enabled_changed - Signals Enabled property changes
504 * @wpa_s: %wpa_supplicant network interface data
505 * @ssid: configured network which Enabled property has changed
506 *
507 * Sends PropertyChanged signals containing new value of Enabled property
508 * for specified network
509 */
wpas_dbus_signal_network_enabled_changed(struct wpa_supplicant * wpa_s,struct wpa_ssid * ssid)510 void wpas_dbus_signal_network_enabled_changed(struct wpa_supplicant *wpa_s,
511 struct wpa_ssid *ssid)
512 {
513
514 char path[WPAS_DBUS_OBJECT_PATH_MAX];
515
516 if (!wpa_s->dbus_new_path)
517 return;
518 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
519 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
520 wpa_s->dbus_new_path, ssid->id);
521
522 wpa_dbus_mark_property_changed(wpa_s->global->dbus, path,
523 WPAS_DBUS_NEW_IFACE_NETWORK, "Enabled");
524 }
525
526
527 #ifdef CONFIG_WPS
528
529 /**
530 * wpas_dbus_signal_wps_event_pbc_overlap - Signals PBC overlap WPS event
531 * @wpa_s: %wpa_supplicant network interface data
532 *
533 * Sends Event dbus signal with name "pbc-overlap" and empty dict as arguments
534 */
wpas_dbus_signal_wps_event_pbc_overlap(struct wpa_supplicant * wpa_s)535 void wpas_dbus_signal_wps_event_pbc_overlap(struct wpa_supplicant *wpa_s)
536 {
537
538 DBusMessage *msg;
539 DBusMessageIter iter, dict_iter;
540 struct wpas_dbus_priv *iface;
541 char *key = "pbc-overlap";
542
543 iface = wpa_s->global->dbus;
544
545 /* Do nothing if the control interface is not turned on */
546 if (iface == NULL || !wpa_s->dbus_new_path)
547 return;
548
549 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
550 WPAS_DBUS_NEW_IFACE_WPS, "Event");
551 if (msg == NULL)
552 return;
553
554 dbus_message_iter_init_append(msg, &iter);
555
556 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
557 !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
558 !wpa_dbus_dict_close_write(&iter, &dict_iter))
559 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
560 else
561 dbus_connection_send(iface->con, msg, NULL);
562
563 dbus_message_unref(msg);
564 }
565
566
567 /**
568 * wpas_dbus_signal_wps_event_success - Signals Success WPS event
569 * @wpa_s: %wpa_supplicant network interface data
570 *
571 * Sends Event dbus signal with name "success" and empty dict as arguments
572 */
wpas_dbus_signal_wps_event_success(struct wpa_supplicant * wpa_s)573 void wpas_dbus_signal_wps_event_success(struct wpa_supplicant *wpa_s)
574 {
575
576 DBusMessage *msg;
577 DBusMessageIter iter, dict_iter;
578 struct wpas_dbus_priv *iface;
579 char *key = "success";
580
581 iface = wpa_s->global->dbus;
582
583 /* Do nothing if the control interface is not turned on */
584 if (iface == NULL || !wpa_s->dbus_new_path)
585 return;
586
587 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
588 WPAS_DBUS_NEW_IFACE_WPS, "Event");
589 if (msg == NULL)
590 return;
591
592 dbus_message_iter_init_append(msg, &iter);
593
594 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
595 !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
596 !wpa_dbus_dict_close_write(&iter, &dict_iter))
597 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
598 else
599 dbus_connection_send(iface->con, msg, NULL);
600
601 dbus_message_unref(msg);
602 }
603
604
605 /**
606 * wpas_dbus_signal_wps_event_fail - Signals Fail WPS event
607 * @wpa_s: %wpa_supplicant network interface data
608 * @fail: WPS failure information
609 *
610 * Sends Event dbus signal with name "fail" and dictionary containing
611 * "msg field with fail message number (int32) as arguments
612 */
wpas_dbus_signal_wps_event_fail(struct wpa_supplicant * wpa_s,struct wps_event_fail * fail)613 void wpas_dbus_signal_wps_event_fail(struct wpa_supplicant *wpa_s,
614 struct wps_event_fail *fail)
615 {
616
617 DBusMessage *msg;
618 DBusMessageIter iter, dict_iter;
619 struct wpas_dbus_priv *iface;
620 char *key = "fail";
621
622 iface = wpa_s->global->dbus;
623
624 /* Do nothing if the control interface is not turned on */
625 if (iface == NULL || !wpa_s->dbus_new_path)
626 return;
627
628 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
629 WPAS_DBUS_NEW_IFACE_WPS, "Event");
630 if (msg == NULL)
631 return;
632
633 dbus_message_iter_init_append(msg, &iter);
634
635 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
636 !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
637 !wpa_dbus_dict_append_int32(&dict_iter, "msg", fail->msg) ||
638 !wpa_dbus_dict_append_int32(&dict_iter, "config_error",
639 fail->config_error) ||
640 !wpa_dbus_dict_append_int32(&dict_iter, "error_indication",
641 fail->error_indication) ||
642 !wpa_dbus_dict_close_write(&iter, &dict_iter))
643 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
644 else
645 dbus_connection_send(iface->con, msg, NULL);
646
647 dbus_message_unref(msg);
648 }
649
650
651 /**
652 * wpas_dbus_signal_wps_event_m2d - Signals M2D WPS event
653 * @wpa_s: %wpa_supplicant network interface data
654 * @m2d: M2D event data information
655 *
656 * Sends Event dbus signal with name "m2d" and dictionary containing
657 * fields of wps_event_m2d structure.
658 */
wpas_dbus_signal_wps_event_m2d(struct wpa_supplicant * wpa_s,struct wps_event_m2d * m2d)659 void wpas_dbus_signal_wps_event_m2d(struct wpa_supplicant *wpa_s,
660 struct wps_event_m2d *m2d)
661 {
662
663 DBusMessage *msg;
664 DBusMessageIter iter, dict_iter;
665 struct wpas_dbus_priv *iface;
666 char *key = "m2d";
667
668 iface = wpa_s->global->dbus;
669
670 /* Do nothing if the control interface is not turned on */
671 if (iface == NULL || !wpa_s->dbus_new_path)
672 return;
673
674 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
675 WPAS_DBUS_NEW_IFACE_WPS, "Event");
676 if (msg == NULL)
677 return;
678
679 dbus_message_iter_init_append(msg, &iter);
680
681 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
682 !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
683 !wpa_dbus_dict_append_uint16(&dict_iter, "config_methods",
684 m2d->config_methods) ||
685 !wpa_dbus_dict_append_byte_array(&dict_iter, "manufacturer",
686 (const char *) m2d->manufacturer,
687 m2d->manufacturer_len) ||
688 !wpa_dbus_dict_append_byte_array(&dict_iter, "model_name",
689 (const char *) m2d->model_name,
690 m2d->model_name_len) ||
691 !wpa_dbus_dict_append_byte_array(&dict_iter, "model_number",
692 (const char *) m2d->model_number,
693 m2d->model_number_len) ||
694 !wpa_dbus_dict_append_byte_array(&dict_iter, "serial_number",
695 (const char *)
696 m2d->serial_number,
697 m2d->serial_number_len) ||
698 !wpa_dbus_dict_append_byte_array(&dict_iter, "dev_name",
699 (const char *) m2d->dev_name,
700 m2d->dev_name_len) ||
701 !wpa_dbus_dict_append_byte_array(&dict_iter, "primary_dev_type",
702 (const char *)
703 m2d->primary_dev_type, 8) ||
704 !wpa_dbus_dict_append_uint16(&dict_iter, "config_error",
705 m2d->config_error) ||
706 !wpa_dbus_dict_append_uint16(&dict_iter, "dev_password_id",
707 m2d->dev_password_id) ||
708 !wpa_dbus_dict_close_write(&iter, &dict_iter))
709 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
710 else
711 dbus_connection_send(iface->con, msg, NULL);
712
713 dbus_message_unref(msg);
714 }
715
716
717 /**
718 * wpas_dbus_signal_wps_cred - Signals new credentials
719 * @wpa_s: %wpa_supplicant network interface data
720 * @cred: WPS Credential information
721 *
722 * Sends signal with credentials in directory argument
723 */
wpas_dbus_signal_wps_cred(struct wpa_supplicant * wpa_s,const struct wps_credential * cred)724 void wpas_dbus_signal_wps_cred(struct wpa_supplicant *wpa_s,
725 const struct wps_credential *cred)
726 {
727 DBusMessage *msg;
728 DBusMessageIter iter, dict_iter;
729 struct wpas_dbus_priv *iface;
730 char *auth_type[5]; /* we have five possible authentication types */
731 int at_num = 0;
732 char *encr_type[3]; /* we have three possible encryption types */
733 int et_num = 0;
734
735 iface = wpa_s->global->dbus;
736
737 /* Do nothing if the control interface is not turned on */
738 if (iface == NULL || !wpa_s->dbus_new_path)
739 return;
740
741 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
742 WPAS_DBUS_NEW_IFACE_WPS,
743 "Credentials");
744 if (msg == NULL)
745 return;
746
747 dbus_message_iter_init_append(msg, &iter);
748 if (!wpa_dbus_dict_open_write(&iter, &dict_iter))
749 goto nomem;
750
751 if (cred->auth_type & WPS_AUTH_OPEN)
752 auth_type[at_num++] = "open";
753 #ifndef CONFIG_NO_TKIP
754 if (cred->auth_type & WPS_AUTH_WPAPSK)
755 auth_type[at_num++] = "wpa-psk";
756 if (cred->auth_type & WPS_AUTH_WPA)
757 auth_type[at_num++] = "wpa-eap";
758 #endif /* CONFIG_NO_TKIP */
759 if (cred->auth_type & WPS_AUTH_WPA2)
760 auth_type[at_num++] = "wpa2-eap";
761 if (cred->auth_type & WPS_AUTH_WPA2PSK)
762 auth_type[at_num++] = "wpa2-psk";
763
764 if (cred->encr_type & WPS_ENCR_NONE)
765 encr_type[et_num++] = "none";
766 #ifndef CONFIG_NO_TKIP
767 if (cred->encr_type & WPS_ENCR_TKIP)
768 encr_type[et_num++] = "tkip";
769 #endif /* CONFIG_NO_TKIP */
770 if (cred->encr_type & WPS_ENCR_AES)
771 encr_type[et_num++] = "aes";
772
773 if ((wpa_s->current_ssid &&
774 !wpa_dbus_dict_append_byte_array(
775 &dict_iter, "BSSID",
776 (const char *) wpa_s->current_ssid->bssid, ETH_ALEN)) ||
777 !wpa_dbus_dict_append_byte_array(&dict_iter, "SSID",
778 (const char *) cred->ssid,
779 cred->ssid_len) ||
780 !wpa_dbus_dict_append_string_array(&dict_iter, "AuthType",
781 (const char **) auth_type,
782 at_num) ||
783 !wpa_dbus_dict_append_string_array(&dict_iter, "EncrType",
784 (const char **) encr_type,
785 et_num) ||
786 !wpa_dbus_dict_append_byte_array(&dict_iter, "Key",
787 (const char *) cred->key,
788 cred->key_len) ||
789 !wpa_dbus_dict_append_uint32(&dict_iter, "KeyIndex",
790 cred->key_idx) ||
791 !wpa_dbus_dict_close_write(&iter, &dict_iter))
792 goto nomem;
793
794 dbus_connection_send(iface->con, msg, NULL);
795
796 nomem:
797 dbus_message_unref(msg);
798 }
799
800 #endif /* CONFIG_WPS */
801
802
803 #ifdef CONFIG_MESH
804
wpas_dbus_signal_mesh_group_started(struct wpa_supplicant * wpa_s,struct wpa_ssid * ssid)805 void wpas_dbus_signal_mesh_group_started(struct wpa_supplicant *wpa_s,
806 struct wpa_ssid *ssid)
807 {
808 struct wpas_dbus_priv *iface;
809 DBusMessage *msg;
810 DBusMessageIter iter, dict_iter;
811
812 iface = wpa_s->global->dbus;
813
814 /* Do nothing if the control interface is not turned on */
815 if (!iface || !wpa_s->dbus_new_path)
816 return;
817
818 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
819 WPAS_DBUS_NEW_IFACE_MESH,
820 "MeshGroupStarted");
821 if (!msg)
822 return;
823
824 dbus_message_iter_init_append(msg, &iter);
825 if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
826 !wpa_dbus_dict_append_byte_array(&dict_iter, "SSID",
827 (const char *) ssid->ssid,
828 ssid->ssid_len) ||
829 !wpa_dbus_dict_close_write(&iter, &dict_iter))
830 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
831 else
832 dbus_connection_send(iface->con, msg, NULL);
833 dbus_message_unref(msg);
834 }
835
836
wpas_dbus_signal_mesh_group_removed(struct wpa_supplicant * wpa_s,const u8 * meshid,u8 meshid_len,int reason)837 void wpas_dbus_signal_mesh_group_removed(struct wpa_supplicant *wpa_s,
838 const u8 *meshid, u8 meshid_len,
839 int reason)
840 {
841 struct wpas_dbus_priv *iface;
842 DBusMessage *msg;
843 DBusMessageIter iter, dict_iter;
844
845 iface = wpa_s->global->dbus;
846
847 /* Do nothing if the control interface is not turned on */
848 if (!iface || !wpa_s->dbus_new_path)
849 return;
850
851 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
852 WPAS_DBUS_NEW_IFACE_MESH,
853 "MeshGroupRemoved");
854 if (!msg)
855 return;
856
857 dbus_message_iter_init_append(msg, &iter);
858 if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
859 !wpa_dbus_dict_append_byte_array(&dict_iter, "SSID",
860 (const char *) meshid,
861 meshid_len) ||
862 !wpa_dbus_dict_append_int32(&dict_iter, "DisconnectReason",
863 reason) ||
864 !wpa_dbus_dict_close_write(&iter, &dict_iter))
865 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
866 else
867 dbus_connection_send(iface->con, msg, NULL);
868 dbus_message_unref(msg);
869 }
870
871
wpas_dbus_signal_mesh_peer_connected(struct wpa_supplicant * wpa_s,const u8 * peer_addr)872 void wpas_dbus_signal_mesh_peer_connected(struct wpa_supplicant *wpa_s,
873 const u8 *peer_addr)
874 {
875 struct wpas_dbus_priv *iface;
876 DBusMessage *msg;
877 DBusMessageIter iter, dict_iter;
878
879 iface = wpa_s->global->dbus;
880
881 /* Do nothing if the control interface is not turned on */
882 if (!iface || !wpa_s->dbus_new_path)
883 return;
884
885 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
886 WPAS_DBUS_NEW_IFACE_MESH,
887 "MeshPeerConnected");
888 if (!msg)
889 return;
890
891 dbus_message_iter_init_append(msg, &iter);
892 if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
893 !wpa_dbus_dict_append_byte_array(&dict_iter, "PeerAddress",
894 (const char *) peer_addr,
895 ETH_ALEN) ||
896 !wpa_dbus_dict_close_write(&iter, &dict_iter))
897 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
898 else
899 dbus_connection_send(iface->con, msg, NULL);
900 dbus_message_unref(msg);
901 }
902
903
wpas_dbus_signal_mesh_peer_disconnected(struct wpa_supplicant * wpa_s,const u8 * peer_addr,int reason)904 void wpas_dbus_signal_mesh_peer_disconnected(struct wpa_supplicant *wpa_s,
905 const u8 *peer_addr, int reason)
906 {
907 struct wpas_dbus_priv *iface;
908 DBusMessage *msg;
909 DBusMessageIter iter, dict_iter;
910
911 iface = wpa_s->global->dbus;
912
913 /* Do nothing if the control interface is not turned on */
914 if (!iface || !wpa_s->dbus_new_path)
915 return;
916
917 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
918 WPAS_DBUS_NEW_IFACE_MESH,
919 "MeshPeerDisconnected");
920 if (!msg)
921 return;
922
923 dbus_message_iter_init_append(msg, &iter);
924 if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
925 !wpa_dbus_dict_append_byte_array(&dict_iter, "PeerAddress",
926 (const char *) peer_addr,
927 ETH_ALEN) ||
928 !wpa_dbus_dict_append_int32(&dict_iter, "DisconnectReason",
929 reason) ||
930 !wpa_dbus_dict_close_write(&iter, &dict_iter))
931 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
932 else
933 dbus_connection_send(iface->con, msg, NULL);
934 dbus_message_unref(msg);
935 }
936
937 #endif /* CONFIG_MESH */
938
939
940 #ifdef CONFIG_INTERWORKING
941
wpas_dbus_signal_interworking_ap_added(struct wpa_supplicant * wpa_s,struct wpa_bss * bss,struct wpa_cred * cred,const char * type,int excluded,int bh,int bss_load,int conn_capab)942 void wpas_dbus_signal_interworking_ap_added(struct wpa_supplicant *wpa_s,
943 struct wpa_bss *bss,
944 struct wpa_cred *cred,
945 const char *type,
946 int excluded,
947 int bh,
948 int bss_load,
949 int conn_capab)
950 {
951 struct wpas_dbus_priv *iface;
952 DBusMessage *msg;
953 DBusMessageIter iter, dict_iter;
954 char bss_path[WPAS_DBUS_OBJECT_PATH_MAX], *bss_obj_path;
955 char cred_path[WPAS_DBUS_OBJECT_PATH_MAX], *cred_obj_path;
956
957 iface = wpa_s->global->dbus;
958
959 /* Do nothing if the control interface is not turned on */
960 if (!iface || !wpa_s->dbus_new_path)
961 return;
962
963 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
964 WPAS_DBUS_NEW_IFACE_INTERFACE,
965 "InterworkingAPAdded");
966 if (!msg)
967 return;
968
969 os_snprintf(bss_path, WPAS_DBUS_OBJECT_PATH_MAX,
970 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
971 wpa_s->dbus_new_path, bss->id);
972 bss_obj_path = bss_path;
973
974 os_snprintf(cred_path, WPAS_DBUS_OBJECT_PATH_MAX,
975 "%s/" WPAS_DBUS_NEW_CREDENTIALS_PART "/%u",
976 wpa_s->dbus_new_path, cred->id);
977 cred_obj_path = cred_path;
978
979 dbus_message_iter_init_append(msg, &iter);
980 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
981 &bss_obj_path) ||
982 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
983 &cred_obj_path) ||
984 !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
985 !wpa_dbus_dict_append_string(&dict_iter, "type", type) ||
986 !wpa_dbus_dict_append_int32(&dict_iter, "excluded", excluded) ||
987 !wpa_dbus_dict_append_int32(&dict_iter, "priority",
988 cred->priority) ||
989 !wpa_dbus_dict_append_int32(&dict_iter, "sp_priority",
990 cred->sp_priority) ||
991 !wpa_dbus_dict_append_int32(&dict_iter, "below_min_backhaul", bh) ||
992 !wpa_dbus_dict_append_int32(&dict_iter, "over_max_bss_load",
993 bss_load) ||
994 !wpa_dbus_dict_append_int32(&dict_iter, "conn_capab_missing",
995 conn_capab) ||
996 !wpa_dbus_dict_close_write(&iter, &dict_iter))
997 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
998 else
999 dbus_connection_send(iface->con, msg, NULL);
1000 dbus_message_unref(msg);
1001 }
1002
1003
wpas_dbus_signal_interworking_select_done(struct wpa_supplicant * wpa_s)1004 void wpas_dbus_signal_interworking_select_done(struct wpa_supplicant *wpa_s)
1005 {
1006 struct wpas_dbus_priv *iface;
1007 DBusMessage *msg;
1008
1009 iface = wpa_s->global->dbus;
1010
1011 /* Do nothing if the control interface is not turned on */
1012 if (!iface || !wpa_s->dbus_new_path)
1013 return;
1014
1015 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1016 WPAS_DBUS_NEW_IFACE_INTERFACE,
1017 "InterworkingSelectDone");
1018 if (!msg)
1019 return;
1020
1021 dbus_connection_send(iface->con, msg, NULL);
1022
1023 dbus_message_unref(msg);
1024 }
1025
1026
wpas_dbus_signal_anqp_query_done(struct wpa_supplicant * wpa_s,const u8 * dst,const char * result)1027 void wpas_dbus_signal_anqp_query_done(struct wpa_supplicant *wpa_s,
1028 const u8 *dst, const char *result)
1029 {
1030 struct wpas_dbus_priv *iface;
1031 DBusMessage *msg;
1032 DBusMessageIter iter;
1033 char addr[WPAS_DBUS_OBJECT_PATH_MAX], *bssid;
1034
1035 os_snprintf(addr, WPAS_DBUS_OBJECT_PATH_MAX, MACSTR, MAC2STR(dst));
1036 bssid = addr;
1037
1038 iface = wpa_s->global->dbus;
1039
1040 /* Do nothing if the control interface is not turned on */
1041 if (!iface || !wpa_s->dbus_new_path)
1042 return;
1043
1044 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1045 WPAS_DBUS_NEW_IFACE_INTERFACE,
1046 "ANQPQueryDone");
1047 if (!msg)
1048 return;
1049
1050 dbus_message_iter_init_append(msg, &iter);
1051
1052 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &bssid) ||
1053 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &result))
1054 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1055 else
1056 dbus_connection_send(iface->con, msg, NULL);
1057 dbus_message_unref(msg);
1058 }
1059
1060 #endif /* CONFIG_INTERWORKING */
1061
1062
wpas_dbus_signal_certification(struct wpa_supplicant * wpa_s,int depth,const char * subject,const char * altsubject[],int num_altsubject,const char * cert_hash,const struct wpabuf * cert)1063 void wpas_dbus_signal_certification(struct wpa_supplicant *wpa_s,
1064 int depth, const char *subject,
1065 const char *altsubject[],
1066 int num_altsubject,
1067 const char *cert_hash,
1068 const struct wpabuf *cert)
1069 {
1070 struct wpas_dbus_priv *iface;
1071 DBusMessage *msg;
1072 DBusMessageIter iter, dict_iter;
1073
1074 iface = wpa_s->global->dbus;
1075
1076 /* Do nothing if the control interface is not turned on */
1077 if (iface == NULL || !wpa_s->dbus_new_path)
1078 return;
1079
1080 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1081 WPAS_DBUS_NEW_IFACE_INTERFACE,
1082 "Certification");
1083 if (msg == NULL)
1084 return;
1085
1086 dbus_message_iter_init_append(msg, &iter);
1087 if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
1088 !wpa_dbus_dict_append_uint32(&dict_iter, "depth", depth) ||
1089 !wpa_dbus_dict_append_string(&dict_iter, "subject", subject) ||
1090 (altsubject && num_altsubject &&
1091 !wpa_dbus_dict_append_string_array(&dict_iter, "altsubject",
1092 altsubject, num_altsubject)) ||
1093 (cert_hash &&
1094 !wpa_dbus_dict_append_string(&dict_iter, "cert_hash",
1095 cert_hash)) ||
1096 (cert &&
1097 !wpa_dbus_dict_append_byte_array(&dict_iter, "cert",
1098 wpabuf_head(cert),
1099 wpabuf_len(cert))) ||
1100 !wpa_dbus_dict_close_write(&iter, &dict_iter))
1101 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1102 else
1103 dbus_connection_send(iface->con, msg, NULL);
1104 dbus_message_unref(msg);
1105 }
1106
1107
wpas_dbus_signal_eap_status(struct wpa_supplicant * wpa_s,const char * status,const char * parameter)1108 void wpas_dbus_signal_eap_status(struct wpa_supplicant *wpa_s,
1109 const char *status, const char *parameter)
1110 {
1111 struct wpas_dbus_priv *iface;
1112 DBusMessage *msg;
1113 DBusMessageIter iter;
1114
1115 iface = wpa_s->global->dbus;
1116
1117 /* Do nothing if the control interface is not turned on */
1118 if (iface == NULL || !wpa_s->dbus_new_path)
1119 return;
1120
1121 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1122 WPAS_DBUS_NEW_IFACE_INTERFACE,
1123 "EAP");
1124 if (msg == NULL)
1125 return;
1126
1127 dbus_message_iter_init_append(msg, &iter);
1128
1129 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &status) ||
1130 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING,
1131 ¶meter))
1132 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1133 else
1134 dbus_connection_send(iface->con, msg, NULL);
1135 dbus_message_unref(msg);
1136 }
1137
1138
wpas_dbus_signal_psk_mismatch(struct wpa_supplicant * wpa_s)1139 void wpas_dbus_signal_psk_mismatch(struct wpa_supplicant *wpa_s)
1140 {
1141 struct wpas_dbus_priv *iface;
1142 DBusMessage *msg;
1143
1144 iface = wpa_s->global->dbus;
1145
1146 /* Do nothing if the control interface is not turned on */
1147 if (!iface || !wpa_s->dbus_new_path)
1148 return;
1149
1150 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1151 WPAS_DBUS_NEW_IFACE_INTERFACE,
1152 "PskMismatch");
1153 if (!msg)
1154 return;
1155
1156 dbus_connection_send(iface->con, msg, NULL);
1157
1158 dbus_message_unref(msg);
1159 }
1160
1161
1162 /**
1163 * wpas_dbus_signal_sta - Send a station related event signal
1164 * @wpa_s: %wpa_supplicant network interface data
1165 * @sta: station mac address
1166 * @sig_name: signal name - StaAuthorized or StaDeauthorized
1167 *
1168 * Notify listeners about event related with station
1169 */
wpas_dbus_signal_sta(struct wpa_supplicant * wpa_s,const u8 * sta,const char * sig_name)1170 static void wpas_dbus_signal_sta(struct wpa_supplicant *wpa_s,
1171 const u8 *sta, const char *sig_name)
1172 {
1173 struct wpas_dbus_priv *iface;
1174 DBusMessage *msg;
1175 char sta_mac[WPAS_DBUS_OBJECT_PATH_MAX];
1176 char *dev_mac;
1177
1178 os_snprintf(sta_mac, WPAS_DBUS_OBJECT_PATH_MAX, MACSTR, MAC2STR(sta));
1179 dev_mac = sta_mac;
1180
1181 iface = wpa_s->global->dbus;
1182
1183 /* Do nothing if the control interface is not turned on */
1184 if (iface == NULL || !wpa_s->dbus_new_path)
1185 return;
1186
1187 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1188 WPAS_DBUS_NEW_IFACE_INTERFACE, sig_name);
1189 if (msg == NULL)
1190 return;
1191
1192 if (dbus_message_append_args(msg, DBUS_TYPE_STRING, &dev_mac,
1193 DBUS_TYPE_INVALID))
1194 dbus_connection_send(iface->con, msg, NULL);
1195 else
1196 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1197 dbus_message_unref(msg);
1198
1199 wpa_printf(MSG_DEBUG, "dbus: Station MAC address '%s' '%s'",
1200 sta_mac, sig_name);
1201 }
1202
1203
1204 /**
1205 * wpas_dbus_signal_sta_authorized - Send a STA authorized signal
1206 * @wpa_s: %wpa_supplicant network interface data
1207 * @sta: station mac address
1208 *
1209 * Notify listeners a new station has been authorized
1210 */
wpas_dbus_signal_sta_authorized(struct wpa_supplicant * wpa_s,const u8 * sta)1211 void wpas_dbus_signal_sta_authorized(struct wpa_supplicant *wpa_s,
1212 const u8 *sta)
1213 {
1214 wpas_dbus_signal_sta(wpa_s, sta, "StaAuthorized");
1215 }
1216
1217
1218 /**
1219 * wpas_dbus_signal_sta_deauthorized - Send a STA deauthorized signal
1220 * @wpa_s: %wpa_supplicant network interface data
1221 * @sta: station mac address
1222 *
1223 * Notify listeners a station has been deauthorized
1224 */
wpas_dbus_signal_sta_deauthorized(struct wpa_supplicant * wpa_s,const u8 * sta)1225 void wpas_dbus_signal_sta_deauthorized(struct wpa_supplicant *wpa_s,
1226 const u8 *sta)
1227 {
1228 wpas_dbus_signal_sta(wpa_s, sta, "StaDeauthorized");
1229 }
1230
1231
1232 /**
1233 * wpas_dbus_signal_station - Send an event signal related to a station object
1234 * @wpa_s: %wpa_supplicant network interface data
1235 * @station_obj_path: Station object path
1236 * @sig_name: signal name - StationAdded or StationRemoved
1237 * @properties: Whether to add second argument with object properties
1238 *
1239 * Notify listeners about event related with station.
1240 */
wpas_dbus_signal_station(struct wpa_supplicant * wpa_s,const char * station_obj_path,const char * sig_name,dbus_bool_t properties)1241 static void wpas_dbus_signal_station(struct wpa_supplicant *wpa_s,
1242 const char *station_obj_path,
1243 const char *sig_name,
1244 dbus_bool_t properties)
1245 {
1246 struct wpas_dbus_priv *iface;
1247 DBusMessage *msg;
1248 DBusMessageIter iter;
1249
1250 iface = wpa_s->global->dbus;
1251
1252 /* Do nothing if the control interface is not turned on */
1253 if (!iface || !wpa_s->dbus_new_path)
1254 return;
1255
1256 wpa_printf(MSG_DEBUG, "dbus: STA signal %s", sig_name);
1257 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1258 WPAS_DBUS_NEW_IFACE_INTERFACE, sig_name);
1259 if (!msg)
1260 return;
1261
1262 dbus_message_iter_init_append(msg, &iter);
1263 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
1264 &station_obj_path) ||
1265 (properties &&
1266 !wpa_dbus_get_object_properties(iface, station_obj_path,
1267 WPAS_DBUS_NEW_IFACE_STA,
1268 &iter)))
1269 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1270 else
1271 dbus_connection_send(iface->con, msg, NULL);
1272 dbus_message_unref(msg);
1273 }
1274
1275
1276 /**
1277 * wpas_dbus_signal_station_added - Send a Station added signal
1278 * @wpa_s: %wpa_supplicant network interface data
1279 * @station_obj_path: new Station object path
1280 *
1281 * Notify listeners about adding new Station
1282 */
wpas_dbus_signal_station_added(struct wpa_supplicant * wpa_s,const char * station_obj_path)1283 static void wpas_dbus_signal_station_added(struct wpa_supplicant *wpa_s,
1284 const char *station_obj_path)
1285 {
1286 wpas_dbus_signal_station(wpa_s, station_obj_path, "StationAdded", TRUE);
1287 }
1288
1289
1290 /**
1291 * wpas_dbus_signal_station_removed - Send a Station removed signal
1292 * @wpa_s: %wpa_supplicant network interface data
1293 * @station_obj_path: Station object path
1294 *
1295 * Notify listeners about removing Station
1296 */
wpas_dbus_signal_station_removed(struct wpa_supplicant * wpa_s,const char * station_obj_path)1297 static void wpas_dbus_signal_station_removed(struct wpa_supplicant *wpa_s,
1298 const char *station_obj_path)
1299 {
1300 wpas_dbus_signal_station(wpa_s, station_obj_path, "StationRemoved",
1301 FALSE);
1302 }
1303
1304
1305 #ifdef CONFIG_P2P
1306
1307 /**
1308 * wpas_dbus_signal_p2p_group_removed - Signals P2P group was removed
1309 * @wpa_s: %wpa_supplicant network interface data
1310 * @role: role of this device (client or GO)
1311 * Sends signal with i/f name and role as string arguments
1312 */
wpas_dbus_signal_p2p_group_removed(struct wpa_supplicant * wpa_s,const char * role)1313 void wpas_dbus_signal_p2p_group_removed(struct wpa_supplicant *wpa_s,
1314 const char *role)
1315 {
1316 DBusMessage *msg;
1317 DBusMessageIter iter, dict_iter;
1318 struct wpas_dbus_priv *iface = wpa_s->global->dbus;
1319 struct wpa_supplicant *parent;
1320
1321 /* Do nothing if the control interface is not turned on */
1322 if (iface == NULL)
1323 return;
1324
1325 parent = wpa_s->parent;
1326 if (parent->p2p_mgmt)
1327 parent = parent->parent;
1328
1329 if (!wpa_s->dbus_groupobj_path || !wpa_s->dbus_new_path ||
1330 !parent->dbus_new_path)
1331 return;
1332
1333 msg = dbus_message_new_signal(parent->dbus_new_path,
1334 WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1335 "GroupFinished");
1336 if (msg == NULL)
1337 return;
1338
1339 dbus_message_iter_init_append(msg, &iter);
1340 if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
1341 !wpa_dbus_dict_append_object_path(&dict_iter,
1342 "interface_object",
1343 wpa_s->dbus_new_path) ||
1344 !wpa_dbus_dict_append_string(&dict_iter, "role", role) ||
1345 !wpa_dbus_dict_append_object_path(&dict_iter, "group_object",
1346 wpa_s->dbus_groupobj_path) ||
1347 !wpa_dbus_dict_close_write(&iter, &dict_iter))
1348 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1349 else
1350 dbus_connection_send(iface->con, msg, NULL);
1351 dbus_message_unref(msg);
1352 }
1353
1354
1355 /**
1356 * wpas_dbus_signal_p2p_provision_discovery - Signals various PD events
1357 *
1358 * @dev_addr - who sent the request or responded to our request.
1359 * @request - Will be 1 if request, 0 for response.
1360 * @status - valid only in case of response
1361 * @config_methods - wps config methods
1362 * @generated_pin - pin to be displayed in case of WPS_CONFIG_DISPLAY method
1363 *
1364 * Sends following provision discovery related events:
1365 * ProvisionDiscoveryRequestDisplayPin
1366 * ProvisionDiscoveryResponseDisplayPin
1367 * ProvisionDiscoveryRequestEnterPin
1368 * ProvisionDiscoveryResponseEnterPin
1369 * ProvisionDiscoveryPBCRequest
1370 * ProvisionDiscoveryPBCResponse
1371 *
1372 * TODO::
1373 * ProvisionDiscoveryFailure (timeout case)
1374 */
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)1375 void wpas_dbus_signal_p2p_provision_discovery(struct wpa_supplicant *wpa_s,
1376 const u8 *dev_addr, int request,
1377 enum p2p_prov_disc_status status,
1378 u16 config_methods,
1379 unsigned int generated_pin)
1380 {
1381 DBusMessage *msg;
1382 DBusMessageIter iter;
1383 struct wpas_dbus_priv *iface;
1384 char *_signal;
1385 int add_pin = 0;
1386 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1387 int error_ret = 1;
1388 char pin[9], *p_pin = NULL;
1389
1390 iface = wpa_s->global->dbus;
1391
1392 /* Do nothing if the control interface is not turned on */
1393 if (iface == NULL)
1394 return;
1395
1396 if (wpa_s->p2p_mgmt)
1397 wpa_s = wpa_s->parent;
1398 if (!wpa_s->dbus_new_path)
1399 return;
1400
1401 if (request || !status) {
1402 if (config_methods & WPS_CONFIG_DISPLAY)
1403 _signal = request ?
1404 "ProvisionDiscoveryRequestDisplayPin" :
1405 "ProvisionDiscoveryResponseEnterPin";
1406 else if (config_methods & WPS_CONFIG_KEYPAD)
1407 _signal = request ?
1408 "ProvisionDiscoveryRequestEnterPin" :
1409 "ProvisionDiscoveryResponseDisplayPin";
1410 else if (config_methods & WPS_CONFIG_PUSHBUTTON)
1411 _signal = request ? "ProvisionDiscoveryPBCRequest" :
1412 "ProvisionDiscoveryPBCResponse";
1413 else
1414 return; /* Unknown or un-supported method */
1415 } else {
1416 /* Explicit check for failure response */
1417 _signal = "ProvisionDiscoveryFailure";
1418 }
1419
1420 add_pin = ((request && (config_methods & WPS_CONFIG_DISPLAY)) ||
1421 (!request && !status &&
1422 (config_methods & WPS_CONFIG_KEYPAD)));
1423
1424 if (add_pin) {
1425 os_snprintf(pin, sizeof(pin), "%08d", generated_pin);
1426 p_pin = pin;
1427 }
1428
1429 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1430 WPAS_DBUS_NEW_IFACE_P2PDEVICE, _signal);
1431 if (msg == NULL)
1432 return;
1433
1434 /* Check if this is a known peer */
1435 if (!p2p_peer_known(wpa_s->global->p2p, dev_addr))
1436 goto error;
1437
1438 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1439 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
1440 COMPACT_MACSTR,
1441 wpa_s->dbus_new_path, MAC2STR(dev_addr));
1442
1443 path = peer_obj_path;
1444
1445 dbus_message_iter_init_append(msg, &iter);
1446
1447 if (!dbus_message_iter_append_basic(&iter,
1448 DBUS_TYPE_OBJECT_PATH,
1449 &path))
1450 goto error;
1451
1452 if (!request && status)
1453 /* Attach status to ProvisionDiscoveryFailure */
1454 error_ret = !dbus_message_iter_append_basic(&iter,
1455 DBUS_TYPE_INT32,
1456 &status);
1457 else
1458 error_ret = (add_pin &&
1459 !dbus_message_iter_append_basic(&iter,
1460 DBUS_TYPE_STRING,
1461 &p_pin));
1462
1463 error:
1464 if (!error_ret)
1465 dbus_connection_send(iface->con, msg, NULL);
1466 else
1467 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1468
1469 dbus_message_unref(msg);
1470 }
1471
1472
1473 /**
1474 * wpas_dbus_signal_p2p_go_neg_req - Signal P2P GO Negotiation Request RX
1475 * @wpa_s: %wpa_supplicant network interface data
1476 * @src: Source address of the message triggering this notification
1477 * @dev_passwd_id: WPS Device Password Id
1478 * @go_intent: Peer's GO Intent value
1479 *
1480 * Sends signal to notify that a peer P2P Device is requesting group owner
1481 * negotiation with us.
1482 */
wpas_dbus_signal_p2p_go_neg_req(struct wpa_supplicant * wpa_s,const u8 * src,u16 dev_passwd_id,u8 go_intent)1483 void wpas_dbus_signal_p2p_go_neg_req(struct wpa_supplicant *wpa_s,
1484 const u8 *src, u16 dev_passwd_id,
1485 u8 go_intent)
1486 {
1487 DBusMessage *msg;
1488 DBusMessageIter iter;
1489 struct wpas_dbus_priv *iface;
1490 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1491
1492 iface = wpa_s->global->dbus;
1493
1494 /* Do nothing if the control interface is not turned on */
1495 if (iface == NULL)
1496 return;
1497
1498 if (wpa_s->p2p_mgmt)
1499 wpa_s = wpa_s->parent;
1500 if (!wpa_s->dbus_new_path)
1501 return;
1502
1503 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1504 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
1505 wpa_s->dbus_new_path, MAC2STR(src));
1506 path = peer_obj_path;
1507
1508 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1509 WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1510 "GONegotiationRequest");
1511 if (msg == NULL)
1512 return;
1513
1514 dbus_message_iter_init_append(msg, &iter);
1515
1516 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
1517 &path) ||
1518 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT16,
1519 &dev_passwd_id) ||
1520 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BYTE,
1521 &go_intent))
1522 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1523 else
1524 dbus_connection_send(iface->con, msg, NULL);
1525
1526 dbus_message_unref(msg);
1527 }
1528
1529
wpas_dbus_get_group_obj_path(struct wpa_supplicant * wpa_s,const struct wpa_ssid * ssid,char * group_obj_path)1530 static int wpas_dbus_get_group_obj_path(struct wpa_supplicant *wpa_s,
1531 const struct wpa_ssid *ssid,
1532 char *group_obj_path)
1533 {
1534 char group_name[3];
1535
1536 if (!wpa_s->dbus_new_path ||
1537 os_memcmp(ssid->ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN))
1538 return -1;
1539
1540 os_memcpy(group_name, ssid->ssid + P2P_WILDCARD_SSID_LEN, 2);
1541 group_name[2] = '\0';
1542
1543 os_snprintf(group_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1544 "%s/" WPAS_DBUS_NEW_P2P_GROUPS_PART "/%s",
1545 wpa_s->dbus_new_path, group_name);
1546
1547 return 0;
1548 }
1549
1550
1551 struct group_changed_data {
1552 struct wpa_supplicant *wpa_s;
1553 struct p2p_peer_info *info;
1554 };
1555
1556
match_group_where_peer_is_client(struct p2p_group * group,void * user_data)1557 static int match_group_where_peer_is_client(struct p2p_group *group,
1558 void *user_data)
1559 {
1560 struct group_changed_data *data = user_data;
1561 const struct p2p_group_config *cfg;
1562 struct wpa_supplicant *wpa_s_go;
1563
1564 if (!p2p_group_is_client_connected(group, data->info->p2p_device_addr))
1565 return 1;
1566
1567 cfg = p2p_group_get_config(group);
1568
1569 wpa_s_go = wpas_get_p2p_go_iface(data->wpa_s, cfg->ssid,
1570 cfg->ssid_len);
1571 if (wpa_s_go != NULL && wpa_s_go == data->wpa_s) {
1572 wpas_dbus_signal_peer_groups_changed(
1573 data->wpa_s->p2pdev, data->info->p2p_device_addr);
1574 return 0;
1575 }
1576
1577 return 1;
1578 }
1579
1580
signal_peer_groups_changed(struct p2p_peer_info * info,void * user_data)1581 static void signal_peer_groups_changed(struct p2p_peer_info *info,
1582 void *user_data)
1583 {
1584 struct group_changed_data *data = user_data;
1585 struct wpa_supplicant *wpa_s_go;
1586
1587 wpa_s_go = wpas_get_p2p_client_iface(data->wpa_s,
1588 info->p2p_device_addr);
1589 if (wpa_s_go != NULL && wpa_s_go == data->wpa_s) {
1590 wpas_dbus_signal_peer_groups_changed(data->wpa_s->p2pdev,
1591 info->p2p_device_addr);
1592 return;
1593 }
1594
1595 data->info = info;
1596 p2p_loop_on_all_groups(data->wpa_s->global->p2p,
1597 match_group_where_peer_is_client, data);
1598 data->info = NULL;
1599 }
1600
1601
peer_groups_changed(struct wpa_supplicant * wpa_s)1602 static void peer_groups_changed(struct wpa_supplicant *wpa_s)
1603 {
1604 struct group_changed_data data;
1605
1606 os_memset(&data, 0, sizeof(data));
1607 data.wpa_s = wpa_s;
1608
1609 p2p_loop_on_known_peers(wpa_s->global->p2p,
1610 signal_peer_groups_changed, &data);
1611 }
1612
1613
1614 /**
1615 * wpas_dbus_signal_p2p_group_started - Signals P2P group has
1616 * started. Emitted when a group is successfully started
1617 * irrespective of the role (client/GO) of the current device
1618 *
1619 * @wpa_s: %wpa_supplicant network interface data
1620 * @client: this device is P2P client
1621 * @persistent: 0 - non persistent group, 1 - persistent group
1622 * @ip: When group role is client, it contains local IP address, netmask, and
1623 * GO's IP address, if assigned; otherwise, NULL
1624 */
wpas_dbus_signal_p2p_group_started(struct wpa_supplicant * wpa_s,int client,int persistent,const u8 * ip)1625 void wpas_dbus_signal_p2p_group_started(struct wpa_supplicant *wpa_s,
1626 int client, int persistent,
1627 const u8 *ip)
1628 {
1629 DBusMessage *msg;
1630 DBusMessageIter iter, dict_iter;
1631 struct wpas_dbus_priv *iface;
1632 struct wpa_supplicant *parent;
1633
1634 parent = wpa_s->parent;
1635 if (parent->p2p_mgmt)
1636 parent = parent->parent;
1637
1638 iface = parent->global->dbus;
1639
1640 /* Do nothing if the control interface is not turned on */
1641 if (iface == NULL || !parent->dbus_new_path || !wpa_s->dbus_new_path)
1642 return;
1643
1644 if (wpa_s->dbus_groupobj_path == NULL)
1645 return;
1646
1647 /* New interface has been created for this group */
1648 msg = dbus_message_new_signal(parent->dbus_new_path,
1649 WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1650 "GroupStarted");
1651 if (msg == NULL)
1652 return;
1653
1654 dbus_message_iter_init_append(msg, &iter);
1655 /*
1656 * In case the device supports creating a separate interface the
1657 * DBus client will need to know the object path for the interface
1658 * object this group was created on, so include it here.
1659 */
1660 if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
1661 !wpa_dbus_dict_append_object_path(&dict_iter,
1662 "interface_object",
1663 wpa_s->dbus_new_path) ||
1664 !wpa_dbus_dict_append_string(&dict_iter, "role",
1665 client ? "client" : "GO") ||
1666 !wpa_dbus_dict_append_bool(&dict_iter, "persistent",
1667 !!persistent) ||
1668 !wpa_dbus_dict_append_object_path(&dict_iter, "group_object",
1669 wpa_s->dbus_groupobj_path) ||
1670 (ip &&
1671 (!wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddr",
1672 (char *) ip, 4) ||
1673 !wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddrMask",
1674 (char *) ip + 4, 4) ||
1675 !wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddrGo",
1676 (char *) ip + 8, 4))) ||
1677 !wpa_dbus_dict_close_write(&iter, &dict_iter)) {
1678 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1679 } else {
1680 dbus_connection_send(iface->con, msg, NULL);
1681 if (client)
1682 peer_groups_changed(wpa_s);
1683 }
1684 dbus_message_unref(msg);
1685 }
1686
1687
1688 /**
1689 * wpas_dbus_signal_p2p_go_neg_resp - Emit GONegotiation Success/Failure signal
1690 * @wpa_s: %wpa_supplicant network interface data
1691 * @res: Result of the GO Neg Request
1692 */
wpas_dbus_signal_p2p_go_neg_resp(struct wpa_supplicant * wpa_s,struct p2p_go_neg_results * res)1693 void wpas_dbus_signal_p2p_go_neg_resp(struct wpa_supplicant *wpa_s,
1694 struct p2p_go_neg_results *res)
1695 {
1696 DBusMessage *msg;
1697 DBusMessageIter iter, dict_iter;
1698 DBusMessageIter iter_dict_entry, iter_dict_val, iter_dict_array;
1699 struct wpas_dbus_priv *iface;
1700 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1701 dbus_int32_t freqs[P2P_MAX_CHANNELS];
1702 dbus_int32_t *f_array = freqs;
1703
1704
1705 iface = wpa_s->global->dbus;
1706
1707 if (wpa_s->p2p_mgmt)
1708 wpa_s = wpa_s->parent;
1709
1710 os_memset(freqs, 0, sizeof(freqs));
1711 /* Do nothing if the control interface is not turned on */
1712 if (iface == NULL || !wpa_s->dbus_new_path)
1713 return;
1714
1715 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1716 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
1717 wpa_s->dbus_new_path, MAC2STR(res->peer_device_addr));
1718 path = peer_obj_path;
1719
1720 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1721 WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1722 res->status ? "GONegotiationFailure" :
1723 "GONegotiationSuccess");
1724 if (msg == NULL)
1725 return;
1726
1727 dbus_message_iter_init_append(msg, &iter);
1728 if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
1729 !wpa_dbus_dict_append_object_path(&dict_iter, "peer_object",
1730 path) ||
1731 !wpa_dbus_dict_append_int32(&dict_iter, "status", res->status))
1732 goto err;
1733
1734 if (!res->status) {
1735 int i = 0;
1736 int freq_list_num = 0;
1737
1738 if ((res->role_go &&
1739 !wpa_dbus_dict_append_string(&dict_iter, "passphrase",
1740 res->passphrase)) ||
1741 !wpa_dbus_dict_append_string(&dict_iter, "role_go",
1742 res->role_go ? "GO" :
1743 "client") ||
1744 !wpa_dbus_dict_append_int32(&dict_iter, "frequency",
1745 res->freq) ||
1746 !wpa_dbus_dict_append_byte_array(&dict_iter, "ssid",
1747 (const char *) res->ssid,
1748 res->ssid_len) ||
1749 !wpa_dbus_dict_append_byte_array(&dict_iter,
1750 "peer_device_addr",
1751 (const char *)
1752 res->peer_device_addr,
1753 ETH_ALEN) ||
1754 !wpa_dbus_dict_append_byte_array(&dict_iter,
1755 "peer_interface_addr",
1756 (const char *)
1757 res->peer_interface_addr,
1758 ETH_ALEN) ||
1759 !wpa_dbus_dict_append_string(&dict_iter, "wps_method",
1760 p2p_wps_method_text(
1761 res->wps_method)))
1762 goto err;
1763
1764 for (i = 0; i < P2P_MAX_CHANNELS; i++) {
1765 if (res->freq_list[i]) {
1766 freqs[i] = res->freq_list[i];
1767 freq_list_num++;
1768 }
1769 }
1770
1771 if (!wpa_dbus_dict_begin_array(&dict_iter,
1772 "frequency_list",
1773 DBUS_TYPE_INT32_AS_STRING,
1774 &iter_dict_entry,
1775 &iter_dict_val,
1776 &iter_dict_array) ||
1777 !dbus_message_iter_append_fixed_array(&iter_dict_array,
1778 DBUS_TYPE_INT32,
1779 &f_array,
1780 freq_list_num) ||
1781 !wpa_dbus_dict_end_array(&dict_iter,
1782 &iter_dict_entry,
1783 &iter_dict_val,
1784 &iter_dict_array) ||
1785 !wpa_dbus_dict_append_int32(&dict_iter, "persistent_group",
1786 res->persistent_group) ||
1787 !wpa_dbus_dict_append_uint32(&dict_iter,
1788 "peer_config_timeout",
1789 res->peer_config_timeout))
1790 goto err;
1791 }
1792
1793 if (!wpa_dbus_dict_close_write(&iter, &dict_iter))
1794 goto err;
1795
1796 dbus_connection_send(iface->con, msg, NULL);
1797 err:
1798 dbus_message_unref(msg);
1799 }
1800
1801
1802 /**
1803 * wpas_dbus_signal_p2p_invitation_result - Emit InvitationResult signal
1804 * @wpa_s: %wpa_supplicant network interface data
1805 * @status: Status of invitation process
1806 * @bssid: Basic Service Set Identifier
1807 */
wpas_dbus_signal_p2p_invitation_result(struct wpa_supplicant * wpa_s,int status,const u8 * bssid)1808 void wpas_dbus_signal_p2p_invitation_result(struct wpa_supplicant *wpa_s,
1809 int status, const u8 *bssid)
1810 {
1811 DBusMessage *msg;
1812 DBusMessageIter iter, dict_iter;
1813 struct wpas_dbus_priv *iface;
1814
1815 wpa_printf(MSG_DEBUG, "%s", __func__);
1816
1817 iface = wpa_s->global->dbus;
1818 /* Do nothing if the control interface is not turned on */
1819 if (iface == NULL)
1820 return;
1821
1822 if (wpa_s->p2p_mgmt)
1823 wpa_s = wpa_s->parent;
1824 if (!wpa_s->dbus_new_path)
1825 return;
1826
1827 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1828 WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1829 "InvitationResult");
1830
1831 if (msg == NULL)
1832 return;
1833
1834 dbus_message_iter_init_append(msg, &iter);
1835 if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
1836 !wpa_dbus_dict_append_int32(&dict_iter, "status", status) ||
1837 (bssid &&
1838 !wpa_dbus_dict_append_byte_array(&dict_iter, "BSSID",
1839 (const char *) bssid,
1840 ETH_ALEN)) ||
1841 !wpa_dbus_dict_close_write(&iter, &dict_iter))
1842 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1843 else
1844 dbus_connection_send(iface->con, msg, NULL);
1845 dbus_message_unref(msg);
1846 }
1847
1848
1849 /**
1850 *
1851 * Method to emit a signal for a peer joining the group.
1852 * The signal will carry path to the group member object
1853 * constructed using p2p i/f addr used for connecting.
1854 *
1855 * @wpa_s: %wpa_supplicant network interface data
1856 * @peer_addr: P2P Device Address of the peer joining the group
1857 */
wpas_dbus_signal_p2p_peer_joined(struct wpa_supplicant * wpa_s,const u8 * peer_addr)1858 void wpas_dbus_signal_p2p_peer_joined(struct wpa_supplicant *wpa_s,
1859 const u8 *peer_addr)
1860 {
1861 struct wpas_dbus_priv *iface;
1862 DBusMessage *msg;
1863 DBusMessageIter iter;
1864 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1865 struct wpa_supplicant *parent;
1866
1867 iface = wpa_s->global->dbus;
1868
1869 /* Do nothing if the control interface is not turned on */
1870 if (iface == NULL)
1871 return;
1872
1873 if (!wpa_s->dbus_groupobj_path)
1874 return;
1875
1876 parent = wpa_s->parent;
1877 if (parent->p2p_mgmt)
1878 parent = parent->parent;
1879 if (!parent->dbus_new_path)
1880 return;
1881
1882 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1883 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
1884 COMPACT_MACSTR,
1885 parent->dbus_new_path, MAC2STR(peer_addr));
1886
1887 msg = dbus_message_new_signal(wpa_s->dbus_groupobj_path,
1888 WPAS_DBUS_NEW_IFACE_P2P_GROUP,
1889 "PeerJoined");
1890 if (msg == NULL)
1891 return;
1892
1893 dbus_message_iter_init_append(msg, &iter);
1894 path = peer_obj_path;
1895 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
1896 &path)) {
1897 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1898 } else {
1899 dbus_connection_send(iface->con, msg, NULL);
1900 wpas_dbus_signal_peer_groups_changed(parent, peer_addr);
1901 }
1902 dbus_message_unref(msg);
1903 }
1904
1905
1906 /**
1907 *
1908 * Method to emit a signal for a peer disconnecting the group.
1909 * The signal will carry path to the group member object
1910 * constructed using the P2P Device Address of the peer.
1911 *
1912 * @wpa_s: %wpa_supplicant network interface data
1913 * @peer_addr: P2P Device Address of the peer joining the group
1914 */
wpas_dbus_signal_p2p_peer_disconnected(struct wpa_supplicant * wpa_s,const u8 * peer_addr)1915 void wpas_dbus_signal_p2p_peer_disconnected(struct wpa_supplicant *wpa_s,
1916 const u8 *peer_addr)
1917 {
1918 struct wpas_dbus_priv *iface;
1919 DBusMessage *msg;
1920 DBusMessageIter iter;
1921 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1922 struct wpa_supplicant *parent;
1923
1924 iface = wpa_s->global->dbus;
1925
1926 /* Do nothing if the control interface is not turned on */
1927 if (iface == NULL)
1928 return;
1929
1930 if (!wpa_s->dbus_groupobj_path)
1931 return;
1932
1933 parent = wpa_s->parent;
1934 if (parent->p2p_mgmt)
1935 parent = parent->parent;
1936 if (!parent->dbus_new_path)
1937 return;
1938
1939 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1940 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
1941 COMPACT_MACSTR,
1942 parent->dbus_new_path, MAC2STR(peer_addr));
1943
1944 msg = dbus_message_new_signal(wpa_s->dbus_groupobj_path,
1945 WPAS_DBUS_NEW_IFACE_P2P_GROUP,
1946 "PeerDisconnected");
1947 if (msg == NULL)
1948 return;
1949
1950 dbus_message_iter_init_append(msg, &iter);
1951 path = peer_obj_path;
1952 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
1953 &path)) {
1954 wpa_printf(MSG_ERROR,
1955 "dbus: Failed to construct PeerDisconnected signal");
1956 } else {
1957 dbus_connection_send(iface->con, msg, NULL);
1958 wpas_dbus_signal_peer_groups_changed(parent, peer_addr);
1959 }
1960 dbus_message_unref(msg);
1961 }
1962
1963
1964 /**
1965 *
1966 * Method to emit a signal for a service discovery request.
1967 * The signal will carry station address, frequency, dialog token,
1968 * update indicator and it tlvs
1969 *
1970 * @wpa_s: %wpa_supplicant network interface data
1971 * @sa: station addr (p2p i/f) of the peer
1972 * @dialog_token: service discovery request dialog token
1973 * @update_indic: service discovery request update indicator
1974 * @tlvs: service discovery request generated byte array of tlvs
1975 * @tlvs_len: service discovery request tlvs length
1976 */
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)1977 void wpas_dbus_signal_p2p_sd_request(struct wpa_supplicant *wpa_s,
1978 int freq, const u8 *sa, u8 dialog_token,
1979 u16 update_indic, const u8 *tlvs,
1980 size_t tlvs_len)
1981 {
1982 DBusMessage *msg;
1983 DBusMessageIter iter, dict_iter;
1984 struct wpas_dbus_priv *iface;
1985 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1986
1987 iface = wpa_s->global->dbus;
1988
1989 /* Do nothing if the control interface is not turned on */
1990 if (iface == NULL)
1991 return;
1992
1993 if (wpa_s->p2p_mgmt)
1994 wpa_s = wpa_s->parent;
1995 if (!wpa_s->dbus_new_path)
1996 return;
1997
1998 /* Check if this is a known peer */
1999 if (!p2p_peer_known(wpa_s->global->p2p, sa))
2000 return;
2001
2002 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
2003 WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2004 "ServiceDiscoveryRequest");
2005 if (msg == NULL)
2006 return;
2007
2008 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2009 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
2010 COMPACT_MACSTR, wpa_s->dbus_new_path, MAC2STR(sa));
2011
2012 path = peer_obj_path;
2013
2014 dbus_message_iter_init_append(msg, &iter);
2015 if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
2016 !wpa_dbus_dict_append_object_path(&dict_iter, "peer_object",
2017 path) ||
2018 !wpa_dbus_dict_append_int32(&dict_iter, "frequency", freq) ||
2019 !wpa_dbus_dict_append_int32(&dict_iter, "dialog_token",
2020 dialog_token) ||
2021 !wpa_dbus_dict_append_uint16(&dict_iter, "update_indicator",
2022 update_indic) ||
2023 !wpa_dbus_dict_append_byte_array(&dict_iter, "tlvs",
2024 (const char *) tlvs,
2025 tlvs_len) ||
2026 !wpa_dbus_dict_close_write(&iter, &dict_iter))
2027 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
2028 else
2029 dbus_connection_send(iface->con, msg, NULL);
2030 dbus_message_unref(msg);
2031 }
2032
2033
2034 /**
2035 *
2036 * Method to emit a signal for a service discovery response.
2037 * The signal will carry station address, update indicator and it
2038 * tlvs
2039 *
2040 * @wpa_s: %wpa_supplicant network interface data
2041 * @sa: station addr (p2p i/f) of the peer
2042 * @update_indic: service discovery request update indicator
2043 * @tlvs: service discovery request generated byte array of tlvs
2044 * @tlvs_len: service discovery request tlvs length
2045 */
wpas_dbus_signal_p2p_sd_response(struct wpa_supplicant * wpa_s,const u8 * sa,u16 update_indic,const u8 * tlvs,size_t tlvs_len)2046 void wpas_dbus_signal_p2p_sd_response(struct wpa_supplicant *wpa_s,
2047 const u8 *sa, u16 update_indic,
2048 const u8 *tlvs, size_t tlvs_len)
2049 {
2050 DBusMessage *msg;
2051 DBusMessageIter iter, dict_iter;
2052 struct wpas_dbus_priv *iface;
2053 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
2054
2055 iface = wpa_s->global->dbus;
2056
2057 /* Do nothing if the control interface is not turned on */
2058 if (iface == NULL)
2059 return;
2060
2061 if (wpa_s->p2p_mgmt)
2062 wpa_s = wpa_s->parent;
2063 if (!wpa_s->dbus_new_path)
2064 return;
2065
2066 /* Check if this is a known peer */
2067 if (!p2p_peer_known(wpa_s->global->p2p, sa))
2068 return;
2069
2070 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
2071 WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2072 "ServiceDiscoveryResponse");
2073 if (msg == NULL)
2074 return;
2075
2076 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2077 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
2078 COMPACT_MACSTR, wpa_s->dbus_new_path, MAC2STR(sa));
2079
2080 path = peer_obj_path;
2081
2082 dbus_message_iter_init_append(msg, &iter);
2083 if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
2084 !wpa_dbus_dict_append_object_path(&dict_iter, "peer_object",
2085 path) ||
2086 !wpa_dbus_dict_append_uint16(&dict_iter, "update_indicator",
2087 update_indic) ||
2088 !wpa_dbus_dict_append_byte_array(&dict_iter, "tlvs",
2089 (const char *) tlvs,
2090 tlvs_len) ||
2091 !wpa_dbus_dict_close_write(&iter, &dict_iter))
2092 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
2093 else
2094 dbus_connection_send(iface->con, msg, NULL);
2095 dbus_message_unref(msg);
2096 }
2097
2098
2099 /**
2100 * wpas_dbus_signal_persistent_group - Send a persistent group related
2101 * event signal
2102 * @wpa_s: %wpa_supplicant network interface data
2103 * @id: new persistent group id
2104 * @sig_name: signal name - PersistentGroupAdded, PersistentGroupRemoved
2105 * @properties: determines if add second argument with object properties
2106 *
2107 * Notify listeners about an event related to persistent groups.
2108 */
wpas_dbus_signal_persistent_group(struct wpa_supplicant * wpa_s,int id,const char * sig_name,dbus_bool_t properties)2109 static void wpas_dbus_signal_persistent_group(struct wpa_supplicant *wpa_s,
2110 int id, const char *sig_name,
2111 dbus_bool_t properties)
2112 {
2113 struct wpas_dbus_priv *iface;
2114 DBusMessage *msg;
2115 DBusMessageIter iter;
2116 char pgrp_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
2117
2118 iface = wpa_s->global->dbus;
2119
2120 /* Do nothing if the control interface is not turned on */
2121 if (iface == NULL)
2122 return;
2123
2124 if (wpa_s->p2p_mgmt)
2125 wpa_s = wpa_s->parent;
2126 if (!wpa_s->dbus_new_path)
2127 return;
2128
2129 os_snprintf(pgrp_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2130 "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%u",
2131 wpa_s->dbus_new_path, id);
2132
2133 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
2134 WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2135 sig_name);
2136 if (msg == NULL)
2137 return;
2138
2139 dbus_message_iter_init_append(msg, &iter);
2140 path = pgrp_obj_path;
2141 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
2142 &path) ||
2143 (properties &&
2144 !wpa_dbus_get_object_properties(
2145 iface, pgrp_obj_path,
2146 WPAS_DBUS_NEW_IFACE_PERSISTENT_GROUP, &iter)))
2147 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
2148 else
2149 dbus_connection_send(iface->con, msg, NULL);
2150
2151 dbus_message_unref(msg);
2152 }
2153
2154
2155 /**
2156 * wpas_dbus_signal_persistent_group_added - Send a persistent_group
2157 * added signal
2158 * @wpa_s: %wpa_supplicant network interface data
2159 * @id: new persistent group id
2160 *
2161 * Notify listeners about addition of a new persistent group.
2162 */
wpas_dbus_signal_persistent_group_added(struct wpa_supplicant * wpa_s,int id)2163 static void wpas_dbus_signal_persistent_group_added(
2164 struct wpa_supplicant *wpa_s, int id)
2165 {
2166 wpas_dbus_signal_persistent_group(wpa_s, id, "PersistentGroupAdded",
2167 TRUE);
2168 }
2169
2170
2171 /**
2172 * wpas_dbus_signal_persistent_group_removed - Send a persistent_group
2173 * removed signal
2174 * @wpa_s: %wpa_supplicant network interface data
2175 * @id: persistent group id
2176 *
2177 * Notify listeners about removal of a persistent group.
2178 */
wpas_dbus_signal_persistent_group_removed(struct wpa_supplicant * wpa_s,int id)2179 static void wpas_dbus_signal_persistent_group_removed(
2180 struct wpa_supplicant *wpa_s, int id)
2181 {
2182 wpas_dbus_signal_persistent_group(wpa_s, id, "PersistentGroupRemoved",
2183 FALSE);
2184 }
2185
2186
2187 /**
2188 * wpas_dbus_signal_p2p_wps_failed - Signals WpsFailed event
2189 * @wpa_s: %wpa_supplicant network interface data
2190 * @fail: WPS failure information
2191 *
2192 * Sends Event dbus signal with name "fail" and dictionary containing
2193 * "msg" field with fail message number (int32) as arguments
2194 */
wpas_dbus_signal_p2p_wps_failed(struct wpa_supplicant * wpa_s,struct wps_event_fail * fail)2195 void wpas_dbus_signal_p2p_wps_failed(struct wpa_supplicant *wpa_s,
2196 struct wps_event_fail *fail)
2197 {
2198
2199 DBusMessage *msg;
2200 DBusMessageIter iter, dict_iter;
2201 struct wpas_dbus_priv *iface;
2202 char *key = "fail";
2203
2204 iface = wpa_s->global->dbus;
2205
2206 /* Do nothing if the control interface is not turned on */
2207 if (iface == NULL)
2208 return;
2209
2210 if (wpa_s->p2p_mgmt)
2211 wpa_s = wpa_s->parent;
2212
2213 if (!wpa_s->dbus_new_path)
2214 return;
2215 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
2216 WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2217 "WpsFailed");
2218 if (msg == NULL)
2219 return;
2220
2221 dbus_message_iter_init_append(msg, &iter);
2222
2223 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
2224 !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
2225 !wpa_dbus_dict_append_int32(&dict_iter, "msg", fail->msg) ||
2226 !wpa_dbus_dict_append_int16(&dict_iter, "config_error",
2227 fail->config_error) ||
2228 !wpa_dbus_dict_close_write(&iter, &dict_iter))
2229 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
2230 else
2231 dbus_connection_send(iface->con, msg, NULL);
2232
2233 dbus_message_unref(msg);
2234 }
2235
2236
2237 /**
2238 * wpas_dbus_signal_p2p_group_formation_failure - Signals GroupFormationFailure event
2239 * @wpa_s: %wpa_supplicant network interface data
2240 * @reason: indicates the reason code for group formation failure
2241 *
2242 * Sends Event dbus signal and string reason code when available.
2243 */
wpas_dbus_signal_p2p_group_formation_failure(struct wpa_supplicant * wpa_s,const char * reason)2244 void wpas_dbus_signal_p2p_group_formation_failure(struct wpa_supplicant *wpa_s,
2245 const char *reason)
2246 {
2247 DBusMessage *msg;
2248 struct wpas_dbus_priv *iface;
2249
2250 iface = wpa_s->global->dbus;
2251
2252 /* Do nothing if the control interface is not turned on */
2253 if (iface == NULL)
2254 return;
2255
2256 if (wpa_s->p2p_mgmt)
2257 wpa_s = wpa_s->parent;
2258
2259 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
2260 WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2261 "GroupFormationFailure");
2262 if (msg == NULL)
2263 return;
2264
2265 if (dbus_message_append_args(msg, DBUS_TYPE_STRING, &reason,
2266 DBUS_TYPE_INVALID))
2267 dbus_connection_send(iface->con, msg, NULL);
2268 else
2269 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
2270
2271 dbus_message_unref(msg);
2272 }
2273
2274
2275 /**
2276 * wpas_dbus_signal_p2p_invitation_received - Emit InvitationReceived signal
2277 * @wpa_s: %wpa_supplicant network interface data
2278 * @sa: Source address of the Invitation Request
2279 * @dev_add: GO Device Address
2280 * @bssid: P2P Group BSSID or %NULL if not received
2281 * @id: Persistent group id or %0 if not persistent group
2282 * @op_freq: Operating frequency for the group
2283 */
2284
wpas_dbus_signal_p2p_invitation_received(struct wpa_supplicant * wpa_s,const u8 * sa,const u8 * dev_addr,const u8 * bssid,int id,int op_freq)2285 void wpas_dbus_signal_p2p_invitation_received(struct wpa_supplicant *wpa_s,
2286 const u8 *sa, const u8 *dev_addr,
2287 const u8 *bssid, int id,
2288 int op_freq)
2289 {
2290 DBusMessage *msg;
2291 DBusMessageIter iter, dict_iter;
2292 struct wpas_dbus_priv *iface;
2293
2294 iface = wpa_s->global->dbus;
2295
2296 /* Do nothing if the control interface is not turned on */
2297 if (iface == NULL)
2298 return;
2299
2300 if (wpa_s->p2p_mgmt)
2301 wpa_s = wpa_s->parent;
2302
2303 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
2304 WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2305 "InvitationReceived");
2306 if (msg == NULL)
2307 return;
2308
2309 dbus_message_iter_init_append(msg, &iter);
2310 if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
2311 (sa &&
2312 !wpa_dbus_dict_append_byte_array(&dict_iter, "sa",
2313 (const char *) sa, ETH_ALEN)) ||
2314 (dev_addr &&
2315 !wpa_dbus_dict_append_byte_array(&dict_iter, "go_dev_addr",
2316 (const char *) dev_addr,
2317 ETH_ALEN)) ||
2318 (bssid &&
2319 !wpa_dbus_dict_append_byte_array(&dict_iter, "bssid",
2320 (const char *) bssid,
2321 ETH_ALEN)) ||
2322 (id &&
2323 !wpa_dbus_dict_append_int32(&dict_iter, "persistent_id", id)) ||
2324 !wpa_dbus_dict_append_int32(&dict_iter, "op_freq", op_freq) ||
2325 !wpa_dbus_dict_close_write(&iter, &dict_iter)) {
2326 dbus_message_unref(msg);
2327 return;
2328 }
2329
2330 dbus_connection_send(iface->con, msg, NULL);
2331 dbus_message_unref(msg);
2332 }
2333
2334
2335 #endif /* CONFIG_P2P */
2336
2337
2338 /**
2339 * wpas_dbus_signal_prop_changed - Signals change of property
2340 * @wpa_s: %wpa_supplicant network interface data
2341 * @property: indicates which property has changed
2342 *
2343 * Sends PropertyChanged signals with path, interface and arguments
2344 * depending on which property has changed.
2345 */
wpas_dbus_signal_prop_changed(struct wpa_supplicant * wpa_s,enum wpas_dbus_prop property)2346 void wpas_dbus_signal_prop_changed(struct wpa_supplicant *wpa_s,
2347 enum wpas_dbus_prop property)
2348 {
2349 char *prop;
2350 dbus_bool_t flush;
2351
2352 if (wpa_s->dbus_new_path == NULL)
2353 return; /* Skip signal since D-Bus setup is not yet ready */
2354
2355 flush = FALSE;
2356 switch (property) {
2357 case WPAS_DBUS_PROP_AP_SCAN:
2358 prop = "ApScan";
2359 break;
2360 case WPAS_DBUS_PROP_SCANNING:
2361 prop = "Scanning";
2362 break;
2363 case WPAS_DBUS_PROP_STATE:
2364 prop = "State";
2365 break;
2366 case WPAS_DBUS_PROP_CURRENT_BSS:
2367 prop = "CurrentBSS";
2368 break;
2369 case WPAS_DBUS_PROP_CURRENT_NETWORK:
2370 prop = "CurrentNetwork";
2371 break;
2372 case WPAS_DBUS_PROP_BSSS:
2373 prop = "BSSs";
2374 break;
2375 case WPAS_DBUS_PROP_STATIONS:
2376 prop = "Stations";
2377 break;
2378 case WPAS_DBUS_PROP_CURRENT_AUTH_MODE:
2379 prop = "CurrentAuthMode";
2380 break;
2381 case WPAS_DBUS_PROP_DISCONNECT_REASON:
2382 prop = "DisconnectReason";
2383 flush = TRUE;
2384 break;
2385 case WPAS_DBUS_PROP_AUTH_STATUS_CODE:
2386 prop = "AuthStatusCode";
2387 flush = TRUE;
2388 break;
2389 case WPAS_DBUS_PROP_ASSOC_STATUS_CODE:
2390 prop = "AssocStatusCode";
2391 flush = TRUE;
2392 break;
2393 case WPAS_DBUS_PROP_ROAM_TIME:
2394 prop = "RoamTime";
2395 break;
2396 case WPAS_DBUS_PROP_ROAM_COMPLETE:
2397 prop = "RoamComplete";
2398 break;
2399 case WPAS_DBUS_PROP_SCAN_IN_PROGRESS_6GHZ:
2400 prop = "ScanInProgress6GHz";
2401 flush = TRUE;
2402 break;
2403 case WPAS_DBUS_PROP_SESSION_LENGTH:
2404 prop = "SessionLength";
2405 break;
2406 case WPAS_DBUS_PROP_BSS_TM_STATUS:
2407 prop = "BSSTMStatus";
2408 break;
2409 case WPAS_DBUS_PROP_MAC_ADDRESS:
2410 prop = "MACAddress";
2411 break;
2412 case WPAS_DBUS_PROP_SIGNAL_CHANGE:
2413 prop = "SignalChange";
2414 break;
2415 default:
2416 wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d",
2417 __func__, property);
2418 return;
2419 }
2420
2421 wpa_dbus_mark_property_changed(wpa_s->global->dbus,
2422 wpa_s->dbus_new_path,
2423 WPAS_DBUS_NEW_IFACE_INTERFACE, prop);
2424 if (flush) {
2425 wpa_dbus_flush_object_changed_properties(
2426 wpa_s->global->dbus->con, wpa_s->dbus_new_path);
2427 }
2428 }
2429
2430
2431 /**
2432 * wpas_dbus_bss_signal_prop_changed - Signals change of BSS property
2433 * @wpa_s: %wpa_supplicant network interface data
2434 * @property: indicates which property has changed
2435 * @id: unique BSS identifier
2436 *
2437 * Sends PropertyChanged signals with path, interface, and arguments depending
2438 * on which property has changed.
2439 */
wpas_dbus_bss_signal_prop_changed(struct wpa_supplicant * wpa_s,enum wpas_dbus_bss_prop property,unsigned int id)2440 void wpas_dbus_bss_signal_prop_changed(struct wpa_supplicant *wpa_s,
2441 enum wpas_dbus_bss_prop property,
2442 unsigned int id)
2443 {
2444 char path[WPAS_DBUS_OBJECT_PATH_MAX];
2445 char *prop;
2446
2447 if (!wpa_s->dbus_new_path)
2448 return;
2449
2450 switch (property) {
2451 case WPAS_DBUS_BSS_PROP_SIGNAL:
2452 prop = "Signal";
2453 break;
2454 case WPAS_DBUS_BSS_PROP_FREQ:
2455 prop = "Frequency";
2456 break;
2457 case WPAS_DBUS_BSS_PROP_MODE:
2458 prop = "Mode";
2459 break;
2460 case WPAS_DBUS_BSS_PROP_PRIVACY:
2461 prop = "Privacy";
2462 break;
2463 case WPAS_DBUS_BSS_PROP_RATES:
2464 prop = "Rates";
2465 break;
2466 case WPAS_DBUS_BSS_PROP_WPA:
2467 prop = "WPA";
2468 break;
2469 case WPAS_DBUS_BSS_PROP_RSN:
2470 prop = "RSN";
2471 break;
2472 case WPAS_DBUS_BSS_PROP_WPS:
2473 prop = "WPS";
2474 break;
2475 case WPAS_DBUS_BSS_PROP_IES:
2476 prop = "IEs";
2477 break;
2478 case WPAS_DBUS_BSS_PROP_AGE:
2479 prop = "Age";
2480 break;
2481 case WPAS_DBUS_BSS_PROP_ANQP:
2482 prop = "ANQP";
2483 break;
2484 default:
2485 wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d",
2486 __func__, property);
2487 return;
2488 }
2489
2490 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
2491 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
2492 wpa_s->dbus_new_path, id);
2493
2494 wpa_dbus_mark_property_changed(wpa_s->global->dbus, path,
2495 WPAS_DBUS_NEW_IFACE_BSS, prop);
2496 }
2497
2498
2499 /**
2500 * wpas_dbus_sta_signal_prop_changed - Signals change of STA property
2501 * @wpa_s: %wpa_supplicant network interface data
2502 * @property: indicates which property has changed
2503 * @address: unique BSS identifier
2504 *
2505 * Sends PropertyChanged signals with path, interface, and arguments depending
2506 * on which property has changed.
2507 */
wpas_dbus_sta_signal_prop_changed(struct wpa_supplicant * wpa_s,enum wpas_dbus_bss_prop property,u8 address[ETH_ALEN])2508 void wpas_dbus_sta_signal_prop_changed(struct wpa_supplicant *wpa_s,
2509 enum wpas_dbus_bss_prop property,
2510 u8 address[ETH_ALEN])
2511 {
2512 char path[WPAS_DBUS_OBJECT_PATH_MAX];
2513 char *prop;
2514
2515 switch (property) {
2516 case WPAS_DBUS_STA_PROP_ADDRESS:
2517 prop = "Address";
2518 break;
2519 default:
2520 wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d",
2521 __func__, property);
2522 return;
2523 }
2524
2525 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
2526 "%s/" WPAS_DBUS_NEW_STAS_PART "/" COMPACT_MACSTR,
2527 wpa_s->dbus_new_path, MAC2STR(address));
2528
2529 wpa_dbus_mark_property_changed(wpa_s->global->dbus, path,
2530 WPAS_DBUS_NEW_IFACE_STA, prop);
2531 }
2532
2533
2534 /**
2535 * wpas_dbus_signal_debug_level_changed - Signals change of debug param
2536 * @global: wpa_global structure
2537 *
2538 * Sends PropertyChanged signals informing that debug level has changed.
2539 */
wpas_dbus_signal_debug_level_changed(struct wpa_global * global)2540 void wpas_dbus_signal_debug_level_changed(struct wpa_global *global)
2541 {
2542 wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
2543 WPAS_DBUS_NEW_INTERFACE,
2544 "DebugLevel");
2545 }
2546
2547
2548 /**
2549 * wpas_dbus_signal_debug_timestamp_changed - Signals change of debug param
2550 * @global: wpa_global structure
2551 *
2552 * Sends PropertyChanged signals informing that debug timestamp has changed.
2553 */
wpas_dbus_signal_debug_timestamp_changed(struct wpa_global * global)2554 void wpas_dbus_signal_debug_timestamp_changed(struct wpa_global *global)
2555 {
2556 wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
2557 WPAS_DBUS_NEW_INTERFACE,
2558 "DebugTimestamp");
2559 }
2560
2561
2562 /**
2563 * wpas_dbus_signal_debug_show_keys_changed - Signals change of debug param
2564 * @global: wpa_global structure
2565 *
2566 * Sends PropertyChanged signals informing that debug show_keys has changed.
2567 */
wpas_dbus_signal_debug_show_keys_changed(struct wpa_global * global)2568 void wpas_dbus_signal_debug_show_keys_changed(struct wpa_global *global)
2569 {
2570 wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
2571 WPAS_DBUS_NEW_INTERFACE,
2572 "DebugShowKeys");
2573 }
2574
2575
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)2576 static void wpas_dbus_register(struct wpa_dbus_object_desc *obj_desc,
2577 void *priv,
2578 WPADBusArgumentFreeFunction priv_free,
2579 const struct wpa_dbus_method_desc *methods,
2580 const struct wpa_dbus_property_desc *properties,
2581 const struct wpa_dbus_signal_desc *signals)
2582 {
2583 int n;
2584
2585 obj_desc->user_data = priv;
2586 obj_desc->user_data_free_func = priv_free;
2587 obj_desc->methods = methods;
2588 obj_desc->properties = properties;
2589 obj_desc->signals = signals;
2590
2591 for (n = 0; properties && properties->dbus_property; properties++)
2592 n++;
2593
2594 obj_desc->prop_changed_flags = os_zalloc(n);
2595 if (!obj_desc->prop_changed_flags)
2596 wpa_printf(MSG_DEBUG, "dbus: %s: can't register handlers",
2597 __func__);
2598 }
2599
2600
2601 static const struct wpa_dbus_method_desc wpas_dbus_global_methods[] = {
2602 { "CreateInterface", WPAS_DBUS_NEW_INTERFACE,
2603 (WPADBusMethodHandler) wpas_dbus_handler_create_interface,
2604 {
2605 { "args", "a{sv}", ARG_IN },
2606 { "path", "o", ARG_OUT },
2607 END_ARGS
2608 }
2609 },
2610 { "RemoveInterface", WPAS_DBUS_NEW_INTERFACE,
2611 (WPADBusMethodHandler) wpas_dbus_handler_remove_interface,
2612 {
2613 { "path", "o", ARG_IN },
2614 END_ARGS
2615 }
2616 },
2617 { "GetInterface", WPAS_DBUS_NEW_INTERFACE,
2618 (WPADBusMethodHandler) wpas_dbus_handler_get_interface,
2619 {
2620 { "ifname", "s", ARG_IN },
2621 { "path", "o", ARG_OUT },
2622 END_ARGS
2623 }
2624 },
2625 { "ExpectDisconnect", WPAS_DBUS_NEW_INTERFACE,
2626 (WPADBusMethodHandler) wpas_dbus_handler_expect_disconnect,
2627 {
2628 END_ARGS
2629 }
2630 },
2631 { NULL, NULL, NULL, { END_ARGS } }
2632 };
2633
2634 static const struct wpa_dbus_property_desc wpas_dbus_global_properties[] = {
2635 { "DebugLevel", WPAS_DBUS_NEW_INTERFACE, "s",
2636 wpas_dbus_getter_debug_level,
2637 wpas_dbus_setter_debug_level,
2638 NULL
2639 },
2640 { "DebugTimestamp", WPAS_DBUS_NEW_INTERFACE, "b",
2641 wpas_dbus_getter_debug_timestamp,
2642 wpas_dbus_setter_debug_timestamp,
2643 NULL
2644 },
2645 { "DebugShowKeys", WPAS_DBUS_NEW_INTERFACE, "b",
2646 wpas_dbus_getter_debug_show_keys,
2647 wpas_dbus_setter_debug_show_keys,
2648 NULL
2649 },
2650 { "Interfaces", WPAS_DBUS_NEW_INTERFACE, "ao",
2651 wpas_dbus_getter_interfaces,
2652 NULL,
2653 NULL
2654 },
2655 { "EapMethods", WPAS_DBUS_NEW_INTERFACE, "as",
2656 wpas_dbus_getter_eap_methods,
2657 NULL,
2658 NULL
2659 },
2660 { "Capabilities", WPAS_DBUS_NEW_INTERFACE, "as",
2661 wpas_dbus_getter_global_capabilities,
2662 NULL,
2663 NULL
2664 },
2665 #ifdef CONFIG_WIFI_DISPLAY
2666 { "WFDIEs", WPAS_DBUS_NEW_INTERFACE, "ay",
2667 wpas_dbus_getter_global_wfd_ies,
2668 wpas_dbus_setter_global_wfd_ies,
2669 NULL
2670 },
2671 #endif /* CONFIG_WIFI_DISPLAY */
2672 { NULL, NULL, NULL, NULL, NULL, NULL }
2673 };
2674
2675 static const struct wpa_dbus_signal_desc wpas_dbus_global_signals[] = {
2676 { "InterfaceAdded", WPAS_DBUS_NEW_INTERFACE,
2677 {
2678 { "path", "o", ARG_OUT },
2679 { "properties", "a{sv}", ARG_OUT },
2680 END_ARGS
2681 }
2682 },
2683 { "InterfaceRemoved", WPAS_DBUS_NEW_INTERFACE,
2684 {
2685 { "path", "o", ARG_OUT },
2686 END_ARGS
2687 }
2688 },
2689 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
2690 { "PropertiesChanged", WPAS_DBUS_NEW_INTERFACE,
2691 {
2692 { "properties", "a{sv}", ARG_OUT },
2693 END_ARGS
2694 }
2695 },
2696 { NULL, NULL, { END_ARGS } }
2697 };
2698
2699
uscore_to_dbus(const char * uscore)2700 static char * uscore_to_dbus(const char *uscore)
2701 {
2702 const char *p = uscore;
2703 char *str, *s;
2704 dbus_bool_t last_was_uscore = TRUE;
2705
2706 s = str = os_zalloc(os_strlen(uscore) + 1);
2707 if (!str)
2708 return NULL;
2709 while (p && *p) {
2710 if (*p == '_') {
2711 last_was_uscore = TRUE;
2712 } else {
2713 *s++ = last_was_uscore ? toupper(*p) : *p;
2714 last_was_uscore = FALSE;
2715 }
2716 p++;
2717 }
2718
2719 return str;
2720 }
2721
2722
2723 static int wpa_dbus_ctrl_iface_props_init(struct wpas_dbus_priv *priv);
2724
2725
wpa_dbus_ctrl_iface_props_deinit(struct wpas_dbus_priv * priv)2726 static void wpa_dbus_ctrl_iface_props_deinit(struct wpas_dbus_priv *priv)
2727 {
2728 int idx = priv->globals_start;
2729
2730 /* Free all allocated property values */
2731 while (priv->all_interface_properties[idx].dbus_property)
2732 os_free((char *)
2733 priv->all_interface_properties[idx++].dbus_property);
2734 os_free((char *) priv->all_interface_properties);
2735 }
2736
2737
2738 /**
2739 * wpas_dbus_ctrl_iface_init - Initialize dbus control interface
2740 * @global: Pointer to global data from wpa_supplicant_init()
2741 * Returns: 0 on success or -1 on failure
2742 *
2743 * Initialize the dbus control interface for wpa_supplicant and start
2744 * receiving commands from external programs over the bus.
2745 */
wpas_dbus_ctrl_iface_init(struct wpas_dbus_priv * priv)2746 int wpas_dbus_ctrl_iface_init(struct wpas_dbus_priv *priv)
2747 {
2748 struct wpa_dbus_object_desc *obj_desc;
2749 int ret;
2750
2751 ret = wpa_dbus_ctrl_iface_props_init(priv);
2752 if (ret < 0) {
2753 wpa_printf(MSG_ERROR,
2754 "dbus: Not enough memory to init interface properties");
2755 return -1;
2756 }
2757
2758 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
2759 if (!obj_desc) {
2760 wpa_printf(MSG_ERROR,
2761 "Not enough memory to create object description");
2762 goto error;
2763 }
2764
2765 wpas_dbus_register(obj_desc, priv->global, NULL,
2766 wpas_dbus_global_methods,
2767 wpas_dbus_global_properties,
2768 wpas_dbus_global_signals);
2769
2770 wpa_printf(MSG_DEBUG, "dbus: Register D-Bus object '%s'",
2771 WPAS_DBUS_NEW_PATH);
2772 ret = wpa_dbus_ctrl_iface_init(priv, WPAS_DBUS_NEW_PATH,
2773 WPAS_DBUS_NEW_SERVICE,
2774 obj_desc);
2775 if (ret < 0) {
2776 free_dbus_object_desc(obj_desc);
2777 goto error;
2778 }
2779
2780 priv->dbus_new_initialized = 1;
2781 return 0;
2782
2783 error:
2784 wpa_dbus_ctrl_iface_props_deinit(priv);
2785 return -1;
2786 }
2787
2788
2789 /**
2790 * wpas_dbus_ctrl_iface_deinit - Deinitialize dbus ctrl interface for
2791 * wpa_supplicant
2792 * @priv: Pointer to dbus private data from wpas_dbus_init()
2793 *
2794 * Deinitialize the dbus control interface that was initialized with
2795 * wpas_dbus_ctrl_iface_init().
2796 */
wpas_dbus_ctrl_iface_deinit(struct wpas_dbus_priv * priv)2797 void wpas_dbus_ctrl_iface_deinit(struct wpas_dbus_priv *priv)
2798 {
2799 if (!priv->dbus_new_initialized)
2800 return;
2801 wpa_printf(MSG_DEBUG, "dbus: Unregister D-Bus object '%s'",
2802 WPAS_DBUS_NEW_PATH);
2803 dbus_connection_unregister_object_path(priv->con, WPAS_DBUS_NEW_PATH);
2804 wpa_dbus_ctrl_iface_props_deinit(priv);
2805 }
2806
2807
wpa_dbus_free(void * ptr)2808 static void wpa_dbus_free(void *ptr)
2809 {
2810 os_free(ptr);
2811 }
2812
2813
2814 static const struct wpa_dbus_property_desc wpas_dbus_network_properties[] = {
2815 { "Properties", WPAS_DBUS_NEW_IFACE_NETWORK, "a{sv}",
2816 wpas_dbus_getter_network_properties,
2817 wpas_dbus_setter_network_properties,
2818 NULL
2819 },
2820 { "Enabled", WPAS_DBUS_NEW_IFACE_NETWORK, "b",
2821 wpas_dbus_getter_enabled,
2822 wpas_dbus_setter_enabled,
2823 NULL
2824 },
2825 { NULL, NULL, NULL, NULL, NULL, NULL }
2826 };
2827
2828
2829 static const struct wpa_dbus_signal_desc wpas_dbus_network_signals[] = {
2830 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
2831 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_NETWORK,
2832 {
2833 { "properties", "a{sv}", ARG_OUT },
2834 END_ARGS
2835 }
2836 },
2837 { NULL, NULL, { END_ARGS } }
2838 };
2839
2840
2841 /**
2842 * wpas_dbus_register_network - Register a configured network with dbus
2843 * @wpa_s: wpa_supplicant interface structure
2844 * @ssid: network configuration data
2845 * Returns: 0 on success, -1 on failure
2846 *
2847 * Registers network representing object with dbus
2848 */
wpas_dbus_register_network(struct wpa_supplicant * wpa_s,struct wpa_ssid * ssid)2849 int wpas_dbus_register_network(struct wpa_supplicant *wpa_s,
2850 struct wpa_ssid *ssid)
2851 {
2852 struct wpas_dbus_priv *ctrl_iface;
2853 struct wpa_dbus_object_desc *obj_desc;
2854 struct network_handler_args *arg;
2855 char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
2856
2857 #ifdef CONFIG_P2P
2858 /*
2859 * If it is a persistent group register it as such.
2860 * This is to handle cases where an interface is being initialized
2861 * with a list of networks read from config.
2862 */
2863 if (network_is_persistent_group(ssid))
2864 return wpas_dbus_register_persistent_group(wpa_s, ssid);
2865 #endif /* CONFIG_P2P */
2866
2867 /* Do nothing if the control interface is not turned on */
2868 if (wpa_s == NULL || wpa_s->global == NULL || !wpa_s->dbus_new_path)
2869 return 0;
2870 ctrl_iface = wpa_s->global->dbus;
2871 if (ctrl_iface == NULL)
2872 return 0;
2873
2874 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2875 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
2876 wpa_s->dbus_new_path, ssid->id);
2877
2878 wpa_printf(MSG_DEBUG, "dbus: Register network object '%s'",
2879 net_obj_path);
2880 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
2881 if (!obj_desc) {
2882 wpa_printf(MSG_ERROR,
2883 "Not enough memory to create object description");
2884 goto err;
2885 }
2886
2887 /* allocate memory for handlers arguments */
2888 arg = os_zalloc(sizeof(struct network_handler_args));
2889 if (!arg) {
2890 wpa_printf(MSG_ERROR,
2891 "Not enough memory to create arguments for method");
2892 goto err;
2893 }
2894
2895 arg->wpa_s = wpa_s;
2896 arg->ssid = ssid;
2897
2898 wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
2899 wpas_dbus_network_properties,
2900 wpas_dbus_network_signals);
2901
2902 if (wpa_dbus_register_object_per_iface(ctrl_iface, net_obj_path,
2903 wpa_s->ifname, obj_desc))
2904 goto err;
2905
2906 wpas_dbus_signal_network_added(wpa_s, ssid->id);
2907
2908 return 0;
2909
2910 err:
2911 free_dbus_object_desc(obj_desc);
2912 return -1;
2913 }
2914
2915
2916 /**
2917 * wpas_dbus_unregister_network - Unregister a configured network from dbus
2918 * @wpa_s: wpa_supplicant interface structure
2919 * @nid: network id
2920 * Returns: 0 on success, -1 on failure
2921 *
2922 * Unregisters network representing object from dbus
2923 */
wpas_dbus_unregister_network(struct wpa_supplicant * wpa_s,int nid)2924 int wpas_dbus_unregister_network(struct wpa_supplicant *wpa_s, int nid)
2925 {
2926 struct wpas_dbus_priv *ctrl_iface;
2927 char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
2928 int ret;
2929 #ifdef CONFIG_P2P
2930 struct wpa_ssid *ssid;
2931
2932 ssid = wpa_config_get_network(wpa_s->conf, nid);
2933
2934 /* If it is a persistent group unregister it as such */
2935 if (ssid && network_is_persistent_group(ssid))
2936 return wpas_dbus_unregister_persistent_group(wpa_s, nid);
2937 #endif /* CONFIG_P2P */
2938
2939 /* Do nothing if the control interface is not turned on */
2940 if (wpa_s->global == NULL || wpa_s->dbus_new_path == NULL)
2941 return 0;
2942 ctrl_iface = wpa_s->global->dbus;
2943 if (ctrl_iface == NULL)
2944 return 0;
2945
2946 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2947 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
2948 wpa_s->dbus_new_path, nid);
2949
2950 wpa_printf(MSG_DEBUG, "dbus: Unregister network object '%s'",
2951 net_obj_path);
2952 ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, net_obj_path);
2953
2954 if (!ret)
2955 wpas_dbus_signal_network_removed(wpa_s, nid);
2956
2957 return ret;
2958 }
2959
2960
2961 static const struct wpa_dbus_property_desc wpas_dbus_bss_properties[] = {
2962 { "SSID", WPAS_DBUS_NEW_IFACE_BSS, "ay",
2963 wpas_dbus_getter_bss_ssid,
2964 NULL,
2965 NULL
2966 },
2967 { "BSSID", WPAS_DBUS_NEW_IFACE_BSS, "ay",
2968 wpas_dbus_getter_bss_bssid,
2969 NULL,
2970 NULL
2971 },
2972 { "Privacy", WPAS_DBUS_NEW_IFACE_BSS, "b",
2973 wpas_dbus_getter_bss_privacy,
2974 NULL,
2975 NULL
2976 },
2977 { "Mode", WPAS_DBUS_NEW_IFACE_BSS, "s",
2978 wpas_dbus_getter_bss_mode,
2979 NULL,
2980 NULL
2981 },
2982 { "Signal", WPAS_DBUS_NEW_IFACE_BSS, "n",
2983 wpas_dbus_getter_bss_signal,
2984 NULL,
2985 NULL
2986 },
2987 { "Frequency", WPAS_DBUS_NEW_IFACE_BSS, "q",
2988 wpas_dbus_getter_bss_frequency,
2989 NULL,
2990 NULL
2991 },
2992 { "Rates", WPAS_DBUS_NEW_IFACE_BSS, "au",
2993 wpas_dbus_getter_bss_rates,
2994 NULL,
2995 NULL
2996 },
2997 { "WPA", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
2998 wpas_dbus_getter_bss_wpa,
2999 NULL,
3000 NULL
3001 },
3002 { "RSN", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
3003 wpas_dbus_getter_bss_rsn,
3004 NULL,
3005 NULL
3006 },
3007 { "WPS", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
3008 wpas_dbus_getter_bss_wps,
3009 NULL,
3010 NULL
3011 },
3012 { "IEs", WPAS_DBUS_NEW_IFACE_BSS, "ay",
3013 wpas_dbus_getter_bss_ies,
3014 NULL,
3015 NULL
3016 },
3017 { "Age", WPAS_DBUS_NEW_IFACE_BSS, "u",
3018 wpas_dbus_getter_bss_age,
3019 NULL,
3020 NULL
3021 },
3022 {"ANQP", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
3023 wpas_dbus_getter_bss_anqp,
3024 NULL,
3025 NULL,
3026 },
3027 { NULL, NULL, NULL, NULL, NULL, NULL }
3028 };
3029
3030
3031 static const struct wpa_dbus_signal_desc wpas_dbus_bss_signals[] = {
3032 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
3033 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_BSS,
3034 {
3035 { "properties", "a{sv}", ARG_OUT },
3036 END_ARGS
3037 }
3038 },
3039 { NULL, NULL, { END_ARGS } }
3040 };
3041
3042
3043 /**
3044 * wpas_dbus_unregister_bss - Unregister a scanned BSS from dbus
3045 * @wpa_s: wpa_supplicant interface structure
3046 * @bssid: scanned network bssid
3047 * @id: unique BSS identifier
3048 * Returns: 0 on success, -1 on failure
3049 *
3050 * Unregisters BSS representing object from dbus
3051 */
wpas_dbus_unregister_bss(struct wpa_supplicant * wpa_s,u8 bssid[ETH_ALEN],unsigned int id)3052 int wpas_dbus_unregister_bss(struct wpa_supplicant *wpa_s,
3053 u8 bssid[ETH_ALEN], unsigned int id)
3054 {
3055 struct wpas_dbus_priv *ctrl_iface;
3056 char bss_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3057
3058 /* Do nothing if the control interface is not turned on */
3059 if (wpa_s == NULL || wpa_s->global == NULL || !wpa_s->dbus_new_path)
3060 return 0;
3061 ctrl_iface = wpa_s->global->dbus;
3062 if (ctrl_iface == NULL)
3063 return 0;
3064
3065 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3066 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
3067 wpa_s->dbus_new_path, id);
3068
3069 wpa_printf(MSG_DEBUG, "dbus: Unregister BSS object '%s'",
3070 bss_obj_path);
3071 if (wpa_dbus_unregister_object_per_iface(ctrl_iface, bss_obj_path)) {
3072 wpa_printf(MSG_ERROR, "dbus: Cannot unregister BSS object %s",
3073 bss_obj_path);
3074 return -1;
3075 }
3076
3077 wpas_dbus_signal_bss_removed(wpa_s, bss_obj_path);
3078 wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_BSSS);
3079
3080 return 0;
3081 }
3082
3083
3084 /**
3085 * wpas_dbus_register_bss - Register a scanned BSS with dbus
3086 * @wpa_s: wpa_supplicant interface structure
3087 * @bssid: scanned network bssid
3088 * @id: unique BSS identifier
3089 * Returns: 0 on success, -1 on failure
3090 *
3091 * Registers BSS representing object with dbus
3092 */
wpas_dbus_register_bss(struct wpa_supplicant * wpa_s,u8 bssid[ETH_ALEN],unsigned int id)3093 int wpas_dbus_register_bss(struct wpa_supplicant *wpa_s,
3094 u8 bssid[ETH_ALEN], unsigned int id)
3095 {
3096 struct wpas_dbus_priv *ctrl_iface;
3097 struct wpa_dbus_object_desc *obj_desc;
3098 char bss_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3099 struct bss_handler_args *arg;
3100
3101 /* Do nothing if the control interface is not turned on */
3102 if (wpa_s == NULL || wpa_s->global == NULL || !wpa_s->dbus_new_path)
3103 return 0;
3104 ctrl_iface = wpa_s->global->dbus;
3105 if (ctrl_iface == NULL)
3106 return 0;
3107
3108 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3109 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
3110 wpa_s->dbus_new_path, id);
3111
3112 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
3113 if (!obj_desc) {
3114 wpa_printf(MSG_ERROR,
3115 "Not enough memory to create object description");
3116 goto err;
3117 }
3118
3119 arg = os_zalloc(sizeof(struct bss_handler_args));
3120 if (!arg) {
3121 wpa_printf(MSG_ERROR,
3122 "Not enough memory to create arguments for handler");
3123 goto err;
3124 }
3125 arg->wpa_s = wpa_s;
3126 arg->id = id;
3127
3128 wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
3129 wpas_dbus_bss_properties,
3130 wpas_dbus_bss_signals);
3131
3132 wpa_printf(MSG_DEBUG, "dbus: Register BSS object '%s'",
3133 bss_obj_path);
3134 if (wpa_dbus_register_object_per_iface(ctrl_iface, bss_obj_path,
3135 wpa_s->ifname, obj_desc)) {
3136 wpa_printf(MSG_ERROR,
3137 "Cannot register BSSID dbus object %s.",
3138 bss_obj_path);
3139 goto err;
3140 }
3141
3142 wpas_dbus_signal_bss_added(wpa_s, bss_obj_path);
3143 wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_BSSS);
3144
3145 return 0;
3146
3147 err:
3148 free_dbus_object_desc(obj_desc);
3149 return -1;
3150 }
3151
3152
3153 static const struct wpa_dbus_property_desc wpas_dbus_sta_properties[] = {
3154 { "Address", WPAS_DBUS_NEW_IFACE_STA, "ay",
3155 wpas_dbus_getter_sta_address,
3156 NULL, NULL
3157 },
3158 { "AID", WPAS_DBUS_NEW_IFACE_STA, "q",
3159 wpas_dbus_getter_sta_aid,
3160 NULL, NULL
3161 },
3162 { "Capabilities", WPAS_DBUS_NEW_IFACE_STA, "q",
3163 wpas_dbus_getter_sta_caps,
3164 NULL, NULL
3165 },
3166 { "RxPackets", WPAS_DBUS_NEW_IFACE_STA, "t",
3167 wpas_dbus_getter_sta_rx_packets,
3168 NULL, NULL
3169 },
3170 { "TxPackets", WPAS_DBUS_NEW_IFACE_STA, "t",
3171 wpas_dbus_getter_sta_tx_packets,
3172 NULL, NULL
3173 },
3174 { "RxBytes", WPAS_DBUS_NEW_IFACE_STA, "t",
3175 wpas_dbus_getter_sta_rx_bytes,
3176 NULL, NULL
3177 },
3178 { "TxBytes", WPAS_DBUS_NEW_IFACE_STA, "t",
3179 wpas_dbus_getter_sta_tx_bytes,
3180 NULL, NULL
3181 },
3182 { NULL, NULL, NULL, NULL, NULL, NULL }
3183 };
3184
3185
3186 static const struct wpa_dbus_signal_desc wpas_dbus_sta_signals[] = {
3187 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
3188 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_STA,
3189 {
3190 { "properties", "a{sv}", ARG_OUT },
3191 END_ARGS
3192 }
3193 },
3194 { NULL, NULL, { END_ARGS } }
3195 };
3196
3197
3198 /**
3199 * wpas_dbus_unregister_sta - Unregister a connected station from dbus
3200 * @wpa_s: wpa_supplicant interface structure
3201 * @sta: station MAC address
3202 * Returns: 0 on success, -1 on failure
3203 *
3204 * Unregisters STA representing object from dbus.
3205 */
wpas_dbus_unregister_sta(struct wpa_supplicant * wpa_s,const u8 * sta)3206 int wpas_dbus_unregister_sta(struct wpa_supplicant *wpa_s, const u8 *sta)
3207 {
3208 struct wpas_dbus_priv *ctrl_iface;
3209 char station_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3210
3211 /* Do nothing if the control interface is not turned on */
3212 if (!wpa_s || !wpa_s->global)
3213 return 0;
3214 ctrl_iface = wpa_s->global->dbus;
3215 if (!ctrl_iface)
3216 return 0;
3217
3218 os_snprintf(station_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3219 "%s/" WPAS_DBUS_NEW_STAS_PART "/" COMPACT_MACSTR,
3220 wpa_s->dbus_new_path, MAC2STR(sta));
3221
3222 wpa_printf(MSG_DEBUG, "dbus: Unregister STA object '%s'",
3223 station_obj_path);
3224 if (wpa_dbus_unregister_object_per_iface(ctrl_iface,
3225 station_obj_path)) {
3226 wpa_printf(MSG_ERROR, "dbus: Cannot unregister STA object %s",
3227 station_obj_path);
3228 return -1;
3229 }
3230
3231 wpas_dbus_signal_station_removed(wpa_s, station_obj_path);
3232 wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_STATIONS);
3233
3234 return 0;
3235 }
3236
3237
3238 /**
3239 * wpas_dbus_register_sta - Register a connected station with dbus
3240 * @wpa_s: wpa_supplicant interface structure
3241 * @sta: station MAC address
3242 * Returns: 0 on success, -1 on failure
3243 *
3244 * Registers STA representing object with dbus.
3245 */
wpas_dbus_register_sta(struct wpa_supplicant * wpa_s,const u8 * sta)3246 int wpas_dbus_register_sta(struct wpa_supplicant *wpa_s, const u8 *sta)
3247 {
3248 struct wpas_dbus_priv *ctrl_iface;
3249 struct wpa_dbus_object_desc *obj_desc;
3250 char station_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3251 struct sta_handler_args *arg;
3252
3253 /* Do nothing if the control interface is not turned on */
3254 if (!wpa_s || !wpa_s->global)
3255 return 0;
3256 ctrl_iface = wpa_s->global->dbus;
3257 if (!ctrl_iface)
3258 return 0;
3259
3260 os_snprintf(station_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3261 "%s/" WPAS_DBUS_NEW_STAS_PART "/" COMPACT_MACSTR,
3262 wpa_s->dbus_new_path, MAC2STR(sta));
3263
3264 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
3265 if (!obj_desc) {
3266 wpa_printf(MSG_ERROR,
3267 "Not enough memory to create object description");
3268 goto err;
3269 }
3270
3271 arg = os_zalloc(sizeof(struct sta_handler_args));
3272 if (!arg) {
3273 wpa_printf(MSG_ERROR,
3274 "Not enough memory to create arguments for handler");
3275 goto err;
3276 }
3277 arg->wpa_s = wpa_s;
3278 arg->sta = sta;
3279
3280 wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
3281 wpas_dbus_sta_properties, wpas_dbus_sta_signals);
3282
3283 wpa_printf(MSG_DEBUG, "dbus: Register STA object '%s'",
3284 station_obj_path);
3285 if (wpa_dbus_register_object_per_iface(ctrl_iface, station_obj_path,
3286 wpa_s->ifname, obj_desc)) {
3287 wpa_printf(MSG_ERROR,
3288 "Cannot register STA dbus object %s",
3289 station_obj_path);
3290 goto err;
3291 }
3292
3293 wpas_dbus_signal_station_added(wpa_s, station_obj_path);
3294 wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_STATIONS);
3295
3296 return 0;
3297
3298 err:
3299 free_dbus_object_desc(obj_desc);
3300 return -1;
3301 }
3302
3303
3304 static const struct wpa_dbus_method_desc wpas_dbus_interface_methods[] = {
3305 { "Scan", WPAS_DBUS_NEW_IFACE_INTERFACE,
3306 (WPADBusMethodHandler) wpas_dbus_handler_scan,
3307 {
3308 { "args", "a{sv}", ARG_IN },
3309 END_ARGS
3310 }
3311 },
3312 { "SignalPoll", WPAS_DBUS_NEW_IFACE_INTERFACE,
3313 (WPADBusMethodHandler) wpas_dbus_handler_signal_poll,
3314 {
3315 { "args", "a{sv}", ARG_OUT },
3316 END_ARGS
3317 }
3318 },
3319 { "Disconnect", WPAS_DBUS_NEW_IFACE_INTERFACE,
3320 (WPADBusMethodHandler) wpas_dbus_handler_disconnect,
3321 {
3322 END_ARGS
3323 }
3324 },
3325 { "AddNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
3326 (WPADBusMethodHandler) wpas_dbus_handler_add_network,
3327 {
3328 { "args", "a{sv}", ARG_IN },
3329 { "path", "o", ARG_OUT },
3330 END_ARGS
3331 }
3332 },
3333 { "Reassociate", WPAS_DBUS_NEW_IFACE_INTERFACE,
3334 (WPADBusMethodHandler) wpas_dbus_handler_reassociate,
3335 {
3336 END_ARGS
3337 }
3338 },
3339 { "Reattach", WPAS_DBUS_NEW_IFACE_INTERFACE,
3340 (WPADBusMethodHandler) wpas_dbus_handler_reattach,
3341 {
3342 END_ARGS
3343 }
3344 },
3345 { "Reconnect", WPAS_DBUS_NEW_IFACE_INTERFACE,
3346 (WPADBusMethodHandler) wpas_dbus_handler_reconnect,
3347 {
3348 END_ARGS
3349 }
3350 },
3351 { "RemoveNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
3352 (WPADBusMethodHandler) wpas_dbus_handler_remove_network,
3353 {
3354 { "path", "o", ARG_IN },
3355 END_ARGS
3356 }
3357 },
3358 { "RemoveAllNetworks", WPAS_DBUS_NEW_IFACE_INTERFACE,
3359 (WPADBusMethodHandler) wpas_dbus_handler_remove_all_networks,
3360 {
3361 END_ARGS
3362 }
3363 },
3364 { "SelectNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
3365 (WPADBusMethodHandler) wpas_dbus_handler_select_network,
3366 {
3367 { "path", "o", ARG_IN },
3368 END_ARGS
3369 }
3370 },
3371 { "NetworkReply", WPAS_DBUS_NEW_IFACE_INTERFACE,
3372 (WPADBusMethodHandler) wpas_dbus_handler_network_reply,
3373 {
3374 { "path", "o", ARG_IN },
3375 { "field", "s", ARG_IN },
3376 { "value", "s", ARG_IN },
3377 END_ARGS
3378 }
3379 },
3380 { "Roam", WPAS_DBUS_NEW_IFACE_INTERFACE,
3381 (WPADBusMethodHandler) wpas_dbus_handler_roam,
3382 {
3383 { "addr", "s", ARG_IN },
3384 END_ARGS
3385 }
3386 },
3387
3388 #ifndef CONFIG_NO_CONFIG_BLOBS
3389 { "AddBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
3390 (WPADBusMethodHandler) wpas_dbus_handler_add_blob,
3391 {
3392 { "name", "s", ARG_IN },
3393 { "data", "ay", ARG_IN },
3394 END_ARGS
3395 }
3396 },
3397 { "GetBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
3398 (WPADBusMethodHandler) wpas_dbus_handler_get_blob,
3399 {
3400 { "name", "s", ARG_IN },
3401 { "data", "ay", ARG_OUT },
3402 END_ARGS
3403 }
3404 },
3405 { "RemoveBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
3406 (WPADBusMethodHandler) wpas_dbus_handler_remove_blob,
3407 {
3408 { "name", "s", ARG_IN },
3409 END_ARGS
3410 }
3411 },
3412 #endif /* CONFIG_NO_CONFIG_BLOBS */
3413 { "SetPKCS11EngineAndModulePath", WPAS_DBUS_NEW_IFACE_INTERFACE,
3414 (WPADBusMethodHandler)
3415 wpas_dbus_handler_set_pkcs11_engine_and_module_path,
3416 {
3417 { "pkcs11_engine_path", "s", ARG_IN },
3418 { "pkcs11_module_path", "s", ARG_IN },
3419 END_ARGS
3420 }
3421 },
3422 #ifdef CONFIG_WPS
3423 { "Start", WPAS_DBUS_NEW_IFACE_WPS,
3424 (WPADBusMethodHandler) wpas_dbus_handler_wps_start,
3425 {
3426 { "args", "a{sv}", ARG_IN },
3427 { "output", "a{sv}", ARG_OUT },
3428 END_ARGS
3429 }
3430 },
3431 { "Cancel", WPAS_DBUS_NEW_IFACE_WPS,
3432 (WPADBusMethodHandler) wpas_dbus_handler_wps_cancel,
3433 {
3434 END_ARGS
3435 }
3436 },
3437 #endif /* CONFIG_WPS */
3438 #ifdef CONFIG_P2P
3439 { "Find", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3440 (WPADBusMethodHandler) wpas_dbus_handler_p2p_find,
3441 {
3442 { "args", "a{sv}", ARG_IN },
3443 END_ARGS
3444 }
3445 },
3446 { "StopFind", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3447 (WPADBusMethodHandler) wpas_dbus_handler_p2p_stop_find,
3448 {
3449 END_ARGS
3450 }
3451 },
3452 { "Listen", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3453 (WPADBusMethodHandler) wpas_dbus_handler_p2p_listen,
3454 {
3455 { "timeout", "i", ARG_IN },
3456 END_ARGS
3457 }
3458 },
3459 { "ExtendedListen", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3460 (WPADBusMethodHandler) wpas_dbus_handler_p2p_extendedlisten,
3461 {
3462 { "args", "a{sv}", ARG_IN },
3463 END_ARGS
3464 }
3465 },
3466 { "PresenceRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3467 (WPADBusMethodHandler) wpas_dbus_handler_p2p_presence_request,
3468 {
3469 { "args", "a{sv}", ARG_IN },
3470 END_ARGS
3471 }
3472 },
3473 { "ProvisionDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3474 (WPADBusMethodHandler) wpas_dbus_handler_p2p_prov_disc_req,
3475 {
3476 { "peer", "o", ARG_IN },
3477 { "config_method", "s", ARG_IN },
3478 END_ARGS
3479 }
3480 },
3481 { "Connect", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3482 (WPADBusMethodHandler) wpas_dbus_handler_p2p_connect,
3483 {
3484 { "args", "a{sv}", ARG_IN },
3485 { "generated_pin", "s", ARG_OUT },
3486 END_ARGS
3487 }
3488 },
3489 { "GroupAdd", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3490 (WPADBusMethodHandler) wpas_dbus_handler_p2p_group_add,
3491 {
3492 { "args", "a{sv}", ARG_IN },
3493 END_ARGS
3494 }
3495 },
3496 { "Cancel", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3497 (WPADBusMethodHandler) wpas_dbus_handler_p2p_cancel,
3498 {
3499 END_ARGS
3500 }
3501 },
3502 { "Invite", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3503 (WPADBusMethodHandler) wpas_dbus_handler_p2p_invite,
3504 {
3505 { "args", "a{sv}", ARG_IN },
3506 END_ARGS
3507 }
3508 },
3509 { "Disconnect", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3510 (WPADBusMethodHandler) wpas_dbus_handler_p2p_disconnect,
3511 {
3512 END_ARGS
3513 }
3514 },
3515 { "RejectPeer", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3516 (WPADBusMethodHandler) wpas_dbus_handler_p2p_rejectpeer,
3517 {
3518 { "peer", "o", ARG_IN },
3519 END_ARGS
3520 }
3521 },
3522 { "RemoveClient", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3523 (WPADBusMethodHandler) wpas_dbus_handler_p2p_remove_client,
3524 {
3525 { "args", "a{sv}", ARG_IN },
3526 END_ARGS
3527 }
3528 },
3529 { "Flush", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3530 (WPADBusMethodHandler) wpas_dbus_handler_p2p_flush,
3531 {
3532 END_ARGS
3533 }
3534 },
3535 { "AddService", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3536 (WPADBusMethodHandler) wpas_dbus_handler_p2p_add_service,
3537 {
3538 { "args", "a{sv}", ARG_IN },
3539 END_ARGS
3540 }
3541 },
3542 { "DeleteService", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3543 (WPADBusMethodHandler) wpas_dbus_handler_p2p_delete_service,
3544 {
3545 { "args", "a{sv}", ARG_IN },
3546 END_ARGS
3547 }
3548 },
3549 { "FlushService", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3550 (WPADBusMethodHandler) wpas_dbus_handler_p2p_flush_service,
3551 {
3552 END_ARGS
3553 }
3554 },
3555 { "ServiceDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3556 (WPADBusMethodHandler) wpas_dbus_handler_p2p_service_sd_req,
3557 {
3558 { "args", "a{sv}", ARG_IN },
3559 { "ref", "t", ARG_OUT },
3560 END_ARGS
3561 }
3562 },
3563 { "ServiceDiscoveryResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3564 (WPADBusMethodHandler) wpas_dbus_handler_p2p_service_sd_res,
3565 {
3566 { "args", "a{sv}", ARG_IN },
3567 END_ARGS
3568 }
3569 },
3570 { "ServiceDiscoveryCancelRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3571 (WPADBusMethodHandler) wpas_dbus_handler_p2p_service_sd_cancel_req,
3572 {
3573 { "args", "t", ARG_IN },
3574 END_ARGS
3575 }
3576 },
3577 { "ServiceUpdate", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3578 (WPADBusMethodHandler) wpas_dbus_handler_p2p_service_update,
3579 {
3580 END_ARGS
3581 }
3582 },
3583 { "ServiceDiscoveryExternal", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3584 (WPADBusMethodHandler) wpas_dbus_handler_p2p_serv_disc_external,
3585 {
3586 { "arg", "i", ARG_IN },
3587 END_ARGS
3588 }
3589 },
3590 { "AddPersistentGroup", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3591 (WPADBusMethodHandler) wpas_dbus_handler_add_persistent_group,
3592 {
3593 { "args", "a{sv}", ARG_IN },
3594 { "path", "o", ARG_OUT },
3595 END_ARGS
3596 }
3597 },
3598 { "RemovePersistentGroup", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3599 (WPADBusMethodHandler) wpas_dbus_handler_remove_persistent_group,
3600 {
3601 { "path", "o", ARG_IN },
3602 END_ARGS
3603 }
3604 },
3605 { "RemoveAllPersistentGroups", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3606 (WPADBusMethodHandler)
3607 wpas_dbus_handler_remove_all_persistent_groups,
3608 {
3609 END_ARGS
3610 }
3611 },
3612 #endif /* CONFIG_P2P */
3613 { "FlushBSS", WPAS_DBUS_NEW_IFACE_INTERFACE,
3614 (WPADBusMethodHandler) wpas_dbus_handler_flush_bss,
3615 {
3616 { "age", "u", ARG_IN },
3617 END_ARGS
3618 }
3619 },
3620 #ifdef CONFIG_AP
3621 { "SubscribeProbeReq", WPAS_DBUS_NEW_IFACE_INTERFACE,
3622 (WPADBusMethodHandler) wpas_dbus_handler_subscribe_preq,
3623 {
3624 END_ARGS
3625 }
3626 },
3627 { "UnsubscribeProbeReq", WPAS_DBUS_NEW_IFACE_INTERFACE,
3628 (WPADBusMethodHandler) wpas_dbus_handler_unsubscribe_preq,
3629 {
3630 END_ARGS
3631 }
3632 },
3633 #endif /* CONFIG_AP */
3634 { "EAPLogoff", WPAS_DBUS_NEW_IFACE_INTERFACE,
3635 (WPADBusMethodHandler) wpas_dbus_handler_eap_logoff,
3636 {
3637 END_ARGS
3638 }
3639 },
3640 { "EAPLogon", WPAS_DBUS_NEW_IFACE_INTERFACE,
3641 (WPADBusMethodHandler) wpas_dbus_handler_eap_logon,
3642 {
3643 END_ARGS
3644 }
3645 },
3646 #ifdef CONFIG_AUTOSCAN
3647 { "AutoScan", WPAS_DBUS_NEW_IFACE_INTERFACE,
3648 (WPADBusMethodHandler) wpas_dbus_handler_autoscan,
3649 {
3650 { "arg", "s", ARG_IN },
3651 END_ARGS
3652 }
3653 },
3654 #endif /* CONFIG_AUTOSCAN */
3655 #ifdef CONFIG_TDLS
3656 { "TDLSDiscover", WPAS_DBUS_NEW_IFACE_INTERFACE,
3657 (WPADBusMethodHandler) wpas_dbus_handler_tdls_discover,
3658 {
3659 { "peer_address", "s", ARG_IN },
3660 END_ARGS
3661 }
3662 },
3663 { "TDLSSetup", WPAS_DBUS_NEW_IFACE_INTERFACE,
3664 (WPADBusMethodHandler) wpas_dbus_handler_tdls_setup,
3665 {
3666 { "peer_address", "s", ARG_IN },
3667 END_ARGS
3668 }
3669 },
3670 { "TDLSStatus", WPAS_DBUS_NEW_IFACE_INTERFACE,
3671 (WPADBusMethodHandler) wpas_dbus_handler_tdls_status,
3672 {
3673 { "peer_address", "s", ARG_IN },
3674 { "status", "s", ARG_OUT },
3675 END_ARGS
3676 }
3677 },
3678 { "TDLSTeardown", WPAS_DBUS_NEW_IFACE_INTERFACE,
3679 (WPADBusMethodHandler) wpas_dbus_handler_tdls_teardown,
3680 {
3681 { "peer_address", "s", ARG_IN },
3682 END_ARGS
3683 }
3684 },
3685 { "TDLSChannelSwitch", WPAS_DBUS_NEW_IFACE_INTERFACE,
3686 (WPADBusMethodHandler) wpas_dbus_handler_tdls_channel_switch,
3687 {
3688 { "args", "a{sv}", ARG_IN },
3689 END_ARGS
3690 }
3691 },
3692 { "TDLSCancelChannelSwitch", WPAS_DBUS_NEW_IFACE_INTERFACE,
3693 (WPADBusMethodHandler) wpas_dbus_handler_tdls_cancel_channel_switch,
3694 {
3695 { "peer_address", "s", ARG_IN },
3696 END_ARGS
3697 }
3698 },
3699 #endif /* CONFIG_TDLS */
3700 { "VendorElemAdd", WPAS_DBUS_NEW_IFACE_INTERFACE,
3701 (WPADBusMethodHandler) wpas_dbus_handler_vendor_elem_add,
3702 {
3703 { "frame_id", "i", ARG_IN },
3704 { "ielems", "ay", ARG_IN },
3705 END_ARGS
3706 }
3707 },
3708 { "VendorElemGet", WPAS_DBUS_NEW_IFACE_INTERFACE,
3709 (WPADBusMethodHandler) wpas_dbus_handler_vendor_elem_get,
3710 {
3711 { "frame_id", "i", ARG_IN },
3712 { "ielems", "ay", ARG_OUT },
3713 END_ARGS
3714 }
3715 },
3716 { "VendorElemRem", WPAS_DBUS_NEW_IFACE_INTERFACE,
3717 (WPADBusMethodHandler) wpas_dbus_handler_vendor_elem_remove,
3718 {
3719 { "frame_id", "i", ARG_IN },
3720 { "ielems", "ay", ARG_IN },
3721 END_ARGS
3722 }
3723 },
3724 #ifndef CONFIG_NO_CONFIG_WRITE
3725 { "SaveConfig", WPAS_DBUS_NEW_IFACE_INTERFACE,
3726 (WPADBusMethodHandler) wpas_dbus_handler_save_config,
3727 {
3728 END_ARGS
3729 }
3730 },
3731 #endif /* CONFIG_NO_CONFIG_WRITE */
3732 { "AbortScan", WPAS_DBUS_NEW_IFACE_INTERFACE,
3733 (WPADBusMethodHandler) wpas_dbus_handler_abort_scan,
3734 {
3735 END_ARGS
3736 }
3737 },
3738 #ifdef CONFIG_INTERWORKING
3739 { "AddCred", WPAS_DBUS_NEW_IFACE_INTERFACE,
3740 (WPADBusMethodHandler) wpas_dbus_handler_add_cred,
3741 {
3742 { "args", "a{sv}", ARG_IN },
3743 { "path", "o", ARG_OUT },
3744 END_ARGS
3745 }
3746 },
3747 { "RemoveCred", WPAS_DBUS_NEW_IFACE_INTERFACE,
3748 (WPADBusMethodHandler) wpas_dbus_handler_remove_cred,
3749 {
3750 { "path", "o", ARG_IN },
3751 END_ARGS
3752 }
3753 },
3754 { "RemoveAllCreds", WPAS_DBUS_NEW_IFACE_INTERFACE,
3755 (WPADBusMethodHandler) wpas_dbus_handler_remove_all_creds,
3756 {
3757 END_ARGS
3758 }
3759 },
3760 { "InterworkingSelect", WPAS_DBUS_NEW_IFACE_INTERFACE,
3761 (WPADBusMethodHandler) wpas_dbus_handler_interworking_select,
3762 {
3763 END_ARGS
3764 }
3765 },
3766 {"ANQPGet", WPAS_DBUS_NEW_IFACE_INTERFACE,
3767 (WPADBusMethodHandler) wpas_dbus_handler_anqp_get,
3768 {
3769 { "args", "a{sv}", ARG_IN },
3770 END_ARGS
3771 },
3772 },
3773 #endif /* CONFIG_INTERWORKING */
3774 { NULL, NULL, NULL, { END_ARGS } }
3775 };
3776
3777 static const struct wpa_dbus_property_desc wpas_dbus_interface_properties[] = {
3778 { "Capabilities", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{sv}",
3779 wpas_dbus_getter_capabilities,
3780 NULL,
3781 NULL
3782 },
3783 { "State", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3784 wpas_dbus_getter_state,
3785 NULL,
3786 NULL
3787 },
3788 { "Scanning", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
3789 wpas_dbus_getter_scanning,
3790 NULL,
3791 NULL
3792 },
3793 { "ApScan", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
3794 wpas_dbus_getter_ap_scan,
3795 wpas_dbus_setter_ap_scan,
3796 NULL
3797 },
3798 { "BSSExpireAge", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
3799 wpas_dbus_getter_bss_expire_age,
3800 wpas_dbus_setter_bss_expire_age,
3801 NULL
3802 },
3803 { "BSSExpireCount", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
3804 wpas_dbus_getter_bss_expire_count,
3805 wpas_dbus_setter_bss_expire_count,
3806 NULL
3807 },
3808 { "Country", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3809 wpas_dbus_getter_country,
3810 wpas_dbus_setter_country,
3811 NULL
3812 },
3813 { "Ifname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3814 wpas_dbus_getter_ifname,
3815 NULL,
3816 NULL
3817 },
3818 { "Driver", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3819 wpas_dbus_getter_driver,
3820 NULL,
3821 NULL
3822 },
3823 { "BridgeIfname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3824 wpas_dbus_getter_bridge_ifname,
3825 wpas_dbus_setter_bridge_ifname,
3826 NULL
3827 },
3828 { "ConfigFile", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3829 wpas_dbus_getter_config_file,
3830 NULL,
3831 NULL
3832 },
3833 { "CurrentBSS", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
3834 wpas_dbus_getter_current_bss,
3835 NULL,
3836 NULL
3837 },
3838 { "CurrentNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
3839 wpas_dbus_getter_current_network,
3840 NULL,
3841 NULL
3842 },
3843 { "CurrentAuthMode", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3844 wpas_dbus_getter_current_auth_mode,
3845 NULL,
3846 NULL
3847 },
3848 { "Blobs", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{say}",
3849 wpas_dbus_getter_blobs,
3850 NULL,
3851 NULL
3852 },
3853 { "BSSs", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
3854 wpas_dbus_getter_bsss,
3855 NULL,
3856 NULL
3857 },
3858 { "Networks", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
3859 wpas_dbus_getter_networks,
3860 NULL,
3861 NULL
3862 },
3863 { "FastReauth", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
3864 wpas_dbus_getter_fast_reauth,
3865 wpas_dbus_setter_fast_reauth,
3866 NULL
3867 },
3868 { "ScanInterval", WPAS_DBUS_NEW_IFACE_INTERFACE, "i",
3869 wpas_dbus_getter_scan_interval,
3870 wpas_dbus_setter_scan_interval,
3871 NULL
3872 },
3873 { "PKCS11EnginePath", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3874 wpas_dbus_getter_pkcs11_engine_path,
3875 NULL,
3876 NULL
3877 },
3878 { "PKCS11ModulePath", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3879 wpas_dbus_getter_pkcs11_module_path,
3880 NULL,
3881 NULL
3882 },
3883 #ifdef CONFIG_WPS
3884 { "ProcessCredentials", WPAS_DBUS_NEW_IFACE_WPS, "b",
3885 wpas_dbus_getter_process_credentials,
3886 wpas_dbus_setter_process_credentials,
3887 NULL
3888 },
3889 { "ConfigMethods", WPAS_DBUS_NEW_IFACE_WPS, "s",
3890 wpas_dbus_getter_config_methods,
3891 wpas_dbus_setter_config_methods,
3892 NULL
3893 },
3894 {
3895 "DeviceName", WPAS_DBUS_NEW_IFACE_WPS, "s",
3896 wpas_dbus_getter_wps_device_name,
3897 wpas_dbus_setter_wps_device_name,
3898 NULL
3899 },
3900 {
3901 "Manufacturer", WPAS_DBUS_NEW_IFACE_WPS, "s",
3902 wpas_dbus_getter_wps_manufacturer,
3903 wpas_dbus_setter_wps_manufacturer,
3904 NULL
3905 },
3906 {
3907 "ModelName", WPAS_DBUS_NEW_IFACE_WPS, "s",
3908 wpas_dbus_getter_wps_device_model_name,
3909 wpas_dbus_setter_wps_device_model_name,
3910 NULL
3911 },
3912 {
3913 "ModelNumber", WPAS_DBUS_NEW_IFACE_WPS, "s",
3914 wpas_dbus_getter_wps_device_model_number,
3915 wpas_dbus_setter_wps_device_model_number,
3916 NULL
3917 },
3918 {
3919 "SerialNumber", WPAS_DBUS_NEW_IFACE_WPS, "s",
3920 wpas_dbus_getter_wps_device_serial_number,
3921 wpas_dbus_setter_wps_device_serial_number,
3922 NULL
3923 },
3924 {
3925 "DeviceType", WPAS_DBUS_NEW_IFACE_WPS, "ay",
3926 wpas_dbus_getter_wps_device_device_type,
3927 wpas_dbus_setter_wps_device_device_type,
3928 NULL
3929 },
3930 #endif /* CONFIG_WPS */
3931 #ifdef CONFIG_P2P
3932 { "P2PDeviceConfig", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "a{sv}",
3933 wpas_dbus_getter_p2p_device_config,
3934 wpas_dbus_setter_p2p_device_config,
3935 NULL
3936 },
3937 { "Peers", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "ao",
3938 wpas_dbus_getter_p2p_peers,
3939 NULL,
3940 NULL
3941 },
3942 { "Role", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "s",
3943 wpas_dbus_getter_p2p_role,
3944 NULL,
3945 NULL
3946 },
3947 { "Group", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "o",
3948 wpas_dbus_getter_p2p_group,
3949 NULL,
3950 NULL
3951 },
3952 { "PeerGO", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "o",
3953 wpas_dbus_getter_p2p_peergo,
3954 NULL,
3955 NULL
3956 },
3957 { "PersistentGroups", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "ao",
3958 wpas_dbus_getter_persistent_groups,
3959 NULL,
3960 NULL
3961 },
3962 #endif /* CONFIG_P2P */
3963 { "DisconnectReason", WPAS_DBUS_NEW_IFACE_INTERFACE, "i",
3964 wpas_dbus_getter_disconnect_reason,
3965 NULL,
3966 NULL
3967 },
3968 { "AuthStatusCode", WPAS_DBUS_NEW_IFACE_INTERFACE, "i",
3969 wpas_dbus_getter_auth_status_code,
3970 NULL,
3971 NULL
3972 },
3973 { "AssocStatusCode", WPAS_DBUS_NEW_IFACE_INTERFACE, "i",
3974 wpas_dbus_getter_assoc_status_code,
3975 NULL,
3976 NULL
3977 },
3978 {
3979 "RoamTime", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
3980 wpas_dbus_getter_roam_time,
3981 NULL,
3982 NULL
3983 },
3984 {
3985 "RoamComplete", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
3986 wpas_dbus_getter_roam_complete,
3987 NULL,
3988 NULL
3989 },
3990 {
3991 "ScanInProgress6GHz", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
3992 wpas_dbus_getter_scan_in_progress_6ghz,
3993 NULL,
3994 NULL
3995 },
3996 {
3997 "SessionLength", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
3998 wpas_dbus_getter_session_length,
3999 NULL,
4000 NULL
4001 },
4002 {
4003 "BSSTMStatus", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
4004 wpas_dbus_getter_bss_tm_status,
4005 NULL,
4006 NULL
4007 },
4008 #ifdef CONFIG_MESH
4009 { "MeshPeers", WPAS_DBUS_NEW_IFACE_MESH, "aay",
4010 wpas_dbus_getter_mesh_peers,
4011 NULL,
4012 NULL
4013 },
4014 { "MeshGroup", WPAS_DBUS_NEW_IFACE_MESH, "ay",
4015 wpas_dbus_getter_mesh_group,
4016 NULL,
4017 NULL
4018 },
4019 #endif /* CONFIG_MESH */
4020 { "Stations", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
4021 wpas_dbus_getter_stas,
4022 NULL,
4023 NULL
4024 },
4025 { "MACAddressRandomizationMask", WPAS_DBUS_NEW_IFACE_INTERFACE,
4026 "a{say}",
4027 wpas_dbus_getter_mac_address_randomization_mask,
4028 wpas_dbus_setter_mac_address_randomization_mask,
4029 NULL
4030 },
4031 { "MACAddress", WPAS_DBUS_NEW_IFACE_INTERFACE, "ay",
4032 wpas_dbus_getter_mac_address,
4033 NULL,
4034 NULL,
4035 },
4036 { "SignalChange", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{sv}",
4037 wpas_dbus_getter_signal_change,
4038 NULL,
4039 NULL
4040 },
4041 { NULL, NULL, NULL, NULL, NULL, NULL }
4042 };
4043
4044 static const struct wpa_dbus_signal_desc wpas_dbus_interface_signals[] = {
4045 { "ScanDone", WPAS_DBUS_NEW_IFACE_INTERFACE,
4046 {
4047 { "success", "b", ARG_OUT },
4048 END_ARGS
4049 }
4050 },
4051 { "BSSAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
4052 {
4053 { "path", "o", ARG_OUT },
4054 { "properties", "a{sv}", ARG_OUT },
4055 END_ARGS
4056 }
4057 },
4058 { "BSSRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
4059 {
4060 { "path", "o", ARG_OUT },
4061 END_ARGS
4062 }
4063 },
4064 { "BlobAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
4065 {
4066 { "name", "s", ARG_OUT },
4067 END_ARGS
4068 }
4069 },
4070 { "BlobRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
4071 {
4072 { "name", "s", ARG_OUT },
4073 END_ARGS
4074 }
4075 },
4076 { "NetworkAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
4077 {
4078 { "path", "o", ARG_OUT },
4079 { "properties", "a{sv}", ARG_OUT },
4080 END_ARGS
4081 }
4082 },
4083 { "NetworkRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
4084 {
4085 { "path", "o", ARG_OUT },
4086 END_ARGS
4087 }
4088 },
4089 { "NetworkSelected", WPAS_DBUS_NEW_IFACE_INTERFACE,
4090 {
4091 { "path", "o", ARG_OUT },
4092 END_ARGS
4093 }
4094 },
4095 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
4096 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_INTERFACE,
4097 {
4098 { "properties", "a{sv}", ARG_OUT },
4099 END_ARGS
4100 }
4101 },
4102 #ifdef CONFIG_WPS
4103 { "Event", WPAS_DBUS_NEW_IFACE_WPS,
4104 {
4105 { "name", "s", ARG_OUT },
4106 { "args", "a{sv}", ARG_OUT },
4107 END_ARGS
4108 }
4109 },
4110 { "Credentials", WPAS_DBUS_NEW_IFACE_WPS,
4111 {
4112 { "credentials", "a{sv}", ARG_OUT },
4113 END_ARGS
4114 }
4115 },
4116 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
4117 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_WPS,
4118 {
4119 { "properties", "a{sv}", ARG_OUT },
4120 END_ARGS
4121 }
4122 },
4123 #endif /* CONFIG_WPS */
4124 #ifdef CONFIG_P2P
4125 { "DeviceFound", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4126 {
4127 { "path", "o", ARG_OUT },
4128 END_ARGS
4129 }
4130 },
4131 { "DeviceFoundProperties", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4132 {
4133 { "path", "o", ARG_OUT },
4134 { "properties", "a{sv}", ARG_OUT },
4135 END_ARGS
4136 }
4137 },
4138 { "DeviceLost", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4139 {
4140 { "path", "o", ARG_OUT },
4141 END_ARGS
4142 }
4143 },
4144 { "FindStopped", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4145 {
4146 END_ARGS
4147 }
4148 },
4149 { "ProvisionDiscoveryRequestDisplayPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4150 {
4151 { "peer_object", "o", ARG_OUT },
4152 { "pin", "s", ARG_OUT },
4153 END_ARGS
4154 }
4155 },
4156 { "ProvisionDiscoveryResponseDisplayPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4157 {
4158 { "peer_object", "o", ARG_OUT },
4159 { "pin", "s", ARG_OUT },
4160 END_ARGS
4161 }
4162 },
4163 { "ProvisionDiscoveryRequestEnterPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4164 {
4165 { "peer_object", "o", ARG_OUT },
4166 END_ARGS
4167 }
4168 },
4169 { "ProvisionDiscoveryResponseEnterPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4170 {
4171 { "peer_object", "o", ARG_OUT },
4172 END_ARGS
4173 }
4174 },
4175 { "ProvisionDiscoveryPBCRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4176 {
4177 { "peer_object", "o", ARG_OUT },
4178 END_ARGS
4179 }
4180 },
4181 { "ProvisionDiscoveryPBCResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4182 {
4183 { "peer_object", "o", ARG_OUT },
4184 END_ARGS
4185 }
4186 },
4187 { "ProvisionDiscoveryFailure", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4188 {
4189 { "peer_object", "o", ARG_OUT },
4190 { "status", "i", ARG_OUT },
4191 END_ARGS
4192 }
4193 },
4194 { "GroupStarted", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4195 {
4196 { "properties", "a{sv}", ARG_OUT },
4197 END_ARGS
4198 }
4199 },
4200 { "GroupFormationFailure", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4201 {
4202 { "reason", "s", ARG_OUT },
4203 END_ARGS
4204 }
4205 },
4206 { "GONegotiationSuccess", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4207 {
4208 { "properties", "a{sv}", ARG_OUT },
4209 END_ARGS
4210 }
4211 },
4212 { "GONegotiationFailure", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4213 {
4214 { "properties", "a{sv}", ARG_OUT },
4215 END_ARGS
4216 }
4217 },
4218 { "GONegotiationRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4219 {
4220 { "path", "o", ARG_OUT },
4221 { "dev_passwd_id", "q", ARG_OUT },
4222 { "device_go_intent", "y", ARG_OUT },
4223 END_ARGS
4224 }
4225 },
4226 { "InvitationResult", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4227 {
4228 { "invite_result", "a{sv}", ARG_OUT },
4229 END_ARGS
4230 }
4231 },
4232 { "GroupFinished", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4233 {
4234 { "properties", "a{sv}", ARG_OUT },
4235 END_ARGS
4236 }
4237 },
4238 { "ServiceDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4239 {
4240 { "sd_request", "a{sv}", ARG_OUT },
4241 END_ARGS
4242 }
4243 },
4244 { "ServiceDiscoveryResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4245 {
4246 { "sd_response", "a{sv}", ARG_OUT },
4247 END_ARGS
4248 }
4249 },
4250 { "PersistentGroupAdded", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4251 {
4252 { "path", "o", ARG_OUT },
4253 { "properties", "a{sv}", ARG_OUT },
4254 END_ARGS
4255 }
4256 },
4257 { "PersistentGroupRemoved", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4258 {
4259 { "path", "o", ARG_OUT },
4260 END_ARGS
4261 }
4262 },
4263 { "WpsFailed", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4264 {
4265 { "name", "s", ARG_OUT },
4266 { "args", "a{sv}", ARG_OUT },
4267 END_ARGS
4268 }
4269 },
4270 { "InvitationReceived", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4271 {
4272 { "properties", "a{sv}", ARG_OUT },
4273 END_ARGS
4274 }
4275 },
4276 #endif /* CONFIG_P2P */
4277 #ifdef CONFIG_AP
4278 { "ProbeRequest", WPAS_DBUS_NEW_IFACE_INTERFACE,
4279 {
4280 { "args", "a{sv}", ARG_OUT },
4281 END_ARGS
4282 }
4283 },
4284 #endif /* CONFIG_AP */
4285 { "Certification", WPAS_DBUS_NEW_IFACE_INTERFACE,
4286 {
4287 { "certification", "a{sv}", ARG_OUT },
4288 END_ARGS
4289 }
4290 },
4291 { "EAP", WPAS_DBUS_NEW_IFACE_INTERFACE,
4292 {
4293 { "status", "s", ARG_OUT },
4294 { "parameter", "s", ARG_OUT },
4295 END_ARGS
4296 }
4297 },
4298 { "StaAuthorized", WPAS_DBUS_NEW_IFACE_INTERFACE,
4299 {
4300 { "name", "s", ARG_OUT },
4301 END_ARGS
4302 }
4303 },
4304 { "StaDeauthorized", WPAS_DBUS_NEW_IFACE_INTERFACE,
4305 {
4306 { "name", "s", ARG_OUT },
4307 END_ARGS
4308 }
4309 },
4310 { "StationAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
4311 {
4312 { "path", "o", ARG_OUT },
4313 { "properties", "a{sv}", ARG_OUT },
4314 END_ARGS
4315 }
4316 },
4317 { "StationRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
4318 {
4319 { "path", "o", ARG_OUT },
4320 END_ARGS
4321 }
4322 },
4323 { "NetworkRequest", WPAS_DBUS_NEW_IFACE_INTERFACE,
4324 {
4325 { "path", "o", ARG_OUT },
4326 { "field", "s", ARG_OUT },
4327 { "text", "s", ARG_OUT },
4328 END_ARGS
4329 }
4330 },
4331 #ifdef CONFIG_MESH
4332 { "MeshGroupStarted", WPAS_DBUS_NEW_IFACE_MESH,
4333 {
4334 { "args", "a{sv}", ARG_OUT },
4335 END_ARGS
4336 }
4337 },
4338 { "MeshGroupRemoved", WPAS_DBUS_NEW_IFACE_MESH,
4339 {
4340 { "args", "a{sv}", ARG_OUT },
4341 END_ARGS
4342 }
4343 },
4344 { "MeshPeerConnected", WPAS_DBUS_NEW_IFACE_MESH,
4345 {
4346 { "args", "a{sv}", ARG_OUT },
4347 END_ARGS
4348 }
4349 },
4350 { "MeshPeerDisconnected", WPAS_DBUS_NEW_IFACE_MESH,
4351 {
4352 { "args", "a{sv}", ARG_OUT },
4353 END_ARGS
4354 }
4355 },
4356 #endif /* CONFIG_MESH */
4357 #ifdef CONFIG_INTERWORKING
4358 { "InterworkingAPAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
4359 {
4360 { "bss", "o", ARG_OUT },
4361 { "cred", "o", ARG_OUT },
4362 { "properties", "a{sv}", ARG_OUT },
4363 END_ARGS
4364 }
4365 },
4366 { "InterworkingSelectDone", WPAS_DBUS_NEW_IFACE_INTERFACE,
4367 {
4368 END_ARGS
4369 }
4370 },
4371 {"ANQPQueryDone", WPAS_DBUS_NEW_IFACE_INTERFACE,
4372 {
4373 { "addr", "s", ARG_OUT },
4374 { "result", "s", ARG_OUT },
4375 END_ARGS
4376 }
4377 },
4378 #endif /* CONFIG_INTERWORKING */
4379 #ifdef CONFIG_HS20
4380 { "HS20TermsAndConditions", WPAS_DBUS_NEW_IFACE_INTERFACE,
4381 {
4382 { "url", "s", ARG_OUT },
4383 END_ARGS
4384 }
4385 },
4386 #endif /* CONFIG_HS20 */
4387 { NULL, NULL, { END_ARGS } }
4388 };
4389
4390
wpa_dbus_ctrl_iface_props_init(struct wpas_dbus_priv * priv)4391 static int wpa_dbus_ctrl_iface_props_init(struct wpas_dbus_priv *priv)
4392 {
4393 size_t all_size;
4394 unsigned int i, j, count, num_const, num_globals;
4395 const char *global_name;
4396 static const char * const ignored_globals[] = {
4397 "bss_expiration_age", "bss_expiration_scan_count",
4398 "ap_scan", "country", "fast_reauth",
4399 "pkcs11_engine_path", "pkcs11_module_path"
4400 };
4401
4402 /* wpas_dbus_interface_properties terminates with a NULL element */
4403 num_const = ARRAY_SIZE(wpas_dbus_interface_properties) - 1;
4404
4405 num_globals = wpa_config_get_num_global_field_names();
4406 priv->globals_start = num_const;
4407
4408 /* allocate enough for all properties + terminating NULL element */
4409 all_size = (num_globals + num_const + 1) *
4410 sizeof(wpas_dbus_interface_properties[0]);
4411 priv->all_interface_properties = os_zalloc(all_size);
4412 if (!priv->all_interface_properties) {
4413 wpa_printf(MSG_ERROR,
4414 "dbus: Not enough memory for interface properties");
4415 return -1;
4416 }
4417
4418 /* Copy constant interface properties to the start of the array */
4419 os_memcpy(priv->all_interface_properties,
4420 wpas_dbus_interface_properties,
4421 sizeof(wpas_dbus_interface_properties));
4422
4423 /* Dynamically construct interface global properties */
4424 for (i = 0, count = num_const; i < num_globals; i++) {
4425 struct wpa_dbus_property_desc *desc;
4426 int no_var = 0;
4427
4428 /* ignore globals that are actually just methods */
4429 global_name = wpa_config_get_global_field_name(i, &no_var);
4430 if (no_var)
4431 continue;
4432 /* Ignore fields already explicitly exposed */
4433 for (j = 0; j < ARRAY_SIZE(ignored_globals); j++) {
4434 if (os_strcmp(global_name, ignored_globals[j]) == 0)
4435 break;
4436 }
4437 if (j < ARRAY_SIZE(ignored_globals))
4438 continue;
4439
4440 desc = &priv->all_interface_properties[count++];
4441 desc->dbus_property = uscore_to_dbus(global_name);
4442 if (!desc->dbus_property) {
4443 wpa_printf(MSG_ERROR,
4444 "dbus: Not enough memory for D-Bus property name");
4445 goto error;
4446 }
4447 desc->dbus_interface = WPAS_DBUS_NEW_IFACE_INTERFACE;
4448 desc->type = "s";
4449 desc->getter = wpas_dbus_getter_iface_global;
4450 desc->setter = wpas_dbus_setter_iface_global;
4451 desc->data = global_name;
4452 }
4453
4454 return 0;
4455
4456 error:
4457 wpa_dbus_ctrl_iface_props_deinit(priv);
4458 return -1;
4459 }
4460
4461
4462 /**
4463 * wpas_dbus_register_interface - Register an interface with D-Bus
4464 * @wpa_s: wpa_supplicant interface structure
4465 * Returns: 0 on success, -1 on failure
4466 */
wpas_dbus_register_interface(struct wpa_supplicant * wpa_s)4467 int wpas_dbus_register_interface(struct wpa_supplicant *wpa_s)
4468 {
4469 struct wpa_dbus_object_desc *obj_desc = NULL;
4470 struct wpas_dbus_priv *ctrl_iface = wpa_s->global->dbus;
4471 int next;
4472
4473 /* Do nothing if the control interface is not turned on */
4474 if (ctrl_iface == NULL)
4475 return 0;
4476
4477 /* Create and set the interface's object path */
4478 wpa_s->dbus_new_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
4479 if (wpa_s->dbus_new_path == NULL)
4480 return -1;
4481 next = ctrl_iface->next_objid++;
4482 os_snprintf(wpa_s->dbus_new_path, WPAS_DBUS_OBJECT_PATH_MAX,
4483 WPAS_DBUS_NEW_PATH_INTERFACES "/%u",
4484 next);
4485
4486 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
4487 if (!obj_desc) {
4488 wpa_printf(MSG_ERROR,
4489 "Not enough memory to create object description");
4490 goto err;
4491 }
4492
4493 wpas_dbus_register(obj_desc, wpa_s, NULL, wpas_dbus_interface_methods,
4494 ctrl_iface->all_interface_properties,
4495 wpas_dbus_interface_signals);
4496
4497 wpa_printf(MSG_DEBUG, "dbus: Register interface object '%s'",
4498 wpa_s->dbus_new_path);
4499 if (wpa_dbus_register_object_per_iface(ctrl_iface,
4500 wpa_s->dbus_new_path,
4501 wpa_s->ifname, obj_desc))
4502 goto err;
4503
4504 wpas_dbus_signal_interface_added(wpa_s);
4505
4506 return 0;
4507
4508 err:
4509 os_free(wpa_s->dbus_new_path);
4510 wpa_s->dbus_new_path = NULL;
4511 free_dbus_object_desc(obj_desc);
4512 return -1;
4513 }
4514
4515
4516 /**
4517 * wpas_dbus_unregister_interface - Unregister the interface from D-Bus
4518 * @wpa_s: wpa_supplicant interface structure
4519 * Returns: 0 on success, -1 on failure
4520 */
wpas_dbus_unregister_interface(struct wpa_supplicant * wpa_s)4521 int wpas_dbus_unregister_interface(struct wpa_supplicant *wpa_s)
4522 {
4523 struct wpas_dbus_priv *ctrl_iface;
4524
4525 /* Do nothing if the control interface is not turned on */
4526 if (wpa_s == NULL || wpa_s->global == NULL)
4527 return 0;
4528 ctrl_iface = wpa_s->global->dbus;
4529 if (ctrl_iface == NULL || wpa_s->dbus_new_path == NULL)
4530 return 0;
4531
4532 wpa_printf(MSG_DEBUG, "dbus: Unregister interface object '%s'",
4533 wpa_s->dbus_new_path);
4534
4535 #ifdef CONFIG_AP
4536 if (wpa_s->preq_notify_peer) {
4537 wpas_dbus_unsubscribe_noc(ctrl_iface);
4538 os_free(wpa_s->preq_notify_peer);
4539 wpa_s->preq_notify_peer = NULL;
4540 }
4541 #endif /* CONFIG_AP */
4542
4543 if (wpa_dbus_unregister_object_per_iface(ctrl_iface,
4544 wpa_s->dbus_new_path))
4545 return -1;
4546
4547 wpas_dbus_signal_interface_removed(wpa_s);
4548
4549 os_free(wpa_s->dbus_new_path);
4550 wpa_s->dbus_new_path = NULL;
4551
4552 return 0;
4553 }
4554
4555 #ifdef CONFIG_P2P
4556
4557 static const struct wpa_dbus_property_desc wpas_dbus_p2p_peer_properties[] = {
4558 { "DeviceName", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
4559 wpas_dbus_getter_p2p_peer_device_name,
4560 NULL,
4561 NULL
4562 },
4563 { "Manufacturer", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
4564 wpas_dbus_getter_p2p_peer_manufacturer,
4565 NULL,
4566 NULL
4567 },
4568 { "ModelName", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
4569 wpas_dbus_getter_p2p_peer_modelname,
4570 NULL,
4571 NULL
4572 },
4573 { "ModelNumber", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
4574 wpas_dbus_getter_p2p_peer_modelnumber,
4575 NULL,
4576 NULL
4577 },
4578 { "SerialNumber", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
4579 wpas_dbus_getter_p2p_peer_serialnumber,
4580 NULL,
4581 NULL
4582 },
4583 { "PrimaryDeviceType", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
4584 wpas_dbus_getter_p2p_peer_primary_device_type,
4585 NULL,
4586 NULL
4587 },
4588 { "config_method", WPAS_DBUS_NEW_IFACE_P2P_PEER, "q",
4589 wpas_dbus_getter_p2p_peer_config_method,
4590 NULL,
4591 NULL
4592 },
4593 { "level", WPAS_DBUS_NEW_IFACE_P2P_PEER, "i",
4594 wpas_dbus_getter_p2p_peer_level,
4595 NULL,
4596 NULL
4597 },
4598 { "devicecapability", WPAS_DBUS_NEW_IFACE_P2P_PEER, "y",
4599 wpas_dbus_getter_p2p_peer_device_capability,
4600 NULL,
4601 NULL
4602 },
4603 { "groupcapability", WPAS_DBUS_NEW_IFACE_P2P_PEER, "y",
4604 wpas_dbus_getter_p2p_peer_group_capability,
4605 NULL,
4606 NULL
4607 },
4608 { "SecondaryDeviceTypes", WPAS_DBUS_NEW_IFACE_P2P_PEER, "aay",
4609 wpas_dbus_getter_p2p_peer_secondary_device_types,
4610 NULL,
4611 NULL
4612 },
4613 { "VendorExtension", WPAS_DBUS_NEW_IFACE_P2P_PEER, "aay",
4614 wpas_dbus_getter_p2p_peer_vendor_extension,
4615 NULL,
4616 NULL
4617 },
4618 { "IEs", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
4619 wpas_dbus_getter_p2p_peer_ies,
4620 NULL,
4621 NULL
4622 },
4623 { "DeviceAddress", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
4624 wpas_dbus_getter_p2p_peer_device_address,
4625 NULL,
4626 NULL
4627 },
4628 { "Groups", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ao",
4629 wpas_dbus_getter_p2p_peer_groups,
4630 NULL,
4631 NULL
4632 },
4633 { "VSIE", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
4634 wpas_dbus_getter_p2p_peer_vsie,
4635 NULL,
4636 NULL
4637 },
4638 { NULL, NULL, NULL, NULL, NULL, NULL }
4639 };
4640
4641 static const struct wpa_dbus_signal_desc wpas_dbus_p2p_peer_signals[] = {
4642 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
4643 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_P2P_PEER,
4644 {
4645 { "properties", "a{sv}", ARG_OUT },
4646 END_ARGS
4647 }
4648 },
4649 { NULL, NULL, { END_ARGS } }
4650 };
4651
4652 /**
4653 * wpas_dbus_signal_peer - Send a peer related event signal
4654 * @wpa_s: %wpa_supplicant network interface data
4655 * @dev: peer device object
4656 * @interface: name of the interface emitting this signal.
4657 * In case of peer objects, it would be emitted by either
4658 * the "interface object" or by "peer objects"
4659 * @sig_name: signal name - DeviceFound
4660 * @properties: Whether to add a second argument with object properties
4661 *
4662 * Notify listeners about event related with p2p peer device
4663 */
wpas_dbus_signal_peer(struct wpa_supplicant * wpa_s,const u8 * dev_addr,const char * interface,const char * sig_name,dbus_bool_t properties)4664 static void wpas_dbus_signal_peer(struct wpa_supplicant *wpa_s,
4665 const u8 *dev_addr, const char *interface,
4666 const char *sig_name, dbus_bool_t properties)
4667 {
4668 struct wpas_dbus_priv *iface;
4669 DBusMessage *msg;
4670 DBusMessageIter iter;
4671 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
4672
4673 if (wpa_s->p2p_mgmt)
4674 wpa_s = wpa_s->parent;
4675
4676 iface = wpa_s->global->dbus;
4677
4678 /* Do nothing if the control interface is not turned on */
4679 if (iface == NULL || !wpa_s->dbus_new_path)
4680 return;
4681
4682 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
4683 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
4684 wpa_s->dbus_new_path, MAC2STR(dev_addr));
4685
4686 msg = dbus_message_new_signal(wpa_s->dbus_new_path, interface,
4687 sig_name);
4688 if (msg == NULL)
4689 return;
4690
4691 dbus_message_iter_init_append(msg, &iter);
4692 path = peer_obj_path;
4693 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
4694 &path) ||
4695 (properties && !wpa_dbus_get_object_properties(
4696 iface, peer_obj_path, WPAS_DBUS_NEW_IFACE_P2P_PEER,
4697 &iter)))
4698 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
4699 else
4700 dbus_connection_send(iface->con, msg, NULL);
4701
4702 dbus_message_unref(msg);
4703 }
4704
4705
4706 /**
4707 * wpas_dbus_signal_peer_found - Send a peer found signal
4708 * @wpa_s: %wpa_supplicant network interface data
4709 * @dev_addr: Peer P2P Device Address
4710 *
4711 * Notify listeners about find a p2p peer device found
4712 */
wpas_dbus_signal_peer_device_found(struct wpa_supplicant * wpa_s,const u8 * dev_addr)4713 void wpas_dbus_signal_peer_device_found(struct wpa_supplicant *wpa_s,
4714 const u8 *dev_addr)
4715 {
4716 wpas_dbus_signal_peer(wpa_s, dev_addr,
4717 WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4718 "DeviceFound", FALSE);
4719
4720 wpas_dbus_signal_peer(wpa_s, dev_addr,
4721 WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4722 "DeviceFoundProperties", TRUE);
4723 }
4724
4725 /**
4726 * wpas_dbus_signal_peer_lost - Send a peer lost signal
4727 * @wpa_s: %wpa_supplicant network interface data
4728 * @dev_addr: Peer P2P Device Address
4729 *
4730 * Notify listeners about lost a p2p peer device
4731 */
wpas_dbus_signal_peer_device_lost(struct wpa_supplicant * wpa_s,const u8 * dev_addr)4732 void wpas_dbus_signal_peer_device_lost(struct wpa_supplicant *wpa_s,
4733 const u8 *dev_addr)
4734 {
4735 wpas_dbus_signal_peer(wpa_s, dev_addr,
4736 WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4737 "DeviceLost", FALSE);
4738 }
4739
4740 /**
4741 * wpas_dbus_register_peer - Register a discovered peer object with dbus
4742 * @wpa_s: wpa_supplicant interface structure
4743 * @dev_addr: P2P Device Address of the peer
4744 * Returns: 0 on success, -1 on failure
4745 *
4746 * Registers network representing object with dbus
4747 */
wpas_dbus_register_peer(struct wpa_supplicant * wpa_s,const u8 * dev_addr)4748 int wpas_dbus_register_peer(struct wpa_supplicant *wpa_s, const u8 *dev_addr)
4749 {
4750 struct wpas_dbus_priv *ctrl_iface;
4751 struct wpa_dbus_object_desc *obj_desc;
4752 struct peer_handler_args *arg;
4753 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
4754
4755 /* Do nothing if the control interface is not turned on */
4756 if (wpa_s == NULL || wpa_s->global == NULL)
4757 return 0;
4758
4759 ctrl_iface = wpa_s->global->dbus;
4760 if (ctrl_iface == NULL)
4761 return 0;
4762
4763 wpa_s = wpa_s->parent->parent;
4764 if (!wpa_s->dbus_new_path)
4765 return 0;
4766
4767 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
4768 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
4769 wpa_s->dbus_new_path, MAC2STR(dev_addr));
4770
4771 wpa_printf(MSG_INFO, "dbus: Register peer object '%s'",
4772 peer_obj_path);
4773 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
4774 if (!obj_desc) {
4775 wpa_printf(MSG_ERROR,
4776 "Not enough memory to create object description");
4777 goto err;
4778 }
4779
4780 /* allocate memory for handlers arguments */
4781 arg = os_zalloc(sizeof(struct peer_handler_args));
4782 if (!arg) {
4783 wpa_printf(MSG_ERROR,
4784 "Not enough memory to create arguments for method");
4785 goto err;
4786 }
4787
4788 arg->wpa_s = wpa_s;
4789 os_memcpy(arg->p2p_device_addr, dev_addr, ETH_ALEN);
4790
4791 wpas_dbus_register(obj_desc, arg, wpa_dbus_free,
4792 NULL,
4793 wpas_dbus_p2p_peer_properties,
4794 wpas_dbus_p2p_peer_signals);
4795
4796 if (wpa_dbus_register_object_per_iface(ctrl_iface, peer_obj_path,
4797 wpa_s->ifname, obj_desc))
4798 goto err;
4799
4800 return 0;
4801
4802 err:
4803 free_dbus_object_desc(obj_desc);
4804 return -1;
4805 }
4806
4807 /**
4808 * wpas_dbus_unregister_peer - Unregister a peer object with dbus
4809 * @wpa_s: wpa_supplicant interface structure
4810 * @dev_addr: p2p device addr
4811 * Returns: 0 on success, -1 on failure
4812 *
4813 * Registers network representing object with dbus
4814 */
wpas_dbus_unregister_peer(struct wpa_supplicant * wpa_s,const u8 * dev_addr)4815 int wpas_dbus_unregister_peer(struct wpa_supplicant *wpa_s,
4816 const u8 *dev_addr)
4817 {
4818 struct wpas_dbus_priv *ctrl_iface;
4819 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
4820 int ret;
4821
4822 /* Do nothing if the control interface is not turned on */
4823 if (wpa_s == NULL || wpa_s->global == NULL)
4824 return 0;
4825
4826 wpa_s = wpa_s->parent->parent;
4827 if (!wpa_s->dbus_new_path)
4828 return 0;
4829
4830 ctrl_iface = wpa_s->global->dbus;
4831 if (ctrl_iface == NULL)
4832 return 0;
4833
4834 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
4835 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
4836 wpa_s->dbus_new_path, MAC2STR(dev_addr));
4837
4838 wpa_printf(MSG_INFO, "dbus: Unregister peer object '%s'",
4839 peer_obj_path);
4840 ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, peer_obj_path);
4841
4842 return ret;
4843 }
4844
4845
4846 /**
4847 * wpas_dbus_signal_p2p_find_stopped - Send P2P Find stopped signal
4848 * @wpa_s: %wpa_supplicant network interface data
4849 *
4850 * Notify listeners about P2P Find stopped
4851 */
wpas_dbus_signal_p2p_find_stopped(struct wpa_supplicant * wpa_s)4852 void wpas_dbus_signal_p2p_find_stopped(struct wpa_supplicant *wpa_s)
4853 {
4854 struct wpas_dbus_priv *iface;
4855 DBusMessage *msg;
4856
4857 iface = wpa_s->global->dbus;
4858
4859 /* Do nothing if the control interface is not turned on */
4860 if (iface == NULL)
4861 return;
4862
4863 if (wpa_s->p2p_mgmt)
4864 wpa_s = wpa_s->parent;
4865
4866 if (!wpa_s->dbus_new_path)
4867 return;
4868
4869 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
4870 WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4871 "FindStopped");
4872 if (msg == NULL)
4873 return;
4874
4875 dbus_connection_send(iface->con, msg, NULL);
4876
4877 dbus_message_unref(msg);
4878 }
4879
4880
4881 /**
4882 * wpas_dbus_signal_peer_groups_changed - Send peer group change property signal
4883 * @wpa_s: %wpa_supplicant network interface data
4884 * @dev_addr: P2P Device Address
4885 *
4886 * Notify listeners about peer Groups property changes.
4887 */
wpas_dbus_signal_peer_groups_changed(struct wpa_supplicant * wpa_s,const u8 * dev_addr)4888 void wpas_dbus_signal_peer_groups_changed(struct wpa_supplicant *wpa_s,
4889 const u8 *dev_addr)
4890 {
4891 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
4892
4893 if (wpa_s->p2p_mgmt)
4894 wpa_s = wpa_s->parent;
4895
4896 if (!wpa_s->dbus_new_path)
4897 return;
4898 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
4899 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
4900 wpa_s->dbus_new_path, MAC2STR(dev_addr));
4901
4902 wpa_dbus_mark_property_changed(wpa_s->global->dbus, peer_obj_path,
4903 WPAS_DBUS_NEW_IFACE_P2P_PEER, "Groups");
4904 }
4905
4906
4907 static const struct wpa_dbus_property_desc wpas_dbus_p2p_group_properties[] = {
4908 { "Members", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ao",
4909 wpas_dbus_getter_p2p_group_members,
4910 NULL,
4911 NULL
4912 },
4913 { "Group", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "o",
4914 wpas_dbus_getter_p2p_group,
4915 NULL,
4916 NULL
4917 },
4918 { "Role", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "s",
4919 wpas_dbus_getter_p2p_role,
4920 NULL,
4921 NULL
4922 },
4923 { "SSID", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay",
4924 wpas_dbus_getter_p2p_group_ssid,
4925 NULL,
4926 NULL
4927 },
4928 { "BSSID", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay",
4929 wpas_dbus_getter_p2p_group_bssid,
4930 NULL,
4931 NULL
4932 },
4933 { "Frequency", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "q",
4934 wpas_dbus_getter_p2p_group_frequency,
4935 NULL,
4936 NULL
4937 },
4938 { "Passphrase", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "s",
4939 wpas_dbus_getter_p2p_group_passphrase,
4940 NULL,
4941 NULL
4942 },
4943 { "PSK", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay",
4944 wpas_dbus_getter_p2p_group_psk,
4945 NULL,
4946 NULL
4947 },
4948 { "WPSVendorExtensions", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "aay",
4949 wpas_dbus_getter_p2p_group_vendor_ext,
4950 wpas_dbus_setter_p2p_group_vendor_ext,
4951 NULL
4952 },
4953 { NULL, NULL, NULL, NULL, NULL, NULL }
4954 };
4955
4956 static const struct wpa_dbus_signal_desc wpas_dbus_p2p_group_signals[] = {
4957 { "PeerJoined", WPAS_DBUS_NEW_IFACE_P2P_GROUP,
4958 {
4959 { "peer", "o", ARG_OUT },
4960 END_ARGS
4961 }
4962 },
4963 { "PeerDisconnected", WPAS_DBUS_NEW_IFACE_P2P_GROUP,
4964 {
4965 { "peer", "o", ARG_OUT },
4966 END_ARGS
4967 }
4968 },
4969 { NULL, NULL, { END_ARGS } }
4970 };
4971
4972 /**
4973 * wpas_dbus_register_p2p_group - Register a p2p group object with dbus
4974 * @wpa_s: wpa_supplicant interface structure
4975 * @ssid: SSID struct
4976 * Returns: 0 on success, -1 on failure
4977 *
4978 * Registers p2p group representing object with dbus
4979 */
wpas_dbus_register_p2p_group(struct wpa_supplicant * wpa_s,struct wpa_ssid * ssid)4980 void wpas_dbus_register_p2p_group(struct wpa_supplicant *wpa_s,
4981 struct wpa_ssid *ssid)
4982 {
4983 struct wpas_dbus_priv *ctrl_iface;
4984 struct wpa_dbus_object_desc *obj_desc;
4985 char group_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
4986
4987 /* Do nothing if the control interface is not turned on */
4988 if (wpa_s == NULL || wpa_s->global == NULL)
4989 return;
4990
4991 ctrl_iface = wpa_s->global->dbus;
4992 if (ctrl_iface == NULL)
4993 return;
4994
4995 if (wpa_s->dbus_groupobj_path) {
4996 wpa_printf(MSG_INFO, "%s: Group object '%s' already exists",
4997 __func__, wpa_s->dbus_groupobj_path);
4998 return;
4999 }
5000
5001 if (wpas_dbus_get_group_obj_path(wpa_s, ssid, group_obj_path) < 0)
5002 return;
5003
5004 wpa_s->dbus_groupobj_path = os_strdup(group_obj_path);
5005 if (wpa_s->dbus_groupobj_path == NULL)
5006 return;
5007
5008 wpa_printf(MSG_INFO, "dbus: Register group object '%s'",
5009 group_obj_path);
5010 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
5011 if (!obj_desc) {
5012 wpa_printf(MSG_ERROR,
5013 "Not enough memory to create object description");
5014 goto err;
5015 }
5016
5017 wpas_dbus_register(obj_desc, wpa_s, NULL, NULL,
5018 wpas_dbus_p2p_group_properties,
5019 wpas_dbus_p2p_group_signals);
5020
5021 if (wpa_dbus_register_object_per_iface(ctrl_iface, group_obj_path,
5022 wpa_s->ifname, obj_desc))
5023 goto err;
5024
5025 return;
5026
5027 err:
5028 if (wpa_s->dbus_groupobj_path) {
5029 os_free(wpa_s->dbus_groupobj_path);
5030 wpa_s->dbus_groupobj_path = NULL;
5031 }
5032
5033 free_dbus_object_desc(obj_desc);
5034 }
5035
5036 /**
5037 * wpas_dbus_unregister_p2p_group - Unregister a p2p group object from dbus
5038 * @wpa_s: wpa_supplicant interface structure
5039 * @ssid: network name of the p2p group started
5040 */
wpas_dbus_unregister_p2p_group(struct wpa_supplicant * wpa_s,const struct wpa_ssid * ssid)5041 void wpas_dbus_unregister_p2p_group(struct wpa_supplicant *wpa_s,
5042 const struct wpa_ssid *ssid)
5043 {
5044 struct wpas_dbus_priv *ctrl_iface;
5045
5046 /* Do nothing if the control interface is not turned on */
5047 if (wpa_s == NULL || wpa_s->global == NULL)
5048 return;
5049
5050 if (wpa_s->p2p_mgmt)
5051 wpa_s = wpa_s->parent;
5052
5053 ctrl_iface = wpa_s->global->dbus;
5054 if (ctrl_iface == NULL)
5055 return;
5056
5057 if (!wpa_s->dbus_groupobj_path) {
5058 wpa_printf(MSG_DEBUG,
5059 "%s: Group object has already unregistered",
5060 __func__);
5061 return;
5062 }
5063
5064 peer_groups_changed(wpa_s);
5065
5066 wpa_printf(MSG_DEBUG, "dbus: Unregister group object '%s'",
5067 wpa_s->dbus_groupobj_path);
5068
5069 wpa_dbus_unregister_object_per_iface(ctrl_iface,
5070 wpa_s->dbus_groupobj_path);
5071
5072 os_free(wpa_s->dbus_groupobj_path);
5073 wpa_s->dbus_groupobj_path = NULL;
5074 }
5075
5076 static const struct wpa_dbus_property_desc
5077 wpas_dbus_persistent_group_properties[] = {
5078 { "Properties", WPAS_DBUS_NEW_IFACE_PERSISTENT_GROUP, "a{sv}",
5079 wpas_dbus_getter_persistent_group_properties,
5080 wpas_dbus_setter_persistent_group_properties,
5081 NULL
5082 },
5083 { NULL, NULL, NULL, NULL, NULL, NULL }
5084 };
5085
5086 /* No signals intended for persistent group objects */
5087
5088 /**
5089 * wpas_dbus_register_persistent_group - Register a configured(saved)
5090 * persistent group with dbus
5091 * @wpa_s: wpa_supplicant interface structure
5092 * @ssid: persistent group (still represented as a network within wpa)
5093 * configuration data
5094 * Returns: 0 on success, -1 on failure
5095 *
5096 * Registers a persistent group representing object with dbus.
5097 */
wpas_dbus_register_persistent_group(struct wpa_supplicant * wpa_s,struct wpa_ssid * ssid)5098 int wpas_dbus_register_persistent_group(struct wpa_supplicant *wpa_s,
5099 struct wpa_ssid *ssid)
5100 {
5101 struct wpas_dbus_priv *ctrl_iface;
5102 struct wpa_dbus_object_desc *obj_desc;
5103 struct network_handler_args *arg;
5104 char pgrp_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
5105
5106 /* Do nothing if the control interface is not turned on */
5107 if (wpa_s == NULL || wpa_s->global == NULL)
5108 return 0;
5109 wpa_s = wpa_s->parent->parent;
5110 if (!wpa_s->dbus_new_path)
5111 return 0;
5112
5113 /* Make sure ssid is a persistent group */
5114 if (ssid->disabled != 2 && !ssid->p2p_persistent_group)
5115 return -1; /* should we return w/o complaining? */
5116
5117 if (wpa_s->p2p_mgmt)
5118 wpa_s = wpa_s->parent;
5119
5120 ctrl_iface = wpa_s->global->dbus;
5121 if (ctrl_iface == NULL)
5122 return 0;
5123
5124 /*
5125 * Intentionally not coming up with different numbering scheme
5126 * for persistent groups.
5127 */
5128 os_snprintf(pgrp_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
5129 "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%u",
5130 wpa_s->dbus_new_path, ssid->id);
5131
5132 wpa_printf(MSG_DEBUG, "dbus: Register persistent group object '%s'",
5133 pgrp_obj_path);
5134 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
5135 if (!obj_desc) {
5136 wpa_printf(MSG_ERROR,
5137 "dbus: Not enough memory to create object description");
5138 goto err;
5139 }
5140
5141 /*
5142 * Reusing the same context structure as that for networks
5143 * since these are represented using same data structure.
5144 */
5145 /* allocate memory for handlers arguments */
5146 arg = os_zalloc(sizeof(struct network_handler_args));
5147 if (!arg) {
5148 wpa_printf(MSG_ERROR,
5149 "dbus: Not enough memory to create arguments for method");
5150 goto err;
5151 }
5152
5153 arg->wpa_s = wpa_s;
5154 arg->ssid = ssid;
5155
5156 wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
5157 wpas_dbus_persistent_group_properties,
5158 NULL);
5159
5160 if (wpa_dbus_register_object_per_iface(ctrl_iface, pgrp_obj_path,
5161 wpa_s->ifname, obj_desc))
5162 goto err;
5163
5164 wpas_dbus_signal_persistent_group_added(wpa_s, ssid->id);
5165
5166 return 0;
5167
5168 err:
5169 free_dbus_object_desc(obj_desc);
5170 return -1;
5171 }
5172
5173
5174 /**
5175 * wpas_dbus_unregister_persistent_group - Unregister a persistent_group
5176 * from dbus
5177 * @wpa_s: wpa_supplicant interface structure
5178 * @nid: network id
5179 * Returns: 0 on success, -1 on failure
5180 *
5181 * Unregisters persistent group representing object from dbus
5182 *
5183 * NOTE: There is a slight issue with the semantics here. While the
5184 * implementation simply means the persistent group is unloaded from memory,
5185 * it should not get interpreted as the group is actually being erased/removed
5186 * from persistent storage as well.
5187 */
wpas_dbus_unregister_persistent_group(struct wpa_supplicant * wpa_s,int nid)5188 int wpas_dbus_unregister_persistent_group(struct wpa_supplicant *wpa_s,
5189 int nid)
5190 {
5191 struct wpas_dbus_priv *ctrl_iface;
5192 char pgrp_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
5193 int ret;
5194
5195 /* Do nothing if the control interface is not turned on */
5196 if (wpa_s == NULL || wpa_s->global == NULL)
5197 return 0;
5198
5199 wpa_s = wpa_s->parent->parent;
5200
5201 ctrl_iface = wpa_s->global->dbus;
5202 if (ctrl_iface == NULL || !wpa_s->dbus_new_path)
5203 return 0;
5204
5205 os_snprintf(pgrp_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
5206 "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%u",
5207 wpa_s->dbus_new_path, nid);
5208
5209 wpa_printf(MSG_DEBUG, "dbus: Unregister persistent group object '%s'",
5210 pgrp_obj_path);
5211 ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, pgrp_obj_path);
5212
5213 if (!ret)
5214 wpas_dbus_signal_persistent_group_removed(wpa_s, nid);
5215
5216 return ret;
5217 }
5218
5219 #endif /* CONFIG_P2P */
5220
5221
5222 #ifdef CONFIG_HS20
5223 /**
5224 * wpas_dbus_signal_hs20_t_c_acceptance - Signals a terms and conditions was
5225 * received.
5226 *
5227 * @wpa_s: %wpa_supplicant network interface data
5228 * @url: URL of the terms and conditions acceptance page.
5229 */
wpas_dbus_signal_hs20_t_c_acceptance(struct wpa_supplicant * wpa_s,const char * url)5230 void wpas_dbus_signal_hs20_t_c_acceptance(struct wpa_supplicant *wpa_s,
5231 const char *url)
5232 {
5233 struct wpas_dbus_priv *iface;
5234 DBusMessage *msg;
5235
5236 iface = wpa_s->global->dbus;
5237
5238 /* Do nothing if the control interface is not turned on */
5239 if (!iface || !wpa_s->dbus_new_path)
5240 return;
5241
5242 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
5243 WPAS_DBUS_NEW_IFACE_INTERFACE,
5244 "HS20TermsAndConditions");
5245 if (!msg)
5246 return;
5247
5248 if (dbus_message_append_args(msg, DBUS_TYPE_STRING, &url,
5249 DBUS_TYPE_INVALID))
5250 dbus_connection_send(iface->con, msg, NULL);
5251 else
5252 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
5253 dbus_message_unref(msg);
5254 }
5255 #endif /* CONFIG_HS20 */
5256