瀏覽代碼

Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/padovan/bluetooth-next-2.6

John W. Linville 14 年之前
父節點
當前提交
dee04cac28

+ 9 - 0
include/net/bluetooth/hci.h

@@ -246,6 +246,15 @@ enum {
 #define HCI_AT_GENERAL_BONDING		0x04
 #define HCI_AT_GENERAL_BONDING		0x04
 #define HCI_AT_GENERAL_BONDING_MITM	0x05
 #define HCI_AT_GENERAL_BONDING_MITM	0x05
 
 
+/* Link Key types */
+#define HCI_LK_COMBINATION		0x00
+#define HCI_LK_LOCAL_UNIT		0x01
+#define HCI_LK_REMOTE_UNIT		0x02
+#define HCI_LK_DEBUG_COMBINATION	0x03
+#define HCI_LK_UNAUTH_COMBINATION	0x04
+#define HCI_LK_AUTH_COMBINATION		0x05
+#define HCI_LK_CHANGED_COMBINATION	0x06
+
 /* -----  HCI Commands ---- */
 /* -----  HCI Commands ---- */
 #define HCI_OP_NOP			0x0000
 #define HCI_OP_NOP			0x0000
 
 

+ 11 - 5
include/net/bluetooth/hci_core.h

@@ -126,6 +126,8 @@ struct hci_dev {
 	__u16		sniff_min_interval;
 	__u16		sniff_min_interval;
 	__u16		sniff_max_interval;
 	__u16		sniff_max_interval;
 
 
+	unsigned int	auto_accept_delay;
+
 	unsigned long	quirks;
 	unsigned long	quirks;
 
 
 	atomic_t	cmd_cnt;
 	atomic_t	cmd_cnt;
@@ -226,6 +228,7 @@ struct hci_conn {
 	__u16		pkt_type;
 	__u16		pkt_type;
 	__u16		link_policy;
 	__u16		link_policy;
 	__u32		link_mode;
 	__u32		link_mode;
+	__u8		key_type;
 	__u8		auth_type;
 	__u8		auth_type;
 	__u8		sec_level;
 	__u8		sec_level;
 	__u8		pending_sec_level;
 	__u8		pending_sec_level;
@@ -245,6 +248,7 @@ struct hci_conn {
 
 
 	struct timer_list disc_timer;
 	struct timer_list disc_timer;
 	struct timer_list idle_timer;
 	struct timer_list idle_timer;
+	struct timer_list auto_accept_timer;
 
 
 	struct work_struct work_add;
 	struct work_struct work_add;
 	struct work_struct work_del;
 	struct work_struct work_del;
@@ -511,8 +515,8 @@ int hci_uuids_clear(struct hci_dev *hdev);
 
 
 int hci_link_keys_clear(struct hci_dev *hdev);
 int hci_link_keys_clear(struct hci_dev *hdev);
 struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr);
 struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr);
-int hci_add_link_key(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr,
-						u8 *key, u8 type, u8 pin_len);
+int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key,
+			bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len);
 int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr);
 int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr);
 
 
 int hci_remote_oob_data_clear(struct hci_dev *hdev);
 int hci_remote_oob_data_clear(struct hci_dev *hdev);
@@ -771,15 +775,16 @@ int mgmt_index_removed(u16 index);
 int mgmt_powered(u16 index, u8 powered);
 int mgmt_powered(u16 index, u8 powered);
 int mgmt_discoverable(u16 index, u8 discoverable);
 int mgmt_discoverable(u16 index, u8 discoverable);
 int mgmt_connectable(u16 index, u8 connectable);
 int mgmt_connectable(u16 index, u8 connectable);
-int mgmt_new_key(u16 index, struct link_key *key, u8 old_key_type);
+int mgmt_new_key(u16 index, struct link_key *key, u8 persistent);
 int mgmt_connected(u16 index, bdaddr_t *bdaddr);
 int mgmt_connected(u16 index, bdaddr_t *bdaddr);
 int mgmt_disconnected(u16 index, bdaddr_t *bdaddr);
 int mgmt_disconnected(u16 index, bdaddr_t *bdaddr);
 int mgmt_disconnect_failed(u16 index);
 int mgmt_disconnect_failed(u16 index);
 int mgmt_connect_failed(u16 index, bdaddr_t *bdaddr, u8 status);
 int mgmt_connect_failed(u16 index, bdaddr_t *bdaddr, u8 status);
-int mgmt_pin_code_request(u16 index, bdaddr_t *bdaddr);
+int mgmt_pin_code_request(u16 index, bdaddr_t *bdaddr, u8 secure);
 int mgmt_pin_code_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status);
 int mgmt_pin_code_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status);
 int mgmt_pin_code_neg_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status);
 int mgmt_pin_code_neg_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status);
-int mgmt_user_confirm_request(u16 index, bdaddr_t *bdaddr, __le32 value);
+int mgmt_user_confirm_request(u16 index, bdaddr_t *bdaddr, __le32 value,
+							u8 confirm_hint);
 int mgmt_user_confirm_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status);
 int mgmt_user_confirm_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status);
 int mgmt_user_confirm_neg_reply_complete(u16 index, bdaddr_t *bdaddr,
 int mgmt_user_confirm_neg_reply_complete(u16 index, bdaddr_t *bdaddr,
 								u8 status);
 								u8 status);
@@ -790,6 +795,7 @@ int mgmt_read_local_oob_data_reply_complete(u16 index, u8 *hash, u8 *randomizer,
 int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 *dev_class, s8 rssi,
 int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 *dev_class, s8 rssi,
 								u8 *eir);
 								u8 *eir);
 int mgmt_remote_name(u16 index, bdaddr_t *bdaddr, u8 *name);
 int mgmt_remote_name(u16 index, bdaddr_t *bdaddr, u8 *name);
+int mgmt_discovering(u16 index, u8 discovering);
 
 
 /* HCI info for socket */
 /* HCI info for socket */
 #define hci_pi(sk) ((struct hci_pinfo *) sk)
 #define hci_pi(sk) ((struct hci_pinfo *) sk)

+ 36 - 33
include/net/bluetooth/l2cap.h

@@ -284,6 +284,25 @@ struct srej_list {
 
 
 struct l2cap_chan {
 struct l2cap_chan {
 	struct sock *sk;
 	struct sock *sk;
+
+	struct l2cap_conn	*conn;
+
+	__le16		psm;
+	__u16		dcid;
+	__u16		scid;
+
+	__u16		imtu;
+	__u16		omtu;
+	__u16		flush_to;
+	__u8		mode;
+
+	__le16		sport;
+
+	__u8		sec_level;
+	__u8		role_switch;
+	__u8		force_reliable;
+	__u8		flushable;
+
 	__u8		ident;
 	__u8		ident;
 
 
 	__u8		conf_req[64];
 	__u8		conf_req[64];
@@ -291,6 +310,15 @@ struct l2cap_chan {
 	__u8		num_conf_req;
 	__u8		num_conf_req;
 	__u8		num_conf_rsp;
 	__u8		num_conf_rsp;
 
 
+	__u8		fcs;
+
+	__u8		tx_win;
+	__u8		max_tx;
+	__u16		retrans_timeout;
+	__u16		monitor_timeout;
+	__u16		mps;
+
+	__u8		conf_state;
 	__u16		conn_state;
 	__u16		conn_state;
 
 
 	__u8		next_tx_seq;
 	__u8		next_tx_seq;
@@ -360,32 +388,6 @@ struct l2cap_conn {
 
 
 struct l2cap_pinfo {
 struct l2cap_pinfo {
 	struct bt_sock	bt;
 	struct bt_sock	bt;
-	__le16		psm;
-	__u16		dcid;
-	__u16		scid;
-
-	__u16		imtu;
-	__u16		omtu;
-	__u16		flush_to;
-	__u8		mode;
-
-	__u8		fcs;
-	__u8		sec_level;
-	__u8		role_switch;
-	__u8		force_reliable;
-	__u8		flushable;
-
-	__u8		conf_state;
-
-	__u8		tx_win;
-	__u8		max_tx;
-	__u16		retrans_timeout;
-	__u16		monitor_timeout;
-	__u16		mps;
-
-	__le16		sport;
-
-	struct l2cap_conn	*conn;
 	struct l2cap_chan	*chan;
 	struct l2cap_chan	*chan;
 };
 };
 
 
@@ -439,21 +441,20 @@ static inline int l2cap_tx_window_full(struct l2cap_chan *ch)
 #define __is_sar_start(ctrl)	(((ctrl) & L2CAP_CTRL_SAR) == L2CAP_SDU_START)
 #define __is_sar_start(ctrl)	(((ctrl) & L2CAP_CTRL_SAR) == L2CAP_SDU_START)
 
 
 extern int disable_ertm;
 extern int disable_ertm;
-extern const struct proto_ops l2cap_sock_ops;
 extern struct bt_sock_list l2cap_sk_list;
 extern struct bt_sock_list l2cap_sk_list;
 
 
 int l2cap_init_sockets(void);
 int l2cap_init_sockets(void);
 void l2cap_cleanup_sockets(void);
 void l2cap_cleanup_sockets(void);
 
 
 void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data);
 void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data);
-void __l2cap_connect_rsp_defer(struct sock *sk);
+void __l2cap_connect_rsp_defer(struct l2cap_chan *chan);
 int __l2cap_wait_ack(struct sock *sk);
 int __l2cap_wait_ack(struct sock *sk);
 
 
-struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len);
-struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len);
-struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *msg, size_t len, u16 control, u16 sdulen);
+struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len);
+struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len);
+struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len, u16 control, u16 sdulen);
 int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len);
 int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len);
-void l2cap_do_send(struct sock *sk, struct sk_buff *skb);
+void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb);
 void l2cap_streaming_send(struct l2cap_chan *chan);
 void l2cap_streaming_send(struct l2cap_chan *chan);
 int l2cap_ertm_send(struct l2cap_chan *chan);
 int l2cap_ertm_send(struct l2cap_chan *chan);
 
 
@@ -465,7 +466,9 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent);
 struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock,
 struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock,
 							int proto, gfp_t prio);
 							int proto, gfp_t prio);
 void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err);
 void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err);
+struct l2cap_chan *l2cap_chan_alloc(struct sock *sk);
 void l2cap_chan_del(struct l2cap_chan *chan, int err);
 void l2cap_chan_del(struct l2cap_chan *chan, int err);
-int l2cap_do_connect(struct sock *sk);
+void l2cap_chan_free(struct l2cap_chan *chan);
+int l2cap_chan_connect(struct l2cap_chan *chan);
 
 
 #endif /* __L2CAP_H */
 #endif /* __L2CAP_H */

+ 9 - 1
include/net/bluetooth/mgmt.h

@@ -195,6 +195,10 @@ struct mgmt_cp_remove_remote_oob_data {
 	bdaddr_t bdaddr;
 	bdaddr_t bdaddr;
 } __packed;
 } __packed;
 
 
