head 1.31; access; symbols RELENG_9_1_0_RELEASE:1.27.2.1.4.2 RELENG_9_1:1.27.2.1.0.4 RELENG_9_1_BP:1.27.2.1 RELENG_8_3_0_RELEASE:1.26.2.1.8.1 RELENG_8_3:1.26.2.1.0.8 RELENG_8_3_BP:1.26.2.1 RELENG_9_0_0_RELEASE:1.27.2.1.2.1 RELENG_9_0:1.27.2.1.0.2 RELENG_9_0_BP:1.27.2.1 RELENG_9:1.27.0.2 RELENG_9_BP:1.27 RELENG_7_4_0_RELEASE:1.23.2.2.8.1 RELENG_8_2_0_RELEASE:1.26.2.1.6.1 RELENG_7_4:1.23.2.2.0.8 RELENG_7_4_BP:1.23.2.2 RELENG_8_2:1.26.2.1.0.6 RELENG_8_2_BP:1.26.2.1 RELENG_8_1_0_RELEASE:1.26.2.1.4.1 RELENG_8_1:1.26.2.1.0.4 RELENG_8_1_BP:1.26.2.1 RELENG_7_3_0_RELEASE:1.23.2.2.6.1 RELENG_7_3:1.23.2.2.0.6 RELENG_7_3_BP:1.23.2.2 RELENG_8_0_0_RELEASE:1.26.2.1.2.1 RELENG_8_0:1.26.2.1.0.2 RELENG_8_0_BP:1.26.2.1 RELENG_8:1.26.0.2 RELENG_8_BP:1.26 RELENG_7_2_0_RELEASE:1.23.2.2.4.1 RELENG_7_2:1.23.2.2.0.4 RELENG_7_2_BP:1.23.2.2 RELENG_7_1_0_RELEASE:1.23.2.2.2.1 RELENG_6_4_0_RELEASE:1.17.2.4.2.1 RELENG_7_1:1.23.2.2.0.2 RELENG_7_1_BP:1.23.2.2 RELENG_6_4:1.17.2.4.0.2 RELENG_6_4_BP:1.17.2.4 RELENG_7_0_0_RELEASE:1.23 RELENG_6_3_0_RELEASE:1.17.2.2 RELENG_7_0:1.23.0.4 RELENG_7_0_BP:1.23 RELENG_6_3:1.17.2.2.0.4 RELENG_6_3_BP:1.17.2.2 RELENG_7:1.23.0.2 RELENG_7_BP:1.23 RELENG_6_2_0_RELEASE:1.17.2.2 RELENG_6_2:1.17.2.2.0.2 RELENG_6_2_BP:1.17.2.2 RELENG_5_5_0_RELEASE:1.15.2.3 RELENG_5_5:1.15.2.3.0.2 RELENG_5_5_BP:1.15.2.3 RELENG_6_1_0_RELEASE:1.17.2.1 RELENG_6_1:1.17.2.1.0.4 RELENG_6_1_BP:1.17.2.1 RELENG_6_0_0_RELEASE:1.17.2.1 RELENG_6_0:1.17.2.1.0.2 RELENG_6_0_BP:1.17.2.1 RELENG_6:1.17.0.2 RELENG_6_BP:1.17 RELENG_5_4_0_RELEASE:1.15.2.2 RELENG_5_4:1.15.2.2.0.2 RELENG_5_4_BP:1.15.2.2 RELENG_5_3_0_RELEASE:1.15.4.1 RELENG_5_3:1.15.0.4 RELENG_5_3_BP:1.15 RELENG_5:1.15.0.2 RELENG_5_BP:1.15 RELENG_5_2_1_RELEASE:1.9 RELENG_5_2_0_RELEASE:1.9 RELENG_5_2:1.9.0.2 RELENG_5_2_BP:1.9 RELENG_5_1_0_RELEASE:1.7 RELENG_5_1:1.7.0.2 RELENG_5_1_BP:1.7 RELENG_5_0_0_RELEASE:1.1 RELENG_5_0:1.1.0.2 RELENG_5_0_BP:1.1; locks; strict; comment @ * @; 1.31 date 2012.12.05.08.06.45; author svnexp; state Exp; branches; next 1.30; 1.30 date 2012.11.17.01.53.09; author svnexp; state Exp; branches; next 1.29; 1.29 date 2011.11.07.15.43.11; author ed; state Exp; branches; next 1.28; 1.28 date 2011.11.07.06.44.47; author ed; state Exp; branches; next 1.27; 1.27 date 2011.01.12.19.53.39; author mdf; state Exp; branches 1.27.2.1; next 1.26; 1.26 date 2008.10.23.15.53.51; author des; state Exp; branches 1.26.2.1; next 1.25; 1.25 date 2008.08.01.00.36.43; author emax; state Exp; branches; next 1.24; 1.24 date 2008.08.01.00.16.40; author emax; state Exp; branches; next 1.23; 1.23 date 2006.11.06.13.42.04; author rwatson; state Exp; branches 1.23.2.1; next 1.22; 1.22 date 2006.07.21.17.11.13; author rwatson; state Exp; branches; next 1.21; 1.21 date 2006.05.17.00.13.07; author emax; state Exp; branches; next 1.20; 1.20 date 2006.04.01.15.42.00; author rwatson; state Exp; branches; next 1.19; 1.19 date 2006.04.01.15.15.03; author rwatson; state Exp; branches; next 1.18; 1.18 date 2005.07.28.17.43.20; author emax; state Exp; branches; next 1.17; 1.17 date 2005.01.07.01.45.44; author imp; state Exp; branches 1.17.2.1; next 1.16; 1.16 date 2004.10.18.22.19.42; author rwatson; state Exp; branches; next 1.15; 1.15 date 2004.06.12.20.47.30; author rwatson; state Exp; branches 1.15.2.1 1.15.4.1; next 1.14; 1.14 date 2004.05.29.00.51.18; author julian; state Exp; branches; next 1.13; 1.13 date 2004.04.27.16.38.15; author emax; state Exp; branches; next 1.12; 1.12 date 2004.03.01.03.14.22; author rwatson; state Exp; branches; next 1.11; 1.11 date 2004.01.26.15.19.43; author harti; state Exp; branches; next 1.10; 1.10 date 2003.12.24.18.51.00; author alfred; state Exp; branches; next 1.9; 1.9 date 2003.10.12.22.04.21; author emax; state Exp; branches; next 1.8; 1.8 date 2003.06.13.19.40.44; author phk; state Exp; branches; next 1.7; 1.7 date 2003.05.10.21.44.41; author julian; state Exp; branches; next 1.6; 1.6 date 2003.04.08.14.25.45; author des; state Exp; branches; next 1.5; 1.5 date 2003.02.26.03.15.42; author scottl; state Exp; branches; next 1.4; 1.4 date 2003.02.19.05.47.33; author imp; state Exp; branches; next 1.3; 1.3 date 2003.01.21.08.56.03; author alfred; state Exp; branches; next 1.2; 1.2 date 2002.12.19.22.58.26; author bmilekic; state Exp; branches; next 1.1; 1.1 date 2002.11.20.23.01.57; author julian; state Exp; branches; next ; 1.27.2.1 date 2011.09.23.00.51.37; author kensmith; state Exp; branches 1.27.2.1.2.1 1.27.2.1.4.1; next 1.27.2.2; 1.27.2.2 date 2012.11.17.11.37.20; author svnexp; state Exp; branches; next ; 1.27.2.1.2.1 date 2011.11.11.04.20.22; author kensmith; state Exp; branches; next 1.27.2.1.2.2; 1.27.2.1.2.2 date 2012.11.17.08.37.17; author svnexp; state Exp; branches; next ; 1.27.2.1.4.1 date 2012.08.05.23.54.33; author kensmith; state Exp; branches; next 1.27.2.1.4.2; 1.27.2.1.4.2 date 2012.11.17.08.48.08; author svnexp; state Exp; branches; next ; 1.26.2.1 date 2009.08.03.08.13.06; author kensmith; state Exp; branches 1.26.2.1.2.1 1.26.2.1.4.1 1.26.2.1.6.1 1.26.2.1.8.1; next 1.26.2.2; 1.26.2.2 date 2012.11.17.10.37.00; author svnexp; state Exp; branches; next ; 1.26.2.1.2.1 date 2009.10.25.01.10.29; author kensmith; state Exp; branches; next ; 1.26.2.1.4.1 date 2010.06.14.02.09.06; author kensmith; state Exp; branches; next ; 1.26.2.1.6.1 date 2010.12.21.17.09.25; author kensmith; state Exp; branches; next ; 1.26.2.1.8.1 date 2012.03.03.06.15.13; author kensmith; state Exp; branches; next 1.26.2.1.8.2; 1.26.2.1.8.2 date 2012.11.17.08.25.36; author svnexp; state Exp; branches; next ; 1.23.2.1 date 2008.08.04.22.07.06; author emax; state Exp; branches; next 1.23.2.2; 1.23.2.2 date 2008.08.08.23.19.48; author emax; state Exp; branches 1.23.2.2.2.1 1.23.2.2.4.1 1.23.2.2.6.1 1.23.2.2.8.1; next 1.23.2.3; 1.23.2.3 date 2012.11.17.08.07.09; author svnexp; state Exp; branches; next ; 1.23.2.2.2.1 date 2008.11.25.02.59.29; author kensmith; state Exp; branches; next ; 1.23.2.2.4.1 date 2009.04.15.03.14.26; author kensmith; state Exp; branches; next ; 1.23.2.2.6.1 date 2010.02.10.00.26.20; author kensmith; state Exp; branches; next ; 1.23.2.2.8.1 date 2010.12.21.17.10.29; author kensmith; state Exp; branches; next 1.23.2.2.8.2; 1.23.2.2.8.2 date 2012.11.17.08.17.29; author svnexp; state Exp; branches; next ; 1.17.2.1 date 2005.08.29.17.00.54; author emax; state Exp; branches; next 1.17.2.2; 1.17.2.2 date 2006.05.24.00.51.22; author emax; state Exp; branches; next 1.17.2.3; 1.17.2.3 date 2008.08.04.22.21.44; author emax; state Exp; branches; next 1.17.2.4; 1.17.2.4 date 2008.08.08.23.23.44; author emax; state Exp; branches 1.17.2.4.2.1; next 1.17.2.5; 1.17.2.5 date 2012.11.17.07.44.40; author svnexp; state Exp; branches; next ; 1.17.2.4.2.1 date 2008.10.02.02.57.24; author kensmith; state Exp; branches; next ; 1.15.2.1 date 2004.10.20.12.42.55; author rwatson; state Exp; branches; next 1.15.2.2; 1.15.2.2 date 2005.01.31.23.26.34; author imp; state Exp; branches; next 1.15.2.3; 1.15.2.3 date 2005.08.29.17.03.51; author emax; state Exp; branches; next ; 1.15.4.1 date 2004.10.21.09.30.47; author rwatson; state Exp; branches; next ; desc @@ 1.31 log @## SVN ## Exported commit - http://svnweb.freebsd.org/changeset/base/243882 ## SVN ## CVS IS DEPRECATED: http://wiki.freebsd.org/CvsIsDeprecated @ text @/* * ng_btsocket_hci_raw.c */ /*- * Copyright (c) 2001-2002 Maksim Yevmenkin * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: ng_btsocket_hci_raw.c,v 1.14 2003/09/14 23:29:06 max Exp $ * $FreeBSD: head/sys/netgraph/bluetooth/socket/ng_btsocket_hci_raw.c 243882 2012-12-05 08:04:20Z glebius $ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* MALLOC define */ #ifdef NG_SEPARATE_MALLOC static MALLOC_DEFINE(M_NETGRAPH_BTSOCKET_HCI_RAW, "netgraph_btsocks_hci_raw", "Netgraph Bluetooth raw HCI sockets"); #else #define M_NETGRAPH_BTSOCKET_HCI_RAW M_NETGRAPH #endif /* NG_SEPARATE_MALLOC */ /* Netgraph node methods */ static ng_constructor_t ng_btsocket_hci_raw_node_constructor; static ng_rcvmsg_t ng_btsocket_hci_raw_node_rcvmsg; static ng_shutdown_t ng_btsocket_hci_raw_node_shutdown; static ng_newhook_t ng_btsocket_hci_raw_node_newhook; static ng_connect_t ng_btsocket_hci_raw_node_connect; static ng_rcvdata_t ng_btsocket_hci_raw_node_rcvdata; static ng_disconnect_t ng_btsocket_hci_raw_node_disconnect; static void ng_btsocket_hci_raw_input (void *, int); static void ng_btsocket_hci_raw_output(node_p, hook_p, void *, int); static void ng_btsocket_hci_raw_savctl(ng_btsocket_hci_raw_pcb_p, struct mbuf **, struct mbuf *); static int ng_btsocket_hci_raw_filter(ng_btsocket_hci_raw_pcb_p, struct mbuf *, int); #define ng_btsocket_hci_raw_wakeup_input_task() \ taskqueue_enqueue(taskqueue_swi, &ng_btsocket_hci_raw_task) /* Security filter */ struct ng_btsocket_hci_raw_sec_filter { bitstr_t bit_decl(events, 0xff); bitstr_t bit_decl(commands[0x3f], 0x3ff); }; /* Netgraph type descriptor */ static struct ng_type typestruct = { .version = NG_ABI_VERSION, .name = NG_BTSOCKET_HCI_RAW_NODE_TYPE, .constructor = ng_btsocket_hci_raw_node_constructor, .rcvmsg = ng_btsocket_hci_raw_node_rcvmsg, .shutdown = ng_btsocket_hci_raw_node_shutdown, .newhook = ng_btsocket_hci_raw_node_newhook, .connect = ng_btsocket_hci_raw_node_connect, .rcvdata = ng_btsocket_hci_raw_node_rcvdata, .disconnect = ng_btsocket_hci_raw_node_disconnect, }; /* Globals */ static u_int32_t ng_btsocket_hci_raw_debug_level; static u_int32_t ng_btsocket_hci_raw_ioctl_timeout; static node_p ng_btsocket_hci_raw_node; static struct ng_bt_itemq ng_btsocket_hci_raw_queue; static struct mtx ng_btsocket_hci_raw_queue_mtx; static struct task ng_btsocket_hci_raw_task; static LIST_HEAD(, ng_btsocket_hci_raw_pcb) ng_btsocket_hci_raw_sockets; static struct mtx ng_btsocket_hci_raw_sockets_mtx; static u_int32_t ng_btsocket_hci_raw_token; static struct mtx ng_btsocket_hci_raw_token_mtx; static struct ng_btsocket_hci_raw_sec_filter *ng_btsocket_hci_raw_sec_filter; static struct timeval ng_btsocket_hci_raw_lasttime; static int ng_btsocket_hci_raw_curpps; /* Sysctl tree */ SYSCTL_DECL(_net_bluetooth_hci_sockets); static SYSCTL_NODE(_net_bluetooth_hci_sockets, OID_AUTO, raw, CTLFLAG_RW, 0, "Bluetooth raw HCI sockets family"); SYSCTL_UINT(_net_bluetooth_hci_sockets_raw, OID_AUTO, debug_level, CTLFLAG_RW, &ng_btsocket_hci_raw_debug_level, NG_BTSOCKET_WARN_LEVEL, "Bluetooth raw HCI sockets debug level"); SYSCTL_UINT(_net_bluetooth_hci_sockets_raw, OID_AUTO, ioctl_timeout, CTLFLAG_RW, &ng_btsocket_hci_raw_ioctl_timeout, 5, "Bluetooth raw HCI sockets ioctl timeout"); SYSCTL_UINT(_net_bluetooth_hci_sockets_raw, OID_AUTO, queue_len, CTLFLAG_RD, &ng_btsocket_hci_raw_queue.len, 0, "Bluetooth raw HCI sockets input queue length"); SYSCTL_UINT(_net_bluetooth_hci_sockets_raw, OID_AUTO, queue_maxlen, CTLFLAG_RD, &ng_btsocket_hci_raw_queue.maxlen, 0, "Bluetooth raw HCI sockets input queue max. length"); SYSCTL_UINT(_net_bluetooth_hci_sockets_raw, OID_AUTO, queue_drops, CTLFLAG_RD, &ng_btsocket_hci_raw_queue.drops, 0, "Bluetooth raw HCI sockets input queue drops"); /* Debug */ #define NG_BTSOCKET_HCI_RAW_INFO \ if (ng_btsocket_hci_raw_debug_level >= NG_BTSOCKET_INFO_LEVEL && \ ppsratecheck(&ng_btsocket_hci_raw_lasttime, &ng_btsocket_hci_raw_curpps, 1)) \ printf #define NG_BTSOCKET_HCI_RAW_WARN \ if (ng_btsocket_hci_raw_debug_level >= NG_BTSOCKET_WARN_LEVEL && \ ppsratecheck(&ng_btsocket_hci_raw_lasttime, &ng_btsocket_hci_raw_curpps, 1)) \ printf #define NG_BTSOCKET_HCI_RAW_ERR \ if (ng_btsocket_hci_raw_debug_level >= NG_BTSOCKET_ERR_LEVEL && \ ppsratecheck(&ng_btsocket_hci_raw_lasttime, &ng_btsocket_hci_raw_curpps, 1)) \ printf #define NG_BTSOCKET_HCI_RAW_ALERT \ if (ng_btsocket_hci_raw_debug_level >= NG_BTSOCKET_ALERT_LEVEL && \ ppsratecheck(&ng_btsocket_hci_raw_lasttime, &ng_btsocket_hci_raw_curpps, 1)) \ printf /**************************************************************************** **************************************************************************** ** Netgraph specific **************************************************************************** ****************************************************************************/ /* * Netgraph node constructor. Do not allow to create node of this type. */ static int ng_btsocket_hci_raw_node_constructor(node_p node) { return (EINVAL); } /* ng_btsocket_hci_raw_node_constructor */ /* * Netgraph node destructor. Just let old node go and create new fresh one. */ static int ng_btsocket_hci_raw_node_shutdown(node_p node) { int error = 0; NG_NODE_UNREF(node); error = ng_make_node_common(&typestruct, &ng_btsocket_hci_raw_node); if (error != 0) { NG_BTSOCKET_HCI_RAW_ALERT( "%s: Could not create Netgraph node, error=%d\n", __func__, error); ng_btsocket_hci_raw_node = NULL; return (ENOMEM); } error = ng_name_node(ng_btsocket_hci_raw_node, NG_BTSOCKET_HCI_RAW_NODE_TYPE); if (error != 0) { NG_BTSOCKET_HCI_RAW_ALERT( "%s: Could not name Netgraph node, error=%d\n", __func__, error); NG_NODE_UNREF(ng_btsocket_hci_raw_node); ng_btsocket_hci_raw_node = NULL; return (EINVAL); } return (0); } /* ng_btsocket_hci_raw_node_shutdown */ /* * Create new hook. Just say "yes" */ static int ng_btsocket_hci_raw_node_newhook(node_p node, hook_p hook, char const *name) { return (0); } /* ng_btsocket_hci_raw_node_newhook */ /* * Connect hook. Just say "yes" */ static int ng_btsocket_hci_raw_node_connect(hook_p hook) { return (0); } /* ng_btsocket_hci_raw_node_connect */ /* * Disconnect hook */ static int ng_btsocket_hci_raw_node_disconnect(hook_p hook) { return (0); } /* ng_btsocket_hci_raw_node_disconnect */ /* * Receive control message. * Make sure it is a message from HCI node and it is a response. * Enqueue item and schedule input task. */ static int ng_btsocket_hci_raw_node_rcvmsg(node_p node, item_p item, hook_p lasthook) { struct ng_mesg *msg = NGI_MSG(item); /* item still has message */ int error = 0; /* * Check for empty sockets list creates LOR when both sender and * receiver device are connected to the same host, so remove it * for now */ if (msg != NULL && (msg->header.typecookie == NGM_HCI_COOKIE || msg->header.typecookie == NGM_GENERIC_COOKIE) && msg->header.flags & NGF_RESP) { if (msg->header.token == 0) { NG_FREE_ITEM(item); return (0); } mtx_lock(&ng_btsocket_hci_raw_queue_mtx); if (NG_BT_ITEMQ_FULL(&ng_btsocket_hci_raw_queue)) { NG_BTSOCKET_HCI_RAW_ERR( "%s: Input queue is full\n", __func__); NG_BT_ITEMQ_DROP(&ng_btsocket_hci_raw_queue); NG_FREE_ITEM(item); error = ENOBUFS; } else { NG_BT_ITEMQ_ENQUEUE(&ng_btsocket_hci_raw_queue, item); error = ng_btsocket_hci_raw_wakeup_input_task(); } mtx_unlock(&ng_btsocket_hci_raw_queue_mtx); } else { NG_FREE_ITEM(item); error = EINVAL; } return (error); } /* ng_btsocket_hci_raw_node_rcvmsg */ /* * Receive packet from the one of our hook. * Prepend every packet with sockaddr_hci and record sender's node name. * Enqueue item and schedule input task. */ static int ng_btsocket_hci_raw_node_rcvdata(hook_p hook, item_p item) { struct mbuf *nam = NULL; int error; /* * Check for empty sockets list creates LOR when both sender and * receiver device are connected to the same host, so remove it * for now */ MGET(nam, M_NOWAIT, MT_SONAME); if (nam != NULL) { struct sockaddr_hci *sa = mtod(nam, struct sockaddr_hci *); nam->m_len = sizeof(struct sockaddr_hci); sa->hci_len = sizeof(*sa); sa->hci_family = AF_BLUETOOTH; strlcpy(sa->hci_node, NG_PEER_NODE_NAME(hook), sizeof(sa->hci_node)); NGI_GET_M(item, nam->m_next); NGI_M(item) = nam; mtx_lock(&ng_btsocket_hci_raw_queue_mtx); if (NG_BT_ITEMQ_FULL(&ng_btsocket_hci_raw_queue)) { NG_BTSOCKET_HCI_RAW_ERR( "%s: Input queue is full\n", __func__); NG_BT_ITEMQ_DROP(&ng_btsocket_hci_raw_queue); NG_FREE_ITEM(item); error = ENOBUFS; } else { NG_BT_ITEMQ_ENQUEUE(&ng_btsocket_hci_raw_queue, item); error = ng_btsocket_hci_raw_wakeup_input_task(); } mtx_unlock(&ng_btsocket_hci_raw_queue_mtx); } else { NG_BTSOCKET_HCI_RAW_ERR( "%s: Failed to allocate address mbuf\n", __func__); NG_FREE_ITEM(item); error = ENOBUFS; } return (error); } /* ng_btsocket_hci_raw_node_rcvdata */ /**************************************************************************** **************************************************************************** ** Sockets specific **************************************************************************** ****************************************************************************/ /* * Get next token. We need token to avoid theoretical race where process * submits ioctl() message then interrupts ioctl() and re-submits another * ioctl() on the same socket *before* first ioctl() complete. */ static void ng_btsocket_hci_raw_get_token(u_int32_t *token) { mtx_lock(&ng_btsocket_hci_raw_token_mtx); if (++ ng_btsocket_hci_raw_token == 0) ng_btsocket_hci_raw_token = 1; *token = ng_btsocket_hci_raw_token; mtx_unlock(&ng_btsocket_hci_raw_token_mtx); } /* ng_btsocket_hci_raw_get_token */ /* * Send Netgraph message to the node - do not expect reply */ static int ng_btsocket_hci_raw_send_ngmsg(char *path, int cmd, void *arg, int arglen) { struct ng_mesg *msg = NULL; int error = 0; NG_MKMESSAGE(msg, NGM_HCI_COOKIE, cmd, arglen, M_NOWAIT); if (msg == NULL) return (ENOMEM); if (arg != NULL && arglen > 0) bcopy(arg, msg->data, arglen); NG_SEND_MSG_PATH(error, ng_btsocket_hci_raw_node, msg, path, 0); return (error); } /* ng_btsocket_hci_raw_send_ngmsg */ /* * Send Netgraph message to the node (no data) and wait for reply */ static int ng_btsocket_hci_raw_send_sync_ngmsg(ng_btsocket_hci_raw_pcb_p pcb, char *path, int cmd, void *rsp, int rsplen) { struct ng_mesg *msg = NULL; int error = 0; mtx_assert(&pcb->pcb_mtx, MA_OWNED); NG_MKMESSAGE(msg, NGM_HCI_COOKIE, cmd, 0, M_NOWAIT); if (msg == NULL) return (ENOMEM); ng_btsocket_hci_raw_get_token(&msg->header.token); pcb->token = msg->header.token; pcb->msg = NULL; NG_SEND_MSG_PATH(error, ng_btsocket_hci_raw_node, msg, path, 0); if (error != 0) { pcb->token = 0; return (error); } error = msleep(&pcb->msg, &pcb->pcb_mtx, PZERO|PCATCH, "hcictl", ng_btsocket_hci_raw_ioctl_timeout * hz); pcb->token = 0; if (error != 0) return (error); if (pcb->msg != NULL && pcb->msg->header.cmd == cmd) bcopy(pcb->msg->data, rsp, rsplen); else error = EINVAL; NG_FREE_MSG(pcb->msg); /* checks for != NULL */ return (0); } /* ng_btsocket_hci_raw_send_sync_ngmsg */ /* * Create control information for the packet */ static void ng_btsocket_hci_raw_savctl(ng_btsocket_hci_raw_pcb_p pcb, struct mbuf **ctl, struct mbuf *m) { int dir; struct timeval tv; mtx_assert(&pcb->pcb_mtx, MA_OWNED); if (pcb->flags & NG_BTSOCKET_HCI_RAW_DIRECTION) { dir = (m->m_flags & M_PROTO1)? 1 : 0; *ctl = sbcreatecontrol((caddr_t) &dir, sizeof(dir), SCM_HCI_RAW_DIRECTION, SOL_HCI_RAW); if (*ctl != NULL) ctl = &((*ctl)->m_next); } if (pcb->so->so_options & SO_TIMESTAMP) { microtime(&tv); *ctl = sbcreatecontrol((caddr_t) &tv, sizeof(tv), SCM_TIMESTAMP, SOL_SOCKET); if (*ctl != NULL) ctl = &((*ctl)->m_next); } } /* ng_btsocket_hci_raw_savctl */ /* * Raw HCI sockets data input routine */ static void ng_btsocket_hci_raw_data_input(struct mbuf *nam) { ng_btsocket_hci_raw_pcb_p pcb = NULL; struct mbuf *m0 = NULL, *m = NULL; struct sockaddr_hci *sa = NULL; m0 = nam->m_next; nam->m_next = NULL; KASSERT((nam->m_type == MT_SONAME), ("%s: m_type=%d\n", __func__, nam->m_type)); KASSERT((m0->m_flags & M_PKTHDR), ("%s: m_flags=%#x\n", __func__, m0->m_flags)); sa = mtod(nam, struct sockaddr_hci *); mtx_lock(&ng_btsocket_hci_raw_sockets_mtx); LIST_FOREACH(pcb, &ng_btsocket_hci_raw_sockets, next) { mtx_lock(&pcb->pcb_mtx); /* * If socket was bound then check address and * make sure it matches. */ if (pcb->addr.hci_node[0] != 0 && strcmp(sa->hci_node, pcb->addr.hci_node) != 0) goto next; /* * Check packet against filters * XXX do we have to call m_pullup() here? */ if (ng_btsocket_hci_raw_filter(pcb, m0, 1) != 0) goto next; /* * Make a copy of the packet, append to the socket's * receive queue and wakeup socket. sbappendaddr() * will check if socket has enough buffer space. */ m = m_dup(m0, M_NOWAIT); if (m != NULL) { struct mbuf *ctl = NULL; ng_btsocket_hci_raw_savctl(pcb, &ctl, m); if (sbappendaddr(&pcb->so->so_rcv, (struct sockaddr *) sa, m, ctl)) sorwakeup(pcb->so); else { NG_BTSOCKET_HCI_RAW_INFO( "%s: sbappendaddr() failed\n", __func__); NG_FREE_M(m); NG_FREE_M(ctl); } } next: mtx_unlock(&pcb->pcb_mtx); } mtx_unlock(&ng_btsocket_hci_raw_sockets_mtx); NG_FREE_M(nam); NG_FREE_M(m0); } /* ng_btsocket_hci_raw_data_input */ /* * Raw HCI sockets message input routine */ static void ng_btsocket_hci_raw_msg_input(struct ng_mesg *msg) { ng_btsocket_hci_raw_pcb_p pcb = NULL; mtx_lock(&ng_btsocket_hci_raw_sockets_mtx); LIST_FOREACH(pcb, &ng_btsocket_hci_raw_sockets, next) { mtx_lock(&pcb->pcb_mtx); if (msg->header.token == pcb->token) { pcb->msg = msg; wakeup(&pcb->msg); mtx_unlock(&pcb->pcb_mtx); mtx_unlock(&ng_btsocket_hci_raw_sockets_mtx); return; } mtx_unlock(&pcb->pcb_mtx); } mtx_unlock(&ng_btsocket_hci_raw_sockets_mtx); NG_FREE_MSG(msg); /* checks for != NULL */ } /* ng_btsocket_hci_raw_msg_input */ /* * Raw HCI sockets input routines */ static void ng_btsocket_hci_raw_input(void *context, int pending) { item_p item = NULL; for (;;) { mtx_lock(&ng_btsocket_hci_raw_queue_mtx); NG_BT_ITEMQ_DEQUEUE(&ng_btsocket_hci_raw_queue, item); mtx_unlock(&ng_btsocket_hci_raw_queue_mtx); if (item == NULL) break; switch(item->el_flags & NGQF_TYPE) { case NGQF_DATA: { struct mbuf *m = NULL; NGI_GET_M(item, m); ng_btsocket_hci_raw_data_input(m); } break; case NGQF_MESG: { struct ng_mesg *msg = NULL; NGI_GET_MSG(item, msg); ng_btsocket_hci_raw_msg_input(msg); } break; default: KASSERT(0, ("%s: invalid item type=%ld\n", __func__, (item->el_flags & NGQF_TYPE))); break; } NG_FREE_ITEM(item); } } /* ng_btsocket_hci_raw_input */ /* * Raw HCI sockets output routine */ static void ng_btsocket_hci_raw_output(node_p node, hook_p hook, void *arg1, int arg2) { struct mbuf *nam = (struct mbuf *) arg1, *m = NULL; struct sockaddr_hci *sa = NULL; int error; m = nam->m_next; nam->m_next = NULL; KASSERT((nam->m_type == MT_SONAME), ("%s: m_type=%d\n", __func__, nam->m_type)); KASSERT((m->m_flags & M_PKTHDR), ("%s: m_flags=%#x\n", __func__, m->m_flags)); sa = mtod(nam, struct sockaddr_hci *); /* * Find downstream hook * XXX For now access node hook list directly. Should be safe because * we used ng_send_fn() and we should have exclusive lock on the node. */ LIST_FOREACH(hook, &node->nd_hooks, hk_hooks) { if (hook == NULL || NG_HOOK_NOT_VALID(hook) || NG_NODE_NOT_VALID(NG_PEER_NODE(hook))) continue; if (strcmp(sa->hci_node, NG_PEER_NODE_NAME(hook)) == 0) { NG_SEND_DATA_ONLY(error, hook, m); /* sets m to NULL */ break; } } NG_FREE_M(nam); /* check for != NULL */ NG_FREE_M(m); } /* ng_btsocket_hci_raw_output */ /* * Check frame against security and socket filters. * d (direction bit) == 1 means incoming frame. */ static int ng_btsocket_hci_raw_filter(ng_btsocket_hci_raw_pcb_p pcb, struct mbuf *m, int d) { int type, event, opcode; mtx_assert(&pcb->pcb_mtx, MA_OWNED); switch ((type = *mtod(m, u_int8_t *))) { case NG_HCI_CMD_PKT: if (!(pcb->flags & NG_BTSOCKET_HCI_RAW_PRIVILEGED)) { opcode = le16toh(mtod(m, ng_hci_cmd_pkt_t *)->opcode); if (!bit_test( ng_btsocket_hci_raw_sec_filter->commands[NG_HCI_OGF(opcode) - 1], NG_HCI_OCF(opcode) - 1)) return (EPERM); } if (d && !bit_test(pcb->filter.packet_mask, NG_HCI_CMD_PKT - 1)) return (EPERM); break; case NG_HCI_ACL_DATA_PKT: case NG_HCI_SCO_DATA_PKT: if (!(pcb->flags & NG_BTSOCKET_HCI_RAW_PRIVILEGED) || !bit_test(pcb->filter.packet_mask, type - 1) || !d) return (EPERM); break; case NG_HCI_EVENT_PKT: if (!d) return (EINVAL); event = mtod(m, ng_hci_event_pkt_t *)->event - 1; if (!(pcb->flags & NG_BTSOCKET_HCI_RAW_PRIVILEGED)) if (!bit_test(ng_btsocket_hci_raw_sec_filter->events, event)) return (EPERM); if (!bit_test(pcb->filter.event_mask, event)) return (EPERM); break; default: return (EINVAL); } return (0); } /* ng_btsocket_hci_raw_filter */ /* * Initialize everything */ void ng_btsocket_hci_raw_init(void) { bitstr_t *f = NULL; int error = 0; ng_btsocket_hci_raw_node = NULL; ng_btsocket_hci_raw_debug_level = NG_BTSOCKET_WARN_LEVEL; ng_btsocket_hci_raw_ioctl_timeout = 5; /* Register Netgraph node type */ error = ng_newtype(&typestruct); if (error != 0) { NG_BTSOCKET_HCI_RAW_ALERT( "%s: Could not register Netgraph node type, error=%d\n", __func__, error); return; } /* Create Netgrapg node */ error = ng_make_node_common(&typestruct, &ng_btsocket_hci_raw_node); if (error != 0) { NG_BTSOCKET_HCI_RAW_ALERT( "%s: Could not create Netgraph node, error=%d\n", __func__, error); ng_btsocket_hci_raw_node = NULL; return; } error = ng_name_node(ng_btsocket_hci_raw_node, NG_BTSOCKET_HCI_RAW_NODE_TYPE); if (error != 0) { NG_BTSOCKET_HCI_RAW_ALERT( "%s: Could not name Netgraph node, error=%d\n", __func__, error); NG_NODE_UNREF(ng_btsocket_hci_raw_node); ng_btsocket_hci_raw_node = NULL; return; } /* Create input queue */ NG_BT_ITEMQ_INIT(&ng_btsocket_hci_raw_queue, 300); mtx_init(&ng_btsocket_hci_raw_queue_mtx, "btsocks_hci_raw_queue_mtx", NULL, MTX_DEF); TASK_INIT(&ng_btsocket_hci_raw_task, 0, ng_btsocket_hci_raw_input, NULL); /* Create list of sockets */ LIST_INIT(&ng_btsocket_hci_raw_sockets); mtx_init(&ng_btsocket_hci_raw_sockets_mtx, "btsocks_hci_raw_sockets_mtx", NULL, MTX_DEF); /* Tokens */ ng_btsocket_hci_raw_token = 0; mtx_init(&ng_btsocket_hci_raw_token_mtx, "btsocks_hci_raw_token_mtx", NULL, MTX_DEF); /* * Security filter * XXX never free()ed */ ng_btsocket_hci_raw_sec_filter = malloc(sizeof(struct ng_btsocket_hci_raw_sec_filter), M_NETGRAPH_BTSOCKET_HCI_RAW, M_NOWAIT|M_ZERO); if (ng_btsocket_hci_raw_sec_filter == NULL) { printf("%s: Could not allocate security filter!\n", __func__); return; } /* * XXX How paranoid can we get? * * Initialize security filter. If bit is set in the mask then * unprivileged socket is allowed to send (receive) this command * (event). */ /* Enable all events */ memset(&ng_btsocket_hci_raw_sec_filter->events, 0xff, sizeof(ng_btsocket_hci_raw_sec_filter->events)/ sizeof(ng_btsocket_hci_raw_sec_filter->events[0])); /* Disable some critical events */ f = ng_btsocket_hci_raw_sec_filter->events; bit_clear(f, NG_HCI_EVENT_RETURN_LINK_KEYS - 1); bit_clear(f, NG_HCI_EVENT_LINK_KEY_NOTIFICATION - 1); bit_clear(f, NG_HCI_EVENT_VENDOR - 1); /* Commands - Link control */ f = ng_btsocket_hci_raw_sec_filter->commands[NG_HCI_OGF_LINK_CONTROL-1]; bit_set(f, NG_HCI_OCF_INQUIRY - 1); bit_set(f, NG_HCI_OCF_INQUIRY_CANCEL - 1); bit_set(f, NG_HCI_OCF_PERIODIC_INQUIRY - 1); bit_set(f, NG_HCI_OCF_EXIT_PERIODIC_INQUIRY - 1); bit_set(f, NG_HCI_OCF_REMOTE_NAME_REQ - 1); bit_set(f, NG_HCI_OCF_READ_REMOTE_FEATURES - 1); bit_set(f, NG_HCI_OCF_READ_REMOTE_VER_INFO - 1); bit_set(f, NG_HCI_OCF_READ_CLOCK_OFFSET - 1); /* Commands - Link policy */ f = ng_btsocket_hci_raw_sec_filter->commands[NG_HCI_OGF_LINK_POLICY-1]; bit_set(f, NG_HCI_OCF_ROLE_DISCOVERY - 1); bit_set(f, NG_HCI_OCF_READ_LINK_POLICY_SETTINGS - 1); /* Commands - Host controller and baseband */ f = ng_btsocket_hci_raw_sec_filter->commands[NG_HCI_OGF_HC_BASEBAND-1]; bit_set(f, NG_HCI_OCF_READ_PIN_TYPE - 1); bit_set(f, NG_HCI_OCF_READ_LOCAL_NAME - 1); bit_set(f, NG_HCI_OCF_READ_CON_ACCEPT_TIMO - 1); bit_set(f, NG_HCI_OCF_READ_PAGE_TIMO - 1); bit_set(f, NG_HCI_OCF_READ_SCAN_ENABLE - 1); bit_set(f, NG_HCI_OCF_READ_PAGE_SCAN_ACTIVITY - 1); bit_set(f, NG_HCI_OCF_READ_INQUIRY_SCAN_ACTIVITY - 1); bit_set(f, NG_HCI_OCF_READ_AUTH_ENABLE - 1); bit_set(f, NG_HCI_OCF_READ_ENCRYPTION_MODE - 1); bit_set(f, NG_HCI_OCF_READ_UNIT_CLASS - 1); bit_set(f, NG_HCI_OCF_READ_VOICE_SETTINGS - 1); bit_set(f, NG_HCI_OCF_READ_AUTO_FLUSH_TIMO - 1); bit_set(f, NG_HCI_OCF_READ_NUM_BROADCAST_RETRANS - 1); bit_set(f, NG_HCI_OCF_READ_HOLD_MODE_ACTIVITY - 1); bit_set(f, NG_HCI_OCF_READ_XMIT_LEVEL - 1); bit_set(f, NG_HCI_OCF_READ_SCO_FLOW_CONTROL - 1); bit_set(f, NG_HCI_OCF_READ_LINK_SUPERVISION_TIMO - 1); bit_set(f, NG_HCI_OCF_READ_SUPPORTED_IAC_NUM - 1); bit_set(f, NG_HCI_OCF_READ_IAC_LAP - 1); bit_set(f, NG_HCI_OCF_READ_PAGE_SCAN_PERIOD - 1); bit_set(f, NG_HCI_OCF_READ_PAGE_SCAN - 1); /* Commands - Informational */ f = ng_btsocket_hci_raw_sec_filter->commands[NG_HCI_OGF_INFO - 1]; bit_set(f, NG_HCI_OCF_READ_LOCAL_VER - 1); bit_set(f, NG_HCI_OCF_READ_LOCAL_FEATURES - 1); bit_set(f, NG_HCI_OCF_READ_BUFFER_SIZE - 1); bit_set(f, NG_HCI_OCF_READ_COUNTRY_CODE - 1); bit_set(f, NG_HCI_OCF_READ_BDADDR - 1); /* Commands - Status */ f = ng_btsocket_hci_raw_sec_filter->commands[NG_HCI_OGF_STATUS - 1]; bit_set(f, NG_HCI_OCF_READ_FAILED_CONTACT_CNTR - 1); bit_set(f, NG_HCI_OCF_GET_LINK_QUALITY - 1); bit_set(f, NG_HCI_OCF_READ_RSSI - 1); /* Commands - Testing */ f = ng_btsocket_hci_raw_sec_filter->commands[NG_HCI_OGF_TESTING - 1]; bit_set(f, NG_HCI_OCF_READ_LOOPBACK_MODE - 1); } /* ng_btsocket_hci_raw_init */ /* * Abort connection on socket */ void ng_btsocket_hci_raw_abort(struct socket *so) { } /* ng_btsocket_hci_raw_abort */ void ng_btsocket_hci_raw_close(struct socket *so) { } /* ng_btsocket_hci_raw_close */ /* * Create new raw HCI socket */ int ng_btsocket_hci_raw_attach(struct socket *so, int proto, struct thread *td) { ng_btsocket_hci_raw_pcb_p pcb = so2hci_raw_pcb(so); int error = 0; if (pcb != NULL) return (EISCONN); if (ng_btsocket_hci_raw_node == NULL) return (EPROTONOSUPPORT); if (proto != BLUETOOTH_PROTO_HCI) return (EPROTONOSUPPORT); if (so->so_type != SOCK_RAW) return (ESOCKTNOSUPPORT); error = soreserve(so, NG_BTSOCKET_HCI_RAW_SENDSPACE, NG_BTSOCKET_HCI_RAW_RECVSPACE); if (error != 0) return (error); pcb = malloc(sizeof(*pcb), M_NETGRAPH_BTSOCKET_HCI_RAW, M_NOWAIT|M_ZERO); if (pcb == NULL) return (ENOMEM); so->so_pcb = (caddr_t) pcb; pcb->so = so; if (priv_check(td, PRIV_NETBLUETOOTH_RAW) == 0) pcb->flags |= NG_BTSOCKET_HCI_RAW_PRIVILEGED; /* * Set default socket filter. By default socket only accepts HCI * Command_Complete and Command_Status event packets. */ bit_set(pcb->filter.event_mask, NG_HCI_EVENT_COMMAND_COMPL - 1); bit_set(pcb->filter.event_mask, NG_HCI_EVENT_COMMAND_STATUS - 1); mtx_init(&pcb->pcb_mtx, "btsocks_hci_raw_pcb_mtx", NULL, MTX_DEF); mtx_lock(&ng_btsocket_hci_raw_sockets_mtx); LIST_INSERT_HEAD(&ng_btsocket_hci_raw_sockets, pcb, next); mtx_unlock(&ng_btsocket_hci_raw_sockets_mtx); return (0); } /* ng_btsocket_hci_raw_attach */ /* * Bind raw HCI socket */ int ng_btsocket_hci_raw_bind(struct socket *so, struct sockaddr *nam, struct thread *td) { ng_btsocket_hci_raw_pcb_p pcb = so2hci_raw_pcb(so); struct sockaddr_hci *sa = (struct sockaddr_hci *) nam; if (pcb == NULL) return (EINVAL); if (ng_btsocket_hci_raw_node == NULL) return (EINVAL); if (sa == NULL) return (EINVAL); if (sa->hci_family != AF_BLUETOOTH) return (EAFNOSUPPORT); if (sa->hci_len != sizeof(*sa)) return (EINVAL); if (sa->hci_node[0] == 0) return (EINVAL); mtx_lock(&pcb->pcb_mtx); bcopy(sa, &pcb->addr, sizeof(pcb->addr)); mtx_unlock(&pcb->pcb_mtx); return (0); } /* ng_btsocket_hci_raw_bind */ /* * Connect raw HCI socket */ int ng_btsocket_hci_raw_connect(struct socket *so, struct sockaddr *nam, struct thread *td) { ng_btsocket_hci_raw_pcb_p pcb = so2hci_raw_pcb(so); struct sockaddr_hci *sa = (struct sockaddr_hci *) nam; if (pcb == NULL) return (EINVAL); if (ng_btsocket_hci_raw_node == NULL) return (EINVAL); if (sa == NULL) return (EINVAL); if (sa->hci_family != AF_BLUETOOTH) return (EAFNOSUPPORT); if (sa->hci_len != sizeof(*sa)) return (EINVAL); if (sa->hci_node[0] == 0) return (EDESTADDRREQ); mtx_lock(&pcb->pcb_mtx); if (bcmp(sa, &pcb->addr, sizeof(pcb->addr)) != 0) { mtx_unlock(&pcb->pcb_mtx); return (EADDRNOTAVAIL); } soisconnected(so); mtx_unlock(&pcb->pcb_mtx); return (0); } /* ng_btsocket_hci_raw_connect */ /* * Process ioctl on socket */ int ng_btsocket_hci_raw_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp, struct thread *td) { ng_btsocket_hci_raw_pcb_p pcb = so2hci_raw_pcb(so); char path[NG_NODESIZ + 1]; struct ng_mesg *msg = NULL; int error = 0; if (pcb == NULL) return (EINVAL); if (ng_btsocket_hci_raw_node == NULL) return (EINVAL); mtx_lock(&pcb->pcb_mtx); /* Check if we have device name */ if (pcb->addr.hci_node[0] == 0) { mtx_unlock(&pcb->pcb_mtx); return (EHOSTUNREACH); } /* Check if we have pending ioctl() */ if (pcb->token != 0) { mtx_unlock(&pcb->pcb_mtx); return (EBUSY); } snprintf(path, sizeof(path), "%s:", pcb->addr.hci_node); switch (cmd) { case SIOC_HCI_RAW_NODE_GET_STATE: { struct ng_btsocket_hci_raw_node_state *p = (struct ng_btsocket_hci_raw_node_state *) data; error = ng_btsocket_hci_raw_send_sync_ngmsg(pcb, path, NGM_HCI_NODE_GET_STATE, &p->state, sizeof(p->state)); } break; case SIOC_HCI_RAW_NODE_INIT: if (pcb->flags & NG_BTSOCKET_HCI_RAW_PRIVILEGED) error = ng_btsocket_hci_raw_send_ngmsg(path, NGM_HCI_NODE_INIT, NULL, 0); else error = EPERM; break; case SIOC_HCI_RAW_NODE_GET_DEBUG: { struct ng_btsocket_hci_raw_node_debug *p = (struct ng_btsocket_hci_raw_node_debug *) data; error = ng_btsocket_hci_raw_send_sync_ngmsg(pcb, path, NGM_HCI_NODE_GET_DEBUG, &p->debug, sizeof(p->debug)); } break; case SIOC_HCI_RAW_NODE_SET_DEBUG: { struct ng_btsocket_hci_raw_node_debug *p = (struct ng_btsocket_hci_raw_node_debug *) data; if (pcb->flags & NG_BTSOCKET_HCI_RAW_PRIVILEGED) error = ng_btsocket_hci_raw_send_ngmsg(path, NGM_HCI_NODE_SET_DEBUG, &p->debug, sizeof(p->debug)); else error = EPERM; } break; case SIOC_HCI_RAW_NODE_GET_BUFFER: { struct ng_btsocket_hci_raw_node_buffer *p = (struct ng_btsocket_hci_raw_node_buffer *) data; error = ng_btsocket_hci_raw_send_sync_ngmsg(pcb, path, NGM_HCI_NODE_GET_BUFFER, &p->buffer, sizeof(p->buffer)); } break; case SIOC_HCI_RAW_NODE_GET_BDADDR: { struct ng_btsocket_hci_raw_node_bdaddr *p = (struct ng_btsocket_hci_raw_node_bdaddr *) data; error = ng_btsocket_hci_raw_send_sync_ngmsg(pcb, path, NGM_HCI_NODE_GET_BDADDR, &p->bdaddr, sizeof(p->bdaddr)); } break; case SIOC_HCI_RAW_NODE_GET_FEATURES: { struct ng_btsocket_hci_raw_node_features *p = (struct ng_btsocket_hci_raw_node_features *) data; error = ng_btsocket_hci_raw_send_sync_ngmsg(pcb, path, NGM_HCI_NODE_GET_FEATURES, &p->features, sizeof(p->features)); } break; case SIOC_HCI_RAW_NODE_GET_STAT: { struct ng_btsocket_hci_raw_node_stat *p = (struct ng_btsocket_hci_raw_node_stat *) data; error = ng_btsocket_hci_raw_send_sync_ngmsg(pcb, path, NGM_HCI_NODE_GET_STAT, &p->stat, sizeof(p->stat)); } break; case SIOC_HCI_RAW_NODE_RESET_STAT: if (pcb->flags & NG_BTSOCKET_HCI_RAW_PRIVILEGED) error = ng_btsocket_hci_raw_send_ngmsg(path, NGM_HCI_NODE_RESET_STAT, NULL, 0); else error = EPERM; break; case SIOC_HCI_RAW_NODE_FLUSH_NEIGHBOR_CACHE: if (pcb->flags & NG_BTSOCKET_HCI_RAW_PRIVILEGED) error = ng_btsocket_hci_raw_send_ngmsg(path, NGM_HCI_NODE_FLUSH_NEIGHBOR_CACHE, NULL, 0); else error = EPERM; break; case SIOC_HCI_RAW_NODE_GET_NEIGHBOR_CACHE: { struct ng_btsocket_hci_raw_node_neighbor_cache *p = (struct ng_btsocket_hci_raw_node_neighbor_cache *) data; ng_hci_node_get_neighbor_cache_ep *p1 = NULL; ng_hci_node_neighbor_cache_entry_ep *p2 = NULL; if (p->num_entries <= 0 || p->num_entries > NG_HCI_MAX_NEIGHBOR_NUM || p->entries == NULL) { error = EINVAL; break; } NG_MKMESSAGE(msg, NGM_HCI_COOKIE, NGM_HCI_NODE_GET_NEIGHBOR_CACHE, 0, M_NOWAIT); if (msg == NULL) { error = ENOMEM; break; } ng_btsocket_hci_raw_get_token(&msg->header.token); pcb->token = msg->header.token; pcb->msg = NULL; NG_SEND_MSG_PATH(error, ng_btsocket_hci_raw_node, msg, path, 0); if (error != 0) { pcb->token = 0; break; } error = msleep(&pcb->msg, &pcb->pcb_mtx, PZERO|PCATCH, "hcictl", ng_btsocket_hci_raw_ioctl_timeout * hz); pcb->token = 0; if (error != 0) break; if (pcb->msg != NULL && pcb->msg->header.cmd == NGM_HCI_NODE_GET_NEIGHBOR_CACHE) { /* Return data back to user space */ p1 = (ng_hci_node_get_neighbor_cache_ep *) (pcb->msg->data); p2 = (ng_hci_node_neighbor_cache_entry_ep *) (p1 + 1); p->num_entries = min(p->num_entries, p1->num_entries); if (p->num_entries > 0) error = copyout((caddr_t) p2, (caddr_t) p->entries, p->num_entries * sizeof(*p2)); } else error = EINVAL; NG_FREE_MSG(pcb->msg); /* checks for != NULL */ }break; case SIOC_HCI_RAW_NODE_GET_CON_LIST: { struct ng_btsocket_hci_raw_con_list *p = (struct ng_btsocket_hci_raw_con_list *) data; ng_hci_node_con_list_ep *p1 = NULL; ng_hci_node_con_ep *p2 = NULL; if (p->num_connections == 0 || p->num_connections > NG_HCI_MAX_CON_NUM || p->connections == NULL) { error = EINVAL; break; } NG_MKMESSAGE(msg, NGM_HCI_COOKIE, NGM_HCI_NODE_GET_CON_LIST, 0, M_NOWAIT); if (msg == NULL) { error = ENOMEM; break; } ng_btsocket_hci_raw_get_token(&msg->header.token); pcb->token = msg->header.token; pcb->msg = NULL; NG_SEND_MSG_PATH(error, ng_btsocket_hci_raw_node, msg, path, 0); if (error != 0) { pcb->token = 0; break; } error = msleep(&pcb->msg, &pcb->pcb_mtx, PZERO|PCATCH, "hcictl", ng_btsocket_hci_raw_ioctl_timeout * hz); pcb->token = 0; if (error != 0) break; if (pcb->msg != NULL && pcb->msg->header.cmd == NGM_HCI_NODE_GET_CON_LIST) { /* Return data back to user space */ p1 = (ng_hci_node_con_list_ep *)(pcb->msg->data); p2 = (ng_hci_node_con_ep *)(p1 + 1); p->num_connections = min(p->num_connections, p1->num_connections); if (p->num_connections > 0) error = copyout((caddr_t) p2, (caddr_t) p->connections, p->num_connections * sizeof(*p2)); } else error = EINVAL; NG_FREE_MSG(pcb->msg); /* checks for != NULL */ } break; case SIOC_HCI_RAW_NODE_GET_LINK_POLICY_MASK: { struct ng_btsocket_hci_raw_node_link_policy_mask *p = (struct ng_btsocket_hci_raw_node_link_policy_mask *) data; error = ng_btsocket_hci_raw_send_sync_ngmsg(pcb, path, NGM_HCI_NODE_GET_LINK_POLICY_SETTINGS_MASK, &p->policy_mask, sizeof(p->policy_mask)); } break; case SIOC_HCI_RAW_NODE_SET_LINK_POLICY_MASK: { struct ng_btsocket_hci_raw_node_link_policy_mask *p = (struct ng_btsocket_hci_raw_node_link_policy_mask *) data; if (pcb->flags & NG_BTSOCKET_HCI_RAW_PRIVILEGED) error = ng_btsocket_hci_raw_send_ngmsg(path, NGM_HCI_NODE_SET_LINK_POLICY_SETTINGS_MASK, &p->policy_mask, sizeof(p->policy_mask)); else error = EPERM; } break; case SIOC_HCI_RAW_NODE_GET_PACKET_MASK: { struct ng_btsocket_hci_raw_node_packet_mask *p = (struct ng_btsocket_hci_raw_node_packet_mask *) data; error = ng_btsocket_hci_raw_send_sync_ngmsg(pcb, path, NGM_HCI_NODE_GET_PACKET_MASK, &p->packet_mask, sizeof(p->packet_mask)); } break; case SIOC_HCI_RAW_NODE_SET_PACKET_MASK: { struct ng_btsocket_hci_raw_node_packet_mask *p = (struct ng_btsocket_hci_raw_node_packet_mask *) data; if (pcb->flags & NG_BTSOCKET_HCI_RAW_PRIVILEGED) error = ng_btsocket_hci_raw_send_ngmsg(path, NGM_HCI_NODE_SET_PACKET_MASK, &p->packet_mask, sizeof(p->packet_mask)); else error = EPERM; } break; case SIOC_HCI_RAW_NODE_GET_ROLE_SWITCH: { struct ng_btsocket_hci_raw_node_role_switch *p = (struct ng_btsocket_hci_raw_node_role_switch *) data; error = ng_btsocket_hci_raw_send_sync_ngmsg(pcb, path, NGM_HCI_NODE_GET_ROLE_SWITCH, &p->role_switch, sizeof(p->role_switch)); } break; case SIOC_HCI_RAW_NODE_SET_ROLE_SWITCH: { struct ng_btsocket_hci_raw_node_role_switch *p = (struct ng_btsocket_hci_raw_node_role_switch *) data; if (pcb->flags & NG_BTSOCKET_HCI_RAW_PRIVILEGED) error = ng_btsocket_hci_raw_send_ngmsg(path, NGM_HCI_NODE_SET_ROLE_SWITCH, &p->role_switch, sizeof(p->role_switch)); else error = EPERM; } break; case SIOC_HCI_RAW_NODE_LIST_NAMES: { struct ng_btsocket_hci_raw_node_list_names *nl = (struct ng_btsocket_hci_raw_node_list_names *) data; struct nodeinfo *ni = nl->names; if (nl->num_names == 0) { error = EINVAL; break; } NG_MKMESSAGE(msg, NGM_GENERIC_COOKIE, NGM_LISTNAMES, 0, M_NOWAIT); if (msg == NULL) { error = ENOMEM; break; } ng_btsocket_hci_raw_get_token(&msg->header.token); pcb->token = msg->header.token; pcb->msg = NULL; NG_SEND_MSG_PATH(error, ng_btsocket_hci_raw_node, msg, ".:", 0); if (error != 0) { pcb->token = 0; break; } error = msleep(&pcb->msg, &pcb->pcb_mtx, PZERO|PCATCH, "hcictl", ng_btsocket_hci_raw_ioctl_timeout * hz); pcb->token = 0; if (error != 0) break; if (pcb->msg != NULL && pcb->msg->header.cmd == NGM_LISTNAMES) { /* Return data back to user space */ struct namelist *nl1 = (struct namelist *) pcb->msg->data; struct nodeinfo *ni1 = &nl1->nodeinfo[0]; while (nl->num_names > 0 && nl1->numnames > 0) { if (strcmp(ni1->type, NG_HCI_NODE_TYPE) == 0) { error = copyout((caddr_t) ni1, (caddr_t) ni, sizeof(*ni)); if (error != 0) break; nl->num_names --; ni ++; } nl1->numnames --; ni1 ++; } nl->num_names = ni - nl->names; } else error = EINVAL; NG_FREE_MSG(pcb->msg); /* checks for != NULL */ } break; default: error = EINVAL; break; } mtx_unlock(&pcb->pcb_mtx); return (error); } /* ng_btsocket_hci_raw_control */ /* * Process getsockopt/setsockopt system calls */ int ng_btsocket_hci_raw_ctloutput(struct socket *so, struct sockopt *sopt) { ng_btsocket_hci_raw_pcb_p pcb = so2hci_raw_pcb(so); struct ng_btsocket_hci_raw_filter filter; int error = 0, dir; if (pcb == NULL) return (EINVAL); if (ng_btsocket_hci_raw_node == NULL) return (EINVAL); if (sopt->sopt_level != SOL_HCI_RAW) return (0); mtx_lock(&pcb->pcb_mtx); switch (sopt->sopt_dir) { case SOPT_GET: switch (sopt->sopt_name) { case SO_HCI_RAW_FILTER: error = sooptcopyout(sopt, &pcb->filter, sizeof(pcb->filter)); break; case SO_HCI_RAW_DIRECTION: dir = (pcb->flags & NG_BTSOCKET_HCI_RAW_DIRECTION)?1:0; error = sooptcopyout(sopt, &dir, sizeof(dir)); break; default: error = EINVAL; break; } break; case SOPT_SET: switch (sopt->sopt_name) { case SO_HCI_RAW_FILTER: error = sooptcopyin(sopt, &filter, sizeof(filter), sizeof(filter)); if (error == 0) bcopy(&filter, &pcb->filter, sizeof(pcb->filter)); break; case SO_HCI_RAW_DIRECTION: error = sooptcopyin(sopt, &dir, sizeof(dir), sizeof(dir)); if (error != 0) break; if (dir) pcb->flags |= NG_BTSOCKET_HCI_RAW_DIRECTION; else pcb->flags &= ~NG_BTSOCKET_HCI_RAW_DIRECTION; break; default: error = EINVAL; break; } break; default: error = EINVAL; break; } mtx_unlock(&pcb->pcb_mtx); return (error); } /* ng_btsocket_hci_raw_ctloutput */ /* * Detach raw HCI socket */ void ng_btsocket_hci_raw_detach(struct socket *so) { ng_btsocket_hci_raw_pcb_p pcb = so2hci_raw_pcb(so); KASSERT(pcb != NULL, ("ng_btsocket_hci_raw_detach: pcb == NULL")); if (ng_btsocket_hci_raw_node == NULL) return; mtx_lock(&ng_btsocket_hci_raw_sockets_mtx); mtx_lock(&pcb->pcb_mtx); LIST_REMOVE(pcb, next); mtx_unlock(&pcb->pcb_mtx); mtx_unlock(&ng_btsocket_hci_raw_sockets_mtx); mtx_destroy(&pcb->pcb_mtx); bzero(pcb, sizeof(*pcb)); free(pcb, M_NETGRAPH_BTSOCKET_HCI_RAW); so->so_pcb = NULL; } /* ng_btsocket_hci_raw_detach */ /* * Disconnect raw HCI socket */ int ng_btsocket_hci_raw_disconnect(struct socket *so) { ng_btsocket_hci_raw_pcb_p pcb = so2hci_raw_pcb(so); if (pcb == NULL) return (EINVAL); if (ng_btsocket_hci_raw_node == NULL) return (EINVAL); mtx_lock(&pcb->pcb_mtx); soisdisconnected(so); mtx_unlock(&pcb->pcb_mtx); return (0); } /* ng_btsocket_hci_raw_disconnect */ /* * Get socket peer's address */ int ng_btsocket_hci_raw_peeraddr(struct socket *so, struct sockaddr **nam) { return (ng_btsocket_hci_raw_sockaddr(so, nam)); } /* ng_btsocket_hci_raw_peeraddr */ /* * Send data */ int ng_btsocket_hci_raw_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *sa, struct mbuf *control, struct thread *td) { ng_btsocket_hci_raw_pcb_p pcb = so2hci_raw_pcb(so); struct mbuf *nam = NULL; int error = 0; if (ng_btsocket_hci_raw_node == NULL) { error = ENETDOWN; goto drop; } if (pcb == NULL) { error = EINVAL; goto drop; } if (control != NULL) { error = EINVAL; goto drop; } if (m->m_pkthdr.len < sizeof(ng_hci_cmd_pkt_t) || m->m_pkthdr.len > sizeof(ng_hci_cmd_pkt_t) + NG_HCI_CMD_PKT_SIZE) { error = EMSGSIZE; goto drop; } if (m->m_len < sizeof(ng_hci_cmd_pkt_t)) { if ((m = m_pullup(m, sizeof(ng_hci_cmd_pkt_t))) == NULL) { error = ENOBUFS; goto drop; } } if (*mtod(m, u_int8_t *) != NG_HCI_CMD_PKT) { error = ENOTSUP; goto drop; } mtx_lock(&pcb->pcb_mtx); error = ng_btsocket_hci_raw_filter(pcb, m, 0); if (error != 0) { mtx_unlock(&pcb->pcb_mtx); goto drop; } if (sa == NULL) { if (pcb->addr.hci_node[0] == 0) { mtx_unlock(&pcb->pcb_mtx); error = EDESTADDRREQ; goto drop; } sa = (struct sockaddr *) &pcb->addr; } MGET(nam, M_NOWAIT, MT_SONAME); if (nam == NULL) { mtx_unlock(&pcb->pcb_mtx); error = ENOBUFS; goto drop; } nam->m_len = sizeof(struct sockaddr_hci); bcopy(sa,mtod(nam, struct sockaddr_hci *),sizeof(struct sockaddr_hci)); nam->m_next = m; m = NULL; mtx_unlock(&pcb->pcb_mtx); return (ng_send_fn(ng_btsocket_hci_raw_node, NULL, ng_btsocket_hci_raw_output, nam, 0)); drop: NG_FREE_M(control); /* NG_FREE_M checks for != NULL */ NG_FREE_M(nam); NG_FREE_M(m); return (error); } /* ng_btsocket_hci_raw_send */ /* * Get socket address */ int ng_btsocket_hci_raw_sockaddr(struct socket *so, struct sockaddr **nam) { ng_btsocket_hci_raw_pcb_p pcb = so2hci_raw_pcb(so); struct sockaddr_hci sa; if (pcb == NULL) return (EINVAL); if (ng_btsocket_hci_raw_node == NULL) return (EINVAL); bzero(&sa, sizeof(sa)); sa.hci_len = sizeof(sa); sa.hci_family = AF_BLUETOOTH; mtx_lock(&pcb->pcb_mtx); strlcpy(sa.hci_node, pcb->addr.hci_node, sizeof(sa.hci_node)); mtx_unlock(&pcb->pcb_mtx); *nam = sodupsockaddr((struct sockaddr *) &sa, M_NOWAIT); return ((*nam == NULL)? ENOMEM : 0); } /* ng_btsocket_hci_raw_sockaddr */ @ 1.30 log @Switching exporter and resync @ text @d31 1 a31 1 * $FreeBSD: head/sys/netgraph/bluetooth/socket/ng_btsocket_hci_raw.c 227309 2011-11-07 15:43:11Z ed $ d313 1 a313 1 MGET(nam, M_DONTWAIT, MT_SONAME); d522 1 a522 1 m = m_dup(m0, M_DONTWAIT); d1588 1 a1588 1 MGET(nam, M_DONTWAIT, MT_SONAME); @ 1.29 log @SVN rev 227309 on 2011-11-07 15:43:11Z by ed Mark all SYSCTL_NODEs static that have no corresponding SYSCTL_DECLs. The SYSCTL_NODE macro defines a list that stores all child-elements of that node. If there's no SYSCTL_DECL macro anywhere else, there's no reason why it shouldn't be static. @ text @d31 1 a31 1 * $FreeBSD$ @ 1.28 log @SVN rev 227293 on 2011-11-07 06:44:47Z by ed Mark MALLOC_DEFINEs static that have no corresponding MALLOC_DECLAREs. This means that their use is restricted to a single C file. @ text @d126 1 a126 1 SYSCTL_NODE(_net_bluetooth_hci_sockets, OID_AUTO, raw, CTLFLAG_RW, @ 1.27 log @SVN rev 217320 on 2011-01-12 19:53:39Z by mdf sysctl(9) cleanup checkpoint: amd64 GENERIC builds cleanly. Commit the netgraph piece. @ text @d64 1 a64 1 MALLOC_DEFINE(M_NETGRAPH_BTSOCKET_HCI_RAW, "netgraph_btsocks_hci_raw", @ 1.27.2.1 log @SVN rev 225736 on 2011-09-23 00:51:37Z by kensmith Copy head to stable/9 as part of 9.0-RELEASE release cycle. Approved by: re (implicit) @ text @@ 1.27.2.2 log @## SVN ## ## SVN ## Exported commit - http://svnweb.freebsd.org/changeset/base/ 242902 ## SVN ## CVS IS DEPRECATED: http://wiki.freebsd.org/CvsIsDeprecated ## SVN ## ## SVN ## ------------------------------------------------------------------------ ## SVN ## r242902 | dteske | 2012-11-11 23:29:45 +0000 (Sun, 11 Nov 2012) | 10 lines ## SVN ## ## SVN ## Fix a regression introduced by SVN r211417 that saw the breakage of a feature ## SVN ## documented in usr.sbin/sysinstall/help/shortcuts.hlp (reproduced below): ## SVN ## ## SVN ## If /usr/sbin/sysinstall is linked to another filename, say ## SVN ## `/usr/local/bin/configPackages', then the basename will be used ## SVN ## as an implicit command name. ## SVN ## ## SVN ## Reviewed by: adrian (co-mentor) ## SVN ## Approved by: adrian (co-mentor) ## SVN ## ## SVN ## ------------------------------------------------------------------------ ## SVN ## @ text @d31 1 a31 1 * $FreeBSD: stable/9/sys/netgraph/bluetooth/socket/ng_btsocket_hci_raw.c 217320 2011-01-12 19:53:39Z mdf $ @ 1.27.2.1.4.1 log @SVN rev 239080 on 2012-08-05 23:54:33Z by kensmith Copy stable/9 to releng/9.1 as part of the 9.1-RELEASE release process. Approved by: re (implicit) @ text @@ 1.27.2.1.4.2 log @Switch importer @ text @d31 1 a31 1 * $FreeBSD: releng/9.1/sys/netgraph/bluetooth/socket/ng_btsocket_hci_raw.c 217320 2011-01-12 19:53:39Z mdf $ @ 1.27.2.1.2.1 log @SVN rev 227445 on 2011-11-11 04:20:22Z by kensmith Copy stable/9 to releng/9.0 as part of the FreeBSD 9.0-RELEASE release cycle. Approved by: re (implicit) @ text @@ 1.27.2.1.2.2 log @Switch importer @ text @d31 1 a31 1 * $FreeBSD: releng/9.0/sys/netgraph/bluetooth/socket/ng_btsocket_hci_raw.c 217320 2011-01-12 19:53:39Z mdf $ @ 1.26 log @SVN rev 184205 on 2008-10-23 15:53:51Z by des Retire the MALLOC and FREE macros. They are an abomination unto style(9). MFC after: 3 months @ text @d128 1 a128 1 SYSCTL_INT(_net_bluetooth_hci_sockets_raw, OID_AUTO, debug_level, CTLFLAG_RW, d131 1 a131 1 SYSCTL_INT(_net_bluetooth_hci_sockets_raw, OID_AUTO, ioctl_timeout, CTLFLAG_RW, d134 1 a134 1 SYSCTL_INT(_net_bluetooth_hci_sockets_raw, OID_AUTO, queue_len, CTLFLAG_RD, d137 1 a137 1 SYSCTL_INT(_net_bluetooth_hci_sockets_raw, OID_AUTO, queue_maxlen, CTLFLAG_RD, d140 1 a140 1 SYSCTL_INT(_net_bluetooth_hci_sockets_raw, OID_AUTO, queue_drops, CTLFLAG_RD, @ 1.26.2.1 log @SVN rev 196045 on 2009-08-03 08:13:06Z by kensmith Copy head to stable/8 as part of 8.0 Release cycle. Approved by: re (Implicit) @ text @@ 1.26.2.2 log @## SVN ## ## SVN ## Exported commit - http://svnweb.freebsd.org/changeset/base/ 242909 ## SVN ## CVS IS DEPRECATED: http://wiki.freebsd.org/CvsIsDeprecated ## SVN ## ## SVN ## ------------------------------------------------------------------------ ## SVN ## r242909 | dim | 2012-11-12 07:47:19 +0000 (Mon, 12 Nov 2012) | 20 lines ## SVN ## ## SVN ## MFC r242625: ## SVN ## ## SVN ## Remove duplicate const specifiers in many drivers (I hope I got all of ## SVN ## them, please let me know if not). Most of these are of the form: ## SVN ## ## SVN ## static const struct bzzt_type { ## SVN ## [...list of members...] ## SVN ## } const bzzt_devs[] = { ## SVN ## [...list of initializers...] ## SVN ## }; ## SVN ## ## SVN ## The second const is unnecessary, as arrays cannot be modified anyway, ## SVN ## and if the elements are const, the whole thing is const automatically ## SVN ## (e.g. it is placed in .rodata). ## SVN ## ## SVN ## I have verified this does not change the binary output of a full kernel ## SVN ## build (except for build timestamps embedded in the object files). ## SVN ## ## SVN ## Reviewed by: yongari, marius ## SVN ## ## SVN ## ------------------------------------------------------------------------ ## SVN ## @ text @d31 1 a31 1 * $FreeBSD: stable/8/sys/netgraph/bluetooth/socket/ng_btsocket_hci_raw.c 184205 2008-10-23 15:53:51Z des $ @ 1.26.2.1.8.1 log @SVN rev 232438 on 2012-03-03 06:15:13Z by kensmith Copy stable/8 to releng/8.3 as part of 8.3-RELEASE release cycle. Approved by: re (implicit) @ text @@ 1.26.2.1.8.2 log @Switch importer @ text @d31 1 a31 1 * $FreeBSD: releng/8.3/sys/netgraph/bluetooth/socket/ng_btsocket_hci_raw.c 184205 2008-10-23 15:53:51Z des $ @ 1.26.2.1.6.1 log @SVN rev 216617 on 2010-12-21 17:09:25Z by kensmith Copy stable/8 to releng/8.2 in preparation for FreeBSD-8.2 release. Approved by: re (implicit) @ text @@ 1.26.2.1.4.1 log @SVN rev 209145 on 2010-06-14 02:09:06Z by kensmith Copy stable/8 to releng/8.1 in preparation for 8.1-RC1. Approved by: re (implicit) @ text @@ 1.26.2.1.2.1 log @SVN rev 198460 on 2009-10-25 01:10:29Z by kensmith Copy stable/8 to releng/8.0 as part of 8.0-RELEASE release procedure. Approved by: re (implicit) @ text @@ 1.25 log @SVN rev 181093 on 2008-08-01 00:36:43Z by emax Implement ratelimiting for debug messages. For now, allow at most one message per second. In the future might add a sysctl knob for each socket family to fine tune this. MFC after: 1 week @ text @d786 1 a786 1 * XXX never FREE()ed d788 2 a789 6 ng_btsocket_hci_raw_sec_filter = NULL; MALLOC(ng_btsocket_hci_raw_sec_filter, struct ng_btsocket_hci_raw_sec_filter *, sizeof(struct ng_btsocket_hci_raw_sec_filter), d913 1 a913 1 MALLOC(pcb, ng_btsocket_hci_raw_pcb_p, sizeof(*pcb), d1492 1 a1492 1 FREE(pcb, M_NETGRAPH_BTSOCKET_HCI_RAW); @ 1.24 log @SVN rev 181089 on 2008-08-01 00:16:40Z by emax Increase maximum input queue size limit for raw Bluetooth HCI sockets. MFC after: 3 days @ text @d121 2 d146 2 a147 1 if (ng_btsocket_hci_raw_debug_level >= NG_BTSOCKET_INFO_LEVEL) \ d151 2 a152 1 if (ng_btsocket_hci_raw_debug_level >= NG_BTSOCKET_WARN_LEVEL) \ d156 2 a157 1 if (ng_btsocket_hci_raw_debug_level >= NG_BTSOCKET_ERR_LEVEL) \ d161 2 a162 1 if (ng_btsocket_hci_raw_debug_level >= NG_BTSOCKET_ALERT_LEVEL) \ @ 1.23 log @Sweep kernel replacing suser(9) calls with priv(9) calls, assigning specific privilege names to a broad range of privileges. These may require some future tweaking. Sponsored by: nCircle Network Security, Inc. Obtained from: TrustedBSD Project Discussed on: arch@@ Reviewed (at least in part) by: mlaier, jmg, pjd, bde, ceri, Alex Lyashkov , Skip Ford , Antoine Brodin @ text @a109 1 extern int ifqmaxlen; d762 1 a762 1 NG_BT_ITEMQ_INIT(&ng_btsocket_hci_raw_queue, ifqmaxlen); @ 1.23.2.1 log @SVN rev 181310 on 2008-08-04 22:07:06Z by emax MFC: SVN rev 181089 Increase maximum input queue size limit for raw Bluetooth HCI sockets. @ text @d110 1 d763 1 a763 1 NG_BT_ITEMQ_INIT(&ng_btsocket_hci_raw_queue, 300); @ 1.23.2.2 log @SVN rev 181441 on 2008-08-08 23:19:48Z by emax MFC SVN rev 181093 Implement ratelimiting for debug messages. For now, allow at most one message per second. In the future might add a sysctl knob for each socket family to fine tune this. @ text @a120 2 static struct timeval ng_btsocket_hci_raw_lasttime; static int ng_btsocket_hci_raw_curpps; d144 1 a144 2 if (ng_btsocket_hci_raw_debug_level >= NG_BTSOCKET_INFO_LEVEL && \ ppsratecheck(&ng_btsocket_hci_raw_lasttime, &ng_btsocket_hci_raw_curpps, 1)) \ d148 1 a148 2 if (ng_btsocket_hci_raw_debug_level >= NG_BTSOCKET_WARN_LEVEL && \ ppsratecheck(&ng_btsocket_hci_raw_lasttime, &ng_btsocket_hci_raw_curpps, 1)) \ d152 1 a152 2 if (ng_btsocket_hci_raw_debug_level >= NG_BTSOCKET_ERR_LEVEL && \ ppsratecheck(&ng_btsocket_hci_raw_lasttime, &ng_btsocket_hci_raw_curpps, 1)) \ d156 1 a156 2 if (ng_btsocket_hci_raw_debug_level >= NG_BTSOCKET_ALERT_LEVEL && \ ppsratecheck(&ng_btsocket_hci_raw_lasttime, &ng_btsocket_hci_raw_curpps, 1)) \ @ 1.23.2.3 log @Switch importer @ text @d31 1 a31 1 * $FreeBSD: stable/7/sys/netgraph/bluetooth/socket/ng_btsocket_hci_raw.c 181441 2008-08-08 23:19:48Z emax $ @ 1.23.2.2.8.1 log @SVN rev 216618 on 2010-12-21 17:10:29Z by kensmith Copy stable/7 to releng/7.4 in preparation for FreeBSD-7.4 release. Approved by: re (implicit) @ text @@ 1.23.2.2.8.2 log @Switch importer @ text @d31 1 a31 1 * $FreeBSD: releng/7.4/sys/netgraph/bluetooth/socket/ng_btsocket_hci_raw.c 181441 2008-08-08 23:19:48Z emax $ @ 1.23.2.2.6.1 log @SVN rev 203736 on 2010-02-10 00:26:20Z by kensmith Copy stable/7 to releng/7.3 as part of the 7.3-RELEASE process. Approved by: re (implicit) @ text @@ 1.23.2.2.4.1 log @SVN rev 191087 on 2009-04-15 03:14:26Z by kensmith Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE. Approved by: re (implicit) @ text @@ 1.23.2.2.2.1 log @SVN rev 185281 on 2008-11-25 02:59:29Z by kensmith Create releng/7.1 in preparation for moving into RC phase of 7.1 release cycle. Approved by: re (implicit) @ text @@ 1.22 log @Change semantics of socket close and detach. Add a new protocol switch function, pru_close, to notify protocols that the file descriptor or other consumer of a socket is closing the socket. pru_abort is now a notification of close also, and no longer detaches. pru_detach is no longer used to notify of close, and will be called during socket tear-down by sofree() when all references to a socket evaporate after an earlier call to abort or close the socket. This means detach is now an unconditional teardown of a socket, whereas previously sockets could persist after detach of the protocol retained a reference. This faciliates sharing mutexes between layers of the network stack as the mutex is required during the checking and removal of references at the head of sofree(). With this change, pru_detach can now assume that the mutex will no longer be required by the socket layer after completion, whereas before this was not necessarily true. Reviewed by: gnn @ text @d47 1 d920 1 a920 1 if (suser(td) == 0) @ 1.21 log @Add new SIOC_HCI_RAW_NODE_LIST_NAMES ioctl. User-space applications can use this ioctl to obtain the list of HCI nodes. User-space application is expected to preallocate 'ng_btsocket_hci_raw_node_list_names' structure and set limit in 'num_nodes' field. The 'nodes' field should be allocated as well and it should have space for at least 'num_nodes' elements. The SIOC_HCI_RAW_NODE_LIST_NAMES should be issued on bound raw HCI socket. It does not really really matter what HCI name the socket is bound to, as long as it is not empty. MFC after: 1 week @ text @a878 1 ng_btsocket_hci_raw_detach(so); d881 5 @ 1.20 log @Chance protocol switch method pru_detach() so that it returns void rather than an error. Detaches do not "fail", they other occur or the protocol flags SS_PROTOREF to take ownership of the socket. soclose() no longer looks at so_pcb to see if it's NULL, relying entirely on the protocol to decide whether it's time to free the socket or not using SS_PROTOREF. so_pcb is now entirely owned and managed by the protocol code. Likewise, no longer test so_pcb in other socket functions, such as soreceive(), which have no business digging into protocol internals. Protocol detach routines no longer try to free the socket on detach, this is performed in the socket code if the protocol permits it. In rts_detach(), no longer test for rp != NULL in detach, and likewise in other protocols that don't permit a NULL so_pcb, reduce the incidence of testing for it during detach. netinet and netinet6 are not fully updated to this change, which will be in an upcoming commit. In their current state they may leak memory or panic. MFC after: 3 months @ text @d260 2 a261 1 msg->header.typecookie == NGM_HCI_COOKIE && d1311 62 @ 1.19 log @Change protocol switch pru_abort() API so that it returns void rather than an int, as an error here is not meaningful. Modify soabort() to unconditionally free the socket on the return of pru_abort(), and modify most protocols to no longer conditionally free the socket, since the caller will do this. This commit likely leaves parts of netinet and netinet6 in a situation where they may panic or leak memory, as they have not are not fully updated by this commit. This will be corrected shortly in followup commits to these components. MFC after: 3 months @ text @d1402 1 a1402 1 int d1407 2 a1408 2 if (pcb == NULL) return (EINVAL); d1410 1 a1410 1 return (EINVAL); a1424 2 ACCEPT_LOCK(); SOCK_LOCK(so); a1425 3 sotryfree(so); return (0); @ 1.18 log @Address minor locking issues. Use taskqueue_swi instead of taskqueue_swi_giant. MFC after: 1 month @ text @d875 1 a875 1 int d878 1 a878 1 return (ng_btsocket_hci_raw_detach(so)); @ 1.17 log @/* -> /*- for license, minor formatting changes @ text @d87 1 a87 1 taskqueue_enqueue(taskqueue_swi_giant, &ng_btsocket_hci_raw_task) d251 1 a251 1 int empty, error = 0; d253 5 a257 8 mtx_lock(&ng_btsocket_hci_raw_sockets_mtx); empty = LIST_EMPTY(&ng_btsocket_hci_raw_sockets); mtx_unlock(&ng_btsocket_hci_raw_sockets_mtx); if (empty) { NG_FREE_ITEM(item); return (0); } d298 1 a298 1 int empty, error; d300 5 a304 8 mtx_lock(&ng_btsocket_hci_raw_sockets_mtx); empty = LIST_EMPTY(&ng_btsocket_hci_raw_sockets); mtx_unlock(&ng_btsocket_hci_raw_sockets_mtx); if (empty) { NG_FREE_ITEM(item); return (0); } d549 1 a549 1 ng_btsocket_hci_raw_pcb_p pcb = NULL; d959 1 d961 1 d990 5 a994 1 if (bcmp(sa, &pcb->addr, sizeof(pcb->addr)) != 0) d996 1 d1000 2 d1447 1 d1449 1 d1567 2 d1570 1 @ 1.17.2.1 log @MFC to RELENG_6 Address minor locking issues. Use taskqueue_swi instead of taskqueue_swi_giant. Approved by: re (scottl) @ text @d87 1 a87 1 taskqueue_enqueue(taskqueue_swi, &ng_btsocket_hci_raw_task) d251 5 a255 1 int error = 0; d257 4 a260 5 /* * Check for empty sockets list creates LOR when both sender and * receiver device are connected to the same host, so remove it * for now */ d301 5 a305 1 int error; d307 4 a310 5 /* * Check for empty sockets list creates LOR when both sender and * receiver device are connected to the same host, so remove it * for now */ d555 1 a555 1 ng_btsocket_hci_raw_pcb_p pcb = NULL; a964 1 mtx_lock(&pcb->pcb_mtx); a965 1 mtx_unlock(&pcb->pcb_mtx); d994 1 a994 5 mtx_lock(&pcb->pcb_mtx); if (bcmp(sa, &pcb->addr, sizeof(pcb->addr)) != 0) { mtx_unlock(&pcb->pcb_mtx); a995 1 } a998 2 mtx_unlock(&pcb->pcb_mtx); a1443 1 mtx_lock(&pcb->pcb_mtx); a1444 1 mtx_unlock(&pcb->pcb_mtx); a1561 2 mtx_lock(&pcb->pcb_mtx); a1562 1 mtx_unlock(&pcb->pcb_mtx); @ 1.17.2.2 log @MFC: Add new SIOC_HCI_RAW_NODE_LIST_NAMES ioctl. User-space applications can use this ioctl to obtain the list of HCI nodes. User-space application is expected to preallocate 'ng_btsocket_hci_raw_node_list_names' structure and set limit in 'num_nodes' field. The 'nodes' field should be allocated as well and it should have space for at least 'num_nodes' elements. The SIOC_HCI_RAW_NODE_LIST_NAMES should be issued on bound raw HCI socket. It does not really really matter what HCI name the socket is bound to, as long as it is not empty. @ text @d260 1 a260 2 (msg->header.typecookie == NGM_HCI_COOKIE || msg->header.typecookie == NGM_GENERIC_COOKIE) && a1309 62 case SIOC_HCI_RAW_NODE_LIST_NAMES: { struct ng_btsocket_hci_raw_node_list_names *nl = (struct ng_btsocket_hci_raw_node_list_names *) data; struct nodeinfo *ni = nl->names; if (nl->num_names == 0) { error = EINVAL; break; } NG_MKMESSAGE(msg, NGM_GENERIC_COOKIE, NGM_LISTNAMES, 0, M_NOWAIT); if (msg == NULL) { error = ENOMEM; break; } ng_btsocket_hci_raw_get_token(&msg->header.token); pcb->token = msg->header.token; pcb->msg = NULL; NG_SEND_MSG_PATH(error, ng_btsocket_hci_raw_node, msg, ".:", 0); if (error != 0) { pcb->token = 0; break; } error = msleep(&pcb->msg, &pcb->pcb_mtx, PZERO|PCATCH, "hcictl", ng_btsocket_hci_raw_ioctl_timeout * hz); pcb->token = 0; if (error != 0) break; if (pcb->msg != NULL && pcb->msg->header.cmd == NGM_LISTNAMES) { /* Return data back to user space */ struct namelist *nl1 = (struct namelist *) pcb->msg->data; struct nodeinfo *ni1 = &nl1->nodeinfo[0]; while (nl->num_names > 0 && nl1->numnames > 0) { if (strcmp(ni1->type, NG_HCI_NODE_TYPE) == 0) { error = copyout((caddr_t) ni1, (caddr_t) ni, sizeof(*ni)); if (error != 0) break; nl->num_names --; ni ++; } nl1->numnames --; ni1 ++; } nl->num_names = ni - nl->names; } else error = EINVAL; NG_FREE_MSG(pcb->msg); /* checks for != NULL */ } break; @ 1.17.2.3 log @SVN rev 181311 on 2008-08-04 22:21:44Z by emax MFC: SVN rev 181089 Increase maximum input queue size limit for raw Bluetooth HCI sockets. @ text @d109 1 d762 1 a762 1 NG_BT_ITEMQ_INIT(&ng_btsocket_hci_raw_queue, 300); @ 1.17.2.4 log @SVN rev 181442 on 2008-08-08 23:23:44Z by emax MFC SVN rev 181093 Implement ratelimiting for debug messages. For now, allow at most one message per second. In the future might add a sysctl knob for each socket family to fine tune this. @ text @a119 2 static struct timeval ng_btsocket_hci_raw_lasttime; static int ng_btsocket_hci_raw_curpps; d143 1 a143 2 if (ng_btsocket_hci_raw_debug_level >= NG_BTSOCKET_INFO_LEVEL && \ ppsratecheck(&ng_btsocket_hci_raw_lasttime, &ng_btsocket_hci_raw_curpps, 1)) \ d147 1 a147 2 if (ng_btsocket_hci_raw_debug_level >= NG_BTSOCKET_WARN_LEVEL && \ ppsratecheck(&ng_btsocket_hci_raw_lasttime, &ng_btsocket_hci_raw_curpps, 1)) \ d151 1 a151 2 if (ng_btsocket_hci_raw_debug_level >= NG_BTSOCKET_ERR_LEVEL && \ ppsratecheck(&ng_btsocket_hci_raw_lasttime, &ng_btsocket_hci_raw_curpps, 1)) \ d155 1 a155 2 if (ng_btsocket_hci_raw_debug_level >= NG_BTSOCKET_ALERT_LEVEL && \ ppsratecheck(&ng_btsocket_hci_raw_lasttime, &ng_btsocket_hci_raw_curpps, 1)) \ @ 1.17.2.5 log @Switch importer @ text @d31 1 a31 1 * $FreeBSD: stable/6/sys/netgraph/bluetooth/socket/ng_btsocket_hci_raw.c 181442 2008-08-08 23:23:44Z emax $ @ 1.17.2.4.2.1 log @SVN rev 183531 on 2008-10-02 02:57:24Z by kensmith Create releng/6.4 from stable/6 in preparation for 6.4-RC1. Approved by: re (implicit) @ text @@ 1.16 log @Push acquisition of the accept mutex out of sofree() into the caller (sorele()/sotryfree()): - This permits the caller to acquire the accept mutex before the socket mutex, avoiding sofree() having to drop the socket mutex and re-order, which could lead to races permitting more than one thread to enter sofree() after a socket is ready to be free'd. - This also covers clearing of the so_pcb weak socket reference from the protocol to the socket, preventing races in clearing and evaluation of the reference such that sofree() might be called more than once on the same socket. This appears to close a race I was able to easily trigger by repeatedly opening and resetting TCP connections to a host, in which the tcp_close() code called as a result of the RST raced with the close() of the accepted socket in the user process resulting in simultaneous attempts to de-allocate the same socket. The new locking increases the overhead for operations that may potentially free the socket, so we will want to revise the synchronization strategy here as we normalize the reference counting model for sockets. The use of the accept mutex in freeing of sockets that are not listen sockets is primarily motivated by the potential need to remove the socket from the incomplete connection queue on its parent (listen) socket, so cleaning up the reference model here may allow us to substantially weaken the synchronization requirements. RELENG_5_3 candidate. MFC after: 3 days Reviewed by: dwhite Discussed with: gnn, dwhite, green Reported by: Marc UBM Bocklet Reported by: Vlad @ text @d3 3 a5 1 * @ 1.15 log @Extend coverage of SOCK_LOCK(so) to include so_count, the socket reference count: - Assert SOCK_LOCK(so) macros that directly manipulate so_count: soref(), sorele(). - Assert SOCK_LOCK(so) in macros/functions that rely on the state of so_count: sofree(), sotryfree(). - Acquire SOCK_LOCK(so) before calling these functions or macros in various contexts in the stack, both at the socket and protocol layers. - In some cases, perform soisdisconnected() before sotryfree(), as this could result in frobbing of a non-present socket if sotryfree() actually frees the socket. - Note that sofree()/sotryfree() will release the socket lock even if they don't free the socket. Submitted by: sam Sponsored by: FreeBSD Foundation Obtained from: BSD/OS @ text @d1420 1 @ 1.15.4.1 log @Merge kern_descrip.c:1.246, uipc_socket.c:1.214, uipc_usrreq.c:1.141, raw_cb.c:1.30, raw_usrreq.c:1.35, ddp_pcb.c:1.45, atm_socket.c:1.21, ng_btsocket_hci_raw.c:1.16, ng_btsocket_l2cap.c:1.14, ng_btsocket_l2cap_raw.c:1.13, ng_btsocket_rfcomm.c:1.13, in_pcb.c:1.156, tcp_subr.c:1.205, in6_pcb.c:1.61, ipx_pcb.c:1.29, ipx_usrreq.c:1.41, natm.c:1.35, socketvar.h:1.135 from HEAD to RELENG_5_3: Push acquisition of the accept mutex out of sofree() into the caller (sorele()/sotryfree()): - This permits the caller to acquire the accept mutex before the socket mutex, avoiding sofree() having to drop the socket mutex and re-order, which could lead to races permitting more than one thread to enter sofree() after a socket is ready to be free'd. - This also covers clearing of the so_pcb weak socket reference from the protocol to the socket, preventing races in clearing and evaluation of the reference such that sofree() might be called more than once on the same socket. This appears to close a race I was able to easily trigger by repeatedly opening and resetting TCP connections to a host, in which the tcp_close() code called as a result of the RST raced with the close() of the accepted socket in the user process resulting in simultaneous attempts to de-allocate the same socket. The new locking increases the overhead for operations that may potentially free the socket, so we will want to revise the synchronization strategy here as we normalize the reference counting model for sockets. The use of the accept mutex in freeing of sockets that are not listen sockets is primarily motivated by the potential need to remove the socket from the incomplete connection queue on its parent (listen) socket, so cleaning up the reference model here may allow us to substantially weaken the synchronization requirements. RELENG_5_3 candidate. MFC after: 3 days Reviewed by: dwhite Discussed with: gnn, dwhite, green Reported by: Marc UBM Bocklet Reported by: Vlad Approved by: re (scottl) @ text @a1419 1 ACCEPT_LOCK(); @ 1.15.2.1 log @Merge kern_descrip.c:1.246, uipc_socket.c:1.214, uipc_usrreq.c:1.141, raw_cb.c:1.30, raw_usrreq.c:1.35, ddp_pcb.c:1.45, atm_socket.c:1.21, ng_btsocket_hci_raw.c:1.16, ng_btsocket_l2cap.c:1.14, ng_btsocket_l2cap_raw.c:1.13, ng_btsocket_rfcomm.c:1.13, in_pcb.c:1.156, tcp_subr.c:1.205, in6_pcb.c:1.61, ipx_pcb.c:1.29, ipx_usrreq.c:1.41, natm.c:1.35, socketvar.h:1.135 from HEAD to RELENG_5: Push acquisition of the accept mutex out of sofree() into the caller (sorele()/sotryfree()): - This permits the caller to acquire the accept mutex before the socket mutex, avoiding sofree() having to drop the socket mutex and re-order, which could lead to races permitting more than one thread to enter sofree() after a socket is ready to be free'd. - This also covers clearing of the so_pcb weak socket reference from the protocol to the socket, preventing races in clearing and evaluation of the reference such that sofree() might be called more than once on the same socket. This appears to close a race I was able to easily trigger by repeatedly opening and resetting TCP connections to a host, in which the tcp_close() code called as a result of the RST raced with the close() of the accepted socket in the user process resulting in simultaneous attempts to de-allocate the same socket. The new locking increases the overhead for operations that may potentially free the socket, so we will want to revise the synchronization strategy here as we normalize the reference counting model for sockets. The use of the accept mutex in freeing of sockets that are not listen sockets is primarily motivated by the potential need to remove the socket from the incomplete connection queue on its parent (listen) socket, so cleaning up the reference model here may allow us to substantially weaken the synchronization requirements. RELENG_5_3 candidate. MFC after: 3 days Reviewed by: dwhite Discussed with: gnn, dwhite, green Reported by: Marc UBM Bocklet Reported by: Vlad MFC after: 1 day Approved by: re (scottl) @ text @a1419 1 ACCEPT_LOCK(); @ 1.15.2.2 log @MFC: /*- and related license changes @ text @d3 1 a3 3 */ /*- @ 1.15.2.3 log @MFC to RELENG_5 Address minor locking issues. Use taskqueue_swi instead of taskqueue_swi_giant. Approved by: re (scottl) @ text @d87 1 a87 1 taskqueue_enqueue(taskqueue_swi, &ng_btsocket_hci_raw_task) d251 5 a255 1 int error = 0; d257 4 a260 5 /* * Check for empty sockets list creates LOR when both sender and * receiver device are connected to the same host, so remove it * for now */ d301 5 a305 1 int error; d307 4 a310 5 /* * Check for empty sockets list creates LOR when both sender and * receiver device are connected to the same host, so remove it * for now */ d555 1 a555 1 ng_btsocket_hci_raw_pcb_p pcb = NULL; a964 1 mtx_lock(&pcb->pcb_mtx); a965 1 mtx_unlock(&pcb->pcb_mtx); d994 1 a994 5 mtx_lock(&pcb->pcb_mtx); if (bcmp(sa, &pcb->addr, sizeof(pcb->addr)) != 0) { mtx_unlock(&pcb->pcb_mtx); a995 1 } a998 2 mtx_unlock(&pcb->pcb_mtx); a1443 1 mtx_lock(&pcb->pcb_mtx); a1444 1 mtx_unlock(&pcb->pcb_mtx); a1561 2 mtx_lock(&pcb->pcb_mtx); a1562 1 mtx_unlock(&pcb->pcb_mtx); @ 1.14 log @Switch to using C99 sparse initialisers for the type methods array. Should make no binary difference. Submitted by: Gleb Smirnoff Reviewed by: Harti Brandt MFC after: 1 week @ text @d1420 1 @ 1.13 log @Address few style issues pointed out by bde Reviewed by: bde, ru @ text @d94 10 a103 13 static struct ng_type typestruct = { NG_ABI_VERSION, NG_BTSOCKET_HCI_RAW_NODE_TYPE, /* typename */ NULL, /* modevent */ ng_btsocket_hci_raw_node_constructor, /* constructor */ ng_btsocket_hci_raw_node_rcvmsg, /* control message */ ng_btsocket_hci_raw_node_shutdown, /* destructor */ ng_btsocket_hci_raw_node_newhook, /* new hook */ NULL, /* find hook */ ng_btsocket_hci_raw_node_connect, /* connect hook */ ng_btsocket_hci_raw_node_rcvdata, /* data */ ng_btsocket_hci_raw_node_disconnect, /* disconnect hook */ NULL /* node command list */ @ 1.12 log @Rename dup_sockaddr() to sodupsockaddr() for consistency with other functions in kern_socket.c. Rename the "canwait" field to "mflags" and pass M_WAITOK and M_NOWAIT in from the caller context rather than "1" or "0". Correct mflags pass into mac_init_socket() from previous commit to not include M_ZERO. Submitted by: sam @ text @d53 5 a57 5 #include "ng_bluetooth.h" #include "ng_hci.h" #include "ng_l2cap.h" #include "ng_btsocket.h" #include "ng_btsocket_hci_raw.h" @ 1.11 log @Replace deprecated NG_NODELEN with the new NG_NODESIZ. There is one problem here still to be solved: the sockaddr_hci has still a 16 byte field for the node name. The code currently does not correctly use the length field in the sockaddr to handle the address length, so node names get truncated to 15 characters when put into a sockaddr_hci. @ text @d1563 1 a1563 1 *nam = dup_sockaddr((struct sockaddr *) &sa, 0); @ 1.10 log @NULL -> 0 where appropriate. @ text @d1012 1 a1012 1 char path[NG_NODELEN + 2]; @ 1.9 log @Update Bluetooth code. Reviewed by: M. Warner Losh ; John Hay Approved by: M. Warner Losh (mentor) @ text @d393 1 a393 1 NG_SEND_MSG_PATH(error, ng_btsocket_hci_raw_node, msg, path, NULL); d419 1 a419 1 NG_SEND_MSG_PATH(error, ng_btsocket_hci_raw_node, msg, path, NULL); d1152 1 a1152 1 NG_SEND_MSG_PATH(error,ng_btsocket_hci_raw_node,msg,path,NULL); d1208 1 a1208 1 NG_SEND_MSG_PATH(error,ng_btsocket_hci_raw_node,msg,path,NULL); @ 1.8 log @Use the rather than @ text @d28 1 a28 1 * $Id: ng_btsocket_hci_raw.c,v 1.13 2003/04/01 18:15:27 max Exp $ d34 1 a52 1 #include @ 1.7 log @Part one of undating the bluetooth code to the newest version Submitted by: Maksim Yevmenkin Approved by: re@@ @ text @d52 1 a52 1 #include @ 1.6 log @Introduce an M_ASSERTPKTHDR() macro which performs the very common task of asserting that an mbuf has a packet header. Use it instead of hand- rolled versions wherever applicable. Submitted by: Hiten Pandya @ text @d28 1 a28 1 * $Id: ng_btsocket_hci_raw.c,v 1.3 2002/11/12 22:31:39 max Exp $ d35 1 d81 11 d121 2 a122 1 d252 10 a261 1 int error = 0; d266 5 d281 1 a281 2 error = taskqueue_enqueue(taskqueue_swi_giant, &ng_btsocket_hci_raw_task); d302 10 a311 1 int error; d321 1 a321 1 strncpy(sa->hci_node, NG_PEER_NODE_NAME(hook), a322 1 sa->hci_node[sizeof(sa->hci_node) - 1] = 0; /* sanity */ d337 1 a337 2 error = taskqueue_enqueue(taskqueue_swi_giant, &ng_btsocket_hci_raw_task); d358 3 a360 1 * Get next token d362 1 a362 1 d367 1 a367 1 d370 1 a370 1 d372 1 a372 1 d374 1 a374 1 } /* ng_btsocket_hci_raw_token */ d381 1 a381 1 ng_btsocket_raw_send_ngmsg(char *path, int cmd, void *arg, int arglen) d386 1 a386 1 NG_MKMESSAGE(msg, NGM_HCI_COOKIE, cmd, arglen, M_WAITOK); d396 1 a396 1 } /* ng_btsocket_raw_send_ngmsg */ d403 1 a403 1 ng_btsocket_raw_send_sync_ngmsg(ng_btsocket_hci_raw_pcb_p pcb, char *path, d409 1 a409 2 ng_btsocket_hci_raw_get_token(&pcb->token); pcb->msg = NULL; d411 2 a412 3 NG_MKMESSAGE(msg, NGM_HCI_COOKIE, cmd, 0, M_WAITOK); if (msg == NULL) { pcb->token = 0; d414 4 a417 2 } msg->header.token = pcb->token; d425 1 a425 1 error = tsleep(&pcb->msg, PZERO|PCATCH, "hcictl", d427 3 a429 2 if (error != 0) { pcb->token = 0; a430 1 } a437 1 pcb->token = 0; d440 1 a440 1 } /* ng_btsocket_raw_send_sync_ngmsg */ d453 2 a481 2 bitstr_t *mask = NULL; int bit; d488 2 a489 1 M_ASSERTPKTHDR(m0); d496 3 d506 1 a506 1 continue; d509 1 a509 1 * Check packet agains socket filter d513 2 a514 24 switch (*mtod(m0, u_int8_t *)) { case NG_HCI_CMD_PKT: case NG_HCI_ACL_DATA_PKT: case NG_HCI_SCO_DATA_PKT: mask = pcb->filter.packet_mask; bit = *mtod(m0, u_int8_t *) - 1; break; case NG_HCI_EVENT_PKT: mask = pcb->filter.event_mask; bit = mtod(m0, ng_hci_event_pkt_t *)->event - 1; break; default: KASSERT(0, ("%s: invalid packet type=%#x\n", __func__, *mtod(m0, u_int8_t *))); mask = NULL; bit = 0; break; } if (mask == NULL || !bit_test(mask, bit)) continue; d532 2 a533 2 NG_BTSOCKET_HCI_RAW_WARN( "%s: sbappendadd() failed\n", __func__); d539 2 d558 11 a568 2 if (msg->header.token != 0) { mtx_lock(&ng_btsocket_hci_raw_sockets_mtx); d570 1 a570 7 LIST_FOREACH(pcb, &ng_btsocket_hci_raw_sockets, next) { if (msg->header.token == pcb->token) { pcb->msg = msg; msg = NULL; wakeup(&pcb->msg); break; } d573 1 a573 1 mtx_unlock(&ng_btsocket_hci_raw_sockets_mtx); d576 2 d639 2 a640 1 M_ASSERTPKTHDR(m); d666 56 d728 2 a729 1 int error = 0; d783 93 a884 2 soisdisconnected(so); a906 2 if ((error = suser(td)) != 0) return (error); d914 1 a914 1 M_NETGRAPH_BTSOCKET_HCI_RAW, M_WAITOK | M_ZERO); d921 3 d932 2 d1012 1 a1012 2 char path[NG_NODELEN + 2], *hci_node = (char *) data; d1021 1 a1021 4 /* * Make sure caller has provided HCI node name, if not try to * use addr from socket (if socket was bound) */ d1023 5 a1027 3 if (hci_node[0] == 0) { if (pcb->addr.hci_node[0] == 0) return (EINVAL); d1029 4 a1032 2 bzero(hci_node, sizeof(pcb->addr.hci_node)); strncpy(hci_node,pcb->addr.hci_node,sizeof(pcb->addr.hci_node)); d1035 1 a1035 1 snprintf(path, sizeof(path), "%s:", hci_node); d1042 1 a1042 1 error = ng_btsocket_raw_send_sync_ngmsg(pcb, path, d1048 5 a1052 2 error = ng_btsocket_raw_send_ngmsg(path, NGM_HCI_NODE_INIT, NULL, 0); d1059 1 a1059 1 error = ng_btsocket_raw_send_sync_ngmsg(pcb, path, d1068 6 a1073 2 error = ng_btsocket_raw_send_ngmsg(path, NGM_HCI_NODE_SET_DEBUG, &p->debug, sizeof(p->debug)); d1080 1 a1080 1 error = ng_btsocket_raw_send_sync_ngmsg(pcb, path, d1089 1 a1089 1 error = ng_btsocket_raw_send_sync_ngmsg(pcb, path, d1098 1 a1098 1 error = ng_btsocket_raw_send_sync_ngmsg(pcb, path, d1107 1 a1107 1 error = ng_btsocket_raw_send_sync_ngmsg(pcb, path, d1113 5 a1117 2 error = ng_btsocket_raw_send_ngmsg(path, NGM_HCI_NODE_RESET_STAT, NULL, 0); d1121 6 a1126 2 error = ng_btsocket_raw_send_ngmsg(path, NGM_HCI_NODE_FLUSH_NEIGHBOR_CACHE, NULL, 0); a1141 3 ng_btsocket_hci_raw_get_token(&pcb->token); pcb->msg = NULL; d1143 1 a1143 1 NGM_HCI_NODE_GET_NEIGHBOR_CACHE, 0, M_WAITOK); a1144 1 pcb->token = 0; d1148 3 a1150 1 msg->header.token = pcb->token; d1158 2 a1159 1 error = tsleep(&pcb->msg, PZERO|PCATCH, "hcictl", d1161 3 a1163 2 if (error != 0) { pcb->token = 0; a1164 1 } a1182 1 pcb->token = 0; a1197 3 ng_btsocket_hci_raw_get_token(&pcb->token); pcb->msg = NULL; d1199 1 a1199 1 0, M_WAITOK); a1200 1 pcb->token = 0; d1204 3 a1206 1 msg->header.token = pcb->token; d1214 2 a1215 1 error = tsleep(&pcb->msg, PZERO|PCATCH, "hcictl", d1217 3 a1219 2 if (error != 0) { pcb->token = 0; a1220 1 } a1237 1 pcb->token = 0; d1245 1 a1245 1 error = ng_btsocket_raw_send_sync_ngmsg(pcb, path, d1255 7 a1261 3 error = ng_btsocket_raw_send_ngmsg(path, NGM_HCI_NODE_SET_LINK_POLICY_SETTINGS_MASK, &p->policy_mask, sizeof(p->policy_mask)); d1268 1 a1268 1 error = ng_btsocket_raw_send_sync_ngmsg(pcb, path, d1277 17 a1293 3 error = ng_btsocket_raw_send_ngmsg(path, NGM_HCI_NODE_SET_PACKET_MASK, &p->packet_mask, sizeof(p->packet_mask)); d1295 11 d1313 2 d1337 2 d1390 2 d1410 2 a1411 2 so->so_pcb = NULL; sotryfree(so); a1412 1 mtx_lock(&ng_btsocket_hci_raw_sockets_mtx); d1414 2 d1418 2 d1423 3 d1455 1 a1455 1 return (EOPNOTSUPP); d1489 19 d1510 1 d1518 1 a1518 1 MGET(nam, M_TRYWAIT, MT_SONAME); d1520 1 d1531 2 d1561 1 a1561 1 strncpy(sa.hci_node, pcb->addr.hci_node, sizeof(sa.hci_node)); @ 1.5 log @Introduce a new taskqueue that runs completely free of Giant, and in turns runs its tasks free of Giant too. It is intended that as drivers become locked down, they will move out of the old, Giant-bound taskqueue and into this new one. The old taskqueue has been renamed to taskqueue_swi_giant, and the new one keeps the name taskqueue_swi. @ text @d454 1 a454 2 KASSERT((m0->m_flags & M_PKTHDR), ("%s: m_flags=%#x\n", __func__, m0->m_flags)); d616 1 a616 2 KASSERT((m->m_flags & M_PKTHDR), ("%s: m_flags=%#x\n", __func__, m->m_flags)); @ 1.4 log @Back out M_* changes, per decision of the TRB. Approved by: trb @ text @d254 1 a254 1 error = taskqueue_enqueue(taskqueue_swi, d303 1 a303 1 error = taskqueue_enqueue(taskqueue_swi, @ 1.3 log @Remove M_TRYWAIT/M_WAITOK/M_WAIT. Callers should use 0. Merge M_NOWAIT/M_DONTWAIT into a single flag M_NOWAIT. @ text @d278 1 a278 1 MGET(nam, M_NOWAIT, MT_SONAME); d351 1 a351 1 NG_MKMESSAGE(msg, NGM_HCI_COOKIE, cmd, arglen, 0); d377 1 a377 1 NG_MKMESSAGE(msg, NGM_HCI_COOKIE, cmd, 0, 0); d507 1 a507 1 m = m_dup(m0, M_NOWAIT); d746 1 a746 1 M_NETGRAPH_BTSOCKET_HCI_RAW, M_ZERO); d959 1 a959 1 NGM_HCI_NODE_GET_NEIGHBOR_CACHE, 0, 0); d1017 1 a1017 1 0, 0); d1274 1 a1274 1 MGET(nam, 0, MT_SONAME); @ 1.2 log @o Untangle the confusion with the malloc flags {M_WAITOK, M_NOWAIT} and the mbuf allocator flags {M_TRYWAIT, M_DONTWAIT}. o Fix a bpf_compat issue where malloc() was defined to just call bpf_alloc() and pass the 'canwait' flag(s) along. It's been changed to call bpf_alloc() but pass the corresponding M_TRYWAIT or M_DONTWAIT flag (and only one of those two). Submitted by: Hiten Pandya (hiten->commit_count++) @ text @d278 1 a278 1 MGET(nam, M_DONTWAIT, MT_SONAME); d351 1 a351 1 NG_MKMESSAGE(msg, NGM_HCI_COOKIE, cmd, arglen, M_WAITOK); d377 1 a377 1 NG_MKMESSAGE(msg, NGM_HCI_COOKIE, cmd, 0, M_WAITOK); d507 1 a507 1 m = m_dup(m0, M_DONTWAIT); d746 1 a746 1 M_NETGRAPH_BTSOCKET_HCI_RAW, M_WAITOK | M_ZERO); d959 1 a959 1 NGM_HCI_NODE_GET_NEIGHBOR_CACHE, 0, M_WAITOK); d1017 1 a1017 1 0, M_WAITOK); d1274 1 a1274 1 MGET(nam, M_TRYWAIT, MT_SONAME); @ 1.1 log @The second try a committing the bluetooth code Has been seen to work on several cards and communicating with several mobile phones to use them as modems etc. We are still talking with 3com to try get them to allow us to include the firmware for their pccard in the driver but the driver is here.. In the mean time it can be downloaded from the 3com website and loaded using the utility bt3cfw(8) (supplied) (instructions in the man page) Not yet linked to the build Submitted by: Maksim Yevmenkin Approved by: re @ text @d1274 1 a1274 1 MGET(nam, M_WAITOK, MT_SONAME); @