aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2006-07-14 05:42:12 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-07-24 15:44:25 -0400
commit98bcd08b5bfe78c1c9bda5768aa081e0fe4fcc4f (patch)
tree171c7984eeaade72d57a325ee26d55e4408bbdd1 /net
parent2266d8886f64c66e0a4e61e3e1c19dbc27ed00d4 (diff)
[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: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net')
-rw-r--r--net/bluetooth/rfcomm/core.c19
1 files changed, 17 insertions, 2 deletions
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index 77eab8f4c7fd..332dd8f436ea 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -55,6 +55,7 @@
55#define VERSION "1.8" 55#define VERSION "1.8"
56 56
57static int disable_cfc = 0; 57static int disable_cfc = 0;
58static int channel_mtu = -1;
58static unsigned int l2cap_mtu = RFCOMM_MAX_L2CAP_MTU; 59static unsigned int l2cap_mtu = RFCOMM_MAX_L2CAP_MTU;
59 60
60static struct task_struct *rfcomm_thread; 61static 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 pn->credits = 0; 813 pn->credits = 0;
813 } 814 }
814 815
815 pn->mtu = htobs(d->mtu); 816 if (cr && channel_mtu >= 0)
817 pn->mtu = htobs(channel_mtu);
818 else
819 pn->mtu = htobs(d->mtu);
816 820
817 *ptr = __fcs(buf); ptr++; 821 *ptr = __fcs(buf); ptr++;
818 822
@@ -1243,7 +1247,10 @@ static int rfcomm_apply_pn(struct rfcomm_dlc *d, int cr, struct rfcomm_pn *pn)
1243 1247
1244 d->priority = pn->priority; 1248 d->priority = pn->priority;
1245 1249
1246 d->mtu = s->mtu = btohs(pn->mtu); 1250 d->mtu = btohs(pn->mtu);
1251
1252 if (cr && d->mtu > s->mtu)
1253 d->mtu = s->mtu;
1247 1254
1248 return 0; 1255 return 0;
1249} 1256}
@@ -1770,6 +1777,11 @@ static inline void rfcomm_accept_connection(struct rfcomm_session *s)
1770 s = rfcomm_session_add(nsock, BT_OPEN); 1777 s = rfcomm_session_add(nsock, BT_OPEN);
1771 if (s) { 1778 if (s) {
1772 rfcomm_session_hold(s); 1779 rfcomm_session_hold(s);
1780
1781 /* We should adjust MTU on incoming sessions.
1782 * L2CAP MTU minus UIH header and FCS. */
1783 s->mtu = min(l2cap_pi(nsock->sk)->omtu, l2cap_pi(nsock->sk)->imtu) - 5;
1784
1773 rfcomm_schedule(RFCOMM_SCHED_RX); 1785 rfcomm_schedule(RFCOMM_SCHED_RX);
1774 } else 1786 } else
1775 sock_release(nsock); 1787 sock_release(nsock);
@@ -2087,6 +2099,9 @@ module_exit(rfcomm_exit);
2087module_param(disable_cfc, bool, 0644); 2099module_param(disable_cfc, bool, 0644);
2088MODULE_PARM_DESC(disable_cfc, "Disable credit based flow control"); 2100MODULE_PARM_DESC(disable_cfc, "Disable credit based flow control");
2089 2101
2102module_param(channel_mtu, int, 0644);
2103MODULE_PARM_DESC(channel_mtu, "Default MTU for the RFCOMM channel");
2104
2090module_param(l2cap_mtu, uint, 0644); 2105module_param(l2cap_mtu, uint, 0644);
2091MODULE_PARM_DESC(l2cap_mtu, "Default MTU for the L2CAP connection"); 2106MODULE_PARM_DESC(l2cap_mtu, "Default MTU for the L2CAP connection");
2092 2107