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 } /* ng_btsocket_hci_raw_init */ 880 881 /* 882 * Abort connection on socket 883 */ 884 885 void 886 ng_btsocket_hci_raw_abort(struct socket *so) 887 { 888 } /* ng_btsocket_hci_raw_abort */ 889 890 void 891 ng_btsocket_hci_raw_close(struct socket *so) 892 { 893 } /* ng_btsocket_hci_raw_close */ 894 895 /* 896 * Create new raw HCI socket 897 */ 898 899 int 900 ng_btsocket_hci_raw_attach(struct socket *so, int proto, struct thread *td) 901 { 902 ng_btsocket_hci_raw_pcb_p pcb = so2hci_raw_pcb(so); 903 int error = 0; 904 905 if (pcb != NULL) 906 return (EISCONN); 907 908 if (ng_btsocket_hci_raw_node == NULL) 909 return (EPROTONOSUPPORT); 910 if (proto != BLUETOOTH_PROTO_HCI) 911 return (EPROTONOSUPPORT); 912 if (so->so_type != SOCK_RAW) 913 return (ESOCKTNOSUPPORT); 914 915 error = soreserve(so, NG_BTSOCKET_HCI_RAW_SENDSPACE, 916 NG_BTSOCKET_HCI_RAW_RECVSPACE); 917 if (error != 0) 918 return (error); 919 920 pcb = malloc(sizeof(*pcb), 921 M_NETGRAPH_BTSOCKET_HCI_RAW, M_NOWAIT|M_ZERO); 922 if (pcb == NULL) 923 return (ENOMEM); 924 925 so->so_pcb = (caddr_t) pcb; 926 pcb->so = so; 927 928 if (priv_check(td, PRIV_NETBLUETOOTH_RAW) == 0) 929 pcb->flags |= NG_BTSOCKET_HCI_RAW_PRIVILEGED; 930 931 /* 932 * Set default socket filter. By default socket only accepts HCI 933 * Command_Complete and Command_Status event packets. 934 */ 935 936 bit_set(pcb->filter.event_mask, NG_HCI_EVENT_COMMAND_COMPL - 1); 937 bit_set(pcb->filter.event_mask, NG_HCI_EVENT_COMMAND_STATUS - 1); 938 939 mtx_init(&pcb->pcb_mtx, "btsocks_hci_raw_pcb_mtx", NULL, MTX_DEF); 940 941 mtx_lock(&ng_btsocket_hci_raw_sockets_mtx); 942 LIST_INSERT_HEAD(&ng_btsocket_hci_raw_sockets, pcb, next); 943 mtx_unlock(&ng_btsocket_hci_raw_sockets_mtx); 944 945 return (0); 946 } /* ng_btsocket_hci_raw_attach */ 947 948 /* 949 * Bind raw HCI socket 950 */ 951 952 int 953 ng_btsocket_hci_raw_bind(struct socket *so, struct sockaddr *nam, 954 struct thread *td) 955 { 956 ng_btsocket_hci_raw_pcb_p pcb = so2hci_raw_pcb(so); 957 struct sockaddr_hci *sa = (struct sockaddr_hci *) nam; 958 959 if (pcb == NULL) 960 return (EINVAL); 961 if (ng_btsocket_hci_raw_node == NULL) 962 return (EINVAL); 963 964 if (sa == NULL) 965 return (EINVAL); 966 if (sa->hci_family != AF_BLUETOOTH) 967 return (EAFNOSUPPORT); 968 if (sa->hci_len != sizeof(*sa)) 969 return (EINVAL); 970 if (sa->hci_node[0] == 0) 971 return (EINVAL); 972 973 mtx_lock(&pcb->pcb_mtx); 974 bcopy(sa, &pcb->addr, sizeof(pcb->addr)); 975 mtx_unlock(&pcb->pcb_mtx); 976 977 return (0); 978 } /* ng_btsocket_hci_raw_bind */ 979 980 /* 981 * Connect raw HCI socket 982 */ 983 984 int 985 ng_btsocket_hci_raw_connect(struct socket *so, struct sockaddr *nam, 986 struct thread *td) 987 { 988 ng_btsocket_hci_raw_pcb_p pcb = so2hci_raw_pcb(so); 989 struct sockaddr_hci *sa = (struct sockaddr_hci *) nam; 990 991 if (pcb == NULL) 992 return (EINVAL); 993 if (ng_btsocket_hci_raw_node == NULL) 994 return (EINVAL); 995 996 if (sa == NULL) 997 return (EINVAL); 998 if (sa->hci_family != AF_BLUETOOTH) 999 return (EAFNOSUPPORT); 1000 if (sa->hci_len != sizeof(*sa)) 1001 return (EINVAL); 1002 if (sa->hci_node[0] == 0) 1003 return (EDESTADDRREQ); 1004 1005 mtx_lock(&pcb->pcb_mtx); 1006 1007 if (bcmp(sa, &pcb->addr, sizeof(pcb->addr)) != 0) { 1008 mtx_unlock(&pcb->pcb_mtx); 1009 return (EADDRNOTAVAIL); 1010 } 1011 1012 soisconnected(so); 1013 1014 mtx_unlock(&pcb->pcb_mtx); 1015 1016 return (0); 1017 } /* ng_btsocket_hci_raw_connect */ 1018 1019 /* 1020 * Process ioctl on socket 1021 */ 1022 1023 int 1024 ng_btsocket_hci_raw_control(struct socket *so, u_long cmd, caddr_t data, 1025 struct ifnet *ifp, struct thread *td) 1026 { 1027 ng_btsocket_hci_raw_pcb_p pcb = so2hci_raw_pcb(so); 1028 char path[NG_NODESIZ + 1]; 1029 struct ng_mesg *msg = NULL; 1030 int error = 0; 1031 1032 if (pcb == NULL) 1033 return (EINVAL); 1034 if (ng_btsocket_hci_raw_node == NULL) 1035 return (EINVAL); 1036 1037 mtx_lock(&pcb->pcb_mtx); 1038 1039 /* Check if we have device name */ 1040 if (pcb->addr.hci_node[0] == 0) { 1041 mtx_unlock(&pcb->pcb_mtx); 1042 return (EHOSTUNREACH); 1043 } 1044 1045 /* Check if we have pending ioctl() */ 1046 if (pcb->token != 0) { 1047 mtx_unlock(&pcb->pcb_mtx); 1048 return (EBUSY); 1049 } 1050 1051 snprintf(path, sizeof(path), "%s:", pcb->addr.hci_node); 1052 1053 switch (cmd) { 1054 case SIOC_HCI_RAW_NODE_GET_STATE: { 1055 struct ng_btsocket_hci_raw_node_state *p = 1056 (struct ng_btsocket_hci_raw_node_state *) data; 1057 1058 error = ng_btsocket_hci_raw_send_sync_ngmsg(pcb, path, 1059 NGM_HCI_NODE_GET_STATE, 1060 &p->state, sizeof(p->state)); 1061 } break; 1062 1063 case SIOC_HCI_RAW_NODE_INIT: 1064 if (pcb->flags & NG_BTSOCKET_HCI_RAW_PRIVILEGED) 1065 error = ng_btsocket_hci_raw_send_ngmsg(path, 1066 NGM_HCI_NODE_INIT, NULL, 0); 1067 else 1068 error = EPERM; 1069 break; 1070 1071 case SIOC_HCI_RAW_NODE_GET_DEBUG: { 1072 struct ng_btsocket_hci_raw_node_debug *p = 1073 (struct ng_btsocket_hci_raw_node_debug *) data; 1074 1075 error = ng_btsocket_hci_raw_send_sync_ngmsg(pcb, path, 1076 NGM_HCI_NODE_GET_DEBUG, 1077 &p->debug, sizeof(p->debug)); 1078 } break; 1079 1080 case SIOC_HCI_RAW_NODE_SET_DEBUG: { 1081 struct ng_btsocket_hci_raw_node_debug *p = 1082 (struct ng_btsocket_hci_raw_node_debug *) data; 1083 1084 if (pcb->flags & NG_BTSOCKET_HCI_RAW_PRIVILEGED) 1085 error = ng_btsocket_hci_raw_send_ngmsg(path, 1086 NGM_HCI_NODE_SET_DEBUG, &p->debug, 1087 sizeof(p->debug)); 1088 else 1089 error = EPERM; 1090 } break; 1091 1092 case SIOC_HCI_RAW_NODE_GET_BUFFER: { 1093 struct ng_btsocket_hci_raw_node_buffer *p = 1094 (struct ng_btsocket_hci_raw_node_buffer *) data; 1095 1096 error = ng_btsocket_hci_raw_send_sync_ngmsg(pcb, path, 1097 NGM_HCI_NODE_GET_BUFFER, 1098 &p->buffer, sizeof(p->buffer)); 1099 } break; 1100 1101 case SIOC_HCI_RAW_NODE_GET_BDADDR: { 1102 struct ng_btsocket_hci_raw_node_bdaddr *p = 1103 (struct ng_btsocket_hci_raw_node_bdaddr *) data; 1104 1105 error = ng_btsocket_hci_raw_send_sync_ngmsg(pcb, path, 1106 NGM_HCI_NODE_GET_BDADDR, 1107 &p->bdaddr, sizeof(p->bdaddr)); 1108 } break; 1109 1110 case SIOC_HCI_RAW_NODE_GET_FEATURES: { 1111 struct ng_btsocket_hci_raw_node_features *p = 1112 (struct ng_btsocket_hci_raw_node_features *) data; 1113 1114 error = ng_btsocket_hci_raw_send_sync_ngmsg(pcb, path, 1115 NGM_HCI_NODE_GET_FEATURES, 1116 &p->features, sizeof(p->features)); 1117 } break; 1118 1119 case SIOC_HCI_RAW_NODE_GET_STAT: { 1120 struct ng_btsocket_hci_raw_node_stat *p = 1121 (struct ng_btsocket_hci_raw_node_stat *) data; 1122 1123 error = ng_btsocket_hci_raw_send_sync_ngmsg(pcb, path, 1124 NGM_HCI_NODE_GET_STAT, 1125 &p->stat, sizeof(p->stat)); 1126 } break; 1127 1128 case SIOC_HCI_RAW_NODE_RESET_STAT: 1129 if (pcb->flags & NG_BTSOCKET_HCI_RAW_PRIVILEGED) 1130 error = ng_btsocket_hci_raw_send_ngmsg(path, 1131 NGM_HCI_NODE_RESET_STAT, NULL, 0); 1132 else 1133 error = EPERM; 1134 break; 1135 1136 case SIOC_HCI_RAW_NODE_FLUSH_NEIGHBOR_CACHE: 1137 if (pcb->flags & NG_BTSOCKET_HCI_RAW_PRIVILEGED) 1138 error = ng_btsocket_hci_raw_send_ngmsg(path, 1139 NGM_HCI_NODE_FLUSH_NEIGHBOR_CACHE, 1140 NULL, 0); 1141 else 1142 error = EPERM; 1143 break; 1144 1145 case SIOC_HCI_RAW_NODE_GET_NEIGHBOR_CACHE: { 1146 struct ng_btsocket_hci_raw_node_neighbor_cache *p = 1147 (struct ng_btsocket_hci_raw_node_neighbor_cache *) data; 1148 ng_hci_node_get_neighbor_cache_ep *p1 = NULL; 1149 ng_hci_node_neighbor_cache_entry_ep *p2 = NULL; 1150 1151 if (p->num_entries <= 0 || 1152 p->num_entries > NG_HCI_MAX_NEIGHBOR_NUM || 1153 p->entries == NULL) { 1154 error = EINVAL; 1155 break; 1156 } 1157 1158 NG_MKMESSAGE(msg, NGM_HCI_COOKIE, 1159 NGM_HCI_NODE_GET_NEIGHBOR_CACHE, 0, M_NOWAIT); 1160 if (msg == NULL) { 1161 error = ENOMEM; 1162 break; 1163 } 1164 ng_btsocket_hci_raw_get_token(&msg->header.token); 1165 pcb->token = msg->header.token; 1166 pcb->msg = NULL; 1167 1168 NG_SEND_MSG_PATH(error, ng_btsocket_hci_raw_node, msg, path, 0); 1169 if (error != 0) { 1170 pcb->token = 0; 1171 break; 1172 } 1173 1174 error = msleep(&pcb->msg, &pcb->pcb_mtx, 1175 PZERO|PCATCH, "hcictl", 1176 ng_btsocket_hci_raw_ioctl_timeout * hz); 1177 pcb->token = 0; 1178 1179 if (error != 0) 1180 break; 1181 1182 if (pcb->msg != NULL && 1183 pcb->msg->header.cmd == NGM_HCI_NODE_GET_NEIGHBOR_CACHE) { 1184 /* Return data back to user space */ 1185 p1 = (ng_hci_node_get_neighbor_cache_ep *) 1186 (pcb->msg->data); 1187 p2 = (ng_hci_node_neighbor_cache_entry_ep *) 1188 (p1 + 1); 1189 1190 p->num_entries = min(p->num_entries, p1->num_entries); 1191 if (p->num_entries > 0) 1192 error = copyout((caddr_t) p2, 1193 (caddr_t) p->entries, 1194 p->num_entries * sizeof(*p2)); 1195 } else 1196 error = EINVAL; 1197 1198 NG_FREE_MSG(pcb->msg); /* checks for != NULL */ 1199 }break; 1200 1201 case SIOC_HCI_RAW_NODE_GET_CON_LIST: { 1202 struct ng_btsocket_hci_raw_con_list *p = 1203 (struct ng_btsocket_hci_raw_con_list *) data; 1204 ng_hci_node_con_list_ep *p1 = NULL; 1205 ng_hci_node_con_ep *p2 = NULL; 1206 1207 if (p->num_connections == 0 || 1208 p->num_connections > NG_HCI_MAX_CON_NUM || 1209 p->connections == NULL) { 1210 error = EINVAL; 1211 break; 1212 } 1213 1214 NG_MKMESSAGE(msg, NGM_HCI_COOKIE, NGM_HCI_NODE_GET_CON_LIST, 1215 0, M_NOWAIT); 1216 if (msg == NULL) { 1217 error = ENOMEM; 1218 break; 1219 } 1220 ng_btsocket_hci_raw_get_token(&msg->header.token); 1221 pcb->token = msg->header.token; 1222 pcb->msg = NULL; 1223 1224 NG_SEND_MSG_PATH(error, ng_btsocket_hci_raw_node, msg, path, 0); 1225 if (error != 0) { 1226 pcb->token = 0; 1227 break; 1228 } 1229 1230 error = msleep(&pcb->msg, &pcb->pcb_mtx, 1231 PZERO|PCATCH, "hcictl", 1232 ng_btsocket_hci_raw_ioctl_timeout * hz); 1233 pcb->token = 0; 1234 1235 if (error != 0) 1236 break; 1237 1238 if (pcb->msg != NULL && 1239 pcb->msg->header.cmd == NGM_HCI_NODE_GET_CON_LIST) { 1240 /* Return data back to user space */ 1241 p1 = (ng_hci_node_con_list_ep *)(pcb->msg->data); 1242 p2 = (ng_hci_node_con_ep *)(p1 + 1); 1243 1244 p->num_connections = min(p->num_connections, 1245 p1->num_connections); 1246 if (p->num_connections > 0) 1247 error = copyout((caddr_t) p2, 1248 (caddr_t) p->connections, 1249 p->num_connections * sizeof(*p2)); 1250 } else 1251 error = EINVAL; 1252 1253 NG_FREE_MSG(pcb->msg); /* checks for != NULL */ 1254 } break; 1255 1256 case SIOC_HCI_RAW_NODE_GET_LINK_POLICY_MASK: { 1257 struct ng_btsocket_hci_raw_node_link_policy_mask *p = 1258 (struct ng_btsocket_hci_raw_node_link_policy_mask *) 1259 data; 1260 1261 error = ng_btsocket_hci_raw_send_sync_ngmsg(pcb, path, 1262 NGM_HCI_NODE_GET_LINK_POLICY_SETTINGS_MASK, 1263 &p->policy_mask, sizeof(p->policy_mask)); 1264 } break; 1265 1266 case SIOC_HCI_RAW_NODE_SET_LINK_POLICY_MASK: { 1267 struct ng_btsocket_hci_raw_node_link_policy_mask *p = 1268 (struct ng_btsocket_hci_raw_node_link_policy_mask *) 1269 data; 1270 1271 if (pcb->flags & NG_BTSOCKET_HCI_RAW_PRIVILEGED) 1272 error = ng_btsocket_hci_raw_send_ngmsg(path, 1273 NGM_HCI_NODE_SET_LINK_POLICY_SETTINGS_MASK, 1274 &p->policy_mask, 1275 sizeof(p->policy_mask)); 1276 else 1277 error = EPERM; 1278 } break; 1279 1280 case SIOC_HCI_RAW_NODE_GET_PACKET_MASK: { 1281 struct ng_btsocket_hci_raw_node_packet_mask *p = 1282 (struct ng_btsocket_hci_raw_node_packet_mask *) data; 1283 1284 error = ng_btsocket_hci_raw_send_sync_ngmsg(pcb, path, 1285 NGM_HCI_NODE_GET_PACKET_MASK, 1286 &p->packet_mask, sizeof(p->packet_mask)); 1287 } break; 1288 1289 case SIOC_HCI_RAW_NODE_SET_PACKET_MASK: { 1290 struct ng_btsocket_hci_raw_node_packet_mask *p = 1291 (struct ng_btsocket_hci_raw_node_packet_mask *) data; 1292 1293 if (pcb->flags & NG_BTSOCKET_HCI_RAW_PRIVILEGED) 1294 error = ng_btsocket_hci_raw_send_ngmsg(path, 1295 NGM_HCI_NODE_SET_PACKET_MASK, 1296 &p->packet_mask, 1297 sizeof(p->packet_mask)); 1298 else 1299 error = EPERM; 1300 } break; 1301 1302 case SIOC_HCI_RAW_NODE_GET_ROLE_SWITCH: { 1303 struct ng_btsocket_hci_raw_node_role_switch *p = 1304 (struct ng_btsocket_hci_raw_node_role_switch *) data; 1305 1306 error = ng_btsocket_hci_raw_send_sync_ngmsg(pcb, path, 1307 NGM_HCI_NODE_GET_ROLE_SWITCH, 1308 &p->role_switch, sizeof(p->role_switch)); 1309 } break; 1310 1311 case SIOC_HCI_RAW_NODE_SET_ROLE_SWITCH: { 1312 struct ng_btsocket_hci_raw_node_role_switch *p = 1313 (struct ng_btsocket_hci_raw_node_role_switch *) data; 1314 1315 if (pcb->flags & NG_BTSOCKET_HCI_RAW_PRIVILEGED) 1316 error = ng_btsocket_hci_raw_send_ngmsg(path, 1317 NGM_HCI_NODE_SET_ROLE_SWITCH, 1318 &p->role_switch, 1319 sizeof(p->role_switch)); 1320 else 1321 error = EPERM; 1322 } break; 1323 1324 case SIOC_HCI_RAW_NODE_LIST_NAMES: { 1325 struct ng_btsocket_hci_raw_node_list_names *nl = 1326 (struct ng_btsocket_hci_raw_node_list_names *) data; 1327 struct nodeinfo *ni = nl->names; 1328 1329 if (nl->num_names == 0) { 1330 error = EINVAL; 1331 break; 1332 } 1333 1334 NG_MKMESSAGE(msg, NGM_GENERIC_COOKIE, NGM_LISTNAMES, 1335 0, M_NOWAIT); 1336 if (msg == NULL) { 1337 error = ENOMEM; 1338 break; 1339 } 1340 ng_btsocket_hci_raw_get_token(&msg->header.token); 1341 pcb->token = msg->header.token; 1342 pcb->msg = NULL; 1343 1344 NG_SEND_MSG_PATH(error, ng_btsocket_hci_raw_node, msg, ".:", 0); 1345 if (error != 0) { 1346 pcb->token = 0; 1347 break; 1348 } 1349 1350 error = msleep(&pcb->msg, &pcb->pcb_mtx, 1351 PZERO|PCATCH, "hcictl", 1352 ng_btsocket_hci_raw_ioctl_timeout * hz); 1353 pcb->token = 0; 1354 1355 if (error != 0) 1356 break; 1357 1358 if (pcb->msg != NULL && pcb->msg->header.cmd == NGM_LISTNAMES) { 1359 /* Return data back to user space */ 1360 struct namelist *nl1 = (struct namelist *) pcb->msg->data; 1361 struct nodeinfo *ni1 = &nl1->nodeinfo[0]; 1362 1363 while (nl->num_names > 0 && nl1->numnames > 0) { 1364 if (strcmp(ni1->type, NG_HCI_NODE_TYPE) == 0) { 1365 error = copyout((caddr_t) ni1, 1366 (caddr_t) ni, 1367 sizeof(*ni)); 1368 if (error != 0) 1369 break; 1370 1371 nl->num_names --; 1372 ni ++; 1373 } 1374 1375 nl1->numnames --; 1376 ni1 ++; 1377 } 1378 1379 nl->num_names = ni - nl->names; 1380 } else 1381 error = EINVAL; 1382 1383 NG_FREE_MSG(pcb->msg); /* checks for != NULL */ 1384 } break; 1385 1386 default: 1387 error = EINVAL; 1388 break; 1389 } 1390 1391 mtx_unlock(&pcb->pcb_mtx); 1392 1393 return (error); 1394 } /* ng_btsocket_hci_raw_control */ 1395 1396 /* 1397 * Process getsockopt/setsockopt system calls 1398 */ 1399 1400 int 1401 ng_btsocket_hci_raw_ctloutput(struct socket *so, struct sockopt *sopt) 1402 { 1403 ng_btsocket_hci_raw_pcb_p pcb = so2hci_raw_pcb(so); 1404 struct ng_btsocket_hci_raw_filter filter; 1405 int error = 0, dir; 1406 1407 if (pcb == NULL) 1408 return (EINVAL); 1409 if (ng_btsocket_hci_raw_node == NULL) 1410 return (EINVAL); 1411 1412 if (sopt->sopt_level != SOL_HCI_RAW) 1413 return (0); 1414 1415 mtx_lock(&pcb->pcb_mtx); 1416 1417 switch (sopt->sopt_dir) { 1418 case SOPT_GET: 1419 switch (sopt->sopt_name) { 1420 case SO_HCI_RAW_FILTER: 1421 error = sooptcopyout(sopt, &pcb->filter, 1422 sizeof(pcb->filter)); 1423 break; 1424 1425 case SO_HCI_RAW_DIRECTION: 1426 dir = (pcb->flags & NG_BTSOCKET_HCI_RAW_DIRECTION)?1:0; 1427 error = sooptcopyout(sopt, &dir, sizeof(dir)); 1428 break; 1429 1430 default: 1431 error = EINVAL; 1432 break; 1433 } 1434 break; 1435 1436 case SOPT_SET: 1437 switch (sopt->sopt_name) { 1438 case SO_HCI_RAW_FILTER: 1439 error = sooptcopyin(sopt, &filter, sizeof(filter), 1440 sizeof(filter)); 1441 if (error == 0) 1442 bcopy(&filter, &pcb->filter, 1443 sizeof(pcb->filter)); 1444 break; 1445 1446 case SO_HCI_RAW_DIRECTION: 1447 error = sooptcopyin(sopt, &dir, sizeof(dir), 1448 sizeof(dir)); 1449 if (error != 0) 1450 break; 1451 1452 if (dir) 1453 pcb->flags |= NG_BTSOCKET_HCI_RAW_DIRECTION; 1454 else 1455 pcb->flags &= ~NG_BTSOCKET_HCI_RAW_DIRECTION; 1456 break; 1457 1458 default: 1459 error = EINVAL; 1460 break; 1461 } 1462 break; 1463 1464 default: 1465 error = EINVAL; 1466 break; 1467 } 1468 1469 mtx_unlock(&pcb->pcb_mtx); 1470 1471 return (error); 1472 } /* ng_btsocket_hci_raw_ctloutput */ 1473 1474 /* 1475 * Detach raw HCI socket 1476 */ 1477 1478 void 1479 ng_btsocket_hci_raw_detach(struct socket *so) 1480 { 1481 ng_btsocket_hci_raw_pcb_p pcb = so2hci_raw_pcb(so); 1482 1483 KASSERT(pcb != NULL, ("ng_btsocket_hci_raw_detach: pcb == NULL")); 1484 1485 if (ng_btsocket_hci_raw_node == NULL) 1486 return; 1487 1488 mtx_lock(&ng_btsocket_hci_raw_sockets_mtx); 1489 mtx_lock(&pcb->pcb_mtx); 1490 1491 LIST_REMOVE(pcb, next); 1492 1493 mtx_unlock(&pcb->pcb_mtx); 1494 mtx_unlock(&ng_btsocket_hci_raw_sockets_mtx); 1495 1496 mtx_destroy(&pcb->pcb_mtx); 1497 1498 bzero(pcb, sizeof(*pcb)); 1499 free(pcb, M_NETGRAPH_BTSOCKET_HCI_RAW); 1500 1501 so->so_pcb = NULL; 1502 } /* ng_btsocket_hci_raw_detach */ 1503 1504 /* 1505 * Disconnect raw HCI socket 1506 */ 1507 1508 int 1509 ng_btsocket_hci_raw_disconnect(struct socket *so) 1510 { 1511 ng_btsocket_hci_raw_pcb_p pcb = so2hci_raw_pcb(so); 1512 1513 if (pcb == NULL) 1514 return (EINVAL); 1515 if (ng_btsocket_hci_raw_node == NULL) 1516 return (EINVAL); 1517 1518 mtx_lock(&pcb->pcb_mtx); 1519 soisdisconnected(so); 1520 mtx_unlock(&pcb->pcb_mtx); 1521 1522 return (0); 1523 } /* ng_btsocket_hci_raw_disconnect */ 1524 1525 /* 1526 * Get socket peer's address 1527 */ 1528 1529 int 1530 ng_btsocket_hci_raw_peeraddr(struct socket *so, struct sockaddr **nam) 1531 { 1532 return (ng_btsocket_hci_raw_sockaddr(so, nam)); 1533 } /* ng_btsocket_hci_raw_peeraddr */ 1534 1535 /* 1536 * Send data 1537 */ 1538 1539 int 1540 ng_btsocket_hci_raw_send(struct socket *so, int flags, struct mbuf *m, 1541 struct sockaddr *sa, struct mbuf *control, struct thread *td) 1542 { 1543 ng_btsocket_hci_raw_pcb_p pcb = so2hci_raw_pcb(so); 1544 struct mbuf *nam = NULL; 1545 int error = 0; 1546 1547 if (ng_btsocket_hci_raw_node == NULL) { 1548 error = ENETDOWN; 1549 goto drop; 1550 } 1551 if (pcb == NULL) { 1552 error = EINVAL; 1553 goto drop; 1554 } 1555 if (control != NULL) { 1556 error = EINVAL; 1557 goto drop; 1558 } 1559 1560 if (m->m_pkthdr.len < sizeof(ng_hci_cmd_pkt_t) || 1561 m->m_pkthdr.len > sizeof(ng_hci_cmd_pkt_t) + NG_HCI_CMD_PKT_SIZE) { 1562 error = EMSGSIZE; 1563 goto drop; 1564 } 1565 1566 if (m->m_len < sizeof(ng_hci_cmd_pkt_t)) { 1567 if ((m = m_pullup(m, sizeof(ng_hci_cmd_pkt_t))) == NULL) { 1568 error = ENOBUFS; 1569 goto drop; 1570 } 1571 } 1572 if (*mtod(m, u_int8_t *) != NG_HCI_CMD_PKT) { 1573 error = ENOTSUP; 1574 goto drop; 1575 } 1576 1577 mtx_lock(&pcb->pcb_mtx); 1578 1579 error = ng_btsocket_hci_raw_filter(pcb, m, 0); 1580 if (error != 0) { 1581 mtx_unlock(&pcb->pcb_mtx); 1582 goto drop; 1583 } 1584 1585 if (sa == NULL) { 1586 if (pcb->addr.hci_node[0] == 0) { 1587 mtx_unlock(&pcb->pcb_mtx); 1588 error = EDESTADDRREQ; 1589 goto drop; 1590 } 1591 1592 sa = (struct sockaddr *) &pcb->addr; 1593 } 1594 1595 MGET(nam, M_NOWAIT, MT_SONAME); 1596 if (nam == NULL) { 1597 mtx_unlock(&pcb->pcb_mtx); 1598 error = ENOBUFS; 1599 goto drop; 1600 } 1601 1602 nam->m_len = sizeof(struct sockaddr_hci); 1603 bcopy(sa,mtod(nam, struct sockaddr_hci *),sizeof(struct sockaddr_hci)); 1604 1605 nam->m_next = m; 1606 m = NULL; 1607 1608 mtx_unlock(&pcb->pcb_mtx); 1609 1610 return (ng_send_fn(ng_btsocket_hci_raw_node, NULL, 1611 ng_btsocket_hci_raw_output, nam, 0)); 1612 drop: 1613 NG_FREE_M(control); /* NG_FREE_M checks for != NULL */ 1614 NG_FREE_M(nam); 1615 NG_FREE_M(m); 1616 1617 return (error); 1618 } /* ng_btsocket_hci_raw_send */ 1619 1620 /* 1621 * Get socket address 1622 */ 1623 1624 int 1625 ng_btsocket_hci_raw_sockaddr(struct socket *so, struct sockaddr **nam) 1626 { 1627 ng_btsocket_hci_raw_pcb_p pcb = so2hci_raw_pcb(so); 1628 struct sockaddr_hci sa; 1629 1630 if (pcb == NULL) 1631 return (EINVAL); 1632 if (ng_btsocket_hci_raw_node == NULL) 1633 return (EINVAL); 1634 1635 bzero(&sa, sizeof(sa)); 1636 sa.hci_len = sizeof(sa); 1637 sa.hci_family = AF_BLUETOOTH; 1638 1639 mtx_lock(&pcb->pcb_mtx); 1640 strlcpy(sa.hci_node, pcb->addr.hci_node, sizeof(sa.hci_node)); 1641 mtx_unlock(&pcb->pcb_mtx); 1642 1643 *nam = sodupsockaddr((struct sockaddr *) &sa, M_NOWAIT); 1644 1645 return ((*nam == NULL)? ENOMEM : 0); 1646 } /* ng_btsocket_hci_raw_sockaddr */ 1647 1648