38#include <sys/bitstring.h>
39#include <sys/domain.h>
41#include <sys/filedesc.h>
42#include <sys/ioccom.h>
43#include <sys/kernel.h>
45#include <sys/malloc.h>
49#include <sys/protosw.h>
51#include <sys/socket.h>
52#include <sys/socketvar.h>
53#include <sys/sysctl.h>
54#include <sys/taskqueue.h>
67#ifdef NG_SEPARATE_MALLOC
69 "netgraph_btsocks_l2cap_raw",
"Netgraph Bluetooth raw L2CAP sockets");
71#define M_NETGRAPH_BTSOCKET_L2CAP_RAW M_NETGRAPH
88 (
hook_p,
int,
void *,
int);
92#define ng_btsocket_l2cap_raw_wakeup_input_task() \
93 taskqueue_enqueue(taskqueue_swi, &ng_btsocket_l2cap_raw_queue_task)
95#define ng_btsocket_l2cap_raw_wakeup_route_task() \
96 taskqueue_enqueue(taskqueue_swi, &ng_btsocket_l2cap_raw_rt_task)
120static struct mtx ng_btsocket_l2cap_raw_sockets_mtx;
121static u_int32_t ng_btsocket_l2cap_raw_token;
122static struct mtx ng_btsocket_l2cap_raw_token_mtx;
124static struct mtx ng_btsocket_l2cap_raw_rt_mtx;
125static struct task ng_btsocket_l2cap_raw_rt_task;
126static struct timeval ng_btsocket_l2cap_raw_lasttime;
127static int ng_btsocket_l2cap_raw_curpps;
130SYSCTL_DECL(_net_bluetooth_l2cap_sockets);
131static SYSCTL_NODE(_net_bluetooth_l2cap_sockets, OID_AUTO, raw,
132 CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
133 "Bluetooth raw L2CAP sockets family");
134SYSCTL_UINT(_net_bluetooth_l2cap_sockets_raw, OID_AUTO, debug_level,
137 "Bluetooth raw L2CAP sockets debug level");
138SYSCTL_UINT(_net_bluetooth_l2cap_sockets_raw, OID_AUTO, ioctl_timeout,
141 "Bluetooth raw L2CAP sockets ioctl timeout");
142SYSCTL_UINT(_net_bluetooth_l2cap_sockets_raw, OID_AUTO, queue_len,
145 "Bluetooth raw L2CAP sockets input queue length");
146SYSCTL_UINT(_net_bluetooth_l2cap_sockets_raw, OID_AUTO, queue_maxlen,
149 "Bluetooth raw L2CAP sockets input queue max. length");
150SYSCTL_UINT(_net_bluetooth_l2cap_sockets_raw, OID_AUTO, queue_drops,
153 "Bluetooth raw L2CAP sockets input queue drops");
156#define NG_BTSOCKET_L2CAP_RAW_INFO \
157 if (ng_btsocket_l2cap_raw_debug_level >= NG_BTSOCKET_INFO_LEVEL && \
158 ppsratecheck(&ng_btsocket_l2cap_raw_lasttime, &ng_btsocket_l2cap_raw_curpps, 1)) \
161#define NG_BTSOCKET_L2CAP_RAW_WARN \
162 if (ng_btsocket_l2cap_raw_debug_level >= NG_BTSOCKET_WARN_LEVEL && \
163 ppsratecheck(&ng_btsocket_l2cap_raw_lasttime, &ng_btsocket_l2cap_raw_curpps, 1)) \
166#define NG_BTSOCKET_L2CAP_RAW_ERR \
167 if (ng_btsocket_l2cap_raw_debug_level >= NG_BTSOCKET_ERR_LEVEL && \
168 ppsratecheck(&ng_btsocket_l2cap_raw_lasttime, &ng_btsocket_l2cap_raw_curpps, 1)) \
171#define NG_BTSOCKET_L2CAP_RAW_ALERT \
172 if (ng_btsocket_l2cap_raw_debug_level >= NG_BTSOCKET_ALERT_LEVEL && \
173 ppsratecheck(&ng_btsocket_l2cap_raw_lasttime, &ng_btsocket_l2cap_raw_curpps, 1)) \
207"%s: Could not create Netgraph node, error=%d\n", __func__, error);
218"%s: Could not name Netgraph node, error=%d\n", __func__, error);
303"%s: Input queue is full\n", __func__);
379 sizeof(bdaddr_t)) == 0)
385 rt = malloc(
sizeof(*rt),
393 mtx_lock(&ng_btsocket_l2cap_raw_rt_mtx);
395 LIST_INSERT_HEAD(&ng_btsocket_l2cap_raw_rt,
398 mtx_lock(&ng_btsocket_l2cap_raw_rt_mtx);
404"%s: Updating hook \"%s\", src bdaddr=%x:%x:%x:%x:%x:%x\n",
406 rt->
src.b[5], rt->
src.b[4], rt->
src.b[3],
407 rt->
src.b[2], rt->
src.b[1], rt->
src.b[0]);
409 mtx_unlock(&ng_btsocket_l2cap_raw_rt_mtx);
421 mtx_lock(&ng_btsocket_l2cap_raw_sockets_mtx);
423 LIST_FOREACH(pcb,&ng_btsocket_l2cap_raw_sockets,next) {
437 mtx_unlock(&ng_btsocket_l2cap_raw_sockets_mtx);
442"%s: Unknown message, cmd=%d\n", __func__, msg->
header.
cmd);
468 mtx_lock(&ng_btsocket_l2cap_raw_sockets_mtx);
470 LIST_FOREACH(pcb, &ng_btsocket_l2cap_raw_sockets, next) {
473 if (pcb->
rt != NULL &&
475 if (pcb->
so != NULL &&
476 pcb->
so->so_state & SS_ISCONNECTED)
477 soisdisconnected(pcb->
so);
485 mtx_unlock(&ng_btsocket_l2cap_raw_sockets_mtx);
491 mtx_lock(&ng_btsocket_l2cap_raw_rt_mtx);
493 for (rt = LIST_FIRST(&ng_btsocket_l2cap_raw_rt); rt != NULL; ) {
497 LIST_REMOVE(rt, next);
502 bzero(rt,
sizeof(*rt));
509 mtx_unlock(&ng_btsocket_l2cap_raw_rt_mtx);
529"%s: Could not register Netgraph node type, error=%d\n", __func__, error);
538"%s: Could not create Netgraph node, error=%d\n", __func__, error);
549"%s: Could not name Netgraph node, error=%d\n", __func__, error);
560 "btsocks_l2cap_raw_queue_mtx", NULL, MTX_DEF);
565 LIST_INIT(&ng_btsocket_l2cap_raw_sockets);
566 mtx_init(&ng_btsocket_l2cap_raw_sockets_mtx,
567 "btsocks_l2cap_raw_sockets_mtx", NULL, MTX_DEF);
570 ng_btsocket_l2cap_raw_token = 0;
571 mtx_init(&ng_btsocket_l2cap_raw_token_mtx,
572 "btsocks_l2cap_raw_token_mtx", NULL, MTX_DEF);
575 LIST_INIT(&ng_btsocket_l2cap_raw_rt);
576 mtx_init(&ng_btsocket_l2cap_raw_rt_mtx,
577 "btsocks_l2cap_raw_rt_mtx", NULL, MTX_DEF);
578 TASK_INIT(&ng_btsocket_l2cap_raw_rt_task, 0,
616 return (EPROTONOSUPPORT);
617 if (so->so_type != SOCK_RAW)
618 return (ESOCKTNOSUPPORT);
627 pcb = malloc(
sizeof(*pcb),
633 so->so_pcb = (caddr_t) pcb;
636 if (priv_check(td, PRIV_NETBLUETOOTH_RAW) == 0)
639 mtx_init(&pcb->
pcb_mtx,
"btsocks_l2cap_raw_pcb_mtx", NULL, MTX_DEF);
642 mtx_lock(&ng_btsocket_l2cap_raw_sockets_mtx);
643 LIST_INSERT_HEAD(&ng_btsocket_l2cap_raw_sockets, pcb, next);
644 mtx_unlock(&ng_btsocket_l2cap_raw_sockets_mtx);
669 return (EAFNOSUPPORT);
676 mtx_lock(&ng_btsocket_l2cap_raw_rt_mtx);
678 LIST_FOREACH(rt, &ng_btsocket_l2cap_raw_rt, next) {
683 sizeof(rt->
src)) == 0)
687 mtx_unlock(&ng_btsocket_l2cap_raw_rt_mtx);
723 return (EAFNOSUPPORT);
735 if (bcmp(&pcb->
src, &pcb->
dst,
sizeof(pcb->
src)) == 0) {
738 return (EADDRNOTAVAIL);
745 if (pcb->
rt != NULL) {
756 mtx_lock(&ng_btsocket_l2cap_raw_rt_mtx);
758 LIST_FOREACH(rt, &ng_btsocket_l2cap_raw_rt, next) {
762 if (bcmp(&pcb->
dst, &rt->
src,
sizeof(rt->
src)) != 0)
770 bcopy(&rt->
src, &pcb->
src,
sizeof(pcb->
src));
776 mtx_unlock(&ng_btsocket_l2cap_raw_rt_mtx);
788 struct ifnet *ifp,
struct thread *td)
802 if (pcb->
rt == NULL) {
804 return (EHOSTUNREACH);
808 if (pcb->
token != 0) {
875 error = msleep(&pcb->
msg, &pcb->
pcb_mtx, PZERO|PCATCH,
"l2ctl",
898 error = copyout((caddr_t) p2,
939 error = msleep(&pcb->
msg, &pcb->
pcb_mtx, PZERO|PCATCH,
"l2ctl",
962 error = copyout((caddr_t) p2,
1020 error = msleep(&pcb->
msg, &pcb->
pcb_mtx, PZERO|PCATCH,
"l2ctl",
1090 error = msleep(&pcb->
msg, &pcb->
pcb_mtx, PZERO|PCATCH,
"l2ctl",
1161 KASSERT(pcb != NULL, (
"nt_btsocket_l2cap_raw_detach: pcb == NULL"));
1165 mtx_lock(&ng_btsocket_l2cap_raw_sockets_mtx);
1168 LIST_REMOVE(pcb, next);
1171 mtx_unlock(&ng_btsocket_l2cap_raw_sockets_mtx);
1175 bzero(pcb,
sizeof(*pcb));
1197 soisdisconnected(so);
1228 *nam = sodupsockaddr((
struct sockaddr *) &sa, M_NOWAIT);
1230 return ((*nam == NULL)? ENOMEM : 0);
1239 struct sockaddr *nam,
struct mbuf *
control,
struct thread *td)
1244 return (EOPNOTSUPP);
1271 *nam = sodupsockaddr((
struct sockaddr *) &sa, M_NOWAIT);
1273 return ((*nam == NULL)? ENOMEM : 0);
1283 mtx_lock(&ng_btsocket_l2cap_raw_token_mtx);
1285 if (++ ng_btsocket_l2cap_raw_token == 0)
1286 ng_btsocket_l2cap_raw_token = 1;
1288 *token = ng_btsocket_l2cap_raw_token;
1290 mtx_unlock(&ng_btsocket_l2cap_raw_token_mtx);
1307 if (arg != NULL && arglen > 0)
1308 bcopy(arg, msg->
data, arglen);
1321 int cmd,
void *rsp,
int rsplen)
1326 mtx_assert(&pcb->
pcb_mtx, MA_OWNED);
1343 error = msleep(&pcb->
msg, &pcb->
pcb_mtx, PZERO|PCATCH,
"l2ctl",
1351 bcopy(pcb->
msg->
data, rsp, rsplen);
#define NGI_SET_HOOK(i, h)
int ng_connect_t(hook_p hook)
#define NGI_GET_HOOK(i, h)
#define NG_HOOK_UNREF(hook)
#define NG_HOOK_NOT_VALID(hook)
int ng_rcvmsg_t(node_p node, item_p item, hook_p lasthook)
int ng_disconnect_t(hook_p hook)
int ng_newtype(struct ng_type *tp)
#define NG_NODE_UNREF(node)
#define NG_HOOK_SET_PRIVATE(hook, val)
#define NG_HOOK_REF(hook)
int ng_rcvdata_t(hook_p hook, item_p item)
int ng_shutdown_t(node_p node)
#define NG_HOOK_NAME(hook)
#define NG_FREE_ITEM(item)
int ng_make_node_common(struct ng_type *typep, node_p *nodep)
int ng_name_node(node_p node, const char *name)
int ng_constructor_t(node_p node)
#define NGI_GET_MSG(i, m)
#define NG_SEND_MSG_HOOK(error, here, msg, hook, retaddr)
int ng_newhook_t(node_p node, hook_p hook, const char *name)
#define NG_HOOK_PRIVATE(hook)
SYSCTL_NODE(_net, OID_AUTO, bluetooth, CTLFLAG_RW|CTLFLAG_MPSAFE, 0, "Bluetooth family")
u_int32_t bluetooth_l2cap_rtx_timeout(void)
SYSCTL_UINT(_net_bluetooth_hci, OID_AUTO, max_neighbor_age, CTLFLAG_RW, &bluetooth_hci_max_neighbor_age_value, 600, "Maximal HCI neighbor cache entry age (sec)")
#define NG_BT_ITEMQ_ENQUEUE(q, i)
#define NG_BT_ITEMQ_FULL(q)
#define NG_BT_ITEMQ_INIT(q, _maxlen)
#define NG_BT_ITEMQ_DEQUEUE(q, i)
#define NG_BT_ITEMQ_DROP(q)
#define SIOC_L2CAP_L2CA_GET_INFO
#define SIOC_L2CAP_NODE_GET_FLAGS
#define SIOC_L2CAP_NODE_GET_DEBUG
#define SIOC_L2CAP_NODE_SET_AUTO_DISCON_TIMO
#define SIOC_L2CAP_NODE_GET_AUTO_DISCON_TIMO
#define NG_BTSOCKET_L2CAP_RAW_NODE_TYPE
#define SIOC_L2CAP_L2CA_PING
#define SIOC_L2CAP_NODE_GET_CON_LIST
#define SIOC_L2CAP_NODE_SET_DEBUG
#define NG_BTSOCKET_WARN_LEVEL
#define SIOC_L2CAP_NODE_GET_CHAN_LIST
#define NG_BTSOCKET_L2CAP_RAW_SENDSPACE
#define so2l2cap_raw_pcb(so)
#define NG_BTSOCKET_L2CAP_RAW_RECVSPACE
#define NG_BTSOCKET_L2CAP_RAW_PRIVILEGED
static int ng_btsocket_l2cap_raw_send_sync_ngmsg(ng_btsocket_l2cap_raw_pcb_p, int, void *, int)
static struct mtx ng_btsocket_l2cap_raw_queue_mtx
void ng_btsocket_l2cap_raw_close(struct socket *so)
int ng_btsocket_l2cap_raw_disconnect(struct socket *so)
void ng_btsocket_l2cap_raw_detach(struct socket *so)
static void ng_btsocket_l2cap_raw_rtclean(void *, int)
static struct task ng_btsocket_l2cap_raw_queue_task
static u_int32_t ng_btsocket_l2cap_raw_ioctl_timeout
static ng_rcvmsg_t ng_btsocket_l2cap_raw_node_rcvmsg
static ng_constructor_t ng_btsocket_l2cap_raw_node_constructor
static void ng_btsocket_l2cap_raw_input(void *, int)
int ng_btsocket_l2cap_raw_sockaddr(struct socket *so, struct sockaddr **nam)
#define ng_btsocket_l2cap_raw_wakeup_route_task()
#define M_NETGRAPH_BTSOCKET_L2CAP_RAW
static node_p ng_btsocket_l2cap_raw_node
static u_int32_t ng_btsocket_l2cap_raw_debug_level
static ng_rcvdata_t ng_btsocket_l2cap_raw_node_rcvdata
#define NG_BTSOCKET_L2CAP_RAW_INFO
static ng_connect_t ng_btsocket_l2cap_raw_node_connect
static struct ng_type typestruct
int ng_btsocket_l2cap_raw_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp, struct thread *td)
static LIST_HEAD(ng_btsocket_l2cap_raw_pcb)
#define NG_BTSOCKET_L2CAP_RAW_ERR
int ng_btsocket_l2cap_raw_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam, struct mbuf *control, struct thread *td)
int ng_btsocket_l2cap_raw_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
SYSINIT(ng_btsocket_l2cap_raw_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, ng_btsocket_l2cap_raw_init, NULL)
void ng_btsocket_l2cap_raw_abort(struct socket *so)
static ng_shutdown_t ng_btsocket_l2cap_raw_node_shutdown
static ng_newhook_t ng_btsocket_l2cap_raw_node_newhook
static int ng_btsocket_l2cap_raw_send_ngmsg(hook_p, int, void *, int)
#define NG_BTSOCKET_L2CAP_RAW_ALERT
int ng_btsocket_l2cap_raw_attach(struct socket *so, int proto, struct thread *td)
int ng_btsocket_l2cap_raw_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
static ng_disconnect_t ng_btsocket_l2cap_raw_node_disconnect
#define ng_btsocket_l2cap_raw_wakeup_input_task()
static void ng_btsocket_l2cap_raw_init(void *arg __unused)
static void ng_btsocket_l2cap_raw_get_token(u_int32_t *)
static struct ng_bt_itemq ng_btsocket_l2cap_raw_queue
#define NG_BTSOCKET_L2CAP_RAW_WARN
int ng_btsocket_l2cap_raw_peeraddr(struct socket *so, struct sockaddr **nam)
MALLOC_DEFINE(M_NG_CCATM, "ng_ccatm", "netgraph uni api node")
#define NG_HCI_BDADDR_ANY
#define NGM_L2CAP_NODE_GET_CHAN_LIST
#define NGM_L2CAP_NODE_GET_AUTO_DISCON_TIMO
#define NGM_L2CAP_NODE_SET_DEBUG
#define NGM_L2CAP_L2CA_PING
#define NGM_L2CAP_NODE_GET_CON_LIST
#define NGM_L2CAP_NODE_GET_FLAGS
#define NGM_L2CAP_NODE_GET_DEBUG
#define NGM_L2CAP_L2CA_GET_INFO
#define NG_L2CAP_MAX_CON_NUM
#define NGM_L2CAP_NODE_SET_AUTO_DISCON_TIMO
#define NG_L2CAP_MAX_CHAN_NUM
#define NG_L2CAP_MAX_ECHO_SIZE
#define NGM_L2CAP_NODE_HOOK_INFO
#define NG_MKMESSAGE(msg, cookie, cmdid, len, how)
ng_l2cap_node_auto_discon_ep timeout
ng_l2cap_node_chan_ep * channels
u_int32_t num_connections
ng_l2cap_node_con_ep * connections
ng_l2cap_node_debug_ep debug
ng_l2cap_node_flags_ep flags
ng_btsocket_l2cap_rtentry_p rt
u_int32_t num_connections
struct ng_mesg::ng_msghdr header
u_int8_t l2cap_bdaddr_type