This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

BLE Reject new devices attempting to pair, only allow old bonded device

Hi All,

I am running nrfConnect SDK v1.8.0 ad started a new sample LBS project. I ultimately want to have 3 devices, 1 being a Central and 2 Peripherals both running LBS. This will be reworked and extended in the future but for now that is fine.

My plan is to initially using the LBS peripheral app on my nrf52840 devkit set it up to allow a single mobile phone to connect and bond. Then reject any new pairing attempts by other phones or devices. If I remove the bonding on the device it will allow phones to pair and bond once again.

Currently, by default it allows only 1 device to bond, but once that device disconnects a new device can pair and hold the connection hostage. While the new device cannot be bonded, it still holds the connection hostage and my other device cannot re-establish a connection. Once I disconnect the new device, my old one can connect and resume its bonded state as it once was.

Thus far for code, I added the bonded device check on boot and load this into a variable so I knows its address.

 

struct
{
	int count;
	bt_addr_le_t addr;
} Bonded;

static void verify_bond(const struct bt_bond_info *info, void *user_data)
{
	Bonded.count++;
	bt_addr_le_copy(&Bonded.addr, &info->addr);

	char str[32];
	bt_addr_to_str(&info->addr.a, str, 18);
	
	
bt_foreach_bond(BT_ID_DEFAULT, verify_bond, NULL);

I also extended the connected callback function to reject all new connections. Though unfortunately as you can see in my printk statements, I am trying to see which address to use to know what to reject the connection based on. I know that all my addresses coming through are doing to be set to Random/Private addressing, so I can't take them on face value.

static void connected(struct bt_conn *conn, uint8_t err)
{
	if (err)
	{
		printk("Connection failed (err %u)\n", err);
		return;
	}

	printk("Connected\n");

	dk_set_led_on(CON_STATUS_LED);

	err = bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
	if (err)
	{
		printk("Disconnection failed (err %d).\n", err);
	}
	else
	{
		char str[32];
		bt_addr_to_str(&conn->le.dst.a, str, 18);
		printk("dst: %s\n", str);

		bt_addr_to_str(&conn->le.init_addr.a, str, 18);
		printk("init: %s\n", str);

		bt_addr_to_str(&conn->le.resp_addr.a, str, 18);
		printk("resp: %s\n", str);

		printk("Disconnection forced success\n");
	}
}

What would be the more appropriate way to do this? I personally don't actually know if the "bond" value is actually my genuine mac address for my device either, or its some special number thingy.

Parents Reply Children
  • Hey Simonr,

    After a bit more playing around I found the answer!

    I couldn't get the remote_info to work as you suggested. The callback function within the bt_conn_cb is never called. Moreover if I do the call manually from the connected callback, it doesn't populate any fields to do with the IRK nor the RPA conversion or confirmation against a previously Public address.

    static void remote_info_available(struct bt_conn *conn, struct bt_conn_remote_info *remote_info)
    {
    	printk("remote info available\n");
    }
    
    static struct bt_conn_cb conn_callbacks = {
    	.connected = connected,
    	.disconnected = disconnected,
    	.identity_resolved = identity_resolved,
    	.remote_info_available = remote_info_available,
    #ifdef CONFIG_BT_LBS_SECURITY_ENABLED
    	.security_changed = security_changed,
    #endif
    };

    After a bit more poking around I found a function buried in the rpa.c file called bt_rpa_irk_matches though after testing it within connected callback, either I am doing something wrong with my irk, or the function wasn't made for this purpose.

    I tried reversing the byte order in case I had the wrong endianess, same result.

    NEVERTHELESS,

    As it turns out, once a device has been bonded, once it enters the connect callback, even if the device has to enter the passkey again, the conn argument (struct bt_conn *conn) contains the target resolved address.

    bt_conn structure has 3 ble addresses that it parses.

    conn->le.init_addr     the address as seen by a sniffer, raw and unresolved. Likely private etc.

    conn->le.dst     if device was previoulsy bonded, this address actually is already resolved with the public one <---- Solution!!

    conn->le.resp_addr     the address of THIS device.

    So by taking the address provided by the destination, I am able to reject any bonded devices!

    Thanks again for your help,

    Ryan.

Related