diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-11-04 09:41:05 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-11-04 09:41:05 -0800 |
| commit | b0f85fa11aefc4f3e03306b4cd47f113bd57dcba (patch) | |
| tree | 1333d36d99fde3f97210795941fc246f0ad08a75 /net/bluetooth/mgmt.c | |
| parent | ccc9d4a6d640cbde05d519edeb727881646cf71b (diff) | |
| parent | f32bfb9a8ca083f8d148ea90ae5ba66f4831836e (diff) | |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
Pull networking updates from David Miller:
Changes of note:
1) Allow to schedule ICMP packets in IPVS, from Alex Gartrell.
2) Provide FIB table ID in ipv4 route dumps just as ipv6 does, from
David Ahern.
3) Allow the user to ask for the statistics to be filtered out of
ipv4/ipv6 address netlink dumps. From Sowmini Varadhan.
4) More work to pass the network namespace context around deep into
various packet path APIs, starting with the netfilter hooks. From
Eric W Biederman.
5) Add layer 2 TX/RX checksum offloading to qeth driver, from Thomas
Richter.
6) Use usec resolution for SYN/ACK RTTs in TCP, from Yuchung Cheng.
7) Support Very High Throughput in wireless MESH code, from Bob
Copeland.
8) Allow setting the ageing_time in switchdev/rocker. From Scott
Feldman.
9) Properly autoload L2TP type modules, from Stephen Hemminger.
10) Fix and enable offload features by default in 8139cp driver, from
David Woodhouse.
11) Support both ipv4 and ipv6 sockets in a single vxlan device, from
Jiri Benc.
12) Fix CWND limiting of thin streams in TCP, from Bendik Rønning
Opstad.
13) Fix IPSEC flowcache overflows on large systems, from Steffen
Klassert.
14) Convert bridging to track VLANs using rhashtable entries rather than
a bitmap. From Nikolay Aleksandrov.
15) Make TCP listener handling completely lockless, this is a major
accomplishment. Incoming request sockets now live in the
established hash table just like any other socket too.
From Eric Dumazet.
15) Provide more bridging attributes to netlink, from Nikolay
Aleksandrov.
16) Use hash based algorithm for ipv4 multipath routing, this was very
long overdue. From Peter Nørlund.
17) Several y2038 cures, mostly avoiding timespec. From Arnd Bergmann.
18) Allow non-root execution of EBPF programs, from Alexei Starovoitov.
19) Support SO_INCOMING_CPU as setsockopt, from Eric Dumazet. This
influences the port binding selection logic used by SO_REUSEPORT.
20) Add ipv6 support to VRF, from David Ahern.
21) Add support for Mellanox Spectrum switch ASIC, from Jiri Pirko.
22) Add rtl8xxxu Realtek wireless driver, from Jes Sorensen.
23) Implement RACK loss recovery in TCP, from Yuchung Cheng.
24) Support multipath routes in MPLS, from Roopa Prabhu.
25) Fix POLLOUT notification for listening sockets in AF_UNIX, from Eric
Dumazet.
26) Add new QED Qlogic river, from Yuval Mintz, Manish Chopra, and
Sudarsana Kalluru.
27) Don't fetch timestamps on AF_UNIX sockets, from Hannes Frederic
Sowa.
28) Support ipv6 geneve tunnels, from John W Linville.
29) Add flood control support to switchdev layer, from Ido Schimmel.
30) Fix CHECKSUM_PARTIAL handling of potentially fragmented frames, from
Hannes Frederic Sowa.
31) Support persistent maps and progs in bpf, from Daniel Borkmann.
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (1790 commits)
sh_eth: use DMA barriers
switchdev: respect SKIP_EOPNOTSUPP flag in case there is no recursion
net: sched: kill dead code in sch_choke.c
irda: Delete an unnecessary check before the function call "irlmp_unregister_service"
net: dsa: mv88e6xxx: include DSA ports in VLANs
net: dsa: mv88e6xxx: disable SA learning for DSA and CPU ports
net/core: fix for_each_netdev_feature
vlan: Invoke driver vlan hooks only if device is present
arcnet/com20020: add LEDS_CLASS dependency
bpf, verifier: annotate verbose printer with __printf
dp83640: Only wait for timestamps for packets with timestamping enabled.
ptp: Change ptp_class to a proper bitmask
dp83640: Prune rx timestamp list before reading from it
dp83640: Delay scheduled work.
dp83640: Include hash in timestamp/packet matching
ipv6: fix tunnel error handling
net/mlx5e: Fix LSO vlan insertion
net/mlx5e: Re-eanble client vlan TX acceleration
net/mlx5e: Return error in case mlx5e_set_features() fails
net/mlx5e: Don't allow more than max supported channels
...
Diffstat (limited to 'net/bluetooth/mgmt.c')
| -rw-r--r-- | net/bluetooth/mgmt.c | 178 |
1 files changed, 70 insertions, 108 deletions
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index c4fe2fee753f..7f22119276f3 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -268,6 +268,14 @@ static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 len, HCI_SOCK_TRUSTED, skip_sk); } +static u8 le_addr_type(u8 mgmt_addr_type) +{ + if (mgmt_addr_type == BDADDR_LE_PUBLIC) + return ADDR_LE_DEV_PUBLIC; + else + return ADDR_LE_DEV_RANDOM; +} + static int read_version(struct sock *sk, struct hci_dev *hdev, void *data, u16 data_len) { @@ -1631,35 +1639,8 @@ static int clean_up_hci_state(struct hci_dev *hdev) discov_stopped = hci_stop_discovery(&req); list_for_each_entry(conn, &hdev->conn_hash.list, list) { - struct hci_cp_disconnect dc; - struct hci_cp_reject_conn_req rej; - - switch (conn->state) { - case BT_CONNECTED: - case BT_CONFIG: - dc.handle = cpu_to_le16(conn->handle); - dc.reason = 0x15; /* Terminated due to Power Off */ - hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc); - break; - case BT_CONNECT: - if (conn->type == LE_LINK) - hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL, - 0, NULL); - else if (conn->type == ACL_LINK) - hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL, - 6, &conn->dst); - break; - case BT_CONNECT2: - bacpy(&rej.bdaddr, &conn->dst); - rej.reason = 0x15; /* Terminated due to Power Off */ - if (conn->type == ACL_LINK) - hci_req_add(&req, HCI_OP_REJECT_CONN_REQ, - sizeof(rej), &rej); - else if (conn->type == SCO_LINK) - hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ, - sizeof(rej), &rej); - break; - } + /* 0x15 == Terminated due to Power Off */ + __hci_abort_conn(&req, conn, 0x15); } err = hci_req_run(&req, clean_up_hci_complete); @@ -3044,9 +3025,10 @@ static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data, { struct mgmt_cp_unpair_device *cp = data; struct mgmt_rp_unpair_device rp; - struct hci_cp_disconnect dc; + struct hci_conn_params *params; struct mgmt_pending_cmd *cmd; struct hci_conn *conn; + u8 addr_type; int err; memset(&rp, 0, sizeof(rp)); @@ -3087,36 +3069,23 @@ static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data, conn = NULL; err = hci_remove_link_key(hdev, &cp->addr.bdaddr); - } else { - u8 addr_type; - - conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, - &cp->addr.bdaddr); - if (conn) { - /* Defer clearing up the connection parameters - * until closing to give a chance of keeping - * them if a repairing happens. - */ - set_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags); - - /* If disconnection is not requested, then - * clear the connection variable so that the - * link is not terminated. - */ - if (!cp->disconnect) - conn = NULL; + if (err < 0) { + err = mgmt_cmd_complete(sk, hdev->id, + MGMT_OP_UNPAIR_DEVICE, + MGMT_STATUS_NOT_PAIRED, &rp, + sizeof(rp)); + goto unlock; } - if (cp->addr.type == BDADDR_LE_PUBLIC) - addr_type = ADDR_LE_DEV_PUBLIC; - else - addr_type = ADDR_LE_DEV_RANDOM; + goto done; + } - hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type); + /* LE address type */ + addr_type = le_addr_type(cp->addr.type); - err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type); - } + hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type); + err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type); if (err < 0) { err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, MGMT_STATUS_NOT_PAIRED, &rp, @@ -3124,6 +3093,36 @@ static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data, goto unlock; } + conn = hci_conn_hash_lookup_le(hdev, &cp->addr.bdaddr, addr_type); + if (!conn) { + hci_conn_params_del(hdev, &cp->addr.bdaddr, addr_type); + goto done; + } + + /* Abort any ongoing SMP pairing */ + smp_cancel_pairing(conn); + + /* Defer clearing up the connection parameters until closing to + * give a chance of keeping them if a repairing happens. + */ + set_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags); + + /* Disable auto-connection parameters if present */ + params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr, addr_type); + if (params) { + if (params->explicit_connect) + params->auto_connect = HCI_AUTO_CONN_EXPLICIT; + else + params->auto_connect = HCI_AUTO_CONN_DISABLED; + } + + /* If disconnection is not requested, then clear the connection + * variable so that the link is not terminated. + */ + if (!cp->disconnect) + conn = NULL; + +done: /* If the connection variable is set, then termination of the * link is requested. */ @@ -3143,9 +3142,7 @@ static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data, cmd->cmd_complete = addr_cmd_complete; - dc.handle = cpu_to_le16(conn->handle); - dc.reason = 0x13; /* Remote User Terminated Connection */ - err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc); + err = hci_abort_conn(conn, HCI_ERROR_REMOTE_USER_TERM); if (err < 0) mgmt_pending_remove(cmd); @@ -3193,7 +3190,8 @@ static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data, conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr); else - conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr); + conn = hci_conn_hash_lookup_le(hdev, &cp->addr.bdaddr, + le_addr_type(cp->addr.type)); if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) { err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT, @@ -3544,16 +3542,9 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data, conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level, auth_type); } else { - u8 addr_type; + u8 addr_type = le_addr_type(cp->addr.type); struct hci_conn_params *p; - /* Convert from L2CAP channel address type to HCI address type - */ - if (cp->addr.type == BDADDR_LE_PUBLIC) - addr_type = ADDR_LE_DEV_PUBLIC; - else - addr_type = ADDR_LE_DEV_RANDOM; - /* When pairing a new device, it is expected to remember * this device for future connections. Adding the connection * parameter information ahead of time allows tracking @@ -3697,7 +3688,8 @@ static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev, if (addr->type == BDADDR_BREDR) conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr); else - conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr); + conn = hci_conn_hash_lookup_le(hdev, &addr->bdaddr, + le_addr_type(addr->type)); if (!conn) { err = mgmt_cmd_complete(sk, hdev->id, mgmt_op, @@ -5600,14 +5592,9 @@ static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data, for (i = 0; i < irk_count; i++) { struct mgmt_irk_info *irk = &cp->irks[i]; - u8 addr_type; - - if (irk->addr.type == BDADDR_LE_PUBLIC) - addr_type = ADDR_LE_DEV_PUBLIC; - else - addr_type = ADDR_LE_DEV_RANDOM; - hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val, + hci_add_irk(hdev, &irk->addr.bdaddr, + le_addr_type(irk->addr.type), irk->val, BDADDR_ANY); } @@ -5687,12 +5674,7 @@ static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev, for (i = 0; i < key_count; i++) { struct mgmt_ltk_info *key = &cp->keys[i]; - u8 type, addr_type, authenticated; - - if (key->addr.type == BDADDR_LE_PUBLIC) - addr_type = ADDR_LE_DEV_PUBLIC; - else - addr_type = ADDR_LE_DEV_RANDOM; + u8 type, authenticated; switch (key->type) { case MGMT_LTK_UNAUTHENTICATED: @@ -5718,9 +5700,9 @@ static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev, continue; } - hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type, - authenticated, key->val, key->enc_size, key->ediv, - key->rand); + hci_add_ltk(hdev, &key->addr.bdaddr, + le_addr_type(key->addr.type), type, authenticated, + key->val, key->enc_size, key->ediv, key->rand); } err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0, @@ -6232,10 +6214,7 @@ static int add_device(struct sock *sk, struct hci_dev *hdev, goto added; } - if (cp->addr.type == BDADDR_LE_PUBLIC) - addr_type = ADDR_LE_DEV_PUBLIC; - else - addr_type = ADDR_LE_DEV_RANDOM; + addr_type = le_addr_type(cp->addr.type); if (cp->action == 0x02) auto_conn = HCI_AUTO_CONN_ALWAYS; @@ -6364,10 +6343,7 @@ static int remove_device(struct sock *sk, struct hci_dev *hdev, goto complete; } - if (cp->addr.type == BDADDR_LE_PUBLIC) - addr_type = ADDR_LE_DEV_PUBLIC; - else - addr_type = ADDR_LE_DEV_RANDOM; + addr_type = le_addr_type(cp->addr.type); /* Kernel internally uses conn_params with resolvable private * address, but Remove Device allows only identity addresses. @@ -7873,27 +7849,13 @@ void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent) mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL); } -void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk) +void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk, bool persistent) { struct mgmt_ev_new_irk ev; memset(&ev, 0, sizeof(ev)); - /* For identity resolving keys from devices that are already - * using a public address or static random address, do not - * ask for storing this key. The identity resolving key really - * is only mandatory for devices using resolvable random - * addresses. - * - * Storing all identity resolving keys has the downside that - * they will be also loaded on next boot of they system. More - * identity resolving keys, means more time during scanning is - * needed to actually resolve these addresses. - */ - if (bacmp(&irk->rpa, BDADDR_ANY)) - ev.store_hint = 0x01; - else - ev.store_hint = 0x00; + ev.store_hint = persistent; bacpy(&ev.rpa, &irk->rpa); bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr); |
