Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
Pull networking updates from David Miller: "Highlights: 1) Steady transitioning of the BPF instructure to a generic spot so all kernel subsystems can make use of it, from Alexei Starovoitov. 2) SFC driver supports busy polling, from Alexandre Rames. 3) Take advantage of hash table in UDP multicast delivery, from David Held. 4) Lighten locking, in particular by getting rid of the LRU lists, in inet frag handling. From Florian Westphal. 5) Add support for various RFC6458 control messages in SCTP, from Geir Ola Vaagland. 6) Allow to filter bridge forwarding database dumps by device, from Jamal Hadi Salim. 7) virtio-net also now supports busy polling, from Jason Wang. 8) Some low level optimization tweaks in pktgen from Jesper Dangaard Brouer. 9) Add support for ipv6 address generation modes, so that userland can have some input into the process. From Jiri Pirko. 10) Consolidate common TCP connection request code in ipv4 and ipv6, from Octavian Purdila. 11) New ARP packet logger in netfilter, from Pablo Neira Ayuso. 12) Generic resizable RCU hash table, with intial users in netlink and nftables. From Thomas Graf. 13) Maintain a name assignment type so that userspace can see where a network device name came from (enumerated by kernel, assigned explicitly by userspace, etc.) From Tom Gundersen. 14) Automatic flow label generation on transmit in ipv6, from Tom Herbert. 15) New packet timestamping facilities from Willem de Bruijn, meant to assist in measuring latencies going into/out-of the packet scheduler, latency from TCP data transmission to ACK, etc" * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (1536 commits) cxgb4 : Disable recursive mailbox commands when enabling vi net: reduce USB network driver config options. tg3: Modify tg3_tso_bug() to handle multiple TX rings amd-xgbe: Perform phy connect/disconnect at dev open/stop amd-xgbe: Use dma_set_mask_and_coherent to set DMA mask net: sun4i-emac: fix memory leak on bad packet sctp: fix possible seqlock seadlock in sctp_packet_transmit() Revert "net: phy: Set the driver when registering an MDIO bus device" cxgb4vf: Turn off SGE RX/TX Callback Timers and interrupts in PCI shutdown routine team: Simplify return path of team_newlink bridge: Update outdated comment on promiscuous mode net-timestamp: ACK timestamp for bytestreams net-timestamp: TCP timestamping net-timestamp: SCHED timestamp on entering packet scheduler net-timestamp: add key to disambiguate concurrent datagrams net-timestamp: move timestamp flags out of sk_flags net-timestamp: extend SCM_TIMESTAMPING ancillary data struct cxgb4i : Move stray CPL definitions to cxgb4 driver tcp: reduce spurious retransmits due to transient SACK reneging qlcnic: Initialize dcbnl_ops before register_netdev ...
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2013 Intel Corp.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2 and
|
||||
only version 2 as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __6LOWPAN_H
|
||||
#define __6LOWPAN_H
|
||||
|
||||
#include <linux/errno.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <net/bluetooth/l2cap.h>
|
||||
|
||||
#if IS_ENABLED(CONFIG_BT_6LOWPAN)
|
||||
int bt_6lowpan_recv(struct l2cap_conn *conn, struct sk_buff *skb);
|
||||
int bt_6lowpan_add_conn(struct l2cap_conn *conn);
|
||||
int bt_6lowpan_del_conn(struct l2cap_conn *conn);
|
||||
int bt_6lowpan_init(void);
|
||||
void bt_6lowpan_cleanup(void);
|
||||
#else
|
||||
static int bt_6lowpan_recv(struct l2cap_conn *conn, struct sk_buff *skb)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
static int bt_6lowpan_add_conn(struct l2cap_conn *conn)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
int bt_6lowpan_del_conn(struct l2cap_conn *conn)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
static int bt_6lowpan_init(void)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
static void bt_6lowpan_cleanup(void) { }
|
||||
#endif
|
||||
|
||||
#endif /* __6LOWPAN_H */
|
@@ -6,7 +6,6 @@ menuconfig BT
|
||||
tristate "Bluetooth subsystem support"
|
||||
depends on NET && !S390
|
||||
depends on RFKILL || !RFKILL
|
||||
select 6LOWPAN_IPHC if BT_6LOWPAN
|
||||
select CRC16
|
||||
select CRYPTO
|
||||
select CRYPTO_BLKCIPHER
|
||||
@@ -41,10 +40,10 @@ menuconfig BT
|
||||
more information, see <http://www.bluez.org/>.
|
||||
|
||||
config BT_6LOWPAN
|
||||
bool "Bluetooth 6LoWPAN support"
|
||||
depends on BT && IPV6
|
||||
tristate "Bluetooth 6LoWPAN support"
|
||||
depends on BT && 6LOWPAN
|
||||
help
|
||||
IPv6 compression over Bluetooth.
|
||||
IPv6 compression over Bluetooth Low Energy.
|
||||
|
||||
source "net/bluetooth/rfcomm/Kconfig"
|
||||
|
||||
|
@@ -7,10 +7,12 @@ obj-$(CONFIG_BT_RFCOMM) += rfcomm/
|
||||
obj-$(CONFIG_BT_BNEP) += bnep/
|
||||
obj-$(CONFIG_BT_CMTP) += cmtp/
|
||||
obj-$(CONFIG_BT_HIDP) += hidp/
|
||||
obj-$(CONFIG_BT_6LOWPAN) += bluetooth_6lowpan.o
|
||||
|
||||
bluetooth_6lowpan-y := 6lowpan.o
|
||||
|
||||
bluetooth-y := af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o \
|
||||
hci_sock.o hci_sysfs.o l2cap_core.o l2cap_sock.o smp.o sco.o lib.o \
|
||||
a2mp.o amp.o
|
||||
bluetooth-$(CONFIG_BT_6LOWPAN) += 6lowpan.o
|
||||
|
||||
subdir-ccflags-y += -D__CHECK_ENDIAN__
|
||||
|
@@ -63,7 +63,7 @@ void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len, void *data)
|
||||
msg.msg_iov = (struct iovec *) &iv;
|
||||
msg.msg_iovlen = 1;
|
||||
|
||||
l2cap_chan_send(chan, &msg, total_len, 0);
|
||||
l2cap_chan_send(chan, &msg, total_len);
|
||||
|
||||
kfree(cmd);
|
||||
}
|
||||
@@ -693,18 +693,19 @@ static void a2mp_chan_state_change_cb(struct l2cap_chan *chan, int state,
|
||||
}
|
||||
|
||||
static struct sk_buff *a2mp_chan_alloc_skb_cb(struct l2cap_chan *chan,
|
||||
unsigned long hdr_len,
|
||||
unsigned long len, int nb)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
|
||||
skb = bt_skb_alloc(len, GFP_KERNEL);
|
||||
skb = bt_skb_alloc(hdr_len + len, GFP_KERNEL);
|
||||
if (!skb)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
return skb;
|
||||
}
|
||||
|
||||
static struct l2cap_ops a2mp_chan_ops = {
|
||||
static const struct l2cap_ops a2mp_chan_ops = {
|
||||
.name = "L2CAP A2MP channel",
|
||||
.recv = a2mp_chan_recv_cb,
|
||||
.close = a2mp_chan_close_cb,
|
||||
@@ -719,6 +720,7 @@ static struct l2cap_ops a2mp_chan_ops = {
|
||||
.resume = l2cap_chan_no_resume,
|
||||
.set_shutdown = l2cap_chan_no_set_shutdown,
|
||||
.get_sndtimeo = l2cap_chan_no_get_sndtimeo,
|
||||
.memcpy_fromiovec = l2cap_chan_no_memcpy_fromiovec,
|
||||
};
|
||||
|
||||
static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn, bool locked)
|
||||
|
@@ -639,7 +639,7 @@ static int bt_seq_show(struct seq_file *seq, void *v)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct seq_operations bt_seq_ops = {
|
||||
static const struct seq_operations bt_seq_ops = {
|
||||
.start = bt_seq_start,
|
||||
.next = bt_seq_next,
|
||||
.stop = bt_seq_stop,
|
||||
|
@@ -113,8 +113,9 @@ struct hci_conn *phylink_add(struct hci_dev *hdev, struct amp_mgr *mgr,
|
||||
{
|
||||
bdaddr_t *dst = &mgr->l2cap_conn->hcon->dst;
|
||||
struct hci_conn *hcon;
|
||||
u8 role = out ? HCI_ROLE_MASTER : HCI_ROLE_SLAVE;
|
||||
|
||||
hcon = hci_conn_add(hdev, AMP_LINK, dst);
|
||||
hcon = hci_conn_add(hdev, AMP_LINK, dst, role);
|
||||
if (!hcon)
|
||||
return NULL;
|
||||
|
||||
@@ -125,7 +126,6 @@ struct hci_conn *phylink_add(struct hci_dev *hdev, struct amp_mgr *mgr,
|
||||
hcon->handle = __next_handle(mgr);
|
||||
hcon->remote_id = remote_id;
|
||||
hcon->amp_mgr = amp_mgr_get(mgr);
|
||||
hcon->out = out;
|
||||
|
||||
return hcon;
|
||||
}
|
||||
@@ -133,8 +133,8 @@ struct hci_conn *phylink_add(struct hci_dev *hdev, struct amp_mgr *mgr,
|
||||
/* AMP crypto key generation interface */
|
||||
static int hmac_sha256(u8 *key, u8 ksize, char *plaintext, u8 psize, u8 *output)
|
||||
{
|
||||
int ret = 0;
|
||||
struct crypto_shash *tfm;
|
||||
int ret;
|
||||
|
||||
if (!ksize)
|
||||
return -EINVAL;
|
||||
|
@@ -538,8 +538,9 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
|
||||
|
||||
/* session struct allocated as private part of net_device */
|
||||
dev = alloc_netdev(sizeof(struct bnep_session),
|
||||
(*req->device) ? req->device : "bnep%d",
|
||||
bnep_net_setup);
|
||||
(*req->device) ? req->device : "bnep%d",
|
||||
NET_NAME_UNKNOWN,
|
||||
bnep_net_setup);
|
||||
if (!dev)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@@ -362,12 +362,6 @@ void cmtp_recv_capimsg(struct cmtp_session *session, struct sk_buff *skb)
|
||||
CAPIMSG_SETCONTROL(skb->data, contr);
|
||||
}
|
||||
|
||||
if (!ctrl) {
|
||||
BT_ERR("Can't find controller %d for message", session->num);
|
||||
kfree_skb(skb);
|
||||
return;
|
||||
}
|
||||
|
||||
capi_ctr_handle_message(ctrl, appl, skb);
|
||||
}
|
||||
|
||||
|
@@ -66,8 +66,7 @@ static void hci_acl_create_connection(struct hci_conn *conn)
|
||||
|
||||
conn->state = BT_CONNECT;
|
||||
conn->out = true;
|
||||
|
||||
conn->link_mode = HCI_LM_MASTER;
|
||||
conn->role = HCI_ROLE_MASTER;
|
||||
|
||||
conn->attempt++;
|
||||
|
||||
@@ -136,7 +135,7 @@ void hci_disconnect(struct hci_conn *conn, __u8 reason)
|
||||
hci_send_cmd(conn->hdev, HCI_OP_DISCONNECT, sizeof(cp), &cp);
|
||||
}
|
||||
|
||||
static void hci_amp_disconn(struct hci_conn *conn, __u8 reason)
|
||||
static void hci_amp_disconn(struct hci_conn *conn)
|
||||
{
|
||||
struct hci_cp_disconn_phy_link cp;
|
||||
|
||||
@@ -145,7 +144,7 @@ static void hci_amp_disconn(struct hci_conn *conn, __u8 reason)
|
||||
conn->state = BT_DISCONN;
|
||||
|
||||
cp.phy_handle = HCI_PHY_HANDLE(conn->handle);
|
||||
cp.reason = reason;
|
||||
cp.reason = hci_proto_disconn_ind(conn);
|
||||
hci_send_cmd(conn->hdev, HCI_OP_DISCONN_PHY_LINK,
|
||||
sizeof(cp), &cp);
|
||||
}
|
||||
@@ -213,14 +212,26 @@ bool hci_setup_sync(struct hci_conn *conn, __u16 handle)
|
||||
return true;
|
||||
}
|
||||
|
||||
void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max,
|
||||
u16 latency, u16 to_multiplier)
|
||||
u8 hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, u16 latency,
|
||||
u16 to_multiplier)
|
||||
{
|
||||
struct hci_cp_le_conn_update cp;
|
||||
struct hci_dev *hdev = conn->hdev;
|
||||
struct hci_conn_params *params;
|
||||
struct hci_cp_le_conn_update cp;
|
||||
|
||||
hci_dev_lock(hdev);
|
||||
|
||||
params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type);
|
||||
if (params) {
|
||||
params->conn_min_interval = min;
|
||||
params->conn_max_interval = max;
|
||||
params->conn_latency = latency;
|
||||
params->supervision_timeout = to_multiplier;
|
||||
}
|
||||
|
||||
hci_dev_unlock(hdev);
|
||||
|
||||
memset(&cp, 0, sizeof(cp));
|
||||
|
||||
cp.handle = cpu_to_le16(conn->handle);
|
||||
cp.conn_interval_min = cpu_to_le16(min);
|
||||
cp.conn_interval_max = cpu_to_le16(max);
|
||||
@@ -230,6 +241,11 @@ void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max,
|
||||
cp.max_ce_len = cpu_to_le16(0x0000);
|
||||
|
||||
hci_send_cmd(hdev, HCI_OP_LE_CONN_UPDATE, sizeof(cp), &cp);
|
||||
|
||||
if (params)
|
||||
return 0x01;
|
||||
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __le64 rand,
|
||||
@@ -271,20 +287,6 @@ void hci_sco_setup(struct hci_conn *conn, __u8 status)
|
||||
}
|
||||
}
|
||||
|
||||
static void hci_conn_disconnect(struct hci_conn *conn)
|
||||
{
|
||||
__u8 reason = hci_proto_disconn_ind(conn);
|
||||
|
||||
switch (conn->type) {
|
||||
case AMP_LINK:
|
||||
hci_amp_disconn(conn, reason);
|
||||
break;
|
||||
default:
|
||||
hci_disconnect(conn, reason);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void hci_conn_timeout(struct work_struct *work)
|
||||
{
|
||||
struct hci_conn *conn = container_of(work, struct hci_conn,
|
||||
@@ -319,7 +321,31 @@ static void hci_conn_timeout(struct work_struct *work)
|
||||
break;
|
||||
case BT_CONFIG:
|
||||
case BT_CONNECTED:
|
||||
hci_conn_disconnect(conn);
|
||||
if (conn->type == AMP_LINK) {
|
||||
hci_amp_disconn(conn);
|
||||
} else {
|
||||
__u8 reason = hci_proto_disconn_ind(conn);
|
||||
|
||||
/* When we are master of an established connection
|
||||
* and it enters the disconnect timeout, then go
|
||||
* ahead and try to read the current clock offset.
|
||||
*
|
||||
* Processing of the result is done within the
|
||||
* event handling and hci_clock_offset_evt function.
|
||||
*/
|
||||
if (conn->type == ACL_LINK &&
|
||||
conn->role == HCI_ROLE_MASTER) {
|
||||
struct hci_dev *hdev = conn->hdev;
|
||||
struct hci_cp_read_clock_offset cp;
|
||||
|
||||
cp.handle = cpu_to_le16(conn->handle);
|
||||
|
||||
hci_send_cmd(hdev, HCI_OP_READ_CLOCK_OFFSET,
|
||||
sizeof(cp), &cp);
|
||||
}
|
||||
|
||||
hci_disconnect(conn, reason);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
conn->state = BT_CLOSED;
|
||||
@@ -336,9 +362,6 @@ static void hci_conn_idle(struct work_struct *work)
|
||||
|
||||
BT_DBG("hcon %p mode %d", conn, conn->mode);
|
||||
|
||||
if (test_bit(HCI_RAW, &hdev->flags))
|
||||
return;
|
||||
|
||||
if (!lmp_sniff_capable(hdev) || !lmp_sniff_capable(conn))
|
||||
return;
|
||||
|
||||
@@ -398,13 +421,14 @@ static void le_conn_timeout(struct work_struct *work)
|
||||
hci_le_create_connection_cancel(conn);
|
||||
}
|
||||
|
||||
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,
|
||||
u8 role)
|
||||
{
|
||||
struct hci_conn *conn;
|
||||
|
||||
BT_DBG("%s dst %pMR", hdev->name, dst);
|
||||
|
||||
conn = kzalloc(sizeof(struct hci_conn), GFP_KERNEL);
|
||||
conn = kzalloc(sizeof(*conn), GFP_KERNEL);
|
||||
if (!conn)
|
||||
return NULL;
|
||||
|
||||
@@ -412,6 +436,7 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
|
||||
bacpy(&conn->src, &hdev->bdaddr);
|
||||
conn->hdev = hdev;
|
||||
conn->type = type;
|
||||
conn->role = role;
|
||||
conn->mode = HCI_CM_ACTIVE;
|
||||
conn->state = BT_OPEN;
|
||||
conn->auth_type = HCI_AT_GENERAL_BONDING;
|
||||
@@ -424,6 +449,9 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
|
||||
set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
|
||||
conn->disc_timeout = HCI_DISCONN_TIMEOUT;
|
||||
|
||||
if (conn->role == HCI_ROLE_MASTER)
|
||||
conn->out = true;
|
||||
|
||||
switch (type) {
|
||||
case ACL_LINK:
|
||||
conn->pkt_type = hdev->pkt_type & ACL_PTYPE_MASK;
|
||||
@@ -529,7 +557,6 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src)
|
||||
|
||||
list_for_each_entry(d, &hci_dev_list, list) {
|
||||
if (!test_bit(HCI_UP, &d->flags) ||
|
||||
test_bit(HCI_RAW, &d->flags) ||
|
||||
test_bit(HCI_USER_CHANNEL, &d->dev_flags) ||
|
||||
d->dev_type != HCI_BREDR)
|
||||
continue;
|
||||
@@ -627,7 +654,8 @@ static void hci_req_add_le_create_conn(struct hci_request *req,
|
||||
cp.own_address_type = own_addr_type;
|
||||
cp.conn_interval_min = cpu_to_le16(conn->le_conn_min_interval);
|
||||
cp.conn_interval_max = cpu_to_le16(conn->le_conn_max_interval);
|
||||
cp.supervision_timeout = cpu_to_le16(0x002a);
|
||||
cp.conn_latency = cpu_to_le16(conn->le_conn_latency);
|
||||
cp.supervision_timeout = cpu_to_le16(conn->le_supv_timeout);
|
||||
cp.min_ce_len = cpu_to_le16(0x0000);
|
||||
cp.max_ce_len = cpu_to_le16(0x0000);
|
||||
|
||||
@@ -644,15 +672,12 @@ static void hci_req_directed_advertising(struct hci_request *req,
|
||||
u8 own_addr_type;
|
||||
u8 enable;
|
||||
|
||||
enable = 0x00;
|
||||
hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
|
||||
|
||||
/* Clear the HCI_ADVERTISING bit temporarily so that the
|
||||
/* Clear the HCI_LE_ADV bit temporarily so that the
|
||||
* hci_update_random_address knows that it's safe to go ahead
|
||||
* and write a new random address. The flag will be set back on
|
||||
* as soon as the SET_ADV_ENABLE HCI command completes.
|
||||
*/
|
||||
clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
|
||||
clear_bit(HCI_LE_ADV, &hdev->dev_flags);
|
||||
|
||||
/* Set require_privacy to false so that the remote device has a
|
||||
* chance of identifying us.
|
||||
@@ -676,7 +701,8 @@ static void hci_req_directed_advertising(struct hci_request *req,
|
||||
}
|
||||
|
||||
struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
|
||||
u8 dst_type, u8 sec_level, u8 auth_type)
|
||||
u8 dst_type, u8 sec_level, u16 conn_timeout,
|
||||
u8 role)
|
||||
{
|
||||
struct hci_conn_params *params;
|
||||
struct hci_conn *conn;
|
||||
@@ -696,7 +722,6 @@ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
|
||||
conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst);
|
||||
if (conn) {
|
||||
conn->pending_sec_level = sec_level;
|
||||
conn->auth_type = auth_type;
|
||||
goto done;
|
||||
}
|
||||
|
||||
@@ -726,32 +751,56 @@ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
|
||||
dst_type = ADDR_LE_DEV_RANDOM;
|
||||
}
|
||||
|
||||
conn = hci_conn_add(hdev, LE_LINK, dst);
|
||||
conn = hci_conn_add(hdev, LE_LINK, dst, role);
|
||||
if (!conn)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
conn->dst_type = dst_type;
|
||||
conn->sec_level = BT_SECURITY_LOW;
|
||||
conn->pending_sec_level = sec_level;
|
||||
conn->auth_type = auth_type;
|
||||
conn->conn_timeout = conn_timeout;
|
||||
|
||||
hci_req_init(&req, hdev);
|
||||
|
||||
if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
|
||||
/* Disable advertising if we're active. For master role
|
||||
* connections most controllers will refuse to connect if
|
||||
* advertising is enabled, and for slave role connections we
|
||||
* anyway have to disable it in order to start directed
|
||||
* advertising.
|
||||
*/
|
||||
if (test_bit(HCI_LE_ADV, &hdev->dev_flags)) {
|
||||
u8 enable = 0x00;
|
||||
hci_req_add(&req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable),
|
||||
&enable);
|
||||
}
|
||||
|
||||
/* If requested to connect as slave use directed advertising */
|
||||
if (conn->role == HCI_ROLE_SLAVE) {
|
||||
/* If we're active scanning most controllers are unable
|
||||
* to initiate advertising. Simply reject the attempt.
|
||||
*/
|
||||
if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
|
||||
hdev->le_scan_type == LE_SCAN_ACTIVE) {
|
||||
skb_queue_purge(&req.cmd_q);
|
||||
hci_conn_del(conn);
|
||||
return ERR_PTR(-EBUSY);
|
||||
}
|
||||
|
||||
hci_req_directed_advertising(&req, conn);
|
||||
goto create_conn;
|
||||
}
|
||||
|
||||
conn->out = true;
|
||||
conn->link_mode |= HCI_LM_MASTER;
|
||||
|
||||
params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type);
|
||||
if (params) {
|
||||
conn->le_conn_min_interval = params->conn_min_interval;
|
||||
conn->le_conn_max_interval = params->conn_max_interval;
|
||||
conn->le_conn_latency = params->conn_latency;
|
||||
conn->le_supv_timeout = params->supervision_timeout;
|
||||
} else {
|
||||
conn->le_conn_min_interval = hdev->le_conn_min_interval;
|
||||
conn->le_conn_max_interval = hdev->le_conn_max_interval;
|
||||
conn->le_conn_latency = hdev->le_conn_latency;
|
||||
conn->le_supv_timeout = hdev->le_supv_timeout;
|
||||
}
|
||||
|
||||
/* If controller is scanning, we stop it since some controllers are
|
||||
@@ -785,11 +834,11 @@ struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst,
|
||||
struct hci_conn *acl;
|
||||
|
||||
if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
|
||||
return ERR_PTR(-ENOTSUPP);
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
|
||||
acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
|
||||
if (!acl) {
|
||||
acl = hci_conn_add(hdev, ACL_LINK, dst);
|
||||
acl = hci_conn_add(hdev, ACL_LINK, dst, HCI_ROLE_MASTER);
|
||||
if (!acl)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
@@ -818,7 +867,7 @@ struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst,
|
||||
|
||||
sco = hci_conn_hash_lookup_ba(hdev, type, dst);
|
||||
if (!sco) {
|
||||
sco = hci_conn_add(hdev, type, dst);
|
||||
sco = hci_conn_add(hdev, type, dst, HCI_ROLE_MASTER);
|
||||
if (!sco) {
|
||||
hci_conn_drop(acl);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
@@ -865,7 +914,8 @@ int hci_conn_check_link_mode(struct hci_conn *conn)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (hci_conn_ssp_enabled(conn) && !(conn->link_mode & HCI_LM_ENCRYPT))
|
||||
if (hci_conn_ssp_enabled(conn) &&
|
||||
!test_bit(HCI_CONN_ENCRYPT, &conn->flags))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
@@ -881,7 +931,7 @@ static int hci_conn_auth(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
|
||||
|
||||
if (sec_level > conn->sec_level)
|
||||
conn->pending_sec_level = sec_level;
|
||||
else if (conn->link_mode & HCI_LM_AUTH)
|
||||
else if (test_bit(HCI_CONN_AUTH, &conn->flags))
|
||||
return 1;
|
||||
|
||||
/* Make sure we preserve an existing MITM requirement*/
|
||||
@@ -899,7 +949,7 @@ static int hci_conn_auth(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
|
||||
/* If we're already encrypted set the REAUTH_PEND flag,
|
||||
* otherwise set the ENCRYPT_PEND.
|
||||
*/
|
||||
if (conn->link_mode & HCI_LM_ENCRYPT)
|
||||
if (test_bit(HCI_CONN_ENCRYPT, &conn->flags))
|
||||
set_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
|
||||
else
|
||||
set_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
|
||||
@@ -923,7 +973,8 @@ static void hci_conn_encrypt(struct hci_conn *conn)
|
||||
}
|
||||
|
||||
/* 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,
|
||||
bool initiator)
|
||||
{
|
||||
BT_DBG("hcon %p", conn);
|
||||
|
||||
@@ -940,7 +991,7 @@ int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
|
||||
return 1;
|
||||
|
||||
/* For other security levels we need the link key. */
|
||||
if (!(conn->link_mode & HCI_LM_AUTH))
|
||||
if (!test_bit(HCI_CONN_AUTH, &conn->flags))
|
||||
goto auth;
|
||||
|
||||
/* An authenticated FIPS approved combination key has sufficient
|
||||
@@ -976,11 +1027,14 @@ auth:
|
||||
if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags))
|
||||
return 0;
|
||||
|
||||
if (initiator)
|
||||
set_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags);
|
||||
|
||||
if (!hci_conn_auth(conn, sec_level, auth_type))
|
||||
return 0;
|
||||
|
||||
encrypt:
|
||||
if (conn->link_mode & HCI_LM_ENCRYPT)
|
||||
if (test_bit(HCI_CONN_ENCRYPT, &conn->flags))
|
||||
return 1;
|
||||
|
||||
hci_conn_encrypt(conn);
|
||||
@@ -1027,7 +1081,7 @@ int hci_conn_switch_role(struct hci_conn *conn, __u8 role)
|
||||
{
|
||||
BT_DBG("hcon %p", conn);
|
||||
|
||||
if (!role && conn->link_mode & HCI_LM_MASTER)
|
||||
if (role == conn->role)
|
||||
return 1;
|
||||
|
||||
if (!test_and_set_bit(HCI_CONN_RSWITCH_PEND, &conn->flags)) {
|
||||
@@ -1048,9 +1102,6 @@ void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active)
|
||||
|
||||
BT_DBG("hcon %p mode %d", conn, conn->mode);
|
||||
|
||||
if (test_bit(HCI_RAW, &hdev->flags))
|
||||
return;
|
||||
|
||||
if (conn->mode != HCI_CM_SNIFF)
|
||||
goto timer;
|
||||
|
||||
@@ -1101,6 +1152,28 @@ void hci_conn_check_pending(struct hci_dev *hdev)
|
||||
hci_dev_unlock(hdev);
|
||||
}
|
||||
|
||||
static u32 get_link_mode(struct hci_conn *conn)
|
||||
{
|
||||
u32 link_mode = 0;
|
||||
|
||||
if (conn->role == HCI_ROLE_MASTER)
|
||||
link_mode |= HCI_LM_MASTER;
|
||||
|
||||
if (test_bit(HCI_CONN_ENCRYPT, &conn->flags))
|
||||
link_mode |= HCI_LM_ENCRYPT;
|
||||
|
||||
if (test_bit(HCI_CONN_AUTH, &conn->flags))
|
||||
link_mode |= HCI_LM_AUTH;
|
||||
|
||||
if (test_bit(HCI_CONN_SECURE, &conn->flags))
|
||||
link_mode |= HCI_LM_SECURE;
|
||||
|
||||
if (test_bit(HCI_CONN_FIPS, &conn->flags))
|
||||
link_mode |= HCI_LM_FIPS;
|
||||
|
||||
return link_mode;
|
||||
}
|
||||
|
||||
int hci_get_conn_list(void __user *arg)
|
||||
{
|
||||
struct hci_conn *c;
|
||||
@@ -1136,7 +1209,7 @@ int hci_get_conn_list(void __user *arg)
|
||||
(ci + n)->type = c->type;
|
||||
(ci + n)->out = c->out;
|
||||
(ci + n)->state = c->state;
|
||||
(ci + n)->link_mode = c->link_mode;
|
||||
(ci + n)->link_mode = get_link_mode(c);
|
||||
if (++n >= req.conn_num)
|
||||
break;
|
||||
}
|
||||
@@ -1172,7 +1245,7 @@ int hci_get_conn_info(struct hci_dev *hdev, void __user *arg)
|
||||
ci.type = conn->type;
|
||||
ci.out = conn->out;
|
||||
ci.state = conn->state;
|
||||
ci.link_mode = conn->link_mode;
|
||||
ci.link_mode = get_link_mode(conn);
|
||||
}
|
||||
hci_dev_unlock(hdev);
|
||||
|
||||
@@ -1209,7 +1282,7 @@ struct hci_chan *hci_chan_create(struct hci_conn *conn)
|
||||
|
||||
BT_DBG("%s hcon %p", hdev->name, conn);
|
||||
|
||||
chan = kzalloc(sizeof(struct hci_chan), GFP_KERNEL);
|
||||
chan = kzalloc(sizeof(*chan), GFP_KERNEL);
|
||||
if (!chan)
|
||||
return NULL;
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -35,13 +35,32 @@ static atomic_t monitor_promisc = ATOMIC_INIT(0);
|
||||
|
||||
/* ----- HCI socket interface ----- */
|
||||
|
||||
/* Socket info */
|
||||
#define hci_pi(sk) ((struct hci_pinfo *) sk)
|
||||
|
||||
struct hci_pinfo {
|
||||
struct bt_sock bt;
|
||||
struct hci_dev *hdev;
|
||||
struct hci_filter filter;
|
||||
__u32 cmsg_mask;
|
||||
unsigned short channel;
|
||||
};
|
||||
|
||||
static inline int hci_test_bit(int nr, void *addr)
|
||||
{
|
||||
return *((__u32 *) addr + (nr >> 5)) & ((__u32) 1 << (nr & 31));
|
||||
}
|
||||
|
||||
/* Security filter */
|
||||
static struct hci_sec_filter hci_sec_filter = {
|
||||
#define HCI_SFLT_MAX_OGF 5
|
||||
|
||||
struct hci_sec_filter {
|
||||
__u32 type_mask;
|
||||
__u32 event_mask[2];
|
||||
__u32 ocf_mask[HCI_SFLT_MAX_OGF + 1][4];
|
||||
};
|
||||
|
||||
static const struct hci_sec_filter hci_sec_filter = {
|
||||
/* Packet types */
|
||||
0x10,
|
||||
/* Events */
|
||||
@@ -481,7 +500,7 @@ static int hci_sock_blacklist_add(struct hci_dev *hdev, void __user *arg)
|
||||
|
||||
hci_dev_lock(hdev);
|
||||
|
||||
err = hci_blacklist_add(hdev, &bdaddr, BDADDR_BREDR);
|
||||
err = hci_bdaddr_list_add(&hdev->blacklist, &bdaddr, BDADDR_BREDR);
|
||||
|
||||
hci_dev_unlock(hdev);
|
||||
|
||||
@@ -498,7 +517,7 @@ static int hci_sock_blacklist_del(struct hci_dev *hdev, void __user *arg)
|
||||
|
||||
hci_dev_lock(hdev);
|
||||
|
||||
err = hci_blacklist_del(hdev, &bdaddr, BDADDR_BREDR);
|
||||
err = hci_bdaddr_list_del(&hdev->blacklist, &bdaddr, BDADDR_BREDR);
|
||||
|
||||
hci_dev_unlock(hdev);
|
||||
|
||||
@@ -517,6 +536,9 @@ static int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd,
|
||||
if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags))
|
||||
return -EBUSY;
|
||||
|
||||
if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (hdev->dev_type != HCI_BREDR)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
@@ -690,7 +712,8 @@ static int hci_sock_bind(struct socket *sock, struct sockaddr *addr,
|
||||
|
||||
if (test_bit(HCI_UP, &hdev->flags) ||
|
||||
test_bit(HCI_INIT, &hdev->flags) ||
|
||||
test_bit(HCI_SETUP, &hdev->dev_flags)) {
|
||||
test_bit(HCI_SETUP, &hdev->dev_flags) ||
|
||||
test_bit(HCI_CONFIG, &hdev->dev_flags)) {
|
||||
err = -EBUSY;
|
||||
hci_dev_put(hdev);
|
||||
goto done;
|
||||
@@ -960,7 +983,7 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
|
||||
goto drop;
|
||||
}
|
||||
|
||||
if (test_bit(HCI_RAW, &hdev->flags) || (ogf == 0x3f)) {
|
||||
if (ogf == 0x3f) {
|
||||
skb_queue_tail(&hdev->raw_q, skb);
|
||||
queue_work(hdev->workqueue, &hdev->tx_work);
|
||||
} else {
|
||||
|
@@ -154,7 +154,7 @@ static int hidp_input_event(struct input_dev *dev, unsigned int type,
|
||||
(!!test_bit(LED_COMPOSE, dev->led) << 3) |
|
||||
(!!test_bit(LED_SCROLLL, dev->led) << 2) |
|
||||
(!!test_bit(LED_CAPSL, dev->led) << 1) |
|
||||
(!!test_bit(LED_NUML, dev->led));
|
||||
(!!test_bit(LED_NUML, dev->led) << 0);
|
||||
|
||||
if (session->leds == newleds)
|
||||
return 0;
|
||||
|
@@ -40,14 +40,13 @@
|
||||
#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 | L2CAP_FEAT_UCD;
|
||||
static u8 l2cap_fixed_chan[8] = { L2CAP_FC_L2CAP | L2CAP_FC_CONNLESS, };
|
||||
static u8 l2cap_fixed_chan[8] = { L2CAP_FC_SIG_BREDR | L2CAP_FC_CONNLESS, };
|
||||
|
||||
static LIST_HEAD(chan_list);
|
||||
static DEFINE_RWLOCK(chan_list_lock);
|
||||
@@ -205,6 +204,7 @@ done:
|
||||
write_unlock(&chan_list_lock);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(l2cap_add_psm);
|
||||
|
||||
int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid)
|
||||
{
|
||||
@@ -437,6 +437,7 @@ struct l2cap_chan *l2cap_chan_create(void)
|
||||
|
||||
return chan;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(l2cap_chan_create);
|
||||
|
||||
static void l2cap_chan_destroy(struct kref *kref)
|
||||
{
|
||||
@@ -464,6 +465,7 @@ void l2cap_chan_put(struct l2cap_chan *c)
|
||||
|
||||
kref_put(&c->kref, l2cap_chan_destroy);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(l2cap_chan_put);
|
||||
|
||||
void l2cap_chan_set_defaults(struct l2cap_chan *chan)
|
||||
{
|
||||
@@ -482,6 +484,7 @@ void l2cap_chan_set_defaults(struct l2cap_chan *chan)
|
||||
|
||||
set_bit(FLAG_FORCE_ACTIVE, &chan->flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(l2cap_chan_set_defaults);
|
||||
|
||||
static void l2cap_le_flowctl_init(struct l2cap_chan *chan)
|
||||
{
|
||||
@@ -614,6 +617,7 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err)
|
||||
|
||||
return;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(l2cap_chan_del);
|
||||
|
||||
void l2cap_conn_update_id_addr(struct hci_conn *hcon)
|
||||
{
|
||||
@@ -717,6 +721,7 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason)
|
||||
break;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(l2cap_chan_close);
|
||||
|
||||
static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
|
||||
{
|
||||
@@ -770,7 +775,7 @@ static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
|
||||
}
|
||||
|
||||
/* Service level security */
|
||||
int l2cap_chan_check_security(struct l2cap_chan *chan)
|
||||
int l2cap_chan_check_security(struct l2cap_chan *chan, bool initiator)
|
||||
{
|
||||
struct l2cap_conn *conn = chan->conn;
|
||||
__u8 auth_type;
|
||||
@@ -780,7 +785,8 @@ int l2cap_chan_check_security(struct l2cap_chan *chan)
|
||||
|
||||
auth_type = l2cap_get_auth_type(chan);
|
||||
|
||||
return hci_conn_security(conn->hcon, chan->sec_level, auth_type);
|
||||
return hci_conn_security(conn->hcon, chan->sec_level, auth_type,
|
||||
initiator);
|
||||
}
|
||||
|
||||
static u8 l2cap_get_ident(struct l2cap_conn *conn)
|
||||
@@ -793,14 +799,14 @@ static u8 l2cap_get_ident(struct l2cap_conn *conn)
|
||||
* 200 - 254 are used by utilities like l2ping, etc.
|
||||
*/
|
||||
|
||||
spin_lock(&conn->lock);
|
||||
mutex_lock(&conn->ident_lock);
|
||||
|
||||
if (++conn->tx_ident > 128)
|
||||
conn->tx_ident = 1;
|
||||
|
||||
id = conn->tx_ident;
|
||||
|
||||
spin_unlock(&conn->lock);
|
||||
mutex_unlock(&conn->ident_lock);
|
||||
|
||||
return id;
|
||||
}
|
||||
@@ -1273,7 +1279,7 @@ static void l2cap_do_start(struct l2cap_chan *chan)
|
||||
if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
|
||||
return;
|
||||
|
||||
if (l2cap_chan_check_security(chan) &&
|
||||
if (l2cap_chan_check_security(chan, true) &&
|
||||
__l2cap_no_conn_pending(chan)) {
|
||||
l2cap_start_connection(chan);
|
||||
}
|
||||
@@ -1352,7 +1358,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
|
||||
}
|
||||
|
||||
if (chan->state == BT_CONNECT) {
|
||||
if (!l2cap_chan_check_security(chan) ||
|
||||
if (!l2cap_chan_check_security(chan, true) ||
|
||||
!__l2cap_no_conn_pending(chan)) {
|
||||
l2cap_chan_unlock(chan);
|
||||
continue;
|
||||
@@ -1374,7 +1380,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
|
||||
rsp.scid = cpu_to_le16(chan->dcid);
|
||||
rsp.dcid = cpu_to_le16(chan->scid);
|
||||
|
||||
if (l2cap_chan_check_security(chan)) {
|
||||
if (l2cap_chan_check_security(chan, false)) {
|
||||
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);
|
||||
@@ -1455,13 +1461,12 @@ static struct l2cap_chan *l2cap_global_chan_by_scid(int state, u16 cid,
|
||||
static void l2cap_le_conn_ready(struct l2cap_conn *conn)
|
||||
{
|
||||
struct hci_conn *hcon = conn->hcon;
|
||||
struct hci_dev *hdev = hcon->hdev;
|
||||
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,
|
||||
&hcon->src, &hcon->dst);
|
||||
@@ -1475,9 +1480,28 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)
|
||||
dst_type = bdaddr_type(hcon, hcon->dst_type);
|
||||
|
||||
/* If device is blocked, do not create a channel for it */
|
||||
if (hci_blacklist_lookup(hcon->hdev, &hcon->dst, dst_type))
|
||||
if (hci_bdaddr_list_lookup(&hdev->blacklist, &hcon->dst, dst_type))
|
||||
return;
|
||||
|
||||
/* For LE slave connections, make sure the connection interval
|
||||
* is in the range of the minium and maximum interval that has
|
||||
* been configured for this connection. If not, then trigger
|
||||
* the connection update procedure.
|
||||
*/
|
||||
if (hcon->role == HCI_ROLE_SLAVE &&
|
||||
(hcon->le_conn_interval < hcon->le_conn_min_interval ||
|
||||
hcon->le_conn_interval > hcon->le_conn_max_interval)) {
|
||||
struct l2cap_conn_param_update_req req;
|
||||
|
||||
req.min = cpu_to_le16(hcon->le_conn_min_interval);
|
||||
req.max = cpu_to_le16(hcon->le_conn_max_interval);
|
||||
req.latency = cpu_to_le16(hcon->le_conn_latency);
|
||||
req.to_multiplier = cpu_to_le16(hcon->le_supv_timeout);
|
||||
|
||||
l2cap_send_cmd(conn, l2cap_get_ident(conn),
|
||||
L2CAP_CONN_PARAM_UPDATE_REQ, sizeof(req), &req);
|
||||
}
|
||||
|
||||
l2cap_chan_lock(pchan);
|
||||
|
||||
chan = pchan->ops->new_connection(pchan);
|
||||
@@ -2118,7 +2142,8 @@ static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan,
|
||||
struct sk_buff **frag;
|
||||
int sent = 0;
|
||||
|
||||
if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
|
||||
if (chan->ops->memcpy_fromiovec(chan, skb_put(skb, count),
|
||||
msg->msg_iov, count))
|
||||
return -EFAULT;
|
||||
|
||||
sent += count;
|
||||
@@ -2131,18 +2156,17 @@ static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan,
|
||||
|
||||
count = min_t(unsigned int, conn->mtu, len);
|
||||
|
||||
tmp = chan->ops->alloc_skb(chan, count,
|
||||
tmp = chan->ops->alloc_skb(chan, 0, count,
|
||||
msg->msg_flags & MSG_DONTWAIT);
|
||||
if (IS_ERR(tmp))
|
||||
return PTR_ERR(tmp);
|
||||
|
||||
*frag = tmp;
|
||||
|
||||
if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
|
||||
if (chan->ops->memcpy_fromiovec(chan, skb_put(*frag, count),
|
||||
msg->msg_iov, count))
|
||||
return -EFAULT;
|
||||
|
||||
(*frag)->priority = skb->priority;
|
||||
|
||||
sent += count;
|
||||
len -= count;
|
||||
|
||||
@@ -2156,26 +2180,23 @@ static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan,
|
||||
}
|
||||
|
||||
static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan,
|
||||
struct msghdr *msg, size_t len,
|
||||
u32 priority)
|
||||
struct msghdr *msg, size_t len)
|
||||
{
|
||||
struct l2cap_conn *conn = chan->conn;
|
||||
struct sk_buff *skb;
|
||||
int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE;
|
||||
struct l2cap_hdr *lh;
|
||||
|
||||
BT_DBG("chan %p psm 0x%2.2x len %zu priority %u", chan,
|
||||
__le16_to_cpu(chan->psm), len, priority);
|
||||
BT_DBG("chan %p psm 0x%2.2x len %zu", chan,
|
||||
__le16_to_cpu(chan->psm), len);
|
||||
|
||||
count = min_t(unsigned int, (conn->mtu - hlen), len);
|
||||
|
||||
skb = chan->ops->alloc_skb(chan, count + hlen,
|
||||
skb = chan->ops->alloc_skb(chan, hlen, count,
|
||||
msg->msg_flags & MSG_DONTWAIT);
|
||||
if (IS_ERR(skb))
|
||||
return skb;
|
||||
|
||||
skb->priority = priority;
|
||||
|
||||
/* Create L2CAP header */
|
||||
lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
|
||||
lh->cid = cpu_to_le16(chan->dcid);
|
||||
@@ -2191,8 +2212,7 @@ static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan,
|
||||
}
|
||||
|
||||
static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan,
|
||||
struct msghdr *msg, size_t len,
|
||||
u32 priority)
|
||||
struct msghdr *msg, size_t len)
|
||||
{
|
||||
struct l2cap_conn *conn = chan->conn;
|
||||
struct sk_buff *skb;
|
||||
@@ -2203,13 +2223,11 @@ static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan,
|
||||
|
||||
count = min_t(unsigned int, (conn->mtu - L2CAP_HDR_SIZE), len);
|
||||
|
||||
skb = chan->ops->alloc_skb(chan, count + L2CAP_HDR_SIZE,
|
||||
skb = chan->ops->alloc_skb(chan, L2CAP_HDR_SIZE, count,
|
||||
msg->msg_flags & MSG_DONTWAIT);
|
||||
if (IS_ERR(skb))
|
||||
return skb;
|
||||
|
||||
skb->priority = priority;
|
||||
|
||||
/* Create L2CAP header */
|
||||
lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
|
||||
lh->cid = cpu_to_le16(chan->dcid);
|
||||
@@ -2247,7 +2265,7 @@ static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
|
||||
|
||||
count = min_t(unsigned int, (conn->mtu - hlen), len);
|
||||
|
||||
skb = chan->ops->alloc_skb(chan, count + hlen,
|
||||
skb = chan->ops->alloc_skb(chan, hlen, count,
|
||||
msg->msg_flags & MSG_DONTWAIT);
|
||||
if (IS_ERR(skb))
|
||||
return skb;
|
||||
@@ -2368,7 +2386,7 @@ static struct sk_buff *l2cap_create_le_flowctl_pdu(struct l2cap_chan *chan,
|
||||
|
||||
count = min_t(unsigned int, (conn->mtu - hlen), len);
|
||||
|
||||
skb = chan->ops->alloc_skb(chan, count + hlen,
|
||||
skb = chan->ops->alloc_skb(chan, hlen, count,
|
||||
msg->msg_flags & MSG_DONTWAIT);
|
||||
if (IS_ERR(skb))
|
||||
return skb;
|
||||
@@ -2430,8 +2448,7 @@ static int l2cap_segment_le_sdu(struct l2cap_chan *chan,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
|
||||
u32 priority)
|
||||
int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
int err;
|
||||
@@ -2442,7 +2459,7 @@ int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
|
||||
|
||||
/* Connectionless channel */
|
||||
if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
|
||||
skb = l2cap_create_connless_pdu(chan, msg, len, priority);
|
||||
skb = l2cap_create_connless_pdu(chan, msg, len);
|
||||
if (IS_ERR(skb))
|
||||
return PTR_ERR(skb);
|
||||
|
||||
@@ -2499,7 +2516,7 @@ int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
|
||||
return -EMSGSIZE;
|
||||
|
||||
/* Create a basic PDU */
|
||||
skb = l2cap_create_basic_pdu(chan, msg, len, priority);
|
||||
skb = l2cap_create_basic_pdu(chan, msg, len);
|
||||
if (IS_ERR(skb))
|
||||
return PTR_ERR(skb);
|
||||
|
||||
@@ -2562,6 +2579,7 @@ int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(l2cap_chan_send);
|
||||
|
||||
static void l2cap_send_srej(struct l2cap_chan *chan, u16 txseq)
|
||||
{
|
||||
@@ -3217,6 +3235,9 @@ done:
|
||||
|
||||
switch (chan->mode) {
|
||||
case L2CAP_MODE_BASIC:
|
||||
if (disable_ertm)
|
||||
break;
|
||||
|
||||
if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
|
||||
!(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
|
||||
break;
|
||||
@@ -3829,7 +3850,7 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,
|
||||
chan->ident = cmd->ident;
|
||||
|
||||
if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
|
||||
if (l2cap_chan_check_security(chan)) {
|
||||
if (l2cap_chan_check_security(chan, false)) {
|
||||
if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
|
||||
l2cap_state_change(chan, BT_CONNECT2);
|
||||
result = L2CAP_CR_PEND;
|
||||
@@ -5197,27 +5218,6 @@ static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
|
||||
u16 to_multiplier)
|
||||
{
|
||||
u16 max_latency;
|
||||
|
||||
if (min > max || min < 6 || max > 3200)
|
||||
return -EINVAL;
|
||||
|
||||
if (to_multiplier < 10 || to_multiplier > 3200)
|
||||
return -EINVAL;
|
||||
|
||||
if (max >= to_multiplier * 8)
|
||||
return -EINVAL;
|
||||
|
||||
max_latency = (to_multiplier * 8 / max) - 1;
|
||||
if (latency > 499 || latency > max_latency)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
|
||||
struct l2cap_cmd_hdr *cmd,
|
||||
u16 cmd_len, u8 *data)
|
||||
@@ -5228,7 +5228,7 @@ static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
|
||||
u16 min, max, latency, to_multiplier;
|
||||
int err;
|
||||
|
||||
if (!(hcon->link_mode & HCI_LM_MASTER))
|
||||
if (hcon->role != HCI_ROLE_MASTER)
|
||||
return -EINVAL;
|
||||
|
||||
if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
|
||||
@@ -5245,7 +5245,7 @@ static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
|
||||
|
||||
memset(&rsp, 0, sizeof(rsp));
|
||||
|
||||
err = l2cap_check_conn_param(min, max, latency, to_multiplier);
|
||||
err = hci_check_conn_params(min, max, latency, to_multiplier);
|
||||
if (err)
|
||||
rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
|
||||
else
|
||||
@@ -5254,8 +5254,16 @@ static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
|
||||
l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
|
||||
sizeof(rsp), &rsp);
|
||||
|
||||
if (!err)
|
||||
hci_le_conn_update(hcon, min, max, latency, to_multiplier);
|
||||
if (!err) {
|
||||
u8 store_hint;
|
||||
|
||||
store_hint = hci_le_conn_update(hcon, min, max, latency,
|
||||
to_multiplier);
|
||||
mgmt_new_conn_param(hcon->hdev, &hcon->dst, hcon->dst_type,
|
||||
store_hint, min, max, latency,
|
||||
to_multiplier);
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -6879,9 +6887,6 @@ static void l2cap_att_channel(struct l2cap_conn *conn,
|
||||
|
||||
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;
|
||||
|
||||
@@ -6914,6 +6919,16 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Since we can't actively block incoming LE connections we must
|
||||
* at least ensure that we ignore incoming data from them.
|
||||
*/
|
||||
if (hcon->type == LE_LINK &&
|
||||
hci_bdaddr_list_lookup(&hcon->hdev->blacklist, &hcon->dst,
|
||||
bdaddr_type(hcon, hcon->dst_type))) {
|
||||
kfree_skb(skb);
|
||||
return;
|
||||
}
|
||||
|
||||
BT_DBG("len %d, cid 0x%4.4x", len, cid);
|
||||
|
||||
switch (cid) {
|
||||
@@ -6940,10 +6955,6 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *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;
|
||||
@@ -6974,7 +6985,7 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon)
|
||||
if (!hchan)
|
||||
return NULL;
|
||||
|
||||
conn = kzalloc(sizeof(struct l2cap_conn), GFP_KERNEL);
|
||||
conn = kzalloc(sizeof(*conn), GFP_KERNEL);
|
||||
if (!conn) {
|
||||
hci_chan_del(hchan);
|
||||
return NULL;
|
||||
@@ -7006,7 +7017,7 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon)
|
||||
conn->hs_enabled = test_bit(HCI_HS_ENABLED,
|
||||
&hcon->hdev->dev_flags);
|
||||
|
||||
spin_lock_init(&conn->lock);
|
||||
mutex_init(&conn->ident_lock);
|
||||
mutex_init(&conn->chan_lock);
|
||||
|
||||
INIT_LIST_HEAD(&conn->chan_l);
|
||||
@@ -7042,7 +7053,6 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
|
||||
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,
|
||||
@@ -7084,7 +7094,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
|
||||
break;
|
||||
/* fall through */
|
||||
default:
|
||||
err = -ENOTSUPP;
|
||||
err = -EOPNOTSUPP;
|
||||
goto done;
|
||||
}
|
||||
|
||||
@@ -7118,9 +7128,9 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
|
||||
chan->psm = psm;
|
||||
chan->dcid = cid;
|
||||
|
||||
auth_type = l2cap_get_auth_type(chan);
|
||||
|
||||
if (bdaddr_type_is_le(dst_type)) {
|
||||
u8 role;
|
||||
|
||||
/* Convert from L2CAP channel address type to HCI address type
|
||||
*/
|
||||
if (dst_type == BDADDR_LE_PUBLIC)
|
||||
@@ -7128,9 +7138,15 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
|
||||
else
|
||||
dst_type = ADDR_LE_DEV_RANDOM;
|
||||
|
||||
if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
|
||||
role = HCI_ROLE_SLAVE;
|
||||
else
|
||||
role = HCI_ROLE_MASTER;
|
||||
|
||||
hcon = hci_connect_le(hdev, dst, dst_type, chan->sec_level,
|
||||
auth_type);
|
||||
HCI_LE_CONN_TIMEOUT, role);
|
||||
} else {
|
||||
u8 auth_type = l2cap_get_auth_type(chan);
|
||||
hcon = hci_connect_acl(hdev, dst, chan->sec_level, auth_type);
|
||||
}
|
||||
|
||||
@@ -7176,7 +7192,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
|
||||
if (hcon->state == BT_CONNECTED) {
|
||||
if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
|
||||
__clear_chan_timer(chan);
|
||||
if (l2cap_chan_check_security(chan))
|
||||
if (l2cap_chan_check_security(chan, true))
|
||||
l2cap_state_change(chan, BT_CONNECTED);
|
||||
} else
|
||||
l2cap_do_start(chan);
|
||||
@@ -7190,6 +7206,7 @@ done:
|
||||
hci_dev_put(hdev);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(l2cap_chan_connect);
|
||||
|
||||
/* ---- L2CAP interface with lower layer (HCI) ---- */
|
||||
|
||||
@@ -7252,8 +7269,6 @@ 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));
|
||||
}
|
||||
|
||||
@@ -7536,14 +7551,11 @@ int __init l2cap_init(void)
|
||||
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();
|
||||
}
|
||||
|
@@ -279,7 +279,7 @@ static int l2cap_sock_listen(struct socket *sock, int backlog)
|
||||
break;
|
||||
/* fall through */
|
||||
default:
|
||||
err = -ENOTSUPP;
|
||||
err = -EOPNOTSUPP;
|
||||
goto done;
|
||||
}
|
||||
|
||||
@@ -361,7 +361,8 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr,
|
||||
BT_DBG("sock %p, sk %p", sock, sk);
|
||||
|
||||
if (peer && sk->sk_state != BT_CONNECTED &&
|
||||
sk->sk_state != BT_CONNECT && sk->sk_state != BT_CONNECT2)
|
||||
sk->sk_state != BT_CONNECT && sk->sk_state != BT_CONNECT2 &&
|
||||
sk->sk_state != BT_CONFIG)
|
||||
return -ENOTCONN;
|
||||
|
||||
memset(la, 0, sizeof(struct sockaddr_l2));
|
||||
@@ -796,7 +797,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
|
||||
} else if ((sk->sk_state == BT_CONNECT2 &&
|
||||
test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) ||
|
||||
sk->sk_state == BT_CONNECTED) {
|
||||
if (!l2cap_chan_check_security(chan))
|
||||
if (!l2cap_chan_check_security(chan, true))
|
||||
set_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags);
|
||||
else
|
||||
sk->sk_state_change(sk);
|
||||
@@ -964,7 +965,7 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
|
||||
return err;
|
||||
|
||||
l2cap_chan_lock(chan);
|
||||
err = l2cap_chan_send(chan, msg, len, sk->sk_priority);
|
||||
err = l2cap_chan_send(chan, msg, len);
|
||||
l2cap_chan_unlock(chan);
|
||||
|
||||
return err;
|
||||
@@ -1111,7 +1112,8 @@ static int l2cap_sock_shutdown(struct socket *sock, int how)
|
||||
l2cap_chan_close(chan, 0);
|
||||
lock_sock(sk);
|
||||
|
||||
if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime)
|
||||
if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime &&
|
||||
!(current->flags & PF_EXITING))
|
||||
err = bt_sock_wait_state(sk, BT_CLOSED,
|
||||
sk->sk_lingertime);
|
||||
}
|
||||
@@ -1292,6 +1294,7 @@ static void l2cap_sock_state_change_cb(struct l2cap_chan *chan, int state,
|
||||
}
|
||||
|
||||
static struct sk_buff *l2cap_sock_alloc_skb_cb(struct l2cap_chan *chan,
|
||||
unsigned long hdr_len,
|
||||
unsigned long len, int nb)
|
||||
{
|
||||
struct sock *sk = chan->data;
|
||||
@@ -1299,17 +1302,26 @@ static struct sk_buff *l2cap_sock_alloc_skb_cb(struct l2cap_chan *chan,
|
||||
int err;
|
||||
|
||||
l2cap_chan_unlock(chan);
|
||||
skb = bt_skb_send_alloc(sk, len, nb, &err);
|
||||
skb = bt_skb_send_alloc(sk, hdr_len + len, nb, &err);
|
||||
l2cap_chan_lock(chan);
|
||||
|
||||
if (!skb)
|
||||
return ERR_PTR(err);
|
||||
|
||||
skb->priority = sk->sk_priority;
|
||||
|
||||
bt_cb(skb)->chan = chan;
|
||||
|
||||
return skb;
|
||||
}
|
||||
|
||||
static int l2cap_sock_memcpy_fromiovec_cb(struct l2cap_chan *chan,
|
||||
unsigned char *kdata,
|
||||
struct iovec *iov, int len)
|
||||
{
|
||||
return memcpy_fromiovec(kdata, iov, len);
|
||||
}
|
||||
|
||||
static void l2cap_sock_ready_cb(struct l2cap_chan *chan)
|
||||
{
|
||||
struct sock *sk = chan->data;
|
||||
@@ -1375,20 +1387,21 @@ static void l2cap_sock_suspend_cb(struct l2cap_chan *chan)
|
||||
sk->sk_state_change(sk);
|
||||
}
|
||||
|
||||
static struct l2cap_ops l2cap_chan_ops = {
|
||||
.name = "L2CAP Socket Interface",
|
||||
.new_connection = l2cap_sock_new_connection_cb,
|
||||
.recv = l2cap_sock_recv_cb,
|
||||
.close = l2cap_sock_close_cb,
|
||||
.teardown = l2cap_sock_teardown_cb,
|
||||
.state_change = l2cap_sock_state_change_cb,
|
||||
.ready = l2cap_sock_ready_cb,
|
||||
.defer = l2cap_sock_defer_cb,
|
||||
.resume = l2cap_sock_resume_cb,
|
||||
.suspend = l2cap_sock_suspend_cb,
|
||||
.set_shutdown = l2cap_sock_set_shutdown_cb,
|
||||
.get_sndtimeo = l2cap_sock_get_sndtimeo_cb,
|
||||
.alloc_skb = l2cap_sock_alloc_skb_cb,
|
||||
static const struct l2cap_ops l2cap_chan_ops = {
|
||||
.name = "L2CAP Socket Interface",
|
||||
.new_connection = l2cap_sock_new_connection_cb,
|
||||
.recv = l2cap_sock_recv_cb,
|
||||
.close = l2cap_sock_close_cb,
|
||||
.teardown = l2cap_sock_teardown_cb,
|
||||
.state_change = l2cap_sock_state_change_cb,
|
||||
.ready = l2cap_sock_ready_cb,
|
||||
.defer = l2cap_sock_defer_cb,
|
||||
.resume = l2cap_sock_resume_cb,
|
||||
.suspend = l2cap_sock_suspend_cb,
|
||||
.set_shutdown = l2cap_sock_set_shutdown_cb,
|
||||
.get_sndtimeo = l2cap_sock_get_sndtimeo_cb,
|
||||
.alloc_skb = l2cap_sock_alloc_skb_cb,
|
||||
.memcpy_fromiovec = l2cap_sock_memcpy_fromiovec_cb,
|
||||
};
|
||||
|
||||
static void l2cap_sock_destruct(struct sock *sk)
|
||||
|
1399
net/bluetooth/mgmt.c
1399
net/bluetooth/mgmt.c
File diff suppressed because it is too large
Load Diff
@@ -227,7 +227,8 @@ static int rfcomm_check_security(struct rfcomm_dlc *d)
|
||||
break;
|
||||
}
|
||||
|
||||
return hci_conn_security(conn->hcon, d->sec_level, auth_type);
|
||||
return hci_conn_security(conn->hcon, d->sec_level, auth_type,
|
||||
d->out);
|
||||
}
|
||||
|
||||
static void rfcomm_session_timeout(unsigned long arg)
|
||||
@@ -1909,10 +1910,13 @@ static struct rfcomm_session *rfcomm_process_rx(struct rfcomm_session *s)
|
||||
/* Get data directly from socket receive queue without copying it. */
|
||||
while ((skb = skb_dequeue(&sk->sk_receive_queue))) {
|
||||
skb_orphan(skb);
|
||||
if (!skb_linearize(skb))
|
||||
if (!skb_linearize(skb)) {
|
||||
s = rfcomm_recv_frame(s, skb);
|
||||
else
|
||||
if (!s)
|
||||
break;
|
||||
} else {
|
||||
kfree_skb(skb);
|
||||
}
|
||||
}
|
||||
|
||||
if (s && (sk->sk_state == BT_CLOSED))
|
||||
|
@@ -918,7 +918,8 @@ static int rfcomm_sock_shutdown(struct socket *sock, int how)
|
||||
sk->sk_shutdown = SHUTDOWN_MASK;
|
||||
__rfcomm_sock_close(sk);
|
||||
|
||||
if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime)
|
||||
if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime &&
|
||||
!(current->flags & PF_EXITING))
|
||||
err = bt_sock_wait_state(sk, BT_CLOSED, sk->sk_lingertime);
|
||||
}
|
||||
release_sock(sk);
|
||||
|
@@ -40,13 +40,38 @@ static struct bt_sock_list sco_sk_list = {
|
||||
.lock = __RW_LOCK_UNLOCKED(sco_sk_list.lock)
|
||||
};
|
||||
|
||||
static void __sco_chan_add(struct sco_conn *conn, struct sock *sk, struct sock *parent);
|
||||
static void sco_chan_del(struct sock *sk, int err);
|
||||
/* ---- SCO connections ---- */
|
||||
struct sco_conn {
|
||||
struct hci_conn *hcon;
|
||||
|
||||
spinlock_t lock;
|
||||
struct sock *sk;
|
||||
|
||||
unsigned int mtu;
|
||||
};
|
||||
|
||||
#define sco_conn_lock(c) spin_lock(&c->lock);
|
||||
#define sco_conn_unlock(c) spin_unlock(&c->lock);
|
||||
|
||||
static void sco_sock_close(struct sock *sk);
|
||||
static void sco_sock_kill(struct sock *sk);
|
||||
|
||||
/* ----- SCO socket info ----- */
|
||||
#define sco_pi(sk) ((struct sco_pinfo *) sk)
|
||||
|
||||
struct sco_pinfo {
|
||||
struct bt_sock bt;
|
||||
bdaddr_t src;
|
||||
bdaddr_t dst;
|
||||
__u32 flags;
|
||||
__u16 setting;
|
||||
struct sco_conn *conn;
|
||||
};
|
||||
|
||||
/* ---- SCO timers ---- */
|
||||
#define SCO_CONN_TIMEOUT (HZ * 40)
|
||||
#define SCO_DISCONN_TIMEOUT (HZ * 2)
|
||||
|
||||
static void sco_sock_timeout(unsigned long arg)
|
||||
{
|
||||
struct sock *sk = (struct sock *) arg;
|
||||
@@ -102,13 +127,31 @@ static struct sco_conn *sco_conn_add(struct hci_conn *hcon)
|
||||
return conn;
|
||||
}
|
||||
|
||||
static struct sock *sco_chan_get(struct sco_conn *conn)
|
||||
/* Delete channel.
|
||||
* Must be called on the locked socket. */
|
||||
static void sco_chan_del(struct sock *sk, int err)
|
||||
{
|
||||
struct sock *sk = NULL;
|
||||
sco_conn_lock(conn);
|
||||
sk = conn->sk;
|
||||
sco_conn_unlock(conn);
|
||||
return sk;
|
||||
struct sco_conn *conn;
|
||||
|
||||
conn = sco_pi(sk)->conn;
|
||||
|
||||
BT_DBG("sk %p, conn %p, err %d", sk, conn, err);
|
||||
|
||||
if (conn) {
|
||||
sco_conn_lock(conn);
|
||||
conn->sk = NULL;
|
||||
sco_pi(sk)->conn = NULL;
|
||||
sco_conn_unlock(conn);
|
||||
|
||||
if (conn->hcon)
|
||||
hci_conn_drop(conn->hcon);
|
||||
}
|
||||
|
||||
sk->sk_state = BT_CLOSED;
|
||||
sk->sk_err = err;
|
||||
sk->sk_state_change(sk);
|
||||
|
||||
sock_set_flag(sk, SOCK_ZAPPED);
|
||||
}
|
||||
|
||||
static int sco_conn_del(struct hci_conn *hcon, int err)
|
||||
@@ -122,7 +165,10 @@ static int sco_conn_del(struct hci_conn *hcon, int err)
|
||||
BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
|
||||
|
||||
/* Kill socket */
|
||||
sk = sco_chan_get(conn);
|
||||
sco_conn_lock(conn);
|
||||
sk = conn->sk;
|
||||
sco_conn_unlock(conn);
|
||||
|
||||
if (sk) {
|
||||
bh_lock_sock(sk);
|
||||
sco_sock_clear_timer(sk);
|
||||
@@ -136,6 +182,17 @@ static int sco_conn_del(struct hci_conn *hcon, int err)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __sco_chan_add(struct sco_conn *conn, struct sock *sk, struct sock *parent)
|
||||
{
|
||||
BT_DBG("conn %p", conn);
|
||||
|
||||
sco_pi(sk)->conn = conn;
|
||||
conn->sk = sk;
|
||||
|
||||
if (parent)
|
||||
bt_accept_enqueue(parent, sk);
|
||||
}
|
||||
|
||||
static int sco_chan_add(struct sco_conn *conn, struct sock *sk,
|
||||
struct sock *parent)
|
||||
{
|
||||
@@ -240,7 +297,11 @@ static int sco_send_frame(struct sock *sk, struct msghdr *msg, int len)
|
||||
|
||||
static void sco_recv_frame(struct sco_conn *conn, struct sk_buff *skb)
|
||||
{
|
||||
struct sock *sk = sco_chan_get(conn);
|
||||
struct sock *sk;
|
||||
|
||||
sco_conn_lock(conn);
|
||||
sk = conn->sk;
|
||||
sco_conn_unlock(conn);
|
||||
|
||||
if (!sk)
|
||||
goto drop;
|
||||
@@ -909,7 +970,8 @@ static int sco_sock_shutdown(struct socket *sock, int how)
|
||||
sco_sock_clear_timer(sk);
|
||||
__sco_sock_close(sk);
|
||||
|
||||
if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime)
|
||||
if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime &&
|
||||
!(current->flags & PF_EXITING))
|
||||
err = bt_sock_wait_state(sk, BT_CLOSED,
|
||||
sk->sk_lingertime);
|
||||
}
|
||||
@@ -929,7 +991,8 @@ static int sco_sock_release(struct socket *sock)
|
||||
|
||||
sco_sock_close(sk);
|
||||
|
||||
if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime) {
|
||||
if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime &&
|
||||
!(current->flags & PF_EXITING)) {
|
||||
lock_sock(sk);
|
||||
err = bt_sock_wait_state(sk, BT_CLOSED, sk->sk_lingertime);
|
||||
release_sock(sk);
|
||||
@@ -940,44 +1003,6 @@ static int sco_sock_release(struct socket *sock)
|
||||
return err;
|
||||
}
|
||||
|
||||
static void __sco_chan_add(struct sco_conn *conn, struct sock *sk, struct sock *parent)
|
||||
{
|
||||
BT_DBG("conn %p", conn);
|
||||
|
||||
sco_pi(sk)->conn = conn;
|
||||
conn->sk = sk;
|
||||
|
||||
if (parent)
|
||||
bt_accept_enqueue(parent, sk);
|
||||
}
|
||||
|
||||
/* Delete channel.
|
||||
* Must be called on the locked socket. */
|
||||
static void sco_chan_del(struct sock *sk, int err)
|
||||
{
|
||||
struct sco_conn *conn;
|
||||
|
||||
conn = sco_pi(sk)->conn;
|
||||
|
||||
BT_DBG("sk %p, conn %p, err %d", sk, conn, err);
|
||||
|
||||
if (conn) {
|
||||
sco_conn_lock(conn);
|
||||
conn->sk = NULL;
|
||||
sco_pi(sk)->conn = NULL;
|
||||
sco_conn_unlock(conn);
|
||||
|
||||
if (conn->hcon)
|
||||
hci_conn_drop(conn->hcon);
|
||||
}
|
||||
|
||||
sk->sk_state = BT_CLOSED;
|
||||
sk->sk_err = err;
|
||||
sk->sk_state_change(sk);
|
||||
|
||||
sock_set_flag(sk, SOCK_ZAPPED);
|
||||
}
|
||||
|
||||
static void sco_conn_ready(struct sco_conn *conn)
|
||||
{
|
||||
struct sock *parent;
|
||||
|
@@ -35,11 +35,13 @@
|
||||
|
||||
#define AUTH_REQ_MASK 0x07
|
||||
|
||||
#define SMP_FLAG_TK_VALID 1
|
||||
#define SMP_FLAG_CFM_PENDING 2
|
||||
#define SMP_FLAG_MITM_AUTH 3
|
||||
#define SMP_FLAG_COMPLETE 4
|
||||
#define SMP_FLAG_INITIATOR 5
|
||||
enum {
|
||||
SMP_FLAG_TK_VALID,
|
||||
SMP_FLAG_CFM_PENDING,
|
||||
SMP_FLAG_MITM_AUTH,
|
||||
SMP_FLAG_COMPLETE,
|
||||
SMP_FLAG_INITIATOR,
|
||||
};
|
||||
|
||||
struct smp_chan {
|
||||
struct l2cap_conn *conn;
|
||||
@@ -60,20 +62,16 @@ struct smp_chan {
|
||||
struct smp_ltk *slave_ltk;
|
||||
struct smp_irk *remote_irk;
|
||||
unsigned long flags;
|
||||
|
||||
struct crypto_blkcipher *tfm_aes;
|
||||
};
|
||||
|
||||
static inline void swap128(const u8 src[16], u8 dst[16])
|
||||
static inline void swap_buf(const u8 *src, u8 *dst, size_t len)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 16; i++)
|
||||
dst[15 - i] = src[i];
|
||||
}
|
||||
size_t i;
|
||||
|
||||
static inline void swap56(const u8 src[7], u8 dst[7])
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 7; i++)
|
||||
dst[6 - i] = src[i];
|
||||
for (i = 0; i < len; i++)
|
||||
dst[len - 1 - i] = src[i];
|
||||
}
|
||||
|
||||
static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r)
|
||||
@@ -92,7 +90,7 @@ static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r)
|
||||
desc.flags = 0;
|
||||
|
||||
/* The most significant octet of key corresponds to k[0] */
|
||||
swap128(k, tmp);
|
||||
swap_buf(k, tmp, 16);
|
||||
|
||||
err = crypto_blkcipher_setkey(tfm, tmp, 16);
|
||||
if (err) {
|
||||
@@ -101,7 +99,7 @@ static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r)
|
||||
}
|
||||
|
||||
/* Most significant octet of plaintextData corresponds to data[0] */
|
||||
swap128(r, data);
|
||||
swap_buf(r, data, 16);
|
||||
|
||||
sg_init_one(&sg, data, 16);
|
||||
|
||||
@@ -110,7 +108,7 @@ static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r)
|
||||
BT_ERR("Encrypt data error %d", err);
|
||||
|
||||
/* Most significant octet of encryptedData corresponds to data[0] */
|
||||
swap128(data, r);
|
||||
swap_buf(data, r, 16);
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -174,13 +172,16 @@ int smp_generate_rpa(struct crypto_blkcipher *tfm, u8 irk[16], bdaddr_t *rpa)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16],
|
||||
u8 preq[7], u8 pres[7], u8 _iat, bdaddr_t *ia,
|
||||
u8 _rat, bdaddr_t *ra, u8 res[16])
|
||||
static int smp_c1(struct smp_chan *smp, u8 k[16], u8 r[16], u8 preq[7],
|
||||
u8 pres[7], u8 _iat, bdaddr_t *ia, u8 _rat, bdaddr_t *ra,
|
||||
u8 res[16])
|
||||
{
|
||||
struct hci_dev *hdev = smp->conn->hcon->hdev;
|
||||
u8 p1[16], p2[16];
|
||||
int err;
|
||||
|
||||
BT_DBG("%s", hdev->name);
|
||||
|
||||
memset(p1, 0, 16);
|
||||
|
||||
/* p1 = pres || preq || _rat || _iat */
|
||||
@@ -198,7 +199,7 @@ static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16],
|
||||
u128_xor((u128 *) res, (u128 *) r, (u128 *) p1);
|
||||
|
||||
/* res = e(k, res) */
|
||||
err = smp_e(tfm, k, res);
|
||||
err = smp_e(smp->tfm_aes, k, res);
|
||||
if (err) {
|
||||
BT_ERR("Encrypt data error");
|
||||
return err;
|
||||
@@ -208,23 +209,26 @@ static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16],
|
||||
u128_xor((u128 *) res, (u128 *) res, (u128 *) p2);
|
||||
|
||||
/* res = e(k, res) */
|
||||
err = smp_e(tfm, k, res);
|
||||
err = smp_e(smp->tfm_aes, k, res);
|
||||
if (err)
|
||||
BT_ERR("Encrypt data error");
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int smp_s1(struct crypto_blkcipher *tfm, u8 k[16], u8 r1[16],
|
||||
u8 r2[16], u8 _r[16])
|
||||
static int smp_s1(struct smp_chan *smp, u8 k[16], u8 r1[16], u8 r2[16],
|
||||
u8 _r[16])
|
||||
{
|
||||
struct hci_dev *hdev = smp->conn->hcon->hdev;
|
||||
int err;
|
||||
|
||||
BT_DBG("%s", hdev->name);
|
||||
|
||||
/* Just least significant octets from r1 and r2 are considered */
|
||||
memcpy(_r, r2, 8);
|
||||
memcpy(_r + 8, r1, 8);
|
||||
|
||||
err = smp_e(tfm, k, _r);
|
||||
err = smp_e(smp->tfm_aes, k, _r);
|
||||
if (err)
|
||||
BT_ERR("Encrypt data error");
|
||||
|
||||
@@ -303,7 +307,7 @@ static void build_pairing_cmd(struct l2cap_conn *conn,
|
||||
struct hci_dev *hdev = hcon->hdev;
|
||||
u8 local_dist = 0, remote_dist = 0;
|
||||
|
||||
if (test_bit(HCI_PAIRABLE, &conn->hcon->hdev->dev_flags)) {
|
||||
if (test_bit(HCI_BONDABLE, &conn->hcon->hdev->dev_flags)) {
|
||||
local_dist = SMP_DIST_ENC_KEY | SMP_DIST_SIGN;
|
||||
remote_dist = SMP_DIST_ENC_KEY | SMP_DIST_SIGN;
|
||||
authreq |= SMP_AUTH_BONDING;
|
||||
@@ -387,10 +391,12 @@ static const u8 gen_method[5][5] = {
|
||||
|
||||
static u8 get_auth_method(struct smp_chan *smp, u8 local_io, u8 remote_io)
|
||||
{
|
||||
/* If either side has unknown io_caps, use JUST WORKS */
|
||||
/* If either side has unknown io_caps, use JUST_CFM (which gets
|
||||
* converted later to JUST_WORKS if we're initiators.
|
||||
*/
|
||||
if (local_io > SMP_IO_KEYBOARD_DISPLAY ||
|
||||
remote_io > SMP_IO_KEYBOARD_DISPLAY)
|
||||
return JUST_WORKS;
|
||||
return JUST_CFM;
|
||||
|
||||
return gen_method[remote_io][local_io];
|
||||
}
|
||||
@@ -410,21 +416,25 @@ static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth,
|
||||
|
||||
BT_DBG("tk_request: auth:%d lcl:%d rem:%d", auth, local_io, remote_io);
|
||||
|
||||
/* If neither side wants MITM, use JUST WORKS */
|
||||
/* Otherwise, look up method from the table */
|
||||
/* If neither side wants MITM, either "just" confirm an incoming
|
||||
* request or use just-works for outgoing ones. The JUST_CFM
|
||||
* will be converted to JUST_WORKS if necessary later in this
|
||||
* function. If either side has MITM look up the method from the
|
||||
* table.
|
||||
*/
|
||||
if (!(auth & SMP_AUTH_MITM))
|
||||
method = JUST_WORKS;
|
||||
method = JUST_CFM;
|
||||
else
|
||||
method = get_auth_method(smp, local_io, remote_io);
|
||||
|
||||
/* If not bonding, don't ask user to confirm a Zero TK */
|
||||
if (!(auth & SMP_AUTH_BONDING) && method == JUST_CFM)
|
||||
method = JUST_WORKS;
|
||||
|
||||
/* Don't confirm locally initiated pairing attempts */
|
||||
if (method == JUST_CFM && test_bit(SMP_FLAG_INITIATOR, &smp->flags))
|
||||
method = JUST_WORKS;
|
||||
|
||||
/* Don't bother user space with no IO capabilities */
|
||||
if (method == JUST_CFM && hcon->io_capability == HCI_IO_NO_INPUT_OUTPUT)
|
||||
method = JUST_WORKS;
|
||||
|
||||
/* If Just Works, Continue with Zero TK */
|
||||
if (method == JUST_WORKS) {
|
||||
set_bit(SMP_FLAG_TK_VALID, &smp->flags);
|
||||
@@ -439,7 +449,7 @@ static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth,
|
||||
* Confirms and the slave Enters the passkey.
|
||||
*/
|
||||
if (method == OVERLAP) {
|
||||
if (hcon->link_mode & HCI_LM_MASTER)
|
||||
if (hcon->role == HCI_ROLE_MASTER)
|
||||
method = CFM_PASSKEY;
|
||||
else
|
||||
method = REQ_PASSKEY;
|
||||
@@ -477,23 +487,15 @@ static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth,
|
||||
static u8 smp_confirm(struct smp_chan *smp)
|
||||
{
|
||||
struct l2cap_conn *conn = smp->conn;
|
||||
struct hci_dev *hdev = conn->hcon->hdev;
|
||||
struct crypto_blkcipher *tfm = hdev->tfm_aes;
|
||||
struct smp_cmd_pairing_confirm cp;
|
||||
int ret;
|
||||
|
||||
BT_DBG("conn %p", conn);
|
||||
|
||||
/* Prevent mutual access to hdev->tfm_aes */
|
||||
hci_dev_lock(hdev);
|
||||
|
||||
ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp,
|
||||
ret = smp_c1(smp, smp->tk, smp->prnd, smp->preq, smp->prsp,
|
||||
conn->hcon->init_addr_type, &conn->hcon->init_addr,
|
||||
conn->hcon->resp_addr_type, &conn->hcon->resp_addr,
|
||||
cp.confirm_val);
|
||||
|
||||
hci_dev_unlock(hdev);
|
||||
|
||||
if (ret)
|
||||
return SMP_UNSPECIFIED;
|
||||
|
||||
@@ -508,25 +510,17 @@ static u8 smp_random(struct smp_chan *smp)
|
||||
{
|
||||
struct l2cap_conn *conn = smp->conn;
|
||||
struct hci_conn *hcon = conn->hcon;
|
||||
struct hci_dev *hdev = hcon->hdev;
|
||||
struct crypto_blkcipher *tfm = hdev->tfm_aes;
|
||||
u8 confirm[16];
|
||||
int ret;
|
||||
|
||||
if (IS_ERR_OR_NULL(tfm))
|
||||
if (IS_ERR_OR_NULL(smp->tfm_aes))
|
||||
return SMP_UNSPECIFIED;
|
||||
|
||||
BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
|
||||
|
||||
/* Prevent mutual access to hdev->tfm_aes */
|
||||
hci_dev_lock(hdev);
|
||||
|
||||
ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp,
|
||||
ret = smp_c1(smp, smp->tk, smp->rrnd, smp->preq, smp->prsp,
|
||||
hcon->init_addr_type, &hcon->init_addr,
|
||||
hcon->resp_addr_type, &hcon->resp_addr, confirm);
|
||||
|
||||
hci_dev_unlock(hdev);
|
||||
|
||||
if (ret)
|
||||
return SMP_UNSPECIFIED;
|
||||
|
||||
@@ -540,7 +534,7 @@ static u8 smp_random(struct smp_chan *smp)
|
||||
__le64 rand = 0;
|
||||
__le16 ediv = 0;
|
||||
|
||||
smp_s1(tfm, smp->tk, smp->rrnd, smp->prnd, stk);
|
||||
smp_s1(smp, smp->tk, smp->rrnd, smp->prnd, stk);
|
||||
|
||||
memset(stk + smp->enc_key_size, 0,
|
||||
SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);
|
||||
@@ -550,6 +544,7 @@ static u8 smp_random(struct smp_chan *smp)
|
||||
|
||||
hci_le_start_enc(hcon, ediv, rand, stk);
|
||||
hcon->enc_key_size = smp->enc_key_size;
|
||||
set_bit(HCI_CONN_STK_ENCRYPT, &hcon->flags);
|
||||
} else {
|
||||
u8 stk[16], auth;
|
||||
__le64 rand = 0;
|
||||
@@ -558,7 +553,7 @@ static u8 smp_random(struct smp_chan *smp)
|
||||
smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(smp->prnd),
|
||||
smp->prnd);
|
||||
|
||||
smp_s1(tfm, smp->tk, smp->prnd, smp->rrnd, stk);
|
||||
smp_s1(smp, smp->tk, smp->prnd, smp->rrnd, stk);
|
||||
|
||||
memset(stk + smp->enc_key_size, 0,
|
||||
SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);
|
||||
@@ -568,9 +563,12 @@ static u8 smp_random(struct smp_chan *smp)
|
||||
else
|
||||
auth = 0;
|
||||
|
||||
/* Even though there's no _SLAVE suffix this is the
|
||||
* slave STK we're adding for later lookup (the master
|
||||
* STK never needs to be stored).
|
||||
*/
|
||||
hci_add_ltk(hcon->hdev, &hcon->dst, hcon->dst_type,
|
||||
HCI_SMP_STK_SLAVE, auth, stk, smp->enc_key_size,
|
||||
ediv, rand);
|
||||
SMP_STK, auth, stk, smp->enc_key_size, ediv, rand);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -581,12 +579,21 @@ static struct smp_chan *smp_chan_create(struct l2cap_conn *conn)
|
||||
struct smp_chan *smp;
|
||||
|
||||
smp = kzalloc(sizeof(*smp), GFP_ATOMIC);
|
||||
if (!smp)
|
||||
if (!smp) {
|
||||
clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
smp->tfm_aes = crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
|
||||
if (IS_ERR(smp->tfm_aes)) {
|
||||
BT_ERR("Unable to create ECB crypto context");
|
||||
kfree(smp);
|
||||
clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
smp->conn = conn;
|
||||
conn->smp_chan = smp;
|
||||
conn->hcon->smp_conn = conn;
|
||||
|
||||
hci_conn_hold(conn->hcon);
|
||||
|
||||
@@ -606,6 +613,8 @@ void smp_chan_destroy(struct l2cap_conn *conn)
|
||||
kfree(smp->csrk);
|
||||
kfree(smp->slave_csrk);
|
||||
|
||||
crypto_free_blkcipher(smp->tfm_aes);
|
||||
|
||||
/* If pairing failed clean up any keys we might have */
|
||||
if (!complete) {
|
||||
if (smp->ltk) {
|
||||
@@ -626,19 +635,18 @@ void smp_chan_destroy(struct l2cap_conn *conn)
|
||||
|
||||
kfree(smp);
|
||||
conn->smp_chan = NULL;
|
||||
conn->hcon->smp_conn = NULL;
|
||||
hci_conn_drop(conn->hcon);
|
||||
}
|
||||
|
||||
int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey)
|
||||
{
|
||||
struct l2cap_conn *conn = hcon->smp_conn;
|
||||
struct l2cap_conn *conn = hcon->l2cap_data;
|
||||
struct smp_chan *smp;
|
||||
u32 value;
|
||||
|
||||
BT_DBG("");
|
||||
|
||||
if (!conn)
|
||||
if (!conn || !test_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
|
||||
return -ENOTCONN;
|
||||
|
||||
smp = conn->smp_chan;
|
||||
@@ -675,6 +683,7 @@ int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey)
|
||||
static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
|
||||
{
|
||||
struct smp_cmd_pairing rsp, *req = (void *) skb->data;
|
||||
struct hci_dev *hdev = conn->hcon->hdev;
|
||||
struct smp_chan *smp;
|
||||
u8 key_size, auth, sec_level;
|
||||
int ret;
|
||||
@@ -684,7 +693,7 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
|
||||
if (skb->len < sizeof(*req))
|
||||
return SMP_INVALID_PARAMS;
|
||||
|
||||
if (conn->hcon->link_mode & HCI_LM_MASTER)
|
||||
if (conn->hcon->role != HCI_ROLE_SLAVE)
|
||||
return SMP_CMD_NOTSUPP;
|
||||
|
||||
if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags))
|
||||
@@ -695,6 +704,10 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
|
||||
if (!smp)
|
||||
return SMP_UNSPECIFIED;
|
||||
|
||||
if (!test_bit(HCI_BONDABLE, &hdev->dev_flags) &&
|
||||
(req->auth_req & SMP_AUTH_BONDING))
|
||||
return SMP_PAIRING_NOTSUPP;
|
||||
|
||||
smp->preq[0] = SMP_CMD_PAIRING_REQ;
|
||||
memcpy(&smp->preq[1], req, sizeof(*req));
|
||||
skb_pull(skb, sizeof(*req));
|
||||
@@ -734,8 +747,6 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
|
||||
if (ret)
|
||||
return SMP_UNSPECIFIED;
|
||||
|
||||
clear_bit(SMP_FLAG_INITIATOR, &smp->flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -751,7 +762,7 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
|
||||
if (skb->len < sizeof(*rsp))
|
||||
return SMP_INVALID_PARAMS;
|
||||
|
||||
if (!(conn->hcon->link_mode & HCI_LM_MASTER))
|
||||
if (conn->hcon->role != HCI_ROLE_MASTER)
|
||||
return SMP_CMD_NOTSUPP;
|
||||
|
||||
skb_pull(skb, sizeof(*rsp));
|
||||
@@ -839,26 +850,51 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
|
||||
return smp_random(smp);
|
||||
}
|
||||
|
||||
static u8 smp_ltk_encrypt(struct l2cap_conn *conn, u8 sec_level)
|
||||
static bool smp_ltk_encrypt(struct l2cap_conn *conn, u8 sec_level)
|
||||
{
|
||||
struct smp_ltk *key;
|
||||
struct hci_conn *hcon = conn->hcon;
|
||||
|
||||
key = hci_find_ltk_by_addr(hcon->hdev, &hcon->dst, hcon->dst_type,
|
||||
hcon->out);
|
||||
hcon->role);
|
||||
if (!key)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
if (sec_level > BT_SECURITY_MEDIUM && !key->authenticated)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags))
|
||||
return 1;
|
||||
return true;
|
||||
|
||||
hci_le_start_enc(hcon, key->ediv, key->rand, key->val);
|
||||
hcon->enc_key_size = key->enc_size;
|
||||
|
||||
return 1;
|
||||
/* We never store STKs for master role, so clear this flag */
|
||||
clear_bit(HCI_CONN_STK_ENCRYPT, &hcon->flags);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level)
|
||||
{
|
||||
if (sec_level == BT_SECURITY_LOW)
|
||||
return true;
|
||||
|
||||
/* If we're encrypted with an STK always claim insufficient
|
||||
* security. This way we allow the connection to be re-encrypted
|
||||
* with an LTK, even if the LTK provides the same level of
|
||||
* security. Only exception is if we don't have an LTK (e.g.
|
||||
* because of key distribution bits).
|
||||
*/
|
||||
if (test_bit(HCI_CONN_STK_ENCRYPT, &hcon->flags) &&
|
||||
hci_find_ltk_by_addr(hcon->hdev, &hcon->dst, hcon->dst_type,
|
||||
hcon->role))
|
||||
return false;
|
||||
|
||||
if (hcon->sec_level >= sec_level)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
|
||||
@@ -874,10 +910,13 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
|
||||
if (skb->len < sizeof(*rp))
|
||||
return SMP_INVALID_PARAMS;
|
||||
|
||||
if (!(conn->hcon->link_mode & HCI_LM_MASTER))
|
||||
if (hcon->role != HCI_ROLE_MASTER)
|
||||
return SMP_CMD_NOTSUPP;
|
||||
|
||||
sec_level = authreq_to_seclevel(rp->auth_req);
|
||||
if (smp_sufficient_security(hcon, sec_level))
|
||||
return 0;
|
||||
|
||||
if (sec_level > hcon->pending_sec_level)
|
||||
hcon->pending_sec_level = sec_level;
|
||||
|
||||
@@ -888,6 +927,12 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
|
||||
return 0;
|
||||
|
||||
smp = smp_chan_create(conn);
|
||||
if (!smp)
|
||||
return SMP_UNSPECIFIED;
|
||||
|
||||
if (!test_bit(HCI_BONDABLE, &hcon->hdev->dev_flags) &&
|
||||
(rp->auth_req & SMP_AUTH_BONDING))
|
||||
return SMP_PAIRING_NOTSUPP;
|
||||
|
||||
skb_pull(skb, sizeof(*rp));
|
||||
|
||||
@@ -899,22 +944,9 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
|
||||
|
||||
smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
|
||||
|
||||
clear_bit(SMP_FLAG_INITIATOR, &smp->flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level)
|
||||
{
|
||||
if (sec_level == BT_SECURITY_LOW)
|
||||
return true;
|
||||
|
||||
if (hcon->sec_level >= sec_level)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
|
||||
{
|
||||
struct l2cap_conn *conn = hcon->l2cap_data;
|
||||
@@ -936,7 +968,7 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
|
||||
if (sec_level > hcon->pending_sec_level)
|
||||
hcon->pending_sec_level = sec_level;
|
||||
|
||||
if (hcon->link_mode & HCI_LM_MASTER)
|
||||
if (hcon->role == HCI_ROLE_MASTER)
|
||||
if (smp_ltk_encrypt(conn, hcon->pending_sec_level))
|
||||
return 0;
|
||||
|
||||
@@ -956,7 +988,7 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
|
||||
hcon->pending_sec_level > BT_SECURITY_MEDIUM)
|
||||
authreq |= SMP_AUTH_MITM;
|
||||
|
||||
if (hcon->link_mode & HCI_LM_MASTER) {
|
||||
if (hcon->role == HCI_ROLE_MASTER) {
|
||||
struct smp_cmd_pairing cp;
|
||||
|
||||
build_pairing_cmd(conn, &cp, NULL, authreq);
|
||||
@@ -1021,7 +1053,7 @@ static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
|
||||
|
||||
hci_dev_lock(hdev);
|
||||
authenticated = (hcon->sec_level == BT_SECURITY_HIGH);
|
||||
ltk = hci_add_ltk(hdev, &hcon->dst, hcon->dst_type, HCI_SMP_LTK,
|
||||
ltk = hci_add_ltk(hdev, &hcon->dst, hcon->dst_type, SMP_LTK,
|
||||
authenticated, smp->tk, smp->enc_key_size,
|
||||
rp->ediv, rp->rand);
|
||||
smp->ltk = ltk;
|
||||
@@ -1075,6 +1107,8 @@ static int smp_cmd_ident_addr_info(struct l2cap_conn *conn,
|
||||
|
||||
skb_pull(skb, sizeof(*info));
|
||||
|
||||
hci_dev_lock(hcon->hdev);
|
||||
|
||||
/* Strictly speaking the Core Specification (4.1) allows sending
|
||||
* an empty address which would force us to rely on just the IRK
|
||||
* as "identity information". However, since such
|
||||
@@ -1084,8 +1118,7 @@ static int smp_cmd_ident_addr_info(struct l2cap_conn *conn,
|
||||
*/
|
||||
if (!bacmp(&info->bdaddr, BDADDR_ANY)) {
|
||||
BT_ERR("Ignoring IRK with no identity address");
|
||||
smp_distribute_keys(conn);
|
||||
return 0;
|
||||
goto distribute;
|
||||
}
|
||||
|
||||
bacpy(&smp->id_addr, &info->bdaddr);
|
||||
@@ -1099,8 +1132,11 @@ static int smp_cmd_ident_addr_info(struct l2cap_conn *conn,
|
||||
smp->remote_irk = hci_add_irk(conn->hcon->hdev, &smp->id_addr,
|
||||
smp->id_addr_type, smp->irk, &rpa);
|
||||
|
||||
distribute:
|
||||
smp_distribute_keys(conn);
|
||||
|
||||
hci_dev_unlock(hcon->hdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1156,7 +1192,7 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
|
||||
}
|
||||
|
||||
if (!test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags)) {
|
||||
err = -ENOTSUPP;
|
||||
err = -EOPNOTSUPP;
|
||||
reason = SMP_PAIRING_NOTSUPP;
|
||||
goto done;
|
||||
}
|
||||
@@ -1174,7 +1210,7 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
|
||||
!conn->smp_chan) {
|
||||
BT_ERR("Unexpected SMP command 0x%02x. Disconnecting.", code);
|
||||
kfree_skb(skb);
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
switch (code) {
|
||||
@@ -1258,6 +1294,22 @@ static void smp_notify_keys(struct l2cap_conn *conn)
|
||||
bacpy(&hcon->dst, &smp->remote_irk->bdaddr);
|
||||
hcon->dst_type = smp->remote_irk->addr_type;
|
||||
l2cap_conn_update_id_addr(hcon);
|
||||
|
||||
/* When receiving an indentity resolving key for
|
||||
* a remote device that does not use a resolvable
|
||||
* private address, just remove the key so that
|
||||
* it is possible to use the controller white
|
||||
* list for scanning.
|
||||
*
|
||||
* Userspace will have been told to not store
|
||||
* this key at this point. So it is safe to
|
||||
* just remove it.
|
||||
*/
|
||||
if (!bacmp(&smp->remote_irk->rpa, BDADDR_ANY)) {
|
||||
list_del(&smp->remote_irk->list);
|
||||
kfree(smp->remote_irk);
|
||||
smp->remote_irk = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* The LTKs and CSRKs should be persistent only if both sides
|
||||
@@ -1337,7 +1389,7 @@ int smp_distribute_keys(struct l2cap_conn *conn)
|
||||
|
||||
authenticated = hcon->sec_level == BT_SECURITY_HIGH;
|
||||
ltk = hci_add_ltk(hdev, &hcon->dst, hcon->dst_type,
|
||||
HCI_SMP_LTK_SLAVE, authenticated, enc.ltk,
|
||||
SMP_LTK_SLAVE, authenticated, enc.ltk,
|
||||
smp->enc_key_size, ediv, rand);
|
||||
smp->slave_ltk = ltk;
|
||||
|
||||
|
@@ -116,6 +116,13 @@ struct smp_cmd_security_req {
|
||||
#define SMP_MIN_ENC_KEY_SIZE 7
|
||||
#define SMP_MAX_ENC_KEY_SIZE 16
|
||||
|
||||
/* LTK types used in internal storage (struct smp_ltk) */
|
||||
enum {
|
||||
SMP_STK,
|
||||
SMP_LTK,
|
||||
SMP_LTK_SLAVE,
|
||||
};
|
||||
|
||||
/* SMP Commands */
|
||||
bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level);
|
||||
int smp_conn_security(struct hci_conn *hcon, __u8 sec_level);
|
||||
|
Reference in New Issue
Block a user