OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [net/] [bluetooth/] [hci_sock.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
   BlueZ - Bluetooth protocol stack for Linux
3
   Copyright (C) 2000-2001 Qualcomm Incorporated
4
 
5
   Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
6
 
7
   This program is free software; you can redistribute it and/or modify
8
   it under the terms of the GNU General Public License version 2 as
9
   published by the Free Software Foundation;
10
 
11
   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
12
   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
14
   IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
15
   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
16
   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17
   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18
   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
 
20
   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
21
   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
22
   SOFTWARE IS DISCLAIMED.
23
*/
24
 
25
/*
26
 * BlueZ HCI socket layer.
27
 *
28
 * $Id: hci_sock.c,v 1.1.1.1 2004-04-15 01:17:06 phoenix Exp $
29
 */
30
 
31
#include <linux/config.h>
32
#include <linux/module.h>
33
 
34
#include <linux/types.h>
35
#include <linux/errno.h>
36
#include <linux/kernel.h>
37
#include <linux/major.h>
38
#include <linux/sched.h>
39
#include <linux/slab.h>
40
#include <linux/poll.h>
41
#include <linux/fcntl.h>
42
#include <linux/init.h>
43
#include <linux/skbuff.h>
44
#include <linux/tqueue.h>
45
#include <linux/interrupt.h>
46
#include <linux/socket.h>
47
#include <linux/ioctl.h>
48
#include <net/sock.h>
49
 
50
#include <asm/system.h>
51
#include <asm/uaccess.h>
52
#include <asm/unaligned.h>
53
 
54
#include <net/bluetooth/bluetooth.h>
55
#include <net/bluetooth/hci_core.h>
56
 
57
#ifndef HCI_SOCK_DEBUG
58
#undef  BT_DBG
59
#define BT_DBG( A... )
60
#endif
61
 
62
/* ----- HCI socket interface ----- */
63
 
64
/* Security filter */
65
static struct hci_sec_filter hci_sec_filter = {
66
        /* Packet types */
67
        0x10,
68
        /* Events */
69
        { 0x1000d9fe, 0x0000300c },
70
        /* Commands */
71
        {
72
                { 0x0 },
73
                /* OGF_LINK_CTL */
74
                { 0xbe000006, 0x00000001, 0x0000, 0x00 },
75
                /* OGF_LINK_POLICY */
76
                { 0x00005200, 0x00000000, 0x0000, 0x00 },
77
                /* OGF_HOST_CTL */
78
                { 0xaab00200, 0x2b402aaa, 0x0154, 0x00 },
79
                /* OGF_INFO_PARAM */
80
                { 0x000002be, 0x00000000, 0x0000, 0x00 },
81
                /* OGF_STATUS_PARAM */
82
                { 0x000000ea, 0x00000000, 0x0000, 0x00 }
83
        }
84
};
85
 
86
static struct bluez_sock_list hci_sk_list = {
87
        lock: RW_LOCK_UNLOCKED
88
};
89
 
90
/* Send frame to RAW socket */
91
void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb)
92
{
93
        struct sock * sk;
94
 
95
        BT_DBG("hdev %p len %d", hdev, skb->len);
96
 
97
        read_lock(&hci_sk_list.lock);
98
        for (sk = hci_sk_list.head; sk; sk = sk->next) {
99
                struct hci_filter *flt;
100
                struct sk_buff *nskb;
101
 
102
                if (sk->state != BT_BOUND || hci_pi(sk)->hdev != hdev)
103
                        continue;
104
 
105
                /* Don't send frame to the socket it came from */
106
                if (skb->sk == sk)
107
                        continue;
108
 
109
                /* Apply filter */
110
                flt = &hci_pi(sk)->filter;
111
 
112
                if (!hci_test_bit((skb->pkt_type & HCI_FLT_TYPE_BITS), &flt->type_mask))
113
                        continue;
114
 
115
                if (skb->pkt_type == HCI_EVENT_PKT) {
116
                        register int evt = (*(__u8 *)skb->data & HCI_FLT_EVENT_BITS);
117
 
118
                        if (!hci_test_bit(evt, &flt->event_mask))
119
                                continue;
120
 
121
                        if (flt->opcode && ((evt == EVT_CMD_COMPLETE &&
122
                                        flt->opcode != *(__u16 *)(skb->data + 3)) ||
123
                                        (evt == EVT_CMD_STATUS &&
124
                                        flt->opcode != *(__u16 *)(skb->data + 4))))
125
                                continue;
126
                }
127
 
128
                if (!(nskb = skb_clone(skb, GFP_ATOMIC)))
129
                        continue;
130
 
131
                /* Put type byte before the data */
132
                memcpy(skb_push(nskb, 1), &nskb->pkt_type, 1);
133
 
134
                if (sock_queue_rcv_skb(sk, nskb))
135
                        kfree_skb(nskb);
136
        }
137
        read_unlock(&hci_sk_list.lock);
138
}
139
 
