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