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 #endif /* CONFIG_INTERWORKING */
1027
1028
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)1029 void wpas_dbus_signal_certification(struct wpa_supplicant *wpa_s,
1030 int depth, const char *subject,
1031 const char *altsubject[],
1032 int num_altsubject,
1033 const char *cert_hash,
1034 const struct wpabuf *cert)
1035 {
1036 struct wpas_dbus_priv *iface;
1037 DBusMessage *msg;
1038 DBusMessageIter iter, dict_iter;
1039
1040 iface = wpa_s->global->dbus;
1041
1042 /* Do nothing if the control interface is not turned on */
1043 if (iface == NULL || !wpa_s->dbus_new_path)
1044 return;
1045
1046 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1047 WPAS_DBUS_NEW_IFACE_INTERFACE,
1048 "Certification");
1049 if (msg == NULL)
1050 return;
1051
1052 dbus_message_iter_init_append(msg, &iter);
1053 if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
1054 !wpa_dbus_dict_append_uint32(&dict_iter, "depth", depth) ||
1055 !wpa_dbus_dict_append_string(&dict_iter, "subject", subject) ||
1056 (altsubject && num_altsubject &&
1057 !wpa_dbus_dict_append_string_array(&dict_iter, "altsubject",
1058 altsubject, num_altsubject)) ||
1059 (cert_hash &&
1060 !wpa_dbus_dict_append_string(&dict_iter, "cert_hash",
1061 cert_hash)) ||
1062 (cert &&
1063 !wpa_dbus_dict_append_byte_array(&dict_iter, "cert",
1064 wpabuf_head(cert),
1065 wpabuf_len(cert))) ||
1066 !wpa_dbus_dict_close_write(&iter, &dict_iter))
1067 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1068 else
1069 dbus_connection_send(iface->con, msg, NULL);
1070 dbus_message_unref(msg);
1071 }
1072
1073
wpas_dbus_signal_eap_status(struct wpa_supplicant * wpa_s,const char * status,const char * parameter)1074 void wpas_dbus_signal_eap_status(struct wpa_supplicant *wpa_s,
1075 const char *status, const char *parameter)
1076 {
1077 struct wpas_dbus_priv *iface;
1078 DBusMessage *msg;
1079 DBusMessageIter iter;
1080
1081 iface = wpa_s->global->dbus;
1082
1083 /* Do nothing if the control interface is not turned on */
1084 if (iface == NULL || !wpa_s->dbus_new_path)
1085 return;
1086
1087 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1088 WPAS_DBUS_NEW_IFACE_INTERFACE,
1089 "EAP");
1090 if (msg == NULL)
1091 return;
1092
1093 dbus_message_iter_init_append(msg, &iter);
1094
1095 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &status) ||
1096 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING,
1097 ¶meter))
1098 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1099 else
1100 dbus_connection_send(iface->con, msg, NULL);
1101 dbus_message_unref(msg);
1102 }
1103
1104
1105 /**
1106 * wpas_dbus_signal_sta - Send a station related event signal
1107 * @wpa_s: %wpa_supplicant network interface data
1108 * @sta: station mac address
1109 * @sig_name: signal name - StaAuthorized or StaDeauthorized
1110 *
1111 * Notify listeners about event related with station
1112 */
wpas_dbus_signal_sta(struct wpa_supplicant * wpa_s,const u8 * sta,const char * sig_name)1113 static void wpas_dbus_signal_sta(struct wpa_supplicant *wpa_s,
1114 const u8 *sta, const char *sig_name)
1115 {
1116 struct wpas_dbus_priv *iface;
1117 DBusMessage *msg;
1118 char sta_mac[WPAS_DBUS_OBJECT_PATH_MAX];
1119 char *dev_mac;
1120
1121 os_snprintf(sta_mac, WPAS_DBUS_OBJECT_PATH_MAX, MACSTR, MAC2STR(sta));
1122 dev_mac = sta_mac;
1123
1124 iface = wpa_s->global->dbus;
1125
1126 /* Do nothing if the control interface is not turned on */
1127 if (iface == NULL || !wpa_s->dbus_new_path)
1128 return;
1129
1130 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1131 WPAS_DBUS_NEW_IFACE_INTERFACE, sig_name);
1132 if (msg == NULL)
1133 return;
1134
1135 if (dbus_message_append_args(msg, DBUS_TYPE_STRING, &dev_mac,
1136 DBUS_TYPE_INVALID))
1137 dbus_connection_send(iface->con, msg, NULL);
1138 else
1139 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1140 dbus_message_unref(msg);
1141
1142 wpa_printf(MSG_DEBUG, "dbus: Station MAC address '%s' '%s'",
1143 sta_mac, sig_name);
1144 }
1145
1146
1147 /**
1148 * wpas_dbus_signal_sta_authorized - Send a STA authorized signal
1149 * @wpa_s: %wpa_supplicant network interface data
1150 * @sta: station mac address
1151 *
1152 * Notify listeners a new station has been authorized
1153 */
wpas_dbus_signal_sta_authorized(struct wpa_supplicant * wpa_s,const u8 * sta)1154 void wpas_dbus_signal_sta_authorized(struct wpa_supplicant *wpa_s,
1155 const u8 *sta)
1156 {
1157 wpas_dbus_signal_sta(wpa_s, sta, "StaAuthorized");
1158 }
1159
1160
1161 /**
1162 * wpas_dbus_signal_sta_deauthorized - Send a STA deauthorized signal
1163 * @wpa_s: %wpa_supplicant network interface data
1164 * @sta: station mac address
1165 *
1166 * Notify listeners a station has been deauthorized
1167 */
wpas_dbus_signal_sta_deauthorized(struct wpa_supplicant * wpa_s,const u8 * sta)1168 void wpas_dbus_signal_sta_deauthorized(struct wpa_supplicant *wpa_s,
1169 const u8 *sta)
1170 {
1171 wpas_dbus_signal_sta(wpa_s, sta, "StaDeauthorized");
1172 }
1173
1174
1175 /**
1176 * wpas_dbus_signal_station - Send an event signal related to a station object
1177 * @wpa_s: %wpa_supplicant network interface data
1178 * @station_obj_path: Station object path
1179 * @sig_name: signal name - StationAdded or StationRemoved
1180 * @properties: Whether to add second argument with object properties
1181 *
1182 * Notify listeners about event related with station.
1183 */
wpas_dbus_signal_station(struct wpa_supplicant * wpa_s,const char * station_obj_path,const char * sig_name,dbus_bool_t properties)1184 static void wpas_dbus_signal_station(struct wpa_supplicant *wpa_s,
1185 const char *station_obj_path,
1186 const char *sig_name,
1187 dbus_bool_t properties)
1188 {
1189 struct wpas_dbus_priv *iface;
1190 DBusMessage *msg;
1191 DBusMessageIter iter;
1192
1193 iface = wpa_s->global->dbus;
1194
1195 /* Do nothing if the control interface is not turned on */
1196 if (!iface || !wpa_s->dbus_new_path)
1197 return;
1198
1199 wpa_printf(MSG_DEBUG, "dbus: STA signal %s", sig_name);
1200 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1201 WPAS_DBUS_NEW_IFACE_INTERFACE, sig_name);
1202 if (!msg)
1203 return;
1204
1205 dbus_message_iter_init_append(msg, &iter);
1206 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
1207 &station_obj_path) ||
1208 (properties &&
1209 !wpa_dbus_get_object_properties(iface, station_obj_path,
1210 WPAS_DBUS_NEW_IFACE_STA,
1211 &iter)))
1212 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1213 else
1214 dbus_connection_send(iface->con, msg, NULL);
1215 dbus_message_unref(msg);
1216 }
1217
1218
1219 /**
1220 * wpas_dbus_signal_station_added - Send a Station added signal
1221 * @wpa_s: %wpa_supplicant network interface data
1222 * @station_obj_path: new Station object path
1223 *
1224 * Notify listeners about adding new Station
1225 */
wpas_dbus_signal_station_added(struct wpa_supplicant * wpa_s,const char * station_obj_path)1226 static void wpas_dbus_signal_station_added(struct wpa_supplicant *wpa_s,
1227 const char *station_obj_path)
1228 {
1229 wpas_dbus_signal_station(wpa_s, station_obj_path, "StationAdded", TRUE);
1230 }
1231
1232
1233 /**
1234 * wpas_dbus_signal_station_removed - Send a Station removed signal
1235 * @wpa_s: %wpa_supplicant network interface data
1236 * @station_obj_path: Station object path
1237 *
1238 * Notify listeners about removing Station
1239 */
wpas_dbus_signal_station_removed(struct wpa_supplicant * wpa_s,const char * station_obj_path)1240 static void wpas_dbus_signal_station_removed(struct wpa_supplicant *wpa_s,
1241 const char *station_obj_path)
1242 {
1243 wpas_dbus_signal_station(wpa_s, station_obj_path, "StationRemoved",
1244 FALSE);
1245 }
1246
1247
1248 #ifdef CONFIG_P2P
1249
1250 /**
1251 * wpas_dbus_signal_p2p_group_removed - Signals P2P group was removed
1252 * @wpa_s: %wpa_supplicant network interface data
1253 * @role: role of this device (client or GO)
1254 * Sends signal with i/f name and role as string arguments
1255 */
wpas_dbus_signal_p2p_group_removed(struct wpa_supplicant * wpa_s,const char * role)1256 void wpas_dbus_signal_p2p_group_removed(struct wpa_supplicant *wpa_s,
1257 const char *role)
1258 {
1259 DBusMessage *msg;
1260 DBusMessageIter iter, dict_iter;
1261 struct wpas_dbus_priv *iface = wpa_s->global->dbus;
1262 struct wpa_supplicant *parent;
1263
1264 /* Do nothing if the control interface is not turned on */
1265 if (iface == NULL)
1266 return;
1267
1268 parent = wpa_s->parent;
1269 if (parent->p2p_mgmt)
1270 parent = parent->parent;
1271
1272 if (!wpa_s->dbus_groupobj_path || !wpa_s->dbus_new_path ||
1273 !parent->dbus_new_path)
1274 return;
1275
1276 msg = dbus_message_new_signal(parent->dbus_new_path,
1277 WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1278 "GroupFinished");
1279 if (msg == NULL)
1280 return;
1281
1282 dbus_message_iter_init_append(msg, &iter);
1283 if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
1284 !wpa_dbus_dict_append_object_path(&dict_iter,
1285 "interface_object",
1286 wpa_s->dbus_new_path) ||
1287 !wpa_dbus_dict_append_string(&dict_iter, "role", role) ||
1288 !wpa_dbus_dict_append_object_path(&dict_iter, "group_object",
1289 wpa_s->dbus_groupobj_path) ||
1290 !wpa_dbus_dict_close_write(&iter, &dict_iter))
1291 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1292 else
1293 dbus_connection_send(iface->con, msg, NULL);
1294 dbus_message_unref(msg);
1295 }
1296
1297
1298 /**
1299 * wpas_dbus_signal_p2p_provision_discovery - Signals various PD events
1300 *
1301 * @dev_addr - who sent the request or responded to our request.
1302 * @request - Will be 1 if request, 0 for response.
1303 * @status - valid only in case of response
1304 * @config_methods - wps config methods
1305 * @generated_pin - pin to be displayed in case of WPS_CONFIG_DISPLAY method
1306 *
1307 * Sends following provision discovery related events:
1308 * ProvisionDiscoveryRequestDisplayPin
1309 * ProvisionDiscoveryResponseDisplayPin
1310 * ProvisionDiscoveryRequestEnterPin
1311 * ProvisionDiscoveryResponseEnterPin
1312 * ProvisionDiscoveryPBCRequest
1313 * ProvisionDiscoveryPBCResponse
1314 *
1315 * TODO::
1316 * ProvisionDiscoveryFailure (timeout case)
1317 */
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)1318 void wpas_dbus_signal_p2p_provision_discovery(struct wpa_supplicant *wpa_s,
1319 const u8 *dev_addr, int request,
1320 enum p2p_prov_disc_status status,
1321 u16 config_methods,
1322 unsigned int generated_pin)
1323 {
1324 DBusMessage *msg;
1325 DBusMessageIter iter;
1326 struct wpas_dbus_priv *iface;
1327 char *_signal;
1328 int add_pin = 0;
1329 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1330 int error_ret = 1;
1331 char pin[9], *p_pin = NULL;
1332
1333 iface = wpa_s->global->dbus;
1334
1335 /* Do nothing if the control interface is not turned on */
1336 if (iface == NULL)
1337 return;
1338
1339 if (wpa_s->p2p_mgmt)
1340 wpa_s = wpa_s->parent;
1341 if (!wpa_s->dbus_new_path)
1342 return;
1343
1344 if (request || !status) {
1345 if (config_methods & WPS_CONFIG_DISPLAY)
1346 _signal = request ?
1347 "ProvisionDiscoveryRequestDisplayPin" :
1348 "ProvisionDiscoveryResponseEnterPin";
1349 else if (config_methods & WPS_CONFIG_KEYPAD)
1350 _signal = request ?
1351 "ProvisionDiscoveryRequestEnterPin" :
1352 "ProvisionDiscoveryResponseDisplayPin";
1353 else if (config_methods & WPS_CONFIG_PUSHBUTTON)
1354 _signal = request ? "ProvisionDiscoveryPBCRequest" :
1355 "ProvisionDiscoveryPBCResponse";
1356 else
1357 return; /* Unknown or un-supported method */
1358 } else {
1359 /* Explicit check for failure response */
1360 _signal = "ProvisionDiscoveryFailure";
1361 }
1362
1363 add_pin = ((request && (config_methods & WPS_CONFIG_DISPLAY)) ||
1364 (!request && !status &&
1365 (config_methods & WPS_CONFIG_KEYPAD)));
1366
1367 if (add_pin) {
1368 os_snprintf(pin, sizeof(pin), "%08d", generated_pin);
1369 p_pin = pin;
1370 }
1371
1372 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1373 WPAS_DBUS_NEW_IFACE_P2PDEVICE, _signal);
1374 if (msg == NULL)
1375 return;
1376
1377 /* Check if this is a known peer */
1378 if (!p2p_peer_known(wpa_s->global->p2p, dev_addr))
1379 goto error;
1380
1381 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1382 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
1383 COMPACT_MACSTR,
1384 wpa_s->dbus_new_path, MAC2STR(dev_addr));
1385
1386 path = peer_obj_path;
1387
1388 dbus_message_iter_init_append(msg, &iter);
1389
1390 if (!dbus_message_iter_append_basic(&iter,
1391 DBUS_TYPE_OBJECT_PATH,
1392 &path))
1393 goto error;
1394
1395 if (!request && status)
1396 /* Attach status to ProvisionDiscoveryFailure */
1397 error_ret = !dbus_message_iter_append_basic(&iter,
1398 DBUS_TYPE_INT32,
1399 &status);
1400 else
1401 error_ret = (add_pin &&
1402 !dbus_message_iter_append_basic(&iter,
1403 DBUS_TYPE_STRING,
1404 &p_pin));
1405
1406 error:
1407 if (!error_ret)
1408 dbus_connection_send(iface->con, msg, NULL);
1409 else
1410 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1411
1412 dbus_message_unref(msg);
1413 }
1414
1415
1416 /**
1417 * wpas_dbus_signal_p2p_go_neg_req - Signal P2P GO Negotiation Request RX
1418 * @wpa_s: %wpa_supplicant network interface data
1419 * @src: Source address of the message triggering this notification
1420 * @dev_passwd_id: WPS Device Password Id
1421 * @go_intent: Peer's GO Intent value
1422 *
1423 * Sends signal to notify that a peer P2P Device is requesting group owner
1424 * negotiation with us.
1425 */
wpas_dbus_signal_p2p_go_neg_req(struct wpa_supplicant * wpa_s,const u8 * src,u16 dev_passwd_id,u8 go_intent)1426 void wpas_dbus_signal_p2p_go_neg_req(struct wpa_supplicant *wpa_s,
1427 const u8 *src, u16 dev_passwd_id,
1428 u8 go_intent)
1429 {
1430 DBusMessage *msg;
1431 DBusMessageIter iter;
1432 struct wpas_dbus_priv *iface;
1433 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1434
1435 iface = wpa_s->global->dbus;
1436
1437 /* Do nothing if the control interface is not turned on */
1438 if (iface == NULL)
1439 return;
1440
1441 if (wpa_s->p2p_mgmt)
1442 wpa_s = wpa_s->parent;
1443 if (!wpa_s->dbus_new_path)
1444 return;
1445
1446 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1447 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
1448 wpa_s->dbus_new_path, MAC2STR(src));
1449 path = peer_obj_path;
1450
1451 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1452 WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1453 "GONegotiationRequest");
1454 if (msg == NULL)
1455 return;
1456
1457 dbus_message_iter_init_append(msg, &iter);
1458
1459 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
1460 &path) ||
1461 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT16,
1462 &dev_passwd_id) ||
1463 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BYTE,
1464 &go_intent))
1465 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1466 else
1467 dbus_connection_send(iface->con, msg, NULL);
1468
1469 dbus_message_unref(msg);
1470 }
1471
1472
wpas_dbus_get_group_obj_path(struct wpa_supplicant * wpa_s,const struct wpa_ssid * ssid,char * group_obj_path)1473 static int wpas_dbus_get_group_obj_path(struct wpa_supplicant *wpa_s,
1474 const struct wpa_ssid *ssid,
1475 char *group_obj_path)
1476 {
1477 char group_name[3];
1478
1479 if (!wpa_s->dbus_new_path ||
1480 os_memcmp(ssid->ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN))
1481 return -1;
1482
1483 os_memcpy(group_name, ssid->ssid + P2P_WILDCARD_SSID_LEN, 2);
1484 group_name[2] = '\0';
1485
1486 os_snprintf(group_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1487 "%s/" WPAS_DBUS_NEW_P2P_GROUPS_PART "/%s",
1488 wpa_s->dbus_new_path, group_name);
1489
1490 return 0;
1491 }
1492
1493
1494 struct group_changed_data {
1495 struct wpa_supplicant *wpa_s;
1496 struct p2p_peer_info *info;
1497 };
1498
1499
match_group_where_peer_is_client(struct p2p_group * group,void * user_data)1500 static int match_group_where_peer_is_client(struct p2p_group *group,
1501 void *user_data)
1502 {
1503 struct group_changed_data *data = user_data;
1504 const struct p2p_group_config *cfg;
1505 struct wpa_supplicant *wpa_s_go;
1506
1507 if (!p2p_group_is_client_connected(group, data->info->p2p_device_addr))
1508 return 1;
1509
1510 cfg = p2p_group_get_config(group);
1511
1512 wpa_s_go = wpas_get_p2p_go_iface(data->wpa_s, cfg->ssid,
1513 cfg->ssid_len);
1514 if (wpa_s_go != NULL && wpa_s_go == data->wpa_s) {
1515 wpas_dbus_signal_peer_groups_changed(
1516 data->wpa_s->p2pdev, data->info->p2p_device_addr);
1517 return 0;
1518 }
1519
1520 return 1;
1521 }
1522
1523
signal_peer_groups_changed(struct p2p_peer_info * info,void * user_data)1524 static void signal_peer_groups_changed(struct p2p_peer_info *info,
1525 void *user_data)
1526 {
1527 struct group_changed_data *data = user_data;
1528 struct wpa_supplicant *wpa_s_go;
1529
1530 wpa_s_go = wpas_get_p2p_client_iface(data->wpa_s,
1531 info->p2p_device_addr);
1532 if (wpa_s_go != NULL && wpa_s_go == data->wpa_s) {
1533 wpas_dbus_signal_peer_groups_changed(data->wpa_s->p2pdev,
1534 info->p2p_device_addr);
1535 return;
1536 }
1537
1538 data->info = info;
1539 p2p_loop_on_all_groups(data->wpa_s->global->p2p,
1540 match_group_where_peer_is_client, data);
1541 data->info = NULL;
1542 }
1543
1544
peer_groups_changed(struct wpa_supplicant * wpa_s)1545 static void peer_groups_changed(struct wpa_supplicant *wpa_s)
1546 {
1547 struct group_changed_data data;
1548
1549 os_memset(&data, 0, sizeof(data));
1550 data.wpa_s = wpa_s;
1551
1552 p2p_loop_on_known_peers(wpa_s->global->p2p,
1553 signal_peer_groups_changed, &data);
1554 }
1555
1556
1557 /**
1558 * wpas_dbus_signal_p2p_group_started - Signals P2P group has
1559 * started. Emitted when a group is successfully started
1560 * irrespective of the role (client/GO) of the current device
1561 *
1562 * @wpa_s: %wpa_supplicant network interface data
1563 * @client: this device is P2P client
1564 * @persistent: 0 - non persistent group, 1 - persistent group
1565 * @ip: When group role is client, it contains local IP address, netmask, and
1566 * GO's IP address, if assigned; otherwise, NULL
1567 */
wpas_dbus_signal_p2p_group_started(struct wpa_supplicant * wpa_s,int client,int persistent,const u8 * ip)1568 void wpas_dbus_signal_p2p_group_started(struct wpa_supplicant *wpa_s,
1569 int client, int persistent,
1570 const u8 *ip)
1571 {
1572 DBusMessage *msg;
1573 DBusMessageIter iter, dict_iter;
1574 struct wpas_dbus_priv *iface;
1575 struct wpa_supplicant *parent;
1576
1577 parent = wpa_s->parent;
1578 if (parent->p2p_mgmt)
1579 parent = parent->parent;
1580
1581 iface = parent->global->dbus;
1582
1583 /* Do nothing if the control interface is not turned on */
1584 if (iface == NULL || !parent->dbus_new_path || !wpa_s->dbus_new_path)
1585 return;
1586
1587 if (wpa_s->dbus_groupobj_path == NULL)
1588 return;
1589
1590 /* New interface has been created for this group */
1591 msg = dbus_message_new_signal(parent->dbus_new_path,
1592 WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1593 "GroupStarted");
1594 if (msg == NULL)
1595 return;
1596
1597 dbus_message_iter_init_append(msg, &iter);
1598 /*
1599 * In case the device supports creating a separate interface the
1600 * DBus client will need to know the object path for the interface
1601 * object this group was created on, so include it here.
1602 */
1603 if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
1604 !wpa_dbus_dict_append_object_path(&dict_iter,
1605 "interface_object",
1606 wpa_s->dbus_new_path) ||
1607 !wpa_dbus_dict_append_string(&dict_iter, "role",
1608 client ? "client" : "GO") ||
1609 !wpa_dbus_dict_append_bool(&dict_iter, "persistent", persistent) ||
1610 !wpa_dbus_dict_append_object_path(&dict_iter, "group_object",
1611 wpa_s->dbus_groupobj_path) ||
1612 (ip &&
1613 (!wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddr",
1614 (char *) ip, 4) ||
1615 !wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddrMask",
1616 (char *) ip + 4, 4) ||
1617 !wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddrGo",
1618 (char *) ip + 8, 4))) ||
1619 !wpa_dbus_dict_close_write(&iter, &dict_iter)) {
1620 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1621 } else {
1622 dbus_connection_send(iface->con, msg, NULL);
1623 if (client)
1624 peer_groups_changed(wpa_s);
1625 }
1626 dbus_message_unref(msg);
1627 }
1628
1629
1630 /**
1631 * wpas_dbus_signal_p2p_go_neg_resp - Emit GONegotiation Success/Failure signal
1632 * @wpa_s: %wpa_supplicant network interface data
1633 * @res: Result of the GO Neg Request
1634 */
wpas_dbus_signal_p2p_go_neg_resp(struct wpa_supplicant * wpa_s,struct p2p_go_neg_results * res)1635 void wpas_dbus_signal_p2p_go_neg_resp(struct wpa_supplicant *wpa_s,
1636 struct p2p_go_neg_results *res)
1637 {
1638 DBusMessage *msg;
1639 DBusMessageIter iter, dict_iter;
1640 DBusMessageIter iter_dict_entry, iter_dict_val, iter_dict_array;
1641 struct wpas_dbus_priv *iface;
1642 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1643 dbus_int32_t freqs[P2P_MAX_CHANNELS];
1644 dbus_int32_t *f_array = freqs;
1645
1646
1647 iface = wpa_s->global->dbus;
1648
1649 if (wpa_s->p2p_mgmt)
1650 wpa_s = wpa_s->parent;
1651
1652 os_memset(freqs, 0, sizeof(freqs));
1653 /* Do nothing if the control interface is not turned on */
1654 if (iface == NULL || !wpa_s->dbus_new_path)
1655 return;
1656
1657 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1658 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
1659 wpa_s->dbus_new_path, MAC2STR(res->peer_device_addr));
1660 path = peer_obj_path;
1661
1662 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1663 WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1664 res->status ? "GONegotiationFailure" :
1665 "GONegotiationSuccess");
1666 if (msg == NULL)
1667 return;
1668
1669 dbus_message_iter_init_append(msg, &iter);
1670 if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
1671 !wpa_dbus_dict_append_object_path(&dict_iter, "peer_object",
1672 path) ||
1673 !wpa_dbus_dict_append_int32(&dict_iter, "status", res->status))
1674 goto err;
1675
1676 if (!res->status) {
1677 int i = 0;
1678 int freq_list_num = 0;
1679
1680 if ((res->role_go &&
1681 !wpa_dbus_dict_append_string(&dict_iter, "passphrase",
1682 res->passphrase)) ||
1683 !wpa_dbus_dict_append_string(&dict_iter, "role_go",
1684 res->role_go ? "GO" :
1685 "client") ||
1686 !wpa_dbus_dict_append_int32(&dict_iter, "frequency",
1687 res->freq) ||
1688 !wpa_dbus_dict_append_byte_array(&dict_iter, "ssid",
1689 (const char *) res->ssid,
1690 res->ssid_len) ||
1691 !wpa_dbus_dict_append_byte_array(&dict_iter,
1692 "peer_device_addr",
1693 (const char *)
1694 res->peer_device_addr,
1695 ETH_ALEN) ||
1696 !wpa_dbus_dict_append_byte_array(&dict_iter,
1697 "peer_interface_addr",
1698 (const char *)
1699 res->peer_interface_addr,
1700 ETH_ALEN) ||
1701 !wpa_dbus_dict_append_string(&dict_iter, "wps_method",
1702 p2p_wps_method_text(
1703 res->wps_method)))
1704 goto err;
1705
1706 for (i = 0; i < P2P_MAX_CHANNELS; i++) {
1707 if (res->freq_list[i]) {
1708 freqs[i] = res->freq_list[i];
1709 freq_list_num++;
1710 }
1711 }
1712
1713 if (!wpa_dbus_dict_begin_array(&dict_iter,
1714 "frequency_list",
1715 DBUS_TYPE_INT32_AS_STRING,
1716 &iter_dict_entry,
1717 &iter_dict_val,
1718 &iter_dict_array) ||
1719 !dbus_message_iter_append_fixed_array(&iter_dict_array,
1720 DBUS_TYPE_INT32,
1721 &f_array,
1722 freq_list_num) ||
1723 !wpa_dbus_dict_end_array(&dict_iter,
1724 &iter_dict_entry,
1725 &iter_dict_val,
1726 &iter_dict_array) ||
1727 !wpa_dbus_dict_append_int32(&dict_iter, "persistent_group",
1728 res->persistent_group) ||
1729 !wpa_dbus_dict_append_uint32(&dict_iter,
1730 "peer_config_timeout",
1731 res->peer_config_timeout))
1732 goto err;
1733 }
1734
1735 if (!wpa_dbus_dict_close_write(&iter, &dict_iter))
1736 goto err;
1737
1738 dbus_connection_send(iface->con, msg, NULL);
1739 err:
1740 dbus_message_unref(msg);
1741 }
1742
1743
1744 /**
1745 * wpas_dbus_signal_p2p_invitation_result - Emit InvitationResult signal
1746 * @wpa_s: %wpa_supplicant network interface data
1747 * @status: Status of invitation process
1748 * @bssid: Basic Service Set Identifier
1749 */
wpas_dbus_signal_p2p_invitation_result(struct wpa_supplicant * wpa_s,int status,const u8 * bssid)1750 void wpas_dbus_signal_p2p_invitation_result(struct wpa_supplicant *wpa_s,
1751 int status, const u8 *bssid)
1752 {
1753 DBusMessage *msg;
1754 DBusMessageIter iter, dict_iter;
1755 struct wpas_dbus_priv *iface;
1756
1757 wpa_printf(MSG_DEBUG, "%s", __func__);
1758
1759 iface = wpa_s->global->dbus;
1760 /* Do nothing if the control interface is not turned on */
1761 if (iface == NULL)
1762 return;
1763
1764 if (wpa_s->p2p_mgmt)
1765 wpa_s = wpa_s->parent;
1766 if (!wpa_s->dbus_new_path)
1767 return;
1768
1769 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1770 WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1771 "InvitationResult");
1772
1773 if (msg == NULL)
1774 return;
1775
1776 dbus_message_iter_init_append(msg, &iter);
1777 if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
1778 !wpa_dbus_dict_append_int32(&dict_iter, "status", status) ||
1779 (bssid &&
1780 !wpa_dbus_dict_append_byte_array(&dict_iter, "BSSID",
1781 (const char *) bssid,
1782 ETH_ALEN)) ||
1783 !wpa_dbus_dict_close_write(&iter, &dict_iter))
1784 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1785 else
1786 dbus_connection_send(iface->con, msg, NULL);
1787 dbus_message_unref(msg);
1788 }
1789
1790
1791 /**
1792 *
1793 * Method to emit a signal for a peer joining the group.
1794 * The signal will carry path to the group member object
1795 * constructed using p2p i/f addr used for connecting.
1796 *
1797 * @wpa_s: %wpa_supplicant network interface data
1798 * @peer_addr: P2P Device Address of the peer joining the group
1799 */
wpas_dbus_signal_p2p_peer_joined(struct wpa_supplicant * wpa_s,const u8 * peer_addr)1800 void wpas_dbus_signal_p2p_peer_joined(struct wpa_supplicant *wpa_s,
1801 const u8 *peer_addr)
1802 {
1803 struct wpas_dbus_priv *iface;
1804 DBusMessage *msg;
1805 DBusMessageIter iter;
1806 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1807 struct wpa_supplicant *parent;
1808
1809 iface = wpa_s->global->dbus;
1810
1811 /* Do nothing if the control interface is not turned on */
1812 if (iface == NULL)
1813 return;
1814
1815 if (!wpa_s->dbus_groupobj_path)
1816 return;
1817
1818 parent = wpa_s->parent;
1819 if (parent->p2p_mgmt)
1820 parent = parent->parent;
1821 if (!parent->dbus_new_path)
1822 return;
1823
1824 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1825 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
1826 COMPACT_MACSTR,
1827 parent->dbus_new_path, MAC2STR(peer_addr));
1828
1829 msg = dbus_message_new_signal(wpa_s->dbus_groupobj_path,
1830 WPAS_DBUS_NEW_IFACE_P2P_GROUP,
1831 "PeerJoined");
1832 if (msg == NULL)
1833 return;
1834
1835 dbus_message_iter_init_append(msg, &iter);
1836 path = peer_obj_path;
1837 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
1838 &path)) {
1839 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1840 } else {
1841 dbus_connection_send(iface->con, msg, NULL);
1842 wpas_dbus_signal_peer_groups_changed(parent, peer_addr);
1843 }
1844 dbus_message_unref(msg);
1845 }
1846
1847
1848 /**
1849 *
1850 * Method to emit a signal for a peer disconnecting the group.
1851 * The signal will carry path to the group member object
1852 * constructed using the P2P Device Address of the peer.
1853 *
1854 * @wpa_s: %wpa_supplicant network interface data
1855 * @peer_addr: P2P Device Address of the peer joining the group
1856 */
wpas_dbus_signal_p2p_peer_disconnected(struct wpa_supplicant * wpa_s,const u8 * peer_addr)1857 void wpas_dbus_signal_p2p_peer_disconnected(struct wpa_supplicant *wpa_s,
1858 const u8 *peer_addr)
1859 {
1860 struct wpas_dbus_priv *iface;
1861 DBusMessage *msg;
1862 DBusMessageIter iter;
1863 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1864 struct wpa_supplicant *parent;
1865
1866 iface = wpa_s->global->dbus;
1867
1868 /* Do nothing if the control interface is not turned on */
1869 if (iface == NULL)
1870 return;
1871
1872 if (!wpa_s->dbus_groupobj_path)
1873 return;
1874
1875 parent = wpa_s->parent;
1876 if (parent->p2p_mgmt)
1877 parent = parent->parent;
1878 if (!parent->dbus_new_path)
1879 return;
1880
1881 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1882 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
1883 COMPACT_MACSTR,
1884 parent->dbus_new_path, MAC2STR(peer_addr));
1885
1886 msg = dbus_message_new_signal(wpa_s->dbus_groupobj_path,
1887 WPAS_DBUS_NEW_IFACE_P2P_GROUP,
1888 "PeerDisconnected");
1889 if (msg == NULL)
1890 return;
1891
1892 dbus_message_iter_init_append(msg, &iter);
1893 path = peer_obj_path;
1894 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
1895 &path)) {
1896 wpa_printf(MSG_ERROR,
1897 "dbus: Failed to construct PeerDisconnected 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 service discovery request.
1909 * The signal will carry station address, frequency, dialog token,
1910 * update indicator and it tlvs
1911 *
1912 * @wpa_s: %wpa_supplicant network interface data
1913 * @sa: station addr (p2p i/f) of the peer
1914 * @dialog_token: service discovery request dialog token
1915 * @update_indic: service discovery request update indicator
1916 * @tlvs: service discovery request generated byte array of tlvs
1917 * @tlvs_len: service discovery request tlvs length
1918 */
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)1919 void wpas_dbus_signal_p2p_sd_request(struct wpa_supplicant *wpa_s,
1920 int freq, const u8 *sa, u8 dialog_token,
1921 u16 update_indic, const u8 *tlvs,
1922 size_t tlvs_len)
1923 {
1924 DBusMessage *msg;
1925 DBusMessageIter iter, dict_iter;
1926 struct wpas_dbus_priv *iface;
1927 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1928
1929 iface = wpa_s->global->dbus;
1930
1931 /* Do nothing if the control interface is not turned on */
1932 if (iface == NULL)
1933 return;
1934
1935 if (wpa_s->p2p_mgmt)
1936 wpa_s = wpa_s->parent;
1937 if (!wpa_s->dbus_new_path)
1938 return;
1939
1940 /* Check if this is a known peer */
1941 if (!p2p_peer_known(wpa_s->global->p2p, sa))
1942 return;
1943
1944 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1945 WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1946 "ServiceDiscoveryRequest");
1947 if (msg == NULL)
1948 return;
1949
1950 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1951 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
1952 COMPACT_MACSTR, wpa_s->dbus_new_path, MAC2STR(sa));
1953
1954 path = peer_obj_path;
1955
1956 dbus_message_iter_init_append(msg, &iter);
1957 if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
1958 !wpa_dbus_dict_append_object_path(&dict_iter, "peer_object",
1959 path) ||
1960 !wpa_dbus_dict_append_int32(&dict_iter, "frequency", freq) ||
1961 !wpa_dbus_dict_append_int32(&dict_iter, "dialog_token",
1962 dialog_token) ||
1963 !wpa_dbus_dict_append_uint16(&dict_iter, "update_indicator",
1964 update_indic) ||
1965 !wpa_dbus_dict_append_byte_array(&dict_iter, "tlvs",
1966 (const char *) tlvs,
1967 tlvs_len) ||
1968 !wpa_dbus_dict_close_write(&iter, &dict_iter))
1969 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1970 else
1971 dbus_connection_send(iface->con, msg, NULL);
1972 dbus_message_unref(msg);
1973 }
1974
1975
1976 /**
1977 *
1978 * Method to emit a signal for a service discovery response.
1979 * The signal will carry station address, update indicator and it
1980 * tlvs
1981 *
1982 * @wpa_s: %wpa_supplicant network interface data
1983 * @sa: station addr (p2p i/f) of the peer
1984 * @update_indic: service discovery request update indicator
1985 * @tlvs: service discovery request generated byte array of tlvs
1986 * @tlvs_len: service discovery request tlvs length
1987 */
wpas_dbus_signal_p2p_sd_response(struct wpa_supplicant * wpa_s,const u8 * sa,u16 update_indic,const u8 * tlvs,size_t tlvs_len)1988 void wpas_dbus_signal_p2p_sd_response(struct wpa_supplicant *wpa_s,
1989 const u8 *sa, u16 update_indic,
1990 const u8 *tlvs, size_t tlvs_len)
1991 {
1992 DBusMessage *msg;
1993 DBusMessageIter iter, dict_iter;
1994 struct wpas_dbus_priv *iface;
1995 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1996
1997 iface = wpa_s->global->dbus;
1998
1999 /* Do nothing if the control interface is not turned on */
2000 if (iface == NULL)
2001 return;
2002
2003 if (wpa_s->p2p_mgmt)
2004 wpa_s = wpa_s->parent;
2005 if (!wpa_s->dbus_new_path)
2006 return;
2007
2008 /* Check if this is a known peer */
2009 if (!p2p_peer_known(wpa_s->global->p2p, sa))
2010 return;
2011
2012 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
2013 WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2014 "ServiceDiscoveryResponse");
2015 if (msg == NULL)
2016 return;
2017
2018 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2019 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
2020 COMPACT_MACSTR, wpa_s->dbus_new_path, MAC2STR(sa));
2021
2022 path = peer_obj_path;
2023
2024 dbus_message_iter_init_append(msg, &iter);
2025 if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
2026 !wpa_dbus_dict_append_object_path(&dict_iter, "peer_object",
2027 path) ||
2028 !wpa_dbus_dict_append_uint16(&dict_iter, "update_indicator",
2029 update_indic) ||
2030 !wpa_dbus_dict_append_byte_array(&dict_iter, "tlvs",
2031 (const char *) tlvs,
2032 tlvs_len) ||
2033 !wpa_dbus_dict_close_write(&iter, &dict_iter))
2034 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
2035 else
2036 dbus_connection_send(iface->con, msg, NULL);
2037 dbus_message_unref(msg);
2038 }
2039
2040
2041 /**
2042 * wpas_dbus_signal_persistent_group - Send a persistent group related
2043 * event signal
2044 * @wpa_s: %wpa_supplicant network interface data
2045 * @id: new persistent group id
2046 * @sig_name: signal name - PersistentGroupAdded, PersistentGroupRemoved
2047 * @properties: determines if add second argument with object properties
2048 *
2049 * Notify listeners about an event related to persistent groups.
2050 */
wpas_dbus_signal_persistent_group(struct wpa_supplicant * wpa_s,int id,const char * sig_name,dbus_bool_t properties)2051 static void wpas_dbus_signal_persistent_group(struct wpa_supplicant *wpa_s,
2052 int id, const char *sig_name,
2053 dbus_bool_t properties)
2054 {
2055 struct wpas_dbus_priv *iface;
2056 DBusMessage *msg;
2057 DBusMessageIter iter;
2058 char pgrp_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
2059
2060 iface = wpa_s->global->dbus;
2061
2062 /* Do nothing if the control interface is not turned on */
2063 if (iface == NULL)
2064 return;
2065
2066 if (wpa_s->p2p_mgmt)
2067 wpa_s = wpa_s->parent;
2068 if (!wpa_s->dbus_new_path)
2069 return;
2070
2071 os_snprintf(pgrp_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2072 "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%u",
2073 wpa_s->dbus_new_path, id);
2074
2075 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
2076 WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2077 sig_name);
2078 if (msg == NULL)
2079 return;
2080
2081 dbus_message_iter_init_append(msg, &iter);
2082 path = pgrp_obj_path;
2083 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
2084 &path) ||
2085 (properties &&
2086 !wpa_dbus_get_object_properties(
2087 iface, pgrp_obj_path,
2088 WPAS_DBUS_NEW_IFACE_PERSISTENT_GROUP, &iter)))
2089 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
2090 else
2091 dbus_connection_send(iface->con, msg, NULL);
2092
2093 dbus_message_unref(msg);
2094 }
2095
2096
2097 /**
2098 * wpas_dbus_signal_persistent_group_added - Send a persistent_group
2099 * added signal
2100 * @wpa_s: %wpa_supplicant network interface data
2101 * @id: new persistent group id
2102 *
2103 * Notify listeners about addition of a new persistent group.
2104 */
wpas_dbus_signal_persistent_group_added(struct wpa_supplicant * wpa_s,int id)2105 static void wpas_dbus_signal_persistent_group_added(
2106 struct wpa_supplicant *wpa_s, int id)
2107 {
2108 wpas_dbus_signal_persistent_group(wpa_s, id, "PersistentGroupAdded",
2109 TRUE);
2110 }
2111
2112
2113 /**
2114 * wpas_dbus_signal_persistent_group_removed - Send a persistent_group
2115 * removed signal
2116 * @wpa_s: %wpa_supplicant network interface data
2117 * @id: persistent group id
2118 *
2119 * Notify listeners about removal of a persistent group.
2120 */
wpas_dbus_signal_persistent_group_removed(struct wpa_supplicant * wpa_s,int id)2121 static void wpas_dbus_signal_persistent_group_removed(
2122 struct wpa_supplicant *wpa_s, int id)
2123 {
2124 wpas_dbus_signal_persistent_group(wpa_s, id, "PersistentGroupRemoved",
2125 FALSE);
2126 }
2127
2128
2129 /**
2130 * wpas_dbus_signal_p2p_wps_failed - Signals WpsFailed event
2131 * @wpa_s: %wpa_supplicant network interface data
2132 * @fail: WPS failure information
2133 *
2134 * Sends Event dbus signal with name "fail" and dictionary containing
2135 * "msg" field with fail message number (int32) as arguments
2136 */
wpas_dbus_signal_p2p_wps_failed(struct wpa_supplicant * wpa_s,struct wps_event_fail * fail)2137 void wpas_dbus_signal_p2p_wps_failed(struct wpa_supplicant *wpa_s,
2138 struct wps_event_fail *fail)
2139 {
2140
2141 DBusMessage *msg;
2142 DBusMessageIter iter, dict_iter;
2143 struct wpas_dbus_priv *iface;
2144 char *key = "fail";
2145
2146 iface = wpa_s->global->dbus;
2147
2148 /* Do nothing if the control interface is not turned on */
2149 if (iface == NULL)
2150 return;
2151
2152 if (wpa_s->p2p_mgmt)
2153 wpa_s = wpa_s->parent;
2154
2155 if (!wpa_s->dbus_new_path)
2156 return;
2157 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
2158 WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2159 "WpsFailed");
2160 if (msg == NULL)
2161 return;
2162
2163 dbus_message_iter_init_append(msg, &iter);
2164
2165 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
2166 !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
2167 !wpa_dbus_dict_append_int32(&dict_iter, "msg", fail->msg) ||
2168 !wpa_dbus_dict_append_int16(&dict_iter, "config_error",
2169 fail->config_error) ||
2170 !wpa_dbus_dict_close_write(&iter, &dict_iter))
2171 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
2172 else
2173 dbus_connection_send(iface->con, msg, NULL);
2174
2175 dbus_message_unref(msg);
2176 }
2177
2178
2179 /**
2180 * wpas_dbus_signal_p2p_group_formation_failure - Signals GroupFormationFailure event
2181 * @wpa_s: %wpa_supplicant network interface data
2182 * @reason: indicates the reason code for group formation failure
2183 *
2184 * Sends Event dbus signal and string reason code when available.
2185 */
wpas_dbus_signal_p2p_group_formation_failure(struct wpa_supplicant * wpa_s,const char * reason)2186 void wpas_dbus_signal_p2p_group_formation_failure(struct wpa_supplicant *wpa_s,
2187 const char *reason)
2188 {
2189 DBusMessage *msg;
2190 struct wpas_dbus_priv *iface;
2191
2192 iface = wpa_s->global->dbus;
2193
2194 /* Do nothing if the control interface is not turned on */
2195 if (iface == NULL)
2196 return;
2197
2198 if (wpa_s->p2p_mgmt)
2199 wpa_s = wpa_s->parent;
2200
2201 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
2202 WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2203 "GroupFormationFailure");
2204 if (msg == NULL)
2205 return;
2206
2207 if (dbus_message_append_args(msg, DBUS_TYPE_STRING, &reason,
2208 DBUS_TYPE_INVALID))
2209 dbus_connection_send(iface->con, msg, NULL);
2210 else
2211 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
2212
2213 dbus_message_unref(msg);
2214 }
2215
2216
2217 /**
2218 * wpas_dbus_signal_p2p_invitation_received - Emit InvitationReceived signal
2219 * @wpa_s: %wpa_supplicant network interface data
2220 * @sa: Source address of the Invitation Request
2221 * @dev_add: GO Device Address
2222 * @bssid: P2P Group BSSID or %NULL if not received
2223 * @id: Persistent group id or %0 if not persistent group
2224 * @op_freq: Operating frequency for the group
2225 */
2226
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)2227 void wpas_dbus_signal_p2p_invitation_received(struct wpa_supplicant *wpa_s,
2228 const u8 *sa, const u8 *dev_addr,
2229 const u8 *bssid, int id,
2230 int op_freq)
2231 {
2232 DBusMessage *msg;
2233 DBusMessageIter iter, dict_iter;
2234 struct wpas_dbus_priv *iface;
2235
2236 iface = wpa_s->global->dbus;
2237
2238 /* Do nothing if the control interface is not turned on */
2239 if (iface == NULL)
2240 return;
2241
2242 if (wpa_s->p2p_mgmt)
2243 wpa_s = wpa_s->parent;
2244
2245 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
2246 WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2247 "InvitationReceived");
2248 if (msg == NULL)
2249 return;
2250
2251 dbus_message_iter_init_append(msg, &iter);
2252 if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
2253 (sa &&
2254 !wpa_dbus_dict_append_byte_array(&dict_iter, "sa",
2255 (const char *) sa, ETH_ALEN)) ||
2256 (dev_addr &&
2257 !wpa_dbus_dict_append_byte_array(&dict_iter, "go_dev_addr",
2258 (const char *) dev_addr,
2259 ETH_ALEN)) ||
2260 (bssid &&
2261 !wpa_dbus_dict_append_byte_array(&dict_iter, "bssid",
2262 (const char *) bssid,
2263 ETH_ALEN)) ||
2264 (id &&
2265 !wpa_dbus_dict_append_int32(&dict_iter, "persistent_id", id)) ||
2266 !wpa_dbus_dict_append_int32(&dict_iter, "op_freq", op_freq) ||
2267 !wpa_dbus_dict_close_write(&iter, &dict_iter)) {
2268 dbus_message_unref(msg);
2269 return;
2270 }
2271
2272 dbus_connection_send(iface->con, msg, NULL);
2273 dbus_message_unref(msg);
2274 }
2275
2276
2277 #endif /* CONFIG_P2P */
2278
2279
2280 /**
2281 * wpas_dbus_signal_prop_changed - Signals change of property
2282 * @wpa_s: %wpa_supplicant network interface data
2283 * @property: indicates which property has changed
2284 *
2285 * Sends PropertyChanged signals with path, interface and arguments
2286 * depending on which property has changed.
2287 */
wpas_dbus_signal_prop_changed(struct wpa_supplicant * wpa_s,enum wpas_dbus_prop property)2288 void wpas_dbus_signal_prop_changed(struct wpa_supplicant *wpa_s,
2289 enum wpas_dbus_prop property)
2290 {
2291 char *prop;
2292 dbus_bool_t flush;
2293
2294 if (wpa_s->dbus_new_path == NULL)
2295 return; /* Skip signal since D-Bus setup is not yet ready */
2296
2297 flush = FALSE;
2298 switch (property) {
2299 case WPAS_DBUS_PROP_AP_SCAN:
2300 prop = "ApScan";
2301 break;
2302 case WPAS_DBUS_PROP_SCANNING:
2303 prop = "Scanning";
2304 break;
2305 case WPAS_DBUS_PROP_STATE:
2306 prop = "State";
2307 break;
2308 case WPAS_DBUS_PROP_CURRENT_BSS:
2309 prop = "CurrentBSS";
2310 break;
2311 case WPAS_DBUS_PROP_CURRENT_NETWORK:
2312 prop = "CurrentNetwork";
2313 break;
2314 case WPAS_DBUS_PROP_BSSS:
2315 prop = "BSSs";
2316 break;
2317 case WPAS_DBUS_PROP_STATIONS:
2318 prop = "Stations";
2319 break;
2320 case WPAS_DBUS_PROP_CURRENT_AUTH_MODE:
2321 prop = "CurrentAuthMode";
2322 break;
2323 case WPAS_DBUS_PROP_DISCONNECT_REASON:
2324 prop = "DisconnectReason";
2325 flush = TRUE;
2326 break;
2327 case WPAS_DBUS_PROP_AUTH_STATUS_CODE:
2328 prop = "AuthStatusCode";
2329 flush = TRUE;
2330 break;
2331 case WPAS_DBUS_PROP_ASSOC_STATUS_CODE:
2332 prop = "AssocStatusCode";
2333 flush = TRUE;
2334 break;
2335 case WPAS_DBUS_PROP_ROAM_TIME:
2336 prop = "RoamTime";
2337 break;
2338 case WPAS_DBUS_PROP_ROAM_COMPLETE:
2339 prop = "RoamComplete";
2340 break;
2341 case WPAS_DBUS_PROP_SESSION_LENGTH:
2342 prop = "SessionLength";
2343 break;
2344 case WPAS_DBUS_PROP_BSS_TM_STATUS:
2345 prop = "BSSTMStatus";
2346 break;
2347 default:
2348 wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d",
2349 __func__, property);
2350 return;
2351 }
2352
2353 wpa_dbus_mark_property_changed(wpa_s->global->dbus,
2354 wpa_s->dbus_new_path,
2355 WPAS_DBUS_NEW_IFACE_INTERFACE, prop);
2356 if (flush) {
2357 wpa_dbus_flush_object_changed_properties(
2358 wpa_s->global->dbus->con, wpa_s->dbus_new_path);
2359 }
2360 }
2361
2362
2363 /**
2364 * wpas_dbus_bss_signal_prop_changed - Signals change of BSS property
2365 * @wpa_s: %wpa_supplicant network interface data
2366 * @property: indicates which property has changed
2367 * @id: unique BSS identifier
2368 *
2369 * Sends PropertyChanged signals with path, interface, and arguments depending
2370 * on which property has changed.
2371 */
wpas_dbus_bss_signal_prop_changed(struct wpa_supplicant * wpa_s,enum wpas_dbus_bss_prop property,unsigned int id)2372 void wpas_dbus_bss_signal_prop_changed(struct wpa_supplicant *wpa_s,
2373 enum wpas_dbus_bss_prop property,
2374 unsigned int id)
2375 {
2376 char path[WPAS_DBUS_OBJECT_PATH_MAX];
2377 char *prop;
2378
2379 if (!wpa_s->dbus_new_path)
2380 return;
2381
2382 switch (property) {
2383 case WPAS_DBUS_BSS_PROP_SIGNAL:
2384 prop = "Signal";
2385 break;
2386 case WPAS_DBUS_BSS_PROP_FREQ:
2387 prop = "Frequency";
2388 break;
2389 case WPAS_DBUS_BSS_PROP_MODE:
2390 prop = "Mode";
2391 break;
2392 case WPAS_DBUS_BSS_PROP_PRIVACY:
2393 prop = "Privacy";
2394 break;
2395 case WPAS_DBUS_BSS_PROP_RATES:
2396 prop = "Rates";
2397 break;
2398 case WPAS_DBUS_BSS_PROP_WPA:
2399 prop = "WPA";
2400 break;
2401 case WPAS_DBUS_BSS_PROP_RSN:
2402 prop = "RSN";
2403 break;
2404 case WPAS_DBUS_BSS_PROP_WPS:
2405 prop = "WPS";
2406 break;
2407 case WPAS_DBUS_BSS_PROP_IES:
2408 prop = "IEs";
2409 break;
2410 case WPAS_DBUS_BSS_PROP_AGE:
2411 prop = "Age";
2412 break;
2413 default:
2414 wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d",
2415 __func__, property);
2416 return;
2417 }
2418
2419 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
2420 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
2421 wpa_s->dbus_new_path, id);
2422
2423 wpa_dbus_mark_property_changed(wpa_s->global->dbus, path,
2424 WPAS_DBUS_NEW_IFACE_BSS, prop);
2425 }
2426
2427
2428 /**
2429 * wpas_dbus_sta_signal_prop_changed - Signals change of STA property
2430 * @wpa_s: %wpa_supplicant network interface data
2431 * @property: indicates which property has changed
2432 * @address: unique BSS identifier
2433 *
2434 * Sends PropertyChanged signals with path, interface, and arguments depending
2435 * on which property has changed.
2436 */
wpas_dbus_sta_signal_prop_changed(struct wpa_supplicant * wpa_s,enum wpas_dbus_bss_prop property,u8 address[ETH_ALEN])2437 void wpas_dbus_sta_signal_prop_changed(struct wpa_supplicant *wpa_s,
2438 enum wpas_dbus_bss_prop property,
2439 u8 address[ETH_ALEN])
2440 {
2441 char path[WPAS_DBUS_OBJECT_PATH_MAX];
2442 char *prop;
2443
2444 switch (property) {
2445 case WPAS_DBUS_STA_PROP_ADDRESS:
2446 prop = "Address";
2447 break;
2448 default:
2449 wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d",
2450 __func__, property);
2451 return;
2452 }
2453
2454 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
2455 "%s/" WPAS_DBUS_NEW_STAS_PART "/" COMPACT_MACSTR,
2456 wpa_s->dbus_new_path, MAC2STR(address));
2457
2458 wpa_dbus_mark_property_changed(wpa_s->global->dbus, path,
2459 WPAS_DBUS_NEW_IFACE_STA, prop);
2460 }
2461
2462
2463 /**
2464 * wpas_dbus_signal_debug_level_changed - Signals change of debug param
2465 * @global: wpa_global structure
2466 *
2467 * Sends PropertyChanged signals informing that debug level has changed.
2468 */
wpas_dbus_signal_debug_level_changed(struct wpa_global * global)2469 void wpas_dbus_signal_debug_level_changed(struct wpa_global *global)
2470 {
2471 wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
2472 WPAS_DBUS_NEW_INTERFACE,
2473 "DebugLevel");
2474 }
2475
2476
2477 /**
2478 * wpas_dbus_signal_debug_timestamp_changed - Signals change of debug param
2479 * @global: wpa_global structure
2480 *
2481 * Sends PropertyChanged signals informing that debug timestamp has changed.
2482 */
wpas_dbus_signal_debug_timestamp_changed(struct wpa_global * global)2483 void wpas_dbus_signal_debug_timestamp_changed(struct wpa_global *global)
2484 {
2485 wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
2486 WPAS_DBUS_NEW_INTERFACE,
2487 "DebugTimestamp");
2488 }
2489
2490
2491 /**
2492 * wpas_dbus_signal_debug_show_keys_changed - Signals change of debug param
2493 * @global: wpa_global structure
2494 *
2495 * Sends PropertyChanged signals informing that debug show_keys has changed.
2496 */
wpas_dbus_signal_debug_show_keys_changed(struct wpa_global * global)2497 void wpas_dbus_signal_debug_show_keys_changed(struct wpa_global *global)
2498 {
2499 wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
2500 WPAS_DBUS_NEW_INTERFACE,
2501 "DebugShowKeys");
2502 }
2503
2504
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)2505 static void wpas_dbus_register(struct wpa_dbus_object_desc *obj_desc,
2506 void *priv,
2507 WPADBusArgumentFreeFunction priv_free,
2508 const struct wpa_dbus_method_desc *methods,
2509 const struct wpa_dbus_property_desc *properties,
2510 const struct wpa_dbus_signal_desc *signals)
2511 {
2512 int n;
2513
2514 obj_desc->user_data = priv;
2515 obj_desc->user_data_free_func = priv_free;
2516 obj_desc->methods = methods;
2517 obj_desc->properties = properties;
2518 obj_desc->signals = signals;
2519
2520 for (n = 0; properties && properties->dbus_property; properties++)
2521 n++;
2522
2523 obj_desc->prop_changed_flags = os_zalloc(n);
2524 if (!obj_desc->prop_changed_flags)
2525 wpa_printf(MSG_DEBUG, "dbus: %s: can't register handlers",
2526 __func__);
2527 }
2528
2529
2530 static const struct wpa_dbus_method_desc wpas_dbus_global_methods[] = {
2531 { "CreateInterface", WPAS_DBUS_NEW_INTERFACE,
2532 (WPADBusMethodHandler) wpas_dbus_handler_create_interface,
2533 {
2534 { "args", "a{sv}", ARG_IN },
2535 { "path", "o", ARG_OUT },
2536 END_ARGS
2537 }
2538 },
2539 { "RemoveInterface", WPAS_DBUS_NEW_INTERFACE,
2540 (WPADBusMethodHandler) wpas_dbus_handler_remove_interface,
2541 {
2542 { "path", "o", ARG_IN },
2543 END_ARGS
2544 }
2545 },
2546 { "GetInterface", WPAS_DBUS_NEW_INTERFACE,
2547 (WPADBusMethodHandler) wpas_dbus_handler_get_interface,
2548 {
2549 { "ifname", "s", ARG_IN },
2550 { "path", "o", ARG_OUT },
2551 END_ARGS
2552 }
2553 },
2554 { "ExpectDisconnect", WPAS_DBUS_NEW_INTERFACE,
2555 (WPADBusMethodHandler) wpas_dbus_handler_expect_disconnect,
2556 {
2557 END_ARGS
2558 }
2559 },
2560 { NULL, NULL, NULL, { END_ARGS } }
2561 };
2562
2563 static const struct wpa_dbus_property_desc wpas_dbus_global_properties[] = {
2564 { "DebugLevel", WPAS_DBUS_NEW_INTERFACE, "s",
2565 wpas_dbus_getter_debug_level,
2566 wpas_dbus_setter_debug_level,
2567 NULL
2568 },
2569 { "DebugTimestamp", WPAS_DBUS_NEW_INTERFACE, "b",
2570 wpas_dbus_getter_debug_timestamp,
2571 wpas_dbus_setter_debug_timestamp,
2572 NULL
2573 },
2574 { "DebugShowKeys", WPAS_DBUS_NEW_INTERFACE, "b",
2575 wpas_dbus_getter_debug_show_keys,
2576 wpas_dbus_setter_debug_show_keys,
2577 NULL
2578 },
2579 { "Interfaces", WPAS_DBUS_NEW_INTERFACE, "ao",
2580 wpas_dbus_getter_interfaces,
2581 NULL,
2582 NULL
2583 },
2584 { "EapMethods", WPAS_DBUS_NEW_INTERFACE, "as",
2585 wpas_dbus_getter_eap_methods,
2586 NULL,
2587 NULL
2588 },
2589 { "Capabilities", WPAS_DBUS_NEW_INTERFACE, "as",
2590 wpas_dbus_getter_global_capabilities,
2591 NULL,
2592 NULL
2593 },
2594 #ifdef CONFIG_WIFI_DISPLAY
2595 { "WFDIEs", WPAS_DBUS_NEW_INTERFACE, "ay",
2596 wpas_dbus_getter_global_wfd_ies,
2597 wpas_dbus_setter_global_wfd_ies,
2598 NULL
2599 },
2600 #endif /* CONFIG_WIFI_DISPLAY */
2601 { NULL, NULL, NULL, NULL, NULL, NULL }
2602 };
2603
2604 static const struct wpa_dbus_signal_desc wpas_dbus_global_signals[] = {
2605 { "InterfaceAdded", WPAS_DBUS_NEW_INTERFACE,
2606 {
2607 { "path", "o", ARG_OUT },
2608 { "properties", "a{sv}", ARG_OUT },
2609 END_ARGS
2610 }
2611 },
2612 { "InterfaceRemoved", WPAS_DBUS_NEW_INTERFACE,
2613 {
2614 { "path", "o", ARG_OUT },
2615 END_ARGS
2616 }
2617 },
2618 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
2619 { "PropertiesChanged", WPAS_DBUS_NEW_INTERFACE,
2620 {
2621 { "properties", "a{sv}", ARG_OUT },
2622 END_ARGS
2623 }
2624 },
2625 { NULL, NULL, { END_ARGS } }
2626 };
2627
2628
uscore_to_dbus(const char * uscore)2629 static char * uscore_to_dbus(const char *uscore)
2630 {
2631 const char *p = uscore;
2632 char *str, *s;
2633 dbus_bool_t last_was_uscore = TRUE;
2634
2635 s = str = os_zalloc(os_strlen(uscore) + 1);
2636 if (!str)
2637 return NULL;
2638 while (p && *p) {
2639 if (*p == '_') {
2640 last_was_uscore = TRUE;
2641 } else {
2642 *s++ = last_was_uscore ? toupper(*p) : *p;
2643 last_was_uscore = FALSE;
2644 }
2645 p++;
2646 }
2647
2648 return str;
2649 }
2650
2651
2652 static int wpa_dbus_ctrl_iface_props_init(struct wpas_dbus_priv *priv);
2653
2654
wpa_dbus_ctrl_iface_props_deinit(struct wpas_dbus_priv * priv)2655 static void wpa_dbus_ctrl_iface_props_deinit(struct wpas_dbus_priv *priv)
2656 {
2657 int idx = priv->globals_start;
2658
2659 /* Free all allocated property values */
2660 while (priv->all_interface_properties[idx].dbus_property)
2661 os_free((char *)
2662 priv->all_interface_properties[idx++].dbus_property);
2663 os_free((char *) priv->all_interface_properties);
2664 }
2665
2666
2667 /**
2668 * wpas_dbus_ctrl_iface_init - Initialize dbus control interface
2669 * @global: Pointer to global data from wpa_supplicant_init()
2670 * Returns: 0 on success or -1 on failure
2671 *
2672 * Initialize the dbus control interface for wpa_supplicant and start
2673 * receiving commands from external programs over the bus.
2674 */
wpas_dbus_ctrl_iface_init(struct wpas_dbus_priv * priv)2675 int wpas_dbus_ctrl_iface_init(struct wpas_dbus_priv *priv)
2676 {
2677 struct wpa_dbus_object_desc *obj_desc;
2678 int ret;
2679
2680 ret = wpa_dbus_ctrl_iface_props_init(priv);
2681 if (ret < 0) {
2682 wpa_printf(MSG_ERROR,
2683 "dbus: Not enough memory to init interface properties");
2684 return -1;
2685 }
2686
2687 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
2688 if (!obj_desc) {
2689 wpa_printf(MSG_ERROR,
2690 "Not enough memory to create object description");
2691 goto error;
2692 }
2693
2694 wpas_dbus_register(obj_desc, priv->global, NULL,
2695 wpas_dbus_global_methods,
2696 wpas_dbus_global_properties,
2697 wpas_dbus_global_signals);
2698
2699 wpa_printf(MSG_DEBUG, "dbus: Register D-Bus object '%s'",
2700 WPAS_DBUS_NEW_PATH);
2701 ret = wpa_dbus_ctrl_iface_init(priv, WPAS_DBUS_NEW_PATH,
2702 WPAS_DBUS_NEW_SERVICE,
2703 obj_desc);
2704 if (ret < 0) {
2705 free_dbus_object_desc(obj_desc);
2706 goto error;
2707 }
2708
2709 priv->dbus_new_initialized = 1;
2710 return 0;
2711
2712 error:
2713 wpa_dbus_ctrl_iface_props_deinit(priv);
2714 return -1;
2715 }
2716
2717
2718 /**
2719 * wpas_dbus_ctrl_iface_deinit - Deinitialize dbus ctrl interface for
2720 * wpa_supplicant
2721 * @priv: Pointer to dbus private data from wpas_dbus_init()
2722 *
2723 * Deinitialize the dbus control interface that was initialized with
2724 * wpas_dbus_ctrl_iface_init().
2725 */
wpas_dbus_ctrl_iface_deinit(struct wpas_dbus_priv * priv)2726 void wpas_dbus_ctrl_iface_deinit(struct wpas_dbus_priv *priv)
2727 {
2728 if (!priv->dbus_new_initialized)
2729 return;
2730 wpa_printf(MSG_DEBUG, "dbus: Unregister D-Bus object '%s'",
2731 WPAS_DBUS_NEW_PATH);
2732 dbus_connection_unregister_object_path(priv->con, WPAS_DBUS_NEW_PATH);
2733 wpa_dbus_ctrl_iface_props_deinit(priv);
2734 }
2735
2736
wpa_dbus_free(void * ptr)2737 static void wpa_dbus_free(void *ptr)
2738 {
2739 os_free(ptr);
2740 }
2741
2742
2743 static const struct wpa_dbus_property_desc wpas_dbus_network_properties[] = {
2744 { "Properties", WPAS_DBUS_NEW_IFACE_NETWORK, "a{sv}",
2745 wpas_dbus_getter_network_properties,
2746 wpas_dbus_setter_network_properties,
2747 NULL
2748 },
2749 { "Enabled", WPAS_DBUS_NEW_IFACE_NETWORK, "b",
2750 wpas_dbus_getter_enabled,
2751 wpas_dbus_setter_enabled,
2752 NULL
2753 },
2754 { NULL, NULL, NULL, NULL, NULL, NULL }
2755 };
2756
2757
2758 static const struct wpa_dbus_signal_desc wpas_dbus_network_signals[] = {
2759 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
2760 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_NETWORK,
2761 {
2762 { "properties", "a{sv}", ARG_OUT },
2763 END_ARGS
2764 }
2765 },
2766 { NULL, NULL, { END_ARGS } }
2767 };
2768
2769
2770 /**
2771 * wpas_dbus_register_network - Register a configured network with dbus
2772 * @wpa_s: wpa_supplicant interface structure
2773 * @ssid: network configuration data
2774 * Returns: 0 on success, -1 on failure
2775 *
2776 * Registers network representing object with dbus
2777 */
wpas_dbus_register_network(struct wpa_supplicant * wpa_s,struct wpa_ssid * ssid)2778 int wpas_dbus_register_network(struct wpa_supplicant *wpa_s,
2779 struct wpa_ssid *ssid)
2780 {
2781 struct wpas_dbus_priv *ctrl_iface;
2782 struct wpa_dbus_object_desc *obj_desc;
2783 struct network_handler_args *arg;
2784 char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
2785
2786 #ifdef CONFIG_P2P
2787 /*
2788 * If it is a persistent group register it as such.
2789 * This is to handle cases where an interface is being initialized
2790 * with a list of networks read from config.
2791 */
2792 if (network_is_persistent_group(ssid))
2793 return wpas_dbus_register_persistent_group(wpa_s, ssid);
2794 #endif /* CONFIG_P2P */
2795
2796 /* Do nothing if the control interface is not turned on */
2797 if (wpa_s == NULL || wpa_s->global == NULL || !wpa_s->dbus_new_path)
2798 return 0;
2799 ctrl_iface = wpa_s->global->dbus;
2800 if (ctrl_iface == NULL)
2801 return 0;
2802
2803 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2804 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
2805 wpa_s->dbus_new_path, ssid->id);
2806
2807 wpa_printf(MSG_DEBUG, "dbus: Register network object '%s'",
2808 net_obj_path);
2809 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
2810 if (!obj_desc) {
2811 wpa_printf(MSG_ERROR,
2812 "Not enough memory to create object description");
2813 goto err;
2814 }
2815
2816 /* allocate memory for handlers arguments */
2817 arg = os_zalloc(sizeof(struct network_handler_args));
2818 if (!arg) {
2819 wpa_printf(MSG_ERROR,
2820 "Not enough memory to create arguments for method");
2821 goto err;
2822 }
2823
2824 arg->wpa_s = wpa_s;
2825 arg->ssid = ssid;
2826
2827 wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
2828 wpas_dbus_network_properties,
2829 wpas_dbus_network_signals);
2830
2831 if (wpa_dbus_register_object_per_iface(ctrl_iface, net_obj_path,
2832 wpa_s->ifname, obj_desc))
2833 goto err;
2834
2835 wpas_dbus_signal_network_added(wpa_s, ssid->id);
2836
2837 return 0;
2838
2839 err:
2840 free_dbus_object_desc(obj_desc);
2841 return -1;
2842 }
2843
2844
2845 /**
2846 * wpas_dbus_unregister_network - Unregister a configured network from dbus
2847 * @wpa_s: wpa_supplicant interface structure
2848 * @nid: network id
2849 * Returns: 0 on success, -1 on failure
2850 *
2851 * Unregisters network representing object from dbus
2852 */
wpas_dbus_unregister_network(struct wpa_supplicant * wpa_s,int nid)2853 int wpas_dbus_unregister_network(struct wpa_supplicant *wpa_s, int nid)
2854 {
2855 struct wpas_dbus_priv *ctrl_iface;
2856 char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
2857 int ret;
2858 #ifdef CONFIG_P2P
2859 struct wpa_ssid *ssid;
2860
2861 ssid = wpa_config_get_network(wpa_s->conf, nid);
2862
2863 /* If it is a persistent group unregister it as such */
2864 if (ssid && network_is_persistent_group(ssid))
2865 return wpas_dbus_unregister_persistent_group(wpa_s, nid);
2866 #endif /* CONFIG_P2P */
2867
2868 /* Do nothing if the control interface is not turned on */
2869 if (wpa_s->global == NULL || wpa_s->dbus_new_path == NULL)
2870 return 0;
2871 ctrl_iface = wpa_s->global->dbus;
2872 if (ctrl_iface == NULL)
2873 return 0;
2874
2875 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2876 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
2877 wpa_s->dbus_new_path, nid);
2878
2879 wpa_printf(MSG_DEBUG, "dbus: Unregister network object '%s'",
2880 net_obj_path);
2881 ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, net_obj_path);
2882
2883 if (!ret)
2884 wpas_dbus_signal_network_removed(wpa_s, nid);
2885
2886 return ret;
2887 }
2888
2889
2890 static const struct wpa_dbus_property_desc wpas_dbus_bss_properties[] = {
2891 { "SSID", WPAS_DBUS_NEW_IFACE_BSS, "ay",
2892 wpas_dbus_getter_bss_ssid,
2893 NULL,
2894 NULL
2895 },
2896 { "BSSID", WPAS_DBUS_NEW_IFACE_BSS, "ay",
2897 wpas_dbus_getter_bss_bssid,
2898 NULL,
2899 NULL
2900 },
2901 { "Privacy", WPAS_DBUS_NEW_IFACE_BSS, "b",
2902 wpas_dbus_getter_bss_privacy,
2903 NULL,
2904 NULL
2905 },
2906 { "Mode", WPAS_DBUS_NEW_IFACE_BSS, "s",
2907 wpas_dbus_getter_bss_mode,
2908 NULL,
2909 NULL
2910 },
2911 { "Signal", WPAS_DBUS_NEW_IFACE_BSS, "n",
2912 wpas_dbus_getter_bss_signal,
2913 NULL,
2914 NULL
2915 },
2916 { "Frequency", WPAS_DBUS_NEW_IFACE_BSS, "q",
2917 wpas_dbus_getter_bss_frequency,
2918 NULL,
2919 NULL
2920 },
2921 { "Rates", WPAS_DBUS_NEW_IFACE_BSS, "au",
2922 wpas_dbus_getter_bss_rates,
2923 NULL,
2924 NULL
2925 },
2926 { "WPA", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
2927 wpas_dbus_getter_bss_wpa,
2928 NULL,
2929 NULL
2930 },
2931 { "RSN", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
2932 wpas_dbus_getter_bss_rsn,
2933 NULL,
2934 NULL
2935 },
2936 { "WPS", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
2937 wpas_dbus_getter_bss_wps,
2938 NULL,
2939 NULL
2940 },
2941 { "IEs", WPAS_DBUS_NEW_IFACE_BSS, "ay",
2942 wpas_dbus_getter_bss_ies,
2943 NULL,
2944 NULL
2945 },
2946 { "Age", WPAS_DBUS_NEW_IFACE_BSS, "u",
2947 wpas_dbus_getter_bss_age,
2948 NULL,
2949 NULL
2950 },
2951 { NULL, NULL, NULL, NULL, NULL, NULL }
2952 };
2953
2954
2955 static const struct wpa_dbus_signal_desc wpas_dbus_bss_signals[] = {
2956 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
2957 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_BSS,
2958 {
2959 { "properties", "a{sv}", ARG_OUT },
2960 END_ARGS
2961 }
2962 },
2963 { NULL, NULL, { END_ARGS } }
2964 };
2965
2966
2967 /**
2968 * wpas_dbus_unregister_bss - Unregister a scanned BSS from dbus
2969 * @wpa_s: wpa_supplicant interface structure
2970 * @bssid: scanned network bssid
2971 * @id: unique BSS identifier
2972 * Returns: 0 on success, -1 on failure
2973 *
2974 * Unregisters BSS representing object from dbus
2975 */
wpas_dbus_unregister_bss(struct wpa_supplicant * wpa_s,u8 bssid[ETH_ALEN],unsigned int id)2976 int wpas_dbus_unregister_bss(struct wpa_supplicant *wpa_s,
2977 u8 bssid[ETH_ALEN], unsigned int id)
2978 {
2979 struct wpas_dbus_priv *ctrl_iface;
2980 char bss_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
2981
2982 /* Do nothing if the control interface is not turned on */
2983 if (wpa_s == NULL || wpa_s->global == NULL || !wpa_s->dbus_new_path)
2984 return 0;
2985 ctrl_iface = wpa_s->global->dbus;
2986 if (ctrl_iface == NULL)
2987 return 0;
2988
2989 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2990 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
2991 wpa_s->dbus_new_path, id);
2992
2993 wpa_printf(MSG_DEBUG, "dbus: Unregister BSS object '%s'",
2994 bss_obj_path);
2995 if (wpa_dbus_unregister_object_per_iface(ctrl_iface, bss_obj_path)) {
2996 wpa_printf(MSG_ERROR, "dbus: Cannot unregister BSS object %s",
2997 bss_obj_path);
2998 return -1;
2999 }
3000
3001 wpas_dbus_signal_bss_removed(wpa_s, bss_obj_path);
3002 wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_BSSS);
3003
3004 return 0;
3005 }
3006
3007
3008 /**
3009 * wpas_dbus_register_bss - Register a scanned BSS with dbus
3010 * @wpa_s: wpa_supplicant interface structure
3011 * @bssid: scanned network bssid
3012 * @id: unique BSS identifier
3013 * Returns: 0 on success, -1 on failure
3014 *
3015 * Registers BSS representing object with dbus
3016 */
wpas_dbus_register_bss(struct wpa_supplicant * wpa_s,u8 bssid[ETH_ALEN],unsigned int id)3017 int wpas_dbus_register_bss(struct wpa_supplicant *wpa_s,
3018 u8 bssid[ETH_ALEN], unsigned int id)
3019 {
3020 struct wpas_dbus_priv *ctrl_iface;
3021 struct wpa_dbus_object_desc *obj_desc;
3022 char bss_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3023 struct bss_handler_args *arg;
3024
3025 /* Do nothing if the control interface is not turned on */
3026 if (wpa_s == NULL || wpa_s->global == NULL || !wpa_s->dbus_new_path)
3027 return 0;
3028 ctrl_iface = wpa_s->global->dbus;
3029 if (ctrl_iface == NULL)
3030 return 0;
3031
3032 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3033 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
3034 wpa_s->dbus_new_path, id);
3035
3036 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
3037 if (!obj_desc) {
3038 wpa_printf(MSG_ERROR,
3039 "Not enough memory to create object description");
3040 goto err;
3041 }
3042
3043 arg = os_zalloc(sizeof(struct bss_handler_args));
3044 if (!arg) {
3045 wpa_printf(MSG_ERROR,
3046 "Not enough memory to create arguments for handler");
3047 goto err;
3048 }
3049 arg->wpa_s = wpa_s;
3050 arg->id = id;
3051
3052 wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
3053 wpas_dbus_bss_properties,
3054 wpas_dbus_bss_signals);
3055
3056 wpa_printf(MSG_DEBUG, "dbus: Register BSS object '%s'",
3057 bss_obj_path);
3058 if (wpa_dbus_register_object_per_iface(ctrl_iface, bss_obj_path,
3059 wpa_s->ifname, obj_desc)) {
3060 wpa_printf(MSG_ERROR,
3061 "Cannot register BSSID dbus object %s.",
3062 bss_obj_path);
3063 goto err;
3064 }
3065
3066 wpas_dbus_signal_bss_added(wpa_s, bss_obj_path);
3067 wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_BSSS);
3068
3069 return 0;
3070
3071 err:
3072 free_dbus_object_desc(obj_desc);
3073 return -1;
3074 }
3075
3076
3077 static const struct wpa_dbus_property_desc wpas_dbus_sta_properties[] = {
3078 { "Address", WPAS_DBUS_NEW_IFACE_STA, "ay",
3079 wpas_dbus_getter_sta_address,
3080 NULL, NULL
3081 },
3082 { "AID", WPAS_DBUS_NEW_IFACE_STA, "q",
3083 wpas_dbus_getter_sta_aid,
3084 NULL, NULL
3085 },
3086 { "Capabilities", WPAS_DBUS_NEW_IFACE_STA, "q",
3087 wpas_dbus_getter_sta_caps,
3088 NULL, NULL
3089 },
3090 { "RxPackets", WPAS_DBUS_NEW_IFACE_STA, "t",
3091 wpas_dbus_getter_sta_rx_packets,
3092 NULL, NULL
3093 },
3094 { "TxPackets", WPAS_DBUS_NEW_IFACE_STA, "t",
3095 wpas_dbus_getter_sta_tx_packets,
3096 NULL, NULL
3097 },
3098 { "RxBytes", WPAS_DBUS_NEW_IFACE_STA, "t",
3099 wpas_dbus_getter_sta_rx_bytes,
3100 NULL, NULL
3101 },
3102 { "TxBytes", WPAS_DBUS_NEW_IFACE_STA, "t",
3103 wpas_dbus_getter_sta_tx_bytes,
3104 NULL, NULL
3105 },
3106 { NULL, NULL, NULL, NULL, NULL, NULL }
3107 };
3108
3109
3110 static const struct wpa_dbus_signal_desc wpas_dbus_sta_signals[] = {
3111 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
3112 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_STA,
3113 {
3114 { "properties", "a{sv}", ARG_OUT },
3115 END_ARGS
3116 }
3117 },
3118 { NULL, NULL, { END_ARGS } }
3119 };
3120
3121
3122 /**
3123 * wpas_dbus_unregister_sta - Unregister a connected station from dbus
3124 * @wpa_s: wpa_supplicant interface structure
3125 * @sta: station MAC address
3126 * Returns: 0 on success, -1 on failure
3127 *
3128 * Unregisters STA representing object from dbus.
3129 */
wpas_dbus_unregister_sta(struct wpa_supplicant * wpa_s,const u8 * sta)3130 int wpas_dbus_unregister_sta(struct wpa_supplicant *wpa_s, const u8 *sta)
3131 {
3132 struct wpas_dbus_priv *ctrl_iface;
3133 char station_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3134
3135 /* Do nothing if the control interface is not turned on */
3136 if (!wpa_s || !wpa_s->global)
3137 return 0;
3138 ctrl_iface = wpa_s->global->dbus;
3139 if (!ctrl_iface)
3140 return 0;
3141
3142 os_snprintf(station_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3143 "%s/" WPAS_DBUS_NEW_STAS_PART "/" COMPACT_MACSTR,
3144 wpa_s->dbus_new_path, MAC2STR(sta));
3145
3146 wpa_printf(MSG_DEBUG, "dbus: Unregister STA object '%s'",
3147 station_obj_path);
3148 if (wpa_dbus_unregister_object_per_iface(ctrl_iface,
3149 station_obj_path)) {
3150 wpa_printf(MSG_ERROR, "dbus: Cannot unregister STA object %s",
3151 station_obj_path);
3152 return -1;
3153 }
3154
3155 wpas_dbus_signal_station_removed(wpa_s, station_obj_path);
3156 wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_STATIONS);
3157
3158 return 0;
3159 }
3160
3161
3162 /**
3163 * wpas_dbus_register_sta - Register a connected station with dbus
3164 * @wpa_s: wpa_supplicant interface structure
3165 * @sta: station MAC address
3166 * Returns: 0 on success, -1 on failure
3167 *
3168 * Registers STA representing object with dbus.
3169 */
wpas_dbus_register_sta(struct wpa_supplicant * wpa_s,const u8 * sta)3170 int wpas_dbus_register_sta(struct wpa_supplicant *wpa_s, const u8 *sta)
3171 {
3172 struct wpas_dbus_priv *ctrl_iface;
3173 struct wpa_dbus_object_desc *obj_desc;
3174 char station_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3175 struct sta_handler_args *arg;
3176
3177 /* Do nothing if the control interface is not turned on */
3178 if (!wpa_s || !wpa_s->global)
3179 return 0;
3180 ctrl_iface = wpa_s->global->dbus;
3181 if (!ctrl_iface)
3182 return 0;
3183
3184 os_snprintf(station_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3185 "%s/" WPAS_DBUS_NEW_STAS_PART "/" COMPACT_MACSTR,
3186 wpa_s->dbus_new_path, MAC2STR(sta));
3187
3188 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
3189 if (!obj_desc) {
3190 wpa_printf(MSG_ERROR,
3191 "Not enough memory to create object description");
3192 goto err;
3193 }
3194
3195 arg = os_zalloc(sizeof(struct sta_handler_args));
3196 if (!arg) {
3197 wpa_printf(MSG_ERROR,
3198 "Not enough memory to create arguments for handler");
3199 goto err;
3200 }
3201 arg->wpa_s = wpa_s;
3202 arg->sta = sta;
3203
3204 wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
3205 wpas_dbus_sta_properties, wpas_dbus_sta_signals);
3206
3207 wpa_printf(MSG_DEBUG, "dbus: Register STA object '%s'",
3208 station_obj_path);
3209 if (wpa_dbus_register_object_per_iface(ctrl_iface, station_obj_path,
3210 wpa_s->ifname, obj_desc)) {
3211 wpa_printf(MSG_ERROR,
3212 "Cannot register STA dbus object %s",
3213 station_obj_path);
3214 goto err;
3215 }
3216
3217 wpas_dbus_signal_station_added(wpa_s, station_obj_path);
3218 wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_STATIONS);
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_method_desc wpas_dbus_interface_methods[] = {
3229 { "Scan", WPAS_DBUS_NEW_IFACE_INTERFACE,
3230 (WPADBusMethodHandler) wpas_dbus_handler_scan,
3231 {
3232 { "args", "a{sv}", ARG_IN },
3233 END_ARGS
3234 }
3235 },
3236 { "SignalPoll", WPAS_DBUS_NEW_IFACE_INTERFACE,
3237 (WPADBusMethodHandler) wpas_dbus_handler_signal_poll,
3238 {
3239 { "args", "a{sv}", ARG_OUT },
3240 END_ARGS
3241 }
3242 },
3243 { "Disconnect", WPAS_DBUS_NEW_IFACE_INTERFACE,
3244 (WPADBusMethodHandler) wpas_dbus_handler_disconnect,
3245 {
3246 END_ARGS
3247 }
3248 },
3249 { "AddNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
3250 (WPADBusMethodHandler) wpas_dbus_handler_add_network,
3251 {
3252 { "args", "a{sv}", ARG_IN },
3253 { "path", "o", ARG_OUT },
3254 END_ARGS
3255 }
3256 },
3257 { "Reassociate", WPAS_DBUS_NEW_IFACE_INTERFACE,
3258 (WPADBusMethodHandler) wpas_dbus_handler_reassociate,
3259 {
3260 END_ARGS
3261 }
3262 },
3263 { "Reattach", WPAS_DBUS_NEW_IFACE_INTERFACE,
3264 (WPADBusMethodHandler) wpas_dbus_handler_reattach,
3265 {
3266 END_ARGS
3267 }
3268 },
3269 { "Reconnect", WPAS_DBUS_NEW_IFACE_INTERFACE,
3270 (WPADBusMethodHandler) wpas_dbus_handler_reconnect,
3271 {
3272 END_ARGS
3273 }
3274 },
3275 { "RemoveNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
3276 (WPADBusMethodHandler) wpas_dbus_handler_remove_network,
3277 {
3278 { "path", "o", ARG_IN },
3279 END_ARGS
3280 }
3281 },
3282 { "RemoveAllNetworks", WPAS_DBUS_NEW_IFACE_INTERFACE,
3283 (WPADBusMethodHandler) wpas_dbus_handler_remove_all_networks,
3284 {
3285 END_ARGS
3286 }
3287 },
3288 { "SelectNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
3289 (WPADBusMethodHandler) wpas_dbus_handler_select_network,
3290 {
3291 { "path", "o", ARG_IN },
3292 END_ARGS
3293 }
3294 },
3295 { "NetworkReply", WPAS_DBUS_NEW_IFACE_INTERFACE,
3296 (WPADBusMethodHandler) wpas_dbus_handler_network_reply,
3297 {
3298 { "path", "o", ARG_IN },
3299 { "field", "s", ARG_IN },
3300 { "value", "s", ARG_IN },
3301 END_ARGS
3302 }
3303 },
3304 { "Roam", WPAS_DBUS_NEW_IFACE_INTERFACE,
3305 (WPADBusMethodHandler) wpas_dbus_handler_roam,
3306 {
3307 { "addr", "s", ARG_IN },
3308 END_ARGS
3309 }
3310 },
3311
3312 #ifndef CONFIG_NO_CONFIG_BLOBS
3313 { "AddBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
3314 (WPADBusMethodHandler) wpas_dbus_handler_add_blob,
3315 {
3316 { "name", "s", ARG_IN },
3317 { "data", "ay", ARG_IN },
3318 END_ARGS
3319 }
3320 },
3321 { "GetBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
3322 (WPADBusMethodHandler) wpas_dbus_handler_get_blob,
3323 {
3324 { "name", "s", ARG_IN },
3325 { "data", "ay", ARG_OUT },
3326 END_ARGS
3327 }
3328 },
3329 { "RemoveBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
3330 (WPADBusMethodHandler) wpas_dbus_handler_remove_blob,
3331 {
3332 { "name", "s", ARG_IN },
3333 END_ARGS
3334 }
3335 },
3336 #endif /* CONFIG_NO_CONFIG_BLOBS */
3337 { "SetPKCS11EngineAndModulePath", WPAS_DBUS_NEW_IFACE_INTERFACE,
3338 (WPADBusMethodHandler)
3339 wpas_dbus_handler_set_pkcs11_engine_and_module_path,
3340 {
3341 { "pkcs11_engine_path", "s", ARG_IN },
3342 { "pkcs11_module_path", "s", ARG_IN },
3343 END_ARGS
3344 }
3345 },
3346 #ifdef CONFIG_WPS
3347 { "Start", WPAS_DBUS_NEW_IFACE_WPS,
3348 (WPADBusMethodHandler) wpas_dbus_handler_wps_start,
3349 {
3350 { "args", "a{sv}", ARG_IN },
3351 { "output", "a{sv}", ARG_OUT },
3352 END_ARGS
3353 }
3354 },
3355 { "Cancel", WPAS_DBUS_NEW_IFACE_WPS,
3356 (WPADBusMethodHandler) wpas_dbus_handler_wps_cancel,
3357 {
3358 END_ARGS
3359 }
3360 },
3361 #endif /* CONFIG_WPS */
3362 #ifdef CONFIG_P2P
3363 { "Find", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3364 (WPADBusMethodHandler) wpas_dbus_handler_p2p_find,
3365 {
3366 { "args", "a{sv}", ARG_IN },
3367 END_ARGS
3368 }
3369 },
3370 { "StopFind", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3371 (WPADBusMethodHandler) wpas_dbus_handler_p2p_stop_find,
3372 {
3373 END_ARGS
3374 }
3375 },
3376 { "Listen", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3377 (WPADBusMethodHandler) wpas_dbus_handler_p2p_listen,
3378 {
3379 { "timeout", "i", ARG_IN },
3380 END_ARGS
3381 }
3382 },
3383 { "ExtendedListen", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3384 (WPADBusMethodHandler) wpas_dbus_handler_p2p_extendedlisten,
3385 {
3386 { "args", "a{sv}", ARG_IN },
3387 END_ARGS
3388 }
3389 },
3390 { "PresenceRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3391 (WPADBusMethodHandler) wpas_dbus_handler_p2p_presence_request,
3392 {
3393 { "args", "a{sv}", ARG_IN },
3394 END_ARGS
3395 }
3396 },
3397 { "ProvisionDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3398 (WPADBusMethodHandler) wpas_dbus_handler_p2p_prov_disc_req,
3399 {
3400 { "peer", "o", ARG_IN },
3401 { "config_method", "s", ARG_IN },
3402 END_ARGS
3403 }
3404 },
3405 { "Connect", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3406 (WPADBusMethodHandler) wpas_dbus_handler_p2p_connect,
3407 {
3408 { "args", "a{sv}", ARG_IN },
3409 { "generated_pin", "s", ARG_OUT },
3410 END_ARGS
3411 }
3412 },
3413 { "GroupAdd", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3414 (WPADBusMethodHandler) wpas_dbus_handler_p2p_group_add,
3415 {
3416 { "args", "a{sv}", ARG_IN },
3417 END_ARGS
3418 }
3419 },
3420 { "Cancel", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3421 (WPADBusMethodHandler) wpas_dbus_handler_p2p_cancel,
3422 {
3423 END_ARGS
3424 }
3425 },
3426 { "Invite", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3427 (WPADBusMethodHandler) wpas_dbus_handler_p2p_invite,
3428 {
3429 { "args", "a{sv}", ARG_IN },
3430 END_ARGS
3431 }
3432 },
3433 { "Disconnect", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3434 (WPADBusMethodHandler) wpas_dbus_handler_p2p_disconnect,
3435 {
3436 END_ARGS
3437 }
3438 },
3439 { "RejectPeer", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3440 (WPADBusMethodHandler) wpas_dbus_handler_p2p_rejectpeer,
3441 {
3442 { "peer", "o", ARG_IN },
3443 END_ARGS
3444 }
3445 },
3446 { "RemoveClient", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3447 (WPADBusMethodHandler) wpas_dbus_handler_p2p_remove_client,
3448 {
3449 { "args", "a{sv}", ARG_IN },
3450 END_ARGS
3451 }
3452 },
3453 { "Flush", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3454 (WPADBusMethodHandler) wpas_dbus_handler_p2p_flush,
3455 {
3456 END_ARGS
3457 }
3458 },
3459 { "AddService", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3460 (WPADBusMethodHandler) wpas_dbus_handler_p2p_add_service,
3461 {
3462 { "args", "a{sv}", ARG_IN },
3463 END_ARGS
3464 }
3465 },
3466 { "DeleteService", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3467 (WPADBusMethodHandler) wpas_dbus_handler_p2p_delete_service,
3468 {
3469 { "args", "a{sv}", ARG_IN },
3470 END_ARGS
3471 }
3472 },
3473 { "FlushService", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3474 (WPADBusMethodHandler) wpas_dbus_handler_p2p_flush_service,
3475 {
3476 END_ARGS
3477 }
3478 },
3479 { "ServiceDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3480 (WPADBusMethodHandler) wpas_dbus_handler_p2p_service_sd_req,
3481 {
3482 { "args", "a{sv}", ARG_IN },
3483 { "ref", "t", ARG_OUT },
3484 END_ARGS
3485 }
3486 },
3487 { "ServiceDiscoveryResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3488 (WPADBusMethodHandler) wpas_dbus_handler_p2p_service_sd_res,
3489 {
3490 { "args", "a{sv}", ARG_IN },
3491 END_ARGS
3492 }
3493 },
3494 { "ServiceDiscoveryCancelRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3495 (WPADBusMethodHandler) wpas_dbus_handler_p2p_service_sd_cancel_req,
3496 {
3497 { "args", "t", ARG_IN },
3498 END_ARGS
3499 }
3500 },
3501 { "ServiceUpdate", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3502 (WPADBusMethodHandler) wpas_dbus_handler_p2p_service_update,
3503 {
3504 END_ARGS
3505 }
3506 },
3507 { "ServiceDiscoveryExternal", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3508 (WPADBusMethodHandler) wpas_dbus_handler_p2p_serv_disc_external,
3509 {
3510 { "arg", "i", ARG_IN },
3511 END_ARGS
3512 }
3513 },
3514 { "AddPersistentGroup", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3515 (WPADBusMethodHandler) wpas_dbus_handler_add_persistent_group,
3516 {
3517 { "args", "a{sv}", ARG_IN },
3518 { "path", "o", ARG_OUT },
3519 END_ARGS
3520 }
3521 },
3522 { "RemovePersistentGroup", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3523 (WPADBusMethodHandler) wpas_dbus_handler_remove_persistent_group,
3524 {
3525 { "path", "o", ARG_IN },
3526 END_ARGS
3527 }
3528 },
3529 { "RemoveAllPersistentGroups", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3530 (WPADBusMethodHandler)
3531 wpas_dbus_handler_remove_all_persistent_groups,
3532 {
3533 END_ARGS
3534 }
3535 },
3536 #endif /* CONFIG_P2P */
3537 { "FlushBSS", WPAS_DBUS_NEW_IFACE_INTERFACE,
3538 (WPADBusMethodHandler) wpas_dbus_handler_flush_bss,
3539 {
3540 { "age", "u", ARG_IN },
3541 END_ARGS
3542 }
3543 },
3544 #ifdef CONFIG_AP
3545 { "SubscribeProbeReq", WPAS_DBUS_NEW_IFACE_INTERFACE,
3546 (WPADBusMethodHandler) wpas_dbus_handler_subscribe_preq,
3547 {
3548 END_ARGS
3549 }
3550 },
3551 { "UnsubscribeProbeReq", WPAS_DBUS_NEW_IFACE_INTERFACE,
3552 (WPADBusMethodHandler) wpas_dbus_handler_unsubscribe_preq,
3553 {
3554 END_ARGS
3555 }
3556 },
3557 #endif /* CONFIG_AP */
3558 { "EAPLogoff", WPAS_DBUS_NEW_IFACE_INTERFACE,
3559 (WPADBusMethodHandler) wpas_dbus_handler_eap_logoff,
3560 {
3561 END_ARGS
3562 }
3563 },
3564 { "EAPLogon", WPAS_DBUS_NEW_IFACE_INTERFACE,
3565 (WPADBusMethodHandler) wpas_dbus_handler_eap_logon,
3566 {
3567 END_ARGS
3568 }
3569 },
3570 #ifdef CONFIG_AUTOSCAN
3571 { "AutoScan", WPAS_DBUS_NEW_IFACE_INTERFACE,
3572 (WPADBusMethodHandler) wpas_dbus_handler_autoscan,
3573 {
3574 { "arg", "s", ARG_IN },
3575 END_ARGS
3576 }
3577 },
3578 #endif /* CONFIG_AUTOSCAN */
3579 #ifdef CONFIG_TDLS
3580 { "TDLSDiscover", WPAS_DBUS_NEW_IFACE_INTERFACE,
3581 (WPADBusMethodHandler) wpas_dbus_handler_tdls_discover,
3582 {
3583 { "peer_address", "s", ARG_IN },
3584 END_ARGS
3585 }
3586 },
3587 { "TDLSSetup", WPAS_DBUS_NEW_IFACE_INTERFACE,
3588 (WPADBusMethodHandler) wpas_dbus_handler_tdls_setup,
3589 {
3590 { "peer_address", "s", ARG_IN },
3591 END_ARGS
3592 }
3593 },
3594 { "TDLSStatus", WPAS_DBUS_NEW_IFACE_INTERFACE,
3595 (WPADBusMethodHandler) wpas_dbus_handler_tdls_status,
3596 {
3597 { "peer_address", "s", ARG_IN },
3598 { "status", "s", ARG_OUT },
3599 END_ARGS
3600 }
3601 },
3602 { "TDLSTeardown", WPAS_DBUS_NEW_IFACE_INTERFACE,
3603 (WPADBusMethodHandler) wpas_dbus_handler_tdls_teardown,
3604 {
3605 { "peer_address", "s", ARG_IN },
3606 END_ARGS
3607 }
3608 },
3609 { "TDLSChannelSwitch", WPAS_DBUS_NEW_IFACE_INTERFACE,
3610 (WPADBusMethodHandler) wpas_dbus_handler_tdls_channel_switch,
3611 {
3612 { "args", "a{sv}", ARG_IN },
3613 END_ARGS
3614 }
3615 },
3616 { "TDLSCancelChannelSwitch", WPAS_DBUS_NEW_IFACE_INTERFACE,
3617 (WPADBusMethodHandler) wpas_dbus_handler_tdls_cancel_channel_switch,
3618 {
3619 { "peer_address", "s", ARG_IN },
3620 END_ARGS
3621 }
3622 },
3623 #endif /* CONFIG_TDLS */
3624 { "VendorElemAdd", WPAS_DBUS_NEW_IFACE_INTERFACE,
3625 (WPADBusMethodHandler) wpas_dbus_handler_vendor_elem_add,
3626 {
3627 { "frame_id", "i", ARG_IN },
3628 { "ielems", "ay", ARG_IN },
3629 END_ARGS
3630 }
3631 },
3632 { "VendorElemGet", WPAS_DBUS_NEW_IFACE_INTERFACE,
3633 (WPADBusMethodHandler) wpas_dbus_handler_vendor_elem_get,
3634 {
3635 { "frame_id", "i", ARG_IN },
3636 { "ielems", "ay", ARG_OUT },
3637 END_ARGS
3638 }
3639 },
3640 { "VendorElemRem", WPAS_DBUS_NEW_IFACE_INTERFACE,
3641 (WPADBusMethodHandler) wpas_dbus_handler_vendor_elem_remove,
3642 {
3643 { "frame_id", "i", ARG_IN },
3644 { "ielems", "ay", ARG_IN },
3645 END_ARGS
3646 }
3647 },
3648 #ifndef CONFIG_NO_CONFIG_WRITE
3649 { "SaveConfig", WPAS_DBUS_NEW_IFACE_INTERFACE,
3650 (WPADBusMethodHandler) wpas_dbus_handler_save_config,
3651 {
3652 END_ARGS
3653 }
3654 },
3655 #endif /* CONFIG_NO_CONFIG_WRITE */
3656 { "AbortScan", WPAS_DBUS_NEW_IFACE_INTERFACE,
3657 (WPADBusMethodHandler) wpas_dbus_handler_abort_scan,
3658 {
3659 END_ARGS
3660 }
3661 },
3662 #ifdef CONFIG_INTERWORKING
3663 { "AddCred", WPAS_DBUS_NEW_IFACE_INTERFACE,
3664 (WPADBusMethodHandler) wpas_dbus_handler_add_cred,
3665 {
3666 { "args", "a{sv}", ARG_IN },
3667 { "path", "o", ARG_OUT },
3668 END_ARGS
3669 }
3670 },
3671 { "RemoveCred", WPAS_DBUS_NEW_IFACE_INTERFACE,
3672 (WPADBusMethodHandler) wpas_dbus_handler_remove_cred,
3673 {
3674 { "path", "o", ARG_IN },
3675 END_ARGS
3676 }
3677 },
3678 { "RemoveAllCreds", WPAS_DBUS_NEW_IFACE_INTERFACE,
3679 (WPADBusMethodHandler) wpas_dbus_handler_remove_all_creds,
3680 {
3681 END_ARGS
3682 }
3683 },
3684 { "InterworkingSelect", WPAS_DBUS_NEW_IFACE_INTERFACE,
3685 (WPADBusMethodHandler) wpas_dbus_handler_interworking_select,
3686 {
3687 END_ARGS
3688 }
3689 },
3690 #endif /* CONFIG_INTERWORKING */
3691 { NULL, NULL, NULL, { END_ARGS } }
3692 };
3693
3694 static const struct wpa_dbus_property_desc wpas_dbus_interface_properties[] = {
3695 { "Capabilities", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{sv}",
3696 wpas_dbus_getter_capabilities,
3697 NULL,
3698 NULL
3699 },
3700 { "State", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3701 wpas_dbus_getter_state,
3702 NULL,
3703 NULL
3704 },
3705 { "Scanning", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
3706 wpas_dbus_getter_scanning,
3707 NULL,
3708 NULL
3709 },
3710 { "ApScan", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
3711 wpas_dbus_getter_ap_scan,
3712 wpas_dbus_setter_ap_scan,
3713 NULL
3714 },
3715 { "BSSExpireAge", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
3716 wpas_dbus_getter_bss_expire_age,
3717 wpas_dbus_setter_bss_expire_age,
3718 NULL
3719 },
3720 { "BSSExpireCount", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
3721 wpas_dbus_getter_bss_expire_count,
3722 wpas_dbus_setter_bss_expire_count,
3723 NULL
3724 },
3725 { "Country", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3726 wpas_dbus_getter_country,
3727 wpas_dbus_setter_country,
3728 NULL
3729 },
3730 { "Ifname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3731 wpas_dbus_getter_ifname,
3732 NULL,
3733 NULL
3734 },
3735 { "Driver", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3736 wpas_dbus_getter_driver,
3737 NULL,
3738 NULL
3739 },
3740 { "BridgeIfname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3741 wpas_dbus_getter_bridge_ifname,
3742 wpas_dbus_setter_bridge_ifname,
3743 NULL
3744 },
3745 { "ConfigFile", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3746 wpas_dbus_getter_config_file,
3747 NULL,
3748 NULL
3749 },
3750 { "CurrentBSS", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
3751 wpas_dbus_getter_current_bss,
3752 NULL,
3753 NULL
3754 },
3755 { "CurrentNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
3756 wpas_dbus_getter_current_network,
3757 NULL,
3758 NULL
3759 },
3760 { "CurrentAuthMode", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3761 wpas_dbus_getter_current_auth_mode,
3762 NULL,
3763 NULL
3764 },
3765 { "Blobs", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{say}",
3766 wpas_dbus_getter_blobs,
3767 NULL,
3768 NULL
3769 },
3770 { "BSSs", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
3771 wpas_dbus_getter_bsss,
3772 NULL,
3773 NULL
3774 },
3775 { "Networks", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
3776 wpas_dbus_getter_networks,
3777 NULL,
3778 NULL
3779 },
3780 { "FastReauth", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
3781 wpas_dbus_getter_fast_reauth,
3782 wpas_dbus_setter_fast_reauth,
3783 NULL
3784 },
3785 { "ScanInterval", WPAS_DBUS_NEW_IFACE_INTERFACE, "i",
3786 wpas_dbus_getter_scan_interval,
3787 wpas_dbus_setter_scan_interval,
3788 NULL
3789 },
3790 { "PKCS11EnginePath", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3791 wpas_dbus_getter_pkcs11_engine_path,
3792 NULL,
3793 NULL
3794 },
3795 { "PKCS11ModulePath", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3796 wpas_dbus_getter_pkcs11_module_path,
3797 NULL,
3798 NULL
3799 },
3800 #ifdef CONFIG_WPS
3801 { "ProcessCredentials", WPAS_DBUS_NEW_IFACE_WPS, "b",
3802 wpas_dbus_getter_process_credentials,
3803 wpas_dbus_setter_process_credentials,
3804 NULL
3805 },
3806 { "ConfigMethods", WPAS_DBUS_NEW_IFACE_WPS, "s",
3807 wpas_dbus_getter_config_methods,
3808 wpas_dbus_setter_config_methods,
3809 NULL
3810 },
3811 {
3812 "DeviceName", WPAS_DBUS_NEW_IFACE_WPS, "s",
3813 wpas_dbus_getter_wps_device_name,
3814 wpas_dbus_setter_wps_device_name,
3815 NULL
3816 },
3817 {
3818 "Manufacturer", WPAS_DBUS_NEW_IFACE_WPS, "s",
3819 wpas_dbus_getter_wps_manufacturer,
3820 wpas_dbus_setter_wps_manufacturer,
3821 NULL
3822 },
3823 {
3824 "ModelName", WPAS_DBUS_NEW_IFACE_WPS, "s",
3825 wpas_dbus_getter_wps_device_model_name,
3826 wpas_dbus_setter_wps_device_model_name,
3827 NULL
3828 },
3829 {
3830 "ModelNumber", WPAS_DBUS_NEW_IFACE_WPS, "s",
3831 wpas_dbus_getter_wps_device_model_number,
3832 wpas_dbus_setter_wps_device_model_number,
3833 NULL
3834 },
3835 {
3836 "SerialNumber", WPAS_DBUS_NEW_IFACE_WPS, "s",
3837 wpas_dbus_getter_wps_device_serial_number,
3838 wpas_dbus_setter_wps_device_serial_number,
3839 NULL
3840 },
3841 {
3842 "DeviceType", WPAS_DBUS_NEW_IFACE_WPS, "ay",
3843 wpas_dbus_getter_wps_device_device_type,
3844 wpas_dbus_setter_wps_device_device_type,
3845 NULL
3846 },
3847 #endif /* CONFIG_WPS */
3848 #ifdef CONFIG_P2P
3849 { "P2PDeviceConfig", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "a{sv}",
3850 wpas_dbus_getter_p2p_device_config,
3851 wpas_dbus_setter_p2p_device_config,
3852 NULL
3853 },
3854 { "Peers", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "ao",
3855 wpas_dbus_getter_p2p_peers,
3856 NULL,
3857 NULL
3858 },
3859 { "Role", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "s",
3860 wpas_dbus_getter_p2p_role,
3861 NULL,
3862 NULL
3863 },
3864 { "Group", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "o",
3865 wpas_dbus_getter_p2p_group,
3866 NULL,
3867 NULL
3868 },
3869 { "PeerGO", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "o",
3870 wpas_dbus_getter_p2p_peergo,
3871 NULL,
3872 NULL
3873 },
3874 { "PersistentGroups", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "ao",
3875 wpas_dbus_getter_persistent_groups,
3876 NULL,
3877 NULL
3878 },
3879 #endif /* CONFIG_P2P */
3880 { "DisconnectReason", WPAS_DBUS_NEW_IFACE_INTERFACE, "i",
3881 wpas_dbus_getter_disconnect_reason,
3882 NULL,
3883 NULL
3884 },
3885 { "AuthStatusCode", WPAS_DBUS_NEW_IFACE_INTERFACE, "i",
3886 wpas_dbus_getter_auth_status_code,
3887 NULL,
3888 NULL
3889 },
3890 { "AssocStatusCode", WPAS_DBUS_NEW_IFACE_INTERFACE, "i",
3891 wpas_dbus_getter_assoc_status_code,
3892 NULL,
3893 NULL
3894 },
3895 {
3896 "RoamTime", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
3897 wpas_dbus_getter_roam_time,
3898 NULL,
3899 NULL
3900 },
3901 {
3902 "RoamComplete", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
3903 wpas_dbus_getter_roam_complete,
3904 NULL,
3905 NULL
3906 },
3907 {
3908 "SessionLength", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
3909 wpas_dbus_getter_session_length,
3910 NULL,
3911 NULL
3912 },
3913 {
3914 "BSSTMStatus", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
3915 wpas_dbus_getter_bss_tm_status,
3916 NULL,
3917 NULL
3918 },
3919 #ifdef CONFIG_MESH
3920 { "MeshPeers", WPAS_DBUS_NEW_IFACE_MESH, "aay",
3921 wpas_dbus_getter_mesh_peers,
3922 NULL,
3923 NULL
3924 },
3925 { "MeshGroup", WPAS_DBUS_NEW_IFACE_MESH, "ay",
3926 wpas_dbus_getter_mesh_group,
3927 NULL,
3928 NULL
3929 },
3930 #endif /* CONFIG_MESH */
3931 { "Stations", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
3932 wpas_dbus_getter_stas,
3933 NULL,
3934 NULL
3935 },
3936 { "MACAddressRandomizationMask", WPAS_DBUS_NEW_IFACE_INTERFACE,
3937 "a{say}",
3938 wpas_dbus_getter_mac_address_randomization_mask,
3939 wpas_dbus_setter_mac_address_randomization_mask,
3940 NULL
3941 },
3942 { NULL, NULL, NULL, NULL, NULL, NULL }
3943 };
3944
3945 static const struct wpa_dbus_signal_desc wpas_dbus_interface_signals[] = {
3946 { "ScanDone", WPAS_DBUS_NEW_IFACE_INTERFACE,
3947 {
3948 { "success", "b", ARG_OUT },
3949 END_ARGS
3950 }
3951 },
3952 { "BSSAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
3953 {
3954 { "path", "o", ARG_OUT },
3955 { "properties", "a{sv}", ARG_OUT },
3956 END_ARGS
3957 }
3958 },
3959 { "BSSRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
3960 {
3961 { "path", "o", ARG_OUT },
3962 END_ARGS
3963 }
3964 },
3965 { "BlobAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
3966 {
3967 { "name", "s", ARG_OUT },
3968 END_ARGS
3969 }
3970 },
3971 { "BlobRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
3972 {
3973 { "name", "s", ARG_OUT },
3974 END_ARGS
3975 }
3976 },
3977 { "NetworkAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
3978 {
3979 { "path", "o", ARG_OUT },
3980 { "properties", "a{sv}", ARG_OUT },
3981 END_ARGS
3982 }
3983 },
3984 { "NetworkRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
3985 {
3986 { "path", "o", ARG_OUT },
3987 END_ARGS
3988 }
3989 },
3990 { "NetworkSelected", WPAS_DBUS_NEW_IFACE_INTERFACE,
3991 {
3992 { "path", "o", ARG_OUT },
3993 END_ARGS
3994 }
3995 },
3996 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
3997 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_INTERFACE,
3998 {
3999 { "properties", "a{sv}", ARG_OUT },
4000 END_ARGS
4001 }
4002 },
4003 #ifdef CONFIG_WPS
4004 { "Event", WPAS_DBUS_NEW_IFACE_WPS,
4005 {
4006 { "name", "s", ARG_OUT },
4007 { "args", "a{sv}", ARG_OUT },
4008 END_ARGS
4009 }
4010 },
4011 { "Credentials", WPAS_DBUS_NEW_IFACE_WPS,
4012 {
4013 { "credentials", "a{sv}", ARG_OUT },
4014 END_ARGS
4015 }
4016 },
4017 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
4018 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_WPS,
4019 {
4020 { "properties", "a{sv}", ARG_OUT },
4021 END_ARGS
4022 }
4023 },
4024 #endif /* CONFIG_WPS */
4025 #ifdef CONFIG_P2P
4026 { "DeviceFound", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4027 {
4028 { "path", "o", ARG_OUT },
4029 END_ARGS
4030 }
4031 },
4032 { "DeviceFoundProperties", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4033 {
4034 { "path", "o", ARG_OUT },
4035 { "properties", "a{sv}", ARG_OUT },
4036 END_ARGS
4037 }
4038 },
4039 { "DeviceLost", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4040 {
4041 { "path", "o", ARG_OUT },
4042 END_ARGS
4043 }
4044 },
4045 { "FindStopped", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4046 {
4047 END_ARGS
4048 }
4049 },
4050 { "ProvisionDiscoveryRequestDisplayPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4051 {
4052 { "peer_object", "o", ARG_OUT },
4053 { "pin", "s", ARG_OUT },
4054 END_ARGS
4055 }
4056 },
4057 { "ProvisionDiscoveryResponseDisplayPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4058 {
4059 { "peer_object", "o", ARG_OUT },
4060 { "pin", "s", ARG_OUT },
4061 END_ARGS
4062 }
4063 },
4064 { "ProvisionDiscoveryRequestEnterPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4065 {
4066 { "peer_object", "o", ARG_OUT },
4067 END_ARGS
4068 }
4069 },
4070 { "ProvisionDiscoveryResponseEnterPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4071 {
4072 { "peer_object", "o", ARG_OUT },
4073 END_ARGS
4074 }
4075 },
4076 { "ProvisionDiscoveryPBCRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4077 {
4078 { "peer_object", "o", ARG_OUT },
4079 END_ARGS
4080 }
4081 },
4082 { "ProvisionDiscoveryPBCResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4083 {
4084 { "peer_object", "o", ARG_OUT },
4085 END_ARGS
4086 }
4087 },
4088 { "ProvisionDiscoveryFailure", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4089 {
4090 { "peer_object", "o", ARG_OUT },
4091 { "status", "i", ARG_OUT },
4092 END_ARGS
4093 }
4094 },
4095 { "GroupStarted", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4096 {
4097 { "properties", "a{sv}", ARG_OUT },
4098 END_ARGS
4099 }
4100 },
4101 { "GroupFormationFailure", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4102 {
4103 { "reason", "s", ARG_OUT },
4104 END_ARGS
4105 }
4106 },
4107 { "GONegotiationSuccess", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4108 {
4109 { "properties", "a{sv}", ARG_OUT },
4110 END_ARGS
4111 }
4112 },
4113 { "GONegotiationFailure", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4114 {
4115 { "properties", "a{sv}", ARG_OUT },
4116 END_ARGS
4117 }
4118 },
4119 { "GONegotiationRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4120 {
4121 { "path", "o", ARG_OUT },
4122 { "dev_passwd_id", "q", ARG_OUT },
4123 { "device_go_intent", "y", ARG_OUT },
4124 END_ARGS
4125 }
4126 },
4127 { "InvitationResult", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4128 {
4129 { "invite_result", "a{sv}", ARG_OUT },
4130 END_ARGS
4131 }
4132 },
4133 { "GroupFinished", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4134 {
4135 { "properties", "a{sv}", ARG_OUT },
4136 END_ARGS
4137 }
4138 },
4139 { "ServiceDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4140 {
4141 { "sd_request", "a{sv}", ARG_OUT },
4142 END_ARGS
4143 }
4144 },
4145 { "ServiceDiscoveryResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4146 {
4147 { "sd_response", "a{sv}", ARG_OUT },
4148 END_ARGS
4149 }
4150 },
4151 { "PersistentGroupAdded", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4152 {
4153 { "path", "o", ARG_OUT },
4154 { "properties", "a{sv}", ARG_OUT },
4155 END_ARGS
4156 }
4157 },
4158 { "PersistentGroupRemoved", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4159 {
4160 { "path", "o", ARG_OUT },
4161 END_ARGS
4162 }
4163 },
4164 { "WpsFailed", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4165 {
4166 { "name", "s", ARG_OUT },
4167 { "args", "a{sv}", ARG_OUT },
4168 END_ARGS
4169 }
4170 },
4171 { "InvitationReceived", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4172 {
4173 { "properties", "a{sv}", ARG_OUT },
4174 END_ARGS
4175 }
4176 },
4177 #endif /* CONFIG_P2P */
4178 #ifdef CONFIG_AP
4179 { "ProbeRequest", WPAS_DBUS_NEW_IFACE_INTERFACE,
4180 {
4181 { "args", "a{sv}", ARG_OUT },
4182 END_ARGS
4183 }
4184 },
4185 #endif /* CONFIG_AP */
4186 { "Certification", WPAS_DBUS_NEW_IFACE_INTERFACE,
4187 {
4188 { "certification", "a{sv}", ARG_OUT },
4189 END_ARGS
4190 }
4191 },
4192 { "EAP", WPAS_DBUS_NEW_IFACE_INTERFACE,
4193 {
4194 { "status", "s", ARG_OUT },
4195 { "parameter", "s", ARG_OUT },
4196 END_ARGS
4197 }
4198 },
4199 { "StaAuthorized", WPAS_DBUS_NEW_IFACE_INTERFACE,
4200 {
4201 { "name", "s", ARG_OUT },
4202 END_ARGS
4203 }
4204 },
4205 { "StaDeauthorized", WPAS_DBUS_NEW_IFACE_INTERFACE,
4206 {
4207 { "name", "s", ARG_OUT },
4208 END_ARGS
4209 }
4210 },
4211 { "StationAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
4212 {
4213 { "path", "o", ARG_OUT },
4214 { "properties", "a{sv}", ARG_OUT },
4215 END_ARGS
4216 }
4217 },
4218 { "StationRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
4219 {
4220 { "path", "o", ARG_OUT },
4221 END_ARGS
4222 }
4223 },
4224 { "NetworkRequest", WPAS_DBUS_NEW_IFACE_INTERFACE,
4225 {
4226 { "path", "o", ARG_OUT },
4227 { "field", "s", ARG_OUT },
4228 { "text", "s", ARG_OUT },
4229 END_ARGS
4230 }
4231 },
4232 #ifdef CONFIG_MESH
4233 { "MeshGroupStarted", WPAS_DBUS_NEW_IFACE_MESH,
4234 {
4235 { "args", "a{sv}", ARG_OUT },
4236 END_ARGS
4237 }
4238 },
4239 { "MeshGroupRemoved", WPAS_DBUS_NEW_IFACE_MESH,
4240 {
4241 { "args", "a{sv}", ARG_OUT },
4242 END_ARGS
4243 }
4244 },
4245 { "MeshPeerConnected", WPAS_DBUS_NEW_IFACE_MESH,
4246 {
4247 { "args", "a{sv}", ARG_OUT },
4248 END_ARGS
4249 }
4250 },
4251 { "MeshPeerDisconnected", WPAS_DBUS_NEW_IFACE_MESH,
4252 {
4253 { "args", "a{sv}", ARG_OUT },
4254 END_ARGS
4255 }
4256 },
4257 #endif /* CONFIG_MESH */
4258 #ifdef CONFIG_INTERWORKING
4259 { "InterworkingAPAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
4260 {
4261 { "bss", "o", ARG_OUT },
4262 { "cred", "o", ARG_OUT },
4263 { "properties", "a{sv}", ARG_OUT },
4264 END_ARGS
4265 }
4266 },
4267 { "InterworkingSelectDone", WPAS_DBUS_NEW_IFACE_INTERFACE,
4268 {
4269 END_ARGS
4270 }
4271 },
4272 #endif /* CONFIG_INTERWORKING */
4273 { NULL, NULL, { END_ARGS } }
4274 };
4275
4276
wpa_dbus_ctrl_iface_props_init(struct wpas_dbus_priv * priv)4277 static int wpa_dbus_ctrl_iface_props_init(struct wpas_dbus_priv *priv)
4278 {
4279 size_t all_size;
4280 unsigned int i, j, count, num_const, num_globals;
4281 const char *global_name;
4282 static const char * const ignored_globals[] = {
4283 "bss_expiration_age", "bss_expiration_scan_count",
4284 "ap_scan", "country", "fast_reauth",
4285 "pkcs11_engine_path", "pkcs11_module_path"
4286 };
4287
4288 /* wpas_dbus_interface_properties terminates with a NULL element */
4289 num_const = ARRAY_SIZE(wpas_dbus_interface_properties) - 1;
4290
4291 num_globals = wpa_config_get_num_global_field_names();
4292 priv->globals_start = num_const;
4293
4294 /* allocate enough for all properties + terminating NULL element */
4295 all_size = (num_globals + num_const + 1) *
4296 sizeof(wpas_dbus_interface_properties[0]);
4297 priv->all_interface_properties = os_zalloc(all_size);
4298 if (!priv->all_interface_properties) {
4299 wpa_printf(MSG_ERROR,
4300 "dbus: Not enough memory for interface properties");
4301 return -1;
4302 }
4303
4304 /* Copy constant interface properties to the start of the array */
4305 os_memcpy(priv->all_interface_properties,
4306 wpas_dbus_interface_properties,
4307 sizeof(wpas_dbus_interface_properties));
4308
4309 /* Dynamically construct interface global properties */
4310 for (i = 0, count = num_const; i < num_globals; i++) {
4311 struct wpa_dbus_property_desc *desc;
4312 int no_var = 0;
4313
4314 /* ignore globals that are actually just methods */
4315 global_name = wpa_config_get_global_field_name(i, &no_var);
4316 if (no_var)
4317 continue;
4318 /* Ignore fields already explicitly exposed */
4319 for (j = 0; j < ARRAY_SIZE(ignored_globals); j++) {
4320 if (os_strcmp(global_name, ignored_globals[j]) == 0)
4321 break;
4322 }
4323 if (j < ARRAY_SIZE(ignored_globals))
4324 continue;
4325
4326 desc = &priv->all_interface_properties[count++];
4327 desc->dbus_property = uscore_to_dbus(global_name);
4328 if (!desc->dbus_property) {
4329 wpa_printf(MSG_ERROR,
4330 "dbus: Not enough memory for D-Bus property name");
4331 goto error;
4332 }
4333 desc->dbus_interface = WPAS_DBUS_NEW_IFACE_INTERFACE;
4334 desc->type = "s";
4335 desc->getter = wpas_dbus_getter_iface_global;
4336 desc->setter = wpas_dbus_setter_iface_global;
4337 desc->data = global_name;
4338 }
4339
4340 return 0;
4341
4342 error:
4343 wpa_dbus_ctrl_iface_props_deinit(priv);
4344 return -1;
4345 }
4346
4347
4348 /**
4349 * wpas_dbus_register_interface - Register an interface with D-Bus
4350 * @wpa_s: wpa_supplicant interface structure
4351 * Returns: 0 on success, -1 on failure
4352 */
wpas_dbus_register_interface(struct wpa_supplicant * wpa_s)4353 int wpas_dbus_register_interface(struct wpa_supplicant *wpa_s)
4354 {
4355 struct wpa_dbus_object_desc *obj_desc = NULL;
4356 struct wpas_dbus_priv *ctrl_iface = wpa_s->global->dbus;
4357 int next;
4358
4359 /* Do nothing if the control interface is not turned on */
4360 if (ctrl_iface == NULL)
4361 return 0;
4362
4363 /* Create and set the interface's object path */
4364 wpa_s->dbus_new_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
4365 if (wpa_s->dbus_new_path == NULL)
4366 return -1;
4367 next = ctrl_iface->next_objid++;
4368 os_snprintf(wpa_s->dbus_new_path, WPAS_DBUS_OBJECT_PATH_MAX,
4369 WPAS_DBUS_NEW_PATH_INTERFACES "/%u",
4370 next);
4371
4372 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
4373 if (!obj_desc) {
4374 wpa_printf(MSG_ERROR,
4375 "Not enough memory to create object description");
4376 goto err;
4377 }
4378
4379 wpas_dbus_register(obj_desc, wpa_s, NULL, wpas_dbus_interface_methods,
4380 ctrl_iface->all_interface_properties,
4381 wpas_dbus_interface_signals);
4382
4383 wpa_printf(MSG_DEBUG, "dbus: Register interface object '%s'",
4384 wpa_s->dbus_new_path);
4385 if (wpa_dbus_register_object_per_iface(ctrl_iface,
4386 wpa_s->dbus_new_path,
4387 wpa_s->ifname, obj_desc))
4388 goto err;
4389
4390 wpas_dbus_signal_interface_added(wpa_s);
4391
4392 return 0;
4393
4394 err:
4395 os_free(wpa_s->dbus_new_path);
4396 wpa_s->dbus_new_path = NULL;
4397 free_dbus_object_desc(obj_desc);
4398 return -1;
4399 }
4400
4401
4402 /**
4403 * wpas_dbus_unregister_interface - Unregister the interface from D-Bus
4404 * @wpa_s: wpa_supplicant interface structure
4405 * Returns: 0 on success, -1 on failure
4406 */
wpas_dbus_unregister_interface(struct wpa_supplicant * wpa_s)4407 int wpas_dbus_unregister_interface(struct wpa_supplicant *wpa_s)
4408 {
4409 struct wpas_dbus_priv *ctrl_iface;
4410
4411 /* Do nothing if the control interface is not turned on */
4412 if (wpa_s == NULL || wpa_s->global == NULL)
4413 return 0;
4414 ctrl_iface = wpa_s->global->dbus;
4415 if (ctrl_iface == NULL || wpa_s->dbus_new_path == NULL)
4416 return 0;
4417
4418 wpa_printf(MSG_DEBUG, "dbus: Unregister interface object '%s'",
4419 wpa_s->dbus_new_path);
4420
4421 #ifdef CONFIG_AP
4422 if (wpa_s->preq_notify_peer) {
4423 wpas_dbus_unsubscribe_noc(ctrl_iface);
4424 os_free(wpa_s->preq_notify_peer);
4425 wpa_s->preq_notify_peer = NULL;
4426 }
4427 #endif /* CONFIG_AP */
4428
4429 if (wpa_dbus_unregister_object_per_iface(ctrl_iface,
4430 wpa_s->dbus_new_path))
4431 return -1;
4432
4433 wpas_dbus_signal_interface_removed(wpa_s);
4434
4435 os_free(wpa_s->dbus_new_path);
4436 wpa_s->dbus_new_path = NULL;
4437
4438 return 0;
4439 }
4440
4441 #ifdef CONFIG_P2P
4442
4443 static const struct wpa_dbus_property_desc wpas_dbus_p2p_peer_properties[] = {
4444 { "DeviceName", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
4445 wpas_dbus_getter_p2p_peer_device_name,
4446 NULL,
4447 NULL
4448 },
4449 { "Manufacturer", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
4450 wpas_dbus_getter_p2p_peer_manufacturer,
4451 NULL,
4452 NULL
4453 },
4454 { "ModelName", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
4455 wpas_dbus_getter_p2p_peer_modelname,
4456 NULL,
4457 NULL
4458 },
4459 { "ModelNumber", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
4460 wpas_dbus_getter_p2p_peer_modelnumber,
4461 NULL,
4462 NULL
4463 },
4464 { "SerialNumber", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
4465 wpas_dbus_getter_p2p_peer_serialnumber,
4466 NULL,
4467 NULL
4468 },
4469 { "PrimaryDeviceType", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
4470 wpas_dbus_getter_p2p_peer_primary_device_type,
4471 NULL,
4472 NULL
4473 },
4474 { "config_method", WPAS_DBUS_NEW_IFACE_P2P_PEER, "q",
4475 wpas_dbus_getter_p2p_peer_config_method,
4476 NULL,
4477 NULL
4478 },
4479 { "level", WPAS_DBUS_NEW_IFACE_P2P_PEER, "i",
4480 wpas_dbus_getter_p2p_peer_level,
4481 NULL,
4482 NULL
4483 },
4484 { "devicecapability", WPAS_DBUS_NEW_IFACE_P2P_PEER, "y",
4485 wpas_dbus_getter_p2p_peer_device_capability,
4486 NULL,
4487 NULL
4488 },
4489 { "groupcapability", WPAS_DBUS_NEW_IFACE_P2P_PEER, "y",
4490 wpas_dbus_getter_p2p_peer_group_capability,
4491 NULL,
4492 NULL
4493 },
4494 { "SecondaryDeviceTypes", WPAS_DBUS_NEW_IFACE_P2P_PEER, "aay",
4495 wpas_dbus_getter_p2p_peer_secondary_device_types,
4496 NULL,
4497 NULL
4498 },
4499 { "VendorExtension", WPAS_DBUS_NEW_IFACE_P2P_PEER, "aay",
4500 wpas_dbus_getter_p2p_peer_vendor_extension,
4501 NULL,
4502 NULL
4503 },
4504 { "IEs", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
4505 wpas_dbus_getter_p2p_peer_ies,
4506 NULL,
4507 NULL
4508 },
4509 { "DeviceAddress", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
4510 wpas_dbus_getter_p2p_peer_device_address,
4511 NULL,
4512 NULL
4513 },
4514 { "Groups", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ao",
4515 wpas_dbus_getter_p2p_peer_groups,
4516 NULL,
4517 NULL
4518 },
4519 { "VSIE", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
4520 wpas_dbus_getter_p2p_peer_vsie,
4521 NULL,
4522 NULL
4523 },
4524 { NULL, NULL, NULL, NULL, NULL, NULL }
4525 };
4526
4527 static const struct wpa_dbus_signal_desc wpas_dbus_p2p_peer_signals[] = {
4528 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
4529 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_P2P_PEER,
4530 {
4531 { "properties", "a{sv}", ARG_OUT },
4532 END_ARGS
4533 }
4534 },
4535 { NULL, NULL, { END_ARGS } }
4536 };
4537
4538 /**
4539 * wpas_dbus_signal_peer - Send a peer related event signal
4540 * @wpa_s: %wpa_supplicant network interface data
4541 * @dev: peer device object
4542 * @interface: name of the interface emitting this signal.
4543 * In case of peer objects, it would be emitted by either
4544 * the "interface object" or by "peer objects"
4545 * @sig_name: signal name - DeviceFound
4546 * @properties: Whether to add a second argument with object properties
4547 *
4548 * Notify listeners about event related with p2p peer device
4549 */
wpas_dbus_signal_peer(struct wpa_supplicant * wpa_s,const u8 * dev_addr,const char * interface,const char * sig_name,dbus_bool_t properties)4550 static void wpas_dbus_signal_peer(struct wpa_supplicant *wpa_s,
4551 const u8 *dev_addr, const char *interface,
4552 const char *sig_name, dbus_bool_t properties)
4553 {
4554 struct wpas_dbus_priv *iface;
4555 DBusMessage *msg;
4556 DBusMessageIter iter;
4557 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
4558
4559 if (wpa_s->p2p_mgmt)
4560 wpa_s = wpa_s->parent;
4561
4562 iface = wpa_s->global->dbus;
4563
4564 /* Do nothing if the control interface is not turned on */
4565 if (iface == NULL || !wpa_s->dbus_new_path)
4566 return;
4567
4568 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
4569 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
4570 wpa_s->dbus_new_path, MAC2STR(dev_addr));
4571
4572 msg = dbus_message_new_signal(wpa_s->dbus_new_path, interface,
4573 sig_name);
4574 if (msg == NULL)
4575 return;
4576
4577 dbus_message_iter_init_append(msg, &iter);
4578 path = peer_obj_path;
4579 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
4580 &path) ||
4581 (properties && !wpa_dbus_get_object_properties(
4582 iface, peer_obj_path, WPAS_DBUS_NEW_IFACE_P2P_PEER,
4583 &iter)))
4584 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
4585 else
4586 dbus_connection_send(iface->con, msg, NULL);
4587
4588 dbus_message_unref(msg);
4589 }
4590
4591
4592 /**
4593 * wpas_dbus_signal_peer_found - Send a peer found signal
4594 * @wpa_s: %wpa_supplicant network interface data
4595 * @dev_addr: Peer P2P Device Address
4596 *
4597 * Notify listeners about find a p2p peer device found
4598 */
wpas_dbus_signal_peer_device_found(struct wpa_supplicant * wpa_s,const u8 * dev_addr)4599 void wpas_dbus_signal_peer_device_found(struct wpa_supplicant *wpa_s,
4600 const u8 *dev_addr)
4601 {
4602 wpas_dbus_signal_peer(wpa_s, dev_addr,
4603 WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4604 "DeviceFound", FALSE);
4605
4606 wpas_dbus_signal_peer(wpa_s, dev_addr,
4607 WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4608 "DeviceFoundProperties", TRUE);
4609 }
4610
4611 /**
4612 * wpas_dbus_signal_peer_lost - Send a peer lost signal
4613 * @wpa_s: %wpa_supplicant network interface data
4614 * @dev_addr: Peer P2P Device Address
4615 *
4616 * Notify listeners about lost a p2p peer device
4617 */
wpas_dbus_signal_peer_device_lost(struct wpa_supplicant * wpa_s,const u8 * dev_addr)4618 void wpas_dbus_signal_peer_device_lost(struct wpa_supplicant *wpa_s,
4619 const u8 *dev_addr)
4620 {
4621 wpas_dbus_signal_peer(wpa_s, dev_addr,
4622 WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4623 "DeviceLost", FALSE);
4624 }
4625
4626 /**
4627 * wpas_dbus_register_peer - Register a discovered peer object with dbus
4628 * @wpa_s: wpa_supplicant interface structure
4629 * @dev_addr: P2P Device Address of the peer
4630 * Returns: 0 on success, -1 on failure
4631 *
4632 * Registers network representing object with dbus
4633 */
wpas_dbus_register_peer(struct wpa_supplicant * wpa_s,const u8 * dev_addr)4634 int wpas_dbus_register_peer(struct wpa_supplicant *wpa_s, const u8 *dev_addr)
4635 {
4636 struct wpas_dbus_priv *ctrl_iface;
4637 struct wpa_dbus_object_desc *obj_desc;
4638 struct peer_handler_args *arg;
4639 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
4640
4641 /* Do nothing if the control interface is not turned on */
4642 if (wpa_s == NULL || wpa_s->global == NULL)
4643 return 0;
4644
4645 ctrl_iface = wpa_s->global->dbus;
4646 if (ctrl_iface == NULL)
4647 return 0;
4648
4649 wpa_s = wpa_s->parent->parent;
4650 if (!wpa_s->dbus_new_path)
4651 return 0;
4652
4653 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
4654 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
4655 wpa_s->dbus_new_path, MAC2STR(dev_addr));
4656
4657 wpa_printf(MSG_INFO, "dbus: Register peer object '%s'",
4658 peer_obj_path);
4659 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
4660 if (!obj_desc) {
4661 wpa_printf(MSG_ERROR,
4662 "Not enough memory to create object description");
4663 goto err;
4664 }
4665
4666 /* allocate memory for handlers arguments */
4667 arg = os_zalloc(sizeof(struct peer_handler_args));
4668 if (!arg) {
4669 wpa_printf(MSG_ERROR,
4670 "Not enough memory to create arguments for method");
4671 goto err;
4672 }
4673
4674 arg->wpa_s = wpa_s;
4675 os_memcpy(arg->p2p_device_addr, dev_addr, ETH_ALEN);
4676
4677 wpas_dbus_register(obj_desc, arg, wpa_dbus_free,
4678 NULL,
4679 wpas_dbus_p2p_peer_properties,
4680 wpas_dbus_p2p_peer_signals);
4681
4682 if (wpa_dbus_register_object_per_iface(ctrl_iface, peer_obj_path,
4683 wpa_s->ifname, obj_desc))
4684 goto err;
4685
4686 return 0;
4687
4688 err:
4689 free_dbus_object_desc(obj_desc);
4690 return -1;
4691 }
4692
4693 /**
4694 * wpas_dbus_unregister_peer - Unregister a peer object with dbus
4695 * @wpa_s: wpa_supplicant interface structure
4696 * @dev_addr: p2p device addr
4697 * Returns: 0 on success, -1 on failure
4698 *
4699 * Registers network representing object with dbus
4700 */
wpas_dbus_unregister_peer(struct wpa_supplicant * wpa_s,const u8 * dev_addr)4701 int wpas_dbus_unregister_peer(struct wpa_supplicant *wpa_s,
4702 const u8 *dev_addr)
4703 {
4704 struct wpas_dbus_priv *ctrl_iface;
4705 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
4706 int ret;
4707
4708 /* Do nothing if the control interface is not turned on */
4709 if (wpa_s == NULL || wpa_s->global == NULL)
4710 return 0;
4711
4712 wpa_s = wpa_s->parent->parent;
4713 if (!wpa_s->dbus_new_path)
4714 return 0;
4715
4716 ctrl_iface = wpa_s->global->dbus;
4717 if (ctrl_iface == NULL)
4718 return 0;
4719
4720 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
4721 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
4722 wpa_s->dbus_new_path, MAC2STR(dev_addr));
4723
4724 wpa_printf(MSG_INFO, "dbus: Unregister peer object '%s'",
4725 peer_obj_path);
4726 ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, peer_obj_path);
4727
4728 return ret;
4729 }
4730
4731
4732 /**
4733 * wpas_dbus_signal_p2p_find_stopped - Send P2P Find stopped signal
4734 * @wpa_s: %wpa_supplicant network interface data
4735 *
4736 * Notify listeners about P2P Find stopped
4737 */
wpas_dbus_signal_p2p_find_stopped(struct wpa_supplicant * wpa_s)4738 void wpas_dbus_signal_p2p_find_stopped(struct wpa_supplicant *wpa_s)
4739 {
4740 struct wpas_dbus_priv *iface;
4741 DBusMessage *msg;
4742
4743 iface = wpa_s->global->dbus;
4744
4745 /* Do nothing if the control interface is not turned on */
4746 if (iface == NULL)
4747 return;
4748
4749 if (wpa_s->p2p_mgmt)
4750 wpa_s = wpa_s->parent;
4751
4752 if (!wpa_s->dbus_new_path)
4753 return;
4754
4755 msg = dbus_message_new_signal(wpa_s->dbus_new_path,
4756 WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4757 "FindStopped");
4758 if (msg == NULL)
4759 return;
4760
4761 dbus_connection_send(iface->con, msg, NULL);
4762
4763 dbus_message_unref(msg);
4764 }
4765
4766
4767 /**
4768 * wpas_dbus_signal_peer_groups_changed - Send peer group change property signal
4769 * @wpa_s: %wpa_supplicant network interface data
4770 * @dev_addr: P2P Device Address
4771 *
4772 * Notify listeners about peer Groups property changes.
4773 */
wpas_dbus_signal_peer_groups_changed(struct wpa_supplicant * wpa_s,const u8 * dev_addr)4774 void wpas_dbus_signal_peer_groups_changed(struct wpa_supplicant *wpa_s,
4775 const u8 *dev_addr)
4776 {
4777 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
4778
4779 if (wpa_s->p2p_mgmt)
4780 wpa_s = wpa_s->parent;
4781
4782 if (!wpa_s->dbus_new_path)
4783 return;
4784 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
4785 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
4786 wpa_s->dbus_new_path, MAC2STR(dev_addr));
4787
4788 wpa_dbus_mark_property_changed(wpa_s->global->dbus, peer_obj_path,
4789 WPAS_DBUS_NEW_IFACE_P2P_PEER, "Groups");
4790 }
4791
4792
4793 static const struct wpa_dbus_property_desc wpas_dbus_p2p_group_properties[] = {
4794 { "Members", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ao",
4795 wpas_dbus_getter_p2p_group_members,
4796 NULL,
4797 NULL
4798 },
4799 { "Group", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "o",
4800 wpas_dbus_getter_p2p_group,
4801 NULL,
4802 NULL
4803 },
4804 { "Role", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "s",
4805 wpas_dbus_getter_p2p_role,
4806 NULL,
4807 NULL
4808 },
4809 { "SSID", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay",
4810 wpas_dbus_getter_p2p_group_ssid,
4811 NULL,
4812 NULL
4813 },
4814 { "BSSID", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay",
4815 wpas_dbus_getter_p2p_group_bssid,
4816 NULL,
4817 NULL
4818 },
4819 { "Frequency", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "q",
4820 wpas_dbus_getter_p2p_group_frequency,
4821 NULL,
4822 NULL
4823 },
4824 { "Passphrase", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "s",
4825 wpas_dbus_getter_p2p_group_passphrase,
4826 NULL,
4827 NULL
4828 },
4829 { "PSK", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay",
4830 wpas_dbus_getter_p2p_group_psk,
4831 NULL,
4832 NULL
4833 },
4834 { "WPSVendorExtensions", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "aay",
4835 wpas_dbus_getter_p2p_group_vendor_ext,
4836 wpas_dbus_setter_p2p_group_vendor_ext,
4837 NULL
4838 },
4839 { NULL, NULL, NULL, NULL, NULL, NULL }
4840 };
4841
4842 static const struct wpa_dbus_signal_desc wpas_dbus_p2p_group_signals[] = {
4843 { "PeerJoined", WPAS_DBUS_NEW_IFACE_P2P_GROUP,
4844 {
4845 { "peer", "o", ARG_OUT },
4846 END_ARGS
4847 }
4848 },
4849 { "PeerDisconnected", WPAS_DBUS_NEW_IFACE_P2P_GROUP,
4850 {
4851 { "peer", "o", ARG_OUT },
4852 END_ARGS
4853 }
4854 },
4855 { NULL, NULL, { END_ARGS } }
4856 };
4857
4858 /**
4859 * wpas_dbus_register_p2p_group - Register a p2p group object with dbus
4860 * @wpa_s: wpa_supplicant interface structure
4861 * @ssid: SSID struct
4862 * Returns: 0 on success, -1 on failure
4863 *
4864 * Registers p2p group representing object with dbus
4865 */
wpas_dbus_register_p2p_group(struct wpa_supplicant * wpa_s,struct wpa_ssid * ssid)4866 void wpas_dbus_register_p2p_group(struct wpa_supplicant *wpa_s,
4867 struct wpa_ssid *ssid)
4868 {
4869 struct wpas_dbus_priv *ctrl_iface;
4870 struct wpa_dbus_object_desc *obj_desc;
4871 char group_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
4872
4873 /* Do nothing if the control interface is not turned on */
4874 if (wpa_s == NULL || wpa_s->global == NULL)
4875 return;
4876
4877 ctrl_iface = wpa_s->global->dbus;
4878 if (ctrl_iface == NULL)
4879 return;
4880
4881 if (wpa_s->dbus_groupobj_path) {
4882 wpa_printf(MSG_INFO, "%s: Group object '%s' already exists",
4883 __func__, wpa_s->dbus_groupobj_path);
4884 return;
4885 }
4886
4887 if (wpas_dbus_get_group_obj_path(wpa_s, ssid, group_obj_path) < 0)
4888 return;
4889
4890 wpa_s->dbus_groupobj_path = os_strdup(group_obj_path);
4891 if (wpa_s->dbus_groupobj_path == NULL)
4892 return;
4893
4894 wpa_printf(MSG_INFO, "dbus: Register group object '%s'",
4895 group_obj_path);
4896 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
4897 if (!obj_desc) {
4898 wpa_printf(MSG_ERROR,
4899 "Not enough memory to create object description");
4900 goto err;
4901 }
4902
4903 wpas_dbus_register(obj_desc, wpa_s, NULL, NULL,
4904 wpas_dbus_p2p_group_properties,
4905 wpas_dbus_p2p_group_signals);
4906
4907 if (wpa_dbus_register_object_per_iface(ctrl_iface, group_obj_path,
4908 wpa_s->ifname, obj_desc))
4909 goto err;
4910
4911 return;
4912
4913 err:
4914 if (wpa_s->dbus_groupobj_path) {
4915 os_free(wpa_s->dbus_groupobj_path);
4916 wpa_s->dbus_groupobj_path = NULL;
4917 }
4918
4919 free_dbus_object_desc(obj_desc);
4920 }
4921
4922 /**
4923 * wpas_dbus_unregister_p2p_group - Unregister a p2p group object from dbus
4924 * @wpa_s: wpa_supplicant interface structure
4925 * @ssid: network name of the p2p group started
4926 */
wpas_dbus_unregister_p2p_group(struct wpa_supplicant * wpa_s,const struct wpa_ssid * ssid)4927 void wpas_dbus_unregister_p2p_group(struct wpa_supplicant *wpa_s,
4928 const struct wpa_ssid *ssid)
4929 {
4930 struct wpas_dbus_priv *ctrl_iface;
4931
4932 /* Do nothing if the control interface is not turned on */
4933 if (wpa_s == NULL || wpa_s->global == NULL)
4934 return;
4935
4936 if (wpa_s->p2p_mgmt)
4937 wpa_s = wpa_s->parent;
4938
4939 ctrl_iface = wpa_s->global->dbus;
4940 if (ctrl_iface == NULL)
4941 return;
4942
4943 if (!wpa_s->dbus_groupobj_path) {
4944 wpa_printf(MSG_DEBUG,
4945 "%s: Group object has already unregistered",
4946 __func__);
4947 return;
4948 }
4949
4950 peer_groups_changed(wpa_s);
4951
4952 wpa_printf(MSG_DEBUG, "dbus: Unregister group object '%s'",
4953 wpa_s->dbus_groupobj_path);
4954
4955 wpa_dbus_unregister_object_per_iface(ctrl_iface,
4956 wpa_s->dbus_groupobj_path);
4957
4958 os_free(wpa_s->dbus_groupobj_path);
4959 wpa_s->dbus_groupobj_path = NULL;
4960 }
4961
4962 static const struct wpa_dbus_property_desc
4963 wpas_dbus_persistent_group_properties[] = {
4964 { "Properties", WPAS_DBUS_NEW_IFACE_PERSISTENT_GROUP, "a{sv}",
4965 wpas_dbus_getter_persistent_group_properties,
4966 wpas_dbus_setter_persistent_group_properties,
4967 NULL
4968 },
4969 { NULL, NULL, NULL, NULL, NULL, NULL }
4970 };
4971
4972 /* No signals intended for persistent group objects */
4973
4974 /**
4975 * wpas_dbus_register_persistent_group - Register a configured(saved)
4976 * persistent group with dbus
4977 * @wpa_s: wpa_supplicant interface structure
4978 * @ssid: persistent group (still represented as a network within wpa)
4979 * configuration data
4980 * Returns: 0 on success, -1 on failure
4981 *
4982 * Registers a persistent group representing object with dbus.
4983 */
wpas_dbus_register_persistent_group(struct wpa_supplicant * wpa_s,struct wpa_ssid * ssid)4984 int wpas_dbus_register_persistent_group(struct wpa_supplicant *wpa_s,
4985 struct wpa_ssid *ssid)
4986 {
4987 struct wpas_dbus_priv *ctrl_iface;
4988 struct wpa_dbus_object_desc *obj_desc;
4989 struct network_handler_args *arg;
4990 char pgrp_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
4991
4992 /* Do nothing if the control interface is not turned on */
4993 if (wpa_s == NULL || wpa_s->global == NULL)
4994 return 0;
4995 wpa_s = wpa_s->parent->parent;
4996 if (!wpa_s->dbus_new_path)
4997 return 0;
4998
4999 /* Make sure ssid is a persistent group */
5000 if (ssid->disabled != 2 && !ssid->p2p_persistent_group)
5001 return -1; /* should we return w/o complaining? */
5002
5003 if (wpa_s->p2p_mgmt)
5004 wpa_s = wpa_s->parent;
5005
5006 ctrl_iface = wpa_s->global->dbus;
5007 if (ctrl_iface == NULL)
5008 return 0;
5009
5010 /*
5011 * Intentionally not coming up with different numbering scheme
5012 * for persistent groups.
5013 */
5014 os_snprintf(pgrp_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
5015 "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%u",
5016 wpa_s->dbus_new_path, ssid->id);
5017
5018 wpa_printf(MSG_DEBUG, "dbus: Register persistent group object '%s'",
5019 pgrp_obj_path);
5020 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
5021 if (!obj_desc) {
5022 wpa_printf(MSG_ERROR,
5023 "dbus: Not enough memory to create object description");
5024 goto err;
5025 }
5026
5027 /*
5028 * Reusing the same context structure as that for networks
5029 * since these are represented using same data structure.
5030 */
5031 /* allocate memory for handlers arguments */
5032 arg = os_zalloc(sizeof(struct network_handler_args));
5033 if (!arg) {
5034 wpa_printf(MSG_ERROR,
5035 "dbus: Not enough memory to create arguments for method");
5036 goto err;
5037 }
5038
5039 arg->wpa_s = wpa_s;
5040 arg->ssid = ssid;
5041
5042 wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
5043 wpas_dbus_persistent_group_properties,
5044 NULL);
5045
5046 if (wpa_dbus_register_object_per_iface(ctrl_iface, pgrp_obj_path,
5047 wpa_s->ifname, obj_desc))
5048 goto err;
5049
5050 wpas_dbus_signal_persistent_group_added(wpa_s, ssid->id);
5051
5052 return 0;
5053
5054 err:
5055 free_dbus_object_desc(obj_desc);
5056 return -1;
5057 }
5058
5059
5060 /**
5061 * wpas_dbus_unregister_persistent_group - Unregister a persistent_group
5062 * from dbus
5063 * @wpa_s: wpa_supplicant interface structure
5064 * @nid: network id
5065 * Returns: 0 on success, -1 on failure
5066 *
5067 * Unregisters persistent group representing object from dbus
5068 *
5069 * NOTE: There is a slight issue with the semantics here. While the
5070 * implementation simply means the persistent group is unloaded from memory,
5071 * it should not get interpreted as the group is actually being erased/removed
5072 * from persistent storage as well.
5073 */
wpas_dbus_unregister_persistent_group(struct wpa_supplicant * wpa_s,int nid)5074 int wpas_dbus_unregister_persistent_group(struct wpa_supplicant *wpa_s,
5075 int nid)
5076 {
5077 struct wpas_dbus_priv *ctrl_iface;
5078 char pgrp_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
5079 int ret;
5080
5081 /* Do nothing if the control interface is not turned on */
5082 if (wpa_s == NULL || wpa_s->global == NULL)
5083 return 0;
5084
5085 wpa_s = wpa_s->parent->parent;
5086
5087 ctrl_iface = wpa_s->global->dbus;
5088 if (ctrl_iface == NULL || !wpa_s->dbus_new_path)
5089 return 0;
5090
5091 os_snprintf(pgrp_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
5092 "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%u",
5093 wpa_s->dbus_new_path, nid);
5094
5095 wpa_printf(MSG_DEBUG, "dbus: Unregister persistent group object '%s'",
5096 pgrp_obj_path);
5097 ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, pgrp_obj_path);
5098
5099 if (!ret)
5100 wpas_dbus_signal_persistent_group_removed(wpa_s, nid);
5101
5102 return ret;
5103 }
5104
5105 #endif /* CONFIG_P2P */
5106