diff options
| -rw-r--r-- | hcid/dbus-adapter.c | 230 | ||||
| -rw-r--r-- | hcid/dbus-error.c | 6 | ||||
| -rw-r--r-- | hcid/dbus.c | 150 | ||||
| -rw-r--r-- | hcid/dbus.h | 12 | ||||
| -rw-r--r-- | hcid/hcid.h | 2 | ||||
| -rw-r--r-- | hcid/security.c | 3 | 
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;  | 
