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>
50#include <sys/protosw.h>
52#include <sys/socket.h>
53#include <sys/socketvar.h>
54#include <sys/sysctl.h>
55#include <sys/taskqueue.h>
70#ifdef NG_SEPARATE_MALLOC
72 "Netgraph Bluetooth RFCOMM sockets");
74#define M_NETGRAPH_BTSOCKET_RFCOMM M_NETGRAPH
78#define NG_BTSOCKET_RFCOMM_INFO \
79 if (ng_btsocket_rfcomm_debug_level >= NG_BTSOCKET_INFO_LEVEL && \
80 ppsratecheck(&ng_btsocket_rfcomm_lasttime, &ng_btsocket_rfcomm_curpps, 1)) \
83#define NG_BTSOCKET_RFCOMM_WARN \
84 if (ng_btsocket_rfcomm_debug_level >= NG_BTSOCKET_WARN_LEVEL && \
85 ppsratecheck(&ng_btsocket_rfcomm_lasttime, &ng_btsocket_rfcomm_curpps, 1)) \
88#define NG_BTSOCKET_RFCOMM_ERR \
89 if (ng_btsocket_rfcomm_debug_level >= NG_BTSOCKET_ERR_LEVEL && \
90 ppsratecheck(&ng_btsocket_rfcomm_lasttime, &ng_btsocket_rfcomm_curpps, 1)) \
93#define NG_BTSOCKET_RFCOMM_ALERT \
94 if (ng_btsocket_rfcomm_debug_level >= NG_BTSOCKET_ALERT_LEVEL && \
95 ppsratecheck(&ng_btsocket_rfcomm_lasttime, &ng_btsocket_rfcomm_curpps, 1)) \
102 (
struct socket *so,
void *arg,
int waitflag);
104 (
void *ctx,
int pending);
107#define ng_btsocket_rfcomm_task_wakeup() \
108 taskqueue_enqueue(taskqueue_swi_giant, &ng_btsocket_rfcomm_task)
192 (
struct sockbuf *sb,
int length);
200static struct mtx ng_btsocket_rfcomm_sessions_mtx;
202static struct mtx ng_btsocket_rfcomm_sockets_mtx;
203static struct timeval ng_btsocket_rfcomm_lasttime;
204static int ng_btsocket_rfcomm_curpps;
207SYSCTL_DECL(_net_bluetooth_rfcomm_sockets);
208static SYSCTL_NODE(_net_bluetooth_rfcomm_sockets, OID_AUTO, stream,
209 CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
210 "Bluetooth STREAM RFCOMM sockets family");
211SYSCTL_UINT(_net_bluetooth_rfcomm_sockets_stream, OID_AUTO, debug_level,
214 "Bluetooth STREAM RFCOMM sockets debug level");
215SYSCTL_UINT(_net_bluetooth_rfcomm_sockets_stream, OID_AUTO, timeout,
218 "Bluetooth STREAM RFCOMM sockets timeout");
226static u_int8_t ng_btsocket_rfcomm_crc_table[256] = {
227 0x00, 0x91, 0xe3, 0x72, 0x07, 0x96, 0xe4, 0x75,
228 0x0e, 0x9f, 0xed, 0x7c, 0x09, 0x98, 0xea, 0x7b,
229 0x1c, 0x8d, 0xff, 0x6e, 0x1b, 0x8a, 0xf8, 0x69,
230 0x12, 0x83, 0xf1, 0x60, 0x15, 0x84, 0xf6, 0x67,
232 0x38, 0xa9, 0xdb, 0x4a, 0x3f, 0xae, 0xdc, 0x4d,
233 0x36, 0xa7, 0xd5, 0x44, 0x31, 0xa0, 0xd2, 0x43,
234 0x24, 0xb5, 0xc7, 0x56, 0x23, 0xb2, 0xc0, 0x51,
235 0x2a, 0xbb, 0xc9, 0x58, 0x2d, 0xbc, 0xce, 0x5f,
237 0x70, 0xe1, 0x93, 0x02, 0x77, 0xe6, 0x94, 0x05,
238 0x7e, 0xef, 0x9d, 0x0c, 0x79, 0xe8, 0x9a, 0x0b,
239 0x6c, 0xfd, 0x8f, 0x1e, 0x6b, 0xfa, 0x88, 0x19,
240 0x62, 0xf3, 0x81, 0x10, 0x65, 0xf4, 0x86, 0x17,
242 0x48, 0xd9, 0xab, 0x3a, 0x4f, 0xde, 0xac, 0x3d,
243 0x46, 0xd7, 0xa5, 0x34, 0x41, 0xd0, 0xa2, 0x33,
244 0x54, 0xc5, 0xb7, 0x26, 0x53, 0xc2, 0xb0, 0x21,
245 0x5a, 0xcb, 0xb9, 0x28, 0x5d, 0xcc, 0xbe, 0x2f,
247 0xe0, 0x71, 0x03, 0x92, 0xe7, 0x76, 0x04, 0x95,
248 0xee, 0x7f, 0x0d, 0x9c, 0xe9, 0x78, 0x0a, 0x9b,
249 0xfc, 0x6d, 0x1f, 0x8e, 0xfb, 0x6a, 0x18, 0x89,
250 0xf2, 0x63, 0x11, 0x80, 0xf5, 0x64, 0x16, 0x87,
252 0xd8, 0x49, 0x3b, 0xaa, 0xdf, 0x4e, 0x3c, 0xad,
253 0xd6, 0x47, 0x35, 0xa4, 0xd1, 0x40, 0x32, 0xa3,
254 0xc4, 0x55, 0x27, 0xb6, 0xc3, 0x52, 0x20, 0xb1,
255 0xca, 0x5b, 0x29, 0xb8, 0xcd, 0x5c, 0x2e, 0xbf,
257 0x90, 0x01, 0x73, 0xe2, 0x97, 0x06, 0x74, 0xe5,
258 0x9e, 0x0f, 0x7d, 0xec, 0x99, 0x08, 0x7a, 0xeb,
259 0x8c, 0x1d, 0x6f, 0xfe, 0x8b, 0x1a, 0x68, 0xf9,
260 0x82, 0x13, 0x61, 0xf0, 0x85, 0x14, 0x66, 0xf7,
262 0xa8, 0x39, 0x4b, 0xda, 0xaf, 0x3e, 0x4c, 0xdd,
263 0xa6, 0x37, 0x45, 0xd4, 0xa1, 0x30, 0x42, 0xd3,
264 0xb4, 0x25, 0x57, 0xc6, 0xb3, 0x22, 0x50, 0xc1,
265 0xba, 0x2b, 0x59, 0xc8, 0xbd, 0x2c, 0x5e, 0xcf
275 crc = ng_btsocket_rfcomm_crc_table[crc ^ *
data++];
343 LIST_INIT(&ng_btsocket_rfcomm_sessions);
344 mtx_init(&ng_btsocket_rfcomm_sessions_mtx,
345 "btsocks_rfcomm_sessions_mtx", NULL, MTX_DEF);
348 LIST_INIT(&ng_btsocket_rfcomm_sockets);
349 mtx_init(&ng_btsocket_rfcomm_sockets_mtx,
350 "btsocks_rfcomm_sockets_mtx", NULL, MTX_DEF);
363 so->so_error = ECONNABORTED;
396 if (so->so_type != SOCK_STREAM)
397 return (ESOCKTNOSUPPORT);
402 return (EPROTONOSUPPORT);
409 if ((so->so_snd.sb_hiwat == 0) || (so->so_rcv.sb_hiwat == 0)) {
417 pcb = malloc(
sizeof(*pcb),
423 so->so_pcb = (caddr_t) pcb;
437 mtx_init(&pcb->
pcb_mtx,
"btsocks_rfcomm_pcb_mtx", NULL, MTX_DEF);
441 mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
442 LIST_INSERT_HEAD(&ng_btsocket_rfcomm_sockets, pcb, next);
443 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
466 return (EAFNOSUPPORT);
475 mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
477 LIST_FOREACH(pcb1, &ng_btsocket_rfcomm_sockets, next) {
480 sizeof(pcb1->src)) == 0) {
481 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
488 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
510 struct socket *l2so = NULL;
520 return (EAFNOSUPPORT);
527 return (EDESTADDRREQ);
535 error = socreate(PF_BLUETOOTH, &l2so, SOCK_SEQPACKET,
542 mtx_lock(&ng_btsocket_rfcomm_sessions_mtx);
553 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
560 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
565 }
else if (l2so != NULL)
580 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
602 LIST_INSERT_HEAD(&s->dlcs, pcb, session_next);
606 soisconnecting(pcb->
so);
629 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
641 struct ifnet *ifp,
struct thread *td)
664 switch (sopt->sopt_dir) {
666 switch (sopt->sopt_name) {
668 error = sooptcopyout(sopt, &pcb->
mtu,
sizeof(pcb->
mtu));
680 error = sooptcopyout(sopt, &fcinfo,
sizeof(fcinfo));
690 switch (sopt->sopt_name) {
716 KASSERT(pcb != NULL, (
"ng_btsocket_rfcomm_detach: pcb == NULL"));
720 switch (pcb->
state) {
746 panic(
"%s: pcb->session != NULL\n", __func__);
748 panic(
"%s: timeout on closed DLC, flags=%#x\n",
749 __func__, pcb->
flags);
751 mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
752 LIST_REMOVE(pcb, next);
753 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
758 bzero(pcb,
sizeof(*pcb));
761 soisdisconnected(so);
781 return (EINPROGRESS);
788 switch (pcb->
state) {
799 soisdisconnecting(so);
809 panic(
"%s: Invalid DLC state=%d, flags=%#x\n",
828 struct socket *l2so = NULL;
829 int error, socreate_error, usedchannels;
834 return (EADDRNOTAVAIL);
841 mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
843 LIST_FOREACH(pcb1, &ng_btsocket_rfcomm_sockets, next)
844 if (pcb1->channel != 0 &&
845 bcmp(&pcb1->src, &pcb->
src,
sizeof(pcb->
src)) == 0)
846 usedchannels |= (1 << (pcb1->channel - 1));
849 if (!(usedchannels & (1 << (pcb->
channel - 1))))
853 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
856 return (EADDRNOTAVAIL);
859 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
870 socreate_error = socreate(PF_BLUETOOTH, &l2so, SOCK_SEQPACKET,
877 mtx_lock(&ng_btsocket_rfcomm_sessions_mtx);
879 error = solisten_proto_check(so);
884 LIST_FOREACH(s, &ng_btsocket_rfcomm_sessions, next)
895 solisten_proto_abort(so);
896 error = socreate_error;
910 solisten_proto_abort(so);
916 solisten_proto(so, backlog);
919 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
947 *nam = sodupsockaddr((
struct sockaddr *) &sa, M_NOWAIT);
949 return ((*nam == NULL)? ENOMEM : 0);
958 struct sockaddr *nam,
struct mbuf *
control,
struct thread *td)
964 if (pcb == NULL || m == NULL ||
control != NULL) {
979 sbappend(&pcb->
so->so_snd, m,
flags);
1013 *nam = sodupsockaddr((
struct sockaddr *) &sa, M_NOWAIT);
1015 return ((*nam == NULL)? ENOMEM : 0);
1028 panic(
"%s: so == NULL\n", __func__);
1032"%s: Could not enqueue RFCOMM task, error=%d\n", __func__, error);
1046 mtx_lock(&ng_btsocket_rfcomm_sessions_mtx);
1048 for (s = LIST_FIRST(&ng_btsocket_rfcomm_sessions); s != NULL; ) {
1050 s_next = LIST_NEXT(s, next);
1056 LIST_REMOVE(s, next);
1059 if (!LIST_EMPTY(&s->dlcs))
1060 panic(
"%s: DLC list is not empty\n", __func__);
1063 SOCKBUF_LOCK(&s->
l2so->so_rcv);
1064 soupcall_clear(s->
l2so, SO_RCV);
1065 SOCKBUF_UNLOCK(&s->
l2so->so_rcv);
1066 SOCKBUF_LOCK(&s->
l2so->so_snd);
1067 soupcall_clear(s->
l2so, SO_SND);
1068 SOCKBUF_UNLOCK(&s->
l2so->so_snd);
1074 bzero(s,
sizeof(*s));
1082 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
1094 if (s->
l2so->so_rcv.sb_state & SBS_CANTRCVMORE) {
1096"%s: L2CAP connection has been terminated, so=%p, so_state=%#x, so_count=%d, " \
1097"state=%d, flags=%#x\n", __func__, s->
l2so, s->
l2so->so_state,
1141 panic(
"%s: Invalid session state=%d, flags=%#x\n",
1178 CURVNET_SET(pcb->
so->so_vnet);
1179 so1 = sonewconn(pcb->
so, 0);
1194 panic(
"%s: pcb1 == NULL\n", __func__);
1196 mtx_lock(&pcb1->pcb_mtx);
1198 bcopy(&l2pcb->
src, &pcb1->src,
sizeof(pcb1->src));
1199 bcopy(&l2pcb->
dst, &pcb1->dst,
sizeof(pcb1->dst));
1200 pcb1->channel = channel;
1203 LIST_INSERT_HEAD(&s->dlcs, pcb1, session_next);
1206 mtx_unlock(&pcb1->pcb_mtx);
1231 for (pcb = LIST_FIRST(&s->dlcs); pcb != NULL; ) {
1233 pcb_next = LIST_NEXT(pcb, session_next);
1270 struct sockopt l2sopt;
1274 mtx_assert(&ng_btsocket_rfcomm_sessions_mtx, MA_OWNED);
1277 s = malloc(
sizeof(*s),
1295 mtx_init(&s->
session_mtx,
"btsocks_rfcomm_session_mtx", NULL,
1298 LIST_INIT(&s->dlcs);
1301 SOCKBUF_LOCK(&l2so->so_rcv);
1303 SOCKBUF_UNLOCK(&l2so->so_rcv);
1304 SOCKBUF_LOCK(&l2so->so_snd);
1306 SOCKBUF_UNLOCK(&l2so->so_snd);
1307 l2so->so_state |= SS_NBIO;
1317 if (src == NULL && dst == NULL)
1328 l2sopt.sopt_dir = SOPT_SET;
1331 l2sopt.sopt_val = (
void *) &
mtu;
1332 l2sopt.sopt_valsize =
sizeof(
mtu);
1333 l2sopt.sopt_td = NULL;
1335 error = sosetopt(s->
l2so, &l2sopt);
1347 error = sobind(s->
l2so, (
struct sockaddr *) &l2sa, td);
1356 error = solisten(s->
l2so, 10, td);
1370 error = soconnect(s->
l2so, (
struct sockaddr *) &l2sa, td);
1376 LIST_INSERT_HEAD(&ng_btsocket_rfcomm_sessions, s, next);
1387 SOCKBUF_LOCK(&l2so->so_rcv);
1388 soupcall_clear(s->
l2so, SO_RCV);
1389 SOCKBUF_UNLOCK(&l2so->so_rcv);
1390 SOCKBUF_LOCK(&l2so->so_snd);
1391 soupcall_clear(s->
l2so, SO_SND);
1392 SOCKBUF_UNLOCK(&l2so->so_snd);
1393 l2so->so_state &= ~SS_NBIO;
1396 bzero(s,
sizeof(*s));
1410 struct socket *l2so;
1416 mtx_assert(&ng_btsocket_rfcomm_sessions_mtx, MA_OWNED);
1419 SOLISTEN_LOCK(s0->
l2so);
1420 error = solisten_dequeue(s0->
l2so, &l2so, 0);
1421 if (error == EWOULDBLOCK)
1425"%s: Could not accept connection on L2CAP socket, error=%d\n", __func__, error);
1429 error = soaccept(l2so, (
struct sockaddr **) &l2sa);
1432"%s: soaccept() on L2CAP socket failed, error=%d\n", __func__, error);
1469"%s: Failed to create new RFCOMM session, error=%d\n", __func__, error);
1475"%s: Rejecting duplicating RFCOMM session between src=%x:%x:%x:%x:%x:%x and " \
1476"dst=%x:%x:%x:%x:%x:%x, state=%d, flags=%#x\n", __func__,
1477 l2pcb->
src.b[5], l2pcb->
src.b[4], l2pcb->
src.b[3],
1478 l2pcb->
src.b[2], l2pcb->
src.b[1], l2pcb->
src.b[0],
1479 l2pcb->
dst.b[5], l2pcb->
dst.b[4], l2pcb->
dst.b[3],
1480 l2pcb->
dst.b[2], l2pcb->
dst.b[1], l2pcb->
dst.b[0],
1504 if ((error = s->
l2so->so_error) != 0) {
1505 s->
l2so->so_error = 0;
1508"%s: Could not connect RFCOMM session, error=%d, state=%d, flags=%#x\n",
1515 if (s->
l2so->so_state & SS_ISCONNECTING)
1551 struct mbuf *m = NULL;
1553 int more,
flags, error;
1558 if (!soreadable(s->
l2so))
1562 if ((error = s->
l2so->so_error) != 0) {
1563 s->
l2so->so_error = 0;
1566"%s: Could not receive data from L2CAP socket, error=%d, state=%d, flags=%#x\n",
1580 for (more = 1; more; ) {
1582 bzero(&uio,
sizeof(uio));
1584 uio.uio_resid = 1000000000;
1585 flags = MSG_DONTWAIT;
1588 error = soreceive(s->
l2so, NULL, &uio, &m,
1589 (
struct mbuf **) NULL, &
flags);
1591 if (error == EWOULDBLOCK)
1595"%s: Could not receive data from L2CAP socket, error=%d\n", __func__, error);
1600 more = (m->m_nextpkt != NULL);
1601 m->m_nextpkt = NULL;
1617 struct mbuf *m = NULL;
1623 while (sowriteable(s->
l2so)) {
1625 if ((error = s->
l2so->so_error) != 0) {
1626 s->
l2so->so_error = 0;
1629"%s: Detected error=%d on L2CAP socket, state=%d, flags=%#x\n",
1640 error = (*s->
l2so->so_proto->pr_usrreqs->pru_send)(s->
l2so,
1641 0, m, NULL, NULL, curthread );
1644"%s: Could not send data to L2CAP socket, error=%d\n", __func__, error);
1671 for (pcb = LIST_FIRST(&s->dlcs); pcb != NULL; ) {
1673 pcb_next = LIST_NEXT(pcb, session_next);
1676"%s: Disconnecting dlci=%d, state=%d, flags=%#x\n",
1682 error = ECONNREFUSED;
1708 for (pcb = LIST_FIRST(&s->dlcs); pcb != NULL; ) {
1710 pcb_next = LIST_NEXT(pcb, session_next);
1712 switch (pcb->
state) {
1776 panic(
"%s: Invalid DLC state=%d, flags=%#x\n",
1798 mtx_assert(&ng_btsocket_rfcomm_sessions_mtx, MA_OWNED);
1802 LIST_FOREACH(s, &ng_btsocket_rfcomm_sessions, next) {
1805 if ((any_src || bcmp(&l2pcb->
src, src,
sizeof(*src)) == 0) &&
1806 bcmp(&l2pcb->
dst, dst,
sizeof(*dst)) == 0)
1829 struct mbuf *m = NULL;
1838 if (m0->m_len <
length) {
1839 if ((m0 = m_pullup(m0,
length)) == NULL) {
1841"%s: m_pullup(%d) failed\n", __func__,
length);
1855 m_adj(m0,
sizeof(*hdr) + 1);
1858 m_adj(m0,
sizeof(*hdr));
1862"%s: Got frame type=%#x, dlci=%d, length=%d, cr=%d, pf=%d, len=%d\n",
1872 for (m = m0; m->m_next != NULL; m = m->m_next)
1875 panic(
"%s: Empty mbuf at the end of the chain, len=%d\n",
1876 __func__, m->m_len);
1885"%s: Invalid RFCOMM packet. Bad checksum\n", __func__);
1948"%s: Invalid RFCOMM packet. Unknown type=%#x\n", __func__,
type);
1971"%s: Got SABM, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
1992"%s: Got SABM for session in invalid state state=%d, flags=%#x\n",
2004"%s: Got SABM for dlci=%d with mulitplexor channel closed, state=%d, " \
2021"%s: Got SABM for dlci=%d in invalid state=%d, flags=%#x\n",
2036 soisconnected(pcb->
so);
2062 soisconnected(pcb->
so);
2087"%s: Got DISC, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
2111"%s: Got DISC for dlci=%d, state=%d, flags=%#x\n",
2127"%s: Got DISC for non-existing dlci=%d\n", __func__,
dlci);
2150"%s: Got UA, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
2168"%s: Got UA for session in invalid state=%d(%d), flags=%#x, mtu=%d\n",
2184"%s: Got UA for dlci=%d, state=%d, flags=%#x\n",
2187 switch (pcb->
state) {
2194 soisconnected(pcb->
so);
2204"%s: Got UA for dlci=%d in invalid state=%d, flags=%#x\n",
2213"%s: Got UA for non-existing dlci=%d\n", __func__,
dlci);
2234"%s: Got DM, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
2248"%s: Got DM for dlci=%d, state=%d, flags=%#x\n",
2254 error = ECONNREFUSED;
2261"%s: Got DM for non-existing dlci=%d\n", __func__,
dlci);
2273 int pf,
struct mbuf *m0)
2281"%s: Got UIH, session state=%d, flags=%#x, mtu=%d, dlci=%d, pf=%d, len=%d\n",
2288"%s: Got UIH with session flow control asserted, state=%d, flags=%#x\n",
2297"%s: Got UIH for non-existing dlci=%d\n", __func__,
dlci);
2307"%s: Got UIH for dlci=%d in invalid state=%d, flags=%#x\n",
2317"%s: Got UIH for dlci=%d with asserted flow control, state=%d, " \
2318"flags=%#x, rx_cred=%d, lmodem=%#x\n",
2327"%s: Got %d more credits for dlci=%d, state=%d, flags=%#x, " \
2328"rx_cred=%d, tx_cred=%d\n",
2329 __func__, *mtod(m0, u_int8_t *),
dlci, pcb->
state,
2332 pcb->
tx_cred += *mtod(m0, u_int8_t *);
2340 if (m0->m_pkthdr.len > 0) {
2348"%s: Remote side still has credits, dlci=%d, state=%d, flags=%#x, " \
2349"rx_cred=%d, tx_cred=%d\n", __func__,
dlci, pcb->
state, pcb->
flags,
2354 if (m0->m_pkthdr.len > pcb->
mtu) {
2356"%s: Got oversized UIH for dlci=%d, state=%d, flags=%#x, mtu=%d, len=%d\n",
2358 pcb->
mtu, m0->m_pkthdr.len);
2361 }
else if (m0->m_pkthdr.len > sbspace(&pcb->
so->so_rcv)) {
2369"%s: Not enough space in socket receive queue. Dropping UIH for dlci=%d, " \
2370"state=%d, flags=%#x, len=%d, space=%ld\n",
2372 m0->m_pkthdr.len, sbspace(&pcb->
so->so_rcv));
2377 sbappend(&pcb->
so->so_rcv, m0, 0);
2436 if (
sizeof(*hdr) +
length != m0->m_pkthdr.len) {
2438"%s: Invalid MCC frame length=%d, len=%d\n",
2439 __func__,
length, m0->m_pkthdr.len);
2473"%s: Got MCC NSC, type=%#x, cr=%d, length=%d, session state=%d, flags=%#x, " \
2474"mtu=%d, len=%d\n", __func__,
RFCOMM_MCC_TYPE(*((u_int8_t *)(hdr + 1))), cr,
2481"%s: Got unknown MCC, type=%#x, cr=%d, length=%d, session state=%d, " \
2482"flags=%#x, mtu=%d, len=%d\n",
2484 s->
mtu, m0->m_pkthdr.len);
2488 m0->m_pkthdr.len = m0->m_len =
sizeof(*hdr);
2496 m0->m_pkthdr.len ++;
2521"%s: Got MCC TEST, cr=%d, length=%d, session state=%d, flags=%#x, mtu=%d, " \
2555"%s: Got MCC FC%s, cr=%d, length=%d, session state=%d, flags=%#x, mtu=%d, " \
2562 s->
flags &= ~NG_BTSOCKET_RFCOMM_SESSION_RFC;
2590"%s: Got MCC MSC, dlci=%d, cr=%d, length=%d, session state=%d, flags=%#x, " \
2594 s->
mtu, m0->m_pkthdr.len);
2600"%s: Got MSC command for non-existing dlci=%d\n",
2612"%s: Got MSC on dlci=%d in invalid state=%d\n",
2654 u_int8_t
bit_rate, data_bits, stop_bits, parity,
2660"%s: Got MCC RPN, dlci=%d, cr=%d, length=%d, session state=%d, flags=%#x, " \
2664 s->
mtu, m0->m_pkthdr.len);
2739 m0->m_pkthdr.len = m0->m_len =
sizeof(*hdr) +
sizeof(*rpn);
2770"%s: Got MCC RLS, dlci=%d, status=%#x, cr=%d, length=%d, session state=%d, " \
2771"flags=%#x, mtu=%d, len=%d\n",
2806"%s: Got MCC PN, dlci=%d, cr=%d, length=%d, flow_control=%#x, priority=%d, " \
2807"ack_timer=%d, mtu=%d, max_retrans=%d, credits=%d, session state=%d, " \
2808"flags=%#x, session mtu=%d, len=%d\n",
2814 if (pn->
dlci == 0) {
2854"%s: Got PN response for dlci=%d in invalid state=%d\n",
2889 soisconnecting(pcb->
so);
2932 mtx_assert(&pcb->
pcb_mtx, MA_OWNED);
2941 pcb->
flags &= ~NG_BTSOCKET_RFCOMM_DLC_CFC;
2949 pcb->
flags &= ~NG_BTSOCKET_RFCOMM_DLC_CFC;
2955"%s: cr=%d, dlci=%d, state=%d, flags=%#x, mtu=%d, rx_cred=%d, tx_cred=%d\n",
2969 struct mbuf *m = NULL;
2975"%s: Sending command type %#x, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
2990 panic(
"%s: Invalid frame type=%#x\n", __func__,
type);
2995 MGETHDR(m, M_NOWAIT, MT_DATA);
2999 m->m_pkthdr.len = m->m_len =
sizeof(*hdr);
3021 struct mbuf *m = NULL, *mcrc = NULL;
3026 MGETHDR(m, M_NOWAIT, MT_DATA);
3031 m->m_pkthdr.len = m->m_len =
sizeof(*hdr);
3033 MGET(mcrc, M_NOWAIT, MT_DATA);
3053 bcopy(&l, &hdr->
length,
sizeof(l));
3060 m->m_data[m->m_len] =
credits;
3068 m->m_pkthdr.len +=
length;
3076"%s: Sending UIH state=%d, flags=%#x, address=%d, length=%d, pf=%d, " \
3077"credits=%d, len=%d\n",
3093 struct mbuf *m = NULL;
3098 mtx_assert(&pcb->
pcb_mtx, MA_OWNED);
3100 MGETHDR(m, M_NOWAIT, MT_DATA);
3104 m->m_pkthdr.len = m->m_len =
sizeof(*hdr) +
sizeof(*msc);
3116"%s: Sending MSC dlci=%d, state=%d, flags=%#x, address=%d, modem=%#x\n",
3131 struct mbuf *m = NULL;
3136 mtx_assert(&pcb->
pcb_mtx, MA_OWNED);
3138 MGETHDR(m, M_NOWAIT, MT_DATA);
3142 m->m_pkthdr.len = m->m_len =
sizeof(*hdr) +
sizeof(*pn);
3159 pn->
mtu = htole16(pcb->
mtu);
3171"%s: Sending PN dlci=%d, state=%d, flags=%#x, mtu=%d, flow_control=%#x, " \
3189 mtx_assert(&pcb->
pcb_mtx, MA_OWNED);
3193"%s: Sending more credits, dlci=%d, state=%d, flags=%#x, mtu=%d, " \
3194"space=%ld, tx_cred=%d, rx_cred=%d\n",
3211"%s: Gave remote side %d more credits, dlci=%d, state=%d, flags=%#x, " \
3216"%s: Could not send credits, error=%d, dlci=%d, state=%d, flags=%#x, " \
3217"mtu=%d, space=%ld, tx_cred=%d, rx_cred=%d\n",
3219 pcb->
flags, pcb->
mtu, sbspace(&pcb->
so->so_rcv),
3240 struct mbuf *m = NULL;
3244 mtx_assert(&pcb->
pcb_mtx, MA_OWNED);
3255"%s: Could not send - remote flow control asserted, dlci=%d, flags=%#x, " \
3256"rmodem=%#x, tx_cred=%d\n",
3263 for (error = 0, sent = 0; sent < limit; sent ++) {
3279 pcb->
dlci), 0, 0, m);
3287 if (error == 0 && sent > 0) {
3288 pcb->
flags &= ~NG_BTSOCKET_RFCOMM_DLC_SENDING;
3307"%s: Killing DLC, so=%p, dlci=%d, state=%d, flags=%#x, error=%d\n",
3311 panic(
"%s: DLC without session, pcb=%p, state=%d, flags=%#x\n",
3315 mtx_assert(&pcb->
pcb_mtx, MA_OWNED);
3321 LIST_REMOVE(pcb, session_next);
3326 pcb->
so->so_error = error;
3327 soisdisconnected(pcb->
so);
3328 wakeup(&pcb->
state);
3331 if (LIST_EMPTY(&s->dlcs) &&
INITIATOR(s)) {
3333"%s: Disconnecting session, state=%d, flags=%#x, mtu=%d\n",
3363 panic(
"%s: Invalid session state=%d, flags=%#x\n",
3383 LIST_FOREACH(pcb, &s->dlcs, session_next)
3399 mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
3401 LIST_FOREACH(pcb, &ng_btsocket_rfcomm_sockets, next) {
3402 if (pcb->
channel != channel || !SOLISTENING(pcb->
so))
3405 if (bcmp(&pcb->
src, src,
sizeof(*src)) == 0)
3412 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
3414 return ((pcb != NULL)? pcb : pcb1);
3430 mtx_assert(&pcb->
pcb_mtx, MA_OWNED);
3434 pcb->
flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT;
3438 panic(
"%s: Duplicated socket timeout?!\n", __func__);
3448 mtx_assert(&pcb->
pcb_mtx, MA_OWNED);
3451 callout_stop(&pcb->
timo);
3452 pcb->
flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMO;
3453 pcb->
flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT;
3455 panic(
"%s: No socket timeout?!\n", __func__);
3467 mtx_assert(&pcb->
pcb_mtx, MA_OWNED);
3470"%s: Timeout, so=%p, dlci=%d, state=%d, flags=%#x\n",
3473 pcb->
flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMO;
3476 switch (pcb->
state) {
3488"%s: DLC timeout in invalid state, dlci=%d, state=%d, flags=%#x\n",
3503 struct mbuf *top = NULL, *m = NULL, *n = NULL, *nextpkt = NULL;
3504 int mlen, noff, len;
3506 MGETHDR(top, M_NOWAIT, MT_DATA);
3510 top->m_pkthdr.len =
length;
3516 nextpkt = n->m_nextpkt;
3519 while (
length > 0 && n != NULL) {
3520 len =
min(mlen - m->m_len, n->m_len - noff);
3524 bcopy(mtod(n, caddr_t)+noff, mtod(m, caddr_t)+m->m_len, len);
3529 if (
length > 0 && m->m_len == mlen) {
3530 MGET(m->m_next, M_NOWAIT, MT_DATA);
3531 if (m->m_next == NULL) {
3541 if (noff == n->m_len) {
3548 nextpkt = (n != NULL)? n->m_nextpkt : NULL;
3553 panic(
"%s: length=%d\n", __func__,
length);
3554 if (
length > 0 && n == NULL)
3555 panic(
"%s: bogus length=%d, n=%p\n", __func__,
length, n);
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_MBUFQ_DRAIN(q)
#define NG_BT_MBUFQ_DEQUEUE(q, i)
#define NG_BT_MBUFQ_INIT(q, _maxlen)
#define NG_BT_MBUFQ_ENQUEUE(q, i)
#define NG_BTSOCKET_INFO_LEVEL
#define SO_RFCOMM_FC_INFO
#define BLUETOOTH_PROTO_L2CAP
#define NG_BTSOCKET_WARN_LEVEL
#define BLUETOOTH_PROTO_RFCOMM
static ng_btsocket_rfcomm_pcb_p ng_btsocket_rfcomm_pcb_listener(bdaddr_p src, int channel)
static void ng_btsocket_rfcomm_init(void *arg __unused)
static int ng_btsocket_rfcomm_receive_frame(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
#define NG_BTSOCKET_RFCOMM_WARN
static int ng_btsocket_rfcomm_receive_msc(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
#define M_NETGRAPH_BTSOCKET_RFCOMM
int ng_btsocket_rfcomm_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam, struct mbuf *control, struct thread *td)
static void ng_btsocket_rfcomm_session_task(ng_btsocket_rfcomm_session_p s)
static int ng_btsocket_rfcomm_check_fcs(u_int8_t *data, int type, u_int8_t fcs)
int ng_btsocket_rfcomm_ctloutput(struct socket *so, struct sockopt *sopt)
static int ng_btsocket_rfcomm_receive_sabm(ng_btsocket_rfcomm_session_p s, int dlci)
static void ng_btsocket_rfcomm_set_pn(ng_btsocket_rfcomm_pcb_p pcb, u_int8_t cr, u_int8_t flow_control, u_int8_t credits, u_int16_t mtu)
#define ng_btsocket_rfcomm_task_wakeup()
static int ng_btsocket_rfcomm_receive_uih(ng_btsocket_rfcomm_session_p s, int dlci, int pf, struct mbuf *m0)
static int ng_btsocket_rfcomm_receive_test(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
void ng_btsocket_rfcomm_close(struct socket *so)
static void ng_btsocket_rfcomm_timeout(ng_btsocket_rfcomm_pcb_p pcb)
SYSINIT(ng_btsocket_rfcomm_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, ng_btsocket_rfcomm_init, NULL)
#define NG_BTSOCKET_RFCOMM_INFO
static void ng_btsocket_rfcomm_pcb_kill(ng_btsocket_rfcomm_pcb_p pcb, int error)
static int ng_btsocket_rfcomm_upcall(struct socket *so, void *arg, int waitflag)
static void ng_btsocket_rfcomm_process_timeout(void *xpcb)
static int ng_btsocket_rfcomm_send_command(ng_btsocket_rfcomm_session_p s, u_int8_t type, u_int8_t dlci)
static ng_btsocket_rfcomm_session_p ng_btsocket_rfcomm_session_by_addr(bdaddr_p src, bdaddr_p dst)
static int ng_btsocket_rfcomm_session_accept(ng_btsocket_rfcomm_session_p s0)
int ng_btsocket_rfcomm_sockaddr(struct socket *so, struct sockaddr **nam)
static int ng_btsocket_rfcomm_session_create(ng_btsocket_rfcomm_session_p *sp, struct socket *l2so, bdaddr_p src, bdaddr_p dst, struct thread *td)
static u_int8_t ng_btsocket_rfcomm_fcs3(u_int8_t *data)
static struct mbuf * ng_btsocket_rfcomm_prepare_packet(struct sockbuf *sb, int length)
int ng_btsocket_rfcomm_disconnect(struct socket *so)
static LIST_HEAD(ng_btsocket_rfcomm_session)
int ng_btsocket_rfcomm_peeraddr(struct socket *so, struct sockaddr **nam)
struct task ng_btsocket_rfcomm_task
static int ng_btsocket_rfcomm_send_credits(ng_btsocket_rfcomm_pcb_p pcb)
static int ng_btsocket_rfcomm_receive_dm(ng_btsocket_rfcomm_session_p s, int dlci)
int ng_btsocket_rfcomm_accept(struct socket *so, struct sockaddr **nam)
static int ng_btsocket_rfcomm_receive_ua(ng_btsocket_rfcomm_session_p s, int dlci)
static int ng_btsocket_rfcomm_receive_fc(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
int ng_btsocket_rfcomm_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
static int ng_btsocket_rfcomm_receive_disc(ng_btsocket_rfcomm_session_p s, int dlci)
static int ng_btsocket_rfcomm_pcb_send(ng_btsocket_rfcomm_pcb_p pcb, int limit)
static int ng_btsocket_rfcomm_send_pn(ng_btsocket_rfcomm_pcb_p pcb)
static int ng_btsocket_rfcomm_receive_pn(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
static int ng_btsocket_rfcomm_session_send(ng_btsocket_rfcomm_session_p s)
static u_int8_t ng_btsocket_rfcomm_crc(u_int8_t *data, int length)
static int ng_btsocket_rfcomm_send_uih(ng_btsocket_rfcomm_session_p s, u_int8_t address, u_int8_t pf, u_int8_t credits, struct mbuf *data)
static void ng_btsocket_rfcomm_connect_cfm(ng_btsocket_rfcomm_session_p s)
static ng_btsocket_rfcomm_pcb_p ng_btsocket_rfcomm_connect_ind(ng_btsocket_rfcomm_session_p s, int channel)
static void ng_btsocket_rfcomm_untimeout(ng_btsocket_rfcomm_pcb_p pcb)
int ng_btsocket_rfcomm_listen(struct socket *so, int backlog, struct thread *td)
void ng_btsocket_rfcomm_detach(struct socket *so)
#define NG_BTSOCKET_RFCOMM_ERR
static int ng_btsocket_rfcomm_receive_rls(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
int ng_btsocket_rfcomm_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp, struct thread *td)
int ng_btsocket_rfcomm_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
static u_int8_t ng_btsocket_rfcomm_fcs2(u_int8_t *data)
static u_int32_t ng_btsocket_rfcomm_timo
static int ng_btsocket_rfcomm_session_connect(ng_btsocket_rfcomm_session_p s)
void ng_btsocket_rfcomm_abort(struct socket *so)
static ng_btsocket_rfcomm_pcb_p ng_btsocket_rfcomm_pcb_by_dlci(ng_btsocket_rfcomm_session_p s, int dlci)
int ng_btsocket_rfcomm_attach(struct socket *so, int proto, struct thread *td)
static int ng_btsocket_rfcomm_receive_mcc(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
static u_int32_t ng_btsocket_rfcomm_debug_level
static int ng_btsocket_rfcomm_send_msc(ng_btsocket_rfcomm_pcb_p pcb)
static void ng_btsocket_rfcomm_sessions_task(void *ctx, int pending)
static void ng_btsocket_rfcomm_session_clean(ng_btsocket_rfcomm_session_p s)
static void ng_btsocket_rfcomm_session_process_pcb(ng_btsocket_rfcomm_session_p s)
static int ng_btsocket_rfcomm_receive_rpn(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
#define NG_BTSOCKET_RFCOMM_ALERT
static int ng_btsocket_rfcomm_session_receive(ng_btsocket_rfcomm_session_p s)
#define NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING
#define RFCOMM_MKRPN_LINE_SETTINGS(data, stop, parity)
#define RFCOMM_MCC_TYPE(b)
#define RFCOMM_RPN_STOP_BITS(line)
#define NG_BTSOCKET_RFCOMM_SESSION_LISTENING
#define RFCOMM_RPN_DATA_8
#define NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT
#define NG_BTSOCKET_RFCOMM_SESSION_CONNECTING
#define RFCOMM_RPN_PARITY(line)
#define NG_BTSOCKET_RFCOMM_DLC_CLOSED
#define RFCOMM_RPN_XON_CHAR
#define RFCOMM_MAX_CREDITS
#define RFCOMM_FRAME_SABM
#define RFCOMM_RPN_DATA_BITS(line)
#define NG_BTSOCKET_RFCOMM_SESSION_OPEN
#define RFCOMM_RPN_STOP_1
#define RFCOMM_RPN_PARITY_NONE
#define RFCOMM_MKDLCI(dir, channel)
#define RFCOMM_RPN_PM_XON
#define RFCOMM_RPN_PM_STOP
#define RFCOMM_SRVCHANNEL(dlci)
#define NG_BTSOCKET_RFCOMM_RECVSPACE
#define NG_BTSOCKET_RFCOMM_SESSION_LFC
#define RFCOMM_FRAME_DISC
#define RFCOMM_RPN_BR_115200
#define NG_BTSOCKET_RFCOMM_DLC_CONNECTED
#define NG_BTSOCKET_RFCOMM_SESSION_INITIATOR
#define NG_BTSOCKET_RFCOMM_DLC_CONNECTING
#define NG_BTSOCKET_RFCOMM_DLC_SENDING
#define RFCOMM_RPN_PM_FLOW
struct ng_btsocket_rfcomm_pcb * ng_btsocket_rfcomm_pcb_p
#define NG_BTSOCKET_RFCOMM_DLC_CONFIGURING
#define RFCOMM_RPN_XOFF_CHAR
#define RFCOMM_RPN_PM_XOFF
#define so2rfcomm_pcb(so)
#define RFCOMM_MKLEN8(len)
#define RFCOMM_MKLEN16(len)
#define NG_BTSOCKET_RFCOMM_DLC_DETACHED
#define NG_BTSOCKET_RFCOMM_DLC_TIMO
#define RFCOMM_MKMCC_TYPE(cr, type)
#define RFCOMM_MKADDRESS(cr, dlci)
#define NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING
#define RFCOMM_MCC_LENGTH(b)
#define NG_BTSOCKET_RFCOMM_SESSION_CONNECTED
#define NG_BTSOCKET_RFCOMM_DLC_CFC
#define NG_BTSOCKET_RFCOMM_SESSION_CLOSED
#define RFCOMM_RPN_PM_DATA
#define NG_BTSOCKET_RFCOMM_SESSION_RFC
#define NG_BTSOCKET_RFCOMM_SENDSPACE
#define RFCOMM_DEFAULT_MTU
#define RFCOMM_RPN_FLOW_NONE
#define RFCOMM_RPN_PM_ALL
#define RFCOMM_MKCONTROL(type, pf)
#define NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT
#define RFCOMM_DEFAULT_CREDITS
#define RFCOMM_RPN_PM_PARITY
MALLOC_DEFINE(M_NG_CCATM, "ng_ccatm", "netgraph uni api node")
#define NG_HCI_BDADDR_ANY
#define NG_L2CAP_PSM_RFCOMM
struct ng_btsocket_rfcomm_session * session
u_int8_t l2cap_bdaddr_type