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