aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@intel.com>2013-10-16 04:20:47 -0400
committerMarcel Holtmann <marcel@holtmann.org>2013-10-16 04:22:55 -0400
commit662d652dd60edbb45acab772baedaf39a2f22ffc (patch)
tree7c94da98fdfad1e09e6506b2e2d02bfe2c585c2e
parentdb3aebf4a13562c60761e5530f2cbf6ef9fdee2b (diff)
Bluetooth: Fix L2CAP "Command Reject: Invalid CID" response
When the reason code in the L2CAP command reject is "invalid CID" there should be four additional bytes of data in the PDU, namely the source and destination CIDs (which should be zero if one or both are not applicable). This patch fixes all occurrences of such errors to return the right kind of PDU. Signed-off-by: Johan Hedberg <johan.hedberg@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
-rw-r--r--net/bluetooth/l2cap_core.c37
1 files changed, 23 insertions, 14 deletions
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 72ce21a822f7..157833051a06 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -3971,6 +3971,18 @@ static void l2cap_send_efs_conf_rsp(struct l2cap_chan *chan, void *data,
3971 L2CAP_CONF_SUCCESS, flags), data); 3971 L2CAP_CONF_SUCCESS, flags), data);
3972} 3972}
3973 3973
3974static void cmd_reject_invalid_cid(struct l2cap_conn *conn, u8 ident,
3975 u16 scid, u16 dcid)
3976{
3977 struct l2cap_cmd_rej_cid rej;
3978
3979 rej.reason = __constant_cpu_to_le16(L2CAP_REJ_INVALID_CID);
3980 rej.scid = __cpu_to_le16(scid);
3981 rej.dcid = __cpu_to_le16(dcid);
3982
3983 l2cap_send_cmd(conn, ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
3984}
3985
3974static inline int l2cap_config_req(struct l2cap_conn *conn, 3986static inline int l2cap_config_req(struct l2cap_conn *conn,
3975 struct l2cap_cmd_hdr *cmd, u16 cmd_len, 3987 struct l2cap_cmd_hdr *cmd, u16 cmd_len,
3976 u8 *data) 3988 u8 *data)
@@ -3990,18 +4002,14 @@ static inline int l2cap_config_req(struct l2cap_conn *conn,
3990 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags); 4002 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
3991 4003
3992 chan = l2cap_get_chan_by_scid(conn, dcid); 4004 chan = l2cap_get_chan_by_scid(conn, dcid);
3993 if (!chan) 4005 if (!chan) {
3994 return -EBADSLT; 4006 cmd_reject_invalid_cid(conn, cmd->ident, dcid, 0);
4007 return 0;
4008 }
3995 4009
3996 if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) { 4010 if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
3997 struct l2cap_cmd_rej_cid rej; 4011 cmd_reject_invalid_cid(conn, cmd->ident, chan->scid,
3998 4012 chan->dcid);
3999 rej.reason = __constant_cpu_to_le16(L2CAP_REJ_INVALID_CID);
4000 rej.scid = cpu_to_le16(chan->scid);
4001 rej.dcid = cpu_to_le16(chan->dcid);
4002
4003 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
4004 sizeof(rej), &rej);
4005 goto unlock; 4013 goto unlock;
4006 } 4014 }
4007 4015
@@ -4218,7 +4226,8 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn,
4218 chan = __l2cap_get_chan_by_scid(conn, dcid); 4226 chan = __l2cap_get_chan_by_scid(conn, dcid);
4219 if (!chan) { 4227 if (!chan) {
4220 mutex_unlock(&conn->chan_lock); 4228 mutex_unlock(&conn->chan_lock);
4221 return -EBADSLT; 4229 cmd_reject_invalid_cid(conn, cmd->ident, dcid, scid);
4230 return 0;
4222 } 4231 }
4223 4232
4224 l2cap_chan_lock(chan); 4233 l2cap_chan_lock(chan);
@@ -4447,7 +4456,9 @@ static int l2cap_create_channel_req(struct l2cap_conn *conn,
4447 &conn->hcon->dst); 4456 &conn->hcon->dst);
4448 if (!hs_hcon) { 4457 if (!hs_hcon) {
4449 hci_dev_put(hdev); 4458 hci_dev_put(hdev);
4450 return -EBADSLT; 4459 cmd_reject_invalid_cid(conn, cmd->ident, chan->scid,
4460 chan->dcid);
4461 return 0;
4451 } 4462 }
4452 4463
4453 BT_DBG("mgr %p bredr_chan %p hs_hcon %p", mgr, chan, hs_hcon); 4464 BT_DBG("mgr %p bredr_chan %p hs_hcon %p", mgr, chan, hs_hcon);
@@ -5306,8 +5317,6 @@ static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
5306static __le16 l2cap_err_to_reason(int err) 5317static __le16 l2cap_err_to_reason(int err)
5307{ 5318{
5308 switch (err) { 5319 switch (err) {
5309 case -EBADSLT:
5310 return __constant_cpu_to_le16(L2CAP_REJ_INVALID_CID);
5311 case -EMSGSIZE: 5320 case -EMSGSIZE:
5312 return __constant_cpu_to_le16(L2CAP_REJ_MTU_EXCEEDED); 5321 return __constant_cpu_to_le16(L2CAP_REJ_MTU_EXCEEDED);
5313 case -EINVAL: 5322 case -EINVAL: