diff options
Diffstat (limited to 'net/bluetooth/l2cap_core.c')
| -rw-r--r-- | net/bluetooth/l2cap_core.c | 1895 | 
1 files changed, 1308 insertions, 587 deletions
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 63fa11109a1..323f23cd2c3 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -36,18 +36,25 @@  #include <net/bluetooth/bluetooth.h>  #include <net/bluetooth/hci_core.h>  #include <net/bluetooth/l2cap.h> -#include <net/bluetooth/smp.h> -#include <net/bluetooth/a2mp.h> -#include <net/bluetooth/amp.h> + +#include "smp.h" +#include "a2mp.h" +#include "amp.h" +#include "6lowpan.h" + +#define LE_FLOWCTL_MAX_CREDITS 65535  bool disable_ertm; -static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN; -static u8 l2cap_fixed_chan[8] = { L2CAP_FC_L2CAP, }; +static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN | L2CAP_FEAT_UCD; +static u8 l2cap_fixed_chan[8] = { L2CAP_FC_L2CAP | L2CAP_FC_CONNLESS, };  static LIST_HEAD(chan_list);  static DEFINE_RWLOCK(chan_list_lock); +static u16 le_max_credits = L2CAP_LE_MAX_CREDITS; +static u16 le_default_mps = L2CAP_LE_DEFAULT_MPS; +  static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,  				       u8 code, u8 ident, u16 dlen, void *data);  static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, @@ -58,6 +65,18 @@ static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err);  static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control,  		     struct sk_buff_head *skbs, u8 event); +static inline __u8 bdaddr_type(struct hci_conn *hcon, __u8 type) +{ +	if (hcon->type == LE_LINK) { +		if (type == ADDR_LE_DEV_PUBLIC) +			return BDADDR_LE_PUBLIC; +		else +			return BDADDR_LE_RANDOM; +	} + +	return BDADDR_BREDR; +} +  /* ---- L2CAP channels ---- */  static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, @@ -148,7 +167,7 @@ static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src)  	struct l2cap_chan *c;  	list_for_each_entry(c, &chan_list, global_l) { -		if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src)) +		if (c->sport == psm && !bacmp(&c->src, src))  			return c;  	}  	return NULL; @@ -200,9 +219,14 @@ int l2cap_add_scid(struct l2cap_chan *chan,  __u16 scid)  static u16 l2cap_alloc_cid(struct l2cap_conn *conn)  { -	u16 cid = L2CAP_CID_DYN_START; +	u16 cid, dyn_end; + +	if (conn->hcon->type == LE_LINK) +		dyn_end = L2CAP_CID_LE_DYN_END; +	else +		dyn_end = L2CAP_CID_DYN_END; -	for (; cid < L2CAP_CID_DYN_END; cid++) { +	for (cid = L2CAP_CID_DYN_START; cid < dyn_end; cid++) {  		if (!__l2cap_get_chan_by_scid(conn, cid))  			return cid;  	} @@ -210,38 +234,25 @@ static u16 l2cap_alloc_cid(struct l2cap_conn *conn)  	return 0;  } -static void __l2cap_state_change(struct l2cap_chan *chan, int state) +static void l2cap_state_change(struct l2cap_chan *chan, int state)  {  	BT_DBG("chan %p %s -> %s", chan, state_to_string(chan->state),  	       state_to_string(state));  	chan->state = state; -	chan->ops->state_change(chan, state); +	chan->ops->state_change(chan, state, 0);  } -static void l2cap_state_change(struct l2cap_chan *chan, int state) +static inline void l2cap_state_change_and_error(struct l2cap_chan *chan, +						int state, int err)  { -	struct sock *sk = chan->sk; - -	lock_sock(sk); -	__l2cap_state_change(chan, state); -	release_sock(sk); -} - -static inline void __l2cap_chan_set_err(struct l2cap_chan *chan, int err) -{ -	struct sock *sk = chan->sk; - -	sk->sk_err = err; +	chan->state = state; +	chan->ops->state_change(chan, chan->state, err);  }  static inline void l2cap_chan_set_err(struct l2cap_chan *chan, int err)  { -	struct sock *sk = chan->sk; - -	lock_sock(sk); -	__l2cap_chan_set_err(chan, err); -	release_sock(sk); +	chan->ops->state_change(chan, chan->state, err);  }  static void __set_retrans_timer(struct l2cap_chan *chan) @@ -321,44 +332,20 @@ static inline bool l2cap_seq_list_contains(struct l2cap_seq_list *seq_list,  	return seq_list->list[seq & seq_list->mask] != L2CAP_SEQ_LIST_CLEAR;  } -static u16 l2cap_seq_list_remove(struct l2cap_seq_list *seq_list, u16 seq) +static inline u16 l2cap_seq_list_pop(struct l2cap_seq_list *seq_list)  { +	u16 seq = seq_list->head;  	u16 mask = seq_list->mask; -	if (seq_list->head == L2CAP_SEQ_LIST_CLEAR) { -		/* In case someone tries to pop the head of an empty list */ -		return L2CAP_SEQ_LIST_CLEAR; -	} else if (seq_list->head == seq) { -		/* Head can be removed in constant time */ -		seq_list->head = seq_list->list[seq & mask]; -		seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR; - -		if (seq_list->head == L2CAP_SEQ_LIST_TAIL) { -			seq_list->head = L2CAP_SEQ_LIST_CLEAR; -			seq_list->tail = L2CAP_SEQ_LIST_CLEAR; -		} -	} else { -		/* Walk the list to find the sequence number */ -		u16 prev = seq_list->head; -		while (seq_list->list[prev & mask] != seq) { -			prev = seq_list->list[prev & mask]; -			if (prev == L2CAP_SEQ_LIST_TAIL) -				return L2CAP_SEQ_LIST_CLEAR; -		} +	seq_list->head = seq_list->list[seq & mask]; +	seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR; -		/* Unlink the number from the list and clear it */ -		seq_list->list[prev & mask] = seq_list->list[seq & mask]; -		seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR; -		if (seq_list->tail == seq) -			seq_list->tail = prev; +	if (seq_list->head == L2CAP_SEQ_LIST_TAIL) { +		seq_list->head = L2CAP_SEQ_LIST_CLEAR; +		seq_list->tail = L2CAP_SEQ_LIST_CLEAR;  	} -	return seq; -} -static inline u16 l2cap_seq_list_pop(struct l2cap_seq_list *seq_list) -{ -	/* Remove the head in constant time */ -	return l2cap_seq_list_remove(seq_list, seq_list->head); +	return seq;  }  static void l2cap_seq_list_clear(struct l2cap_seq_list *seq_list) @@ -484,12 +471,30 @@ void l2cap_chan_set_defaults(struct l2cap_chan *chan)  	chan->max_tx = L2CAP_DEFAULT_MAX_TX;  	chan->tx_win = L2CAP_DEFAULT_TX_WINDOW;  	chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW; +	chan->remote_max_tx = chan->max_tx; +	chan->remote_tx_win = chan->tx_win;  	chan->ack_win = L2CAP_DEFAULT_TX_WINDOW;  	chan->sec_level = BT_SECURITY_LOW; +	chan->flush_to = L2CAP_DEFAULT_FLUSH_TO; +	chan->retrans_timeout = L2CAP_DEFAULT_RETRANS_TO; +	chan->monitor_timeout = L2CAP_DEFAULT_MONITOR_TO; +	chan->conf_state = 0;  	set_bit(FLAG_FORCE_ACTIVE, &chan->flags);  } +static void l2cap_le_flowctl_init(struct l2cap_chan *chan) +{ +	chan->sdu = NULL; +	chan->sdu_last_frag = NULL; +	chan->sdu_len = 0; +	chan->tx_credits = 0; +	chan->rx_credits = le_max_credits; +	chan->mps = min_t(u16, chan->imtu, le_default_mps); + +	skb_queue_head_init(&chan->tx_q); +} +  void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)  {  	BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn, @@ -501,18 +506,10 @@ void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)  	switch (chan->chan_type) {  	case L2CAP_CHAN_CONN_ORIENTED: -		if (conn->hcon->type == LE_LINK) { -			/* LE connection */ -			chan->omtu = L2CAP_DEFAULT_MTU; -			if (chan->dcid == L2CAP_CID_ATT) -				chan->scid = L2CAP_CID_ATT; -			else -				chan->scid = l2cap_alloc_cid(conn); -		} else { -			/* Alloc CID for connection-oriented socket */ -			chan->scid = l2cap_alloc_cid(conn); +		/* Alloc CID for connection-oriented socket */ +		chan->scid = l2cap_alloc_cid(conn); +		if (conn->hcon->type == ACL_LINK)  			chan->omtu = L2CAP_DEFAULT_MTU; -		}  		break;  	case L2CAP_CHAN_CONN_LESS: @@ -522,11 +519,8 @@ void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)  		chan->omtu = L2CAP_DEFAULT_MTU;  		break; -	case L2CAP_CHAN_CONN_FIX_A2MP: -		chan->scid = L2CAP_CID_A2MP; -		chan->dcid = L2CAP_CID_A2MP; -		chan->omtu = L2CAP_A2MP_DEFAULT_MTU; -		chan->imtu = L2CAP_A2MP_DEFAULT_MTU; +	case L2CAP_CHAN_FIXED: +		/* Caller will set CID and CID specific MTU values */  		break;  	default: @@ -574,7 +568,7 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err)  		chan->conn = NULL; -		if (chan->chan_type != L2CAP_CHAN_CONN_FIX_A2MP) +		if (chan->scid != L2CAP_CID_A2MP)  			hci_conn_drop(conn->hcon);  		if (mgr && mgr->bredr_chan == chan) @@ -597,6 +591,10 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err)  	case L2CAP_MODE_BASIC:  		break; +	case L2CAP_MODE_LE_FLOWCTL: +		skb_queue_purge(&chan->tx_q); +		break; +  	case L2CAP_MODE_ERTM:  		__clear_retrans_timer(chan);  		__clear_monitor_timer(chan); @@ -617,13 +615,72 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err)  	return;  } +void l2cap_conn_update_id_addr(struct hci_conn *hcon) +{ +	struct l2cap_conn *conn = hcon->l2cap_data; +	struct l2cap_chan *chan; + +	mutex_lock(&conn->chan_lock); + +	list_for_each_entry(chan, &conn->chan_l, list) { +		l2cap_chan_lock(chan); +		bacpy(&chan->dst, &hcon->dst); +		chan->dst_type = bdaddr_type(hcon, hcon->dst_type); +		l2cap_chan_unlock(chan); +	} + +	mutex_unlock(&conn->chan_lock); +} + +static void l2cap_chan_le_connect_reject(struct l2cap_chan *chan) +{ +	struct l2cap_conn *conn = chan->conn; +	struct l2cap_le_conn_rsp rsp; +	u16 result; + +	if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) +		result = L2CAP_CR_AUTHORIZATION; +	else +		result = L2CAP_CR_BAD_PSM; + +	l2cap_state_change(chan, BT_DISCONN); + +	rsp.dcid    = cpu_to_le16(chan->scid); +	rsp.mtu     = cpu_to_le16(chan->imtu); +	rsp.mps     = cpu_to_le16(chan->mps); +	rsp.credits = cpu_to_le16(chan->rx_credits); +	rsp.result  = cpu_to_le16(result); + +	l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp), +		       &rsp); +} + +static void l2cap_chan_connect_reject(struct l2cap_chan *chan) +{ +	struct l2cap_conn *conn = chan->conn; +	struct l2cap_conn_rsp rsp; +	u16 result; + +	if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) +		result = L2CAP_CR_SEC_BLOCK; +	else +		result = L2CAP_CR_BAD_PSM; + +	l2cap_state_change(chan, BT_DISCONN); + +	rsp.scid   = cpu_to_le16(chan->dcid); +	rsp.dcid   = cpu_to_le16(chan->scid); +	rsp.result = cpu_to_le16(result); +	rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); + +	l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp); +} +  void l2cap_chan_close(struct l2cap_chan *chan, int reason)  {  	struct l2cap_conn *conn = chan->conn; -	struct sock *sk = chan->sk; -	BT_DBG("chan %p state %s sk %p", chan, state_to_string(chan->state), -	       sk); +	BT_DBG("chan %p state %s", chan, state_to_string(chan->state));  	switch (chan->state) {  	case BT_LISTEN: @@ -632,32 +689,19 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason)  	case BT_CONNECTED:  	case BT_CONFIG: -		if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && -		    conn->hcon->type == ACL_LINK) { -			__set_chan_timer(chan, sk->sk_sndtimeo); +		if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) { +			__set_chan_timer(chan, chan->ops->get_sndtimeo(chan));  			l2cap_send_disconn_req(chan, reason);  		} else  			l2cap_chan_del(chan, reason);  		break;  	case BT_CONNECT2: -		if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && -		    conn->hcon->type == ACL_LINK) { -			struct l2cap_conn_rsp rsp; -			__u16 result; - -			if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) -				result = L2CAP_CR_SEC_BLOCK; -			else -				result = L2CAP_CR_BAD_PSM; -			l2cap_state_change(chan, BT_DISCONN); - -			rsp.scid   = cpu_to_le16(chan->dcid); -			rsp.dcid   = cpu_to_le16(chan->scid); -			rsp.result = cpu_to_le16(result); -			rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); -			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, -				       sizeof(rsp), &rsp); +		if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) { +			if (conn->hcon->type == ACL_LINK) +				l2cap_chan_connect_reject(chan); +			else if (conn->hcon->type == LE_LINK) +				l2cap_chan_le_connect_reject(chan);  		}  		l2cap_chan_del(chan, reason); @@ -676,32 +720,52 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason)  static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)  { -	if (chan->chan_type == L2CAP_CHAN_RAW) { +	switch (chan->chan_type) { +	case L2CAP_CHAN_RAW:  		switch (chan->sec_level) {  		case BT_SECURITY_HIGH: +		case BT_SECURITY_FIPS:  			return HCI_AT_DEDICATED_BONDING_MITM;  		case BT_SECURITY_MEDIUM:  			return HCI_AT_DEDICATED_BONDING;  		default:  			return HCI_AT_NO_BONDING;  		} -	} else if (chan->psm == __constant_cpu_to_le16(L2CAP_PSM_SDP)) { -		if (chan->sec_level == BT_SECURITY_LOW) -			chan->sec_level = BT_SECURITY_SDP; - -		if (chan->sec_level == BT_SECURITY_HIGH) +		break; +	case L2CAP_CHAN_CONN_LESS: +		if (chan->psm == cpu_to_le16(L2CAP_PSM_3DSP)) { +			if (chan->sec_level == BT_SECURITY_LOW) +				chan->sec_level = BT_SECURITY_SDP; +		} +		if (chan->sec_level == BT_SECURITY_HIGH || +		    chan->sec_level == BT_SECURITY_FIPS)  			return HCI_AT_NO_BONDING_MITM;  		else  			return HCI_AT_NO_BONDING; -	} else { +		break; +	case L2CAP_CHAN_CONN_ORIENTED: +		if (chan->psm == cpu_to_le16(L2CAP_PSM_SDP)) { +			if (chan->sec_level == BT_SECURITY_LOW) +				chan->sec_level = BT_SECURITY_SDP; + +			if (chan->sec_level == BT_SECURITY_HIGH || +			    chan->sec_level == BT_SECURITY_FIPS) +				return HCI_AT_NO_BONDING_MITM; +			else +				return HCI_AT_NO_BONDING; +		} +		/* fall through */ +	default:  		switch (chan->sec_level) {  		case BT_SECURITY_HIGH: +		case BT_SECURITY_FIPS:  			return HCI_AT_GENERAL_BONDING_MITM;  		case BT_SECURITY_MEDIUM:  			return HCI_AT_GENERAL_BONDING;  		default:  			return HCI_AT_NO_BONDING;  		} +		break;  	}  } @@ -711,6 +775,9 @@ int l2cap_chan_check_security(struct l2cap_chan *chan)  	struct l2cap_conn *conn = chan->conn;  	__u8 auth_type; +	if (conn->hcon->type == LE_LINK) +		return smp_conn_security(conn->hcon, chan->sec_level); +  	auth_type = l2cap_get_auth_type(chan);  	return hci_conn_security(conn->hcon, chan->sec_level, auth_type); @@ -1015,14 +1082,29 @@ static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)  static bool __amp_capable(struct l2cap_chan *chan)  {  	struct l2cap_conn *conn = chan->conn; +	struct hci_dev *hdev; +	bool amp_available = false; -	if (enable_hs && -	    hci_amp_capable() && -	    chan->chan_policy == BT_CHANNEL_POLICY_AMP_PREFERRED && -	    conn->fixed_chan_mask & L2CAP_FC_A2MP) -		return true; -	else +	if (!conn->hs_enabled)  		return false; + +	if (!(conn->fixed_chan_mask & L2CAP_FC_A2MP)) +		return false; + +	read_lock(&hci_dev_list_lock); +	list_for_each_entry(hdev, &hci_dev_list, list) { +		if (hdev->amp_type != AMP_TYPE_BREDR && +		    test_bit(HCI_UP, &hdev->flags)) { +			amp_available = true; +			break; +		} +	} +	read_unlock(&hci_dev_list_lock); + +	if (chan->chan_policy == BT_CHANNEL_POLICY_AMP_PREFERRED) +		return amp_available; + +	return false;  }  static bool l2cap_check_efs(struct l2cap_chan *chan) @@ -1122,16 +1204,57 @@ static void l2cap_chan_ready(struct l2cap_chan *chan)  	chan->conf_state = 0;  	__clear_chan_timer(chan); +	if (chan->mode == L2CAP_MODE_LE_FLOWCTL && !chan->tx_credits) +		chan->ops->suspend(chan); +  	chan->state = BT_CONNECTED;  	chan->ops->ready(chan);  } +static void l2cap_le_connect(struct l2cap_chan *chan) +{ +	struct l2cap_conn *conn = chan->conn; +	struct l2cap_le_conn_req req; + +	if (test_and_set_bit(FLAG_LE_CONN_REQ_SENT, &chan->flags)) +		return; + +	req.psm     = chan->psm; +	req.scid    = cpu_to_le16(chan->scid); +	req.mtu     = cpu_to_le16(chan->imtu); +	req.mps     = cpu_to_le16(chan->mps); +	req.credits = cpu_to_le16(chan->rx_credits); + +	chan->ident = l2cap_get_ident(conn); + +	l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_REQ, +		       sizeof(req), &req); +} + +static void l2cap_le_start(struct l2cap_chan *chan) +{ +	struct l2cap_conn *conn = chan->conn; + +	if (!smp_conn_security(conn->hcon, chan->sec_level)) +		return; + +	if (!chan->psm) { +		l2cap_chan_ready(chan); +		return; +	} + +	if (chan->state == BT_CONNECT) +		l2cap_le_connect(chan); +} +  static void l2cap_start_connection(struct l2cap_chan *chan)  {  	if (__amp_capable(chan)) {  		BT_DBG("chan %p AMP capable: discover AMPs", chan);  		a2mp_discover_amp(chan); +	} else if (chan->conn->hcon->type == LE_LINK) { +		l2cap_le_start(chan);  	} else {  		l2cap_send_conn_req(chan);  	} @@ -1142,7 +1265,7 @@ static void l2cap_do_start(struct l2cap_chan *chan)  	struct l2cap_conn *conn = chan->conn;  	if (conn->hcon->type == LE_LINK) { -		l2cap_chan_ready(chan); +		l2cap_le_start(chan);  		return;  	} @@ -1156,7 +1279,7 @@ static void l2cap_do_start(struct l2cap_chan *chan)  		}  	} else {  		struct l2cap_info_req req; -		req.type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK); +		req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);  		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;  		conn->info_ident = l2cap_get_ident(conn); @@ -1186,7 +1309,6 @@ static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)  static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err)  { -	struct sock *sk = chan->sk;  	struct l2cap_conn *conn = chan->conn;  	struct l2cap_disconn_req req; @@ -1199,7 +1321,7 @@ static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err)  		__clear_ack_timer(chan);  	} -	if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) { +	if (chan->scid == L2CAP_CID_A2MP) {  		l2cap_state_change(chan, BT_DISCONN);  		return;  	} @@ -1209,10 +1331,7 @@ static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err)  	l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_DISCONN_REQ,  		       sizeof(req), &req); -	lock_sock(sk); -	__l2cap_state_change(chan, BT_DISCONN); -	__l2cap_chan_set_err(chan, err); -	release_sock(sk); +	l2cap_state_change_and_error(chan, BT_DISCONN, err);  }  /* ---- L2CAP connections ---- */ @@ -1225,8 +1344,6 @@ static void l2cap_conn_start(struct l2cap_conn *conn)  	mutex_lock(&conn->chan_lock);  	list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) { -		struct sock *sk = chan->sk; -  		l2cap_chan_lock(chan);  		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { @@ -1258,22 +1375,19 @@ static void l2cap_conn_start(struct l2cap_conn *conn)  			rsp.dcid = cpu_to_le16(chan->scid);  			if (l2cap_chan_check_security(chan)) { -				lock_sock(sk); -				if (test_bit(BT_SK_DEFER_SETUP, -					     &bt_sk(sk)->flags)) { -					rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND); -					rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHOR_PEND); +				if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { +					rsp.result = cpu_to_le16(L2CAP_CR_PEND); +					rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);  					chan->ops->defer(chan);  				} else { -					__l2cap_state_change(chan, BT_CONFIG); -					rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS); -					rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); +					l2cap_state_change(chan, BT_CONFIG); +					rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); +					rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);  				} -				release_sock(sk);  			} else { -				rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND); -				rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHEN_PEND); +				rsp.result = cpu_to_le16(L2CAP_CR_PEND); +				rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);  			}  			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, @@ -1309,8 +1423,6 @@ static struct l2cap_chan *l2cap_global_chan_by_scid(int state, u16 cid,  	read_lock(&chan_list_lock);  	list_for_each_entry(c, &chan_list, global_l) { -		struct sock *sk = c->sk; -  		if (state && c->state != state)  			continue; @@ -1319,16 +1431,16 @@ static struct l2cap_chan *l2cap_global_chan_by_scid(int state, u16 cid,  			int src_any, dst_any;  			/* Exact match. */ -			src_match = !bacmp(&bt_sk(sk)->src, src); -			dst_match = !bacmp(&bt_sk(sk)->dst, dst); +			src_match = !bacmp(&c->src, src); +			dst_match = !bacmp(&c->dst, dst);  			if (src_match && dst_match) {  				read_unlock(&chan_list_lock);  				return c;  			}  			/* Closest match */ -			src_any = !bacmp(&bt_sk(sk)->src, BDADDR_ANY); -			dst_any = !bacmp(&bt_sk(sk)->dst, BDADDR_ANY); +			src_any = !bacmp(&c->src, BDADDR_ANY); +			dst_any = !bacmp(&c->dst, BDADDR_ANY);  			if ((src_match && dst_any) || (src_any && dst_match) ||  			    (src_any && dst_any))  				c1 = c; @@ -1342,14 +1454,17 @@ static struct l2cap_chan *l2cap_global_chan_by_scid(int state, u16 cid,  static void l2cap_le_conn_ready(struct l2cap_conn *conn)  { -	struct sock *parent; +	struct hci_conn *hcon = conn->hcon;  	struct l2cap_chan *chan, *pchan; +	u8 dst_type;  	BT_DBG(""); +	bt_6lowpan_add_conn(conn); +  	/* Check if we have socket listening on cid */  	pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_ATT, -					  conn->src, conn->dst); +					  &hcon->src, &hcon->dst);  	if (!pchan)  		return; @@ -1357,23 +1472,27 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)  	if (__l2cap_get_chan_by_dcid(conn, L2CAP_CID_ATT))  		return; -	parent = pchan->sk; +	dst_type = bdaddr_type(hcon, hcon->dst_type); -	lock_sock(parent); +	/* If device is blocked, do not create a channel for it */ +	if (hci_blacklist_lookup(hcon->hdev, &hcon->dst, dst_type)) +		return; + +	l2cap_chan_lock(pchan);  	chan = pchan->ops->new_connection(pchan);  	if (!chan)  		goto clean; -	chan->dcid = L2CAP_CID_ATT; - -	bacpy(&bt_sk(chan->sk)->src, conn->src); -	bacpy(&bt_sk(chan->sk)->dst, conn->dst); +	bacpy(&chan->src, &hcon->src); +	bacpy(&chan->dst, &hcon->dst); +	chan->src_type = bdaddr_type(hcon, hcon->src_type); +	chan->dst_type = dst_type;  	__l2cap_chan_add(conn, chan);  clean: -	release_sock(parent); +	l2cap_chan_unlock(pchan);  }  static void l2cap_conn_ready(struct l2cap_conn *conn) @@ -1398,22 +1517,15 @@ static void l2cap_conn_ready(struct l2cap_conn *conn)  		l2cap_chan_lock(chan); -		if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) { +		if (chan->scid == L2CAP_CID_A2MP) {  			l2cap_chan_unlock(chan);  			continue;  		}  		if (hcon->type == LE_LINK) { -			if (smp_conn_security(hcon, chan->sec_level)) -				l2cap_chan_ready(chan); - +			l2cap_le_start(chan);  		} else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { -			struct sock *sk = chan->sk; -			__clear_chan_timer(chan); -			lock_sock(sk); -			__l2cap_state_change(chan, BT_CONNECTED); -			sk->sk_state_change(sk); -			release_sock(sk); +			l2cap_chan_ready(chan);  		} else if (chan->state == BT_CONNECT) {  			l2cap_do_start(chan); @@ -1423,6 +1535,8 @@ static void l2cap_conn_ready(struct l2cap_conn *conn)  	}  	mutex_unlock(&conn->chan_lock); + +	queue_work(hcon->hdev->workqueue, &conn->pending_rx_work);  }  /* Notify sockets that we cannot guaranty reliability anymore */ @@ -1548,6 +1662,15 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err)  	kfree_skb(conn->rx_skb); +	skb_queue_purge(&conn->pending_rx); + +	/* We can not call flush_work(&conn->pending_rx_work) here since we +	 * might block if we are running on a worker from the same workqueue +	 * pending_rx_work is waiting on. +	 */ +	if (work_pending(&conn->pending_rx_work)) +		cancel_work_sync(&conn->pending_rx_work); +  	l2cap_unregister_all_users(conn);  	mutex_lock(&conn->chan_lock); @@ -1595,65 +1718,6 @@ static void security_timeout(struct work_struct *work)  	}  } -static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon) -{ -	struct l2cap_conn *conn = hcon->l2cap_data; -	struct hci_chan *hchan; - -	if (conn) -		return conn; - -	hchan = hci_chan_create(hcon); -	if (!hchan) -		return NULL; - -	conn = kzalloc(sizeof(struct l2cap_conn), GFP_KERNEL); -	if (!conn) { -		hci_chan_del(hchan); -		return NULL; -	} - -	kref_init(&conn->ref); -	hcon->l2cap_data = conn; -	conn->hcon = hcon; -	hci_conn_get(conn->hcon); -	conn->hchan = hchan; - -	BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan); - -	switch (hcon->type) { -	case LE_LINK: -		if (hcon->hdev->le_mtu) { -			conn->mtu = hcon->hdev->le_mtu; -			break; -		} -		/* fall through */ -	default: -		conn->mtu = hcon->hdev->acl_mtu; -		break; -	} - -	conn->src = &hcon->hdev->bdaddr; -	conn->dst = &hcon->dst; - -	conn->feat_mask = 0; - -	spin_lock_init(&conn->lock); -	mutex_init(&conn->chan_lock); - -	INIT_LIST_HEAD(&conn->chan_l); -	INIT_LIST_HEAD(&conn->users); - -	if (hcon->type == LE_LINK) -		INIT_DELAYED_WORK(&conn->security_timer, security_timeout); -	else -		INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout); - -	conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM; - -	return conn; -} -  static void l2cap_conn_free(struct kref *ref)  {  	struct l2cap_conn *conn = container_of(ref, struct l2cap_conn, ref); @@ -1681,33 +1745,38 @@ EXPORT_SYMBOL(l2cap_conn_put);   */  static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm,  						   bdaddr_t *src, -						   bdaddr_t *dst) +						   bdaddr_t *dst, +						   u8 link_type)  {  	struct l2cap_chan *c, *c1 = NULL;  	read_lock(&chan_list_lock);  	list_for_each_entry(c, &chan_list, global_l) { -		struct sock *sk = c->sk; -  		if (state && c->state != state)  			continue; +		if (link_type == ACL_LINK && c->src_type != BDADDR_BREDR) +			continue; + +		if (link_type == LE_LINK && c->src_type == BDADDR_BREDR) +			continue; +  		if (c->psm == psm) {  			int src_match, dst_match;  			int src_any, dst_any;  			/* Exact match. */ -			src_match = !bacmp(&bt_sk(sk)->src, src); -			dst_match = !bacmp(&bt_sk(sk)->dst, dst); +			src_match = !bacmp(&c->src, src); +			dst_match = !bacmp(&c->dst, dst);  			if (src_match && dst_match) {  				read_unlock(&chan_list_lock);  				return c;  			}  			/* Closest match */ -			src_any = !bacmp(&bt_sk(sk)->src, BDADDR_ANY); -			dst_any = !bacmp(&bt_sk(sk)->dst, BDADDR_ANY); +			src_any = !bacmp(&c->src, BDADDR_ANY); +			dst_any = !bacmp(&c->dst, BDADDR_ANY);  			if ((src_match && dst_any) || (src_any && dst_match) ||  			    (src_any && dst_any))  				c1 = c; @@ -1719,174 +1788,6 @@ static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm,  	return c1;  } -int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, -		       bdaddr_t *dst, u8 dst_type) -{ -	struct sock *sk = chan->sk; -	bdaddr_t *src = &bt_sk(sk)->src; -	struct l2cap_conn *conn; -	struct hci_conn *hcon; -	struct hci_dev *hdev; -	__u8 auth_type; -	int err; - -	BT_DBG("%pMR -> %pMR (type %u) psm 0x%2.2x", src, dst, -	       dst_type, __le16_to_cpu(psm)); - -	hdev = hci_get_route(dst, src); -	if (!hdev) -		return -EHOSTUNREACH; - -	hci_dev_lock(hdev); - -	l2cap_chan_lock(chan); - -	/* PSM must be odd and lsb of upper byte must be 0 */ -	if ((__le16_to_cpu(psm) & 0x0101) != 0x0001 && !cid && -	    chan->chan_type != L2CAP_CHAN_RAW) { -		err = -EINVAL; -		goto done; -	} - -	if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !(psm || cid)) { -		err = -EINVAL; -		goto done; -	} - -	switch (chan->mode) { -	case L2CAP_MODE_BASIC: -		break; -	case L2CAP_MODE_ERTM: -	case L2CAP_MODE_STREAMING: -		if (!disable_ertm) -			break; -		/* fall through */ -	default: -		err = -ENOTSUPP; -		goto done; -	} - -	switch (chan->state) { -	case BT_CONNECT: -	case BT_CONNECT2: -	case BT_CONFIG: -		/* Already connecting */ -		err = 0; -		goto done; - -	case BT_CONNECTED: -		/* Already connected */ -		err = -EISCONN; -		goto done; - -	case BT_OPEN: -	case BT_BOUND: -		/* Can connect */ -		break; - -	default: -		err = -EBADFD; -		goto done; -	} - -	/* Set destination address and psm */ -	lock_sock(sk); -	bacpy(&bt_sk(sk)->dst, dst); -	release_sock(sk); - -	chan->psm = psm; -	chan->dcid = cid; - -	auth_type = l2cap_get_auth_type(chan); - -	if (bdaddr_type_is_le(dst_type)) -		hcon = hci_connect(hdev, LE_LINK, dst, dst_type, -				   chan->sec_level, auth_type); -	else -		hcon = hci_connect(hdev, ACL_LINK, dst, dst_type, -				   chan->sec_level, auth_type); - -	if (IS_ERR(hcon)) { -		err = PTR_ERR(hcon); -		goto done; -	} - -	conn = l2cap_conn_add(hcon); -	if (!conn) { -		hci_conn_drop(hcon); -		err = -ENOMEM; -		goto done; -	} - -	if (cid && __l2cap_get_chan_by_dcid(conn, cid)) { -		hci_conn_drop(hcon); -		err = -EBUSY; -		goto done; -	} - -	/* Update source addr of the socket */ -	bacpy(src, conn->src); - -	l2cap_chan_unlock(chan); -	l2cap_chan_add(conn, chan); -	l2cap_chan_lock(chan); - -	/* l2cap_chan_add takes its own ref so we can drop this one */ -	hci_conn_drop(hcon); - -	l2cap_state_change(chan, BT_CONNECT); -	__set_chan_timer(chan, sk->sk_sndtimeo); - -	if (hcon->state == BT_CONNECTED) { -		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { -			__clear_chan_timer(chan); -			if (l2cap_chan_check_security(chan)) -				l2cap_state_change(chan, BT_CONNECTED); -		} else -			l2cap_do_start(chan); -	} - -	err = 0; - -done: -	l2cap_chan_unlock(chan); -	hci_dev_unlock(hdev); -	hci_dev_put(hdev); -	return err; -} - -int __l2cap_wait_ack(struct sock *sk) -{ -	struct l2cap_chan *chan = l2cap_pi(sk)->chan; -	DECLARE_WAITQUEUE(wait, current); -	int err = 0; -	int timeo = HZ/5; - -	add_wait_queue(sk_sleep(sk), &wait); -	set_current_state(TASK_INTERRUPTIBLE); -	while (chan->unacked_frames > 0 && chan->conn) { -		if (!timeo) -			timeo = HZ/5; - -		if (signal_pending(current)) { -			err = sock_intr_errno(timeo); -			break; -		} - -		release_sock(sk); -		timeo = schedule_timeout(timeo); -		lock_sock(sk); -		set_current_state(TASK_INTERRUPTIBLE); - -		err = sock_error(sk); -		if (err) -			break; -	} -	set_current_state(TASK_RUNNING); -	remove_wait_queue(sk_sleep(sk), &wait); -	return err; -} -  static void l2cap_monitor_timeout(struct work_struct *work)  {  	struct l2cap_chan *chan = container_of(work, struct l2cap_chan, @@ -2263,7 +2164,8 @@ static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan,  	int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE;  	struct l2cap_hdr *lh; -	BT_DBG("chan %p len %zu priority %u", chan, len, priority); +	BT_DBG("chan %p psm 0x%2.2x len %zu priority %u", chan, +	       __le16_to_cpu(chan->psm), len, priority);  	count = min_t(unsigned int, (conn->mtu - hlen), len); @@ -2278,7 +2180,7 @@ static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan,  	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);  	lh->cid = cpu_to_le16(chan->dcid);  	lh->len = cpu_to_le16(len + L2CAP_PSMLEN_SIZE); -	put_unaligned(chan->psm, skb_put(skb, L2CAP_PSMLEN_SIZE)); +	put_unaligned(chan->psm, (__le16 *) skb_put(skb, L2CAP_PSMLEN_SIZE));  	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);  	if (unlikely(err < 0)) { @@ -2445,6 +2347,89 @@ static int l2cap_segment_sdu(struct l2cap_chan *chan,  	return 0;  } +static struct sk_buff *l2cap_create_le_flowctl_pdu(struct l2cap_chan *chan, +						   struct msghdr *msg, +						   size_t len, u16 sdulen) +{ +	struct l2cap_conn *conn = chan->conn; +	struct sk_buff *skb; +	int err, count, hlen; +	struct l2cap_hdr *lh; + +	BT_DBG("chan %p len %zu", chan, len); + +	if (!conn) +		return ERR_PTR(-ENOTCONN); + +	hlen = L2CAP_HDR_SIZE; + +	if (sdulen) +		hlen += L2CAP_SDULEN_SIZE; + +	count = min_t(unsigned int, (conn->mtu - hlen), len); + +	skb = chan->ops->alloc_skb(chan, count + hlen, +				   msg->msg_flags & MSG_DONTWAIT); +	if (IS_ERR(skb)) +		return skb; + +	/* Create L2CAP header */ +	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); +	lh->cid = cpu_to_le16(chan->dcid); +	lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE)); + +	if (sdulen) +		put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE)); + +	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); +	if (unlikely(err < 0)) { +		kfree_skb(skb); +		return ERR_PTR(err); +	} + +	return skb; +} + +static int l2cap_segment_le_sdu(struct l2cap_chan *chan, +				struct sk_buff_head *seg_queue, +				struct msghdr *msg, size_t len) +{ +	struct sk_buff *skb; +	size_t pdu_len; +	u16 sdu_len; + +	BT_DBG("chan %p, msg %p, len %zu", chan, msg, len); + +	pdu_len = chan->conn->mtu - L2CAP_HDR_SIZE; + +	pdu_len = min_t(size_t, pdu_len, chan->remote_mps); + +	sdu_len = len; +	pdu_len -= L2CAP_SDULEN_SIZE; + +	while (len > 0) { +		if (len <= pdu_len) +			pdu_len = len; + +		skb = l2cap_create_le_flowctl_pdu(chan, msg, pdu_len, sdu_len); +		if (IS_ERR(skb)) { +			__skb_queue_purge(seg_queue); +			return PTR_ERR(skb); +		} + +		__skb_queue_tail(seg_queue, skb); + +		len -= pdu_len; + +		if (sdu_len) { +			sdu_len = 0; +			pdu_len += L2CAP_SDULEN_SIZE; +		} +	} + +	return 0; +} +  int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,  		    u32 priority)  { @@ -2452,17 +2437,62 @@ int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,  	int err;  	struct sk_buff_head seg_queue; +	if (!chan->conn) +		return -ENOTCONN; +  	/* Connectionless channel */  	if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {  		skb = l2cap_create_connless_pdu(chan, msg, len, priority);  		if (IS_ERR(skb))  			return PTR_ERR(skb); +		/* Channel lock is released before requesting new skb and then +		 * reacquired thus we need to recheck channel state. +		 */ +		if (chan->state != BT_CONNECTED) { +			kfree_skb(skb); +			return -ENOTCONN; +		} +  		l2cap_do_send(chan, skb);  		return len;  	}  	switch (chan->mode) { +	case L2CAP_MODE_LE_FLOWCTL: +		/* Check outgoing MTU */ +		if (len > chan->omtu) +			return -EMSGSIZE; + +		if (!chan->tx_credits) +			return -EAGAIN; + +		__skb_queue_head_init(&seg_queue); + +		err = l2cap_segment_le_sdu(chan, &seg_queue, msg, len); + +		if (chan->state != BT_CONNECTED) { +			__skb_queue_purge(&seg_queue); +			err = -ENOTCONN; +		} + +		if (err) +			return err; + +		skb_queue_splice_tail_init(&seg_queue, &chan->tx_q); + +		while (chan->tx_credits && !skb_queue_empty(&chan->tx_q)) { +			l2cap_do_send(chan, skb_dequeue(&chan->tx_q)); +			chan->tx_credits--; +		} + +		if (!chan->tx_credits) +			chan->ops->suspend(chan); + +		err = len; + +		break; +  	case L2CAP_MODE_BASIC:  		/* Check outgoing MTU */  		if (len > chan->omtu) @@ -2473,6 +2503,14 @@ int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,  		if (IS_ERR(skb))  			return PTR_ERR(skb); +		/* Channel lock is released before requesting new skb and then +		 * reacquired thus we need to recheck channel state. +		 */ +		if (chan->state != BT_CONNECTED) { +			kfree_skb(skb); +			return -ENOTCONN; +		} +  		l2cap_do_send(chan, skb);  		err = len;  		break; @@ -2826,17 +2864,16 @@ static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)  	mutex_lock(&conn->chan_lock);  	list_for_each_entry(chan, &conn->chan_l, list) { -		struct sock *sk = chan->sk;  		if (chan->chan_type != L2CAP_CHAN_RAW)  			continue; -		/* Don't send frame to the socket it came from */ -		if (skb->sk == sk) +		/* Don't send frame to the channel it came from */ +		if (bt_cb(skb)->chan == chan)  			continue; +  		nskb = skb_clone(skb, GFP_KERNEL);  		if (!nskb)  			continue; -  		if (chan->ops->recv(chan, nskb))  			kfree_skb(nskb);  	} @@ -2870,9 +2907,9 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, u8 code,  	lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);  	if (conn->hcon->type == LE_LINK) -		lh->cid = __constant_cpu_to_le16(L2CAP_CID_LE_SIGNALING); +		lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);  	else -		lh->cid = __constant_cpu_to_le16(L2CAP_CID_SIGNALING); +		lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);  	cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);  	cmd->code  = code; @@ -2985,8 +3022,8 @@ static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan)  		efs.stype	= chan->local_stype;  		efs.msdu	= cpu_to_le16(chan->local_msdu);  		efs.sdu_itime	= cpu_to_le32(chan->local_sdu_itime); -		efs.acc_lat	= __constant_cpu_to_le32(L2CAP_DEFAULT_ACC_LAT); -		efs.flush_to	= __constant_cpu_to_le32(L2CAP_EFS_DEFAULT_FLUSH_TO); +		efs.acc_lat	= cpu_to_le32(L2CAP_DEFAULT_ACC_LAT); +		efs.flush_to	= cpu_to_le32(L2CAP_EFS_DEFAULT_FLUSH_TO);  		break;  	case L2CAP_MODE_STREAMING: @@ -3043,8 +3080,8 @@ int l2cap_ertm_init(struct l2cap_chan *chan)  	skb_queue_head_init(&chan->tx_q); -	chan->local_amp_id = 0; -	chan->move_id = 0; +	chan->local_amp_id = AMP_ID_BREDR; +	chan->move_id = AMP_ID_BREDR;  	chan->move_state = L2CAP_MOVE_STABLE;  	chan->move_role = L2CAP_MOVE_ROLE_NONE; @@ -3084,20 +3121,20 @@ static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)  	}  } -static inline bool __l2cap_ews_supported(struct l2cap_chan *chan) +static inline bool __l2cap_ews_supported(struct l2cap_conn *conn)  { -	return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_WINDOW; +	return conn->hs_enabled && conn->feat_mask & L2CAP_FEAT_EXT_WINDOW;  } -static inline bool __l2cap_efs_supported(struct l2cap_chan *chan) +static inline bool __l2cap_efs_supported(struct l2cap_conn *conn)  { -	return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_FLOW; +	return conn->hs_enabled && conn->feat_mask & L2CAP_FEAT_EXT_FLOW;  }  static void __l2cap_set_ertm_timeouts(struct l2cap_chan *chan,  				      struct l2cap_conf_rfc *rfc)  { -	if (chan->local_amp_id && chan->hs_hcon) { +	if (chan->local_amp_id != AMP_ID_BREDR && chan->hs_hcon) {  		u64 ertm_to = chan->hs_hcon->hdev->amp_be_flush_to;  		/* Class 1 devices have must have ERTM timeouts @@ -3127,15 +3164,15 @@ static void __l2cap_set_ertm_timeouts(struct l2cap_chan *chan,  		rfc->retrans_timeout = cpu_to_le16((u16) ertm_to);  		rfc->monitor_timeout = rfc->retrans_timeout;  	} else { -		rfc->retrans_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO); -		rfc->monitor_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO); +		rfc->retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO); +		rfc->monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);  	}  }  static inline void l2cap_txwin_setup(struct l2cap_chan *chan)  {  	if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW && -	    __l2cap_ews_supported(chan)) { +	    __l2cap_ews_supported(chan->conn)) {  		/* use extended control field */  		set_bit(FLAG_EXT_CTRL, &chan->flags);  		chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW; @@ -3165,7 +3202,7 @@ static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)  		if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))  			break; -		if (__l2cap_efs_supported(chan)) +		if (__l2cap_efs_supported(chan->conn))  			set_bit(FLAG_EFS_ENABLE, &chan->flags);  		/* fall through */ @@ -3260,7 +3297,7 @@ done:  	}  	req->dcid  = cpu_to_le16(chan->dcid); -	req->flags = __constant_cpu_to_le16(0); +	req->flags = cpu_to_le16(0);  	return ptr - data;  } @@ -3317,7 +3354,7 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)  			break;  		case L2CAP_CONF_EWS: -			if (!enable_hs) +			if (!chan->conn->hs_enabled)  				return -ECONNREFUSED;  			set_bit(FLAG_EXT_CTRL, &chan->flags); @@ -3349,7 +3386,7 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)  		}  		if (remote_efs) { -			if (__l2cap_efs_supported(chan)) +			if (__l2cap_efs_supported(chan->conn))  				set_bit(FLAG_EFS_ENABLE, &chan->flags);  			else  				return -ECONNREFUSED; @@ -3474,7 +3511,7 @@ done:  	}  	rsp->scid   = cpu_to_le16(chan->dcid);  	rsp->result = cpu_to_le16(result); -	rsp->flags  = __constant_cpu_to_le16(0); +	rsp->flags  = cpu_to_le16(0);  	return ptr - data;  } @@ -3583,7 +3620,7 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len,  	}  	req->dcid   = cpu_to_le16(chan->dcid); -	req->flags  = __constant_cpu_to_le16(0); +	req->flags  = cpu_to_le16(0);  	return ptr - data;  } @@ -3603,6 +3640,23 @@ static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data,  	return ptr - data;  } +void __l2cap_le_connect_rsp_defer(struct l2cap_chan *chan) +{ +	struct l2cap_le_conn_rsp rsp; +	struct l2cap_conn *conn = chan->conn; + +	BT_DBG("chan %p", chan); + +	rsp.dcid    = cpu_to_le16(chan->scid); +	rsp.mtu     = cpu_to_le16(chan->imtu); +	rsp.mps     = cpu_to_le16(chan->mps); +	rsp.credits = cpu_to_le16(chan->rx_credits); +	rsp.result  = cpu_to_le16(L2CAP_CR_SUCCESS); + +	l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp), +		       &rsp); +} +  void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)  {  	struct l2cap_conn_rsp rsp; @@ -3612,8 +3666,8 @@ void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)  	rsp.scid   = cpu_to_le16(chan->dcid);  	rsp.dcid   = cpu_to_le16(chan->scid); -	rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS); -	rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); +	rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); +	rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);  	if (chan->hs_hcon)  		rsp_code = L2CAP_CREATE_CHAN_RSP; @@ -3642,8 +3696,8 @@ static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)  	u16 txwin_ext = chan->ack_win;  	struct l2cap_conf_rfc rfc = {  		.mode = chan->mode, -		.retrans_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO), -		.monitor_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO), +		.retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO), +		.monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO),  		.max_pdu_size = cpu_to_le16(chan->imtu),  		.txwin_size = min_t(u16, chan->ack_win, L2CAP_DEFAULT_TX_WINDOW),  	}; @@ -3715,7 +3769,6 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,  	struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;  	struct l2cap_conn_rsp rsp;  	struct l2cap_chan *chan = NULL, *pchan; -	struct sock *parent, *sk = NULL;  	int result, status = L2CAP_CS_NO_INFO;  	u16 dcid = 0, scid = __le16_to_cpu(req->scid); @@ -3724,19 +3777,18 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,  	BT_DBG("psm 0x%2.2x scid 0x%4.4x", __le16_to_cpu(psm), scid);  	/* Check if we have socket listening on psm */ -	pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src, conn->dst); +	pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src, +					 &conn->hcon->dst, ACL_LINK);  	if (!pchan) {  		result = L2CAP_CR_BAD_PSM;  		goto sendresp;  	} -	parent = pchan->sk; -  	mutex_lock(&conn->chan_lock); -	lock_sock(parent); +	l2cap_chan_lock(pchan);  	/* Check if the ACL is secure enough (if not SDP) */ -	if (psm != __constant_cpu_to_le16(L2CAP_PSM_SDP) && +	if (psm != cpu_to_le16(L2CAP_PSM_SDP) &&  	    !hci_conn_check_link_mode(conn->hcon)) {  		conn->disc_reason = HCI_ERROR_AUTH_FAILURE;  		result = L2CAP_CR_SEC_BLOCK; @@ -3753,8 +3805,6 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,  	if (!chan)  		goto response; -	sk = chan->sk; -  	/* For certain devices (ex: HID mouse), support for authentication,  	 * pairing and bonding is optional. For such devices, inorder to avoid  	 * the ACL alive for too long after L2CAP disconnection, reset the ACL @@ -3762,8 +3812,10 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,  	 */  	conn->hcon->disc_timeout = HCI_DISCONN_TIMEOUT; -	bacpy(&bt_sk(sk)->src, conn->src); -	bacpy(&bt_sk(sk)->dst, conn->dst); +	bacpy(&chan->src, &conn->hcon->src); +	bacpy(&chan->dst, &conn->hcon->dst); +	chan->src_type = bdaddr_type(conn->hcon, conn->hcon->src_type); +	chan->dst_type = bdaddr_type(conn->hcon, conn->hcon->dst_type);  	chan->psm  = psm;  	chan->dcid = scid;  	chan->local_amp_id = amp_id; @@ -3772,14 +3824,14 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,  	dcid = chan->scid; -	__set_chan_timer(chan, sk->sk_sndtimeo); +	__set_chan_timer(chan, chan->ops->get_sndtimeo(chan));  	chan->ident = cmd->ident;  	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {  		if (l2cap_chan_check_security(chan)) { -			if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) { -				__l2cap_state_change(chan, BT_CONNECT2); +			if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { +				l2cap_state_change(chan, BT_CONNECT2);  				result = L2CAP_CR_PEND;  				status = L2CAP_CS_AUTHOR_PEND;  				chan->ops->defer(chan); @@ -3788,28 +3840,28 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,  				 * The connection will succeed after the  				 * physical link is up.  				 */ -				if (amp_id) { -					__l2cap_state_change(chan, BT_CONNECT2); -					result = L2CAP_CR_PEND; -				} else { -					__l2cap_state_change(chan, BT_CONFIG); +				if (amp_id == AMP_ID_BREDR) { +					l2cap_state_change(chan, BT_CONFIG);  					result = L2CAP_CR_SUCCESS; +				} else { +					l2cap_state_change(chan, BT_CONNECT2); +					result = L2CAP_CR_PEND;  				}  				status = L2CAP_CS_NO_INFO;  			}  		} else { -			__l2cap_state_change(chan, BT_CONNECT2); +			l2cap_state_change(chan, BT_CONNECT2);  			result = L2CAP_CR_PEND;  			status = L2CAP_CS_AUTHEN_PEND;  		}  	} else { -		__l2cap_state_change(chan, BT_CONNECT2); +		l2cap_state_change(chan, BT_CONNECT2);  		result = L2CAP_CR_PEND;  		status = L2CAP_CS_NO_INFO;  	}  response: -	release_sock(parent); +	l2cap_chan_unlock(pchan);  	mutex_unlock(&conn->chan_lock);  sendresp: @@ -3821,7 +3873,7 @@ sendresp:  	if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {  		struct l2cap_info_req info; -		info.type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK); +		info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);  		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;  		conn->info_ident = l2cap_get_ident(conn); @@ -3891,13 +3943,13 @@ static int l2cap_connect_create_rsp(struct l2cap_conn *conn,  	if (scid) {  		chan = __l2cap_get_chan_by_scid(conn, scid);  		if (!chan) { -			err = -EFAULT; +			err = -EBADSLT;  			goto unlock;  		}  	} else {  		chan = __l2cap_get_chan_by_ident(conn, cmd->ident);  		if (!chan) { -			err = -EFAULT; +			err = -EBADSLT;  			goto unlock;  		}  	} @@ -3965,6 +4017,18 @@ static void l2cap_send_efs_conf_rsp(struct l2cap_chan *chan, void *data,  					    L2CAP_CONF_SUCCESS, flags), data);  } +static void cmd_reject_invalid_cid(struct l2cap_conn *conn, u8 ident, +				   u16 scid, u16 dcid) +{ +	struct l2cap_cmd_rej_cid rej; + +	rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID); +	rej.scid = __cpu_to_le16(scid); +	rej.dcid = __cpu_to_le16(dcid); + +	l2cap_send_cmd(conn, ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej); +} +  static inline int l2cap_config_req(struct l2cap_conn *conn,  				   struct l2cap_cmd_hdr *cmd, u16 cmd_len,  				   u8 *data) @@ -3984,18 +4048,14 @@ static inline int l2cap_config_req(struct l2cap_conn *conn,  	BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);  	chan = l2cap_get_chan_by_scid(conn, dcid); -	if (!chan) -		return -ENOENT; +	if (!chan) { +		cmd_reject_invalid_cid(conn, cmd->ident, dcid, 0); +		return 0; +	}  	if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) { -		struct l2cap_cmd_rej_cid rej; - -		rej.reason = __constant_cpu_to_le16(L2CAP_REJ_INVALID_CID); -		rej.scid = cpu_to_le16(chan->scid); -		rej.dcid = cpu_to_le16(chan->dcid); - -		l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ, -			       sizeof(rej), &rej); +		cmd_reject_invalid_cid(conn, cmd->ident, chan->scid, +				       chan->dcid);  		goto unlock;  	} @@ -4198,7 +4258,6 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn,  	struct l2cap_disconn_rsp rsp;  	u16 dcid, scid;  	struct l2cap_chan *chan; -	struct sock *sk;  	if (cmd_len != sizeof(*req))  		return -EPROTO; @@ -4213,20 +4272,17 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn,  	chan = __l2cap_get_chan_by_scid(conn, dcid);  	if (!chan) {  		mutex_unlock(&conn->chan_lock); +		cmd_reject_invalid_cid(conn, cmd->ident, dcid, scid);  		return 0;  	}  	l2cap_chan_lock(chan); -	sk = chan->sk; -  	rsp.dcid = cpu_to_le16(chan->scid);  	rsp.scid = cpu_to_le16(chan->dcid);  	l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp); -	lock_sock(sk); -	sk->sk_shutdown = SHUTDOWN_MASK; -	release_sock(sk); +	chan->ops->set_shutdown(chan);  	l2cap_chan_hold(chan);  	l2cap_chan_del(chan, ECONNRESET); @@ -4298,12 +4354,12 @@ static inline int l2cap_information_req(struct l2cap_conn *conn,  		u8 buf[8];  		u32 feat_mask = l2cap_feat_mask;  		struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf; -		rsp->type   = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK); -		rsp->result = __constant_cpu_to_le16(L2CAP_IR_SUCCESS); +		rsp->type   = cpu_to_le16(L2CAP_IT_FEAT_MASK); +		rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);  		if (!disable_ertm)  			feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING  				| L2CAP_FEAT_FCS; -		if (enable_hs) +		if (conn->hs_enabled)  			feat_mask |= L2CAP_FEAT_EXT_FLOW  				| L2CAP_FEAT_EXT_WINDOW; @@ -4314,20 +4370,20 @@ static inline int l2cap_information_req(struct l2cap_conn *conn,  		u8 buf[12];  		struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf; -		if (enable_hs) +		if (conn->hs_enabled)  			l2cap_fixed_chan[0] |= L2CAP_FC_A2MP;  		else  			l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP; -		rsp->type   = __constant_cpu_to_le16(L2CAP_IT_FIXED_CHAN); -		rsp->result = __constant_cpu_to_le16(L2CAP_IR_SUCCESS); +		rsp->type   = cpu_to_le16(L2CAP_IT_FIXED_CHAN); +		rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);  		memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan));  		l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf),  			       buf);  	} else {  		struct l2cap_info_rsp rsp;  		rsp.type   = cpu_to_le16(type); -		rsp.result = __constant_cpu_to_le16(L2CAP_IR_NOTSUPP); +		rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);  		l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(rsp),  			       &rsp);  	} @@ -4372,7 +4428,7 @@ static inline int l2cap_information_rsp(struct l2cap_conn *conn,  		if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {  			struct l2cap_info_req req; -			req.type = __constant_cpu_to_le16(L2CAP_IT_FIXED_CHAN); +			req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);  			conn->info_ident = l2cap_get_ident(conn); @@ -4411,7 +4467,7 @@ static int l2cap_create_channel_req(struct l2cap_conn *conn,  	if (cmd_len != sizeof(*req))  		return -EPROTO; -	if (!enable_hs) +	if (!conn->hs_enabled)  		return -EINVAL;  	psm = le16_to_cpu(req->psm); @@ -4420,7 +4476,7 @@ static int l2cap_create_channel_req(struct l2cap_conn *conn,  	BT_DBG("psm 0x%2.2x, scid 0x%4.4x, amp_id %d", psm, scid, req->amp_id);  	/* For controller id 0 make BR/EDR connection */ -	if (req->amp_id == HCI_BREDR_ID) { +	if (req->amp_id == AMP_ID_BREDR) {  		l2cap_connect(conn, cmd, data, L2CAP_CREATE_CHAN_RSP,  			      req->amp_id);  		return 0; @@ -4442,10 +4498,13 @@ static int l2cap_create_channel_req(struct l2cap_conn *conn,  		struct amp_mgr *mgr = conn->hcon->amp_mgr;  		struct hci_conn *hs_hcon; -		hs_hcon = hci_conn_hash_lookup_ba(hdev, AMP_LINK, conn->dst); +		hs_hcon = hci_conn_hash_lookup_ba(hdev, AMP_LINK, +						  &conn->hcon->dst);  		if (!hs_hcon) {  			hci_dev_put(hdev); -			return -EFAULT; +			cmd_reject_invalid_cid(conn, cmd->ident, chan->scid, +					       chan->dcid); +			return 0;  		}  		BT_DBG("mgr %p bredr_chan %p hs_hcon %p", mgr, chan, hs_hcon); @@ -4463,13 +4522,13 @@ static int l2cap_create_channel_req(struct l2cap_conn *conn,  error:  	rsp.dcid = 0;  	rsp.scid = cpu_to_le16(scid); -	rsp.result = __constant_cpu_to_le16(L2CAP_CR_BAD_AMP); -	rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); +	rsp.result = cpu_to_le16(L2CAP_CR_BAD_AMP); +	rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);  	l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP,  		       sizeof(rsp), &rsp); -	return -EFAULT; +	return 0;  }  static void l2cap_send_move_chan_req(struct l2cap_chan *chan, u8 dest_amp_id) @@ -4528,7 +4587,7 @@ static void l2cap_send_move_chan_cfm_icid(struct l2cap_conn *conn, u16 icid)  	BT_DBG("conn %p, icid 0x%4.4x", conn, icid);  	cfm.icid = cpu_to_le16(icid); -	cfm.result = __constant_cpu_to_le16(L2CAP_MC_UNCONFIRMED); +	cfm.result = cpu_to_le16(L2CAP_MC_UNCONFIRMED);  	l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_MOVE_CHAN_CFM,  		       sizeof(cfm), &cfm); @@ -4655,7 +4714,7 @@ void l2cap_logical_cfm(struct l2cap_chan *chan, struct hci_chan *hchan,  	if (chan->state != BT_CONNECTED) {  		/* Ignore logical link if channel is on BR/EDR */ -		if (chan->local_amp_id) +		if (chan->local_amp_id != AMP_ID_BREDR)  			l2cap_logical_finish_create(chan, hchan);  	} else {  		l2cap_logical_finish_move(chan, hchan); @@ -4666,7 +4725,7 @@ void l2cap_move_start(struct l2cap_chan *chan)  {  	BT_DBG("chan %p", chan); -	if (chan->local_amp_id == HCI_BREDR_ID) { +	if (chan->local_amp_id == AMP_ID_BREDR) {  		if (chan->chan_policy != BT_CHANNEL_POLICY_AMP_PREFERRED)  			return;  		chan->move_role = L2CAP_MOVE_ROLE_INITIATOR; @@ -4711,19 +4770,19 @@ static void l2cap_do_create(struct l2cap_chan *chan, int result,  		if (result == L2CAP_CR_SUCCESS) {  			/* Send successful response */ -			rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS); -			rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); +			rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); +			rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);  		} else {  			/* Send negative response */ -			rsp.result = __constant_cpu_to_le16(L2CAP_CR_NO_MEM); -			rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); +			rsp.result = cpu_to_le16(L2CAP_CR_NO_MEM); +			rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);  		}  		l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CREATE_CHAN_RSP,  			       sizeof(rsp), &rsp);  		if (result == L2CAP_CR_SUCCESS) { -			__l2cap_state_change(chan, BT_CONFIG); +			l2cap_state_change(chan, BT_CONFIG);  			set_bit(CONF_REQ_SENT, &chan->conf_state);  			l2cap_send_cmd(chan->conn, l2cap_get_ident(chan->conn),  				       L2CAP_CONF_REQ, @@ -4838,13 +4897,13 @@ static inline int l2cap_move_channel_req(struct l2cap_conn *conn,  	BT_DBG("icid 0x%4.4x, dest_amp_id %d", icid, req->dest_amp_id); -	if (!enable_hs) +	if (!conn->hs_enabled)  		return -EINVAL;  	chan = l2cap_get_chan_by_dcid(conn, icid);  	if (!chan) {  		rsp.icid = cpu_to_le16(icid); -		rsp.result = __constant_cpu_to_le16(L2CAP_MR_NOT_ALLOWED); +		rsp.result = cpu_to_le16(L2CAP_MR_NOT_ALLOWED);  		l2cap_send_cmd(conn, cmd->ident, L2CAP_MOVE_CHAN_RSP,  			       sizeof(rsp), &rsp);  		return 0; @@ -4865,7 +4924,7 @@ static inline int l2cap_move_channel_req(struct l2cap_conn *conn,  		goto send_move_response;  	} -	if (req->dest_amp_id) { +	if (req->dest_amp_id != AMP_ID_BREDR) {  		struct hci_dev *hdev;  		hdev = hci_dev_get(req->dest_amp_id);  		if (!hdev || hdev->dev_type != HCI_AMP || @@ -4885,7 +4944,7 @@ static inline int l2cap_move_channel_req(struct l2cap_conn *conn,  	 */  	if ((__chan_is_moving(chan) ||  	     chan->move_role != L2CAP_MOVE_ROLE_NONE) && -	    bacmp(conn->src, conn->dst) > 0) { +	    bacmp(&conn->hcon->src, &conn->hcon->dst) > 0) {  		result = L2CAP_MR_COLLISION;  		goto send_move_response;  	} @@ -4895,7 +4954,7 @@ static inline int l2cap_move_channel_req(struct l2cap_conn *conn,  	chan->move_id = req->dest_amp_id;  	icid = chan->dcid; -	if (!req->dest_amp_id) { +	if (req->dest_amp_id == AMP_ID_BREDR) {  		/* Moving to BR/EDR */  		if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {  			chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY; @@ -5087,7 +5146,7 @@ static int l2cap_move_channel_confirm(struct l2cap_conn *conn,  	if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM) {  		if (result == L2CAP_MC_CONFIRMED) {  			chan->local_amp_id = chan->move_id; -			if (!chan->local_amp_id) +			if (chan->local_amp_id == AMP_ID_BREDR)  				__release_logical_link(chan);  		} else {  			chan->move_id = chan->local_amp_id; @@ -5127,7 +5186,7 @@ static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn,  	if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM_RSP) {  		chan->local_amp_id = chan->move_id; -		if (!chan->local_amp_id && chan->hs_hchan) +		if (chan->local_amp_id == AMP_ID_BREDR && chan->hs_hchan)  			__release_logical_link(chan);  		l2cap_move_done(chan); @@ -5161,18 +5220,17 @@ static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,  static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,  					      struct l2cap_cmd_hdr *cmd, -					      u8 *data) +					      u16 cmd_len, u8 *data)  {  	struct hci_conn *hcon = conn->hcon;  	struct l2cap_conn_param_update_req *req;  	struct l2cap_conn_param_update_rsp rsp; -	u16 min, max, latency, to_multiplier, cmd_len; +	u16 min, max, latency, to_multiplier;  	int err;  	if (!(hcon->link_mode & HCI_LM_MASTER))  		return -EINVAL; -	cmd_len = __le16_to_cpu(cmd->len);  	if (cmd_len != sizeof(struct l2cap_conn_param_update_req))  		return -EPROTO; @@ -5189,9 +5247,9 @@ static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,  	err = l2cap_check_conn_param(min, max, latency, to_multiplier);  	if (err) -		rsp.result = __constant_cpu_to_le16(L2CAP_CONN_PARAM_REJECTED); +		rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);  	else -		rsp.result = __constant_cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED); +		rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);  	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,  		       sizeof(rsp), &rsp); @@ -5202,6 +5260,65 @@ static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,  	return 0;  } +static int l2cap_le_connect_rsp(struct l2cap_conn *conn, +				struct l2cap_cmd_hdr *cmd, u16 cmd_len, +				u8 *data) +{ +	struct l2cap_le_conn_rsp *rsp = (struct l2cap_le_conn_rsp *) data; +	u16 dcid, mtu, mps, credits, result; +	struct l2cap_chan *chan; +	int err; + +	if (cmd_len < sizeof(*rsp)) +		return -EPROTO; + +	dcid    = __le16_to_cpu(rsp->dcid); +	mtu     = __le16_to_cpu(rsp->mtu); +	mps     = __le16_to_cpu(rsp->mps); +	credits = __le16_to_cpu(rsp->credits); +	result  = __le16_to_cpu(rsp->result); + +	if (result == L2CAP_CR_SUCCESS && (mtu < 23 || mps < 23)) +		return -EPROTO; + +	BT_DBG("dcid 0x%4.4x mtu %u mps %u credits %u result 0x%2.2x", +	       dcid, mtu, mps, credits, result); + +	mutex_lock(&conn->chan_lock); + +	chan = __l2cap_get_chan_by_ident(conn, cmd->ident); +	if (!chan) { +		err = -EBADSLT; +		goto unlock; +	} + +	err = 0; + +	l2cap_chan_lock(chan); + +	switch (result) { +	case L2CAP_CR_SUCCESS: +		chan->ident = 0; +		chan->dcid = dcid; +		chan->omtu = mtu; +		chan->remote_mps = mps; +		chan->tx_credits = credits; +		l2cap_chan_ready(chan); +		break; + +	default: +		l2cap_chan_del(chan, ECONNREFUSED); +		break; +	} + +	l2cap_chan_unlock(chan); + +unlock: +	mutex_unlock(&conn->chan_lock); + +	return err; +} +  static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,  				      struct l2cap_cmd_hdr *cmd, u16 cmd_len,  				      u8 *data) @@ -5219,7 +5336,7 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,  	case L2CAP_CONN_RSP:  	case L2CAP_CREATE_CHAN_RSP: -		err = l2cap_connect_create_rsp(conn, cmd, cmd_len, data); +		l2cap_connect_create_rsp(conn, cmd, cmd_len, data);  		break;  	case L2CAP_CONF_REQ: @@ -5227,7 +5344,7 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,  		break;  	case L2CAP_CONF_RSP: -		err = l2cap_config_rsp(conn, cmd, cmd_len, data); +		l2cap_config_rsp(conn, cmd, cmd_len, data);  		break;  	case L2CAP_DISCONN_REQ: @@ -5235,7 +5352,7 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,  		break;  	case L2CAP_DISCONN_RSP: -		err = l2cap_disconnect_rsp(conn, cmd, cmd_len, data); +		l2cap_disconnect_rsp(conn, cmd, cmd_len, data);  		break;  	case L2CAP_ECHO_REQ: @@ -5250,7 +5367,7 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,  		break;  	case L2CAP_INFO_RSP: -		err = l2cap_information_rsp(conn, cmd, cmd_len, data); +		l2cap_information_rsp(conn, cmd, cmd_len, data);  		break;  	case L2CAP_CREATE_CHAN_REQ: @@ -5262,7 +5379,7 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,  		break;  	case L2CAP_MOVE_CHAN_RSP: -		err = l2cap_move_channel_rsp(conn, cmd, cmd_len, data); +		l2cap_move_channel_rsp(conn, cmd, cmd_len, data);  		break;  	case L2CAP_MOVE_CHAN_CFM: @@ -5270,7 +5387,7 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,  		break;  	case L2CAP_MOVE_CHAN_CFM_RSP: -		err = l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data); +		l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data);  		break;  	default: @@ -5282,73 +5399,282 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,  	return err;  } +static int l2cap_le_connect_req(struct l2cap_conn *conn, +				struct l2cap_cmd_hdr *cmd, u16 cmd_len, +				u8 *data) +{ +	struct l2cap_le_conn_req *req = (struct l2cap_le_conn_req *) data; +	struct l2cap_le_conn_rsp rsp; +	struct l2cap_chan *chan, *pchan; +	u16 dcid, scid, credits, mtu, mps; +	__le16 psm; +	u8 result; + +	if (cmd_len != sizeof(*req)) +		return -EPROTO; + +	scid = __le16_to_cpu(req->scid); +	mtu  = __le16_to_cpu(req->mtu); +	mps  = __le16_to_cpu(req->mps); +	psm  = req->psm; +	dcid = 0; +	credits = 0; + +	if (mtu < 23 || mps < 23) +		return -EPROTO; + +	BT_DBG("psm 0x%2.2x scid 0x%4.4x mtu %u mps %u", __le16_to_cpu(psm), +	       scid, mtu, mps); + +	/* Check if we have socket listening on psm */ +	pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src, +					 &conn->hcon->dst, LE_LINK); +	if (!pchan) { +		result = L2CAP_CR_BAD_PSM; +		chan = NULL; +		goto response; +	} + +	mutex_lock(&conn->chan_lock); +	l2cap_chan_lock(pchan); + +	if (!smp_sufficient_security(conn->hcon, pchan->sec_level)) { +		result = L2CAP_CR_AUTHENTICATION; +		chan = NULL; +		goto response_unlock; +	} + +	/* Check if we already have channel with that dcid */ +	if (__l2cap_get_chan_by_dcid(conn, scid)) { +		result = L2CAP_CR_NO_MEM; +		chan = NULL; +		goto response_unlock; +	} + +	chan = pchan->ops->new_connection(pchan); +	if (!chan) { +		result = L2CAP_CR_NO_MEM; +		goto response_unlock; +	} + +	l2cap_le_flowctl_init(chan); + +	bacpy(&chan->src, &conn->hcon->src); +	bacpy(&chan->dst, &conn->hcon->dst); +	chan->src_type = bdaddr_type(conn->hcon, conn->hcon->src_type); +	chan->dst_type = bdaddr_type(conn->hcon, conn->hcon->dst_type); +	chan->psm  = psm; +	chan->dcid = scid; +	chan->omtu = mtu; +	chan->remote_mps = mps; +	chan->tx_credits = __le16_to_cpu(req->credits); + +	__l2cap_chan_add(conn, chan); +	dcid = chan->scid; +	credits = chan->rx_credits; + +	__set_chan_timer(chan, chan->ops->get_sndtimeo(chan)); + +	chan->ident = cmd->ident; + +	if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { +		l2cap_state_change(chan, BT_CONNECT2); +		result = L2CAP_CR_PEND; +		chan->ops->defer(chan); +	} else { +		l2cap_chan_ready(chan); +		result = L2CAP_CR_SUCCESS; +	} + +response_unlock: +	l2cap_chan_unlock(pchan); +	mutex_unlock(&conn->chan_lock); + +	if (result == L2CAP_CR_PEND) +		return 0; + +response: +	if (chan) { +		rsp.mtu = cpu_to_le16(chan->imtu); +		rsp.mps = cpu_to_le16(chan->mps); +	} else { +		rsp.mtu = 0; +		rsp.mps = 0; +	} + +	rsp.dcid    = cpu_to_le16(dcid); +	rsp.credits = cpu_to_le16(credits); +	rsp.result  = cpu_to_le16(result); + +	l2cap_send_cmd(conn, cmd->ident, L2CAP_LE_CONN_RSP, sizeof(rsp), &rsp); + +	return 0; +} + +static inline int l2cap_le_credits(struct l2cap_conn *conn, +				   struct l2cap_cmd_hdr *cmd, u16 cmd_len, +				   u8 *data) +{ +	struct l2cap_le_credits *pkt; +	struct l2cap_chan *chan; +	u16 cid, credits, max_credits; + +	if (cmd_len != sizeof(*pkt)) +		return -EPROTO; + +	pkt = (struct l2cap_le_credits *) data; +	cid	= __le16_to_cpu(pkt->cid); +	credits	= __le16_to_cpu(pkt->credits); + +	BT_DBG("cid 0x%4.4x credits 0x%4.4x", cid, credits); + +	chan = l2cap_get_chan_by_dcid(conn, cid); +	if (!chan) +		return -EBADSLT; + +	max_credits = LE_FLOWCTL_MAX_CREDITS - chan->tx_credits; +	if (credits > max_credits) { +		BT_ERR("LE credits overflow"); +		l2cap_send_disconn_req(chan, ECONNRESET); + +		/* Return 0 so that we don't trigger an unnecessary +		 * command reject packet. +		 */ +		return 0; +	} + +	chan->tx_credits += credits; + +	while (chan->tx_credits && !skb_queue_empty(&chan->tx_q)) { +		l2cap_do_send(chan, skb_dequeue(&chan->tx_q)); +		chan->tx_credits--; +	} + +	if (chan->tx_credits) +		chan->ops->resume(chan); + +	l2cap_chan_unlock(chan); + +	return 0; +} + +static inline int l2cap_le_command_rej(struct l2cap_conn *conn, +				       struct l2cap_cmd_hdr *cmd, u16 cmd_len, +				       u8 *data) +{ +	struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data; +	struct l2cap_chan *chan; + +	if (cmd_len < sizeof(*rej)) +		return -EPROTO; + +	mutex_lock(&conn->chan_lock); + +	chan = __l2cap_get_chan_by_ident(conn, cmd->ident); +	if (!chan) +		goto done; + +	l2cap_chan_lock(chan); +	l2cap_chan_del(chan, ECONNREFUSED); +	l2cap_chan_unlock(chan); + +done: +	mutex_unlock(&conn->chan_lock); +	return 0; +} +  static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn, -				   struct l2cap_cmd_hdr *cmd, u8 *data) +				   struct l2cap_cmd_hdr *cmd, u16 cmd_len, +				   u8 *data)  { +	int err = 0; +  	switch (cmd->code) {  	case L2CAP_COMMAND_REJ: -		return 0; +		l2cap_le_command_rej(conn, cmd, cmd_len, data); +		break;  	case L2CAP_CONN_PARAM_UPDATE_REQ: -		return l2cap_conn_param_update_req(conn, cmd, data); +		err = l2cap_conn_param_update_req(conn, cmd, cmd_len, data); +		break;  	case L2CAP_CONN_PARAM_UPDATE_RSP: -		return 0; +		break; + +	case L2CAP_LE_CONN_RSP: +		l2cap_le_connect_rsp(conn, cmd, cmd_len, data); +		break; + +	case L2CAP_LE_CONN_REQ: +		err = l2cap_le_connect_req(conn, cmd, cmd_len, data); +		break; + +	case L2CAP_LE_CREDITS: +		err = l2cap_le_credits(conn, cmd, cmd_len, data); +		break; + +	case L2CAP_DISCONN_REQ: +		err = l2cap_disconnect_req(conn, cmd, cmd_len, data); +		break; + +	case L2CAP_DISCONN_RSP: +		l2cap_disconnect_rsp(conn, cmd, cmd_len, data); +		break;  	default:  		BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code); -		return -EINVAL; +		err = -EINVAL; +		break;  	} + +	return err;  }  static inline void l2cap_le_sig_channel(struct l2cap_conn *conn,  					struct sk_buff *skb)  { -	u8 *data = skb->data; -	int len = skb->len; -	struct l2cap_cmd_hdr cmd; +	struct hci_conn *hcon = conn->hcon; +	struct l2cap_cmd_hdr *cmd; +	u16 len;  	int err; -	l2cap_raw_recv(conn, skb); +	if (hcon->type != LE_LINK) +		goto drop; -	while (len >= L2CAP_CMD_HDR_SIZE) { -		u16 cmd_len; -		memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE); -		data += L2CAP_CMD_HDR_SIZE; -		len  -= L2CAP_CMD_HDR_SIZE; +	if (skb->len < L2CAP_CMD_HDR_SIZE) +		goto drop; -		cmd_len = le16_to_cpu(cmd.len); +	cmd = (void *) skb->data; +	skb_pull(skb, L2CAP_CMD_HDR_SIZE); -		BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len, -		       cmd.ident); +	len = le16_to_cpu(cmd->len); -		if (cmd_len > len || !cmd.ident) { -			BT_DBG("corrupted command"); -			break; -		} +	BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd->code, len, cmd->ident); -		err = l2cap_le_sig_cmd(conn, &cmd, data); -		if (err) { -			struct l2cap_cmd_rej_unk rej; +	if (len != skb->len || !cmd->ident) { +		BT_DBG("corrupted command"); +		goto drop; +	} -			BT_ERR("Wrong link type (%d)", err); +	err = l2cap_le_sig_cmd(conn, cmd, len, skb->data); +	if (err) { +		struct l2cap_cmd_rej_unk rej; -			/* FIXME: Map err to a valid reason */ -			rej.reason = __constant_cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD); -			l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, -				       sizeof(rej), &rej); -		} +		BT_ERR("Wrong link type (%d)", err); -		data += cmd_len; -		len  -= cmd_len; +		rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD); +		l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ, +			       sizeof(rej), &rej);  	} +drop:  	kfree_skb(skb);  }  static inline void l2cap_sig_channel(struct l2cap_conn *conn,  				     struct sk_buff *skb)  { +	struct hci_conn *hcon = conn->hcon;  	u8 *data = skb->data;  	int len = skb->len;  	struct l2cap_cmd_hdr cmd; @@ -5356,6 +5682,9 @@ static inline void l2cap_sig_channel(struct l2cap_conn *conn,  	l2cap_raw_recv(conn, skb); +	if (hcon->type != ACL_LINK) +		goto drop; +  	while (len >= L2CAP_CMD_HDR_SIZE) {  		u16 cmd_len;  		memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE); @@ -5378,8 +5707,7 @@ static inline void l2cap_sig_channel(struct l2cap_conn *conn,  			BT_ERR("Wrong link type (%d)", err); -			/* FIXME: Map err to a valid reason */ -			rej.reason = __constant_cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD); +			rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);  			l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ,  				       sizeof(rej), &rej);  		} @@ -5388,6 +5716,7 @@ static inline void l2cap_sig_channel(struct l2cap_conn *conn,  		len  -= cmd_len;  	} +drop:  	kfree_skb(skb);  } @@ -5784,7 +6113,7 @@ static int l2cap_rx_state_recv(struct l2cap_chan *chan,  			       struct sk_buff *skb, u8 event)  {  	int err = 0; -	bool skb_in_use = 0; +	bool skb_in_use = false;  	BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,  	       event); @@ -5805,7 +6134,7 @@ static int l2cap_rx_state_recv(struct l2cap_chan *chan,  							   control->txseq);  			chan->buffer_seq = chan->expected_tx_seq; -			skb_in_use = 1; +			skb_in_use = true;  			err = l2cap_reassemble_sdu(chan, skb, control);  			if (err) @@ -5841,7 +6170,7 @@ static int l2cap_rx_state_recv(struct l2cap_chan *chan,  			 * current frame is stored for later use.  			 */  			skb_queue_tail(&chan->srej_q, skb); -			skb_in_use = 1; +			skb_in_use = true;  			BT_DBG("Queued %p (queue len %d)", skb,  			       skb_queue_len(&chan->srej_q)); @@ -5919,7 +6248,7 @@ static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan,  {  	int err = 0;  	u16 txseq = control->txseq; -	bool skb_in_use = 0; +	bool skb_in_use = false;  	BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,  	       event); @@ -5931,7 +6260,7 @@ static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan,  			/* Keep frame for reassembly later */  			l2cap_pass_to_tx(chan, control);  			skb_queue_tail(&chan->srej_q, skb); -			skb_in_use = 1; +			skb_in_use = true;  			BT_DBG("Queued %p (queue len %d)", skb,  			       skb_queue_len(&chan->srej_q)); @@ -5942,7 +6271,7 @@ static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan,  			l2cap_pass_to_tx(chan, control);  			skb_queue_tail(&chan->srej_q, skb); -			skb_in_use = 1; +			skb_in_use = true;  			BT_DBG("Queued %p (queue len %d)", skb,  			       skb_queue_len(&chan->srej_q)); @@ -5957,7 +6286,7 @@ static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan,  			 * the missing frames.  			 */  			skb_queue_tail(&chan->srej_q, skb); -			skb_in_use = 1; +			skb_in_use = true;  			BT_DBG("Queued %p (queue len %d)", skb,  			       skb_queue_len(&chan->srej_q)); @@ -5971,7 +6300,7 @@ static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan,  			 * SREJ'd frames.  			 */  			skb_queue_tail(&chan->srej_q, skb); -			skb_in_use = 1; +			skb_in_use = true;  			BT_DBG("Queued %p (queue len %d)", skb,  			       skb_queue_len(&chan->srej_q)); @@ -6318,6 +6647,122 @@ drop:  	return 0;  } +static void l2cap_chan_le_send_credits(struct l2cap_chan *chan) +{ +	struct l2cap_conn *conn = chan->conn; +	struct l2cap_le_credits pkt; +	u16 return_credits; + +	/* We return more credits to the sender only after the amount of +	 * credits falls below half of the initial amount. +	 */ +	if (chan->rx_credits >= (le_max_credits + 1) / 2) +		return; + +	return_credits = le_max_credits - chan->rx_credits; + +	BT_DBG("chan %p returning %u credits to sender", chan, return_credits); + +	chan->rx_credits += return_credits; + +	pkt.cid     = cpu_to_le16(chan->scid); +	pkt.credits = cpu_to_le16(return_credits); + +	chan->ident = l2cap_get_ident(conn); + +	l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CREDITS, sizeof(pkt), &pkt); +} + +static int l2cap_le_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) +{ +	int err; + +	if (!chan->rx_credits) { +		BT_ERR("No credits to receive LE L2CAP data"); +		l2cap_send_disconn_req(chan, ECONNRESET); +		return -ENOBUFS; +	} + +	if (chan->imtu < skb->len) { +		BT_ERR("Too big LE L2CAP PDU"); +		return -ENOBUFS; +	} + +	chan->rx_credits--; +	BT_DBG("rx_credits %u -> %u", chan->rx_credits + 1, chan->rx_credits); + +	l2cap_chan_le_send_credits(chan); + +	err = 0; + +	if (!chan->sdu) { +		u16 sdu_len; + +		sdu_len = get_unaligned_le16(skb->data); +		skb_pull(skb, L2CAP_SDULEN_SIZE); + +		BT_DBG("Start of new SDU. sdu_len %u skb->len %u imtu %u", +		       sdu_len, skb->len, chan->imtu); + +		if (sdu_len > chan->imtu) { +			BT_ERR("Too big LE L2CAP SDU length received"); +			err = -EMSGSIZE; +			goto failed; +		} + +		if (skb->len > sdu_len) { +			BT_ERR("Too much LE L2CAP data received"); +			err = -EINVAL; +			goto failed; +		} + +		if (skb->len == sdu_len) +			return chan->ops->recv(chan, skb); + +		chan->sdu = skb; +		chan->sdu_len = sdu_len; +		chan->sdu_last_frag = skb; + +		return 0; +	} + +	BT_DBG("SDU fragment. chan->sdu->len %u skb->len %u chan->sdu_len %u", +	       chan->sdu->len, skb->len, chan->sdu_len); + +	if (chan->sdu->len + skb->len > chan->sdu_len) { +		BT_ERR("Too much LE L2CAP data received"); +		err = -EINVAL; +		goto failed; +	} + +	append_skb_frag(chan->sdu, skb, &chan->sdu_last_frag); +	skb = NULL; + +	if (chan->sdu->len == chan->sdu_len) { +		err = chan->ops->recv(chan, chan->sdu); +		if (!err) { +			chan->sdu = NULL; +			chan->sdu_last_frag = NULL; +			chan->sdu_len = 0; +		} +	} + +failed: +	if (err) { +		kfree_skb(skb); +		kfree_skb(chan->sdu); +		chan->sdu = NULL; +		chan->sdu_last_frag = NULL; +		chan->sdu_len = 0; +	} + +	/* We can't return an error here since we took care of the skb +	 * freeing internally. An error return would cause the caller to +	 * do a double-free of the skb. +	 */ +	return 0; +} +  static void l2cap_data_channel(struct l2cap_conn *conn, u16 cid,  			       struct sk_buff *skb)  { @@ -6347,14 +6792,22 @@ static void l2cap_data_channel(struct l2cap_conn *conn, u16 cid,  		goto drop;  	switch (chan->mode) { +	case L2CAP_MODE_LE_FLOWCTL: +		if (l2cap_le_data_rcv(chan, skb) < 0) +			goto drop; + +		goto done; +  	case L2CAP_MODE_BASIC:  		/* If socket recv buffers overflows we drop data here  		 * which is *bad* because L2CAP has to be reliable.  		 * But we don't have any other choice. L2CAP doesn't  		 * provide flow control mechanism. */ -		if (chan->imtu < skb->len) +		if (chan->imtu < skb->len) { +			BT_ERR("Dropping L2CAP data: receive buffer overflow");  			goto drop; +		}  		if (!chan->ops->recv(chan, skb))  			goto done; @@ -6380,9 +6833,14 @@ done:  static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm,  				  struct sk_buff *skb)  { +	struct hci_conn *hcon = conn->hcon;  	struct l2cap_chan *chan; -	chan = l2cap_global_chan_by_psm(0, psm, conn->src, conn->dst); +	if (hcon->type != ACL_LINK) +		goto drop; + +	chan = l2cap_global_chan_by_psm(0, psm, &hcon->src, &hcon->dst, +					ACL_LINK);  	if (!chan)  		goto drop; @@ -6394,6 +6852,10 @@ static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm,  	if (chan->imtu < skb->len)  		goto drop; +	/* Store remote BD_ADDR and PSM for msg_name */ +	bacpy(&bt_cb(skb)->bdaddr, &hcon->dst); +	bt_cb(skb)->psm = psm; +  	if (!chan->ops->recv(chan, skb))  		return; @@ -6404,15 +6866,22 @@ drop:  static void l2cap_att_channel(struct l2cap_conn *conn,  			      struct sk_buff *skb)  { +	struct hci_conn *hcon = conn->hcon;  	struct l2cap_chan *chan; +	if (hcon->type != LE_LINK) +		goto drop; +  	chan = l2cap_global_chan_by_scid(BT_CONNECTED, L2CAP_CID_ATT, -					 conn->src, conn->dst); +					 &hcon->src, &hcon->dst);  	if (!chan)  		goto drop;  	BT_DBG("chan %p, len %d", chan, skb->len); +	if (hci_blacklist_lookup(hcon->hdev, &hcon->dst, hcon->dst_type)) +		goto drop; +  	if (chan->imtu < skb->len)  		goto drop; @@ -6426,9 +6895,16 @@ drop:  static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)  {  	struct l2cap_hdr *lh = (void *) skb->data; +	struct hci_conn *hcon = conn->hcon;  	u16 cid, len;  	__le16 psm; +	if (hcon->state != BT_CONNECTED) { +		BT_DBG("queueing pending rx skb"); +		skb_queue_tail(&conn->pending_rx, skb); +		return; +	} +  	skb_pull(skb, L2CAP_HDR_SIZE);  	cid = __le16_to_cpu(lh->cid);  	len = __le16_to_cpu(lh->len); @@ -6441,9 +6917,6 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)  	BT_DBG("len %d, cid 0x%4.4x", len, cid);  	switch (cid) { -	case L2CAP_CID_LE_SIGNALING: -		l2cap_le_sig_channel(conn, skb); -		break;  	case L2CAP_CID_SIGNALING:  		l2cap_sig_channel(conn, skb);  		break; @@ -6458,17 +6931,266 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)  		l2cap_att_channel(conn, skb);  		break; +	case L2CAP_CID_LE_SIGNALING: +		l2cap_le_sig_channel(conn, skb); +		break; +  	case L2CAP_CID_SMP:  		if (smp_sig_channel(conn, skb))  			l2cap_conn_del(conn->hcon, EACCES);  		break; +	case L2CAP_FC_6LOWPAN: +		bt_6lowpan_recv(conn, skb); +		break; +  	default:  		l2cap_data_channel(conn, cid, skb);  		break;  	}  } +static void process_pending_rx(struct work_struct *work) +{ +	struct l2cap_conn *conn = container_of(work, struct l2cap_conn, +					       pending_rx_work); +	struct sk_buff *skb; + +	BT_DBG(""); + +	while ((skb = skb_dequeue(&conn->pending_rx))) +		l2cap_recv_frame(conn, skb); +} + +static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon) +{ +	struct l2cap_conn *conn = hcon->l2cap_data; +	struct hci_chan *hchan; + +	if (conn) +		return conn; + +	hchan = hci_chan_create(hcon); +	if (!hchan) +		return NULL; + +	conn = kzalloc(sizeof(struct l2cap_conn), GFP_KERNEL); +	if (!conn) { +		hci_chan_del(hchan); +		return NULL; +	} + +	kref_init(&conn->ref); +	hcon->l2cap_data = conn; +	conn->hcon = hcon; +	hci_conn_get(conn->hcon); +	conn->hchan = hchan; + +	BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan); + +	switch (hcon->type) { +	case LE_LINK: +		if (hcon->hdev->le_mtu) { +			conn->mtu = hcon->hdev->le_mtu; +			break; +		} +		/* fall through */ +	default: +		conn->mtu = hcon->hdev->acl_mtu; +		break; +	} + +	conn->feat_mask = 0; + +	if (hcon->type == ACL_LINK) +		conn->hs_enabled = test_bit(HCI_HS_ENABLED, +					    &hcon->hdev->dev_flags); + +	spin_lock_init(&conn->lock); +	mutex_init(&conn->chan_lock); + +	INIT_LIST_HEAD(&conn->chan_l); +	INIT_LIST_HEAD(&conn->users); + +	if (hcon->type == LE_LINK) +		INIT_DELAYED_WORK(&conn->security_timer, security_timeout); +	else +		INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout); + +	skb_queue_head_init(&conn->pending_rx); +	INIT_WORK(&conn->pending_rx_work, process_pending_rx); + +	conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM; + +	return conn; +} + +static bool is_valid_psm(u16 psm, u8 dst_type) { +	if (!psm) +		return false; + +	if (bdaddr_type_is_le(dst_type)) +		return (psm <= 0x00ff); + +	/* PSM must be odd and lsb of upper byte must be 0 */ +	return ((psm & 0x0101) == 0x0001); +} + +int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, +		       bdaddr_t *dst, u8 dst_type) +{ +	struct l2cap_conn *conn; +	struct hci_conn *hcon; +	struct hci_dev *hdev; +	__u8 auth_type; +	int err; + +	BT_DBG("%pMR -> %pMR (type %u) psm 0x%2.2x", &chan->src, dst, +	       dst_type, __le16_to_cpu(psm)); + +	hdev = hci_get_route(dst, &chan->src); +	if (!hdev) +		return -EHOSTUNREACH; + +	hci_dev_lock(hdev); + +	l2cap_chan_lock(chan); + +	if (!is_valid_psm(__le16_to_cpu(psm), dst_type) && !cid && +	    chan->chan_type != L2CAP_CHAN_RAW) { +		err = -EINVAL; +		goto done; +	} + +	if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !psm) { +		err = -EINVAL; +		goto done; +	} + +	if (chan->chan_type == L2CAP_CHAN_FIXED && !cid) { +		err = -EINVAL; +		goto done; +	} + +	switch (chan->mode) { +	case L2CAP_MODE_BASIC: +		break; +	case L2CAP_MODE_LE_FLOWCTL: +		l2cap_le_flowctl_init(chan); +		break; +	case L2CAP_MODE_ERTM: +	case L2CAP_MODE_STREAMING: +		if (!disable_ertm) +			break; +		/* fall through */ +	default: +		err = -ENOTSUPP; +		goto done; +	} + +	switch (chan->state) { +	case BT_CONNECT: +	case BT_CONNECT2: +	case BT_CONFIG: +		/* Already connecting */ +		err = 0; +		goto done; + +	case BT_CONNECTED: +		/* Already connected */ +		err = -EISCONN; +		goto done; + +	case BT_OPEN: +	case BT_BOUND: +		/* Can connect */ +		break; + +	default: +		err = -EBADFD; +		goto done; +	} + +	/* Set destination address and psm */ +	bacpy(&chan->dst, dst); +	chan->dst_type = dst_type; + +	chan->psm = psm; +	chan->dcid = cid; + +	auth_type = l2cap_get_auth_type(chan); + +	if (bdaddr_type_is_le(dst_type)) { +		/* Convert from L2CAP channel address type to HCI address type +		 */ +		if (dst_type == BDADDR_LE_PUBLIC) +			dst_type = ADDR_LE_DEV_PUBLIC; +		else +			dst_type = ADDR_LE_DEV_RANDOM; + +		hcon = hci_connect_le(hdev, dst, dst_type, chan->sec_level, +				      auth_type); +	} else { +		hcon = hci_connect_acl(hdev, dst, chan->sec_level, auth_type); +	} + +	if (IS_ERR(hcon)) { +		err = PTR_ERR(hcon); +		goto done; +	} + +	conn = l2cap_conn_add(hcon); +	if (!conn) { +		hci_conn_drop(hcon); +		err = -ENOMEM; +		goto done; +	} + +	if (cid && __l2cap_get_chan_by_dcid(conn, cid)) { +		hci_conn_drop(hcon); +		err = -EBUSY; +		goto done; +	} + +	/* Update source addr of the socket */ +	bacpy(&chan->src, &hcon->src); +	chan->src_type = bdaddr_type(hcon, hcon->src_type); + +	l2cap_chan_unlock(chan); +	l2cap_chan_add(conn, chan); +	l2cap_chan_lock(chan); + +	/* l2cap_chan_add takes its own ref so we can drop this one */ +	hci_conn_drop(hcon); + +	l2cap_state_change(chan, BT_CONNECT); +	__set_chan_timer(chan, chan->ops->get_sndtimeo(chan)); + +	/* Release chan->sport so that it can be reused by other +	 * sockets (as it's only used for listening sockets). +	 */ +	write_lock(&chan_list_lock); +	chan->sport = 0; +	write_unlock(&chan_list_lock); + +	if (hcon->state == BT_CONNECTED) { +		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { +			__clear_chan_timer(chan); +			if (l2cap_chan_check_security(chan)) +				l2cap_state_change(chan, BT_CONNECTED); +		} else +			l2cap_do_start(chan); +	} + +	err = 0; + +done: +	l2cap_chan_unlock(chan); +	hci_dev_unlock(hdev); +	hci_dev_put(hdev); +	return err; +} +  /* ---- L2CAP interface with lower layer (HCI) ---- */  int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr) @@ -6481,17 +7203,15 @@ int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)  	/* Find listening sockets and check their link_mode */  	read_lock(&chan_list_lock);  	list_for_each_entry(c, &chan_list, global_l) { -		struct sock *sk = c->sk; -  		if (c->state != BT_LISTEN)  			continue; -		if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) { +		if (!bacmp(&c->src, &hdev->bdaddr)) {  			lm1 |= HCI_LM_ACCEPT;  			if (test_bit(FLAG_ROLE_SWITCH, &c->flags))  				lm1 |= HCI_LM_MASTER;  			exact++; -		} else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) { +		} else if (!bacmp(&c->src, BDADDR_ANY)) {  			lm2 |= HCI_LM_ACCEPT;  			if (test_bit(FLAG_ROLE_SWITCH, &c->flags))  				lm2 |= HCI_LM_MASTER; @@ -6532,6 +7252,8 @@ void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)  {  	BT_DBG("hcon %p reason %d", hcon, reason); +	bt_6lowpan_del_conn(hcon->l2cap_data); +  	l2cap_conn_del(hcon, bt_to_errno(reason));  } @@ -6543,7 +7265,8 @@ static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)  	if (encrypt == 0x00) {  		if (chan->sec_level == BT_SECURITY_MEDIUM) {  			__set_chan_timer(chan, L2CAP_ENC_TIMEOUT); -		} else if (chan->sec_level == BT_SECURITY_HIGH) +		} else if (chan->sec_level == BT_SECURITY_HIGH || +			   chan->sec_level == BT_SECURITY_FIPS)  			l2cap_chan_close(chan, ECONNREFUSED);  	} else {  		if (chan->sec_level == BT_SECURITY_MEDIUM) @@ -6563,7 +7286,7 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)  	if (hcon->type == LE_LINK) {  		if (!status && encrypt) -			smp_distribute_keys(conn, 0); +			smp_distribute_keys(conn);  		cancel_delayed_work(&conn->security_timer);  	} @@ -6575,7 +7298,7 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)  		BT_DBG("chan %p scid 0x%4.4x state %s", chan, chan->scid,  		       state_to_string(chan->state)); -		if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) { +		if (chan->scid == L2CAP_CID_A2MP) {  			l2cap_chan_unlock(chan);  			continue;  		} @@ -6597,49 +7320,38 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)  		if (!status && (chan->state == BT_CONNECTED ||  				chan->state == BT_CONFIG)) { -			struct sock *sk = chan->sk; - -			clear_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags); -			sk->sk_state_change(sk); - +			chan->ops->resume(chan);  			l2cap_check_encryption(chan, encrypt);  			l2cap_chan_unlock(chan);  			continue;  		}  		if (chan->state == BT_CONNECT) { -			if (!status) { +			if (!status)  				l2cap_start_connection(chan); -			} else { +			else  				__set_chan_timer(chan, L2CAP_DISC_TIMEOUT); -			}  		} else if (chan->state == BT_CONNECT2) { -			struct sock *sk = chan->sk;  			struct l2cap_conn_rsp rsp;  			__u16 res, stat; -			lock_sock(sk); -  			if (!status) { -				if (test_bit(BT_SK_DEFER_SETUP, -					     &bt_sk(sk)->flags)) { +				if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {  					res = L2CAP_CR_PEND;  					stat = L2CAP_CS_AUTHOR_PEND;  					chan->ops->defer(chan);  				} else { -					__l2cap_state_change(chan, BT_CONFIG); +					l2cap_state_change(chan, BT_CONFIG);  					res = L2CAP_CR_SUCCESS;  					stat = L2CAP_CS_NO_INFO;  				}  			} else { -				__l2cap_state_change(chan, BT_DISCONN); +				l2cap_state_change(chan, BT_DISCONN);  				__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);  				res = L2CAP_CR_SEC_BLOCK;  				stat = L2CAP_CS_NO_INFO;  			} -			release_sock(sk); -  			rsp.scid   = cpu_to_le16(chan->dcid);  			rsp.dcid   = cpu_to_le16(chan->scid);  			rsp.result = cpu_to_le16(res); @@ -6756,9 +7468,13 @@ int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)  		conn->rx_len -= skb->len;  		if (!conn->rx_len) { -			/* Complete frame received */ -			l2cap_recv_frame(conn, conn->rx_skb); +			/* Complete frame received. l2cap_recv_frame +			 * takes ownership of the skb so set the global +			 * rx_skb pointer to NULL first. +			 */ +			struct sk_buff *rx_skb = conn->rx_skb;  			conn->rx_skb = NULL; +			l2cap_recv_frame(conn, rx_skb);  		}  		break;  	} @@ -6775,10 +7491,8 @@ static int l2cap_debugfs_show(struct seq_file *f, void *p)  	read_lock(&chan_list_lock);  	list_for_each_entry(c, &chan_list, global_l) { -		struct sock *sk = c->sk; -  		seq_printf(f, "%pMR %pMR %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n", -			   &bt_sk(sk)->src, &bt_sk(sk)->dst, +			   &c->src, &c->dst,  			   c->state, __le16_to_cpu(c->psm),  			   c->scid, c->dcid, c->imtu, c->omtu,  			   c->sec_level, c->mode); @@ -6811,18 +7525,25 @@ int __init l2cap_init(void)  	if (err < 0)  		return err; -	if (bt_debugfs) { -		l2cap_debugfs = debugfs_create_file("l2cap", 0444, bt_debugfs, -						    NULL, &l2cap_debugfs_fops); -		if (!l2cap_debugfs) -			BT_ERR("Failed to create L2CAP debug file"); -	} +	if (IS_ERR_OR_NULL(bt_debugfs)) +		return 0; + +	l2cap_debugfs = debugfs_create_file("l2cap", 0444, bt_debugfs, +					    NULL, &l2cap_debugfs_fops); + +	debugfs_create_u16("l2cap_le_max_credits", 0644, bt_debugfs, +			   &le_max_credits); +	debugfs_create_u16("l2cap_le_default_mps", 0644, bt_debugfs, +			   &le_default_mps); + +	bt_6lowpan_init();  	return 0;  }  void l2cap_exit(void)  { +	bt_6lowpan_cleanup();  	debugfs_remove(l2cap_debugfs);  	l2cap_cleanup_sockets();  }  | 
