aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2015-03-14 22:27:59 -0400
committerJohan Hedberg <johan.hedberg@intel.com>2015-03-15 03:56:41 -0400
commitc08b1a1dba524c1cdef331c1f169db3a1b37bb4c (patch)
treee4b2abbdb127002e22ae36b1c1a124cfaae7bf5f /net
parent50ebc055fa758c731e6e1ce174608327aab07aec (diff)
Bluetooth: Consolidate socket channel sending function back into one
With the introduction of trusted socket flag for control and monitor channels, it is now possible to use a single function for sending packets to these sockets. And with that consolidate the handling. Signed-off-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Diffstat (limited to 'net')
-rw-r--r--net/bluetooth/hci_sock.c45
-rw-r--r--net/bluetooth/mgmt.c34
2 files changed, 16 insertions, 63 deletions
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index 54118868b3f6..e7f463f6fd69 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -199,7 +199,7 @@ void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb)
199 199
200/* Send frame to sockets with specific channel */ 200/* Send frame to sockets with specific channel */
201void hci_send_to_channel(unsigned short channel, struct sk_buff *skb, 201void hci_send_to_channel(unsigned short channel, struct sk_buff *skb,
202 struct sock *skip_sk) 202 int flag, struct sock *skip_sk)
203{ 203{
204 struct sock *sk; 204 struct sock *sk;
205 205
@@ -210,41 +210,12 @@ void hci_send_to_channel(unsigned short channel, struct sk_buff *skb,
210 sk_for_each(sk, &hci_sk_list.head) { 210 sk_for_each(sk, &hci_sk_list.head) {
211 struct sk_buff *nskb; 211 struct sk_buff *nskb;
212 212
213 /* Skip the original socket */ 213 /* Ignore socket without the flag set */
214 if (sk == skip_sk) 214 if (!test_bit(flag, &hci_pi(sk)->flags))
215 continue;
216
217 if (sk->sk_state != BT_BOUND)
218 continue;
219
220 if (hci_pi(sk)->channel != channel)
221 continue;
222
223 nskb = skb_clone(skb, GFP_ATOMIC);
224 if (!nskb)
225 continue; 215 continue;
226 216
227 if (sock_queue_rcv_skb(sk, nskb)) 217 /* Skip the original socket */
228 kfree_skb(nskb); 218 if (sk == skip_sk)
229 }
230
231 read_unlock(&hci_sk_list.lock);
232}
233
234/* Send frame to sockets with specific channel flag set */
235void hci_send_to_flagged_channel(unsigned short channel, struct sk_buff *skb,
236 int flag)
237{
238 struct sock *sk;
239
240 BT_DBG("channel %u len %d", channel, skb->len);
241
242 read_lock(&hci_sk_list.lock);
243
244 sk_for_each(sk, &hci_sk_list.head) {
245 struct sk_buff *nskb;
246
247 if (!test_bit(flag, &hci_pi(sk)->flags))
248 continue; 219 continue;
249 220
250 if (sk->sk_state != BT_BOUND) 221 if (sk->sk_state != BT_BOUND)
@@ -310,7 +281,8 @@ void hci_send_to_monitor(struct hci_dev *hdev, struct sk_buff *skb)
310 hdr->index = cpu_to_le16(hdev->id); 281 hdr->index = cpu_to_le16(hdev->id);
311 hdr->len = cpu_to_le16(skb->len); 282 hdr->len = cpu_to_le16(skb->len);
312 283
313 hci_send_to_channel(HCI_CHANNEL_MONITOR, skb_copy, NULL); 284 hci_send_to_channel(HCI_CHANNEL_MONITOR, skb_copy,
285 HCI_SOCK_TRUSTED, NULL);
314 kfree_skb(skb_copy); 286 kfree_skb(skb_copy);
315} 287}
316 288
@@ -417,7 +389,8 @@ void hci_sock_dev_event(struct hci_dev *hdev, int event)
417 389
418 skb = create_monitor_event(hdev, event); 390 skb = create_monitor_event(hdev, event);
419 if (skb) { 391 if (skb) {
420 hci_send_to_channel(HCI_CHANNEL_MONITOR, skb, NULL); 392 hci_send_to_channel(HCI_CHANNEL_MONITOR, skb,
393 HCI_SOCK_TRUSTED, NULL);
421 kfree_skb(skb); 394 kfree_skb(skb);
422 } 395 }
423 } 396 }
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index ff636bd9523b..1e5afa76e371 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -224,7 +224,7 @@ static u8 mgmt_status(u8 hci_status)
224 224
225static int mgmt_send_event(u16 event, struct hci_dev *hdev, 225static int mgmt_send_event(u16 event, struct hci_dev *hdev,
226 unsigned short channel, void *data, u16 data_len, 226 unsigned short channel, void *data, u16 data_len,
227 struct sock *skip_sk) 227 int flag, struct sock *skip_sk)
228{ 228{
229 struct sk_buff *skb; 229 struct sk_buff *skb;
230 struct mgmt_hdr *hdr; 230 struct mgmt_hdr *hdr;
@@ -247,44 +247,24 @@ static int mgmt_send_event(u16 event, struct hci_dev *hdev,
247 /* Time stamp */ 247 /* Time stamp */
248 __net_timestamp(skb); 248 __net_timestamp(skb);
249 249
250 hci_send_to_channel(channel, skb, skip_sk); 250 hci_send_to_channel(channel, skb, flag, skip_sk);
251 kfree_skb(skb); 251 kfree_skb(skb);
252 252
253 return 0; 253 return 0;
254} 254}
255 255
256static int mgmt_index_event(u16 event, struct hci_dev *hdev, 256static int mgmt_index_event(u16 event, struct hci_dev *hdev, void *data,
257 void *data, u16 data_len, int flag) 257 u16 len, int flag)
258{ 258{
259 struct sk_buff *skb; 259 return mgmt_send_event(event, hdev, HCI_CHANNEL_CONTROL, data, len,
260 struct mgmt_hdr *hdr; 260 flag, NULL);
261
262 skb = alloc_skb(sizeof(*hdr) + data_len, GFP_KERNEL);
263 if (!skb)
264 return -ENOMEM;
265
266 hdr = (void *) skb_put(skb, sizeof(*hdr));
267 hdr->opcode = cpu_to_le16(event);
268 hdr->index = cpu_to_le16(hdev->id);
269 hdr->len = cpu_to_le16(data_len);
270
271 if (data)
272 memcpy(skb_put(skb, data_len), data, data_len);
273
274 /* Time stamp */
275 __net_timestamp(skb);
276
277 hci_send_to_flagged_channel(HCI_CHANNEL_CONTROL, skb, flag);
278 kfree_skb(skb);
279
280 return 0;
281} 261}
282 262
283static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 len, 263static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 len,
284 struct sock *skip_sk) 264 struct sock *skip_sk)
285{ 265{
286 return mgmt_send_event(event, hdev, HCI_CHANNEL_CONTROL, data, len, 266 return mgmt_send_event(event, hdev, HCI_CHANNEL_CONTROL, data, len,
287 skip_sk); 267 HCI_SOCK_TRUSTED, skip_sk);
288} 268}
289 269
290static int mgmt_cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status) 270static int mgmt_cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)