xref: /dflybsd-src/sys/netbt/hci_socket.c (revision 6cef7136f04e2b24a6db289e78720d6d8c60274e)
1 /* $DragonFly: src/sys/netbt/hci_socket.c,v 1.3 2008/06/20 20:52:29 aggelos Exp $ */
2 /* $OpenBSD: src/sys/netbt/hci_socket.c,v 1.5 2008/02/24 21:34:48 uwe Exp $ */
3 /* $NetBSD: hci_socket.c,v 1.14 2008/02/10 17:40:54 plunky Exp $ */
4 
5 /*-
6  * Copyright (c) 2005 Iain Hibbert.
7  * Copyright (c) 2006 Itronix Inc.
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. The name of Itronix Inc. may not be used to endorse
19  *    or promote products derived from this software without specific
20  *    prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
25  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
26  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29  * ON ANY THEORY OF LIABILITY, WHETHER IN
30  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  */
34 
35 /* load symbolic names */
36 #ifdef BLUETOOTH_DEBUG
37 #define PRUREQUESTS
38 #define PRCOREQUESTS
39 #endif
40 
41 #include <sys/param.h>
42 #include <sys/domain.h>
43 #include <sys/kernel.h>
44 #include <sys/mbuf.h>
45 #include <sys/proc.h>
46 #include <sys/priv.h>
47 #include <sys/protosw.h>
48 #include <sys/socket.h>
49 #include <sys/socketvar.h>
50 #include <sys/systm.h>
51 #include <sys/endian.h>
52 #include <net/if.h>
53 #include <net/if_var.h>
54 #include <sys/sysctl.h>
55 
56 #include <sys/thread2.h>
57 #include <sys/socketvar2.h>
58 
59 #include <netbt/bluetooth.h>
60 #include <netbt/hci.h>
61 
62 /*******************************************************************************
63  *
64  * HCI SOCK_RAW Sockets - for control of Bluetooth Devices
65  *
66  */
67 
68 /*
69  * the raw HCI protocol control block
70  */
71 struct hci_pcb {
72 	struct socket		*hp_socket;	/* socket */
73 	unsigned int		hp_flags;	/* flags */
74 	bdaddr_t		hp_laddr;	/* local address */
75 	bdaddr_t		hp_raddr;	/* remote address */
76 	struct hci_filter	hp_efilter;	/* user event filter */
77 	struct hci_filter	hp_pfilter;	/* user packet filter */
78 	LIST_ENTRY(hci_pcb)	hp_next;	/* next HCI pcb */
79 };
80 
81 /* hp_flags */
82 #define HCI_PRIVILEGED		(1<<0)	/* no security filter for root */
83 #define HCI_DIRECTION		(1<<1)	/* direction control messages */
84 #define HCI_PROMISCUOUS		(1<<2)	/* listen to all units */
85 
86 LIST_HEAD(hci_pcb_list, hci_pcb) hci_pcb = LIST_HEAD_INITIALIZER(hci_pcb);
87 
88 /* sysctl defaults */
89 int hci_sendspace = HCI_CMD_PKT_SIZE;
90 int hci_recvspace = 4096;
91 
92 extern struct pr_usrreqs hci_usrreqs;
93 
94 /* Prototypes for usrreqs methods. */
95 static int hci_sabort (struct socket *so);
96 static int hci_sdetach(struct socket *so);
97 static int hci_sdisconnect (struct socket *so);
98 static int hci_scontrol (struct socket *so, u_long cmd, caddr_t data,
99                                     struct ifnet *ifp, struct thread *td);
100 static int hci_sattach (struct socket *so, int proto,
101                                struct pru_attach_info *ai);
102 static int hci_sbind (struct socket *so, struct sockaddr *nam,
103                                  struct thread *td);
104 static int hci_sconnect (struct socket *so, struct sockaddr *nam,
105                                     struct thread *td);
106 static int hci_speeraddr (struct socket *so, struct sockaddr **nam);
107 static int hci_ssockaddr (struct socket *so, struct sockaddr **nam);
108 static int hci_sshutdown (struct socket *so);
109 static int hci_ssend (struct socket *so, int flags, struct mbuf *m,
110                                  struct sockaddr *addr, struct mbuf *control,
111                                  struct thread *td);
112 
113 /* supported commands opcode table */
114 static const struct {
115 	uint16_t	opcode;
116 	uint8_t		offs;	/* 0 - 63 */
117 	uint8_t		mask;	/* bit 0 - 7 */
118 	int16_t		length;	/* -1 if privileged */
119 } hci_cmds[] = {
120 	{ HCI_CMD_INQUIRY,
121 	  0,  0x01, sizeof(hci_inquiry_cp) },
122 	{ HCI_CMD_INQUIRY_CANCEL,
123 	  0,  0x02, -1 },
124 	{ HCI_CMD_PERIODIC_INQUIRY,
125 	  0,  0x04, -1 },
126 	{ HCI_CMD_EXIT_PERIODIC_INQUIRY,
127 	  0,  0x08, -1 },
128 	{ HCI_CMD_CREATE_CON,
129 	  0,  0x10, -1 },
130 	{ HCI_CMD_DISCONNECT,
131 	  0,  0x20, -1 },
132 	{ HCI_CMD_ADD_SCO_CON,
133 	  0,  0x40, -1 },
134 	{ HCI_CMD_CREATE_CON_CANCEL,
135 	  0,  0x80, -1 },
136 	{ HCI_CMD_ACCEPT_CON,
137 	  1,  0x01, -1 },
138 	{ HCI_CMD_REJECT_CON,
139 	  1,  0x02, -1 },
140 	{ HCI_CMD_LINK_KEY_REP,
141 	  1,  0x04, -1 },
142 	{ HCI_CMD_LINK_KEY_NEG_REP,
143 	  1,  0x08, -1 },
144 	{ HCI_CMD_PIN_CODE_REP,
145 	  1,  0x10, -1 },
146 	{ HCI_CMD_PIN_CODE_NEG_REP,
147 	  1,  0x20, -1 },
148 	{ HCI_CMD_CHANGE_CON_PACKET_TYPE,
149 	  1,  0x40, -1 },
150 	{ HCI_CMD_AUTH_REQ,
151 	  1,  0x80, -1 },
152 	{ HCI_CMD_SET_CON_ENCRYPTION,
153 	  2,  0x01, -1 },
154 	{ HCI_CMD_CHANGE_CON_LINK_KEY,
155 	  2,  0x02, -1 },
156 	{ HCI_CMD_MASTER_LINK_KEY,
157 	  2,  0x04, -1 },
158 	{ HCI_CMD_REMOTE_NAME_REQ,
159 	  2,  0x08, sizeof(hci_remote_name_req_cp) },
160 	{ HCI_CMD_REMOTE_NAME_REQ_CANCEL,
161 	  2,  0x10, -1 },
162 	{ HCI_CMD_READ_REMOTE_FEATURES,
163 	  2,  0x20, sizeof(hci_read_remote_features_cp) },
164 	{ HCI_CMD_READ_REMOTE_EXTENDED_FEATURES,
165 	  2,  0x40, sizeof(hci_read_remote_extended_features_cp) },
166 	{ HCI_CMD_READ_REMOTE_VER_INFO,
167 	  2,  0x80, sizeof(hci_read_remote_ver_info_cp) },
168 	{ HCI_CMD_READ_CLOCK_OFFSET,
169 	  3,  0x01, sizeof(hci_read_clock_offset_cp) },
170 	{ HCI_CMD_READ_LMP_HANDLE,
171 	  3,  0x02, sizeof(hci_read_lmp_handle_cp) },
172 	{ HCI_CMD_HOLD_MODE,
173 	  4,  0x02, -1 },
174 	{ HCI_CMD_SNIFF_MODE,
175 	  4,  0x04, -1 },
176 	{ HCI_CMD_EXIT_SNIFF_MODE,
177 	  4,  0x08, -1 },
178 	{ HCI_CMD_PARK_MODE,
179 	  4,  0x10, -1 },
180 	{ HCI_CMD_EXIT_PARK_MODE,
181 	  4,  0x20, -1 },
182 	{ HCI_CMD_QOS_SETUP,
183 	  4,  0x40, -1 },
184 	{ HCI_CMD_ROLE_DISCOVERY,
185 	  4,  0x80, sizeof(hci_role_discovery_cp) },
186 	{ HCI_CMD_SWITCH_ROLE,
187 	  5,  0x01, -1 },
188 	{ HCI_CMD_READ_LINK_POLICY_SETTINGS,
189 	  5,  0x02, sizeof(hci_read_link_policy_settings_cp) },
190 	{ HCI_CMD_WRITE_LINK_POLICY_SETTINGS,
191 	  5,  0x04, -1 },
192 	{ HCI_CMD_READ_DEFAULT_LINK_POLICY_SETTINGS,
193 	  5,  0x08, 0 },
194 	{ HCI_CMD_WRITE_DEFAULT_LINK_POLICY_SETTINGS,
195 	  5,  0x10, -1 },
196 	{ HCI_CMD_FLOW_SPECIFICATION,
197 	  5,  0x20, -1 },
198 	{ HCI_CMD_SET_EVENT_MASK,
199 	  5,  0x40, -1 },
200 	{ HCI_CMD_RESET,
201 	  5,  0x80, -1 },
202 	{ HCI_CMD_SET_EVENT_FILTER,
203 	  6,  0x01, -1 },
204 	{ HCI_CMD_FLUSH,
205 	  6,  0x02, -1 },
206 	{ HCI_CMD_READ_PIN_TYPE,
207 	  6,  0x04, 0 },
208 	{ HCI_CMD_WRITE_PIN_TYPE,
209 	  6,  0x08, -1 },
210 	{ HCI_CMD_CREATE_NEW_UNIT_KEY,
211 	  6,  0x10, -1 },
212 	{ HCI_CMD_READ_STORED_LINK_KEY,
213 	  6,  0x20, -1 },
214 	{ HCI_CMD_WRITE_STORED_LINK_KEY,
215 	  6,  0x40, -1 },
216 	{ HCI_CMD_DELETE_STORED_LINK_KEY,
217 	  6,  0x80, -1 },
218 	{ HCI_CMD_WRITE_LOCAL_NAME,
219 	  7,  0x01, -1 },
220 	{ HCI_CMD_READ_LOCAL_NAME,
221 	  7,  0x02, 0 },
222 	{ HCI_CMD_READ_CON_ACCEPT_TIMEOUT,
223 	  7,  0x04, 0 },
224 	{ HCI_CMD_WRITE_CON_ACCEPT_TIMEOUT,
225 	  7,  0x08, -1 },
226 	{ HCI_CMD_READ_PAGE_TIMEOUT,
227 	  7,  0x10, 0 },
228 	{ HCI_CMD_WRITE_PAGE_TIMEOUT,
229 	  7,  0x20, -1 },
230 	{ HCI_CMD_READ_SCAN_ENABLE,
231 	  7,  0x40, 0 },
232 	{ HCI_CMD_WRITE_SCAN_ENABLE,
233 	  7,  0x80, -1 },
234 	{ HCI_CMD_READ_PAGE_SCAN_ACTIVITY,
235 	  8,  0x01, 0 },
236 	{ HCI_CMD_WRITE_PAGE_SCAN_ACTIVITY,
237 	  8,  0x02, -1 },
238 	{ HCI_CMD_READ_INQUIRY_SCAN_ACTIVITY,
239 	  8,  0x04, 0 },
240 	{ HCI_CMD_WRITE_INQUIRY_SCAN_ACTIVITY,
241 	  8,  0x08, -1 },
242 	{ HCI_CMD_READ_AUTH_ENABLE,
243 	  8,  0x10, 0 },
244 	{ HCI_CMD_WRITE_AUTH_ENABLE,
245 	  8,  0x20, -1 },
246 	{ HCI_CMD_READ_ENCRYPTION_MODE,
247 	  8,  0x40, 0 },
248 	{ HCI_CMD_WRITE_ENCRYPTION_MODE,
249 	  8,  0x80, -1 },
250 	{ HCI_CMD_READ_UNIT_CLASS,
251 	  9,  0x01, 0 },
252 	{ HCI_CMD_WRITE_UNIT_CLASS,
253 	  9,  0x02, -1 },
254 	{ HCI_CMD_READ_VOICE_SETTING,
255 	  9,  0x04, 0 },
256 	{ HCI_CMD_WRITE_VOICE_SETTING,
257 	  9,  0x08, -1 },
258 	{ HCI_CMD_READ_AUTO_FLUSH_TIMEOUT,
259 	  9,  0x10, sizeof(hci_read_auto_flush_timeout_cp) },
260 	{ HCI_CMD_WRITE_AUTO_FLUSH_TIMEOUT,
261 	  9,  0x20, -1 },
262 	{ HCI_CMD_READ_NUM_BROADCAST_RETRANS,
263 	  9,  0x40, 0 },
264 	{ HCI_CMD_WRITE_NUM_BROADCAST_RETRANS,
265 	  9,  0x80, -1 },
266 	{ HCI_CMD_READ_HOLD_MODE_ACTIVITY,
267 	  10, 0x01, 0 },
268 	{ HCI_CMD_WRITE_HOLD_MODE_ACTIVITY,
269 	  10, 0x02, -1 },
270 	{ HCI_CMD_READ_XMIT_LEVEL,
271 	  10, 0x04, sizeof(hci_read_xmit_level_cp) },
272 	{ HCI_CMD_READ_SCO_FLOW_CONTROL,
273 	  10, 0x08, 0 },
274 	{ HCI_CMD_WRITE_SCO_FLOW_CONTROL,
275 	  10, 0x10, -1 },
276 	{ HCI_CMD_HC2H_FLOW_CONTROL,
277 	  10, 0x20, -1 },
278 	{ HCI_CMD_HOST_BUFFER_SIZE,
279 	  10, 0x40, -1 },
280 	{ HCI_CMD_HOST_NUM_COMPL_PKTS,
281 	  10, 0x80, -1 },
282 	{ HCI_CMD_READ_LINK_SUPERVISION_TIMEOUT,
283 	  11, 0x01, sizeof(hci_read_link_supervision_timeout_cp) },
284 	{ HCI_CMD_WRITE_LINK_SUPERVISION_TIMEOUT,
285 	  11, 0x02, -1 },
286 	{ HCI_CMD_READ_NUM_SUPPORTED_IAC,
287 	  11, 0x04, 0 },
288 	{ HCI_CMD_READ_IAC_LAP,
289 	  11, 0x08, 0 },
290 	{ HCI_CMD_WRITE_IAC_LAP,
291 	  11, 0x10, -1 },
292 	{ HCI_CMD_READ_PAGE_SCAN_PERIOD,
293 	  11, 0x20, 0 },
294 	{ HCI_CMD_WRITE_PAGE_SCAN_PERIOD,
295 	  11, 0x40, -1 },
296 	{ HCI_CMD_READ_PAGE_SCAN,
297 	  11, 0x80, 0 },
298 	{ HCI_CMD_WRITE_PAGE_SCAN,
299 	  12, 0x01, -1 },
300 	{ HCI_CMD_SET_AFH_CLASSIFICATION,
301 	  12, 0x02, -1 },
302 	{ HCI_CMD_READ_INQUIRY_SCAN_TYPE,
303 	  12, 0x10, 0 },
304 	{ HCI_CMD_WRITE_INQUIRY_SCAN_TYPE,
305 	  12, 0x20, -1 },
306 	{ HCI_CMD_READ_INQUIRY_MODE,
307 	  12, 0x40, 0 },
308 	{ HCI_CMD_WRITE_INQUIRY_MODE,
309 	  12, 0x80, -1 },
310 	{ HCI_CMD_READ_PAGE_SCAN_TYPE,
311 	  13, 0x01, 0 },
312 	{ HCI_CMD_WRITE_PAGE_SCAN_TYPE,
313 	  13, 0x02, -1 },
314 	{ HCI_CMD_READ_AFH_ASSESSMENT,
315 	  13, 0x04, 0 },
316 	{ HCI_CMD_WRITE_AFH_ASSESSMENT,
317 	  13, 0x08, -1 },
318 	{ HCI_CMD_READ_LOCAL_VER,
319 	  14, 0x08, 0 },
320 	{ HCI_CMD_READ_LOCAL_COMMANDS,
321 	  14, 0x10, 0 },
322 	{ HCI_CMD_READ_LOCAL_FEATURES,
323 	  14, 0x20, 0 },
324 	{ HCI_CMD_READ_LOCAL_EXTENDED_FEATURES,
325 	  14, 0x40, sizeof(hci_read_local_extended_features_cp) },
326 	{ HCI_CMD_READ_BUFFER_SIZE,
327 	  14, 0x80, 0 },
328 	{ HCI_CMD_READ_COUNTRY_CODE,
329 	  15, 0x01, 0 },
330 	{ HCI_CMD_READ_BDADDR,
331 	  15, 0x02, 0 },
332 	{ HCI_CMD_READ_FAILED_CONTACT_CNTR,
333 	  15, 0x04, sizeof(hci_read_failed_contact_cntr_cp) },
334 	{ HCI_CMD_RESET_FAILED_CONTACT_CNTR,
335 	  15, 0x08, -1 },
336 	{ HCI_CMD_READ_LINK_QUALITY,
337 	  15, 0x10, sizeof(hci_read_link_quality_cp) },
338 	{ HCI_CMD_READ_RSSI,
339 	  15, 0x20, sizeof(hci_read_rssi_cp) },
340 	{ HCI_CMD_READ_AFH_CHANNEL_MAP,
341 	  15, 0x40, sizeof(hci_read_afh_channel_map_cp) },
342 	{ HCI_CMD_READ_CLOCK,
343 	  15, 0x80, sizeof(hci_read_clock_cp) },
344 	{ HCI_CMD_READ_LOOPBACK_MODE,
345 	  16, 0x01, 0 },
346 	{ HCI_CMD_WRITE_LOOPBACK_MODE,
347 	  16, 0x02, -1 },
348 	{ HCI_CMD_ENABLE_UNIT_UNDER_TEST,
349 	  16, 0x04, -1 },
350 	{ HCI_CMD_SETUP_SCO_CON,
351 	  16, 0x08, -1 },
352 	{ HCI_CMD_ACCEPT_SCO_CON_REQ,
353 	  16, 0x10, -1 },
354 	{ HCI_CMD_REJECT_SCO_CON_REQ,
355 	  16, 0x20, -1 },
356 	{ HCI_CMD_READ_EXTENDED_INQUIRY_RSP,
357 	  17, 0x01, 0 },
358 	{ HCI_CMD_WRITE_EXTENDED_INQUIRY_RSP,
359 	  17, 0x02, -1 },
360 	{ HCI_CMD_REFRESH_ENCRYPTION_KEY,
361 	  17, 0x04, -1 },
362 	{ HCI_CMD_SNIFF_SUBRATING,
363 	  17, 0x10, -1 },
364 	{ HCI_CMD_READ_SIMPLE_PAIRING_MODE,
365 	  17, 0x20, 0 },
366 	{ HCI_CMD_WRITE_SIMPLE_PAIRING_MODE,
367 	  17, 0x40, -1 },
368 	{ HCI_CMD_READ_LOCAL_OOB_DATA,
369 	  17, 0x80, -1 },
370 	{ HCI_CMD_READ_INQUIRY_RSP_XMIT_POWER,
371 	  18, 0x01, 0 },
372 	{ HCI_CMD_WRITE_INQUIRY_RSP_XMIT_POWER,
373 	  18, 0x02, -1 },
374 	{ HCI_CMD_READ_DEFAULT_ERRDATA_REPORTING,
375 	  18, 0x04, 0 },
376 	{ HCI_CMD_WRITE_DEFAULT_ERRDATA_REPORTING,
377 	  18, 0x08, -1 },
378 	{ HCI_CMD_IO_CAPABILITY_REP,
379 	  18, 0x80, -1 },
380 	{ HCI_CMD_USER_CONFIRM_REP,
381 	  19, 0x01, -1 },
382 	{ HCI_CMD_USER_CONFIRM_NEG_REP,
383 	  19, 0x02, -1 },
384 	{ HCI_CMD_USER_PASSKEY_REP,
385 	  19, 0x04, -1 },
386 	{ HCI_CMD_USER_PASSKEY_NEG_REP,
387 	  19, 0x08, -1 },
388 	{ HCI_CMD_OOB_DATA_REP,
389 	  19, 0x10, -1 },
390 	{ HCI_CMD_WRITE_SIMPLE_PAIRING_DEBUG_MODE,
391 	  19, 0x20, -1 },
392 	{ HCI_CMD_ENHANCED_FLUSH,
393 	  19, 0x40, -1 },
394 	{ HCI_CMD_OOB_DATA_NEG_REP,
395 	  19, 0x80, -1 },
396 	{ HCI_CMD_SEND_KEYPRESS_NOTIFICATION,
397 	  20, 0x40, -1 },
398 	{ HCI_CMD_IO_CAPABILITY_NEG_REP,
399 	  20, 0x80, -1 },
400 };
401 
402 /*
403  * Security filter routines for unprivileged users.
404  *	Allow all but a few critical events, and only permit read commands.
405  *	If a unit is given, verify the command is supported.
406  */
407 
408 static int
409 hci_security_check_opcode(struct hci_unit *unit, uint16_t opcode)
410 {
411 	int i;
412 
413 	for (i = 0 ; i < sizeof(hci_cmds) / sizeof(hci_cmds[0]); i++) {
414 		if (opcode != hci_cmds[i].opcode)
415 			continue;
416 
417 		if (unit == NULL
418 		    || (unit->hci_cmds[hci_cmds[i].offs] & hci_cmds[i].mask))
419 			return hci_cmds[i].length;
420 
421 		break;
422 	}
423 
424 	return -1;
425 }
426 
427 static int
428 hci_security_check_event(uint8_t event)
429 {
430 
431 	switch (event) {
432 	case HCI_EVENT_RETURN_LINK_KEYS:
433 	case HCI_EVENT_LINK_KEY_NOTIFICATION:
434 	case HCI_EVENT_USER_CONFIRM_REQ:
435 	case HCI_EVENT_USER_PASSKEY_NOTIFICATION:
436 	case HCI_EVENT_VENDOR:
437 		return -1;	/* disallowed */
438 	}
439 
440 	return 0;	/* ok */
441 }
442 
443 /*
444  * When command packet reaches the device, we can drop
445  * it from the socket buffer (called from hci_output_acl)
446  */
447 void
448 hci_drop(void *arg)
449 {
450 	struct socket *so = arg;
451 
452 	sbdroprecord(&so->so_snd.sb);
453 	sowwakeup(so);
454 }
455 
456 /*
457  * HCI socket is going away and has some pending packets. We let them
458  * go by design, but remove the context pointer as it will be invalid
459  * and we no longer need to be notified.
460  */
461 static void
462 hci_cmdwait_flush(struct socket *so)
463 {
464 	struct hci_unit *unit;
465 	struct socket *ctx;
466 	struct mbuf *m;
467 
468 	DPRINTF("flushing %p\n", so);
469 
470 	TAILQ_FOREACH(unit, &hci_unit_list, hci_next) {
471 		IF_POLL(&unit->hci_cmdwait, m);
472 		while (m != NULL) {
473 			ctx = M_GETCTX(m, struct socket *);
474 			if (ctx == so)
475 				M_SETCTX(m, NULL);
476 
477 			m = m->m_nextpkt;
478 		}
479 	}
480 }
481 
482 /*
483  * HCI send packet
484  *     This came from userland, so check it out.
485  */
486 static int
487 hci_send(struct hci_pcb *pcb, struct mbuf *m, bdaddr_t *addr)
488 {
489 	struct hci_unit *unit;
490 	struct mbuf *m0;
491 	hci_cmd_hdr_t hdr;
492 	int err;
493 
494 	KKASSERT(m != NULL);
495 	KKASSERT(addr != NULL);
496 
497 	/* wants at least a header to start with */
498 	if (m->m_pkthdr.len < sizeof(hdr)) {
499 		err = EMSGSIZE;
500 		goto bad;
501 	}
502 	m_copydata(m, 0, sizeof(hdr), (caddr_t)&hdr);
503 	hdr.opcode = letoh16(hdr.opcode);
504 
505 	/* only allows CMD packets to be sent */
506 	if (hdr.type != HCI_CMD_PKT) {
507 		err = EINVAL;
508 		goto bad;
509 	}
510 
511 	/* validates packet length */
512 	if (m->m_pkthdr.len != sizeof(hdr) + hdr.length) {
513 		err = EMSGSIZE;
514 		goto bad;
515 	}
516 
517 	/* finds destination */
518 	unit = hci_unit_lookup(addr);
519 	if (unit == NULL) {
520 		err = ENETDOWN;
521 		goto bad;
522 	}
523 
524 	/* security checks for unprivileged users */
525 	if ((pcb->hp_flags & HCI_PRIVILEGED) == 0
526 	    && hci_security_check_opcode(unit, hdr.opcode) != hdr.length) {
527 		err = EPERM;
528 		goto bad;
529 	}
530 
531 	/* makes a copy for precious to keep */
532 	m0 = m_copym(m, 0, M_COPYALL, MB_DONTWAIT);
533 	if (m0 == NULL) {
534 		err = ENOMEM;
535 		goto bad;
536 	}
537 	sbappendrecord(&pcb->hp_socket->so_snd.sb, m0);
538 	M_SETCTX(m, pcb->hp_socket);	/* enable drop callback */
539 
540 	DPRINTFN(2, "(%s) opcode (%03x|%04x)\n",
541 		device_get_nameunit(unit->hci_dev),
542 		HCI_OGF(hdr.opcode), HCI_OCF(hdr.opcode));
543 
544 	/* Sendss it */
545 	if (unit->hci_num_cmd_pkts == 0)
546 		IF_ENQUEUE(&unit->hci_cmdwait, m);
547 	else
548 		hci_output_cmd(unit, m);
549 
550 	return 0;
551 
552 bad:
553 	DPRINTF("packet (%d bytes) not sent (error %d)\n",
554 	    m->m_pkthdr.len, err);
555 	if (m) m_freem(m);
556 	return err;
557 }
558 
559 /*
560  * Implementation of usrreqs.
561  *
562  * NOTE: (so) is referenced from soabort*() and netmsg_pru_abort()
563  *	 will sofree() it when we return.
564  */
565 static int
566 hci_sabort (struct socket *so)
567 {
568 	int error;
569 
570 	/* struct hci_pcb *pcb = (struct hci_pcb *)so->so_pcb;	*/
571 
572 	soisdisconnected(so);
573 	error = hci_sdetach(so);
574 	return (error);
575 }
576 
577 static int
578 hci_sdetach(struct socket *so)
579 {
580 	struct hci_pcb *pcb = (struct hci_pcb *)so->so_pcb;
581 
582 	if (pcb == NULL)
583 		return EINVAL;
584 	if (so->so_snd.ssb_mb != NULL)
585 		hci_cmdwait_flush(so);
586 
587 	so->so_pcb = NULL;
588 	sofree(so);		/* remove pcb ref */
589 
590 	LIST_REMOVE(pcb, hp_next);
591 	kfree(pcb, M_PCB);
592 
593 	return 0;
594 }
595 
596 static int
597 hci_sdisconnect (struct socket *so)
598 {
599 	struct hci_pcb *pcb = (struct hci_pcb *)so->so_pcb;
600 
601 	if (pcb==NULL)
602 		return EINVAL;
603 
604 	bdaddr_copy(&pcb->hp_raddr, BDADDR_ANY);
605 	/*
606 	 * XXX We cannot call soisdisconnected() here, as it sets
607 	 * SS_CANTRCVMORE and SS_CANTSENDMORE. The problem is that
608 	 * soisconnected() does not clear these and if you try to reconnect
609 	 * this socket (which is permitted) you get a broken pipe when you
610 	 * try to write any data.
611 	 */
612 	soclrstate(so, SS_ISCONNECTED);
613 
614 	return 0;
615 }
616 
617 static int
618 hci_scontrol (struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
619     struct thread *td)
620 {
621 	return hci_ioctl(cmd, (void*)data, NULL);
622 }
623 
624 static int
625 hci_sattach (struct socket *so, int proto, struct pru_attach_info *ai)
626 {
627 	struct hci_pcb *pcb = (struct hci_pcb *)so->so_pcb;
628 	int err = 0;
629 
630 	if (pcb)
631 		return EINVAL;
632 
633 	err = soreserve(so, hci_sendspace, hci_recvspace,NULL);
634 	if (err)
635 		return err;
636 
637 	pcb = kmalloc(sizeof *pcb, M_PCB, M_NOWAIT | M_ZERO);
638 	if (pcb == NULL)
639 		return ENOMEM;
640 
641 	soreference(so);
642 	so->so_pcb = pcb;
643 	pcb->hp_socket = so;
644 
645 	if (curproc == NULL || priv_check(curthread, PRIV_ROOT) == 0)
646 		pcb->hp_flags |= HCI_PRIVILEGED;
647 
648 	/*
649 	 * Set default user filter. By default, socket only passes
650 	 * Command_Complete and Command_Status Events.
651 	 */
652 	hci_filter_set(HCI_EVENT_COMMAND_COMPL, &pcb->hp_efilter);
653 	hci_filter_set(HCI_EVENT_COMMAND_STATUS, &pcb->hp_efilter);
654 	hci_filter_set(HCI_EVENT_PKT, &pcb->hp_pfilter);
655 
656 	crit_enter();
657 	LIST_INSERT_HEAD(&hci_pcb, pcb, hp_next);
658 	crit_exit();
659 
660 	return 0;
661 }
662 
663 static int
664 hci_sbind (struct socket *so, struct sockaddr *nam,
665 				 struct thread *td)
666 {
667 	struct hci_pcb *pcb = (struct hci_pcb *)so->so_pcb;
668 	struct sockaddr_bt *sa;
669 
670 	KKASSERT(nam != NULL);
671 	sa = (struct sockaddr_bt *)nam;
672 
673 	if (sa->bt_len != sizeof(struct sockaddr_bt))
674 		return EINVAL;
675 
676 	if (sa->bt_family != AF_BLUETOOTH)
677 		return EAFNOSUPPORT;
678 
679 	bdaddr_copy(&pcb->hp_laddr, &sa->bt_bdaddr);
680 
681 	if (bdaddr_any(&sa->bt_bdaddr))
682 		pcb->hp_flags |= HCI_PROMISCUOUS;
683 	else
684 		pcb->hp_flags &= ~HCI_PROMISCUOUS;
685 
686 	return 0;
687 }
688 
689 static int
690 hci_sconnect (struct socket *so, struct sockaddr *nam,
691 				    struct thread *td)
692 {
693 	struct hci_pcb *pcb = (struct hci_pcb *)so->so_pcb;
694 	struct sockaddr_bt *sa;
695 	KKASSERT(nam != NULL);
696 	sa = (struct sockaddr_bt *)nam;
697 
698 	if (sa->bt_len != sizeof(struct sockaddr_bt))
699 		return EINVAL;
700 
701 	if (sa->bt_family != AF_BLUETOOTH)
702 		return EAFNOSUPPORT;
703 
704 	if (hci_unit_lookup(&sa->bt_bdaddr) == NULL)
705 		return EADDRNOTAVAIL;
706 
707 	bdaddr_copy(&pcb->hp_raddr, &sa->bt_bdaddr);
708 	soisconnected(so);
709 
710 	return 0;
711 }
712 
713 static int
714 hci_speeraddr (struct socket *so, struct sockaddr **nam)
715 {
716 	struct hci_pcb *pcb = (struct hci_pcb *)so->so_pcb;
717 	struct sockaddr_bt *sa;
718 
719 	KKASSERT(nam != NULL);
720 	sa = (struct sockaddr_bt *)nam;
721 
722 	memset(sa, 0, sizeof(struct sockaddr_bt));
723 	sa->bt_len = sizeof(struct sockaddr_bt);
724 	sa->bt_family = AF_BLUETOOTH;
725 	bdaddr_copy(&sa->bt_bdaddr, &pcb->hp_raddr);
726 
727 	return 0;
728 }
729 
730 static int
731 hci_ssockaddr (struct socket *so, struct sockaddr **nam)
732 {
733 	struct hci_pcb *pcb = (struct hci_pcb *)so->so_pcb;
734 	struct sockaddr_bt *sa;
735 
736 	KKASSERT(nam != NULL);
737 	sa = (struct sockaddr_bt *)nam;
738 
739 	memset(sa, 0, sizeof(struct sockaddr_bt));
740 	sa->bt_len = sizeof(struct sockaddr_bt);
741 	sa->bt_family = AF_BLUETOOTH;
742 	bdaddr_copy(&sa->bt_bdaddr, &pcb->hp_laddr);
743 
744 	return 0;
745 }
746 
747 static int
748 hci_sshutdown (struct socket *so)
749 {
750 	socantsendmore(so);
751 	return 0;
752 }
753 
754 static int
755 hci_ssend (struct socket *so, int flags, struct mbuf *m,
756 				 struct sockaddr *addr, struct mbuf *control,
757 				 struct thread *td)
758 {
759 	int err = 0;
760 	struct hci_pcb *pcb = (struct hci_pcb *)so->so_pcb;
761 	struct sockaddr_bt *sa;
762 
763 	sa = NULL;
764 	if (addr) {
765 		sa = (struct sockaddr_bt *)addr;
766 
767 		if (sa->bt_len != sizeof(struct sockaddr_bt)) {
768 			err = EINVAL;
769 			if (m) m_freem(m);
770 			if (control) m_freem(control);
771 			return err;
772 		}
773 
774 		if (sa->bt_family != AF_BLUETOOTH) {
775 			err = EAFNOSUPPORT;
776 			if (m) m_freem(m);
777 			if (control) m_freem(control);
778 			return err;
779 		}
780 	}
781 
782 	if (control) /* have no use for this */
783 		m_freem(control);
784 
785 	return hci_send(pcb, m, (sa ? &sa->bt_bdaddr : &pcb->hp_raddr));
786 }
787 
788 /*
789  * get/set socket options
790  */
791 int
792 hci_ctloutput (struct socket *so, struct sockopt *sopt)
793 {
794 	struct hci_pcb *pcb = (struct hci_pcb *)so->so_pcb;
795 	int idir = 0;
796 	int err = 0;
797 
798 #ifdef notyet			/* XXX */
799 	DPRINTFN(2, "req %s\n", prcorequests[req]);
800 #endif
801 
802 	if (pcb == NULL)
803 		return EINVAL;
804 
805 	if (sopt->sopt_level != BTPROTO_HCI)
806 		return ENOPROTOOPT;
807 
808 	switch(sopt->sopt_dir) {
809 	case PRCO_GETOPT:
810 		switch (sopt->sopt_name) {
811 		case SO_HCI_EVT_FILTER:
812 			soopt_from_kbuf(sopt, &pcb->hp_efilter,
813 			    sizeof(struct hci_filter));
814 			break;
815 
816 		case SO_HCI_PKT_FILTER:
817                         soopt_from_kbuf(sopt, &pcb->hp_pfilter,
818 			    sizeof(struct hci_filter));
819 			break;
820 
821 		case SO_HCI_DIRECTION:
822 			if (pcb->hp_flags & HCI_DIRECTION)
823 				idir = 1;
824 			else
825 				idir = 0;
826 			soopt_from_kbuf(sopt, &idir, sizeof(int));
827 			break;
828 
829 		default:
830 			err = ENOPROTOOPT;
831 			break;
832 		}
833 		break;
834 
835 	case PRCO_SETOPT:
836 		switch (sopt->sopt_name) {
837 		case SO_HCI_EVT_FILTER:	/* set event filter */
838 			err = soopt_to_kbuf(sopt, &pcb->hp_efilter,
839 			    sizeof(struct hci_filter),
840 			    sizeof(struct hci_filter));
841 			break;
842 
843 		case SO_HCI_PKT_FILTER:	/* set packet filter */
844 			err = soopt_to_kbuf(sopt, &pcb->hp_pfilter,
845 			    sizeof(struct hci_filter),
846 			    sizeof(struct hci_filter));
847 			break;
848 
849 		case SO_HCI_DIRECTION:	/* request direction ctl messages */
850 			err = soopt_to_kbuf(sopt, &idir, sizeof(int),
851 			    sizeof(int));
852 			if (err) break;
853 			if (idir)
854 				pcb->hp_flags |= HCI_DIRECTION;
855 			else
856 				pcb->hp_flags &= ~HCI_DIRECTION;
857 			break;
858 
859 		default:
860 			err = ENOPROTOOPT;
861 			break;
862 		}
863 		break;
864 
865 	default:
866 		err = ENOPROTOOPT;
867 		break;
868 	}
869 
870 	return err;
871 }
872 
873 /*
874  * HCI mbuf tap routine
875  *
876  * copy packets to any raw HCI sockets that wish (and are
877  * permitted) to see them
878  */
879 void
880 hci_mtap(struct mbuf *m, struct hci_unit *unit)
881 {
882 	struct hci_pcb *pcb;
883 	struct mbuf *m0, *ctlmsg, **ctl;
884 	struct sockaddr_bt sa;
885 	uint8_t type;
886 	uint8_t event;
887 	uint16_t opcode;
888 
889 	KKASSERT(m->m_len >= sizeof(type));
890 
891 	type = *mtod(m, uint8_t *);
892 
893 	memset(&sa, 0, sizeof(sa));
894 	sa.bt_len = sizeof(struct sockaddr_bt);
895 	sa.bt_family = AF_BLUETOOTH;
896 	bdaddr_copy(&sa.bt_bdaddr, &unit->hci_bdaddr);
897 
898 	LIST_FOREACH(pcb, &hci_pcb, hp_next) {
899 		/*
900 		 * filter according to source address
901 		 */
902 		if ((pcb->hp_flags & HCI_PROMISCUOUS) == 0
903 		    && bdaddr_same(&pcb->hp_laddr, &sa.bt_bdaddr) == 0)
904 			continue;
905 
906 		/*
907 		 * filter according to packet type filter
908 		 */
909 		if (hci_filter_test(type, &pcb->hp_pfilter) == 0)
910 			continue;
911 
912 		/*
913 		 * filter according to event/security filters
914 		 */
915 		switch(type) {
916 		case HCI_EVENT_PKT:
917 			KKASSERT(m->m_len >= sizeof(hci_event_hdr_t));
918 
919 			event = mtod(m, hci_event_hdr_t *)->event;
920 
921 			if (hci_filter_test(event, &pcb->hp_efilter) == 0)
922 				continue;
923 
924 			if ((pcb->hp_flags & HCI_PRIVILEGED) == 0
925 			    && hci_security_check_event(event) == -1)
926 				continue;
927 			break;
928 
929 		case HCI_CMD_PKT:
930 			KKASSERT(m->m_len >= sizeof(hci_cmd_hdr_t));
931 
932 			opcode = letoh16(mtod(m, hci_cmd_hdr_t *)->opcode);
933 
934 			if ((pcb->hp_flags & HCI_PRIVILEGED) == 0
935 			    && hci_security_check_opcode(NULL, opcode) == -1)
936 				continue;
937 			break;
938 
939 		case HCI_ACL_DATA_PKT:
940 		case HCI_SCO_DATA_PKT:
941 		default:
942 			if ((pcb->hp_flags & HCI_PRIVILEGED) == 0)
943 				continue;
944 
945 			break;
946 		}
947 
948 		/*
949 		 * create control messages
950 		 */
951 		ctlmsg = NULL;
952 		ctl = &ctlmsg;
953 		if (pcb->hp_flags & HCI_DIRECTION) {
954 			int dir = m->m_flags & IFF_LINK0 ? 1 : 0;
955 
956 			*ctl = sbcreatecontrol((void *)&dir, sizeof(dir),
957 			    SCM_HCI_DIRECTION, BTPROTO_HCI);
958 
959 			if (*ctl != NULL)
960 				ctl = &((*ctl)->m_next);
961 		}
962 
963 		/*
964 		 * copy to socket
965 		 */
966 		m0 = m_copym(m, 0, M_COPYALL, MB_DONTWAIT);
967 		if (m0 && sbappendaddr(&pcb->hp_socket->so_rcv.sb,
968 				(struct sockaddr *)&sa, m0, ctlmsg)) {
969 			sorwakeup(pcb->hp_socket);
970 		} else {
971 			m_freem(ctlmsg);
972 			m_freem(m0);
973 		}
974 	}
975 }
976 
977 struct pr_usrreqs hci_usrreqs = {
978         .pru_abort = hci_sabort,
979         .pru_accept = pru_accept_notsupp,
980         .pru_attach = hci_sattach,
981         .pru_bind = hci_sbind,
982         .pru_connect = hci_sconnect,
983         .pru_connect2 = pru_connect2_notsupp,
984         .pru_control = hci_scontrol,
985         .pru_detach = hci_sdetach,
986         .pru_disconnect = hci_sdisconnect,
987         .pru_listen = pru_listen_notsupp,
988         .pru_peeraddr = hci_speeraddr,
989         .pru_rcvd = pru_rcvd_notsupp,
990         .pru_rcvoob = pru_rcvoob_notsupp,
991         .pru_send = hci_ssend,
992         .pru_sense = pru_sense_null,
993         .pru_shutdown = hci_sshutdown,
994         .pru_sockaddr = hci_ssockaddr,
995         .pru_sosend = sosend,
996         .pru_soreceive = soreceive
997 };
998