Skip to content

Commit

Permalink
[Bluetooth] Fall back to L2CAP in basic mode
Browse files Browse the repository at this point in the history
In case the remote entity tries to negogiate retransmission or flow
control mode, reject it and fall back to basic mode.

Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
  • Loading branch information
Marcel Holtmann authored and David S. Miller committed Oct 22, 2007
1 parent f0709e0 commit 6464f35
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 8 deletions.
13 changes: 13 additions & 0 deletions include/net/bluetooth/l2cap.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,19 @@ struct l2cap_conf_opt {

#define L2CAP_CONF_MAX_SIZE 22

struct l2cap_conf_rfc {
__u8 mode;
__u8 txwin_size;
__u8 max_transmit;
__le16 retrans_timeout;
__le16 monitor_timeout;
__le16 max_pdu_size;
} __attribute__ ((packed));

#define L2CAP_MODE_BASIC 0x00
#define L2CAP_MODE_RETRANS 0x01
#define L2CAP_MODE_FLOWCTL 0x02

struct l2cap_disconn_req {
__le16 dcid;
__le16 scid;
Expand Down
32 changes: 24 additions & 8 deletions net/bluetooth/l2cap.c
Original file line number Diff line number Diff line change
Expand Up @@ -1048,7 +1048,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
opts.imtu = l2cap_pi(sk)->imtu;
opts.omtu = l2cap_pi(sk)->omtu;
opts.flush_to = l2cap_pi(sk)->flush_to;
opts.mode = 0x00;
opts.mode = L2CAP_MODE_BASIC;

len = min_t(unsigned int, sizeof(opts), optlen);
if (copy_from_user((char *) &opts, optval, len)) {
Expand Down Expand Up @@ -1097,7 +1097,7 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch
opts.imtu = l2cap_pi(sk)->imtu;
opts.omtu = l2cap_pi(sk)->omtu;
opts.flush_to = l2cap_pi(sk)->flush_to;
opts.mode = 0x00;
opts.mode = L2CAP_MODE_BASIC;

len = min_t(unsigned int, len, sizeof(opts));
if (copy_to_user(optval, (char *) &opts, len))
Expand Down Expand Up @@ -1376,6 +1376,7 @@ static int l2cap_parse_conf_req(struct sock *sk, void *data)
int len = pi->conf_len;
int type, hint, olen;
unsigned long val;
struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
u16 mtu = L2CAP_DEFAULT_MTU;
u16 result = L2CAP_CONF_SUCCESS;

Expand All @@ -1399,6 +1400,11 @@ static int l2cap_parse_conf_req(struct sock *sk, void *data)
case L2CAP_CONF_QOS:
break;

case L2CAP_CONF_RFC:
if (olen == sizeof(rfc))
memcpy(&rfc, (void *) val, olen);
break;

default:
if (hint)
break;
Expand All @@ -1413,14 +1419,24 @@ static int l2cap_parse_conf_req(struct sock *sk, void *data)
/* Configure output options and let the other side know
* which ones we don't like. */

if (mtu < pi->omtu)
if (rfc.mode == L2CAP_MODE_BASIC) {
if (mtu < pi->omtu)
result = L2CAP_CONF_UNACCEPT;
else {
pi->omtu = mtu;
pi->conf_state |= L2CAP_CONF_OUTPUT_DONE;
}

l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu);
} else {
result = L2CAP_CONF_UNACCEPT;
else {
pi->omtu = mtu;
pi->conf_state |= L2CAP_CONF_OUTPUT_DONE;
}

l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu);
memset(&rfc, 0, sizeof(rfc));
rfc.mode = L2CAP_MODE_BASIC;

l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
sizeof(rfc), (unsigned long) &rfc);
}
}

rsp->scid = cpu_to_le16(pi->dcid);
Expand Down

0 comments on commit 6464f35

Please sign in to comment.