blob: edee60bbc7b46dd189e7b83297d627432fcc280d [file] [log] [blame]
Johan Hedberga380b6c2015-03-17 13:48:48 +02001/*
2 BlueZ - Bluetooth protocol stack for Linux
3
4 Copyright (C) 2015 Intel Corporation
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License version 2 as
8 published by the Free Software Foundation;
9
10 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
11 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
12 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
13 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
14 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
15 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
19 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
20 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
21 SOFTWARE IS DISCLAIMED.
22*/
23
Marcel Holtmann38ceaa02016-08-27 20:23:41 +020024#include <asm/unaligned.h>
25
Johan Hedberga380b6c2015-03-17 13:48:48 +020026#include <net/bluetooth/bluetooth.h>
27#include <net/bluetooth/hci_core.h>
Marcel Holtmann38ceaa02016-08-27 20:23:41 +020028#include <net/bluetooth/hci_mon.h>
Johan Hedberga380b6c2015-03-17 13:48:48 +020029#include <net/bluetooth/mgmt.h>
30
31#include "mgmt_util.h"
32
Marcel Holtmann38ceaa02016-08-27 20:23:41 +020033static struct sk_buff *create_monitor_ctrl_event(__le16 index, u32 cookie,
34 u16 opcode, u16 len, void *buf)
35{
36 struct hci_mon_hdr *hdr;
37 struct sk_buff *skb;
38
39 skb = bt_skb_alloc(6 + len, GFP_ATOMIC);
40 if (!skb)
41 return NULL;
42
43 put_unaligned_le32(cookie, skb_put(skb, 4));
44 put_unaligned_le16(opcode, skb_put(skb, 2));
45
46 if (buf)
Johannes Berg59ae1d12017-06-16 14:29:20 +020047 skb_put_data(skb, buf, len);
Marcel Holtmann38ceaa02016-08-27 20:23:41 +020048
49 __net_timestamp(skb);
50
Johannes Bergd58ff352017-06-16 14:29:23 +020051 hdr = skb_push(skb, HCI_MON_HDR_SIZE);
Marcel Holtmann38ceaa02016-08-27 20:23:41 +020052 hdr->opcode = cpu_to_le16(HCI_MON_CTRL_EVENT);
53 hdr->index = index;
54 hdr->len = cpu_to_le16(skb->len - HCI_MON_HDR_SIZE);
55
56 return skb;
57}
58
Luiz Augusto von Dentz8aca46f2021-12-03 16:15:40 -080059struct sk_buff *mgmt_alloc_skb(struct hci_dev *hdev, u16 opcode,
60 unsigned int size)
Johan Hedberga380b6c2015-03-17 13:48:48 +020061{
62 struct sk_buff *skb;
Johan Hedberga380b6c2015-03-17 13:48:48 +020063
Luiz Augusto von Dentz8aca46f2021-12-03 16:15:40 -080064 skb = alloc_skb(sizeof(struct mgmt_hdr) + size, GFP_KERNEL);
Johan Hedberga380b6c2015-03-17 13:48:48 +020065 if (!skb)
Luiz Augusto von Dentz8aca46f2021-12-03 16:15:40 -080066 return skb;
Johan Hedberga380b6c2015-03-17 13:48:48 +020067
Luiz Augusto von Dentz8aca46f2021-12-03 16:15:40 -080068 skb_reserve(skb, sizeof(struct mgmt_hdr));
69 bt_cb(skb)->mgmt.hdev = hdev;
70 bt_cb(skb)->mgmt.opcode = opcode;
Johan Hedberga380b6c2015-03-17 13:48:48 +020071
Luiz Augusto von Dentz8aca46f2021-12-03 16:15:40 -080072 return skb;
73}
74
75int mgmt_send_event_skb(unsigned short channel, struct sk_buff *skb, int flag,
76 struct sock *skip_sk)
77{
78 struct hci_dev *hdev;
79 struct mgmt_hdr *hdr;
80 int len = skb->len;
81
82 if (!skb)
83 return -EINVAL;
84
85 hdev = bt_cb(skb)->mgmt.hdev;
Johan Hedberga380b6c2015-03-17 13:48:48 +020086
87 /* Time stamp */
88 __net_timestamp(skb);
89
Luiz Augusto von Dentz8aca46f2021-12-03 16:15:40 -080090 /* Send just the data, without headers, to the monitor */
Marcel Holtmann38ceaa02016-08-27 20:23:41 +020091 if (channel == HCI_CHANNEL_CONTROL)
Luiz Augusto von Dentz8aca46f2021-12-03 16:15:40 -080092 hci_send_monitor_ctrl_event(hdev, bt_cb(skb)->mgmt.opcode,
93 skb->data, skb->len,
Marcel Holtmann38ceaa02016-08-27 20:23:41 +020094 skb_get_ktime(skb), flag, skip_sk);
95
Luiz Augusto von Dentz8aca46f2021-12-03 16:15:40 -080096 hdr = skb_push(skb, sizeof(*hdr));
97 hdr->opcode = cpu_to_le16(bt_cb(skb)->mgmt.opcode);
98 if (hdev)
99 hdr->index = cpu_to_le16(hdev->id);
100 else
101 hdr->index = cpu_to_le16(MGMT_INDEX_NONE);
102 hdr->len = cpu_to_le16(len);
103
104 hci_send_to_channel(channel, skb, flag, skip_sk);
105
Marcel Holtmann38ceaa02016-08-27 20:23:41 +0200106 kfree_skb(skb);
Johan Hedberga380b6c2015-03-17 13:48:48 +0200107 return 0;
108}
109
Luiz Augusto von Dentz8aca46f2021-12-03 16:15:40 -0800110int mgmt_send_event(u16 event, struct hci_dev *hdev, unsigned short channel,
111 void *data, u16 data_len, int flag, struct sock *skip_sk)
112{
113 struct sk_buff *skb;
114
115 skb = mgmt_alloc_skb(hdev, event, data_len);
116 if (!skb)
117 return -ENOMEM;
118
119 if (data)
120 skb_put_data(skb, data, data_len);
121
122 return mgmt_send_event_skb(channel, skb, flag, skip_sk);
123}
124
Johan Hedberga380b6c2015-03-17 13:48:48 +0200125int mgmt_cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
126{
Marcel Holtmann38ceaa02016-08-27 20:23:41 +0200127 struct sk_buff *skb, *mskb;
Johan Hedberga380b6c2015-03-17 13:48:48 +0200128 struct mgmt_hdr *hdr;
129 struct mgmt_ev_cmd_status *ev;
130 int err;
131
132 BT_DBG("sock %p, index %u, cmd %u, status %u", sk, index, cmd, status);
133
134 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_KERNEL);
135 if (!skb)
136 return -ENOMEM;
137
Johannes Berg4df864c2017-06-16 14:29:21 +0200138 hdr = skb_put(skb, sizeof(*hdr));
Johan Hedberga380b6c2015-03-17 13:48:48 +0200139
140 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS);
141 hdr->index = cpu_to_le16(index);
142 hdr->len = cpu_to_le16(sizeof(*ev));
143
Johannes Berg4df864c2017-06-16 14:29:21 +0200144 ev = skb_put(skb, sizeof(*ev));
Johan Hedberga380b6c2015-03-17 13:48:48 +0200145 ev->status = status;
146 ev->opcode = cpu_to_le16(cmd);
147
Marcel Holtmann38ceaa02016-08-27 20:23:41 +0200148 mskb = create_monitor_ctrl_event(hdr->index, hci_sock_get_cookie(sk),
149 MGMT_EV_CMD_STATUS, sizeof(*ev), ev);
150 if (mskb)
151 skb->tstamp = mskb->tstamp;
152 else
153 __net_timestamp(skb);
154
Johan Hedberga380b6c2015-03-17 13:48:48 +0200155 err = sock_queue_rcv_skb(sk, skb);
156 if (err < 0)
157 kfree_skb(skb);
158
Marcel Holtmann38ceaa02016-08-27 20:23:41 +0200159 if (mskb) {
160 hci_send_to_channel(HCI_CHANNEL_MONITOR, mskb,
161 HCI_SOCK_TRUSTED, NULL);
162 kfree_skb(mskb);
163 }
164
Johan Hedberga380b6c2015-03-17 13:48:48 +0200165 return err;
166}
167
168int mgmt_cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status,
169 void *rp, size_t rp_len)
170{
Marcel Holtmann38ceaa02016-08-27 20:23:41 +0200171 struct sk_buff *skb, *mskb;
Johan Hedberga380b6c2015-03-17 13:48:48 +0200172 struct mgmt_hdr *hdr;
173 struct mgmt_ev_cmd_complete *ev;
174 int err;
175
176 BT_DBG("sock %p", sk);
177
178 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + rp_len, GFP_KERNEL);
179 if (!skb)
180 return -ENOMEM;
181
Johannes Berg4df864c2017-06-16 14:29:21 +0200182 hdr = skb_put(skb, sizeof(*hdr));
Johan Hedberga380b6c2015-03-17 13:48:48 +0200183
184 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
185 hdr->index = cpu_to_le16(index);
186 hdr->len = cpu_to_le16(sizeof(*ev) + rp_len);
187
Johannes Berg4df864c2017-06-16 14:29:21 +0200188 ev = skb_put(skb, sizeof(*ev) + rp_len);
Johan Hedberga380b6c2015-03-17 13:48:48 +0200189 ev->opcode = cpu_to_le16(cmd);
190 ev->status = status;
191
192 if (rp)
193 memcpy(ev->data, rp, rp_len);
194
Marcel Holtmann38ceaa02016-08-27 20:23:41 +0200195 mskb = create_monitor_ctrl_event(hdr->index, hci_sock_get_cookie(sk),
196 MGMT_EV_CMD_COMPLETE,
197 sizeof(*ev) + rp_len, ev);
198 if (mskb)
199 skb->tstamp = mskb->tstamp;
200 else
201 __net_timestamp(skb);
202
Johan Hedberga380b6c2015-03-17 13:48:48 +0200203 err = sock_queue_rcv_skb(sk, skb);
204 if (err < 0)
205 kfree_skb(skb);
206
Marcel Holtmann38ceaa02016-08-27 20:23:41 +0200207 if (mskb) {
208 hci_send_to_channel(HCI_CHANNEL_MONITOR, mskb,
209 HCI_SOCK_TRUSTED, NULL);
210 kfree_skb(mskb);
211 }
212
Johan Hedberga380b6c2015-03-17 13:48:48 +0200213 return err;
214}
215
216struct mgmt_pending_cmd *mgmt_pending_find(unsigned short channel, u16 opcode,
217 struct hci_dev *hdev)
218{
219 struct mgmt_pending_cmd *cmd;
220
221 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
222 if (hci_sock_get_channel(cmd->sk) != channel)
223 continue;
224 if (cmd->opcode == opcode)
225 return cmd;
226 }
227
228 return NULL;
229}
230
231struct mgmt_pending_cmd *mgmt_pending_find_data(unsigned short channel,
232 u16 opcode,
233 struct hci_dev *hdev,
234 const void *data)
235{
236 struct mgmt_pending_cmd *cmd;
237
238 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
239 if (cmd->user_data != data)
240 continue;
241 if (cmd->opcode == opcode)
242 return cmd;
243 }
244
245 return NULL;
246}
247
248void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
249 void (*cb)(struct mgmt_pending_cmd *cmd, void *data),
250 void *data)
251{
252 struct mgmt_pending_cmd *cmd, *tmp;
253
254 list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) {
255 if (opcode > 0 && cmd->opcode != opcode)
256 continue;
257
258 cb(cmd, data);
259 }
260}
261
Luiz Augusto von Dentz161510c2021-10-27 16:58:39 -0700262struct mgmt_pending_cmd *mgmt_pending_new(struct sock *sk, u16 opcode,
Johan Hedberga380b6c2015-03-17 13:48:48 +0200263 struct hci_dev *hdev,
264 void *data, u16 len)
265{
266 struct mgmt_pending_cmd *cmd;
267
268 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
269 if (!cmd)
270 return NULL;
271
272 cmd->opcode = opcode;
273 cmd->index = hdev->id;
274
275 cmd->param = kmemdup(data, len, GFP_KERNEL);
276 if (!cmd->param) {
277 kfree(cmd);
278 return NULL;
279 }
280
281 cmd->param_len = len;
282
283 cmd->sk = sk;
284 sock_hold(sk);
285
Luiz Augusto von Dentz161510c2021-10-27 16:58:39 -0700286 return cmd;
287}
288
289struct mgmt_pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
290 struct hci_dev *hdev,
291 void *data, u16 len)
292{
293 struct mgmt_pending_cmd *cmd;
294
295 cmd = mgmt_pending_new(sk, opcode, hdev, data, len);
296 if (!cmd)
297 return NULL;
298
Johan Hedberga380b6c2015-03-17 13:48:48 +0200299 list_add(&cmd->list, &hdev->mgmt_pending);
300
301 return cmd;
302}
303
304void mgmt_pending_free(struct mgmt_pending_cmd *cmd)
305{
306 sock_put(cmd->sk);
307 kfree(cmd->param);
308 kfree(cmd);
309}
310
311void mgmt_pending_remove(struct mgmt_pending_cmd *cmd)
312{
313 list_del(&cmd->list);
314 mgmt_pending_free(cmd);
315}