Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6464f35f authored by Marcel Holtmann's avatar Marcel Holtmann Committed by David S. Miller
Browse files

[Bluetooth] Fall back to L2CAP in basic mode



In case the remote entity tries to negogiate retransmission or flow
control mode, reject it and fall back to basic mode.

Signed-off-by: default avatarMarcel Holtmann <marcel@holtmann.org>
parent f0709e03
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -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;
+24 −8
Original line number Diff line number Diff line
@@ -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)) {
@@ -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))
@@ -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;

@@ -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;
@@ -1413,6 +1419,7 @@ 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 (rfc.mode == L2CAP_MODE_BASIC) {
			if (mtu < pi->omtu)
				result = L2CAP_CONF_UNACCEPT;
			else {
@@ -1421,6 +1428,15 @@ static int l2cap_parse_conf_req(struct sock *sk, void *data)
			}

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

			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);