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