dbus_old.c revision c55524ad84d13014e8019491c2b17e5dcf13545a
1/*
2 * WPA Supplicant / dbus-based control interface
3 * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 * Alternatively, this software may be distributed under the terms of BSD
10 * license.
11 *
12 * See README and COPYING for more details.
13 */
14
15#include "includes.h"
16#include <dbus/dbus.h>
17
18#include "common.h"
19#include "eloop.h"
20#include "wps/wps.h"
21#include "../config.h"
22#include "../wpa_supplicant_i.h"
23#include "../bss.h"
24#include "dbus_old.h"
25#include "dbus_old_handlers.h"
26#include "dbus_common.h"
27#include "dbus_common_i.h"
28
29
30/**
31 * wpas_dbus_decompose_object_path - Decompose an interface object path into parts
32 * @path: The dbus object path
33 * @network: (out) the configured network this object path refers to, if any
34 * @bssid: (out) the scanned bssid this object path refers to, if any
35 * Returns: The object path of the network interface this path refers to
36 *
37 * For a given object path, decomposes the object path into object id, network,
38 * and BSSID parts, if those parts exist.
39 */
40char * wpas_dbus_decompose_object_path(const char *path, char **network,
41				       char **bssid)
42{
43	const unsigned int dev_path_prefix_len =
44		strlen(WPAS_DBUS_PATH_INTERFACES "/");
45	char *obj_path_only;
46	char *next_sep;
47
48	/* Be a bit paranoid about path */
49	if (!path || strncmp(path, WPAS_DBUS_PATH_INTERFACES "/",
50			     dev_path_prefix_len))
51		return NULL;
52
53	/* Ensure there's something at the end of the path */
54	if ((path + dev_path_prefix_len)[0] == '\0')
55		return NULL;
56
57	obj_path_only = os_strdup(path);
58	if (obj_path_only == NULL)
59		return NULL;
60
61	next_sep = strchr(obj_path_only + dev_path_prefix_len, '/');
62	if (next_sep != NULL) {
63		const char *net_part = strstr(next_sep,
64					      WPAS_DBUS_NETWORKS_PART "/");
65		const char *bssid_part = strstr(next_sep,
66						WPAS_DBUS_BSSIDS_PART "/");
67
68		if (network && net_part) {
69			/* Deal with a request for a configured network */
70			const char *net_name = net_part +
71				strlen(WPAS_DBUS_NETWORKS_PART "/");
72			*network = NULL;
73			if (strlen(net_name))
74				*network = os_strdup(net_name);
75		} else if (bssid && bssid_part) {
76			/* Deal with a request for a scanned BSSID */
77			const char *bssid_name = bssid_part +
78				strlen(WPAS_DBUS_BSSIDS_PART "/");
79			if (strlen(bssid_name))
80				*bssid = os_strdup(bssid_name);
81			else
82				*bssid = NULL;
83		}
84
85		/* Cut off interface object path before "/" */
86		*next_sep = '\0';
87	}
88
89	return obj_path_only;
90}
91
92
93/**
94 * wpas_dbus_new_invalid_iface_error - Return a new invalid interface error message
95 * @message: Pointer to incoming dbus message this error refers to
96 * Returns: A dbus error message
97 *
98 * Convenience function to create and return an invalid interface error
99 */
100DBusMessage * wpas_dbus_new_invalid_iface_error(DBusMessage *message)
101{
102	return dbus_message_new_error(message, WPAS_ERROR_INVALID_IFACE,
103				      "wpa_supplicant knows nothing about "
104				      "this interface.");
105}
106
107
108/**
109 * wpas_dbus_new_invalid_network_error - Return a new invalid network error message
110 * @message: Pointer to incoming dbus message this error refers to
111 * Returns: a dbus error message
112 *
113 * Convenience function to create and return an invalid network error
114 */
115DBusMessage * wpas_dbus_new_invalid_network_error(DBusMessage *message)
116{
117	return dbus_message_new_error(message, WPAS_ERROR_INVALID_NETWORK,
118				      "The requested network does not exist.");
119}
120
121
122/**
123 * wpas_dbus_new_invalid_bssid_error - Return a new invalid bssid error message
124 * @message: Pointer to incoming dbus message this error refers to
125 * Returns: a dbus error message
126 *
127 * Convenience function to create and return an invalid bssid error
128 */
129static DBusMessage * wpas_dbus_new_invalid_bssid_error(DBusMessage *message)
130{
131	return dbus_message_new_error(message, WPAS_ERROR_INVALID_BSSID,
132				      "The BSSID requested was invalid.");
133}
134
135
136/**
137 * wpas_dispatch_network_method - dispatch messages for configured networks
138 * @message: the incoming dbus message
139 * @wpa_s: a network interface's data
140 * @network_id: id of the configured network we're interested in
141 * Returns: a reply dbus message, or a dbus error message
142 *
143 * This function dispatches all incoming dbus messages for configured networks.
144 */
145static DBusMessage * wpas_dispatch_network_method(DBusMessage *message,
146						  struct wpa_supplicant *wpa_s,
147						  int network_id)
148{
149	DBusMessage *reply = NULL;
150	const char *method = dbus_message_get_member(message);
151	struct wpa_ssid *ssid;
152
153	ssid = wpa_config_get_network(wpa_s->conf, network_id);
154	if (ssid == NULL)
155		return wpas_dbus_new_invalid_network_error(message);
156
157	if (!strcmp(method, "set"))
158		reply = wpas_dbus_iface_set_network(message, wpa_s, ssid);
159	else if (!strcmp(method, "enable"))
160		reply = wpas_dbus_iface_enable_network(message, wpa_s, ssid);
161	else if (!strcmp(method, "disable"))
162		reply = wpas_dbus_iface_disable_network(message, wpa_s, ssid);
163
164	return reply;
165}
166
167
168/**
169 * wpas_dispatch_bssid_method - dispatch messages for scanned networks
170 * @message: the incoming dbus message
171 * @wpa_s: a network interface's data
172 * @bssid: bssid of the scanned network we're interested in
173 * Returns: a reply dbus message, or a dbus error message
174 *
175 * This function dispatches all incoming dbus messages for scanned networks.
176 */
177static DBusMessage * wpas_dispatch_bssid_method(DBusMessage *message,
178						struct wpa_supplicant *wpa_s,
179						const char *bssid_txt)
180{
181	u8 bssid[ETH_ALEN];
182	struct wpa_bss *bss;
183
184	if (hexstr2bin(bssid_txt, bssid, ETH_ALEN) < 0)
185		return wpas_dbus_new_invalid_bssid_error(message);
186
187	bss = wpa_bss_get_bssid(wpa_s, bssid);
188	if (bss == NULL)
189		return wpas_dbus_new_invalid_bssid_error(message);
190
191	/* Dispatch the method call against the scanned bssid */
192	if (os_strcmp(dbus_message_get_member(message), "properties") == 0)
193		return wpas_dbus_bssid_properties(message, wpa_s, bss);
194
195	return NULL;
196}
197
198
199/**
200 * wpas_iface_message_handler - Dispatch messages for interfaces or networks
201 * @connection: Connection to the system message bus
202 * @message: An incoming dbus message
203 * @user_data: A pointer to a dbus control interface data structure
204 * Returns: Whether or not the message was handled
205 *
206 * This function dispatches all incoming dbus messages for network interfaces,
207 * or objects owned by them, such as scanned BSSIDs and configured networks.
208 */
209static DBusHandlerResult wpas_iface_message_handler(DBusConnection *connection,
210						    DBusMessage *message,
211						    void *user_data)
212{
213	struct wpa_supplicant *wpa_s = user_data;
214	const char *method = dbus_message_get_member(message);
215	const char *path = dbus_message_get_path(message);
216	const char *msg_interface = dbus_message_get_interface(message);
217	char *iface_obj_path = NULL;
218	char *network = NULL;
219	char *bssid = NULL;
220	DBusMessage *reply = NULL;
221
222	/* Caller must specify a message interface */
223	if (!msg_interface)
224		goto out;
225
226	iface_obj_path = wpas_dbus_decompose_object_path(path, &network,
227	                                                 &bssid);
228	if (iface_obj_path == NULL) {
229		reply = wpas_dbus_new_invalid_iface_error(message);
230		goto out;
231	}
232
233	/* Make sure the message's object path actually refers to the
234	 * wpa_supplicant structure it's supposed to (which is wpa_s)
235	 */
236	if (wpa_supplicant_get_iface_by_dbus_path(wpa_s->global,
237	                                          iface_obj_path) != wpa_s) {
238		reply = wpas_dbus_new_invalid_iface_error(message);
239		goto out;
240	}
241
242	if (network && !strcmp(msg_interface, WPAS_DBUS_IFACE_NETWORK)) {
243		/* A method for one of this interface's configured networks */
244		int nid = strtoul(network, NULL, 10);
245		if (errno != EINVAL)
246			reply = wpas_dispatch_network_method(message, wpa_s,
247							     nid);
248		else
249			reply = wpas_dbus_new_invalid_network_error(message);
250	} else if (bssid && !strcmp(msg_interface, WPAS_DBUS_IFACE_BSSID)) {
251		/* A method for one of this interface's scanned BSSIDs */
252		reply = wpas_dispatch_bssid_method(message, wpa_s, bssid);
253	} else if (!strcmp(msg_interface, WPAS_DBUS_IFACE_INTERFACE)) {
254		/* A method for an interface only. */
255		if (!strcmp(method, "scan"))
256			reply = wpas_dbus_iface_scan(message, wpa_s);
257		else if (!strcmp(method, "scanResults"))
258			reply = wpas_dbus_iface_scan_results(message, wpa_s);
259		else if (!strcmp(method, "addNetwork"))
260			reply = wpas_dbus_iface_add_network(message, wpa_s);
261		else if (!strcmp(method, "removeNetwork"))
262			reply = wpas_dbus_iface_remove_network(message, wpa_s);
263		else if (!strcmp(method, "selectNetwork"))
264			reply = wpas_dbus_iface_select_network(message, wpa_s);
265		else if (!strcmp(method, "capabilities"))
266			reply = wpas_dbus_iface_capabilities(message, wpa_s);
267		else if (!strcmp(method, "disconnect"))
268			reply = wpas_dbus_iface_disconnect(message, wpa_s);
269		else if (!strcmp(method, "setAPScan"))
270			reply = wpas_dbus_iface_set_ap_scan(message, wpa_s);
271		else if (!strcmp(method, "setSmartcardModules"))
272			reply = wpas_dbus_iface_set_smartcard_modules(message,
273								      wpa_s);
274		else if (!strcmp(method, "state"))
275			reply = wpas_dbus_iface_get_state(message, wpa_s);
276		else if (!strcmp(method, "scanning"))
277			reply = wpas_dbus_iface_get_scanning(message, wpa_s);
278		else if (!strcmp(method, "setBlobs"))
279			reply = wpas_dbus_iface_set_blobs(message, wpa_s);
280		else if (!strcmp(method, "removeBlobs"))
281			reply = wpas_dbus_iface_remove_blobs(message, wpa_s);
282#ifdef CONFIG_WPS
283		else if (!os_strcmp(method, "wpsPbc"))
284			reply = wpas_dbus_iface_wps_pbc(message, wpa_s);
285		else if (!os_strcmp(method, "wpsPin"))
286			reply = wpas_dbus_iface_wps_pin(message, wpa_s);
287		else if (!os_strcmp(method, "wpsReg"))
288			reply = wpas_dbus_iface_wps_reg(message, wpa_s);
289#endif /* CONFIG_WPS */
290		else if (!os_strcmp(method, "flush"))
291			reply = wpas_dbus_iface_flush(message, wpa_s);
292	}
293
294	/* If the message was handled, send back the reply */
295	if (reply) {
296		if (!dbus_message_get_no_reply(message))
297			dbus_connection_send(connection, reply, NULL);
298		dbus_message_unref(reply);
299	}
300
301out:
302	os_free(iface_obj_path);
303	os_free(network);
304	os_free(bssid);
305	return reply ? DBUS_HANDLER_RESULT_HANDLED :
306		DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
307}
308
309
310/**
311 * wpas_message_handler - dispatch incoming dbus messages
312 * @connection: connection to the system message bus
313 * @message: an incoming dbus message
314 * @user_data: a pointer to a dbus control interface data structure
315 * Returns: whether or not the message was handled
316 *
317 * This function dispatches all incoming dbus messages to the correct
318 * handlers, depending on what the message's target object path is,
319 * and what the method call is.
320 */
321static DBusHandlerResult wpas_message_handler(DBusConnection *connection,
322	DBusMessage *message, void *user_data)
323{
324	struct wpas_dbus_priv *ctrl_iface = user_data;
325	const char *method;
326	const char *path;
327	const char *msg_interface;
328	DBusMessage *reply = NULL;
329
330	method = dbus_message_get_member(message);
331	path = dbus_message_get_path(message);
332	msg_interface = dbus_message_get_interface(message);
333	if (!method || !path || !ctrl_iface || !msg_interface)
334		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
335
336	/* Validate the method interface */
337	if (strcmp(msg_interface, WPAS_DBUS_INTERFACE) != 0)
338		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
339
340	if (!strcmp(path, WPAS_DBUS_PATH)) {
341		/* dispatch methods against our global dbus interface here */
342		if (!strcmp(method, "addInterface")) {
343			reply = wpas_dbus_global_add_interface(
344				message, ctrl_iface->global);
345		} else if (!strcmp(method, "removeInterface")) {
346			reply = wpas_dbus_global_remove_interface(
347				message, ctrl_iface->global);
348		} else if (!strcmp(method, "getInterface")) {
349			reply = wpas_dbus_global_get_interface(
350				message, ctrl_iface->global);
351		} else if (!strcmp(method, "setDebugParams")) {
352			reply = wpas_dbus_global_set_debugparams(
353				message, ctrl_iface->global);
354		}
355	}
356
357	/* If the message was handled, send back the reply */
358	if (reply) {
359		if (!dbus_message_get_no_reply(message))
360			dbus_connection_send(connection, reply, NULL);
361		dbus_message_unref(reply);
362	}
363
364	return reply ? DBUS_HANDLER_RESULT_HANDLED :
365		DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
366}
367
368
369/**
370 * wpa_supplicant_dbus_notify_scan_results - Send a scan results signal
371 * @wpa_s: %wpa_supplicant network interface data
372 * Returns: 0 on success, -1 on failure
373 *
374 * Notify listeners that this interface has updated scan results.
375 */
376void wpa_supplicant_dbus_notify_scan_results(struct wpa_supplicant *wpa_s)
377{
378	struct wpas_dbus_priv *iface = wpa_s->global->dbus;
379	DBusMessage *_signal;
380
381	/* Do nothing if the control interface is not turned on */
382	if (iface == NULL)
383		return;
384
385	_signal = dbus_message_new_signal(wpa_s->dbus_path,
386					  WPAS_DBUS_IFACE_INTERFACE,
387					  "ScanResultsAvailable");
388	if (_signal == NULL) {
389		wpa_printf(MSG_ERROR, "dbus: Not enough memory to send scan "
390			   "results signal");
391		return;
392	}
393	dbus_connection_send(iface->con, _signal, NULL);
394	dbus_message_unref(_signal);
395}
396
397
398/**
399 * wpa_supplicant_dbus_notify_state_change - Send a state change signal
400 * @wpa_s: %wpa_supplicant network interface data
401 * @new_state: new state wpa_supplicant is entering
402 * @old_state: old state wpa_supplicant is leaving
403 * Returns: 0 on success, -1 on failure
404 *
405 * Notify listeners that wpa_supplicant has changed state
406 */
407void wpa_supplicant_dbus_notify_state_change(struct wpa_supplicant *wpa_s,
408					     enum wpa_states new_state,
409					     enum wpa_states old_state)
410{
411	struct wpas_dbus_priv *iface;
412	DBusMessage *_signal = NULL;
413	const char *new_state_str, *old_state_str;
414
415	if (wpa_s->dbus_path == NULL)
416		return; /* Skip signal since D-Bus setup is not yet ready */
417
418	/* Do nothing if the control interface is not turned on */
419	if (wpa_s->global == NULL)
420		return;
421	iface = wpa_s->global->dbus;
422	if (iface == NULL)
423		return;
424
425	/* Only send signal if state really changed */
426	if (new_state == old_state)
427		return;
428
429	_signal = dbus_message_new_signal(wpa_s->dbus_path,
430					  WPAS_DBUS_IFACE_INTERFACE,
431					  "StateChange");
432	if (_signal == NULL) {
433		wpa_printf(MSG_ERROR,
434		           "dbus: wpa_supplicant_dbus_notify_state_change: "
435		           "could not create dbus signal; likely out of "
436		           "memory");
437		return;
438	}
439
440	new_state_str = wpa_supplicant_state_txt(new_state);
441	old_state_str = wpa_supplicant_state_txt(old_state);
442	if (new_state_str == NULL || old_state_str == NULL) {
443		wpa_printf(MSG_ERROR,
444		           "dbus: wpa_supplicant_dbus_notify_state_change: "
445		           "Could not convert state strings");
446		goto out;
447	}
448
449	if (!dbus_message_append_args(_signal,
450	                              DBUS_TYPE_STRING, &new_state_str,
451	                              DBUS_TYPE_STRING, &old_state_str,
452	                              DBUS_TYPE_INVALID)) {
453		wpa_printf(MSG_ERROR,
454		           "dbus: wpa_supplicant_dbus_notify_state_change: "
455		           "Not enough memory to construct state change "
456		           "signal");
457		goto out;
458	}
459
460	dbus_connection_send(iface->con, _signal, NULL);
461
462out:
463	dbus_message_unref(_signal);
464}
465
466
467/**
468 * wpa_supplicant_dbus_notify_scanning - send scanning status
469 * @wpa_s: %wpa_supplicant network interface data
470 * Returns: 0 on success, -1 on failure
471 *
472 * Notify listeners of interface scanning state changes
473 */
474void wpa_supplicant_dbus_notify_scanning(struct wpa_supplicant *wpa_s)
475{
476	struct wpas_dbus_priv *iface = wpa_s->global->dbus;
477	DBusMessage *_signal;
478	dbus_bool_t scanning = wpa_s->scanning ? TRUE : FALSE;
479
480	/* Do nothing if the control interface is not turned on */
481	if (iface == NULL)
482		return;
483
484	_signal = dbus_message_new_signal(wpa_s->dbus_path,
485					  WPAS_DBUS_IFACE_INTERFACE,
486					  "Scanning");
487	if (_signal == NULL) {
488		wpa_printf(MSG_ERROR, "dbus: Not enough memory to send scan "
489			   "results signal");
490		return;
491	}
492
493	if (dbus_message_append_args(_signal,
494	                             DBUS_TYPE_BOOLEAN, &scanning,
495	                             DBUS_TYPE_INVALID)) {
496		dbus_connection_send(iface->con, _signal, NULL);
497	} else {
498		wpa_printf(MSG_ERROR, "dbus: Not enough memory to construct "
499			   "signal");
500	}
501	dbus_message_unref(_signal);
502}
503
504
505#ifdef CONFIG_WPS
506void wpa_supplicant_dbus_notify_wps_cred(struct wpa_supplicant *wpa_s,
507					 const struct wps_credential *cred)
508{
509	struct wpas_dbus_priv *iface;
510	DBusMessage *_signal = NULL;
511
512	/* Do nothing if the control interface is not turned on */
513	if (wpa_s->global == NULL)
514		return;
515	iface = wpa_s->global->dbus;
516	if (iface == NULL)
517		return;
518
519	_signal = dbus_message_new_signal(wpa_s->dbus_path,
520					  WPAS_DBUS_IFACE_INTERFACE,
521					  "WpsCred");
522	if (_signal == NULL) {
523		wpa_printf(MSG_ERROR,
524		           "dbus: wpa_supplicant_dbus_notify_wps_cred: "
525		           "Could not create dbus signal; likely out of "
526		           "memory");
527		return;
528	}
529
530	if (!dbus_message_append_args(_signal,
531	                              DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
532				      &cred->cred_attr, cred->cred_attr_len,
533	                              DBUS_TYPE_INVALID)) {
534		wpa_printf(MSG_ERROR,
535		           "dbus: wpa_supplicant_dbus_notify_wps_cred: "
536		           "Not enough memory to construct signal");
537		goto out;
538	}
539
540	dbus_connection_send(iface->con, _signal, NULL);
541
542out:
543	dbus_message_unref(_signal);
544}
545#else /* CONFIG_WPS */
546void wpa_supplicant_dbus_notify_wps_cred(struct wpa_supplicant *wpa_s,
547					 const struct wps_credential *cred)
548{
549}
550#endif /* CONFIG_WPS */
551
552void wpa_supplicant_dbus_notify_certification(struct wpa_supplicant *wpa_s,
553					      int depth, const char *subject,
554					      const char *cert_hash,
555					      const struct wpabuf *cert)
556{
557	struct wpas_dbus_priv *iface;
558	DBusMessage *_signal = NULL;
559	const char *hash;
560	const char *cert_hex;
561	int cert_hex_len;
562
563	/* Do nothing if the control interface is not turned on */
564	if (wpa_s->global == NULL)
565		return;
566	iface = wpa_s->global->dbus;
567	if (iface == NULL)
568		return;
569
570	_signal = dbus_message_new_signal(wpa_s->dbus_path,
571					  WPAS_DBUS_IFACE_INTERFACE,
572					  "Certification");
573	if (_signal == NULL) {
574		wpa_printf(MSG_ERROR,
575		           "dbus: wpa_supplicant_dbus_notify_certification: "
576		           "Could not create dbus signal; likely out of "
577		           "memory");
578		return;
579	}
580
581	hash = cert_hash ? cert_hash : "";
582	cert_hex = cert ? wpabuf_head(cert) : "";
583	cert_hex_len = cert ? wpabuf_len(cert) : 0;
584
585	if (!dbus_message_append_args(_signal,
586				      DBUS_TYPE_INT32,&depth,
587				      DBUS_TYPE_STRING, &subject,
588	                              DBUS_TYPE_STRING, &hash,
589	                              DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
590				      &cert_hex, cert_hex_len,
591	                              DBUS_TYPE_INVALID)) {
592		wpa_printf(MSG_ERROR,
593		           "dbus: wpa_supplicant_dbus_notify_certification: "
594		           "Not enough memory to construct signal");
595		goto out;
596	}
597
598	dbus_connection_send(iface->con, _signal, NULL);
599
600out:
601	dbus_message_unref(_signal);
602
603}
604
605
606/**
607 * wpa_supplicant_dbus_ctrl_iface_init - Initialize dbus control interface
608 * @global: Pointer to global data from wpa_supplicant_init()
609 * Returns: 0 on success, -1 on failure
610 *
611 * Initialize the dbus control interface and start receiving commands from
612 * external programs over the bus.
613 */
614int wpa_supplicant_dbus_ctrl_iface_init(struct wpas_dbus_priv *iface)
615{
616	DBusError error;
617	int ret = -1;
618	DBusObjectPathVTable wpas_vtable = {
619		NULL, &wpas_message_handler, NULL, NULL, NULL, NULL
620	};
621
622	/* Register the message handler for the global dbus interface */
623	if (!dbus_connection_register_object_path(iface->con,
624						  WPAS_DBUS_PATH, &wpas_vtable,
625						  iface)) {
626		wpa_printf(MSG_ERROR, "dbus: Could not set up message "
627			   "handler");
628		return -1;
629	}
630
631	/* Register our service with the message bus */
632	dbus_error_init(&error);
633	switch (dbus_bus_request_name(iface->con, WPAS_DBUS_SERVICE,
634				      0, &error)) {
635	case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER:
636		ret = 0;
637		break;
638	case DBUS_REQUEST_NAME_REPLY_EXISTS:
639	case DBUS_REQUEST_NAME_REPLY_IN_QUEUE:
640	case DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER:
641		wpa_printf(MSG_ERROR, "dbus: Could not request service name: "
642			   "already registered");
643		break;
644	default:
645		wpa_printf(MSG_ERROR, "dbus: Could not request service name: "
646			   "%s %s", error.name, error.message);
647		break;
648	}
649	dbus_error_free(&error);
650
651	if (ret != 0)
652		return -1;
653
654	wpa_printf(MSG_DEBUG, "Providing DBus service '" WPAS_DBUS_SERVICE
655		   "'.");
656
657	return 0;
658}
659
660
661/**
662 * wpas_dbus_register_new_iface - Register a new interface with dbus
663 * @wpa_s: %wpa_supplicant interface description structure to register
664 * Returns: 0 on success, -1 on error
665 *
666 * Registers a new interface with dbus and assigns it a dbus object path.
667 */
668int wpas_dbus_register_iface(struct wpa_supplicant *wpa_s)
669{
670	struct wpas_dbus_priv *ctrl_iface = wpa_s->global->dbus;
671	DBusConnection * con;
672	u32 next;
673	DBusObjectPathVTable vtable = {
674		NULL, &wpas_iface_message_handler, NULL, NULL, NULL, NULL
675	};
676
677	/* Do nothing if the control interface is not turned on */
678	if (ctrl_iface == NULL)
679		return 0;
680
681	con = ctrl_iface->con;
682	next = ctrl_iface->next_objid++;
683
684	/* Create and set the interface's object path */
685	wpa_s->dbus_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
686	if (wpa_s->dbus_path == NULL)
687		return -1;
688	os_snprintf(wpa_s->dbus_path, WPAS_DBUS_OBJECT_PATH_MAX,
689		    WPAS_DBUS_PATH_INTERFACES "/%u",
690		    next);
691
692	/* Register the message handler for the interface functions */
693	if (!dbus_connection_register_fallback(con, wpa_s->dbus_path, &vtable,
694					       wpa_s)) {
695		wpa_printf(MSG_ERROR, "dbus: Could not set up message "
696			   "handler for interface %s", wpa_s->ifname);
697		return -1;
698	}
699
700	return 0;
701}
702
703
704/**
705 * wpas_dbus_unregister_iface - Unregister an interface from dbus
706 * @wpa_s: wpa_supplicant interface structure
707 * Returns: 0 on success, -1 on failure
708 *
709 * Unregisters the interface with dbus
710 */
711int wpas_dbus_unregister_iface(struct wpa_supplicant *wpa_s)
712{
713	struct wpas_dbus_priv *ctrl_iface;
714	DBusConnection *con;
715
716	/* Do nothing if the control interface is not turned on */
717	if (wpa_s == NULL || wpa_s->global == NULL)
718		return 0;
719	ctrl_iface = wpa_s->global->dbus;
720	if (ctrl_iface == NULL)
721		return 0;
722
723	con = ctrl_iface->con;
724	if (!dbus_connection_unregister_object_path(con, wpa_s->dbus_path))
725		return -1;
726
727	os_free(wpa_s->dbus_path);
728	wpa_s->dbus_path = NULL;
729
730	return 0;
731}
732
733
734/**
735 * wpa_supplicant_get_iface_by_dbus_path - Get a new network interface
736 * @global: Pointer to global data from wpa_supplicant_init()
737 * @path: Pointer to a dbus object path representing an interface
738 * Returns: Pointer to the interface or %NULL if not found
739 */
740struct wpa_supplicant * wpa_supplicant_get_iface_by_dbus_path(
741	struct wpa_global *global, const char *path)
742{
743	struct wpa_supplicant *wpa_s;
744
745	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
746		if (strcmp(wpa_s->dbus_path, path) == 0)
747			return wpa_s;
748	}
749	return NULL;
750}
751