+#define MGMT_OP_START_DISCOVERY		0x001B
+
+#define MGMT_OP_STOP_DISCOVERY		0x001C
+
 #define MGMT_EV_CMD_COMPLETE		0x0001
 #define MGMT_EV_CMD_COMPLETE		0x0001
 struct mgmt_ev_cmd_complete {
 struct mgmt_ev_cmd_complete {
 	__le16 opcode;
 	__le16 opcode;
@@ -226,8 +230,8 @@ struct mgmt_ev_controller_error {
 
 
 #define MGMT_EV_NEW_KEY			0x000A
 #define MGMT_EV_NEW_KEY			0x000A
 struct mgmt_ev_new_key {
 struct mgmt_ev_new_key {
+	__u8 store_hint;
 	struct mgmt_key_info key;
 	struct mgmt_key_info key;
-	__u8 old_key_type;
 } __packed;
 } __packed;
 
 
 #define MGMT_EV_CONNECTED		0x000B
 #define MGMT_EV_CONNECTED		0x000B
@@ -249,11 +253,13 @@ struct mgmt_ev_connect_failed {
 #define MGMT_EV_PIN_CODE_REQUEST	0x000E
 #define MGMT_EV_PIN_CODE_REQUEST	0x000E
 struct mgmt_ev_pin_code_request {
 struct mgmt_ev_pin_code_request {
 	bdaddr_t bdaddr;
 	bdaddr_t bdaddr;
+	__u8 secure;
 } __packed;
 } __packed;
 
 
 #define MGMT_EV_USER_CONFIRM_REQUEST	0x000F
 #define MGMT_EV_USER_CONFIRM_REQUEST	0x000F
 struct mgmt_ev_user_confirm_request {
 struct mgmt_ev_user_confirm_request {
 	bdaddr_t bdaddr;
 	bdaddr_t bdaddr;
+	__u8 confirm_hint;
 	__le32 value;
 	__le32 value;
 } __packed;
 } __packed;
 
 
@@ -281,3 +287,5 @@ struct mgmt_ev_remote_name {
 	bdaddr_t bdaddr;
 	bdaddr_t bdaddr;
 	__u8 name[MGMT_MAX_NAME_LENGTH];
 	__u8 name[MGMT_MAX_NAME_LENGTH];
 } __packed;
 } __packed;
+
+#define MGMT_EV_DISCOVERING		0x0014

+ 2 - 1
net/bluetooth/cmtp/core.c

@@ -346,7 +346,8 @@ int cmtp_add_connection(struct cmtp_connadd_req *req, struct socket *sock)
 
 
 	bacpy(&session->bdaddr, &bt_sk(sock->sk)->dst);
 	bacpy(&session->bdaddr, &bt_sk(sock->sk)->dst);
 
 
-	session->mtu = min_t(uint, l2cap_pi(sock->sk)->omtu, l2cap_pi(sock->sk)->imtu);
+	session->mtu = min_t(uint, l2cap_pi(sock->sk)->chan->omtu,
+					l2cap_pi(sock->sk)->chan->imtu);
 
 
 	BT_DBG("mtu %d", session->mtu);
 	BT_DBG("mtu %d", session->mtu);
 
 

+ 68 - 10
net/bluetooth/hci_conn.c

@@ -269,6 +269,19 @@ static void hci_conn_idle(unsigned long arg)
 	hci_conn_enter_sniff_mode(conn);
 	hci_conn_enter_sniff_mode(conn);
 }
 }
 
 
+static void hci_conn_auto_accept(unsigned long arg)
+{
+	struct hci_conn *conn = (void *) arg;
+	struct hci_dev *hdev = conn->hdev;
+
+	hci_dev_lock(hdev);
+
+	hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY, sizeof(conn->dst),
+								&conn->dst);
+
+	hci_dev_unlock(hdev);
+}
+
 struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
 struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
 {
 {
 	struct hci_conn *conn;
 	struct hci_conn *conn;
@@ -287,6 +300,7 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
 	conn->auth_type = HCI_AT_GENERAL_BONDING;
 	conn->auth_type = HCI_AT_GENERAL_BONDING;
 	conn->io_capability = hdev->io_capability;
 	conn->io_capability = hdev->io_capability;
 	conn->remote_auth = 0xff;
 	conn->remote_auth = 0xff;
+	conn->key_type = 0xff;
 
 
 	conn->power_save = 1;
 	conn->power_save = 1;
 	conn->disc_timeout = HCI_DISCONN_TIMEOUT;
 	conn->disc_timeout = HCI_DISCONN_TIMEOUT;
@@ -311,6 +325,8 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
 
 
 	setup_timer(&conn->disc_timer, hci_conn_timeout, (unsigned long)conn);
 	setup_timer(&conn->disc_timer, hci_conn_timeout, (unsigned long)conn);
 	setup_timer(&conn->idle_timer, hci_conn_idle, (unsigned long)conn);
 	setup_timer(&conn->idle_timer, hci_conn_idle, (unsigned long)conn);
+	setup_timer(&conn->auto_accept_timer, hci_conn_auto_accept,
+							(unsigned long) conn);
 
 
 	atomic_set(&conn->refcnt, 0);
 	atomic_set(&conn->refcnt, 0);
 
 
@@ -341,6 +357,8 @@ int hci_conn_del(struct hci_conn *conn)
 
 
 	del_timer(&conn->disc_timer);
 	del_timer(&conn->disc_timer);
 
 
+	del_timer(&conn->auto_accept_timer);
+
 	if (conn->type == ACL_LINK) {
 	if (conn->type == ACL_LINK) {
 		struct hci_conn *sco = conn->link;
 		struct hci_conn *sco = conn->link;
 		if (sco)
 		if (sco)
@@ -535,32 +553,72 @@ static int hci_conn_auth(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
 	return 0;
 	return 0;
 }
 }
 
 
+/* Encrypt the the link */
+static void hci_conn_encrypt(struct hci_conn *conn)
+{
+	BT_DBG("conn %p", conn);
+
+	if (!test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {
+		struct hci_cp_set_conn_encrypt cp;
+		cp.handle  = cpu_to_le16(conn->handle);
+		cp.encrypt = 0x01;
+		hci_send_cmd(conn->hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
+									&cp);
+	}
+}
+
 /* Enable security */
 /* Enable security */
 int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
 int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
 {
 {
 	BT_DBG("conn %p", conn);
 	BT_DBG("conn %p", conn);
 
 
+	/* For sdp we don't need the link key. */
 	if (sec_level == BT_SECURITY_SDP)
 	if (sec_level == BT_SECURITY_SDP)
 		return 1;
 		return 1;
 
 
+	/* For non 2.1 devices and low security level we don't need the link
+	   key. */
 	if (sec_level == BT_SECURITY_LOW &&
 	if (sec_level == BT_SECURITY_LOW &&
 				(!conn->ssp_mode || !conn->hdev->ssp_mode))
 				(!conn->ssp_mode || !conn->hdev->ssp_mode))
 		return 1;
 		return 1;
 
 
-	if (conn->link_mode & HCI_LM_ENCRYPT)
-		return hci_conn_auth(conn, sec_level, auth_type);
-
+	/* For other security levels we need the link key. */
+	if (!(conn->link_mode & HCI_LM_AUTH))
+		goto auth;
+
+	/* An authenticated combination key has sufficient security for any
+	   security level. */
+	if (conn->key_type == HCI_LK_AUTH_COMBINATION)
+		goto encrypt;
+
+	/* An unauthenticated combination key has sufficient security for
+	   security level 1 and 2. */
+	if (conn->key_type == HCI_LK_UNAUTH_COMBINATION &&
+			(sec_level == BT_SECURITY_MEDIUM ||
+			sec_level == BT_SECURITY_LOW))
+		goto encrypt;
+
+	/* A combination key has always sufficient security for the security
+	   levels 1 or 2. High security level requires the combination key
+	   is generated using maximum PIN code length (16).
+	   For pre 2.1 units. */
+	if (conn->key_type == HCI_LK_COMBINATION &&
+			(sec_level != BT_SECURITY_HIGH ||
+			conn->pin_length == 16))
+		goto encrypt;
+
+auth:
 	if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend))
 	if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend))
 		return 0;
 		return 0;
 
 
-	if (hci_conn_auth(conn, sec_level, auth_type)) {
-		struct hci_cp_set_conn_encrypt cp;
-		cp.handle  = cpu_to_le16(conn->handle);
-		cp.encrypt = 1;
-		hci_send_cmd(conn->hdev, HCI_OP_SET_CONN_ENCRYPT,
-							sizeof(cp), &cp);
-	}
+	hci_conn_auth(conn, sec_level, auth_type);
+	return 0;
+
+encrypt:
+	if (conn->link_mode & HCI_LM_ENCRYPT)
+		return 1;
 
 
+	hci_conn_encrypt(conn);
 	return 0;
 	return 0;
 }
 }
 EXPORT_SYMBOL(hci_conn_security);
 EXPORT_SYMBOL(hci_conn_security);

+ 66 - 9
net/bluetooth/hci_core.c

@@ -1020,18 +1020,54 @@ struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr)
 	return NULL;
 	return NULL;
 }
 }
 
 
