1 /* 2 * ng_btsocket_hci_raw.c 3 */ 4 5 /*- 6 * Copyright (c) 2001-2002 Maksim Yevmenkin <m_evmenkin@yahoo.com> 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 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 * 30 * $Id: ng_btsocket_hci_raw.c,v 1.14 2003/09/14 23:29:06 max Exp $ 31 * $FreeBSD$ 32 */ 33 34 #include <sys/param.h> 35 #include <sys/systm.h> 36 #include <sys/bitstring.h> 37 #include <sys/domain.h> 38 #include <sys/endian.h> 39 #include <sys/errno.h> 40 #include <sys/filedesc.h> 41 #include <sys/ioccom.h> 42 #include <sys/kernel.h> 43 #include <sys/lock.h> 44 #include <sys/malloc.h> 45 #include <sys/mbuf.h> 46 #include <sys/mutex.h> 47 #include <sys/priv.h> 48 #include <sys/protosw.h> 49 #include <sys/queue.h> 50 #include <sys/socket.h> 51 #include <sys/socketvar.h> 52 #include <sys/sysctl.h> 53 #include <sys/taskqueue.h> 54 55 #include <net/vnet.h> 56 57 #include <netgraph/ng_message.h> 58 #include <netgraph/netgraph.h> 59 #include <netgraph/bluetooth/include/ng_bluetooth.h> 60 #include <netgraph/bluetooth/include/ng_hci.h> 61 #include <netgraph/bluetooth/include/ng_l2cap.h> 62 #include <netgraph/bluetooth/include/ng_btsocket.h> 63 #include <netgraph/bluetooth/include/ng_btsocket_hci_raw.h> 64 65 /* MALLOC define */ 66 #ifdef NG_SEPARATE_MALLOC 67 static MALLOC_DEFINE(M_NETGRAPH_BTSOCKET_HCI_RAW, "netgraph_btsocks_hci_raw", 68 "Netgraph Bluetooth raw HCI sockets"); 69 #else 70 #define M_NETGRAPH_BTSOCKET_HCI_RAW M_NETGRAPH 71 #endif /* NG_SEPARATE_MALLOC */ 72 73 /* Netgraph node methods */ 74 static ng_constructor_t ng_btsocket_hci_raw_node_constructor; 75 static ng_rcvmsg_t ng_btsocket_hci_raw_node_rcvmsg; 76 static ng_shutdown_t ng_btsocket_hci_raw_node_shutdown; 77 static ng_newhook_t ng_btsocket_hci_raw_node_newhook; 78 static ng_connect_t ng_btsocket_hci_raw_node_connect; 79 static ng_rcvdata_t ng_btsocket_hci_raw_node_rcvdata; 80 static ng_disconnect_t ng_btsocket_hci_raw_node_disconnect; 81 82 static void ng_btsocket_hci_raw_input (void *, int); 83 static void ng_btsocket_hci_raw_output(node_p, hook_p, void *, int); 84 static void ng_btsocket_hci_raw_savctl(ng_btsocket_hci_raw_pcb_p, 85 struct mbuf **, 86 struct mbuf *); 87 static int ng_btsocket_hci_raw_filter(ng_btsocket_hci_raw_pcb_p, 88 struct mbuf *, int); 89 90 #define ng_btsocket_hci_raw_wakeup_input_task() \ 91 taskqueue_enqueue(taskqueue_swi, &ng_btsocket_hci_raw_task) 92 93 /* Security filter */ 94 struct ng_btsocket_hci_raw_sec_filter { 95 bitstr_t bit_decl(events, 0xff); 96 bitstr_t bit_decl(commands[0x3f], 0x3ff); 97 }; 98 99 /* Netgraph type descriptor */ 100 static struct ng_type typestruct = { 101 .version = NG_ABI_VERSION, 102 .name = NG_BTSOCKET_HCI_RAW_NODE_TYPE, 103 .constructor = ng_btsocket_hci_raw_node_constructor, 104 .rcvmsg = ng_btsocket_hci_raw_node_rcvmsg, 105 .shutdown = ng_btsocket_hci_raw_node_shutdown, 106 .newhook = ng_btsocket_hci_raw_node_newhook, 107 .connect = ng_btsocket_hci_raw_node_connect, 108 .rcvdata = ng_btsocket_hci_raw_node_rcvdata, 109 .disconnect = ng_btsocket_hci_raw_node_disconnect, 110 }; 111 112 /* Globals */ 113 static u_int32_t ng_btsocket_hci_raw_debug_level; 114 static u_int32_t ng_btsocket_hci_raw_ioctl_timeout; 115 static node_p ng_btsocket_hci_raw_node; 116 static struct ng_bt_itemq ng_btsocket_hci_raw_queue; 117 static struct mtx ng_btsocket_hci_raw_queue_mtx; 118 static struct task ng_btsocket_hci_raw_task; 119 static LIST_HEAD(, ng_btsocket_hci_raw_pcb) ng_btsocket_hci_raw_sockets; 120 static struct mtx ng_btsocket_hci_raw_sockets_mtx; 121 static u_int32_t ng_btsocket_hci_raw_token; 122 static struct mtx ng_btsocket_hci_raw_token_mtx; 123 static struct ng_btsocket_hci_raw_sec_filter *ng_btsocket_hci_raw_sec_filter; 124 static struct timeval ng_btsocket_hci_raw_lasttime; 125 static int ng_btsocket_hci_raw_curpps; 126 127 /* Sysctl tree */ 128 SYSCTL_DECL(_net_bluetooth_hci_sockets); 129 static SYSCTL_NODE(_net_bluetooth_hci_sockets, OID_AUTO, raw, CTLFLAG_RW, 130 0, "Bluetooth raw HCI sockets family"); 131 SYSCTL_UINT(_net_bluetooth_hci_sockets_raw, OID_AUTO, debug_level, CTLFLAG_RW, 132 &ng_btsocket_hci_raw_debug_level, NG_BTSOCKET_WARN_LEVEL, 133 "Bluetooth raw HCI sockets debug level"); 134 SYSCTL_UINT(_net_bluetooth_hci_sockets_raw, OID_AUTO, ioctl_timeout, CTLFLAG_RW, 135 &ng_btsocket_hci_raw_ioctl_timeout, 5, 136 "Bluetooth raw HCI sockets ioctl timeout"); 137 SYSCTL_UINT(_net_bluetooth_hci_sockets_raw, OID_AUTO, queue_len, CTLFLAG_RD, 138 &ng_btsocket_hci_raw_queue.len, 0, 139 "Bluetooth raw HCI sockets input queue length"); 140 SYSCTL_UINT(_net_bluetooth_hci_sockets_raw, OID_AUTO, queue_maxlen, CTLFLAG_RD, 141 &ng_btsocket_hci_raw_queue.maxlen, 0, 142 "Bluetooth raw HCI sockets input queue max. length"); 143 SYSCTL_UINT(_net_bluetooth_hci_sockets_raw, OID_AUTO, queue_drops, CTLFLAG_RD, 144 &ng_btsocket_hci_raw_queue.drops, 0, 145 "Bluetooth raw HCI sockets input queue drops"); 146 147 /* Debug */ 148 #define NG_BTSOCKET_HCI_RAW_INFO \ 149 if (ng_btsocket_hci_raw_debug_level >= NG_BTSOCKET_INFO_LEVEL && \ 150 ppsratecheck(&ng_btsocket_hci_raw_lasttime, &ng_btsocket_hci_raw_curpps, 1)) \ 151 printf 152 153 #define NG_BTSOCKET_HCI_RAW_WARN \ 154 if (ng_btsocket_hci_raw_debug_level >= NG_BTSOCKET_WARN_LEVEL && \ 155 ppsratecheck(&ng_btsocket_hci_raw_lasttime, &ng_btsocket_hci_raw_curpps, 1)) \ 156 printf 157 158 #define NG_BTSOCKET_HCI_RAW_ERR \ 159 if (ng_btsocket_hci_raw_debug_level >= NG_BTSOCKET_ERR_LEVEL && \ 160 ppsratecheck(&ng_btsocket_hci_raw_lasttime, &ng_btsocket_hci_raw_curpps, 1)) \ 161 printf 162 163 #define NG_BTSOCKET_HCI_RAW_ALERT \ 164 if (ng_btsocket_hci_raw_debug_level >= NG_BTSOCKET_ALERT_LEVEL && \ 165 ppsratecheck(&ng_btsocket_hci_raw_lasttime, &ng_btsocket_hci_raw_curpps, 1)) \ 166 printf 167 168 /**************************************************************************** 169 **************************************************************************** 170 ** Netgraph specific 171 **************************************************************************** 172 ****************************************************************************/ 173 174 /* 175 * Netgraph node constructor. Do not allow to create node of this type. 176 */ 177 178 static int 179 ng_btsocket_hci_raw_node_constructor(node_p node) 180 { 181 return (EINVAL); 182 } /* ng_btsocket_hci_raw_node_constructor */ 183 184 /* 185 * Netgraph node destructor. Just let old node go and create new fresh one. 186 */ 187 188 static int 189 ng_btsocket_hci_raw_node_shutdown(node_p node) 190 { 191 int error = 0; 192 193 NG_NODE_UNREF(node); 194 195 error = ng_make_node_common(&typestruct, &ng_btsocket_hci_raw_node); 196 if (error != 0) { 197 NG_BTSOCKET_HCI_RAW_ALERT( 198 "%s: Could not create Netgraph node, error=%d\n", __func__, error); 199 200 ng_btsocket_hci_raw_node = NULL; 201 202 return (ENOMEM); 203 } 204 205 error = ng_name_node(ng_btsocket_hci_raw_node, 206 NG_BTSOCKET_HCI_RAW_NODE_TYPE); 207 if (error != 0) { 208 NG_BTSOCKET_HCI_RAW_ALERT( 209 "%s: Could not name Netgraph node, error=%d\n", __func__, error); 210 211 NG_NODE_UNREF(ng_btsocket_hci_raw_node); 212 ng_btsocket_hci_raw_node = NULL; 213 214 return (EINVAL); 215 } 216 217 return (0); 218 } /* ng_btsocket_hci_raw_node_shutdown */ 219 220 /* 221 * Create new hook. Just say "yes" 222 */ 223 224 static int 225 ng_btsocket_hci_raw_node_newhook(node_p node, hook_p hook, char const *name) 226 { 227 return (0); 228 } /* ng_btsocket_hci_raw_node_newhook */ 229 230 /* 231 * Connect hook. Just say "yes" 232 */ 233 234 static int 235 ng_btsocket_hci_raw_node_connect(hook_p hook) 236 { 237 return (0); 238 } /* ng_btsocket_hci_raw_node_connect */ 239 240 /* 241 * Disconnect hook 242 */ 243 244 static int 245 ng_btsocket_hci_raw_node_disconnect(hook_p hook) 246 { 247 return (0); 248 } /* ng_btsocket_hci_raw_node_disconnect */ 249 250 /* 251 * Receive control message. 252 * Make sure it is a message from HCI node and it is a response. 253 * Enqueue item and schedule input task. 254 */ 255 256 static int 257 ng_btsocket_hci_raw_node_rcvmsg(node_p node, item_p item, hook_p lasthook) 258 { 259 struct ng_mesg *msg = NGI_MSG(item); /* item still has message */ 260 int error = 0; 261 262 /* 263 * Check for empty sockets list creates LOR when both sender and 264 * receiver device are connected to the same host, so remove it 265 * for now 266 */ 267 268 if (msg != NULL && 269 (msg->header.typecookie == NGM_HCI_COOKIE || 270 msg->header.typecookie == NGM_GENERIC_COOKIE) && 271 msg->header.flags & NGF_RESP) { 272 if (msg->header.token == 0) { 273 NG_FREE_ITEM(item); 274 return (0); 275 } 276 277 mtx_lock(&ng_btsocket_hci_raw_queue_mtx); 278 if (NG_BT_ITEMQ_FULL(&ng_btsocket_hci_raw_queue)) { 279 NG_BTSOCKET_HCI_RAW_ERR( 280 "%s: Input queue is full\n", __func__); 281 282 NG_BT_ITEMQ_DROP(&ng_btsocket_hci_raw_queue); 283 NG_FREE_ITEM(item); 284 error = ENOBUFS; 285 } else { 286 NG_BT_ITEMQ_ENQUEUE(&ng_btsocket_hci_raw_queue, item); 287 error = ng_btsocket_hci_raw_wakeup_input_task(); 288 } 289 mtx_unlock(&ng_btsocket_hci_raw_queue_mtx); 290 } else { 291 NG_FREE_ITEM(item); 292 error = EINVAL; 293 } 294 295 return (error); 296 } /* ng_btsocket_hci_raw_node_rcvmsg */ 297 298 /* 299 * Receive packet from the one of our hook. 300 * Prepend every packet with sockaddr_hci and record sender's node name. 301 * Enqueue item and schedule input task. 302 */ 303 304 static int 305 ng_btsocket_hci_raw_node_rcvdata(hook_p hook, item_p item) 306 { 307 struct mbuf *nam = NULL; 308 int error; 309 310 /* 311 * Check for empty sockets list creates LOR when both sender and 312 * receiver device are connected to the same host, so remove it 313 * for now 314 */ 315 316 MGET(nam, M_NOWAIT, MT_SONAME); 317 if (nam != NULL) { 318 struct sockaddr_hci *sa = mtod(nam, struct sockaddr_hci *); 319 320 nam->m_len = sizeof(struct sockaddr_hci); 321 322 sa->hci_len = sizeof(*sa); 323 sa->hci_family = AF_BLUETOOTH; 324 strlcpy(sa->hci_node, NG_PEER_NODE_NAME(hook), 325 sizeof(sa->hci_node)); 326 327 NGI_GET_M(item, nam->m_next); 328 NGI_M(item) = nam; 329 330 mtx_lock(&ng_btsocket_hci_raw_queue_mtx); 331 if (NG_BT_ITEMQ_FULL(&ng_btsocket_hci_raw_queue)) { 332 NG_BTSOCKET_HCI_RAW_ERR( 333 "%s: Input queue is full\n", __func__); 334 335 NG_BT_ITEMQ_DROP(&ng_btsocket_hci_raw_queue); 336 NG_FREE_ITEM(item); 337 error = ENOBUFS; 338 } else { 339 NG_BT_ITEMQ_ENQUEUE(&ng_btsocket_hci_raw_queue, item); 340 error = ng_btsocket_hci_raw_wakeup_input_task(); 341 } 342 mtx_unlock(&ng_btsocket_hci_raw_queue_mtx); 343 } else { 344 NG_BTSOCKET_HCI_RAW_ERR( 345 "%s: Failed to allocate address mbuf\n", __func__); 346 347 NG_FREE_ITEM(item); 348 error = ENOBUFS; 349 } 350 351 return (error); 352 } /* ng_btsocket_hci_raw_node_rcvdata */ 353 354 /**************************************************************************** 355 **************************************************************************** 356 ** Sockets specific 357 **************************************************************************** 358 ****************************************************************************/ 359 360 /* 361 * Get next token. We need token to avoid theoretical race where process 362 * submits ioctl() message then interrupts ioctl() and re-submits another 363 * ioctl() on the same socket *before* first ioctl() complete. 364 */ 365 366 static void 367 ng_btsocket_hci_raw_get_token(u_int32_t *token) 368 { 369 mtx_lock(&ng_btsocket_hci_raw_token_mtx); 370 371 if (++ ng_btsocket_hci_raw_token == 0) 372 ng_btsocket_hci_raw_token = 1; 373 374 *token = ng_btsocket_hci_raw_token; 375 376 mtx_unlock(&ng_btsocket_hci_raw_token_mtx); 377 } /* ng_btsocket_hci_raw_get_token */ 378 379 /* 380 * Send Netgraph message to the node - do not expect reply 381 */ 382 383 static int 384 ng_btsocket_hci_raw_send_ngmsg(char *path, int cmd, void *arg, int arglen) 385 { 386 struct ng_mesg *msg = NULL; 387 int error = 0; 388 389 NG_MKMESSAGE(msg, NGM_HCI_COOKIE, cmd, arglen, M_NOWAIT); 390 if (msg == NULL) 391 return (ENOMEM); 392 393 if (arg != NULL && arglen > 0) 394 bcopy(arg, msg->data, arglen); 395 396 NG_SEND_MSG_PATH(error, ng_btsocket_hci_raw_node, msg, path, 0); 397 398 return (error); 399 } /* ng_btsocket_hci_raw_send_ngmsg */ 400 401 /* 402 * Send Netgraph message to the node (no data) and wait for reply 403 */ 404 405 static int 406 ng_btsocket_hci_raw_send_sync_ngmsg(ng_btsocket_hci_raw_pcb_p pcb, char *path, 407 int cmd, void *rsp, int rsplen) 408 { 409 struct ng_mesg *msg = NULL; 410 int error = 0; 411 412 mtx_assert(&pcb->pcb_mtx, MA_OWNED); 413 414 NG_MKMESSAGE(msg, NGM_HCI_COOKIE, cmd, 0, M_NOWAIT); 415 if (msg == NULL) 416 return (ENOMEM); 417 418 ng_btsocket_hci_raw_get_token(&msg->header.token); 419 pcb->token = msg->header.token; 420 pcb->msg = NULL; 421 422 NG_SEND_MSG_PATH(error, ng_btsocket_hci_raw_node, msg, path, 0); 423 if (error != 0) { 424 pcb->token = 0; 425 return (error); 426 } 427 428 error = msleep(&pcb->msg, &pcb->pcb_mtx, PZERO|PCATCH, "hcictl", 429 ng_btsocket_hci_raw_ioctl_timeout * hz); 430 pcb->token = 0; 431 432 if (error != 0) 433 return (error); 434 435 if (pcb->msg != NULL && pcb->msg->header.cmd == cmd) 436 bcopy(pcb->msg->data, rsp, rsplen); 437 else 438 error = EINVAL; 439 440 NG_FREE_MSG(pcb->msg); /* checks for != NULL */ 441 442 return (0); 443 } /* ng_btsocket_hci_raw_send_sync_ngmsg */ 444 445 /* 446 * Create control information for the packet 447 */ 448 449 static void 450 ng_btsocket_hci_raw_savctl(ng_btsocket_hci_raw_pcb_p pcb, struct mbuf **ctl, 451 struct mbuf *m) 452 { 453 int dir; 454 struct timeval tv; 455 456 mtx_assert(&pcb->pcb_mtx, MA_OWNED); 457 458 if (pcb->flags & NG_BTSOCKET_HCI_RAW_DIRECTION) { 459 dir = (m->m_flags & M_PROTO1)? 1 : 0; 460 *ctl = sbcreatecontrol((caddr_t) &dir, sizeof(dir), 461 SCM_HCI_RAW_DIRECTION, SOL_HCI_RAW); 462 if (*ctl != NULL) 463 ctl = &((*ctl)->m_next); 464 } 465 466 if (pcb->so->so_options & SO_TIMESTAMP) { 467 microtime(&tv); 468 *ctl = sbcreatecontrol((caddr_t) &tv, sizeof(tv), 469 SCM_TIMESTAMP, SOL_SOCKET); 470 if (*ctl != NULL) 471 ctl = &((*ctl)->m_next); 472 } 473 } /* ng_btsocket_hci_raw_savctl */ 474 475 /* 476 * Raw HCI sockets data input routine 477 */ 478 479 static void 480 ng_btsocket_hci_raw_data_input(struct mbuf *nam) 481 { 482 ng_btsocket_hci_raw_pcb_p pcb = NULL; 483 struct mbuf *m0 = NULL, *m = NULL; 484 struct sockaddr_hci *sa = NULL; 485 486 m0 = nam->m_next; 487 nam->m_next = NULL; 488 489 KASSERT((nam->m_type == MT_SONAME), 490 ("%s: m_type=%d\n", __func__, nam->m_type)); 491 KASSERT((m0->m_flags & M_PKTHDR), 492 ("%s: m_flags=%#x\n", __func__, m0->m_flags)); 493 494 sa = mtod(nam, struct sockaddr_hci *); 495 496 mtx_lock(&ng_btsocket_hci_raw_sockets_mtx); 497 498 LIST_FOREACH(pcb, &ng_btsocket_hci_raw_sockets, next) { 499 500 mtx_lock(&pcb->pcb_mtx); 501 502 /* 503 * If socket was bound then check address and 504 * make sure it matches. 505 */ 506 507 if (pcb->addr.hci_node[0] != 0 && 508 strcmp(sa->hci_node, pcb->addr.hci_node) != 0) 509 goto next; 510 511 /* 512 * Check packet against filters 513 * XXX do we have to call m_pullup() here? 514 */ 515 516 if (ng_btsocket_hci_raw_filter(pcb, m0, 1) != 0) 517 goto next; 518 519 /* 520 * Make a copy of the packet, append to the socket's 521 * receive queue and wakeup socket. sbappendaddr() 522 * will check if socket has enough buffer space. 523 */ 524 525 m = m_dup(m0, M_NOWAIT); 526 if (m != NULL) { 527 struct mbuf *ctl = NULL; 528 529 ng_btsocket_hci_raw_savctl(pcb, &ctl, m); 530 531 if (sbappendaddr(&pcb->so->so_rcv, 532 (struct sockaddr *) sa, m, ctl)) 533 sorwakeup(pcb->so); 534 else { 535 NG_BTSOCKET_HCI_RAW_INFO( 536 "%s: sbappendaddr() failed\n", __func__); 537 538 NG_FREE_M(m); 539 NG_FREE_M(ctl); 540 } 541 } 542 next: 543 mtx_unlock(&pcb->pcb_mtx); 544 } 545 546 mtx_unlock(&ng_btsocket_hci_raw_sockets_mtx); 547 548 NG_FREE_M(nam); 549 NG_FREE_M(m0); 550 } /* ng_btsocket_hci_raw_data_input */ 551 552 /* 553 * Raw HCI sockets message input routine 554 */ 555 556 static void 557 ng_btsocket_hci_raw_msg_input(struct ng_mesg *msg) 558 { 559 ng_btsocket_hci_raw_pcb_p pcb = NULL; 560 561 mtx_lock(&ng_btsocket_hci_raw_sockets_mtx); 562 563 LIST_FOREACH(pcb, &ng_btsocket_hci_raw_sockets, next) { 564 mtx_lock(&pcb->pcb_mtx); 565 566 if (msg->header.token == pcb->token) { 567 pcb->msg = msg; 568 wakeup(&pcb->msg); 569 570 mtx_unlock(&pcb->pcb_mtx); 571 mtx_unlock(&ng_btsocket_hci_raw_sockets_mtx); 572 573 return; 574 } 575 576 mtx_unlock(&pcb->pcb_mtx); 577 } 578 579 mtx_unlock(&ng_btsocket_hci_raw_sockets_mtx); 580 581 NG_FREE_MSG(msg); /* checks for != NULL */ 582 } /* ng_btsocket_hci_raw_msg_input */ 583 584 /* 585 * Raw HCI sockets input routines 586 */ 587 588 static void 589 ng_btsocket_hci_raw_input(void *context, int pending) 590 { 591 item_p item = NULL; 592 593 for (;;) { 594 mtx_lock(&ng_btsocket_hci_raw_queue_mtx); 595 NG_BT_ITEMQ_DEQUEUE(&ng_btsocket_hci_raw_queue, item); 596 mtx_unlock(&ng_btsocket_hci_raw_queue_mtx); 597 598 if (item == NULL) 599 break; 600 601 switch(item->el_flags & NGQF_TYPE) { 602 case NGQF_DATA: { 603 struct mbuf *m = NULL; 604 605 NGI_GET_M(item, m); 606 ng_btsocket_hci_raw_data_input(m); 607 } break; 608 609 case NGQF_MESG: { 610 struct ng_mesg *msg = NULL; 611 612 NGI_GET_MSG(item, msg); 613 ng_btsocket_hci_raw_msg_input(msg); 614 } break; 615 616 default: 617 KASSERT(0, 618 ("%s: invalid item type=%ld\n", __func__, (item->el_flags & NGQF_TYPE))); 619 break; 620 } 621 622 NG_FREE_ITEM(item); 623 } 624 } /* ng_btsocket_hci_raw_input */ 625 626 /* 627 * Raw HCI sockets output routine 628 */ 629 630 static void 631 ng_btsocket_hci_raw_output(node_p node, hook_p hook, void *arg1, int arg2) 632 { 633 struct mbuf *nam = (struct mbuf *) arg1, *m = NULL; 634 struct sockaddr_hci *sa = NULL; 635 int error; 636 637 m = nam->m_next; 638 nam->m_next = NULL; 639 640 KASSERT((nam->m_type == MT_SONAME), 641 ("%s: m_type=%d\n", __func__, nam->m_type)); 642 KASSERT((m->m_flags & M_PKTHDR), 643 ("%s: m_flags=%#x\n", __func__, m->m_flags)); 644 645 sa = mtod(nam, struct sockaddr_hci *); 646 647 /* 648 * Find downstream hook 649 * XXX For now access node hook list directly. Should be safe because 650 * we used ng_send_fn() and we should have exclusive lock on the node. 651 */ 652 653 LIST_FOREACH(hook, &node->nd_hooks, hk_hooks) { 654 if (hook == NULL || NG_HOOK_NOT_VALID(hook) || 655 NG_NODE_NOT_VALID(NG_PEER_NODE(hook))) 656 continue; 657 658 if (strcmp(sa->hci_node, NG_PEER_NODE_NAME(hook)) == 0) { 659 NG_SEND_DATA_ONLY(error, hook, m); /* sets m to NULL */ 660 break; 661 } 662 } 663 664 NG_FREE_M(nam); /* check for != NULL */ 665 NG_FREE_M(m); 666 } /* ng_btsocket_hci_raw_output */ 667 668 /* 669 * Check frame against security and socket filters. 670 * d (direction bit) == 1 means incoming frame. 671 */ 672 673 static int 674 ng_btsocket_hci_raw_filter(ng_btsocket_hci_raw_pcb_p pcb, struct mbuf *m, int d) 675 { 676 int type, event, opcode; 677 678 mtx_assert(&pcb->pcb_mtx, MA_OWNED); 679 680 switch ((type = *mtod(m, u_int8_t *))) { 681 case NG_HCI_CMD_PKT: 682 if (!(pcb->flags & NG_BTSOCKET_HCI_RAW_PRIVILEGED)) { 683 opcode = le16toh(mtod(m, ng_hci_cmd_pkt_t *)->opcode); 684 685 if (!bit_test( 686 ng_btsocket_hci_raw_sec_filter->commands[NG_HCI_OGF(opcode) - 1], 687 NG_HCI_OCF(opcode) - 1)) 688 return (EPERM); 689 } 690 691 if (d && !bit_test(pcb->filter.packet_mask, NG_HCI_CMD_PKT - 1)) 692 return (EPERM); 693 break; 694 695 case NG_HCI_ACL_DATA_PKT: 696 case NG_HCI_SCO_DATA_PKT: 697 if (!(pcb->flags & NG_BTSOCKET_HCI_RAW_PRIVILEGED) || 698 !bit_test(pcb->filter.packet_mask, type - 1) || 699 !d) 700 return (EPERM); 701 break; 702 703 case NG_HCI_EVENT_PKT: 704 if (!d) 705 return (EINVAL); 706 707 event = mtod(m, ng_hci_event_pkt_t *)->event - 1; 708 709 if (!(pcb->flags & NG_BTSOCKET_HCI_RAW_PRIVILEGED)) 710 if (!bit_test(ng_btsocket_hci_raw_sec_filter->events, event)) 711 return (EPERM); 712 713 if (!bit_test(pcb->filter.event_mask, event)) 714 return (EPERM); 715 break; 716 717 default: 718 return (EINVAL); 719 } 720 721 return (0); 722 } /* ng_btsocket_hci_raw_filter */ 723 724 /* 725 * Initialize everything 726 */ 727 728 void 729 ng_btsocket_hci_raw_init(void) 730 { 731 bitstr_t *f = NULL; 732 int error = 0; 733 734 /* Skip initialization of globals for non-default instances. */ 735 if (!IS_DEFAULT_VNET(curvnet)) 736 return; 737 738 ng_btsocket_hci_raw_node = NULL; 739 ng_btsocket_hci_raw_debug_level = NG_BTSOCKET_WARN_LEVEL; 740 ng_btsocket_hci_raw_ioctl_timeout = 5; 741 742 /* Register Netgraph node type */ 743 error = ng_newtype(&typestruct); 744 if (error != 0) { 745 NG_BTSOCKET_HCI_RAW_ALERT( 746 "%s: Could not register Netgraph node type, error=%d\n", __func__, error); 747 748 return; 749 } 750 751 /* Create Netgrapg node */ 752 error = ng_make_node_common(&typestruct, &ng_btsocket_hci_raw_node); 753 if (error != 0) { 754 NG_BTSOCKET_HCI_RAW_ALERT( 755 "%s: Could not create Netgraph node, error=%d\n", __func__, error); 756 757 ng_btsocket_hci_raw_node = NULL; 758 759 return; 760 } 761 762 error = ng_name_node(ng_btsocket_hci_raw_node, 763 NG_BTSOCKET_HCI_RAW_NODE_TYPE); 764 if (error != 0) { 765 NG_BTSOCKET_HCI_RAW_ALERT( 766 "%s: Could not name Netgraph node, error=%d\n", __func__, error); 767 768 NG_NODE_UNREF(ng_btsocket_hci_raw_node); 769 ng_btsocket_hci_raw_node = NULL; 770 771 return; 772 } 773 774 /* Create input queue */ 775 NG_BT_ITEMQ_INIT(&ng_btsocket_hci_raw_queue, 300); 776 mtx_init(&ng_btsocket_hci_raw_queue_mtx, 777 "btsocks_hci_raw_queue_mtx", NULL, MTX_DEF); 778 TASK_INIT(&ng_btsocket_hci_raw_task, 0, 779 ng_btsocket_hci_raw_input, NULL); 780 781 /* Create list of sockets */ 782 LIST_INIT(&ng_btsocket_hci_raw_sockets); 783 mtx_init(&ng_btsocket_hci_raw_sockets_mtx, 784 "btsocks_hci_raw_sockets_mtx", NULL, MTX_DEF); 785 786 /* Tokens */ 787 ng_btsocket_hci_raw_token = 0; 788 mtx_init(&ng_btsocket_hci_raw_token_mtx, 789 "btsocks_hci_raw_token_mtx", NULL, MTX_DEF); 790 791 /* 792 * Security filter 793 * XXX never free()ed 794 */ 795 ng_btsocket_hci_raw_sec_filter = 796 malloc(sizeof(struct ng_btsocket_hci_raw_sec_filter), 797 M_NETGRAPH_BTSOCKET_HCI_RAW, M_NOWAIT|M_ZERO); 798 if (ng_btsocket_hci_raw_sec_filter == NULL) { 799 printf("%s: Could not allocate security filter!\n", __func__); 800 return; 801 } 802 803 /* 804 * XXX How paranoid can we get? 805 * 806 * Initialize security filter. If bit is set in the mask then 807 * unprivileged socket is allowed to send (receive) this command 808 * (event). 809 */ 810 811 /* Enable all events */ 812 memset(&ng_btsocket_hci_raw_sec_filter->events, 0xff, 813 sizeof(ng_btsocket_hci_raw_sec_filter->events)/ 814 sizeof(ng_btsocket_hci_raw_sec_filter->events[0])); 815 816 /* Disable some critical events */ 817 f = ng_btsocket_hci_raw_sec_filter->events; 818 bit_clear(f, NG_HCI_EVENT_RETURN_LINK_KEYS - 1); 819 bit_clear(f, NG_HCI_EVENT_LINK_KEY_NOTIFICATION - 1); 820 bit_clear(f, NG_HCI_EVENT_VENDOR - 1); 821 822 /* Commands - Link control */ 823 f = ng_btsocket_hci_raw_sec_filter->commands[NG_HCI_OGF_LINK_CONTROL-1]; 824 bit_set(f, NG_HCI_OCF_INQUIRY - 1); 825 bit_set(f, NG_HCI_OCF_INQUIRY_CANCEL - 1); 826 bit_set(f, NG_HCI_OCF_PERIODIC_INQUIRY - 1); 827 bit_set(f, NG_HCI_OCF_EXIT_PERIODIC_INQUIRY - 1); 828 bit_set(f, NG_HCI_OCF_REMOTE_NAME_REQ - 1); 829 bit_set(f, NG_HCI_OCF_READ_REMOTE_FEATURES - 1); 830 bit_set(f, NG_HCI_OCF_READ_REMOTE_VER_INFO - 1); 831 bit_set(f, NG_HCI_OCF_READ_CLOCK_OFFSET - 1); 832 833 /* Commands - Link policy */ 834 f = ng_btsocket_hci_raw_sec_filter->commands[NG_HCI_OGF_LINK_POLICY-1]; 835 bit_set(f, NG_HCI_OCF_ROLE_DISCOVERY - 1); 836 bit_set(f, NG_HCI_OCF_READ_LINK_POLICY_SETTINGS - 1); 837 838 /* Commands - Host controller and baseband */ 839 f = ng_btsocket_hci_raw_sec_filter->commands[NG_HCI_OGF_HC_BASEBAND-1]; 840 bit_set(f, NG_HCI_OCF_READ_PIN_TYPE - 1); 841 bit_set(f, NG_HCI_OCF_READ_LOCAL_NAME - 1); 842 bit_set(f, NG_HCI_OCF_READ_CON_ACCEPT_TIMO - 1); 843 bit_set(f, NG_HCI_OCF_READ_PAGE_TIMO - 1); 844 bit_set(f, NG_HCI_OCF_READ_SCAN_ENABLE - 1); 845 bit_set(f, NG_HCI_OCF_READ_PAGE_SCAN_ACTIVITY - 1); 846 bit_set(f, NG_HCI_OCF_READ_INQUIRY_SCAN_ACTIVITY - 1); 847 bit_set(f, NG_HCI_OCF_READ_AUTH_ENABLE - 1); 848 bit_set(f, NG_HCI_OCF_READ_ENCRYPTION_MODE - 1); 849 bit_set(f, NG_HCI_OCF_READ_UNIT_CLASS - 1); 850 bit_set(f, NG_HCI_OCF_READ_VOICE_SETTINGS - 1); 851 bit_set(f, NG_HCI_OCF_READ_AUTO_FLUSH_TIMO - 1); 852 bit_set(f, NG_HCI_OCF_READ_NUM_BROADCAST_RETRANS - 1); 853 bit_set(f, NG_HCI_OCF_READ_HOLD_MODE_ACTIVITY - 1); 854 bit_set(f, NG_HCI_OCF_READ_XMIT_LEVEL - 1); 855 bit_set(f, NG_HCI_OCF_READ_SCO_FLOW_CONTROL - 1); 856 bit_set(f, NG_HCI_OCF_READ_LINK_SUPERVISION_TIMO - 1); 857 bit_set(f, NG_HCI_OCF_READ_SUPPORTED_IAC_NUM - 1); 858 bit_set(f, NG_HCI_OCF_READ_IAC_LAP - 1); 859 bit_set(f, NG_HCI_OCF_READ_PAGE_SCAN_PERIOD - 1); 860 bit_set(f, NG_HCI_OCF_READ_PAGE_SCAN - 1); 861 862 /* Commands - Informational */ 863 f = ng_btsocket_hci_raw_sec_filter->commands[NG_HCI_OGF_INFO - 1]; 864 bit_set(f, NG_HCI_OCF_READ_LOCAL_VER - 1); 865 bit_set(f, NG_HCI_OCF_READ_LOCAL_FEATURES - 1); 866 bit_set(f, NG_HCI_OCF_READ_BUFFER_SIZE - 1); 867 bit_set(f, NG_HCI_OCF_READ_COUNTRY_CODE - 1); 868 bit_set(f, NG_HCI_OCF_READ_BDADDR - 1); 869 870 /* Commands - Status */ 871 f = ng_btsocket_hci_raw_sec_filter->commands[NG_HCI_OGF_STATUS - 1]; 872 bit_set(f, NG_HCI_OCF_READ_FAILED_CONTACT_CNTR - 1); 873 bit_set(f, NG_HCI_OCF_GET_LINK_QUALITY - 1); 874 bit_set(f, NG_HCI_OCF_READ_RSSI - 1); 875 876 /* Commands - Testing */ 877 f = ng_btsocket_hci_raw_sec_filter->commands[NG_HCI_OGF_TESTING - 1]; 878 bit_set(f, NG_HCI_OCF_READ_LOOPBACK_MODE - 1); 879 /*Commands - LE*/ 880 f = ng_btsocket_hci_raw_sec_filter->commands[NG_HCI_OGF_LE -1]; 881 882 } /* ng_btsocket_hci_raw_init */ 883 884 /* 885 * Abort connection on socket 886 */ 887 888 void 889 ng_btsocket_hci_raw_abort(struct socket *so) 890 { 891 } /* ng_btsocket_hci_raw_abort */ 892 893 void 894 ng_btsocket_hci_raw_close(struct socket *so) 895 { 896 } /* ng_btsocket_hci_raw_close */ 897 898 /* 899 * Create new raw HCI socket 900 */ 901 902 int 903 ng_btsocket_hci_raw_attach(struct socket *so, int proto, struct thread *td) 904 { 905 ng_btsocket_hci_raw_pcb_p pcb = so2hci_raw_pcb(so); 906 int error = 0; 907 908 if (pcb != NULL) 909 return (EISCONN); 910 911 if (ng_btsocket_hci_raw_node == NULL) 912 return (EPROTONOSUPPORT); 913 if (proto != BLUETOOTH_PROTO_HCI) 914 return (EPROTONOSUPPORT); 915 if (so->so_type != SOCK_RAW) 916 return (ESOCKTNOSUPPORT); 917 918 error = soreserve(so, NG_BTSOCKET_HCI_RAW_SENDSPACE, 919 NG_BTSOCKET_HCI_RAW_RECVSPACE); 920 if (error != 0) 921 return (error); 922 923 pcb = malloc(sizeof(*pcb), 924 M_NETGRAPH_BTSOCKET_HCI_RAW, M_NOWAIT|M_ZERO); 925 if (pcb == NULL) 926 return (ENOMEM); 927 928 so->so_pcb = (caddr_t) pcb; 929 pcb->so = so; 930 931 if (priv_check(td, PRIV_NETBLUETOOTH_RAW) == 0) 932 pcb->flags |= NG_BTSOCKET_HCI_RAW_PRIVILEGED; 933 934 /* 935 * Set default socket filter. By default socket only accepts HCI 936 * Command_Complete and Command_Status event packets. 937 */ 938 939 bit_set(pcb->filter.event_mask, NG_HCI_EVENT_COMMAND_COMPL - 1); 940 bit_set(pcb->filter.event_mask, NG_HCI_EVENT_COMMAND_STATUS - 1); 941 942 mtx_init(&pcb->pcb_mtx, "btsocks_hci_raw_pcb_mtx", NULL, MTX_DEF); 943 944 mtx_lock(&ng_btsocket_hci_raw_sockets_mtx); 945 LIST_INSERT_HEAD(&ng_btsocket_hci_raw_sockets, pcb, next); 946 mtx_unlock(&ng_btsocket_hci_raw_sockets_mtx); 947 948 return (0); 949 } /* ng_btsocket_hci_raw_attach */ 950 951 /* 952 * Bind raw HCI socket 953 */ 954 955 int 956 ng_btsocket_hci_raw_bind(struct socket *so, struct sockaddr *nam, 957 struct thread *td) 958 { 959 ng_btsocket_hci_raw_pcb_p pcb = so2hci_raw_pcb(so); 960 struct sockaddr_hci *sa = (struct sockaddr_hci *) nam; 961 962 if (pcb == NULL) 963 return (EINVAL); 964 if (ng_btsocket_hci_raw_node == NULL) 965 return (EINVAL); 966 967 if (sa == NULL) 968 return (EINVAL); 969 if (sa->hci_family != AF_BLUETOOTH) 970 return (EAFNOSUPPORT); 971 if (sa->hci_len != sizeof(*sa)) 972 return (EINVAL); 973 if (sa->hci_node[0] == 0) 974 return (EINVAL); 975 976 mtx_lock(&pcb->pcb_mtx); 977 bcopy(sa, &pcb->addr, sizeof(pcb->addr)); 978 mtx_unlock(&pcb->pcb_mtx); 979 980 return (0); 981 } /* ng_btsocket_hci_raw_bind */ 982 983 /* 984 * Connect raw HCI socket 985 */ 986 987 int 988 ng_btsocket_hci_raw_connect(struct socket *so, struct sockaddr *nam, 989 struct thread *td) 990 { 991 ng_btsocket_hci_raw_pcb_p pcb = so2hci_raw_pcb(so); 992 struct sockaddr_hci *sa = (struct sockaddr_hci *) nam; 993 994 if (pcb == NULL) 995 return (EINVAL); 996 if (ng_btsocket_hci_raw_node == NULL) 997 return (EINVAL); 998 999 if (sa == NULL) 1000 return (EINVAL); 1001 if (sa->hci_family != AF_BLUETOOTH) 1002 return (EAFNOSUPPORT); 1003 if (sa->hci_len != sizeof(*sa)) 1004 return (EINVAL); 1005 if (sa->hci_node[0] == 0) 1006 return (EDESTADDRREQ); 1007 1008 mtx_lock(&pcb->pcb_mtx); 1009 1010 if (bcmp(sa, &pcb->addr, sizeof(pcb->addr)) != 0) { 1011 mtx_unlock(&pcb->pcb_mtx); 1012 return (EADDRNOTAVAIL); 1013 } 1014 1015 soisconnected(so); 1016 1017 mtx_unlock(&pcb->pcb_mtx); 1018 1019 return (0); 1020 } /* ng_btsocket_hci_raw_connect */ 1021 1022 /* 1023 * Process ioctl on socket 1024 */ 1025 1026 int 1027 ng_btsocket_hci_raw_control(struct socket *so, u_long cmd, caddr_t data, 1028 struct ifnet *ifp, struct thread *td) 1029 { 1030 ng_btsocket_hci_raw_pcb_p pcb = so2hci_raw_pcb(so); 1031 char path[NG_NODESIZ + 1]; 1032 struct ng_mesg *msg = NULL; 1033 int error = 0; 1034 1035 if (pcb == NULL) 1036 return (EINVAL); 1037 if (ng_btsocket_hci_raw_node == NULL) 1038 return (EINVAL); 1039 1040 mtx_lock(&pcb->pcb_mtx); 1041 1042 /* Check if we have device name */ 1043 if (pcb->addr.hci_node[0] == 0) { 1044 mtx_unlock(&pcb->pcb_mtx); 1045 return (EHOSTUNREACH); 1046 } 1047 1048 /* Check if we have pending ioctl() */ 1049 if (pcb->token != 0) { 1050 mtx_unlock(&pcb->pcb_mtx); 1051 return (EBUSY); 1052 } 1053 1054 snprintf(path, sizeof(path), "%s:", pcb->addr.hci_node); 1055 1056 switch (cmd) { 1057 case SIOC_HCI_RAW_NODE_GET_STATE: { 1058 struct ng_btsocket_hci_raw_node_state *p = 1059 (struct ng_btsocket_hci_raw_node_state *) data; 1060 1061 error = ng_btsocket_hci_raw_send_sync_ngmsg(pcb, path, 1062 NGM_HCI_NODE_GET_STATE, 1063 &p->state, sizeof(p->state)); 1064 } break; 1065 1066 case SIOC_HCI_RAW_NODE_INIT: 1067 if (pcb->flags & NG_BTSOCKET_HCI_RAW_PRIVILEGED) 1068 error = ng_btsocket_hci_raw_send_ngmsg(path, 1069 NGM_HCI_NODE_INIT, NULL, 0); 1070 else 1071 error = EPERM; 1072 break; 1073 1074 case SIOC_HCI_RAW_NODE_GET_DEBUG: { 1075 struct ng_btsocket_hci_raw_node_debug *p = 1076 (struct ng_btsocket_hci_raw_node_debug *) data; 1077 1078 error = ng_btsocket_hci_raw_send_sync_ngmsg(pcb, path, 1079 NGM_HCI_NODE_GET_DEBUG, 1080 &p->debug, sizeof(p->debug)); 1081 } break; 1082 1083 case SIOC_HCI_RAW_NODE_SET_DEBUG: { 1084 struct ng_btsocket_hci_raw_node_debug *p = 1085 (struct ng_btsocket_hci_raw_node_debug *) data; 1086 1087 if (pcb->flags & NG_BTSOCKET_HCI_RAW_PRIVILEGED) 1088 error = ng_btsocket_hci_raw_send_ngmsg(path, 1089 NGM_HCI_NODE_SET_DEBUG, &p->debug, 1090 sizeof(p->debug)); 1091 else 1092 error = EPERM; 1093 } break; 1094 1095 case SIOC_HCI_RAW_NODE_GET_BUFFER: { 1096 struct ng_btsocket_hci_raw_node_buffer *p = 1097 (struct ng_btsocket_hci_raw_node_buffer *) data; 1098 1099 error = ng_btsocket_hci_raw_send_sync_ngmsg(pcb, path, 1100 NGM_HCI_NODE_GET_BUFFER, 1101 &p->buffer, sizeof(p->buffer)); 1102 } break; 1103 1104 case SIOC_HCI_RAW_NODE_GET_BDADDR: { 1105 struct ng_btsocket_hci_raw_node_bdaddr *p = 1106 (struct ng_btsocket_hci_raw_node_bdaddr *) data; 1107 1108 error = ng_btsocket_hci_raw_send_sync_ngmsg(pcb, path, 1109 NGM_HCI_NODE_GET_BDADDR, 1110 &p->bdaddr, sizeof(p->bdaddr)); 1111 } break; 1112 1113 case SIOC_HCI_RAW_NODE_GET_FEATURES: { 1114 struct ng_btsocket_hci_raw_node_features *p = 1115 (struct ng_btsocket_hci_raw_node_features *) data; 1116 1117 error = ng_btsocket_hci_raw_send_sync_ngmsg(pcb, path, 1118 NGM_HCI_NODE_GET_FEATURES, 1119 &p->features, sizeof(p->features)); 1120 } break; 1121 1122 case SIOC_HCI_RAW_NODE_GET_STAT: { 1123 struct ng_btsocket_hci_raw_node_stat *p = 1124 (struct ng_btsocket_hci_raw_node_stat *) data; 1125 1126 error = ng_btsocket_hci_raw_send_sync_ngmsg(pcb, path, 1127 NGM_HCI_NODE_GET_STAT, 1128 &p->stat, sizeof(p->stat)); 1129 } break; 1130 1131 case SIOC_HCI_RAW_NODE_RESET_STAT: 1132 if (pcb->flags & NG_BTSOCKET_HCI_RAW_PRIVILEGED) 1133 error = ng_btsocket_hci_raw_send_ngmsg(path, 1134 NGM_HCI_NODE_RESET_STAT, NULL, 0); 1135 else 1136 error = EPERM; 1137 break; 1138 1139 case SIOC_HCI_RAW_NODE_FLUSH_NEIGHBOR_CACHE: 1140 if (pcb->flags & NG_BTSOCKET_HCI_RAW_PRIVILEGED) 1141 error = ng_btsocket_hci_raw_send_ngmsg(path, 1142 NGM_HCI_NODE_FLUSH_NEIGHBOR_CACHE, 1143 NULL, 0); 1144 else 1145 error = EPERM; 1146 break; 1147 1148 case SIOC_HCI_RAW_NODE_GET_NEIGHBOR_CACHE: { 1149 struct ng_btsocket_hci_raw_node_neighbor_cache *p = 1150 (struct ng_btsocket_hci_raw_node_neighbor_cache *) data; 1151 ng_hci_node_get_neighbor_cache_ep *p1 = NULL; 1152 ng_hci_node_neighbor_cache_entry_ep *p2 = NULL; 1153 1154 if (p->num_entries <= 0 || 1155 p->num_entries > NG_HCI_MAX_NEIGHBOR_NUM || 1156 p->entries == NULL) { 1157 error = EINVAL; 1158 break; 1159 } 1160 1161 NG_MKMESSAGE(msg, NGM_HCI_COOKIE, 1162 NGM_HCI_NODE_GET_NEIGHBOR_CACHE, 0, M_NOWAIT); 1163 if (msg == NULL) { 1164 error = ENOMEM; 1165 break; 1166 } 1167 ng_btsocket_hci_raw_get_token(&msg->header.token); 1168 pcb->token = msg->header.token; 1169 pcb->msg = NULL; 1170 1171 NG_SEND_MSG_PATH(error, ng_btsocket_hci_raw_node, msg, path, 0); 1172 if (error != 0) { 1173 pcb->token = 0; 1174 break; 1175 } 1176 1177 error = msleep(&pcb->msg, &pcb->pcb_mtx, 1178 PZERO|PCATCH, "hcictl", 1179 ng_btsocket_hci_raw_ioctl_timeout * hz); 1180 pcb->token = 0; 1181 1182 if (error != 0) 1183 break; 1184 1185 if (pcb->msg != NULL && 1186 pcb->msg->header.cmd == NGM_HCI_NODE_GET_NEIGHBOR_CACHE) { 1187 /* Return data back to user space */ 1188 p1 = (ng_hci_node_get_neighbor_cache_ep *) 1189 (pcb->msg->data); 1190 p2 = (ng_hci_node_neighbor_cache_entry_ep *) 1191 (p1 + 1); 1192 1193 p->num_entries = min(p->num_entries, p1->num_entries); 1194 if (p->num_entries > 0) 1195 error = copyout((caddr_t) p2, 1196 (caddr_t) p->entries, 1197 p->num_entries * sizeof(*p2)); 1198 } else 1199 error = EINVAL; 1200 1201 NG_FREE_MSG(pcb->msg); /* checks for != NULL */ 1202 }break; 1203 1204 case SIOC_HCI_RAW_NODE_GET_CON_LIST: { 1205 struct ng_btsocket_hci_raw_con_list *p = 1206 (struct ng_btsocket_hci_raw_con_list *) data; 1207 ng_hci_node_con_list_ep *p1 = NULL; 1208 ng_hci_node_con_ep *p2 = NULL; 1209 1210 if (p->num_connections == 0 || 1211 p->num_connections > NG_HCI_MAX_CON_NUM || 1212 p->connections == NULL) { 1213 error = EINVAL; 1214 break; 1215 } 1216 1217 NG_MKMESSAGE(msg, NGM_HCI_COOKIE, NGM_HCI_NODE_GET_CON_LIST, 1218 0, M_NOWAIT); 1219 if (msg == NULL) { 1220 error = ENOMEM; 1221 break; 1222 } 1223 ng_btsocket_hci_raw_get_token(&msg->header.token); 1224 pcb->token = msg->header.token; 1225 pcb->msg = NULL; 1226 1227 NG_SEND_MSG_PATH(error, ng_btsocket_hci_raw_node, msg, path, 0); 1228 if (error != 0) { 1229 pcb->token = 0; 1230 break; 1231 } 1232 1233 error = msleep(&pcb->msg, &pcb->pcb_mtx, 1234 PZERO|PCATCH, "hcictl", 1235 ng_btsocket_hci_raw_ioctl_timeout * hz); 1236 pcb->token = 0; 1237 1238 if (error != 0) 1239 break; 1240 1241 if (pcb->msg != NULL && 1242 pcb->msg->header.cmd == NGM_HCI_NODE_GET_CON_LIST) { 1243 /* Return data back to user space */ 1244 p1 = (ng_hci_node_con_list_ep *)(pcb->msg->data); 1245 p2 = (ng_hci_node_con_ep *)(p1 + 1); 1246 1247 p->num_connections = min(p->num_connections, 1248 p1->num_connections); 1249 if (p->num_connections > 0) 1250 error = copyout((caddr_t) p2, 1251 (caddr_t) p->connections, 1252 p->num_connections * sizeof(*p2)); 1253 } else 1254 error = EINVAL; 1255 1256 NG_FREE_MSG(pcb->msg); /* checks for != NULL */ 1257 } break; 1258 1259 case SIOC_HCI_RAW_NODE_GET_LINK_POLICY_MASK: { 1260 struct ng_btsocket_hci_raw_node_link_policy_mask *p = 1261 (struct ng_btsocket_hci_raw_node_link_policy_mask *) 1262 data; 1263 1264 error = ng_btsocket_hci_raw_send_sync_ngmsg(pcb, path, 1265 NGM_HCI_NODE_GET_LINK_POLICY_SETTINGS_MASK, 1266 &p->policy_mask, sizeof(p->policy_mask)); 1267 } break; 1268 1269 case SIOC_HCI_RAW_NODE_SET_LINK_POLICY_MASK: { 1270 struct ng_btsocket_hci_raw_node_link_policy_mask *p = 1271 (struct ng_btsocket_hci_raw_node_link_policy_mask *) 1272 data; 1273 1274 if (pcb->flags & NG_BTSOCKET_HCI_RAW_PRIVILEGED) 1275 error = ng_btsocket_hci_raw_send_ngmsg(path, 1276 NGM_HCI_NODE_SET_LINK_POLICY_SETTINGS_MASK, 1277 &p->policy_mask, 1278 sizeof(p->policy_mask)); 1279 else 1280 error = EPERM; 1281 } break; 1282 1283 case SIOC_HCI_RAW_NODE_GET_PACKET_MASK: { 1284 struct ng_btsocket_hci_raw_node_packet_mask *p = 1285 (struct ng_btsocket_hci_raw_node_packet_mask *) data; 1286 1287 error = ng_btsocket_hci_raw_send_sync_ngmsg(pcb, path, 1288 NGM_HCI_NODE_GET_PACKET_MASK, 1289 &p->packet_mask, sizeof(p->packet_mask)); 1290 } break; 1291 1292 case SIOC_HCI_RAW_NODE_SET_PACKET_MASK: { 1293 struct ng_btsocket_hci_raw_node_packet_mask *p = 1294 (struct ng_btsocket_hci_raw_node_packet_mask *) data; 1295 1296 if (pcb->flags & NG_BTSOCKET_HCI_RAW_PRIVILEGED) 1297 error = ng_btsocket_hci_raw_send_ngmsg(path, 1298 NGM_HCI_NODE_SET_PACKET_MASK, 1299 &p->packet_mask, 1300 sizeof(p->packet_mask)); 1301 else 1302 error = EPERM; 1303 } break; 1304 1305 case SIOC_HCI_RAW_NODE_GET_ROLE_SWITCH: { 1306 struct ng_btsocket_hci_raw_node_role_switch *p = 1307 (struct ng_btsocket_hci_raw_node_role_switch *) data; 1308 1309 error = ng_btsocket_hci_raw_send_sync_ngmsg(pcb, path, 1310 NGM_HCI_NODE_GET_ROLE_SWITCH, 1311 &p->role_switch, sizeof(p->role_switch)); 1312 } break; 1313 1314 case SIOC_HCI_RAW_NODE_SET_ROLE_SWITCH: { 1315 struct ng_btsocket_hci_raw_node_role_switch *p = 1316 (struct ng_btsocket_hci_raw_node_role_switch *) data; 1317 1318 if (pcb->flags & NG_BTSOCKET_HCI_RAW_PRIVILEGED) 1319 error = ng_btsocket_hci_raw_send_ngmsg(path, 1320 NGM_HCI_NODE_SET_ROLE_SWITCH, 1321 &p->role_switch, 1322 sizeof(p->role_switch)); 1323 else 1324 error = EPERM; 1325 } break; 1326 1327 case SIOC_HCI_RAW_NODE_LIST_NAMES: { 1328 struct ng_btsocket_hci_raw_node_list_names *nl = 1329 (struct ng_btsocket_hci_raw_node_list_names *) data; 1330 struct nodeinfo *ni = nl->names; 1331 1332 if (nl->num_names == 0) { 1333 error = EINVAL; 1334 break; 1335 } 1336 1337 NG_MKMESSAGE(msg, NGM_GENERIC_COOKIE, NGM_LISTNAMES, 1338 0, M_NOWAIT); 1339 if (msg == NULL) { 1340 error = ENOMEM; 1341 break; 1342 } 1343 ng_btsocket_hci_raw_get_token(&msg->header.token); 1344 pcb->token = msg->header.token; 1345 pcb->msg = NULL; 1346 1347 NG_SEND_MSG_PATH(error, ng_btsocket_hci_raw_node, msg, ".:", 0); 1348 if (error != 0) { 1349 pcb->token = 0; 1350 break; 1351 } 1352 1353 error = msleep(&pcb->msg, &pcb->pcb_mtx, 1354 PZERO|PCATCH, "hcictl", 1355 ng_btsocket_hci_raw_ioctl_timeout * hz); 1356 pcb->token = 0; 1357 1358 if (error != 0) 1359 break; 1360 1361 if (pcb->msg != NULL && pcb->msg->header.cmd == NGM_LISTNAMES) { 1362 /* Return data back to user space */ 1363 struct namelist *nl1 = (struct namelist *) pcb->msg->data; 1364 struct nodeinfo *ni1 = &nl1->nodeinfo[0]; 1365 1366 while (nl->num_names > 0 && nl1->numnames > 0) { 1367 if (strcmp(ni1->type, NG_HCI_NODE_TYPE) == 0) { 1368 error = copyout((caddr_t) ni1, 1369 (caddr_t) ni, 1370 sizeof(*ni)); 1371 if (error != 0) 1372 break; 1373 1374 nl->num_names --; 1375 ni ++; 1376 } 1377 1378 nl1->numnames --; 1379 ni1 ++; 1380 } 1381 1382 nl->num_names = ni - nl->names; 1383 } else 1384 error = EINVAL; 1385 1386 NG_FREE_MSG(pcb->msg); /* checks for != NULL */ 1387 } break; 1388 1389 default: 1390 error = EINVAL; 1391 break; 1392 } 1393 1394 mtx_unlock(&pcb->pcb_mtx); 1395 1396 return (error); 1397 } /* ng_btsocket_hci_raw_control */ 1398 1399 /* 1400 * Process getsockopt/setsockopt system calls 1401 */ 1402 1403 int 1404 ng_btsocket_hci_raw_ctloutput(struct socket *so, struct sockopt *sopt) 1405 { 1406 ng_btsocket_hci_raw_pcb_p pcb = so2hci_raw_pcb(so); 1407 struct ng_btsocket_hci_raw_filter filter; 1408 int error = 0, dir; 1409 1410 if (pcb == NULL) 1411 return (EINVAL); 1412 if (ng_btsocket_hci_raw_node == NULL) 1413 return (EINVAL); 1414 1415 if (sopt->sopt_level != SOL_HCI_RAW) 1416 return (0); 1417 1418 mtx_lock(&pcb->pcb_mtx); 1419 1420 switch (sopt->sopt_dir) { 1421 case SOPT_GET: 1422 switch (sopt->sopt_name) { 1423 case SO_HCI_RAW_FILTER: 1424 error = sooptcopyout(sopt, &pcb->filter, 1425 sizeof(pcb->filter)); 1426 break; 1427 1428 case SO_HCI_RAW_DIRECTION: 1429 dir = (pcb->flags & NG_BTSOCKET_HCI_RAW_DIRECTION)?1:0; 1430 error = sooptcopyout(sopt, &dir, sizeof(dir)); 1431 break; 1432 1433 default: 1434 error = EINVAL; 1435 break; 1436 } 1437 break; 1438 1439 case SOPT_SET: 1440 switch (sopt->sopt_name) { 1441 case SO_HCI_RAW_FILTER: 1442 error = sooptcopyin(sopt, &filter, sizeof(filter), 1443 sizeof(filter)); 1444 if (error == 0) 1445 bcopy(&filter, &pcb->filter, 1446 sizeof(pcb->filter)); 1447 break; 1448 1449 case SO_HCI_RAW_DIRECTION: 1450 error = sooptcopyin(sopt, &dir, sizeof(dir), 1451 sizeof(dir)); 1452 if (error != 0) 1453 break; 1454 1455 if (dir) 1456 pcb->flags |= NG_BTSOCKET_HCI_RAW_DIRECTION; 1457 else 1458 pcb->flags &= ~NG_BTSOCKET_HCI_RAW_DIRECTION; 1459 break; 1460 1461 default: 1462 error = EINVAL; 1463 break; 1464 } 1465 break; 1466 1467 default: 1468 error = EINVAL; 1469 break; 1470 } 1471 1472 mtx_unlock(&pcb->pcb_mtx); 1473 1474 return (error); 1475 } /* ng_btsocket_hci_raw_ctloutput */ 1476 1477 /* 1478 * Detach raw HCI socket 1479 */ 1480 1481 void 1482 ng_btsocket_hci_raw_detach(struct socket *so) 1483 { 1484 ng_btsocket_hci_raw_pcb_p pcb = so2hci_raw_pcb(so); 1485 1486 KASSERT(pcb != NULL, ("ng_btsocket_hci_raw_detach: pcb == NULL")); 1487 1488 if (ng_btsocket_hci_raw_node == NULL) 1489 return; 1490 1491 mtx_lock(&ng_btsocket_hci_raw_sockets_mtx); 1492 mtx_lock(&pcb->pcb_mtx); 1493 1494 LIST_REMOVE(pcb, next); 1495 1496 mtx_unlock(&pcb->pcb_mtx); 1497 mtx_unlock(&ng_btsocket_hci_raw_sockets_mtx); 1498 1499 mtx_destroy(&pcb->pcb_mtx); 1500 1501 bzero(pcb, sizeof(*pcb)); 1502 free(pcb, M_NETGRAPH_BTSOCKET_HCI_RAW); 1503 1504 so->so_pcb = NULL; 1505 } /* ng_btsocket_hci_raw_detach */ 1506 1507 /* 1508 * Disconnect raw HCI socket 1509 */ 1510 1511 int 1512 ng_btsocket_hci_raw_disconnect(struct socket *so) 1513 { 1514 ng_btsocket_hci_raw_pcb_p pcb = so2hci_raw_pcb(so); 1515 1516 if (pcb == NULL) 1517 return (EINVAL); 1518 if (ng_btsocket_hci_raw_node == NULL) 1519 return (EINVAL); 1520 1521 mtx_lock(&pcb->pcb_mtx); 1522 soisdisconnected(so); 1523 mtx_unlock(&pcb->pcb_mtx); 1524 1525 return (0); 1526 } /* ng_btsocket_hci_raw_disconnect */ 1527 1528 /* 1529 * Get socket peer's address 1530 */ 1531 1532 int 1533 ng_btsocket_hci_raw_peeraddr(struct socket *so, struct sockaddr **nam) 1534 { 1535 return (ng_btsocket_hci_raw_sockaddr(so, nam)); 1536 } /* ng_btsocket_hci_raw_peeraddr */ 1537 1538 /* 1539 * Send data 1540 */ 1541 1542 int 1543 ng_btsocket_hci_raw_send(struct socket *so, int flags, struct mbuf *m, 1544 struct sockaddr *sa, struct mbuf *control, struct thread *td) 1545 { 1546 ng_btsocket_hci_raw_pcb_p pcb = so2hci_raw_pcb(so); 1547 struct mbuf *nam = NULL; 1548 int error = 0; 1549 1550 if (ng_btsocket_hci_raw_node == NULL) { 1551 error = ENETDOWN; 1552 goto drop; 1553 } 1554 if (pcb == NULL) { 1555 error = EINVAL; 1556 goto drop; 1557 } 1558 if (control != NULL) { 1559 error = EINVAL; 1560 goto drop; 1561 } 1562 1563 if (m->m_pkthdr.len < sizeof(ng_hci_cmd_pkt_t) || 1564 m->m_pkthdr.len > sizeof(ng_hci_cmd_pkt_t) + NG_HCI_CMD_PKT_SIZE) { 1565 error = EMSGSIZE; 1566 goto drop; 1567 } 1568 1569 if (m->m_len < sizeof(ng_hci_cmd_pkt_t)) { 1570 if ((m = m_pullup(m, sizeof(ng_hci_cmd_pkt_t))) == NULL) { 1571 error = ENOBUFS; 1572 goto drop; 1573 } 1574 } 1575 if (*mtod(m, u_int8_t *) != NG_HCI_CMD_PKT) { 1576 error = ENOTSUP; 1577 goto drop; 1578 } 1579 1580 mtx_lock(&pcb->pcb_mtx); 1581 1582 error = ng_btsocket_hci_raw_filter(pcb, m, 0); 1583 if (error != 0) { 1584 mtx_unlock(&pcb->pcb_mtx); 1585 goto drop; 1586 } 1587 1588 if (sa == NULL) { 1589 if (pcb->addr.hci_node[0] == 0) { 1590 mtx_unlock(&pcb->pcb_mtx); 1591 error = EDESTADDRREQ; 1592 goto drop; 1593 } 1594 1595 sa = (struct sockaddr *) &pcb->addr; 1596 } 1597 1598 MGET(nam, M_NOWAIT, MT_SONAME); 1599 if (nam == NULL) { 1600 mtx_unlock(&pcb->pcb_mtx); 1601 error = ENOBUFS; 1602 goto drop; 1603 } 1604 1605 nam->m_len = sizeof(struct sockaddr_hci); 1606 bcopy(sa,mtod(nam, struct sockaddr_hci *),sizeof(struct sockaddr_hci)); 1607 1608 nam->m_next = m; 1609 m = NULL; 1610 1611 mtx_unlock(&pcb->pcb_mtx); 1612 1613 return (ng_send_fn(ng_btsocket_hci_raw_node, NULL, 1614 ng_btsocket_hci_raw_output, nam, 0)); 1615 drop: 1616 NG_FREE_M(control); /* NG_FREE_M checks for != NULL */ 1617 NG_FREE_M(nam); 1618 NG_FREE_M(m); 1619 1620 return (error); 1621 } /* ng_btsocket_hci_raw_send */ 1622 1623 /* 1624 * Get socket address 1625 */ 1626 1627 int 1628 ng_btsocket_hci_raw_sockaddr(struct socket *so, struct sockaddr **nam) 1629 { 1630 ng_btsocket_hci_raw_pcb_p pcb = so2hci_raw_pcb(so); 1631 struct sockaddr_hci sa; 1632 1633 if (pcb == NULL) 1634 return (EINVAL); 1635 if (ng_btsocket_hci_raw_node == NULL) 1636 return (EINVAL); 1637 1638 bzero(&sa, sizeof(sa)); 1639 sa.hci_len = sizeof(sa); 1640 sa.hci_family = AF_BLUETOOTH; 1641 1642 mtx_lock(&pcb->pcb_mtx); 1643 strlcpy(sa.hci_node, pcb->addr.hci_node, sizeof(sa.hci_node)); 1644 mtx_unlock(&pcb->pcb_mtx); 1645 1646 *nam = sodupsockaddr((struct sockaddr *) &sa, M_NOWAIT); 1647 1648 return ((*nam == NULL)? ENOMEM : 0); 1649 } /* ng_btsocket_hci_raw_sockaddr */ 1650 1651