Diff between 36547e6aaf1efa85b0158b2078df74f273077086 and 31bcaff56ed31560eebb607c948b18013b620750

Changed Files

File Additions Deletions Status
btio/btio.c +3 -2 modified
tools/l2cap-tester.c +58 -3 modified

Full Patch

diff --git a/btio/btio.c b/btio/btio.c
index 7ef7ec7..f9b2507 100644
--- a/btio/btio.c
+++ b/btio/btio.c
@@ -972,10 +972,10 @@ static gboolean l2cap_get(int sock, GError **err, BtIOOption opt1,
 				(struct sockaddr *) &dst, sizeof(src), err))
 		return FALSE;
 
-	len = sizeof(l2o);
-	memset(&l2o, 0, len);
+	memset(&l2o, 0, sizeof(l2o));
 
 	if (src.l2_bdaddr_type != BDADDR_BREDR) {
+		len = sizeof(l2o.imtu);
 		if (getsockopt(sock, SOL_BLUETOOTH, BT_RCVMTU,
 						&l2o.imtu, &len) == 0)
 			goto parse_opts;
@@ -989,6 +989,7 @@ static gboolean l2cap_get(int sock, GError **err, BtIOOption opt1,
 		}
 	}
 
+	len = sizeof(l2o);
 	if (getsockopt(sock, SOL_L2CAP, L2CAP_OPTIONS, &l2o, &len) < 0) {
 		ERROR_FAILED(err, "getsockopt(L2CAP_OPTIONS)", errno);
 		return FALSE;
diff --git a/tools/l2cap-tester.c b/tools/l2cap-tester.c
index fd6c5ea..ffa9223 100644
--- a/tools/l2cap-tester.c
+++ b/tools/l2cap-tester.c
@@ -828,6 +828,48 @@ static void server_bthost_received_data(const void *buf, uint16_t len,
 		tester_test_passed();
 }
 
+static bool check_mtu(struct test_data *data, int sk)
+{
+	const struct l2cap_data *l2data = data->test_data;
+	struct l2cap_options l2o;
+	socklen_t len;
+
+	memset(&l2o, 0, sizeof(l2o));
+
+	if (data->hciemu_type == HCIEMU_TYPE_LE &&
+				(l2data->client_psm || l2data->server_psm)) {
+		/* LE CoC enabled kernels should support BT_RCVMTU and
+		 * BT_SNDMTU.
+		 */
+		len = sizeof(l2o.imtu);
+		if (getsockopt(sk, SOL_BLUETOOTH, BT_RCVMTU,
+							&l2o.imtu, &len) < 0) {
+			tester_warn("getsockopt(BT_RCVMTU): %s (%d)",
+					strerror(errno), errno);
+			return false;
+		}
+
+		len = sizeof(l2o.omtu);
+		if (getsockopt(sk, SOL_BLUETOOTH, BT_SNDMTU,
+							&l2o.omtu, &len) < 0) {
+			tester_warn("getsockopt(BT_SNDMTU): %s (%d)",
+					strerror(errno), errno);
+			return false;
+		}
+	} else {
+		/* For non-LE CoC enabled kernels we need to fall back to
+		 * L2CAP_OPTIONS, so test support for it as well */
+		len = sizeof(l2o);
+		if (getsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &l2o, &len) < 0) {
+			 tester_warn("getsockopt(L2CAP_OPTIONS): %s (%d)",
+						strerror(errno), errno);
+			 return false;
+		 }
+	}
+
+	return true;
+}
+
 static gboolean l2cap_connect_cb(GIOChannel *io, GIOCondition cond,
 							gpointer user_data)
 {
@@ -845,10 +887,17 @@ static gboolean l2cap_connect_cb(GIOChannel *io, GIOCondition cond,
 	else
 		err = -sk_err;
 
-	if (err < 0)
+	if (err < 0) {
 		tester_warn("Connect failed: %s (%d)", strerror(-err), -err);
-	else
-		tester_print("Successfully connected");
+		goto failed;
+	}
+
+	tester_print("Successfully connected");
+
+	if (!check_mtu(data, sk)) {
+		tester_test_failed();
+		return FALSE;
+	}
 
 	if (l2data->read_data) {
 		struct bthost *bthost;
@@ -877,6 +926,7 @@ static gboolean l2cap_connect_cb(GIOChannel *io, GIOCondition cond,
 		return FALSE;
 	}
 
+failed:
 	if (-err != l2data->expect_err)
 		tester_test_failed();
 	else
@@ -1047,6 +1097,11 @@ static gboolean l2cap_listen_cb(GIOChannel *io, GIOCondition cond,
 		return FALSE;
 	}
 
+	if (!check_mtu(data, new_sk)) {
+		tester_test_failed();
+		return FALSE;
+	}
+
 	if (l2data->read_data) {
 		struct bthost *bthost;
 		GIOChannel *new_io;