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