static void init_bdaddr(struct test_data *data) { const uint8_t *master_bdaddr, *client_bdaddr; master_bdaddr = hciemu_get_master_bdaddr(data->hciemu); if (!master_bdaddr) { tester_warn("No master bdaddr"); tester_test_failed(); return; } client_bdaddr = hciemu_get_client_bdaddr(data->hciemu); if (!client_bdaddr) { tester_warn("No client bdaddr"); tester_test_failed(); return; } data->ia_type = LE_PUBLIC_ADDRESS; data->ra_type = LE_PUBLIC_ADDRESS; if (data->out) { memcpy(data->ia, client_bdaddr, sizeof(data->ia)); memcpy(data->ra, master_bdaddr, sizeof(data->ra)); } else { memcpy(data->ia, master_bdaddr, sizeof(data->ia)); memcpy(data->ra, client_bdaddr, sizeof(data->ra)); } }
static int create_sco_sock(struct test_data *data, uint16_t psm) { const uint8_t *master_bdaddr; struct sockaddr_sco addr; int sk, err; sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET | SOCK_NONBLOCK, BTPROTO_SCO); if (sk < 0) { err = -errno; tester_warn("Can't create socket: %s (%d)", strerror(errno), errno); return err; } master_bdaddr = hciemu_get_master_bdaddr(data->hciemu); if (!master_bdaddr) { tester_warn("No master bdaddr"); return -ENODEV; } memset(&addr, 0, sizeof(addr)); addr.sco_family = AF_BLUETOOTH; bacpy(&addr.sco_bdaddr, (void *) master_bdaddr); if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) { err = -errno; tester_warn("Can't bind socket: %s (%d)", strerror(errno), errno); close(sk); return err; } return sk; }
static void test_connect(const void *test_data) { struct test_data *data = tester_get_data(); struct bthost *bthost = hciemu_client_get_host(data->hciemu); const struct rfcomm_client_data *client_data = data->test_data; const uint8_t *client_addr, *master_addr; GIOChannel *io; int sk; bthost_add_l2cap_server(bthost, 0x0003, NULL, NULL); bthost_add_rfcomm_server(bthost, client_data->server_channel, rfcomm_connect_cb, NULL); master_addr = hciemu_get_master_bdaddr(data->hciemu); client_addr = hciemu_get_client_bdaddr(data->hciemu); sk = create_rfcomm_sock((bdaddr_t *) master_addr, 0); if (connect_rfcomm_sock(sk, (const bdaddr_t *) client_addr, client_data->client_channel) < 0) { close(sk); tester_test_failed(); return; } io = g_io_channel_unix_new(sk); g_io_channel_set_close_on_unref(io, TRUE); data->io_id = g_io_add_watch(io, G_IO_OUT, rc_connect_cb, NULL); g_io_channel_unref(io); tester_print("Connect in progress %d", sk); }
static int create_l2cap_sock(struct test_data *data, uint16_t psm, uint16_t cid, int sec_level) { const uint8_t *master_bdaddr; struct sockaddr_l2 addr; int sk, err; sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET | SOCK_NONBLOCK, BTPROTO_L2CAP); if (sk < 0) { err = -errno; tester_warn("Can't create socket: %s (%d)", strerror(errno), errno); return err; } master_bdaddr = hciemu_get_master_bdaddr(data->hciemu); if (!master_bdaddr) { tester_warn("No master bdaddr"); close(sk); return -ENODEV; } memset(&addr, 0, sizeof(addr)); addr.l2_family = AF_BLUETOOTH; addr.l2_psm = htobs(psm); addr.l2_cid = htobs(cid); bacpy(&addr.l2_bdaddr, (void *) master_bdaddr); if (data->hciemu_type == HCIEMU_TYPE_LE) addr.l2_bdaddr_type = BDADDR_LE_PUBLIC; else addr.l2_bdaddr_type = BDADDR_BREDR; if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) { err = -errno; tester_warn("Can't bind socket: %s (%d)", strerror(errno), errno); close(sk); return err; } if (sec_level) { struct bt_security sec; memset(&sec, 0, sizeof(sec)); sec.level = sec_level; if (setsockopt(sk, SOL_BLUETOOTH, BT_SECURITY, &sec, sizeof(sec)) < 0) { err = -errno; tester_warn("Can't set security level: %s (%d)", strerror(errno), errno); close(sk); return err; } } return sk; }
static void test_server(const void *test_data) { struct test_data *data = tester_get_data(); const struct l2cap_data *l2data = data->test_data; const uint8_t *master_bdaddr; uint8_t addr_type; struct bthost *bthost; GIOChannel *io; int sk; if (l2data->server_psm || l2data->cid) { sk = create_l2cap_sock(data, l2data->server_psm, l2data->cid, l2data->sec_level); if (sk < 0) { tester_test_failed(); return; } if (listen(sk, 5) < 0) { tester_warn("listening on socket failed: %s (%u)", strerror(errno), errno); tester_test_failed(); close(sk); return; } io = g_io_channel_unix_new(sk); g_io_channel_set_close_on_unref(io, TRUE); data->io_id = g_io_add_watch(io, G_IO_IN, l2cap_listen_cb, NULL); g_io_channel_unref(io); tester_print("Listening for connections"); } master_bdaddr = hciemu_get_master_bdaddr(data->hciemu); if (!master_bdaddr) { tester_warn("No master bdaddr"); tester_test_failed(); return; } bthost = hciemu_client_get_host(data->hciemu); bthost_set_connect_cb(bthost, send_req_new_conn, data); if (data->hciemu_type == HCIEMU_TYPE_BREDR) addr_type = BDADDR_BREDR; else addr_type = BDADDR_LE_PUBLIC; bthost_hci_connect(bthost, master_bdaddr, addr_type); }
static void test_server(const void *test_data) { struct test_data *data = tester_get_data(); const struct rfcomm_server_data *server_data = data->test_data; const uint8_t *master_addr; struct bthost *bthost; GIOChannel *io; int sk; master_addr = hciemu_get_master_bdaddr(data->hciemu); sk = create_rfcomm_sock((bdaddr_t *) master_addr, server_data->server_channel); if (sk < 0) { tester_test_failed(); return; } if (listen(sk, 5) < 0) { tester_warn("listening on socket failed: %s (%u)", strerror(errno), errno); tester_test_failed(); close(sk); return; } io = g_io_channel_unix_new(sk); g_io_channel_set_close_on_unref(io, TRUE); data->io_id = g_io_add_watch(io, G_IO_IN, rfcomm_listen_cb, NULL); g_io_channel_unref(io); tester_print("Listening for connections"); bthost = hciemu_client_get_host(data->hciemu); bthost_set_connect_cb(bthost, client_new_conn, data); bthost_hci_connect(bthost, master_addr, BDADDR_BREDR); }