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