diff mbox series

[BlueZ,v1] shared/hci: Make use of util_iov* to parse packets

Message ID 20250317140440.470397-1-luiz.dentz@gmail.com (mailing list archive)
State New
Headers show
Series [BlueZ,v1] shared/hci: Make use of util_iov* to parse packets | expand

Checks

Context Check Description
tedd_an/pre-ci_am success Success
tedd_an/BuildEll success Build ELL PASS
tedd_an/BluezMake success Bluez Make PASS
tedd_an/MakeCheck success Bluez Make Check PASS
tedd_an/MakeDistcheck success Make Distcheck PASS
tedd_an/CheckValgrind success Check Valgrind PASS
tedd_an/CheckSmatch success CheckSparse PASS
tedd_an/bluezmakeextell success Make External ELL PASS
tedd_an/ScanBuild success Scan Build PASS

Commit Message

Luiz Augusto von Dentz March 17, 2025, 2:04 p.m. UTC
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

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(-)

Comments

bluez.test.bot@gmail.com March 17, 2025, 5:15 p.m. UTC | #1
This is automated email and please do not reply to this email!

Dear submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=944727

---Test result---

Test Summary:
CheckPatch                    PENDING   0.25 seconds
GitLint                       PENDING   0.22 seconds
BuildEll                      PASS      20.49 seconds
BluezMake                     PASS      1454.62 seconds
MakeCheck                     PASS      12.79 seconds
MakeDistcheck                 PASS      159.41 seconds
CheckValgrind                 PASS      216.72 seconds
CheckSmatch                   PASS      285.22 seconds
bluezmakeextell               PASS      98.16 seconds
IncrementalBuild              PENDING   0.33 seconds
ScanBuild                     PASS      895.05 seconds

Details
##############################
Test: CheckPatch - PENDING
Desc: Run checkpatch.pl script
Output:

##############################
Test: GitLint - PENDING
Desc: Run gitlint
Output:

##############################
Test: IncrementalBuild - PENDING
Desc: Incremental build with the patches in the series
Output:



---
Regards,
Linux Bluetooth
diff mbox series

Patch

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;