140
static int hci_sock_release(struct socket *sock)
141
{
142
        struct sock *sk = sock->sk;
143
        struct hci_dev *hdev = hci_pi(sk)->hdev;
144
 
145
        BT_DBG("sock %p sk %p", sock, sk);
146
 
147
        if (!sk)
148
                return 0;
149
 
150
        bluez_sock_unlink(&hci_sk_list, sk);
151
 
152
        if (hdev) {
153
                atomic_dec(&hdev->promisc);
154
                hci_dev_put(hdev);
155
        }
156
 
157
        sock_orphan(sk);
158
 
159
        skb_queue_purge(&sk->receive_queue);
160
        skb_queue_purge(&sk->write_queue);
161
 
162
        sock_put(sk);
163
 
164
        MOD_DEC_USE_COUNT;
165
        return 0;
166
}
167
 
168
/* Ioctls that require bound socket */
169
static inline int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, unsigned long arg)
170
{
171
        struct hci_dev *hdev = hci_pi(sk)->hdev;
172
 
173
        if (!hdev)
174
                return -EBADFD;
175
 
176
        switch (cmd) {
177
        case HCISETRAW:
178
                if (!capable(CAP_NET_ADMIN))
179
                        return -EACCES;
180
 
181
                if (arg)
182
                        set_bit(HCI_RAW, &hdev->flags);
183
                else
184
                        clear_bit(HCI_RAW, &hdev->flags);
185
 
186
                return 0;
187
 
188
        case HCIGETCONNINFO:
189
                return hci_get_conn_info(hdev, arg);
190
 
191
        default:
192
                if (hdev->ioctl)
193
                        return hdev->ioctl(hdev, cmd, arg);
194
                return -EINVAL;
195
        }
196
}
197
 
198
static int hci_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
199
{
200
        struct sock *sk = sock->sk;
201
        int err;
202
 
203
        BT_DBG("cmd %x arg %lx", cmd, arg);
204
 
205
        switch (cmd) {
206
        case HCIGETDEVLIST:
207
                return hci_get_dev_list(arg);
208
 
209
        case HCIGETDEVINFO:
210
                return hci_get_dev_info(arg);
211
 
212
        case HCIGETCONNLIST:
213
                return hci_get_conn_list(arg);
214
 
215
        case HCIDEVUP:
216
                if (!capable(CAP_NET_ADMIN))
217
                        return -EACCES;
218
                return hci_dev_open(arg);
219
 
220
        case HCIDEVDOWN:
221
                if (!capable(CAP_NET_ADMIN))
222
                        return -EACCES;
223
                return hci_dev_close(arg);
224
 
225
        case HCIDEVRESET:
226
                if (!capable(CAP_NET_ADMIN))
227
                        return -EACCES;
228
                return hci_dev_reset(arg);
229
 
230
        case HCIDEVRESTAT:
231
                if (!capable(CAP_NET_ADMIN))
232
                        return -EACCES;
233
                return hci_dev_reset_stat(arg);
234
 
235
        case HCISETSCAN:
236
        case HCISETAUTH:
237
        case HCISETENCRYPT:
238
        case HCISETPTYPE:
239
        case HCISETLINKPOL:
240
        case HCISETLINKMODE:
241
        case HCISETACLMTU:
242
        case HCISETSCOMTU:
243
                if (!capable(CAP_NET_ADMIN))
244
                        return -EACCES;
245
                return hci_dev_cmd(cmd, arg);
246
 
247
        case HCIINQUIRY:
248
                return hci_inquiry(arg);
249
 
250
        default:
251
                lock_sock(sk);
252
                err = hci_sock_bound_ioctl(sk, cmd, arg);
253
                release_sock(sk);
254
                return err;
255
        };
256
}
257
 
