From: Luiz Augusto von Dentz <luiz.von.dentz@xxxxxxxxx> Instead of pairing HCI directly this uses struct iovec and util_iov* helper functions to parse packets. --- client/hci.c | 8 +- mesh/mesh-io-generic.c | 66 +++++---- src/shared/hci-crypto.c | 16 +-- src/shared/hci.c | 50 +++---- src/shared/hci.h | 4 +- tools/3dsp.c | 116 +++++++++------- tools/advtest.c | 54 ++++---- tools/bluemoon.c | 104 ++++++--------- tools/btattach.c | 11 +- tools/btinfo.c | 19 +-- tools/eddystone.c | 25 ++-- tools/hci-tester.c | 289 +++++++++++++++++++++++++++++----------- tools/ibeacon.c | 25 ++-- 13 files changed, 463 insertions(+), 324 deletions(-) diff --git a/client/hci.c b/client/hci.c index 69fc4ba91707..8c8fe97cb51b 100644 --- a/client/hci.c +++ b/client/hci.c @@ -102,10 +102,10 @@ static uint8_t *str2bytearray(char *arg, size_t *val_len) return util_memdup(value, i); } -static void hci_cmd_complete(const void *data, uint8_t size, void *user_data) +static void hci_cmd_complete(struct iovec *iov, void *user_data) { bt_shell_printf("HCI Command complete:\n"); - bt_shell_hexdump(data, size); + bt_shell_hexdump(iov->iov_base, iov->iov_len); return bt_shell_noninteractive_quit(EXIT_SUCCESS); } @@ -198,12 +198,12 @@ static bool match_event(const void *data, const void *match_data) return evt->event == event; } -static void hci_evt_received(const void *data, uint8_t size, void *user_data) +static void hci_evt_received(struct iovec *iov, void *user_data) { struct hci_event *evt = user_data; bt_shell_printf("HCI Event 0x%02x received:\n", evt->event); - bt_shell_hexdump(data, size); + bt_shell_hexdump(iov->iov_base, iov->iov_len); } static void hci_register(int argc, char *argv[]) diff --git a/mesh/mesh-io-generic.c b/mesh/mesh-io-generic.c index 13a863b48158..eb3dd00451d7 100644 --- a/mesh/mesh-io-generic.c +++ b/mesh/mesh-io-generic.c @@ -18,6 +18,7 @@ #include <ell/ell.h> #include "monitor/bt.h" +#include "src/shared/util.h" #include "src/shared/hci.h" #include "src/shared/mgmt.h" #include "lib/bluetooth.h" @@ -144,14 +145,17 @@ static void event_adv_report(struct mesh_io *io, const void *buf, uint8_t size) } } -static void event_callback(const void *buf, uint8_t size, void *user_data) +static void event_callback(struct iovec *iov, void *user_data) { - uint8_t event = l_get_u8(buf); + uint8_t event; struct mesh_io *io = user_data; + if (!util_iov_pull_u8(iov, &event)) + return; + switch (event) { case BT_HCI_EVT_LE_ADV_REPORT: - event_adv_report(io, buf + 1, size - 1); + event_adv_report(io, iov->iov_base, iov->iov_len); break; default: @@ -159,30 +163,29 @@ static void event_callback(const void *buf, uint8_t size, void *user_data) } } -static void local_commands_callback(const void *data, uint8_t size, - void *user_data) +static void local_commands_callback(struct iovec *iov, void *user_data) { - const struct bt_hci_rsp_read_local_commands *rsp = data; + const struct bt_hci_rsp_read_local_commands *rsp; - if (rsp->status) + rsp = util_iov_pull_mem(iov, sizeof(*rsp)); + if (!rsp || rsp->status) l_error("Failed to read local commands"); } -static void local_features_callback(const void *data, uint8_t size, - void *user_data) +static void local_features_callback(struct iovec *iov, void *user_data) { - const struct bt_hci_rsp_read_local_features *rsp = data; + const struct bt_hci_rsp_read_local_features *rsp; - if (rsp->status) + rsp = util_iov_pull_mem(iov, sizeof(*rsp)); + if (!rsp || rsp->status) l_error("Failed to read local features"); } -static void hci_generic_callback(const void *data, uint8_t size, - void *user_data) +static void hci_generic_callback(struct iovec *iov, void *user_data) { - uint8_t status = l_get_u8(data); + uint8_t status; - if (status) + if (!util_iov_pull_u8(iov, &status) || status) l_error("Failed to initialize HCI"); } @@ -278,17 +281,15 @@ static void configure_hci(struct mesh_io_private *io) sizeof(cmd), hci_generic_callback, NULL, NULL); } -static void scan_enable_rsp(const void *buf, uint8_t size, - void *user_data) +static void scan_enable_rsp(struct iovec *iov, void *user_data) { - uint8_t status = *((uint8_t *) buf); + uint8_t status; - if (status) + if (!util_iov_pull_u8(iov, &status) || status) l_error("LE Scan enable failed (0x%02x)", status); } -static void set_recv_scan_enable(const void *buf, uint8_t size, - void *user_data) +static void set_recv_scan_enable(struct iovec *iov, void *user_data) { struct mesh_io_private *pvt = user_data; struct bt_hci_cmd_le_set_scan_enable cmd; @@ -299,14 +300,13 @@ static void set_recv_scan_enable(const void *buf, uint8_t size, &cmd, sizeof(cmd), scan_enable_rsp, pvt, NULL); } -static void scan_disable_rsp(const void *buf, uint8_t size, - void *user_data) +static void scan_disable_rsp(struct iovec *iov, void *user_data) { struct bt_hci_cmd_le_set_scan_parameters cmd; struct mesh_io_private *pvt = user_data; - uint8_t status = *((uint8_t *) buf); + uint8_t status; - if (status) + if (!util_iov_pull_u8(iov, &status) || status) l_error("LE Scan disable failed (0x%02x)", status); cmd.type = pvt->active ? 0x01 : 0x00; /* Passive/Active scanning */ @@ -452,8 +452,7 @@ static bool dev_caps(struct mesh_io *io, struct mesh_io_caps *caps) return true; } -static void send_cancel_done(const void *buf, uint8_t size, - void *user_data) +static void send_cancel_done(struct iovec *iov, void *user_data) { struct mesh_io_private *pvt = user_data; struct bt_hci_cmd_le_set_random_address cmd; @@ -478,7 +477,7 @@ static void send_cancel(struct mesh_io_private *pvt) return; if (!pvt->sending) { - send_cancel_done(NULL, 0, pvt); + send_cancel_done(NULL, pvt); return; } @@ -488,8 +487,7 @@ static void send_cancel(struct mesh_io_private *pvt) send_cancel_done, pvt, NULL); } -static void set_send_adv_enable(const void *buf, uint8_t size, - void *user_data) +static void set_send_adv_enable(struct iovec *iov, void *user_data) { struct mesh_io_private *pvt = user_data; struct bt_hci_cmd_le_set_adv_enable cmd; @@ -503,8 +501,7 @@ static void set_send_adv_enable(const void *buf, uint8_t size, &cmd, sizeof(cmd), NULL, NULL, NULL); } -static void set_send_adv_data(const void *buf, uint8_t size, - void *user_data) +static void set_send_adv_data(struct iovec *iov, void *user_data) { struct mesh_io_private *pvt = user_data; struct tx_pkt *tx; @@ -535,8 +532,7 @@ done: pvt->tx = NULL; } -static void set_send_adv_params(const void *buf, uint8_t size, - void *user_data) +static void set_send_adv_params(struct iovec *iov, void *user_data) { struct mesh_io_private *pvt = user_data; struct bt_hci_cmd_le_set_adv_parameters cmd; @@ -575,7 +571,7 @@ static void send_pkt(struct mesh_io_private *pvt, struct tx_pkt *tx, pvt->interval = interval; if (!pvt->sending) { - set_send_adv_params(NULL, 0, pvt); + set_send_adv_params(NULL, pvt); return; } diff --git a/src/shared/hci-crypto.c b/src/shared/hci-crypto.c index 5e6dd3e20361..548a943297e7 100644 --- a/src/shared/hci-crypto.c +++ b/src/shared/hci-crypto.c @@ -25,13 +25,13 @@ struct crypto_data { void *user_data; }; -static void le_encrypt_callback(const void *response, uint8_t size, - void *user_data) +static void le_encrypt_callback(struct iovec *iov, void *user_data) { struct crypto_data *data = user_data; - const struct bt_hci_rsp_le_encrypt *rsp = response; + const struct bt_hci_rsp_le_encrypt *rsp; - if (rsp->status) { + rsp = util_iov_pull_mem(iov, sizeof(*rsp)); + if (!rsp || rsp->status) { data->callback(NULL, 0, data->user_data); return; } @@ -66,14 +66,14 @@ static bool le_encrypt(struct bt_hci *hci, uint8_t size, return true; } -static void prand_callback(const void *response, uint8_t size, - void *user_data) +static void prand_callback(struct iovec *iov, void *user_data) { struct crypto_data *data = user_data; - const struct bt_hci_rsp_le_rand *rsp = response; + const struct bt_hci_rsp_le_rand *rsp; uint8_t prand[3]; - if (rsp->status) { + rsp = util_iov_pull_mem(iov, sizeof(*rsp)); + if (!rsp || rsp->status) { data->callback(NULL, 0, data->user_data); return; } diff --git a/src/shared/hci.c b/src/shared/hci.c index 575254c09d25..a3a24dc00a98 100644 --- a/src/shared/hci.c +++ b/src/shared/hci.c @@ -30,6 +30,8 @@ #include "src/shared/queue.h" #include "src/shared/hci.h" +#define HCI_MAX_EVENT_SIZE 260 + #define BTPROTO_HCI 1 struct sockaddr_hci { sa_family_t hci_family; @@ -213,7 +215,7 @@ static bool match_cmd_opcode(const void *a, const void *b) } static void process_response(struct bt_hci *hci, uint16_t opcode, - const void *data, size_t size) + struct iovec *iov) { struct cmd *cmd; @@ -233,7 +235,7 @@ static void process_response(struct bt_hci *hci, uint16_t opcode, bt_hci_ref(hci); if (cmd->callback) - cmd->callback(data, size, cmd->user_data); + cmd->callback(iov, cmd->user_data); cmd_free(cmd); @@ -246,44 +248,42 @@ static void process_notify(void *data, void *user_data) { struct bt_hci_evt_hdr *hdr = user_data; struct evt *evt = data; + struct iovec iov = { hdr + sizeof(*hdr), hdr->plen }; if (evt->event == hdr->evt) - evt->callback(user_data + sizeof(struct bt_hci_evt_hdr), - hdr->plen, evt->user_data); + evt->callback(&iov, evt->user_data); } -static void process_event(struct bt_hci *hci, const void *data, size_t size) +static void process_event(struct bt_hci *hci, struct iovec *iov) { - const struct bt_hci_evt_hdr *hdr = data; + const struct bt_hci_evt_hdr *hdr; const struct bt_hci_evt_cmd_complete *cc; const struct bt_hci_evt_cmd_status *cs; - if (size < sizeof(struct bt_hci_evt_hdr)) + hdr = util_iov_pull_mem(iov, sizeof(*hdr)); + if (!hdr) return; - data += sizeof(struct bt_hci_evt_hdr); - size -= sizeof(struct bt_hci_evt_hdr); - - if (hdr->plen != size) + if (hdr->plen != iov->iov_len) return; switch (hdr->evt) { case BT_HCI_EVT_CMD_COMPLETE: - if (size < sizeof(*cc)) + cc = util_iov_pull_mem(iov, sizeof(*cc)); + if (!cc) return; - cc = data; hci->num_cmds = cc->ncmd; - process_response(hci, le16_to_cpu(cc->opcode), - data + sizeof(*cc), - size - sizeof(*cc)); + process_response(hci, le16_to_cpu(cc->opcode), iov); break; case BT_HCI_EVT_CMD_STATUS: - if (size < sizeof(*cs)) + cs = util_iov_pull_mem(iov, sizeof(*cs)); + if (!cs) return; - cs = data; hci->num_cmds = cs->ncmd; - process_response(hci, le16_to_cpu(cs->opcode), &cs->status, 1); + iov->iov_base = (void *)&cs->status; + iov->iov_len = sizeof(cs->status); + process_response(hci, le16_to_cpu(cs->opcode), iov); break; default: @@ -295,9 +295,11 @@ static void process_event(struct bt_hci *hci, const void *data, size_t size) static bool io_read_callback(struct io *io, void *user_data) { struct bt_hci *hci = user_data; - uint8_t buf[512]; + uint8_t buf[HCI_MAX_EVENT_SIZE]; + struct iovec iov = { buf }; ssize_t len; int fd; + uint8_t h4; fd = io_get_fd(hci->io); if (fd < 0) @@ -310,12 +312,14 @@ static bool io_read_callback(struct io *io, void *user_data) if (len < 0) return false; - if (len < 1) + iov.iov_len = len; + + if (!util_iov_pull_u8(&iov, &h4)) return true; - switch (buf[0]) { + switch (h4) { case BT_H4_EVT_PKT: - process_event(hci, buf + 1, len - 1); + process_event(hci, &iov); break; } diff --git a/src/shared/hci.h b/src/shared/hci.h index 76ee72f54ace..655d410286e3 100644 --- a/src/shared/hci.h +++ b/src/shared/hci.h @@ -10,6 +10,7 @@ #include <stdbool.h> #include <stdint.h> +#include <sys/uio.h> typedef void (*bt_hci_destroy_func_t)(void *user_data); @@ -24,8 +25,7 @@ void bt_hci_unref(struct bt_hci *hci); bool bt_hci_set_close_on_unref(struct bt_hci *hci, bool do_close); -typedef void (*bt_hci_callback_func_t)(const void *data, uint8_t size, - void *user_data); +typedef void (*bt_hci_callback_func_t)(struct iovec *iov, void *user_data); unsigned int bt_hci_send(struct bt_hci *hci, uint16_t opcode, const void *data, uint8_t size, diff --git a/tools/3dsp.c b/tools/3dsp.c index 267a39e9043b..3acfc9c1aa6f 100644 --- a/tools/3dsp.c +++ b/tools/3dsp.c @@ -62,7 +62,7 @@ static bool shutdown_timeout(void *user_data) return false; } -static void shutdown_complete(const void *data, uint8_t size, void *user_data) +static void shutdown_complete(struct iovec *iov, void *user_data) { unsigned int id = PTR_TO_UINT(user_data); @@ -85,11 +85,11 @@ static void shutdown_device(void) mainloop_quit(); } -static void inquiry_started(const void *data, uint8_t size, void *user_data) +static void inquiry_started(struct iovec *iov, void *user_data) { - uint8_t status = *((uint8_t *) data); + uint8_t status; - if (status) { + if (!util_iov_pull_u8(iov, &status) || status) { printf("Failed to search for 3D display\n"); shutdown_device(); return; @@ -112,19 +112,18 @@ static void start_inquiry(void) inquiry_started, NULL, NULL); } -static void set_peripheral_broadcast_receive(const void *data, uint8_t size, - void *user_data) +static void set_peripheral_broadcast_receive(struct iovec *iov, void *user_data) { printf("Peripheral broadcast reception enabled\n"); } -static void sync_train_received(const void *data, uint8_t size, - void *user_data) +static void sync_train_received(struct iovec *iov, void *user_data) { - const struct bt_hci_evt_sync_train_received *evt = data; + const struct bt_hci_evt_sync_train_received *evt; struct bt_hci_cmd_set_peripheral_broadcast_receive cmd; - if (evt->status) { + evt = util_iov_pull_mem(iov, sizeof(*evt)); + if (!evt || evt->status) { printf("Failed to synchronize with 3D display\n"); start_inquiry(); return; @@ -152,13 +151,13 @@ static void sync_train_received(const void *data, uint8_t size, set_peripheral_broadcast_receive, NULL, NULL); } -static void brcm_sync_train_received(const void *data, uint8_t size, - void *user_data) +static void brcm_sync_train_received(struct iovec *iov, void *user_data) { - const struct brcm_evt_sync_train_received *evt = data; + const struct brcm_evt_sync_train_received *evt; struct bt_hci_cmd_set_peripheral_broadcast_receive cmd; - if (evt->status) { + evt = util_iov_pull_mem(iov, sizeof(*evt)); + if (!evt || evt->status) { printf("Failed to synchronize with 3D display\n"); start_inquiry(); return; @@ -186,13 +185,13 @@ static void brcm_sync_train_received(const void *data, uint8_t size, set_peripheral_broadcast_receive, NULL, NULL); } -static void truncated_page_complete(const void *data, uint8_t size, - void *user_data) +static void truncated_page_complete(struct iovec *iov, void *user_data) { - const struct bt_hci_evt_truncated_page_complete *evt = data; + const struct bt_hci_evt_truncated_page_complete *evt; struct bt_hci_cmd_receive_sync_train cmd; - if (evt->status) { + evt = util_iov_pull_mem(iov, sizeof(*evt)); + if (!evt || evt->status) { printf("Failed to contact 3D display\n"); shutdown_device(); return; @@ -209,12 +208,18 @@ static void truncated_page_complete(const void *data, uint8_t size, NULL, NULL, NULL); } -static void peripheral_broadcast_timeout(const void *data, uint8_t size, - void *user_data) +static void peripheral_broadcast_timeout(struct iovec *iov, void *user_data) { - const struct bt_hci_evt_peripheral_broadcast_timeout *evt = data; + const struct bt_hci_evt_peripheral_broadcast_timeout *evt; struct bt_hci_cmd_receive_sync_train cmd; + evt = util_iov_pull_mem(iov, sizeof(*evt)); + if (!evt) { + printf("Failed to synchronize with 3D display\n"); + shutdown_device(); + return; + } + printf("Re-synchronizing with 3D display\n"); memcpy(cmd.bdaddr, evt->bdaddr, 6); @@ -226,13 +231,13 @@ static void peripheral_broadcast_timeout(const void *data, uint8_t size, NULL, NULL, NULL); } -static void peripheral_broadcast_receive(const void *data, uint8_t size, - void *user_data) +static void peripheral_broadcast_receive(struct iovec *iov, void *user_data) { - const struct bt_hci_evt_peripheral_broadcast_receive *evt = data; + const struct bt_hci_evt_peripheral_broadcast_receive *evt; struct bt_hci_cmd_read_clock cmd; - if (evt->status != 0x00) + evt = util_iov_pull_mem(iov, sizeof(*evt)); + if (!evt || evt->status) return; if (le32_to_cpu(evt->clock) != 0x00000000) @@ -245,9 +250,13 @@ static void peripheral_broadcast_receive(const void *data, uint8_t size, NULL, NULL, NULL); } -static void ext_inquiry_result(const void *data, uint8_t size, void *user_data) +static void ext_inquiry_result(struct iovec *iov, void *user_data) { - const struct bt_hci_evt_ext_inquiry_result *evt = data; + const struct bt_hci_evt_ext_inquiry_result *evt; + + evt = util_iov_pull_mem(iov, sizeof(*evt)); + if (!evt) + return; if (evt->dev_class[0] != 0x3c || evt->dev_class[1] != 0x04 || evt->dev_class[2] != 0x08) @@ -270,18 +279,19 @@ static void ext_inquiry_result(const void *data, uint8_t size, void *user_data) } } -static void inquiry_complete(const void *data, uint8_t size, void *user_data) +static void inquiry_complete(struct iovec *iov, void *user_data) { printf("No 3D display found\n"); start_inquiry(); } -static void read_local_version(const void *data, uint8_t size, void *user_data) +static void read_local_version(struct iovec *iov, void *user_data) { - const struct bt_hci_rsp_read_local_version *rsp = data; + const struct bt_hci_rsp_read_local_version *rsp; - if (rsp->status) { + rsp = util_iov_pull_mem(iov, sizeof(*rsp)); + if (!rsp || rsp->status) { printf("Failed to read local version information\n"); shutdown_device(); return; @@ -336,8 +346,7 @@ static void start_glasses(void) static bool sync_train_active = false; -static void sync_train_complete(const void *data, uint8_t size, - void *user_data) +static void sync_train_complete(struct iovec *iov, void *user_data) { sync_train_active = false; } @@ -365,11 +374,15 @@ static void start_sync_train(void) sync_train_active = true; } -static void conn_request(const void *data, uint8_t size, void *user_data) +static void conn_request(struct iovec *io, void *user_data) { - const struct bt_hci_evt_conn_request *evt = data; + const struct bt_hci_evt_conn_request *evt; struct bt_hci_cmd_accept_conn_request cmd; + evt = util_iov_pull_mem(io, sizeof(*evt)); + if (!evt) + return; + printf("Incoming connection from 3D glasses\n"); memcpy(cmd.bdaddr, evt->bdaddr, 6); @@ -381,31 +394,35 @@ static void conn_request(const void *data, uint8_t size, void *user_data) start_sync_train(); } -static void peripheral_page_response_timeout(const void *data, uint8_t size, - void *user_data) +static void peripheral_page_response_timeout(struct iovec *iov, void *user_data) { printf("Incoming truncated page received\n"); start_sync_train(); } -static void peripheral_broadcast_channel_map_change(const void *data, - uint8_t size, void *user_data) +static void peripheral_broadcast_channel_map_change(struct iovec *iov, + void *user_data) { printf("Broadcast channel map changed\n"); start_sync_train(); } -static void inquiry_resp_tx_power(const void *data, uint8_t size, - void *user_data) +static void inquiry_resp_tx_power(struct iovec *iov, void *user_data) { - const struct bt_hci_rsp_read_inquiry_resp_tx_power *rsp = data; + const struct bt_hci_rsp_read_inquiry_resp_tx_power *rsp; struct bt_hci_cmd_write_ext_inquiry_response cmd; uint8_t inqdata[] = { 0x03, 0x3d, 0x03, 0x43, 0x02, 0x0a, 0x00, 0x00 }; uint8_t devclass[] = { 0x3c, 0x04, 0x08 }; uint8_t scanmode = 0x03; + rsp = util_iov_pull_mem(iov, sizeof(*rsp)); + if (!rsp || rsp->status) { + fprintf(stderr, "Failed to read local tx power\n"); + return; + } + inqdata[6] = (uint8_t) rsp->level; cmd.fec = 0x00; @@ -421,13 +438,14 @@ static void inquiry_resp_tx_power(const void *data, uint8_t size, NULL, NULL, NULL); } -static void read_clock(const void *data, uint8_t size, void *user_data) +static void read_clock(struct iovec *iov, void *user_data) { - const struct bt_hci_rsp_read_clock *rsp = data; + const struct bt_hci_rsp_read_clock *rsp; struct broadcast_message msg; uint8_t bcastdata[sizeof(msg) + 3] = { LT_ADDR, 0x03, 0x11, }; - if (rsp->status) { + rsp = util_iov_pull_mem(iov, sizeof(*rsp)); + if (!rsp || rsp->status) { printf("Failed to read local clock information\n"); shutdown_device(); return; @@ -447,13 +465,13 @@ static void read_clock(const void *data, uint8_t size, void *user_data) bcastdata, sizeof(bcastdata), NULL, NULL, NULL); } -static void set_peripheral_broadcast(const void *data, uint8_t size, - void *user_data) +static void set_peripheral_broadcast(struct iovec *iov, void *user_data) { - const struct bt_hci_rsp_set_peripheral_broadcast *rsp = data; + const struct bt_hci_rsp_set_peripheral_broadcast *rsp; struct bt_hci_cmd_read_clock cmd; - if (rsp->status) { + rsp = util_iov_pull_mem(iov, sizeof(*rsp)); + if (!rsp || rsp->status) { printf("Failed to set peripheral broadcast transmission\n"); shutdown_device(); return; diff --git a/tools/advtest.c b/tools/advtest.c index 9ef69ed5124a..d0c00c3b0582 100644 --- a/tools/advtest.c +++ b/tools/advtest.c @@ -146,25 +146,25 @@ static void scan_le_adv_report(const void *data, uint8_t size, } } -static void scan_le_meta_event(const void *data, uint8_t size, - void *user_data) +static void scan_le_meta_event(struct iovec *iov, void *user_data) { - uint8_t evt_code = ((const uint8_t *) data)[0]; + uint8_t evt_code; + + if (!util_iov_pull_u8(iov, &evt_code)) + return; switch (evt_code) { case BT_HCI_EVT_LE_ADV_REPORT: - scan_le_adv_report(data + 1, size - 1, user_data); + scan_le_adv_report(iov->iov_base, iov->iov_len, user_data); break; } } -static void scan_enable_callback(const void *data, uint8_t size, - void *user_data) +static void scan_enable_callback(struct iovec *iov, void *user_data) { } -static void adv_enable_callback(const void *data, uint8_t size, - void *user_data) +static void adv_enable_callback(struct iovec *iov, void *user_data) { struct bt_hci_cmd_le_set_scan_parameters cmd4; struct bt_hci_cmd_le_set_scan_enable cmd5; @@ -186,8 +186,7 @@ static void adv_enable_callback(const void *data, uint8_t size, scan_enable_callback, NULL, NULL); } -static void adv_le_evtmask_callback(const void *data, uint8_t size, - void *user_data) +static void adv_le_evtmask_callback(struct iovec *iov, void *user_data) { struct bt_hci_cmd_le_set_resolv_timeout cmd0; struct bt_hci_cmd_le_add_to_resolv_list cmd1; @@ -244,13 +243,13 @@ static void adv_le_evtmask_callback(const void *data, uint8_t size, adv_enable_callback, NULL, NULL); } -static void adv_le_features_callback(const void *data, uint8_t size, - void *user_data) +static void adv_le_features_callback(struct iovec *iov, void *user_data) { - const struct bt_hci_rsp_le_read_local_features *rsp = data; + const struct bt_hci_rsp_le_read_local_features *rsp; uint8_t evtmask[] = { 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00 }; - if (rsp->status) { + rsp = util_iov_pull_mem(iov, sizeof(*rsp)); + if (!rsp || rsp->status) { fprintf(stderr, "Failed to read local LE features\n"); mainloop_exit_failure(); return; @@ -260,13 +259,13 @@ static void adv_le_features_callback(const void *data, uint8_t size, adv_le_evtmask_callback, NULL, NULL); } -static void adv_features_callback(const void *data, uint8_t size, - void *user_data) +static void adv_features_callback(struct iovec *iov, void *user_data) { - const struct bt_hci_rsp_read_local_features *rsp = data; + const struct bt_hci_rsp_read_local_features *rsp; uint8_t evtmask[] = { 0x90, 0xe8, 0x04, 0x02, 0x00, 0x80, 0x00, 0x20 }; - if (rsp->status) { + rsp = util_iov_pull_mem(iov, sizeof(*rsp)); + if (!rsp || rsp->status) { fprintf(stderr, "Failed to read local features\n"); mainloop_exit_failure(); return; @@ -285,8 +284,7 @@ static void adv_features_callback(const void *data, uint8_t size, adv_le_features_callback, NULL, NULL); } -static void scan_le_evtmask_callback(const void *data, uint8_t size, - void *user_data) +static void scan_le_evtmask_callback(struct iovec *iov, void *user_data) { bt_hci_send(adv_dev, BT_HCI_CMD_RESET, NULL, 0, NULL, NULL, NULL); @@ -294,13 +292,13 @@ static void scan_le_evtmask_callback(const void *data, uint8_t size, adv_features_callback, NULL, NULL); } -static void scan_le_features_callback(const void *data, uint8_t size, - void *user_data) +static void scan_le_features_callback(struct iovec *iov, void *user_data) { - const struct bt_hci_rsp_le_read_local_features *rsp = data; + const struct bt_hci_rsp_le_read_local_features *rsp; uint8_t evtmask[] = { 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00 }; - if (rsp->status) { + rsp = util_iov_pull_mem(iov, sizeof(*rsp)); + if (!rsp || rsp->status) { fprintf(stderr, "Failed to read local LE features\n"); mainloop_exit_failure(); return; @@ -310,13 +308,13 @@ static void scan_le_features_callback(const void *data, uint8_t size, scan_le_evtmask_callback, NULL, NULL); } -static void scan_features_callback(const void *data, uint8_t size, - void *user_data) +static void scan_features_callback(struct iovec *iov, void *user_data) { - const struct bt_hci_rsp_read_local_features *rsp = data; + const struct bt_hci_rsp_read_local_features *rsp; uint8_t evtmask[] = { 0x90, 0xe8, 0x04, 0x02, 0x00, 0x80, 0x00, 0x20 }; - if (rsp->status) { + rsp = util_iov_pull_mem(iov, sizeof(*rsp)); + if (!rsp || rsp->status) { fprintf(stderr, "Failed to read local features\n"); mainloop_exit_failure(); return; diff --git a/tools/bluemoon.c b/tools/bluemoon.c index 9aaf6428da42..d8c4e4d9257e 100644 --- a/tools/bluemoon.c +++ b/tools/bluemoon.c @@ -154,11 +154,11 @@ static bool set_exception = false; static bool reset_on_exit = false; static bool cold_boot = false; -static void reset_complete(const void *data, uint8_t size, void *user_data) +static void reset_complete(struct iovec *iov, void *user_data) { - uint8_t status = *((uint8_t *) data); + uint8_t status; - if (status) { + if (!util_iov_pull_u8(iov, &status) || status) { fprintf(stderr, "Failed to reset (0x%02x)\n", status); mainloop_quit(); return; @@ -167,11 +167,11 @@ static void reset_complete(const void *data, uint8_t size, void *user_data) mainloop_quit(); } -static void cold_boot_complete(const void *data, uint8_t size, void *user_data) +static void cold_boot_complete(struct iovec *iov, void *user_data) { - uint8_t status = *((uint8_t *) data); + uint8_t status; - if (status) { + if (!util_iov_pull_u8(iov, &status) || status) { fprintf(stderr, "Failed to cold boot (0x%02x)\n", status); mainloop_quit(); return; @@ -186,12 +186,11 @@ static void cold_boot_complete(const void *data, uint8_t size, void *user_data) mainloop_quit(); } -static void leave_manufacturer_mode_complete(const void *data, uint8_t size, - void *user_data) +static void leave_manufacturer_mode_complete(struct iovec *iov, void *user_data) { - uint8_t status = *((uint8_t *) data); + uint8_t status; - if (status) { + if (!util_iov_pull_u8(iov, &status) || status) { fprintf(stderr, "Failed to leave manufacturer mode (0x%02x)\n", status); mainloop_quit(); @@ -233,12 +232,11 @@ static void shutdown_device(void) mainloop_quit(); } -static void write_bd_address_complete(const void *data, uint8_t size, - void *user_data) +static void write_bd_address_complete(struct iovec *iov, void *user_data) { - uint8_t status = *((uint8_t *) data); + uint8_t status; - if (status) { + if (!util_iov_pull_u8(iov, &status) || status) { fprintf(stderr, "Failed to write address (0x%02x)\n", status); mainloop_quit(); return; @@ -247,13 +245,13 @@ static void write_bd_address_complete(const void *data, uint8_t size, shutdown_device(); } -static void read_bd_addr_complete(const void *data, uint8_t size, - void *user_data) +static void read_bd_addr_complete(struct iovec *data, void *user_data) { - const struct bt_hci_rsp_read_bd_addr *rsp = data; + const struct bt_hci_rsp_read_bd_addr *rsp; struct cmd_write_bd_address cmd; - if (rsp->status) { + rsp = util_iov_pull_mem(data, sizeof(*rsp)); + if (!rsp || rsp->status) { fprintf(stderr, "Failed to read address (0x%02x)\n", rsp->status); mainloop_quit(); @@ -285,12 +283,11 @@ static void read_bd_addr_complete(const void *data, uint8_t size, write_bd_address_complete, NULL, NULL); } -static void act_deact_traces_complete(const void *data, uint8_t size, - void *user_data) +static void act_deact_traces_complete(struct iovec *iov, void *user_data) { - uint8_t status = *((uint8_t *) data); + uint8_t status; - if (status) { + if (!util_iov_pull_u8(iov, &status) || status) { fprintf(stderr, "Failed to activate traces (0x%02x)\n", status); shutdown_device(); return; @@ -323,12 +320,11 @@ static void trigger_exception(void) shutdown_device(); } -static void write_bd_data_complete(const void *data, uint8_t size, - void *user_data) +static void write_bd_data_complete(struct iovec *iov, void *user_data) { - uint8_t status = *((uint8_t *) data); + uint8_t status; - if (status) { + if (!util_iov_pull_u8(iov, &status) || status) { fprintf(stderr, "Failed to write data (0x%02x)\n", status); shutdown_device(); return; @@ -342,13 +338,13 @@ static void write_bd_data_complete(const void *data, uint8_t size, shutdown_device(); } -static void read_bd_data_complete(const void *data, uint8_t size, - void *user_data) +static void read_bd_data_complete(struct iovec *iov, void *user_data) { - const struct rsp_read_bd_data *rsp = data; + const struct rsp_read_bd_data *rsp; - if (rsp->status) { - fprintf(stderr, "Failed to read data (0x%02x)\n", rsp->status); + rsp = util_iov_pull_mem(iov, sizeof(*rsp)); + if (!rsp || rsp->status) { + fprintf(stderr, "Failed to read data\n"); shutdown_device(); return; } @@ -389,12 +385,11 @@ static void read_bd_data_complete(const void *data, uint8_t size, shutdown_device(); } -static void firmware_command_complete(const void *data, uint8_t size, - void *user_data) +static void firmware_command_complete(struct iovec *iov, void *user_data) { - uint8_t status = *((uint8_t *) data); + uint8_t status; - if (status) { + if (!util_iov_pull_u8(iov, &status) || status) { fprintf(stderr, "Failed to load firmware (0x%02x)\n", status); manufacturer_mode_reset = 0x01; shutdown_device(); @@ -434,12 +429,11 @@ static void firmware_command_complete(const void *data, uint8_t size, } -static void enter_manufacturer_mode_complete(const void *data, uint8_t size, - void *user_data) +static void enter_manufacturer_mode_complete(struct iovec *iov, void *user_data) { - uint8_t status = *((uint8_t *) data); + uint8_t status; - if (status) { + if (!util_iov_pull_u8(iov, &status) || status) { fprintf(stderr, "Failed to enter manufacturer mode (0x%02x)\n", status); mainloop_quit(); @@ -448,7 +442,9 @@ static void enter_manufacturer_mode_complete(const void *data, uint8_t size, if (load_firmware) { uint8_t status = BT_HCI_ERR_SUCCESS; - firmware_command_complete(&status, sizeof(status), NULL); + struct iovec data = { &status, sizeof(status) }; + + firmware_command_complete(&data, NULL); return; } @@ -563,24 +559,18 @@ static void request_firmware(const char *path) firmware_offset = 1; } -static void read_boot_params_complete(const void *data, uint8_t size, - void *user_data) +static void read_boot_params_complete(struct iovec *iov, void *user_data) { - const struct rsp_read_boot_params *rsp = data; + const struct rsp_read_boot_params *rsp; - if (rsp->status) { + rsp = util_iov_pull_mem(iov, sizeof(*rsp)); + if (!rsp || rsp->status) { fprintf(stderr, "Failed to read boot params (0x%02x)\n", rsp->status); mainloop_quit(); return; } - if (size != sizeof(*rsp)) { - fprintf(stderr, "Size mismatch for read boot params\n"); - mainloop_quit(); - return; - } - printf("Secure Boot Parameters\n"); printf("\tOTP Format Version:\t%u\n", rsp->otp_format); printf("\tOTP Content Version:\t%u\n", rsp->otp_content); @@ -628,26 +618,20 @@ static const struct { { } }; -static void read_version_complete(const void *data, uint8_t size, - void *user_data) +static void read_version_complete(struct iovec *iov, void *user_data) { - const struct rsp_read_version *rsp = data; + const struct rsp_read_version *rsp; const char *str; int i; - if (rsp->status) { + rsp = util_iov_pull_mem(iov, sizeof(*rsp)); + if (!rsp || rsp->status) { fprintf(stderr, "Failed to read version (0x%02x)\n", rsp->status); mainloop_quit(); return; } - if (size != sizeof(*rsp)) { - fprintf(stderr, "Size mismatch for read version response\n"); - mainloop_quit(); - return; - } - if (cold_boot) { struct cmd_reset cmd; diff --git a/tools/btattach.c b/tools/btattach.c index 4ce1be78d69c..4e9a94e6de8b 100644 --- a/tools/btattach.c +++ b/tools/btattach.c @@ -88,10 +88,15 @@ static int open_serial(const char *path, unsigned int speed, bool flowctl) return fd; } -static void local_version_callback(const void *data, uint8_t size, - void *user_data) +static void local_version_callback(struct iovec *iov, void *user_data) { - const struct bt_hci_rsp_read_local_version *rsp = data; + const struct bt_hci_rsp_read_local_version *rsp; + + rsp = util_iov_pull_mem(iov, sizeof(*rsp)); + if (!rsp || rsp->status) { + fprintf(stderr, "Failed to read local version\n"); + return; + } printf("Manufacturer: %u\n", le16_to_cpu(rsp->manufacturer)); } diff --git a/tools/btinfo.c b/tools/btinfo.c index 5f3650c782bd..60521530fd56 100644 --- a/tools/btinfo.c +++ b/tools/btinfo.c @@ -83,7 +83,7 @@ static bool shutdown_timeout(void *user_data) return false; } -static void shutdown_complete(const void *data, uint8_t size, void *user_data) +static void shutdown_complete(struct iovec *iov, void *user_data) { unsigned int id = PTR_TO_UINT(user_data); @@ -106,10 +106,15 @@ static void shutdown_device(void) mainloop_quit(); } -static void local_version_callback(const void *data, uint8_t size, - void *user_data) +static void local_version_callback(struct iovec *iov, void *user_data) { - const struct bt_hci_rsp_read_local_version *rsp = data; + const struct bt_hci_rsp_read_local_version *rsp; + + rsp = util_iov_pull_mem(iov, sizeof(*rsp)); + if (!rsp || rsp->status) { + fprintf(stderr, "Failed to read local version\n"); + return; + } printf("HCI version: %u\n", rsp->hci_ver); printf("HCI revision: %u\n", le16_to_cpu(rsp->hci_rev)); @@ -128,14 +133,12 @@ static void local_version_callback(const void *data, uint8_t size, printf("Manufacturer: %u\n", le16_to_cpu(rsp->manufacturer)); } -static void local_commands_callback(const void *data, uint8_t size, - void *user_data) +static void local_commands_callback(struct iovec *iov, void *user_data) { shutdown_device(); } -static void local_features_callback(const void *data, uint8_t size, - void *user_data) +static void local_features_callback(struct iovec *iov, void *user_data) { bt_hci_send(hci_dev, BT_HCI_CMD_READ_LOCAL_COMMANDS, NULL, 0, local_commands_callback, NULL, NULL); diff --git a/tools/eddystone.c b/tools/eddystone.c index 4a593e823027..4c26d1b9042d 100644 --- a/tools/eddystone.c +++ b/tools/eddystone.c @@ -39,7 +39,7 @@ static bool shutdown_timeout(void *user_data) return false; } -static void shutdown_complete(const void *data, uint8_t size, void *user_data) +static void shutdown_complete(struct iovec *iov, void *user_data) { unsigned int id = PTR_TO_UINT(user_data); @@ -106,12 +106,11 @@ static void set_adv_enable(void) &enable, 1, NULL, NULL, NULL); } -static void adv_data_callback(const void *data, uint8_t size, - void *user_data) +static void adv_data_callback(struct iovec *iov, void *user_data) { - uint8_t status = *((uint8_t *) data); + uint8_t status; - if (status) { + if (util_iov_pull_u8(iov, &status) || status) { fprintf(stderr, "Failed to set advertising data\n"); shutdown_device(); return; @@ -122,13 +121,13 @@ static void adv_data_callback(const void *data, uint8_t size, set_adv_enable(); } -static void adv_tx_power_callback(const void *data, uint8_t size, - void *user_data) +static void adv_tx_power_callback(struct iovec *iov, void *user_data) { - const struct bt_hci_rsp_le_read_adv_tx_power *rsp = data; + const struct bt_hci_rsp_le_read_adv_tx_power *rsp; struct bt_hci_cmd_le_set_adv_data cmd; - if (rsp->status) { + rsp = util_iov_pull_mem(iov, sizeof(*rsp)); + if (rsp || rsp->status) { fprintf(stderr, "Failed to read advertising TX power\n"); shutdown_device(); return; @@ -166,12 +165,12 @@ static void adv_tx_power_callback(const void *data, uint8_t size, adv_data_callback, NULL, NULL); } -static void local_features_callback(const void *data, uint8_t size, - void *user_data) +static void local_features_callback(struct iovec *iov, void *user_data) { - const struct bt_hci_rsp_read_local_features *rsp = data; + const struct bt_hci_rsp_read_local_features *rsp; - if (rsp->status) { + rsp = util_iov_pull_mem(iov, sizeof(*rsp)); + if (!rsp || rsp->status) { fprintf(stderr, "Failed to read local features\n"); shutdown_device(); return; diff --git a/tools/hci-tester.c b/tools/hci-tester.c index 79193220feec..e529f7c365c7 100644 --- a/tools/hci-tester.c +++ b/tools/hci-tester.c @@ -51,11 +51,17 @@ static void test_debug(const char *str, void *user_data) tester_debug("%s", str); } -static void test_pre_setup_lt_address(const void *data, uint8_t size, - void *user_data) +static void test_pre_setup_lt_address(struct iovec *data, void *user_data) { struct user_data *user = tester_get_data(); - const struct bt_hci_rsp_read_bd_addr *rsp = data; + const struct bt_hci_rsp_read_bd_addr *rsp; + + rsp = util_iov_pull_mem(data, sizeof(*rsp)); + if (!rsp) { + tester_warn("Invalid response (length too short)"); + tester_pre_setup_failed(); + return; + } if (rsp->status) { tester_warn("Read lower tester address failed (0x%02x)", @@ -69,11 +75,16 @@ static void test_pre_setup_lt_address(const void *data, uint8_t size, tester_pre_setup_complete(); } -static void test_pre_setup_lt_complete(const void *data, uint8_t size, - void *user_data) +static void test_pre_setup_lt_complete(struct iovec *iov, void *user_data) { struct user_data *user = tester_get_data(); - uint8_t status = *((uint8_t *) data); + uint8_t status; + + if (!util_iov_pull_u8(iov, &status)) { + tester_warn("Invalid response (length too short)"); + tester_pre_setup_failed(); + return; + } if (status) { tester_warn("Reset lower tester failed (0x%02x)", status); @@ -89,11 +100,17 @@ static void test_pre_setup_lt_complete(const void *data, uint8_t size, } } -static void test_pre_setup_ut_address(const void *data, uint8_t size, - void *user_data) +static void test_pre_setup_ut_address(struct iovec *iov, void *user_data) { struct user_data *user = tester_get_data(); - const struct bt_hci_rsp_read_bd_addr *rsp = data; + const struct bt_hci_rsp_read_bd_addr *rsp; + + rsp = util_iov_pull_mem(iov, sizeof(*rsp)); + if (!rsp) { + tester_warn("Invalid response (length too short)"); + tester_pre_setup_failed(); + return; + } if (rsp->status) { tester_warn("Read upper tester address failed (0x%02x)", @@ -119,11 +136,16 @@ static void test_pre_setup_ut_address(const void *data, uint8_t size, } } -static void test_pre_setup_ut_complete(const void *data, uint8_t size, - void *user_data) +static void test_pre_setup_ut_complete(struct iovec *iov, void *user_data) { struct user_data *user = tester_get_data(); - uint8_t status = *((uint8_t *) data); + uint8_t status; + + if (!util_iov_pull_u8(iov, &status)) { + tester_warn("Invalid response (length too short)"); + tester_pre_setup_failed(); + return; + } if (status) { tester_warn("Reset upper tester failed (0x%02x)", status); @@ -211,10 +233,16 @@ static void user_data_free(void *data) test_post_teardown, 30, user, user_data_free); \ } while (0) -static void setup_features_complete(const void *data, uint8_t size, - void *user_data) +static void setup_features_complete(struct iovec *iov, void *user_data) { - const struct bt_hci_rsp_read_local_features *rsp = data; + const struct bt_hci_rsp_read_local_features *rsp; + + rsp = util_iov_pull_mem(iov, sizeof(*rsp)); + if (!rsp) { + tester_warn("Invalid response (length too short)"); + tester_setup_failed(); + return; + } if (rsp->status) { tester_warn("Failed to get HCI features (0x%02x)", rsp->status); @@ -242,10 +270,15 @@ static void test_reset(const void *test_data) tester_test_passed(); } -static void test_command_complete(const void *data, uint8_t size, - void *user_data) +static void test_command_complete(struct iovec *iov, void *user_data) { - uint8_t status = *((uint8_t *) data); + uint8_t status; + + if (!util_iov_pull_u8(iov, &status)) { + tester_warn("Invalid response (length too short)"); + tester_test_failed(); + return; + } if (status) { tester_warn("HCI command failed (0x%02x)", status); @@ -283,10 +316,17 @@ static void test_read_local_supported_features(const void *test_data) test_command(BT_HCI_CMD_READ_LOCAL_FEATURES); } -static void test_local_extended_features_complete(const void *data, - uint8_t size, void *user_data) +static void test_local_extended_features_complete(struct iovec *iov, + void *user_data) { - const struct bt_hci_rsp_read_local_ext_features *rsp = data; + const struct bt_hci_rsp_read_local_ext_features *rsp; + + rsp = util_iov_pull_mem(iov, sizeof(*rsp)); + if (!rsp) { + tester_warn("Invalid response (length too short)"); + tester_test_failed(); + return; + } if (rsp->status) { tester_warn("Failed to get HCI extended features (0x%02x)", @@ -308,7 +348,7 @@ static void test_read_local_extended_features(const void *test_data) if (!bt_hci_send(user->hci_ut, BT_HCI_CMD_READ_LOCAL_EXT_FEATURES, &cmd, sizeof(cmd), test_local_extended_features_complete, - NULL, NULL)) { + NULL, NULL)) { tester_warn("Failed to send HCI extended features command"); tester_test_failed(); return; @@ -345,16 +385,22 @@ static void test_le_clear_accept_list(const void *test_data) test_command(BT_HCI_CMD_LE_CLEAR_ACCEPT_LIST); } -static void test_le_encrypt_complete(const void *data, uint8_t size, - void *user_data) +static void test_le_encrypt_complete(struct iovec *iov, void *user_data) { - const struct bt_hci_rsp_le_encrypt *rsp = data; + const struct bt_hci_rsp_le_encrypt *rsp; uint8_t sample[16] = { 0x7d, 0xf7, 0x6b, 0x0c, 0x1a, 0xb8, 0x99, 0xb3, 0x3e, 0x42, 0xf0, 0x47, 0xb9, 0x1b, 0x54, 0x6f }; uint8_t enc_data[16]; + rsp = util_iov_pull_mem(iov, sizeof(*rsp)); + if (!rsp) { + tester_warn("Invalid response (length too short)"); + tester_test_failed(); + return; + } + if (rsp->status) { tester_warn("Failed HCI LE Encrypt (0x%02x)", rsp->status); tester_test_failed(); @@ -404,20 +450,31 @@ static void test_le_rand(const void *test_data) test_command(BT_HCI_CMD_LE_RAND); } -static void test_le_read_local_pk_complete(const void *data, uint8_t size, - void *user_data) +static void test_le_read_local_pk_complete(struct iovec *iov, void *user_data) { - const uint8_t *event = data; + uint8_t event; const struct bt_hci_evt_le_read_local_pk256_complete *evt; struct le_keys *keys = user_data; - if (*event != BT_HCI_EVT_LE_READ_LOCAL_PK256_COMPLETE) { + if (!util_iov_pull_u8(iov, &event)) { + tester_warn("Invalid response (length too short)"); + tester_test_failed(); + return; + } + + if (event != BT_HCI_EVT_LE_READ_LOCAL_PK256_COMPLETE) { tester_warn("Failed Read Local PK256 command"); tester_test_failed(); return; } - evt = (void *)(event + 1); + evt = util_iov_pull_mem(iov, sizeof(*evt)); + if (!evt) { + tester_warn("Invalid response (length too short)"); + tester_test_failed(); + return; + } + if (evt->status) { tester_warn("HCI Read Local PK complete failed (0x%02x)", evt->status); @@ -432,13 +489,13 @@ static void test_le_read_local_pk_complete(const void *data, uint8_t size, tester_test_passed(); } -static void test_le_read_local_pk_status(const void *data, uint8_t size, - void *user_data) +static void test_le_read_local_pk_status(struct iovec *iov, void *user_data) { - uint8_t status = *((uint8_t *) data); + uint8_t status; - if (status) { - tester_warn("Failed to send Read Local PK256 cmd (0x%02x)", status); + if (!util_iov_pull_u8(iov, &status) || status) { + tester_warn("Failed to send Read Local PK256 cmd (0x%02x)", + status); tester_test_failed(); return; } @@ -477,20 +534,31 @@ static void test_le_read_local_pk(const void *test_data) } } -static void setup_le_read_local_pk_complete(const void *data, uint8_t size, - void *user_data) +static void setup_le_read_local_pk_complete(struct iovec *iov, void *user_data) { - const uint8_t *event = data; + uint8_t event; const struct bt_hci_evt_le_read_local_pk256_complete *evt; struct le_keys *keys = user_data; - if (*event != BT_HCI_EVT_LE_READ_LOCAL_PK256_COMPLETE) { + if (!util_iov_pull_u8(iov, &event)) { + tester_warn("Invalid response (length too short)"); + tester_setup_failed(); + return; + } + + if (event != BT_HCI_EVT_LE_READ_LOCAL_PK256_COMPLETE) { tester_warn("Failed Read Local PK256 command"); tester_setup_failed(); return; } - evt = (void *)(event + 1); + evt = util_iov_pull_mem(iov, sizeof(*evt)); + if (!evt) { + tester_warn("Invalid response (length too short)"); + tester_setup_failed(); + return; + } + if (evt->status) { tester_warn("HCI Read Local PK complete failed (0x%02x)", evt->status); @@ -505,10 +573,15 @@ static void setup_le_read_local_pk_complete(const void *data, uint8_t size, tester_setup_complete(); } -static void setup_le_read_local_pk_status(const void *data, uint8_t size, - void *user_data) +static void setup_le_read_local_pk_status(struct iovec *iov, void *user_data) { - uint8_t status = *((uint8_t *) data); + uint8_t status; + + if (!util_iov_pull_u8(iov, &status)) { + tester_warn("Invalid response (length too short)"); + tester_setup_failed(); + return; + } if (status) { tester_warn("Failed to send DHKey gen cmd (0x%02x)", status); @@ -551,21 +624,32 @@ static void setup_le_generate_dhkey(const void *test_data) } } -static void test_le_generate_dhkey_complete(const void *data, uint8_t size, - void *user_data) +static void test_le_generate_dhkey_complete(struct iovec *iov, void *user_data) { - const uint8_t *event = data; + uint8_t event; const struct bt_hci_evt_le_generate_dhkey_complete *evt; struct le_keys *keys = user_data; uint8_t dhkey[32]; - if (*event != BT_HCI_EVT_LE_GENERATE_DHKEY_COMPLETE) { + if (!util_iov_pull_u8(iov, &event)) { + tester_warn("Invalid response (length too short)"); + tester_test_failed(); + return; + } + + if (event != BT_HCI_EVT_LE_GENERATE_DHKEY_COMPLETE) { tester_warn("Failed DHKey generation command"); tester_test_failed(); return; } - evt = (void *)(event + 1); + evt = util_iov_pull_mem(iov, sizeof(*evt)); + if (!evt) { + tester_warn("Invalid response (length too short)"); + tester_test_failed(); + return; + } + if (evt->status) { tester_warn("HCI Generate DHKey complete failed (0x%02x)", evt->status); @@ -593,12 +677,11 @@ static void test_le_generate_dhkey_complete(const void *data, uint8_t size, tester_test_failed(); } -static void test_le_generate_dhkey_status(const void *data, uint8_t size, - void *user_data) +static void test_le_generate_dhkey_status(struct iovec *iov, void *user_data) { - uint8_t status = *((uint8_t *) data); + uint8_t status; - if (status) { + if (util_iov_pull_u8(iov, &status) || status) { tester_warn("Failed to send DHKey gen cmd (0x%02x)", status); tester_test_failed(); return; @@ -630,10 +713,16 @@ static void test_le_generate_dhkey(const void *test_data) } -static void test_inquiry_complete(const void *data, uint8_t size, - void *user_data) +static void test_inquiry_complete(struct iovec *iov, void *user_data) { - const struct bt_hci_evt_inquiry_complete *evt = data; + const struct bt_hci_evt_inquiry_complete *evt; + + evt = util_iov_pull_mem(iov, sizeof(*evt)); + if (!iov) { + tester_warn("Invalid response (length too short)"); + tester_test_failed(); + return; + } if (evt->status) { tester_warn("HCI inquiry complete failed (0x%02x)", @@ -645,10 +734,15 @@ static void test_inquiry_complete(const void *data, uint8_t size, tester_test_passed(); } -static void test_inquiry_status(const void *data, uint8_t size, - void *user_data) +static void test_inquiry_status(struct iovec *iov, void *user_data) { - uint8_t status = *((uint8_t *) data); + uint8_t status; + + if (!util_iov_pull_u8(iov, &status)) { + tester_warn("Invalid response (length too short)"); + tester_test_failed(); + return; + } if (status) { tester_warn("HCI inquiry command failed (0x%02x)", status); @@ -679,10 +773,15 @@ static void test_inquiry_liac(const void *test_data) } } -static void setup_lt_connectable_complete(const void *data, uint8_t size, - void *user_data) +static void setup_lt_connectable_complete(struct iovec *iov, void *user_data) { - uint8_t status = *((uint8_t *) data); + uint8_t status; + + if (!util_iov_pull_u8(iov, &status)) { + tester_warn("Invalid response (length too short)"); + tester_setup_failed(); + return; + } if (status) { tester_warn("Failed to set HCI scan enable (0x%02x)", status); @@ -693,13 +792,18 @@ static void setup_lt_connectable_complete(const void *data, uint8_t size, tester_setup_complete(); } -static void setup_lt_connect_request_accept(const void *data, uint8_t size, - void *user_data) +static void setup_lt_connect_request_accept(struct iovec *iov, void *user_data) { struct user_data *user = tester_get_data(); - const struct bt_hci_evt_conn_request *evt = data; + const struct bt_hci_evt_conn_request *evt; struct bt_hci_cmd_accept_conn_request cmd; + evt = util_iov_pull_mem(iov, sizeof(*evt)); + if (!evt) { + tester_warn("Invalid response (length too short)"); + return; + } + memcpy(cmd.bdaddr, evt->bdaddr, 6); cmd.role = 0x01; @@ -734,11 +838,17 @@ static void test_create_connection_disconnect(void *user_data) tester_test_passed(); } -static void test_create_connection_complete(const void *data, uint8_t size, - void *user_data) +static void test_create_connection_complete(struct iovec *iov, void *user_data) { struct user_data *user = tester_get_data(); - const struct bt_hci_evt_conn_complete *evt = data; + const struct bt_hci_evt_conn_complete *evt; + + evt = util_iov_pull_mem(iov, sizeof(*evt)); + if (!evt) { + tester_warn("Invalid response (length too short)"); + tester_test_failed(); + return; + } if (evt->status) { tester_warn("HCI create connection complete failed (0x%02x)", @@ -752,10 +862,15 @@ static void test_create_connection_complete(const void *data, uint8_t size, tester_wait(2, test_create_connection_disconnect, NULL); } -static void test_create_connection_status(const void *data, uint8_t size, - void *user_data) +static void test_create_connection_status(struct iovec *iov, void *user_data) { - uint8_t status = *((uint8_t *) data); + uint8_t status; + + if (!util_iov_pull_u8(iov, &status)) { + tester_warn("Invalid response (length too short)"); + tester_test_failed(); + return; + } if (status) { tester_warn("HCI create connection command failed (0x%02x)", @@ -783,7 +898,7 @@ static void test_create_connection(const void *test_data) if (!bt_hci_send(user->hci_ut, BT_HCI_CMD_CREATE_CONN, &cmd, sizeof(cmd), test_create_connection_status, - NULL, NULL)) { + NULL, NULL)) { tester_warn("Failed to send HCI create connection command"); tester_test_failed(); return; @@ -795,10 +910,15 @@ static void teardown_timeout(void *user_data) tester_teardown_complete(); } -static void teardown_disconnect_status(const void *data, uint8_t size, - void *user_data) +static void teardown_disconnect_status(struct iovec *iov, void *user_data) { - uint8_t status = *((uint8_t *) data); + uint8_t status; + + if (!util_iov_pull_u8(iov, &status)) { + tester_warn("Invalid response (length too short)"); + tester_teardown_failed(); + return; + } if (status) { tester_warn("HCI disconnect failed (0x%02x)", status); @@ -820,21 +940,34 @@ static void teardown_connection(const void *test_data) if (!bt_hci_send(user->hci_ut, BT_HCI_CMD_DISCONNECT, &cmd, sizeof(cmd), teardown_disconnect_status, - NULL, NULL)) { + NULL, NULL)) { tester_warn("Failed to send HCI disconnect command"); tester_test_failed(); return; } } -static void test_adv_report(const void *data, uint8_t size, void *user_data) +static void test_adv_report(struct iovec *iov, void *user_data) { struct user_data *user = tester_get_data(); - uint8_t subevent = *((uint8_t *) data); - const struct bt_hci_evt_le_adv_report *lar = data + 1; + uint8_t subevent; + const struct bt_hci_evt_le_adv_report *lar; + + if (!util_iov_pull_u8(iov, &subevent)) { + tester_warn("Invalid response (length too short)"); + tester_setup_failed(); + return; + } switch (subevent) { case BT_HCI_EVT_LE_ADV_REPORT: + lar = util_iov_pull_mem(iov, sizeof(*lar)); + if (!lar) { + tester_warn("Invalid response (length too short)"); + tester_setup_failed(); + return; + } + if (!memcmp(lar->addr, user->bdaddr_ut, 6)) tester_setup_complete(); break; diff --git a/tools/ibeacon.c b/tools/ibeacon.c index 8dd1f4616c77..0f96c1f6b307 100644 --- a/tools/ibeacon.c +++ b/tools/ibeacon.c @@ -39,7 +39,7 @@ static bool shutdown_timeout(void *user_data) return false; } -static void shutdown_complete(const void *data, uint8_t size, void *user_data) +static void shutdown_complete(struct iovec *iov, void *user_data) { unsigned int id = PTR_TO_UINT(user_data); @@ -106,12 +106,11 @@ static void set_adv_enable(void) &enable, 1, NULL, NULL, NULL); } -static void adv_data_callback(const void *data, uint8_t size, - void *user_data) +static void adv_data_callback(struct iovec *iov, void *user_data) { - uint8_t status = *((uint8_t *) data); + uint8_t status; - if (status) { + if (!util_iov_pull_u8(iov, &status) || status) { fprintf(stderr, "Failed to set advertising data\n"); shutdown_device(); return; @@ -122,13 +121,13 @@ static void adv_data_callback(const void *data, uint8_t size, set_adv_enable(); } -static void adv_tx_power_callback(const void *data, uint8_t size, - void *user_data) +static void adv_tx_power_callback(struct iovec *iov, void *user_data) { - const struct bt_hci_rsp_le_read_adv_tx_power *rsp = data; + const struct bt_hci_rsp_le_read_adv_tx_power *rsp; struct bt_hci_cmd_le_set_adv_data cmd; - if (rsp->status) { + rsp = util_iov_pull_mem(iov, sizeof(*rsp)); + if (!rsp || rsp->status) { fprintf(stderr, "Failed to read advertising TX power\n"); shutdown_device(); return; @@ -159,12 +158,12 @@ static void adv_tx_power_callback(const void *data, uint8_t size, adv_data_callback, NULL, NULL); } -static void local_features_callback(const void *data, uint8_t size, - void *user_data) +static void local_features_callback(struct iovec *iov, void *user_data) { - const struct bt_hci_rsp_read_local_features *rsp = data; + const struct bt_hci_rsp_read_local_features *rsp; - if (rsp->status) { + rsp = util_iov_pull_mem(iov, sizeof(*rsp)); + if (!rsp || rsp->status) { fprintf(stderr, "Failed to read local features\n"); shutdown_device(); return; -- 2.48.1