Annotation of sys/netbt/hci_socket.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: hci_socket.c,v 1.3 2007/06/02 01:46:01 uwe Exp $ */
2: /* $NetBSD: hci_socket.c,v 1.10 2007/03/31 18:17:13 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: #include <sys/cdefs.h>
35:
36: /* load symbolic names */
37: #ifdef BLUETOOTH_DEBUG
38: #define PRUREQUESTS
39: #define PRCOREQUESTS
40: #endif
41:
42: #include <sys/param.h>
43: #include <sys/domain.h>
44: #include <sys/kernel.h>
45: #include <sys/mbuf.h>
46: #include <sys/proc.h>
47: #include <sys/protosw.h>
48: #include <sys/socket.h>
49: #include <sys/socketvar.h>
50: #include <sys/systm.h>
51:
52: #include <netbt/bluetooth.h>
53: #include <netbt/hci.h>
54:
55: /*******************************************************************************
56: *
57: * HCI SOCK_RAW Sockets - for control of Bluetooth Devices
58: *
59: */
60:
61: /*
62: * the raw HCI protocol control block
63: */
64: struct hci_pcb {
65: struct socket *hp_socket; /* socket */
66: unsigned int hp_flags; /* flags */
67: bdaddr_t hp_laddr; /* local address */
68: bdaddr_t hp_raddr; /* remote address */
69: struct hci_filter hp_efilter; /* user event filter */
70: struct hci_filter hp_pfilter; /* user packet filter */
71: LIST_ENTRY(hci_pcb) hp_next; /* next HCI pcb */
72: };
73:
74: /* hp_flags */
75: #define HCI_PRIVILEGED (1<<0) /* no security filter for root */
76: #define HCI_DIRECTION (1<<1) /* direction control messages */
77: #define HCI_PROMISCUOUS (1<<2) /* listen to all units */
78:
79: LIST_HEAD(hci_pcb_list, hci_pcb) hci_pcb = LIST_HEAD_INITIALIZER(hci_pcb);
80:
81: /* sysctl defaults */
82: int hci_sendspace = HCI_CMD_PKT_SIZE;
83: int hci_recvspace = 4096;
84:
85: /*
86: * Security filter routines for unprivileged users.
87: * Allow all but a few critical events, and only permit read commands.
88: */
89:
90: static int
91: hci_security_check_opcode(uint16_t opcode)
92: {
93:
94: switch (opcode) {
95: /* Link control */
96: case HCI_CMD_INQUIRY:
97: return sizeof(hci_inquiry_cp);
98: case HCI_CMD_REMOTE_NAME_REQ:
99: return sizeof(hci_remote_name_req_cp);
100: case HCI_CMD_READ_REMOTE_FEATURES:
101: return sizeof(hci_read_remote_features_cp);
102: case HCI_CMD_READ_REMOTE_EXTENDED_FEATURES:
103: return sizeof(hci_read_remote_extended_features_cp);
104: case HCI_CMD_READ_REMOTE_VER_INFO:
105: return sizeof(hci_read_remote_ver_info_cp);
106: case HCI_CMD_READ_CLOCK_OFFSET:
107: return sizeof(hci_read_clock_offset_cp);
108: case HCI_CMD_READ_LMP_HANDLE:
109: return sizeof(hci_read_lmp_handle_cp);
110:
111: /* Link policy */
112: case HCI_CMD_ROLE_DISCOVERY:
113: return sizeof(hci_role_discovery_cp);
114: case HCI_CMD_READ_LINK_POLICY_SETTINGS:
115: return sizeof(hci_read_link_policy_settings_cp);
116: case HCI_CMD_READ_DEFAULT_LINK_POLICY_SETTINGS:
117: return 0; /* No command parameters */
118:
119: /* Host controller and baseband */
120: case HCI_CMD_READ_PIN_TYPE:
121: case HCI_CMD_READ_LOCAL_NAME:
122: case HCI_CMD_READ_CON_ACCEPT_TIMEOUT:
123: case HCI_CMD_READ_PAGE_TIMEOUT:
124: case HCI_CMD_READ_SCAN_ENABLE:
125: case HCI_CMD_READ_PAGE_SCAN_ACTIVITY:
126: case HCI_CMD_READ_INQUIRY_SCAN_ACTIVITY:
127: case HCI_CMD_READ_AUTH_ENABLE:
128: case HCI_CMD_READ_ENCRYPTION_MODE:
129: case HCI_CMD_READ_UNIT_CLASS:
130: case HCI_CMD_READ_VOICE_SETTING:
131: return 0; /* No command parameters */
132: case HCI_CMD_READ_AUTO_FLUSH_TIMEOUT:
133: return sizeof(hci_read_auto_flush_timeout_cp);
134: case HCI_CMD_READ_NUM_BROADCAST_RETRANS:
135: case HCI_CMD_READ_HOLD_MODE_ACTIVITY:
136: return 0; /* No command parameters */
137: case HCI_CMD_READ_XMIT_LEVEL:
138: return sizeof(hci_read_xmit_level_cp);
139: case HCI_CMD_READ_SCO_FLOW_CONTROL:
140: return 0; /* No command parameters */
141: case HCI_CMD_READ_LINK_SUPERVISION_TIMEOUT:
142: return sizeof(hci_read_link_supervision_timeout_cp);
143: case HCI_CMD_READ_NUM_SUPPORTED_IAC:
144: case HCI_CMD_READ_IAC_LAP:
145: case HCI_CMD_READ_PAGE_SCAN_PERIOD:
146: case HCI_CMD_READ_PAGE_SCAN:
147: case HCI_CMD_READ_INQUIRY_SCAN_TYPE:
148: case HCI_CMD_READ_INQUIRY_MODE:
149: case HCI_CMD_READ_PAGE_SCAN_TYPE:
150: case HCI_CMD_READ_AFH_ASSESSMENT:
151: return 0; /* No command parameters */
152:
153: /* Informational */
154: case HCI_CMD_READ_LOCAL_VER:
155: case HCI_CMD_READ_LOCAL_COMMANDS:
156: case HCI_CMD_READ_LOCAL_FEATURES:
157: return 0; /* No command parameters */
158: case HCI_CMD_READ_LOCAL_EXTENDED_FEATURES:
159: return sizeof(hci_read_local_extended_features_cp);
160: case HCI_CMD_READ_BUFFER_SIZE:
161: case HCI_CMD_READ_COUNTRY_CODE:
162: case HCI_CMD_READ_BDADDR:
163: return 0; /* No command parameters */
164:
165: /* Status */
166: case HCI_CMD_READ_FAILED_CONTACT_CNTR:
167: return sizeof(hci_read_failed_contact_cntr_cp);
168: case HCI_CMD_READ_LINK_QUALITY:
169: return sizeof(hci_read_link_quality_cp);
170: case HCI_CMD_READ_RSSI:
171: return sizeof(hci_read_rssi_cp);
172: case HCI_CMD_READ_AFH_CHANNEL_MAP:
173: return sizeof(hci_read_afh_channel_map_cp);
174: case HCI_CMD_READ_CLOCK:
175: return sizeof(hci_read_clock_cp);
176:
177: /* Testing */
178: case HCI_CMD_READ_LOOPBACK_MODE:
179: return 0; /* No command parameters */
180: }
181:
182: return -1; /* disallowed */
183: }
184:
185: static int
186: hci_security_check_event(uint8_t event)
187: {
188:
189: switch (event) {
190: case HCI_EVENT_RETURN_LINK_KEYS:
191: case HCI_EVENT_LINK_KEY_NOTIFICATION:
192: case HCI_EVENT_VENDOR:
193: return -1; /* disallowed */
194: }
195:
196: return 0; /* ok */
197: }
198:
199: /*
200: * When command packet reaches the device, we can drop
201: * it from the socket buffer (called from hci_output_acl)
202: */
203: void
204: hci_drop(void *arg)
205: {
206: struct socket *so = arg;
207:
208: sbdroprecord(&so->so_snd);
209: sowwakeup(so);
210: }
211:
212: /*
213: * HCI socket is going away and has some pending packets. We let them
214: * go by design, but remove the context pointer as it will be invalid
215: * and we no longer need to be notified.
216: */
217: static void
218: hci_cmdwait_flush(struct socket *so)
219: {
220: struct hci_unit *unit;
221: struct socket *ctx;
222: struct mbuf *m;
223:
224: DPRINTF("flushing %p\n", so);
225:
226: TAILQ_FOREACH(unit, &hci_unit_list, hci_next) {
227: IF_POLL(&unit->hci_cmdwait, m);
228: while (m != NULL) {
229: ctx = M_GETCTX(m, struct socket *);
230: if (ctx == so)
231: M_SETCTX(m, NULL);
232:
233: m = m->m_nextpkt;
234: }
235: }
236: }
237:
238: /*
239: * HCI send packet
240: * This came from userland, so check it out.
241: */
242: static int
243: hci_send(struct hci_pcb *pcb, struct mbuf *m, bdaddr_t *addr)
244: {
245: struct hci_unit *unit;
246: struct mbuf *m0;
247: hci_cmd_hdr_t hdr;
248: int err;
249:
250: KASSERT(m != NULL);
251: KASSERT(addr != NULL);
252:
253: /* wants at least a header to start with */
254: if (m->m_pkthdr.len < sizeof(hdr)) {
255: err = EMSGSIZE;
256: goto bad;
257: }
258: m_copydata(m, 0, sizeof(hdr), (caddr_t)&hdr);
259:
260: /* only allows CMD packets to be sent */
261: if (hdr.type != HCI_CMD_PKT) {
262: err = EINVAL;
263: goto bad;
264: }
265:
266: /* validates packet length */
267: if (m->m_pkthdr.len != sizeof(hdr) + hdr.length) {
268: err = EMSGSIZE;
269: goto bad;
270: }
271:
272: /* security checks for unprivileged users */
273: if ((pcb->hp_flags & HCI_PRIVILEGED) == 0
274: && hci_security_check_opcode(letoh16(hdr.opcode)) != hdr.length) {
275: err = EPERM;
276: goto bad;
277: }
278:
279: /* finds destination */
280: unit = hci_unit_lookup(addr);
281: if (unit == NULL) {
282: err = ENETDOWN;
283: goto bad;
284: }
285:
286: /* makes a copy for precious to keep */
287: m0 = m_copym(m, 0, M_COPYALL, M_DONTWAIT);
288: if (m0 == NULL) {
289: err = ENOMEM;
290: goto bad;
291: }
292: sbappendrecord(&pcb->hp_socket->so_snd, m0);
293: M_SETCTX(m, pcb->hp_socket); /* enable drop callback */
294:
295: DPRINTFN(2, "(%s) opcode (%03x|%04x)\n", unit->hci_devname,
296: HCI_OGF(letoh16(hdr.opcode)), HCI_OCF(letoh16(hdr.opcode)));
297:
298: /* Sendss it */
299: if (unit->hci_num_cmd_pkts == 0)
300: IF_ENQUEUE(&unit->hci_cmdwait, m);
301: else
302: hci_output_cmd(unit, m);
303:
304: return 0;
305:
306: bad:
307: DPRINTF("packet (%d bytes) not sent (error %d)\n",
308: m->m_pkthdr.len, err);
309: if (m) m_freem(m);
310: return err;
311: }
312:
313: /*
314: * User Request.
315: * up is socket
316: * m is either
317: * optional mbuf chain containing message
318: * ioctl command (PRU_CONTROL)
319: * nam is either
320: * optional mbuf chain containing an address
321: * ioctl data (PRU_CONTROL)
322: * optionally, protocol number (PRU_ATTACH)
323: * ctl is optional mbuf chain containing socket options
324: * l is pointer to process requesting action (if any)
325: *
326: * we are responsible for disposing of m and ctl if
327: * they are mbuf chains
328: */
329: int
330: hci_usrreq(struct socket *up, int req, struct mbuf *m,
331: struct mbuf *nam, struct mbuf *ctl)
332: {
333: struct hci_pcb *pcb = (struct hci_pcb *)up->so_pcb;
334: struct sockaddr_bt *sa;
335: int err = 0;
336:
337: #ifdef notyet /* XXX */
338: DPRINTFN(2, "%s\n", prurequests[req]);
339: #endif
340:
341: switch(req) {
342: case PRU_CONTROL:
343: return hci_ioctl((unsigned long)m, (void *)nam, curproc);
344:
345: case PRU_ATTACH:
346: if (pcb)
347: return EINVAL;
348:
349: err = soreserve(up, hci_sendspace, hci_recvspace);
350: if (err)
351: return err;
352:
353: pcb = malloc(sizeof *pcb, M_PCB, M_NOWAIT);
354: if (pcb == NULL)
355: return ENOMEM;
356: bzero(pcb, sizeof *pcb);
357:
358: up->so_pcb = pcb;
359: pcb->hp_socket = up;
360:
361: if (curproc == NULL || suser(curproc, 0) == 0)
362: pcb->hp_flags |= HCI_PRIVILEGED;
363:
364: /*
365: * Set default user filter. By default, socket only passes
366: * Command_Complete and Command_Status Events.
367: */
368: hci_filter_set(HCI_EVENT_COMMAND_COMPL, &pcb->hp_efilter);
369: hci_filter_set(HCI_EVENT_COMMAND_STATUS, &pcb->hp_efilter);
370: hci_filter_set(HCI_EVENT_PKT, &pcb->hp_pfilter);
371:
372: LIST_INSERT_HEAD(&hci_pcb, pcb, hp_next);
373:
374: return 0;
375: }
376:
377: /* anything after here *requires* a pcb */
378: if (pcb == NULL) {
379: err = EINVAL;
380: goto release;
381: }
382:
383: switch(req) {
384: case PRU_DISCONNECT:
385: bdaddr_copy(&pcb->hp_raddr, BDADDR_ANY);
386:
387: /* XXX we cannot call soisdisconnected() here, as it sets
388: * SS_CANTRCVMORE and SS_CANTSENDMORE. The problem being,
389: * that soisconnected() does not clear these and if you
390: * try to reconnect this socket (which is permitted) you
391: * get a broken pipe when you try to write any data.
392: */
393: up->so_state &= ~SS_ISCONNECTED;
394: break;
395:
396: case PRU_ABORT:
397: soisdisconnected(up);
398: /* fall through to */
399: case PRU_DETACH:
400: if (up->so_snd.sb_mb != NULL)
401: hci_cmdwait_flush(up);
402:
403: up->so_pcb = NULL;
404: LIST_REMOVE(pcb, hp_next);
405: free(pcb, M_PCB);
406: return 0;
407:
408: case PRU_BIND:
409: KASSERT(nam != NULL);
410: sa = mtod(nam, struct sockaddr_bt *);
411:
412: if (sa->bt_len != sizeof(struct sockaddr_bt))
413: return EINVAL;
414:
415: if (sa->bt_family != AF_BLUETOOTH)
416: return EAFNOSUPPORT;
417:
418: bdaddr_copy(&pcb->hp_laddr, &sa->bt_bdaddr);
419:
420: if (bdaddr_any(&sa->bt_bdaddr))
421: pcb->hp_flags |= HCI_PROMISCUOUS;
422: else
423: pcb->hp_flags &= ~HCI_PROMISCUOUS;
424:
425: return 0;
426:
427: case PRU_CONNECT:
428: KASSERT(nam != NULL);
429: sa = mtod(nam, struct sockaddr_bt *);
430:
431: if (sa->bt_len != sizeof(struct sockaddr_bt))
432: return EINVAL;
433:
434: if (sa->bt_family != AF_BLUETOOTH)
435: return EAFNOSUPPORT;
436:
437: if (hci_unit_lookup(&sa->bt_bdaddr) == NULL)
438: return EADDRNOTAVAIL;
439:
440: bdaddr_copy(&pcb->hp_raddr, &sa->bt_bdaddr);
441: soisconnected(up);
442: return 0;
443:
444: case PRU_PEERADDR:
445: KASSERT(nam != NULL);
446: sa = mtod(nam, struct sockaddr_bt *);
447:
448: memset(sa, 0, sizeof(struct sockaddr_bt));
449: nam->m_len =
450: sa->bt_len = sizeof(struct sockaddr_bt);
451: sa->bt_family = AF_BLUETOOTH;
452: bdaddr_copy(&sa->bt_bdaddr, &pcb->hp_raddr);
453: return 0;
454:
455: case PRU_SOCKADDR:
456: KASSERT(nam != NULL);
457: sa = mtod(nam, struct sockaddr_bt *);
458:
459: memset(sa, 0, sizeof(struct sockaddr_bt));
460: nam->m_len =
461: sa->bt_len = sizeof(struct sockaddr_bt);
462: sa->bt_family = AF_BLUETOOTH;
463: bdaddr_copy(&sa->bt_bdaddr, &pcb->hp_laddr);
464: return 0;
465:
466: case PRU_SHUTDOWN:
467: socantsendmore(up);
468: break;
469:
470: case PRU_SEND:
471: sa = NULL;
472: if (nam) {
473: sa = mtod(nam, struct sockaddr_bt *);
474:
475: if (sa->bt_len != sizeof(struct sockaddr_bt)) {
476: err = EINVAL;
477: goto release;
478: }
479:
480: if (sa->bt_family != AF_BLUETOOTH) {
481: err = EAFNOSUPPORT;
482: goto release;
483: }
484: }
485:
486: if (ctl) /* have no use for this */
487: m_freem(ctl);
488:
489: return hci_send(pcb, m, (sa ? &sa->bt_bdaddr : &pcb->hp_raddr));
490:
491: case PRU_SENSE:
492: return 0; /* (no sense - Doh!) */
493:
494: case PRU_RCVD:
495: case PRU_RCVOOB:
496: return EOPNOTSUPP; /* (no release) */
497:
498: case PRU_ACCEPT:
499: case PRU_CONNECT2:
500: case PRU_LISTEN:
501: case PRU_SENDOOB:
502: case PRU_FASTTIMO:
503: case PRU_SLOWTIMO:
504: case PRU_PROTORCV:
505: case PRU_PROTOSEND:
506: err = EOPNOTSUPP;
507: break;
508:
509: default:
510: UNKNOWN(req);
511: err = EOPNOTSUPP;
512: break;
513: }
514:
515: release:
516: if (m)
517: m_freem(m);
518: if (ctl)
519: m_freem(ctl);
520: return err;
521: }
522:
523: /*
524: * get/set socket options
525: */
526: int
527: hci_ctloutput(int req, struct socket *so, int level,
528: int optname, struct mbuf **opt)
529: {
530: struct hci_pcb *pcb = (struct hci_pcb *)so->so_pcb;
531: struct mbuf *m;
532: int err = 0;
533:
534: #ifdef notyet /* XXX */
535: DPRINTFN(2, "req %s\n", prcorequests[req]);
536: #endif
537:
538: if (pcb == NULL)
539: return EINVAL;
540:
541: if (level != BTPROTO_HCI)
542: return ENOPROTOOPT;
543:
544: switch(req) {
545: case PRCO_GETOPT:
546: m = m_get(M_WAIT, MT_SOOPTS);
547: switch (optname) {
548: case SO_HCI_EVT_FILTER:
549: m->m_len = sizeof(struct hci_filter);
550: memcpy(mtod(m, void *), &pcb->hp_efilter, m->m_len);
551: break;
552:
553: case SO_HCI_PKT_FILTER:
554: m->m_len = sizeof(struct hci_filter);
555: memcpy(mtod(m, void *), &pcb->hp_pfilter, m->m_len);
556: break;
557:
558: case SO_HCI_DIRECTION:
559: m->m_len = sizeof(int);
560: if (pcb->hp_flags & HCI_DIRECTION)
561: *mtod(m, int *) = 1;
562: else
563: *mtod(m, int *) = 0;
564: break;
565:
566: default:
567: err = ENOPROTOOPT;
568: m_freem(m);
569: m = NULL;
570: break;
571: }
572: *opt = m;
573: break;
574:
575: case PRCO_SETOPT:
576: m = *opt;
577: if (m) switch (optname) {
578: case SO_HCI_EVT_FILTER: /* set event filter */
579: m->m_len = min(m->m_len, sizeof(struct hci_filter));
580: memcpy(&pcb->hp_efilter, mtod(m, void *), m->m_len);
581: break;
582:
583: case SO_HCI_PKT_FILTER: /* set packet filter */
584: m->m_len = min(m->m_len, sizeof(struct hci_filter));
585: memcpy(&pcb->hp_pfilter, mtod(m, void *), m->m_len);
586: break;
587:
588: case SO_HCI_DIRECTION: /* request direction ctl messages */
589: if (*mtod(m, int *))
590: pcb->hp_flags |= HCI_DIRECTION;
591: else
592: pcb->hp_flags &= ~HCI_DIRECTION;
593: break;
594:
595: default:
596: err = ENOPROTOOPT;
597: break;
598: }
599: m_freem(m);
600: break;
601:
602: default:
603: err = ENOPROTOOPT;
604: break;
605: }
606:
607: return err;
608: }
609:
610: /*
611: * HCI mbuf tap routine
612: *
613: * copy packets to any raw HCI sockets that wish (and are
614: * permitted) to see them
615: */
616: void
617: hci_mtap(struct mbuf *m, struct hci_unit *unit)
618: {
619: struct hci_pcb *pcb;
620: struct mbuf *m0, *ctlmsg, **ctl;
621: struct sockaddr_bt sa;
622: uint8_t type;
623: uint8_t event;
624: uint16_t opcode;
625:
626: KASSERT(m->m_len >= sizeof(type));
627:
628: type = *mtod(m, uint8_t *);
629:
630: memset(&sa, 0, sizeof(sa));
631: sa.bt_len = sizeof(struct sockaddr_bt);
632: sa.bt_family = AF_BLUETOOTH;
633: bdaddr_copy(&sa.bt_bdaddr, &unit->hci_bdaddr);
634:
635: LIST_FOREACH(pcb, &hci_pcb, hp_next) {
636: /*
637: * filter according to source address
638: */
639: if ((pcb->hp_flags & HCI_PROMISCUOUS) == 0
640: && bdaddr_same(&pcb->hp_laddr, &sa.bt_bdaddr) == 0)
641: continue;
642:
643: /*
644: * filter according to packet type filter
645: */
646: if (hci_filter_test(type, &pcb->hp_pfilter) == 0)
647: continue;
648:
649: /*
650: * filter according to event/security filters
651: */
652: switch(type) {
653: case HCI_EVENT_PKT:
654: KASSERT(m->m_len >= sizeof(hci_event_hdr_t));
655:
656: event = mtod(m, hci_event_hdr_t *)->event;
657:
658: if (hci_filter_test(event, &pcb->hp_efilter) == 0)
659: continue;
660:
661: if ((pcb->hp_flags & HCI_PRIVILEGED) == 0
662: && hci_security_check_event(event) == -1)
663: continue;
664: break;
665:
666: case HCI_CMD_PKT:
667: KASSERT(m->m_len >= sizeof(hci_cmd_hdr_t));
668:
669: opcode = letoh16(mtod(m, hci_cmd_hdr_t *)->opcode);
670:
671: if ((pcb->hp_flags & HCI_PRIVILEGED) == 0
672: && hci_security_check_opcode(opcode) == -1)
673: continue;
674: break;
675:
676: case HCI_ACL_DATA_PKT:
677: case HCI_SCO_DATA_PKT:
678: default:
679: if ((pcb->hp_flags & HCI_PRIVILEGED) == 0)
680: continue;
681:
682: break;
683: }
684:
685: /*
686: * create control messages
687: */
688: ctlmsg = NULL;
689: ctl = &ctlmsg;
690: if (pcb->hp_flags & HCI_DIRECTION) {
691: int dir = m->m_flags & M_LINK0 ? 1 : 0;
692:
693: *ctl = sbcreatecontrol((void *)&dir, sizeof(dir),
694: SCM_HCI_DIRECTION, BTPROTO_HCI);
695:
696: if (*ctl != NULL)
697: ctl = &((*ctl)->m_next);
698: }
699:
700: /*
701: * copy to socket
702: */
703: m0 = m_copym(m, 0, M_COPYALL, M_DONTWAIT);
704: if (m0 && sbappendaddr(&pcb->hp_socket->so_rcv,
705: (struct sockaddr *)&sa, m0, ctlmsg)) {
706: sorwakeup(pcb->hp_socket);
707: } else {
708: m_freem(ctlmsg);
709: m_freem(m0);
710: }
711: }
712: }
CVSweb