258
static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
259
{
260
        struct sockaddr_hci *haddr = (struct sockaddr_hci *) addr;
261
        struct sock *sk = sock->sk;
262
        struct hci_dev *hdev = NULL;
263
        int err = 0;
264
 
265
        BT_DBG("sock %p sk %p", sock, sk);
266
 
267
        if (!haddr || haddr->hci_family != AF_BLUETOOTH)
268
                return -EINVAL;
269
 
270
        lock_sock(sk);
271
 
272
        if (hci_pi(sk)->hdev) {
273
                err = -EALREADY;
274
                goto done;
275
        }
276
 
277
        if (haddr->hci_dev != HCI_DEV_NONE) {
278
                if (!(hdev = hci_dev_get(haddr->hci_dev))) {
279
                        err = -ENODEV;
280
                        goto done;
281
                }
282
 
283
                atomic_inc(&hdev->promisc);
284
        }
285
 
286
        hci_pi(sk)->hdev = hdev;
287
        sk->state = BT_BOUND;
288
 
289
done:
290
        release_sock(sk);
291
        return err;
292
}
293
 
294
static int hci_sock_getname(struct socket *sock, struct sockaddr *addr, int *addr_len, int peer)
295
{
296
        struct sockaddr_hci *haddr = (struct sockaddr_hci *) addr;
297
        struct sock *sk = sock->sk;
298
 
299
        BT_DBG("sock %p sk %p", sock, sk);
300
 
301
        lock_sock(sk);
302
 
303
        *addr_len = sizeof(*haddr);
304
        haddr->hci_family = AF_BLUETOOTH;
305
        haddr->hci_dev    = hci_pi(sk)->hdev->id;
306
 
307
        release_sock(sk);
308
        return 0;
309
}
310
 
311
static inline void hci_sock_cmsg(struct sock *sk, struct msghdr *msg, struct sk_buff *skb)
312
{
313
        __u32 mask = hci_pi(sk)->cmsg_mask;
314
 
315
        if (mask & HCI_CMSG_DIR)
316
                put_cmsg(msg, SOL_HCI, HCI_CMSG_DIR, sizeof(int), &bluez_cb(skb)->incomming);
317
 
318
        if (mask & HCI_CMSG_TSTAMP)
319
                put_cmsg(msg, SOL_HCI, HCI_CMSG_TSTAMP, sizeof(skb->stamp), &skb->stamp);
320
}
321
 
322
static int hci_sock_recvmsg(struct socket *sock, struct msghdr *msg, int len, int flags, struct scm_cookie *scm)
323
{
324
        int noblock = flags & MSG_DONTWAIT;
325
        struct sock *sk = sock->sk;
326
        struct sk_buff *skb;
327
        int copied, err;
328
 
329
        BT_DBG("sock %p, sk %p", sock, sk);
330
 
331
        if (flags & (MSG_OOB))
332
                return -EOPNOTSUPP;
333
 
334
        if (sk->state == BT_CLOSED)
335
                return 0;
336
 
337
        if (!(skb = skb_recv_datagram(sk, flags, noblock, &err)))
338
                return err;
339
 
340
        msg->msg_namelen = 0;
341
 
342
        copied = skb->len;
343
        if (len < copied) {
344
                msg->msg_flags |= MSG_TRUNC;
345
                copied = len;
346
        }
347
 
348
        skb->h.raw = skb->data;
349
        err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
350
 
351
        hci_sock_cmsg(sk, msg, skb);
352
 
353
        skb_free_datagram(sk, skb);
354
 
355
        return err ? : copied;
356
}
357
 
358
static int hci_sock_sendmsg(struct socket *sock, struct msghdr *msg, int len,
359
                            struct scm_cookie *scm)
360
{
361
        struct sock *sk = sock->sk;
362
        struct hci_dev *hdev;
363
        struct sk_buff *skb;
364
        int err;
365
 
366
        BT_DBG("sock %p sk %p", sock, sk);
367
 
368
        if (msg->msg_flags & MSG_OOB)
369
                return -EOPNOTSUPP;
370
 
371
        if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_NOSIGNAL|MSG_ERRQUEUE))
372
                return -EINVAL;
373
 
374
        if (len < 4)
375
                return -EINVAL;
376
 
377
        lock_sock(sk);
378
 
379
        if (!(hdev = hci_pi(sk)->hdev)) {
380
                err = -EBADFD;
381
                goto done;
382
        }
383
 
384
        if (!(skb = bluez_skb_send_alloc(sk, len, msg->msg_flags & MSG_DONTWAIT, &err)))
385
                goto done;
386
 
387
        if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) {
388
                err = -EFAULT;
389
                goto drop;
390
        }
391
 
392
        skb->pkt_type = *((unsigned char *) skb->data);
393
        skb_pull(skb, 1);
394
        skb->dev = (void *) hdev;
395
 