-int hci_add_link_key(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr,
-						u8 *val, u8 type, u8 pin_len)
+static int hci_persistent_key(struct hci_dev *hdev, struct hci_conn *conn,
+						u8 key_type, u8 old_key_type)
+{
+	/* Legacy key */
+	if (key_type < 0x03)
+		return 1;
+
+	/* Debug keys are insecure so don't store them persistently */
+	if (key_type == HCI_LK_DEBUG_COMBINATION)
+		return 0;
+
+	/* Changed combination key and there's no previous one */
+	if (key_type == HCI_LK_CHANGED_COMBINATION && old_key_type == 0xff)
+		return 0;
+
+	/* Security mode 3 case */
+	if (!conn)
+		return 1;
+
+	/* Neither local nor remote side had no-bonding as requirement */
+	if (conn->auth_type > 0x01 && conn->remote_auth > 0x01)
+		return 1;
+
+	/* Local side had dedicated bonding as requirement */
+	if (conn->auth_type == 0x02 || conn->auth_type == 0x03)
+		return 1;
+
+	/* Remote side had dedicated bonding as requirement */
+	if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03)
+		return 1;
+
+	/* If none of the above criteria match, then don't store the key
+	 * persistently */
+	return 0;
+}
+
+int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key,
+				bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len)
 {
 {
 	struct link_key *key, *old_key;
 	struct link_key *key, *old_key;
-	u8 old_key_type;
+	u8 old_key_type, persistent;
 
 
 	old_key = hci_find_link_key(hdev, bdaddr);
 	old_key = hci_find_link_key(hdev, bdaddr);
 	if (old_key) {
 	if (old_key) {
 		old_key_type = old_key->type;
 		old_key_type = old_key->type;
 		key = old_key;
 		key = old_key;
 	} else {
 	} else {
-		old_key_type = 0xff;
+		old_key_type = conn ? conn->key_type : 0xff;
 		key = kzalloc(sizeof(*key), GFP_ATOMIC);
 		key = kzalloc(sizeof(*key), GFP_ATOMIC);
 		if (!key)
 		if (!key)
 			return -ENOMEM;
 			return -ENOMEM;
@@ -1040,16 +1076,37 @@ int hci_add_link_key(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr,
 
 
 	BT_DBG("%s key for %s type %u", hdev->name, batostr(bdaddr), type);
 	BT_DBG("%s key for %s type %u", hdev->name, batostr(bdaddr), type);
 
 
+	/* Some buggy controller combinations generate a changed
+	 * combination key for legacy pairing even when there's no
+	 * previous key */
+	if (type == HCI_LK_CHANGED_COMBINATION &&
+					(!conn || conn->remote_auth == 0xff) &&
+					old_key_type == 0xff) {
+		type = HCI_LK_COMBINATION;
+		if (conn)
+			conn->key_type = type;
+	}
+
 	bacpy(&key->bdaddr, bdaddr);
 	bacpy(&key->bdaddr, bdaddr);
 	memcpy(key->val, val, 16);
 	memcpy(key->val, val, 16);
-	key->type = type;
 	key->pin_len = pin_len;
 	key->pin_len = pin_len;
 
 
-	if (new_key)
-		mgmt_new_key(hdev->id, key, old_key_type);
-
-	if (type == 0x06)
+	if (type == HCI_LK_CHANGED_COMBINATION)
 		key->type = old_key_type;
 		key->type = old_key_type;
+	else
+		key->type = type;
+
+	if (!new_key)
+		return 0;
+
+	persistent = hci_persistent_key(hdev, conn, type, old_key_type);
+
+	mgmt_new_key(hdev->id, key, persistent);
+
+	if (!persistent) {
+		list_del(&key->list);
+		kfree(key);
+	}
 
 
 	return 0;
 	return 0;
 }
 }

+ 141 - 22
net/bluetooth/hci_event.c

@@ -56,7 +56,9 @@ static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
 	if (status)
 	if (status)
 		return;
 		return;
 
 
-	clear_bit(HCI_INQUIRY, &hdev->flags);
+	if (test_bit(HCI_MGMT, &hdev->flags) &&
+				test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
+		mgmt_discovering(hdev->id, 0);
 
 
 	hci_req_complete(hdev, HCI_OP_INQUIRY_CANCEL, status);
 	hci_req_complete(hdev, HCI_OP_INQUIRY_CANCEL, status);
 
 
@@ -72,7 +74,9 @@ static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
 	if (status)
 	if (status)
 		return;
 		return;
 
 
-	clear_bit(HCI_INQUIRY, &hdev->flags);
+	if (test_bit(HCI_MGMT, &hdev->flags) &&
+				test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
+		mgmt_discovering(hdev->id, 0);
 
 
 	hci_conn_check_pending(hdev);
 	hci_conn_check_pending(hdev);
 }
 }
@@ -841,10 +845,14 @@ static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
 
 
 	if (status) {
 	if (status) {
 		hci_req_complete(hdev, HCI_OP_INQUIRY, status);
 		hci_req_complete(hdev, HCI_OP_INQUIRY, status);
-
 		hci_conn_check_pending(hdev);
 		hci_conn_check_pending(hdev);
-	} else
-		set_bit(HCI_INQUIRY, &hdev->flags);
+		return;
+	}
+
+	if (test_bit(HCI_MGMT, &hdev->flags) &&
+					!test_and_set_bit(HCI_INQUIRY,
+							&hdev->flags))
+		mgmt_discovering(hdev->id, 1);
 }
 }
 
 
 static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
 static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
@@ -1013,12 +1021,19 @@ static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
 	hci_dev_lock(hdev);
 	hci_dev_lock(hdev);
 
 
 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
-	if (conn && hci_outgoing_auth_needed(hdev, conn)) {
+	if (!conn)
+		goto unlock;
+
+	if (!hci_outgoing_auth_needed(hdev, conn))
+		goto unlock;
+
+	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
 		struct hci_cp_auth_requested cp;
 		struct hci_cp_auth_requested cp;
 		cp.handle = __cpu_to_le16(conn->handle);
 		cp.handle = __cpu_to_le16(conn->handle);
 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
 	}
 	}
 
 
+unlock:
 	hci_dev_unlock(hdev);
 	hci_dev_unlock(hdev);
 }
 }
 
 
@@ -1208,7 +1223,9 @@ static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff
 
 
 	BT_DBG("%s status %d", hdev->name, status);
 	BT_DBG("%s status %d", hdev->name, status);
 
 
-	clear_bit(HCI_INQUIRY, &hdev->flags);
+	if (test_bit(HCI_MGMT, &hdev->flags) &&
+				test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
+		mgmt_discovering(hdev->id, 0);
 
 
 	hci_req_complete(hdev, HCI_OP_INQUIRY, status);
 	hci_req_complete(hdev, HCI_OP_INQUIRY, status);
 
 
@@ -1228,6 +1245,12 @@ static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *
 
 
 	hci_dev_lock(hdev);
 	hci_dev_lock(hdev);
 
 
+	if (!test_and_set_bit(HCI_INQUIRY, &hdev->flags)) {
+
+		if (test_bit(HCI_MGMT, &hdev->flags))
+			mgmt_discovering(hdev->id, 1);
+	}
+
 	for (; num_rsp; num_rsp--, info++) {
 	for (; num_rsp; num_rsp--, info++) {
 		bacpy(&data.bdaddr, &info->bdaddr);
 		bacpy(&data.bdaddr, &info->bdaddr);
 		data.pscan_rep_mode	= info->pscan_rep_mode;
 		data.pscan_rep_mode	= info->pscan_rep_mode;
@@ -1443,7 +1466,6 @@ static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *s
 			conn->sec_level = conn->pending_sec_level;
 			conn->sec_level = conn->pending_sec_level;
 		} else {
 		} else {
 			mgmt_auth_failed(hdev->id, &conn->dst, ev->status);
 			mgmt_auth_failed(hdev->id, &conn->dst, ev->status);
-			conn->sec_level = BT_SECURITY_LOW;
 		}
 		}
 
 
 		clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
 		clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
@@ -1501,12 +1523,19 @@ static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb
 		mgmt_remote_name(hdev->id, &ev->bdaddr, ev->name);
 		mgmt_remote_name(hdev->id, &ev->bdaddr, ev->name);
 
 
 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
-	if (conn && hci_outgoing_auth_needed(hdev, conn)) {
+	if (!conn)
+		goto unlock;
+
+	if (!hci_outgoing_auth_needed(hdev, conn))
+		goto unlock;
+
+	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
 		struct hci_cp_auth_requested cp;
 		struct hci_cp_auth_requested cp;
 		cp.handle = __cpu_to_le16(conn->handle);
 		cp.handle = __cpu_to_le16(conn->handle);
 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
 	}
 	}
 
 
+unlock:
 	hci_dev_unlock(hdev);
 	hci_dev_unlock(hdev);
 }
 }
 
 
@@ -2006,9 +2035,16 @@ static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff
 	if (!test_bit(HCI_PAIRABLE, &hdev->flags))
 	if (!test_bit(HCI_PAIRABLE, &hdev->flags))
 		hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
 		hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
 					sizeof(ev->bdaddr), &ev->bdaddr);
 					sizeof(ev->bdaddr), &ev->bdaddr);
+	else if (test_bit(HCI_MGMT, &hdev->flags)) {
+		u8 secure;
 
 
-	if (test_bit(HCI_MGMT, &hdev->flags))
-		mgmt_pin_code_request(hdev->id, &ev->bdaddr);
+		if (conn->pending_sec_level == BT_SECURITY_HIGH)
+			secure = 1;
+		else
+			secure = 0;
+
+		mgmt_pin_code_request(hdev->id, &ev->bdaddr, secure);
+	}
 
 
 	hci_dev_unlock(hdev);
 	hci_dev_unlock(hdev);
 }
 }
@@ -2037,17 +2073,30 @@ static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff
 	BT_DBG("%s found key type %u for %s", hdev->name, key->type,
 	BT_DBG("%s found key type %u for %s", hdev->name, key->type,
 							batostr(&ev->bdaddr));
 							batostr(&ev->bdaddr));
 
 
-	if (!test_bit(HCI_DEBUG_KEYS, &hdev->flags) && key->type == 0x03) {
+	if (!test_bit(HCI_DEBUG_KEYS, &hdev->flags) &&
+				key->type == HCI_LK_DEBUG_COMBINATION) {
 		BT_DBG("%s ignoring debug key", hdev->name);
 		BT_DBG("%s ignoring debug key", hdev->name);
 		goto not_found;
 		goto not_found;
 	}
 	}
 
 
 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
+	if (conn) {
+		if (key->type == HCI_LK_UNAUTH_COMBINATION &&
+				conn->auth_type != 0xff &&
+				(conn->auth_type & 0x01)) {
+			BT_DBG("%s ignoring unauthenticated key", hdev->name);
+			goto not_found;
+		}
 
 
-	if (key->type == 0x04 && conn && conn->auth_type != 0xff &&
-						(conn->auth_type & 0x01)) {
-		BT_DBG("%s ignoring unauthenticated key", hdev->name);
-		goto not_found;
+		if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
+				conn->pending_sec_level == BT_SECURITY_HIGH) {
+			BT_DBG("%s ignoring key unauthenticated for high \
+							security", hdev->name);
+			goto not_found;
+		}
+
+		conn->key_type = key->type;
+		conn->pin_length = key->pin_len;
 	}
 	}
 
 
 	bacpy(&cp.bdaddr, &ev->bdaddr);
 	bacpy(&cp.bdaddr, &ev->bdaddr);
@@ -2079,11 +2128,15 @@ static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff
 		hci_conn_hold(conn);
 		hci_conn_hold(conn);
 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
 		pin_len = conn->pin_length;
 		pin_len = conn->pin_length;
+
+		if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
+			conn->key_type = ev->key_type;
+
 		hci_conn_put(conn);
 		hci_conn_put(conn);
 	}
 	}
 
 
 	if (test_bit(HCI_LINK_KEYS, &hdev->flags))
 	if (test_bit(HCI_LINK_KEYS, &hdev->flags))
-		hci_add_link_key(hdev, 1, &ev->bdaddr, ev->link_key,
+		hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
 							ev->key_type, pin_len);
 							ev->key_type, pin_len);
 
 
 	hci_dev_unlock(hdev);
 	hci_dev_unlock(hdev);
@@ -2158,6 +2211,12 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct
 
 
 	hci_dev_lock(hdev);
 	hci_dev_lock(hdev);
 
 
+	if (!test_and_set_bit(HCI_INQUIRY, &hdev->flags)) {
+
+		if (test_bit(HCI_MGMT, &hdev->flags))
+			mgmt_discovering(hdev->id, 1);
+	}
+
 	if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
 	if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
 		struct inquiry_info_with_rssi_and_pscan_mode *info;
 		struct inquiry_info_with_rssi_and_pscan_mode *info;
 		info = (void *) (skb->data + 1);
 		info = (void *) (skb->data + 1);
@@ -2320,6 +2379,12 @@ static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct
 	if (!num_rsp)
 	if (!num_rsp)
 		return;
 		return;
 
 
+	if (!test_and_set_bit(HCI_INQUIRY, &hdev->flags)) {
+
+		if (test_bit(HCI_MGMT, &hdev->flags))
+			mgmt_discovering(hdev->id, 1);
+	}
+
 	hci_dev_lock(hdev);
 	hci_dev_lock(hdev);
 
 
 	for (; num_rsp; num_rsp--, info++) {
 	for (; num_rsp; num_rsp--, info++) {
@@ -2353,7 +2418,7 @@ static inline u8 hci_get_auth_req(struct hci_conn *conn)
 
 
 	/* If remote requests no-bonding follow that lead */
 	/* If remote requests no-bonding follow that lead */
 	if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
 	if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
-		return 0x00;
+		return conn->remote_auth | (conn->auth_type & 0x01);
 
 
 	return conn->auth_type;
 	return conn->auth_type;
 }
 }
