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 $ */
6 * Copyright (c) 2005 Iain Hibbert.
7 * Copyright (c) 2006 Itronix Inc.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
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.
35 /* load symbolic names */
36 #ifdef BLUETOOTH_DEBUG
41 #include <sys/param.h>
42 #include <sys/domain.h>
43 #include <sys/kernel.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>
53 #include <net/if_var.h>
54 #include <sys/sysctl.h>
55 #include <sys/thread2.h>
57 #include <netbt/bluetooth.h>
58 #include <netbt/hci.h>
60 /*******************************************************************************
62 * HCI SOCK_RAW Sockets - for control of Bluetooth Devices
67 * the raw HCI protocol control block
70 struct socket
*hp_socket
; /* socket */
71 unsigned int hp_flags
; /* flags */
72 bdaddr_t hp_laddr
; /* local address */
73 bdaddr_t hp_raddr
; /* remote address */
74 struct hci_filter hp_efilter
; /* user event filter */
75 struct hci_filter hp_pfilter
; /* user packet filter */
76 LIST_ENTRY(hci_pcb
) hp_next
; /* next HCI pcb */
80 #define HCI_PRIVILEGED (1<<0) /* no security filter for root */
81 #define HCI_DIRECTION (1<<1) /* direction control messages */
82 #define HCI_PROMISCUOUS (1<<2) /* listen to all units */
84 LIST_HEAD(hci_pcb_list
, hci_pcb
) hci_pcb
= LIST_HEAD_INITIALIZER(hci_pcb
);
87 int hci_sendspace
= HCI_CMD_PKT_SIZE
;
88 int hci_recvspace
= 4096;
90 extern struct pr_usrreqs hci_usrreqs
;
92 /* Prototypes for usrreqs methods. */
93 static int hci_sabort (struct socket
*so
);
94 static int hci_sdetach(struct socket
*so
);
95 static int hci_sdisconnect (struct socket
*so
);
96 static int hci_scontrol (struct socket
*so
, u_long cmd
, caddr_t data
,
97 struct ifnet
*ifp
, struct thread
*td
);
98 static int hci_sattach (struct socket
*so
, int proto
,
99 struct pru_attach_info
*ai
);
100 static int hci_sbind (struct socket
*so
, struct sockaddr
*nam
,
102 static int hci_sconnect (struct socket
*so
, struct sockaddr
*nam
,
104 static int hci_speeraddr (struct socket
*so
, struct sockaddr
**nam
);
105 static int hci_ssockaddr (struct socket
*so
, struct sockaddr
**nam
);
106 static int hci_sshutdown (struct socket
*so
);
107 static int hci_ssend (struct socket
*so
, int flags
, struct mbuf
*m
,
108 struct sockaddr
*addr
, struct mbuf
*control
,
111 /* supported commands opcode table */
112 static const struct {
114 uint8_t offs
; /* 0 - 63 */
115 uint8_t mask
; /* bit 0 - 7 */
116 int16_t length
; /* -1 if privileged */
119 0, 0x01, sizeof(hci_inquiry_cp
) },
120 { HCI_CMD_INQUIRY_CANCEL
,
122 { HCI_CMD_PERIODIC_INQUIRY
,
124 { HCI_CMD_EXIT_PERIODIC_INQUIRY
,
126 { HCI_CMD_CREATE_CON
,
128 { HCI_CMD_DISCONNECT
,
130 { HCI_CMD_ADD_SCO_CON
,
132 { HCI_CMD_CREATE_CON_CANCEL
,
134 { HCI_CMD_ACCEPT_CON
,
136 { HCI_CMD_REJECT_CON
,
138 { HCI_CMD_LINK_KEY_REP
,
140 { HCI_CMD_LINK_KEY_NEG_REP
,
142 { HCI_CMD_PIN_CODE_REP
,
144 { HCI_CMD_PIN_CODE_NEG_REP
,
146 { HCI_CMD_CHANGE_CON_PACKET_TYPE
,
150 { HCI_CMD_SET_CON_ENCRYPTION
,
152 { HCI_CMD_CHANGE_CON_LINK_KEY
,
154 { HCI_CMD_MASTER_LINK_KEY
,
156 { HCI_CMD_REMOTE_NAME_REQ
,
157 2, 0x08, sizeof(hci_remote_name_req_cp
) },
158 { HCI_CMD_REMOTE_NAME_REQ_CANCEL
,
160 { HCI_CMD_READ_REMOTE_FEATURES
,
161 2, 0x20, sizeof(hci_read_remote_features_cp
) },
162 { HCI_CMD_READ_REMOTE_EXTENDED_FEATURES
,
163 2, 0x40, sizeof(hci_read_remote_extended_features_cp
) },
164 { HCI_CMD_READ_REMOTE_VER_INFO
,
165 2, 0x80, sizeof(hci_read_remote_ver_info_cp
) },
166 { HCI_CMD_READ_CLOCK_OFFSET
,
167 3, 0x01, sizeof(hci_read_clock_offset_cp
) },
168 { HCI_CMD_READ_LMP_HANDLE
,
169 3, 0x02, sizeof(hci_read_lmp_handle_cp
) },
172 { HCI_CMD_SNIFF_MODE
,
174 { HCI_CMD_EXIT_SNIFF_MODE
,
178 { HCI_CMD_EXIT_PARK_MODE
,
182 { HCI_CMD_ROLE_DISCOVERY
,
183 4, 0x80, sizeof(hci_role_discovery_cp
) },
184 { HCI_CMD_SWITCH_ROLE
,
186 { HCI_CMD_READ_LINK_POLICY_SETTINGS
,
187 5, 0x02, sizeof(hci_read_link_policy_settings_cp
) },
188 { HCI_CMD_WRITE_LINK_POLICY_SETTINGS
,
190 { HCI_CMD_READ_DEFAULT_LINK_POLICY_SETTINGS
,
192 { HCI_CMD_WRITE_DEFAULT_LINK_POLICY_SETTINGS
,
194 { HCI_CMD_FLOW_SPECIFICATION
,
196 { HCI_CMD_SET_EVENT_MASK
,
200 { HCI_CMD_SET_EVENT_FILTER
,
204 { HCI_CMD_READ_PIN_TYPE
,
206 { HCI_CMD_WRITE_PIN_TYPE
,
208 { HCI_CMD_CREATE_NEW_UNIT_KEY
,
210 { HCI_CMD_READ_STORED_LINK_KEY
,
212 { HCI_CMD_WRITE_STORED_LINK_KEY
,
214 { HCI_CMD_DELETE_STORED_LINK_KEY
,
216 { HCI_CMD_WRITE_LOCAL_NAME
,
218 { HCI_CMD_READ_LOCAL_NAME
,
220 { HCI_CMD_READ_CON_ACCEPT_TIMEOUT
,
222 { HCI_CMD_WRITE_CON_ACCEPT_TIMEOUT
,
224 { HCI_CMD_READ_PAGE_TIMEOUT
,
226 { HCI_CMD_WRITE_PAGE_TIMEOUT
,
228 { HCI_CMD_READ_SCAN_ENABLE
,
230 { HCI_CMD_WRITE_SCAN_ENABLE
,
232 { HCI_CMD_READ_PAGE_SCAN_ACTIVITY
,
234 { HCI_CMD_WRITE_PAGE_SCAN_ACTIVITY
,
236 { HCI_CMD_READ_INQUIRY_SCAN_ACTIVITY
,
238 { HCI_CMD_WRITE_INQUIRY_SCAN_ACTIVITY
,
240 { HCI_CMD_READ_AUTH_ENABLE
,
242 { HCI_CMD_WRITE_AUTH_ENABLE
,
244 { HCI_CMD_READ_ENCRYPTION_MODE
,
246 { HCI_CMD_WRITE_ENCRYPTION_MODE
,
248 { HCI_CMD_READ_UNIT_CLASS
,
250 { HCI_CMD_WRITE_UNIT_CLASS
,
252 { HCI_CMD_READ_VOICE_SETTING
,
254 { HCI_CMD_WRITE_VOICE_SETTING
,
256 { HCI_CMD_READ_AUTO_FLUSH_TIMEOUT
,
257 9, 0x10, sizeof(hci_read_auto_flush_timeout_cp
) },
258 { HCI_CMD_WRITE_AUTO_FLUSH_TIMEOUT
,
260 { HCI_CMD_READ_NUM_BROADCAST_RETRANS
,
262 { HCI_CMD_WRITE_NUM_BROADCAST_RETRANS
,
264 { HCI_CMD_READ_HOLD_MODE_ACTIVITY
,
266 { HCI_CMD_WRITE_HOLD_MODE_ACTIVITY
,
268 { HCI_CMD_READ_XMIT_LEVEL
,
269 10, 0x04, sizeof(hci_read_xmit_level_cp
) },
270 { HCI_CMD_READ_SCO_FLOW_CONTROL
,
272 { HCI_CMD_WRITE_SCO_FLOW_CONTROL
,
274 { HCI_CMD_HC2H_FLOW_CONTROL
,
276 { HCI_CMD_HOST_BUFFER_SIZE
,
278 { HCI_CMD_HOST_NUM_COMPL_PKTS
,
280 { HCI_CMD_READ_LINK_SUPERVISION_TIMEOUT
,
281 11, 0x01, sizeof(hci_read_link_supervision_timeout_cp
) },
282 { HCI_CMD_WRITE_LINK_SUPERVISION_TIMEOUT
,
284 { HCI_CMD_READ_NUM_SUPPORTED_IAC
,
286 { HCI_CMD_READ_IAC_LAP
,
288 { HCI_CMD_WRITE_IAC_LAP
,
290 { HCI_CMD_READ_PAGE_SCAN_PERIOD
,
292 { HCI_CMD_WRITE_PAGE_SCAN_PERIOD
,
294 { HCI_CMD_READ_PAGE_SCAN
,
296 { HCI_CMD_WRITE_PAGE_SCAN
,
298 { HCI_CMD_SET_AFH_CLASSIFICATION
,
300 { HCI_CMD_READ_INQUIRY_SCAN_TYPE
,
302 { HCI_CMD_WRITE_INQUIRY_SCAN_TYPE
,
304 { HCI_CMD_READ_INQUIRY_MODE
,
306 { HCI_CMD_WRITE_INQUIRY_MODE
,
308 { HCI_CMD_READ_PAGE_SCAN_TYPE
,
310 { HCI_CMD_WRITE_PAGE_SCAN_TYPE
,
312 { HCI_CMD_READ_AFH_ASSESSMENT
,
314 { HCI_CMD_WRITE_AFH_ASSESSMENT
,
316 { HCI_CMD_READ_LOCAL_VER
,
318 { HCI_CMD_READ_LOCAL_COMMANDS
,
320 { HCI_CMD_READ_LOCAL_FEATURES
,
322 { HCI_CMD_READ_LOCAL_EXTENDED_FEATURES
,
323 14, 0x40, sizeof(hci_read_local_extended_features_cp
) },
324 { HCI_CMD_READ_BUFFER_SIZE
,
326 { HCI_CMD_READ_COUNTRY_CODE
,
328 { HCI_CMD_READ_BDADDR
,
330 { HCI_CMD_READ_FAILED_CONTACT_CNTR
,
331 15, 0x04, sizeof(hci_read_failed_contact_cntr_cp
) },
332 { HCI_CMD_RESET_FAILED_CONTACT_CNTR
,
334 { HCI_CMD_READ_LINK_QUALITY
,
335 15, 0x10, sizeof(hci_read_link_quality_cp
) },
337 15, 0x20, sizeof(hci_read_rssi_cp
) },
338 { HCI_CMD_READ_AFH_CHANNEL_MAP
,
339 15, 0x40, sizeof(hci_read_afh_channel_map_cp
) },
340 { HCI_CMD_READ_CLOCK
,
341 15, 0x80, sizeof(hci_read_clock_cp
) },
342 { HCI_CMD_READ_LOOPBACK_MODE
,
344 { HCI_CMD_WRITE_LOOPBACK_MODE
,
346 { HCI_CMD_ENABLE_UNIT_UNDER_TEST
,
348 { HCI_CMD_SETUP_SCO_CON
,
350 { HCI_CMD_ACCEPT_SCO_CON_REQ
,
352 { HCI_CMD_REJECT_SCO_CON_REQ
,
354 { HCI_CMD_READ_EXTENDED_INQUIRY_RSP
,
356 { HCI_CMD_WRITE_EXTENDED_INQUIRY_RSP
,
358 { HCI_CMD_REFRESH_ENCRYPTION_KEY
,
360 { HCI_CMD_SNIFF_SUBRATING
,
362 { HCI_CMD_READ_SIMPLE_PAIRING_MODE
,
364 { HCI_CMD_WRITE_SIMPLE_PAIRING_MODE
,
366 { HCI_CMD_READ_LOCAL_OOB_DATA
,
368 { HCI_CMD_READ_INQUIRY_RSP_XMIT_POWER
,
370 { HCI_CMD_WRITE_INQUIRY_RSP_XMIT_POWER
,
372 { HCI_CMD_READ_DEFAULT_ERRDATA_REPORTING
,
374 { HCI_CMD_WRITE_DEFAULT_ERRDATA_REPORTING
,
376 { HCI_CMD_IO_CAPABILITY_REP
,
378 { HCI_CMD_USER_CONFIRM_REP
,
380 { HCI_CMD_USER_CONFIRM_NEG_REP
,
382 { HCI_CMD_USER_PASSKEY_REP
,
384 { HCI_CMD_USER_PASSKEY_NEG_REP
,
386 { HCI_CMD_OOB_DATA_REP
,
388 { HCI_CMD_WRITE_SIMPLE_PAIRING_DEBUG_MODE
,
390 { HCI_CMD_ENHANCED_FLUSH
,
392 { HCI_CMD_OOB_DATA_NEG_REP
,
394 { HCI_CMD_SEND_KEYPRESS_NOTIFICATION
,
396 { HCI_CMD_IO_CAPABILITY_NEG_REP
,
401 * Security filter routines for unprivileged users.
402 * Allow all but a few critical events, and only permit read commands.
403 * If a unit is given, verify the command is supported.
407 hci_security_check_opcode(struct hci_unit
*unit
, uint16_t opcode
)
411 for (i
= 0 ; i
< sizeof(hci_cmds
) / sizeof(hci_cmds
[0]); i
++) {
412 if (opcode
!= hci_cmds
[i
].opcode
)
416 || (unit
->hci_cmds
[hci_cmds
[i
].offs
] & hci_cmds
[i
].mask
))
417 return hci_cmds
[i
].length
;
426 hci_security_check_event(uint8_t event
)
430 case HCI_EVENT_RETURN_LINK_KEYS
:
431 case HCI_EVENT_LINK_KEY_NOTIFICATION
:
432 case HCI_EVENT_USER_CONFIRM_REQ
:
433 case HCI_EVENT_USER_PASSKEY_NOTIFICATION
:
434 case HCI_EVENT_VENDOR
:
435 return -1; /* disallowed */
442 * When command packet reaches the device, we can drop
443 * it from the socket buffer (called from hci_output_acl)
448 struct socket
*so
= arg
;
450 sbdroprecord(&so
->so_snd
.sb
);
455 * HCI socket is going away and has some pending packets. We let them
456 * go by design, but remove the context pointer as it will be invalid
457 * and we no longer need to be notified.
460 hci_cmdwait_flush(struct socket
*so
)
462 struct hci_unit
*unit
;
466 DPRINTF("flushing %p\n", so
);
468 TAILQ_FOREACH(unit
, &hci_unit_list
, hci_next
) {
469 IF_POLL(&unit
->hci_cmdwait
, m
);
471 ctx
= M_GETCTX(m
, struct socket
*);
482 * This came from userland, so check it out.
485 hci_send(struct hci_pcb
*pcb
, struct mbuf
*m
, bdaddr_t
*addr
)
487 struct hci_unit
*unit
;
493 KKASSERT(addr
!= NULL
);
495 /* wants at least a header to start with */
496 if (m
->m_pkthdr
.len
< sizeof(hdr
)) {
500 m_copydata(m
, 0, sizeof(hdr
), (caddr_t
)&hdr
);
501 hdr
.opcode
= letoh16(hdr
.opcode
);
503 /* only allows CMD packets to be sent */
504 if (hdr
.type
!= HCI_CMD_PKT
) {
509 /* validates packet length */
510 if (m
->m_pkthdr
.len
!= sizeof(hdr
) + hdr
.length
) {
515 /* finds destination */
516 unit
= hci_unit_lookup(addr
);
522 /* security checks for unprivileged users */
523 if ((pcb
->hp_flags
& HCI_PRIVILEGED
) == 0
524 && hci_security_check_opcode(unit
, hdr
.opcode
) != hdr
.length
) {
529 /* makes a copy for precious to keep */
530 m0
= m_copym(m
, 0, M_COPYALL
, MB_DONTWAIT
);
535 sbappendrecord(&pcb
->hp_socket
->so_snd
.sb
, m0
);
536 M_SETCTX(m
, pcb
->hp_socket
); /* enable drop callback */
538 DPRINTFN(2, "(%s) opcode (%03x|%04x)\n",
539 device_get_nameunit(unit
->hci_dev
),
540 HCI_OGF(hdr
.opcode
), HCI_OCF(hdr
.opcode
));
543 if (unit
->hci_num_cmd_pkts
== 0)
544 IF_ENQUEUE(&unit
->hci_cmdwait
, m
);
546 hci_output_cmd(unit
, m
);
551 DPRINTF("packet (%d bytes) not sent (error %d)\n",
552 m
->m_pkthdr
.len
, err
);
558 * Implementation of usrreqs.
561 hci_sabort (struct socket
*so
)
563 /* struct hci_pcb *pcb = (struct hci_pcb *)so->so_pcb; */
565 soisdisconnected(so
);
566 return hci_sdetach(so
);
570 hci_sdetach(struct socket
*so
)
572 struct hci_pcb
*pcb
= (struct hci_pcb
*)so
->so_pcb
;
576 if (so
->so_snd
.ssb_mb
!= NULL
)
577 hci_cmdwait_flush(so
);
580 LIST_REMOVE(pcb
, hp_next
);
587 hci_sdisconnect (struct socket
*so
)
589 struct hci_pcb
*pcb
= (struct hci_pcb
*)so
->so_pcb
;
594 bdaddr_copy(&pcb
->hp_raddr
, BDADDR_ANY
);
596 * XXX We cannot call soisdisconnected() here, as it sets
597 * SS_CANTRCVMORE and SS_CANTSENDMORE. The problem is that
598 * soisconnected() does not clear these and if you try to reconnect
599 * this socket (which is permitted) you get a broken pipe when you
600 * try to write any data.
602 so
->so_state
&= ~SS_ISCONNECTED
;
608 hci_scontrol (struct socket
*so
, u_long cmd
, caddr_t data
, struct ifnet
*ifp
,
611 return hci_ioctl(cmd
, (void*)data
, NULL
);
615 hci_sattach (struct socket
*so
, int proto
, struct pru_attach_info
*ai
)
617 struct hci_pcb
*pcb
= (struct hci_pcb
*)so
->so_pcb
;
623 err
= soreserve(so
, hci_sendspace
, hci_recvspace
,NULL
);
627 pcb
= kmalloc(sizeof *pcb
, M_PCB
, M_NOWAIT
| M_ZERO
);
634 if (curproc
== NULL
|| priv_check(curthread
, PRIV_ROOT
) == 0)
635 pcb
->hp_flags
|= HCI_PRIVILEGED
;
638 * Set default user filter. By default, socket only passes
639 * Command_Complete and Command_Status Events.
641 hci_filter_set(HCI_EVENT_COMMAND_COMPL
, &pcb
->hp_efilter
);
642 hci_filter_set(HCI_EVENT_COMMAND_STATUS
, &pcb
->hp_efilter
);
643 hci_filter_set(HCI_EVENT_PKT
, &pcb
->hp_pfilter
);
646 LIST_INSERT_HEAD(&hci_pcb
, pcb
, hp_next
);
653 hci_sbind (struct socket
*so
, struct sockaddr
*nam
,
656 struct hci_pcb
*pcb
= (struct hci_pcb
*)so
->so_pcb
;
657 struct sockaddr_bt
*sa
;
659 KKASSERT(nam
!= NULL
);
660 sa
= (struct sockaddr_bt
*)nam
;
662 if (sa
->bt_len
!= sizeof(struct sockaddr_bt
))
665 if (sa
->bt_family
!= AF_BLUETOOTH
)
668 bdaddr_copy(&pcb
->hp_laddr
, &sa
->bt_bdaddr
);
670 if (bdaddr_any(&sa
->bt_bdaddr
))
671 pcb
->hp_flags
|= HCI_PROMISCUOUS
;
673 pcb
->hp_flags
&= ~HCI_PROMISCUOUS
;
679 hci_sconnect (struct socket
*so
, struct sockaddr
*nam
,
682 struct hci_pcb
*pcb
= (struct hci_pcb
*)so
->so_pcb
;
683 struct sockaddr_bt
*sa
;
684 KKASSERT(nam
!= NULL
);
685 sa
= (struct sockaddr_bt
*)nam
;
687 if (sa
->bt_len
!= sizeof(struct sockaddr_bt
))
690 if (sa
->bt_family
!= AF_BLUETOOTH
)
693 if (hci_unit_lookup(&sa
->bt_bdaddr
) == NULL
)
694 return EADDRNOTAVAIL
;
696 bdaddr_copy(&pcb
->hp_raddr
, &sa
->bt_bdaddr
);
703 hci_speeraddr (struct socket
*so
, struct sockaddr
**nam
)
705 struct hci_pcb
*pcb
= (struct hci_pcb
*)so
->so_pcb
;
706 struct sockaddr_bt
*sa
;
708 KKASSERT(nam
!= NULL
);
709 sa
= (struct sockaddr_bt
*)nam
;
711 memset(sa
, 0, sizeof(struct sockaddr_bt
));
712 sa
->bt_len
= sizeof(struct sockaddr_bt
);
713 sa
->bt_family
= AF_BLUETOOTH
;
714 bdaddr_copy(&sa
->bt_bdaddr
, &pcb
->hp_raddr
);
720 hci_ssockaddr (struct socket
*so
, struct sockaddr
**nam
)
722 struct hci_pcb
*pcb
= (struct hci_pcb
*)so
->so_pcb
;
723 struct sockaddr_bt
*sa
;
725 KKASSERT(nam
!= NULL
);
726 sa
= (struct sockaddr_bt
*)nam
;
728 memset(sa
, 0, sizeof(struct sockaddr_bt
));
729 sa
->bt_len
= sizeof(struct sockaddr_bt
);
730 sa
->bt_family
= AF_BLUETOOTH
;
731 bdaddr_copy(&sa
->bt_bdaddr
, &pcb
->hp_laddr
);
737 hci_sshutdown (struct socket
*so
)
744 hci_ssend (struct socket
*so
, int flags
, struct mbuf
*m
,
745 struct sockaddr
*addr
, struct mbuf
*control
,
749 struct hci_pcb
*pcb
= (struct hci_pcb
*)so
->so_pcb
;
750 struct sockaddr_bt
*sa
;
754 sa
= (struct sockaddr_bt
*)addr
;
756 if (sa
->bt_len
!= sizeof(struct sockaddr_bt
)) {
759 if (control
) m_freem(control
);
763 if (sa
->bt_family
!= AF_BLUETOOTH
) {
766 if (control
) m_freem(control
);
771 if (control
) /* have no use for this */
774 return hci_send(pcb
, m
, (sa
? &sa
->bt_bdaddr
: &pcb
->hp_raddr
));
778 * get/set socket options
781 hci_ctloutput (struct socket
*so
, struct sockopt
*sopt
)
783 struct hci_pcb
*pcb
= (struct hci_pcb
*)so
->so_pcb
;
787 #ifdef notyet /* XXX */
788 DPRINTFN(2, "req %s\n", prcorequests
[req
]);
794 if (sopt
->sopt_level
!= BTPROTO_HCI
)
797 switch(sopt
->sopt_dir
) {
799 switch (sopt
->sopt_name
) {
800 case SO_HCI_EVT_FILTER
:
801 soopt_from_kbuf(sopt
, &pcb
->hp_efilter
,
802 sizeof(struct hci_filter
));
805 case SO_HCI_PKT_FILTER
:
806 soopt_from_kbuf(sopt
, &pcb
->hp_pfilter
,
807 sizeof(struct hci_filter
));
810 case SO_HCI_DIRECTION
:
811 if (pcb
->hp_flags
& HCI_DIRECTION
)
815 soopt_from_kbuf(sopt
, &idir
, sizeof(int));
825 switch (sopt
->sopt_name
) {
826 case SO_HCI_EVT_FILTER
: /* set event filter */
827 err
= soopt_to_kbuf(sopt
, &pcb
->hp_efilter
,
828 sizeof(struct hci_filter
),
829 sizeof(struct hci_filter
));
832 case SO_HCI_PKT_FILTER
: /* set packet filter */
833 err
= soopt_to_kbuf(sopt
, &pcb
->hp_pfilter
,
834 sizeof(struct hci_filter
),
835 sizeof(struct hci_filter
));
838 case SO_HCI_DIRECTION
: /* request direction ctl messages */
839 err
= soopt_to_kbuf(sopt
, &idir
, sizeof(int),
843 pcb
->hp_flags
|= HCI_DIRECTION
;
845 pcb
->hp_flags
&= ~HCI_DIRECTION
;
863 * HCI mbuf tap routine
865 * copy packets to any raw HCI sockets that wish (and are
866 * permitted) to see them
869 hci_mtap(struct mbuf
*m
, struct hci_unit
*unit
)
872 struct mbuf
*m0
, *ctlmsg
, **ctl
;
873 struct sockaddr_bt sa
;
878 KKASSERT(m
->m_len
>= sizeof(type
));
880 type
= *mtod(m
, uint8_t *);
882 memset(&sa
, 0, sizeof(sa
));
883 sa
.bt_len
= sizeof(struct sockaddr_bt
);
884 sa
.bt_family
= AF_BLUETOOTH
;
885 bdaddr_copy(&sa
.bt_bdaddr
, &unit
->hci_bdaddr
);
887 LIST_FOREACH(pcb
, &hci_pcb
, hp_next
) {
889 * filter according to source address
891 if ((pcb
->hp_flags
& HCI_PROMISCUOUS
) == 0
892 && bdaddr_same(&pcb
->hp_laddr
, &sa
.bt_bdaddr
) == 0)
896 * filter according to packet type filter
898 if (hci_filter_test(type
, &pcb
->hp_pfilter
) == 0)
902 * filter according to event/security filters
906 KKASSERT(m
->m_len
>= sizeof(hci_event_hdr_t
));
908 event
= mtod(m
, hci_event_hdr_t
*)->event
;
910 if (hci_filter_test(event
, &pcb
->hp_efilter
) == 0)
913 if ((pcb
->hp_flags
& HCI_PRIVILEGED
) == 0
914 && hci_security_check_event(event
) == -1)
919 KKASSERT(m
->m_len
>= sizeof(hci_cmd_hdr_t
));
921 opcode
= letoh16(mtod(m
, hci_cmd_hdr_t
*)->opcode
);
923 if ((pcb
->hp_flags
& HCI_PRIVILEGED
) == 0
924 && hci_security_check_opcode(NULL
, opcode
) == -1)
928 case HCI_ACL_DATA_PKT
:
929 case HCI_SCO_DATA_PKT
:
931 if ((pcb
->hp_flags
& HCI_PRIVILEGED
) == 0)
938 * create control messages
942 if (pcb
->hp_flags
& HCI_DIRECTION
) {
943 int dir
= m
->m_flags
& IFF_LINK0
? 1 : 0;
945 *ctl
= sbcreatecontrol((void *)&dir
, sizeof(dir
),
946 SCM_HCI_DIRECTION
, BTPROTO_HCI
);
949 ctl
= &((*ctl
)->m_next
);
955 m0
= m_copym(m
, 0, M_COPYALL
, MB_DONTWAIT
);
956 if (m0
&& sbappendaddr(&pcb
->hp_socket
->so_rcv
.sb
,
957 (struct sockaddr
*)&sa
, m0
, ctlmsg
)) {
958 sorwakeup(pcb
->hp_socket
);
966 struct pr_usrreqs hci_usrreqs
= {
967 .pru_abort
= hci_sabort
,
968 .pru_accept
= pru_accept_notsupp
,
969 .pru_attach
= hci_sattach
,
970 .pru_bind
= hci_sbind
,
971 .pru_connect
= hci_sconnect
,
972 .pru_connect2
= pru_connect2_notsupp
,
973 .pru_control
= hci_scontrol
,
974 .pru_detach
= hci_sdetach
,
975 .pru_disconnect
= hci_sdisconnect
,
976 .pru_listen
= pru_listen_notsupp
,
977 .pru_peeraddr
= hci_speeraddr
,
978 .pru_rcvd
= pru_rcvd_notsupp
,
979 .pru_rcvoob
= pru_rcvoob_notsupp
,
980 .pru_send
= hci_ssend
,
981 .pru_sense
= pru_sense_null
,
982 .pru_shutdown
= hci_sshutdown
,
983 .pru_sockaddr
= hci_ssockaddr
,
984 .pru_sosend
= sosend
,
985 .pru_soreceive
= soreceive
,