xref: /dragonfly/contrib/wpa_supplicant/wpa_supplicant/dbus/dbus_new.c (revision 3a84a4273475ed07d0ab1c2dfeffdfedef35d9cd)
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                                                       &parameter))
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