396
        if (skb->pkt_type == HCI_COMMAND_PKT) {
397
                u16 opcode = __le16_to_cpu(get_unaligned((u16 *)skb->data));
398
                u16 ogf = cmd_opcode_ogf(opcode);
399
                u16 ocf = cmd_opcode_ocf(opcode);
400
 
401
                if (((ogf > HCI_SFLT_MAX_OGF) ||
402
                                !hci_test_bit(ocf & HCI_FLT_OCF_BITS, &hci_sec_filter.ocf_mask[ogf])) &&
403
                                        !capable(CAP_NET_RAW)) {
404
                        err = -EPERM;
405
                        goto drop;
406
                }
407
 
408
                if (test_bit(HCI_RAW, &hdev->flags) || (ogf == OGF_VENDOR_CMD)) {
409
                        skb_queue_tail(&hdev->raw_q, skb);
410
                        hci_sched_tx(hdev);
411
                } else {
412
                        skb_queue_tail(&hdev->cmd_q, skb);
413
                        hci_sched_cmd(hdev);
414
                }
415
        } else {
416
                if (!capable(CAP_NET_RAW)) {
417
                        err = -EPERM;
418
                        goto drop;
419
                }
420
 
421
                skb_queue_tail(&hdev->raw_q, skb);
422
                hci_sched_tx(hdev);
423
        }
424
 
425
        err = len;
426
 
427
done:
428
        release_sock(sk);
429
        return err;
430
 
431
drop:
432
        kfree_skb(skb);
433
        goto done;
434
}
435
 
436
int hci_sock_setsockopt(struct socket *sock, int level, int optname, char *optval, int len)
437
{
438
        struct sock *sk = sock->sk;
439
        struct hci_filter flt = { opcode: 0 };
440
        int err = 0, opt = 0;
441
 
442
        BT_DBG("sk %p, opt %d", sk, optname);
443
 
444
        lock_sock(sk);
445
 
446
        switch (optname) {
447
        case HCI_DATA_DIR:
448
                if (get_user(opt, (int *)optval)) {
449
                        err = -EFAULT;
450
                        break;
451
                }
452
 
453
                if (opt)
454
                        hci_pi(sk)->cmsg_mask |= HCI_CMSG_DIR;
455
                else
456
                        hci_pi(sk)->cmsg_mask &= ~HCI_CMSG_DIR;
457
                break;
458
 
459
        case HCI_TIME_STAMP:
460
                if (get_user(opt, (int *)optval)) {
461
                        err = -EFAULT;
462
                        break;
463
                }
464
 
465
                if (opt)
466
                        hci_pi(sk)->cmsg_mask |= HCI_CMSG_TSTAMP;
467
                else
468
                        hci_pi(sk)->cmsg_mask &= ~HCI_CMSG_TSTAMP;
469
                break;
470
 
471
        case HCI_FILTER:
472
                len = MIN(len, sizeof(struct hci_filter));
473
                if (copy_from_user(&flt, optval, len)) {
474
                        err = -EFAULT;
475
                        break;
476
                }
477
 
478
                if (!capable(CAP_NET_RAW)) {
479
                        flt.type_mask     &= hci_sec_filter.type_mask;
480
                        flt.event_mask[0] &= hci_sec_filter.event_mask[0];
481
                        flt.event_mask[1] &= hci_sec_filter.event_mask[1];
482
                }
483
 
484
                memcpy(&hci_pi(sk)->filter, &flt, len);
485
                break;
486
 
487
        default:
488
                err = -ENOPROTOOPT;
489
                break;
490
        };
491
 
492
        release_sock(sk);
493
        return err;
494
}
495
 
496
int hci_sock_getsockopt(struct socket *sock, int level, int optname, char *optval, int *optlen)
497
{
498
        struct sock *sk = sock->sk;
499
        int len, opt;
500
 
501
        if (get_user(len, optlen))
502
                return -EFAULT;
503
 
504
        switch (optname) {
505
        case HCI_DATA_DIR:
506
                if (hci_pi(sk)->cmsg_mask & HCI_CMSG_DIR)
507
                        opt = 1;
508
                else
509
                        opt = 0;
510
 
511
                if (put_user(opt, optval))
512
                        return -EFAULT;
513
                break;
514
 
515
        case HCI_TIME_STAMP:
516
                if (hci_pi(sk)->cmsg_mask & HCI_CMSG_TSTAMP)
517
                        opt = 1;
518
                else
519
                        opt = 0;
520
 
521
                if (put_user(opt, optval))
522
                        return -EFAULT;
523
                break;
524
 
525
        case HCI_FILTER:
526
                len = MIN(len, sizeof(struct hci_filter));
527
                if (copy_to_user(optval, &hci_pi(sk)->filter, len))
528
                        return -EFAULT;
529
                break;
530
 
531
        default:
532
                return -ENOPROTOOPT;
533
                break;
534
        };
535
 
536
        return 0;
537
}
538
 
