2 * ng_btsocket_hci_raw.c
6 * Copyright (c) 2001-2002 Maksim Yevmenkin <m_evmenkin@yahoo.com>
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * $Id: ng_btsocket_hci_raw.c,v 1.14 2003/09/14 23:29:06 max Exp $
31 * $FreeBSD: src/sys/netgraph/bluetooth/socket/ng_btsocket_hci_raw.c,v 1.23 2006/11/06 13:42:04 rwatson Exp $
32 * $DragonFly: src/sys/netgraph7/bluetooth/socket/ng_btsocket_hci_raw.c,v 1.2 2008/06/26 23:05:40 dillon Exp $
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/bitstring.h>
38 #include <sys/domain.h>
39 #include <sys/endian.h>
40 #include <sys/errno.h>
41 #include <sys/filedesc.h>
42 #include <sys/ioccom.h>
43 #include <sys/kernel.h>
45 #include <sys/malloc.h>
47 #include <sys/mutex.h>
49 #include <sys/protosw.h>
50 #include <sys/queue.h>
51 #include <sys/socket.h>
52 #include <sys/socketvar.h>
53 #include <sys/sysctl.h>
54 #include <sys/taskqueue.h>
55 #include "ng_message.h"
57 #include "bluetooth/include/ng_bluetooth.h"
58 #include "bluetooth/include/ng_hci.h"
59 #include "bluetooth/include/ng_l2cap.h"
60 #include "bluetooth/include/ng_btsocket.h"
61 #include "bluetooth/include/ng_btsocket_hci_raw.h"
64 #ifdef NG_SEPARATE_MALLOC
65 MALLOC_DEFINE(M_NETGRAPH_BTSOCKET_HCI_RAW
, "netgraph_btsocks_hci_raw",
66 "Netgraph Bluetooth raw HCI sockets");
68 #define M_NETGRAPH_BTSOCKET_HCI_RAW M_NETGRAPH
69 #endif /* NG_SEPARATE_MALLOC */
71 /* Netgraph node methods */
72 static ng_constructor_t ng_btsocket_hci_raw_node_constructor
;
73 static ng_rcvmsg_t ng_btsocket_hci_raw_node_rcvmsg
;
74 static ng_shutdown_t ng_btsocket_hci_raw_node_shutdown
;
75 static ng_newhook_t ng_btsocket_hci_raw_node_newhook
;
76 static ng_connect_t ng_btsocket_hci_raw_node_connect
;
77 static ng_rcvdata_t ng_btsocket_hci_raw_node_rcvdata
;
78 static ng_disconnect_t ng_btsocket_hci_raw_node_disconnect
;
80 static void ng_btsocket_hci_raw_input (void *, int);
81 static void ng_btsocket_hci_raw_output(node_p
, hook_p
, void *, int);
82 static void ng_btsocket_hci_raw_savctl(ng_btsocket_hci_raw_pcb_p
,
85 static int ng_btsocket_hci_raw_filter(ng_btsocket_hci_raw_pcb_p
,
88 #define ng_btsocket_hci_raw_wakeup_input_task() \
89 taskqueue_enqueue(taskqueue_swi, &ng_btsocket_hci_raw_task)
92 struct ng_btsocket_hci_raw_sec_filter
{
93 bitstr_t
bit_decl(events
, 0xff);
94 bitstr_t
bit_decl(commands
[0x3f], 0x3ff);
97 /* Netgraph type descriptor */
98 static struct ng_type typestruct
= {
99 .version
= NG_ABI_VERSION
,
100 .name
= NG_BTSOCKET_HCI_RAW_NODE_TYPE
,
101 .constructor
= ng_btsocket_hci_raw_node_constructor
,
102 .rcvmsg
= ng_btsocket_hci_raw_node_rcvmsg
,
103 .shutdown
= ng_btsocket_hci_raw_node_shutdown
,
104 .newhook
= ng_btsocket_hci_raw_node_newhook
,
105 .connect
= ng_btsocket_hci_raw_node_connect
,
106 .rcvdata
= ng_btsocket_hci_raw_node_rcvdata
,
107 .disconnect
= ng_btsocket_hci_raw_node_disconnect
,
111 extern int ifqmaxlen
;
112 static u_int32_t ng_btsocket_hci_raw_debug_level
;
113 static u_int32_t ng_btsocket_hci_raw_ioctl_timeout
;
114 static node_p ng_btsocket_hci_raw_node
;
115 static struct ng_bt_itemq ng_btsocket_hci_raw_queue
;
116 static struct mtx ng_btsocket_hci_raw_queue_mtx
;
117 static struct task ng_btsocket_hci_raw_task
;
118 static LIST_HEAD(, ng_btsocket_hci_raw_pcb
) ng_btsocket_hci_raw_sockets
;
119 static struct mtx ng_btsocket_hci_raw_sockets_mtx
;
120 static u_int32_t ng_btsocket_hci_raw_token
;
121 static struct mtx ng_btsocket_hci_raw_token_mtx
;
122 static struct ng_btsocket_hci_raw_sec_filter
*ng_btsocket_hci_raw_sec_filter
;
125 SYSCTL_DECL(_net_bluetooth_hci_sockets
);
126 SYSCTL_NODE(_net_bluetooth_hci_sockets
, OID_AUTO
, raw
, CTLFLAG_RW
,
127 0, "Bluetooth raw HCI sockets family");
128 SYSCTL_INT(_net_bluetooth_hci_sockets_raw
, OID_AUTO
, debug_level
, CTLFLAG_RW
,
129 &ng_btsocket_hci_raw_debug_level
, NG_BTSOCKET_WARN_LEVEL
,
130 "Bluetooth raw HCI sockets debug level");
131 SYSCTL_INT(_net_bluetooth_hci_sockets_raw
, OID_AUTO
, ioctl_timeout
, CTLFLAG_RW
,
132 &ng_btsocket_hci_raw_ioctl_timeout
, 5,
133 "Bluetooth raw HCI sockets ioctl timeout");
134 SYSCTL_INT(_net_bluetooth_hci_sockets_raw
, OID_AUTO
, queue_len
, CTLFLAG_RD
,
135 &ng_btsocket_hci_raw_queue
.len
, 0,
136 "Bluetooth raw HCI sockets input queue length");
137 SYSCTL_INT(_net_bluetooth_hci_sockets_raw
, OID_AUTO
, queue_maxlen
, CTLFLAG_RD
,
138 &ng_btsocket_hci_raw_queue
.maxlen
, 0,
139 "Bluetooth raw HCI sockets input queue max. length");
140 SYSCTL_INT(_net_bluetooth_hci_sockets_raw
, OID_AUTO
, queue_drops
, CTLFLAG_RD
,
141 &ng_btsocket_hci_raw_queue
.drops
, 0,
142 "Bluetooth raw HCI sockets input queue drops");
145 #define NG_BTSOCKET_HCI_RAW_INFO \
146 if (ng_btsocket_hci_raw_debug_level >= NG_BTSOCKET_INFO_LEVEL) \
149 #define NG_BTSOCKET_HCI_RAW_WARN \
150 if (ng_btsocket_hci_raw_debug_level >= NG_BTSOCKET_WARN_LEVEL) \
153 #define NG_BTSOCKET_HCI_RAW_ERR \
154 if (ng_btsocket_hci_raw_debug_level >= NG_BTSOCKET_ERR_LEVEL) \
157 #define NG_BTSOCKET_HCI_RAW_ALERT \
158 if (ng_btsocket_hci_raw_debug_level >= NG_BTSOCKET_ALERT_LEVEL) \
161 /****************************************************************************
162 ****************************************************************************
164 ****************************************************************************
165 ****************************************************************************/
168 * Netgraph node constructor. Do not allow to create node of this type.
172 ng_btsocket_hci_raw_node_constructor(node_p node
)
175 } /* ng_btsocket_hci_raw_node_constructor */
178 * Netgraph node destructor. Just let old node go and create new fresh one.
182 ng_btsocket_hci_raw_node_shutdown(node_p node
)
188 error
= ng_make_node_common(&typestruct
, &ng_btsocket_hci_raw_node
);
190 NG_BTSOCKET_HCI_RAW_ALERT(
191 "%s: Could not create Netgraph node, error=%d\n", __func__
, error
);
193 ng_btsocket_hci_raw_node
= NULL
;
198 error
= ng_name_node(ng_btsocket_hci_raw_node
,
199 NG_BTSOCKET_HCI_RAW_NODE_TYPE
);
201 NG_BTSOCKET_HCI_RAW_ALERT(
202 "%s: Could not name Netgraph node, error=%d\n", __func__
, error
);
204 NG_NODE_UNREF(ng_btsocket_hci_raw_node
);
205 ng_btsocket_hci_raw_node
= NULL
;
211 } /* ng_btsocket_hci_raw_node_shutdown */
214 * Create new hook. Just say "yes"
218 ng_btsocket_hci_raw_node_newhook(node_p node
, hook_p hook
, char const *name
)
221 } /* ng_btsocket_hci_raw_node_newhook */
224 * Connect hook. Just say "yes"
228 ng_btsocket_hci_raw_node_connect(hook_p hook
)
231 } /* ng_btsocket_hci_raw_node_connect */
238 ng_btsocket_hci_raw_node_disconnect(hook_p hook
)
241 } /* ng_btsocket_hci_raw_node_disconnect */
244 * Receive control message.
245 * Make sure it is a message from HCI node and it is a response.
246 * Enqueue item and schedule input task.
250 ng_btsocket_hci_raw_node_rcvmsg(node_p node
, item_p item
, hook_p lasthook
)
252 struct ng_mesg
*msg
= NGI_MSG(item
); /* item still has message */
256 * Check for empty sockets list creates LOR when both sender and
257 * receiver device are connected to the same host, so remove it
262 (msg
->header
.typecookie
== NGM_HCI_COOKIE
||
263 msg
->header
.typecookie
== NGM_GENERIC_COOKIE
) &&
264 msg
->header
.flags
& NGF_RESP
) {
265 if (msg
->header
.token
== 0) {
270 mtx_lock(&ng_btsocket_hci_raw_queue_mtx
);
271 if (NG_BT_ITEMQ_FULL(&ng_btsocket_hci_raw_queue
)) {
272 NG_BTSOCKET_HCI_RAW_ERR(
273 "%s: Input queue is full\n", __func__
);
275 NG_BT_ITEMQ_DROP(&ng_btsocket_hci_raw_queue
);
279 NG_BT_ITEMQ_ENQUEUE(&ng_btsocket_hci_raw_queue
, item
);
280 error
= ng_btsocket_hci_raw_wakeup_input_task();
282 mtx_unlock(&ng_btsocket_hci_raw_queue_mtx
);
289 } /* ng_btsocket_hci_raw_node_rcvmsg */
292 * Receive packet from the one of our hook.
293 * Prepend every packet with sockaddr_hci and record sender's node name.
294 * Enqueue item and schedule input task.
298 ng_btsocket_hci_raw_node_rcvdata(hook_p hook
, item_p item
)
300 struct mbuf
*nam
= NULL
;
304 * Check for empty sockets list creates LOR when both sender and
305 * receiver device are connected to the same host, so remove it
309 MGET(nam
, MB_DONTWAIT
, MT_SONAME
);
311 struct sockaddr_hci
*sa
= mtod(nam
, struct sockaddr_hci
*);
313 nam
->m_len
= sizeof(struct sockaddr_hci
);
315 sa
->hci_len
= sizeof(*sa
);
316 sa
->hci_family
= AF_BLUETOOTH
;
317 strlcpy(sa
->hci_node
, NG_PEER_NODE_NAME(hook
),
318 sizeof(sa
->hci_node
));
320 NGI_GET_M(item
, nam
->m_next
);
323 mtx_lock(&ng_btsocket_hci_raw_queue_mtx
);
324 if (NG_BT_ITEMQ_FULL(&ng_btsocket_hci_raw_queue
)) {
325 NG_BTSOCKET_HCI_RAW_ERR(
326 "%s: Input queue is full\n", __func__
);
328 NG_BT_ITEMQ_DROP(&ng_btsocket_hci_raw_queue
);
332 NG_BT_ITEMQ_ENQUEUE(&ng_btsocket_hci_raw_queue
, item
);
333 error
= ng_btsocket_hci_raw_wakeup_input_task();
335 mtx_unlock(&ng_btsocket_hci_raw_queue_mtx
);
337 NG_BTSOCKET_HCI_RAW_ERR(
338 "%s: Failed to allocate address mbuf\n", __func__
);
345 } /* ng_btsocket_hci_raw_node_rcvdata */
347 /****************************************************************************
348 ****************************************************************************
350 ****************************************************************************
351 ****************************************************************************/
354 * Get next token. We need token to avoid theoretical race where process
355 * submits ioctl() message then interrupts ioctl() and re-submits another
356 * ioctl() on the same socket *before* first ioctl() complete.
360 ng_btsocket_hci_raw_get_token(u_int32_t
*token
)
362 mtx_lock(&ng_btsocket_hci_raw_token_mtx
);
364 if (++ ng_btsocket_hci_raw_token
== 0)
365 ng_btsocket_hci_raw_token
= 1;
367 *token
= ng_btsocket_hci_raw_token
;
369 mtx_unlock(&ng_btsocket_hci_raw_token_mtx
);
370 } /* ng_btsocket_hci_raw_get_token */
373 * Send Netgraph message to the node - do not expect reply
377 ng_btsocket_hci_raw_send_ngmsg(char *path
, int cmd
, void *arg
, int arglen
)
379 struct ng_mesg
*msg
= NULL
;
382 NG_MKMESSAGE(msg
, NGM_HCI_COOKIE
, cmd
, arglen
, M_WAITOK
| M_NULLOK
);
386 if (arg
!= NULL
&& arglen
> 0)
387 bcopy(arg
, msg
->data
, arglen
);
389 NG_SEND_MSG_PATH(error
, ng_btsocket_hci_raw_node
, msg
, path
, 0);
392 } /* ng_btsocket_hci_raw_send_ngmsg */
395 * Send Netgraph message to the node (no data) and wait for reply
399 ng_btsocket_hci_raw_send_sync_ngmsg(ng_btsocket_hci_raw_pcb_p pcb
, char *path
,
400 int cmd
, void *rsp
, int rsplen
)
402 struct ng_mesg
*msg
= NULL
;
405 mtx_assert(&pcb
->pcb_mtx
, MA_OWNED
);
407 NG_MKMESSAGE(msg
, NGM_HCI_COOKIE
, cmd
, 0, M_WAITOK
| M_NULLOK
);
411 ng_btsocket_hci_raw_get_token(&msg
->header
.token
);
412 pcb
->token
= msg
->header
.token
;
415 NG_SEND_MSG_PATH(error
, ng_btsocket_hci_raw_node
, msg
, path
, 0);
421 error
= msleep(&pcb
->msg
, &pcb
->pcb_mtx
, PZERO
|PCATCH
, "hcictl",
422 ng_btsocket_hci_raw_ioctl_timeout
* hz
);
428 if (pcb
->msg
!= NULL
&& pcb
->msg
->header
.cmd
== cmd
)
429 bcopy(pcb
->msg
->data
, rsp
, rsplen
);
433 NG_FREE_MSG(pcb
->msg
); /* checks for != NULL */
436 } /* ng_btsocket_hci_raw_send_sync_ngmsg */
439 * Create control information for the packet
443 ng_btsocket_hci_raw_savctl(ng_btsocket_hci_raw_pcb_p pcb
, struct mbuf
**ctl
,
449 mtx_assert(&pcb
->pcb_mtx
, MA_OWNED
);
451 if (pcb
->flags
& NG_BTSOCKET_HCI_RAW_DIRECTION
) {
452 dir
= (m
->m_flags
& M_PROTO1
)? 1 : 0;
453 *ctl
= sbcreatecontrol((caddr_t
) &dir
, sizeof(dir
),
454 SCM_HCI_RAW_DIRECTION
, SOL_HCI_RAW
);
456 ctl
= &((*ctl
)->m_next
);
459 if (pcb
->so
->so_options
& SO_TIMESTAMP
) {
461 *ctl
= sbcreatecontrol((caddr_t
) &tv
, sizeof(tv
),
462 SCM_TIMESTAMP
, SOL_SOCKET
);
464 ctl
= &((*ctl
)->m_next
);
466 } /* ng_btsocket_hci_raw_savctl */
469 * Raw HCI sockets data input routine
473 ng_btsocket_hci_raw_data_input(struct mbuf
*nam
)
475 ng_btsocket_hci_raw_pcb_p pcb
= NULL
;
476 struct mbuf
*m0
= NULL
, *m
= NULL
;
477 struct sockaddr_hci
*sa
= NULL
;
482 KASSERT((nam
->m_type
== MT_SONAME
),
483 ("%s: m_type=%d\n", __func__
, nam
->m_type
));
484 KASSERT((m0
->m_flags
& M_PKTHDR
),
485 ("%s: m_flags=%#x\n", __func__
, m0
->m_flags
));
487 sa
= mtod(nam
, struct sockaddr_hci
*);
489 mtx_lock(&ng_btsocket_hci_raw_sockets_mtx
);
491 LIST_FOREACH(pcb
, &ng_btsocket_hci_raw_sockets
, next
) {
493 mtx_lock(&pcb
->pcb_mtx
);
496 * If socket was bound then check address and
497 * make sure it matches.
500 if (pcb
->addr
.hci_node
[0] != 0 &&
501 strcmp(sa
->hci_node
, pcb
->addr
.hci_node
) != 0)
505 * Check packet against filters
506 * XXX do we have to call m_pullup() here?
509 if (ng_btsocket_hci_raw_filter(pcb
, m0
, 1) != 0)
513 * Make a copy of the packet, append to the socket's
514 * receive queue and wakeup socket. sbappendaddr()
515 * will check if socket has enough buffer space.
518 m
= m_dup(m0
, MB_DONTWAIT
);
520 struct mbuf
*ctl
= NULL
;
522 ng_btsocket_hci_raw_savctl(pcb
, &ctl
, m
);
524 if (sbappendaddr(&pcb
->so
->so_rcv
,
525 (struct sockaddr
*) sa
, m
, ctl
))
528 NG_BTSOCKET_HCI_RAW_INFO(
529 "%s: sbappendaddr() failed\n", __func__
);
536 mtx_unlock(&pcb
->pcb_mtx
);
539 mtx_unlock(&ng_btsocket_hci_raw_sockets_mtx
);
543 } /* ng_btsocket_hci_raw_data_input */
546 * Raw HCI sockets message input routine
550 ng_btsocket_hci_raw_msg_input(struct ng_mesg
*msg
)
552 ng_btsocket_hci_raw_pcb_p pcb
= NULL
;
554 mtx_lock(&ng_btsocket_hci_raw_sockets_mtx
);
556 LIST_FOREACH(pcb
, &ng_btsocket_hci_raw_sockets
, next
) {
557 mtx_lock(&pcb
->pcb_mtx
);
559 if (msg
->header
.token
== pcb
->token
) {
563 mtx_unlock(&pcb
->pcb_mtx
);
564 mtx_unlock(&ng_btsocket_hci_raw_sockets_mtx
);
569 mtx_unlock(&pcb
->pcb_mtx
);
572 mtx_unlock(&ng_btsocket_hci_raw_sockets_mtx
);
574 NG_FREE_MSG(msg
); /* checks for != NULL */
575 } /* ng_btsocket_hci_raw_msg_input */
578 * Raw HCI sockets input routines
582 ng_btsocket_hci_raw_input(void *context
, int pending
)
587 mtx_lock(&ng_btsocket_hci_raw_queue_mtx
);
588 NG_BT_ITEMQ_DEQUEUE(&ng_btsocket_hci_raw_queue
, item
);
589 mtx_unlock(&ng_btsocket_hci_raw_queue_mtx
);
594 switch(item
->el_flags
& NGQF_TYPE
) {
596 struct mbuf
*m
= NULL
;
599 ng_btsocket_hci_raw_data_input(m
);
603 struct ng_mesg
*msg
= NULL
;
605 NGI_GET_MSG(item
, msg
);
606 ng_btsocket_hci_raw_msg_input(msg
);
611 ("%s: invalid item type=%ld\n", __func__
, (item
->el_flags
& NGQF_TYPE
)));
617 } /* ng_btsocket_hci_raw_input */
620 * Raw HCI sockets output routine
624 ng_btsocket_hci_raw_output(node_p node
, hook_p hook
, void *arg1
, int arg2
)
626 struct mbuf
*nam
= (struct mbuf
*) arg1
, *m
= NULL
;
627 struct sockaddr_hci
*sa
= NULL
;
633 KASSERT((nam
->m_type
== MT_SONAME
),
634 ("%s: m_type=%d\n", __func__
, nam
->m_type
));
635 KASSERT((m
->m_flags
& M_PKTHDR
),
636 ("%s: m_flags=%#x\n", __func__
, m
->m_flags
));
638 sa
= mtod(nam
, struct sockaddr_hci
*);
641 * Find downstream hook
642 * XXX For now access node hook list directly. Should be safe because
643 * we used ng_send_fn() and we should have exclusive lock on the node.
646 LIST_FOREACH(hook
, &node
->nd_hooks
, hk_hooks
) {
647 if (hook
== NULL
|| NG_HOOK_NOT_VALID(hook
) ||
648 NG_NODE_NOT_VALID(NG_PEER_NODE(hook
)))
651 if (strcmp(sa
->hci_node
, NG_PEER_NODE_NAME(hook
)) == 0) {
652 NG_SEND_DATA_ONLY(error
, hook
, m
); /* sets m to NULL */
657 NG_FREE_M(nam
); /* check for != NULL */
659 } /* ng_btsocket_hci_raw_output */
662 * Check frame against security and socket filters.
663 * d (direction bit) == 1 means incoming frame.
667 ng_btsocket_hci_raw_filter(ng_btsocket_hci_raw_pcb_p pcb
, struct mbuf
*m
, int d
)
669 int type
, event
, opcode
;
671 mtx_assert(&pcb
->pcb_mtx
, MA_OWNED
);
673 switch ((type
= *mtod(m
, u_int8_t
*))) {
675 if (!(pcb
->flags
& NG_BTSOCKET_HCI_RAW_PRIVILEGED
)) {
676 opcode
= le16toh(mtod(m
, ng_hci_cmd_pkt_t
*)->opcode
);
679 ng_btsocket_hci_raw_sec_filter
->commands
[NG_HCI_OGF(opcode
) - 1],
680 NG_HCI_OCF(opcode
) - 1))
684 if (d
&& !bit_test(pcb
->filter
.packet_mask
, NG_HCI_CMD_PKT
- 1))
688 case NG_HCI_ACL_DATA_PKT
:
689 case NG_HCI_SCO_DATA_PKT
:
690 if (!(pcb
->flags
& NG_BTSOCKET_HCI_RAW_PRIVILEGED
) ||
691 !bit_test(pcb
->filter
.packet_mask
, type
- 1) ||
696 case NG_HCI_EVENT_PKT
:
700 event
= mtod(m
, ng_hci_event_pkt_t
*)->event
- 1;
702 if (!(pcb
->flags
& NG_BTSOCKET_HCI_RAW_PRIVILEGED
))
703 if (!bit_test(ng_btsocket_hci_raw_sec_filter
->events
, event
))
706 if (!bit_test(pcb
->filter
.event_mask
, event
))
715 } /* ng_btsocket_hci_raw_filter */
718 * Initialize everything
722 ng_btsocket_hci_raw_init(void)
727 ng_btsocket_hci_raw_node
= NULL
;
728 ng_btsocket_hci_raw_debug_level
= NG_BTSOCKET_WARN_LEVEL
;
729 ng_btsocket_hci_raw_ioctl_timeout
= 5;
731 /* Register Netgraph node type */
732 error
= ng_newtype(&typestruct
);
734 NG_BTSOCKET_HCI_RAW_ALERT(
735 "%s: Could not register Netgraph node type, error=%d\n", __func__
, error
);
740 /* Create Netgrapg node */
741 error
= ng_make_node_common(&typestruct
, &ng_btsocket_hci_raw_node
);
743 NG_BTSOCKET_HCI_RAW_ALERT(
744 "%s: Could not create Netgraph node, error=%d\n", __func__
, error
);
746 ng_btsocket_hci_raw_node
= NULL
;
751 error
= ng_name_node(ng_btsocket_hci_raw_node
,
752 NG_BTSOCKET_HCI_RAW_NODE_TYPE
);
754 NG_BTSOCKET_HCI_RAW_ALERT(
755 "%s: Could not name Netgraph node, error=%d\n", __func__
, error
);
757 NG_NODE_UNREF(ng_btsocket_hci_raw_node
);
758 ng_btsocket_hci_raw_node
= NULL
;
763 /* Create input queue */
764 NG_BT_ITEMQ_INIT(&ng_btsocket_hci_raw_queue
, ifqmaxlen
);
765 mtx_init(&ng_btsocket_hci_raw_queue_mtx
,
766 "btsocks_hci_raw_queue_mtx", NULL
, MTX_DEF
);
767 TASK_INIT(&ng_btsocket_hci_raw_task
, 0,
768 ng_btsocket_hci_raw_input
, NULL
);
770 /* Create list of sockets */
771 LIST_INIT(&ng_btsocket_hci_raw_sockets
);
772 mtx_init(&ng_btsocket_hci_raw_sockets_mtx
,
773 "btsocks_hci_raw_sockets_mtx", NULL
, MTX_DEF
);
776 ng_btsocket_hci_raw_token
= 0;
777 mtx_init(&ng_btsocket_hci_raw_token_mtx
,
778 "btsocks_hci_raw_token_mtx", NULL
, MTX_DEF
);
785 ng_btsocket_hci_raw_sec_filter
= NULL
;
787 MALLOC(ng_btsocket_hci_raw_sec_filter
,
788 struct ng_btsocket_hci_raw_sec_filter
*,
789 sizeof(struct ng_btsocket_hci_raw_sec_filter
),
790 M_NETGRAPH_BTSOCKET_HCI_RAW
, M_WAITOK
| M_NULLOK
| M_ZERO
);
791 if (ng_btsocket_hci_raw_sec_filter
== NULL
) {
792 printf("%s: Could not allocate security filter!\n", __func__
);
797 * XXX How paranoid can we get?
799 * Initialize security filter. If bit is set in the mask then
800 * unprivileged socket is allowed to send (receive) this command
804 /* Enable all events */
805 memset(&ng_btsocket_hci_raw_sec_filter
->events
, 0xff,
806 sizeof(ng_btsocket_hci_raw_sec_filter
->events
)/
807 sizeof(ng_btsocket_hci_raw_sec_filter
->events
[0]));
809 /* Disable some critical events */
810 f
= ng_btsocket_hci_raw_sec_filter
->events
;
811 bit_clear(f
, NG_HCI_EVENT_RETURN_LINK_KEYS
- 1);
812 bit_clear(f
, NG_HCI_EVENT_LINK_KEY_NOTIFICATION
- 1);
813 bit_clear(f
, NG_HCI_EVENT_VENDOR
- 1);
815 /* Commands - Link control */
816 f
= ng_btsocket_hci_raw_sec_filter
->commands
[NG_HCI_OGF_LINK_CONTROL
-1];
817 bit_set(f
, NG_HCI_OCF_INQUIRY
- 1);
818 bit_set(f
, NG_HCI_OCF_INQUIRY_CANCEL
- 1);
819 bit_set(f
, NG_HCI_OCF_PERIODIC_INQUIRY
- 1);
820 bit_set(f
, NG_HCI_OCF_EXIT_PERIODIC_INQUIRY
- 1);
821 bit_set(f
, NG_HCI_OCF_REMOTE_NAME_REQ
- 1);
822 bit_set(f
, NG_HCI_OCF_READ_REMOTE_FEATURES
- 1);
823 bit_set(f
, NG_HCI_OCF_READ_REMOTE_VER_INFO
- 1);
824 bit_set(f
, NG_HCI_OCF_READ_CLOCK_OFFSET
- 1);
826 /* Commands - Link policy */
827 f
= ng_btsocket_hci_raw_sec_filter
->commands
[NG_HCI_OGF_LINK_POLICY
-1];
828 bit_set(f
, NG_HCI_OCF_ROLE_DISCOVERY
- 1);
829 bit_set(f
, NG_HCI_OCF_READ_LINK_POLICY_SETTINGS
- 1);
831 /* Commands - Host controller and baseband */
832 f
= ng_btsocket_hci_raw_sec_filter
->commands
[NG_HCI_OGF_HC_BASEBAND
-1];
833 bit_set(f
, NG_HCI_OCF_READ_PIN_TYPE
- 1);
834 bit_set(f
, NG_HCI_OCF_READ_LOCAL_NAME
- 1);
835 bit_set(f
, NG_HCI_OCF_READ_CON_ACCEPT_TIMO
- 1);
836 bit_set(f
, NG_HCI_OCF_READ_PAGE_TIMO
- 1);
837 bit_set(f
, NG_HCI_OCF_READ_SCAN_ENABLE
- 1);
838 bit_set(f
, NG_HCI_OCF_READ_PAGE_SCAN_ACTIVITY
- 1);
839 bit_set(f
, NG_HCI_OCF_READ_INQUIRY_SCAN_ACTIVITY
- 1);
840 bit_set(f
, NG_HCI_OCF_READ_AUTH_ENABLE
- 1);
841 bit_set(f
, NG_HCI_OCF_READ_ENCRYPTION_MODE
- 1);
842 bit_set(f
, NG_HCI_OCF_READ_UNIT_CLASS
- 1);
843 bit_set(f
, NG_HCI_OCF_READ_VOICE_SETTINGS
- 1);
844 bit_set(f
, NG_HCI_OCF_READ_AUTO_FLUSH_TIMO
- 1);
845 bit_set(f
, NG_HCI_OCF_READ_NUM_BROADCAST_RETRANS
- 1);
846 bit_set(f
, NG_HCI_OCF_READ_HOLD_MODE_ACTIVITY
- 1);
847 bit_set(f
, NG_HCI_OCF_READ_XMIT_LEVEL
- 1);
848 bit_set(f
, NG_HCI_OCF_READ_SCO_FLOW_CONTROL
- 1);
849 bit_set(f
, NG_HCI_OCF_READ_LINK_SUPERVISION_TIMO
- 1);
850 bit_set(f
, NG_HCI_OCF_READ_SUPPORTED_IAC_NUM
- 1);
851 bit_set(f
, NG_HCI_OCF_READ_IAC_LAP
- 1);
852 bit_set(f
, NG_HCI_OCF_READ_PAGE_SCAN_PERIOD
- 1);
853 bit_set(f
, NG_HCI_OCF_READ_PAGE_SCAN
- 1);
855 /* Commands - Informational */
856 f
= ng_btsocket_hci_raw_sec_filter
->commands
[NG_HCI_OGF_INFO
- 1];
857 bit_set(f
, NG_HCI_OCF_READ_LOCAL_VER
- 1);
858 bit_set(f
, NG_HCI_OCF_READ_LOCAL_FEATURES
- 1);
859 bit_set(f
, NG_HCI_OCF_READ_BUFFER_SIZE
- 1);
860 bit_set(f
, NG_HCI_OCF_READ_COUNTRY_CODE
- 1);
861 bit_set(f
, NG_HCI_OCF_READ_BDADDR
- 1);
863 /* Commands - Status */
864 f
= ng_btsocket_hci_raw_sec_filter
->commands
[NG_HCI_OGF_STATUS
- 1];
865 bit_set(f
, NG_HCI_OCF_READ_FAILED_CONTACT_CNTR
- 1);
866 bit_set(f
, NG_HCI_OCF_GET_LINK_QUALITY
- 1);
867 bit_set(f
, NG_HCI_OCF_READ_RSSI
- 1);
869 /* Commands - Testing */
870 f
= ng_btsocket_hci_raw_sec_filter
->commands
[NG_HCI_OGF_TESTING
- 1];
871 bit_set(f
, NG_HCI_OCF_READ_LOOPBACK_MODE
- 1);
872 } /* ng_btsocket_hci_raw_init */
875 * Abort connection on socket
879 ng_btsocket_hci_raw_abort(struct socket
*so
)
881 } /* ng_btsocket_hci_raw_abort */
884 ng_btsocket_hci_raw_close(struct socket
*so
)
886 } /* ng_btsocket_hci_raw_close */
889 * Create new raw HCI socket
893 ng_btsocket_hci_raw_attach(struct socket
*so
, int proto
, struct thread
*td
)
895 ng_btsocket_hci_raw_pcb_p pcb
= so2hci_raw_pcb(so
);
901 if (ng_btsocket_hci_raw_node
== NULL
)
902 return (EPROTONOSUPPORT
);
903 if (proto
!= BLUETOOTH_PROTO_HCI
)
904 return (EPROTONOSUPPORT
);
905 if (so
->so_type
!= SOCK_RAW
)
906 return (ESOCKTNOSUPPORT
);
908 error
= soreserve(so
, NG_BTSOCKET_HCI_RAW_SENDSPACE
,
909 NG_BTSOCKET_HCI_RAW_RECVSPACE
);
913 MALLOC(pcb
, ng_btsocket_hci_raw_pcb_p
, sizeof(*pcb
),
914 M_NETGRAPH_BTSOCKET_HCI_RAW
, M_WAITOK
| M_NULLOK
| M_ZERO
);
918 so
->so_pcb
= (caddr_t
) pcb
;
921 if (priv_check(td
, PRIV_NETBLUETOOTH_RAW
) == 0)
922 pcb
->flags
|= NG_BTSOCKET_HCI_RAW_PRIVILEGED
;
925 * Set default socket filter. By default socket only accepts HCI
926 * Command_Complete and Command_Status event packets.
929 bit_set(pcb
->filter
.event_mask
, NG_HCI_EVENT_COMMAND_COMPL
- 1);
930 bit_set(pcb
->filter
.event_mask
, NG_HCI_EVENT_COMMAND_STATUS
- 1);
932 mtx_init(&pcb
->pcb_mtx
, "btsocks_hci_raw_pcb_mtx", NULL
, MTX_DEF
);
934 mtx_lock(&ng_btsocket_hci_raw_sockets_mtx
);
935 LIST_INSERT_HEAD(&ng_btsocket_hci_raw_sockets
, pcb
, next
);
936 mtx_unlock(&ng_btsocket_hci_raw_sockets_mtx
);
939 } /* ng_btsocket_hci_raw_attach */
942 * Bind raw HCI socket
946 ng_btsocket_hci_raw_bind(struct socket
*so
, struct sockaddr
*nam
,
949 ng_btsocket_hci_raw_pcb_p pcb
= so2hci_raw_pcb(so
);
950 struct sockaddr_hci
*sa
= (struct sockaddr_hci
*) nam
;
954 if (ng_btsocket_hci_raw_node
== NULL
)
959 if (sa
->hci_family
!= AF_BLUETOOTH
)
960 return (EAFNOSUPPORT
);
961 if (sa
->hci_len
!= sizeof(*sa
))
963 if (sa
->hci_node
[0] == 0)
966 mtx_lock(&pcb
->pcb_mtx
);
967 bcopy(sa
, &pcb
->addr
, sizeof(pcb
->addr
));
968 mtx_unlock(&pcb
->pcb_mtx
);
971 } /* ng_btsocket_hci_raw_bind */
974 * Connect raw HCI socket
978 ng_btsocket_hci_raw_connect(struct socket
*so
, struct sockaddr
*nam
,
981 ng_btsocket_hci_raw_pcb_p pcb
= so2hci_raw_pcb(so
);
982 struct sockaddr_hci
*sa
= (struct sockaddr_hci
*) nam
;
986 if (ng_btsocket_hci_raw_node
== NULL
)
991 if (sa
->hci_family
!= AF_BLUETOOTH
)
992 return (EAFNOSUPPORT
);
993 if (sa
->hci_len
!= sizeof(*sa
))
995 if (sa
->hci_node
[0] == 0)
996 return (EDESTADDRREQ
);
998 mtx_lock(&pcb
->pcb_mtx
);
1000 if (bcmp(sa
, &pcb
->addr
, sizeof(pcb
->addr
)) != 0) {
1001 mtx_unlock(&pcb
->pcb_mtx
);
1002 return (EADDRNOTAVAIL
);
1007 mtx_unlock(&pcb
->pcb_mtx
);
1010 } /* ng_btsocket_hci_raw_connect */
1013 * Process ioctl on socket
1017 ng_btsocket_hci_raw_control(struct socket
*so
, u_long cmd
, caddr_t data
,
1018 struct ifnet
*ifp
, struct thread
*td
)
1020 ng_btsocket_hci_raw_pcb_p pcb
= so2hci_raw_pcb(so
);
1021 char path
[NG_NODESIZ
+ 1];
1022 struct ng_mesg
*msg
= NULL
;
1027 if (ng_btsocket_hci_raw_node
== NULL
)
1030 mtx_lock(&pcb
->pcb_mtx
);
1032 /* Check if we have device name */
1033 if (pcb
->addr
.hci_node
[0] == 0) {
1034 mtx_unlock(&pcb
->pcb_mtx
);
1035 return (EHOSTUNREACH
);
1038 /* Check if we have pending ioctl() */
1039 if (pcb
->token
!= 0) {
1040 mtx_unlock(&pcb
->pcb_mtx
);
1044 snprintf(path
, sizeof(path
), "%s:", pcb
->addr
.hci_node
);
1047 case SIOC_HCI_RAW_NODE_GET_STATE
: {
1048 struct ng_btsocket_hci_raw_node_state
*p
=
1049 (struct ng_btsocket_hci_raw_node_state
*) data
;
1051 error
= ng_btsocket_hci_raw_send_sync_ngmsg(pcb
, path
,
1052 NGM_HCI_NODE_GET_STATE
,
1053 &p
->state
, sizeof(p
->state
));
1056 case SIOC_HCI_RAW_NODE_INIT
:
1057 if (pcb
->flags
& NG_BTSOCKET_HCI_RAW_PRIVILEGED
)
1058 error
= ng_btsocket_hci_raw_send_ngmsg(path
,
1059 NGM_HCI_NODE_INIT
, NULL
, 0);
1064 case SIOC_HCI_RAW_NODE_GET_DEBUG
: {
1065 struct ng_btsocket_hci_raw_node_debug
*p
=
1066 (struct ng_btsocket_hci_raw_node_debug
*) data
;
1068 error
= ng_btsocket_hci_raw_send_sync_ngmsg(pcb
, path
,
1069 NGM_HCI_NODE_GET_DEBUG
,
1070 &p
->debug
, sizeof(p
->debug
));
1073 case SIOC_HCI_RAW_NODE_SET_DEBUG
: {
1074 struct ng_btsocket_hci_raw_node_debug
*p
=
1075 (struct ng_btsocket_hci_raw_node_debug
*) data
;
1077 if (pcb
->flags
& NG_BTSOCKET_HCI_RAW_PRIVILEGED
)
1078 error
= ng_btsocket_hci_raw_send_ngmsg(path
,
1079 NGM_HCI_NODE_SET_DEBUG
, &p
->debug
,
1085 case SIOC_HCI_RAW_NODE_GET_BUFFER
: {
1086 struct ng_btsocket_hci_raw_node_buffer
*p
=
1087 (struct ng_btsocket_hci_raw_node_buffer
*) data
;
1089 error
= ng_btsocket_hci_raw_send_sync_ngmsg(pcb
, path
,
1090 NGM_HCI_NODE_GET_BUFFER
,
1091 &p
->buffer
, sizeof(p
->buffer
));
1094 case SIOC_HCI_RAW_NODE_GET_BDADDR
: {
1095 struct ng_btsocket_hci_raw_node_bdaddr
*p
=
1096 (struct ng_btsocket_hci_raw_node_bdaddr
*) data
;
1098 error
= ng_btsocket_hci_raw_send_sync_ngmsg(pcb
, path
,
1099 NGM_HCI_NODE_GET_BDADDR
,
1100 &p
->bdaddr
, sizeof(p
->bdaddr
));
1103 case SIOC_HCI_RAW_NODE_GET_FEATURES
: {
1104 struct ng_btsocket_hci_raw_node_features
*p
=
1105 (struct ng_btsocket_hci_raw_node_features
*) data
;
1107 error
= ng_btsocket_hci_raw_send_sync_ngmsg(pcb
, path
,
1108 NGM_HCI_NODE_GET_FEATURES
,
1109 &p
->features
, sizeof(p
->features
));
1112 case SIOC_HCI_RAW_NODE_GET_STAT
: {
1113 struct ng_btsocket_hci_raw_node_stat
*p
=
1114 (struct ng_btsocket_hci_raw_node_stat
*) data
;
1116 error
= ng_btsocket_hci_raw_send_sync_ngmsg(pcb
, path
,
1117 NGM_HCI_NODE_GET_STAT
,
1118 &p
->stat
, sizeof(p
->stat
));
1121 case SIOC_HCI_RAW_NODE_RESET_STAT
:
1122 if (pcb
->flags
& NG_BTSOCKET_HCI_RAW_PRIVILEGED
)
1123 error
= ng_btsocket_hci_raw_send_ngmsg(path
,
1124 NGM_HCI_NODE_RESET_STAT
, NULL
, 0);
1129 case SIOC_HCI_RAW_NODE_FLUSH_NEIGHBOR_CACHE
:
1130 if (pcb
->flags
& NG_BTSOCKET_HCI_RAW_PRIVILEGED
)
1131 error
= ng_btsocket_hci_raw_send_ngmsg(path
,
1132 NGM_HCI_NODE_FLUSH_NEIGHBOR_CACHE
,
1138 case SIOC_HCI_RAW_NODE_GET_NEIGHBOR_CACHE
: {
1139 struct ng_btsocket_hci_raw_node_neighbor_cache
*p
=
1140 (struct ng_btsocket_hci_raw_node_neighbor_cache
*) data
;
1141 ng_hci_node_get_neighbor_cache_ep
*p1
= NULL
;
1142 ng_hci_node_neighbor_cache_entry_ep
*p2
= NULL
;
1144 if (p
->num_entries
<= 0 ||
1145 p
->num_entries
> NG_HCI_MAX_NEIGHBOR_NUM
||
1146 p
->entries
== NULL
) {
1151 NG_MKMESSAGE(msg
, NGM_HCI_COOKIE
,
1152 NGM_HCI_NODE_GET_NEIGHBOR_CACHE
, 0, M_WAITOK
| M_NULLOK
);
1157 ng_btsocket_hci_raw_get_token(&msg
->header
.token
);
1158 pcb
->token
= msg
->header
.token
;
1161 NG_SEND_MSG_PATH(error
, ng_btsocket_hci_raw_node
, msg
, path
, 0);
1167 error
= msleep(&pcb
->msg
, &pcb
->pcb_mtx
,
1168 PZERO
|PCATCH
, "hcictl",
1169 ng_btsocket_hci_raw_ioctl_timeout
* hz
);
1175 if (pcb
->msg
!= NULL
&&
1176 pcb
->msg
->header
.cmd
== NGM_HCI_NODE_GET_NEIGHBOR_CACHE
) {
1177 /* Return data back to user space */
1178 p1
= (ng_hci_node_get_neighbor_cache_ep
*)
1180 p2
= (ng_hci_node_neighbor_cache_entry_ep
*)
1183 p
->num_entries
= min(p
->num_entries
, p1
->num_entries
);
1184 if (p
->num_entries
> 0)
1185 error
= copyout((caddr_t
) p2
,
1186 (caddr_t
) p
->entries
,
1187 p
->num_entries
* sizeof(*p2
));
1191 NG_FREE_MSG(pcb
->msg
); /* checks for != NULL */
1194 case SIOC_HCI_RAW_NODE_GET_CON_LIST
: {
1195 struct ng_btsocket_hci_raw_con_list
*p
=
1196 (struct ng_btsocket_hci_raw_con_list
*) data
;
1197 ng_hci_node_con_list_ep
*p1
= NULL
;
1198 ng_hci_node_con_ep
*p2
= NULL
;
1200 if (p
->num_connections
== 0 ||
1201 p
->num_connections
> NG_HCI_MAX_CON_NUM
||
1202 p
->connections
== NULL
) {
1207 NG_MKMESSAGE(msg
, NGM_HCI_COOKIE
, NGM_HCI_NODE_GET_CON_LIST
,
1208 0, M_WAITOK
| M_NULLOK
);
1213 ng_btsocket_hci_raw_get_token(&msg
->header
.token
);
1214 pcb
->token
= msg
->header
.token
;
1217 NG_SEND_MSG_PATH(error
, ng_btsocket_hci_raw_node
, msg
, path
, 0);
1223 error
= msleep(&pcb
->msg
, &pcb
->pcb_mtx
,
1224 PZERO
|PCATCH
, "hcictl",
1225 ng_btsocket_hci_raw_ioctl_timeout
* hz
);
1231 if (pcb
->msg
!= NULL
&&
1232 pcb
->msg
->header
.cmd
== NGM_HCI_NODE_GET_CON_LIST
) {
1233 /* Return data back to user space */
1234 p1
= (ng_hci_node_con_list_ep
*)(pcb
->msg
->data
);
1235 p2
= (ng_hci_node_con_ep
*)(p1
+ 1);
1237 p
->num_connections
= min(p
->num_connections
,
1238 p1
->num_connections
);
1239 if (p
->num_connections
> 0)
1240 error
= copyout((caddr_t
) p2
,
1241 (caddr_t
) p
->connections
,
1242 p
->num_connections
* sizeof(*p2
));
1246 NG_FREE_MSG(pcb
->msg
); /* checks for != NULL */
1249 case SIOC_HCI_RAW_NODE_GET_LINK_POLICY_MASK
: {
1250 struct ng_btsocket_hci_raw_node_link_policy_mask
*p
=
1251 (struct ng_btsocket_hci_raw_node_link_policy_mask
*)
1254 error
= ng_btsocket_hci_raw_send_sync_ngmsg(pcb
, path
,
1255 NGM_HCI_NODE_GET_LINK_POLICY_SETTINGS_MASK
,
1256 &p
->policy_mask
, sizeof(p
->policy_mask
));
1259 case SIOC_HCI_RAW_NODE_SET_LINK_POLICY_MASK
: {
1260 struct ng_btsocket_hci_raw_node_link_policy_mask
*p
=
1261 (struct ng_btsocket_hci_raw_node_link_policy_mask
*)
1264 if (pcb
->flags
& NG_BTSOCKET_HCI_RAW_PRIVILEGED
)
1265 error
= ng_btsocket_hci_raw_send_ngmsg(path
,
1266 NGM_HCI_NODE_SET_LINK_POLICY_SETTINGS_MASK
,
1268 sizeof(p
->policy_mask
));
1273 case SIOC_HCI_RAW_NODE_GET_PACKET_MASK
: {
1274 struct ng_btsocket_hci_raw_node_packet_mask
*p
=
1275 (struct ng_btsocket_hci_raw_node_packet_mask
*) data
;
1277 error
= ng_btsocket_hci_raw_send_sync_ngmsg(pcb
, path
,
1278 NGM_HCI_NODE_GET_PACKET_MASK
,
1279 &p
->packet_mask
, sizeof(p
->packet_mask
));
1282 case SIOC_HCI_RAW_NODE_SET_PACKET_MASK
: {
1283 struct ng_btsocket_hci_raw_node_packet_mask
*p
=
1284 (struct ng_btsocket_hci_raw_node_packet_mask
*) data
;
1286 if (pcb
->flags
& NG_BTSOCKET_HCI_RAW_PRIVILEGED
)
1287 error
= ng_btsocket_hci_raw_send_ngmsg(path
,
1288 NGM_HCI_NODE_SET_PACKET_MASK
,
1290 sizeof(p
->packet_mask
));
1295 case SIOC_HCI_RAW_NODE_GET_ROLE_SWITCH
: {
1296 struct ng_btsocket_hci_raw_node_role_switch
*p
=
1297 (struct ng_btsocket_hci_raw_node_role_switch
*) data
;
1299 error
= ng_btsocket_hci_raw_send_sync_ngmsg(pcb
, path
,
1300 NGM_HCI_NODE_GET_ROLE_SWITCH
,
1301 &p
->role_switch
, sizeof(p
->role_switch
));
1304 case SIOC_HCI_RAW_NODE_SET_ROLE_SWITCH
: {
1305 struct ng_btsocket_hci_raw_node_role_switch
*p
=
1306 (struct ng_btsocket_hci_raw_node_role_switch
*) data
;
1308 if (pcb
->flags
& NG_BTSOCKET_HCI_RAW_PRIVILEGED
)
1309 error
= ng_btsocket_hci_raw_send_ngmsg(path
,
1310 NGM_HCI_NODE_SET_ROLE_SWITCH
,
1312 sizeof(p
->role_switch
));
1317 case SIOC_HCI_RAW_NODE_LIST_NAMES
: {
1318 struct ng_btsocket_hci_raw_node_list_names
*nl
=
1319 (struct ng_btsocket_hci_raw_node_list_names
*) data
;
1320 struct nodeinfo
*ni
= nl
->names
;
1322 if (nl
->num_names
== 0) {
1327 NG_MKMESSAGE(msg
, NGM_GENERIC_COOKIE
, NGM_LISTNAMES
,
1328 0, M_WAITOK
| M_NULLOK
);
1333 ng_btsocket_hci_raw_get_token(&msg
->header
.token
);
1334 pcb
->token
= msg
->header
.token
;
1337 NG_SEND_MSG_PATH(error
, ng_btsocket_hci_raw_node
, msg
, ".:", 0);
1343 error
= msleep(&pcb
->msg
, &pcb
->pcb_mtx
,
1344 PZERO
|PCATCH
, "hcictl",
1345 ng_btsocket_hci_raw_ioctl_timeout
* hz
);
1351 if (pcb
->msg
!= NULL
&& pcb
->msg
->header
.cmd
== NGM_LISTNAMES
) {
1352 /* Return data back to user space */
1353 struct namelist
*nl1
= (struct namelist
*) pcb
->msg
->data
;
1354 struct nodeinfo
*ni1
= &nl1
->nodeinfo
[0];
1356 while (nl
->num_names
> 0 && nl1
->numnames
> 0) {
1357 if (strcmp(ni1
->type
, NG_HCI_NODE_TYPE
) == 0) {
1358 error
= copyout((caddr_t
) ni1
,
1372 nl
->num_names
= ni
- nl
->names
;
1376 NG_FREE_MSG(pcb
->msg
); /* checks for != NULL */
1384 mtx_unlock(&pcb
->pcb_mtx
);
1387 } /* ng_btsocket_hci_raw_control */
1390 * Process getsockopt/setsockopt system calls
1394 ng_btsocket_hci_raw_ctloutput(struct socket
*so
, struct sockopt
*sopt
)
1396 ng_btsocket_hci_raw_pcb_p pcb
= so2hci_raw_pcb(so
);
1397 struct ng_btsocket_hci_raw_filter filter
;
1402 if (ng_btsocket_hci_raw_node
== NULL
)
1405 if (sopt
->sopt_level
!= SOL_HCI_RAW
)
1408 mtx_lock(&pcb
->pcb_mtx
);
1410 switch (sopt
->sopt_dir
) {
1412 switch (sopt
->sopt_name
) {
1413 case SO_HCI_RAW_FILTER
:
1414 error
= sooptcopyout(sopt
, &pcb
->filter
,
1415 sizeof(pcb
->filter
));
1418 case SO_HCI_RAW_DIRECTION
:
1419 dir
= (pcb
->flags
& NG_BTSOCKET_HCI_RAW_DIRECTION
)?1:0;
1420 error
= sooptcopyout(sopt
, &dir
, sizeof(dir
));
1430 switch (sopt
->sopt_name
) {
1431 case SO_HCI_RAW_FILTER
:
1432 error
= sooptcopyin(sopt
, &filter
, sizeof(filter
),
1435 bcopy(&filter
, &pcb
->filter
,
1436 sizeof(pcb
->filter
));
1439 case SO_HCI_RAW_DIRECTION
:
1440 error
= sooptcopyin(sopt
, &dir
, sizeof(dir
),
1446 pcb
->flags
|= NG_BTSOCKET_HCI_RAW_DIRECTION
;
1448 pcb
->flags
&= ~NG_BTSOCKET_HCI_RAW_DIRECTION
;
1462 mtx_unlock(&pcb
->pcb_mtx
);
1465 } /* ng_btsocket_hci_raw_ctloutput */
1468 * Detach raw HCI socket
1472 ng_btsocket_hci_raw_detach(struct socket
*so
)
1474 ng_btsocket_hci_raw_pcb_p pcb
= so2hci_raw_pcb(so
);
1476 KASSERT(pcb
!= NULL
, ("ng_btsocket_hci_raw_detach: pcb == NULL"));
1478 if (ng_btsocket_hci_raw_node
== NULL
)
1481 mtx_lock(&ng_btsocket_hci_raw_sockets_mtx
);
1482 mtx_lock(&pcb
->pcb_mtx
);
1484 LIST_REMOVE(pcb
, next
);
1486 mtx_unlock(&pcb
->pcb_mtx
);
1487 mtx_unlock(&ng_btsocket_hci_raw_sockets_mtx
);
1489 mtx_destroy(&pcb
->pcb_mtx
);
1491 bzero(pcb
, sizeof(*pcb
));
1492 FREE(pcb
, M_NETGRAPH_BTSOCKET_HCI_RAW
);
1495 } /* ng_btsocket_hci_raw_detach */
1498 * Disconnect raw HCI socket
1502 ng_btsocket_hci_raw_disconnect(struct socket
*so
)
1504 ng_btsocket_hci_raw_pcb_p pcb
= so2hci_raw_pcb(so
);
1508 if (ng_btsocket_hci_raw_node
== NULL
)
1511 mtx_lock(&pcb
->pcb_mtx
);
1512 soisdisconnected(so
);
1513 mtx_unlock(&pcb
->pcb_mtx
);
1516 } /* ng_btsocket_hci_raw_disconnect */
1519 * Get socket peer's address
1523 ng_btsocket_hci_raw_peeraddr(struct socket
*so
, struct sockaddr
**nam
)
1525 return (ng_btsocket_hci_raw_sockaddr(so
, nam
));
1526 } /* ng_btsocket_hci_raw_peeraddr */
1533 ng_btsocket_hci_raw_send(struct socket
*so
, int flags
, struct mbuf
*m
,
1534 struct sockaddr
*sa
, struct mbuf
*control
, struct thread
*td
)
1536 ng_btsocket_hci_raw_pcb_p pcb
= so2hci_raw_pcb(so
);
1537 struct mbuf
*nam
= NULL
;
1540 if (ng_btsocket_hci_raw_node
== NULL
) {
1548 if (control
!= NULL
) {
1553 if (m
->m_pkthdr
.len
< sizeof(ng_hci_cmd_pkt_t
) ||
1554 m
->m_pkthdr
.len
> sizeof(ng_hci_cmd_pkt_t
) + NG_HCI_CMD_PKT_SIZE
) {
1559 if (m
->m_len
< sizeof(ng_hci_cmd_pkt_t
)) {
1560 if ((m
= m_pullup(m
, sizeof(ng_hci_cmd_pkt_t
))) == NULL
) {
1565 if (*mtod(m
, u_int8_t
*) != NG_HCI_CMD_PKT
) {
1570 mtx_lock(&pcb
->pcb_mtx
);
1572 error
= ng_btsocket_hci_raw_filter(pcb
, m
, 0);
1574 mtx_unlock(&pcb
->pcb_mtx
);
1579 if (pcb
->addr
.hci_node
[0] == 0) {
1580 mtx_unlock(&pcb
->pcb_mtx
);
1581 error
= EDESTADDRREQ
;
1585 sa
= (struct sockaddr
*) &pcb
->addr
;
1588 MGET(nam
, MB_DONTWAIT
, MT_SONAME
);
1590 mtx_unlock(&pcb
->pcb_mtx
);
1595 nam
->m_len
= sizeof(struct sockaddr_hci
);
1596 bcopy(sa
,mtod(nam
, struct sockaddr_hci
*),sizeof(struct sockaddr_hci
));
1601 mtx_unlock(&pcb
->pcb_mtx
);
1603 return (ng_send_fn(ng_btsocket_hci_raw_node
, NULL
,
1604 ng_btsocket_hci_raw_output
, nam
, 0));
1606 NG_FREE_M(control
); /* NG_FREE_M checks for != NULL */
1611 } /* ng_btsocket_hci_raw_send */
1614 * Get socket address
1618 ng_btsocket_hci_raw_sockaddr(struct socket
*so
, struct sockaddr
**nam
)
1620 ng_btsocket_hci_raw_pcb_p pcb
= so2hci_raw_pcb(so
);
1621 struct sockaddr_hci sa
;
1625 if (ng_btsocket_hci_raw_node
== NULL
)
1628 bzero(&sa
, sizeof(sa
));
1629 sa
.hci_len
= sizeof(sa
);
1630 sa
.hci_family
= AF_BLUETOOTH
;
1632 mtx_lock(&pcb
->pcb_mtx
);
1633 strlcpy(sa
.hci_node
, pcb
->addr
.hci_node
, sizeof(sa
.hci_node
));
1634 mtx_unlock(&pcb
->pcb_mtx
);
1636 *nam
= sodupsockaddr((struct sockaddr
*) &sa
, M_WAITOK
| M_NULLOK
);
1638 return ((*nam
== NULL
)? ENOMEM
: 0);
1639 } /* ng_btsocket_hci_raw_sockaddr */