@@ -2382,7 +2447,8 @@ static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff
 
 
 		bacpy(&cp.bdaddr, &ev->bdaddr);
 		bacpy(&cp.bdaddr, &ev->bdaddr);
 		cp.capability = conn->io_capability;
 		cp.capability = conn->io_capability;
-		cp.authentication = hci_get_auth_req(conn);
+		conn->auth_type = hci_get_auth_req(conn);
+		cp.authentication = conn->auth_type;
 
 
 		if ((conn->out == 0x01 || conn->remote_oob == 0x01) &&
 		if ((conn->out == 0x01 || conn->remote_oob == 0x01) &&
 				hci_find_remote_oob_data(hdev, &conn->dst))
 				hci_find_remote_oob_data(hdev, &conn->dst))
@@ -2396,7 +2462,7 @@ static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff
 		struct hci_cp_io_capability_neg_reply cp;
 		struct hci_cp_io_capability_neg_reply cp;
 
 
 		bacpy(&cp.bdaddr, &ev->bdaddr);
 		bacpy(&cp.bdaddr, &ev->bdaddr);
-		cp.reason = 0x16; /* Pairing not allowed */
+		cp.reason = 0x18; /* Pairing not allowed */
 
 
 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
 							sizeof(cp), &cp);
 							sizeof(cp), &cp);
@@ -2431,14 +2497,67 @@ static inline void hci_user_confirm_request_evt(struct hci_dev *hdev,
 							struct sk_buff *skb)
 							struct sk_buff *skb)
 {
 {
 	struct hci_ev_user_confirm_req *ev = (void *) skb->data;
 	struct hci_ev_user_confirm_req *ev = (void *) skb->data;
+	int loc_mitm, rem_mitm, confirm_hint = 0;
+	struct hci_conn *conn;
 
 
 	BT_DBG("%s", hdev->name);
 	BT_DBG("%s", hdev->name);
 
 
 	hci_dev_lock(hdev);
 	hci_dev_lock(hdev);
 
 
-	if (test_bit(HCI_MGMT, &hdev->flags))
-		mgmt_user_confirm_request(hdev->id, &ev->bdaddr, ev->passkey);
+	if (!test_bit(HCI_MGMT, &hdev->flags))
+		goto unlock;
+
+	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
+	if (!conn)
+		goto unlock;
+
+	loc_mitm = (conn->auth_type & 0x01);
+	rem_mitm = (conn->remote_auth & 0x01);
+
+	/* If we require MITM but the remote device can't provide that
+	 * (it has NoInputNoOutput) then reject the confirmation
+	 * request. The only exception is when we're dedicated bonding
+	 * initiators (connect_cfm_cb set) since then we always have the MITM
+	 * bit set. */
+	if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
+		BT_DBG("Rejecting request: remote device can't provide MITM");
+		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
+					sizeof(ev->bdaddr), &ev->bdaddr);
+		goto unlock;
+	}
+
+	/* If no side requires MITM protection; auto-accept */
+	if ((!loc_mitm || conn->remote_cap == 0x03) &&
+				(!rem_mitm || conn->io_capability == 0x03)) {
 
 
+		/* If we're not the initiators request authorization to
+		 * proceed from user space (mgmt_user_confirm with
+		 * confirm_hint set to 1). */
+		if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
+			BT_DBG("Confirming auto-accept as acceptor");
+			confirm_hint = 1;
+			goto confirm;
+		}
+
+		BT_DBG("Auto-accept of user confirmation with %ums delay",
+						hdev->auto_accept_delay);
+
+		if (hdev->auto_accept_delay > 0) {
+			int delay = msecs_to_jiffies(hdev->auto_accept_delay);
+			mod_timer(&conn->auto_accept_timer, jiffies + delay);
+			goto unlock;
+		}
+
+		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
+						sizeof(ev->bdaddr), &ev->bdaddr);
+		goto unlock;
+	}
+
+confirm:
+	mgmt_user_confirm_request(hdev->id, &ev->bdaddr, ev->passkey,
+								confirm_hint);
+
+unlock:
 	hci_dev_unlock(hdev);
 	hci_dev_unlock(hdev);
 }
 }
 
 

+ 31 - 0
net/bluetooth/hci_sysfs.c

@@ -511,6 +511,35 @@ static const struct file_operations uuids_fops = {
 	.release	= single_release,
 	.release	= single_release,
 };
 };
 
 