539
struct proto_ops hci_sock_ops = {
540
        family:         PF_BLUETOOTH,
541
        release:        hci_sock_release,
542
        bind:           hci_sock_bind,
543
        getname:        hci_sock_getname,
544
        sendmsg:        hci_sock_sendmsg,
545
        recvmsg:        hci_sock_recvmsg,
546
        ioctl:          hci_sock_ioctl,
547
        poll:           datagram_poll,
548
        listen:         sock_no_listen,
549
        shutdown:       sock_no_shutdown,
550
        setsockopt:     hci_sock_setsockopt,
551
        getsockopt:     hci_sock_getsockopt,
552
        connect:        sock_no_connect,
553
        socketpair:     sock_no_socketpair,
554
        accept:         sock_no_accept,
555
        mmap:           sock_no_mmap
556
};
557
 
558
static int hci_sock_create(struct socket *sock, int protocol)
559
{
560
        struct sock *sk;
561
 
562
        BT_DBG("sock %p", sock);
563
 
564
        if (sock->type != SOCK_RAW)
565
                return -ESOCKTNOSUPPORT;
566
 
567
        sock->ops = &hci_sock_ops;
568
 
569
        if (!(sk = sk_alloc(PF_BLUETOOTH, GFP_KERNEL, 1)))
570
                return -ENOMEM;
571
 
572
        sock->state = SS_UNCONNECTED;
573
        sock_init_data(sock, sk);
574
 
575
        memset(&sk->protinfo, 0, sizeof(struct hci_pinfo));
576
        sk->destruct = NULL;
577
        sk->protocol = protocol;
578
        sk->state    = BT_OPEN;
579
 
580
        bluez_sock_link(&hci_sk_list, sk);
581
 
582
        MOD_INC_USE_COUNT;
583
        return 0;
584
}
585
 
586
static int hci_sock_dev_event(struct notifier_block *this, unsigned long event, void *ptr)
587
{
588
        struct hci_dev *hdev = (struct hci_dev *) ptr;
589
        evt_si_device sd;
590
 
591
        BT_DBG("hdev %s event %ld", hdev->name, event);
592
 
593
        /* Send event to sockets */
594
        sd.event  = event;
595
        sd.dev_id = hdev->id;
596
        hci_si_event(NULL, EVT_SI_DEVICE, EVT_SI_DEVICE_SIZE, &sd);
597
 
598
        if (event == HCI_DEV_UNREG) {
599
                struct sock *sk;
600
 
601
                /* Detach sockets from device */
602
                read_lock(&hci_sk_list.lock);
603
                for (sk = hci_sk_list.head; sk; sk = sk->next) {
604
                        bh_lock_sock(sk);
605
                        if (hci_pi(sk)->hdev == hdev) {
606
                                hci_pi(sk)->hdev = NULL;
607
                                sk->err = EPIPE;
608
                                sk->state = BT_OPEN;
609
                                sk->state_change(sk);
610
 
611
                                hci_dev_put(hdev);
612
                        }
613
                        bh_unlock_sock(sk);
614
                }
615
                read_unlock(&hci_sk_list.lock);
616
        }
617
 
618
        return NOTIFY_DONE;
619
}
620
 
621
struct net_proto_family hci_sock_family_ops = {
622
        family: PF_BLUETOOTH,
623
        create: hci_sock_create
624
};
625
 
626
struct notifier_block hci_sock_nblock = {
627
        notifier_call: hci_sock_dev_event
628
};
629
 
630
int hci_sock_init(void)
631
{
632
        if (bluez_sock_register(BTPROTO_HCI, &hci_sock_family_ops)) {
633
                BT_ERR("Can't register HCI socket");
634
                return -EPROTO;
635
        }
636
 
637
        hci_register_notifier(&hci_sock_nblock);
638
        return 0;
639
}
640
 
641
int hci_sock_cleanup(void)
642
{
643
        if (bluez_sock_unregister(BTPROTO_HCI))
644
                BT_ERR("Can't unregister HCI socket");
645
 
646
        hci_unregister_notifier(&hci_sock_nblock);
647
        return 0;
648
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.