Home | History | Annotate | Download | only in src
      1 /*
      2  *
      3  *  BlueZ - Bluetooth protocol stack for Linux
      4  *
      5  *  Copyright (C) 2006-2010  Nokia Corporation
      6  *  Copyright (C) 2004-2010  Marcel Holtmann <marcel (at) holtmann.org>
      7  *
      8  *
      9  *  This program is free software; you can redistribute it and/or modify
     10  *  it under the terms of the GNU General Public License as published by
     11  *  the Free Software Foundation; either version 2 of the License, or
     12  *  (at your option) any later version.
     13  *
     14  *  This program is distributed in the hope that it will be useful,
     15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17  *  GNU General Public License for more details.
     18  *
     19  *  You should have received a copy of the GNU General Public License
     20  *  along with this program; if not, write to the Free Software
     21  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     22  *
     23  */
     24 
     25 #ifdef HAVE_CONFIG_H
     26 #include <config.h>
     27 #endif
     28 
     29 #include <stdio.h>
     30 #include <errno.h>
     31 #include <stdlib.h>
     32 #include <sys/socket.h>
     33 #include <sys/ioctl.h>
     34 
     35 #include <bluetooth/bluetooth.h>
     36 #include <bluetooth/hci.h>
     37 #include <bluetooth/hci_lib.h>
     38 #include <bluetooth/sdp.h>
     39 
     40 #include <glib.h>
     41 #include <dbus/dbus.h>
     42 #include <gdbus.h>
     43 
     44 #include "log.h"
     45 
     46 #include "hcid.h"
     47 #include "adapter.h"
     48 #include "device.h"
     49 #include "agent.h"
     50 
     51 #define REQUEST_TIMEOUT (60 * 1000)		/* 60 seconds */
     52 
     53 typedef enum {
     54 	AGENT_REQUEST_PASSKEY,
     55 	AGENT_REQUEST_CONFIRMATION,
     56 	AGENT_REQUEST_PINCODE,
     57 	AGENT_REQUEST_AUTHORIZE,
     58 	AGENT_REQUEST_CONFIRM_MODE,
     59 	AGENT_REQUEST_OOB_AVAILABILITY,
     60 	AGENT_REQUEST_OOB_DATA,
     61 	AGENT_REQUEST_PAIRING_CONSENT,
     62 } agent_request_type_t;
     63 
     64 struct agent {
     65 	struct btd_adapter *adapter;
     66 	char *name;
     67 	char *path;
     68 	uint8_t capability;
     69 	gboolean oob;
     70 	struct agent_request *request;
     71 	int exited;
     72 	agent_remove_cb remove_cb;
     73 	void *remove_cb_data;
     74 	guint listener_id;
     75 };
     76 
     77 struct agent_request {
     78 	agent_request_type_t type;
     79 	struct agent *agent;
     80 	DBusMessage *msg;
     81 	DBusPendingCall *call;
     82 	void *cb;
     83 	void *user_data;
     84 	GDestroyNotify destroy;
     85 };
     86 
     87 static DBusConnection *connection = NULL;
     88 
     89 static int request_fallback(struct agent_request *req,
     90 				DBusPendingCallNotifyFunction function);
     91 
     92 static void agent_release(struct agent *agent)
     93 {
     94 	DBusMessage *message;
     95 
     96 	DBG("Releasing agent %s, %s", agent->name, agent->path);
     97 
     98 	if (agent->request)
     99 		agent_cancel(agent);
    100 
    101 	message = dbus_message_new_method_call(agent->name, agent->path,
    102 			"org.bluez.Agent", "Release");
    103 	if (message == NULL) {
    104 		error("Couldn't allocate D-Bus message");
    105 		return;
    106 	}
    107 
    108 	g_dbus_send_message(connection, message);
    109 }
    110 
    111 static int send_cancel_request(struct agent_request *req)
    112 {
    113 	DBusMessage *message;
    114 
    115 	message = dbus_message_new_method_call(req->agent->name, req->agent->path,
    116 						"org.bluez.Agent", "Cancel");
    117 	if (message == NULL) {
    118 		error("Couldn't allocate D-Bus message");
    119 		return -ENOMEM;
    120 	}
    121 
    122 	g_dbus_send_message(connection, message);
    123 
    124 	return 0;
    125 }
    126 
    127 static void agent_request_free(struct agent_request *req, gboolean destroy)
    128 {
    129 	if (req->msg)
    130 		dbus_message_unref(req->msg);
    131 	if (req->call)
    132 		dbus_pending_call_unref(req->call);
    133 	if (req->agent && req->agent->request)
    134 		req->agent->request = NULL;
    135 	if (destroy && req->destroy)
    136 		req->destroy(req->user_data);
    137 	g_free(req);
    138 }
    139 
    140 static void agent_exited(DBusConnection *conn, void *user_data)
    141 {
    142 	struct agent *agent = user_data;
    143 
    144 	DBG("Agent exited without calling Unregister");
    145 
    146 	agent->exited = TRUE;
    147 
    148 	agent_free(agent);
    149 }
    150 
    151 void agent_free(struct agent *agent)
    152 {
    153 	if (!agent)
    154 		return;
    155 
    156 	if (agent->remove_cb)
    157 		agent->remove_cb(agent, agent->remove_cb_data);
    158 
    159 	if (agent->request) {
    160 		DBusError err;
    161 		agent_pincode_cb pincode_cb;
    162 		agent_cb cb;
    163 
    164 		dbus_error_init(&err);
    165 		dbus_set_error_const(&err, "org.bluez.Error.Failed", "Canceled");
    166 
    167 		switch (agent->request->type) {
    168 		case AGENT_REQUEST_PINCODE:
    169 			pincode_cb = agent->request->cb;
    170 			pincode_cb(agent, &err, NULL, agent->request->user_data);
    171 			break;
    172 		default:
    173 			cb = agent->request->cb;
    174 			cb(agent, &err, agent->request->user_data);
    175 		}
    176 
    177 		dbus_error_free(&err);
    178 
    179 		agent_cancel(agent);
    180 	}
    181 
    182 	if (!agent->exited) {
    183 		g_dbus_remove_watch(connection, agent->listener_id);
    184 		agent_release(agent);
    185 	}
    186 
    187 	g_free(agent->name);
    188 	g_free(agent->path);
    189 
    190 	g_free(agent);
    191 }
    192 
    193 struct agent *agent_create(struct btd_adapter *adapter, const char *name,
    194 				const char *path, uint8_t capability,
    195 				gboolean oob, agent_remove_cb cb,
    196 				void *remove_cb_data)
    197 {
    198 	struct agent *agent;
    199 
    200 	agent = g_new0(struct agent, 1);
    201 
    202 	agent->adapter = adapter;
    203 	agent->name = g_strdup(name);
    204 	agent->path = g_strdup(path);
    205 	agent->capability = capability;
    206 	agent->oob = oob;
    207 	agent->remove_cb = cb;
    208 	agent->remove_cb_data = remove_cb_data;
    209 
    210 	agent->listener_id = g_dbus_add_disconnect_watch(connection, name,
    211 							agent_exited, agent,
    212 							NULL);
    213 
    214 	return agent;
    215 }
    216 
    217 static struct agent_request *agent_request_new(struct agent *agent,
    218 						agent_request_type_t type,
    219 						void *cb,
    220 						void *user_data,
    221 						GDestroyNotify destroy)
    222 {
    223 	struct agent_request *req;
    224 
    225 	req = g_new0(struct agent_request, 1);
    226 
    227 	req->agent = agent;
    228 	req->type = type;
    229 	req->cb = cb;
    230 	req->user_data = user_data;
    231 	req->destroy = destroy;
    232 
    233 	return req;
    234 }
    235 
    236 int agent_cancel(struct agent *agent)
    237 {
    238 	if (!agent->request)
    239 		return -EINVAL;
    240 
    241 	if (agent->request->call)
    242 		dbus_pending_call_cancel(agent->request->call);
    243 
    244 	if (!agent->exited)
    245 		send_cancel_request(agent->request);
    246 
    247 	agent_request_free(agent->request, TRUE);
    248 	agent->request = NULL;
    249 
    250 	return 0;
    251 }
    252 
    253 static void simple_agent_reply(DBusPendingCall *call, void *user_data)
    254 {
    255 	struct agent_request *req = user_data;
    256 	struct agent *agent = req->agent;
    257 	DBusMessage *message;
    258 	DBusError err;
    259 	agent_cb cb = req->cb;
    260 
    261 	/* steal_reply will always return non-NULL since the callback
    262 	 * is only called after a reply has been received */
    263 	message = dbus_pending_call_steal_reply(call);
    264 
    265 	dbus_error_init(&err);
    266 	if (dbus_set_error_from_message(&err, message)) {
    267 		if ((g_str_equal(DBUS_ERROR_UNKNOWN_METHOD, err.name) ||
    268 				g_str_equal(DBUS_ERROR_NO_REPLY, err.name)) &&
    269 				request_fallback(req, simple_agent_reply) == 0) {
    270 			dbus_error_free(&err);
    271 			return;
    272 		}
    273 
    274 		error("Agent replied with an error: %s, %s",
    275 				err.name, err.message);
    276 
    277 		cb(agent, &err, req->user_data);
    278 
    279 		if (dbus_error_has_name(&err, DBUS_ERROR_NO_REPLY)) {
    280 			agent_cancel(agent);
    281 			dbus_message_unref(message);
    282 			dbus_error_free(&err);
    283 			return;
    284 		}
    285 
    286 		dbus_error_free(&err);
    287 		goto done;
    288 	}
    289 
    290 	dbus_error_init(&err);
    291 	if (!dbus_message_get_args(message, &err, DBUS_TYPE_INVALID)) {
    292 		error("Wrong reply signature: %s", err.message);
    293 		cb(agent, &err, req->user_data);
    294 		dbus_error_free(&err);
    295 		goto done;
    296 	}
    297 
    298 	cb(agent, NULL, req->user_data);
    299 done:
    300 	dbus_message_unref(message);
    301 
    302 	agent->request = NULL;
    303 	agent_request_free(req, TRUE);
    304 }
    305 
    306 static int agent_call_authorize(struct agent_request *req,
    307 				const char *device_path,
    308 				const char *uuid)
    309 {
    310 	struct agent *agent = req->agent;
    311 
    312 	req->msg = dbus_message_new_method_call(agent->name, agent->path,
    313 				"org.bluez.Agent", "Authorize");
    314 	if (!req->msg) {
    315 		error("Couldn't allocate D-Bus message");
    316 		return -ENOMEM;
    317 	}
    318 
    319 	dbus_message_append_args(req->msg,
    320 				DBUS_TYPE_OBJECT_PATH, &device_path,
    321 				DBUS_TYPE_STRING, &uuid,
    322 				DBUS_TYPE_INVALID);
    323 
    324 	if (dbus_connection_send_with_reply(connection, req->msg,
    325 					&req->call, REQUEST_TIMEOUT) == FALSE) {
    326 		error("D-Bus send failed");
    327 		return -EIO;
    328 	}
    329 
    330 	dbus_pending_call_set_notify(req->call, simple_agent_reply, req, NULL);
    331 	return 0;
    332 }
    333 
    334 int agent_authorize(struct agent *agent,
    335 			const char *path,
    336 			const char *uuid,
    337 			agent_cb cb,
    338 			void *user_data,
    339 			GDestroyNotify destroy)
    340 {
    341 	struct agent_request *req;
    342 	int err;
    343 
    344 	if (agent->request)
    345 		return -EBUSY;
    346 
    347 	req = agent_request_new(agent, AGENT_REQUEST_AUTHORIZE, cb,
    348 							user_data, destroy);
    349 
    350 	err = agent_call_authorize(req, path, uuid);
    351 	if (err < 0) {
    352 		agent_request_free(req, FALSE);
    353 		return -ENOMEM;
    354 	}
    355 
    356 	agent->request = req;
    357 
    358 	DBG("authorize request was sent for %s", path);
    359 
    360 	return 0;
    361 }
    362 
    363 
    364 static int agent_call_oob_availability(struct agent_request *req,
    365 					const char *device_path)
    366 {
    367 	struct agent *agent = req->agent;
    368 
    369 	req->msg = dbus_message_new_method_call(agent->name, agent->path,
    370 				"org.bluez.Agent", "OutOfBandAvailable");
    371 	if (!req->msg) {
    372 		error("Couldn't allocate D-Bus message");
    373 		return -ENOMEM;
    374 	}
    375 
    376 	dbus_message_append_args(req->msg,
    377 				DBUS_TYPE_OBJECT_PATH, &device_path,
    378 				DBUS_TYPE_INVALID);
    379 
    380 	if (dbus_connection_send_with_reply(connection, req->msg,
    381 					&req->call, REQUEST_TIMEOUT) == FALSE) {
    382 		error("D-Bus send failed");
    383 		return -EIO;
    384 	}
    385 
    386 	dbus_pending_call_set_notify(req->call, simple_agent_reply, req, NULL);
    387 	return 0;
    388 }
    389 
    390 int agent_request_oob_availability(struct agent *agent,
    391 					const char *path,
    392 					agent_cb cb,
    393 					void *user_data,
    394 					GDestroyNotify destroy)
    395 {
    396 	struct agent_request *req;
    397 	int err;
    398 
    399 	if (agent->request)
    400 		return -EBUSY;
    401 
    402 	req = agent_request_new(agent, AGENT_REQUEST_OOB_AVAILABILITY, cb,
    403 							user_data, destroy);
    404 
    405 	err = agent_call_oob_availability(req, path);
    406 	if (err < 0) {
    407 		agent_request_free(req, FALSE);
    408 		return -ENOMEM;
    409 	}
    410 
    411 	agent->request = req;
    412 
    413 	DBG("oob availability request was sent for %s", path);
    414 
    415 	return 0;
    416 }
    417 
    418 static void pincode_reply(DBusPendingCall *call, void *user_data)
    419 {
    420 	struct agent_request *req = user_data;
    421 	struct agent *agent = req->agent;
    422 	struct btd_adapter *adapter = agent->adapter;
    423 	agent_pincode_cb cb = req->cb;
    424 	DBusMessage *message;
    425 	DBusError err;
    426 	bdaddr_t sba;
    427 	size_t len;
    428 	char *pin;
    429 
    430 	adapter_get_address(adapter, &sba);
    431 
    432 	/* steal_reply will always return non-NULL since the callback
    433 	 * is only called after a reply has been received */
    434 	message = dbus_pending_call_steal_reply(call);
    435 
    436 	dbus_error_init(&err);
    437 	if (dbus_set_error_from_message(&err, message)) {
    438 		if ((g_str_equal(DBUS_ERROR_UNKNOWN_METHOD, err.name) ||
    439 				g_str_equal(DBUS_ERROR_NO_REPLY, err.name)) &&
    440 				request_fallback(req, pincode_reply) == 0) {
    441 			dbus_error_free(&err);
    442 			return;
    443 		}
    444 
    445 		error("Agent replied with an error: %s, %s",
    446 				err.name, err.message);
    447 
    448 		cb(agent, &err, NULL, req->user_data);
    449 		dbus_error_free(&err);
    450 		goto done;
    451 	}
    452 
    453 	dbus_error_init(&err);
    454 	if (!dbus_message_get_args(message, &err,
    455 				DBUS_TYPE_STRING, &pin,
    456 				DBUS_TYPE_INVALID)) {
    457 		error("Wrong passkey reply signature: %s", err.message);
    458 		cb(agent, &err, NULL, req->user_data);
    459 		dbus_error_free(&err);
    460 		goto done;
    461 	}
    462 
    463 	len = strlen(pin);
    464 
    465 	dbus_error_init(&err);
    466 	if (len > 16 || len < 1) {
    467 		error("Invalid passkey length from handler");
    468 		dbus_set_error_const(&err, "org.bluez.Error.InvalidArgs",
    469 					"Invalid passkey length");
    470 		cb(agent, &err, NULL, req->user_data);
    471 		dbus_error_free(&err);
    472 		goto done;
    473 	}
    474 
    475 	set_pin_length(&sba, len);
    476 
    477 	cb(agent, NULL, pin, req->user_data);
    478 
    479 done:
    480 	if (message)
    481 		dbus_message_unref(message);
    482 
    483 	dbus_pending_call_cancel(req->call);
    484 	agent->request = NULL;
    485 	agent_request_free(req, TRUE);
    486 }
    487 
    488 static int pincode_request_new(struct agent_request *req, const char *device_path,
    489 				dbus_bool_t numeric)
    490 {
    491 	struct agent *agent = req->agent;
    492 
    493 	req->msg = dbus_message_new_method_call(agent->name, agent->path,
    494 					"org.bluez.Agent", "RequestPinCode");
    495 	if (req->msg == NULL) {
    496 		error("Couldn't allocate D-Bus message");
    497 		return -ENOMEM;
    498 	}
    499 
    500 	dbus_message_append_args(req->msg, DBUS_TYPE_OBJECT_PATH, &device_path,
    501 					DBUS_TYPE_INVALID);
    502 
    503 	if (dbus_connection_send_with_reply(connection, req->msg,
    504 					&req->call, REQUEST_TIMEOUT) == FALSE) {
    505 		error("D-Bus send failed");
    506 		return -EIO;
    507 	}
    508 
    509 	dbus_pending_call_set_notify(req->call, pincode_reply, req, NULL);
    510 	return 0;
    511 }
    512 
    513 int agent_request_pincode(struct agent *agent, struct btd_device *device,
    514 				agent_pincode_cb cb, void *user_data,
    515 				GDestroyNotify destroy)
    516 {
    517 	struct agent_request *req;
    518 	const gchar *dev_path = device_get_path(device);
    519 	int err;
    520 
    521 	if (agent->request)
    522 		return -EBUSY;
    523 
    524 	req = agent_request_new(agent, AGENT_REQUEST_PINCODE, cb,
    525 							user_data, destroy);
    526 
    527 	err = pincode_request_new(req, dev_path, FALSE);
    528 	if (err < 0)
    529 		goto failed;
    530 
    531 	agent->request = req;
    532 
    533 	return 0;
    534 
    535 failed:
    536 	g_free(req);
    537 	return err;
    538 }
    539 
    540 static int confirm_mode_change_request_new(struct agent_request *req,
    541 						const char *mode)
    542 {
    543 	struct agent *agent = req->agent;
    544 
    545 	req->msg = dbus_message_new_method_call(agent->name, agent->path,
    546 				"org.bluez.Agent", "ConfirmModeChange");
    547 	if (req->msg == NULL) {
    548 		error("Couldn't allocate D-Bus message");
    549 		return -ENOMEM;
    550 	}
    551 
    552 	dbus_message_append_args(req->msg,
    553 				DBUS_TYPE_STRING, &mode,
    554 				DBUS_TYPE_INVALID);
    555 
    556 	if (dbus_connection_send_with_reply(connection, req->msg,
    557 					&req->call, REQUEST_TIMEOUT) == FALSE) {
    558 		error("D-Bus send failed");
    559 		return -EIO;
    560 	}
    561 
    562 	dbus_pending_call_set_notify(req->call, simple_agent_reply, req, NULL);
    563 	return 0;
    564 }
    565 
    566 int agent_confirm_mode_change(struct agent *agent, const char *new_mode,
    567 				agent_cb cb, void *user_data,
    568 				GDestroyNotify destroy)
    569 {
    570 	struct agent_request *req;
    571 	int err;
    572 
    573 	if (agent->request)
    574 		return -EBUSY;
    575 
    576 	DBG("Calling Agent.ConfirmModeChange: name=%s, path=%s, mode=%s",
    577 			agent->name, agent->path, new_mode);
    578 
    579 	req = agent_request_new(agent, AGENT_REQUEST_CONFIRM_MODE,
    580 				cb, user_data, destroy);
    581 
    582 	err = confirm_mode_change_request_new(req, new_mode);
    583 	if (err < 0)
    584 		goto failed;
    585 
    586 	agent->request = req;
    587 
    588 	return 0;
    589 
    590 failed:
    591 	agent_request_free(req, FALSE);
    592 	return err;
    593 }
    594 
    595 static void passkey_reply(DBusPendingCall *call, void *user_data)
    596 {
    597 	struct agent_request *req = user_data;
    598 	struct agent *agent = req->agent;
    599 	agent_passkey_cb cb = req->cb;
    600 	DBusMessage *message;
    601 	DBusError err;
    602 	uint32_t passkey;
    603 
    604 	/* steal_reply will always return non-NULL since the callback
    605 	 * is only called after a reply has been received */
    606 	message = dbus_pending_call_steal_reply(call);
    607 
    608 	dbus_error_init(&err);
    609 	if (dbus_set_error_from_message(&err, message)) {
    610 		if ((g_str_equal(DBUS_ERROR_UNKNOWN_METHOD, err.name) ||
    611 				g_str_equal(DBUS_ERROR_NO_REPLY, err.name)) &&
    612 				request_fallback(req, passkey_reply) == 0) {
    613 			dbus_error_free(&err);
    614 			return;
    615 		}
    616 
    617 		error("Agent replied with an error: %s, %s",
    618 				err.name, err.message);
    619 		cb(agent, &err, 0, req->user_data);
    620 		dbus_error_free(&err);
    621 		goto done;
    622 	}
    623 
    624 	dbus_error_init(&err);
    625 	if (!dbus_message_get_args(message, &err,
    626 				DBUS_TYPE_UINT32, &passkey,
    627 				DBUS_TYPE_INVALID)) {
    628 		error("Wrong passkey reply signature: %s", err.message);
    629 		cb(agent, &err, 0, req->user_data);
    630 		dbus_error_free(&err);
    631 		goto done;
    632 	}
    633 
    634 	cb(agent, NULL, passkey, req->user_data);
    635 
    636 done:
    637 	if (message)
    638 		dbus_message_unref(message);
    639 
    640 	dbus_pending_call_cancel(req->call);
    641 	agent->request = NULL;
    642 	agent_request_free(req, TRUE);
    643 }
    644 
    645 static int passkey_request_new(struct agent_request *req,
    646 				const char *device_path)
    647 {
    648 	struct agent *agent = req->agent;
    649 
    650 	req->msg = dbus_message_new_method_call(agent->name, agent->path,
    651 					"org.bluez.Agent", "RequestPasskey");
    652 	if (req->msg == NULL) {
    653 		error("Couldn't allocate D-Bus message");
    654 		return -ENOMEM;
    655 	}
    656 
    657 	dbus_message_append_args(req->msg, DBUS_TYPE_OBJECT_PATH, &device_path,
    658 					DBUS_TYPE_INVALID);
    659 
    660 	if (dbus_connection_send_with_reply(connection, req->msg,
    661 					&req->call, REQUEST_TIMEOUT) == FALSE) {
    662 		error("D-Bus send failed");
    663 		return -EIO;
    664 	}
    665 
    666 	dbus_pending_call_set_notify(req->call, passkey_reply, req, NULL);
    667 	return 0;
    668 }
    669 
    670 int agent_request_passkey(struct agent *agent, struct btd_device *device,
    671 				agent_passkey_cb cb, void *user_data,
    672 				GDestroyNotify destroy)
    673 {
    674 	struct agent_request *req;
    675 	const gchar *dev_path = device_get_path(device);
    676 	int err;
    677 
    678 	if (agent->request)
    679 		return -EBUSY;
    680 
    681 	DBG("Calling Agent.RequestPasskey: name=%s, path=%s",
    682 			agent->name, agent->path);
    683 
    684 	req = agent_request_new(agent, AGENT_REQUEST_PASSKEY, cb,
    685 							user_data, destroy);
    686 
    687 	err = passkey_request_new(req, dev_path);
    688 	if (err < 0)
    689 		goto failed;
    690 
    691 	agent->request = req;
    692 
    693 	return 0;
    694 
    695 failed:
    696 	agent_request_free(req, FALSE);
    697 	return err;
    698 }
    699 
    700 static void oob_data_reply(DBusPendingCall *call, void *user_data)
    701 {
    702 	struct agent_request *req = user_data;
    703 	struct agent *agent = req->agent;
    704 	agent_oob_data_cb cb = req->cb;
    705 	DBusMessage *message;
    706 	DBusError err;
    707 	uint8_t *hash_ptr, *r_ptr;
    708         uint8_t hash_len, r_len;
    709 
    710 	/* steal_reply will always return non-NULL since the callback
    711 	 * is only called after a reply has been received */
    712 	message = dbus_pending_call_steal_reply(call);
    713 
    714 	dbus_error_init(&err);
    715 	if (dbus_set_error_from_message(&err, message)) {
    716 		if ((g_str_equal(DBUS_ERROR_UNKNOWN_METHOD, err.name) ||
    717 				g_str_equal(DBUS_ERROR_NO_REPLY, err.name)) &&
    718 				request_fallback(req, oob_data_reply) == 0) {
    719 			dbus_error_free(&err);
    720 			return;
    721 		}
    722 
    723 		error("Agent replied with an error: %s, %s",
    724 				err.name, err.message);
    725 		cb(agent, &err, 0, 0, req->user_data);
    726 		dbus_error_free(&err);
    727 		goto done;
    728 	}
    729 
    730 	if (!dbus_message_get_args(message, &err,
    731 				DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &hash_ptr, &hash_len,
    732 				DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &r_ptr, &r_len,
    733 				DBUS_TYPE_INVALID)) {
    734 		error("Wrong OOB data reply signature: %s", err.message);
    735 		cb(agent, &err, 0, 0, req->user_data);
    736 		dbus_error_free(&err);
    737 		goto done;
    738 	}
    739 
    740 	cb(agent, NULL, hash_ptr, r_ptr, req->user_data);
    741 
    742 done:
    743 	if (message)
    744 		dbus_message_unref(message);
    745 
    746 	dbus_pending_call_cancel(req->call);
    747 	agent->request = NULL;
    748 	agent_request_free(req, TRUE);
    749 }
    750 
    751 static int oob_data_request_new(struct agent_request *req,
    752 				const char *device_path)
    753 {
    754 	struct agent *agent = req->agent;
    755 
    756 	req->msg = dbus_message_new_method_call(agent->name, agent->path,
    757 					"org.bluez.Agent", "RequestOobData");
    758 	if (req->msg == NULL) {
    759 		error("Couldn't allocate D-Bus message");
    760 		return -ENOMEM;
    761 	}
    762 
    763 	dbus_message_append_args(req->msg, DBUS_TYPE_OBJECT_PATH, &device_path,
    764 					DBUS_TYPE_INVALID);
    765 
    766 	if (dbus_connection_send_with_reply(connection, req->msg,
    767 					&req->call, REQUEST_TIMEOUT) == FALSE) {
    768 		error("D-Bus send failed");
    769 		return -EIO;
    770 	}
    771 
    772 	dbus_pending_call_set_notify(req->call, oob_data_reply, req, NULL);
    773 	return 0;
    774 }
    775 
    776 int agent_request_oob_data(struct agent *agent, struct btd_device *device,
    777 				agent_oob_data_cb cb, void *user_data,
    778 				GDestroyNotify destroy)
    779 {
    780 	struct agent_request *req;
    781 	const gchar *dev_path = device_get_path(device);
    782 	int err;
    783 
    784 	if (agent->request)
    785 		return -EBUSY;
    786 
    787 	DBG("Calling Agent.RequestOobData: name=%s, path=%s",
    788 			agent->name, agent->path);
    789 
    790 	req = agent_request_new(agent, AGENT_REQUEST_OOB_DATA, cb,
    791 							user_data, destroy);
    792 
    793 	err = oob_data_request_new(req, dev_path);
    794 	if (err < 0)
    795 		goto failed;
    796 
    797 	agent->request = req;
    798 
    799 	return 0;
    800 
    801 failed:
    802 	agent_request_free(req, FALSE);
    803 	return err;
    804 }
    805 
    806 static int confirmation_request_new(struct agent_request *req,
    807 					const char *device_path,
    808 					uint32_t passkey)
    809 {
    810 	struct agent *agent = req->agent;
    811 
    812 	req->msg = dbus_message_new_method_call(agent->name, agent->path,
    813 				"org.bluez.Agent", "RequestConfirmation");
    814 	if (req->msg == NULL) {
    815 		error("Couldn't allocate D-Bus message");
    816 		return -ENOMEM;
    817 	}
    818 
    819 	dbus_message_append_args(req->msg,
    820 				DBUS_TYPE_OBJECT_PATH, &device_path,
    821 				DBUS_TYPE_UINT32, &passkey,
    822 				DBUS_TYPE_INVALID);
    823 
    824 	if (dbus_connection_send_with_reply(connection, req->msg,
    825 				&req->call, REQUEST_TIMEOUT) == FALSE) {
    826 		error("D-Bus send failed");
    827 		return -EIO;
    828 	}
    829 
    830 	dbus_pending_call_set_notify(req->call, simple_agent_reply, req, NULL);
    831 
    832 	return 0;
    833 }
    834 
    835 int agent_request_confirmation(struct agent *agent, struct btd_device *device,
    836 				uint32_t passkey, agent_cb cb,
    837 				void *user_data, GDestroyNotify destroy)
    838 {
    839 	struct agent_request *req;
    840 	const gchar *dev_path = device_get_path(device);
    841 	int err;
    842 
    843 	if (agent->request)
    844 		return -EBUSY;
    845 
    846 	DBG("Calling Agent.RequestConfirmation: name=%s, path=%s, passkey=%06u",
    847 			agent->name, agent->path, passkey);
    848 
    849 	req = agent_request_new(agent, AGENT_REQUEST_CONFIRMATION, cb,
    850 				user_data, destroy);
    851 
    852 	err = confirmation_request_new(req, dev_path, passkey);
    853 	if (err < 0)
    854 		goto failed;
    855 
    856 	agent->request = req;
    857 
    858 	return 0;
    859 
    860 failed:
    861 	agent_request_free(req, FALSE);
    862 	return err;
    863 }
    864 
    865 static int pairing_consent_request_new(struct agent_request *req,
    866 						const char *device_path)
    867 {
    868 	struct agent *agent = req->agent;
    869 
    870 	req->msg = dbus_message_new_method_call(agent->name, agent->path,
    871 				"org.bluez.Agent", "RequestPairingConsent");
    872 	if (req->msg == NULL) {
    873 		error("Couldn't allocate D-Bus message");
    874 		return -ENOMEM;
    875 	}
    876 
    877 	dbus_message_append_args(req->msg,
    878 				DBUS_TYPE_OBJECT_PATH, &device_path,
    879 				DBUS_TYPE_INVALID);
    880 
    881 	if (dbus_connection_send_with_reply(connection, req->msg,
    882 				&req->call, REQUEST_TIMEOUT) == FALSE) {
    883 		error("D-Bus send failed");
    884 		return -EIO;
    885 	}
    886 
    887 	dbus_pending_call_set_notify(req->call, simple_agent_reply, req, NULL);
    888 
    889 	return 0;
    890 }
    891 
    892 int agent_request_pairing_consent(struct agent *agent, struct btd_device *device,
    893 				agent_cb cb, void *user_data,
    894 				GDestroyNotify destroy)
    895 {
    896 	struct agent_request *req;
    897 	const gchar *dev_path = device_get_path(device);
    898 	int err;
    899 
    900 	if (agent->request)
    901 		return -EBUSY;
    902 
    903 	DBG("Calling Agent.RequestPairingConsent: name=%s, path=%s",
    904 			agent->name, agent->path);
    905 
    906 	req = agent_request_new(agent, AGENT_REQUEST_PAIRING_CONSENT, cb,
    907 				user_data, destroy);
    908 
    909 	err = pairing_consent_request_new(req, dev_path);
    910 	if (err < 0)
    911 		goto failed;
    912 
    913 	agent->request = req;
    914 
    915 	return 0;
    916 
    917 failed:
    918 	agent_request_free(req, FALSE);
    919 	return err;
    920 }
    921 
    922 static int request_fallback(struct agent_request *req,
    923 				DBusPendingCallNotifyFunction function)
    924 {
    925 	struct btd_adapter *adapter = req->agent->adapter;
    926 	struct agent *adapter_agent = adapter_get_agent(adapter);
    927 	DBusMessage *msg;
    928 
    929 	if (req->agent == adapter_agent || adapter_agent == NULL)
    930 		return -EINVAL;
    931 
    932 	dbus_pending_call_cancel(req->call);
    933 
    934 	msg = dbus_message_copy(req->msg);
    935 
    936 	dbus_message_set_destination(msg, adapter_agent->name);
    937 	dbus_message_set_path(msg, adapter_agent->path);
    938 
    939 	if (dbus_connection_send_with_reply(connection, msg,
    940 					&req->call, REQUEST_TIMEOUT) == FALSE) {
    941 		error("D-Bus send failed");
    942 		dbus_message_unref(msg);
    943 		return -EIO;
    944 	}
    945 
    946 	req->agent->request = NULL;
    947 	req->agent = adapter_agent;
    948 	req->agent->request = req;
    949 
    950 	dbus_message_unref(req->msg);
    951 	req->msg = msg;
    952 
    953 	dbus_pending_call_set_notify(req->call, function, req, NULL);
    954 
    955 	return 0;
    956 }
    957 
    958 int agent_display_passkey(struct agent *agent, struct btd_device *device,
    959 				uint32_t passkey)
    960 {
    961 	DBusMessage *message;
    962 	const gchar *dev_path = device_get_path(device);
    963 
    964 	message = dbus_message_new_method_call(agent->name, agent->path,
    965 				"org.bluez.Agent", "DisplayPasskey");
    966 	if (!message) {
    967 		error("Couldn't allocate D-Bus message");
    968 		return -1;
    969 	}
    970 
    971 	dbus_message_append_args(message,
    972 				DBUS_TYPE_OBJECT_PATH, &dev_path,
    973 				DBUS_TYPE_UINT32, &passkey,
    974 				DBUS_TYPE_INVALID);
    975 
    976 	if (!g_dbus_send_message(connection, message)) {
    977 		error("D-Bus send failed");
    978 		dbus_message_unref(message);
    979 		return -1;
    980 	}
    981 
    982 	return 0;
    983 }
    984 
    985 uint8_t agent_get_io_capability(struct agent *agent)
    986 {
    987 	return agent->capability;
    988 }
    989 
    990 gboolean agent_get_oob_capability(struct agent *agent)
    991 {
    992 	return agent->oob;
    993 }
    994 
    995 gboolean agent_matches(struct agent *agent, const char *name, const char *path)
    996 {
    997 	if (g_str_equal(agent->name, name) && g_str_equal(agent->path, path))
    998 		return TRUE;
    999 
   1000 	return FALSE;
   1001 }
   1002 
   1003 gboolean agent_is_busy(struct agent *agent, void *user_data)
   1004 {
   1005 	if (!agent->request)
   1006 		return FALSE;
   1007 
   1008 	if (user_data && user_data != agent->request->user_data)
   1009 		return FALSE;
   1010 
   1011 	return TRUE;
   1012 }
   1013 
   1014 void agent_exit(void)
   1015 {
   1016 	dbus_connection_unref(connection);
   1017 	connection = NULL;
   1018 }
   1019 
   1020 void agent_init(void)
   1021 {
   1022 	connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
   1023 }
   1024