1214501Srpaulo/*
2214501Srpaulo * WPA Supplicant / dbus-based control interface
3214501Srpaulo * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
4214501Srpaulo * Copyright (c) 2009-2010, Witold Sowa <witold.sowa@gmail.com>
5214501Srpaulo * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
6214501Srpaulo *
7214501Srpaulo * This program is free software; you can redistribute it and/or modify
8214501Srpaulo * it under the terms of the GNU General Public License version 2 as
9214501Srpaulo * published by the Free Software Foundation.
10214501Srpaulo *
11214501Srpaulo * Alternatively, this software may be distributed under the terms of BSD
12214501Srpaulo * license.
13214501Srpaulo *
14214501Srpaulo * See README and COPYING for more details.
15214501Srpaulo */
16214501Srpaulo
17214501Srpaulo#include "includes.h"
18214501Srpaulo
19214501Srpaulo#include "common.h"
20214501Srpaulo#include "wps/wps.h"
21214501Srpaulo#include "../config.h"
22214501Srpaulo#include "../wpa_supplicant_i.h"
23214501Srpaulo#include "../bss.h"
24214501Srpaulo#include "dbus_new_helpers.h"
25214501Srpaulo#include "dbus_dict_helpers.h"
26214501Srpaulo#include "dbus_new.h"
27214501Srpaulo#include "dbus_new_handlers.h"
28214501Srpaulo#include "dbus_common.h"
29214501Srpaulo#include "dbus_common_i.h"
30214501Srpaulo
31214501Srpaulo
32214501Srpaulo/**
33214501Srpaulo * wpas_dbus_signal_interface - Send a interface related event signal
34214501Srpaulo * @wpa_s: %wpa_supplicant network interface data
35214501Srpaulo * @sig_name: signal name - InterfaceAdded or InterfaceRemoved
36214501Srpaulo * @properties: Whether to add second argument with object properties
37214501Srpaulo *
38214501Srpaulo * Notify listeners about event related with interface
39214501Srpaulo */
40214501Srpaulostatic void wpas_dbus_signal_interface(struct wpa_supplicant *wpa_s,
41214501Srpaulo				       const char *sig_name, int properties)
42214501Srpaulo{
43214501Srpaulo	struct wpas_dbus_priv *iface;
44214501Srpaulo	DBusMessage *msg;
45214501Srpaulo	DBusMessageIter iter, iter_dict;
46214501Srpaulo
47214501Srpaulo	iface = wpa_s->global->dbus;
48214501Srpaulo
49214501Srpaulo	/* Do nothing if the control interface is not turned on */
50214501Srpaulo	if (iface == NULL)
51214501Srpaulo		return;
52214501Srpaulo
53214501Srpaulo	msg = dbus_message_new_signal(WPAS_DBUS_NEW_PATH,
54214501Srpaulo				      WPAS_DBUS_NEW_INTERFACE, sig_name);
55214501Srpaulo	if (msg == NULL)
56214501Srpaulo		return;
57214501Srpaulo
58214501Srpaulo	dbus_message_iter_init_append(msg, &iter);
59214501Srpaulo	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
60214501Srpaulo					    &wpa_s->dbus_new_path))
61214501Srpaulo		goto err;
62214501Srpaulo
63214501Srpaulo	if (properties) {
64214501Srpaulo		if (!wpa_dbus_dict_open_write(&iter, &iter_dict))
65214501Srpaulo			goto err;
66214501Srpaulo
67214501Srpaulo		wpa_dbus_get_object_properties(iface, wpa_s->dbus_new_path,
68214501Srpaulo					       WPAS_DBUS_NEW_IFACE_INTERFACE,
69214501Srpaulo					       &iter_dict);
70214501Srpaulo
71214501Srpaulo		if (!wpa_dbus_dict_close_write(&iter, &iter_dict))
72214501Srpaulo			goto err;
73214501Srpaulo	}
74214501Srpaulo
75214501Srpaulo	dbus_connection_send(iface->con, msg, NULL);
76214501Srpaulo	dbus_message_unref(msg);
77214501Srpaulo	return;
78214501Srpaulo
79214501Srpauloerr:
80214501Srpaulo	wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
81214501Srpaulo	dbus_message_unref(msg);
82214501Srpaulo}
83214501Srpaulo
84214501Srpaulo
85214501Srpaulo/**
86214501Srpaulo * wpas_dbus_signal_interface_added - Send a interface created signal
87214501Srpaulo * @wpa_s: %wpa_supplicant network interface data
88214501Srpaulo *
89214501Srpaulo * Notify listeners about creating new interface
90214501Srpaulo */
91214501Srpaulostatic void wpas_dbus_signal_interface_added(struct wpa_supplicant *wpa_s)
92214501Srpaulo{
93214501Srpaulo	wpas_dbus_signal_interface(wpa_s, "InterfaceAdded", TRUE);
94214501Srpaulo}
95214501Srpaulo
96214501Srpaulo
97214501Srpaulo/**
98214501Srpaulo * wpas_dbus_signal_interface_removed - Send a interface removed signal
99214501Srpaulo * @wpa_s: %wpa_supplicant network interface data
100214501Srpaulo *
101214501Srpaulo * Notify listeners about removing interface
102214501Srpaulo */
103214501Srpaulostatic void wpas_dbus_signal_interface_removed(struct wpa_supplicant *wpa_s)
104214501Srpaulo{
105214501Srpaulo	wpas_dbus_signal_interface(wpa_s, "InterfaceRemoved", FALSE);
106214501Srpaulo
107214501Srpaulo}
108214501Srpaulo
109214501Srpaulo
110214501Srpaulo/**
111214501Srpaulo * wpas_dbus_signal_scan_done - send scan done signal
112214501Srpaulo * @wpa_s: %wpa_supplicant network interface data
113214501Srpaulo * @success: indicates if scanning succeed or failed
114214501Srpaulo *
115214501Srpaulo * Notify listeners about finishing a scan
116214501Srpaulo */
117214501Srpaulovoid wpas_dbus_signal_scan_done(struct wpa_supplicant *wpa_s, int success)
118214501Srpaulo{
119214501Srpaulo	struct wpas_dbus_priv *iface;
120214501Srpaulo	DBusMessage *msg;
121214501Srpaulo	dbus_bool_t succ;
122214501Srpaulo
123214501Srpaulo	iface = wpa_s->global->dbus;
124214501Srpaulo
125214501Srpaulo	/* Do nothing if the control interface is not turned on */
126214501Srpaulo	if (iface == NULL)
127214501Srpaulo		return;
128214501Srpaulo
129214501Srpaulo	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
130214501Srpaulo				      WPAS_DBUS_NEW_IFACE_INTERFACE,
131214501Srpaulo				      "ScanDone");
132214501Srpaulo	if (msg == NULL)
133214501Srpaulo		return;
134214501Srpaulo
135214501Srpaulo	succ = success ? TRUE : FALSE;
136214501Srpaulo	if (dbus_message_append_args(msg, DBUS_TYPE_BOOLEAN, &succ,
137214501Srpaulo				     DBUS_TYPE_INVALID))
138214501Srpaulo		dbus_connection_send(iface->con, msg, NULL);
139214501Srpaulo	else
140214501Srpaulo		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
141214501Srpaulo	dbus_message_unref(msg);
142214501Srpaulo}
143214501Srpaulo
144214501Srpaulo
145214501Srpaulo/**
146214501Srpaulo * wpas_dbus_signal_blob - Send a BSS related event signal
147214501Srpaulo * @wpa_s: %wpa_supplicant network interface data
148214501Srpaulo * @bss_obj_path: BSS object path
149214501Srpaulo * @sig_name: signal name - BSSAdded or BSSRemoved
150214501Srpaulo * @properties: Whether to add second argument with object properties
151214501Srpaulo *
152214501Srpaulo * Notify listeners about event related with BSS
153214501Srpaulo */
154214501Srpaulostatic void wpas_dbus_signal_bss(struct wpa_supplicant *wpa_s,
155214501Srpaulo				 const char *bss_obj_path,
156214501Srpaulo				 const char *sig_name, int properties)
157214501Srpaulo{
158214501Srpaulo	struct wpas_dbus_priv *iface;
159214501Srpaulo	DBusMessage *msg;
160214501Srpaulo	DBusMessageIter iter, iter_dict;
161214501Srpaulo
162214501Srpaulo	iface = wpa_s->global->dbus;
163214501Srpaulo
164214501Srpaulo	/* Do nothing if the control interface is not turned on */
165214501Srpaulo	if (iface == NULL)
166214501Srpaulo		return;
167214501Srpaulo
168214501Srpaulo	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
169214501Srpaulo				      WPAS_DBUS_NEW_IFACE_INTERFACE,
170214501Srpaulo				      sig_name);
171214501Srpaulo	if (msg == NULL)
172214501Srpaulo		return;
173214501Srpaulo
174214501Srpaulo	dbus_message_iter_init_append(msg, &iter);
175214501Srpaulo	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
176214501Srpaulo					    &bss_obj_path))
177214501Srpaulo		goto err;
178214501Srpaulo
179214501Srpaulo	if (properties) {
180214501Srpaulo		if (!wpa_dbus_dict_open_write(&iter, &iter_dict))
181214501Srpaulo			goto err;
182214501Srpaulo
183214501Srpaulo		wpa_dbus_get_object_properties(iface, bss_obj_path,
184214501Srpaulo					       WPAS_DBUS_NEW_IFACE_BSS,
185214501Srpaulo					       &iter_dict);
186214501Srpaulo
187214501Srpaulo		if (!wpa_dbus_dict_close_write(&iter, &iter_dict))
188214501Srpaulo			goto err;
189214501Srpaulo	}
190214501Srpaulo
191214501Srpaulo	dbus_connection_send(iface->con, msg, NULL);
192214501Srpaulo	dbus_message_unref(msg);
193214501Srpaulo	return;
194214501Srpaulo
195214501Srpauloerr:
196214501Srpaulo	wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
197214501Srpaulo	dbus_message_unref(msg);
198214501Srpaulo}
199214501Srpaulo
200214501Srpaulo
201214501Srpaulo/**
202214501Srpaulo * wpas_dbus_signal_bss_added - Send a BSS added signal
203214501Srpaulo * @wpa_s: %wpa_supplicant network interface data
204214501Srpaulo * @bss_obj_path: new BSS object path
205214501Srpaulo *
206214501Srpaulo * Notify listeners about adding new BSS
207214501Srpaulo */
208214501Srpaulostatic void wpas_dbus_signal_bss_added(struct wpa_supplicant *wpa_s,
209214501Srpaulo				       const char *bss_obj_path)
210214501Srpaulo{
211214501Srpaulo	wpas_dbus_signal_bss(wpa_s, bss_obj_path, "BSSAdded", TRUE);
212214501Srpaulo}
213214501Srpaulo
214214501Srpaulo
215214501Srpaulo/**
216214501Srpaulo * wpas_dbus_signal_bss_removed - Send a BSS removed signal
217214501Srpaulo * @wpa_s: %wpa_supplicant network interface data
218214501Srpaulo * @bss_obj_path: BSS object path
219214501Srpaulo *
220214501Srpaulo * Notify listeners about removing BSS
221214501Srpaulo */
222214501Srpaulostatic void wpas_dbus_signal_bss_removed(struct wpa_supplicant *wpa_s,
223214501Srpaulo					 const char *bss_obj_path)
224214501Srpaulo{
225214501Srpaulo	wpas_dbus_signal_bss(wpa_s, bss_obj_path, "BSSRemoved", FALSE);
226214501Srpaulo}
227214501Srpaulo
228214501Srpaulo
229214501Srpaulo/**
230214501Srpaulo * wpas_dbus_signal_blob - Send a blob related event signal
231214501Srpaulo * @wpa_s: %wpa_supplicant network interface data
232214501Srpaulo * @name: blob name
233214501Srpaulo * @sig_name: signal name - BlobAdded or BlobRemoved
234214501Srpaulo *
235214501Srpaulo * Notify listeners about event related with blob
236214501Srpaulo */
237214501Srpaulostatic void wpas_dbus_signal_blob(struct wpa_supplicant *wpa_s,
238214501Srpaulo				  const char *name, const char *sig_name)
239214501Srpaulo{
240214501Srpaulo	struct wpas_dbus_priv *iface;
241214501Srpaulo	DBusMessage *msg;
242214501Srpaulo
243214501Srpaulo	iface = wpa_s->global->dbus;
244214501Srpaulo
245214501Srpaulo	/* Do nothing if the control interface is not turned on */
246214501Srpaulo	if (iface == NULL)
247214501Srpaulo		return;
248214501Srpaulo
249214501Srpaulo	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
250214501Srpaulo				      WPAS_DBUS_NEW_IFACE_INTERFACE,
251214501Srpaulo				      sig_name);
252214501Srpaulo	if (msg == NULL)
253214501Srpaulo		return;
254214501Srpaulo
255214501Srpaulo	if (dbus_message_append_args(msg, DBUS_TYPE_STRING, &name,
256214501Srpaulo				     DBUS_TYPE_INVALID))
257214501Srpaulo		dbus_connection_send(iface->con, msg, NULL);
258214501Srpaulo	else
259214501Srpaulo		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
260214501Srpaulo	dbus_message_unref(msg);
261214501Srpaulo}
262214501Srpaulo
263214501Srpaulo
264214501Srpaulo/**
265214501Srpaulo * wpas_dbus_signal_blob_added - Send a blob added signal
266214501Srpaulo * @wpa_s: %wpa_supplicant network interface data
267214501Srpaulo * @name: blob name
268214501Srpaulo *
269214501Srpaulo * Notify listeners about adding a new blob
270214501Srpaulo */
271214501Srpaulovoid wpas_dbus_signal_blob_added(struct wpa_supplicant *wpa_s,
272214501Srpaulo				 const char *name)
273214501Srpaulo{
274214501Srpaulo	wpas_dbus_signal_blob(wpa_s, name, "BlobAdded");
275214501Srpaulo}
276214501Srpaulo
277214501Srpaulo
278214501Srpaulo/**
279214501Srpaulo * wpas_dbus_signal_blob_removed - Send a blob removed signal
280214501Srpaulo * @wpa_s: %wpa_supplicant network interface data
281214501Srpaulo * @name: blob name
282214501Srpaulo *
283214501Srpaulo * Notify listeners about removing blob
284214501Srpaulo */
285214501Srpaulovoid wpas_dbus_signal_blob_removed(struct wpa_supplicant *wpa_s,
286214501Srpaulo				   const char *name)
287214501Srpaulo{
288214501Srpaulo	wpas_dbus_signal_blob(wpa_s, name, "BlobRemoved");
289214501Srpaulo}
290214501Srpaulo
291214501Srpaulo
292214501Srpaulo/**
293214501Srpaulo * wpas_dbus_signal_network - Send a network related event signal
294214501Srpaulo * @wpa_s: %wpa_supplicant network interface data
295214501Srpaulo * @id: new network id
296214501Srpaulo * @sig_name: signal name - NetworkAdded, NetworkRemoved or NetworkSelected
297214501Srpaulo * @properties: determines if add second argument with object properties
298214501Srpaulo *
299214501Srpaulo * Notify listeners about event related with configured network
300214501Srpaulo */
301214501Srpaulostatic void wpas_dbus_signal_network(struct wpa_supplicant *wpa_s,
302214501Srpaulo				     int id, const char *sig_name,
303214501Srpaulo				     int properties)
304214501Srpaulo{
305214501Srpaulo	struct wpas_dbus_priv *iface;
306214501Srpaulo	DBusMessage *msg;
307214501Srpaulo	DBusMessageIter iter, iter_dict;
308214501Srpaulo	char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
309214501Srpaulo
310214501Srpaulo	iface = wpa_s->global->dbus;
311214501Srpaulo
312214501Srpaulo	/* Do nothing if the control interface is not turned on */
313214501Srpaulo	if (iface == NULL)
314214501Srpaulo		return;
315214501Srpaulo
316214501Srpaulo	os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
317214501Srpaulo		    "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
318214501Srpaulo		    wpa_s->dbus_new_path, id);
319214501Srpaulo
320214501Srpaulo	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
321214501Srpaulo				      WPAS_DBUS_NEW_IFACE_INTERFACE,
322214501Srpaulo				      sig_name);
323214501Srpaulo	if (msg == NULL)
324214501Srpaulo		return;
325214501Srpaulo
326214501Srpaulo	dbus_message_iter_init_append(msg, &iter);
327214501Srpaulo	path = net_obj_path;
328214501Srpaulo	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
329214501Srpaulo					    &path))
330214501Srpaulo		goto err;
331214501Srpaulo
332214501Srpaulo	if (properties) {
333214501Srpaulo		if (!wpa_dbus_dict_open_write(&iter, &iter_dict))
334214501Srpaulo			goto err;
335214501Srpaulo
336214501Srpaulo		wpa_dbus_get_object_properties(iface, net_obj_path,
337214501Srpaulo					       WPAS_DBUS_NEW_IFACE_NETWORK,
338214501Srpaulo					       &iter_dict);
339214501Srpaulo
340214501Srpaulo		if (!wpa_dbus_dict_close_write(&iter, &iter_dict))
341214501Srpaulo			goto err;
342214501Srpaulo	}
343214501Srpaulo
344214501Srpaulo	dbus_connection_send(iface->con, msg, NULL);
345214501Srpaulo
346214501Srpaulo	dbus_message_unref(msg);
347214501Srpaulo	return;
348214501Srpaulo
349214501Srpauloerr:
350214501Srpaulo	wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
351214501Srpaulo	dbus_message_unref(msg);
352214501Srpaulo}
353214501Srpaulo
354214501Srpaulo
355214501Srpaulo/**
356214501Srpaulo * wpas_dbus_signal_network_added - Send a network added signal
357214501Srpaulo * @wpa_s: %wpa_supplicant network interface data
358214501Srpaulo * @id: new network id
359214501Srpaulo *
360214501Srpaulo * Notify listeners about adding new network
361214501Srpaulo */
362214501Srpaulostatic void wpas_dbus_signal_network_added(struct wpa_supplicant *wpa_s,
363214501Srpaulo					   int id)
364214501Srpaulo{
365214501Srpaulo	wpas_dbus_signal_network(wpa_s, id, "NetworkAdded", TRUE);
366214501Srpaulo}
367214501Srpaulo
368214501Srpaulo
369214501Srpaulo/**
370214501Srpaulo * wpas_dbus_signal_network_removed - Send a network removed signal
371214501Srpaulo * @wpa_s: %wpa_supplicant network interface data
372214501Srpaulo * @id: network id
373214501Srpaulo *
374214501Srpaulo * Notify listeners about removing a network
375214501Srpaulo */
376214501Srpaulostatic void wpas_dbus_signal_network_removed(struct wpa_supplicant *wpa_s,
377214501Srpaulo					     int id)
378214501Srpaulo{
379214501Srpaulo	wpas_dbus_signal_network(wpa_s, id, "NetworkRemoved", FALSE);
380214501Srpaulo}
381214501Srpaulo
382214501Srpaulo
383214501Srpaulo/**
384214501Srpaulo * wpas_dbus_signal_network_selected - Send a network selected signal
385214501Srpaulo * @wpa_s: %wpa_supplicant network interface data
386214501Srpaulo * @id: network id
387214501Srpaulo *
388214501Srpaulo * Notify listeners about selecting a network
389214501Srpaulo */
390214501Srpaulovoid wpas_dbus_signal_network_selected(struct wpa_supplicant *wpa_s, int id)
391214501Srpaulo{
392214501Srpaulo	wpas_dbus_signal_network(wpa_s, id, "NetworkSelected", FALSE);
393214501Srpaulo}
394214501Srpaulo
395214501Srpaulo
396214501Srpaulo/**
397214501Srpaulo * wpas_dbus_signal_network_enabled_changed - Signals Enabled property changes
398214501Srpaulo * @wpa_s: %wpa_supplicant network interface data
399214501Srpaulo * @ssid: configured network which Enabled property has changed
400214501Srpaulo *
401214501Srpaulo * Sends PropertyChanged signals containing new value of Enabled property
402214501Srpaulo * for specified network
403214501Srpaulo */
404214501Srpaulovoid wpas_dbus_signal_network_enabled_changed(struct wpa_supplicant *wpa_s,
405214501Srpaulo					      struct wpa_ssid *ssid)
406214501Srpaulo{
407214501Srpaulo
408214501Srpaulo	char path[WPAS_DBUS_OBJECT_PATH_MAX];
409214501Srpaulo	os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
410214501Srpaulo		    "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
411214501Srpaulo		    wpa_s->dbus_new_path, ssid->id);
412214501Srpaulo
413214501Srpaulo	wpa_dbus_mark_property_changed(wpa_s->global->dbus, path,
414214501Srpaulo				       WPAS_DBUS_NEW_IFACE_NETWORK, "Enabled");
415214501Srpaulo}
416214501Srpaulo
417214501Srpaulo
418214501Srpaulo#ifdef CONFIG_WPS
419214501Srpaulo
420214501Srpaulo/**
421214501Srpaulo * wpas_dbus_signal_wps_event_success - Signals Success WPS event
422214501Srpaulo * @wpa_s: %wpa_supplicant network interface data
423214501Srpaulo *
424214501Srpaulo * Sends Event dbus signal with name "success" and empty dict as arguments
425214501Srpaulo */
426214501Srpaulovoid wpas_dbus_signal_wps_event_success(struct wpa_supplicant *wpa_s)
427214501Srpaulo{
428214501Srpaulo
429214501Srpaulo	DBusMessage *msg;
430214501Srpaulo	DBusMessageIter iter, dict_iter;
431214501Srpaulo	struct wpas_dbus_priv *iface;
432214501Srpaulo	char *key = "success";
433214501Srpaulo
434214501Srpaulo	iface = wpa_s->global->dbus;
435214501Srpaulo
436214501Srpaulo	/* Do nothing if the control interface is not turned on */
437214501Srpaulo	if (iface == NULL)
438214501Srpaulo		return;
439214501Srpaulo
440214501Srpaulo	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
441214501Srpaulo				      WPAS_DBUS_NEW_IFACE_WPS, "Event");
442214501Srpaulo	if (msg == NULL)
443214501Srpaulo		return;
444214501Srpaulo
445214501Srpaulo	dbus_message_iter_init_append(msg, &iter);
446214501Srpaulo
447214501Srpaulo	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
448214501Srpaulo	    !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
449214501Srpaulo	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
450214501Srpaulo		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
451214501Srpaulo	else
452214501Srpaulo		dbus_connection_send(iface->con, msg, NULL);
453214501Srpaulo
454214501Srpaulo	dbus_message_unref(msg);
455214501Srpaulo}
456214501Srpaulo
457214501Srpaulo
458214501Srpaulo/**
459214501Srpaulo * wpas_dbus_signal_wps_event_fail - Signals Fail WPS event
460214501Srpaulo * @wpa_s: %wpa_supplicant network interface data
461214501Srpaulo *
462214501Srpaulo * Sends Event dbus signal with name "fail" and dictionary containing
463214501Srpaulo * "msg field with fail message number (int32) as arguments
464214501Srpaulo */
465214501Srpaulovoid wpas_dbus_signal_wps_event_fail(struct wpa_supplicant *wpa_s,
466214501Srpaulo				     struct wps_event_fail *fail)
467214501Srpaulo{
468214501Srpaulo
469214501Srpaulo	DBusMessage *msg;
470214501Srpaulo	DBusMessageIter iter, dict_iter;
471214501Srpaulo	struct wpas_dbus_priv *iface;
472214501Srpaulo	char *key = "fail";
473214501Srpaulo
474214501Srpaulo	iface = wpa_s->global->dbus;
475214501Srpaulo
476214501Srpaulo	/* Do nothing if the control interface is not turned on */
477214501Srpaulo	if (iface == NULL)
478214501Srpaulo		return;
479214501Srpaulo
480214501Srpaulo	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
481214501Srpaulo				      WPAS_DBUS_NEW_IFACE_WPS, "Event");
482214501Srpaulo	if (msg == NULL)
483214501Srpaulo		return;
484214501Srpaulo
485214501Srpaulo	dbus_message_iter_init_append(msg, &iter);
486214501Srpaulo
487214501Srpaulo	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
488214501Srpaulo	    !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
489214501Srpaulo	    !wpa_dbus_dict_append_int32(&dict_iter, "msg", fail->msg) ||
490214501Srpaulo	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
491214501Srpaulo		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
492214501Srpaulo	else
493214501Srpaulo		dbus_connection_send(iface->con, msg, NULL);
494214501Srpaulo
495214501Srpaulo	dbus_message_unref(msg);
496214501Srpaulo}
497214501Srpaulo
498214501Srpaulo
499214501Srpaulo/**
500214501Srpaulo * wpas_dbus_signal_wps_event_m2d - Signals M2D WPS event
501214501Srpaulo * @wpa_s: %wpa_supplicant network interface data
502214501Srpaulo *
503214501Srpaulo * Sends Event dbus signal with name "m2d" and dictionary containing
504214501Srpaulo * fields of wps_event_m2d structure.
505214501Srpaulo */
506214501Srpaulovoid wpas_dbus_signal_wps_event_m2d(struct wpa_supplicant *wpa_s,
507214501Srpaulo				    struct wps_event_m2d *m2d)
508214501Srpaulo{
509214501Srpaulo
510214501Srpaulo	DBusMessage *msg;
511214501Srpaulo	DBusMessageIter iter, dict_iter;
512214501Srpaulo	struct wpas_dbus_priv *iface;
513214501Srpaulo	char *key = "m2d";
514214501Srpaulo
515214501Srpaulo	iface = wpa_s->global->dbus;
516214501Srpaulo
517214501Srpaulo	/* Do nothing if the control interface is not turned on */
518214501Srpaulo	if (iface == NULL)
519214501Srpaulo		return;
520214501Srpaulo
521214501Srpaulo	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
522214501Srpaulo				      WPAS_DBUS_NEW_IFACE_WPS, "Event");
523214501Srpaulo	if (msg == NULL)
524214501Srpaulo		return;
525214501Srpaulo
526214501Srpaulo	dbus_message_iter_init_append(msg, &iter);
527214501Srpaulo
528214501Srpaulo	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
529214501Srpaulo	    !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
530214501Srpaulo	    !wpa_dbus_dict_append_uint16(&dict_iter, "config_methods",
531214501Srpaulo					 m2d->config_methods) ||
532214501Srpaulo	    !wpa_dbus_dict_append_byte_array(&dict_iter, "manufacturer",
533214501Srpaulo					     (const char *) m2d->manufacturer,
534214501Srpaulo					     m2d->manufacturer_len) ||
535214501Srpaulo	    !wpa_dbus_dict_append_byte_array(&dict_iter, "model_name",
536214501Srpaulo					     (const char *) m2d->model_name,
537214501Srpaulo					     m2d->model_name_len) ||
538214501Srpaulo	    !wpa_dbus_dict_append_byte_array(&dict_iter, "model_number",
539214501Srpaulo					     (const char *) m2d->model_number,
540214501Srpaulo					     m2d->model_number_len) ||
541214501Srpaulo	    !wpa_dbus_dict_append_byte_array(&dict_iter, "serial_number",
542214501Srpaulo					     (const char *)
543214501Srpaulo					     m2d->serial_number,
544214501Srpaulo					     m2d->serial_number_len) ||
545214501Srpaulo	    !wpa_dbus_dict_append_byte_array(&dict_iter, "dev_name",
546214501Srpaulo					     (const char *) m2d->dev_name,
547214501Srpaulo					     m2d->dev_name_len) ||
548214501Srpaulo	    !wpa_dbus_dict_append_byte_array(&dict_iter, "primary_dev_type",
549214501Srpaulo					     (const char *)
550214501Srpaulo					     m2d->primary_dev_type, 8) ||
551214501Srpaulo	    !wpa_dbus_dict_append_uint16(&dict_iter, "config_error",
552214501Srpaulo					 m2d->config_error) ||
553214501Srpaulo	    !wpa_dbus_dict_append_uint16(&dict_iter, "dev_password_id",
554214501Srpaulo					 m2d->dev_password_id) ||
555214501Srpaulo	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
556214501Srpaulo		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
557214501Srpaulo	else
558214501Srpaulo		dbus_connection_send(iface->con, msg, NULL);
559214501Srpaulo
560214501Srpaulo	dbus_message_unref(msg);
561214501Srpaulo}
562214501Srpaulo
563214501Srpaulo
564214501Srpaulo/**
565214501Srpaulo * wpas_dbus_signal_wps_cred - Signals new credentials
566214501Srpaulo * @wpa_s: %wpa_supplicant network interface data
567214501Srpaulo *
568214501Srpaulo * Sends signal with credentials in directory argument
569214501Srpaulo */
570214501Srpaulovoid wpas_dbus_signal_wps_cred(struct wpa_supplicant *wpa_s,
571214501Srpaulo			       const struct wps_credential *cred)
572214501Srpaulo{
573214501Srpaulo	DBusMessage *msg;
574214501Srpaulo	DBusMessageIter iter, dict_iter;
575214501Srpaulo	struct wpas_dbus_priv *iface;
576214501Srpaulo	char *auth_type[6]; /* we have six possible authorization types */
577214501Srpaulo	int at_num = 0;
578214501Srpaulo	char *encr_type[4]; /* we have four possible encryption types */
579214501Srpaulo	int et_num = 0;
580214501Srpaulo
581214501Srpaulo	iface = wpa_s->global->dbus;
582214501Srpaulo
583214501Srpaulo	/* Do nothing if the control interface is not turned on */
584214501Srpaulo	if (iface == NULL)
585214501Srpaulo		return;
586214501Srpaulo
587214501Srpaulo	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
588214501Srpaulo				      WPAS_DBUS_NEW_IFACE_WPS,
589214501Srpaulo				      "Credentials");
590214501Srpaulo	if (msg == NULL)
591214501Srpaulo		return;
592214501Srpaulo
593214501Srpaulo	dbus_message_iter_init_append(msg, &iter);
594214501Srpaulo	if (!wpa_dbus_dict_open_write(&iter, &dict_iter))
595214501Srpaulo		goto nomem;
596214501Srpaulo
597214501Srpaulo	if (cred->auth_type & WPS_AUTH_OPEN)
598214501Srpaulo		auth_type[at_num++] = "open";
599214501Srpaulo	if (cred->auth_type & WPS_AUTH_WPAPSK)
600214501Srpaulo		auth_type[at_num++] = "wpa-psk";
601214501Srpaulo	if (cred->auth_type & WPS_AUTH_SHARED)
602214501Srpaulo		auth_type[at_num++] = "shared";
603214501Srpaulo	if (cred->auth_type & WPS_AUTH_WPA)
604214501Srpaulo		auth_type[at_num++] = "wpa-eap";
605214501Srpaulo	if (cred->auth_type & WPS_AUTH_WPA2)
606214501Srpaulo		auth_type[at_num++] = "wpa2-eap";
607214501Srpaulo	if (cred->auth_type & WPS_AUTH_WPA2PSK)
608214501Srpaulo		auth_type[at_num++] =
609214501Srpaulo		"wpa2-psk";
610214501Srpaulo
611214501Srpaulo	if (cred->encr_type & WPS_ENCR_NONE)
612214501Srpaulo		encr_type[et_num++] = "none";
613214501Srpaulo	if (cred->encr_type & WPS_ENCR_WEP)
614214501Srpaulo		encr_type[et_num++] = "wep";
615214501Srpaulo	if (cred->encr_type & WPS_ENCR_TKIP)
616214501Srpaulo		encr_type[et_num++] = "tkip";
617214501Srpaulo	if (cred->encr_type & WPS_ENCR_AES)
618214501Srpaulo		encr_type[et_num++] = "aes";
619214501Srpaulo
620214501Srpaulo	if (wpa_s->current_ssid) {
621214501Srpaulo		if (!wpa_dbus_dict_append_byte_array(
622214501Srpaulo			    &dict_iter, "BSSID",
623214501Srpaulo			    (const char *) wpa_s->current_ssid->bssid,
624214501Srpaulo			    ETH_ALEN))
625214501Srpaulo			goto nomem;
626214501Srpaulo	}
627214501Srpaulo
628214501Srpaulo	if (!wpa_dbus_dict_append_byte_array(&dict_iter, "SSID",
629214501Srpaulo					     (const char *) cred->ssid,
630214501Srpaulo					     cred->ssid_len) ||
631214501Srpaulo	    !wpa_dbus_dict_append_string_array(&dict_iter, "AuthType",
632214501Srpaulo					       (const char **) auth_type,
633214501Srpaulo					       at_num) ||
634214501Srpaulo	    !wpa_dbus_dict_append_string_array(&dict_iter, "EncrType",
635214501Srpaulo					       (const char **) encr_type,
636214501Srpaulo					       et_num) ||
637214501Srpaulo	    !wpa_dbus_dict_append_byte_array(&dict_iter, "Key",
638214501Srpaulo					     (const char *) cred->key,
639214501Srpaulo					     cred->key_len) ||
640214501Srpaulo	    !wpa_dbus_dict_append_uint32(&dict_iter, "KeyIndex",
641214501Srpaulo					 cred->key_idx) ||
642214501Srpaulo	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
643214501Srpaulo		goto nomem;
644214501Srpaulo
645214501Srpaulo	dbus_connection_send(iface->con, msg, NULL);
646214501Srpaulo
647214501Srpaulonomem:
648214501Srpaulo	dbus_message_unref(msg);
649214501Srpaulo}
650214501Srpaulo
651214501Srpaulo#endif /* CONFIG_WPS */
652214501Srpaulo
653214501Srpaulo
654214501Srpaulo/**
655214501Srpaulo * wpas_dbus_signal_prop_changed - Signals change of property
656214501Srpaulo * @wpa_s: %wpa_supplicant network interface data
657214501Srpaulo * @property: indicates which property has changed
658214501Srpaulo *
659214501Srpaulo * Sends ProertyChanged signals with path, interface and arguments
660214501Srpaulo * depending on which property has changed.
661214501Srpaulo */
662214501Srpaulovoid wpas_dbus_signal_prop_changed(struct wpa_supplicant *wpa_s,
663214501Srpaulo				   enum wpas_dbus_prop property)
664214501Srpaulo{
665214501Srpaulo	WPADBusPropertyAccessor getter;
666214501Srpaulo	char *prop;
667214501Srpaulo
668214501Srpaulo	if (wpa_s->dbus_new_path == NULL)
669214501Srpaulo		return; /* Skip signal since D-Bus setup is not yet ready */
670214501Srpaulo
671214501Srpaulo	switch (property) {
672214501Srpaulo	case WPAS_DBUS_PROP_AP_SCAN:
673214501Srpaulo		getter = (WPADBusPropertyAccessor) wpas_dbus_getter_ap_scan;
674214501Srpaulo		prop = "ApScan";
675214501Srpaulo		break;
676214501Srpaulo	case WPAS_DBUS_PROP_SCANNING:
677214501Srpaulo		getter = (WPADBusPropertyAccessor) wpas_dbus_getter_scanning;
678214501Srpaulo		prop = "Scanning";
679214501Srpaulo		break;
680214501Srpaulo	case WPAS_DBUS_PROP_STATE:
681214501Srpaulo		getter = (WPADBusPropertyAccessor) wpas_dbus_getter_state;
682214501Srpaulo		prop = "State";
683214501Srpaulo		break;
684214501Srpaulo	case WPAS_DBUS_PROP_CURRENT_BSS:
685214501Srpaulo		getter = (WPADBusPropertyAccessor)
686214501Srpaulo			wpas_dbus_getter_current_bss;
687214501Srpaulo		prop = "CurrentBSS";
688214501Srpaulo		break;
689214501Srpaulo	case WPAS_DBUS_PROP_CURRENT_NETWORK:
690214501Srpaulo		getter = (WPADBusPropertyAccessor)
691214501Srpaulo			wpas_dbus_getter_current_network;
692214501Srpaulo		prop = "CurrentNetwork";
693214501Srpaulo		break;
694214501Srpaulo	default:
695214501Srpaulo		wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d",
696214501Srpaulo			   __func__, property);
697214501Srpaulo		return;
698214501Srpaulo	}
699214501Srpaulo
700214501Srpaulo	wpa_dbus_mark_property_changed(wpa_s->global->dbus,
701214501Srpaulo				       wpa_s->dbus_new_path,
702214501Srpaulo				       WPAS_DBUS_NEW_IFACE_INTERFACE, prop);
703214501Srpaulo}
704214501Srpaulo
705214501Srpaulo
706214501Srpaulo/**
707214501Srpaulo * wpas_dbus_bss_signal_prop_changed - Signals change of BSS property
708214501Srpaulo * @wpa_s: %wpa_supplicant network interface data
709214501Srpaulo * @property: indicates which property has changed
710214501Srpaulo * @id: unique BSS identifier
711214501Srpaulo *
712214501Srpaulo * Sends PropertyChanged signals with path, interface, and arguments depending
713214501Srpaulo * on which property has changed.
714214501Srpaulo */
715214501Srpaulovoid wpas_dbus_bss_signal_prop_changed(struct wpa_supplicant *wpa_s,
716214501Srpaulo				       enum wpas_dbus_bss_prop property,
717214501Srpaulo				       unsigned int id)
718214501Srpaulo{
719214501Srpaulo	char path[WPAS_DBUS_OBJECT_PATH_MAX];
720214501Srpaulo	char *prop;
721214501Srpaulo
722214501Srpaulo	switch (property) {
723214501Srpaulo	case WPAS_DBUS_BSS_PROP_SIGNAL:
724214501Srpaulo		prop = "Signal";
725214501Srpaulo		break;
726214501Srpaulo	case WPAS_DBUS_BSS_PROP_FREQ:
727214501Srpaulo		prop = "Frequency";
728214501Srpaulo		break;
729214501Srpaulo	case WPAS_DBUS_BSS_PROP_MODE:
730214501Srpaulo		prop = "Mode";
731214501Srpaulo		break;
732214501Srpaulo	case WPAS_DBUS_BSS_PROP_PRIVACY:
733214501Srpaulo		prop = "Privacy";
734214501Srpaulo		break;
735214501Srpaulo	case WPAS_DBUS_BSS_PROP_RATES:
736214501Srpaulo		prop = "Rates";
737214501Srpaulo		break;
738214501Srpaulo	case WPAS_DBUS_BSS_PROP_WPA:
739214501Srpaulo		prop = "WPA";
740214501Srpaulo		break;
741214501Srpaulo	case WPAS_DBUS_BSS_PROP_RSN:
742214501Srpaulo		prop = "RSN";
743214501Srpaulo		break;
744214501Srpaulo	case WPAS_DBUS_BSS_PROP_IES:
745214501Srpaulo		prop = "IEs";
746214501Srpaulo		break;
747214501Srpaulo	default:
748214501Srpaulo		wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d",
749214501Srpaulo			   __func__, property);
750214501Srpaulo		return;
751214501Srpaulo	}
752214501Srpaulo
753214501Srpaulo	os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
754214501Srpaulo		    "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
755214501Srpaulo		    wpa_s->dbus_new_path, id);
756214501Srpaulo
757214501Srpaulo	wpa_dbus_mark_property_changed(wpa_s->global->dbus, path,
758214501Srpaulo				       WPAS_DBUS_NEW_IFACE_BSS, prop);
759214501Srpaulo}
760214501Srpaulo
761214501Srpaulo
762214501Srpaulo/**
763214501Srpaulo * wpas_dbus_signal_debug_level_changed - Signals change of debug param
764214501Srpaulo * @global: wpa_global structure
765214501Srpaulo *
766214501Srpaulo * Sends ProertyChanged signals informing that debug level has changed.
767214501Srpaulo */
768214501Srpaulovoid wpas_dbus_signal_debug_level_changed(struct wpa_global *global)
769214501Srpaulo{
770214501Srpaulo	wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
771214501Srpaulo				       WPAS_DBUS_NEW_INTERFACE,
772214501Srpaulo				       "DebugLevel");
773214501Srpaulo}
774214501Srpaulo
775214501Srpaulo
776214501Srpaulo/**
777214501Srpaulo * wpas_dbus_signal_debug_timestamp_changed - Signals change of debug param
778214501Srpaulo * @global: wpa_global structure
779214501Srpaulo *
780214501Srpaulo * Sends ProertyChanged signals informing that debug timestamp has changed.
781214501Srpaulo */
782214501Srpaulovoid wpas_dbus_signal_debug_timestamp_changed(struct wpa_global *global)
783214501Srpaulo{
784214501Srpaulo	wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
785214501Srpaulo				       WPAS_DBUS_NEW_INTERFACE,
786214501Srpaulo				       "DebugTimestamp");
787214501Srpaulo}
788214501Srpaulo
789214501Srpaulo
790214501Srpaulo/**
791214501Srpaulo * wpas_dbus_signal_debug_show_keys_changed - Signals change of debug param
792214501Srpaulo * @global: wpa_global structure
793214501Srpaulo *
794214501Srpaulo * Sends ProertyChanged signals informing that debug show_keys has changed.
795214501Srpaulo */
796214501Srpaulovoid wpas_dbus_signal_debug_show_keys_changed(struct wpa_global *global)
797214501Srpaulo{
798214501Srpaulo	wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
799214501Srpaulo				       WPAS_DBUS_NEW_INTERFACE,
800214501Srpaulo				       "DebugShowKeys");
801214501Srpaulo}
802214501Srpaulo
803214501Srpaulo
804214501Srpaulostatic void wpas_dbus_register(struct wpa_dbus_object_desc *obj_desc,
805214501Srpaulo			       void *priv,
806214501Srpaulo			       WPADBusArgumentFreeFunction priv_free,
807214501Srpaulo			       const struct wpa_dbus_method_desc *methods,
808214501Srpaulo			       const struct wpa_dbus_property_desc *properties,
809214501Srpaulo			       const struct wpa_dbus_signal_desc *signals)
810214501Srpaulo{
811214501Srpaulo	int n;
812214501Srpaulo
813214501Srpaulo	obj_desc->user_data = priv;
814214501Srpaulo	obj_desc->user_data_free_func = priv_free;
815214501Srpaulo	obj_desc->methods = methods;
816214501Srpaulo	obj_desc->properties = properties;
817214501Srpaulo	obj_desc->signals = signals;
818214501Srpaulo
819214501Srpaulo	for (n = 0; properties && properties->dbus_property; properties++)
820214501Srpaulo		n++;
821214501Srpaulo
822214501Srpaulo	obj_desc->prop_changed_flags = os_zalloc(n);
823214501Srpaulo	if (!obj_desc->prop_changed_flags)
824214501Srpaulo		wpa_printf(MSG_DEBUG, "dbus: %s: can't register handlers",
825214501Srpaulo			   __func__);
826214501Srpaulo}
827214501Srpaulo
828214501Srpaulo
829214501Srpaulostatic const struct wpa_dbus_method_desc wpas_dbus_global_methods[] = {
830214501Srpaulo	{ "CreateInterface", WPAS_DBUS_NEW_INTERFACE,
831214501Srpaulo	  (WPADBusMethodHandler) &wpas_dbus_handler_create_interface,
832214501Srpaulo	  {
833214501Srpaulo		  { "args", "a{sv}", ARG_IN },
834214501Srpaulo		  { "path", "o", ARG_OUT },
835214501Srpaulo		  END_ARGS
836214501Srpaulo	  }
837214501Srpaulo	},
838214501Srpaulo	{ "RemoveInterface", WPAS_DBUS_NEW_INTERFACE,
839214501Srpaulo	  (WPADBusMethodHandler) &wpas_dbus_handler_remove_interface,
840214501Srpaulo	  {
841214501Srpaulo		  { "path", "o", ARG_IN },
842214501Srpaulo		  END_ARGS
843214501Srpaulo	  }
844214501Srpaulo	},
845214501Srpaulo	{ "GetInterface", WPAS_DBUS_NEW_INTERFACE,
846214501Srpaulo	  (WPADBusMethodHandler) &wpas_dbus_handler_get_interface,
847214501Srpaulo	  {
848214501Srpaulo		  { "ifname", "s", ARG_IN },
849214501Srpaulo		  { "path", "o", ARG_OUT },
850214501Srpaulo		  END_ARGS
851214501Srpaulo	  }
852214501Srpaulo	},
853214501Srpaulo	{ NULL, NULL, NULL, { END_ARGS } }
854214501Srpaulo};
855214501Srpaulo
856214501Srpaulostatic const struct wpa_dbus_property_desc wpas_dbus_global_properties[] = {
857214501Srpaulo	{ "DebugLevel", WPAS_DBUS_NEW_INTERFACE, "s",
858214501Srpaulo	  (WPADBusPropertyAccessor) wpas_dbus_getter_debug_level,
859214501Srpaulo	  (WPADBusPropertyAccessor) wpas_dbus_setter_debug_level,
860214501Srpaulo	  RW
861214501Srpaulo	},
862214501Srpaulo	{ "DebugTimestamp", WPAS_DBUS_NEW_INTERFACE, "b",
863214501Srpaulo	  (WPADBusPropertyAccessor) wpas_dbus_getter_debug_timestamp,
864214501Srpaulo	  (WPADBusPropertyAccessor) wpas_dbus_setter_debug_timestamp,
865214501Srpaulo	  RW
866214501Srpaulo	},
867214501Srpaulo	{ "DebugShowKeys", WPAS_DBUS_NEW_INTERFACE, "b",
868214501Srpaulo	  (WPADBusPropertyAccessor) wpas_dbus_getter_debug_show_keys,
869214501Srpaulo	  (WPADBusPropertyAccessor) wpas_dbus_setter_debug_show_keys,
870214501Srpaulo	  RW
871214501Srpaulo	},
872214501Srpaulo	{ "Interfaces", WPAS_DBUS_NEW_INTERFACE, "ao",
873214501Srpaulo	  (WPADBusPropertyAccessor) &wpas_dbus_getter_interfaces,
874214501Srpaulo	  NULL,
875214501Srpaulo	  R
876214501Srpaulo	},
877214501Srpaulo	{ "EapMethods", WPAS_DBUS_NEW_INTERFACE, "as",
878214501Srpaulo	  (WPADBusPropertyAccessor) wpas_dbus_getter_eap_methods,
879214501Srpaulo	  NULL,
880214501Srpaulo	  R
881214501Srpaulo	},
882214501Srpaulo	{ NULL, NULL, NULL, NULL, NULL, 0 }
883214501Srpaulo};
884214501Srpaulo
885214501Srpaulostatic const struct wpa_dbus_signal_desc wpas_dbus_global_signals[] = {
886214501Srpaulo	{ "InterfaceAdded", WPAS_DBUS_NEW_INTERFACE,
887214501Srpaulo	  {
888214501Srpaulo		  { "path", "o", ARG_OUT },
889214501Srpaulo		  { "properties", "a{sv}", ARG_OUT },
890214501Srpaulo		  END_ARGS
891214501Srpaulo	  }
892214501Srpaulo	},
893214501Srpaulo	{ "InterfaceRemoved", WPAS_DBUS_NEW_INTERFACE,
894214501Srpaulo	  {
895214501Srpaulo		  { "path", "o", ARG_OUT },
896214501Srpaulo		  END_ARGS
897214501Srpaulo	  }
898214501Srpaulo	},
899214501Srpaulo	{ "PropertiesChanged", WPAS_DBUS_NEW_INTERFACE,
900214501Srpaulo	  {
901214501Srpaulo		  { "properties", "a{sv}", ARG_OUT },
902214501Srpaulo		  END_ARGS
903214501Srpaulo	  }
904214501Srpaulo	},
905214501Srpaulo	{ NULL, NULL, { END_ARGS } }
906214501Srpaulo};
907214501Srpaulo
908214501Srpaulo
909214501Srpaulo/**
910214501Srpaulo * wpas_dbus_ctrl_iface_init - Initialize dbus control interface
911214501Srpaulo * @global: Pointer to global data from wpa_supplicant_init()
912214501Srpaulo * Returns: 0 on success or -1 on failure
913214501Srpaulo *
914214501Srpaulo * Initialize the dbus control interface for wpa_supplicantand and start
915214501Srpaulo * receiving commands from external programs over the bus.
916214501Srpaulo */
917214501Srpauloint wpas_dbus_ctrl_iface_init(struct wpas_dbus_priv *priv)
918214501Srpaulo{
919214501Srpaulo	struct wpa_dbus_object_desc *obj_desc;
920214501Srpaulo	int ret;
921214501Srpaulo
922214501Srpaulo	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
923214501Srpaulo	if (!obj_desc) {
924214501Srpaulo		wpa_printf(MSG_ERROR, "Not enough memory "
925214501Srpaulo			   "to create object description");
926214501Srpaulo		return -1;
927214501Srpaulo	}
928214501Srpaulo
929214501Srpaulo	wpas_dbus_register(obj_desc, priv->global, NULL,
930214501Srpaulo			   wpas_dbus_global_methods,
931214501Srpaulo			   wpas_dbus_global_properties,
932214501Srpaulo			   wpas_dbus_global_signals);
933214501Srpaulo
934214501Srpaulo	wpa_printf(MSG_DEBUG, "dbus: Register D-Bus object '%s'",
935214501Srpaulo		   WPAS_DBUS_NEW_PATH);
936214501Srpaulo	ret = wpa_dbus_ctrl_iface_init(priv, WPAS_DBUS_NEW_PATH,
937214501Srpaulo				       WPAS_DBUS_NEW_SERVICE,
938214501Srpaulo				       obj_desc);
939214501Srpaulo	if (ret < 0)
940214501Srpaulo		free_dbus_object_desc(obj_desc);
941214501Srpaulo	else
942214501Srpaulo		priv->dbus_new_initialized = 1;
943214501Srpaulo
944214501Srpaulo	return ret;
945214501Srpaulo}
946214501Srpaulo
947214501Srpaulo
948214501Srpaulo/**
949214501Srpaulo * wpas_dbus_ctrl_iface_deinit - Deinitialize dbus ctrl interface for
950214501Srpaulo * wpa_supplicant
951214501Srpaulo * @iface: Pointer to dbus private data from wpas_dbus_init()
952214501Srpaulo *
953214501Srpaulo * Deinitialize the dbus control interface that was initialized with
954214501Srpaulo * wpas_dbus_ctrl_iface_init().
955214501Srpaulo */
956214501Srpaulovoid wpas_dbus_ctrl_iface_deinit(struct wpas_dbus_priv *iface)
957214501Srpaulo{
958214501Srpaulo	if (!iface->dbus_new_initialized)
959214501Srpaulo		return;
960214501Srpaulo	wpa_printf(MSG_DEBUG, "dbus: Unregister D-Bus object '%s'",
961214501Srpaulo		   WPAS_DBUS_NEW_PATH);
962214501Srpaulo	dbus_connection_unregister_object_path(iface->con,
963214501Srpaulo					       WPAS_DBUS_NEW_PATH);
964214501Srpaulo}
965214501Srpaulo
966214501Srpaulo
967214501Srpaulostatic void wpa_dbus_free(void *ptr)
968214501Srpaulo{
969214501Srpaulo	os_free(ptr);
970214501Srpaulo}
971214501Srpaulo
972214501Srpaulo
973214501Srpaulostatic const struct wpa_dbus_property_desc wpas_dbus_network_properties[] = {
974214501Srpaulo	{ "Properties", WPAS_DBUS_NEW_IFACE_NETWORK, "a{sv}",
975214501Srpaulo	  (WPADBusPropertyAccessor) wpas_dbus_getter_network_properties,
976214501Srpaulo	  (WPADBusPropertyAccessor) wpas_dbus_setter_network_properties,
977214501Srpaulo	  RW
978214501Srpaulo	},
979214501Srpaulo	{ "Enabled", WPAS_DBUS_NEW_IFACE_NETWORK, "b",
980214501Srpaulo	  (WPADBusPropertyAccessor) wpas_dbus_getter_enabled,
981214501Srpaulo	  (WPADBusPropertyAccessor) wpas_dbus_setter_enabled,
982214501Srpaulo	  RW
983214501Srpaulo	},
984214501Srpaulo	{ NULL, NULL, NULL, NULL, NULL, 0 }
985214501Srpaulo};
986214501Srpaulo
987214501Srpaulo
988214501Srpaulostatic const struct wpa_dbus_signal_desc wpas_dbus_network_signals[] = {
989214501Srpaulo	{ "PropertiesChanged", WPAS_DBUS_NEW_IFACE_NETWORK,
990214501Srpaulo	  {
991214501Srpaulo		  { "properties", "a{sv}", ARG_OUT },
992214501Srpaulo		  END_ARGS
993214501Srpaulo	  }
994214501Srpaulo	},
995214501Srpaulo	{ NULL, NULL, { END_ARGS } }
996214501Srpaulo};
997214501Srpaulo
998214501Srpaulo
999214501Srpaulo/**
1000214501Srpaulo * wpas_dbus_register_network - Register a configured network with dbus
1001214501Srpaulo * @wpa_s: wpa_supplicant interface structure
1002214501Srpaulo * @ssid: network configuration data
1003214501Srpaulo * Returns: 0 on success, -1 on failure
1004214501Srpaulo *
1005214501Srpaulo * Registers network representing object with dbus
1006214501Srpaulo */
1007214501Srpauloint wpas_dbus_register_network(struct wpa_supplicant *wpa_s,
1008214501Srpaulo			       struct wpa_ssid *ssid)
1009214501Srpaulo{
1010214501Srpaulo	struct wpas_dbus_priv *ctrl_iface;
1011214501Srpaulo	struct wpa_dbus_object_desc *obj_desc;
1012214501Srpaulo	struct network_handler_args *arg;
1013214501Srpaulo	char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
1014214501Srpaulo
1015214501Srpaulo	/* Do nothing if the control interface is not turned on */
1016214501Srpaulo	if (wpa_s == NULL || wpa_s->global == NULL)
1017214501Srpaulo		return 0;
1018214501Srpaulo	ctrl_iface = wpa_s->global->dbus;
1019214501Srpaulo	if (ctrl_iface == NULL)
1020214501Srpaulo		return 0;
1021214501Srpaulo
1022214501Srpaulo	os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1023214501Srpaulo		    "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
1024214501Srpaulo		    wpa_s->dbus_new_path, ssid->id);
1025214501Srpaulo
1026214501Srpaulo	wpa_printf(MSG_DEBUG, "dbus: Register network object '%s'",
1027214501Srpaulo		   net_obj_path);
1028214501Srpaulo	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
1029214501Srpaulo	if (!obj_desc) {
1030214501Srpaulo		wpa_printf(MSG_ERROR, "Not enough memory "
1031214501Srpaulo			   "to create object description");
1032214501Srpaulo		goto err;
1033214501Srpaulo	}
1034214501Srpaulo
1035214501Srpaulo	/* allocate memory for handlers arguments */
1036214501Srpaulo	arg = os_zalloc(sizeof(struct network_handler_args));
1037214501Srpaulo	if (!arg) {
1038214501Srpaulo		wpa_printf(MSG_ERROR, "Not enough memory "
1039214501Srpaulo			   "to create arguments for method");
1040214501Srpaulo		goto err;
1041214501Srpaulo	}
1042214501Srpaulo
1043214501Srpaulo	arg->wpa_s = wpa_s;
1044214501Srpaulo	arg->ssid = ssid;
1045214501Srpaulo
1046214501Srpaulo	wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
1047214501Srpaulo			   wpas_dbus_network_properties,
1048214501Srpaulo			   wpas_dbus_network_signals);
1049214501Srpaulo
1050214501Srpaulo	if (wpa_dbus_register_object_per_iface(ctrl_iface, net_obj_path,
1051214501Srpaulo					       wpa_s->ifname, obj_desc))
1052214501Srpaulo		goto err;
1053214501Srpaulo
1054214501Srpaulo	wpas_dbus_signal_network_added(wpa_s, ssid->id);
1055214501Srpaulo
1056214501Srpaulo	return 0;
1057214501Srpaulo
1058214501Srpauloerr:
1059214501Srpaulo	free_dbus_object_desc(obj_desc);
1060214501Srpaulo	return -1;
1061214501Srpaulo}
1062214501Srpaulo
1063214501Srpaulo
1064214501Srpaulo/**
1065214501Srpaulo * wpas_dbus_unregister_network - Unregister a configured network from dbus
1066214501Srpaulo * @wpa_s: wpa_supplicant interface structure
1067214501Srpaulo * @nid: network id
1068214501Srpaulo * Returns: 0 on success, -1 on failure
1069214501Srpaulo *
1070214501Srpaulo * Unregisters network representing object from dbus
1071214501Srpaulo */
1072214501Srpauloint wpas_dbus_unregister_network(struct wpa_supplicant *wpa_s, int nid)
1073214501Srpaulo{
1074214501Srpaulo	struct wpas_dbus_priv *ctrl_iface;
1075214501Srpaulo	char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
1076214501Srpaulo	int ret;
1077214501Srpaulo
1078214501Srpaulo	/* Do nothing if the control interface is not turned on */
1079214501Srpaulo	if (wpa_s == NULL || wpa_s->global == NULL ||
1080214501Srpaulo	    wpa_s->dbus_new_path == NULL)
1081214501Srpaulo		return 0;
1082214501Srpaulo	ctrl_iface = wpa_s->global->dbus;
1083214501Srpaulo	if (ctrl_iface == NULL)
1084214501Srpaulo		return 0;
1085214501Srpaulo
1086214501Srpaulo	os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1087214501Srpaulo		    "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
1088214501Srpaulo		    wpa_s->dbus_new_path, nid);
1089214501Srpaulo
1090214501Srpaulo	wpa_printf(MSG_DEBUG, "dbus: Unregister network object '%s'",
1091214501Srpaulo		   net_obj_path);
1092214501Srpaulo	ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, net_obj_path);
1093214501Srpaulo
1094214501Srpaulo	if (!ret)
1095214501Srpaulo		wpas_dbus_signal_network_removed(wpa_s, nid);
1096214501Srpaulo
1097214501Srpaulo	return ret;
1098214501Srpaulo}
1099214501Srpaulo
1100214501Srpaulo
1101214501Srpaulostatic const struct wpa_dbus_property_desc wpas_dbus_bss_properties[] = {
1102214501Srpaulo	{ "SSID", WPAS_DBUS_NEW_IFACE_BSS, "ay",
1103214501Srpaulo	  (WPADBusPropertyAccessor) wpas_dbus_getter_bss_ssid,
1104214501Srpaulo	  NULL,
1105214501Srpaulo	  R
1106214501Srpaulo	},
1107214501Srpaulo	{ "BSSID", WPAS_DBUS_NEW_IFACE_BSS, "ay",
1108214501Srpaulo	  (WPADBusPropertyAccessor) wpas_dbus_getter_bss_bssid,
1109214501Srpaulo	  NULL,
1110214501Srpaulo	  R
1111214501Srpaulo	},
1112214501Srpaulo	{ "Privacy", WPAS_DBUS_NEW_IFACE_BSS, "b",
1113214501Srpaulo	  (WPADBusPropertyAccessor) wpas_dbus_getter_bss_privacy,
1114214501Srpaulo	  NULL,
1115214501Srpaulo	  R
1116214501Srpaulo	},
1117214501Srpaulo	{ "Mode", WPAS_DBUS_NEW_IFACE_BSS, "s",
1118214501Srpaulo	  (WPADBusPropertyAccessor) wpas_dbus_getter_bss_mode,
1119214501Srpaulo	  NULL,
1120214501Srpaulo	  R
1121214501Srpaulo	},
1122214501Srpaulo	{ "Signal", WPAS_DBUS_NEW_IFACE_BSS, "n",
1123214501Srpaulo	  (WPADBusPropertyAccessor) wpas_dbus_getter_bss_signal,
1124214501Srpaulo	  NULL,
1125214501Srpaulo	  R
1126214501Srpaulo	},
1127214501Srpaulo	{ "Frequency", WPAS_DBUS_NEW_IFACE_BSS, "q",
1128214501Srpaulo	  (WPADBusPropertyAccessor) wpas_dbus_getter_bss_frequency,
1129214501Srpaulo	  NULL,
1130214501Srpaulo	  R
1131214501Srpaulo	},
1132214501Srpaulo	{ "Rates", WPAS_DBUS_NEW_IFACE_BSS, "au",
1133214501Srpaulo	  (WPADBusPropertyAccessor) wpas_dbus_getter_bss_rates,
1134214501Srpaulo	  NULL,
1135214501Srpaulo	  R
1136214501Srpaulo	},
1137214501Srpaulo	{ "WPA", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
1138214501Srpaulo	  (WPADBusPropertyAccessor) wpas_dbus_getter_bss_wpa,
1139214501Srpaulo	  NULL,
1140214501Srpaulo	  R
1141214501Srpaulo	},
1142214501Srpaulo	{ "RSN", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
1143214501Srpaulo	  (WPADBusPropertyAccessor) wpas_dbus_getter_bss_rsn,
1144214501Srpaulo	  NULL,
1145214501Srpaulo	  R
1146214501Srpaulo	},
1147214501Srpaulo	{ "IEs", WPAS_DBUS_NEW_IFACE_BSS, "ay",
1148214501Srpaulo	  (WPADBusPropertyAccessor) wpas_dbus_getter_bss_ies,
1149214501Srpaulo	  NULL,
1150214501Srpaulo	  R
1151214501Srpaulo	},
1152214501Srpaulo	{ NULL, NULL, NULL, NULL, NULL, 0 }
1153214501Srpaulo};
1154214501Srpaulo
1155214501Srpaulo
1156214501Srpaulostatic const struct wpa_dbus_signal_desc wpas_dbus_bss_signals[] = {
1157214501Srpaulo	{ "PropertiesChanged", WPAS_DBUS_NEW_IFACE_BSS,
1158214501Srpaulo	  {
1159214501Srpaulo		  { "properties", "a{sv}", ARG_OUT },
1160214501Srpaulo		  END_ARGS
1161214501Srpaulo	  }
1162214501Srpaulo	},
1163214501Srpaulo	{ NULL, NULL, { END_ARGS } }
1164214501Srpaulo};
1165214501Srpaulo
1166214501Srpaulo
1167214501Srpaulo/**
1168214501Srpaulo * wpas_dbus_unregister_bss - Unregister a scanned BSS from dbus
1169214501Srpaulo * @wpa_s: wpa_supplicant interface structure
1170214501Srpaulo * @bssid: scanned network bssid
1171214501Srpaulo * @id: unique BSS identifier
1172214501Srpaulo * Returns: 0 on success, -1 on failure
1173214501Srpaulo *
1174214501Srpaulo * Unregisters BSS representing object from dbus
1175214501Srpaulo */
1176214501Srpauloint wpas_dbus_unregister_bss(struct wpa_supplicant *wpa_s,
1177214501Srpaulo			     u8 bssid[ETH_ALEN], unsigned int id)
1178214501Srpaulo{
1179214501Srpaulo	struct wpas_dbus_priv *ctrl_iface;
1180214501Srpaulo	char bss_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
1181214501Srpaulo
1182214501Srpaulo	/* Do nothing if the control interface is not turned on */
1183214501Srpaulo	if (wpa_s == NULL || wpa_s->global == NULL)
1184214501Srpaulo		return 0;
1185214501Srpaulo	ctrl_iface = wpa_s->global->dbus;
1186214501Srpaulo	if (ctrl_iface == NULL)
1187214501Srpaulo		return 0;
1188214501Srpaulo
1189214501Srpaulo	os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1190214501Srpaulo		    "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
1191214501Srpaulo		    wpa_s->dbus_new_path, id);
1192214501Srpaulo
1193214501Srpaulo	wpa_printf(MSG_DEBUG, "dbus: Unregister BSS object '%s'",
1194214501Srpaulo		   bss_obj_path);
1195214501Srpaulo	if (wpa_dbus_unregister_object_per_iface(ctrl_iface, bss_obj_path)) {
1196214501Srpaulo		wpa_printf(MSG_ERROR, "dbus: Cannot unregister BSS object %s",
1197214501Srpaulo			   bss_obj_path);
1198214501Srpaulo		return -1;
1199214501Srpaulo	}
1200214501Srpaulo
1201214501Srpaulo	wpas_dbus_signal_bss_removed(wpa_s, bss_obj_path);
1202214501Srpaulo
1203214501Srpaulo	return 0;
1204214501Srpaulo}
1205214501Srpaulo
1206214501Srpaulo
1207214501Srpaulo/**
1208214501Srpaulo * wpas_dbus_register_bss - Register a scanned BSS with dbus
1209214501Srpaulo * @wpa_s: wpa_supplicant interface structure
1210214501Srpaulo * @bssid: scanned network bssid
1211214501Srpaulo * @id: unique BSS identifier
1212214501Srpaulo * Returns: 0 on success, -1 on failure
1213214501Srpaulo *
1214214501Srpaulo * Registers BSS representing object with dbus
1215214501Srpaulo */
1216214501Srpauloint wpas_dbus_register_bss(struct wpa_supplicant *wpa_s,
1217214501Srpaulo			   u8 bssid[ETH_ALEN], unsigned int id)
1218214501Srpaulo{
1219214501Srpaulo	struct wpas_dbus_priv *ctrl_iface;
1220214501Srpaulo	struct wpa_dbus_object_desc *obj_desc;
1221214501Srpaulo	char bss_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
1222214501Srpaulo	struct bss_handler_args *arg;
1223214501Srpaulo
1224214501Srpaulo	/* Do nothing if the control interface is not turned on */
1225214501Srpaulo	if (wpa_s == NULL || wpa_s->global == NULL)
1226214501Srpaulo		return 0;
1227214501Srpaulo	ctrl_iface = wpa_s->global->dbus;
1228214501Srpaulo	if (ctrl_iface == NULL)
1229214501Srpaulo		return 0;
1230214501Srpaulo
1231214501Srpaulo	os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1232214501Srpaulo		    "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
1233214501Srpaulo		    wpa_s->dbus_new_path, id);
1234214501Srpaulo
1235214501Srpaulo	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
1236214501Srpaulo	if (!obj_desc) {
1237214501Srpaulo		wpa_printf(MSG_ERROR, "Not enough memory "
1238214501Srpaulo			   "to create object description");
1239214501Srpaulo		goto err;
1240214501Srpaulo	}
1241214501Srpaulo
1242214501Srpaulo	arg = os_zalloc(sizeof(struct bss_handler_args));
1243214501Srpaulo	if (!arg) {
1244214501Srpaulo		wpa_printf(MSG_ERROR, "Not enough memory "
1245214501Srpaulo			   "to create arguments for handler");
1246214501Srpaulo		goto err;
1247214501Srpaulo	}
1248214501Srpaulo	arg->wpa_s = wpa_s;
1249214501Srpaulo	arg->id = id;
1250214501Srpaulo
1251214501Srpaulo	wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
1252214501Srpaulo			   wpas_dbus_bss_properties,
1253214501Srpaulo			   wpas_dbus_bss_signals);
1254214501Srpaulo
1255214501Srpaulo	wpa_printf(MSG_DEBUG, "dbus: Register BSS object '%s'",
1256214501Srpaulo		   bss_obj_path);
1257214501Srpaulo	if (wpa_dbus_register_object_per_iface(ctrl_iface, bss_obj_path,
1258214501Srpaulo					       wpa_s->ifname, obj_desc)) {
1259214501Srpaulo		wpa_printf(MSG_ERROR,
1260214501Srpaulo			   "Cannot register BSSID dbus object %s.",
1261214501Srpaulo			   bss_obj_path);
1262214501Srpaulo		goto err;
1263214501Srpaulo	}
1264214501Srpaulo
1265214501Srpaulo	wpas_dbus_signal_bss_added(wpa_s, bss_obj_path);
1266214501Srpaulo
1267214501Srpaulo	return 0;
1268214501Srpaulo
1269214501Srpauloerr:
1270214501Srpaulo	free_dbus_object_desc(obj_desc);
1271214501Srpaulo	return -1;
1272214501Srpaulo}
1273214501Srpaulo
1274214501Srpaulo
1275214501Srpaulostatic const struct wpa_dbus_method_desc wpas_dbus_interface_methods[] = {
1276214501Srpaulo	{ "Scan", WPAS_DBUS_NEW_IFACE_INTERFACE,
1277214501Srpaulo	  (WPADBusMethodHandler) &wpas_dbus_handler_scan,
1278214501Srpaulo	  {
1279214501Srpaulo		  { "args", "a{sv}", ARG_IN },
1280214501Srpaulo		  END_ARGS
1281214501Srpaulo	  }
1282214501Srpaulo	},
1283214501Srpaulo	{ "Disconnect", WPAS_DBUS_NEW_IFACE_INTERFACE,
1284214501Srpaulo	  (WPADBusMethodHandler) &wpas_dbus_handler_disconnect,
1285214501Srpaulo	  {
1286214501Srpaulo		  END_ARGS
1287214501Srpaulo	  }
1288214501Srpaulo	},
1289214501Srpaulo	{ "AddNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
1290214501Srpaulo	  (WPADBusMethodHandler) &wpas_dbus_handler_add_network,
1291214501Srpaulo	  {
1292214501Srpaulo		  { "args", "a{sv}", ARG_IN },
1293214501Srpaulo		  { "path", "o", ARG_OUT },
1294214501Srpaulo		  END_ARGS
1295214501Srpaulo	  }
1296214501Srpaulo	},
1297214501Srpaulo	{ "RemoveNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
1298214501Srpaulo	  (WPADBusMethodHandler) &wpas_dbus_handler_remove_network,
1299214501Srpaulo	  {
1300214501Srpaulo		  { "path", "o", ARG_IN },
1301214501Srpaulo		  END_ARGS
1302214501Srpaulo	  }
1303214501Srpaulo	},
1304214501Srpaulo	{ "SelectNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
1305214501Srpaulo	  (WPADBusMethodHandler) &wpas_dbus_handler_select_network,
1306214501Srpaulo	  {
1307214501Srpaulo		  { "path", "o", ARG_IN },
1308214501Srpaulo		  END_ARGS
1309214501Srpaulo	  }
1310214501Srpaulo	},
1311214501Srpaulo	{ "AddBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
1312214501Srpaulo	  (WPADBusMethodHandler) &wpas_dbus_handler_add_blob,
1313214501Srpaulo	  {
1314214501Srpaulo		  { "name", "s", ARG_IN },
1315214501Srpaulo		  { "data", "ay", ARG_IN },
1316214501Srpaulo		  END_ARGS
1317214501Srpaulo	  }
1318214501Srpaulo	},
1319214501Srpaulo	{ "GetBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
1320214501Srpaulo	  (WPADBusMethodHandler) &wpas_dbus_handler_get_blob,
1321214501Srpaulo	  {
1322214501Srpaulo		  { "name", "s", ARG_IN },
1323214501Srpaulo		  { "data", "ay", ARG_OUT },
1324214501Srpaulo		  END_ARGS
1325214501Srpaulo	  }
1326214501Srpaulo	},
1327214501Srpaulo	{ "RemoveBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
1328214501Srpaulo	  (WPADBusMethodHandler) &wpas_dbus_handler_remove_blob,
1329214501Srpaulo	  {
1330214501Srpaulo		  { "name", "s", ARG_IN },
1331214501Srpaulo		  END_ARGS
1332214501Srpaulo	  }
1333214501Srpaulo	},
1334214501Srpaulo#ifdef CONFIG_WPS
1335214501Srpaulo	{ "Start", WPAS_DBUS_NEW_IFACE_WPS,
1336214501Srpaulo	  (WPADBusMethodHandler) &wpas_dbus_handler_wps_start,
1337214501Srpaulo	  {
1338214501Srpaulo		  { "args", "a{sv}", ARG_IN },
1339214501Srpaulo		  { "output", "a{sv}", ARG_OUT },
1340214501Srpaulo		  END_ARGS
1341214501Srpaulo	  }
1342214501Srpaulo	},
1343214501Srpaulo#endif /* CONFIG_WPS */
1344214501Srpaulo	{ NULL, NULL, NULL, { END_ARGS } }
1345214501Srpaulo};
1346214501Srpaulo
1347214501Srpaulostatic const struct wpa_dbus_property_desc wpas_dbus_interface_properties[] = {
1348214501Srpaulo	{ "Capabilities", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{sv}",
1349214501Srpaulo	  (WPADBusPropertyAccessor) wpas_dbus_getter_capabilities,
1350214501Srpaulo	  NULL, R
1351214501Srpaulo	},
1352214501Srpaulo	{ "State", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
1353214501Srpaulo	  (WPADBusPropertyAccessor) wpas_dbus_getter_state,
1354214501Srpaulo	  NULL, R
1355214501Srpaulo	},
1356214501Srpaulo	{ "Scanning", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
1357214501Srpaulo	  (WPADBusPropertyAccessor) wpas_dbus_getter_scanning,
1358214501Srpaulo	  NULL, R
1359214501Srpaulo	},
1360214501Srpaulo	{ "ApScan", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
1361214501Srpaulo	  (WPADBusPropertyAccessor) wpas_dbus_getter_ap_scan,
1362214501Srpaulo	  (WPADBusPropertyAccessor) wpas_dbus_setter_ap_scan,
1363214501Srpaulo	  RW
1364214501Srpaulo	},
1365214501Srpaulo	{ "Ifname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
1366214501Srpaulo	  (WPADBusPropertyAccessor) wpas_dbus_getter_ifname,
1367214501Srpaulo	  NULL, R
1368214501Srpaulo	},
1369214501Srpaulo	{ "Driver", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
1370214501Srpaulo	  (WPADBusPropertyAccessor) wpas_dbus_getter_driver,
1371214501Srpaulo	  NULL, R
1372214501Srpaulo	},
1373214501Srpaulo	{ "BridgeIfname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
1374214501Srpaulo	  (WPADBusPropertyAccessor) wpas_dbus_getter_bridge_ifname,
1375214501Srpaulo	  NULL, R
1376214501Srpaulo	},
1377214501Srpaulo	{ "CurrentBSS", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
1378214501Srpaulo	  (WPADBusPropertyAccessor) wpas_dbus_getter_current_bss,
1379214501Srpaulo	  NULL, R
1380214501Srpaulo	},
1381214501Srpaulo	{ "CurrentNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
1382214501Srpaulo	  (WPADBusPropertyAccessor) wpas_dbus_getter_current_network,
1383214501Srpaulo	  NULL, R
1384214501Srpaulo	},
1385214501Srpaulo	{ "Blobs", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{say}",
1386214501Srpaulo	  (WPADBusPropertyAccessor) wpas_dbus_getter_blobs,
1387214501Srpaulo	  NULL, R
1388214501Srpaulo	},
1389214501Srpaulo	{ "BSSs", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
1390214501Srpaulo	  (WPADBusPropertyAccessor) wpas_dbus_getter_bsss,
1391214501Srpaulo	  NULL, R
1392214501Srpaulo	},
1393214501Srpaulo	{ "Networks", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
1394214501Srpaulo	  (WPADBusPropertyAccessor) wpas_dbus_getter_networks,
1395214501Srpaulo	  NULL, R
1396214501Srpaulo	},
1397214501Srpaulo#ifdef CONFIG_WPS
1398214501Srpaulo	{ "ProcessCredentials", WPAS_DBUS_NEW_IFACE_WPS, "b",
1399214501Srpaulo	  (WPADBusPropertyAccessor) wpas_dbus_getter_process_credentials,
1400214501Srpaulo	  (WPADBusPropertyAccessor) wpas_dbus_setter_process_credentials,
1401214501Srpaulo	  RW
1402214501Srpaulo	},
1403214501Srpaulo#endif /* CONFIG_WPS */
1404214501Srpaulo	{ NULL, NULL, NULL, NULL, NULL, 0 }
1405214501Srpaulo};
1406214501Srpaulo
1407214501Srpaulostatic const struct wpa_dbus_signal_desc wpas_dbus_interface_signals[] = {
1408214501Srpaulo	{ "ScanDone", WPAS_DBUS_NEW_IFACE_INTERFACE,
1409214501Srpaulo	  {
1410214501Srpaulo		  { "success", "b", ARG_OUT },
1411214501Srpaulo		  END_ARGS
1412214501Srpaulo	  }
1413214501Srpaulo	},
1414214501Srpaulo	{ "BSSAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
1415214501Srpaulo	  {
1416214501Srpaulo		  { "path", "o", ARG_OUT },
1417214501Srpaulo		  { "properties", "a{sv}", ARG_OUT },
1418214501Srpaulo		  END_ARGS
1419214501Srpaulo	  }
1420214501Srpaulo	},
1421214501Srpaulo	{ "BSSRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
1422214501Srpaulo	  {
1423214501Srpaulo		  { "path", "o", ARG_OUT },
1424214501Srpaulo		  END_ARGS
1425214501Srpaulo	  }
1426214501Srpaulo	},
1427214501Srpaulo	{ "BlobAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
1428214501Srpaulo	  {
1429214501Srpaulo		  { "name", "s", ARG_OUT },
1430214501Srpaulo		  END_ARGS
1431214501Srpaulo	  }
1432214501Srpaulo	},
1433214501Srpaulo	{ "BlobRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
1434214501Srpaulo	  {
1435214501Srpaulo		  { "name", "s", ARG_OUT },
1436214501Srpaulo		  END_ARGS
1437214501Srpaulo	  }
1438214501Srpaulo	},
1439214501Srpaulo	{ "NetworkAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
1440214501Srpaulo	  {
1441214501Srpaulo		  { "path", "o", ARG_OUT },
1442214501Srpaulo		  { "properties", "a{sv}", ARG_OUT },
1443214501Srpaulo		  END_ARGS
1444214501Srpaulo	  }
1445214501Srpaulo	},
1446214501Srpaulo	{ "NetworkRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
1447214501Srpaulo	  {
1448214501Srpaulo		  { "path", "o", ARG_OUT },
1449214501Srpaulo		  END_ARGS
1450214501Srpaulo	  }
1451214501Srpaulo	},
1452214501Srpaulo	{ "NetworkSelected", WPAS_DBUS_NEW_IFACE_INTERFACE,
1453214501Srpaulo	  {
1454214501Srpaulo		  { "path", "o", ARG_OUT },
1455214501Srpaulo		  END_ARGS
1456214501Srpaulo	  }
1457214501Srpaulo	},
1458214501Srpaulo	{ "PropertiesChanged", WPAS_DBUS_NEW_IFACE_INTERFACE,
1459214501Srpaulo	  {
1460214501Srpaulo		  { "properties", "a{sv}", ARG_OUT },
1461214501Srpaulo		  END_ARGS
1462214501Srpaulo	  }
1463214501Srpaulo	},
1464214501Srpaulo#ifdef CONFIG_WPS
1465214501Srpaulo	{ "Event", WPAS_DBUS_NEW_IFACE_WPS,
1466214501Srpaulo	  {
1467214501Srpaulo		  { "name", "s", ARG_OUT },
1468214501Srpaulo		  { "args", "a{sv}", ARG_OUT },
1469214501Srpaulo		  END_ARGS
1470214501Srpaulo	  }
1471214501Srpaulo	},
1472214501Srpaulo	{ "Credentials", WPAS_DBUS_NEW_IFACE_WPS,
1473214501Srpaulo	  {
1474214501Srpaulo		  { "credentials", "a{sv}", ARG_OUT },
1475214501Srpaulo		  END_ARGS
1476214501Srpaulo	  }
1477214501Srpaulo	},
1478214501Srpaulo	{ "PropertiesChanged", WPAS_DBUS_NEW_IFACE_WPS,
1479214501Srpaulo	  {
1480214501Srpaulo		  { "properties", "a{sv}", ARG_OUT },
1481214501Srpaulo		  END_ARGS
1482214501Srpaulo	  }
1483214501Srpaulo	},
1484214501Srpaulo#endif /* CONFIG_WPS */
1485214501Srpaulo	{ NULL, NULL, { END_ARGS } }
1486214501Srpaulo};
1487214501Srpaulo
1488214501Srpaulo
1489214501Srpauloint wpas_dbus_register_interface(struct wpa_supplicant *wpa_s)
1490214501Srpaulo{
1491214501Srpaulo
1492214501Srpaulo	struct wpa_dbus_object_desc *obj_desc = NULL;
1493214501Srpaulo	struct wpas_dbus_priv *ctrl_iface = wpa_s->global->dbus;
1494214501Srpaulo	int next;
1495214501Srpaulo
1496214501Srpaulo	/* Do nothing if the control interface is not turned on */
1497214501Srpaulo	if (ctrl_iface == NULL)
1498214501Srpaulo		return 0;
1499214501Srpaulo
1500214501Srpaulo	/* Create and set the interface's object path */
1501214501Srpaulo	wpa_s->dbus_new_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1502214501Srpaulo	if (wpa_s->dbus_new_path == NULL)
1503214501Srpaulo		return -1;
1504214501Srpaulo	next = ctrl_iface->next_objid++;
1505214501Srpaulo	os_snprintf(wpa_s->dbus_new_path, WPAS_DBUS_OBJECT_PATH_MAX,
1506214501Srpaulo		    WPAS_DBUS_NEW_PATH_INTERFACES "/%u",
1507214501Srpaulo		    next);
1508214501Srpaulo
1509214501Srpaulo	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
1510214501Srpaulo	if (!obj_desc) {
1511214501Srpaulo		wpa_printf(MSG_ERROR, "Not enough memory "
1512214501Srpaulo			   "to create object description");
1513214501Srpaulo		goto err;
1514214501Srpaulo	}
1515214501Srpaulo
1516214501Srpaulo	wpas_dbus_register(obj_desc, wpa_s, NULL, wpas_dbus_interface_methods,
1517214501Srpaulo			   wpas_dbus_interface_properties,
1518214501Srpaulo			   wpas_dbus_interface_signals);
1519214501Srpaulo
1520214501Srpaulo	wpa_printf(MSG_DEBUG, "dbus: Register interface object '%s'",
1521214501Srpaulo		   wpa_s->dbus_new_path);
1522214501Srpaulo	if (wpa_dbus_register_object_per_iface(ctrl_iface,
1523214501Srpaulo					       wpa_s->dbus_new_path,
1524214501Srpaulo					       wpa_s->ifname, obj_desc))
1525214501Srpaulo		goto err;
1526214501Srpaulo
1527214501Srpaulo	wpas_dbus_signal_interface_added(wpa_s);
1528214501Srpaulo
1529214501Srpaulo	return 0;
1530214501Srpaulo
1531214501Srpauloerr:
1532214501Srpaulo	os_free(wpa_s->dbus_new_path);
1533214501Srpaulo	wpa_s->dbus_new_path = NULL;
1534214501Srpaulo	free_dbus_object_desc(obj_desc);
1535214501Srpaulo	return -1;
1536214501Srpaulo}
1537214501Srpaulo
1538214501Srpaulo
1539214501Srpauloint wpas_dbus_unregister_interface(struct wpa_supplicant *wpa_s)
1540214501Srpaulo{
1541214501Srpaulo	struct wpas_dbus_priv *ctrl_iface;
1542214501Srpaulo
1543214501Srpaulo	/* Do nothing if the control interface is not turned on */
1544214501Srpaulo	if (wpa_s == NULL || wpa_s->global == NULL)
1545214501Srpaulo		return 0;
1546214501Srpaulo	ctrl_iface = wpa_s->global->dbus;
1547214501Srpaulo	if (ctrl_iface == NULL)
1548214501Srpaulo		return 0;
1549214501Srpaulo
1550214501Srpaulo	wpa_printf(MSG_DEBUG, "dbus: Unregister interface object '%s'",
1551214501Srpaulo		   wpa_s->dbus_new_path);
1552214501Srpaulo	if (wpa_dbus_unregister_object_per_iface(ctrl_iface,
1553214501Srpaulo						 wpa_s->dbus_new_path))
1554214501Srpaulo		return -1;
1555214501Srpaulo
1556214501Srpaulo	wpas_dbus_signal_interface_removed(wpa_s);
1557214501Srpaulo
1558214501Srpaulo	os_free(wpa_s->dbus_new_path);
1559214501Srpaulo	wpa_s->dbus_new_path = NULL;
1560214501Srpaulo
1561214501Srpaulo	return 0;
1562214501Srpaulo}
1563