diff options
| author | Johan Hedberg <johan.hedberg@nokia.com> | 2008-04-15 13:33:00 +0000 | 
|---|---|---|
| committer | Johan Hedberg <johan.hedberg@nokia.com> | 2008-04-15 13:33:00 +0000 | 
| commit | 004de00e5a159c3b11984e9ebda8c3f13d1b5154 (patch) | |
| tree | d8b1a6339ab7c5b9dc45aad55626642850315562 | |
| parent | 9a6a6ed3d45968b7edc63a7fd1579f84d91bbd4d (diff) | |
Make bonding fail and clean up properly if storing the link key fails
| -rw-r--r-- | hcid/security.c | 48 | 
1 files changed, 45 insertions, 3 deletions
| diff --git a/hcid/security.c b/hcid/security.c index 118f9862..f3dedd90 100644 --- a/hcid/security.c +++ b/hcid/security.c @@ -187,6 +187,38 @@ static void check_pending_hci_req(int dev_id, int event)  	hci_req_queue_process(dev_id);  } +static int get_handle(int dev, bdaddr_t *sba, bdaddr_t *dba, uint16_t *handle) +{ +	struct hci_conn_list_req *cl; +	struct hci_conn_info *ci; +	char addr[18]; +	int i; + +	cl = g_malloc0(10 * sizeof(*ci) + sizeof(*cl)); + +	ba2str(sba, addr); +	cl->dev_id = hci_devid(addr); +	cl->conn_num = 10; +	ci = cl->conn_info; + +	if (ioctl(dev, HCIGETCONNLIST, (void *) cl) < 0) { +		g_free(cl); +		return -EIO; +	} + +	for (i = 0; i < cl->conn_num; i++, ci++) { +		if (bacmp(&ci->bdaddr, dba) == 0) { +			*handle = ci->handle; +			g_free(cl); +			return 0; +		} +	} + +	g_free(cl); + +	return -ENOENT; +} +  static inline int get_bdaddr(int dev, bdaddr_t *sba, uint16_t handle, bdaddr_t *dba)  {  	struct hci_conn_list_req *cl; @@ -270,17 +302,27 @@ static void link_key_notify(int dev, bdaddr_t *sba, void *ptr)  	evt_link_key_notify *evt = ptr;  	bdaddr_t *dba = &evt->bdaddr;  	char sa[18], da[18]; -	int dev_id; +	int dev_id, err;  	ba2str(sba, sa); ba2str(dba, da);  	info("link_key_notify (sba=%s, dba=%s)", sa, da);  	dev_id = hci_devid(sa); -	write_link_key(sba, dba, evt->link_key, evt->key_type, +	err = write_link_key(sba, dba, evt->link_key, evt->key_type,  						io_data[dev_id].pin_length); +	if (err < 0) { +		uint16_t handle; + +		error("write_link_key: %s (%d)", strerror(-err), -err); -	hcid_dbus_bonding_process_complete(sba, dba, 0); +		hcid_dbus_bonding_process_complete(sba, dba, HCI_MEMORY_FULL); + +		if (get_handle(dev, sba, dba, &handle) == 0) +			hci_disconnect(dev, htobs(handle), +					HCI_OE_LOW_RESOURCES, 500); +	} else +		hcid_dbus_bonding_process_complete(sba, dba, 0);  	io_data[dev_id].pin_length = -1;  } | 
