38#include <sys/bitstring.h>
39#include <sys/domain.h>
40#include <sys/endian.h>
42#include <sys/filedesc.h>
43#include <sys/ioccom.h>
44#include <sys/kernel.h>
46#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 Bluetooth L2CAP sockets");
71#define M_NETGRAPH_BTSOCKET_L2CAP M_NETGRAPH
107static struct mtx ng_btsocket_l2cap_sockets_mtx;
109static struct mtx ng_btsocket_l2cap_rt_mtx;
110static struct task ng_btsocket_l2cap_rt_task;
111static struct timeval ng_btsocket_l2cap_lasttime;
112static int ng_btsocket_l2cap_curpps;
115SYSCTL_DECL(_net_bluetooth_l2cap_sockets);
116static SYSCTL_NODE(_net_bluetooth_l2cap_sockets, OID_AUTO, seq,
117 CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
118 "Bluetooth SEQPACKET L2CAP sockets family");
119SYSCTL_UINT(_net_bluetooth_l2cap_sockets_seq, OID_AUTO, debug_level,
122 "Bluetooth SEQPACKET L2CAP sockets debug level");
123SYSCTL_UINT(_net_bluetooth_l2cap_sockets_seq, OID_AUTO, queue_len,
126 "Bluetooth SEQPACKET L2CAP sockets input queue length");
127SYSCTL_UINT(_net_bluetooth_l2cap_sockets_seq, OID_AUTO, queue_maxlen,
130 "Bluetooth SEQPACKET L2CAP sockets input queue max. length");
131SYSCTL_UINT(_net_bluetooth_l2cap_sockets_seq, OID_AUTO, queue_drops,
134 "Bluetooth SEQPACKET L2CAP sockets input queue drops");
137#define NG_BTSOCKET_L2CAP_INFO \
138 if (ng_btsocket_l2cap_debug_level >= NG_BTSOCKET_INFO_LEVEL && \
139 ppsratecheck(&ng_btsocket_l2cap_lasttime, &ng_btsocket_l2cap_curpps, 1)) \
142#define NG_BTSOCKET_L2CAP_WARN \
143 if (ng_btsocket_l2cap_debug_level >= NG_BTSOCKET_WARN_LEVEL && \
144 ppsratecheck(&ng_btsocket_l2cap_lasttime, &ng_btsocket_l2cap_curpps, 1)) \
147#define NG_BTSOCKET_L2CAP_ERR \
148 if (ng_btsocket_l2cap_debug_level >= NG_BTSOCKET_ERR_LEVEL && \
149 ppsratecheck(&ng_btsocket_l2cap_lasttime, &ng_btsocket_l2cap_curpps, 1)) \
152#define NG_BTSOCKET_L2CAP_ALERT \
153 if (ng_btsocket_l2cap_debug_level >= NG_BTSOCKET_ALERT_LEVEL && \
154 ppsratecheck(&ng_btsocket_l2cap_lasttime, &ng_btsocket_l2cap_curpps, 1)) \
218static int ng_btsock_l2cap_addrtype_to_linktype(
int addrtype);
220#define ng_btsocket_l2cap_wakeup_input_task() \
221 taskqueue_enqueue(taskqueue_swi_giant, &ng_btsocket_l2cap_queue_task)
223#define ng_btsocket_l2cap_wakeup_route_task() \
224 taskqueue_enqueue(taskqueue_swi_giant, &ng_btsocket_l2cap_rt_task)
226int ng_btsock_l2cap_addrtype_to_linktype(
int addrtype)
269"%s: Could not create Netgraph node, error=%d\n", __func__, error);
280"%s: Could not name Netgraph node, error=%d\n", __func__, error);
356"%s: Input queue is full (msg)\n", __func__);
391"%s: Input queue is full (data)\n", __func__);
426 mtx_lock(&ng_btsocket_l2cap_sockets_mtx);
431 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
438"%s: Got L2CA_Connect response, token=%d, src bdaddr=%x:%x:%x:%x:%x:%x, " \
439"dst bdaddr=%x:%x:%x:%x:%x:%x, psm=%d, lcid=%d, result=%d, status=%d, " \
441 pcb->
src.b[5], pcb->
src.b[4], pcb->
src.b[3],
442 pcb->
src.b[2], pcb->
src.b[1], pcb->
src.b[0],
443 pcb->
dst.b[5], pcb->
dst.b[4], pcb->
dst.b[3],
444 pcb->
dst.b[2], pcb->
dst.b[1], pcb->
dst.b[0],
450 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
460 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
474 soisconnected(pcb->
so);
492 soisdisconnected(pcb->
so);
509 soisdisconnected(pcb->
so);
512 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
533 mtx_lock(&ng_btsocket_l2cap_sockets_mtx);
538 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
545"%s: Got L2CA_ConnectRsp response, token=%d, src bdaddr=%x:%x:%x:%x:%x:%x, " \
546"dst bdaddr=%x:%x:%x:%x:%x:%x, psm=%d, lcid=%d, result=%d, state=%d\n",
548 pcb->
src.b[5], pcb->
src.b[4], pcb->
src.b[3],
549 pcb->
src.b[2], pcb->
src.b[1], pcb->
src.b[0],
550 pcb->
dst.b[5], pcb->
dst.b[4], pcb->
dst.b[3],
551 pcb->
dst.b[2], pcb->
dst.b[1], pcb->
dst.b[0],
556 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
568 soisdisconnected(pcb->
so);
577 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
596 u_int16_t result = 0;
604"%s: Got L2CA_Connect indicator, src bdaddr=%x:%x:%x:%x:%x:%x, " \
605"dst bdaddr=%x:%x:%x:%x:%x:%x, psm=%d, lcid=%d, ident=%d\n",
607 rt->
src.b[5], rt->
src.b[4], rt->
src.b[3],
608 rt->
src.b[2], rt->
src.b[1], rt->
src.b[0],
613 mtx_lock(&ng_btsocket_l2cap_sockets_mtx);
621 CURVNET_SET(pcb->
so->so_vnet);
622 so1 = sonewconn(pcb->
so, 0);
637 KASSERT((pcb1 != NULL),
638(
"%s: pcb1 == NULL\n", __func__));
640 mtx_lock(&pcb1->pcb_mtx);
643 bcopy(&pcb->
src, &pcb1->src,
sizeof(pcb1->src));
645 bcopy(&rt->
src, &pcb1->src,
sizeof(pcb1->src));
647 pcb1->flags &= ~NG_BTSOCKET_L2CAP_CLIENT;
649 bcopy(&ip->
bdaddr, &pcb1->dst,
sizeof(pcb1->dst));
651 pcb1->cid = ip->
lcid;
655 pcb1->imtu = pcb->
imtu;
656 bcopy(&pcb->
oflow, &pcb1->oflow,
sizeof(pcb1->oflow));
671 pcb1->so->so_error = error;
673 soisdisconnected(pcb1->so);
676 soisconnecting(pcb1->so);
681 mtx_unlock(&pcb1->pcb_mtx);
687 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
702 mtx_lock(&ng_btsocket_l2cap_sockets_mtx);
707 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
718 __func__, pcb->
state);
721 soisconnected(pcb->
so);
723 pcb->
so->so_error = EPERM;
726 soisdisconnected(pcb->
so);
730 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
750 mtx_lock(&ng_btsocket_l2cap_sockets_mtx);
766 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
773"%s: Got L2CA_Config response, token=%d, src bdaddr=%x:%x:%x:%x:%x:%x, " \
774"dst bdaddr=%x:%x:%x:%x:%x:%x, psm=%d, lcid=%d, result=%d, state=%d, " \
777 pcb->
src.b[5], pcb->
src.b[4], pcb->
src.b[3],
778 pcb->
src.b[2], pcb->
src.b[1], pcb->
src.b[0],
779 pcb->
dst.b[5], pcb->
dst.b[4], pcb->
dst.b[3],
780 pcb->
dst.b[2], pcb->
dst.b[1], pcb->
dst.b[0],
785 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
808 pcb->
cfg_state &= ~NG_BTSOCKET_L2CAP_CFG_IN_SENT;
815 soisconnected(pcb->
so);
829 pcb->
so->so_error = EINVAL;
833 pcb->
so->so_error = ECONNRESET;
842 soisdisconnected(pcb->
so);
846 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
868 mtx_lock(&ng_btsocket_l2cap_sockets_mtx);
873 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
880"%s: Got L2CA_ConfigRsp response, token=%d, src bdaddr=%x:%x:%x:%x:%x:%x, " \
881"dst bdaddr=%x:%x:%x:%x:%x:%x, psm=%d, lcid=%d, result=%d, state=%d, " \
884 pcb->
src.b[5], pcb->
src.b[4], pcb->
src.b[3],
885 pcb->
src.b[2], pcb->
src.b[1], pcb->
src.b[0],
886 pcb->
dst.b[5], pcb->
dst.b[4], pcb->
dst.b[3],
887 pcb->
dst.b[2], pcb->
dst.b[1], pcb->
dst.b[0],
892 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
906 pcb->
cfg_state &= ~NG_BTSOCKET_L2CAP_CFG_OUT_SENT;
913 soisconnected(pcb->
so);
926 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
938 soisdisconnected(pcb->
so);
941 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
963 mtx_lock(&ng_btsocket_l2cap_sockets_mtx);
969 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
976"%s: Got L2CA_Config indicator, src bdaddr=%x:%x:%x:%x:%x:%x, " \
977"dst bdaddr=%x:%x:%x:%x:%x:%x, psm=%d, lcid=%d, state=%d, cfg_state=%x\n",
979 pcb->
src.b[5], pcb->
src.b[4], pcb->
src.b[3],
980 pcb->
src.b[2], pcb->
src.b[1], pcb->
src.b[0],
981 pcb->
dst.b[5], pcb->
dst.b[4], pcb->
dst.b[3],
982 pcb->
dst.b[2], pcb->
dst.b[1], pcb->
dst.b[0],
988 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
1013 pcb->
so->so_error = error;
1020 soisdisconnected(pcb->
so);
1026 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
1048 mtx_lock(&ng_btsocket_l2cap_sockets_mtx);
1058 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
1067"%s: Got L2CA_Disconnect response, token=%d, src bdaddr=%x:%x:%x:%x:%x:%x, " \
1068"dst bdaddr=%x:%x:%x:%x:%x:%x, psm=%d, lcid=%d, result=%d, state=%d\n",
1070 pcb->
src.b[5], pcb->
src.b[4], pcb->
src.b[3],
1071 pcb->
src.b[2], pcb->
src.b[1], pcb->
src.b[0],
1072 pcb->
dst.b[5], pcb->
dst.b[4], pcb->
dst.b[3],
1073 pcb->
dst.b[2], pcb->
dst.b[1], pcb->
dst.b[0],
1079 soisdisconnected(pcb->
so);
1083 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
1105 mtx_lock(&ng_btsocket_l2cap_sockets_mtx);
1111 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
1124"%s: Got L2CA_Disconnect indicator, src bdaddr=%x:%x:%x:%x:%x:%x, " \
1125"dst bdaddr=%x:%x:%x:%x:%x:%x, psm=%d, lcid=%d, state=%d\n",
1127 pcb->
src.b[5], pcb->
src.b[4], pcb->
src.b[3],
1128 pcb->
src.b[2], pcb->
src.b[1], pcb->
src.b[0],
1129 pcb->
dst.b[5], pcb->
dst.b[4], pcb->
dst.b[3],
1130 pcb->
dst.b[2], pcb->
dst.b[1], pcb->
dst.b[0],
1137 soisdisconnected(pcb->
so);
1140 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
1162 mtx_lock(&ng_btsocket_l2cap_sockets_mtx);
1167 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
1174"%s: Got L2CA_Write response, src bdaddr=%x:%x:%x:%x:%x:%x, " \
1175"dst bdaddr=%x:%x:%x:%x:%x:%x, psm=%d, lcid=%d, result=%d, length=%d, " \
1176"state=%d\n", __func__,
1177 pcb->
src.b[5], pcb->
src.b[4], pcb->
src.b[3],
1178 pcb->
src.b[2], pcb->
src.b[1], pcb->
src.b[0],
1179 pcb->
dst.b[5], pcb->
dst.b[4], pcb->
dst.b[3],
1180 pcb->
dst.b[2], pcb->
dst.b[1], pcb->
dst.b[0],
1186 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
1196 sbdroprecord(&pcb->
so->so_snd);
1197 if (sbavail(&pcb->
so->so_snd) > 0) {
1201 sbdroprecord(&pcb->
so->so_snd);
1213 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
1229 mtx_assert(&pcb->
pcb_mtx, MA_OWNED);
1231 if (pcb->
rt == NULL ||
1236 sizeof(*ip), M_NOWAIT);
1259 int lcid,
int result,
int linktype)
1269 sizeof(*ip), M_NOWAIT);
1299 mtx_assert(&pcb->
pcb_mtx, MA_OWNED);
1301 if (pcb->
rt == NULL ||
1306 sizeof(*ip), M_NOWAIT);
1335 mtx_assert(&pcb->
pcb_mtx, MA_OWNED);
1337 if (pcb->
rt == NULL ||
1342 sizeof(*ip), M_NOWAIT);
1370 mtx_assert(&pcb->
pcb_mtx, MA_OWNED);
1372 if (pcb->
rt == NULL ||
1377 sizeof(*ip), M_NOWAIT);
1405 ng_l2cap_hdr_t *hdr = NULL;
1406 ng_l2cap_clt_hdr_t *clt_hdr = NULL;
1413"%s: Invalid source hook for L2CAP data packet\n", __func__);
1420"%s: Could not find out source bdaddr for L2CAP data packet\n", __func__);
1424 m = m_pullup(m,
sizeof(uint16_t));
1425 idtype = *mtod(m, uint16_t *);
1426 m_adj(m,
sizeof(uint16_t));
1429 if (m->m_pkthdr.len <
sizeof(*hdr)) {
1431"%s: L2CAP data packet too small, len=%d\n", __func__, m->m_pkthdr.len);
1435 if (m->m_len <
sizeof(*hdr)) {
1436 m = m_pullup(m,
sizeof(*hdr));
1442 hdr = mtod(m, ng_l2cap_hdr_t *);
1443 m_adj(m,
sizeof(*hdr));
1445 if (hdr->length != m->m_pkthdr.len) {
1447"%s: Bad L2CAP data packet length, len=%d, length=%d\n",
1448 __func__, m->m_pkthdr.len, hdr->length);
1464"%s: Received L2CAP data packet: src bdaddr=%x:%x:%x:%x:%x:%x, " \
1465"dcid=%d, length=%d\n",
1467 rt->
src.b[5], rt->
src.b[4], rt->
src.b[3],
1468 rt->
src.b[2], rt->
src.b[1], rt->
src.b[0],
1469 hdr->dcid, hdr->length);
1475 mtx_lock(&ng_btsocket_l2cap_sockets_mtx);
1480 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
1488"%s: No connected socket found, src bdaddr=%x:%x:%x:%x:%x:%x, dcid=%d, " \
1489"state=%d\n", __func__,
1490 rt->
src.b[5], rt->
src.b[4], rt->
src.b[3],
1491 rt->
src.b[2], rt->
src.b[1], rt->
src.b[0],
1492 hdr->dcid, pcb->
state);
1495 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
1500 if (hdr->length > pcb->
imtu) {
1502"%s: L2CAP data packet too big, src bdaddr=%x:%x:%x:%x:%x:%x, " \
1503"dcid=%d, length=%d, imtu=%d\n",
1505 rt->
src.b[5], rt->
src.b[4], rt->
src.b[3],
1506 rt->
src.b[2], rt->
src.b[1], rt->
src.b[0],
1507 hdr->dcid, hdr->length, pcb->
imtu);
1510 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
1515 if (m->m_pkthdr.len > sbspace(&pcb->
so->so_rcv)) {
1524"%s: Not enough space in socket receive queue. Dropping L2CAP data packet, " \
1525"src bdaddr=%x:%x:%x:%x:%x:%x, dcid=%d, len=%d, space=%ld\n",
1527 rt->
src.b[5], rt->
src.b[4], rt->
src.b[3],
1528 rt->
src.b[2], rt->
src.b[1], rt->
src.b[0],
1529 hdr->dcid, m->m_pkthdr.len,
1530 sbspace(&pcb->
so->so_rcv));
1533 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
1538 sbappendrecord(&pcb->
so->so_rcv, m);
1544 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
1551"%s: Connectionless L2CAP data packet too big, " \
1552"src bdaddr=%x:%x:%x:%x:%x:%x, length=%d\n",
1554 rt->
src.b[5], rt->
src.b[4], rt->
src.b[3],
1555 rt->
src.b[2], rt->
src.b[1], rt->
src.b[0],
1561 if (m->m_pkthdr.len <
sizeof(*clt_hdr)) {
1563"%s: Can not get L2CAP connectionless packet header, " \
1564"src bdaddr=%x:%x:%x:%x:%x:%x, length=%d\n",
1566 rt->
src.b[5], rt->
src.b[4], rt->
src.b[3],
1567 rt->
src.b[2], rt->
src.b[1], rt->
src.b[0],
1572 if (m->m_len <
sizeof(*clt_hdr)) {
1573 m = m_pullup(m,
sizeof(*clt_hdr));
1579 clt_hdr = mtod(m, ng_l2cap_clt_hdr_t *);
1580 m_adj(m,
sizeof(*clt_hdr));
1583"%s: Got L2CAP connectionless data packet, " \
1584"src bdaddr=%x:%x:%x:%x:%x:%x, psm=%d, length=%d\n",
1586 rt->
src.b[5], rt->
src.b[4], rt->
src.b[3],
1587 rt->
src.b[2], rt->
src.b[1], rt->
src.b[0],
1588 clt_hdr->psm, hdr->length);
1590 mtx_lock(&ng_btsocket_l2cap_sockets_mtx);
1592 LIST_FOREACH(pcb, &ng_btsocket_l2cap_sockets, next) {
1593 struct mbuf *copy = NULL;
1597 if (bcmp(&rt->
src, &pcb->
src,
sizeof(pcb->
src)) != 0 ||
1598 pcb->
psm != clt_hdr->psm ||
1600 (pcb->
so->so_options & SO_BROADCAST) == 0 ||
1601 m->m_pkthdr.len > sbspace(&pcb->
so->so_rcv))
1610 copy = m_dup(m, M_NOWAIT);
1612 sbappendrecord(&pcb->
so->so_rcv, copy);
1619 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
1643 mtx_lock(&ng_btsocket_l2cap_rt_mtx);
1647 rt = malloc(
sizeof(*rt),
1650 mtx_unlock(&ng_btsocket_l2cap_rt_mtx);
1654 LIST_INSERT_HEAD(&ng_btsocket_l2cap_rt, rt, next);
1662 mtx_unlock(&ng_btsocket_l2cap_rt_mtx);
1665"%s: Updating hook \"%s\", src bdaddr=%x:%x:%x:%x:%x:%x\n",
1667 rt->
src.b[5], rt->
src.b[4], rt->
src.b[3],
1668 rt->
src.b[2], rt->
src.b[1], rt->
src.b[0]);
1673"%s: Unknown message, cmd=%d\n", __func__, msg->
header.
cmd);
1691"%s: Invalid source hook for L2CA message\n", __func__);
1698"%s: Could not find out source bdaddr for L2CA message\n", __func__);
1746"%s: Unknown L2CA message, cmd=%d\n", __func__, msg->
header.
cmd);
1777 struct mbuf *m = NULL;
1833 mtx_lock(&ng_btsocket_l2cap_rt_mtx);
1834 mtx_lock(&ng_btsocket_l2cap_sockets_mtx);
1840 for (pcb = LIST_FIRST(&ng_btsocket_l2cap_sockets); pcb != NULL; ) {
1842 pcb_next = LIST_NEXT(pcb, next);
1844 if (pcb->
rt != NULL &&
1849 pcb->
so->so_error = ENETDOWN;
1851 soisdisconnected(pcb->
so);
1866 for (rt = LIST_FIRST(&ng_btsocket_l2cap_rt); rt != NULL; ) {
1870 LIST_REMOVE(rt, next);
1875 bzero(rt,
sizeof(*rt));
1882 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
1883 mtx_unlock(&ng_btsocket_l2cap_rt_mtx);
1902"%s: Could not register Netgraph node type, error=%d\n", __func__, error);
1911"%s: Could not create Netgraph node, error=%d\n", __func__, error);
1922"%s: Could not name Netgraph node, error=%d\n", __func__, error);
1933 "btsocks_l2cap_queue_mtx", NULL, MTX_DEF);
1938 LIST_INIT(&ng_btsocket_l2cap_sockets);
1939 mtx_init(&ng_btsocket_l2cap_sockets_mtx,
1940 "btsocks_l2cap_sockets_mtx", NULL, MTX_DEF);
1943 LIST_INIT(&ng_btsocket_l2cap_rt);
1944 mtx_init(&ng_btsocket_l2cap_rt_mtx,
1945 "btsocks_l2cap_rt_mtx", NULL, MTX_DEF);
1946 TASK_INIT(&ng_btsocket_l2cap_rt_task, 0,
1959 so->so_error = ECONNABORTED;
1992 static u_int32_t token = 0;
1998 return (EPROTONOSUPPORT);
1999 if (so->so_type != SOCK_SEQPACKET)
2000 return (ESOCKTNOSUPPORT);
2005 return (EPROTONOSUPPORT);
2012 if ((so->so_snd.sb_hiwat == 0) || (so->so_rcv.sb_hiwat == 0)) {
2020 pcb = malloc(
sizeof(*pcb),
2026 so->so_pcb = (caddr_t) pcb;
2034 pcb->
iflow.flags = 0x0;
2036 pcb->
iflow.token_rate = 0xffffffff;
2037 pcb->
iflow.token_bucket_size = 0xffffffff;
2038 pcb->
iflow.peak_bandwidth = 0x00000000;
2039 pcb->
iflow.latency = 0xffffffff;
2040 pcb->
iflow.delay_variation = 0xffffffff;
2054 mtx_init(&pcb->
pcb_mtx,
"btsocks_l2cap_pcb_mtx", NULL,
2078 mtx_lock(&ng_btsocket_l2cap_sockets_mtx);
2080 mtx_assert(&ng_btsocket_l2cap_sockets_mtx, MA_OWNED);
2088 LIST_INSERT_HEAD(&ng_btsocket_l2cap_sockets, pcb, next);
2091 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
2115 return (EAFNOSUPPORT);
2131 mtx_lock(&ng_btsocket_l2cap_sockets_mtx);
2133 LIST_FOREACH(pcb, &ng_btsocket_l2cap_sockets, next)
2134 if (psm != 0 && psm == pcb->
psm &&
2149 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
2167 int have_src, error = 0;
2175 return (EINPROGRESS);
2181 return (EAFNOSUPPORT);
2183 bcopy(sal, &ba,
sizeof(*sal));
2193 return (EDESTADDRREQ);
2196 return EDESTADDRREQ;
2217 mtx_lock(&ng_btsocket_l2cap_rt_mtx);
2218 mtx_lock(&ng_btsocket_l2cap_sockets_mtx);
2230 LIST_FOREACH(rt, &ng_btsocket_l2cap_rt, next) {
2236 if (bcmp(&pcb->
src, &rt->src,
sizeof(rt->src)) == 0)
2239 if (bcmp(&pcb->
dst, &rt->src,
sizeof(rt->src)) != 0)
2248 bcopy(&rt->src, &pcb->
src,
sizeof(pcb->
src));
2254 error = EHOSTUNREACH;
2265 soisconnecting(pcb->
so);
2272 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
2273 mtx_unlock(&ng_btsocket_l2cap_rt_mtx);
2284 struct ifnet *ifp,
struct thread *td)
2310 switch (sopt->sopt_dir) {
2312 switch (sopt->sopt_name) {
2314 error = sooptcopyout(sopt, &pcb->
imtu,
2319 error = sooptcopyout(sopt, &pcb->
omtu,
2324 error = sooptcopyout(sopt, &pcb->
iflow,
2325 sizeof(pcb->
iflow));
2329 error = sooptcopyout(sopt, &pcb->
oflow,
2330 sizeof(pcb->
oflow));
2343 error = ENOPROTOOPT;
2362 switch (sopt->sopt_name) {
2364 error = sooptcopyin(sopt, &v,
sizeof(v),
sizeof(v.
mtu));
2370 error = sooptcopyin(sopt, &v,
sizeof(v),
sizeof(v.
flow));
2376 error = sooptcopyin(sopt, &v,
sizeof(v),
2384 error = sooptcopyin(sopt, &v,
sizeof(v),
2393 error = ENOPROTOOPT;
2417 KASSERT(pcb != NULL, (
"ng_btsocket_l2cap_detach: pcb == NULL"));
2422 mtx_lock(&ng_btsocket_l2cap_sockets_mtx);
2436 LIST_REMOVE(pcb, next);
2439 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
2442 bzero(pcb,
sizeof(*pcb));
2445 soisdisconnected(so);
2468 return (EINPROGRESS);
2479 soisdisconnecting(so);
2503 error = solisten_proto_check(so);
2507 solisten_proto_abort(so);
2512 solisten_proto_abort(so);
2516 if (pcb->
psm == 0) {
2517 solisten_proto_abort(so);
2518 error = EADDRNOTAVAIL;
2521 solisten_proto(so, backlog);
2558 *nam = sodupsockaddr((
struct sockaddr *) &sa, M_NOWAIT);
2560 return ((*nam == NULL)? ENOMEM : 0);
2569 struct sockaddr *nam,
struct mbuf *
control,
struct thread *td)
2580 if (pcb == NULL || m == NULL ||
control != NULL) {
2595 if (pcb->
rt == NULL ||
2603 if (m->m_pkthdr.len > pcb->
omtu) {
2605"%s: Packet too big, len=%d, omtu=%d\n", __func__, m->m_pkthdr.len, pcb->
omtu);
2619 sbappendrecord(&pcb->
so->so_snd, m);
2627 sbdroprecord(&pcb->
so->so_snd);
2645 struct mbuf *m = NULL;
2646 ng_l2cap_l2ca_hdr_t *hdr = NULL;
2649 mtx_assert(&pcb->
pcb_mtx, MA_OWNED);
2651 if (sbavail(&pcb->
so->so_snd) == 0)
2654 m = m_dup(pcb->
so->so_snd.sb_mb, M_NOWAIT);
2659 M_PREPEND(m,
sizeof(*hdr), M_NOWAIT);
2661 if (m->m_len <
sizeof(*hdr))
2662 m = m_pullup(m,
sizeof(*hdr));
2666"%s: Failed to create L2CA packet header\n", __func__);
2671 hdr = mtod(m, ng_l2cap_l2ca_hdr_t *);
2672 hdr->token = pcb->
token;
2673 hdr->length = m->m_pkthdr.len -
sizeof(*hdr);
2674 hdr->lcid = pcb->
cid;
2675 hdr->idtype = pcb->
idtype;
2677"%s: Sending packet: len=%d, length=%d, lcid=%d, token=%d, state=%d\n",
2678 __func__, m->m_pkthdr.len, hdr->length, hdr->lcid,
2679 hdr->token, pcb->
state);
2713 *nam = sodupsockaddr((
struct sockaddr *) &sa, M_NOWAIT);
2715 return ((*nam == NULL)? ENOMEM : 0);
2734 mtx_assert(&ng_btsocket_l2cap_sockets_mtx, MA_OWNED);
2736 LIST_FOREACH(p, &ng_btsocket_l2cap_sockets, next) {
2737 if (p->
so == NULL || !SOLISTENING(p->
so) || p->
psm != psm)
2740 if (bcmp(&p->
src, bdaddr,
sizeof(p->
src)) == 0)
2747 return ((p != NULL)? p : p1);
2763 mtx_assert(&ng_btsocket_l2cap_sockets_mtx, MA_OWNED);
2765 LIST_FOREACH(p, &ng_btsocket_l2cap_sockets, next)
2766 if (p->
token == token)
2782 mtx_assert(&ng_btsocket_l2cap_sockets_mtx, MA_OWNED);
2784 LIST_FOREACH(p, &ng_btsocket_l2cap_sockets, next){
2785 if (p->
cid == cid &&
2786 bcmp(src, &p->
src,
sizeof(p->
src)) == 0&&
2800 mtx_assert(&pcb->
pcb_mtx, MA_OWNED);
2808(
"%s: Duplicated socket timeout?!\n", __func__));
2818 mtx_assert(&pcb->
pcb_mtx, MA_OWNED);
2821 callout_stop(&pcb->
timo);
2822 pcb->
flags &= ~NG_BTSOCKET_L2CAP_TIMO;
2825(
"%s: No socket timeout?!\n", __func__));
2837 mtx_assert(&pcb->
pcb_mtx, MA_OWNED);
2839 pcb->
flags &= ~NG_BTSOCKET_L2CAP_TIMO;
2840 pcb->
so->so_error = ETIMEDOUT;
2842 switch (pcb->
state) {
2852 soisdisconnected(pcb->
so);
2857 sbdroprecord(&pcb->
so->so_snd);
2864 soisdisconnected(pcb->
so);
2869"%s: Invalid socket state=%d\n", __func__, pcb->
state);
2934 return (ECONNREFUSED);
2942 return (EOPNOTSUPP);
2951 return (ECONNRESET);
2954 return (ECONNABORTED);
#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_HOOK_PEER(hook)
#define NG_NODE_UNREF(node)
#define NG_HOOK_SET_PRIVATE(hook, val)
#define NG_SEND_DATA_ONLY(error, hook, m)
#define NG_HOOK_FORCE_QUEUE(hook)
#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)
u_int32_t bluetooth_l2cap_ertx_timeout(void)
SYSCTL_NODE(_net, OID_AUTO, bluetooth, CTLFLAG_RW|CTLFLAG_MPSAFE, 0, "Bluetooth family")
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 BLUETOOTH_PROTO_L2CAP
#define NG_BTSOCKET_L2CAP_NODE_TYPE
#define SO_L2CAP_ENCRYPTED
#define NG_BTSOCKET_WARN_LEVEL
SYSINIT(ng_btsocket_l2cap_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, ng_btsocket_l2cap_init, NULL)
static int ng_btsocket_l2cap_process_l2ca_con_rsp_rsp(struct ng_mesg *msg, ng_btsocket_l2cap_rtentry_p rt)
static void ng_btsocket_l2cap_init(void *arg __unused)
int ng_btsocket_l2cap_sockaddr(struct socket *so, struct sockaddr **nam)
static void ng_btsocket_l2cap_rtclean(void *, int)
static void ng_btsocket_l2cap_input(void *, int)
static int ng_btsocket_l2cap_send_l2ca_cfg_rsp(ng_btsocket_l2cap_pcb_p pcb)
static ng_disconnect_t ng_btsocket_l2cap_node_disconnect
static LIST_HEAD(ng_btsocket_l2cap_pcb)
void ng_btsocket_l2cap_close(struct socket *so)
static int ng_btsocket_l2cap_send_l2ca_discon_req(u_int32_t token, ng_btsocket_l2cap_pcb_p pcb)
static void ng_btsocket_l2cap_l2ca_msg_input(struct ng_mesg *msg, hook_p hook)
#define NG_BTSOCKET_L2CAP_ALERT
static int ng_btsocket_l2cap_process_l2ca_write_rsp(struct ng_mesg *msg, ng_btsocket_l2cap_rtentry_p rt)
int ng_btsocket_l2cap_accept(struct socket *so, struct sockaddr **nam)
static struct mtx ng_btsocket_l2cap_queue_mtx
int ng_btsocket_l2cap_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp, struct thread *td)
#define NG_BTSOCKET_L2CAP_ERR
static struct task ng_btsocket_l2cap_queue_task
static int ng_btsocket_l2cap_process_l2ca_cfg_rsp_rsp(struct ng_mesg *msg, ng_btsocket_l2cap_rtentry_p rt)
#define NG_BTSOCKET_L2CAP_INFO
#define M_NETGRAPH_BTSOCKET_L2CAP
static void ng_btsocket_l2cap_data_input(struct mbuf *m, hook_p hook)
static int ng_btsocket_l2cap_process_l2ca_enc_change(struct ng_mesg *msg, ng_btsocket_l2cap_rtentry_p rt)
#define NG_BTSOCKET_L2CAP_WARN
static void ng_btsocket_l2cap_process_timeout(void *xpcb)
static int ng_btsocket_l2cap_process_l2ca_discon_ind(struct ng_mesg *msg, ng_btsocket_l2cap_rtentry_p rt)
static ng_btsocket_l2cap_pcb_p ng_btsocket_l2cap_pcb_by_addr(bdaddr_p bdaddr, int psm)
#define ng_btsocket_l2cap_wakeup_route_task()
static int ng_btsocket_l2cap_process_l2ca_con_req_rsp(struct ng_mesg *msg, ng_btsocket_l2cap_rtentry_p rt)
static void ng_btsocket_l2cap_untimeout(ng_btsocket_l2cap_pcb_p pcb)
static ng_connect_t ng_btsocket_l2cap_node_connect
static int ng_btsocket_l2cap_send2(ng_btsocket_l2cap_pcb_p pcb)
static ng_btsocket_l2cap_pcb_p ng_btsocket_l2cap_pcb_by_token(u_int32_t token)
int ng_btsocket_l2cap_ctloutput(struct socket *so, struct sockopt *sopt)
static struct ng_type typestruct
static int ng_btsocket_l2cap_send_l2ca_con_rsp_req(u_int32_t token, ng_btsocket_l2cap_rtentry_p rt, bdaddr_p dst, int ident, int lcid, int result, int linktype)
static int ng_btsocket_l2cap_process_l2ca_cfg_req_rsp(struct ng_mesg *msg, ng_btsocket_l2cap_rtentry_p rt)
int ng_btsocket_l2cap_peeraddr(struct socket *so, struct sockaddr **nam)
int ng_btsocket_l2cap_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam, struct mbuf *control, struct thread *td)
static int ng_btsocket_l2cap_process_l2ca_con_ind(struct ng_mesg *msg, ng_btsocket_l2cap_rtentry_p rt)
static int ng_btsocket_l2cap_send_l2ca_con_req(ng_btsocket_l2cap_pcb_p pcb)
int ng_btsocket_l2cap_disconnect(struct socket *so)
static int ng_btsocket_l2cap_result2errno(int result)
static void ng_btsocket_l2cap_timeout(ng_btsocket_l2cap_pcb_p pcb)
static int ng_btsocket_l2cap_send_l2ca_cfg_req(ng_btsocket_l2cap_pcb_p pcb)
static int ng_btsocket_l2cap_process_l2ca_cfg_ind(struct ng_mesg *msg, ng_btsocket_l2cap_rtentry_p rt)
static node_p ng_btsocket_l2cap_node
int ng_btsocket_l2cap_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
static ng_constructor_t ng_btsocket_l2cap_node_constructor
static ng_shutdown_t ng_btsocket_l2cap_node_shutdown
static ng_btsocket_l2cap_pcb_p ng_btsocket_l2cap_pcb_by_cid(bdaddr_p src, int cid, int idtype)
void ng_btsocket_l2cap_abort(struct socket *so)
int ng_btsocket_l2cap_listen(struct socket *so, int backlog, struct thread *td)
static struct ng_bt_itemq ng_btsocket_l2cap_queue
#define ng_btsocket_l2cap_wakeup_input_task()
void ng_btsocket_l2cap_detach(struct socket *so)
static u_int32_t ng_btsocket_l2cap_debug_level
int ng_btsocket_l2cap_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
static ng_rcvdata_t ng_btsocket_l2cap_node_rcvdata
int ng_btsocket_l2cap_attach(struct socket *so, int proto, struct thread *td)
static int ng_btsocket_l2cap_process_l2ca_discon_rsp(struct ng_mesg *msg, ng_btsocket_l2cap_rtentry_p rt)
static ng_newhook_t ng_btsocket_l2cap_node_newhook
static void ng_btsocket_l2cap_default_msg_input(struct ng_mesg *msg, hook_p hook)
static ng_rcvmsg_t ng_btsocket_l2cap_node_rcvmsg
#define NG_BTSOCKET_L2CAP_DISCONNECTING
#define NG_BTSOCKET_L2CAP_CLIENT
#define NG_BTSOCKET_L2CAP_CONNECTING
#define NG_BTSOCKET_L2CAP_CFG_OUT_SENT
#define NG_BTSOCKET_L2CAP_TIMO
#define NG_BTSOCKET_L2CAP_CFG_OUT
#define NG_BTSOCKET_L2CAP_RECVSPACE
#define NG_BTSOCKET_L2CAP_CFG_IN
#define NG_BTSOCKET_L2CAP_CFG_BOTH
struct ng_btsocket_l2cap_pcb * ng_btsocket_l2cap_pcb_p
#define NG_BTSOCKET_L2CAP_W4_ENC_CHANGE
#define NG_BTSOCKET_L2CAP_CLOSED
struct ng_btsocket_l2cap_rtentry * ng_btsocket_l2cap_rtentry_p
#define NG_BTSOCKET_L2CAP_SENDSPACE
#define NG_BTSOCKET_L2CAP_CFG_IN_SENT
#define NG_BTSOCKET_L2CAP_CONFIGURING
#define NG_BTSOCKET_L2CAP_OPEN
MALLOC_DEFINE(M_NG_CCATM, "ng_ccatm", "netgraph uni api node")
#define NG_HCI_BDADDR_ANY
#define NG_HCI_LINK_LE_RANDOM
#define NG_HCI_SERVICE_TYPE_BEST_EFFORT
#define NG_HCI_LINK_LE_PUBLIC
#define NGM_L2CAP_L2CA_DISCON
#define NGM_L2CAP_L2CA_ENC_CHANGE
#define NG_L2CAP_PSM_NOT_SUPPORTED
#define NGM_L2CAP_L2CA_CFG_RSP
#define NGM_L2CAP_L2CA_WRITE
#define NG_L2CAP_L2CA_IDTYPE_BREDR
#define NG_L2CAP_L2CA_IDTYPE_SMP
#define NG_L2CAP_FLUSH_TIMO_DEFAULT
#define NGM_L2CAP_L2CA_CFG
#define NGM_L2CAP_L2CA_DISCON_IND
#define NG_L2CAP_MTU_DEFAULT
#define NG_L2CAP_L2CA_IDTYPE_ATT
#define NGM_L2CAP_L2CA_CFG_IND
#define NG_L2CAP_UNACCEPTABLE_PARAMS
#define NGM_L2CAP_L2CA_CON_RSP
#define NGM_L2CAP_L2CA_CON
#define NGM_L2CAP_L2CA_CON_IND
#define NG_L2CAP_NO_RESOURCES
#define NG_L2CAP_UNKNOWN_OPTION
#define NG_L2CAP_LINK_TIMO_DEFAULT
#define NGM_L2CAP_NODE_HOOK_INFO
#define NG_L2CAP_FIRST_CID
#define NG_MKMESSAGE(msg, cookie, cmdid, len, how)
ng_btsocket_l2cap_rtentry_p rt
struct ng_mesg::ng_msghdr header
u_int8_t l2cap_bdaddr_type