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