Commit 98bcd08b authored by Marcel Holtmann's avatar Marcel Holtmann Committed by David S. Miller

[Bluetooth] Correct RFCOMM channel MTU for broken implementations

Some Bluetooth RFCOMM implementations try to negotiate a bigger channel
MTU than we can support for a particular session. The maximum MTU for
a RFCOMM session is limited through the L2CAP layer. So if the other
side proposes a channel MTU that is bigger than the underlying L2CAP
MTU, we should reduce it to the L2CAP MTU of the session minus five
bytes for the RFCOMM headers.
Signed-off-by: default avatarMarcel Holtmann <marcel@holtmann.org>
parent 2266d888
...@@ -55,6 +55,7 @@ ...@@ -55,6 +55,7 @@
#define VERSION "1.8" #define VERSION "1.8"
static int disable_cfc = 0; static int disable_cfc = 0;
static int channel_mtu = -1;
static unsigned int l2cap_mtu = RFCOMM_MAX_L2CAP_MTU; static unsigned int l2cap_mtu = RFCOMM_MAX_L2CAP_MTU;
static struct task_struct *rfcomm_thread; static struct task_struct *rfcomm_thread;
...@@ -812,7 +813,10 @@ static int rfcomm_send_pn(struct rfcomm_session *s, int cr, struct rfcomm_dlc *d ...@@ -812,7 +813,10 @@ static int rfcomm_send_pn(struct rfcomm_session *s, int cr, struct rfcomm_dlc *d
pn->credits = 0; pn->credits = 0;
} }
pn->mtu = htobs(d->mtu); if (cr && channel_mtu >= 0)
pn->mtu = htobs(channel_mtu);
else
pn->mtu = htobs(d->mtu);
*ptr = __fcs(buf); ptr++; *ptr = __fcs(buf); ptr++;
...@@ -1243,7 +1247,10 @@ static int rfcomm_apply_pn(struct rfcomm_dlc *d, int cr, struct rfcomm_pn *pn) ...@@ -1243,7 +1247,10 @@ static int rfcomm_apply_pn(struct rfcomm_dlc *d, int cr, struct rfcomm_pn *pn)
d->priority = pn->priority; d->priority = pn->priority;
d->mtu = s->mtu = btohs(pn->mtu); d->mtu = btohs(pn->mtu);
if (cr && d->mtu > s->mtu)
d->mtu = s->mtu;
return 0; return 0;
} }
...@@ -1770,6 +1777,11 @@ static inline void rfcomm_accept_connection(struct rfcomm_session *s) ...@@ -1770,6 +1777,11 @@ static inline void rfcomm_accept_connection(struct rfcomm_session *s)
s = rfcomm_session_add(nsock, BT_OPEN); s = rfcomm_session_add(nsock, BT_OPEN);
if (s) { if (s) {
rfcomm_session_hold(s); rfcomm_session_hold(s);
/* We should adjust MTU on incoming sessions.
* L2CAP MTU minus UIH header and FCS. */
s->mtu = min(l2cap_pi(nsock->sk)->omtu, l2cap_pi(nsock->sk)->imtu) - 5;
rfcomm_schedule(RFCOMM_SCHED_RX); rfcomm_schedule(RFCOMM_SCHED_RX);
} else } else
sock_release(nsock); sock_release(nsock);
...@@ -2087,6 +2099,9 @@ module_exit(rfcomm_exit); ...@@ -2087,6 +2099,9 @@ module_exit(rfcomm_exit);
module_param(disable_cfc, bool, 0644); module_param(disable_cfc, bool, 0644);
MODULE_PARM_DESC(disable_cfc, "Disable credit based flow control"); MODULE_PARM_DESC(disable_cfc, "Disable credit based flow control");
module_param(channel_mtu, int, 0644);
MODULE_PARM_DESC(channel_mtu, "Default MTU for the RFCOMM channel");
module_param(l2cap_mtu, uint, 0644); module_param(l2cap_mtu, uint, 0644);
MODULE_PARM_DESC(l2cap_mtu, "Default MTU for the L2CAP connection"); MODULE_PARM_DESC(l2cap_mtu, "Default MTU for the L2CAP connection");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment