device: Reply br-connection-key-missing on connection bonding error - bluez.git (original) (raw)

Currently when connection is removed while the client is waiting for Connect() the failed message is br-connection-canceled, even if this is due to bonding error. Implement to reply with br-connection-key-missing, when the connection request fails due to a bonding authentication error, allowing the client to differentiate connection failure reasons. This has been tested by: - pair a device - disconnect - edit pairing info to change last character of Key entry of [LinkKey] in /var/lib/bluetooth/<adapter_address>/<device_address>?info - restart bluetoothd - in bluetoothctl, connect <device_address>

diff --git a/src/device.c b/src/device.c
index c364d72c3b..d230af0a8a 100644
--- a/src/device.c
+++ b/src/device.c

@@ -246,6 +246,7 @@ struct btd_device {

struct browse_req *browse; /* service discover request */

struct bonding_req *bonding;

struct authentication_req *authr; /* authentication request */

+ uint8_t bonding_status;

GSList *disconnects; /* disconnects message */

DBusMessage *connect; /* connect message */

DBusMessage *disconnect; /* disconnect message */

@@ -1917,10 +1918,17 @@ void device_request_disconnect(struct btd_device *device, DBusMessage *msg)

}

if (device->connect) {

- DBusMessage *reply = btd_error_failed(device->connect,

- ERR_BREDR_CONN_CANCELED);

+ const char *err_str;

+ DBusMessage *reply;

+ if (device->bonding_status == MGMT_STATUS_AUTH_FAILED)

+ err_str = ERR_BREDR_CONN_KEY_MISSING;

+ else

+ err_str = ERR_BREDR_CONN_CANCELED;

+ reply = btd_error_failed(device->connect, err_str);

g_dbus_send_message(dbus_conn, reply);

dbus_message_unref(device->connect);

+ device->bonding_status = 0;

device->connect = NULL;

}

@@ -6763,6 +6771,10 @@ void device_bonding_complete(struct btd_device *device, uint8_t bdaddr_type,

DBG("bonding %p status 0x%02x", bonding, status);

+ device->bonding_status = status;

+ if (status == MGMT_STATUS_AUTH_FAILED)

+ device_request_disconnect(device, NULL);

if (auth && auth->agent)

agent_cancel(auth->agent);