From 32c66136e4c4447a483dd42dcb1803a16c2ca3f8 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 12 Jun 2008 11:50:27 +0000 Subject: Track agent request status in conjunction with authentication requests --- hcid/adapter.c | 42 +++++++++++++++++++++++++++++++++--- hcid/adapter.h | 1 + hcid/dbus-hci.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++----------- 3 files changed, 94 insertions(+), 15 deletions(-) diff --git a/hcid/adapter.c b/hcid/adapter.c index 7e434965..281dd86c 100644 --- a/hcid/adapter.c +++ b/hcid/adapter.c @@ -273,7 +273,7 @@ void adapter_auth_request_replied(struct adapter *adapter, bdaddr_t *dba) auth = l->data; - auth->replied = 1; + auth->replied = TRUE; } struct pending_auth_info *adapter_find_auth_request(struct adapter *adapter, @@ -360,11 +360,32 @@ int pending_remote_name_cancel(struct adapter *adapter) return err; } +static int auth_info_agent_cmp(const void *a, const void *b) +{ + const struct pending_auth_info *auth = a; + const struct agent *agent = b; + + if (auth->agent == agent) + return 0; + + return -1; +} + static void device_agent_removed(struct agent *agent, void *user_data) { struct device *device = user_data; + struct pending_auth_info *auth; + GSList *l; device->agent = NULL; + + l = g_slist_find_custom(device->adapter->auth_reqs, agent, + auth_info_agent_cmp); + if (!l) + return; + + auth = l->data; + auth->agent = NULL; } static struct bonding_request_info *bonding_request_new(DBusConnection *conn, @@ -2743,6 +2764,8 @@ static void create_bond_req_exit(void *user_data) auth = adapter_find_auth_request(adapter, &adapter->bonding->bdaddr); if (auth) { cancel_auth_request(auth, adapter->dev_id); + if (auth->agent) + agent_cancel(auth->agent); adapter_remove_auth_request(adapter, &adapter->bonding->bdaddr); } @@ -2881,9 +2904,11 @@ static DBusMessage *adapter_cancel_bonding(DBusConnection *conn, */ g_io_channel_close(adapter->bonding->io); return not_authorized(msg); - } else - cancel_auth_request(auth_req, adapter->dev_id); + } + cancel_auth_request(auth_req, adapter->dev_id); + if (auth_req->agent) + agent_cancel(auth_req->agent); adapter_remove_auth_request(adapter, &bdaddr); } @@ -4080,7 +4105,18 @@ static DBusMessage *find_device(DBusConnection *conn, static void agent_removed(struct agent *agent, struct adapter *adapter) { + struct pending_auth_info *auth; + GSList *l; + adapter->agent = NULL; + + l = g_slist_find_custom(adapter->auth_reqs, agent, + auth_info_agent_cmp); + if (!l) + return; + + auth = l->data; + auth->agent = NULL; } static DBusMessage *register_agent(DBusConnection *conn, diff --git a/hcid/adapter.h b/hcid/adapter.h index cf5bb5f9..f6ed7a22 100644 --- a/hcid/adapter.h +++ b/hcid/adapter.h @@ -76,6 +76,7 @@ struct pending_auth_info { auth_type_t type; bdaddr_t bdaddr; gboolean replied; /* If we've already replied to the request */ + struct agent *agent; /* Agent associated with the request */ }; struct active_conn_info { diff --git a/hcid/dbus-hci.c b/hcid/dbus-hci.c index ef283db8..300181ec 100644 --- a/hcid/dbus-hci.c +++ b/hcid/dbus-hci.c @@ -841,6 +841,7 @@ static void pincode_cb(struct agent *agent, DBusError *err, const char *pincode, bdaddr_t sba, dba; size_t len; int dev; + struct pending_auth_info *auth; /* No need to reply anything if the authentication already failed */ if (adapter->bonding && adapter->bonding->hci_status) @@ -853,9 +854,12 @@ static void pincode_cb(struct agent *agent, DBusError *err, const char *pincode, return; } + str2ba(adapter->address, &sba); str2ba(device->address, &dba); + auth = adapter_find_auth_request(adapter, &dba); + if (err) { hci_send_cmd(dev, OGF_LINK_CTL, OCF_PIN_CODE_NEG_REPLY, 6, &dba); @@ -873,7 +877,10 @@ static void pincode_cb(struct agent *agent, DBusError *err, const char *pincode, hci_send_cmd(dev, OGF_LINK_CTL, OCF_PIN_CODE_REPLY, PIN_CODE_REPLY_CP_SIZE, &pr); done: - adapter_auth_request_replied(adapter, &dba); + if (auth) { + auth->replied = TRUE; + auth->agent = NULL; + } hci_close_dev(dev); } @@ -910,9 +917,13 @@ int hcid_dbus_request_pin(int dev, bdaddr_t *sba, struct hci_conn_info *ci) ret = agent_request_pincode(agent, device, (agent_pincode_cb) pincode_cb, device); - if (ret == 0) - adapter_new_auth_request(adapter, &ci->bdaddr, + if (ret == 0) { + struct pending_auth_info *auth; + auth = adapter_new_auth_request(adapter, &ci->bdaddr, AUTH_TYPE_PINCODE); + auth->agent = agent; + } + return ret; @@ -922,7 +933,6 @@ old_fallback: if (ret == 0) adapter_new_auth_request(adapter, &ci->bdaddr, AUTH_TYPE_PINCODE); - return ret; } @@ -932,6 +942,7 @@ static void confirm_cb(struct agent *agent, DBusError *err, void *user_data) struct adapter *adapter = device->adapter; user_confirm_reply_cp cp; int dd; + struct pending_auth_info *auth; /* No need to reply anything if the authentication already failed */ if (adapter->bonding && adapter->bonding->hci_status) @@ -946,6 +957,8 @@ static void confirm_cb(struct agent *agent, DBusError *err, void *user_data) memset(&cp, 0, sizeof(cp)); str2ba(device->address, &cp.bdaddr); + auth = adapter_find_auth_request(adapter, &cp.bdaddr); + if (err) hci_send_cmd(dd, OGF_LINK_CTL, OCF_USER_CONFIRM_NEG_REPLY, USER_CONFIRM_REPLY_CP_SIZE, &cp); @@ -953,7 +966,10 @@ static void confirm_cb(struct agent *agent, DBusError *err, void *user_data) hci_send_cmd(dd, OGF_LINK_CTL, OCF_USER_CONFIRM_REPLY, USER_CONFIRM_REPLY_CP_SIZE, &cp); - adapter_auth_request_replied(adapter, &cp.bdaddr); + if (auth) { + auth->replied = TRUE; + auth->agent = FALSE; + } hci_close_dev(dd); } @@ -966,6 +982,7 @@ static void passkey_cb(struct agent *agent, DBusError *err, uint32_t passkey, user_passkey_reply_cp cp; bdaddr_t dba; int dd; + struct pending_auth_info *auth; /* No need to reply anything if the authentication already failed */ if (adapter->bonding && adapter->bonding->hci_status) @@ -983,6 +1000,8 @@ static void passkey_cb(struct agent *agent, DBusError *err, uint32_t passkey, bacpy(&cp.bdaddr, &dba); cp.passkey = passkey; + auth = adapter_find_auth_request(adapter, &dba); + if (err) hci_send_cmd(dd, OGF_LINK_CTL, OCF_USER_PASSKEY_NEG_REPLY, 6, &dba); @@ -990,7 +1009,10 @@ static void passkey_cb(struct agent *agent, DBusError *err, uint32_t passkey, hci_send_cmd(dd, OGF_LINK_CTL, OCF_USER_PASSKEY_REPLY, USER_PASSKEY_REPLY_CP_SIZE, &cp); - adapter_auth_request_replied(adapter, &dba); + if (auth) { + auth->replied = TRUE; + auth->agent = NULL; + } hci_close_dev(dd); } @@ -1032,6 +1054,7 @@ int hcid_dbus_user_confirm(bdaddr_t *sba, bdaddr_t *dba, uint32_t passkey) struct agent *agent; char addr[18]; uint8_t type; + struct pending_auth_info *auth; adapter = manager_find_adapter(sba); if (!adapter) { @@ -1060,8 +1083,6 @@ int hcid_dbus_user_confirm(bdaddr_t *sba, bdaddr_t *dba, uint32_t passkey) hci_send_cmd(dd, OGF_LINK_CTL, OCF_USER_CONFIRM_REPLY, USER_CONFIRM_REPLY_CP_SIZE, &cp); - adapter_auth_request_replied(adapter, dba); - hci_close_dev(dd); return 0; @@ -1086,7 +1107,8 @@ int hcid_dbus_user_confirm(bdaddr_t *sba, bdaddr_t *dba, uint32_t passkey) return -1; } - adapter_new_auth_request(adapter, dba, AUTH_TYPE_CONFIRM); + auth = adapter_new_auth_request(adapter, dba, AUTH_TYPE_CONFIRM); + auth->agent = agent; return 0; } @@ -1097,6 +1119,7 @@ int hcid_dbus_user_passkey(bdaddr_t *sba, bdaddr_t *dba) struct device *device; struct agent *agent; char addr[18]; + struct pending_auth_info *auth; adapter = manager_find_adapter(sba); if (!adapter) { @@ -1122,7 +1145,8 @@ int hcid_dbus_user_passkey(bdaddr_t *sba, bdaddr_t *dba) return -1; } - adapter_new_auth_request(adapter, dba, AUTH_TYPE_PASSKEY); + auth = adapter_new_auth_request(adapter, dba, AUTH_TYPE_PASSKEY); + auth->agent = agent; return 0; } @@ -1133,6 +1157,7 @@ int hcid_dbus_user_notify(bdaddr_t *sba, bdaddr_t *dba, uint32_t passkey) struct device *device; struct agent *agent; char addr[18]; + struct pending_auth_info *auth; adapter = manager_find_adapter(sba); if (!adapter) { @@ -1158,7 +1183,8 @@ int hcid_dbus_user_notify(bdaddr_t *sba, bdaddr_t *dba, uint32_t passkey) return -1; } - adapter_new_auth_request(adapter, dba, AUTH_TYPE_NOTIFY); + auth = adapter_new_auth_request(adapter, dba, AUTH_TYPE_NOTIFY); + auth->agent = agent; return 0; } @@ -1173,6 +1199,7 @@ void hcid_dbus_bonding_process_complete(bdaddr_t *local, bdaddr_t *peer, struct device *device; struct bonding_request_info *bonding; gboolean paired = TRUE; + struct pending_auth_info *auth; debug("hcid_dbus_bonding_process_complete: status=%02x", status); @@ -1191,11 +1218,15 @@ void hcid_dbus_bonding_process_complete(bdaddr_t *local, bdaddr_t *peer, adapter->path, peer); } - if (!adapter_find_auth_request(adapter, peer)) { + auth = adapter_find_auth_request(adapter, peer); + if (!auth) { debug("hcid_dbus_bonding_process_complete: no pending auth request"); goto proceed; } + if (auth->agent) + agent_cancel(auth->agent); + adapter_remove_auth_request(adapter, peer); if (status) @@ -1977,10 +2008,16 @@ void hcid_dbus_conn_complete(bdaddr_t *local, uint8_t status, uint16_t handle, ba2str(peer, peer_addr); if (status) { + struct pending_auth_info *auth; + cancel_passkey_agent_requests(adapter->passkey_agents, adapter->path, peer); release_passkey_agents(adapter, peer); + auth = adapter_find_auth_request(adapter, peer); + if (auth && auth->agent) + agent_cancel(auth->agent); + adapter_remove_auth_request(adapter, peer); if (adapter->bonding) @@ -2022,6 +2059,7 @@ void hcid_dbus_disconn_complete(bdaddr_t *local, uint8_t status, struct active_conn_info *dev; GSList *l; gboolean connected = FALSE; + struct pending_auth_info *auth; if (status) { error("Disconnection failed: 0x%02x", status); @@ -2052,6 +2090,10 @@ void hcid_dbus_disconn_complete(bdaddr_t *local, uint8_t status, &dev->bdaddr); release_passkey_agents(adapter, &dev->bdaddr); + auth = adapter_find_auth_request(adapter, &dev->bdaddr); + if (auth && auth->agent) + agent_cancel(auth->agent); + adapter_remove_auth_request(adapter, &dev->bdaddr); /* Check if there is a pending CreateBonding request */ -- cgit