1b06ebda0SMatthew Dillon /*
2b06ebda0SMatthew Dillon * ng_btsocket.c
3b06ebda0SMatthew Dillon */
4b06ebda0SMatthew Dillon
5b06ebda0SMatthew Dillon /*-
6b06ebda0SMatthew Dillon * Copyright (c) 2001-2002 Maksim Yevmenkin <m_evmenkin@yahoo.com>
7b06ebda0SMatthew Dillon * All rights reserved.
8b06ebda0SMatthew Dillon *
9b06ebda0SMatthew Dillon * Redistribution and use in source and binary forms, with or without
10b06ebda0SMatthew Dillon * modification, are permitted provided that the following conditions
11b06ebda0SMatthew Dillon * are met:
12b06ebda0SMatthew Dillon * 1. Redistributions of source code must retain the above copyright
13b06ebda0SMatthew Dillon * notice, this list of conditions and the following disclaimer.
14b06ebda0SMatthew Dillon * 2. Redistributions in binary form must reproduce the above copyright
15b06ebda0SMatthew Dillon * notice, this list of conditions and the following disclaimer in the
16b06ebda0SMatthew Dillon * documentation and/or other materials provided with the distribution.
17b06ebda0SMatthew Dillon *
18b06ebda0SMatthew Dillon * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19b06ebda0SMatthew Dillon * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20b06ebda0SMatthew Dillon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21b06ebda0SMatthew Dillon * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22b06ebda0SMatthew Dillon * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23b06ebda0SMatthew Dillon * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24b06ebda0SMatthew Dillon * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25b06ebda0SMatthew Dillon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26b06ebda0SMatthew Dillon * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27b06ebda0SMatthew Dillon * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28b06ebda0SMatthew Dillon * SUCH DAMAGE.
29b06ebda0SMatthew Dillon *
30b06ebda0SMatthew Dillon * $Id: ng_btsocket.c,v 1.4 2003/09/14 23:29:06 max Exp $
31b06ebda0SMatthew Dillon * $FreeBSD: src/sys/netgraph/bluetooth/socket/ng_btsocket.c,v 1.13 2006/07/21 17:11:13 rwatson Exp $
32b06ebda0SMatthew Dillon */
33b06ebda0SMatthew Dillon
34b06ebda0SMatthew Dillon #include <sys/param.h>
35b06ebda0SMatthew Dillon #include <sys/systm.h>
36*84bfc1a1SSascha Wildner #include <sys/bitstring.h>
37b06ebda0SMatthew Dillon #include <sys/errno.h>
38b06ebda0SMatthew Dillon #include <sys/domain.h>
39b06ebda0SMatthew Dillon #include <sys/kernel.h>
40b06ebda0SMatthew Dillon #include <sys/lock.h>
41b06ebda0SMatthew Dillon #include <sys/mbuf.h>
42b06ebda0SMatthew Dillon #include <sys/protosw.h>
43b06ebda0SMatthew Dillon #include <sys/socket.h>
44b06ebda0SMatthew Dillon #include <sys/socketvar.h>
45b06ebda0SMatthew Dillon #include <sys/sysctl.h>
46b06ebda0SMatthew Dillon #include <sys/taskqueue.h>
47e85b99abSSascha Wildner #include <netgraph7/ng_message.h>
48e85b99abSSascha Wildner #include <netgraph7/netgraph.h>
49e85b99abSSascha Wildner #include <netgraph7/bluetooth/include/ng_bluetooth.h>
50e85b99abSSascha Wildner #include <netgraph7/bluetooth/include/ng_hci.h>
51e85b99abSSascha Wildner #include <netgraph7/bluetooth/include/ng_l2cap.h>
52e85b99abSSascha Wildner #include <netgraph7/bluetooth/include/ng_btsocket.h>
53e85b99abSSascha Wildner #include <netgraph7/bluetooth/include/ng_btsocket_hci_raw.h>
54e85b99abSSascha Wildner #include <netgraph7/bluetooth/include/ng_btsocket_l2cap.h>
55e85b99abSSascha Wildner #include <netgraph7/bluetooth/include/ng_btsocket_rfcomm.h>
56b06ebda0SMatthew Dillon
57b06ebda0SMatthew Dillon static int ng_btsocket_modevent (module_t, int, void *);
58b06ebda0SMatthew Dillon extern struct domain ng_btsocket_domain;
59b06ebda0SMatthew Dillon
60b06ebda0SMatthew Dillon /*
61b06ebda0SMatthew Dillon * Bluetooth raw HCI sockets
62b06ebda0SMatthew Dillon */
63b06ebda0SMatthew Dillon
64b06ebda0SMatthew Dillon static struct pr_usrreqs ng_btsocket_hci_raw_usrreqs = {
65b06ebda0SMatthew Dillon .pru_abort = ng_btsocket_hci_raw_abort,
66b06ebda0SMatthew Dillon .pru_attach = ng_btsocket_hci_raw_attach,
67b06ebda0SMatthew Dillon .pru_bind = ng_btsocket_hci_raw_bind,
68b06ebda0SMatthew Dillon .pru_connect = ng_btsocket_hci_raw_connect,
69b06ebda0SMatthew Dillon .pru_control = ng_btsocket_hci_raw_control,
70b06ebda0SMatthew Dillon .pru_detach = ng_btsocket_hci_raw_detach,
71b06ebda0SMatthew Dillon .pru_disconnect = ng_btsocket_hci_raw_disconnect,
72b06ebda0SMatthew Dillon .pru_peeraddr = ng_btsocket_hci_raw_peeraddr,
73b06ebda0SMatthew Dillon .pru_send = ng_btsocket_hci_raw_send,
74b06ebda0SMatthew Dillon .pru_shutdown = NULL,
75b06ebda0SMatthew Dillon .pru_sockaddr = ng_btsocket_hci_raw_sockaddr,
76e85b99abSSascha Wildner #if 0 /* XXX */
77b06ebda0SMatthew Dillon .pru_close = ng_btsocket_hci_raw_close,
78e85b99abSSascha Wildner #endif
79e85b99abSSascha Wildner .pru_sosend = sosend,
80e85b99abSSascha Wildner .pru_soreceive = soreceive,
81b06ebda0SMatthew Dillon };
82b06ebda0SMatthew Dillon
83b06ebda0SMatthew Dillon /*
84b06ebda0SMatthew Dillon * Bluetooth raw L2CAP sockets
85b06ebda0SMatthew Dillon */
86b06ebda0SMatthew Dillon
87b06ebda0SMatthew Dillon static struct pr_usrreqs ng_btsocket_l2cap_raw_usrreqs = {
88b06ebda0SMatthew Dillon .pru_abort = ng_btsocket_l2cap_raw_abort,
89b06ebda0SMatthew Dillon .pru_attach = ng_btsocket_l2cap_raw_attach,
90b06ebda0SMatthew Dillon .pru_bind = ng_btsocket_l2cap_raw_bind,
91b06ebda0SMatthew Dillon .pru_connect = ng_btsocket_l2cap_raw_connect,
92b06ebda0SMatthew Dillon .pru_control = ng_btsocket_l2cap_raw_control,
93b06ebda0SMatthew Dillon .pru_detach = ng_btsocket_l2cap_raw_detach,
94b06ebda0SMatthew Dillon .pru_disconnect = ng_btsocket_l2cap_raw_disconnect,
95b06ebda0SMatthew Dillon .pru_peeraddr = ng_btsocket_l2cap_raw_peeraddr,
96b06ebda0SMatthew Dillon .pru_send = ng_btsocket_l2cap_raw_send,
97b06ebda0SMatthew Dillon .pru_shutdown = NULL,
98b06ebda0SMatthew Dillon .pru_sockaddr = ng_btsocket_l2cap_raw_sockaddr,
99e85b99abSSascha Wildner #if 0 /* XXX */
100b06ebda0SMatthew Dillon .pru_close = ng_btsocket_l2cap_raw_close,
101e85b99abSSascha Wildner #endif
102e85b99abSSascha Wildner .pru_sosend = sosend,
103e85b99abSSascha Wildner .pru_soreceive = soreceive,
104b06ebda0SMatthew Dillon };
105b06ebda0SMatthew Dillon
106b06ebda0SMatthew Dillon /*
107b06ebda0SMatthew Dillon * Bluetooth SEQPACKET L2CAP sockets
108b06ebda0SMatthew Dillon */
109b06ebda0SMatthew Dillon
110b06ebda0SMatthew Dillon static struct pr_usrreqs ng_btsocket_l2cap_usrreqs = {
111b06ebda0SMatthew Dillon .pru_abort = ng_btsocket_l2cap_abort,
112b06ebda0SMatthew Dillon .pru_accept = ng_btsocket_l2cap_accept,
113b06ebda0SMatthew Dillon .pru_attach = ng_btsocket_l2cap_attach,
114b06ebda0SMatthew Dillon .pru_bind = ng_btsocket_l2cap_bind,
115b06ebda0SMatthew Dillon .pru_connect = ng_btsocket_l2cap_connect,
116b06ebda0SMatthew Dillon .pru_control = ng_btsocket_l2cap_control,
117b06ebda0SMatthew Dillon .pru_detach = ng_btsocket_l2cap_detach,
118b06ebda0SMatthew Dillon .pru_disconnect = ng_btsocket_l2cap_disconnect,
119b06ebda0SMatthew Dillon .pru_listen = ng_btsocket_l2cap_listen,
120b06ebda0SMatthew Dillon .pru_peeraddr = ng_btsocket_l2cap_peeraddr,
121b06ebda0SMatthew Dillon .pru_send = ng_btsocket_l2cap_send,
122b06ebda0SMatthew Dillon .pru_shutdown = NULL,
123b06ebda0SMatthew Dillon .pru_sockaddr = ng_btsocket_l2cap_sockaddr,
124e85b99abSSascha Wildner #if 0 /* XXX */
125b06ebda0SMatthew Dillon .pru_close = ng_btsocket_l2cap_close,
126e85b99abSSascha Wildner #endif
127e85b99abSSascha Wildner .pru_sosend = sosend,
128e85b99abSSascha Wildner .pru_soreceive = soreceive,
129b06ebda0SMatthew Dillon };
130b06ebda0SMatthew Dillon
131b06ebda0SMatthew Dillon /*
132b06ebda0SMatthew Dillon * Bluetooth STREAM RFCOMM sockets
133b06ebda0SMatthew Dillon */
134b06ebda0SMatthew Dillon
135b06ebda0SMatthew Dillon static struct pr_usrreqs ng_btsocket_rfcomm_usrreqs = {
136b06ebda0SMatthew Dillon .pru_abort = ng_btsocket_rfcomm_abort,
137b06ebda0SMatthew Dillon .pru_accept = ng_btsocket_rfcomm_accept,
138b06ebda0SMatthew Dillon .pru_attach = ng_btsocket_rfcomm_attach,
139b06ebda0SMatthew Dillon .pru_bind = ng_btsocket_rfcomm_bind,
140b06ebda0SMatthew Dillon .pru_connect = ng_btsocket_rfcomm_connect,
141b06ebda0SMatthew Dillon .pru_control = ng_btsocket_rfcomm_control,
142b06ebda0SMatthew Dillon .pru_detach = ng_btsocket_rfcomm_detach,
143b06ebda0SMatthew Dillon .pru_disconnect = ng_btsocket_rfcomm_disconnect,
144b06ebda0SMatthew Dillon .pru_listen = ng_btsocket_rfcomm_listen,
145b06ebda0SMatthew Dillon .pru_peeraddr = ng_btsocket_rfcomm_peeraddr,
146b06ebda0SMatthew Dillon .pru_send = ng_btsocket_rfcomm_send,
147b06ebda0SMatthew Dillon .pru_shutdown = NULL,
148b06ebda0SMatthew Dillon .pru_sockaddr = ng_btsocket_rfcomm_sockaddr,
149e85b99abSSascha Wildner #if 0 /* XXX */
150b06ebda0SMatthew Dillon .pru_close = ng_btsocket_rfcomm_close,
151e85b99abSSascha Wildner #endif
152e85b99abSSascha Wildner .pru_sosend = sosend,
153e85b99abSSascha Wildner .pru_soreceive = soreceive,
154b06ebda0SMatthew Dillon };
155b06ebda0SMatthew Dillon
156b06ebda0SMatthew Dillon /*
157b06ebda0SMatthew Dillon * Definitions of protocols supported in the BLUETOOTH domain
158b06ebda0SMatthew Dillon */
159b06ebda0SMatthew Dillon
160b06ebda0SMatthew Dillon static struct protosw ng_btsocket_protosw[] = {
161b06ebda0SMatthew Dillon {
162b06ebda0SMatthew Dillon .pr_type = SOCK_RAW,
163b06ebda0SMatthew Dillon .pr_domain = &ng_btsocket_domain,
164b06ebda0SMatthew Dillon .pr_protocol = BLUETOOTH_PROTO_HCI,
165b06ebda0SMatthew Dillon .pr_flags = PR_ATOMIC|PR_ADDR,
166b06ebda0SMatthew Dillon .pr_ctloutput = ng_btsocket_hci_raw_ctloutput,
167b06ebda0SMatthew Dillon .pr_init = ng_btsocket_hci_raw_init,
168b06ebda0SMatthew Dillon .pr_usrreqs = &ng_btsocket_hci_raw_usrreqs,
169b06ebda0SMatthew Dillon },
170b06ebda0SMatthew Dillon {
171b06ebda0SMatthew Dillon .pr_type = SOCK_RAW,
172b06ebda0SMatthew Dillon .pr_domain = &ng_btsocket_domain,
173b06ebda0SMatthew Dillon .pr_protocol = BLUETOOTH_PROTO_L2CAP,
174b06ebda0SMatthew Dillon .pr_flags = PR_ATOMIC|PR_ADDR,
175b06ebda0SMatthew Dillon .pr_init = ng_btsocket_l2cap_raw_init,
176b06ebda0SMatthew Dillon .pr_usrreqs = &ng_btsocket_l2cap_raw_usrreqs,
177b06ebda0SMatthew Dillon },
178b06ebda0SMatthew Dillon {
179b06ebda0SMatthew Dillon .pr_type = SOCK_SEQPACKET,
180b06ebda0SMatthew Dillon .pr_domain = &ng_btsocket_domain,
181b06ebda0SMatthew Dillon .pr_protocol = BLUETOOTH_PROTO_L2CAP,
182b06ebda0SMatthew Dillon .pr_flags = PR_ATOMIC|PR_CONNREQUIRED,
183b06ebda0SMatthew Dillon .pr_ctloutput = ng_btsocket_l2cap_ctloutput,
184b06ebda0SMatthew Dillon .pr_init = ng_btsocket_l2cap_init,
185b06ebda0SMatthew Dillon .pr_usrreqs = &ng_btsocket_l2cap_usrreqs,
186b06ebda0SMatthew Dillon },
187b06ebda0SMatthew Dillon {
188b06ebda0SMatthew Dillon .pr_type = SOCK_STREAM,
189b06ebda0SMatthew Dillon .pr_domain = &ng_btsocket_domain,
190b06ebda0SMatthew Dillon .pr_protocol = BLUETOOTH_PROTO_RFCOMM,
191b06ebda0SMatthew Dillon .pr_flags = PR_CONNREQUIRED,
192b06ebda0SMatthew Dillon .pr_ctloutput = ng_btsocket_rfcomm_ctloutput,
193b06ebda0SMatthew Dillon .pr_init = ng_btsocket_rfcomm_init,
194b06ebda0SMatthew Dillon .pr_usrreqs = &ng_btsocket_rfcomm_usrreqs,
195b06ebda0SMatthew Dillon }
196b06ebda0SMatthew Dillon };
197c157ff7aSSascha Wildner #define ng_btsocket_protosw_size NELEM(ng_btsocket_protosw)
198b06ebda0SMatthew Dillon #define ng_btsocket_protosw_end \
199b06ebda0SMatthew Dillon &ng_btsocket_protosw[ng_btsocket_protosw_size]
200b06ebda0SMatthew Dillon
201b06ebda0SMatthew Dillon /*
202b06ebda0SMatthew Dillon * BLUETOOTH domain
203b06ebda0SMatthew Dillon */
204b06ebda0SMatthew Dillon
205b06ebda0SMatthew Dillon struct domain ng_btsocket_domain = {
206b06ebda0SMatthew Dillon .dom_family = AF_BLUETOOTH,
207b06ebda0SMatthew Dillon .dom_name = "bluetooth",
208b06ebda0SMatthew Dillon .dom_protosw = ng_btsocket_protosw,
209b06ebda0SMatthew Dillon .dom_protoswNPROTOSW = ng_btsocket_protosw_end
210b06ebda0SMatthew Dillon };
211b06ebda0SMatthew Dillon
212b06ebda0SMatthew Dillon /*
213b06ebda0SMatthew Dillon * Socket sysctl tree
214b06ebda0SMatthew Dillon */
215b06ebda0SMatthew Dillon
216b06ebda0SMatthew Dillon SYSCTL_NODE(_net_bluetooth_hci, OID_AUTO, sockets, CTLFLAG_RW,
217b06ebda0SMatthew Dillon 0, "Bluetooth HCI sockets family");
218b06ebda0SMatthew Dillon SYSCTL_NODE(_net_bluetooth_l2cap, OID_AUTO, sockets, CTLFLAG_RW,
219b06ebda0SMatthew Dillon 0, "Bluetooth L2CAP sockets family");
220b06ebda0SMatthew Dillon SYSCTL_NODE(_net_bluetooth_rfcomm, OID_AUTO, sockets, CTLFLAG_RW,
221b06ebda0SMatthew Dillon 0, "Bluetooth RFCOMM sockets family");
222b06ebda0SMatthew Dillon
223b06ebda0SMatthew Dillon /*
224b06ebda0SMatthew Dillon * Module
225b06ebda0SMatthew Dillon */
226b06ebda0SMatthew Dillon
227b06ebda0SMatthew Dillon static moduledata_t ng_btsocket_mod = {
228b06ebda0SMatthew Dillon "ng_btsocket",
229b06ebda0SMatthew Dillon ng_btsocket_modevent,
230b06ebda0SMatthew Dillon NULL
231b06ebda0SMatthew Dillon };
232b06ebda0SMatthew Dillon
233b06ebda0SMatthew Dillon DECLARE_MODULE(ng_btsocket, ng_btsocket_mod, SI_SUB_PROTO_DOMAIN,
234b06ebda0SMatthew Dillon SI_ORDER_ANY);
235b06ebda0SMatthew Dillon MODULE_VERSION(ng_btsocket, NG_BLUETOOTH_VERSION);
236b06ebda0SMatthew Dillon MODULE_DEPEND(ng_btsocket, ng_bluetooth, NG_BLUETOOTH_VERSION,
237b06ebda0SMatthew Dillon NG_BLUETOOTH_VERSION, NG_BLUETOOTH_VERSION);
238b06ebda0SMatthew Dillon MODULE_DEPEND(ng_btsocket, netgraph, NG_ABI_VERSION,
239b06ebda0SMatthew Dillon NG_ABI_VERSION, NG_ABI_VERSION);
240b06ebda0SMatthew Dillon
241b06ebda0SMatthew Dillon /*
242b06ebda0SMatthew Dillon * Handle loading and unloading for this node type.
243b06ebda0SMatthew Dillon * This is to handle auxiliary linkages (e.g protocol domain addition).
244b06ebda0SMatthew Dillon */
245b06ebda0SMatthew Dillon
246b06ebda0SMatthew Dillon static int
ng_btsocket_modevent(module_t mod,int event,void * data)247b06ebda0SMatthew Dillon ng_btsocket_modevent(module_t mod, int event, void *data)
248b06ebda0SMatthew Dillon {
249b06ebda0SMatthew Dillon int error = 0;
250b06ebda0SMatthew Dillon
251b06ebda0SMatthew Dillon switch (event) {
252b06ebda0SMatthew Dillon case MOD_LOAD:
253b06ebda0SMatthew Dillon net_add_domain(&ng_btsocket_domain);
254b06ebda0SMatthew Dillon break;
255b06ebda0SMatthew Dillon
256b06ebda0SMatthew Dillon case MOD_UNLOAD:
257b06ebda0SMatthew Dillon /* XXX can't unload protocol domain yet */
258b06ebda0SMatthew Dillon error = EBUSY;
259b06ebda0SMatthew Dillon break;
260b06ebda0SMatthew Dillon
261b06ebda0SMatthew Dillon default:
262b06ebda0SMatthew Dillon error = EOPNOTSUPP;
263b06ebda0SMatthew Dillon break;
264b06ebda0SMatthew Dillon }
265b06ebda0SMatthew Dillon
266b06ebda0SMatthew Dillon return (error);
267b06ebda0SMatthew Dillon } /* ng_btsocket_modevent */
268b06ebda0SMatthew Dillon
269