Commit fb7bd0c1 authored by David S. Miller's avatar David S. Miller

Merge http://linux-mh.bkbits.net/bluetooth-2.6

into nuts.davemloft.net:/disk1/BK/net-2.6
parents 1947ca57 b01b5bbf
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
* *
* Broadcom Blutonium firmware driver * Broadcom Blutonium firmware driver
* *
* Copyright (C) 2003 Maxim Krasnyansky <maxk@qualcomm.com>
* Copyright (C) 2003 Marcel Holtmann <marcel@holtmann.org> * Copyright (C) 2003 Marcel Holtmann <marcel@holtmann.org>
* *
* *
......
...@@ -170,6 +170,8 @@ enum { ...@@ -170,6 +170,8 @@ enum {
#define HCI_LM_AUTH 0x0002 #define HCI_LM_AUTH 0x0002
#define HCI_LM_ENCRYPT 0x0004 #define HCI_LM_ENCRYPT 0x0004
#define HCI_LM_TRUSTED 0x0008 #define HCI_LM_TRUSTED 0x0008
#define HCI_LM_RELIABLE 0x0010
#define HCI_LM_SECURE 0x0020
/* ----- HCI Commands ---- */ /* ----- HCI Commands ---- */
/* OGF & OCF values */ /* OGF & OCF values */
......
...@@ -56,6 +56,8 @@ struct l2cap_conninfo { ...@@ -56,6 +56,8 @@ struct l2cap_conninfo {
#define L2CAP_LM_AUTH 0x0002 #define L2CAP_LM_AUTH 0x0002
#define L2CAP_LM_ENCRYPT 0x0004 #define L2CAP_LM_ENCRYPT 0x0004
#define L2CAP_LM_TRUSTED 0x0008 #define L2CAP_LM_TRUSTED 0x0008
#define L2CAP_LM_RELIABLE 0x0010
#define L2CAP_LM_SECURE 0x0020
#define L2CAP_QOS 0x04 #define L2CAP_QOS 0x04
struct l2cap_qos { struct l2cap_qos {
......
...@@ -57,7 +57,7 @@ ...@@ -57,7 +57,7 @@
#define BT_DBG(D...) #define BT_DBG(D...)
#endif #endif
#define VERSION "2.5" #define VERSION "2.6"
static struct proto_ops l2cap_sock_ops; static struct proto_ops l2cap_sock_ops;
...@@ -964,6 +964,7 @@ static inline struct sock *l2cap_get_chan_by_ident(struct l2cap_chan_list *l, u8 ...@@ -964,6 +964,7 @@ static inline struct sock *l2cap_get_chan_by_ident(struct l2cap_chan_list *l, u8
struct sock *s; struct sock *s;
read_lock(&l->lock); read_lock(&l->lock);
s = __l2cap_get_chan_by_ident(l, ident); s = __l2cap_get_chan_by_ident(l, ident);
if (s) bh_lock_sock(s);
read_unlock(&l->lock); read_unlock(&l->lock);
return s; return s;
} }
...@@ -1099,6 +1100,22 @@ static void l2cap_conn_ready(struct l2cap_conn *conn) ...@@ -1099,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;
...@@ -1427,7 +1444,8 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd ...@@ -1427,7 +1444,8 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
sk->sk_state = BT_CONNECT2; sk->sk_state = BT_CONNECT2;
l2cap_pi(sk)->ident = cmd->ident; l2cap_pi(sk)->ident = cmd->ident;
if (l2cap_pi(sk)->link_mode & L2CAP_LM_ENCRYPT) { if ((l2cap_pi(sk)->link_mode & L2CAP_LM_ENCRYPT) ||
(l2cap_pi(sk)->link_mode & L2CAP_LM_SECURE)) {
if (!hci_conn_encrypt(conn->hcon)) if (!hci_conn_encrypt(conn->hcon))
goto done; goto done;
} else if (l2cap_pi(sk)->link_mode & L2CAP_LM_AUTH) { } else if (l2cap_pi(sk)->link_mode & L2CAP_LM_AUTH) {
...@@ -1946,7 +1964,8 @@ static int l2cap_auth_cfm(struct hci_conn *hcon, u8 status) ...@@ -1946,7 +1964,8 @@ static int l2cap_auth_cfm(struct hci_conn *hcon, u8 status)
bh_lock_sock(sk); bh_lock_sock(sk);
if (sk->sk_state != BT_CONNECT2 || if (sk->sk_state != BT_CONNECT2 ||
(l2cap_pi(sk)->link_mode & L2CAP_LM_ENCRYPT)) { (l2cap_pi(sk)->link_mode & L2CAP_LM_ENCRYPT) ||
(l2cap_pi(sk)->link_mode & L2CAP_LM_SECURE)) {
bh_unlock_sock(sk); bh_unlock_sock(sk);
continue; continue;
} }
...@@ -2014,6 +2033,9 @@ static int l2cap_encrypt_cfm(struct hci_conn *hcon, u8 status) ...@@ -2014,6 +2033,9 @@ static int l2cap_encrypt_cfm(struct hci_conn *hcon, u8 status)
l2cap_send_cmd(conn, l2cap_pi(sk)->ident, l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
L2CAP_CONN_RSP, sizeof(rsp), &rsp); L2CAP_CONN_RSP, sizeof(rsp), &rsp);
if (l2cap_pi(sk)->link_mode & L2CAP_LM_SECURE)
hci_conn_change_link_key(hcon);
bh_unlock_sock(sk); bh_unlock_sock(sk);
} }
...@@ -2039,10 +2061,12 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl ...@@ -2039,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;
} }
...@@ -2060,6 +2084,7 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl ...@@ -2060,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;
} }
...@@ -2074,6 +2099,7 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl ...@@ -2074,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;
} }
...@@ -2083,6 +2109,7 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl ...@@ -2083,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