Home | History | Annotate | Download | only in dbus
      1 /*
      2  * WPA Supplicant / dbus-based control interface
      3  * Copyright (c) 2006, Dan Williams <dcbw (at) 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  */
     40 char * 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  */
    100 DBusMessage * 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  */
    115 DBusMessage * 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  */
    129 static 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  */
    145 static 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  */
    177 static 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  */
    209 static 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 
    301 out:
    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  */
    321 static 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  */
    376 void 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  */
    407 void 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 
    462 out:
    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  */
    474 void 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
    506 void 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 
    542 out:
    543 	dbus_message_unref(_signal);
    544 }
    545 #else /* CONFIG_WPS */
    546 void wpa_supplicant_dbus_notify_wps_cred(struct wpa_supplicant *wpa_s,
    547 					 const struct wps_credential *cred)
    548 {
    549 }
    550 #endif /* CONFIG_WPS */
    551 
    552 void 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 
    600 out:
    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  */
    614 int 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  */
    668 int 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  */
    711 int 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  */
    740 struct 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