From 04b220a1e485deb3bf025cdc706a4c3958a1c294 Mon Sep 17 00:00:00 2001 From: Fedor Pchelkin Date: Wed, 29 Jan 2025 11:49:49 +0300 Subject: [PATCH] btio: actually try to enable MTU auto-tuning A "0" for the input MTU passed to the underlying socket is supposed to indicate that its value should be determined by the L2CAP layer. However, the current code treats a zero imtu just as if there is nothing to change. Introduce rework the code to indicate that the zero imtu is explicitly requested by the caller for the purpose of auto-tuning and -1 is used as not set value. Found by Linux Verification Center (linuxtesting.org). Fixes: ae5be371a9f5 ("avdtp: Enable MTU auto tunning") --- btio/btio.c | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/btio/btio.c b/btio/btio.c index f32fbd509..7ea17c775 100644 --- a/btio/btio.c +++ b/btio/btio.c @@ -63,7 +63,7 @@ struct set_opts { uint16_t psm; uint16_t cid; uint16_t mtu; - uint16_t imtu; + int imtu; uint16_t omtu; int central; uint8_t mode; @@ -609,8 +609,8 @@ static uint8_t mode_l2mode(uint8_t mode) } } -static gboolean set_l2opts(int sock, uint16_t imtu, uint16_t omtu, - uint8_t mode, GError **err) +static gboolean set_l2opts(int sock, int imtu, uint16_t omtu, uint8_t mode, + GError **err) { struct l2cap_options l2o; socklen_t len; @@ -622,7 +622,7 @@ static gboolean set_l2opts(int sock, uint16_t imtu, uint16_t omtu, return FALSE; } - if (imtu) + if (imtu != -1) l2o.imtu = imtu; if (omtu) l2o.omtu = omtu; @@ -666,17 +666,27 @@ static gboolean set_le_mode(int sock, uint8_t mode, GError **err) } static gboolean l2cap_set(int sock, uint8_t src_type, int sec_level, - uint16_t imtu, uint16_t omtu, uint8_t mode, + int imtu, uint16_t omtu, uint8_t mode, int central, int flushable, uint32_t priority, GError **err) { - if (imtu || omtu || mode) { + if (imtu != -1 || omtu || mode) { gboolean ret = FALSE; - if (src_type == BDADDR_BREDR) + if (src_type == BDADDR_BREDR) { ret = set_l2opts(sock, imtu, omtu, mode, err); - else { - if (imtu) + + /* Back to default behavior in case the first call + * fails: it may happen if the used kernel still + * doesn't support auto-tuning the MTU. + */ + if (!ret && !imtu) { + /* Free existing error */ + g_error_free(*err); + ret = set_l2opts(sock, -1, omtu, mode, err); + } + } else { + if (imtu != -1) ret = set_le_imtu(sock, imtu, err); if (ret && mode) @@ -932,6 +942,7 @@ static gboolean parse_set_opts(struct set_opts *opts, GError **err, opts->priority = 0; opts->src_type = BDADDR_BREDR; opts->dst_type = BDADDR_BREDR; + opts->imtu = -1; while (opt != BT_IO_OPT_INVALID) { switch (opt) { -- 2.47.3