1 /*
2 * WPA Supplicant / dbus-based control interface
3 * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
4 * Copyright (c) 2009-2010, Witold Sowa <witold.sowa@gmail.com>
5 * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
6 *
7 * This software may be distributed under the terms of the BSD license.
8 * See README for more details.
9 */
10
11 #include "includes.h"
12
13 #include "common.h"
14 #include "common/ieee802_11_defs.h"
15 #include "wps/wps.h"
16 #include "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 /**
2336 * wpas_dbus_signal_p2p_bootstrap_req - Signals BootstrappingRequest event
2337 * @wpa_s: %wpa_supplicant network interface data
2338 * @src: Source address of the message triggering this notification
2339 * @bootstrap_method: Peer's bootstrap method
2340 *
2341 * Sends a signal to notify that a peer P2P Device is requesting bootstrapping
2342 * negotiation with us.
2343 */
wpas_dbus_signal_p2p_bootstrap_req(struct wpa_supplicant * wpa_s,const u8 * src,u16 bootstrap_method)2344 void wpas_dbus_signal_p2p_bootstrap_req(struct wpa_supplicant *wpa_s,
2345 const u8 *src, u16 bootstrap_method)
2346 {
2347 DBusMessage *msg;
2348 DBusMessageIter iter;
2349 struct wpas_dbus_priv *iface;
2350 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
2351
2352 iface = wpa_s->global->dbus;
2353
2354 /* Do nothing if the control interface is not turned on */
2355 if (!iface)
2356 return;
2357
2358 if (wpa_s->p2p_mgmt)
2359 wpa_s = wpa_s->parent;
2360 if (!wpa_s->dbus_new_path)
2361 return;
2362
2363 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2364 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
2365 wpa_s->dbus_new_path, MAC2STR(src));
2366 path = peer_obj_path;
2367
2368 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
2369 WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2370 "BootstrappingRequest");
2371 if (!msg)
2372 return;
2373
2374 dbus_message_iter_init_append(msg, &iter);
2375
2376 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
2377 &path) ||
2378 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT16,
2379 &bootstrap_method))
2380 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
2381 else
2382 dbus_connection_send(iface->con, msg, NULL);
2383
2384 dbus_message_unref(msg);
2385 }
2386
2387
2388 /**
2389 * wpas_dbus_signal_p2p_bootstrap_rsp - Signals BootstrappingResponse event
2390 * @wpa_s: %wpa_supplicant network interface data
2391 * @src: Source address of the peer with which bootstrapping is done
2392 * @status: Status of Bootstrapping handshake
2393 * @bootstrap_method: Peer's bootstrap method if status is success
2394 *
2395 * Sends a signal to notify that a peer P2P Device is requesting bootstrapping
2396 * negotiation with us.
2397 */
wpas_dbus_signal_p2p_bootstrap_rsp(struct wpa_supplicant * wpa_s,const u8 * src,int status,u16 bootstrap_method)2398 void wpas_dbus_signal_p2p_bootstrap_rsp(struct wpa_supplicant *wpa_s,
2399 const u8 *src, int status,
2400 u16 bootstrap_method)
2401 {
2402 DBusMessage *msg;
2403 DBusMessageIter iter;
2404 struct wpas_dbus_priv *iface;
2405 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
2406
2407 iface = wpa_s->global->dbus;
2408
2409 /* Do nothing if the control interface is not turned on */
2410 if (!iface)
2411 return;
2412
2413 if (wpa_s->p2p_mgmt)
2414 wpa_s = wpa_s->parent;
2415 if (!wpa_s->dbus_new_path)
2416 return;
2417
2418 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2419 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
2420 wpa_s->dbus_new_path, MAC2STR(src));
2421 path = peer_obj_path;
2422
2423 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
2424 WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2425 "BootstrappingCompleted");
2426 if (!msg)
2427 return;
2428
2429 dbus_message_iter_init_append(msg, &iter);
2430
2431 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
2432 &path) ||
2433 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32,
2434 &status) ||
2435 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT16,
2436 &bootstrap_method))
2437 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
2438 else
2439 dbus_connection_send(iface->con, msg, NULL);
2440
2441 dbus_message_unref(msg);
2442 }
2443
2444
2445 #endif /* CONFIG_P2P */
2446
2447
2448 /**
2449 * wpas_dbus_signal_prop_changed - Signals change of property
2450 * @wpa_s: %wpa_supplicant network interface data
2451 * @property: indicates which property has changed
2452 *
2453 * Sends PropertyChanged signals with path, interface and arguments
2454 * depending on which property has changed.
2455 */
wpas_dbus_signal_prop_changed(struct wpa_supplicant * wpa_s,enum wpas_dbus_prop property)2456 void wpas_dbus_signal_prop_changed(struct wpa_supplicant *wpa_s,
2457 enum wpas_dbus_prop property)
2458 {
2459 char *prop;
2460 dbus_bool_t flush;
2461
2462 if (wpa_s->dbus_new_path == NULL)
2463 return; /* Skip signal since D-Bus setup is not yet ready */
2464
2465 flush = FALSE;
2466 switch (property) {
2467 case WPAS_DBUS_PROP_AP_SCAN:
2468 prop = "ApScan";
2469 break;
2470 case WPAS_DBUS_PROP_SCANNING:
2471 prop = "Scanning";
2472 break;
2473 case WPAS_DBUS_PROP_STATE:
2474 prop = "State";
2475 break;
2476 case WPAS_DBUS_PROP_CURRENT_BSS:
2477 prop = "CurrentBSS";
2478 break;
2479 case WPAS_DBUS_PROP_CURRENT_NETWORK:
2480 prop = "CurrentNetwork";
2481 break;
2482 case WPAS_DBUS_PROP_BSSS:
2483 prop = "BSSs";
2484 break;
2485 case WPAS_DBUS_PROP_STATIONS:
2486 prop = "Stations";
2487 break;
2488 case WPAS_DBUS_PROP_CURRENT_AUTH_MODE:
2489 prop = "CurrentAuthMode";
2490 break;
2491 case WPAS_DBUS_PROP_DISCONNECT_REASON:
2492 prop = "DisconnectReason";
2493 flush = TRUE;
2494 break;
2495 case WPAS_DBUS_PROP_AUTH_STATUS_CODE:
2496 prop = "AuthStatusCode";
2497 flush = TRUE;
2498 break;
2499 case WPAS_DBUS_PROP_ASSOC_STATUS_CODE:
2500 prop = "AssocStatusCode";
2501 flush = TRUE;
2502 break;
2503 case WPAS_DBUS_PROP_ROAM_TIME:
2504 prop = "RoamTime";
2505 break;
2506 case WPAS_DBUS_PROP_ROAM_COMPLETE:
2507 prop = "RoamComplete";
2508 break;
2509 case WPAS_DBUS_PROP_SCAN_IN_PROGRESS_6GHZ:
2510 prop = "ScanInProgress6GHz";
2511 flush = TRUE;
2512 break;
2513 case WPAS_DBUS_PROP_SESSION_LENGTH:
2514 prop = "SessionLength";
2515 break;
2516 case WPAS_DBUS_PROP_BSS_TM_STATUS:
2517 prop = "BSSTMStatus";
2518 break;
2519 case WPAS_DBUS_PROP_MAC_ADDRESS:
2520 prop = "MACAddress";
2521 break;
2522 case WPAS_DBUS_PROP_SIGNAL_CHANGE:
2523 prop = "SignalChange";
2524 break;
2525 default:
2526 wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d",
2527 __func__, property);
2528 return;
2529 }
2530
2531 wpa_dbus_mark_property_changed(wpa_s->global->dbus,
2532 wpa_s->dbus_new_path,
2533 WPAS_DBUS_NEW_IFACE_INTERFACE, prop);
2534 if (flush) {
2535 wpa_dbus_flush_object_changed_properties(
2536 wpa_s->global->dbus->con, wpa_s->dbus_new_path);
2537 }
2538 }
2539
2540
2541 /**
2542 * wpas_dbus_bss_signal_prop_changed - Signals change of BSS property
2543 * @wpa_s: %wpa_supplicant network interface data
2544 * @property: indicates which property has changed
2545 * @id: unique BSS identifier
2546 *
2547 * Sends PropertyChanged signals with path, interface, and arguments depending
2548 * on which property has changed.
2549 */
wpas_dbus_bss_signal_prop_changed(struct wpa_supplicant * wpa_s,enum wpas_dbus_bss_prop property,unsigned int id)2550 void wpas_dbus_bss_signal_prop_changed(struct wpa_supplicant *wpa_s,
2551 enum wpas_dbus_bss_prop property,
2552 unsigned int id)
2553 {
2554 char path[WPAS_DBUS_OBJECT_PATH_MAX];
2555 char *prop;
2556
2557 if (!wpa_s->dbus_new_path)
2558 return;
2559
2560 switch (property) {
2561 case WPAS_DBUS_BSS_PROP_SIGNAL:
2562 prop = "Signal";
2563 break;
2564 case WPAS_DBUS_BSS_PROP_FREQ:
2565 prop = "Frequency";
2566 break;
2567 case WPAS_DBUS_BSS_PROP_MODE:
2568 prop = "Mode";
2569 break;
2570 case WPAS_DBUS_BSS_PROP_PRIVACY:
2571 prop = "Privacy";
2572 break;
2573 case WPAS_DBUS_BSS_PROP_RATES:
2574 prop = "Rates";
2575 break;
2576 case WPAS_DBUS_BSS_PROP_WPA:
2577 prop = "WPA";
2578 break;
2579 case WPAS_DBUS_BSS_PROP_RSN:
2580 prop = "RSN";
2581 break;
2582 case WPAS_DBUS_BSS_PROP_WPS:
2583 prop = "WPS";
2584 break;
2585 case WPAS_DBUS_BSS_PROP_IES:
2586 prop = "IEs";
2587 break;
2588 case WPAS_DBUS_BSS_PROP_AGE:
2589 prop = "Age";
2590 break;
2591 case WPAS_DBUS_BSS_PROP_ANQP:
2592 prop = "ANQP";
2593 break;
2594 default:
2595 wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d",
2596 __func__, property);
2597 return;
2598 }
2599
2600 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
2601 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
2602 wpa_s->dbus_new_path, id);
2603
2604 wpa_dbus_mark_property_changed(wpa_s->global->dbus, path,
2605 WPAS_DBUS_NEW_IFACE_BSS, prop);
2606 }
2607
2608
2609 /**
2610 * wpas_dbus_signal_debug_level_changed - Signals change of debug param
2611 * @global: wpa_global structure
2612 *
2613 * Sends PropertyChanged signals informing that debug level has changed.
2614 */
wpas_dbus_signal_debug_level_changed(struct wpa_global * global)2615 void wpas_dbus_signal_debug_level_changed(struct wpa_global *global)
2616 {
2617 wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
2618 WPAS_DBUS_NEW_INTERFACE,
2619 "DebugLevel");
2620 }
2621
2622
2623 /**
2624 * wpas_dbus_signal_debug_timestamp_changed - Signals change of debug param
2625 * @global: wpa_global structure
2626 *
2627 * Sends PropertyChanged signals informing that debug timestamp has changed.
2628 */
wpas_dbus_signal_debug_timestamp_changed(struct wpa_global * global)2629 void wpas_dbus_signal_debug_timestamp_changed(struct wpa_global *global)
2630 {
2631 wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
2632 WPAS_DBUS_NEW_INTERFACE,
2633 "DebugTimestamp");
2634 }
2635
2636
2637 /**
2638 * wpas_dbus_signal_debug_show_keys_changed - Signals change of debug param
2639 * @global: wpa_global structure
2640 *
2641 * Sends PropertyChanged signals informing that debug show_keys has changed.
2642 */
wpas_dbus_signal_debug_show_keys_changed(struct wpa_global * global)2643 void wpas_dbus_signal_debug_show_keys_changed(struct wpa_global *global)
2644 {
2645 wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
2646 WPAS_DBUS_NEW_INTERFACE,
2647 "DebugShowKeys");
2648 }
2649
2650
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)2651 static void wpas_dbus_register(struct wpa_dbus_object_desc *obj_desc,
2652 void *priv,
2653 WPADBusArgumentFreeFunction priv_free,
2654 const struct wpa_dbus_method_desc *methods,
2655 const struct wpa_dbus_property_desc *properties,
2656 const struct wpa_dbus_signal_desc *signals)
2657 {
2658 int n;
2659
2660 obj_desc->user_data = priv;
2661 obj_desc->user_data_free_func = priv_free;
2662 obj_desc->methods = methods;
2663 obj_desc->properties = properties;
2664 obj_desc->signals = signals;
2665
2666 for (n = 0; properties && properties->dbus_property; properties++)
2667 n++;
2668
2669 obj_desc->prop_changed_flags = os_zalloc(n);
2670 if (!obj_desc->prop_changed_flags)
2671 wpa_printf(MSG_DEBUG, "dbus: %s: can't register handlers",
2672 __func__);
2673 }
2674
2675
2676 static const struct wpa_dbus_method_desc wpas_dbus_global_methods[] = {
2677 { "CreateInterface", WPAS_DBUS_NEW_INTERFACE,
2678 (WPADBusMethodHandler) wpas_dbus_handler_create_interface,
2679 {
2680 { "args", "a{sv}", ARG_IN },
2681 { "path", "o", ARG_OUT },
2682 END_ARGS
2683 }
2684 },
2685 { "RemoveInterface", WPAS_DBUS_NEW_INTERFACE,
2686 (WPADBusMethodHandler) wpas_dbus_handler_remove_interface,
2687 {
2688 { "path", "o", ARG_IN },
2689 END_ARGS
2690 }
2691 },
2692 { "GetInterface", WPAS_DBUS_NEW_INTERFACE,
2693 (WPADBusMethodHandler) wpas_dbus_handler_get_interface,
2694 {
2695 { "ifname", "s", ARG_IN },
2696 { "path", "o", ARG_OUT },
2697 END_ARGS
2698 }
2699 },
2700 { "ExpectDisconnect", WPAS_DBUS_NEW_INTERFACE,
2701 (WPADBusMethodHandler) wpas_dbus_handler_expect_disconnect,
2702 {
2703 END_ARGS
2704 }
2705 },
2706 { NULL, NULL, NULL, { END_ARGS } }
2707 };
2708
2709 static const struct wpa_dbus_property_desc wpas_dbus_global_properties[] = {
2710 { "DebugLevel", WPAS_DBUS_NEW_INTERFACE, "s",
2711 wpas_dbus_getter_debug_level,
2712 wpas_dbus_setter_debug_level,
2713 NULL
2714 },
2715 { "DebugTimestamp", WPAS_DBUS_NEW_INTERFACE, "b",
2716 wpas_dbus_getter_debug_timestamp,
2717 wpas_dbus_setter_debug_timestamp,
2718 NULL
2719 },
2720 { "DebugShowKeys", WPAS_DBUS_NEW_INTERFACE, "b",
2721 wpas_dbus_getter_debug_show_keys,
2722 wpas_dbus_setter_debug_show_keys,
2723 NULL
2724 },
2725 { "Interfaces", WPAS_DBUS_NEW_INTERFACE, "ao",
2726 wpas_dbus_getter_interfaces,
2727 NULL,
2728 NULL
2729 },
2730 { "EapMethods", WPAS_DBUS_NEW_INTERFACE, "as",
2731 wpas_dbus_getter_eap_methods,
2732 NULL,
2733 NULL
2734 },
2735 { "Capabilities", WPAS_DBUS_NEW_INTERFACE, "as",
2736 wpas_dbus_getter_global_capabilities,
2737 NULL,
2738 NULL
2739 },
2740 #ifdef CONFIG_WIFI_DISPLAY
2741 { "WFDIEs", WPAS_DBUS_NEW_INTERFACE, "ay",
2742 wpas_dbus_getter_global_wfd_ies,
2743 wpas_dbus_setter_global_wfd_ies,
2744 NULL
2745 },
2746 #endif /* CONFIG_WIFI_DISPLAY */
2747 { NULL, NULL, NULL, NULL, NULL, NULL }
2748 };
2749
2750 static const struct wpa_dbus_signal_desc wpas_dbus_global_signals[] = {
2751 { "InterfaceAdded", WPAS_DBUS_NEW_INTERFACE,
2752 {
2753 { "path", "o", ARG_OUT },
2754 { "properties", "a{sv}", ARG_OUT },
2755 END_ARGS
2756 }
2757 },
2758 { "InterfaceRemoved", WPAS_DBUS_NEW_INTERFACE,
2759 {
2760 { "path", "o", ARG_OUT },
2761 END_ARGS
2762 }
2763 },
2764 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
2765 { "PropertiesChanged", WPAS_DBUS_NEW_INTERFACE,
2766 {
2767 { "properties", "a{sv}", ARG_OUT },
2768 END_ARGS
2769 }
2770 },
2771 { NULL, NULL, { END_ARGS } }
2772 };
2773
2774
uscore_to_dbus(const char * uscore)2775 static char * uscore_to_dbus(const char *uscore)
2776 {
2777 const char *p = uscore;
2778 char *str, *s;
2779 dbus_bool_t last_was_uscore = TRUE;
2780
2781 s = str = os_zalloc(os_strlen(uscore) + 1);
2782 if (!str)
2783 return NULL;
2784 while (p && *p) {
2785 if (*p == '_') {
2786 last_was_uscore = TRUE;
2787 } else {
2788 *s++ = last_was_uscore ? toupper(*p) : *p;
2789 last_was_uscore = FALSE;
2790 }
2791 p++;
2792 }
2793
2794 return str;
2795 }
2796
2797
2798 static int wpa_dbus_ctrl_iface_props_init(struct wpas_dbus_priv *priv);
2799
2800
wpa_dbus_ctrl_iface_props_deinit(struct wpas_dbus_priv * priv)2801 static void wpa_dbus_ctrl_iface_props_deinit(struct wpas_dbus_priv *priv)
2802 {
2803 int idx = priv->globals_start;
2804
2805 /* Free all allocated property values */
2806 while (priv->all_interface_properties[idx].dbus_property)
2807 os_free((char *)
2808 priv->all_interface_properties[idx++].dbus_property);
2809 os_free((char *) priv->all_interface_properties);
2810 }
2811
2812
2813 /**
2814 * wpas_dbus_ctrl_iface_init - Initialize dbus control interface
2815 * @global: Pointer to global data from wpa_supplicant_init()
2816 * Returns: 0 on success or -1 on failure
2817 *
2818 * Initialize the dbus control interface for wpa_supplicant and start
2819 * receiving commands from external programs over the bus.
2820 */
wpas_dbus_ctrl_iface_init(struct wpas_dbus_priv * priv)2821 int wpas_dbus_ctrl_iface_init(struct wpas_dbus_priv *priv)
2822 {
2823 struct wpa_dbus_object_desc *obj_desc;
2824 int ret;
2825
2826 ret = wpa_dbus_ctrl_iface_props_init(priv);
2827 if (ret < 0) {
2828 wpa_printf(MSG_ERROR,
2829 "dbus: Not enough memory to init interface properties");
2830 return -1;
2831 }
2832
2833 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
2834 if (!obj_desc) {
2835 wpa_printf(MSG_ERROR,
2836 "Not enough memory to create object description");
2837 goto error;
2838 }
2839
2840 wpas_dbus_register(obj_desc, priv->global, NULL,
2841 wpas_dbus_global_methods,
2842 wpas_dbus_global_properties,
2843 wpas_dbus_global_signals);
2844
2845 wpa_printf(MSG_DEBUG, "dbus: Register D-Bus object '%s'",
2846 WPAS_DBUS_NEW_PATH);
2847 ret = wpa_dbus_ctrl_iface_init(priv, WPAS_DBUS_NEW_PATH,
2848 WPAS_DBUS_NEW_SERVICE,
2849 obj_desc);
2850 if (ret < 0) {
2851 free_dbus_object_desc(obj_desc);
2852 goto error;
2853 }
2854
2855 priv->dbus_new_initialized = 1;
2856 return 0;
2857
2858 error:
2859 wpa_dbus_ctrl_iface_props_deinit(priv);
2860 return -1;
2861 }
2862
2863
2864 /**
2865 * wpas_dbus_ctrl_iface_deinit - Deinitialize dbus ctrl interface for
2866 * wpa_supplicant
2867 * @priv: Pointer to dbus private data from wpas_dbus_init()
2868 *
2869 * Deinitialize the dbus control interface that was initialized with
2870 * wpas_dbus_ctrl_iface_init().
2871 */
wpas_dbus_ctrl_iface_deinit(struct wpas_dbus_priv * priv)2872 void wpas_dbus_ctrl_iface_deinit(struct wpas_dbus_priv *priv)
2873 {
2874 if (!priv->dbus_new_initialized)
2875 return;
2876 wpa_printf(MSG_DEBUG, "dbus: Unregister D-Bus object '%s'",
2877 WPAS_DBUS_NEW_PATH);
2878 dbus_connection_unregister_object_path(priv->con, WPAS_DBUS_NEW_PATH);
2879 wpa_dbus_ctrl_iface_props_deinit(priv);
2880 }
2881
2882
wpa_dbus_free(void * ptr)2883 static void wpa_dbus_free(void *ptr)
2884 {
2885 os_free(ptr);
2886 }
2887
2888
2889 static const struct wpa_dbus_property_desc wpas_dbus_network_properties[] = {
2890 { "Properties", WPAS_DBUS_NEW_IFACE_NETWORK, "a{sv}",
2891 wpas_dbus_getter_network_properties,
2892 wpas_dbus_setter_network_properties,
2893 NULL
2894 },
2895 { "Enabled", WPAS_DBUS_NEW_IFACE_NETWORK, "b",
2896 wpas_dbus_getter_enabled,
2897 wpas_dbus_setter_enabled,
2898 NULL
2899 },
2900 { NULL, NULL, NULL, NULL, NULL, NULL }
2901 };
2902
2903
2904 static const struct wpa_dbus_signal_desc wpas_dbus_network_signals[] = {
2905 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
2906 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_NETWORK,
2907 {
2908 { "properties", "a{sv}", ARG_OUT },
2909 END_ARGS
2910 }
2911 },
2912 { NULL, NULL, { END_ARGS } }
2913 };
2914
2915
2916 /**
2917 * wpas_dbus_register_network - Register a configured network with dbus
2918 * @wpa_s: wpa_supplicant interface structure
2919 * @ssid: network configuration data
2920 * Returns: 0 on success, -1 on failure
2921 *
2922 * Registers network representing object with dbus
2923 */
wpas_dbus_register_network(struct wpa_supplicant * wpa_s,struct wpa_ssid * ssid)2924 int wpas_dbus_register_network(struct wpa_supplicant *wpa_s,
2925 struct wpa_ssid *ssid)
2926 {
2927 struct wpas_dbus_priv *ctrl_iface;
2928 struct wpa_dbus_object_desc *obj_desc;
2929 struct network_handler_args *arg;
2930 char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
2931
2932 #ifdef CONFIG_P2P
2933 /*
2934 * If it is a persistent group register it as such.
2935 * This is to handle cases where an interface is being initialized
2936 * with a list of networks read from config.
2937 */
2938 if (network_is_persistent_group(ssid))
2939 return wpas_dbus_register_persistent_group(wpa_s, ssid);
2940 #endif /* CONFIG_P2P */
2941
2942 /* Do nothing if the control interface is not turned on */
2943 if (wpa_s == NULL || wpa_s->global == NULL || !wpa_s->dbus_new_path)
2944 return 0;
2945 ctrl_iface = wpa_s->global->dbus;
2946 if (ctrl_iface == NULL)
2947 return 0;
2948
2949 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2950 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
2951 wpa_s->dbus_new_path, ssid->id);
2952
2953 wpa_printf(MSG_DEBUG, "dbus: Register network object '%s'",
2954 net_obj_path);
2955 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
2956 if (!obj_desc) {
2957 wpa_printf(MSG_ERROR,
2958 "Not enough memory to create object description");
2959 goto err;
2960 }
2961
2962 /* allocate memory for handlers arguments */
2963 arg = os_zalloc(sizeof(struct network_handler_args));
2964 if (!arg) {
2965 wpa_printf(MSG_ERROR,
2966 "Not enough memory to create arguments for method");
2967 goto err;
2968 }
2969
2970 arg->wpa_s = wpa_s;
2971 arg->ssid = ssid;
2972
2973 wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
2974 wpas_dbus_network_properties,
2975 wpas_dbus_network_signals);
2976
2977 if (wpa_dbus_register_object_per_iface(ctrl_iface, net_obj_path,
2978 wpa_s->ifname, obj_desc))
2979 goto err;
2980
2981 wpas_dbus_signal_network_added(wpa_s, ssid->id);
2982
2983 return 0;
2984
2985 err:
2986 free_dbus_object_desc(obj_desc);
2987 return -1;
2988 }
2989
2990
2991 /**
2992 * wpas_dbus_unregister_network - Unregister a configured network from dbus
2993 * @wpa_s: wpa_supplicant interface structure
2994 * @nid: network id
2995 * Returns: 0 on success, -1 on failure
2996 *
2997 * Unregisters network representing object from dbus
2998 */
wpas_dbus_unregister_network(struct wpa_supplicant * wpa_s,int nid)2999 int wpas_dbus_unregister_network(struct wpa_supplicant *wpa_s, int nid)
3000 {
3001 struct wpas_dbus_priv *ctrl_iface;
3002 char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3003 int ret;
3004 #ifdef CONFIG_P2P
3005 struct wpa_ssid *ssid;
3006
3007 ssid = wpa_config_get_network(wpa_s->conf, nid);
3008
3009 /* If it is a persistent group unregister it as such */
3010 if (ssid && network_is_persistent_group(ssid))
3011 return wpas_dbus_unregister_persistent_group(wpa_s, nid);
3012 #endif /* CONFIG_P2P */
3013
3014 /* Do nothing if the control interface is not turned on */
3015 if (wpa_s->global == NULL || wpa_s->dbus_new_path == NULL)
3016 return 0;
3017 ctrl_iface = wpa_s->global->dbus;
3018 if (ctrl_iface == NULL)
3019 return 0;
3020
3021 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3022 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
3023 wpa_s->dbus_new_path, nid);
3024
3025 wpa_printf(MSG_DEBUG, "dbus: Unregister network object '%s'",
3026 net_obj_path);
3027 ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, net_obj_path);
3028
3029 if (!ret)
3030 wpas_dbus_signal_network_removed(wpa_s, nid);
3031
3032 return ret;
3033 }
3034
3035
3036 static const struct wpa_dbus_property_desc wpas_dbus_bss_properties[] = {
3037 { "SSID", WPAS_DBUS_NEW_IFACE_BSS, "ay",
3038 wpas_dbus_getter_bss_ssid,
3039 NULL,
3040 NULL
3041 },
3042 { "BSSID", WPAS_DBUS_NEW_IFACE_BSS, "ay",
3043 wpas_dbus_getter_bss_bssid,
3044 NULL,
3045 NULL
3046 },
3047 { "Privacy", WPAS_DBUS_NEW_IFACE_BSS, "b",
3048 wpas_dbus_getter_bss_privacy,
3049 NULL,
3050 NULL
3051 },
3052 { "Mode", WPAS_DBUS_NEW_IFACE_BSS, "s",
3053 wpas_dbus_getter_bss_mode,
3054 NULL,
3055 NULL
3056 },
3057 { "Signal", WPAS_DBUS_NEW_IFACE_BSS, "n",
3058 wpas_dbus_getter_bss_signal,
3059 NULL,
3060 NULL
3061 },
3062 { "Frequency", WPAS_DBUS_NEW_IFACE_BSS, "q",
3063 wpas_dbus_getter_bss_frequency,
3064 NULL,
3065 NULL
3066 },
3067 { "Rates", WPAS_DBUS_NEW_IFACE_BSS, "au",
3068 wpas_dbus_getter_bss_rates,
3069 NULL,
3070 NULL
3071 },
3072 { "WPA", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
3073 wpas_dbus_getter_bss_wpa,
3074 NULL,
3075 NULL
3076 },
3077 { "RSN", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
3078 wpas_dbus_getter_bss_rsn,
3079 NULL,
3080 NULL
3081 },
3082 { "WPS", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
3083 wpas_dbus_getter_bss_wps,
3084 NULL,
3085 NULL
3086 },
3087 { "IEs", WPAS_DBUS_NEW_IFACE_BSS, "ay",
3088 wpas_dbus_getter_bss_ies,
3089 NULL,
3090 NULL
3091 },
3092 { "Age", WPAS_DBUS_NEW_IFACE_BSS, "u",
3093 wpas_dbus_getter_bss_age,
3094 NULL,
3095 NULL
3096 },
3097 {"ANQP", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
3098 wpas_dbus_getter_bss_anqp,
3099 NULL,
3100 NULL,
3101 },
3102 { NULL, NULL, NULL, NULL, NULL, NULL }
3103 };
3104
3105
3106 static const struct wpa_dbus_signal_desc wpas_dbus_bss_signals[] = {
3107 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
3108 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_BSS,
3109 {
3110 { "properties", "a{sv}", ARG_OUT },
3111 END_ARGS
3112 }
3113 },
3114 { NULL, NULL, { END_ARGS } }
3115 };
3116
3117
3118 /**
3119 * wpas_dbus_unregister_bss - Unregister a scanned BSS from dbus
3120 * @wpa_s: wpa_supplicant interface structure
3121 * @bssid: scanned network bssid
3122 * @id: unique BSS identifier
3123 * Returns: 0 on success, -1 on failure
3124 *
3125 * Unregisters BSS representing object from dbus
3126 */
wpas_dbus_unregister_bss(struct wpa_supplicant * wpa_s,u8 bssid[ETH_ALEN],unsigned int id)3127 int wpas_dbus_unregister_bss(struct wpa_supplicant *wpa_s,
3128 u8 bssid[ETH_ALEN], unsigned int id)
3129 {
3130 struct wpas_dbus_priv *ctrl_iface;
3131 char bss_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3132
3133 /* Do nothing if the control interface is not turned on */
3134 if (wpa_s == NULL || wpa_s->global == NULL || !wpa_s->dbus_new_path)
3135 return 0;
3136 ctrl_iface = wpa_s->global->dbus;
3137 if (ctrl_iface == NULL)
3138 return 0;
3139
3140 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3141 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
3142 wpa_s->dbus_new_path, id);
3143
3144 wpa_printf(MSG_DEBUG, "dbus: Unregister BSS object '%s'",
3145 bss_obj_path);
3146 if (wpa_dbus_unregister_object_per_iface(ctrl_iface, bss_obj_path)) {
3147 wpa_printf(MSG_ERROR, "dbus: Cannot unregister BSS object %s",
3148 bss_obj_path);
3149 return -1;
3150 }
3151
3152 wpas_dbus_signal_bss_removed(wpa_s, bss_obj_path);
3153 wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_BSSS);
3154
3155 return 0;
3156 }
3157
3158
3159 /**
3160 * wpas_dbus_register_bss - Register a scanned BSS with dbus
3161 * @wpa_s: wpa_supplicant interface structure
3162 * @bssid: scanned network bssid
3163 * @id: unique BSS identifier
3164 * Returns: 0 on success, -1 on failure
3165 *
3166 * Registers BSS representing object with dbus
3167 */
wpas_dbus_register_bss(struct wpa_supplicant * wpa_s,u8 bssid[ETH_ALEN],unsigned int id)3168 int wpas_dbus_register_bss(struct wpa_supplicant *wpa_s,
3169 u8 bssid[ETH_ALEN], unsigned int id)
3170 {
3171 struct wpas_dbus_priv *ctrl_iface;
3172 struct wpa_dbus_object_desc *obj_desc;
3173 char bss_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3174 struct bss_handler_args *arg;
3175
3176 /* Do nothing if the control interface is not turned on */
3177 if (wpa_s == NULL || wpa_s->global == NULL || !wpa_s->dbus_new_path)
3178 return 0;
3179 ctrl_iface = wpa_s->global->dbus;
3180 if (ctrl_iface == NULL)
3181 return 0;
3182
3183 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3184 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
3185 wpa_s->dbus_new_path, id);
3186
3187 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
3188 if (!obj_desc) {
3189 wpa_printf(MSG_ERROR,
3190 "Not enough memory to create object description");
3191 goto err;
3192 }
3193
3194 arg = os_zalloc(sizeof(struct bss_handler_args));
3195 if (!arg) {
3196 wpa_printf(MSG_ERROR,
3197 "Not enough memory to create arguments for handler");
3198 goto err;
3199 }
3200 arg->wpa_s = wpa_s;
3201 arg->id = id;
3202
3203 wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
3204 wpas_dbus_bss_properties,
3205 wpas_dbus_bss_signals);
3206
3207 wpa_printf(MSG_DEBUG, "dbus: Register BSS object '%s'",
3208 bss_obj_path);
3209 if (wpa_dbus_register_object_per_iface(ctrl_iface, bss_obj_path,
3210 wpa_s->ifname, obj_desc)) {
3211 wpa_printf(MSG_ERROR,
3212 "Cannot register BSSID dbus object %s.",
3213 bss_obj_path);
3214 goto err;
3215 }
3216
3217 wpas_dbus_signal_bss_added(wpa_s, bss_obj_path);
3218 wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_BSSS);
3219
3220 return 0;
3221
3222 err:
3223 free_dbus_object_desc(obj_desc);
3224 return -1;
3225 }
3226
3227
3228 static const struct wpa_dbus_property_desc wpas_dbus_sta_properties[] = {
3229 { "Address", WPAS_DBUS_NEW_IFACE_STA, "ay",
3230 wpas_dbus_getter_sta_address,
3231 NULL, NULL
3232 },
3233 { "AID", WPAS_DBUS_NEW_IFACE_STA, "q",
3234 wpas_dbus_getter_sta_aid,
3235 NULL, NULL
3236 },
3237 { "Capabilities", WPAS_DBUS_NEW_IFACE_STA, "q",
3238 wpas_dbus_getter_sta_caps,
3239 NULL, NULL
3240 },
3241 { "RxPackets", WPAS_DBUS_NEW_IFACE_STA, "t",
3242 wpas_dbus_getter_sta_rx_packets,
3243 NULL, NULL
3244 },
3245 { "TxPackets", WPAS_DBUS_NEW_IFACE_STA, "t",
3246 wpas_dbus_getter_sta_tx_packets,
3247 NULL, NULL
3248 },
3249 { "RxBytes", WPAS_DBUS_NEW_IFACE_STA, "t",
3250 wpas_dbus_getter_sta_rx_bytes,
3251 NULL, NULL
3252 },
3253 { "TxBytes", WPAS_DBUS_NEW_IFACE_STA, "t",
3254 wpas_dbus_getter_sta_tx_bytes,
3255 NULL, NULL
3256 },
3257 { NULL, NULL, NULL, NULL, NULL, NULL }
3258 };
3259
3260
3261 static const struct wpa_dbus_signal_desc wpas_dbus_sta_signals[] = {
3262 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
3263 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_STA,
3264 {
3265 { "properties", "a{sv}", ARG_OUT },
3266 END_ARGS
3267 }
3268 },
3269 { NULL, NULL, { END_ARGS } }
3270 };
3271
3272
3273 /**
3274 * wpas_dbus_unregister_sta - Unregister a connected station from dbus
3275 * @wpa_s: wpa_supplicant interface structure
3276 * @sta: station MAC address
3277 * Returns: 0 on success, -1 on failure
3278 *
3279 * Unregisters STA representing object from dbus.
3280 */
wpas_dbus_unregister_sta(struct wpa_supplicant * wpa_s,const u8 * sta)3281 int wpas_dbus_unregister_sta(struct wpa_supplicant *wpa_s, const u8 *sta)
3282 {
3283 struct wpas_dbus_priv *ctrl_iface;
3284 char station_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3285
3286 /* Do nothing if the control interface is not turned on */
3287 if (!wpa_s || !wpa_s->global)
3288 return 0;
3289 ctrl_iface = wpa_s->global->dbus;
3290 if (!ctrl_iface)
3291 return 0;
3292
3293 os_snprintf(station_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3294 "%s/" WPAS_DBUS_NEW_STAS_PART "/" COMPACT_MACSTR,
3295 wpa_s->dbus_new_path, MAC2STR(sta));
3296
3297 wpa_printf(MSG_DEBUG, "dbus: Unregister STA object '%s'",
3298 station_obj_path);
3299 if (wpa_dbus_unregister_object_per_iface(ctrl_iface,
3300 station_obj_path)) {
3301 wpa_printf(MSG_ERROR, "dbus: Cannot unregister STA object %s",
3302 station_obj_path);
3303 return -1;
3304 }
3305
3306 wpas_dbus_signal_station_removed(wpa_s, station_obj_path);
3307 wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_STATIONS);
3308
3309 return 0;
3310 }
3311
3312
3313 /**
3314 * wpas_dbus_register_sta - Register a connected station with dbus
3315 * @wpa_s: wpa_supplicant interface structure
3316 * @sta: station MAC address
3317 * Returns: 0 on success, -1 on failure
3318 *
3319 * Registers STA representing object with dbus.
3320 */
wpas_dbus_register_sta(struct wpa_supplicant * wpa_s,const u8 * sta)3321 int wpas_dbus_register_sta(struct wpa_supplicant *wpa_s, const u8 *sta)
3322 {
3323 struct wpas_dbus_priv *ctrl_iface;
3324 struct wpa_dbus_object_desc *obj_desc;
3325 char station_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3326 struct sta_handler_args *arg;
3327
3328 /* Do nothing if the control interface is not turned on */
3329 if (!wpa_s || !wpa_s->global)
3330 return 0;
3331 ctrl_iface = wpa_s->global->dbus;
3332 if (!ctrl_iface)
3333 return 0;
3334
3335 os_snprintf(station_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3336 "%s/" WPAS_DBUS_NEW_STAS_PART "/" COMPACT_MACSTR,
3337 wpa_s->dbus_new_path, MAC2STR(sta));
3338
3339 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
3340 if (!obj_desc) {
3341 wpa_printf(MSG_ERROR,
3342 "Not enough memory to create object description");
3343 goto err;
3344 }
3345
3346 arg = os_zalloc(sizeof(struct sta_handler_args));
3347 if (!arg) {
3348 wpa_printf(MSG_ERROR,
3349 "Not enough memory to create arguments for handler");
3350 goto err;
3351 }
3352 arg->wpa_s = wpa_s;
3353 arg->sta = sta;
3354
3355 wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
3356 wpas_dbus_sta_properties, wpas_dbus_sta_signals);
3357
3358 wpa_printf(MSG_DEBUG, "dbus: Register STA object '%s'",
3359 station_obj_path);
3360 if (wpa_dbus_register_object_per_iface(ctrl_iface, station_obj_path,
3361 wpa_s->ifname, obj_desc)) {
3362 wpa_printf(MSG_ERROR,
3363 "Cannot register STA dbus object %s",
3364 station_obj_path);
3365 goto err;
3366 }
3367
3368 wpas_dbus_signal_station_added(wpa_s, station_obj_path);
3369 wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_STATIONS);
3370
3371 return 0;
3372
3373 err:
3374 free_dbus_object_desc(obj_desc);
3375 return -1;
3376 }
3377
3378
3379 static const struct wpa_dbus_method_desc wpas_dbus_interface_methods[] = {
3380 { "Scan", WPAS_DBUS_NEW_IFACE_INTERFACE,
3381 (WPADBusMethodHandler) wpas_dbus_handler_scan,
3382 {
3383 { "args", "a{sv}", ARG_IN },
3384 END_ARGS
3385 }
3386 },
3387 { "SignalPoll", WPAS_DBUS_NEW_IFACE_INTERFACE,
3388 (WPADBusMethodHandler) wpas_dbus_handler_signal_poll,
3389 {
3390 { "args", "a{sv}", ARG_OUT },
3391 END_ARGS
3392 }
3393 },
3394 { "Disconnect", WPAS_DBUS_NEW_IFACE_INTERFACE,
3395 (WPADBusMethodHandler) wpas_dbus_handler_disconnect,
3396 {
3397 END_ARGS
3398 }
3399 },
3400 { "AddNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
3401 (WPADBusMethodHandler) wpas_dbus_handler_add_network,
3402 {
3403 { "args", "a{sv}", ARG_IN },
3404 { "path", "o", ARG_OUT },
3405 END_ARGS
3406 }
3407 },
3408 { "Reassociate", WPAS_DBUS_NEW_IFACE_INTERFACE,
3409 (WPADBusMethodHandler) wpas_dbus_handler_reassociate,
3410 {
3411 END_ARGS
3412 }
3413 },
3414 { "Reattach", WPAS_DBUS_NEW_IFACE_INTERFACE,
3415 (WPADBusMethodHandler) wpas_dbus_handler_reattach,
3416 {
3417 END_ARGS
3418 }
3419 },
3420 { "Reconnect", WPAS_DBUS_NEW_IFACE_INTERFACE,
3421 (WPADBusMethodHandler) wpas_dbus_handler_reconnect,
3422 {
3423 END_ARGS
3424 }
3425 },
3426 { "RemoveNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
3427 (WPADBusMethodHandler) wpas_dbus_handler_remove_network,
3428 {
3429 { "path", "o", ARG_IN },
3430 END_ARGS
3431 }
3432 },
3433 { "RemoveAllNetworks", WPAS_DBUS_NEW_IFACE_INTERFACE,
3434 (WPADBusMethodHandler) wpas_dbus_handler_remove_all_networks,
3435 {
3436 END_ARGS
3437 }
3438 },
3439 { "SelectNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
3440 (WPADBusMethodHandler) wpas_dbus_handler_select_network,
3441 {
3442 { "path", "o", ARG_IN },
3443 END_ARGS
3444 }
3445 },
3446 { "NetworkReply", WPAS_DBUS_NEW_IFACE_INTERFACE,
3447 (WPADBusMethodHandler) wpas_dbus_handler_network_reply,
3448 {
3449 { "path", "o", ARG_IN },
3450 { "field", "s", ARG_IN },
3451 { "value", "s", ARG_IN },
3452 END_ARGS
3453 }
3454 },
3455 { "Roam", WPAS_DBUS_NEW_IFACE_INTERFACE,
3456 (WPADBusMethodHandler) wpas_dbus_handler_roam,
3457 {
3458 { "addr", "s", ARG_IN },
3459 END_ARGS
3460 }
3461 },
3462
3463 #ifndef CONFIG_NO_CONFIG_BLOBS
3464 { "AddBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
3465 (WPADBusMethodHandler) wpas_dbus_handler_add_blob,
3466 {
3467 { "name", "s", ARG_IN },
3468 { "data", "ay", ARG_IN },
3469 END_ARGS
3470 }
3471 },
3472 { "GetBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
3473 (WPADBusMethodHandler) wpas_dbus_handler_get_blob,
3474 {
3475 { "name", "s", ARG_IN },
3476 { "data", "ay", ARG_OUT },
3477 END_ARGS
3478 }
3479 },
3480 { "RemoveBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
3481 (WPADBusMethodHandler) wpas_dbus_handler_remove_blob,
3482 {
3483 { "name", "s", ARG_IN },
3484 END_ARGS
3485 }
3486 },
3487 #endif /* CONFIG_NO_CONFIG_BLOBS */
3488 { "SetPKCS11EngineAndModulePath", WPAS_DBUS_NEW_IFACE_INTERFACE,
3489 (WPADBusMethodHandler)
3490 wpas_dbus_handler_set_pkcs11_engine_and_module_path,
3491 {
3492 { "pkcs11_engine_path", "s", ARG_IN },
3493 { "pkcs11_module_path", "s", ARG_IN },
3494 END_ARGS
3495 }
3496 },
3497 #ifdef CONFIG_WPS
3498 { "Start", WPAS_DBUS_NEW_IFACE_WPS,
3499 (WPADBusMethodHandler) wpas_dbus_handler_wps_start,
3500 {
3501 { "args", "a{sv}", ARG_IN },
3502 { "output", "a{sv}", ARG_OUT },
3503 END_ARGS
3504 }
3505 },
3506 { "Cancel", WPAS_DBUS_NEW_IFACE_WPS,
3507 (WPADBusMethodHandler) wpas_dbus_handler_wps_cancel,
3508 {
3509 END_ARGS
3510 }
3511 },
3512 #endif /* CONFIG_WPS */
3513 #ifdef CONFIG_P2P
3514 { "Find", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3515 (WPADBusMethodHandler) wpas_dbus_handler_p2p_find,
3516 {
3517 { "args", "a{sv}", ARG_IN },
3518 END_ARGS
3519 }
3520 },
3521 { "StopFind", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3522 (WPADBusMethodHandler) wpas_dbus_handler_p2p_stop_find,
3523 {
3524 END_ARGS
3525 }
3526 },
3527 { "Listen", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3528 (WPADBusMethodHandler) wpas_dbus_handler_p2p_listen,
3529 {
3530 { "timeout", "i", ARG_IN },
3531 END_ARGS
3532 }
3533 },
3534 { "ExtendedListen", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3535 (WPADBusMethodHandler) wpas_dbus_handler_p2p_extendedlisten,
3536 {
3537 { "args", "a{sv}", ARG_IN },
3538 END_ARGS
3539 }
3540 },
3541 { "PresenceRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3542 (WPADBusMethodHandler) wpas_dbus_handler_p2p_presence_request,
3543 {
3544 { "args", "a{sv}", ARG_IN },
3545 END_ARGS
3546 }
3547 },
3548 { "ProvisionDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3549 (WPADBusMethodHandler) wpas_dbus_handler_p2p_prov_disc_req,
3550 {
3551 { "peer", "o", ARG_IN },
3552 { "config_method", "s", ARG_IN },
3553 END_ARGS
3554 }
3555 },
3556 { "Connect", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3557 (WPADBusMethodHandler) wpas_dbus_handler_p2p_connect,
3558 {
3559 { "args", "a{sv}", ARG_IN },
3560 { "generated_pin", "s", ARG_OUT },
3561 END_ARGS
3562 }
3563 },
3564 { "GroupAdd", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3565 (WPADBusMethodHandler) wpas_dbus_handler_p2p_group_add,
3566 {
3567 { "args", "a{sv}", ARG_IN },
3568 END_ARGS
3569 }
3570 },
3571 { "Cancel", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3572 (WPADBusMethodHandler) wpas_dbus_handler_p2p_cancel,
3573 {
3574 END_ARGS
3575 }
3576 },
3577 { "Invite", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3578 (WPADBusMethodHandler) wpas_dbus_handler_p2p_invite,
3579 {
3580 { "args", "a{sv}", ARG_IN },
3581 END_ARGS
3582 }
3583 },
3584 { "Disconnect", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3585 (WPADBusMethodHandler) wpas_dbus_handler_p2p_disconnect,
3586 {
3587 END_ARGS
3588 }
3589 },
3590 { "RejectPeer", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3591 (WPADBusMethodHandler) wpas_dbus_handler_p2p_rejectpeer,
3592 {
3593 { "peer", "o", ARG_IN },
3594 END_ARGS
3595 }
3596 },
3597 { "RemoveClient", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3598 (WPADBusMethodHandler) wpas_dbus_handler_p2p_remove_client,
3599 {
3600 { "args", "a{sv}", ARG_IN },
3601 END_ARGS
3602 }
3603 },
3604 { "Flush", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3605 (WPADBusMethodHandler) wpas_dbus_handler_p2p_flush,
3606 {
3607 END_ARGS
3608 }
3609 },
3610 { "AddService", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3611 (WPADBusMethodHandler) wpas_dbus_handler_p2p_add_service,
3612 {
3613 { "args", "a{sv}", ARG_IN },
3614 END_ARGS
3615 }
3616 },
3617 { "DeleteService", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3618 (WPADBusMethodHandler) wpas_dbus_handler_p2p_delete_service,
3619 {
3620 { "args", "a{sv}", ARG_IN },
3621 END_ARGS
3622 }
3623 },
3624 { "FlushService", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3625 (WPADBusMethodHandler) wpas_dbus_handler_p2p_flush_service,
3626 {
3627 END_ARGS
3628 }
3629 },
3630 { "ServiceDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3631 (WPADBusMethodHandler) wpas_dbus_handler_p2p_service_sd_req,
3632 {
3633 { "args", "a{sv}", ARG_IN },
3634 { "ref", "t", ARG_OUT },
3635 END_ARGS
3636 }
3637 },
3638 { "ServiceDiscoveryResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3639 (WPADBusMethodHandler) wpas_dbus_handler_p2p_service_sd_res,
3640 {
3641 { "args", "a{sv}", ARG_IN },
3642 END_ARGS
3643 }
3644 },
3645 { "ServiceDiscoveryCancelRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3646 (WPADBusMethodHandler) wpas_dbus_handler_p2p_service_sd_cancel_req,
3647 {
3648 { "args", "t", ARG_IN },
3649 END_ARGS
3650 }
3651 },
3652 { "ServiceUpdate", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3653 (WPADBusMethodHandler) wpas_dbus_handler_p2p_service_update,
3654 {
3655 END_ARGS
3656 }
3657 },
3658 { "ServiceDiscoveryExternal", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3659 (WPADBusMethodHandler) wpas_dbus_handler_p2p_serv_disc_external,
3660 {
3661 { "arg", "i", ARG_IN },
3662 END_ARGS
3663 }
3664 },
3665 { "AddPersistentGroup", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3666 (WPADBusMethodHandler) wpas_dbus_handler_add_persistent_group,
3667 {
3668 { "args", "a{sv}", ARG_IN },
3669 { "path", "o", ARG_OUT },
3670 END_ARGS
3671 }
3672 },
3673 { "RemovePersistentGroup", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3674 (WPADBusMethodHandler) wpas_dbus_handler_remove_persistent_group,
3675 {
3676 { "path", "o", ARG_IN },
3677 END_ARGS
3678 }
3679 },
3680 { "RemoveAllPersistentGroups", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3681 (WPADBusMethodHandler)
3682 wpas_dbus_handler_remove_all_persistent_groups,
3683 {
3684 END_ARGS
3685 }
3686 },
3687 #endif /* CONFIG_P2P */
3688 { "FlushBSS", WPAS_DBUS_NEW_IFACE_INTERFACE,
3689 (WPADBusMethodHandler) wpas_dbus_handler_flush_bss,
3690 {
3691 { "age", "u", ARG_IN },
3692 END_ARGS
3693 }
3694 },
3695 #ifdef CONFIG_AP
3696 { "SubscribeProbeReq", WPAS_DBUS_NEW_IFACE_INTERFACE,
3697 (WPADBusMethodHandler) wpas_dbus_handler_subscribe_preq,
3698 {
3699 END_ARGS
3700 }
3701 },
3702 { "UnsubscribeProbeReq", WPAS_DBUS_NEW_IFACE_INTERFACE,
3703 (WPADBusMethodHandler) wpas_dbus_handler_unsubscribe_preq,
3704 {
3705 END_ARGS
3706 }
3707 },
3708 #endif /* CONFIG_AP */
3709 { "EAPLogoff", WPAS_DBUS_NEW_IFACE_INTERFACE,
3710 (WPADBusMethodHandler) wpas_dbus_handler_eap_logoff,
3711 {
3712 END_ARGS
3713 }
3714 },
3715 { "EAPLogon", WPAS_DBUS_NEW_IFACE_INTERFACE,
3716 (WPADBusMethodHandler) wpas_dbus_handler_eap_logon,
3717 {
3718 END_ARGS
3719 }
3720 },
3721 #ifdef CONFIG_AUTOSCAN
3722 { "AutoScan", WPAS_DBUS_NEW_IFACE_INTERFACE,
3723 (WPADBusMethodHandler) wpas_dbus_handler_autoscan,
3724 {
3725 { "arg", "s", ARG_IN },
3726 END_ARGS
3727 }
3728 },
3729 #endif /* CONFIG_AUTOSCAN */
3730 #ifdef CONFIG_TDLS
3731 { "TDLSDiscover", WPAS_DBUS_NEW_IFACE_INTERFACE,
3732 (WPADBusMethodHandler) wpas_dbus_handler_tdls_discover,
3733 {
3734 { "peer_address", "s", ARG_IN },
3735 END_ARGS
3736 }
3737 },
3738 { "TDLSSetup", WPAS_DBUS_NEW_IFACE_INTERFACE,
3739 (WPADBusMethodHandler) wpas_dbus_handler_tdls_setup,
3740 {
3741 { "peer_address", "s", ARG_IN },
3742 END_ARGS
3743 }
3744 },
3745 { "TDLSStatus", WPAS_DBUS_NEW_IFACE_INTERFACE,
3746 (WPADBusMethodHandler) wpas_dbus_handler_tdls_status,
3747 {
3748 { "peer_address", "s", ARG_IN },
3749 { "status", "s", ARG_OUT },
3750 END_ARGS
3751 }
3752 },
3753 { "TDLSTeardown", WPAS_DBUS_NEW_IFACE_INTERFACE,
3754 (WPADBusMethodHandler) wpas_dbus_handler_tdls_teardown,
3755 {
3756 { "peer_address", "s", ARG_IN },
3757 END_ARGS
3758 }
3759 },
3760 { "TDLSChannelSwitch", WPAS_DBUS_NEW_IFACE_INTERFACE,
3761 (WPADBusMethodHandler) wpas_dbus_handler_tdls_channel_switch,
3762 {
3763 { "args", "a{sv}", ARG_IN },
3764 END_ARGS
3765 }
3766 },
3767 { "TDLSCancelChannelSwitch", WPAS_DBUS_NEW_IFACE_INTERFACE,
3768 (WPADBusMethodHandler) wpas_dbus_handler_tdls_cancel_channel_switch,
3769 {
3770 { "peer_address", "s", ARG_IN },
3771 END_ARGS
3772 }
3773 },
3774 #endif /* CONFIG_TDLS */
3775 { "VendorElemAdd", WPAS_DBUS_NEW_IFACE_INTERFACE,
3776 (WPADBusMethodHandler) wpas_dbus_handler_vendor_elem_add,
3777 {
3778 { "frame_id", "i", ARG_IN },
3779 { "ielems", "ay", ARG_IN },
3780 END_ARGS
3781 }
3782 },
3783 { "VendorElemGet", WPAS_DBUS_NEW_IFACE_INTERFACE,
3784 (WPADBusMethodHandler) wpas_dbus_handler_vendor_elem_get,
3785 {
3786 { "frame_id", "i", ARG_IN },
3787 { "ielems", "ay", ARG_OUT },
3788 END_ARGS
3789 }
3790 },
3791 { "VendorElemRem", WPAS_DBUS_NEW_IFACE_INTERFACE,
3792 (WPADBusMethodHandler) wpas_dbus_handler_vendor_elem_remove,
3793 {
3794 { "frame_id", "i", ARG_IN },
3795 { "ielems", "ay", ARG_IN },
3796 END_ARGS
3797 }
3798 },
3799 #ifndef CONFIG_NO_CONFIG_WRITE
3800 { "SaveConfig", WPAS_DBUS_NEW_IFACE_INTERFACE,
3801 (WPADBusMethodHandler) wpas_dbus_handler_save_config,
3802 {
3803 END_ARGS
3804 }
3805 },
3806 #endif /* CONFIG_NO_CONFIG_WRITE */
3807 { "AbortScan", WPAS_DBUS_NEW_IFACE_INTERFACE,
3808 (WPADBusMethodHandler) wpas_dbus_handler_abort_scan,
3809 {
3810 END_ARGS
3811 }
3812 },
3813 #ifdef CONFIG_INTERWORKING
3814 { "AddCred", WPAS_DBUS_NEW_IFACE_INTERFACE,
3815 (WPADBusMethodHandler) wpas_dbus_handler_add_cred,
3816 {
3817 { "args", "a{sv}", ARG_IN },
3818 { "path", "o", ARG_OUT },
3819 END_ARGS
3820 }
3821 },
3822 { "RemoveCred", WPAS_DBUS_NEW_IFACE_INTERFACE,
3823 (WPADBusMethodHandler) wpas_dbus_handler_remove_cred,
3824 {
3825 { "path", "o", ARG_IN },
3826 END_ARGS
3827 }
3828 },
3829 { "RemoveAllCreds", WPAS_DBUS_NEW_IFACE_INTERFACE,
3830 (WPADBusMethodHandler) wpas_dbus_handler_remove_all_creds,
3831 {
3832 END_ARGS
3833 }
3834 },
3835 { "InterworkingSelect", WPAS_DBUS_NEW_IFACE_INTERFACE,
3836 (WPADBusMethodHandler) wpas_dbus_handler_interworking_select,
3837 {
3838 END_ARGS
3839 }
3840 },
3841 {"ANQPGet", WPAS_DBUS_NEW_IFACE_INTERFACE,
3842 (WPADBusMethodHandler) wpas_dbus_handler_anqp_get,
3843 {
3844 { "args", "a{sv}", ARG_IN },
3845 END_ARGS
3846 },
3847 },
3848 #endif /* CONFIG_INTERWORKING */
3849 #ifdef CONFIG_NAN_USD
3850 { "NANPublish", WPAS_DBUS_NEW_IFACE_INTERFACE,
3851 (WPADBusMethodHandler) wpas_dbus_handler_nan_publish,
3852 {
3853 { "args", "a{sv}", ARG_IN },
3854 { "publish_id", "u", ARG_OUT },
3855 END_ARGS
3856 }
3857 },
3858 { "NANCancelPublish", WPAS_DBUS_NEW_IFACE_INTERFACE,
3859 (WPADBusMethodHandler) wpas_dbus_handler_nan_cancel_publish,
3860 {
3861 { "publish_id", "u", ARG_IN },
3862 END_ARGS
3863 }
3864 },
3865 { "NANUpdatePublish", WPAS_DBUS_NEW_IFACE_INTERFACE,
3866 (WPADBusMethodHandler) wpas_dbus_handler_nan_update_publish,
3867 {
3868 { "args", "a{sv}", ARG_IN },
3869 END_ARGS
3870 }
3871 },
3872 { "NANSubscribe", WPAS_DBUS_NEW_IFACE_INTERFACE,
3873 (WPADBusMethodHandler) wpas_dbus_handler_nan_subscribe,
3874 {
3875 { "args", "a{sv}", ARG_IN },
3876 { "subscribe_id", "u", ARG_OUT },
3877 END_ARGS
3878 }
3879 },
3880 { "NANCancelSubscribe", WPAS_DBUS_NEW_IFACE_INTERFACE,
3881 (WPADBusMethodHandler) wpas_dbus_handler_nan_cancel_subscribe,
3882 {
3883 { "subscribe_id", "u", ARG_IN },
3884 END_ARGS
3885 }
3886 },
3887 { "NANTransmit", WPAS_DBUS_NEW_IFACE_INTERFACE,
3888 (WPADBusMethodHandler) wpas_dbus_handler_nan_transmit,
3889 {
3890 { "args", "a{sv}", ARG_IN },
3891 END_ARGS
3892 }
3893 },
3894 #endif /* CONFIG_NAN_USD */
3895 { NULL, NULL, NULL, { END_ARGS } }
3896 };
3897
3898 static const struct wpa_dbus_property_desc wpas_dbus_interface_properties[] = {
3899 { "Capabilities", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{sv}",
3900 wpas_dbus_getter_capabilities,
3901 NULL,
3902 NULL
3903 },
3904 { "State", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3905 wpas_dbus_getter_state,
3906 NULL,
3907 NULL
3908 },
3909 { "Scanning", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
3910 wpas_dbus_getter_scanning,
3911 NULL,
3912 NULL
3913 },
3914 { "ApScan", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
3915 wpas_dbus_getter_ap_scan,
3916 wpas_dbus_setter_ap_scan,
3917 NULL
3918 },
3919 { "BSSExpireAge", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
3920 wpas_dbus_getter_bss_expire_age,
3921 wpas_dbus_setter_bss_expire_age,
3922 NULL
3923 },
3924 { "BSSExpireCount", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
3925 wpas_dbus_getter_bss_expire_count,
3926 wpas_dbus_setter_bss_expire_count,
3927 NULL
3928 },
3929 { "Country", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3930 wpas_dbus_getter_country,
3931 wpas_dbus_setter_country,
3932 NULL
3933 },
3934 { "Ifname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3935 wpas_dbus_getter_ifname,
3936 NULL,
3937 NULL
3938 },
3939 { "Driver", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3940 wpas_dbus_getter_driver,
3941 NULL,
3942 NULL
3943 },
3944 { "BridgeIfname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3945 wpas_dbus_getter_bridge_ifname,
3946 wpas_dbus_setter_bridge_ifname,
3947 NULL
3948 },
3949 { "ConfigFile", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3950 wpas_dbus_getter_config_file,
3951 NULL,
3952 NULL
3953 },
3954 { "CurrentBSS", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
3955 wpas_dbus_getter_current_bss,
3956 NULL,
3957 NULL
3958 },
3959 { "CurrentNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
3960 wpas_dbus_getter_current_network,
3961 NULL,
3962 NULL
3963 },
3964 { "CurrentAuthMode", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3965 wpas_dbus_getter_current_auth_mode,
3966 NULL,
3967 NULL
3968 },
3969 { "Blobs", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{say}",
3970 wpas_dbus_getter_blobs,
3971 NULL,
3972 NULL
3973 },
3974 { "BSSs", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
3975 wpas_dbus_getter_bsss,
3976 NULL,
3977 NULL
3978 },
3979 { "Networks", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
3980 wpas_dbus_getter_networks,
3981 NULL,
3982 NULL
3983 },
3984 { "FastReauth", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
3985 wpas_dbus_getter_fast_reauth,
3986 wpas_dbus_setter_fast_reauth,
3987 NULL
3988 },
3989 { "ScanInterval", WPAS_DBUS_NEW_IFACE_INTERFACE, "i",
3990 wpas_dbus_getter_scan_interval,
3991 wpas_dbus_setter_scan_interval,
3992 NULL
3993 },
3994 { "PKCS11EnginePath", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3995 wpas_dbus_getter_pkcs11_engine_path,
3996 NULL,
3997 NULL
3998 },
3999 { "PKCS11ModulePath", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
4000 wpas_dbus_getter_pkcs11_module_path,
4001 NULL,
4002 NULL
4003 },
4004 #ifdef CONFIG_WPS
4005 { "ProcessCredentials", WPAS_DBUS_NEW_IFACE_WPS, "b",
4006 wpas_dbus_getter_process_credentials,
4007 wpas_dbus_setter_process_credentials,
4008 NULL
4009 },
4010 { "ConfigMethods", WPAS_DBUS_NEW_IFACE_WPS, "s",
4011 wpas_dbus_getter_config_methods,
4012 wpas_dbus_setter_config_methods,
4013 NULL
4014 },
4015 {
4016 "DeviceName", WPAS_DBUS_NEW_IFACE_WPS, "s",
4017 wpas_dbus_getter_wps_device_name,
4018 wpas_dbus_setter_wps_device_name,
4019 NULL
4020 },
4021 {
4022 "Manufacturer", WPAS_DBUS_NEW_IFACE_WPS, "s",
4023 wpas_dbus_getter_wps_manufacturer,
4024 wpas_dbus_setter_wps_manufacturer,
4025 NULL
4026 },
4027 {
4028 "ModelName", WPAS_DBUS_NEW_IFACE_WPS, "s",
4029 wpas_dbus_getter_wps_device_model_name,
4030 wpas_dbus_setter_wps_device_model_name,
4031 NULL
4032 },
4033 {
4034 "ModelNumber", WPAS_DBUS_NEW_IFACE_WPS, "s",
4035 wpas_dbus_getter_wps_device_model_number,
4036 wpas_dbus_setter_wps_device_model_number,
4037 NULL
4038 },
4039 {
4040 "SerialNumber", WPAS_DBUS_NEW_IFACE_WPS, "s",
4041 wpas_dbus_getter_wps_device_serial_number,
4042 wpas_dbus_setter_wps_device_serial_number,
4043 NULL
4044 },
4045 {
4046 "DeviceType", WPAS_DBUS_NEW_IFACE_WPS, "ay",
4047 wpas_dbus_getter_wps_device_device_type,
4048 wpas_dbus_setter_wps_device_device_type,
4049 NULL
4050 },
4051 #endif /* CONFIG_WPS */
4052 #ifdef CONFIG_P2P
4053 { "P2PDeviceConfig", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "a{sv}",
4054 wpas_dbus_getter_p2p_device_config,
4055 wpas_dbus_setter_p2p_device_config,
4056 NULL
4057 },
4058 { "Peers", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "ao",
4059 wpas_dbus_getter_p2p_peers,
4060 NULL,
4061 NULL
4062 },
4063 { "Role", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "s",
4064 wpas_dbus_getter_p2p_role,
4065 NULL,
4066 NULL
4067 },
4068 { "Group", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "o",
4069 wpas_dbus_getter_p2p_group,
4070 NULL,
4071 NULL
4072 },
4073 { "PeerGO", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "o",
4074 wpas_dbus_getter_p2p_peergo,
4075 NULL,
4076 NULL
4077 },
4078 { "PersistentGroups", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "ao",
4079 wpas_dbus_getter_persistent_groups,
4080 NULL,
4081 NULL
4082 },
4083 #endif /* CONFIG_P2P */
4084 { "DisconnectReason", WPAS_DBUS_NEW_IFACE_INTERFACE, "i",
4085 wpas_dbus_getter_disconnect_reason,
4086 NULL,
4087 NULL
4088 },
4089 { "AuthStatusCode", WPAS_DBUS_NEW_IFACE_INTERFACE, "i",
4090 wpas_dbus_getter_auth_status_code,
4091 NULL,
4092 NULL
4093 },
4094 { "AssocStatusCode", WPAS_DBUS_NEW_IFACE_INTERFACE, "i",
4095 wpas_dbus_getter_assoc_status_code,
4096 NULL,
4097 NULL
4098 },
4099 {
4100 "RoamTime", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
4101 wpas_dbus_getter_roam_time,
4102 NULL,
4103 NULL
4104 },
4105 {
4106 "RoamComplete", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
4107 wpas_dbus_getter_roam_complete,
4108 NULL,
4109 NULL
4110 },
4111 {
4112 "ScanInProgress6GHz", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
4113 wpas_dbus_getter_scan_in_progress_6ghz,
4114 NULL,
4115 NULL
4116 },
4117 {
4118 "SessionLength", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
4119 wpas_dbus_getter_session_length,
4120 NULL,
4121 NULL
4122 },
4123 {
4124 "BSSTMStatus", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
4125 wpas_dbus_getter_bss_tm_status,
4126 NULL,
4127 NULL
4128 },
4129 #ifdef CONFIG_MESH
4130 { "MeshPeers", WPAS_DBUS_NEW_IFACE_MESH, "aay",
4131 wpas_dbus_getter_mesh_peers,
4132 NULL,
4133 NULL
4134 },
4135 { "MeshGroup", WPAS_DBUS_NEW_IFACE_MESH, "ay",
4136 wpas_dbus_getter_mesh_group,
4137 NULL,
4138 NULL
4139 },
4140 #endif /* CONFIG_MESH */
4141 { "Stations", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
4142 wpas_dbus_getter_stas,
4143 NULL,
4144 NULL
4145 },
4146 { "MACAddressRandomizationMask", WPAS_DBUS_NEW_IFACE_INTERFACE,
4147 "a{say}",
4148 wpas_dbus_getter_mac_address_randomization_mask,
4149 wpas_dbus_setter_mac_address_randomization_mask,
4150 NULL
4151 },
4152 { "MACAddress", WPAS_DBUS_NEW_IFACE_INTERFACE, "ay",
4153 wpas_dbus_getter_mac_address,
4154 NULL,
4155 NULL,
4156 },
4157 { "SignalChange", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{sv}",
4158 wpas_dbus_getter_signal_change,
4159 NULL,
4160 NULL
4161 },
4162 { NULL, NULL, NULL, NULL, NULL, NULL }
4163 };
4164
4165 static const struct wpa_dbus_signal_desc wpas_dbus_interface_signals[] = {
4166 { "ScanDone", WPAS_DBUS_NEW_IFACE_INTERFACE,
4167 {
4168 { "success", "b", ARG_OUT },
4169 END_ARGS
4170 }
4171 },
4172 { "BSSAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
4173 {
4174 { "path", "o", ARG_OUT },
4175 { "properties", "a{sv}", ARG_OUT },
4176 END_ARGS
4177 }
4178 },
4179 { "BSSRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
4180 {
4181 { "path", "o", ARG_OUT },
4182 END_ARGS
4183 }
4184 },
4185 { "BlobAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
4186 {
4187 { "name", "s", ARG_OUT },
4188 END_ARGS
4189 }
4190 },
4191 { "BlobRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
4192 {
4193 { "name", "s", ARG_OUT },
4194 END_ARGS
4195 }
4196 },
4197 { "NetworkAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
4198 {
4199 { "path", "o", ARG_OUT },
4200 { "properties", "a{sv}", ARG_OUT },
4201 END_ARGS
4202 }
4203 },
4204 { "NetworkRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
4205 {
4206 { "path", "o", ARG_OUT },
4207 END_ARGS
4208 }
4209 },
4210 { "NetworkSelected", WPAS_DBUS_NEW_IFACE_INTERFACE,
4211 {
4212 { "path", "o", ARG_OUT },
4213 END_ARGS
4214 }
4215 },
4216 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
4217 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_INTERFACE,
4218 {
4219 { "properties", "a{sv}", ARG_OUT },
4220 END_ARGS
4221 }
4222 },
4223 #ifdef CONFIG_WPS
4224 { "Event", WPAS_DBUS_NEW_IFACE_WPS,
4225 {
4226 { "name", "s", ARG_OUT },
4227 { "args", "a{sv}", ARG_OUT },
4228 END_ARGS
4229 }
4230 },
4231 { "Credentials", WPAS_DBUS_NEW_IFACE_WPS,
4232 {
4233 { "credentials", "a{sv}", ARG_OUT },
4234 END_ARGS
4235 }
4236 },
4237 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
4238 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_WPS,
4239 {
4240 { "properties", "a{sv}", ARG_OUT },
4241 END_ARGS
4242 }
4243 },
4244 #endif /* CONFIG_WPS */
4245 #ifdef CONFIG_P2P
4246 { "DeviceFound", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4247 {
4248 { "path", "o", ARG_OUT },
4249 END_ARGS
4250 }
4251 },
4252 { "DeviceFoundProperties", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4253 {
4254 { "path", "o", ARG_OUT },
4255 { "properties", "a{sv}", ARG_OUT },
4256 END_ARGS
4257 }
4258 },
4259 { "DeviceLost", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4260 {
4261 { "path", "o", ARG_OUT },
4262 END_ARGS
4263 }
4264 },
4265 { "FindStopped", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4266 {
4267 END_ARGS
4268 }
4269 },
4270 { "ProvisionDiscoveryRequestDisplayPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4271 {
4272 { "peer_object", "o", ARG_OUT },
4273 { "pin", "s", ARG_OUT },
4274 END_ARGS
4275 }
4276 },
4277 { "ProvisionDiscoveryResponseDisplayPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4278 {
4279 { "peer_object", "o", ARG_OUT },
4280 { "pin", "s", ARG_OUT },
4281 END_ARGS
4282 }
4283 },
4284 { "ProvisionDiscoveryRequestEnterPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4285 {
4286 { "peer_object", "o", ARG_OUT },
4287 END_ARGS
4288 }
4289 },
4290 { "ProvisionDiscoveryResponseEnterPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4291 {
4292 { "peer_object", "o", ARG_OUT },
4293 END_ARGS
4294 }
4295 },
4296 { "ProvisionDiscoveryPBCRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4297 {
4298 { "peer_object", "o", ARG_OUT },
4299 END_ARGS
4300 }
4301 },
4302 { "ProvisionDiscoveryPBCResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4303 {
4304 { "peer_object", "o", ARG_OUT },
4305 END_ARGS
4306 }
4307 },
4308 { "ProvisionDiscoveryFailure", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4309 {
4310 { "peer_object", "o", ARG_OUT },
4311 { "status", "i", ARG_OUT },
4312 END_ARGS
4313 }
4314 },
4315 { "GroupStarted", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4316 {
4317 { "properties", "a{sv}", ARG_OUT },
4318 END_ARGS
4319 }
4320 },
4321 { "GroupFormationFailure", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4322 {
4323 { "reason", "s", ARG_OUT },
4324 END_ARGS
4325 }
4326 },
4327 { "GONegotiationSuccess", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4328 {
4329 { "properties", "a{sv}", ARG_OUT },
4330 END_ARGS
4331 }
4332 },
4333 { "GONegotiationFailure", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4334 {
4335 { "properties", "a{sv}", ARG_OUT },
4336 END_ARGS
4337 }
4338 },
4339 { "GONegotiationRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4340 {
4341 { "path", "o", ARG_OUT },
4342 { "dev_passwd_id", "q", ARG_OUT },
4343 { "device_go_intent", "y", ARG_OUT },
4344 END_ARGS
4345 }
4346 },
4347 { "InvitationResult", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4348 {
4349 { "invite_result", "a{sv}", ARG_OUT },
4350 END_ARGS
4351 }
4352 },
4353 { "GroupFinished", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4354 {
4355 { "properties", "a{sv}", ARG_OUT },
4356 END_ARGS
4357 }
4358 },
4359 { "ServiceDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4360 {
4361 { "sd_request", "a{sv}", ARG_OUT },
4362 END_ARGS
4363 }
4364 },
4365 { "ServiceDiscoveryResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4366 {
4367 { "sd_response", "a{sv}", ARG_OUT },
4368 END_ARGS
4369 }
4370 },
4371 { "PersistentGroupAdded", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4372 {
4373 { "path", "o", ARG_OUT },
4374 { "properties", "a{sv}", ARG_OUT },
4375 END_ARGS
4376 }
4377 },
4378 { "PersistentGroupRemoved", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4379 {
4380 { "path", "o", ARG_OUT },
4381 END_ARGS
4382 }
4383 },
4384 { "WpsFailed", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4385 {
4386 { "name", "s", ARG_OUT },
4387 { "args", "a{sv}", ARG_OUT },
4388 END_ARGS
4389 }
4390 },
4391 { "InvitationReceived", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4392 {
4393 { "properties", "a{sv}", ARG_OUT },
4394 END_ARGS
4395 }
4396 },
4397 { "BootstrappingRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4398 {
4399 { "path", "o", ARG_OUT },
4400 { "bootstrap_method", "q", ARG_OUT },
4401 END_ARGS
4402 }
4403 },
4404 { "BootstrappingCompleted", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4405 {
4406 { "path", "o", ARG_OUT },
4407 { "status", "i", ARG_OUT },
4408 END_ARGS
4409 }
4410 },
4411 #endif /* CONFIG_P2P */
4412 #ifdef CONFIG_AP
4413 { "ProbeRequest", WPAS_DBUS_NEW_IFACE_INTERFACE,
4414 {
4415 { "args", "a{sv}", ARG_OUT },
4416 END_ARGS
4417 }
4418 },
4419 #endif /* CONFIG_AP */
4420 { "Certification", WPAS_DBUS_NEW_IFACE_INTERFACE,
4421 {
4422 { "certification", "a{sv}", ARG_OUT },
4423 END_ARGS
4424 }
4425 },
4426 { "EAP", WPAS_DBUS_NEW_IFACE_INTERFACE,
4427 {
4428 { "status", "s", ARG_OUT },
4429 { "parameter", "s", ARG_OUT },
4430 END_ARGS
4431 }
4432 },
4433 { "StaAuthorized", WPAS_DBUS_NEW_IFACE_INTERFACE,
4434 {
4435 { "name", "s", ARG_OUT },
4436 END_ARGS
4437 }
4438 },
4439 { "StaDeauthorized", WPAS_DBUS_NEW_IFACE_INTERFACE,
4440 {
4441 { "name", "s", ARG_OUT },
4442 END_ARGS
4443 }
4444 },
4445 { "StationAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
4446 {
4447 { "path", "o", ARG_OUT },
4448 { "properties", "a{sv}", ARG_OUT },
4449 END_ARGS
4450 }
4451 },
4452 { "StationRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
4453 {
4454 { "path", "o", ARG_OUT },
4455 END_ARGS
4456 }
4457 },
4458 { "NetworkRequest", WPAS_DBUS_NEW_IFACE_INTERFACE,
4459 {
4460 { "path", "o", ARG_OUT },
4461 { "field", "s", ARG_OUT },
4462 { "text", "s", ARG_OUT },
4463 END_ARGS
4464 }
4465 },
4466 #ifdef CONFIG_MESH
4467 { "MeshGroupStarted", WPAS_DBUS_NEW_IFACE_MESH,
4468 {
4469 { "args", "a{sv}", ARG_OUT },
4470 END_ARGS
4471 }
4472 },
4473 { "MeshGroupRemoved", WPAS_DBUS_NEW_IFACE_MESH,
4474 {
4475 { "args", "a{sv}", ARG_OUT },
4476 END_ARGS
4477 }
4478 },
4479 { "MeshPeerConnected", WPAS_DBUS_NEW_IFACE_MESH,
4480 {
4481 { "args", "a{sv}", ARG_OUT },
4482 END_ARGS
4483 }
4484 },
4485 { "MeshPeerDisconnected", WPAS_DBUS_NEW_IFACE_MESH,
4486 {
4487 { "args", "a{sv}", ARG_OUT },
4488 END_ARGS
4489 }
4490 },
4491 #endif /* CONFIG_MESH */
4492 #ifdef CONFIG_INTERWORKING
4493 { "InterworkingAPAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
4494 {
4495 { "bss", "o", ARG_OUT },
4496 { "cred", "o", ARG_OUT },
4497 { "properties", "a{sv}", ARG_OUT },
4498 END_ARGS
4499 }
4500 },
4501 { "InterworkingSelectDone", WPAS_DBUS_NEW_IFACE_INTERFACE,
4502 {
4503 END_ARGS
4504 }
4505 },
4506 {"ANQPQueryDone", WPAS_DBUS_NEW_IFACE_INTERFACE,
4507 {
4508 { "addr", "s", ARG_OUT },
4509 { "result", "s", ARG_OUT },
4510 END_ARGS
4511 }
4512 },
4513 #endif /* CONFIG_INTERWORKING */
4514 #ifdef CONFIG_HS20
4515 { "HS20TermsAndConditions", WPAS_DBUS_NEW_IFACE_INTERFACE,
4516 {
4517 { "url", "s", ARG_OUT },
4518 END_ARGS
4519 }
4520 },
4521 #endif /* CONFIG_HS20 */
4522 #ifdef CONFIG_NAN_USD
4523 { "NANDiscoveryResult", WPAS_DBUS_NEW_IFACE_INTERFACE,
4524 {
4525 { "args", "a{sv}", ARG_OUT },
4526 END_ARGS
4527 }
4528 },
4529 { "NANReplied", WPAS_DBUS_NEW_IFACE_INTERFACE,
4530 {
4531 { "args", "a{sv}", ARG_OUT },
4532 END_ARGS
4533 }
4534 },
4535 { "NANReceive", WPAS_DBUS_NEW_IFACE_INTERFACE,
4536 {
4537 { "args", "a{sv}", ARG_OUT },
4538 END_ARGS
4539 }
4540 },
4541 { "NANPublishTerminated", WPAS_DBUS_NEW_IFACE_INTERFACE,
4542 {
4543 { "publish_id", "u", ARG_OUT },
4544 { "reason", "s", ARG_OUT },
4545 END_ARGS
4546 }
4547 },
4548 { "NANSubscribeTerminated", WPAS_DBUS_NEW_IFACE_INTERFACE,
4549 {
4550 { "subscribe_id", "u", ARG_OUT },
4551 { "reason", "s", ARG_OUT },
4552 END_ARGS
4553 }
4554 },
4555 #endif /* CONFIG_NAN_USD */
4556 { NULL, NULL, { END_ARGS } }
4557 };
4558
4559
wpa_dbus_ctrl_iface_props_init(struct wpas_dbus_priv * priv)4560 static int wpa_dbus_ctrl_iface_props_init(struct wpas_dbus_priv *priv)
4561 {
4562 size_t all_size;
4563 unsigned int i, j, count, num_const, num_globals;
4564 const char *global_name;
4565 static const char * const ignored_globals[] = {
4566 "bss_expiration_age", "bss_expiration_scan_count",
4567 "ap_scan", "country", "fast_reauth",
4568 "pkcs11_engine_path", "pkcs11_module_path"
4569 };
4570
4571 /* wpas_dbus_interface_properties terminates with a NULL element */
4572 num_const = ARRAY_SIZE(wpas_dbus_interface_properties) - 1;
4573
4574 num_globals = wpa_config_get_num_global_field_names();
4575 priv->globals_start = num_const;
4576
4577 /* allocate enough for all properties + terminating NULL element */
4578 all_size = (num_globals + num_const + 1) *
4579 sizeof(wpas_dbus_interface_properties[0]);
4580 priv->all_interface_properties = os_zalloc(all_size);
4581 if (!priv->all_interface_properties) {
4582 wpa_printf(MSG_ERROR,
4583 "dbus: Not enough memory for interface properties");
4584 return -1;
4585 }
4586
4587 /* Copy constant interface properties to the start of the array */
4588 os_memcpy(priv->all_interface_properties,
4589 wpas_dbus_interface_properties,
4590 sizeof(wpas_dbus_interface_properties));
4591
4592 /* Dynamically construct interface global properties */
4593 for (i = 0, count = num_const; i < num_globals; i++) {
4594 struct wpa_dbus_property_desc *desc;
4595 int no_var = 0;
4596
4597 /* ignore globals that are actually just methods */
4598 global_name = wpa_config_get_global_field_name(i, &no_var);
4599 if (no_var)
4600 continue;
4601 /* Ignore fields already explicitly exposed */
4602 for (j = 0; j < ARRAY_SIZE(ignored_globals); j++) {
4603 if (os_strcmp(global_name, ignored_globals[j]) == 0)
4604 break;
4605 }
4606 if (j < ARRAY_SIZE(ignored_globals))
4607 continue;
4608
4609 desc = &priv->all_interface_properties[count++];
4610 desc->dbus_property = uscore_to_dbus(global_name);
4611 if (!desc->dbus_property) {
4612 wpa_printf(MSG_ERROR,
4613 "dbus: Not enough memory for D-Bus property name");
4614 goto error;
4615 }
4616 desc->dbus_interface = WPAS_DBUS_NEW_IFACE_INTERFACE;
4617 desc->type = "s";
4618 desc->getter = wpas_dbus_getter_iface_global;
4619 desc->setter = wpas_dbus_setter_iface_global;
4620 desc->data = global_name;
4621 }
4622
4623 return 0;
4624
4625 error:
4626 wpa_dbus_ctrl_iface_props_deinit(priv);
4627 return -1;
4628 }
4629
4630
4631 /**
4632 * wpas_dbus_register_interface - Register an interface with D-Bus
4633 * @wpa_s: wpa_supplicant interface structure
4634 * Returns: 0 on success, -1 on failure
4635 */
wpas_dbus_register_interface(struct wpa_supplicant * wpa_s)4636 int wpas_dbus_register_interface(struct wpa_supplicant *wpa_s)
4637 {
4638 struct wpa_dbus_object_desc *obj_desc = NULL;
4639 struct wpas_dbus_priv *ctrl_iface = wpa_s->global->dbus;
4640 int next;
4641
4642 /* Do nothing if the control interface is not turned on */
4643 if (ctrl_iface == NULL)
4644 return 0;
4645
4646 /* Create and set the interface's object path */
4647 wpa_s->dbus_new_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
4648 if (wpa_s->dbus_new_path == NULL)
4649 return -1;
4650 next = ctrl_iface->next_objid++;
4651 os_snprintf(wpa_s->dbus_new_path, WPAS_DBUS_OBJECT_PATH_MAX,
4652 WPAS_DBUS_NEW_PATH_INTERFACES "/%u",
4653 next);
4654
4655 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
4656 if (!obj_desc) {
4657 wpa_printf(MSG_ERROR,
4658 "Not enough memory to create object description");
4659 goto err;
4660 }
4661
4662 wpas_dbus_register(obj_desc, wpa_s, NULL, wpas_dbus_interface_methods,
4663 ctrl_iface->all_interface_properties,
4664 wpas_dbus_interface_signals);
4665
4666 wpa_printf(MSG_DEBUG, "dbus: Register interface object '%s'",
4667 wpa_s->dbus_new_path);
4668 if (wpa_dbus_register_object_per_iface(ctrl_iface,
4669 wpa_s->dbus_new_path,
4670 wpa_s->ifname, obj_desc))
4671 goto err;
4672
4673 wpas_dbus_signal_interface_added(wpa_s);
4674
4675 return 0;
4676
4677 err:
4678 os_free(wpa_s->dbus_new_path);
4679 wpa_s->dbus_new_path = NULL;
4680 free_dbus_object_desc(obj_desc);
4681 return -1;
4682 }
4683
4684
4685 /**
4686 * wpas_dbus_unregister_interface - Unregister the interface from D-Bus
4687 * @wpa_s: wpa_supplicant interface structure
4688 * Returns: 0 on success, -1 on failure
4689 */
wpas_dbus_unregister_interface(struct wpa_supplicant * wpa_s)4690 int wpas_dbus_unregister_interface(struct wpa_supplicant *wpa_s)
4691 {
4692 struct wpas_dbus_priv *ctrl_iface;
4693
4694 /* Do nothing if the control interface is not turned on */
4695 if (wpa_s == NULL || wpa_s->global == NULL)
4696 return 0;
4697 ctrl_iface = wpa_s->global->dbus;
4698 if (ctrl_iface == NULL || wpa_s->dbus_new_path == NULL)
4699 return 0;
4700
4701 wpa_printf(MSG_DEBUG, "dbus: Unregister interface object '%s'",
4702 wpa_s->dbus_new_path);
4703
4704 #ifdef CONFIG_AP
4705 if (wpa_s->preq_notify_peer) {
4706 wpas_dbus_unsubscribe_noc(ctrl_iface);
4707 os_free(wpa_s->preq_notify_peer);
4708 wpa_s->preq_notify_peer = NULL;
4709 }
4710 #endif /* CONFIG_AP */
4711
4712 if (wpa_dbus_unregister_object_per_iface(ctrl_iface,
4713 wpa_s->dbus_new_path))
4714 return -1;
4715
4716 wpas_dbus_signal_interface_removed(wpa_s);
4717
4718 os_free(wpa_s->dbus_new_path);
4719 wpa_s->dbus_new_path = NULL;
4720
4721 return 0;
4722 }
4723
4724 #ifdef CONFIG_P2P
4725
4726 static const struct wpa_dbus_property_desc wpas_dbus_p2p_peer_properties[] = {
4727 { "DeviceName", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
4728 wpas_dbus_getter_p2p_peer_device_name,
4729 NULL,
4730 NULL
4731 },
4732 { "Manufacturer", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
4733 wpas_dbus_getter_p2p_peer_manufacturer,
4734 NULL,
4735 NULL
4736 },
4737 { "ModelName", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
4738 wpas_dbus_getter_p2p_peer_modelname,
4739 NULL,
4740 NULL
4741 },
4742 { "ModelNumber", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
4743 wpas_dbus_getter_p2p_peer_modelnumber,
4744 NULL,
4745 NULL
4746 },
4747 { "SerialNumber", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
4748 wpas_dbus_getter_p2p_peer_serialnumber,
4749 NULL,
4750 NULL
4751 },
4752 { "PrimaryDeviceType", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
4753 wpas_dbus_getter_p2p_peer_primary_device_type,
4754 NULL,
4755 NULL
4756 },
4757 { "config_method", WPAS_DBUS_NEW_IFACE_P2P_PEER, "q",
4758 wpas_dbus_getter_p2p_peer_config_method,
4759 NULL,
4760 NULL
4761 },
4762 { "level", WPAS_DBUS_NEW_IFACE_P2P_PEER, "i",
4763 wpas_dbus_getter_p2p_peer_level,
4764 NULL,
4765 NULL
4766 },
4767 { "devicecapability", WPAS_DBUS_NEW_IFACE_P2P_PEER, "y",
4768 wpas_dbus_getter_p2p_peer_device_capability,
4769 NULL,
4770 NULL
4771 },
4772 { "groupcapability", WPAS_DBUS_NEW_IFACE_P2P_PEER, "y",
4773 wpas_dbus_getter_p2p_peer_group_capability,
4774 NULL,
4775 NULL
4776 },
4777 { "SecondaryDeviceTypes", WPAS_DBUS_NEW_IFACE_P2P_PEER, "aay",
4778 wpas_dbus_getter_p2p_peer_secondary_device_types,
4779 NULL,
4780 NULL
4781 },
4782 { "VendorExtension", WPAS_DBUS_NEW_IFACE_P2P_PEER, "aay",
4783 wpas_dbus_getter_p2p_peer_vendor_extension,
4784 NULL,
4785 NULL
4786 },
4787 { "IEs", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
4788 wpas_dbus_getter_p2p_peer_ies,
4789 NULL,
4790 NULL
4791 },
4792 { "DeviceAddress", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
4793 wpas_dbus_getter_p2p_peer_device_address,
4794 NULL,
4795 NULL
4796 },
4797 { "Groups", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ao",
4798 wpas_dbus_getter_p2p_peer_groups,
4799 NULL,
4800 NULL
4801 },
4802 { "VSIE", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
4803 wpas_dbus_getter_p2p_peer_vsie,
4804 NULL,
4805 NULL
4806 },
4807 { NULL, NULL, NULL, NULL, NULL, NULL }
4808 };
4809
4810 static const struct wpa_dbus_signal_desc wpas_dbus_p2p_peer_signals[] = {
4811 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
4812 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_P2P_PEER,
4813 {
4814 { "properties", "a{sv}", ARG_OUT },
4815 END_ARGS
4816 }
4817 },
4818 { NULL, NULL, { END_ARGS } }
4819 };
4820
4821 /**
4822 * wpas_dbus_signal_peer - Send a peer related event signal
4823 * @wpa_s: %wpa_supplicant network interface data
4824 * @dev: peer device object
4825 * @interface: name of the interface emitting this signal.
4826 * In case of peer objects, it would be emitted by either
4827 * the "interface object" or by "peer objects"
4828 * @sig_name: signal name - DeviceFound
4829 * @properties: Whether to add a second argument with object properties
4830 *
4831 * Notify listeners about event related with p2p peer device
4832 */
wpas_dbus_signal_peer(struct wpa_supplicant * wpa_s,const u8 * dev_addr,const char * interface,const char * sig_name,dbus_bool_t properties)4833 static void wpas_dbus_signal_peer(struct wpa_supplicant *wpa_s,
4834 const u8 *dev_addr, const char *interface,
4835 const char *sig_name, dbus_bool_t properties)
4836 {
4837 struct wpas_dbus_priv *iface;
4838 DBusMessage *msg;
4839 DBusMessageIter iter;
4840 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
4841
4842 if (wpa_s->p2p_mgmt)
4843 wpa_s = wpa_s->parent;
4844
4845 iface = wpa_s->global->dbus;
4846
4847 /* Do nothing if the control interface is not turned on */
4848 if (iface == NULL || !wpa_s->dbus_new_path)
4849 return;
4850
4851 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
4852 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
4853 wpa_s->dbus_new_path, MAC2STR(dev_addr));
4854
4855 msg = dbus_message_new_signal(wpa_s->dbus_new_path, interface,
4856 sig_name);
4857 if (msg == NULL)
4858 return;
4859
4860 dbus_message_iter_init_append(msg, &iter);
4861 path = peer_obj_path;
4862 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
4863 &path) ||
4864 (properties && !wpa_dbus_get_object_properties(
4865 iface, peer_obj_path, WPAS_DBUS_NEW_IFACE_P2P_PEER,
4866 &iter)))
4867 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
4868 else
4869 dbus_connection_send(iface->con, msg, NULL);
4870
4871 dbus_message_unref(msg);
4872 }
4873
4874
4875 /**
4876 * wpas_dbus_signal_peer_found - Send a peer found signal
4877 * @wpa_s: %wpa_supplicant network interface data
4878 * @dev_addr: Peer P2P Device Address
4879 *
4880 * Notify listeners about find a p2p peer device found
4881 */
wpas_dbus_signal_peer_device_found(struct wpa_supplicant * wpa_s,const u8 * dev_addr)4882 void wpas_dbus_signal_peer_device_found(struct wpa_supplicant *wpa_s,
4883 const u8 *dev_addr)
4884 {
4885 wpas_dbus_signal_peer(wpa_s, dev_addr,
4886 WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4887 "DeviceFound", FALSE);
4888
4889 wpas_dbus_signal_peer(wpa_s, dev_addr,
4890 WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4891 "DeviceFoundProperties", TRUE);
4892 }
4893
4894 /**
4895 * wpas_dbus_signal_peer_lost - Send a peer lost signal
4896 * @wpa_s: %wpa_supplicant network interface data
4897 * @dev_addr: Peer P2P Device Address
4898 *
4899 * Notify listeners about lost a p2p peer device
4900 */
wpas_dbus_signal_peer_device_lost(struct wpa_supplicant * wpa_s,const u8 * dev_addr)4901 void wpas_dbus_signal_peer_device_lost(struct wpa_supplicant *wpa_s,
4902 const u8 *dev_addr)
4903 {
4904 wpas_dbus_signal_peer(wpa_s, dev_addr,
4905 WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4906 "DeviceLost", FALSE);
4907 }
4908
4909 /**
4910 * wpas_dbus_register_peer - Register a discovered peer object with dbus
4911 * @wpa_s: wpa_supplicant interface structure
4912 * @dev_addr: P2P Device Address of the peer
4913 * Returns: 0 on success, -1 on failure
4914 *
4915 * Registers network representing object with dbus
4916 */
wpas_dbus_register_peer(struct wpa_supplicant * wpa_s,const u8 * dev_addr)4917 int wpas_dbus_register_peer(struct wpa_supplicant *wpa_s, const u8 *dev_addr)
4918 {
4919 struct wpas_dbus_priv *ctrl_iface;
4920 struct wpa_dbus_object_desc *obj_desc;
4921 struct peer_handler_args *arg;
4922 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
4923
4924 /* Do nothing if the control interface is not turned on */
4925 if (wpa_s == NULL || wpa_s->global == NULL)
4926 return 0;
4927
4928 ctrl_iface = wpa_s->global->dbus;
4929 if (ctrl_iface == NULL)
4930 return 0;
4931
4932 wpa_s = wpa_s->parent->parent;
4933 if (!wpa_s->dbus_new_path)
4934 return 0;
4935
4936 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
4937 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
4938 wpa_s->dbus_new_path, MAC2STR(dev_addr));
4939
4940 wpa_printf(MSG_INFO, "dbus: Register peer object '%s'",
4941 peer_obj_path);
4942 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
4943 if (!obj_desc) {
4944 wpa_printf(MSG_ERROR,
4945 "Not enough memory to create object description");
4946 goto err;
4947 }
4948
4949 /* allocate memory for handlers arguments */
4950 arg = os_zalloc(sizeof(struct peer_handler_args));
4951 if (!arg) {
4952 wpa_printf(MSG_ERROR,
4953 "Not enough memory to create arguments for method");
4954 goto err;
4955 }
4956
4957 arg->wpa_s = wpa_s;
4958 os_memcpy(arg->p2p_device_addr, dev_addr, ETH_ALEN);
4959
4960 wpas_dbus_register(obj_desc, arg, wpa_dbus_free,
4961 NULL,
4962 wpas_dbus_p2p_peer_properties,
4963 wpas_dbus_p2p_peer_signals);
4964
4965 if (wpa_dbus_register_object_per_iface(ctrl_iface, peer_obj_path,
4966 wpa_s->ifname, obj_desc))
4967 goto err;
4968
4969 return 0;
4970
4971 err:
4972 free_dbus_object_desc(obj_desc);
4973 return -1;
4974 }
4975
4976 /**
4977 * wpas_dbus_unregister_peer - Unregister a peer object with dbus
4978 * @wpa_s: wpa_supplicant interface structure
4979 * @dev_addr: p2p device addr
4980 * Returns: 0 on success, -1 on failure
4981 *
4982 * Registers network representing object with dbus
4983 */
wpas_dbus_unregister_peer(struct wpa_supplicant * wpa_s,const u8 * dev_addr)4984 int wpas_dbus_unregister_peer(struct wpa_supplicant *wpa_s,
4985 const u8 *dev_addr)
4986 {
4987 struct wpas_dbus_priv *ctrl_iface;
4988 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
4989 int ret;
4990
4991 /* Do nothing if the control interface is not turned on */
4992 if (wpa_s == NULL || wpa_s->global == NULL)
4993 return 0;
4994
4995 wpa_s = wpa_s->parent->parent;
4996 if (!wpa_s->dbus_new_path)
4997 return 0;
4998
4999 ctrl_iface = wpa_s->global->dbus;
5000 if (ctrl_iface == NULL)
5001 return 0;
5002
5003 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
5004 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
5005 wpa_s->dbus_new_path, MAC2STR(dev_addr));
5006
5007 wpa_printf(MSG_INFO, "dbus: Unregister peer object '%s'",
5008 peer_obj_path);
5009 ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, peer_obj_path);
5010
5011 return ret;
5012 }
5013
5014
5015 /**
5016 * wpas_dbus_signal_p2p_find_stopped - Send P2P Find stopped signal
5017 * @wpa_s: %wpa_supplicant network interface data
5018 *
5019 * Notify listeners about P2P Find stopped
5020 */
wpas_dbus_signal_p2p_find_stopped(struct wpa_supplicant * wpa_s)5021 void wpas_dbus_signal_p2p_find_stopped(struct wpa_supplicant *wpa_s)
5022 {
5023 struct wpas_dbus_priv *iface;
5024 DBusMessage *msg;
5025
5026 iface = wpa_s->global->dbus;
5027
5028 /* Do nothing if the control interface is not turned on */
5029 if (iface == NULL)
5030 return;
5031
5032 if (wpa_s->p2p_mgmt)
5033 wpa_s = wpa_s->parent;
5034
5035 if (!wpa_s->dbus_new_path)
5036 return;
5037
5038 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
5039 WPAS_DBUS_NEW_IFACE_P2PDEVICE,
5040 "FindStopped");
5041 if (msg == NULL)
5042 return;
5043
5044 dbus_connection_send(iface->con, msg, NULL);
5045
5046 dbus_message_unref(msg);
5047 }
5048
5049
5050 /**
5051 * wpas_dbus_signal_peer_groups_changed - Send peer group change property signal
5052 * @wpa_s: %wpa_supplicant network interface data
5053 * @dev_addr: P2P Device Address
5054 *
5055 * Notify listeners about peer Groups property changes.
5056 */
wpas_dbus_signal_peer_groups_changed(struct wpa_supplicant * wpa_s,const u8 * dev_addr)5057 void wpas_dbus_signal_peer_groups_changed(struct wpa_supplicant *wpa_s,
5058 const u8 *dev_addr)
5059 {
5060 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
5061
5062 if (wpa_s->p2p_mgmt)
5063 wpa_s = wpa_s->parent;
5064
5065 if (!wpa_s->dbus_new_path)
5066 return;
5067 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
5068 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
5069 wpa_s->dbus_new_path, MAC2STR(dev_addr));
5070
5071 wpa_dbus_mark_property_changed(wpa_s->global->dbus, peer_obj_path,
5072 WPAS_DBUS_NEW_IFACE_P2P_PEER, "Groups");
5073 }
5074
5075
5076 static const struct wpa_dbus_property_desc wpas_dbus_p2p_group_properties[] = {
5077 { "Members", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ao",
5078 wpas_dbus_getter_p2p_group_members,
5079 NULL,
5080 NULL
5081 },
5082 { "Group", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "o",
5083 wpas_dbus_getter_p2p_group,
5084 NULL,
5085 NULL
5086 },
5087 { "Role", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "s",
5088 wpas_dbus_getter_p2p_role,
5089 NULL,
5090 NULL
5091 },
5092 { "SSID", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay",
5093 wpas_dbus_getter_p2p_group_ssid,
5094 NULL,
5095 NULL
5096 },
5097 { "BSSID", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay",
5098 wpas_dbus_getter_p2p_group_bssid,
5099 NULL,
5100 NULL
5101 },
5102 { "Frequency", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "q",
5103 wpas_dbus_getter_p2p_group_frequency,
5104 NULL,
5105 NULL
5106 },
5107 { "Passphrase", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "s",
5108 wpas_dbus_getter_p2p_group_passphrase,
5109 NULL,
5110 NULL
5111 },
5112 { "PSK", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay",
5113 wpas_dbus_getter_p2p_group_psk,
5114 NULL,
5115 NULL
5116 },
5117 { "WPSVendorExtensions", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "aay",
5118 wpas_dbus_getter_p2p_group_vendor_ext,
5119 wpas_dbus_setter_p2p_group_vendor_ext,
5120 NULL
5121 },
5122 { NULL, NULL, NULL, NULL, NULL, NULL }
5123 };
5124
5125 static const struct wpa_dbus_signal_desc wpas_dbus_p2p_group_signals[] = {
5126 { "PeerJoined", WPAS_DBUS_NEW_IFACE_P2P_GROUP,
5127 {
5128 { "peer", "o", ARG_OUT },
5129 END_ARGS
5130 }
5131 },
5132 { "PeerDisconnected", WPAS_DBUS_NEW_IFACE_P2P_GROUP,
5133 {
5134 { "peer", "o", ARG_OUT },
5135 END_ARGS
5136 }
5137 },
5138 { NULL, NULL, { END_ARGS } }
5139 };
5140
5141 /**
5142 * wpas_dbus_register_p2p_group - Register a p2p group object with dbus
5143 * @wpa_s: wpa_supplicant interface structure
5144 * @ssid: SSID struct
5145 * Returns: 0 on success, -1 on failure
5146 *
5147 * Registers p2p group representing object with dbus
5148 */
wpas_dbus_register_p2p_group(struct wpa_supplicant * wpa_s,struct wpa_ssid * ssid)5149 void wpas_dbus_register_p2p_group(struct wpa_supplicant *wpa_s,
5150 struct wpa_ssid *ssid)
5151 {
5152 struct wpas_dbus_priv *ctrl_iface;
5153 struct wpa_dbus_object_desc *obj_desc;
5154 char group_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
5155
5156 /* Do nothing if the control interface is not turned on */
5157 if (wpa_s == NULL || wpa_s->global == NULL)
5158 return;
5159
5160 ctrl_iface = wpa_s->global->dbus;
5161 if (ctrl_iface == NULL)
5162 return;
5163
5164 if (wpa_s->dbus_groupobj_path) {
5165 wpa_printf(MSG_INFO, "%s: Group object '%s' already exists",
5166 __func__, wpa_s->dbus_groupobj_path);
5167 return;
5168 }
5169
5170 if (wpas_dbus_get_group_obj_path(wpa_s, ssid, group_obj_path) < 0)
5171 return;
5172
5173 wpa_s->dbus_groupobj_path = os_strdup(group_obj_path);
5174 if (wpa_s->dbus_groupobj_path == NULL)
5175 return;
5176
5177 wpa_printf(MSG_INFO, "dbus: Register group object '%s'",
5178 group_obj_path);
5179 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
5180 if (!obj_desc) {
5181 wpa_printf(MSG_ERROR,
5182 "Not enough memory to create object description");
5183 goto err;
5184 }
5185
5186 wpas_dbus_register(obj_desc, wpa_s, NULL, NULL,
5187 wpas_dbus_p2p_group_properties,
5188 wpas_dbus_p2p_group_signals);
5189
5190 if (wpa_dbus_register_object_per_iface(ctrl_iface, group_obj_path,
5191 wpa_s->ifname, obj_desc))
5192 goto err;
5193
5194 return;
5195
5196 err:
5197 if (wpa_s->dbus_groupobj_path) {
5198 os_free(wpa_s->dbus_groupobj_path);
5199 wpa_s->dbus_groupobj_path = NULL;
5200 }
5201
5202 free_dbus_object_desc(obj_desc);
5203 }
5204
5205 /**
5206 * wpas_dbus_unregister_p2p_group - Unregister a p2p group object from dbus
5207 * @wpa_s: wpa_supplicant interface structure
5208 * @ssid: network name of the p2p group started
5209 */
wpas_dbus_unregister_p2p_group(struct wpa_supplicant * wpa_s,const struct wpa_ssid * ssid)5210 void wpas_dbus_unregister_p2p_group(struct wpa_supplicant *wpa_s,
5211 const struct wpa_ssid *ssid)
5212 {
5213 struct wpas_dbus_priv *ctrl_iface;
5214
5215 /* Do nothing if the control interface is not turned on */
5216 if (wpa_s == NULL || wpa_s->global == NULL)
5217 return;
5218
5219 if (wpa_s->p2p_mgmt)
5220 wpa_s = wpa_s->parent;
5221
5222 ctrl_iface = wpa_s->global->dbus;
5223 if (ctrl_iface == NULL)
5224 return;
5225
5226 if (!wpa_s->dbus_groupobj_path) {
5227 wpa_printf(MSG_DEBUG,
5228 "%s: Group object has already unregistered",
5229 __func__);
5230 return;
5231 }
5232
5233 peer_groups_changed(wpa_s);
5234
5235 wpa_printf(MSG_DEBUG, "dbus: Unregister group object '%s'",
5236 wpa_s->dbus_groupobj_path);
5237
5238 wpa_dbus_unregister_object_per_iface(ctrl_iface,
5239 wpa_s->dbus_groupobj_path);
5240
5241 os_free(wpa_s->dbus_groupobj_path);
5242 wpa_s->dbus_groupobj_path = NULL;
5243 }
5244
5245 static const struct wpa_dbus_property_desc
5246 wpas_dbus_persistent_group_properties[] = {
5247 { "Properties", WPAS_DBUS_NEW_IFACE_PERSISTENT_GROUP, "a{sv}",
5248 wpas_dbus_getter_persistent_group_properties,
5249 wpas_dbus_setter_persistent_group_properties,
5250 NULL
5251 },
5252 { NULL, NULL, NULL, NULL, NULL, NULL }
5253 };
5254
5255 /* No signals intended for persistent group objects */
5256
5257 /**
5258 * wpas_dbus_register_persistent_group - Register a configured(saved)
5259 * persistent group with dbus
5260 * @wpa_s: wpa_supplicant interface structure
5261 * @ssid: persistent group (still represented as a network within wpa)
5262 * configuration data
5263 * Returns: 0 on success, -1 on failure
5264 *
5265 * Registers a persistent group representing object with dbus.
5266 */
wpas_dbus_register_persistent_group(struct wpa_supplicant * wpa_s,struct wpa_ssid * ssid)5267 int wpas_dbus_register_persistent_group(struct wpa_supplicant *wpa_s,
5268 struct wpa_ssid *ssid)
5269 {
5270 struct wpas_dbus_priv *ctrl_iface;
5271 struct wpa_dbus_object_desc *obj_desc;
5272 struct network_handler_args *arg;
5273 char pgrp_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
5274
5275 /* Do nothing if the control interface is not turned on */
5276 if (wpa_s == NULL || wpa_s->global == NULL)
5277 return 0;
5278 wpa_s = wpa_s->parent->parent;
5279 if (!wpa_s->dbus_new_path)
5280 return 0;
5281
5282 /* Make sure ssid is a persistent group */
5283 if (ssid->disabled != 2 && !ssid->p2p_persistent_group)
5284 return -1; /* should we return w/o complaining? */
5285
5286 if (wpa_s->p2p_mgmt)
5287 wpa_s = wpa_s->parent;
5288
5289 ctrl_iface = wpa_s->global->dbus;
5290 if (ctrl_iface == NULL)
5291 return 0;
5292
5293 /*
5294 * Intentionally not coming up with different numbering scheme
5295 * for persistent groups.
5296 */
5297 os_snprintf(pgrp_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
5298 "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%u",
5299 wpa_s->dbus_new_path, ssid->id);
5300
5301 wpa_printf(MSG_DEBUG, "dbus: Register persistent group object '%s'",
5302 pgrp_obj_path);
5303 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
5304 if (!obj_desc) {
5305 wpa_printf(MSG_ERROR,
5306 "dbus: Not enough memory to create object description");
5307 goto err;
5308 }
5309
5310 /*
5311 * Reusing the same context structure as that for networks
5312 * since these are represented using same data structure.
5313 */
5314 /* allocate memory for handlers arguments */
5315 arg = os_zalloc(sizeof(struct network_handler_args));
5316 if (!arg) {
5317 wpa_printf(MSG_ERROR,
5318 "dbus: Not enough memory to create arguments for method");
5319 goto err;
5320 }
5321
5322 arg->wpa_s = wpa_s;
5323 arg->ssid = ssid;
5324
5325 wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
5326 wpas_dbus_persistent_group_properties,
5327 NULL);
5328
5329 if (wpa_dbus_register_object_per_iface(ctrl_iface, pgrp_obj_path,
5330 wpa_s->ifname, obj_desc))
5331 goto err;
5332
5333 wpas_dbus_signal_persistent_group_added(wpa_s, ssid->id);
5334
5335 return 0;
5336
5337 err:
5338 free_dbus_object_desc(obj_desc);
5339 return -1;
5340 }
5341
5342
5343 /**
5344 * wpas_dbus_unregister_persistent_group - Unregister a persistent_group
5345 * from dbus
5346 * @wpa_s: wpa_supplicant interface structure
5347 * @nid: network id
5348 * Returns: 0 on success, -1 on failure
5349 *
5350 * Unregisters persistent group representing object from dbus
5351 *
5352 * NOTE: There is a slight issue with the semantics here. While the
5353 * implementation simply means the persistent group is unloaded from memory,
5354 * it should not get interpreted as the group is actually being erased/removed
5355 * from persistent storage as well.
5356 */
wpas_dbus_unregister_persistent_group(struct wpa_supplicant * wpa_s,int nid)5357 int wpas_dbus_unregister_persistent_group(struct wpa_supplicant *wpa_s,
5358 int nid)
5359 {
5360 struct wpas_dbus_priv *ctrl_iface;
5361 char pgrp_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
5362 int ret;
5363
5364 /* Do nothing if the control interface is not turned on */
5365 if (wpa_s == NULL || wpa_s->global == NULL)
5366 return 0;
5367
5368 wpa_s = wpa_s->parent->parent;
5369
5370 ctrl_iface = wpa_s->global->dbus;
5371 if (ctrl_iface == NULL || !wpa_s->dbus_new_path)
5372 return 0;
5373
5374 os_snprintf(pgrp_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
5375 "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%u",
5376 wpa_s->dbus_new_path, nid);
5377
5378 wpa_printf(MSG_DEBUG, "dbus: Unregister persistent group object '%s'",
5379 pgrp_obj_path);
5380 ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, pgrp_obj_path);
5381
5382 if (!ret)
5383 wpas_dbus_signal_persistent_group_removed(wpa_s, nid);
5384
5385 return ret;
5386 }
5387
5388 #endif /* CONFIG_P2P */
5389
5390
5391 #ifdef CONFIG_HS20
5392 /**
5393 * wpas_dbus_signal_hs20_t_c_acceptance - Signals a terms and conditions was
5394 * received.
5395 *
5396 * @wpa_s: %wpa_supplicant network interface data
5397 * @url: URL of the terms and conditions acceptance page.
5398 */
wpas_dbus_signal_hs20_t_c_acceptance(struct wpa_supplicant * wpa_s,const char * url)5399 void wpas_dbus_signal_hs20_t_c_acceptance(struct wpa_supplicant *wpa_s,
5400 const char *url)
5401 {
5402 struct wpas_dbus_priv *iface;
5403 DBusMessage *msg;
5404
5405 iface = wpa_s->global->dbus;
5406
5407 /* Do nothing if the control interface is not turned on */
5408 if (!iface || !wpa_s->dbus_new_path)
5409 return;
5410
5411 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
5412 WPAS_DBUS_NEW_IFACE_INTERFACE,
5413 "HS20TermsAndConditions");
5414 if (!msg)
5415 return;
5416
5417 if (dbus_message_append_args(msg, DBUS_TYPE_STRING, &url,
5418 DBUS_TYPE_INVALID))
5419 dbus_connection_send(iface->con, msg, NULL);
5420 else
5421 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
5422 dbus_message_unref(msg);
5423 }
5424 #endif /* CONFIG_HS20 */
5425
5426
5427 #ifdef CONFIG_NAN_USD
5428
5429 /**
5430 * wpas_dbus_signal_nan_discovery_result - Send NANDiscoveryResult signal
5431 * @wpa_s: %wpa_supplicant network interface data
5432 * @srv_proto_type: Service Protocol Type
5433 * @subscribe_id: Subscribe ID of the session
5434 * @peer_publish_id: Publish ID of the sender
5435 * @peer_addr: MAC address of the peer device
5436 * @ssi: Service specific information payload
5437 * @ssi_len: Length of the SSI field
5438 *
5439 * This is used to indicate the NAN DE DiscoveryResult event.
5440 */
wpas_dbus_signal_nan_discovery_result(struct wpa_supplicant * wpa_s,enum nan_service_protocol_type srv_proto_type,int subscribe_id,int peer_publish_id,const u8 * peer_addr,bool fsd,bool fsd_gas,const u8 * ssi,size_t ssi_len)5441 void wpas_dbus_signal_nan_discovery_result(struct wpa_supplicant *wpa_s,
5442 enum nan_service_protocol_type
5443 srv_proto_type,
5444 int subscribe_id,
5445 int peer_publish_id,
5446 const u8 *peer_addr,
5447 bool fsd, bool fsd_gas,
5448 const u8 *ssi, size_t ssi_len)
5449 {
5450 struct wpas_dbus_priv *iface;
5451 DBusMessage *msg;
5452 DBusMessageIter iter, dict_iter;
5453 char addr_str[20];
5454
5455 iface = wpa_s->global->dbus;
5456 /* Do nothing if the interface is not turned on */
5457 if (!iface || !wpa_s->dbus_new_path)
5458 return;
5459 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
5460 WPAS_DBUS_NEW_IFACE_INTERFACE,
5461 "NANDiscoveryResult");
5462 if (!msg)
5463 return;
5464
5465 snprintf(addr_str, sizeof(addr_str), MACSTR, MAC2STR(peer_addr));
5466
5467 dbus_message_iter_init_append(msg, &iter);
5468
5469 if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
5470 !wpa_dbus_dict_append_uint32(&dict_iter, "subscribe_id",
5471 subscribe_id) ||
5472 !wpa_dbus_dict_append_uint32(&dict_iter, "publish_id",
5473 peer_publish_id) ||
5474 !wpa_dbus_dict_append_string(&dict_iter, "peer_addr", addr_str) ||
5475 !wpa_dbus_dict_append_bool(&dict_iter, "fsd", fsd) ||
5476 !wpa_dbus_dict_append_bool(&dict_iter, "fsd_gas", fsd_gas) ||
5477 !wpa_dbus_dict_append_uint32(&dict_iter, "srv_proto_type",
5478 srv_proto_type) ||
5479 (ssi &&
5480 !wpa_dbus_dict_append_byte_array(&dict_iter,
5481 "ssi",
5482 (const char *) ssi,
5483 ssi_len)) ||
5484 !wpa_dbus_dict_close_write(&iter, &dict_iter))
5485 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
5486 else
5487 dbus_connection_send(iface->con, msg, NULL);
5488 dbus_message_unref(msg);
5489 }
5490
5491
5492 /**
5493 * wpas_dbus_signal_nan_replied - Send NANReplied signal
5494 * @wpa_s: %wpa_supplicant network interface data
5495 * @srv_proto_type: Service Protocol Type
5496 * @publish_id: Publish id of the session
5497 * @peer_subscribe_id: Subscribe id of the sender
5498 * @peer_addr: MAC address of the peer device
5499 * @ssi: Service specific information payload
5500 * @ssi_len: Length of the SSI field
5501 *
5502 * This is used to indicate the NAN DE Replied event.
5503 */
wpas_dbus_signal_nan_replied(struct wpa_supplicant * wpa_s,enum nan_service_protocol_type srv_proto_type,int publish_id,int peer_subscribe_id,const u8 * peer_addr,const u8 * ssi,size_t ssi_len)5504 void wpas_dbus_signal_nan_replied(struct wpa_supplicant *wpa_s,
5505 enum nan_service_protocol_type srv_proto_type,
5506 int publish_id,
5507 int peer_subscribe_id,
5508 const u8 *peer_addr,
5509 const u8 *ssi, size_t ssi_len)
5510 {
5511 struct wpas_dbus_priv *iface;
5512 DBusMessage *msg;
5513 DBusMessageIter iter, dict_iter;
5514 char addr_str[20];
5515
5516 iface = wpa_s->global->dbus;
5517 /* Do nothing if the interface is not turned on */
5518 if (!iface || !wpa_s->dbus_new_path)
5519 return;
5520
5521 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
5522 WPAS_DBUS_NEW_IFACE_INTERFACE,
5523 "NANReplied");
5524 if (!msg)
5525 return;
5526
5527 snprintf(addr_str, sizeof(addr_str), MACSTR, MAC2STR(peer_addr));
5528
5529 dbus_message_iter_init_append(msg, &iter);
5530
5531 if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
5532 !wpa_dbus_dict_append_uint32(&dict_iter, "publish_id",
5533 publish_id) ||
5534 !wpa_dbus_dict_append_uint32(&dict_iter, "subscribe_id",
5535 peer_subscribe_id) ||
5536 !wpa_dbus_dict_append_string(&dict_iter, "peer_addr", addr_str) ||
5537 !wpa_dbus_dict_append_uint32(&dict_iter, "srv_proto_type",
5538 srv_proto_type) ||
5539 (ssi &&
5540 !wpa_dbus_dict_append_byte_array(&dict_iter, "ssi",
5541 (const char *) ssi,
5542 ssi_len)) ||
5543 !wpa_dbus_dict_close_write(&iter, &dict_iter))
5544 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
5545 else
5546 dbus_connection_send(iface->con, msg, NULL);
5547 dbus_message_unref(msg);
5548 }
5549
5550
5551 /**
5552 * wpas_dbus_signal_nan_receive - Send NANReceive signal
5553 * @wpa_s: %wpa_supplicant network interface data
5554 * @id: The original publish_id or subscribe_id
5555 * @peer_id: Peer instance identifier
5556 * @peer_addr: Address of the sender
5557 * @ssi: Service specific information payload
5558 * @ssi_len: Length of the SSI
5559 *
5560 * This is used to indicate the NAN DE Receive event to notify reception of a
5561 * follow-up frame.
5562 */
wpas_dbus_signal_nan_receive(struct wpa_supplicant * wpa_s,int id,int peer_id,const u8 * peer_addr,const u8 * ssi,size_t ssi_len)5563 void wpas_dbus_signal_nan_receive(struct wpa_supplicant *wpa_s,
5564 int id, int peer_id, const u8 *peer_addr,
5565 const u8 *ssi, size_t ssi_len)
5566 {
5567 struct wpas_dbus_priv *iface;
5568 DBusMessage *msg;
5569 DBusMessageIter iter, dict_iter;
5570 char addr_str[20];
5571
5572 iface = wpa_s->global->dbus;
5573 /* Do nothing if the interface is not turned on */
5574 if (!iface || !wpa_s->dbus_new_path)
5575 return;
5576
5577 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
5578 WPAS_DBUS_NEW_IFACE_INTERFACE,
5579 "NANReceive");
5580 if (!msg)
5581 return;
5582
5583 snprintf(addr_str, sizeof(addr_str), MACSTR, MAC2STR(peer_addr));
5584
5585 dbus_message_iter_init_append(msg, &iter);
5586
5587 if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
5588 !wpa_dbus_dict_append_uint32(&dict_iter, "id", id) ||
5589 !wpa_dbus_dict_append_uint32(&dict_iter, "peer_id", peer_id) ||
5590 !wpa_dbus_dict_append_string(&dict_iter, "peer_addr", addr_str) ||
5591 (ssi &&
5592 !wpa_dbus_dict_append_byte_array(&dict_iter, "ssi",
5593 (const char *) ssi,
5594 ssi_len)) ||
5595 !wpa_dbus_dict_close_write(&iter, &dict_iter))
5596 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
5597 else
5598 dbus_connection_send(iface->con, msg, NULL);
5599 dbus_message_unref(msg);
5600 }
5601
5602
5603 /**
5604 * wpas_dbus_signal_nan_publish_terminated - Send NANPublishTerminated signal
5605 * @wpa_s: %wpa_supplicant network interface data
5606 * @publish_id: The publish_id of the session
5607 * @reason: The reason of the termination
5608 *
5609 * This is used to indicate the NAN DE PublishTerminated event to notify when
5610 * the session has expired.
5611 */
wpas_dbus_signal_nan_publish_terminated(struct wpa_supplicant * wpa_s,int publish_id,const char * reason)5612 void wpas_dbus_signal_nan_publish_terminated(struct wpa_supplicant *wpa_s,
5613 int publish_id,
5614 const char *reason)
5615 {
5616 struct wpas_dbus_priv *iface;
5617 DBusMessage *msg;
5618 dbus_uint32_t pub_id = publish_id;
5619
5620 iface = wpa_s->global->dbus;
5621 /* Do nothing if the interface is not turned on */
5622 if (!iface || !wpa_s->dbus_new_path)
5623 return;
5624
5625 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
5626 WPAS_DBUS_NEW_IFACE_INTERFACE,
5627 "NANPublishTerminated");
5628 if (!msg)
5629 return;
5630
5631 if (!dbus_message_append_args(msg, DBUS_TYPE_UINT32, &pub_id,
5632 DBUS_TYPE_INVALID) ||
5633 !dbus_message_append_args(msg, DBUS_TYPE_STRING, &reason,
5634 DBUS_TYPE_INVALID))
5635 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
5636 else
5637 dbus_connection_send(iface->con, msg, NULL);
5638 dbus_message_unref(msg);
5639 }
5640
5641
5642 /**
5643 * wpas_dbus_signal_nan_subscribe_terminated - Send NANSubscribeTerminated signal
5644 * @wpa_s: %wpa_supplicant network interface data
5645 * @subscribe_id: The subscribe_id of the session
5646 * @reason: The reason of the termination
5647 *
5648 * This is used to indicate the NAN DE SubscribeTerminated event to notify when
5649 * the session has expired.
5650 */
wpas_dbus_signal_nan_subscribe_terminated(struct wpa_supplicant * wpa_s,int subscribe_id,const char * reason)5651 void wpas_dbus_signal_nan_subscribe_terminated(struct wpa_supplicant *wpa_s,
5652 int subscribe_id,
5653 const char *reason)
5654 {
5655 struct wpas_dbus_priv *iface;
5656 DBusMessage *msg;
5657 dbus_uint32_t sub_id = subscribe_id;
5658
5659 iface = wpa_s->global->dbus;
5660 /* Do nothing if the interface is not turned on */
5661 if (!iface || !wpa_s->dbus_new_path)
5662 return;
5663
5664 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
5665 WPAS_DBUS_NEW_IFACE_INTERFACE,
5666 "NANSubscribeTerminated");
5667 if (!msg)
5668 return;
5669
5670 if (!dbus_message_append_args(msg, DBUS_TYPE_UINT32, &sub_id,
5671 DBUS_TYPE_INVALID) ||
5672 !dbus_message_append_args(msg, DBUS_TYPE_STRING, &reason,
5673 DBUS_TYPE_INVALID))
5674 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
5675 else
5676 dbus_connection_send(iface->con, msg, NULL);
5677 dbus_message_unref(msg);
5678 }
5679
5680 #endif /* CONFIG_NAN_USD */
5681