Commit b01b5bbf authored by Marcel Holtmann's avatar Marcel Holtmann Committed by Marcel Holtmann

[Bluetooth] Check for L2CAP reliability

The L2CAP sockets can now set LM_RELIABLE flag and get notification
when a reliability problem with the ACL connection is detected. The
Bluetooth qualification tests require this functionality.
Signed-off-by: default avatarMaxim Krasnyansky <maxk@qualcomm.com>
Signed-off-by: default avatarMarcel Holtmann <marcel@holtmann.org>
parent 4227e3a8
...@@ -1100,6 +1100,22 @@ static void l2cap_conn_ready(struct l2cap_conn *conn) ...@@ -1100,6 +1100,22 @@ static void l2cap_conn_ready(struct l2cap_conn *conn)
read_unlock(&l->lock); read_unlock(&l->lock);
} }
/* Notify sockets that we cannot guaranty reliability anymore */
static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
{
struct l2cap_chan_list *l = &conn->chan_list;
struct sock *sk;
BT_DBG("conn %p", conn);
read_lock(&l->lock);
for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
if (l2cap_pi(sk)->link_mode & L2CAP_LM_RELIABLE)
sk->sk_err = err;
}
read_unlock(&l->lock);
}
static void l2cap_chan_ready(struct sock *sk) static void l2cap_chan_ready(struct sock *sk)
{ {
struct sock *parent = bt_sk(sk)->parent; struct sock *parent = bt_sk(sk)->parent;
...@@ -2045,10 +2061,12 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl ...@@ -2045,10 +2061,12 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl
kfree_skb(conn->rx_skb); kfree_skb(conn->rx_skb);
conn->rx_skb = NULL; conn->rx_skb = NULL;
conn->rx_len = 0; conn->rx_len = 0;
l2cap_conn_unreliable(conn, ECOMM);
} }
if (skb->len < 2) { if (skb->len < 2) {
BT_ERR("Frame is too short (len %d)", skb->len); BT_ERR("Frame is too short (len %d)", skb->len);
l2cap_conn_unreliable(conn, ECOMM);
goto drop; goto drop;
} }
...@@ -2066,6 +2084,7 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl ...@@ -2066,6 +2084,7 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl
if (skb->len > len) { if (skb->len > len) {
BT_ERR("Frame is too long (len %d, expected len %d)", BT_ERR("Frame is too long (len %d, expected len %d)",
skb->len, len); skb->len, len);
l2cap_conn_unreliable(conn, ECOMM);
goto drop; goto drop;
} }
...@@ -2080,6 +2099,7 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl ...@@ -2080,6 +2099,7 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl
if (!conn->rx_len) { if (!conn->rx_len) {
BT_ERR("Unexpected continuation frame (len %d)", skb->len); BT_ERR("Unexpected continuation frame (len %d)", skb->len);
l2cap_conn_unreliable(conn, ECOMM);
goto drop; goto drop;
} }
...@@ -2089,6 +2109,7 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl ...@@ -2089,6 +2109,7 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl
kfree_skb(conn->rx_skb); kfree_skb(conn->rx_skb);
conn->rx_skb = NULL; conn->rx_skb = NULL;
conn->rx_len = 0; conn->rx_len = 0;
l2cap_conn_unreliable(conn, ECOMM);
goto drop; goto drop;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment