xref: /freebsd/sys/netgraph/bluetooth/socket/ng_btsocket.c (revision f2bb1cae36283a8eb5a0f19d8612c6abc5148e8f)
1878ed226SJulian Elischer /*
2878ed226SJulian Elischer  * ng_btsocket.c
3878ed226SJulian Elischer  *
4878ed226SJulian Elischer  * Copyright (c) 2001-2002 Maksim Yevmenkin <m_evmenkin@yahoo.com>
5878ed226SJulian Elischer  * All rights reserved.
6878ed226SJulian Elischer  *
7878ed226SJulian Elischer  * Redistribution and use in source and binary forms, with or without
8878ed226SJulian Elischer  * modification, are permitted provided that the following conditions
9878ed226SJulian Elischer  * are met:
10878ed226SJulian Elischer  * 1. Redistributions of source code must retain the above copyright
11878ed226SJulian Elischer  *    notice, this list of conditions and the following disclaimer.
12878ed226SJulian Elischer  * 2. Redistributions in binary form must reproduce the above copyright
13878ed226SJulian Elischer  *    notice, this list of conditions and the following disclaimer in the
14878ed226SJulian Elischer  *    documentation and/or other materials provided with the distribution.
15878ed226SJulian Elischer  *
16878ed226SJulian Elischer  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17878ed226SJulian Elischer  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18878ed226SJulian Elischer  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19878ed226SJulian Elischer  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20878ed226SJulian Elischer  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21878ed226SJulian Elischer  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22878ed226SJulian Elischer  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23878ed226SJulian Elischer  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24878ed226SJulian Elischer  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25878ed226SJulian Elischer  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26878ed226SJulian Elischer  * SUCH DAMAGE.
27878ed226SJulian Elischer  *
28f2bb1caeSJulian Elischer  * $Id: ng_btsocket.c,v 1.3 2003/01/19 00:19:04 max Exp $
29878ed226SJulian Elischer  * $FreeBSD$
30878ed226SJulian Elischer  */
31878ed226SJulian Elischer 
32878ed226SJulian Elischer #include <sys/param.h>
33878ed226SJulian Elischer #include <sys/systm.h>
34878ed226SJulian Elischer #include <sys/errno.h>
35878ed226SJulian Elischer #include <sys/domain.h>
36878ed226SJulian Elischer #include <sys/kernel.h>
37878ed226SJulian Elischer #include <sys/lock.h>
38878ed226SJulian Elischer #include <sys/mutex.h>
39878ed226SJulian Elischer #include <sys/protosw.h>
40878ed226SJulian Elischer #include <sys/socket.h>
41878ed226SJulian Elischer #include <sys/socketvar.h>
42878ed226SJulian Elischer #include <sys/sysctl.h>
43f2bb1caeSJulian Elischer #include <sys/taskqueue.h>
44878ed226SJulian Elischer #include <bitstring.h>
45878ed226SJulian Elischer #include <netgraph/ng_message.h>
46878ed226SJulian Elischer #include <netgraph/netgraph.h>
47878ed226SJulian Elischer #include "ng_bluetooth.h"
48878ed226SJulian Elischer #include "ng_hci.h"
49878ed226SJulian Elischer #include "ng_l2cap.h"
50878ed226SJulian Elischer #include "ng_btsocket.h"
51878ed226SJulian Elischer #include "ng_btsocket_hci_raw.h"
52878ed226SJulian Elischer #include "ng_btsocket_l2cap.h"
53f2bb1caeSJulian Elischer #include "ng_btsocket_rfcomm.h"
54878ed226SJulian Elischer 
55878ed226SJulian Elischer static int			ng_btsocket_modevent (module_t, int, void *);
56878ed226SJulian Elischer extern struct domain		ng_btsocket_domain;
57878ed226SJulian Elischer 
58878ed226SJulian Elischer /*
59878ed226SJulian Elischer  * Bluetooth raw HCI sockets
60878ed226SJulian Elischer  */
61878ed226SJulian Elischer 
62878ed226SJulian Elischer static struct pr_usrreqs	ng_btsocket_hci_raw_usrreqs = {
63878ed226SJulian Elischer 	ng_btsocket_hci_raw_abort,	/* abort */
64878ed226SJulian Elischer 	pru_accept_notsupp,		/* accept */
65878ed226SJulian Elischer 	ng_btsocket_hci_raw_attach,	/* attach */
66878ed226SJulian Elischer 	ng_btsocket_hci_raw_bind,	/* bind */
67878ed226SJulian Elischer 	ng_btsocket_hci_raw_connect,	/* connect */
68878ed226SJulian Elischer 	pru_connect2_notsupp,		/* connect2 */
69878ed226SJulian Elischer 	ng_btsocket_hci_raw_control,	/* control */
70878ed226SJulian Elischer 	ng_btsocket_hci_raw_detach,	/* detach */
71878ed226SJulian Elischer 	ng_btsocket_hci_raw_disconnect,	/* disconnect */
72878ed226SJulian Elischer 	pru_listen_notsupp,		/* listen */
73878ed226SJulian Elischer 	ng_btsocket_hci_raw_peeraddr,	/* peeraddr */
74878ed226SJulian Elischer 	pru_rcvd_notsupp,		/* rcvd */
75878ed226SJulian Elischer 	pru_rcvoob_notsupp,		/* rcvoob */
76878ed226SJulian Elischer 	ng_btsocket_hci_raw_send,	/* send */
77878ed226SJulian Elischer 	pru_sense_null,			/* send */
78878ed226SJulian Elischer 	NULL,				/* shutdown */
79878ed226SJulian Elischer 	ng_btsocket_hci_raw_sockaddr,	/* sockaddr */
80878ed226SJulian Elischer 	sosend,
81878ed226SJulian Elischer 	soreceive,
82878ed226SJulian Elischer 	sopoll
83878ed226SJulian Elischer };
84878ed226SJulian Elischer 
85878ed226SJulian Elischer /*
86878ed226SJulian Elischer  * Bluetooth raw L2CAP sockets
87878ed226SJulian Elischer  */
88878ed226SJulian Elischer 
89878ed226SJulian Elischer static struct pr_usrreqs	ng_btsocket_l2cap_raw_usrreqs = {
90878ed226SJulian Elischer 	ng_btsocket_l2cap_raw_abort,	/* abort */
91878ed226SJulian Elischer 	pru_accept_notsupp,		/* accept */
92878ed226SJulian Elischer 	ng_btsocket_l2cap_raw_attach,	/* attach */
93878ed226SJulian Elischer 	ng_btsocket_l2cap_raw_bind,	/* bind */
94878ed226SJulian Elischer 	ng_btsocket_l2cap_raw_connect,	/* connect */
95878ed226SJulian Elischer 	pru_connect2_notsupp,		/* connect2 */
96878ed226SJulian Elischer 	ng_btsocket_l2cap_raw_control,	/* control */
97878ed226SJulian Elischer 	ng_btsocket_l2cap_raw_detach,	/* detach */
98878ed226SJulian Elischer 	ng_btsocket_l2cap_raw_disconnect, /* disconnect */
99878ed226SJulian Elischer         pru_listen_notsupp,		/* listen */
100878ed226SJulian Elischer 	ng_btsocket_l2cap_raw_peeraddr,	/* peeraddr */
101878ed226SJulian Elischer 	pru_rcvd_notsupp,		/* rcvd */
102878ed226SJulian Elischer 	pru_rcvoob_notsupp,		/* rcvoob */
103878ed226SJulian Elischer 	ng_btsocket_l2cap_raw_send,	/* send */
104878ed226SJulian Elischer 	pru_sense_null,			/* send */
105878ed226SJulian Elischer 	NULL,				/* shutdown */
106878ed226SJulian Elischer 	ng_btsocket_l2cap_raw_sockaddr,	/* sockaddr */
107878ed226SJulian Elischer 	sosend,
108878ed226SJulian Elischer 	soreceive,
109878ed226SJulian Elischer 	sopoll
110878ed226SJulian Elischer };
111878ed226SJulian Elischer 
112878ed226SJulian Elischer /*
113878ed226SJulian Elischer  * Bluetooth SEQPACKET L2CAP sockets
114878ed226SJulian Elischer  */
115878ed226SJulian Elischer 
116878ed226SJulian Elischer static struct pr_usrreqs	ng_btsocket_l2cap_usrreqs = {
117878ed226SJulian Elischer 	ng_btsocket_l2cap_abort,	/* abort */
118878ed226SJulian Elischer 	ng_btsocket_l2cap_accept,	/* accept */
119878ed226SJulian Elischer 	ng_btsocket_l2cap_attach,	/* attach */
120878ed226SJulian Elischer 	ng_btsocket_l2cap_bind,		/* bind */
121878ed226SJulian Elischer 	ng_btsocket_l2cap_connect,	/* connect */
122878ed226SJulian Elischer 	pru_connect2_notsupp,		/* connect2 */
123878ed226SJulian Elischer 	ng_btsocket_l2cap_control,	/* control */
124878ed226SJulian Elischer 	ng_btsocket_l2cap_detach,	/* detach */
125878ed226SJulian Elischer 	ng_btsocket_l2cap_disconnect,	/* disconnect */
126878ed226SJulian Elischer         ng_btsocket_l2cap_listen,	/* listen */
127878ed226SJulian Elischer 	ng_btsocket_l2cap_peeraddr,	/* peeraddr */
128878ed226SJulian Elischer 	pru_rcvd_notsupp,		/* rcvd */
129878ed226SJulian Elischer 	pru_rcvoob_notsupp,		/* rcvoob */
130878ed226SJulian Elischer 	ng_btsocket_l2cap_send,		/* send */
131878ed226SJulian Elischer 	pru_sense_null,			/* send */
132878ed226SJulian Elischer 	NULL,				/* shutdown */
133878ed226SJulian Elischer 	ng_btsocket_l2cap_sockaddr,	/* sockaddr */
134878ed226SJulian Elischer 	sosend,
135878ed226SJulian Elischer 	soreceive,
136878ed226SJulian Elischer 	sopoll
137878ed226SJulian Elischer };
138878ed226SJulian Elischer 
139878ed226SJulian Elischer /*
140f2bb1caeSJulian Elischer  * Bluetooth STREAM RFCOMM sockets
141f2bb1caeSJulian Elischer  */
142f2bb1caeSJulian Elischer 
143f2bb1caeSJulian Elischer static struct pr_usrreqs	ng_btsocket_rfcomm_usrreqs = {
144f2bb1caeSJulian Elischer 	ng_btsocket_rfcomm_abort,	/* abort */
145f2bb1caeSJulian Elischer 	ng_btsocket_rfcomm_accept,	/* accept */
146f2bb1caeSJulian Elischer 	ng_btsocket_rfcomm_attach,	/* attach */
147f2bb1caeSJulian Elischer 	ng_btsocket_rfcomm_bind,	/* bind */
148f2bb1caeSJulian Elischer 	ng_btsocket_rfcomm_connect,	/* connect */
149f2bb1caeSJulian Elischer 	pru_connect2_notsupp,		/* connect2 */
150f2bb1caeSJulian Elischer 	ng_btsocket_rfcomm_control,	/* control */
151f2bb1caeSJulian Elischer 	ng_btsocket_rfcomm_detach,	/* detach */
152f2bb1caeSJulian Elischer 	ng_btsocket_rfcomm_disconnect,	/* disconnect */
153f2bb1caeSJulian Elischer         ng_btsocket_rfcomm_listen,	/* listen */
154f2bb1caeSJulian Elischer 	ng_btsocket_rfcomm_peeraddr,	/* peeraddr */
155f2bb1caeSJulian Elischer 	pru_rcvd_notsupp,		/* rcvd */
156f2bb1caeSJulian Elischer 	pru_rcvoob_notsupp,		/* rcvoob */
157f2bb1caeSJulian Elischer 	ng_btsocket_rfcomm_send,	/* send */
158f2bb1caeSJulian Elischer 	pru_sense_null,			/* send */
159f2bb1caeSJulian Elischer 	NULL,				/* shutdown */
160f2bb1caeSJulian Elischer 	ng_btsocket_rfcomm_sockaddr,	/* sockaddr */
161f2bb1caeSJulian Elischer 	sosend,
162f2bb1caeSJulian Elischer 	soreceive,
163f2bb1caeSJulian Elischer 	sopoll
164f2bb1caeSJulian Elischer };
165f2bb1caeSJulian Elischer 
166f2bb1caeSJulian Elischer /*
167878ed226SJulian Elischer  * Definitions of protocols supported in the BLUETOOTH domain
168878ed226SJulian Elischer  */
169878ed226SJulian Elischer 
170878ed226SJulian Elischer static struct protosw		ng_btsocket_protosw[] = {
171878ed226SJulian Elischer {
172878ed226SJulian Elischer 	SOCK_RAW,			/* protocol type */
173878ed226SJulian Elischer 	&ng_btsocket_domain,		/* backpointer to domain */
174878ed226SJulian Elischer 	BLUETOOTH_PROTO_HCI,		/* protocol */
175878ed226SJulian Elischer 	PR_ATOMIC | PR_ADDR,		/* flags */
176878ed226SJulian Elischer 	NULL, NULL, NULL,		/* input, output, ctlinput */
177878ed226SJulian Elischer 	ng_btsocket_hci_raw_ctloutput,	/* ctloutput */
178878ed226SJulian Elischer 	NULL,				/* ousrreq() */
179878ed226SJulian Elischer 	ng_btsocket_hci_raw_init,	/* init */
180878ed226SJulian Elischer 	NULL, NULL, NULL,		/* fasttimeo, slowtimo, drain */
181878ed226SJulian Elischer 	&ng_btsocket_hci_raw_usrreqs,	/* usrreq table (above) */
182878ed226SJulian Elischer 	/* { NULL } */			/* pfh (protocol filter head?) */
183878ed226SJulian Elischer },
184878ed226SJulian Elischer {
185878ed226SJulian Elischer 	SOCK_RAW,			/* protocol type */
186878ed226SJulian Elischer 	&ng_btsocket_domain,		/* backpointer to domain */
187878ed226SJulian Elischer 	BLUETOOTH_PROTO_L2CAP,		/* protocol */
188878ed226SJulian Elischer 	PR_ATOMIC | PR_ADDR,		/* flags */
189878ed226SJulian Elischer 	NULL, NULL, NULL,		/* input, output, ctlinput */
190878ed226SJulian Elischer 	NULL,				/* ctloutput */
191878ed226SJulian Elischer 	NULL,				/* ousrreq() */
192878ed226SJulian Elischer 	ng_btsocket_l2cap_raw_init,	/* init */
193878ed226SJulian Elischer 	NULL, NULL, NULL,		/* fasttimeo, slowtimo, drain */
194878ed226SJulian Elischer 	&ng_btsocket_l2cap_raw_usrreqs,	/* usrreq table (above) */
195878ed226SJulian Elischer 	/* { NULL } */			/* pfh (protocol filter head?) */
196878ed226SJulian Elischer },
197878ed226SJulian Elischer {
198878ed226SJulian Elischer 	SOCK_SEQPACKET,			/* protocol type */
199878ed226SJulian Elischer 	&ng_btsocket_domain,		/* backpointer to domain */
200878ed226SJulian Elischer 	BLUETOOTH_PROTO_L2CAP,		/* protocol */
201878ed226SJulian Elischer 	PR_ATOMIC | PR_CONNREQUIRED,	/* flags */
202878ed226SJulian Elischer 	NULL, NULL, NULL,		/* input, output, ctlinput */
203878ed226SJulian Elischer 	ng_btsocket_l2cap_ctloutput,	/* ctloutput */
204878ed226SJulian Elischer 	NULL,				/* ousrreq() */
205878ed226SJulian Elischer 	ng_btsocket_l2cap_init,		/* init */
206878ed226SJulian Elischer 	NULL, NULL, NULL,		/* fasttimeo, slowtimo, drain */
207878ed226SJulian Elischer 	&ng_btsocket_l2cap_usrreqs,	/* usrreq table (above) */
208878ed226SJulian Elischer 	/* { NULL } */			/* pfh (protocol filter head?) */
209f2bb1caeSJulian Elischer },
210f2bb1caeSJulian Elischer {
211f2bb1caeSJulian Elischer 	SOCK_STREAM,			/* protocol type */
212f2bb1caeSJulian Elischer 	&ng_btsocket_domain,		/* backpointer to domain */
213f2bb1caeSJulian Elischer 	BLUETOOTH_PROTO_RFCOMM,		/* protocol */
214f2bb1caeSJulian Elischer 	PR_ATOMIC | PR_CONNREQUIRED,	/* flags */
215f2bb1caeSJulian Elischer 	NULL, NULL, NULL,		/* input, output, ctlinput */
216f2bb1caeSJulian Elischer 	ng_btsocket_rfcomm_ctloutput,	/* ctloutput */
217f2bb1caeSJulian Elischer 	NULL,				/* ousrreq() */
218f2bb1caeSJulian Elischer 	ng_btsocket_rfcomm_init,	/* init */
219f2bb1caeSJulian Elischer 	NULL, NULL, NULL,		/* fasttimeo, slowtimo, drain */
220f2bb1caeSJulian Elischer 	&ng_btsocket_rfcomm_usrreqs,	/* usrreq table (above) */
221f2bb1caeSJulian Elischer 	/* { NULL } */			/* pfh (protocol filter head?) */
222878ed226SJulian Elischer }
223878ed226SJulian Elischer };
224878ed226SJulian Elischer #define ng_btsocket_protosw_size \
225878ed226SJulian Elischer 	(sizeof(ng_btsocket_protosw)/sizeof(ng_btsocket_protosw[0]))
226878ed226SJulian Elischer #define ng_btsocket_protosw_end \
227878ed226SJulian Elischer 	&ng_btsocket_protosw[ng_btsocket_protosw_size]
228878ed226SJulian Elischer 
229878ed226SJulian Elischer /*
230878ed226SJulian Elischer  * BLUETOOTH domain
231878ed226SJulian Elischer  */
232878ed226SJulian Elischer 
233878ed226SJulian Elischer struct domain			ng_btsocket_domain = {
234878ed226SJulian Elischer 	AF_BLUETOOTH,			/* family */
235878ed226SJulian Elischer 	"bluetooth",			/* domain name */
236878ed226SJulian Elischer 	NULL,				/* init() */
237878ed226SJulian Elischer 	NULL,				/* externalize() */
238878ed226SJulian Elischer 	NULL,				/* dispose() */
239878ed226SJulian Elischer 	ng_btsocket_protosw,		/* protosw entry */
240878ed226SJulian Elischer 	ng_btsocket_protosw_end,	/* end of protosw entries */
241878ed226SJulian Elischer 	NULL,				/* next domain in list */
242878ed226SJulian Elischer 	NULL,				/* rtattach() */
243878ed226SJulian Elischer 	0,				/* arg to rtattach in bits */
244878ed226SJulian Elischer 	0				/* maxrtkey */
245878ed226SJulian Elischer };
246878ed226SJulian Elischer 
247878ed226SJulian Elischer /*
248878ed226SJulian Elischer  * Socket sysctl tree
249878ed226SJulian Elischer  */
250878ed226SJulian Elischer 
251878ed226SJulian Elischer SYSCTL_NODE(_net_bluetooth_hci, OID_AUTO, sockets, CTLFLAG_RW,
252878ed226SJulian Elischer 	0, "Bluetooth HCI sockets family");
253878ed226SJulian Elischer SYSCTL_NODE(_net_bluetooth_l2cap, OID_AUTO, sockets, CTLFLAG_RW,
254878ed226SJulian Elischer 	0, "Bluetooth L2CAP sockets family");
255f2bb1caeSJulian Elischer SYSCTL_NODE(_net_bluetooth_rfcomm, OID_AUTO, sockets, CTLFLAG_RW,
256f2bb1caeSJulian Elischer 	0, "Bluetooth RFCOMM sockets family");
257878ed226SJulian Elischer 
258878ed226SJulian Elischer /*
259878ed226SJulian Elischer  * Module
260878ed226SJulian Elischer  */
261878ed226SJulian Elischer 
262878ed226SJulian Elischer static moduledata_t	ng_btsocket_mod = {
263878ed226SJulian Elischer 	"ng_btsocket",
264878ed226SJulian Elischer 	ng_btsocket_modevent,
265878ed226SJulian Elischer 	NULL
266878ed226SJulian Elischer };
267878ed226SJulian Elischer 
268878ed226SJulian Elischer DECLARE_MODULE(ng_btsocket, ng_btsocket_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
269878ed226SJulian Elischer MODULE_VERSION(ng_btsocket, NG_BLUETOOTH_VERSION);
270878ed226SJulian Elischer MODULE_DEPEND(ng_btsocket, ng_bluetooth, NG_BLUETOOTH_VERSION,
271878ed226SJulian Elischer 	NG_BLUETOOTH_VERSION, NG_BLUETOOTH_VERSION);
272878ed226SJulian Elischer MODULE_DEPEND(ng_btsocket, netgraph, NG_ABI_VERSION,
273878ed226SJulian Elischer 	NG_ABI_VERSION, NG_ABI_VERSION);
274878ed226SJulian Elischer 
275878ed226SJulian Elischer /*
276878ed226SJulian Elischer  * Handle loading and unloading for this node type.
277878ed226SJulian Elischer  * This is to handle auxiliary linkages (e.g protocol domain addition).
278878ed226SJulian Elischer  */
279878ed226SJulian Elischer 
280878ed226SJulian Elischer static int
281878ed226SJulian Elischer ng_btsocket_modevent(module_t mod, int event, void *data)
282878ed226SJulian Elischer {
283878ed226SJulian Elischer 	int	error = 0;
284878ed226SJulian Elischer 
285878ed226SJulian Elischer 	switch (event) {
286878ed226SJulian Elischer 	case MOD_LOAD:
287878ed226SJulian Elischer 		net_add_domain(&ng_btsocket_domain);
288878ed226SJulian Elischer 		break;
289878ed226SJulian Elischer 
290878ed226SJulian Elischer 	case MOD_UNLOAD:
291878ed226SJulian Elischer 		/* XXX can't unload protocol domain yet */
292878ed226SJulian Elischer 		error = EBUSY;
293878ed226SJulian Elischer 		break;
294878ed226SJulian Elischer 
295878ed226SJulian Elischer 	default:
296878ed226SJulian Elischer 		error = EOPNOTSUPP;
297878ed226SJulian Elischer 		break;
298878ed226SJulian Elischer 	}
299878ed226SJulian Elischer 
300878ed226SJulian Elischer 	return (error);
301878ed226SJulian Elischer } /* ng_btsocket_modevent */
302878ed226SJulian Elischer 
303