summaryrefslogtreecommitdiffstats
path: root/hcid
diff options
context:
space:
mode:
Diffstat (limited to 'hcid')
-rw-r--r--hcid/dbus-adapter.c230
-rw-r--r--hcid/dbus-error.c6
-rw-r--r--hcid/dbus.c150
-rw-r--r--hcid/dbus.h12
-rw-r--r--hcid/hcid.h2
-rw-r--r--hcid/security.c3
6 files changed, 284 insertions, 119 deletions
diff --git a/hcid/dbus-adapter.c b/hcid/dbus-adapter.c
index 3c2e9c5c..2f242d74 100644
--- a/hcid/dbus-adapter.c
+++ b/hcid/dbus-adapter.c
@@ -74,7 +74,7 @@ static const char *phone_minor_cls[] = {
"isdn"
};
-static int is_valid_address(const char *addr)
+static int check_address(const char *addr)
{
char tmp[18];
char *ptr = tmp;
@@ -87,7 +87,7 @@ static int is_valid_address(const char *addr)
memcpy(tmp, addr, 18);
- while (ptr) {
+ while (*ptr) {
*ptr = toupper(*ptr);
if (*ptr < '0'|| (*ptr > '9' && *ptr < 'A') || *ptr > 'F')
@@ -111,28 +111,6 @@ static int is_valid_address(const char *addr)
return 0;
}
-int find_connection_handle(int dd, bdaddr_t *peer)
-{
- struct hci_conn_info_req *cr;
- int handle = -1;
-
- cr = malloc(sizeof(*cr) + sizeof(struct hci_conn_info));
- if (!cr)
- return -1;
-
- bacpy(&cr->bdaddr, peer);
- cr->type = ACL_LINK;
-
- if (ioctl(dd, HCIGETCONNINFO, (unsigned long) cr) < 0) {
- free(cr);
- return -1;
- }
-
- handle = cr->conn_info->handle;
- free(cr);
-
- return handle;
-}
int active_conn_find_by_bdaddr(const void *data, const void *user_data)
{
@@ -145,18 +123,20 @@ int active_conn_find_by_bdaddr(const void *data, const void *user_data)
return -1;
}
-static int bonding_requests_append(struct slist **list, bdaddr_t *bdaddr, DBusMessage *msg, bonding_state_t bonding_state)
+static int bonding_requests_append(struct slist **list, bdaddr_t *bdaddr, DBusMessage *msg, int disconnect)
{
struct bonding_request_info *dev;
dev = malloc(sizeof(*dev));
+
if (!dev)
return -1;
+ memset(dev, 0, sizeof(*dev));
dev->bdaddr = malloc(sizeof(*dev->bdaddr));
bacpy(dev->bdaddr, bdaddr);
- dev->msg = msg;
- dev->bonding_state = bonding_state;
+ dev->req_msg = msg;
+ dev->disconnect = disconnect;
*list = slist_append(*list, dev);
@@ -480,7 +460,7 @@ static DBusHandlerResult handle_dev_is_connected_req(DBusConnection *conn, DBusM
return error_invalid_arguments(conn, msg);
}
- if (is_valid_address(peer_addr) < 0)
+ if (check_address(peer_addr) < 0)
return error_invalid_arguments(conn, msg);
str2ba(peer_addr, &peer_bdaddr);
@@ -953,7 +933,7 @@ static DBusHandlerResult handle_dev_get_remote_name_req(DBusConnection *conn, DB
return error_invalid_arguments(conn, msg);
}
- if (is_valid_address(peer_addr) < 0)
+ if (check_address(peer_addr) < 0)
return error_invalid_arguments(conn, msg);
ecode = get_device_address(dbus_data->dev_id, addr, sizeof(addr));
@@ -1021,7 +1001,7 @@ static DBusHandlerResult handle_dev_get_remote_alias_req(DBusConnection *conn, D
return error_invalid_arguments(conn, msg);
}
- if (is_valid_address(addr_ptr) < 0)
+ if (check_address(addr_ptr) < 0)
return error_invalid_arguments(conn, msg);
str2ba(addr_ptr, &bdaddr);
@@ -1062,7 +1042,7 @@ static DBusHandlerResult handle_dev_set_remote_alias_req(DBusConnection *conn, D
return error_invalid_arguments(conn, msg);
}
- if ((strlen(str_ptr) == 0) || (is_valid_address(addr_ptr) < 0)) {
+ if ((strlen(str_ptr) == 0) || (check_address(addr_ptr) < 0)) {
error("Alias change failed: Invalid parameter");
return error_invalid_arguments(conn, msg);
}
@@ -1110,7 +1090,7 @@ static DBusHandlerResult handle_dev_last_seen_req(DBusConnection *conn, DBusMess
return error_invalid_arguments(conn, msg);
}
- if (is_valid_address(addr_ptr) < 0)
+ if (check_address(addr_ptr) < 0)
return error_invalid_arguments(conn, msg);
ecode = get_device_address(dbus_data->dev_id, addr, sizeof(addr));
@@ -1157,7 +1137,7 @@ static DBusHandlerResult handle_dev_last_used_req(DBusConnection *conn, DBusMess
return error_invalid_arguments(conn, msg);
}
- if (is_valid_address(addr_ptr) < 0)
+ if (check_address(addr_ptr) < 0)
return error_invalid_arguments(conn, msg);
ecode = get_device_address(dbus_data->dev_id, addr, sizeof(addr));
@@ -1190,15 +1170,17 @@ static DBusHandlerResult handle_dev_create_bonding_req(DBusConnection *conn, DBu
char filename[PATH_MAX + 1];
char local_addr[18];
struct hci_request rq;
+ create_conn_cp cc_cp;
+ auth_requested_cp ar_cp;
evt_cmd_status rp;
DBusError err;
char *peer_addr = NULL;
char *str;
struct hci_dbus_data *dbus_data = data;
- struct slist *l;
+ struct slist *lbon;
+ struct slist *lconn;
bdaddr_t peer_bdaddr;
- int dd, handle, ecode;
- bonding_state_t bonding_state;
+ int dd, ecode, disconnect;
dbus_error_init(&err);
dbus_message_get_args(msg, &err,
@@ -1211,17 +1193,20 @@ static DBusHandlerResult handle_dev_create_bonding_req(DBusConnection *conn, DBu
return error_invalid_arguments(conn, msg);
}
- if (is_valid_address(peer_addr) < 0)
+ if (check_address(peer_addr) < 0)
return error_invalid_arguments(conn, msg);
str2ba(peer_addr, &peer_bdaddr);
-
+
/* check if there is a pending bonding request */
- l = slist_find(dbus_data->bonding_requests, &peer_bdaddr, bonding_requests_find);
+ lbon = slist_find(dbus_data->bonding_requests, &peer_bdaddr, bonding_requests_find);
- if (l)
+ if (lbon)
return error_bonding_in_progress(conn, msg);
+ if (dbus_data->requestor_name)
+ return error_discover_in_progress(conn, msg);
+
ecode = get_device_address(dbus_data->dev_id, local_addr, sizeof(local_addr));
if (ecode < 0)
return error_failed(conn, msg, -ecode);
@@ -1256,38 +1241,32 @@ static DBusHandlerResult handle_dev_create_bonding_req(DBusConnection *conn, DBu
rq.rlen = EVT_CMD_STATUS_SIZE;
/* check if there is an active connection */
- handle = find_connection_handle(dd, &peer_bdaddr);
+ lconn = slist_find(dbus_data->active_conn, &peer_bdaddr, active_conn_find_by_bdaddr);
- if (handle < 0 ) {
- create_conn_cp cp;
-
- memset(&cp, 0, sizeof(cp));
+ if (!lconn) {
+ memset(&cc_cp, 0, sizeof(cc_cp));
/* create a new connection */
- bonding_state = CONNECTING;
-
- bacpy(&cp.bdaddr, &peer_bdaddr);
- cp.pkt_type = htobs(HCI_DM1 | HCI_DM3 | HCI_DM5 | HCI_DH1 | HCI_DH3 | HCI_DH5);
- cp.pscan_rep_mode = 0x02;
- cp.clock_offset = htobs(0x0000);
- cp.role_switch = 0x01;
+ bacpy(&cc_cp.bdaddr, &peer_bdaddr);
+ cc_cp.pkt_type = htobs(HCI_DM1);
+ cc_cp.pscan_rep_mode = 0x02;
+ cc_cp.clock_offset = htobs(0x0000);
+ cc_cp.role_switch = 0x01;
rq.ocf = OCF_CREATE_CONN;
- rq.cparam = &cp;
+ rq.cparam = &cc_cp;
rq.clen = CREATE_CONN_CP_SIZE;
+ disconnect = 1;
} else {
- /* connection found */
- auth_requested_cp cp;
-
- memset(&cp, 0, sizeof(cp));
+ struct active_conn_info *dev = lconn->data;
+ memset(&ar_cp, 0, sizeof(ar_cp));
/* active connection found */
- bonding_state = PAIRING;
-
- cp.handle = handle;
+ ar_cp.handle = dev->handle;
rq.ocf = OCF_AUTH_REQUESTED;
- rq.cparam = &cp;
+ rq.cparam = &ar_cp;
rq.clen = AUTH_REQUESTED_CP_SIZE;
+ disconnect = 0;
}
if (hci_send_req(dd, &rq, 100) < 0) {
@@ -1304,14 +1283,124 @@ static DBusHandlerResult handle_dev_create_bonding_req(DBusConnection *conn, DBu
}
/* add in the bonding requests list */
- bonding_requests_append(&dbus_data->bonding_requests, &peer_bdaddr, msg, bonding_state);
+ bonding_requests_append(&dbus_data->bonding_requests, &peer_bdaddr,
+ dbus_message_ref(msg), disconnect);
- dbus_message_ref(msg);
hci_close_dev(dd);
return DBUS_HANDLER_RESULT_HANDLED;
}
+static DBusHandlerResult handle_dev_cancel_bonding_req(DBusConnection *conn, DBusMessage *msg, void *data)
+{
+ struct hci_dbus_data *dbus_data = data;
+ struct bonding_request_info *dev;
+ struct slist *lconn;
+ struct slist *lbon;
+ DBusMessage *reply = NULL;
+ struct hci_request rq;
+ create_conn_cancel_cp cc_cp;
+ disconnect_cp dc_cp;
+ evt_cmd_status rp;
+ DBusError err;
+ bdaddr_t peer_bdaddr;
+ const char *peer_addr;
+ int dd = -1;
+
+ dbus_error_init(&err);
+ dbus_message_get_args(msg, &err,
+ DBUS_TYPE_STRING, &peer_addr,
+ DBUS_TYPE_INVALID);
+
+ if (dbus_error_is_set(&err)) {
+ error("Can't extract message arguments:%s", err.message);
+ dbus_error_free(&err);
+ return error_invalid_arguments(conn, msg);
+ }
+
+ if (check_address(peer_addr) < 0)
+ return error_invalid_arguments(conn, msg);
+
+ /* FIXME: check authorization */
+
+ str2ba(peer_addr, &peer_bdaddr);
+
+ /* check if there is a pending bonding request */
+ lbon = slist_find(dbus_data->bonding_requests, &peer_bdaddr, bonding_requests_find);
+
+ if (!lbon) {
+ error("No bonding request pending.");
+ return error_unknown_address(conn, msg);
+ }
+
+ lconn = slist_find(dbus_data->active_conn, &peer_bdaddr, active_conn_find_by_bdaddr);
+
+ dev = lbon->data;
+
+ dd = hci_open_dev(dbus_data->dev_id);
+ if (dd < 0)
+ return error_no_such_adapter(conn, msg);
+
+ memset(&rq, 0, sizeof(rq));
+ rq.ogf = OGF_LINK_CTL;
+ rq.rparam = &rp;
+ rq.rlen = EVT_CMD_STATUS_SIZE;
+ rq.event = EVT_CMD_STATUS;
+
+ if (!lconn) {
+ /* connection request is pending */
+ memset(&cc_cp, 0, sizeof(cc_cp));
+ bacpy(&cc_cp.bdaddr, dev->bdaddr);
+ rq.ocf = OCF_CREATE_CONN_CANCEL;
+ rq.cparam = &cc_cp;
+ rq.clen = CREATE_CONN_CANCEL_CP_SIZE;
+
+ dev->cancel_msg = dbus_message_ref(msg);
+ } else {
+ struct active_conn_info *cinfo = lconn->data;
+ /* FIXME: if waiting remote PIN, which HCI cmd must be sent? */
+
+ /* reply to cancel bonding */
+ reply = dbus_message_new_method_return(msg);
+ send_reply_and_unref(conn, reply);
+
+ /* Reply to the create bonding request */
+ error_authentication_canceled(conn, dev->req_msg);
+
+ dbus_data->bonding_requests = slist_remove(dbus_data->bonding_requests, dev);
+ bonding_request_info_free(dev, NULL);
+
+ /* disconnect from the remote device */
+
+ /* FIXME: send the disconnect if the connection was created by a create
+ * bonding procedure only. Otherwise, keep the connection active.
+ */
+ memset(&dc_cp, 0, sizeof(dc_cp));
+ dc_cp.handle = cinfo->handle;
+ dc_cp.reason = 0x05;
+ rq.ocf = OCF_DISCONNECT;
+ rq.cparam = &dc_cp;
+ rq.clen = DISCONNECT_CP_SIZE;
+ }
+
+ if (hci_send_req(dd, &rq, 100) < 0) {
+
+ error("Cancel bonding - unable to send the HCI request: %s (%d)",
+ strerror(errno), errno);
+ hci_close_dev(dd);
+ return error_failed(conn, msg, errno);
+ }
+
+ if (rp.status) {
+ error("Cancel bonding - Failed with status 0x%02x", rp.status);
+ hci_close_dev(dd);
+ return error_failed(conn, msg, bt_error(rp.status));
+ }
+
+ hci_close_dev(dd);
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
static DBusHandlerResult handle_dev_remove_bonding_req(DBusConnection *conn, DBusMessage *msg, void *data)
{
struct hci_dbus_data *dbus_data = data;
@@ -1336,7 +1425,7 @@ static DBusHandlerResult handle_dev_remove_bonding_req(DBusConnection *conn, DBu
return error_invalid_arguments(conn, msg);
}
- if (is_valid_address(addr_ptr) < 0)
+ if (check_address(addr_ptr) < 0)
return error_invalid_arguments(conn, msg);
dd = hci_open_dev(dbus_data->dev_id);
@@ -1421,7 +1510,7 @@ static DBusHandlerResult handle_dev_has_bonding_req(DBusConnection *conn, DBusMe
return error_invalid_arguments(conn, msg);
}
- if (is_valid_address(addr_ptr) < 0)
+ if (check_address(addr_ptr) < 0)
return error_invalid_arguments(conn, msg);
ecode = get_device_address(dbus_data->dev_id, addr, sizeof(addr));
@@ -1503,7 +1592,7 @@ static DBusHandlerResult handle_dev_get_pin_code_length_req(DBusConnection *conn
return error_invalid_arguments(conn, msg);
}
- if (is_valid_address(addr_ptr) < 0)
+ if (check_address(addr_ptr) < 0)
return error_invalid_arguments(conn, msg);
ecode = get_device_address(dbus_data->dev_id, addr, sizeof(addr));
@@ -1549,7 +1638,7 @@ static DBusHandlerResult handle_dev_get_encryption_key_size_req(DBusConnection *
return error_invalid_arguments(conn, msg);
}
- if (is_valid_address(addr_ptr) < 0)
+ if (check_address(addr_ptr) < 0)
return error_invalid_arguments(conn, msg);
str2ba(addr_ptr, &bdaddr);
@@ -1618,6 +1707,12 @@ static DBusHandlerResult handle_dev_discover_devices_req(DBusConnection *conn, D
return error_failed(conn, msg, errno);
}
+ if (rp.status) {
+ error("Failed with status 0x%02x", rp.status);
+ hci_close_dev(dd);
+ return error_failed(conn, msg, bt_error(rp.status));
+ }
+
requestor_name = dbus_message_get_sender(msg);
dbus_data->requestor_name = strdup(requestor_name);
@@ -1740,6 +1835,7 @@ static struct service_data dev_services[] = {
{ "LastUsed", handle_dev_last_used_req, },
{ "CreateBonding", handle_dev_create_bonding_req, },
+ { "CancelBonding", handle_dev_cancel_bonding_req },
{ "RemoveBonding", handle_dev_remove_bonding_req, },
{ "HasBonding", handle_dev_has_bonding_req, },
{ "ListBondings", handle_dev_list_bondings_req, },
diff --git a/hcid/dbus-error.c b/hcid/dbus-error.c
index 375456bd..5407da15 100644
--- a/hcid/dbus-error.c
+++ b/hcid/dbus-error.c
@@ -168,6 +168,12 @@ DBusHandlerResult error_bonding_in_progress(DBusConnection *conn, DBusMessage *m
return error_in_progress(conn, msg, "Bonding in progress");
}
+DBusHandlerResult error_authentication_canceled(DBusConnection *conn, DBusMessage *msg)
+{
+ return send_reply_and_unref(conn,
+ dbus_message_new_error(msg, ERROR_INTERFACE ".AuthenticationCanceled",
+ "Authentication Canceled"));
+}
DBusHandlerResult error_discover_in_progress(DBusConnection *conn, DBusMessage *msg)
{
return error_in_progress(conn, msg, "Discover in progress");
diff --git a/hcid/dbus.c b/hcid/dbus.c
index 63da099a..b9525ae1 100644
--- a/hcid/dbus.c
+++ b/hcid/dbus.c
@@ -108,13 +108,16 @@ void disc_device_info_free(void *data, void *user_data)
}
}
-static void bonding_request_info_free(void *data, void *user_data)
+void bonding_request_info_free(void *data, void *user_data)
{
struct bonding_request_info *dev = data;
if (dev) {
free(dev->bdaddr);
- dbus_message_unref(dev->msg);
+ if (dev->req_msg)
+ dbus_message_unref(dev->req_msg);
+ if (dev->cancel_msg)
+ dbus_message_unref(dev->cancel_msg);
free(dev);
}
}
@@ -181,6 +184,7 @@ int disc_device_append(struct slist **list, bdaddr_t *bdaddr, name_status_t name
if (!dev)
return -1;
+ memset(dev, 0, sizeof(*dev));
dev->bdaddr = malloc(sizeof(*dev->bdaddr));
bacpy(dev->bdaddr, bdaddr);
dev->name_status = name_status;
@@ -227,6 +231,7 @@ static int active_conn_append(struct slist **list, bdaddr_t *bdaddr, uint16_t ha
if (!dev)
return -1;
+ memset(dev, 0 , sizeof(*dev));
dev->bdaddr = malloc(sizeof(*dev->bdaddr));
bacpy(dev->bdaddr, bdaddr);
dev->handle = handle;
@@ -504,7 +509,7 @@ gboolean hcid_dbus_register_device(uint16_t id)
}
if (!dbus_connection_get_object_path_data(connection, path, (void *) &pdata))
- error("Getting path data failed!");
+ error("Getting %s path data failed!", path);
else
pdata->mode = rp.enable; /* Keep the current scan status */
@@ -627,6 +632,8 @@ void hcid_dbus_bonding_created_complete(bdaddr_t *local, bdaddr_t *peer, const u
struct hci_dbus_data *pdata;
DBusMessage *msg_reply = NULL;
DBusMessage *msg_signal = NULL;
+ struct bonding_request_info *dev = NULL;
+ struct slist *l;
char *local_addr, *peer_addr;
const char *name;
bdaddr_t tmp;
@@ -658,8 +665,8 @@ void hcid_dbus_bonding_created_complete(bdaddr_t *local, bdaddr_t *peer, const u
}
dbus_message_append_args(msg_signal,
- DBUS_TYPE_STRING, &peer_addr,
- DBUS_TYPE_INVALID);
+ DBUS_TYPE_STRING, &peer_addr,
+ DBUS_TYPE_INVALID);
if (dbus_connection_send(connection, msg_signal, NULL) == FALSE) {
error("Can't send D-Bus bonding created signal");
@@ -669,27 +676,29 @@ void hcid_dbus_bonding_created_complete(bdaddr_t *local, bdaddr_t *peer, const u
dbus_connection_flush(connection);
/* create the authentication reply */
- if (dbus_connection_get_object_path_data(connection, path, (void *) &pdata)) {
- struct slist *l;
+ if (!dbus_connection_get_object_path_data(connection, path, (void *) &pdata)) {
+ error("Getting %s path data failed!", path);
+ goto failed;
+ }
- l = slist_find(pdata->bonding_requests, peer, bonding_requests_find);
+ l = slist_find(pdata->bonding_requests, peer, bonding_requests_find);
- if (l) {
- struct bonding_request_info *dev = l->data;
+ if (!l)
+ goto failed;
- msg_reply = dbus_msg_new_authentication_return(dev->msg, status);
- if (dbus_connection_send(connection, msg_reply, NULL) == FALSE) {
- error("Can't send D-Bus reply for create bonding request");
- goto failed;
- }
+ dev = l->data;
- dbus_message_unref(dev->msg);
- pdata->bonding_requests = slist_remove(pdata->bonding_requests, dev);
- free(dev->bdaddr);
- free(dev);
- }
+ msg_reply = dbus_msg_new_authentication_return(dev->req_msg, status);
+ if (dbus_connection_send(connection, msg_reply, NULL) == FALSE) {
+ error("Can't send D-Bus reply for create bonding request");
+ goto failed;
}
+ /* FIXME: disconnect if required */
+
+ pdata->bonding_requests = slist_remove(pdata->bonding_requests, dev);
+ bonding_request_info_free(dev, NULL);
+
failed:
if (msg_signal)
dbus_message_unref(msg_signal);
@@ -701,6 +710,62 @@ failed:
bt_free(peer_addr);
}
+void hcid_dbus_create_conn_cancel(bdaddr_t *local, void *ptr)
+{
+ typedef struct {
+ uint8_t status;
+ bdaddr_t bdaddr;
+ }__attribute__ ((packed)) ret_param_conn_cancel;
+
+ char path[MAX_PATH_LENGTH];
+ bdaddr_t tmp;
+ ret_param_conn_cancel *ret = ptr + sizeof(evt_cmd_complete);
+ struct bonding_request_info *dev = NULL;
+ DBusMessage *reply;
+ char *local_addr, *peer_addr;
+ struct slist *l;
+ struct hci_dbus_data *pdata;
+ int id;
+
+ baswap(&tmp, local); local_addr = batostr(&tmp);
+ baswap(&tmp, &ret->bdaddr); peer_addr = batostr(&tmp);
+
+ id = hci_devid(local_addr);
+ if (id < 0) {
+ error("No matching device id for %s", local_addr);
+ goto failed;
+ }
+
+ snprintf(path, sizeof(path), "%s/hci%d", ADAPTER_PATH, id);
+ if (!dbus_connection_get_object_path_data(connection, path, (void *) &pdata)) {
+ error("Getting %s path data failed!", path);
+ goto failed;
+ }
+
+ l = slist_find(pdata->bonding_requests, &ret->bdaddr, bonding_requests_find);
+
+ if (!l)
+ goto failed;
+
+ dev = l->data;
+
+ if (!ret->status) {
+ reply = dbus_message_new_method_return(dev->cancel_msg);
+ send_reply_and_unref(connection, reply);
+ } else
+ error_failed(connection, dev->cancel_msg, bt_error(ret->status));
+
+ dbus_message_unref(dev->cancel_msg);
+ dev->cancel_msg = NULL;
+ /* Don't remove from the list. It will be necessary
+ * to return the reply for create bonding request
+ */
+
+failed:
+ bt_free(local_addr);
+ bt_free(peer_addr);
+}
+
void hcid_dbus_inquiry_start(bdaddr_t *local)
{
DBusMessage *message = NULL;
@@ -1117,6 +1182,11 @@ void hcid_dbus_conn_complete(bdaddr_t *local, uint8_t status, uint16_t handle, b
snprintf(path, sizeof(path), "%s/hci%d", ADAPTER_PATH, id);
+ if (!dbus_connection_get_object_path_data(connection, path, (void *) &pdata)) {
+ error("Getting %s path data failed!", path);
+ goto failed;
+ }
+
if (!status) {
/* Sent the remote device connected signal */
message = dbus_message_new_signal(path, ADAPTER_INTERFACE, "RemoteDeviceConnected");
@@ -1126,13 +1196,10 @@ void hcid_dbus_conn_complete(bdaddr_t *local, uint8_t status, uint16_t handle, b
DBUS_TYPE_INVALID);
send_reply_and_unref(connection, message);
- }
-
- if (!dbus_connection_get_object_path_data(connection, path, (void *) &pdata))
- goto failed;
- /* add in the active connetions list */
- active_conn_append(&pdata->active_conn, peer, handle);
+ /* add in the active connetions list */
+ active_conn_append(&pdata->active_conn, peer, handle);
+ }
/* check if this connection request was requested by a bonding procedure */
l = slist_find(pdata->bonding_requests, peer, bonding_requests_find);
@@ -1142,16 +1209,13 @@ void hcid_dbus_conn_complete(bdaddr_t *local, uint8_t status, uint16_t handle, b
dev = l->data;
if (status) {
- error_connection_attempt_failed(connection, dev->msg, bt_error(status));
+ error_connection_attempt_failed(connection, dev->req_msg, bt_error(status));
goto failed;
}
- if (dev->bonding_state != CONNECTING)
- goto failed;
-
dd = hci_open_dev(pdata->dev_id);
if (dd < 0) {
- error_no_such_adapter(connection, dev->msg);
+ error_no_such_adapter(connection, dev->req_msg);
goto failed;
}
@@ -1173,29 +1237,23 @@ void hcid_dbus_conn_complete(bdaddr_t *local, uint8_t status, uint16_t handle, b
if (hci_send_req(dd, &rq, 100) < 0) {
error("Unable to send the HCI request: %s (%d)",
strerror(errno), errno);
- error_failed(connection, dev->msg, errno);
+ error_failed(connection, dev->req_msg, errno);
goto failed;
}
if (rp.status) {
error("Failed with status 0x%02x", rp.status);
- error_failed(connection, dev->msg, bt_error(rp.status));
+ error_failed(connection, dev->req_msg, bt_error(rp.status));
goto failed;
}
- /* request sent properly */
- dev->bonding_state = PAIRING;
-
+ goto done;
failed:
/* remove from the list if the HCI pairing request was not sent */
if (dev) {
- if (dev->bonding_state != PAIRING) {
- dbus_message_unref(dev->msg);
- pdata->bonding_requests = slist_remove(pdata->bonding_requests, dev);
- free(dev->bdaddr);
- free(dev);
- }
+ pdata->bonding_requests = slist_remove(pdata->bonding_requests, dev);
+ bonding_request_info_free(dev, NULL);
}
-
+done:
hci_close_dev(dd);
bt_free(local_addr);
@@ -1223,8 +1281,10 @@ void hcid_dbus_disconn_complete(bdaddr_t *local, uint8_t status, uint16_t handle
snprintf(path, sizeof(path), "%s/hci%d", ADAPTER_PATH, id);
- if (!dbus_connection_get_object_path_data(connection, path, (void *) &pdata))
+ if (!dbus_connection_get_object_path_data(connection, path, (void *) &pdata)) {
+ error("Getting %s path data failed!", path);
goto failed;
+ }
l = slist_find(pdata->active_conn, &handle, active_conn_find_by_handle);
@@ -1739,7 +1799,7 @@ void hcid_dbus_setscan_enable_complete(bdaddr_t *local)
}
if (!dbus_connection_get_object_path_data(connection, path, (void *) &pdata)) {
- error("Getting path data failed!");
+ error("Getting %s path data failed!", path);
goto failed;
}
diff --git a/hcid/dbus.h b/hcid/dbus.h
index 92a673e8..c745fbee 100644
--- a/hcid/dbus.h
+++ b/hcid/dbus.h
@@ -89,15 +89,11 @@ struct discovered_dev_info {
name_status_t name_status;
};
-typedef enum {
- CONNECTING,
- PAIRING
-} bonding_state_t;
-
struct bonding_request_info {
bdaddr_t *bdaddr;
- DBusMessage *msg;
- bonding_state_t bonding_state;
+ DBusMessage *req_msg;
+ DBusMessage *cancel_msg;
+ int disconnect; /* disconnect after finish */
};
struct active_conn_info {
@@ -155,6 +151,7 @@ DBusHandlerResult error_connection_attempt_failed(DBusConnection *conn, DBusMess
DBusHandlerResult error_bonding_already_exists(DBusConnection *conn, DBusMessage *msg);
DBusHandlerResult error_bonding_does_not_exist(DBusConnection *conn, DBusMessage *msg);
DBusHandlerResult error_bonding_in_progress(DBusConnection *conn, DBusMessage *msg);
+DBusHandlerResult error_authentication_canceled(DBusConnection *conn, DBusMessage *msg);
DBusHandlerResult error_discover_in_progress(DBusConnection *conn, DBusMessage *msg);
DBusHandlerResult error_connect_in_progress(DBusConnection *conn, DBusMessage *msg);
DBusHandlerResult error_connect_not_in_progress(DBusConnection *conn, DBusMessage *msg);
@@ -191,6 +188,7 @@ static inline DBusHandlerResult send_reply_and_unref(DBusConnection *conn, DBusM
}
void disc_device_info_free(void *data, void *user_data);
+void bonding_request_info_free(void *data, void *user_data);
int bonding_requests_find(const void *data, const void *user_data);
int disc_device_find_by_bdaddr(const void *data, const void *user_data);
int disc_device_append(struct slist **list, bdaddr_t *bdaddr, name_status_t name_status);
diff --git a/hcid/hcid.h b/hcid/hcid.h
index 71389a62..80357937 100644
--- a/hcid/hcid.h
+++ b/hcid/hcid.h
@@ -119,6 +119,7 @@ void hcid_dbus_remote_name(bdaddr_t *local, bdaddr_t *peer, uint8_t status, char
void hcid_dbus_conn_complete(bdaddr_t *local, uint8_t status, uint16_t handle, bdaddr_t *peer);
void hcid_dbus_disconn_complete(bdaddr_t *local, uint8_t status, uint16_t handle, uint8_t reason);
void hcid_dbus_bonding_created_complete(bdaddr_t *local, bdaddr_t *peer, const uint8_t status);
+void hcid_dbus_create_conn_cancel(bdaddr_t *local, void *ptr);
void hcid_dbus_setname_complete(bdaddr_t *local);
void hcid_dbus_setscan_enable_complete(bdaddr_t *local);
#else
@@ -129,6 +130,7 @@ static inline void hcid_dbus_remote_name(bdaddr_t *local, bdaddr_t *peer, uint8_
static inline void hcid_dbus_conn_complete(bdaddr_t *local, uint8_t status, uint16_t handle, bdaddr_t *peer) {}
static inline void hcid_dbus_disconn_complete(bdaddr_t *local, bdaddr_t *peer, uint8_t reason) {}
static inline void hcid_dbus_bonding_created_complete(bdaddr_t *local, bdaddr_t *peer, const uint8_t status) {}
+static inline void hcid_dbus_create_conn_cancel(bdaddr_t *local, void *ptr) {}
static inline void hcid_dbus_setname_complete(bdaddr_t *local) {}
static inline void hcid_dbus_setscan_enable_complete(bdaddr_t *local) {}
#endif
diff --git a/hcid/security.c b/hcid/security.c
index ba1fb0a1..8946b1c5 100644
--- a/hcid/security.c
+++ b/hcid/security.c
@@ -312,6 +312,9 @@ static inline void cmd_complete(int dev, bdaddr_t *sba, void *ptr)
case cmd_opcode_pack(OGF_LINK_CTL, OCF_INQUIRY_CANCEL):
hcid_dbus_inquiry_complete(sba);
break;
+ case cmd_opcode_pack(OGF_LINK_CTL, OCF_CREATE_CONN_CANCEL):
+ hcid_dbus_create_conn_cancel(sba, ptr);
+ break;
case cmd_opcode_pack(OGF_HOST_CTL, OCF_CHANGE_LOCAL_NAME):
hcid_dbus_setname_complete(sba);
break;