+static int auto_accept_delay_set(void *data, u64 val)
+{
+	struct hci_dev *hdev = data;
+
+	hci_dev_lock_bh(hdev);
+
+	hdev->auto_accept_delay = val;
+
+	hci_dev_unlock_bh(hdev);
+
+	return 0;
+}
+
+static int auto_accept_delay_get(void *data, u64 *val)
+{
+	struct hci_dev *hdev = data;
+
+	hci_dev_lock_bh(hdev);
+
+	*val = hdev->auto_accept_delay;
+
+	hci_dev_unlock_bh(hdev);
+
+	return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(auto_accept_delay_fops, auto_accept_delay_get,
+					auto_accept_delay_set, "%llu\n");
+
 int hci_register_sysfs(struct hci_dev *hdev)
 int hci_register_sysfs(struct hci_dev *hdev)
 {
 {
 	struct device *dev = &hdev->dev;
 	struct device *dev = &hdev->dev;
@@ -545,6 +574,8 @@ int hci_register_sysfs(struct hci_dev *hdev)
 
 
 	debugfs_create_file("uuids", 0444, hdev->debugfs, hdev, &uuids_fops);
 	debugfs_create_file("uuids", 0444, hdev->debugfs, hdev, &uuids_fops);
 
 
+	debugfs_create_file("auto_accept_delay", 0444, hdev->debugfs, hdev,
+						&auto_accept_delay_fops);
 	return 0;
 	return 0;
 }
 }
 
 

+ 4 - 2
net/bluetooth/hidp/core.c

@@ -979,8 +979,10 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
 
 
 	bacpy(&session->bdaddr, &bt_sk(ctrl_sock->sk)->dst);
 	bacpy(&session->bdaddr, &bt_sk(ctrl_sock->sk)->dst);
 
 
-	session->ctrl_mtu = min_t(uint, l2cap_pi(ctrl_sock->sk)->omtu, l2cap_pi(ctrl_sock->sk)->imtu);
-	session->intr_mtu = min_t(uint, l2cap_pi(intr_sock->sk)->omtu, l2cap_pi(intr_sock->sk)->imtu);
+	session->ctrl_mtu = min_t(uint, l2cap_pi(ctrl_sock->sk)->chan->omtu,
+					l2cap_pi(ctrl_sock->sk)->chan->imtu);
+	session->intr_mtu = min_t(uint, l2cap_pi(intr_sock->sk)->chan->omtu,
+					l2cap_pi(intr_sock->sk)->chan->imtu);
 
 
 	BT_DBG("ctrl mtu %d intr mtu %d", session->ctrl_mtu, session->intr_mtu);
 	BT_DBG("ctrl mtu %d intr mtu %d", session->ctrl_mtu, session->intr_mtu);
 
 

文件差異過大導致無法顯示
+ 171 - 180
net/bluetooth/l2cap_core.c


+ 137 - 105
net/bluetooth/l2cap_sock.c

@@ -30,6 +30,8 @@
 #include <net/bluetooth/hci_core.h>
 #include <net/bluetooth/hci_core.h>
 #include <net/bluetooth/l2cap.h>
 #include <net/bluetooth/l2cap.h>
 
 
+static const struct proto_ops l2cap_sock_ops;
+
 /* ---- L2CAP timers ---- */
 /* ---- L2CAP timers ---- */
 static void l2cap_sock_timeout(unsigned long arg)
 static void l2cap_sock_timeout(unsigned long arg)
 {
 {
@@ -51,7 +53,7 @@ static void l2cap_sock_timeout(unsigned long arg)
 	if (sk->sk_state == BT_CONNECTED || sk->sk_state == BT_CONFIG)
 	if (sk->sk_state == BT_CONNECTED || sk->sk_state == BT_CONFIG)
 		reason = ECONNREFUSED;
 		reason = ECONNREFUSED;
 	else if (sk->sk_state == BT_CONNECT &&
 	else if (sk->sk_state == BT_CONNECT &&
-				l2cap_pi(sk)->sec_level != BT_SECURITY_SDP)
+			l2cap_pi(sk)->chan->sec_level != BT_SECURITY_SDP)
 		reason = ECONNREFUSED;
 		reason = ECONNREFUSED;
 	else
 	else
 		reason = ETIMEDOUT;
 		reason = ETIMEDOUT;
@@ -80,9 +82,13 @@ static struct sock *__l2cap_get_sock_by_addr(__le16 psm, bdaddr_t *src)
 {
 {
 	struct sock *sk;
 	struct sock *sk;
 	struct hlist_node *node;
 	struct hlist_node *node;
-	sk_for_each(sk, node, &l2cap_sk_list.head)
-		if (l2cap_pi(sk)->sport == psm && !bacmp(&bt_sk(sk)->src, src))
+	sk_for_each(sk, node, &l2cap_sk_list.head) {
+		struct l2cap_chan *chan = l2cap_pi(sk)->chan;
+
+		if (chan->sport == psm && !bacmp(&bt_sk(sk)->src, src))
 			goto found;
 			goto found;
+	}
+
 	sk = NULL;
 	sk = NULL;
 found:
 found:
 	return sk;
 	return sk;
@@ -91,6 +97,7 @@ found:
 static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
 static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
 {
 {
 	struct sock *sk = sock->sk;
 	struct sock *sk = sock->sk;
+	struct l2cap_chan *chan = l2cap_pi(sk)->chan;
 	struct sockaddr_l2 la;
 	struct sockaddr_l2 la;
 	int len, err = 0;
 	int len, err = 0;
 
 
@@ -136,17 +143,17 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
 	} else {
 	} else {
 		/* Save source address */
 		/* Save source address */
 		bacpy(&bt_sk(sk)->src, &la.l2_bdaddr);
 		bacpy(&bt_sk(sk)->src, &la.l2_bdaddr);
-		l2cap_pi(sk)->psm   = la.l2_psm;
-		l2cap_pi(sk)->sport = la.l2_psm;
+		chan->psm   = la.l2_psm;
+		chan->sport = la.l2_psm;
 		sk->sk_state = BT_BOUND;
 		sk->sk_state = BT_BOUND;
 
 
 		if (__le16_to_cpu(la.l2_psm) == 0x0001 ||
 		if (__le16_to_cpu(la.l2_psm) == 0x0001 ||
 					__le16_to_cpu(la.l2_psm) == 0x0003)
 					__le16_to_cpu(la.l2_psm) == 0x0003)
-			l2cap_pi(sk)->sec_level = BT_SECURITY_SDP;
+			chan->sec_level = BT_SECURITY_SDP;
 	}
 	}
 
 
 	if (la.l2_cid)
 	if (la.l2_cid)
-		l2cap_pi(sk)->scid = la.l2_cid;
+		chan->scid = la.l2_cid;
 
 
 	write_unlock_bh(&l2cap_sk_list.lock);
 	write_unlock_bh(&l2cap_sk_list.lock);
 
 
@@ -158,6 +165,7 @@ done:
 static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int alen, int flags)
 static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int alen, int flags)
 {
 {
 	struct sock *sk = sock->sk;
 	struct sock *sk = sock->sk;
+	struct l2cap_chan *chan = l2cap_pi(sk)->chan;
 	struct sockaddr_l2 la;
 	struct sockaddr_l2 la;
 	int len, err = 0;
 	int len, err = 0;
 
 
@@ -182,7 +190,7 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al
 		goto done;
 		goto done;
 	}
 	}
 
 
-	switch (l2cap_pi(sk)->mode) {
+	switch (chan->mode) {
 	case L2CAP_MODE_BASIC:
 	case L2CAP_MODE_BASIC:
 		break;
 		break;
 	case L2CAP_MODE_ERTM:
 	case L2CAP_MODE_ERTM:
@@ -226,10 +234,10 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al
 
 
 	/* Set destination address and psm */
 	/* Set destination address and psm */
 	bacpy(&bt_sk(sk)->dst, &la.l2_bdaddr);
 	bacpy(&bt_sk(sk)->dst, &la.l2_bdaddr);
-	l2cap_pi(sk)->psm = la.l2_psm;
-	l2cap_pi(sk)->dcid = la.l2_cid;
+	chan->psm = la.l2_psm;
+	chan->dcid = la.l2_cid;
 
 
-	err = l2cap_do_connect(sk);
+	err = l2cap_chan_connect(l2cap_pi(sk)->chan);
 	if (err)
 	if (err)
 		goto done;
 		goto done;
 
 
@@ -244,6 +252,7 @@ done:
 static int l2cap_sock_listen(struct socket *sock, int backlog)
 static int l2cap_sock_listen(struct socket *sock, int backlog)
 {
 {
 	struct sock *sk = sock->sk;
 	struct sock *sk = sock->sk;
+	struct l2cap_chan *chan = l2cap_pi(sk)->chan;
 	int err = 0;
 	int err = 0;
 
 
 	BT_DBG("sk %p backlog %d", sk, backlog);
 	BT_DBG("sk %p backlog %d", sk, backlog);
@@ -256,7 +265,7 @@ static int l2cap_sock_listen(struct socket *sock, int backlog)
 		goto done;
 		goto done;
 	}
 	}
 
 
-	switch (l2cap_pi(sk)->mode) {
+	switch (chan->mode) {
 	case L2CAP_MODE_BASIC:
 	case L2CAP_MODE_BASIC:
 		break;
 		break;
 	case L2CAP_MODE_ERTM:
 	case L2CAP_MODE_ERTM:
@@ -269,7 +278,7 @@ static int l2cap_sock_listen(struct socket *sock, int backlog)
 		goto done;
 		goto done;
 	}
 	}
 
 
-	if (!l2cap_pi(sk)->psm && !l2cap_pi(sk)->scid) {
+	if (!chan->psm && !chan->scid) {
 		bdaddr_t *src = &bt_sk(sk)->src;
 		bdaddr_t *src = &bt_sk(sk)->src;
 		u16 psm;
 		u16 psm;
 
 
@@ -279,8 +288,8 @@ static int l2cap_sock_listen(struct socket *sock, int backlog)
 
 
 		for (psm = 0x1001; psm < 0x1100; psm += 2)
 		for (psm = 0x1001; psm < 0x1100; psm += 2)
 			if (!__l2cap_get_sock_by_addr(cpu_to_le16(psm), src)) {
 			if (!__l2cap_get_sock_by_addr(cpu_to_le16(psm), src)) {
-				l2cap_pi(sk)->psm   = cpu_to_le16(psm);
-				l2cap_pi(sk)->sport = cpu_to_le16(psm);
+				chan->psm   = cpu_to_le16(psm);
+				chan->sport = cpu_to_le16(psm);
 				err = 0;
 				err = 0;
 				break;
 				break;
 			}
 			}
@@ -360,6 +369,7 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *l
 {
 {
 	struct sockaddr_l2 *la = (struct sockaddr_l2 *) addr;
 	struct sockaddr_l2 *la = (struct sockaddr_l2 *) addr;
 	struct sock *sk = sock->sk;
 	struct sock *sk = sock->sk;
+	struct l2cap_chan *chan = l2cap_pi(sk)->chan;
 
 
 	BT_DBG("sock %p, sk %p", sock, sk);
 	BT_DBG("sock %p, sk %p", sock, sk);
 
 
@@ -367,13 +377,13 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *l
 	*len = sizeof(struct sockaddr_l2);
 	*len = sizeof(struct sockaddr_l2);
 
 
 	if (peer) {
 	if (peer) {
-		la->l2_psm = l2cap_pi(sk)->psm;
+		la->l2_psm = chan->psm;
 		bacpy(&la->l2_bdaddr, &bt_sk(sk)->dst);
 		bacpy(&la->l2_bdaddr, &bt_sk(sk)->dst);
-		la->l2_cid = cpu_to_le16(l2cap_pi(sk)->dcid);
+		la->l2_cid = cpu_to_le16(chan->dcid);
 	} else {
 	} else {
-		la->l2_psm = l2cap_pi(sk)->sport;
+		la->l2_psm = chan->sport;
 		bacpy(&la->l2_bdaddr, &bt_sk(sk)->src);
 		bacpy(&la->l2_bdaddr, &bt_sk(sk)->src);
-		la->l2_cid = cpu_to_le16(l2cap_pi(sk)->scid);
+		la->l2_cid = cpu_to_le16(chan->scid);
 	}
 	}
 
 
 	return 0;
 	return 0;
@@ -382,6 +392,7 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *l
 static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __user *optval, int __user *optlen)
 static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __user *optval, int __user *optlen)
 {
 {
 	struct sock *sk = sock->sk;
 	struct sock *sk = sock->sk;
+	struct l2cap_chan *chan = l2cap_pi(sk)->chan;
 	struct l2cap_options opts;
 	struct l2cap_options opts;
 	struct l2cap_conninfo cinfo;
 	struct l2cap_conninfo cinfo;
 	int len, err = 0;
 	int len, err = 0;
@@ -397,13 +408,13 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us
 	switch (optname) {
 	switch (optname) {
 	case L2CAP_OPTIONS:
 	case L2CAP_OPTIONS:
 		memset(&opts, 0, sizeof(opts));
 		memset(&opts, 0, sizeof(opts));
-		opts.imtu     = l2cap_pi(sk)->imtu;
-		opts.omtu     = l2cap_pi(sk)->omtu;
-		opts.flush_to = l2cap_pi(sk)->flush_to;
-		opts.mode     = l2cap_pi(sk)->mode;
-		opts.fcs      = l2cap_pi(sk)->fcs;
-		opts.max_tx   = l2cap_pi(sk)->max_tx;
-		opts.txwin_size = (__u16)l2cap_pi(sk)->tx_win;
+		opts.imtu     = chan->imtu;
+		opts.omtu     = chan->omtu;
+		opts.flush_to = chan->flush_to;
+		opts.mode     = chan->mode;
+		opts.fcs      = chan->fcs;
+		opts.max_tx   = chan->max_tx;
+		opts.txwin_size = (__u16)chan->tx_win;
 
 
 		len = min_t(unsigned int, len, sizeof(opts));
 		len = min_t(unsigned int, len, sizeof(opts));
 		if (copy_to_user(optval, (char *) &opts, len))
 		if (copy_to_user(optval, (char *) &opts, len))
@@ -412,7 +423,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us
 		break;
 		break;
 
 
 	case L2CAP_LM:
 	case L2CAP_LM:
-		switch (l2cap_pi(sk)->sec_level) {
+		switch (chan->sec_level) {
 		case BT_SECURITY_LOW:
 		case BT_SECURITY_LOW:
 			opt = L2CAP_LM_AUTH;
 			opt = L2CAP_LM_AUTH;
 			break;
 			break;
@@ -428,10 +439,10 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us
 			break;
 			break;
 		}
 		}
 
 
-		if (l2cap_pi(sk)->role_switch)
+		if (chan->role_switch)
 			opt |= L2CAP_LM_MASTER;
 			opt |= L2CAP_LM_MASTER;
 
 
-		if (l2cap_pi(sk)->force_reliable)
+		if (chan->force_reliable)
 			opt |= L2CAP_LM_RELIABLE;
 			opt |= L2CAP_LM_RELIABLE;
 
 
 		if (put_user(opt, (u32 __user *) optval))
 		if (put_user(opt, (u32 __user *) optval))
@@ -446,8 +457,8 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us
 			break;
 			break;
 		}
 		}
 
 
-		cinfo.hci_handle = l2cap_pi(sk)->conn->hcon->handle;
-		memcpy(cinfo.dev_class, l2cap_pi(sk)->conn->hcon->dev_class, 3);
+		cinfo.hci_handle = chan->conn->hcon->handle;
+		memcpy(cinfo.dev_class, chan->conn->hcon->dev_class, 3);
 
 
 		len = min_t(unsigned int, len, sizeof(cinfo));
 		len = min_t(unsigned int, len, sizeof(cinfo));
 		if (copy_to_user(optval, (char *) &cinfo, len))
 		if (copy_to_user(optval, (char *) &cinfo, len))
@@ -467,6 +478,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us
 static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen)
 static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen)
 {
 {
 	struct sock *sk = sock->sk;
 	struct sock *sk = sock->sk;
+	struct l2cap_chan *chan = l2cap_pi(sk)->chan;
 	struct bt_security sec;
 	struct bt_security sec;
 	int len, err = 0;
 	int len, err = 0;
 
 
@@ -491,7 +503,7 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch
 			break;
 			break;
 		}
 		}
 
 
-		sec.level = l2cap_pi(sk)->sec_level;
+		sec.level = chan->sec_level;
 
 
 		len = min_t(unsigned int, len, sizeof(sec));
 		len = min_t(unsigned int, len, sizeof(sec));
 		if (copy_to_user(optval, (char *) &sec, len))
 		if (copy_to_user(optval, (char *) &sec, len))
@@ -511,7 +523,7 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch
 		break;
 		break;
 
 
 	case BT_FLUSHABLE:
 	case BT_FLUSHABLE:
-		if (put_user(l2cap_pi(sk)->flushable, (u32 __user *) optval))
+		if (put_user(chan->flushable, (u32 __user *) optval))
 			err = -EFAULT;
 			err = -EFAULT;
 
 
 		break;
 		break;
@@ -528,6 +540,7 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch
 static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __user *optval, unsigned int optlen)
 static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __user *optval, unsigned int optlen)
 {
 {
 	struct sock *sk = sock->sk;
 	struct sock *sk = sock->sk;
+	struct l2cap_chan *chan = l2cap_pi(sk)->chan;
 	struct l2cap_options opts;
 	struct l2cap_options opts;
 	int len, err = 0;
 	int len, err = 0;
 	u32 opt;
 	u32 opt;
@@ -543,13 +556,13 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us
 			break;
 			break;
 		}
 		}
 
 
-		opts.imtu     = l2cap_pi(sk)->imtu;
-		opts.omtu     = l2cap_pi(sk)->omtu;
-		opts.flush_to = l2cap_pi(sk)->flush_to;
-		opts.mode     = l2cap_pi(sk)->mode;
-		opts.fcs      = l2cap_pi(sk)->fcs;
-		opts.max_tx   = l2cap_pi(sk)->max_tx;
-		opts.txwin_size = (__u16)l2cap_pi(sk)->tx_win;
+		opts.imtu     = chan->imtu;
+		opts.omtu     = chan->omtu;
+		opts.flush_to = chan->flush_to;
+		opts.mode     = chan->mode;
+		opts.fcs      = chan->fcs;
+		opts.max_tx   = chan->max_tx;
+		opts.txwin_size = (__u16)chan->tx_win;
 
 
 		len = min_t(unsigned int, sizeof(opts), optlen);
 		len = min_t(unsigned int, sizeof(opts), optlen);
 		if (copy_from_user((char *) &opts, optval, len)) {
 		if (copy_from_user((char *) &opts, optval, len)) {
@@ -562,10 +575,10 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us
 			break;
 			break;
 		}
 		}
 
 
-		l2cap_pi(sk)->mode = opts.mode;
-		switch (l2cap_pi(sk)->mode) {
+		chan->mode = opts.mode;
+		switch (chan->mode) {
 		case L2CAP_MODE_BASIC:
 		case L2CAP_MODE_BASIC:
-			l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_STATE2_DEVICE;
+			chan->conf_state &= ~L2CAP_CONF_STATE2_DEVICE;
 			break;
 			break;
 		case L2CAP_MODE_ERTM:
 		case L2CAP_MODE_ERTM:
 		case L2CAP_MODE_STREAMING:
 		case L2CAP_MODE_STREAMING:
@@ -577,11 +590,11 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us
 			break;
 			break;
 		}
 		}
 
 
-		l2cap_pi(sk)->imtu = opts.imtu;
-		l2cap_pi(sk)->omtu = opts.omtu;
-		l2cap_pi(sk)->fcs  = opts.fcs;
-		l2cap_pi(sk)->max_tx = opts.max_tx;
-		l2cap_pi(sk)->tx_win = (__u8)opts.txwin_size;
+		chan->imtu = opts.imtu;
+		chan->omtu = opts.omtu;
+		chan->fcs  = opts.fcs;
+		chan->max_tx = opts.max_tx;
+		chan->tx_win = (__u8)opts.txwin_size;
 		break;
 		break;
 
 
 	case L2CAP_LM:
 	case L2CAP_LM:
@@ -591,14 +604,14 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us
 		}
 		}
 
 
 		if (opt & L2CAP_LM_AUTH)
 		if (opt & L2CAP_LM_AUTH)
-			l2cap_pi(sk)->sec_level = BT_SECURITY_LOW;
+			chan->sec_level = BT_SECURITY_LOW;
 		if (opt & L2CAP_LM_ENCRYPT)
 		if (opt & L2CAP_LM_ENCRYPT)
-			l2cap_pi(sk)->sec_level = BT_SECURITY_MEDIUM;
+			chan->sec_level = BT_SECURITY_MEDIUM;
 		if (opt & L2CAP_LM_SECURE)
 		if (opt & L2CAP_LM_SECURE)
-			l2cap_pi(sk)->sec_level = BT_SECURITY_HIGH;
+			chan->sec_level = BT_SECURITY_HIGH;
 
 
-		l2cap_pi(sk)->role_switch    = (opt & L2CAP_LM_MASTER);
-		l2cap_pi(sk)->force_reliable = (opt & L2CAP_LM_RELIABLE);
+		chan->role_switch    = (opt & L2CAP_LM_MASTER);
+		chan->force_reliable = (opt & L2CAP_LM_RELIABLE);
 		break;
 		break;
 
 
 	default:
 	default:
@@ -613,6 +626,7 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us
 static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen)
 static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen)
 {
 {
 	struct sock *sk = sock->sk;
 	struct sock *sk = sock->sk;
+	struct l2cap_chan *chan = l2cap_pi(sk)->chan;
 	struct bt_security sec;
 	struct bt_security sec;
 	int len, err = 0;
 	int len, err = 0;
 	u32 opt;
 	u32 opt;
@@ -649,7 +663,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
 			break;
 			break;
 		}
 		}
 
 
-		l2cap_pi(sk)->sec_level = sec.level;
+		chan->sec_level = sec.level;
 		break;
 		break;
 
 
 	case BT_DEFER_SETUP:
 	case BT_DEFER_SETUP:
@@ -678,7 +692,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
 		}
 		}
 
 
 		if (opt == BT_FLUSHABLE_OFF) {
 		if (opt == BT_FLUSHABLE_OFF) {
-			struct l2cap_conn *conn = l2cap_pi(sk)->conn;
+			struct l2cap_conn *conn = chan->conn;
 			/* proceed futher only when we have l2cap_conn and
 			/* proceed futher only when we have l2cap_conn and
 			   No Flush support in the LM */
 			   No Flush support in the LM */
 			if (!conn || !lmp_no_flush_capable(conn->hcon->hdev)) {
 			if (!conn || !lmp_no_flush_capable(conn->hcon->hdev)) {
@@ -687,7 +701,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
 			}
 			}
 		}
 		}
 
 
-		l2cap_pi(sk)->flushable = opt;
+		chan->flushable = opt;
 		break;
 		break;
 
 
 	default:
 	default:
@@ -702,7 +716,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
 static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len)
 static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len)
 {
 {
 	struct sock *sk = sock->sk;
 	struct sock *sk = sock->sk;
-	struct l2cap_pinfo *pi = l2cap_pi(sk);
+	struct l2cap_chan *chan = l2cap_pi(sk)->chan;
 	struct sk_buff *skb;
 	struct sk_buff *skb;
 	u16 control;
 	u16 control;
 	int err;
 	int err;
@@ -725,76 +739,77 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms
 
 
 	/* Connectionless channel */
 	/* Connectionless channel */
 	if (sk->sk_type == SOCK_DGRAM) {
 	if (sk->sk_type == SOCK_DGRAM) {
-		skb = l2cap_create_connless_pdu(sk, msg, len);
+		skb = l2cap_create_connless_pdu(chan, msg, len);
 		if (IS_ERR(skb)) {
 		if (IS_ERR(skb)) {
 			err = PTR_ERR(skb);
 			err = PTR_ERR(skb);
 		} else {
 		} else {
-			l2cap_do_send(sk, skb);
+			l2cap_do_send(chan, skb);
 			err = len;
 			err = len;
 		}
 		}
 		goto done;
 		goto done;
 	}
 	}
 
 
-	switch (pi->mode) {
+	switch (chan->mode) {
 	case L2CAP_MODE_BASIC:
 	case L2CAP_MODE_BASIC:
 		/* Check outgoing MTU */
 		/* Check outgoing MTU */
-		if (len > pi->omtu) {
+		if (len > chan->omtu) {
 			err = -EMSGSIZE;
 			err = -EMSGSIZE;
 			goto done;
 			goto done;
 		}
 		}
 
 
 		/* Create a basic PDU */
 		/* Create a basic PDU */
-		skb = l2cap_create_basic_pdu(sk, msg, len);
+		skb = l2cap_create_basic_pdu(chan, msg, len);
 		if (IS_ERR(skb)) {
 		if (IS_ERR(skb)) {
 			err = PTR_ERR(skb);
 			err = PTR_ERR(skb);
 			goto done;
 			goto done;
 		}
 		}
 
 
-		l2cap_do_send(sk, skb);
+		l2cap_do_send(chan, skb);
 		err = len;
 		err = len;
 		break;
 		break;
 
 
 	case L2CAP_MODE_ERTM:
 	case L2CAP_MODE_ERTM:
 	case L2CAP_MODE_STREAMING:
 	case L2CAP_MODE_STREAMING:
 		/* Entire SDU fits into one PDU */
 		/* Entire SDU fits into one PDU */
-		if (len <= pi->chan->remote_mps) {
+		if (len <= chan->remote_mps) {
 			control = L2CAP_SDU_UNSEGMENTED;
 			control = L2CAP_SDU_UNSEGMENTED;
-			skb = l2cap_create_iframe_pdu(sk, msg, len, control, 0);
+			skb = l2cap_create_iframe_pdu(chan, msg, len, control,
+									0);
 			if (IS_ERR(skb)) {
 			if (IS_ERR(skb)) {
 				err = PTR_ERR(skb);
 				err = PTR_ERR(skb);
 				goto done;
 				goto done;
 			}
 			}
-			__skb_queue_tail(&pi->chan->tx_q, skb);
+			__skb_queue_tail(&chan->tx_q, skb);
 
 
-			if (pi->chan->tx_send_head == NULL)
-				pi->chan->tx_send_head = skb;
+			if (chan->tx_send_head == NULL)
+				chan->tx_send_head = skb;
 
 
 		} else {
 		} else {
 		/* Segment SDU into multiples PDUs */
 		/* Segment SDU into multiples PDUs */
-			err = l2cap_sar_segment_sdu(pi->chan, msg, len);
+			err = l2cap_sar_segment_sdu(chan, msg, len);
 			if (err < 0)
 			if (err < 0)
 				goto done;
 				goto done;
 		}
 		}
 
 
-		if (pi->mode == L2CAP_MODE_STREAMING) {
-			l2cap_streaming_send(pi->chan);
+		if (chan->mode == L2CAP_MODE_STREAMING) {
+			l2cap_streaming_send(chan);
 			err = len;
 			err = len;
 			break;
 			break;
 		}
 		}
 
 
-		if ((pi->chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
-				(pi->chan->conn_state & L2CAP_CONN_WAIT_F)) {
+		if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
+				(chan->conn_state & L2CAP_CONN_WAIT_F)) {
 			err = len;
 			err = len;
 			break;
 			break;
 		}
 		}
-		err = l2cap_ertm_send(pi->chan);
+		err = l2cap_ertm_send(chan);
 
 
 		if (err >= 0)
 		if (err >= 0)
 			err = len;
 			err = len;
 		break;
 		break;
 
 
 	default:
 	default:
-		BT_DBG("bad state %1.1x", pi->mode);
+		BT_DBG("bad state %1.1x", chan->mode);
 		err = -EBADFD;
 		err = -EBADFD;
 	}
 	}
 
 
@@ -810,7 +825,9 @@ static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct ms
 	lock_sock(sk);
 	lock_sock(sk);
 
 
 	if (sk->sk_state == BT_CONNECT2 && bt_sk(sk)->defer_setup) {
 	if (sk->sk_state == BT_CONNECT2 && bt_sk(sk)->defer_setup) {
-		__l2cap_connect_rsp_defer(sk);
+		sk->sk_state = BT_CONFIG;
+
+		__l2cap_connect_rsp_defer(l2cap_pi(sk)->chan);
 		release_sock(sk);
 		release_sock(sk);
 		return 0;
 		return 0;
 	}
 	}
@@ -834,6 +851,8 @@ void l2cap_sock_kill(struct sock *sk)
 	BT_DBG("sk %p state %d", sk, sk->sk_state);
 	BT_DBG("sk %p state %d", sk, sk->sk_state);
 
 
 	/* Kill poor orphan */
 	/* Kill poor orphan */
+
+	l2cap_chan_free(l2cap_pi(sk)->chan);
 	bt_sock_unlink(&l2cap_sk_list, sk);
 	bt_sock_unlink(&l2cap_sk_list, sk);
 	sock_set_flag(sk, SOCK_DEAD);
 	sock_set_flag(sk, SOCK_DEAD);
 	sock_put(sk);
 	sock_put(sk);
@@ -865,8 +884,8 @@ static void l2cap_sock_cleanup_listen(struct sock *parent)
 
 
 void __l2cap_sock_close(struct sock *sk, int reason)
 void __l2cap_sock_close(struct sock *sk, int reason)
 {
 {
-	struct l2cap_conn *conn = l2cap_pi(sk)->conn;
 	struct l2cap_chan *chan = l2cap_pi(sk)->chan;
 	struct l2cap_chan *chan = l2cap_pi(sk)->chan;
+	struct l2cap_conn *conn = chan->conn;
 
 
 	BT_DBG("sk %p state %d socket %p", sk, sk->sk_state, sk->sk_socket);
 	BT_DBG("sk %p state %d socket %p", sk, sk->sk_state, sk->sk_socket);
 
 
@@ -898,8 +917,8 @@ void __l2cap_sock_close(struct sock *sk, int reason)
 			else
 			else
 				result = L2CAP_CR_BAD_PSM;
 				result = L2CAP_CR_BAD_PSM;
 
 
-			rsp.scid   = cpu_to_le16(l2cap_pi(sk)->dcid);
-			rsp.dcid   = cpu_to_le16(l2cap_pi(sk)->scid);
+			rsp.scid   = cpu_to_le16(chan->dcid);
+			rsp.dcid   = cpu_to_le16(chan->scid);
 			rsp.result = cpu_to_le16(result);
 			rsp.result = cpu_to_le16(result);
 			rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
 			rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
 			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
 			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
@@ -923,6 +942,7 @@ void __l2cap_sock_close(struct sock *sk, int reason)
 static int l2cap_sock_shutdown(struct socket *sock, int how)
 static int l2cap_sock_shutdown(struct socket *sock, int how)
 {
 {
 	struct sock *sk = sock->sk;
 	struct sock *sk = sock->sk;
+	struct l2cap_chan *chan = l2cap_pi(sk)->chan;
 	int err = 0;
 	int err = 0;
 
 
 	BT_DBG("sock %p, sk %p", sock, sk);
 	BT_DBG("sock %p, sk %p", sock, sk);
@@ -932,7 +952,7 @@ static int l2cap_sock_shutdown(struct socket *sock, int how)
 
 
 	lock_sock(sk);
 	lock_sock(sk);
 	if (!sk->sk_shutdown) {
 	if (!sk->sk_shutdown) {
-		if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
+		if (chan->mode == L2CAP_MODE_ERTM)
 			err = __l2cap_wait_ack(sk);
 			err = __l2cap_wait_ack(sk);
 
 
 		sk->sk_shutdown = SHUTDOWN_MASK;
 		sk->sk_shutdown = SHUTDOWN_MASK;
@@ -979,44 +999,47 @@ static void l2cap_sock_destruct(struct sock *sk)
 void l2cap_sock_init(struct sock *sk, struct sock *parent)
 void l2cap_sock_init(struct sock *sk, struct sock *parent)
 {
 {
 	struct l2cap_pinfo *pi = l2cap_pi(sk);
 	struct l2cap_pinfo *pi = l2cap_pi(sk);
+	struct l2cap_chan *chan = pi->chan;
 
 
 	BT_DBG("sk %p", sk);
 	BT_DBG("sk %p", sk);
 
 
 	if (parent) {
 	if (parent) {
+		struct l2cap_chan *pchan = l2cap_pi(parent)->chan;
+
 		sk->sk_type = parent->sk_type;
 		sk->sk_type = parent->sk_type;
 		bt_sk(sk)->defer_setup = bt_sk(parent)->defer_setup;
 		bt_sk(sk)->defer_setup = bt_sk(parent)->defer_setup;
 
 
-		pi->imtu = l2cap_pi(parent)->imtu;
-		pi->omtu = l2cap_pi(parent)->omtu;
-		pi->conf_state = l2cap_pi(parent)->conf_state;
-		pi->mode = l2cap_pi(parent)->mode;
-		pi->fcs  = l2cap_pi(parent)->fcs;
-		pi->max_tx = l2cap_pi(parent)->max_tx;
-		pi->tx_win = l2cap_pi(parent)->tx_win;
-		pi->sec_level = l2cap_pi(parent)->sec_level;
-		pi->role_switch = l2cap_pi(parent)->role_switch;
-		pi->force_reliable = l2cap_pi(parent)->force_reliable;
-		pi->flushable = l2cap_pi(parent)->flushable;
+		chan->imtu = pchan->imtu;
+		chan->omtu = pchan->omtu;
+		chan->conf_state = pchan->conf_state;
+		chan->mode = pchan->mode;
+		chan->fcs  = pchan->fcs;
+		chan->max_tx = pchan->max_tx;
+		chan->tx_win = pchan->tx_win;
+		chan->sec_level = pchan->sec_level;
+		chan->role_switch = pchan->role_switch;
+		chan->force_reliable = pchan->force_reliable;
+		chan->flushable = pchan->flushable;
 	} else {
 	} else {
-		pi->imtu = L2CAP_DEFAULT_MTU;
-		pi->omtu = 0;
+		chan->imtu = L2CAP_DEFAULT_MTU;
+		chan->omtu = 0;
 		if (!disable_ertm && sk->sk_type == SOCK_STREAM) {
 		if (!disable_ertm && sk->sk_type == SOCK_STREAM) {
-			pi->mode = L2CAP_MODE_ERTM;
-			pi->conf_state |= L2CAP_CONF_STATE2_DEVICE;
+			chan->mode = L2CAP_MODE_ERTM;
+			chan->conf_state |= L2CAP_CONF_STATE2_DEVICE;
 		} else {
 		} else {
-			pi->mode = L2CAP_MODE_BASIC;
+			chan->mode = L2CAP_MODE_BASIC;
 		}
 		}
-		pi->max_tx = L2CAP_DEFAULT_MAX_TX;
-		pi->fcs  = L2CAP_FCS_CRC16;
-		pi->tx_win = L2CAP_DEFAULT_TX_WINDOW;
-		pi->sec_level = BT_SECURITY_LOW;
-		pi->role_switch = 0;
-		pi->force_reliable = 0;
-		pi->flushable = BT_FLUSHABLE_OFF;
+		chan->max_tx = L2CAP_DEFAULT_MAX_TX;
+		chan->fcs  = L2CAP_FCS_CRC16;
+		chan->tx_win = L2CAP_DEFAULT_TX_WINDOW;
+		chan->sec_level = BT_SECURITY_LOW;
+		chan->role_switch = 0;
+		chan->force_reliable = 0;
+		chan->flushable = BT_FLUSHABLE_OFF;
 	}
 	}
 
 
 	/* Default config options */
 	/* Default config options */
-	pi->flush_to = L2CAP_DEFAULT_FLUSH_TO;
+	chan->flush_to = L2CAP_DEFAULT_FLUSH_TO;
 }
 }
 
 
 static struct proto l2cap_proto = {
 static struct proto l2cap_proto = {
@@ -1054,6 +1077,7 @@ static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol,
 			     int kern)
 			     int kern)
 {
 {
 	struct sock *sk;
 	struct sock *sk;
+	struct l2cap_chan *chan;
 
 
 	BT_DBG("sock %p", sock);
 	BT_DBG("sock %p", sock);
 
 
@@ -1072,11 +1096,19 @@ static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol,
 	if (!sk)
 	if (!sk)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
+	chan = l2cap_chan_alloc(sk);
+	if (!chan) {
+		l2cap_sock_kill(sk);
+		return -ENOMEM;
+	}
+
+	l2cap_pi(sk)->chan = chan;
+
 	l2cap_sock_init(sk, NULL);
 	l2cap_sock_init(sk, NULL);
 	return 0;
 	return 0;
 }
 }
 
 
-const struct proto_ops l2cap_sock_ops = {
+static const struct proto_ops l2cap_sock_ops = {
 	.family		= PF_BLUETOOTH,
 	.family		= PF_BLUETOOTH,
 	.owner		= THIS_MODULE,
 	.owner		= THIS_MODULE,
 	.release	= l2cap_sock_release,
 	.release	= l2cap_sock_release,

+ 89 - 6
net/bluetooth/mgmt.c

@@ -945,7 +945,7 @@ static int load_keys(struct sock *sk, u16 index, unsigned char *data, u16 len)
 	for (i = 0; i < key_count; i++) {
 	for (i = 0; i < key_count; i++) {
 		struct mgmt_key_info *key = &cp->keys[i];
 		struct mgmt_key_info *key = &cp->keys[i];
 
 
-		hci_add_link_key(hdev, 0, &key->bdaddr, key->val, key->type,
+		hci_add_link_key(hdev, NULL, 0, &key->bdaddr, key->val, key->type,
 								key->pin_len);
 								key->pin_len);
 	}
 	}
 
 
@@ -1569,6 +1569,75 @@ static int remove_remote_oob_data(struct sock *sk, u16 index,
 	return err;
 	return err;
 }
 }
 
 
+static int start_discovery(struct sock *sk, u16 index)
+{
+	u8 lap[3] = { 0x33, 0x8b, 0x9e };
+	struct hci_cp_inquiry cp;
+	struct pending_cmd *cmd;
+	struct hci_dev *hdev;
+	int err;
+
+	BT_DBG("hci%u", index);
+
+	hdev = hci_dev_get(index);
+	if (!hdev)
+		return cmd_status(sk, index, MGMT_OP_START_DISCOVERY, ENODEV);
+
+	hci_dev_lock_bh(hdev);
+
+	cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, index, NULL, 0);
+	if (!cmd) {
+		err = -ENOMEM;
+		goto failed;
+	}
+
+	memset(&cp, 0, sizeof(cp));
+	memcpy(&cp.lap, lap, 3);
+	cp.length  = 0x08;
+	cp.num_rsp = 0x00;
+
+	err = hci_send_cmd(hdev, HCI_OP_INQUIRY, sizeof(cp), &cp);
+	if (err < 0)
+		mgmt_pending_remove(cmd);
+
+failed:
+	hci_dev_unlock_bh(hdev);
+	hci_dev_put(hdev);
+
+	return err;
+}
+
+static int stop_discovery(struct sock *sk, u16 index)
+{
+	struct hci_dev *hdev;
+	struct pending_cmd *cmd;
+	int err;
+
+	BT_DBG("hci%u", index);
+
+	hdev = hci_dev_get(index);
+	if (!hdev)
+		return cmd_status(sk, index, MGMT_OP_STOP_DISCOVERY, ENODEV);
+
+	hci_dev_lock_bh(hdev);
+
+	cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, index, NULL, 0);
+	if (!cmd) {
+		err = -ENOMEM;
+		goto failed;
+	}
+
+	err = hci_send_cmd(hdev, HCI_OP_INQUIRY_CANCEL, 0, NULL);
+	if (err < 0)
+		mgmt_pending_remove(cmd);
+
+failed:
+	hci_dev_unlock_bh(hdev);
+	hci_dev_put(hdev);
+
+	return err;
+}
+
 int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
 int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
 {
 {
 	unsigned char *buf;
 	unsigned char *buf;
@@ -1677,7 +1746,12 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
 		err = remove_remote_oob_data(sk, index, buf + sizeof(*hdr),
 		err = remove_remote_oob_data(sk, index, buf + sizeof(*hdr),
 									len);
 									len);
 		break;
 		break;
-
+	case MGMT_OP_START_DISCOVERY:
+		err = start_discovery(sk, index);
+		break;
+	case MGMT_OP_STOP_DISCOVERY:
+		err = stop_discovery(sk, index);
+		break;
 	default:
 	default:
 		BT_DBG("Unknown op %u", opcode);
 		BT_DBG("Unknown op %u", opcode);
 		err = cmd_status(sk, index, opcode, 0x01);
 		err = cmd_status(sk, index, opcode, 0x01);
@@ -1784,17 +1858,17 @@ int mgmt_connectable(u16 index, u8 connectable)
 	return ret;
 	return ret;
 }
 }
 
 
-int mgmt_new_key(u16 index, struct link_key *key, u8 old_key_type)
+int mgmt_new_key(u16 index, struct link_key *key, u8 persistent)
 {
 {
 	struct mgmt_ev_new_key ev;
 	struct mgmt_ev_new_key ev;
 
 
 	memset(&ev, 0, sizeof(ev));
 	memset(&ev, 0, sizeof(ev));
 
 
+	ev.store_hint = persistent;
 	bacpy(&ev.key.bdaddr, &key->bdaddr);
 	bacpy(&ev.key.bdaddr, &key->bdaddr);
 	ev.key.type = key->type;
 	ev.key.type = key->type;
 	memcpy(ev.key.val, key->val, 16);
 	memcpy(ev.key.val, key->val, 16);
 	ev.key.pin_len = key->pin_len;
 	ev.key.pin_len = key->pin_len;
-	ev.old_key_type = old_key_type;
 
 
 	return mgmt_event(MGMT_EV_NEW_KEY, index, &ev, sizeof(ev), NULL);
 	return mgmt_event(MGMT_EV_NEW_KEY, index, &ev, sizeof(ev), NULL);
 }
 }
@@ -1868,11 +1942,12 @@ int mgmt_connect_failed(u16 index, bdaddr_t *bdaddr, u8 status)
 	return mgmt_event(MGMT_EV_CONNECT_FAILED, index, &ev, sizeof(ev), NULL);
 	return mgmt_event(MGMT_EV_CONNECT_FAILED, index, &ev, sizeof(ev), NULL);
 }
 }
 
 
-int mgmt_pin_code_request(u16 index, bdaddr_t *bdaddr)
+int mgmt_pin_code_request(u16 index, bdaddr_t *bdaddr, u8 secure)
 {
 {
 	struct mgmt_ev_pin_code_request ev;
 	struct mgmt_ev_pin_code_request ev;
 
 
 	bacpy(&ev.bdaddr, bdaddr);
 	bacpy(&ev.bdaddr, bdaddr);
+	ev.secure = secure;
 
 
 	return mgmt_event(MGMT_EV_PIN_CODE_REQUEST, index, &ev, sizeof(ev),
 	return mgmt_event(MGMT_EV_PIN_CODE_REQUEST, index, &ev, sizeof(ev),
 									NULL);
 									NULL);
@@ -1920,13 +1995,15 @@ int mgmt_pin_code_neg_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status)
 	return err;
 	return err;
 }
 }
 
 
-int mgmt_user_confirm_request(u16 index, bdaddr_t *bdaddr, __le32 value)
+int mgmt_user_confirm_request(u16 index, bdaddr_t *bdaddr, __le32 value,
+							u8 confirm_hint)
 {
 {
 	struct mgmt_ev_user_confirm_request ev;
 	struct mgmt_ev_user_confirm_request ev;
 
 
 	BT_DBG("hci%u", index);
 	BT_DBG("hci%u", index);
 
 
 	bacpy(&ev.bdaddr, bdaddr);
 	bacpy(&ev.bdaddr, bdaddr);
+	ev.confirm_hint = confirm_hint;
 	put_unaligned_le32(value, &ev.value);
 	put_unaligned_le32(value, &ev.value);
 
 
 	return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, index, &ev, sizeof(ev),
 	return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, index, &ev, sizeof(ev),
@@ -2075,3 +2152,9 @@ int mgmt_remote_name(u16 index, bdaddr_t *bdaddr, u8 *name)
 
 
 	return mgmt_event(MGMT_EV_REMOTE_NAME, index, &ev, sizeof(ev), NULL);
 	return mgmt_event(MGMT_EV_REMOTE_NAME, index, &ev, sizeof(ev), NULL);
 }
 }
+
+int mgmt_discovering(u16 index, u8 discovering)
+{
+	return mgmt_event(MGMT_EV_DISCOVERING, index, &discovering,
+						sizeof(discovering), NULL);
+}

+ 12 - 9
net/bluetooth/rfcomm/core.c

@@ -232,6 +232,8 @@ static int rfcomm_l2sock_create(struct socket **sock)
 static inline int rfcomm_check_security(struct rfcomm_dlc *d)
 static inline int rfcomm_check_security(struct rfcomm_dlc *d)
 {
 {
 	struct sock *sk = d->session->sock->sk;
 	struct sock *sk = d->session->sock->sk;
+	struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn;
+
 	__u8 auth_type;
 	__u8 auth_type;
 
 
 	switch (d->sec_level) {
 	switch (d->sec_level) {
@@ -246,8 +248,7 @@ static inline int rfcomm_check_security(struct rfcomm_dlc *d)
 		break;
 		break;
 	}
 	}
 
 
-	return hci_conn_security(l2cap_pi(sk)->conn->hcon, d->sec_level,
-								auth_type);
+	return hci_conn_security(conn->hcon, d->sec_level, auth_type);
 }
 }
 
 
 static void rfcomm_session_timeout(unsigned long arg)
 static void rfcomm_session_timeout(unsigned long arg)
@@ -710,10 +711,10 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src,
 	/* Set L2CAP options */
 	/* Set L2CAP options */
 	sk = sock->sk;
 	sk = sock->sk;
 	lock_sock(sk);
 	lock_sock(sk);
-	l2cap_pi(sk)->imtu = l2cap_mtu;
-	l2cap_pi(sk)->sec_level = sec_level;
+	l2cap_pi(sk)->chan->imtu = l2cap_mtu;
+	l2cap_pi(sk)->chan->sec_level = sec_level;
 	if (l2cap_ertm)
 	if (l2cap_ertm)
-		l2cap_pi(sk)->mode = L2CAP_MODE_ERTM;
+		l2cap_pi(sk)->chan->mode = L2CAP_MODE_ERTM;
 	release_sock(sk);
 	release_sock(sk);
 
 
 	s = rfcomm_session_add(sock, BT_BOUND);
 	s = rfcomm_session_add(sock, BT_BOUND);
@@ -1241,6 +1242,7 @@ static int rfcomm_recv_disc(struct rfcomm_session *s, u8 dlci)
 void rfcomm_dlc_accept(struct rfcomm_dlc *d)
 void rfcomm_dlc_accept(struct rfcomm_dlc *d)
 {
 {
 	struct sock *sk = d->session->sock->sk;
 	struct sock *sk = d->session->sock->sk;
+	struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn;
 
 
 	BT_DBG("dlc %p", d);
 	BT_DBG("dlc %p", d);
 
 
@@ -1254,7 +1256,7 @@ void rfcomm_dlc_accept(struct rfcomm_dlc *d)
 	rfcomm_dlc_unlock(d);
 	rfcomm_dlc_unlock(d);
 
 
 	if (d->role_switch)
 	if (d->role_switch)
-		hci_conn_switch_role(l2cap_pi(sk)->conn->hcon, 0x00);
+		hci_conn_switch_role(conn->hcon, 0x00);
 
 
 	rfcomm_send_msc(d->session, 1, d->dlci, d->v24_sig);
 	rfcomm_send_msc(d->session, 1, d->dlci, d->v24_sig);
 }
 }
@@ -1890,7 +1892,8 @@ static inline void rfcomm_accept_connection(struct rfcomm_session *s)
 
 
 		/* We should adjust MTU on incoming sessions.
 		/* We should adjust MTU on incoming sessions.
 		 * L2CAP MTU minus UIH header and FCS. */
 		 * L2CAP MTU minus UIH header and FCS. */
-		s->mtu = min(l2cap_pi(nsock->sk)->omtu, l2cap_pi(nsock->sk)->imtu) - 5;
+		s->mtu = min(l2cap_pi(nsock->sk)->chan->omtu,
+				l2cap_pi(nsock->sk)->chan->imtu) - 5;
 
 
 		rfcomm_schedule();
 		rfcomm_schedule();
 	} else
 	} else
@@ -1909,7 +1912,7 @@ static inline void rfcomm_check_connection(struct rfcomm_session *s)
 
 
 		/* We can adjust MTU on outgoing sessions.
 		/* We can adjust MTU on outgoing sessions.
 		 * L2CAP MTU minus UIH header and FCS. */
 		 * L2CAP MTU minus UIH header and FCS. */
-		s->mtu = min(l2cap_pi(sk)->omtu, l2cap_pi(sk)->imtu) - 5;
+		s->mtu = min(l2cap_pi(sk)->chan->omtu, l2cap_pi(sk)->chan->imtu) - 5;
 
 
 		rfcomm_send_sabm(s, 0);
 		rfcomm_send_sabm(s, 0);
 		break;
 		break;
@@ -1992,7 +1995,7 @@ static int rfcomm_add_listener(bdaddr_t *ba)
 	/* Set L2CAP options */
 	/* Set L2CAP options */
 	sk = sock->sk;
 	sk = sock->sk;
 	lock_sock(sk);
 	lock_sock(sk);
-	l2cap_pi(sk)->imtu = l2cap_mtu;
+	l2cap_pi(sk)->chan->imtu = l2cap_mtu;
 	release_sock(sk);
 	release_sock(sk);
 
 
 	/* Start listening on the socket */
 	/* Start listening on the socket */

+ 3 - 2
net/bluetooth/rfcomm/sock.c

@@ -743,6 +743,7 @@ static int rfcomm_sock_getsockopt_old(struct socket *sock, int optname, char __u
 	struct sock *sk = sock->sk;
 	struct sock *sk = sock->sk;
 	struct sock *l2cap_sk;
 	struct sock *l2cap_sk;
 	struct rfcomm_conninfo cinfo;
 	struct rfcomm_conninfo cinfo;
+	struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn;
 	int len, err = 0;
 	int len, err = 0;
 	u32 opt;
 	u32 opt;
 
 
@@ -787,8 +788,8 @@ static int rfcomm_sock_getsockopt_old(struct socket *sock, int optname, char __u
 
 
 		l2cap_sk = rfcomm_pi(sk)->dlc->session->sock->sk;
 		l2cap_sk = rfcomm_pi(sk)->dlc->session->sock->sk;
 
 
-		cinfo.hci_handle = l2cap_pi(l2cap_sk)->conn->hcon->handle;
-		memcpy(cinfo.dev_class, l2cap_pi(l2cap_sk)->conn->hcon->dev_class, 3);
+		cinfo.hci_handle = conn->hcon->handle;
+		memcpy(cinfo.dev_class, conn->hcon->dev_class, 3);
 
 
 		len = min_t(unsigned int, len, sizeof(cinfo));
 		len = min_t(unsigned int, len, sizeof(cinfo));
 		if (copy_to_user(optval, (char *) &cinfo, len))
 		if (copy_to_user(optval, (char *) &cinfo, len))

部分文件因文件數量過多而無法顯示