1 /* 2 * ng_btsocket_rfcomm.c 3 */ 4 5 /*- 6 * Copyright (c) 2001-2003 Maksim Yevmenkin <m_evmenkin@yahoo.com> 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 * 30 * $Id: ng_btsocket_rfcomm.c,v 1.28 2003/09/14 23:29:06 max Exp $ 31 * $FreeBSD$ 32 */ 33 34 #include <sys/param.h> 35 #include <sys/systm.h> 36 #include <sys/bitstring.h> 37 #include <sys/domain.h> 38 #include <sys/endian.h> 39 #include <sys/errno.h> 40 #include <sys/filedesc.h> 41 #include <sys/ioccom.h> 42 #include <sys/kernel.h> 43 #include <sys/lock.h> 44 #include <sys/malloc.h> 45 #include <sys/mbuf.h> 46 #include <sys/mutex.h> 47 #include <sys/proc.h> 48 #include <sys/protosw.h> 49 #include <sys/queue.h> 50 #include <sys/socket.h> 51 #include <sys/socketvar.h> 52 #include <sys/sysctl.h> 53 #include <sys/taskqueue.h> 54 #include <sys/uio.h> 55 #include <netgraph/ng_message.h> 56 #include <netgraph/netgraph.h> 57 #include <netgraph/bluetooth/include/ng_bluetooth.h> 58 #include <netgraph/bluetooth/include/ng_hci.h> 59 #include <netgraph/bluetooth/include/ng_l2cap.h> 60 #include <netgraph/bluetooth/include/ng_btsocket.h> 61 #include <netgraph/bluetooth/include/ng_btsocket_l2cap.h> 62 #include <netgraph/bluetooth/include/ng_btsocket_rfcomm.h> 63 64 /* MALLOC define */ 65 #ifdef NG_SEPARATE_MALLOC 66 MALLOC_DEFINE(M_NETGRAPH_BTSOCKET_RFCOMM, "netgraph_btsocks_rfcomm", 67 "Netgraph Bluetooth RFCOMM sockets"); 68 #else 69 #define M_NETGRAPH_BTSOCKET_RFCOMM M_NETGRAPH 70 #endif /* NG_SEPARATE_MALLOC */ 71 72 /* Debug */ 73 #define NG_BTSOCKET_RFCOMM_INFO \ 74 if (ng_btsocket_rfcomm_debug_level >= NG_BTSOCKET_INFO_LEVEL) \ 75 printf 76 77 #define NG_BTSOCKET_RFCOMM_WARN \ 78 if (ng_btsocket_rfcomm_debug_level >= NG_BTSOCKET_WARN_LEVEL) \ 79 printf 80 81 #define NG_BTSOCKET_RFCOMM_ERR \ 82 if (ng_btsocket_rfcomm_debug_level >= NG_BTSOCKET_ERR_LEVEL) \ 83 printf 84 85 #define NG_BTSOCKET_RFCOMM_ALERT \ 86 if (ng_btsocket_rfcomm_debug_level >= NG_BTSOCKET_ALERT_LEVEL) \ 87 printf 88 89 #define ALOT 0x7fff 90 91 /* Local prototypes */ 92 static void ng_btsocket_rfcomm_upcall 93 (struct socket *so, void *arg, int waitflag); 94 static void ng_btsocket_rfcomm_sessions_task 95 (void *ctx, int pending); 96 static void ng_btsocket_rfcomm_session_task 97 (ng_btsocket_rfcomm_session_p s); 98 #define ng_btsocket_rfcomm_task_wakeup() \ 99 taskqueue_enqueue(taskqueue_swi_giant, &ng_btsocket_rfcomm_task) 100 101 static ng_btsocket_rfcomm_pcb_p ng_btsocket_rfcomm_connect_ind 102 (ng_btsocket_rfcomm_session_p s, int channel); 103 static void ng_btsocket_rfcomm_connect_cfm 104 (ng_btsocket_rfcomm_session_p s); 105 106 static int ng_btsocket_rfcomm_session_create 107 (ng_btsocket_rfcomm_session_p *sp, struct socket *l2so, 108 bdaddr_p src, bdaddr_p dst, struct thread *td); 109 static int ng_btsocket_rfcomm_session_accept 110 (ng_btsocket_rfcomm_session_p s0); 111 static int ng_btsocket_rfcomm_session_connect 112 (ng_btsocket_rfcomm_session_p s); 113 static int ng_btsocket_rfcomm_session_receive 114 (ng_btsocket_rfcomm_session_p s); 115 static int ng_btsocket_rfcomm_session_send 116 (ng_btsocket_rfcomm_session_p s); 117 static void ng_btsocket_rfcomm_session_clean 118 (ng_btsocket_rfcomm_session_p s); 119 static void ng_btsocket_rfcomm_session_process_pcb 120 (ng_btsocket_rfcomm_session_p s); 121 static ng_btsocket_rfcomm_session_p ng_btsocket_rfcomm_session_by_addr 122 (bdaddr_p src, bdaddr_p dst); 123 124 static int ng_btsocket_rfcomm_receive_frame 125 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0); 126 static int ng_btsocket_rfcomm_receive_sabm 127 (ng_btsocket_rfcomm_session_p s, int dlci); 128 static int ng_btsocket_rfcomm_receive_disc 129 (ng_btsocket_rfcomm_session_p s, int dlci); 130 static int ng_btsocket_rfcomm_receive_ua 131 (ng_btsocket_rfcomm_session_p s, int dlci); 132 static int ng_btsocket_rfcomm_receive_dm 133 (ng_btsocket_rfcomm_session_p s, int dlci); 134 static int ng_btsocket_rfcomm_receive_uih 135 (ng_btsocket_rfcomm_session_p s, int dlci, int pf, struct mbuf *m0); 136 static int ng_btsocket_rfcomm_receive_mcc 137 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0); 138 static int ng_btsocket_rfcomm_receive_test 139 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0); 140 static int ng_btsocket_rfcomm_receive_fc 141 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0); 142 static int ng_btsocket_rfcomm_receive_msc 143 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0); 144 static int ng_btsocket_rfcomm_receive_rpn 145 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0); 146 static int ng_btsocket_rfcomm_receive_rls 147 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0); 148 static int ng_btsocket_rfcomm_receive_pn 149 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0); 150 static void ng_btsocket_rfcomm_set_pn 151 (ng_btsocket_rfcomm_pcb_p pcb, u_int8_t cr, u_int8_t flow_control, 152 u_int8_t credits, u_int16_t mtu); 153 154 static int ng_btsocket_rfcomm_send_command 155 (ng_btsocket_rfcomm_session_p s, u_int8_t type, u_int8_t dlci); 156 static int ng_btsocket_rfcomm_send_uih 157 (ng_btsocket_rfcomm_session_p s, u_int8_t address, u_int8_t pf, 158 u_int8_t credits, struct mbuf *data); 159 static int ng_btsocket_rfcomm_send_msc 160 (ng_btsocket_rfcomm_pcb_p pcb); 161 static int ng_btsocket_rfcomm_send_pn 162 (ng_btsocket_rfcomm_pcb_p pcb); 163 static int ng_btsocket_rfcomm_send_credits 164 (ng_btsocket_rfcomm_pcb_p pcb); 165 166 static int ng_btsocket_rfcomm_pcb_send 167 (ng_btsocket_rfcomm_pcb_p pcb, int limit); 168 static void ng_btsocket_rfcomm_pcb_kill 169 (ng_btsocket_rfcomm_pcb_p pcb, int error); 170 static ng_btsocket_rfcomm_pcb_p ng_btsocket_rfcomm_pcb_by_channel 171 (bdaddr_p src, int channel); 172 static ng_btsocket_rfcomm_pcb_p ng_btsocket_rfcomm_pcb_by_dlci 173 (ng_btsocket_rfcomm_session_p s, int dlci); 174 static ng_btsocket_rfcomm_pcb_p ng_btsocket_rfcomm_pcb_listener 175 (bdaddr_p src, int channel); 176 177 static void ng_btsocket_rfcomm_timeout 178 (ng_btsocket_rfcomm_pcb_p pcb); 179 static void ng_btsocket_rfcomm_untimeout 180 (ng_btsocket_rfcomm_pcb_p pcb); 181 static void ng_btsocket_rfcomm_process_timeout 182 (void *xpcb); 183 184 static struct mbuf * ng_btsocket_rfcomm_prepare_packet 185 (struct sockbuf *sb, int length); 186 187 /* Globals */ 188 extern int ifqmaxlen; 189 static u_int32_t ng_btsocket_rfcomm_debug_level; 190 static u_int32_t ng_btsocket_rfcomm_timo; 191 struct task ng_btsocket_rfcomm_task; 192 static LIST_HEAD(, ng_btsocket_rfcomm_session) ng_btsocket_rfcomm_sessions; 193 static struct mtx ng_btsocket_rfcomm_sessions_mtx; 194 static LIST_HEAD(, ng_btsocket_rfcomm_pcb) ng_btsocket_rfcomm_sockets; 195 static struct mtx ng_btsocket_rfcomm_sockets_mtx; 196 197 /* Sysctl tree */ 198 SYSCTL_DECL(_net_bluetooth_rfcomm_sockets); 199 SYSCTL_NODE(_net_bluetooth_rfcomm_sockets, OID_AUTO, stream, CTLFLAG_RW, 200 0, "Bluetooth STREAM RFCOMM sockets family"); 201 SYSCTL_INT(_net_bluetooth_rfcomm_sockets_stream, OID_AUTO, debug_level, 202 CTLFLAG_RW, 203 &ng_btsocket_rfcomm_debug_level, NG_BTSOCKET_INFO_LEVEL, 204 "Bluetooth STREAM RFCOMM sockets debug level"); 205 SYSCTL_INT(_net_bluetooth_rfcomm_sockets_stream, OID_AUTO, timeout, 206 CTLFLAG_RW, 207 &ng_btsocket_rfcomm_timo, 60, 208 "Bluetooth STREAM RFCOMM sockets timeout"); 209 210 /***************************************************************************** 211 ***************************************************************************** 212 ** RFCOMM CRC 213 ***************************************************************************** 214 *****************************************************************************/ 215 216 static u_int8_t ng_btsocket_rfcomm_crc_table[256] = { 217 0x00, 0x91, 0xe3, 0x72, 0x07, 0x96, 0xe4, 0x75, 218 0x0e, 0x9f, 0xed, 0x7c, 0x09, 0x98, 0xea, 0x7b, 219 0x1c, 0x8d, 0xff, 0x6e, 0x1b, 0x8a, 0xf8, 0x69, 220 0x12, 0x83, 0xf1, 0x60, 0x15, 0x84, 0xf6, 0x67, 221 222 0x38, 0xa9, 0xdb, 0x4a, 0x3f, 0xae, 0xdc, 0x4d, 223 0x36, 0xa7, 0xd5, 0x44, 0x31, 0xa0, 0xd2, 0x43, 224 0x24, 0xb5, 0xc7, 0x56, 0x23, 0xb2, 0xc0, 0x51, 225 0x2a, 0xbb, 0xc9, 0x58, 0x2d, 0xbc, 0xce, 0x5f, 226 227 0x70, 0xe1, 0x93, 0x02, 0x77, 0xe6, 0x94, 0x05, 228 0x7e, 0xef, 0x9d, 0x0c, 0x79, 0xe8, 0x9a, 0x0b, 229 0x6c, 0xfd, 0x8f, 0x1e, 0x6b, 0xfa, 0x88, 0x19, 230 0x62, 0xf3, 0x81, 0x10, 0x65, 0xf4, 0x86, 0x17, 231 232 0x48, 0xd9, 0xab, 0x3a, 0x4f, 0xde, 0xac, 0x3d, 233 0x46, 0xd7, 0xa5, 0x34, 0x41, 0xd0, 0xa2, 0x33, 234 0x54, 0xc5, 0xb7, 0x26, 0x53, 0xc2, 0xb0, 0x21, 235 0x5a, 0xcb, 0xb9, 0x28, 0x5d, 0xcc, 0xbe, 0x2f, 236 237 0xe0, 0x71, 0x03, 0x92, 0xe7, 0x76, 0x04, 0x95, 238 0xee, 0x7f, 0x0d, 0x9c, 0xe9, 0x78, 0x0a, 0x9b, 239 0xfc, 0x6d, 0x1f, 0x8e, 0xfb, 0x6a, 0x18, 0x89, 240 0xf2, 0x63, 0x11, 0x80, 0xf5, 0x64, 0x16, 0x87, 241 242 0xd8, 0x49, 0x3b, 0xaa, 0xdf, 0x4e, 0x3c, 0xad, 243 0xd6, 0x47, 0x35, 0xa4, 0xd1, 0x40, 0x32, 0xa3, 244 0xc4, 0x55, 0x27, 0xb6, 0xc3, 0x52, 0x20, 0xb1, 245 0xca, 0x5b, 0x29, 0xb8, 0xcd, 0x5c, 0x2e, 0xbf, 246 247 0x90, 0x01, 0x73, 0xe2, 0x97, 0x06, 0x74, 0xe5, 248 0x9e, 0x0f, 0x7d, 0xec, 0x99, 0x08, 0x7a, 0xeb, 249 0x8c, 0x1d, 0x6f, 0xfe, 0x8b, 0x1a, 0x68, 0xf9, 250 0x82, 0x13, 0x61, 0xf0, 0x85, 0x14, 0x66, 0xf7, 251 252 0xa8, 0x39, 0x4b, 0xda, 0xaf, 0x3e, 0x4c, 0xdd, 253 0xa6, 0x37, 0x45, 0xd4, 0xa1, 0x30, 0x42, 0xd3, 254 0xb4, 0x25, 0x57, 0xc6, 0xb3, 0x22, 0x50, 0xc1, 255 0xba, 0x2b, 0x59, 0xc8, 0xbd, 0x2c, 0x5e, 0xcf 256 }; 257 258 /* CRC */ 259 static u_int8_t 260 ng_btsocket_rfcomm_crc(u_int8_t *data, int length) 261 { 262 u_int8_t crc = 0xff; 263 264 while (length --) 265 crc = ng_btsocket_rfcomm_crc_table[crc ^ *data++]; 266 267 return (crc); 268 } /* ng_btsocket_rfcomm_crc */ 269 270 /* FCS on 2 bytes */ 271 static u_int8_t 272 ng_btsocket_rfcomm_fcs2(u_int8_t *data) 273 { 274 return (0xff - ng_btsocket_rfcomm_crc(data, 2)); 275 } /* ng_btsocket_rfcomm_fcs2 */ 276 277 /* FCS on 3 bytes */ 278 static u_int8_t 279 ng_btsocket_rfcomm_fcs3(u_int8_t *data) 280 { 281 return (0xff - ng_btsocket_rfcomm_crc(data, 3)); 282 } /* ng_btsocket_rfcomm_fcs3 */ 283 284 /* 285 * Check FCS 286 * 287 * From Bluetooth spec 288 * 289 * "... In 07.10, the frame check sequence (FCS) is calculated on different 290 * sets of fields for different frame types. These are the fields that the 291 * FCS are calculated on: 292 * 293 * For SABM, DISC, UA, DM frames: on Address, Control and length field. 294 * For UIH frames: on Address and Control field. 295 * 296 * (This is stated here for clarification, and to set the standard for RFCOMM; 297 * the fields included in FCS calculation have actually changed in version 298 * 7.0.0 of TS 07.10, but RFCOMM will not change the FCS calculation scheme 299 * from the one above.) ..." 300 */ 301 302 static int 303 ng_btsocket_rfcomm_check_fcs(u_int8_t *data, int type, u_int8_t fcs) 304 { 305 if (type != RFCOMM_FRAME_UIH) 306 return (ng_btsocket_rfcomm_fcs3(data) != fcs); 307 308 return (ng_btsocket_rfcomm_fcs2(data) != fcs); 309 } /* ng_btsocket_rfcomm_check_fcs */ 310 311 /***************************************************************************** 312 ***************************************************************************** 313 ** Socket interface 314 ***************************************************************************** 315 *****************************************************************************/ 316 317 /* 318 * Initialize everything 319 */ 320 321 void 322 ng_btsocket_rfcomm_init(void) 323 { 324 ng_btsocket_rfcomm_debug_level = NG_BTSOCKET_WARN_LEVEL; 325 ng_btsocket_rfcomm_timo = 60; 326 327 /* RFCOMM task */ 328 TASK_INIT(&ng_btsocket_rfcomm_task, 0, 329 ng_btsocket_rfcomm_sessions_task, NULL); 330 331 /* RFCOMM sessions list */ 332 LIST_INIT(&ng_btsocket_rfcomm_sessions); 333 mtx_init(&ng_btsocket_rfcomm_sessions_mtx, 334 "btsocks_rfcomm_sessions_mtx", NULL, MTX_DEF); 335 336 /* RFCOMM sockets list */ 337 LIST_INIT(&ng_btsocket_rfcomm_sockets); 338 mtx_init(&ng_btsocket_rfcomm_sockets_mtx, 339 "btsocks_rfcomm_sockets_mtx", NULL, MTX_DEF); 340 } /* ng_btsocket_rfcomm_init */ 341 342 /* 343 * Abort connection on socket 344 */ 345 346 void 347 ng_btsocket_rfcomm_abort(struct socket *so) 348 { 349 350 so->so_error = ECONNABORTED; 351 (void)ng_btsocket_rfcomm_disconnect(so); 352 } /* ng_btsocket_rfcomm_abort */ 353 354 void 355 ng_btsocket_rfcomm_close(struct socket *so) 356 { 357 358 (void)ng_btsocket_rfcomm_disconnect(so); 359 } /* ng_btsocket_rfcomm_close */ 360 361 /* 362 * Accept connection on socket. Nothing to do here, socket must be connected 363 * and ready, so just return peer address and be done with it. 364 */ 365 366 int 367 ng_btsocket_rfcomm_accept(struct socket *so, struct sockaddr **nam) 368 { 369 return (ng_btsocket_rfcomm_peeraddr(so, nam)); 370 } /* ng_btsocket_rfcomm_accept */ 371 372 /* 373 * Create and attach new socket 374 */ 375 376 int 377 ng_btsocket_rfcomm_attach(struct socket *so, int proto, struct thread *td) 378 { 379 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so); 380 int error; 381 382 /* Check socket and protocol */ 383 if (so->so_type != SOCK_STREAM) 384 return (ESOCKTNOSUPPORT); 385 386 #if 0 /* XXX sonewconn() calls "pru_attach" with proto == 0 */ 387 if (proto != 0) 388 if (proto != BLUETOOTH_PROTO_RFCOMM) 389 return (EPROTONOSUPPORT); 390 #endif /* XXX */ 391 392 if (pcb != NULL) 393 return (EISCONN); 394 395 /* Reserve send and receive space if it is not reserved yet */ 396 if ((so->so_snd.sb_hiwat == 0) || (so->so_rcv.sb_hiwat == 0)) { 397 error = soreserve(so, NG_BTSOCKET_RFCOMM_SENDSPACE, 398 NG_BTSOCKET_RFCOMM_RECVSPACE); 399 if (error != 0) 400 return (error); 401 } 402 403 /* Allocate the PCB */ 404 MALLOC(pcb, ng_btsocket_rfcomm_pcb_p, sizeof(*pcb), 405 M_NETGRAPH_BTSOCKET_RFCOMM, M_NOWAIT | M_ZERO); 406 if (pcb == NULL) 407 return (ENOMEM); 408 409 /* Link the PCB and the socket */ 410 so->so_pcb = (caddr_t) pcb; 411 pcb->so = so; 412 413 /* Initialize PCB */ 414 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CLOSED; 415 pcb->flags = NG_BTSOCKET_RFCOMM_DLC_CFC; 416 417 pcb->lmodem = 418 pcb->rmodem = (RFCOMM_MODEM_RTC | RFCOMM_MODEM_RTR | RFCOMM_MODEM_DV); 419 420 pcb->mtu = RFCOMM_DEFAULT_MTU; 421 pcb->tx_cred = 0; 422 pcb->rx_cred = RFCOMM_DEFAULT_CREDITS; 423 424 mtx_init(&pcb->pcb_mtx, "btsocks_rfcomm_pcb_mtx", NULL, MTX_DEF); 425 callout_handle_init(&pcb->timo); 426 427 /* Add the PCB to the list */ 428 mtx_lock(&ng_btsocket_rfcomm_sockets_mtx); 429 LIST_INSERT_HEAD(&ng_btsocket_rfcomm_sockets, pcb, next); 430 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx); 431 432 return (0); 433 } /* ng_btsocket_rfcomm_attach */ 434 435 /* 436 * Bind socket 437 */ 438 439 int 440 ng_btsocket_rfcomm_bind(struct socket *so, struct sockaddr *nam, 441 struct thread *td) 442 { 443 ng_btsocket_rfcomm_pcb_t *pcb = so2rfcomm_pcb(so); 444 struct sockaddr_rfcomm *sa = (struct sockaddr_rfcomm *) nam; 445 446 if (pcb == NULL) 447 return (EINVAL); 448 449 /* Verify address */ 450 if (sa == NULL) 451 return (EINVAL); 452 if (sa->rfcomm_family != AF_BLUETOOTH) 453 return (EAFNOSUPPORT); 454 if (sa->rfcomm_len != sizeof(*sa)) 455 return (EINVAL); 456 if (sa->rfcomm_channel > 30) 457 return (EINVAL); 458 if (sa->rfcomm_channel != 0 && 459 ng_btsocket_rfcomm_pcb_by_channel(&sa->rfcomm_bdaddr, sa->rfcomm_channel) != NULL) 460 return (EADDRINUSE); 461 462 bcopy(&sa->rfcomm_bdaddr, &pcb->src, sizeof(pcb->src)); 463 pcb->channel = sa->rfcomm_channel; 464 465 return (0); 466 } /* ng_btsocket_rfcomm_bind */ 467 468 /* 469 * Connect socket 470 */ 471 472 int 473 ng_btsocket_rfcomm_connect(struct socket *so, struct sockaddr *nam, 474 struct thread *td) 475 { 476 ng_btsocket_rfcomm_pcb_t *pcb = so2rfcomm_pcb(so); 477 struct sockaddr_rfcomm *sa = (struct sockaddr_rfcomm *) nam; 478 ng_btsocket_rfcomm_session_t *s = NULL; 479 struct socket *l2so = NULL; 480 int dlci, error = 0; 481 482 if (pcb == NULL) 483 return (EINVAL); 484 485 /* Verify address */ 486 if (sa == NULL) 487 return (EINVAL); 488 if (sa->rfcomm_family != AF_BLUETOOTH) 489 return (EAFNOSUPPORT); 490 if (sa->rfcomm_len != sizeof(*sa)) 491 return (EINVAL); 492 if (sa->rfcomm_channel > 30) 493 return (EINVAL); 494 if (sa->rfcomm_channel == 0 || 495 bcmp(&sa->rfcomm_bdaddr, NG_HCI_BDADDR_ANY, sizeof(bdaddr_t)) == 0) 496 return (EDESTADDRREQ); 497 498 /* 499 * XXX FIXME - This is FUBAR. socreate() will call soalloc(1), i.e. 500 * soalloc() is allowed to sleep in MALLOC. This creates "could sleep" 501 * WITNESS warnings. To work around this problem we will create L2CAP 502 * socket first and then check if we actually need it. Note that we 503 * will not check for errors in socreate() because if we failed to 504 * create L2CAP socket at this point we still might have already open 505 * session. 506 */ 507 508 error = socreate(PF_BLUETOOTH, &l2so, SOCK_SEQPACKET, 509 BLUETOOTH_PROTO_L2CAP, td->td_ucred, td); 510 511 /* 512 * Look for session between "pcb->src" and "sa->rfcomm_bdaddr" (dst) 513 */ 514 515 mtx_lock(&ng_btsocket_rfcomm_sessions_mtx); 516 517 s = ng_btsocket_rfcomm_session_by_addr(&pcb->src, &sa->rfcomm_bdaddr); 518 if (s == NULL) { 519 /* 520 * We need to create new RFCOMM session. Check if we have L2CAP 521 * socket. If l2so == NULL then error has the error code from 522 * socreate() 523 */ 524 525 if (l2so == NULL) { 526 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx); 527 return (error); 528 } 529 530 error = ng_btsocket_rfcomm_session_create(&s, l2so, 531 &pcb->src, &sa->rfcomm_bdaddr, td); 532 if (error != 0) { 533 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx); 534 soclose(l2so); 535 536 return (error); 537 } 538 } else if (l2so != NULL) 539 soclose(l2so); /* we don't need new L2CAP socket */ 540 541 /* 542 * Check if we already have the same DLCI the the same session 543 */ 544 545 mtx_lock(&s->session_mtx); 546 mtx_lock(&pcb->pcb_mtx); 547 548 dlci = RFCOMM_MKDLCI(!INITIATOR(s), sa->rfcomm_channel); 549 550 if (ng_btsocket_rfcomm_pcb_by_dlci(s, dlci) != NULL) { 551 mtx_unlock(&pcb->pcb_mtx); 552 mtx_unlock(&s->session_mtx); 553 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx); 554 555 return (EBUSY); 556 } 557 558 /* 559 * Check session state and if its not acceptable then refuse connection 560 */ 561 562 switch (s->state) { 563 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTING: 564 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED: 565 case NG_BTSOCKET_RFCOMM_SESSION_OPEN: 566 /* 567 * Update destination address and channel and attach 568 * DLC to the session 569 */ 570 571 bcopy(&sa->rfcomm_bdaddr, &pcb->dst, sizeof(pcb->dst)); 572 pcb->channel = sa->rfcomm_channel; 573 pcb->dlci = dlci; 574 575 LIST_INSERT_HEAD(&s->dlcs, pcb, session_next); 576 pcb->session = s; 577 578 ng_btsocket_rfcomm_timeout(pcb); 579 soisconnecting(pcb->so); 580 581 if (s->state == NG_BTSOCKET_RFCOMM_SESSION_OPEN) { 582 pcb->mtu = s->mtu; 583 bcopy(&so2l2cap_pcb(s->l2so)->src, &pcb->src, 584 sizeof(pcb->src)); 585 586 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONFIGURING; 587 588 error = ng_btsocket_rfcomm_send_pn(pcb); 589 if (error == 0) 590 error = ng_btsocket_rfcomm_task_wakeup(); 591 } else 592 pcb->state = NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT; 593 break; 594 595 default: 596 error = ECONNRESET; 597 break; 598 } 599 600 mtx_unlock(&pcb->pcb_mtx); 601 mtx_unlock(&s->session_mtx); 602 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx); 603 604 return (error); 605 } /* ng_btsocket_rfcomm_connect */ 606 607 /* 608 * Process ioctl's calls on socket. 609 * XXX FIXME this should provide interface to the RFCOMM multiplexor channel 610 */ 611 612 int 613 ng_btsocket_rfcomm_control(struct socket *so, u_long cmd, caddr_t data, 614 struct ifnet *ifp, struct thread *td) 615 { 616 return (EINVAL); 617 } /* ng_btsocket_rfcomm_control */ 618 619 /* 620 * Process getsockopt/setsockopt system calls 621 */ 622 623 int 624 ng_btsocket_rfcomm_ctloutput(struct socket *so, struct sockopt *sopt) 625 { 626 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so); 627 struct ng_btsocket_rfcomm_fc_info fcinfo; 628 int error = 0; 629 630 if (pcb == NULL) 631 return (EINVAL); 632 if (sopt->sopt_level != SOL_RFCOMM) 633 return (0); 634 635 mtx_lock(&pcb->pcb_mtx); 636 637 switch (sopt->sopt_dir) { 638 case SOPT_GET: 639 switch (sopt->sopt_name) { 640 case SO_RFCOMM_MTU: 641 error = sooptcopyout(sopt, &pcb->mtu, sizeof(pcb->mtu)); 642 break; 643 644 case SO_RFCOMM_FC_INFO: 645 fcinfo.lmodem = pcb->lmodem; 646 fcinfo.rmodem = pcb->rmodem; 647 fcinfo.tx_cred = pcb->tx_cred; 648 fcinfo.rx_cred = pcb->rx_cred; 649 fcinfo.cfc = (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC)? 650 1 : 0; 651 fcinfo.reserved = 0; 652 653 error = sooptcopyout(sopt, &fcinfo, sizeof(fcinfo)); 654 break; 655 656 default: 657 error = ENOPROTOOPT; 658 break; 659 } 660 break; 661 662 case SOPT_SET: 663 switch (sopt->sopt_name) { 664 default: 665 error = ENOPROTOOPT; 666 break; 667 } 668 break; 669 670 default: 671 error = EINVAL; 672 break; 673 } 674 675 mtx_unlock(&pcb->pcb_mtx); 676 677 return (error); 678 } /* ng_btsocket_rfcomm_ctloutput */ 679 680 /* 681 * Detach and destroy socket 682 */ 683 684 void 685 ng_btsocket_rfcomm_detach(struct socket *so) 686 { 687 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so); 688 689 KASSERT(pcb != NULL, ("ng_btsocket_rfcomm_detach: pcb == NULL")); 690 691 mtx_lock(&pcb->pcb_mtx); 692 693 switch (pcb->state) { 694 case NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT: 695 case NG_BTSOCKET_RFCOMM_DLC_CONFIGURING: 696 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING: 697 case NG_BTSOCKET_RFCOMM_DLC_CONNECTED: 698 /* XXX What to do with pending request? */ 699 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO) 700 ng_btsocket_rfcomm_untimeout(pcb); 701 702 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT) 703 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_DETACHED; 704 else 705 pcb->state = NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING; 706 707 ng_btsocket_rfcomm_task_wakeup(); 708 break; 709 710 case NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING: 711 ng_btsocket_rfcomm_task_wakeup(); 712 break; 713 } 714 715 while (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CLOSED) 716 msleep(&pcb->state, &pcb->pcb_mtx, PZERO, "rf_det", 0); 717 718 if (pcb->session != NULL) 719 panic("%s: pcb->session != NULL\n", __func__); 720 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO) 721 panic("%s: timeout on closed DLC, flags=%#x\n", 722 __func__, pcb->flags); 723 724 mtx_lock(&ng_btsocket_rfcomm_sockets_mtx); 725 LIST_REMOVE(pcb, next); 726 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx); 727 728 mtx_unlock(&pcb->pcb_mtx); 729 730 mtx_destroy(&pcb->pcb_mtx); 731 bzero(pcb, sizeof(*pcb)); 732 FREE(pcb, M_NETGRAPH_BTSOCKET_RFCOMM); 733 734 soisdisconnected(so); 735 so->so_pcb = NULL; 736 } /* ng_btsocket_rfcomm_detach */ 737 738 /* 739 * Disconnect socket 740 */ 741 742 int 743 ng_btsocket_rfcomm_disconnect(struct socket *so) 744 { 745 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so); 746 747 if (pcb == NULL) 748 return (EINVAL); 749 750 mtx_lock(&pcb->pcb_mtx); 751 752 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING) { 753 mtx_unlock(&pcb->pcb_mtx); 754 return (EINPROGRESS); 755 } 756 757 /* XXX What to do with pending request? */ 758 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO) 759 ng_btsocket_rfcomm_untimeout(pcb); 760 761 switch (pcb->state) { 762 case NG_BTSOCKET_RFCOMM_DLC_CONFIGURING: /* XXX can we get here? */ 763 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING: /* XXX can we get here? */ 764 case NG_BTSOCKET_RFCOMM_DLC_CONNECTED: 765 766 /* 767 * Just change DLC state and enqueue RFCOMM task. It will 768 * queue and send DISC on the DLC. 769 */ 770 771 pcb->state = NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING; 772 soisdisconnecting(so); 773 774 ng_btsocket_rfcomm_task_wakeup(); 775 break; 776 777 case NG_BTSOCKET_RFCOMM_DLC_CLOSED: 778 case NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT: 779 break; 780 781 default: 782 panic("%s: Invalid DLC state=%d, flags=%#x\n", 783 __func__, pcb->state, pcb->flags); 784 break; 785 } 786 787 mtx_unlock(&pcb->pcb_mtx); 788 789 return (0); 790 } /* ng_btsocket_rfcomm_disconnect */ 791 792 /* 793 * Listen on socket. First call to listen() will create listening RFCOMM session 794 */ 795 796 int 797 ng_btsocket_rfcomm_listen(struct socket *so, int backlog, struct thread *td) 798 { 799 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so); 800 ng_btsocket_rfcomm_session_p s = NULL; 801 struct socket *l2so = NULL; 802 int error; 803 int socreate_error; 804 805 if (pcb == NULL) 806 return (EINVAL); 807 if (pcb->channel < 1 || pcb->channel > 30) 808 return (EDESTADDRREQ); 809 810 /* 811 * XXX FIXME - This is FUBAR. socreate() will call soalloc(1), i.e. 812 * soalloc() is allowed to sleep in MALLOC. This creates "could sleep" 813 * WITNESS warnings. To work around this problem we will create L2CAP 814 * socket first and then check if we actually need it. Note that we 815 * will not check for errors in socreate() because if we failed to 816 * create L2CAP socket at this point we still might have already open 817 * session. 818 */ 819 820 socreate_error = socreate(PF_BLUETOOTH, &l2so, SOCK_SEQPACKET, 821 BLUETOOTH_PROTO_L2CAP, td->td_ucred, td); 822 823 /* 824 * Transition the socket and session into the LISTENING state. Check 825 * for collisions first, as there can only be one. 826 */ 827 mtx_lock(&ng_btsocket_rfcomm_sessions_mtx); 828 SOCK_LOCK(so); 829 error = solisten_proto_check(so); 830 SOCK_UNLOCK(so); 831 if (error != 0) 832 goto out; 833 834 LIST_FOREACH(s, &ng_btsocket_rfcomm_sessions, next) 835 if (s->state == NG_BTSOCKET_RFCOMM_SESSION_LISTENING) 836 break; 837 838 if (s == NULL) { 839 /* 840 * We need to create default RFCOMM session. Check if we have 841 * L2CAP socket. If l2so == NULL then error has the error code 842 * from socreate() 843 */ 844 if (l2so == NULL) { 845 error = socreate_error; 846 goto out; 847 } 848 849 /* 850 * Create default listen RFCOMM session. The default RFCOMM 851 * session will listen on ANY address. 852 * 853 * XXX FIXME Note that currently there is no way to adjust MTU 854 * for the default session. 855 */ 856 error = ng_btsocket_rfcomm_session_create(&s, l2so, 857 NG_HCI_BDADDR_ANY, NULL, td); 858 if (error != 0) 859 goto out; 860 l2so = NULL; 861 } 862 SOCK_LOCK(so); 863 solisten_proto(so, backlog); 864 SOCK_UNLOCK(so); 865 out: 866 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx); 867 /* 868 * If we still have an l2so reference here, it's unneeded, so release 869 * it. 870 */ 871 if (l2so != NULL) 872 soclose(l2so); 873 return (error); 874 } /* ng_btsocket_listen */ 875 876 /* 877 * Get peer address 878 */ 879 880 int 881 ng_btsocket_rfcomm_peeraddr(struct socket *so, struct sockaddr **nam) 882 { 883 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so); 884 struct sockaddr_rfcomm sa; 885 886 if (pcb == NULL) 887 return (EINVAL); 888 889 bcopy(&pcb->dst, &sa.rfcomm_bdaddr, sizeof(sa.rfcomm_bdaddr)); 890 sa.rfcomm_channel = pcb->channel; 891 sa.rfcomm_len = sizeof(sa); 892 sa.rfcomm_family = AF_BLUETOOTH; 893 894 *nam = sodupsockaddr((struct sockaddr *) &sa, M_NOWAIT); 895 896 return ((*nam == NULL)? ENOMEM : 0); 897 } /* ng_btsocket_rfcomm_peeraddr */ 898 899 /* 900 * Send data to socket 901 */ 902 903 int 904 ng_btsocket_rfcomm_send(struct socket *so, int flags, struct mbuf *m, 905 struct sockaddr *nam, struct mbuf *control, struct thread *td) 906 { 907 ng_btsocket_rfcomm_pcb_t *pcb = so2rfcomm_pcb(so); 908 int error = 0; 909 910 /* Check socket and input */ 911 if (pcb == NULL || m == NULL || control != NULL) { 912 error = EINVAL; 913 goto drop; 914 } 915 916 mtx_lock(&pcb->pcb_mtx); 917 918 /* Make sure DLC is connected */ 919 if (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTED) { 920 mtx_unlock(&pcb->pcb_mtx); 921 error = ENOTCONN; 922 goto drop; 923 } 924 925 /* Put the packet on the socket's send queue and wakeup RFCOMM task */ 926 sbappend(&pcb->so->so_snd, m); 927 m = NULL; 928 929 if (!(pcb->flags & NG_BTSOCKET_RFCOMM_DLC_SENDING)) { 930 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_SENDING; 931 error = ng_btsocket_rfcomm_task_wakeup(); 932 } 933 934 mtx_unlock(&pcb->pcb_mtx); 935 drop: 936 NG_FREE_M(m); /* checks for != NULL */ 937 NG_FREE_M(control); 938 939 return (error); 940 } /* ng_btsocket_rfcomm_send */ 941 942 /* 943 * Get socket address 944 */ 945 946 int 947 ng_btsocket_rfcomm_sockaddr(struct socket *so, struct sockaddr **nam) 948 { 949 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so); 950 struct sockaddr_rfcomm sa; 951 952 if (pcb == NULL) 953 return (EINVAL); 954 955 bcopy(&pcb->src, &sa.rfcomm_bdaddr, sizeof(sa.rfcomm_bdaddr)); 956 sa.rfcomm_channel = pcb->channel; 957 sa.rfcomm_len = sizeof(sa); 958 sa.rfcomm_family = AF_BLUETOOTH; 959 960 *nam = sodupsockaddr((struct sockaddr *) &sa, M_NOWAIT); 961 962 return ((*nam == NULL)? ENOMEM : 0); 963 } /* ng_btsocket_rfcomm_sockaddr */ 964 965 /* 966 * Upcall function for L2CAP sockets. Enqueue RFCOMM task. 967 */ 968 969 static void 970 ng_btsocket_rfcomm_upcall(struct socket *so, void *arg, int waitflag) 971 { 972 int error; 973 974 if (so == NULL) 975 panic("%s: so == NULL\n", __func__); 976 977 if ((error = ng_btsocket_rfcomm_task_wakeup()) != 0) 978 NG_BTSOCKET_RFCOMM_ALERT( 979 "%s: Could not enqueue RFCOMM task, error=%d\n", __func__, error); 980 } /* ng_btsocket_rfcomm_upcall */ 981 982 /* 983 * RFCOMM task. Will handle all RFCOMM sessions in one pass. 984 * XXX FIXME does not scale very well 985 */ 986 987 static void 988 ng_btsocket_rfcomm_sessions_task(void *ctx, int pending) 989 { 990 ng_btsocket_rfcomm_session_p s = NULL, s_next = NULL; 991 992 mtx_lock(&ng_btsocket_rfcomm_sessions_mtx); 993 994 for (s = LIST_FIRST(&ng_btsocket_rfcomm_sessions); s != NULL; ) { 995 mtx_lock(&s->session_mtx); 996 s_next = LIST_NEXT(s, next); 997 998 ng_btsocket_rfcomm_session_task(s); 999 1000 if (s->state == NG_BTSOCKET_RFCOMM_SESSION_CLOSED) { 1001 /* Unlink and clean the session */ 1002 LIST_REMOVE(s, next); 1003 1004 NG_BT_MBUFQ_DRAIN(&s->outq); 1005 if (!LIST_EMPTY(&s->dlcs)) 1006 panic("%s: DLC list is not empty\n", __func__); 1007 1008 /* Close L2CAP socket */ 1009 s->l2so->so_upcallarg = NULL; 1010 s->l2so->so_upcall = NULL; 1011 SOCKBUF_LOCK(&s->l2so->so_rcv); 1012 s->l2so->so_rcv.sb_flags &= ~SB_UPCALL; 1013 SOCKBUF_UNLOCK(&s->l2so->so_rcv); 1014 SOCKBUF_LOCK(&s->l2so->so_snd); 1015 s->l2so->so_snd.sb_flags &= ~SB_UPCALL; 1016 SOCKBUF_UNLOCK(&s->l2so->so_snd); 1017 soclose(s->l2so); 1018 1019 mtx_unlock(&s->session_mtx); 1020 1021 mtx_destroy(&s->session_mtx); 1022 bzero(s, sizeof(*s)); 1023 FREE(s, M_NETGRAPH_BTSOCKET_RFCOMM); 1024 } else 1025 mtx_unlock(&s->session_mtx); 1026 1027 s = s_next; 1028 } 1029 1030 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx); 1031 } /* ng_btsocket_rfcomm_sessions_task */ 1032 1033 /* 1034 * Process RFCOMM session. Will handle all RFCOMM sockets in one pass. 1035 */ 1036 1037 static void 1038 ng_btsocket_rfcomm_session_task(ng_btsocket_rfcomm_session_p s) 1039 { 1040 mtx_assert(&s->session_mtx, MA_OWNED); 1041 1042 if (s->l2so->so_rcv.sb_state & SBS_CANTRCVMORE) { 1043 NG_BTSOCKET_RFCOMM_INFO( 1044 "%s: L2CAP connection has been terminated, so=%p, so_state=%#x, so_count=%d, " \ 1045 "state=%d, flags=%#x\n", __func__, s->l2so, s->l2so->so_state, 1046 s->l2so->so_count, s->state, s->flags); 1047 1048 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED; 1049 ng_btsocket_rfcomm_session_clean(s); 1050 } 1051 1052 /* Now process upcall */ 1053 switch (s->state) { 1054 /* Try to accept new L2CAP connection(s) */ 1055 case NG_BTSOCKET_RFCOMM_SESSION_LISTENING: 1056 while (ng_btsocket_rfcomm_session_accept(s) == 0) 1057 ; 1058 break; 1059 1060 /* Process the results of the L2CAP connect */ 1061 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTING: 1062 ng_btsocket_rfcomm_session_process_pcb(s); 1063 1064 if (ng_btsocket_rfcomm_session_connect(s) != 0) { 1065 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED; 1066 ng_btsocket_rfcomm_session_clean(s); 1067 } 1068 break; 1069 1070 /* Try to receive/send more data */ 1071 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED: 1072 case NG_BTSOCKET_RFCOMM_SESSION_OPEN: 1073 case NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING: 1074 ng_btsocket_rfcomm_session_process_pcb(s); 1075 1076 if (ng_btsocket_rfcomm_session_receive(s) != 0) { 1077 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED; 1078 ng_btsocket_rfcomm_session_clean(s); 1079 } else if (ng_btsocket_rfcomm_session_send(s) != 0) { 1080 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED; 1081 ng_btsocket_rfcomm_session_clean(s); 1082 } 1083 break; 1084 1085 case NG_BTSOCKET_RFCOMM_SESSION_CLOSED: 1086 break; 1087 1088 default: 1089 panic("%s: Invalid session state=%d, flags=%#x\n", 1090 __func__, s->state, s->flags); 1091 break; 1092 } 1093 } /* ng_btsocket_rfcomm_session_task */ 1094 1095 /* 1096 * Process RFCOMM connection indicator. Caller must hold s->session_mtx 1097 */ 1098 1099 static ng_btsocket_rfcomm_pcb_p 1100 ng_btsocket_rfcomm_connect_ind(ng_btsocket_rfcomm_session_p s, int channel) 1101 { 1102 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb1 = NULL; 1103 ng_btsocket_l2cap_pcb_p l2pcb = NULL; 1104 struct socket *so1 = NULL; 1105 1106 mtx_assert(&s->session_mtx, MA_OWNED); 1107 1108 /* 1109 * Try to find RFCOMM socket that listens on given source address 1110 * and channel. This will return the best possible match. 1111 */ 1112 1113 l2pcb = so2l2cap_pcb(s->l2so); 1114 pcb = ng_btsocket_rfcomm_pcb_listener(&l2pcb->src, channel); 1115 if (pcb == NULL) 1116 return (NULL); 1117 1118 /* 1119 * Check the pending connections queue and if we have space then 1120 * create new socket and set proper source and destination address, 1121 * and channel. 1122 */ 1123 1124 mtx_lock(&pcb->pcb_mtx); 1125 1126 if (pcb->so->so_qlen <= pcb->so->so_qlimit) 1127 so1 = sonewconn(pcb->so, 0); 1128 1129 mtx_unlock(&pcb->pcb_mtx); 1130 1131 if (so1 == NULL) 1132 return (NULL); 1133 1134 /* 1135 * If we got here than we have created new socket. So complete the 1136 * connection. Set source and destination address from the session. 1137 */ 1138 1139 pcb1 = so2rfcomm_pcb(so1); 1140 if (pcb1 == NULL) 1141 panic("%s: pcb1 == NULL\n", __func__); 1142 1143 mtx_lock(&pcb1->pcb_mtx); 1144 1145 bcopy(&l2pcb->src, &pcb1->src, sizeof(pcb1->src)); 1146 bcopy(&l2pcb->dst, &pcb1->dst, sizeof(pcb1->dst)); 1147 pcb1->channel = channel; 1148 1149 /* Link new DLC to the session. We already hold s->session_mtx */ 1150 LIST_INSERT_HEAD(&s->dlcs, pcb1, session_next); 1151 pcb1->session = s; 1152 1153 mtx_unlock(&pcb1->pcb_mtx); 1154 1155 return (pcb1); 1156 } /* ng_btsocket_rfcomm_connect_ind */ 1157 1158 /* 1159 * Process RFCOMM connect confirmation. Caller must hold s->session_mtx. 1160 */ 1161 1162 static void 1163 ng_btsocket_rfcomm_connect_cfm(ng_btsocket_rfcomm_session_p s) 1164 { 1165 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb_next = NULL; 1166 int error; 1167 1168 mtx_assert(&s->session_mtx, MA_OWNED); 1169 1170 /* 1171 * Wake up all waiting sockets and send PN request for each of them. 1172 * Note that timeout already been set in ng_btsocket_rfcomm_connect() 1173 * 1174 * Note: cannot use LIST_FOREACH because ng_btsocket_rfcomm_pcb_kill 1175 * will unlink DLC from the session 1176 */ 1177 1178 for (pcb = LIST_FIRST(&s->dlcs); pcb != NULL; ) { 1179 mtx_lock(&pcb->pcb_mtx); 1180 pcb_next = LIST_NEXT(pcb, session_next); 1181 1182 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT) { 1183 pcb->mtu = s->mtu; 1184 bcopy(&so2l2cap_pcb(s->l2so)->src, &pcb->src, 1185 sizeof(pcb->src)); 1186 1187 error = ng_btsocket_rfcomm_send_pn(pcb); 1188 if (error == 0) 1189 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONFIGURING; 1190 else 1191 ng_btsocket_rfcomm_pcb_kill(pcb, error); 1192 } 1193 1194 mtx_unlock(&pcb->pcb_mtx); 1195 pcb = pcb_next; 1196 } 1197 } /* ng_btsocket_rfcomm_connect_cfm */ 1198 1199 /***************************************************************************** 1200 ***************************************************************************** 1201 ** RFCOMM sessions 1202 ***************************************************************************** 1203 *****************************************************************************/ 1204 1205 /* 1206 * Create new RFCOMM session. That function WILL NOT take ownership over l2so. 1207 * Caller MUST free l2so if function failed. 1208 */ 1209 1210 static int 1211 ng_btsocket_rfcomm_session_create(ng_btsocket_rfcomm_session_p *sp, 1212 struct socket *l2so, bdaddr_p src, bdaddr_p dst, 1213 struct thread *td) 1214 { 1215 ng_btsocket_rfcomm_session_p s = NULL; 1216 struct sockaddr_l2cap l2sa; 1217 struct sockopt l2sopt; 1218 int error; 1219 u_int16_t mtu; 1220 1221 mtx_assert(&ng_btsocket_rfcomm_sessions_mtx, MA_OWNED); 1222 1223 /* Allocate the RFCOMM session */ 1224 MALLOC(s, ng_btsocket_rfcomm_session_p, sizeof(*s), 1225 M_NETGRAPH_BTSOCKET_RFCOMM, M_NOWAIT | M_ZERO); 1226 if (s == NULL) 1227 return (ENOMEM); 1228 1229 /* Set defaults */ 1230 s->mtu = RFCOMM_DEFAULT_MTU; 1231 s->flags = 0; 1232 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED; 1233 NG_BT_MBUFQ_INIT(&s->outq, ifqmaxlen); 1234 1235 /* 1236 * XXX Mark session mutex as DUPOK to prevent "duplicated lock of 1237 * the same type" message. When accepting new L2CAP connection 1238 * ng_btsocket_rfcomm_session_accept() holds both session mutexes 1239 * for "old" (accepting) session and "new" (created) session. 1240 */ 1241 1242 mtx_init(&s->session_mtx, "btsocks_rfcomm_session_mtx", NULL, 1243 MTX_DEF|MTX_DUPOK); 1244 1245 LIST_INIT(&s->dlcs); 1246 1247 /* Prepare L2CAP socket */ 1248 l2so->so_upcallarg = NULL; 1249 l2so->so_upcall = ng_btsocket_rfcomm_upcall; 1250 SOCKBUF_LOCK(&l2so->so_rcv); 1251 l2so->so_rcv.sb_flags |= SB_UPCALL; 1252 SOCKBUF_UNLOCK(&l2so->so_rcv); 1253 SOCKBUF_LOCK(&l2so->so_snd); 1254 l2so->so_snd.sb_flags |= SB_UPCALL; 1255 SOCKBUF_UNLOCK(&l2so->so_snd); 1256 l2so->so_state |= SS_NBIO; 1257 s->l2so = l2so; 1258 1259 mtx_lock(&s->session_mtx); 1260 1261 /* 1262 * "src" == NULL and "dst" == NULL means just create session. 1263 * caller must do the rest 1264 */ 1265 1266 if (src == NULL && dst == NULL) 1267 goto done; 1268 1269 /* 1270 * Set incoming MTU on L2CAP socket. It is RFCOMM session default MTU 1271 * plus 5 bytes: RFCOMM frame header, one extra byte for length and one 1272 * extra byte for credits. 1273 */ 1274 1275 mtu = s->mtu + sizeof(struct rfcomm_frame_hdr) + 1 + 1; 1276 1277 l2sopt.sopt_dir = SOPT_SET; 1278 l2sopt.sopt_level = SOL_L2CAP; 1279 l2sopt.sopt_name = SO_L2CAP_IMTU; 1280 l2sopt.sopt_val = (void *) &mtu; 1281 l2sopt.sopt_valsize = sizeof(mtu); 1282 l2sopt.sopt_td = NULL; 1283 1284 error = sosetopt(s->l2so, &l2sopt); 1285 if (error != 0) 1286 goto bad; 1287 1288 /* Bind socket to "src" address */ 1289 l2sa.l2cap_len = sizeof(l2sa); 1290 l2sa.l2cap_family = AF_BLUETOOTH; 1291 l2sa.l2cap_psm = (dst == NULL)? htole16(NG_L2CAP_PSM_RFCOMM) : 0; 1292 bcopy(src, &l2sa.l2cap_bdaddr, sizeof(l2sa.l2cap_bdaddr)); 1293 1294 error = sobind(s->l2so, (struct sockaddr *) &l2sa, td); 1295 if (error != 0) 1296 goto bad; 1297 1298 /* If "dst" is not NULL then initiate connect(), otherwise listen() */ 1299 if (dst == NULL) { 1300 s->flags = 0; 1301 s->state = NG_BTSOCKET_RFCOMM_SESSION_LISTENING; 1302 1303 error = solisten(s->l2so, 10, td); 1304 if (error != 0) 1305 goto bad; 1306 } else { 1307 s->flags = NG_BTSOCKET_RFCOMM_SESSION_INITIATOR; 1308 s->state = NG_BTSOCKET_RFCOMM_SESSION_CONNECTING; 1309 1310 l2sa.l2cap_len = sizeof(l2sa); 1311 l2sa.l2cap_family = AF_BLUETOOTH; 1312 l2sa.l2cap_psm = htole16(NG_L2CAP_PSM_RFCOMM); 1313 bcopy(dst, &l2sa.l2cap_bdaddr, sizeof(l2sa.l2cap_bdaddr)); 1314 1315 error = soconnect(s->l2so, (struct sockaddr *) &l2sa, td); 1316 if (error != 0) 1317 goto bad; 1318 } 1319 1320 done: 1321 LIST_INSERT_HEAD(&ng_btsocket_rfcomm_sessions, s, next); 1322 *sp = s; 1323 1324 mtx_unlock(&s->session_mtx); 1325 1326 return (0); 1327 1328 bad: 1329 mtx_unlock(&s->session_mtx); 1330 1331 /* Return L2CAP socket back to its original state */ 1332 l2so->so_upcallarg = NULL; 1333 l2so->so_upcall = NULL; 1334 SOCKBUF_LOCK(&l2so->so_rcv); 1335 l2so->so_rcv.sb_flags &= ~SB_UPCALL; 1336 SOCKBUF_UNLOCK(&l2so->so_rcv); 1337 SOCKBUF_LOCK(&l2so->so_snd); 1338 l2so->so_snd.sb_flags &= ~SB_UPCALL; 1339 SOCKBUF_UNLOCK(&l2so->so_snd); 1340 l2so->so_state &= ~SS_NBIO; 1341 1342 mtx_destroy(&s->session_mtx); 1343 bzero(s, sizeof(*s)); 1344 FREE(s, M_NETGRAPH_BTSOCKET_RFCOMM); 1345 1346 return (error); 1347 } /* ng_btsocket_rfcomm_session_create */ 1348 1349 /* 1350 * Process accept() on RFCOMM session 1351 * XXX FIXME locking for "l2so"? 1352 */ 1353 1354 static int 1355 ng_btsocket_rfcomm_session_accept(ng_btsocket_rfcomm_session_p s0) 1356 { 1357 struct socket *l2so = NULL; 1358 struct sockaddr_l2cap *l2sa = NULL; 1359 ng_btsocket_l2cap_pcb_t *l2pcb = NULL; 1360 ng_btsocket_rfcomm_session_p s = NULL; 1361 int error = 0; 1362 1363 mtx_assert(&ng_btsocket_rfcomm_sessions_mtx, MA_OWNED); 1364 mtx_assert(&s0->session_mtx, MA_OWNED); 1365 1366 /* Check if there is a complete L2CAP connection in the queue */ 1367 if ((error = s0->l2so->so_error) != 0) { 1368 NG_BTSOCKET_RFCOMM_ERR( 1369 "%s: Could not accept connection on L2CAP socket, error=%d\n", __func__, error); 1370 s0->l2so->so_error = 0; 1371 1372 return (error); 1373 } 1374 1375 ACCEPT_LOCK(); 1376 if (TAILQ_EMPTY(&s0->l2so->so_comp)) { 1377 ACCEPT_UNLOCK(); 1378 if (s0->l2so->so_rcv.sb_state & SBS_CANTRCVMORE) 1379 return (ECONNABORTED); 1380 return (EWOULDBLOCK); 1381 } 1382 1383 /* Accept incoming L2CAP connection */ 1384 l2so = TAILQ_FIRST(&s0->l2so->so_comp); 1385 if (l2so == NULL) 1386 panic("%s: l2so == NULL\n", __func__); 1387 1388 TAILQ_REMOVE(&s0->l2so->so_comp, l2so, so_list); 1389 s0->l2so->so_qlen --; 1390 l2so->so_qstate &= ~SQ_COMP; 1391 l2so->so_head = NULL; 1392 SOCK_LOCK(l2so); 1393 soref(l2so); 1394 l2so->so_state |= SS_NBIO; 1395 SOCK_UNLOCK(l2so); 1396 ACCEPT_UNLOCK(); 1397 1398 error = soaccept(l2so, (struct sockaddr **) &l2sa); 1399 if (error != 0) { 1400 NG_BTSOCKET_RFCOMM_ERR( 1401 "%s: soaccept() on L2CAP socket failed, error=%d\n", __func__, error); 1402 soclose(l2so); 1403 1404 return (error); 1405 } 1406 1407 /* 1408 * Check if there is already active RFCOMM session between two devices. 1409 * If so then close L2CAP connection. We only support one RFCOMM session 1410 * between each pair of devices. Note that here we assume session in any 1411 * state. The session even could be in the middle of disconnecting. 1412 */ 1413 1414 l2pcb = so2l2cap_pcb(l2so); 1415 s = ng_btsocket_rfcomm_session_by_addr(&l2pcb->src, &l2pcb->dst); 1416 if (s == NULL) { 1417 /* Create a new RFCOMM session */ 1418 error = ng_btsocket_rfcomm_session_create(&s, l2so, NULL, NULL, 1419 curthread /* XXX */); 1420 if (error == 0) { 1421 mtx_lock(&s->session_mtx); 1422 1423 s->flags = 0; 1424 s->state = NG_BTSOCKET_RFCOMM_SESSION_CONNECTED; 1425 1426 /* 1427 * Adjust MTU on incomming connection. Reserve 5 bytes: 1428 * RFCOMM frame header, one extra byte for length and 1429 * one extra byte for credits. 1430 */ 1431 1432 s->mtu = min(l2pcb->imtu, l2pcb->omtu) - 1433 sizeof(struct rfcomm_frame_hdr) - 1 - 1; 1434 1435 mtx_unlock(&s->session_mtx); 1436 } else { 1437 NG_BTSOCKET_RFCOMM_ALERT( 1438 "%s: Failed to create new RFCOMM session, error=%d\n", __func__, error); 1439 1440 soclose(l2so); 1441 } 1442 } else { 1443 NG_BTSOCKET_RFCOMM_WARN( 1444 "%s: Rejecting duplicating RFCOMM session between src=%x:%x:%x:%x:%x:%x and " \ 1445 "dst=%x:%x:%x:%x:%x:%x, state=%d, flags=%#x\n", __func__, 1446 l2pcb->src.b[5], l2pcb->src.b[4], l2pcb->src.b[3], 1447 l2pcb->src.b[2], l2pcb->src.b[1], l2pcb->src.b[0], 1448 l2pcb->dst.b[5], l2pcb->dst.b[4], l2pcb->dst.b[3], 1449 l2pcb->dst.b[2], l2pcb->dst.b[1], l2pcb->dst.b[0], 1450 s->state, s->flags); 1451 1452 error = EBUSY; 1453 soclose(l2so); 1454 } 1455 1456 return (error); 1457 } /* ng_btsocket_rfcomm_session_accept */ 1458 1459 /* 1460 * Process connect() on RFCOMM session 1461 * XXX FIXME locking for "l2so"? 1462 */ 1463 1464 static int 1465 ng_btsocket_rfcomm_session_connect(ng_btsocket_rfcomm_session_p s) 1466 { 1467 ng_btsocket_l2cap_pcb_p l2pcb = so2l2cap_pcb(s->l2so); 1468 int error; 1469 1470 mtx_assert(&s->session_mtx, MA_OWNED); 1471 1472 /* First check if connection has failed */ 1473 if ((error = s->l2so->so_error) != 0) { 1474 s->l2so->so_error = 0; 1475 1476 NG_BTSOCKET_RFCOMM_ERR( 1477 "%s: Could not connect RFCOMM session, error=%d, state=%d, flags=%#x\n", 1478 __func__, error, s->state, s->flags); 1479 1480 return (error); 1481 } 1482 1483 /* Is connection still in progress? */ 1484 if (s->l2so->so_state & SS_ISCONNECTING) 1485 return (0); 1486 1487 /* 1488 * If we got here then we are connected. Send SABM on DLCI 0 to 1489 * open multiplexor channel. 1490 */ 1491 1492 if (error == 0) { 1493 s->state = NG_BTSOCKET_RFCOMM_SESSION_CONNECTED; 1494 1495 /* 1496 * Adjust MTU on outgoing connection. Reserve 5 bytes: RFCOMM 1497 * frame header, one extra byte for length and one extra byte 1498 * for credits. 1499 */ 1500 1501 s->mtu = min(l2pcb->imtu, l2pcb->omtu) - 1502 sizeof(struct rfcomm_frame_hdr) - 1 - 1; 1503 1504 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_SABM,0); 1505 if (error == 0) 1506 error = ng_btsocket_rfcomm_task_wakeup(); 1507 } 1508 1509 return (error); 1510 }/* ng_btsocket_rfcomm_session_connect */ 1511 1512 /* 1513 * Receive data on RFCOMM session 1514 * XXX FIXME locking for "l2so"? 1515 */ 1516 1517 static int 1518 ng_btsocket_rfcomm_session_receive(ng_btsocket_rfcomm_session_p s) 1519 { 1520 struct mbuf *m = NULL; 1521 struct uio uio; 1522 int more, flags, error; 1523 1524 mtx_assert(&s->session_mtx, MA_OWNED); 1525 1526 /* Can we read from the L2CAP socket? */ 1527 if (!soreadable(s->l2so)) 1528 return (0); 1529 1530 /* First check for error on L2CAP socket */ 1531 if ((error = s->l2so->so_error) != 0) { 1532 s->l2so->so_error = 0; 1533 1534 NG_BTSOCKET_RFCOMM_ERR( 1535 "%s: Could not receive data from L2CAP socket, error=%d, state=%d, flags=%#x\n", 1536 __func__, error, s->state, s->flags); 1537 1538 return (error); 1539 } 1540 1541 /* 1542 * Read all packets from the L2CAP socket. 1543 * XXX FIXME/VERIFY is that correct? For now use m->m_nextpkt as 1544 * indication that there is more packets on the socket's buffer. 1545 * Also what should we use in uio.uio_resid? 1546 * May be s->mtu + sizeof(struct rfcomm_frame_hdr) + 1 + 1? 1547 */ 1548 1549 for (more = 1; more; ) { 1550 /* Try to get next packet from socket */ 1551 bzero(&uio, sizeof(uio)); 1552 /* uio.uio_td = NULL; */ 1553 uio.uio_resid = 1000000000; 1554 flags = MSG_DONTWAIT; 1555 1556 m = NULL; 1557 error = soreceive(s->l2so, NULL, &uio, &m, 1558 (struct mbuf **) NULL, &flags); 1559 if (error != 0) { 1560 if (error == EWOULDBLOCK) 1561 return (0); /* XXX can happen? */ 1562 1563 NG_BTSOCKET_RFCOMM_ERR( 1564 "%s: Could not receive data from L2CAP socket, error=%d\n", __func__, error); 1565 1566 return (error); 1567 } 1568 1569 more = (m->m_nextpkt != NULL); 1570 m->m_nextpkt = NULL; 1571 1572 ng_btsocket_rfcomm_receive_frame(s, m); 1573 } 1574 1575 return (0); 1576 } /* ng_btsocket_rfcomm_session_receive */ 1577 1578 /* 1579 * Send data on RFCOMM session 1580 * XXX FIXME locking for "l2so"? 1581 */ 1582 1583 static int 1584 ng_btsocket_rfcomm_session_send(ng_btsocket_rfcomm_session_p s) 1585 { 1586 struct mbuf *m = NULL; 1587 int error; 1588 1589 mtx_assert(&s->session_mtx, MA_OWNED); 1590 1591 /* Send as much as we can from the session queue */ 1592 while (sowriteable(s->l2so)) { 1593 /* Check if socket still OK */ 1594 if ((error = s->l2so->so_error) != 0) { 1595 s->l2so->so_error = 0; 1596 1597 NG_BTSOCKET_RFCOMM_ERR( 1598 "%s: Detected error=%d on L2CAP socket, state=%d, flags=%#x\n", 1599 __func__, error, s->state, s->flags); 1600 1601 return (error); 1602 } 1603 1604 NG_BT_MBUFQ_DEQUEUE(&s->outq, m); 1605 if (m == NULL) 1606 return (0); /* we are done */ 1607 1608 /* Call send function on the L2CAP socket */ 1609 error = sosend(s->l2so, NULL, NULL, m, NULL, 0, 1610 curthread /* XXX */); 1611 if (error != 0) { 1612 NG_BTSOCKET_RFCOMM_ERR( 1613 "%s: Could not send data to L2CAP socket, error=%d\n", __func__, error); 1614 1615 return (error); 1616 } 1617 } 1618 1619 return (0); 1620 } /* ng_btsocket_rfcomm_session_send */ 1621 1622 /* 1623 * Close and disconnect all DLCs for the given session. Caller must hold 1624 * s->sesson_mtx. Will wakeup session. 1625 */ 1626 1627 static void 1628 ng_btsocket_rfcomm_session_clean(ng_btsocket_rfcomm_session_p s) 1629 { 1630 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb_next = NULL; 1631 int error; 1632 1633 mtx_assert(&s->session_mtx, MA_OWNED); 1634 1635 /* 1636 * Note: cannot use LIST_FOREACH because ng_btsocket_rfcomm_pcb_kill 1637 * will unlink DLC from the session 1638 */ 1639 1640 for (pcb = LIST_FIRST(&s->dlcs); pcb != NULL; ) { 1641 mtx_lock(&pcb->pcb_mtx); 1642 pcb_next = LIST_NEXT(pcb, session_next); 1643 1644 NG_BTSOCKET_RFCOMM_INFO( 1645 "%s: Disconnecting dlci=%d, state=%d, flags=%#x\n", 1646 __func__, pcb->dlci, pcb->state, pcb->flags); 1647 1648 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONNECTED) 1649 error = ECONNRESET; 1650 else 1651 error = ECONNREFUSED; 1652 1653 ng_btsocket_rfcomm_pcb_kill(pcb, error); 1654 1655 mtx_unlock(&pcb->pcb_mtx); 1656 pcb = pcb_next; 1657 } 1658 } /* ng_btsocket_rfcomm_session_clean */ 1659 1660 /* 1661 * Process all DLCs on the session. Caller MUST hold s->session_mtx. 1662 */ 1663 1664 static void 1665 ng_btsocket_rfcomm_session_process_pcb(ng_btsocket_rfcomm_session_p s) 1666 { 1667 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb_next = NULL; 1668 int error; 1669 1670 mtx_assert(&s->session_mtx, MA_OWNED); 1671 1672 /* 1673 * Note: cannot use LIST_FOREACH because ng_btsocket_rfcomm_pcb_kill 1674 * will unlink DLC from the session 1675 */ 1676 1677 for (pcb = LIST_FIRST(&s->dlcs); pcb != NULL; ) { 1678 mtx_lock(&pcb->pcb_mtx); 1679 pcb_next = LIST_NEXT(pcb, session_next); 1680 1681 switch (pcb->state) { 1682 1683 /* 1684 * If DLC in W4_CONNECT state then we should check for both 1685 * timeout and detach. 1686 */ 1687 1688 case NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT: 1689 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_DETACHED) 1690 ng_btsocket_rfcomm_pcb_kill(pcb, 0); 1691 else if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT) 1692 ng_btsocket_rfcomm_pcb_kill(pcb, ETIMEDOUT); 1693 break; 1694 1695 /* 1696 * If DLC in CONFIGURING or CONNECTING state then we only 1697 * should check for timeout. If detach() was called then 1698 * DLC will be moved into DISCONNECTING state. 1699 */ 1700 1701 case NG_BTSOCKET_RFCOMM_DLC_CONFIGURING: 1702 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING: 1703 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT) 1704 ng_btsocket_rfcomm_pcb_kill(pcb, ETIMEDOUT); 1705 break; 1706 1707 /* 1708 * If DLC in CONNECTED state then we need to send data (if any) 1709 * from the socket's send queue. Note that we will send data 1710 * from either all sockets or none. This may overload session's 1711 * outgoing queue (but we do not check for that). 1712 * 1713 * XXX FIXME need scheduler for RFCOMM sockets 1714 */ 1715 1716 case NG_BTSOCKET_RFCOMM_DLC_CONNECTED: 1717 error = ng_btsocket_rfcomm_pcb_send(pcb, ALOT); 1718 if (error != 0) 1719 ng_btsocket_rfcomm_pcb_kill(pcb, error); 1720 break; 1721 1722 /* 1723 * If DLC in DISCONNECTING state then we must send DISC frame. 1724 * Note that if DLC has timeout set then we do not need to 1725 * resend DISC frame. 1726 * 1727 * XXX FIXME need to drain all data from the socket's queue 1728 * if LINGER option was set 1729 */ 1730 1731 case NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING: 1732 if (!(pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)) { 1733 error = ng_btsocket_rfcomm_send_command( 1734 pcb->session, RFCOMM_FRAME_DISC, 1735 pcb->dlci); 1736 if (error == 0) 1737 ng_btsocket_rfcomm_timeout(pcb); 1738 else 1739 ng_btsocket_rfcomm_pcb_kill(pcb, error); 1740 } else if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT) 1741 ng_btsocket_rfcomm_pcb_kill(pcb, ETIMEDOUT); 1742 break; 1743 1744 /* case NG_BTSOCKET_RFCOMM_DLC_CLOSED: */ 1745 default: 1746 panic("%s: Invalid DLC state=%d, flags=%#x\n", 1747 __func__, pcb->state, pcb->flags); 1748 break; 1749 } 1750 1751 mtx_unlock(&pcb->pcb_mtx); 1752 pcb = pcb_next; 1753 } 1754 } /* ng_btsocket_rfcomm_session_process_pcb */ 1755 1756 /* 1757 * Find RFCOMM session between "src" and "dst". 1758 * Caller MUST hold ng_btsocket_rfcomm_sessions_mtx. 1759 */ 1760 1761 static ng_btsocket_rfcomm_session_p 1762 ng_btsocket_rfcomm_session_by_addr(bdaddr_p src, bdaddr_p dst) 1763 { 1764 ng_btsocket_rfcomm_session_p s = NULL; 1765 ng_btsocket_l2cap_pcb_p l2pcb = NULL; 1766 int any_src; 1767 1768 mtx_assert(&ng_btsocket_rfcomm_sessions_mtx, MA_OWNED); 1769 1770 any_src = (bcmp(src, NG_HCI_BDADDR_ANY, sizeof(*src)) == 0); 1771 1772 LIST_FOREACH(s, &ng_btsocket_rfcomm_sessions, next) { 1773 l2pcb = so2l2cap_pcb(s->l2so); 1774 1775 if ((any_src || bcmp(&l2pcb->src, src, sizeof(*src)) == 0) && 1776 bcmp(&l2pcb->dst, dst, sizeof(*dst)) == 0) 1777 break; 1778 } 1779 1780 return (s); 1781 } /* ng_btsocket_rfcomm_session_by_addr */ 1782 1783 /***************************************************************************** 1784 ***************************************************************************** 1785 ** RFCOMM 1786 ***************************************************************************** 1787 *****************************************************************************/ 1788 1789 /* 1790 * Process incoming RFCOMM frame. Caller must hold s->session_mtx. 1791 * XXX FIXME check frame length 1792 */ 1793 1794 static int 1795 ng_btsocket_rfcomm_receive_frame(ng_btsocket_rfcomm_session_p s, 1796 struct mbuf *m0) 1797 { 1798 struct rfcomm_frame_hdr *hdr = NULL; 1799 struct mbuf *m = NULL; 1800 u_int16_t length; 1801 u_int8_t dlci, type; 1802 int error = 0; 1803 1804 mtx_assert(&s->session_mtx, MA_OWNED); 1805 1806 /* Pullup as much as we can into first mbuf (for direct access) */ 1807 length = min(m0->m_pkthdr.len, MHLEN); 1808 if (m0->m_len < length) { 1809 if ((m0 = m_pullup(m0, length)) == NULL) { 1810 NG_BTSOCKET_RFCOMM_ALERT( 1811 "%s: m_pullup(%d) failed\n", __func__, length); 1812 1813 return (ENOBUFS); 1814 } 1815 } 1816 1817 hdr = mtod(m0, struct rfcomm_frame_hdr *); 1818 dlci = RFCOMM_DLCI(hdr->address); 1819 type = RFCOMM_TYPE(hdr->control); 1820 1821 /* Test EA bit in length. If not set then we have 2 bytes of length */ 1822 if (!RFCOMM_EA(hdr->length)) { 1823 bcopy(&hdr->length, &length, sizeof(length)); 1824 length = le16toh(length) >> 1; 1825 m_adj(m0, sizeof(*hdr) + 1); 1826 } else { 1827 length = hdr->length >> 1; 1828 m_adj(m0, sizeof(*hdr)); 1829 } 1830 1831 NG_BTSOCKET_RFCOMM_INFO( 1832 "%s: Got frame type=%#x, dlci=%d, length=%d, cr=%d, pf=%d, len=%d\n", 1833 __func__, type, dlci, length, RFCOMM_CR(hdr->address), 1834 RFCOMM_PF(hdr->control), m0->m_pkthdr.len); 1835 1836 /* 1837 * Get FCS (the last byte in the frame) 1838 * XXX this will not work if mbuf chain ends with empty mbuf. 1839 * XXX let's hope it never happens :) 1840 */ 1841 1842 for (m = m0; m->m_next != NULL; m = m->m_next) 1843 ; 1844 if (m->m_len <= 0) 1845 panic("%s: Empty mbuf at the end of the chain, len=%d\n", 1846 __func__, m->m_len); 1847 1848 /* 1849 * Check FCS. We only need to calculate FCS on first 2 or 3 bytes 1850 * and already m_pullup'ed mbuf chain, so it should be safe. 1851 */ 1852 1853 if (ng_btsocket_rfcomm_check_fcs((u_int8_t *) hdr, type, m->m_data[m->m_len - 1])) { 1854 NG_BTSOCKET_RFCOMM_ERR( 1855 "%s: Invalid RFCOMM packet. Bad checksum\n", __func__); 1856 NG_FREE_M(m0); 1857 1858 return (EINVAL); 1859 } 1860 1861 m_adj(m0, -1); /* Trim FCS byte */ 1862 1863 /* 1864 * Process RFCOMM frame. 1865 * 1866 * From TS 07.10 spec 1867 * 1868 * "... In the case where a SABM or DISC command with the P bit set 1869 * to 0 is received then the received frame shall be discarded..." 1870 * 1871 * "... If a unsolicited DM response is received then the frame shall 1872 * be processed irrespective of the P/F setting... " 1873 * 1874 * "... The station may transmit response frames with the F bit set 1875 * to 0 at any opportunity on an asynchronous basis. However, in the 1876 * case where a UA response is received with the F bit set to 0 then 1877 * the received frame shall be discarded..." 1878 * 1879 * From Bluetooth spec 1880 * 1881 * "... When credit based flow control is being used, the meaning of 1882 * the P/F bit in the control field of the RFCOMM header is redefined 1883 * for UIH frames..." 1884 */ 1885 1886 switch (type) { 1887 case RFCOMM_FRAME_SABM: 1888 if (RFCOMM_PF(hdr->control)) 1889 error = ng_btsocket_rfcomm_receive_sabm(s, dlci); 1890 break; 1891 1892 case RFCOMM_FRAME_DISC: 1893 if (RFCOMM_PF(hdr->control)) 1894 error = ng_btsocket_rfcomm_receive_disc(s, dlci); 1895 break; 1896 1897 case RFCOMM_FRAME_UA: 1898 if (RFCOMM_PF(hdr->control)) 1899 error = ng_btsocket_rfcomm_receive_ua(s, dlci); 1900 break; 1901 1902 case RFCOMM_FRAME_DM: 1903 error = ng_btsocket_rfcomm_receive_dm(s, dlci); 1904 break; 1905 1906 case RFCOMM_FRAME_UIH: 1907 if (dlci == 0) 1908 error = ng_btsocket_rfcomm_receive_mcc(s, m0); 1909 else 1910 error = ng_btsocket_rfcomm_receive_uih(s, dlci, 1911 RFCOMM_PF(hdr->control), m0); 1912 1913 return (error); 1914 /* NOT REACHED */ 1915 1916 default: 1917 NG_BTSOCKET_RFCOMM_ERR( 1918 "%s: Invalid RFCOMM packet. Unknown type=%#x\n", __func__, type); 1919 error = EINVAL; 1920 break; 1921 } 1922 1923 NG_FREE_M(m0); 1924 1925 return (error); 1926 } /* ng_btsocket_rfcomm_receive_frame */ 1927 1928 /* 1929 * Process RFCOMM SABM frame 1930 */ 1931 1932 static int 1933 ng_btsocket_rfcomm_receive_sabm(ng_btsocket_rfcomm_session_p s, int dlci) 1934 { 1935 ng_btsocket_rfcomm_pcb_p pcb = NULL; 1936 int error = 0; 1937 1938 mtx_assert(&s->session_mtx, MA_OWNED); 1939 1940 NG_BTSOCKET_RFCOMM_INFO( 1941 "%s: Got SABM, session state=%d, flags=%#x, mtu=%d, dlci=%d\n", 1942 __func__, s->state, s->flags, s->mtu, dlci); 1943 1944 /* DLCI == 0 means open multiplexor channel */ 1945 if (dlci == 0) { 1946 switch (s->state) { 1947 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED: 1948 case NG_BTSOCKET_RFCOMM_SESSION_OPEN: 1949 error = ng_btsocket_rfcomm_send_command(s, 1950 RFCOMM_FRAME_UA, dlci); 1951 if (error == 0) { 1952 s->state = NG_BTSOCKET_RFCOMM_SESSION_OPEN; 1953 ng_btsocket_rfcomm_connect_cfm(s); 1954 } else { 1955 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED; 1956 ng_btsocket_rfcomm_session_clean(s); 1957 } 1958 break; 1959 1960 default: 1961 NG_BTSOCKET_RFCOMM_WARN( 1962 "%s: Got SABM for session in invalid state state=%d, flags=%#x\n", 1963 __func__, s->state, s->flags); 1964 error = EINVAL; 1965 break; 1966 } 1967 1968 return (error); 1969 } 1970 1971 /* Make sure multiplexor channel is open */ 1972 if (s->state != NG_BTSOCKET_RFCOMM_SESSION_OPEN) { 1973 NG_BTSOCKET_RFCOMM_ERR( 1974 "%s: Got SABM for dlci=%d with mulitplexor channel closed, state=%d, " \ 1975 "flags=%#x\n", __func__, dlci, s->state, s->flags); 1976 1977 return (EINVAL); 1978 } 1979 1980 /* 1981 * Check if we have this DLCI. This might happen when remote 1982 * peer uses PN command before actual open (SABM) happens. 1983 */ 1984 1985 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci); 1986 if (pcb != NULL) { 1987 mtx_lock(&pcb->pcb_mtx); 1988 1989 if (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTING) { 1990 NG_BTSOCKET_RFCOMM_ERR( 1991 "%s: Got SABM for dlci=%d in invalid state=%d, flags=%#x\n", 1992 __func__, dlci, pcb->state, pcb->flags); 1993 mtx_unlock(&pcb->pcb_mtx); 1994 1995 return (ENOENT); 1996 } 1997 1998 ng_btsocket_rfcomm_untimeout(pcb); 1999 2000 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_UA,dlci); 2001 if (error == 0) 2002 error = ng_btsocket_rfcomm_send_msc(pcb); 2003 2004 if (error == 0) { 2005 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTED; 2006 soisconnected(pcb->so); 2007 } else 2008 ng_btsocket_rfcomm_pcb_kill(pcb, error); 2009 2010 mtx_unlock(&pcb->pcb_mtx); 2011 2012 return (error); 2013 } 2014 2015 /* 2016 * We do not have requested DLCI, so it must be an incoming connection 2017 * with default parameters. Try to accept it. 2018 */ 2019 2020 pcb = ng_btsocket_rfcomm_connect_ind(s, RFCOMM_SRVCHANNEL(dlci)); 2021 if (pcb != NULL) { 2022 mtx_lock(&pcb->pcb_mtx); 2023 2024 pcb->dlci = dlci; 2025 2026 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_UA,dlci); 2027 if (error == 0) 2028 error = ng_btsocket_rfcomm_send_msc(pcb); 2029 2030 if (error == 0) { 2031 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTED; 2032 soisconnected(pcb->so); 2033 } else 2034 ng_btsocket_rfcomm_pcb_kill(pcb, error); 2035 2036 mtx_unlock(&pcb->pcb_mtx); 2037 } else 2038 /* Nobody is listen()ing on the requested DLCI */ 2039 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_DM,dlci); 2040 2041 return (error); 2042 } /* ng_btsocket_rfcomm_receive_sabm */ 2043 2044 /* 2045 * Process RFCOMM DISC frame 2046 */ 2047 2048 static int 2049 ng_btsocket_rfcomm_receive_disc(ng_btsocket_rfcomm_session_p s, int dlci) 2050 { 2051 ng_btsocket_rfcomm_pcb_p pcb = NULL; 2052 int error = 0; 2053 2054 mtx_assert(&s->session_mtx, MA_OWNED); 2055 2056 NG_BTSOCKET_RFCOMM_INFO( 2057 "%s: Got DISC, session state=%d, flags=%#x, mtu=%d, dlci=%d\n", 2058 __func__, s->state, s->flags, s->mtu, dlci); 2059 2060 /* DLCI == 0 means close multiplexor channel */ 2061 if (dlci == 0) { 2062 /* XXX FIXME assume that remote side will close the socket */ 2063 error = ng_btsocket_rfcomm_send_command(s, RFCOMM_FRAME_UA, 0); 2064 if (error == 0) { 2065 if (s->state == NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING) 2066 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED; /* XXX */ 2067 else 2068 s->state = NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING; 2069 } else 2070 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED; /* XXX */ 2071 2072 ng_btsocket_rfcomm_session_clean(s); 2073 } else { 2074 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci); 2075 if (pcb != NULL) { 2076 int err; 2077 2078 mtx_lock(&pcb->pcb_mtx); 2079 2080 NG_BTSOCKET_RFCOMM_INFO( 2081 "%s: Got DISC for dlci=%d, state=%d, flags=%#x\n", 2082 __func__, dlci, pcb->state, pcb->flags); 2083 2084 error = ng_btsocket_rfcomm_send_command(s, 2085 RFCOMM_FRAME_UA, dlci); 2086 2087 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONNECTED) 2088 err = 0; 2089 else 2090 err = ECONNREFUSED; 2091 2092 ng_btsocket_rfcomm_pcb_kill(pcb, err); 2093 2094 mtx_unlock(&pcb->pcb_mtx); 2095 } else { 2096 NG_BTSOCKET_RFCOMM_WARN( 2097 "%s: Got DISC for non-existing dlci=%d\n", __func__, dlci); 2098 2099 error = ng_btsocket_rfcomm_send_command(s, 2100 RFCOMM_FRAME_DM, dlci); 2101 } 2102 } 2103 2104 return (error); 2105 } /* ng_btsocket_rfcomm_receive_disc */ 2106 2107 /* 2108 * Process RFCOMM UA frame 2109 */ 2110 2111 static int 2112 ng_btsocket_rfcomm_receive_ua(ng_btsocket_rfcomm_session_p s, int dlci) 2113 { 2114 ng_btsocket_rfcomm_pcb_p pcb = NULL; 2115 int error = 0; 2116 2117 mtx_assert(&s->session_mtx, MA_OWNED); 2118 2119 NG_BTSOCKET_RFCOMM_INFO( 2120 "%s: Got UA, session state=%d, flags=%#x, mtu=%d, dlci=%d\n", 2121 __func__, s->state, s->flags, s->mtu, dlci); 2122 2123 /* dlci == 0 means multiplexor channel */ 2124 if (dlci == 0) { 2125 switch (s->state) { 2126 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED: 2127 s->state = NG_BTSOCKET_RFCOMM_SESSION_OPEN; 2128 ng_btsocket_rfcomm_connect_cfm(s); 2129 break; 2130 2131 case NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING: 2132 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED; 2133 ng_btsocket_rfcomm_session_clean(s); 2134 break; 2135 2136 default: 2137 NG_BTSOCKET_RFCOMM_WARN( 2138 "%s: Got UA for session in invalid state=%d(%d), flags=%#x, mtu=%d\n", 2139 __func__, s->state, INITIATOR(s), s->flags, 2140 s->mtu); 2141 error = ENOENT; 2142 break; 2143 } 2144 2145 return (error); 2146 } 2147 2148 /* Check if we have this DLCI */ 2149 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci); 2150 if (pcb != NULL) { 2151 mtx_lock(&pcb->pcb_mtx); 2152 2153 NG_BTSOCKET_RFCOMM_INFO( 2154 "%s: Got UA for dlci=%d, state=%d, flags=%#x\n", 2155 __func__, dlci, pcb->state, pcb->flags); 2156 2157 switch (pcb->state) { 2158 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING: 2159 ng_btsocket_rfcomm_untimeout(pcb); 2160 2161 error = ng_btsocket_rfcomm_send_msc(pcb); 2162 if (error == 0) { 2163 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTED; 2164 soisconnected(pcb->so); 2165 } 2166 break; 2167 2168 case NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING: 2169 ng_btsocket_rfcomm_pcb_kill(pcb, 0); 2170 break; 2171 2172 default: 2173 NG_BTSOCKET_RFCOMM_WARN( 2174 "%s: Got UA for dlci=%d in invalid state=%d, flags=%#x\n", 2175 __func__, dlci, pcb->state, pcb->flags); 2176 error = ENOENT; 2177 break; 2178 } 2179 2180 mtx_unlock(&pcb->pcb_mtx); 2181 } else { 2182 NG_BTSOCKET_RFCOMM_WARN( 2183 "%s: Got UA for non-existing dlci=%d\n", __func__, dlci); 2184 2185 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_DM,dlci); 2186 } 2187 2188 return (error); 2189 } /* ng_btsocket_rfcomm_receive_ua */ 2190 2191 /* 2192 * Process RFCOMM DM frame 2193 */ 2194 2195 static int 2196 ng_btsocket_rfcomm_receive_dm(ng_btsocket_rfcomm_session_p s, int dlci) 2197 { 2198 ng_btsocket_rfcomm_pcb_p pcb = NULL; 2199 int error; 2200 2201 mtx_assert(&s->session_mtx, MA_OWNED); 2202 2203 NG_BTSOCKET_RFCOMM_INFO( 2204 "%s: Got DM, session state=%d, flags=%#x, mtu=%d, dlci=%d\n", 2205 __func__, s->state, s->flags, s->mtu, dlci); 2206 2207 /* DLCI == 0 means multiplexor channel */ 2208 if (dlci == 0) { 2209 /* Disconnect all dlc's on the session */ 2210 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED; 2211 ng_btsocket_rfcomm_session_clean(s); 2212 } else { 2213 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci); 2214 if (pcb != NULL) { 2215 mtx_lock(&pcb->pcb_mtx); 2216 2217 NG_BTSOCKET_RFCOMM_INFO( 2218 "%s: Got DM for dlci=%d, state=%d, flags=%#x\n", 2219 __func__, dlci, pcb->state, pcb->flags); 2220 2221 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONNECTED) 2222 error = ECONNRESET; 2223 else 2224 error = ECONNREFUSED; 2225 2226 ng_btsocket_rfcomm_pcb_kill(pcb, error); 2227 2228 mtx_unlock(&pcb->pcb_mtx); 2229 } else 2230 NG_BTSOCKET_RFCOMM_WARN( 2231 "%s: Got DM for non-existing dlci=%d\n", __func__, dlci); 2232 } 2233 2234 return (0); 2235 } /* ng_btsocket_rfcomm_receive_dm */ 2236 2237 /* 2238 * Process RFCOMM UIH frame (data) 2239 */ 2240 2241 static int 2242 ng_btsocket_rfcomm_receive_uih(ng_btsocket_rfcomm_session_p s, int dlci, 2243 int pf, struct mbuf *m0) 2244 { 2245 ng_btsocket_rfcomm_pcb_p pcb = NULL; 2246 int error = 0; 2247 2248 mtx_assert(&s->session_mtx, MA_OWNED); 2249 2250 NG_BTSOCKET_RFCOMM_INFO( 2251 "%s: Got UIH, session state=%d, flags=%#x, mtu=%d, dlci=%d, pf=%d, len=%d\n", 2252 __func__, s->state, s->flags, s->mtu, dlci, pf, 2253 m0->m_pkthdr.len); 2254 2255 /* XXX should we do it here? Check for session flow control */ 2256 if (s->flags & NG_BTSOCKET_RFCOMM_SESSION_LFC) { 2257 NG_BTSOCKET_RFCOMM_WARN( 2258 "%s: Got UIH with session flow control asserted, state=%d, flags=%#x\n", 2259 __func__, s->state, s->flags); 2260 goto drop; 2261 } 2262 2263 /* Check if we have this dlci */ 2264 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci); 2265 if (pcb == NULL) { 2266 NG_BTSOCKET_RFCOMM_WARN( 2267 "%s: Got UIH for non-existing dlci=%d\n", __func__, dlci); 2268 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_DM,dlci); 2269 goto drop; 2270 } 2271 2272 mtx_lock(&pcb->pcb_mtx); 2273 2274 /* Check dlci state */ 2275 if (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTED) { 2276 NG_BTSOCKET_RFCOMM_WARN( 2277 "%s: Got UIH for dlci=%d in invalid state=%d, flags=%#x\n", 2278 __func__, dlci, pcb->state, pcb->flags); 2279 error = EINVAL; 2280 goto drop1; 2281 } 2282 2283 /* Check dlci flow control */ 2284 if (((pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) && pcb->rx_cred <= 0) || 2285 (pcb->lmodem & RFCOMM_MODEM_FC)) { 2286 NG_BTSOCKET_RFCOMM_ERR( 2287 "%s: Got UIH for dlci=%d with asserted flow control, state=%d, " \ 2288 "flags=%#x, rx_cred=%d, lmodem=%#x\n", 2289 __func__, dlci, pcb->state, pcb->flags, 2290 pcb->rx_cred, pcb->lmodem); 2291 goto drop1; 2292 } 2293 2294 /* Did we get any credits? */ 2295 if ((pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) && pf) { 2296 NG_BTSOCKET_RFCOMM_INFO( 2297 "%s: Got %d more credits for dlci=%d, state=%d, flags=%#x, " \ 2298 "rx_cred=%d, tx_cred=%d\n", 2299 __func__, *mtod(m0, u_int8_t *), dlci, pcb->state, 2300 pcb->flags, pcb->rx_cred, pcb->tx_cred); 2301 2302 pcb->tx_cred += *mtod(m0, u_int8_t *); 2303 m_adj(m0, 1); 2304 2305 /* Send more from the DLC. XXX check for errors? */ 2306 ng_btsocket_rfcomm_pcb_send(pcb, ALOT); 2307 } 2308 2309 /* OK the of the rest of the mbuf is the data */ 2310 if (m0->m_pkthdr.len > 0) { 2311 /* If we are using credit flow control decrease rx_cred here */ 2312 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) { 2313 /* Give remote peer more credits (if needed) */ 2314 if (-- pcb->rx_cred <= RFCOMM_MAX_CREDITS / 2) 2315 ng_btsocket_rfcomm_send_credits(pcb); 2316 else 2317 NG_BTSOCKET_RFCOMM_INFO( 2318 "%s: Remote side still has credits, dlci=%d, state=%d, flags=%#x, " \ 2319 "rx_cred=%d, tx_cred=%d\n", __func__, dlci, pcb->state, pcb->flags, 2320 pcb->rx_cred, pcb->tx_cred); 2321 } 2322 2323 /* Check packet against mtu on dlci */ 2324 if (m0->m_pkthdr.len > pcb->mtu) { 2325 NG_BTSOCKET_RFCOMM_ERR( 2326 "%s: Got oversized UIH for dlci=%d, state=%d, flags=%#x, mtu=%d, len=%d\n", 2327 __func__, dlci, pcb->state, pcb->flags, 2328 pcb->mtu, m0->m_pkthdr.len); 2329 2330 error = EMSGSIZE; 2331 } else if (m0->m_pkthdr.len > sbspace(&pcb->so->so_rcv)) { 2332 2333 /* 2334 * This is really bad. Receive queue on socket does 2335 * not have enough space for the packet. We do not 2336 * have any other choice but drop the packet. 2337 */ 2338 2339 NG_BTSOCKET_RFCOMM_ERR( 2340 "%s: Not enough space in socket receive queue. Dropping UIH for dlci=%d, " \ 2341 "state=%d, flags=%#x, len=%d, space=%ld\n", 2342 __func__, dlci, pcb->state, pcb->flags, 2343 m0->m_pkthdr.len, sbspace(&pcb->so->so_rcv)); 2344 2345 error = ENOBUFS; 2346 } else { 2347 /* Append packet to the socket receive queue */ 2348 sbappend(&pcb->so->so_rcv, m0); 2349 m0 = NULL; 2350 2351 sorwakeup(pcb->so); 2352 } 2353 } 2354 drop1: 2355 mtx_unlock(&pcb->pcb_mtx); 2356 drop: 2357 NG_FREE_M(m0); /* checks for != NULL */ 2358 2359 return (error); 2360 } /* ng_btsocket_rfcomm_receive_uih */ 2361 2362 /* 2363 * Process RFCOMM MCC command (Multiplexor) 2364 * 2365 * From TS 07.10 spec 2366 * 2367 * "5.4.3.1 Information Data 2368 * 2369 * ...The frames (UIH) sent by the initiating station have the C/R bit set 2370 * to 1 and those sent by the responding station have the C/R bit set to 0..." 2371 * 2372 * "5.4.6.2 Operating procedures 2373 * 2374 * Messages always exist in pairs; a command message and a corresponding 2375 * response message. If the C/R bit is set to 1 the message is a command, 2376 * if it is set to 0 the message is a response... 2377 * 2378 * ... 2379 * 2380 * NOTE: Notice that when UIH frames are used to convey information on DLCI 0 2381 * there are at least two different fields that contain a C/R bit, and the 2382 * bits are set of different form. The C/R bit in the Type field shall be set 2383 * as it is stated above, while the C/R bit in the Address field (see subclause 2384 * 5.2.1.2) shall be set as it is described in subclause 5.4.3.1." 2385 */ 2386 2387 static int 2388 ng_btsocket_rfcomm_receive_mcc(ng_btsocket_rfcomm_session_p s, struct mbuf *m0) 2389 { 2390 struct rfcomm_mcc_hdr *hdr = NULL; 2391 u_int8_t cr, type, length; 2392 2393 mtx_assert(&s->session_mtx, MA_OWNED); 2394 2395 /* 2396 * We can access data directly in the first mbuf, because we have 2397 * m_pullup()'ed mbuf chain in ng_btsocket_rfcomm_receive_frame(). 2398 * All MCC commands should fit into single mbuf (except probably TEST). 2399 */ 2400 2401 hdr = mtod(m0, struct rfcomm_mcc_hdr *); 2402 cr = RFCOMM_CR(hdr->type); 2403 type = RFCOMM_MCC_TYPE(hdr->type); 2404 length = RFCOMM_MCC_LENGTH(hdr->length); 2405 2406 /* Check MCC frame length */ 2407 if (sizeof(*hdr) + length != m0->m_pkthdr.len) { 2408 NG_BTSOCKET_RFCOMM_ERR( 2409 "%s: Invalid MCC frame length=%d, len=%d\n", 2410 __func__, length, m0->m_pkthdr.len); 2411 NG_FREE_M(m0); 2412 2413 return (EMSGSIZE); 2414 } 2415 2416 switch (type) { 2417 case RFCOMM_MCC_TEST: 2418 return (ng_btsocket_rfcomm_receive_test(s, m0)); 2419 /* NOT REACHED */ 2420 2421 case RFCOMM_MCC_FCON: 2422 case RFCOMM_MCC_FCOFF: 2423 return (ng_btsocket_rfcomm_receive_fc(s, m0)); 2424 /* NOT REACHED */ 2425 2426 case RFCOMM_MCC_MSC: 2427 return (ng_btsocket_rfcomm_receive_msc(s, m0)); 2428 /* NOT REACHED */ 2429 2430 case RFCOMM_MCC_RPN: 2431 return (ng_btsocket_rfcomm_receive_rpn(s, m0)); 2432 /* NOT REACHED */ 2433 2434 case RFCOMM_MCC_RLS: 2435 return (ng_btsocket_rfcomm_receive_rls(s, m0)); 2436 /* NOT REACHED */ 2437 2438 case RFCOMM_MCC_PN: 2439 return (ng_btsocket_rfcomm_receive_pn(s, m0)); 2440 /* NOT REACHED */ 2441 2442 case RFCOMM_MCC_NSC: 2443 NG_BTSOCKET_RFCOMM_ERR( 2444 "%s: Got MCC NSC, type=%#x, cr=%d, length=%d, session state=%d, flags=%#x, " \ 2445 "mtu=%d, len=%d\n", __func__, RFCOMM_MCC_TYPE(*((u_int8_t *)(hdr + 1))), cr, 2446 length, s->state, s->flags, s->mtu, m0->m_pkthdr.len); 2447 NG_FREE_M(m0); 2448 break; 2449 2450 default: 2451 NG_BTSOCKET_RFCOMM_ERR( 2452 "%s: Got unknown MCC, type=%#x, cr=%d, length=%d, session state=%d, " \ 2453 "flags=%#x, mtu=%d, len=%d\n", 2454 __func__, type, cr, length, s->state, s->flags, 2455 s->mtu, m0->m_pkthdr.len); 2456 2457 /* Reuse mbuf to send NSC */ 2458 hdr = mtod(m0, struct rfcomm_mcc_hdr *); 2459 m0->m_pkthdr.len = m0->m_len = sizeof(*hdr); 2460 2461 /* Create MCC NSC header */ 2462 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_NSC); 2463 hdr->length = RFCOMM_MKLEN8(1); 2464 2465 /* Put back MCC command type we did not like */ 2466 m0->m_data[m0->m_len] = RFCOMM_MKMCC_TYPE(cr, type); 2467 m0->m_pkthdr.len ++; 2468 m0->m_len ++; 2469 2470 /* Send UIH frame */ 2471 return (ng_btsocket_rfcomm_send_uih(s, 2472 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0)); 2473 /* NOT REACHED */ 2474 } 2475 2476 return (0); 2477 } /* ng_btsocket_rfcomm_receive_mcc */ 2478 2479 /* 2480 * Receive RFCOMM TEST MCC command 2481 */ 2482 2483 static int 2484 ng_btsocket_rfcomm_receive_test(ng_btsocket_rfcomm_session_p s, struct mbuf *m0) 2485 { 2486 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr *); 2487 int error = 0; 2488 2489 mtx_assert(&s->session_mtx, MA_OWNED); 2490 2491 NG_BTSOCKET_RFCOMM_INFO( 2492 "%s: Got MCC TEST, cr=%d, length=%d, session state=%d, flags=%#x, mtu=%d, " \ 2493 "len=%d\n", __func__, RFCOMM_CR(hdr->type), RFCOMM_MCC_LENGTH(hdr->length), 2494 s->state, s->flags, s->mtu, m0->m_pkthdr.len); 2495 2496 if (RFCOMM_CR(hdr->type)) { 2497 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_TEST); 2498 error = ng_btsocket_rfcomm_send_uih(s, 2499 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0); 2500 } else 2501 NG_FREE_M(m0); /* XXX ignore response */ 2502 2503 return (error); 2504 } /* ng_btsocket_rfcomm_receive_test */ 2505 2506 /* 2507 * Receive RFCOMM FCON/FCOFF MCC command 2508 */ 2509 2510 static int 2511 ng_btsocket_rfcomm_receive_fc(ng_btsocket_rfcomm_session_p s, struct mbuf *m0) 2512 { 2513 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr *); 2514 u_int8_t type = RFCOMM_MCC_TYPE(hdr->type); 2515 int error = 0; 2516 2517 mtx_assert(&s->session_mtx, MA_OWNED); 2518 2519 /* 2520 * Turn ON/OFF aggregate flow on the entire session. When remote peer 2521 * asserted flow control no transmission shall occur except on dlci 0 2522 * (control channel). 2523 */ 2524 2525 NG_BTSOCKET_RFCOMM_INFO( 2526 "%s: Got MCC FC%s, cr=%d, length=%d, session state=%d, flags=%#x, mtu=%d, " \ 2527 "len=%d\n", __func__, (type == RFCOMM_MCC_FCON)? "ON" : "OFF", 2528 RFCOMM_CR(hdr->type), RFCOMM_MCC_LENGTH(hdr->length), 2529 s->state, s->flags, s->mtu, m0->m_pkthdr.len); 2530 2531 if (RFCOMM_CR(hdr->type)) { 2532 if (type == RFCOMM_MCC_FCON) 2533 s->flags &= ~NG_BTSOCKET_RFCOMM_SESSION_RFC; 2534 else 2535 s->flags |= NG_BTSOCKET_RFCOMM_SESSION_RFC; 2536 2537 hdr->type = RFCOMM_MKMCC_TYPE(0, type); 2538 error = ng_btsocket_rfcomm_send_uih(s, 2539 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0); 2540 } else 2541 NG_FREE_M(m0); /* XXX ignore response */ 2542 2543 return (error); 2544 } /* ng_btsocket_rfcomm_receive_fc */ 2545 2546 /* 2547 * Receive RFCOMM MSC MCC command 2548 */ 2549 2550 static int 2551 ng_btsocket_rfcomm_receive_msc(ng_btsocket_rfcomm_session_p s, struct mbuf *m0) 2552 { 2553 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr*); 2554 struct rfcomm_mcc_msc *msc = (struct rfcomm_mcc_msc *)(hdr+1); 2555 ng_btsocket_rfcomm_pcb_t *pcb = NULL; 2556 int error = 0; 2557 2558 mtx_assert(&s->session_mtx, MA_OWNED); 2559 2560 NG_BTSOCKET_RFCOMM_INFO( 2561 "%s: Got MCC MSC, dlci=%d, cr=%d, length=%d, session state=%d, flags=%#x, " \ 2562 "mtu=%d, len=%d\n", 2563 __func__, RFCOMM_DLCI(msc->address), RFCOMM_CR(hdr->type), 2564 RFCOMM_MCC_LENGTH(hdr->length), s->state, s->flags, 2565 s->mtu, m0->m_pkthdr.len); 2566 2567 if (RFCOMM_CR(hdr->type)) { 2568 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, RFCOMM_DLCI(msc->address)); 2569 if (pcb == NULL) { 2570 NG_BTSOCKET_RFCOMM_WARN( 2571 "%s: Got MSC command for non-existing dlci=%d\n", 2572 __func__, RFCOMM_DLCI(msc->address)); 2573 NG_FREE_M(m0); 2574 2575 return (ENOENT); 2576 } 2577 2578 mtx_lock(&pcb->pcb_mtx); 2579 2580 if (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTING && 2581 pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTED) { 2582 NG_BTSOCKET_RFCOMM_WARN( 2583 "%s: Got MSC on dlci=%d in invalid state=%d\n", 2584 __func__, RFCOMM_DLCI(msc->address), 2585 pcb->state); 2586 2587 mtx_unlock(&pcb->pcb_mtx); 2588 NG_FREE_M(m0); 2589 2590 return (EINVAL); 2591 } 2592 2593 pcb->rmodem = msc->modem; /* Update remote port signals */ 2594 2595 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_MSC); 2596 error = ng_btsocket_rfcomm_send_uih(s, 2597 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0); 2598 2599 #if 0 /* YYY */ 2600 /* Send more data from DLC. XXX check for errors? */ 2601 if (!(pcb->rmodem & RFCOMM_MODEM_FC) && 2602 !(pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC)) 2603 ng_btsocket_rfcomm_pcb_send(pcb, ALOT); 2604 #endif /* YYY */ 2605 2606 mtx_unlock(&pcb->pcb_mtx); 2607 } else 2608 NG_FREE_M(m0); /* XXX ignore response */ 2609 2610 return (error); 2611 } /* ng_btsocket_rfcomm_receive_msc */ 2612 2613 /* 2614 * Receive RFCOMM RPN MCC command 2615 * XXX FIXME do we need htole16/le16toh for RPN param_mask? 2616 */ 2617 2618 static int 2619 ng_btsocket_rfcomm_receive_rpn(ng_btsocket_rfcomm_session_p s, struct mbuf *m0) 2620 { 2621 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr *); 2622 struct rfcomm_mcc_rpn *rpn = (struct rfcomm_mcc_rpn *)(hdr + 1); 2623 int error = 0; 2624 u_int16_t param_mask; 2625 u_int8_t bit_rate, data_bits, stop_bits, parity, 2626 flow_control, xon_char, xoff_char; 2627 2628 mtx_assert(&s->session_mtx, MA_OWNED); 2629 2630 NG_BTSOCKET_RFCOMM_INFO( 2631 "%s: Got MCC RPN, dlci=%d, cr=%d, length=%d, session state=%d, flags=%#x, " \ 2632 "mtu=%d, len=%d\n", 2633 __func__, RFCOMM_DLCI(rpn->dlci), RFCOMM_CR(hdr->type), 2634 RFCOMM_MCC_LENGTH(hdr->length), s->state, s->flags, 2635 s->mtu, m0->m_pkthdr.len); 2636 2637 if (RFCOMM_CR(hdr->type)) { 2638 param_mask = RFCOMM_RPN_PM_ALL; 2639 2640 if (RFCOMM_MCC_LENGTH(hdr->length) == 1) { 2641 /* Request - return default setting */ 2642 bit_rate = RFCOMM_RPN_BR_115200; 2643 data_bits = RFCOMM_RPN_DATA_8; 2644 stop_bits = RFCOMM_RPN_STOP_1; 2645 parity = RFCOMM_RPN_PARITY_NONE; 2646 flow_control = RFCOMM_RPN_FLOW_NONE; 2647 xon_char = RFCOMM_RPN_XON_CHAR; 2648 xoff_char = RFCOMM_RPN_XOFF_CHAR; 2649 } else { 2650 /* 2651 * Ignore/accept bit_rate, 8 bits, 1 stop bit, no 2652 * parity, no flow control lines, default XON/XOFF 2653 * chars. 2654 */ 2655 2656 bit_rate = rpn->bit_rate; 2657 rpn->param_mask = le16toh(rpn->param_mask); /* XXX */ 2658 2659 data_bits = RFCOMM_RPN_DATA_BITS(rpn->line_settings); 2660 if (rpn->param_mask & RFCOMM_RPN_PM_DATA && 2661 data_bits != RFCOMM_RPN_DATA_8) { 2662 data_bits = RFCOMM_RPN_DATA_8; 2663 param_mask ^= RFCOMM_RPN_PM_DATA; 2664 } 2665 2666 stop_bits = RFCOMM_RPN_STOP_BITS(rpn->line_settings); 2667 if (rpn->param_mask & RFCOMM_RPN_PM_STOP && 2668 stop_bits != RFCOMM_RPN_STOP_1) { 2669 stop_bits = RFCOMM_RPN_STOP_1; 2670 param_mask ^= RFCOMM_RPN_PM_STOP; 2671 } 2672 2673 parity = RFCOMM_RPN_PARITY(rpn->line_settings); 2674 if (rpn->param_mask & RFCOMM_RPN_PM_PARITY && 2675 parity != RFCOMM_RPN_PARITY_NONE) { 2676 parity = RFCOMM_RPN_PARITY_NONE; 2677 param_mask ^= RFCOMM_RPN_PM_PARITY; 2678 } 2679 2680 flow_control = rpn->flow_control; 2681 if (rpn->param_mask & RFCOMM_RPN_PM_FLOW && 2682 flow_control != RFCOMM_RPN_FLOW_NONE) { 2683 flow_control = RFCOMM_RPN_FLOW_NONE; 2684 param_mask ^= RFCOMM_RPN_PM_FLOW; 2685 } 2686 2687 xon_char = rpn->xon_char; 2688 if (rpn->param_mask & RFCOMM_RPN_PM_XON && 2689 xon_char != RFCOMM_RPN_XON_CHAR) { 2690 xon_char = RFCOMM_RPN_XON_CHAR; 2691 param_mask ^= RFCOMM_RPN_PM_XON; 2692 } 2693 2694 xoff_char = rpn->xoff_char; 2695 if (rpn->param_mask & RFCOMM_RPN_PM_XOFF && 2696 xoff_char != RFCOMM_RPN_XOFF_CHAR) { 2697 xoff_char = RFCOMM_RPN_XOFF_CHAR; 2698 param_mask ^= RFCOMM_RPN_PM_XOFF; 2699 } 2700 } 2701 2702 rpn->bit_rate = bit_rate; 2703 rpn->line_settings = RFCOMM_MKRPN_LINE_SETTINGS(data_bits, 2704 stop_bits, parity); 2705 rpn->flow_control = flow_control; 2706 rpn->xon_char = xon_char; 2707 rpn->xoff_char = xoff_char; 2708 rpn->param_mask = htole16(param_mask); /* XXX */ 2709 2710 m0->m_pkthdr.len = m0->m_len = sizeof(*hdr) + sizeof(*rpn); 2711 2712 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_RPN); 2713 error = ng_btsocket_rfcomm_send_uih(s, 2714 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0); 2715 } else 2716 NG_FREE_M(m0); /* XXX ignore response */ 2717 2718 return (error); 2719 } /* ng_btsocket_rfcomm_receive_rpn */ 2720 2721 /* 2722 * Receive RFCOMM RLS MCC command 2723 */ 2724 2725 static int 2726 ng_btsocket_rfcomm_receive_rls(ng_btsocket_rfcomm_session_p s, struct mbuf *m0) 2727 { 2728 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr *); 2729 struct rfcomm_mcc_rls *rls = (struct rfcomm_mcc_rls *)(hdr + 1); 2730 int error = 0; 2731 2732 mtx_assert(&s->session_mtx, MA_OWNED); 2733 2734 /* 2735 * XXX FIXME Do we have to do anything else here? Remote peer tries to 2736 * tell us something about DLCI. Just report what we have received and 2737 * return back received values as required by TS 07.10 spec. 2738 */ 2739 2740 NG_BTSOCKET_RFCOMM_INFO( 2741 "%s: Got MCC RLS, dlci=%d, status=%#x, cr=%d, length=%d, session state=%d, " \ 2742 "flags=%#x, mtu=%d, len=%d\n", 2743 __func__, RFCOMM_DLCI(rls->address), rls->status, 2744 RFCOMM_CR(hdr->type), RFCOMM_MCC_LENGTH(hdr->length), 2745 s->state, s->flags, s->mtu, m0->m_pkthdr.len); 2746 2747 if (RFCOMM_CR(hdr->type)) { 2748 if (rls->status & 0x1) 2749 NG_BTSOCKET_RFCOMM_ERR( 2750 "%s: Got RLS dlci=%d, error=%#x\n", __func__, RFCOMM_DLCI(rls->address), 2751 rls->status >> 1); 2752 2753 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_RLS); 2754 error = ng_btsocket_rfcomm_send_uih(s, 2755 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0); 2756 } else 2757 NG_FREE_M(m0); /* XXX ignore responses */ 2758 2759 return (error); 2760 } /* ng_btsocket_rfcomm_receive_rls */ 2761 2762 /* 2763 * Receive RFCOMM PN MCC command 2764 */ 2765 2766 static int 2767 ng_btsocket_rfcomm_receive_pn(ng_btsocket_rfcomm_session_p s, struct mbuf *m0) 2768 { 2769 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr*); 2770 struct rfcomm_mcc_pn *pn = (struct rfcomm_mcc_pn *)(hdr+1); 2771 ng_btsocket_rfcomm_pcb_t *pcb = NULL; 2772 int error = 0; 2773 2774 mtx_assert(&s->session_mtx, MA_OWNED); 2775 2776 NG_BTSOCKET_RFCOMM_INFO( 2777 "%s: Got MCC PN, dlci=%d, cr=%d, length=%d, flow_control=%#x, priority=%d, " \ 2778 "ack_timer=%d, mtu=%d, max_retrans=%d, credits=%d, session state=%d, " \ 2779 "flags=%#x, session mtu=%d, len=%d\n", 2780 __func__, pn->dlci, RFCOMM_CR(hdr->type), 2781 RFCOMM_MCC_LENGTH(hdr->length), pn->flow_control, pn->priority, 2782 pn->ack_timer, le16toh(pn->mtu), pn->max_retrans, pn->credits, 2783 s->state, s->flags, s->mtu, m0->m_pkthdr.len); 2784 2785 if (pn->dlci == 0) { 2786 NG_BTSOCKET_RFCOMM_ERR("%s: Zero dlci in MCC PN\n", __func__); 2787 NG_FREE_M(m0); 2788 2789 return (EINVAL); 2790 } 2791 2792 /* Check if we have this dlci */ 2793 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, pn->dlci); 2794 if (pcb != NULL) { 2795 mtx_lock(&pcb->pcb_mtx); 2796 2797 if (RFCOMM_CR(hdr->type)) { 2798 /* PN Request */ 2799 ng_btsocket_rfcomm_set_pn(pcb, 1, pn->flow_control, 2800 pn->credits, pn->mtu); 2801 2802 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) { 2803 pn->flow_control = 0xe0; 2804 pn->credits = RFCOMM_DEFAULT_CREDITS; 2805 } else { 2806 pn->flow_control = 0; 2807 pn->credits = 0; 2808 } 2809 2810 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_PN); 2811 error = ng_btsocket_rfcomm_send_uih(s, 2812 RFCOMM_MKADDRESS(INITIATOR(s), 0), 2813 0, 0, m0); 2814 } else { 2815 /* PN Response - proceed with SABM. Timeout still set */ 2816 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONFIGURING) { 2817 ng_btsocket_rfcomm_set_pn(pcb, 0, 2818 pn->flow_control, pn->credits, pn->mtu); 2819 2820 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTING; 2821 error = ng_btsocket_rfcomm_send_command(s, 2822 RFCOMM_FRAME_SABM, pn->dlci); 2823 } else 2824 NG_BTSOCKET_RFCOMM_WARN( 2825 "%s: Got PN response for dlci=%d in invalid state=%d\n", 2826 __func__, pn->dlci, pcb->state); 2827 2828 NG_FREE_M(m0); 2829 } 2830 2831 mtx_unlock(&pcb->pcb_mtx); 2832 } else if (RFCOMM_CR(hdr->type)) { 2833 /* PN request to non-existing dlci - incomming connection */ 2834 pcb = ng_btsocket_rfcomm_connect_ind(s, 2835 RFCOMM_SRVCHANNEL(pn->dlci)); 2836 if (pcb != NULL) { 2837 mtx_lock(&pcb->pcb_mtx); 2838 2839 pcb->dlci = pn->dlci; 2840 2841 ng_btsocket_rfcomm_set_pn(pcb, 1, pn->flow_control, 2842 pn->credits, pn->mtu); 2843 2844 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) { 2845 pn->flow_control = 0xe0; 2846 pn->credits = RFCOMM_DEFAULT_CREDITS; 2847 } else { 2848 pn->flow_control = 0; 2849 pn->credits = 0; 2850 } 2851 2852 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_PN); 2853 error = ng_btsocket_rfcomm_send_uih(s, 2854 RFCOMM_MKADDRESS(INITIATOR(s), 0), 2855 0, 0, m0); 2856 2857 if (error == 0) { 2858 ng_btsocket_rfcomm_timeout(pcb); 2859 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTING; 2860 soisconnecting(pcb->so); 2861 } else 2862 ng_btsocket_rfcomm_pcb_kill(pcb, error); 2863 2864 mtx_unlock(&pcb->pcb_mtx); 2865 } else { 2866 /* Nobody is listen()ing on this channel */ 2867 error = ng_btsocket_rfcomm_send_command(s, 2868 RFCOMM_FRAME_DM, pn->dlci); 2869 NG_FREE_M(m0); 2870 } 2871 } else 2872 NG_FREE_M(m0); /* XXX ignore response to non-existing dlci */ 2873 2874 return (error); 2875 } /* ng_btsocket_rfcomm_receive_pn */ 2876 2877 /* 2878 * Set PN parameters for dlci. Caller must hold pcb->pcb_mtx. 2879 * 2880 * From Bluetooth spec. 2881 * 2882 * "... The CL1 - CL4 field is completely redefined. (In TS07.10 this defines 2883 * the convergence layer to use, which is not applicable to RFCOMM. In RFCOMM, 2884 * in Bluetooth versions up to 1.0B, this field was forced to 0). 2885 * 2886 * In the PN request sent prior to a DLC establishment, this field must contain 2887 * the value 15 (0xF), indicating support of credit based flow control in the 2888 * sender. See Table 5.3 below. If the PN response contains any other value 2889 * than 14 (0xE) in this field, it is inferred that the peer RFCOMM entity is 2890 * not supporting the credit based flow control feature. (This is only possible 2891 * if the peer RFCOMM implementation is only conforming to Bluetooth version 2892 * 1.0B.) If a PN request is sent on an already open DLC, then this field must 2893 * contain the value zero; it is not possible to set initial credits more 2894 * than once per DLC activation. A responding implementation must set this 2895 * field in the PN response to 14 (0xE), if (and only if) the value in the PN 2896 * request was 15..." 2897 */ 2898 2899 static void 2900 ng_btsocket_rfcomm_set_pn(ng_btsocket_rfcomm_pcb_p pcb, u_int8_t cr, 2901 u_int8_t flow_control, u_int8_t credits, u_int16_t mtu) 2902 { 2903 mtx_assert(&pcb->pcb_mtx, MA_OWNED); 2904 2905 pcb->mtu = le16toh(mtu); 2906 2907 if (cr) { 2908 if (flow_control == 0xf0) { 2909 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_CFC; 2910 pcb->tx_cred = credits; 2911 } else { 2912 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_CFC; 2913 pcb->tx_cred = 0; 2914 } 2915 } else { 2916 if (flow_control == 0xe0) { 2917 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_CFC; 2918 pcb->tx_cred = credits; 2919 } else { 2920 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_CFC; 2921 pcb->tx_cred = 0; 2922 } 2923 } 2924 2925 NG_BTSOCKET_RFCOMM_INFO( 2926 "%s: cr=%d, dlci=%d, state=%d, flags=%#x, mtu=%d, rx_cred=%d, tx_cred=%d\n", 2927 __func__, cr, pcb->dlci, pcb->state, pcb->flags, pcb->mtu, 2928 pcb->rx_cred, pcb->tx_cred); 2929 } /* ng_btsocket_rfcomm_set_pn */ 2930 2931 /* 2932 * Send RFCOMM SABM/DISC/UA/DM frames. Caller must hold s->session_mtx 2933 */ 2934 2935 static int 2936 ng_btsocket_rfcomm_send_command(ng_btsocket_rfcomm_session_p s, 2937 u_int8_t type, u_int8_t dlci) 2938 { 2939 struct rfcomm_cmd_hdr *hdr = NULL; 2940 struct mbuf *m = NULL; 2941 int cr; 2942 2943 mtx_assert(&s->session_mtx, MA_OWNED); 2944 2945 NG_BTSOCKET_RFCOMM_INFO( 2946 "%s: Sending command type %#x, session state=%d, flags=%#x, mtu=%d, dlci=%d\n", 2947 __func__, type, s->state, s->flags, s->mtu, dlci); 2948 2949 switch (type) { 2950 case RFCOMM_FRAME_SABM: 2951 case RFCOMM_FRAME_DISC: 2952 cr = INITIATOR(s); 2953 break; 2954 2955 case RFCOMM_FRAME_UA: 2956 case RFCOMM_FRAME_DM: 2957 cr = !INITIATOR(s); 2958 break; 2959 2960 default: 2961 panic("%s: Invalid frame type=%#x\n", __func__, type); 2962 return (EINVAL); 2963 /* NOT REACHED */ 2964 } 2965 2966 MGETHDR(m, M_DONTWAIT, MT_DATA); 2967 if (m == NULL) 2968 return (ENOBUFS); 2969 2970 m->m_pkthdr.len = m->m_len = sizeof(*hdr); 2971 2972 hdr = mtod(m, struct rfcomm_cmd_hdr *); 2973 hdr->address = RFCOMM_MKADDRESS(cr, dlci); 2974 hdr->control = RFCOMM_MKCONTROL(type, 1); 2975 hdr->length = RFCOMM_MKLEN8(0); 2976 hdr->fcs = ng_btsocket_rfcomm_fcs3((u_int8_t *) hdr); 2977 2978 NG_BT_MBUFQ_ENQUEUE(&s->outq, m); 2979 2980 return (0); 2981 } /* ng_btsocket_rfcomm_send_command */ 2982 2983 /* 2984 * Send RFCOMM UIH frame. Caller must hold s->session_mtx 2985 */ 2986 2987 static int 2988 ng_btsocket_rfcomm_send_uih(ng_btsocket_rfcomm_session_p s, u_int8_t address, 2989 u_int8_t pf, u_int8_t credits, struct mbuf *data) 2990 { 2991 struct rfcomm_frame_hdr *hdr = NULL; 2992 struct mbuf *m = NULL, *mcrc = NULL; 2993 u_int16_t length; 2994 2995 mtx_assert(&s->session_mtx, MA_OWNED); 2996 2997 MGETHDR(m, M_DONTWAIT, MT_DATA); 2998 if (m == NULL) { 2999 NG_FREE_M(data); 3000 return (ENOBUFS); 3001 } 3002 m->m_pkthdr.len = m->m_len = sizeof(*hdr); 3003 3004 MGET(mcrc, M_DONTWAIT, MT_DATA); 3005 if (mcrc == NULL) { 3006 NG_FREE_M(data); 3007 return (ENOBUFS); 3008 } 3009 mcrc->m_len = 1; 3010 3011 /* Fill UIH frame header */ 3012 hdr = mtod(m, struct rfcomm_frame_hdr *); 3013 hdr->address = address; 3014 hdr->control = RFCOMM_MKCONTROL(RFCOMM_FRAME_UIH, pf); 3015 3016 /* Calculate FCS */ 3017 mcrc->m_data[0] = ng_btsocket_rfcomm_fcs2((u_int8_t *) hdr); 3018 3019 /* Put length back */ 3020 length = (data != NULL)? data->m_pkthdr.len : 0; 3021 if (length > 127) { 3022 u_int16_t l = htole16(RFCOMM_MKLEN16(length)); 3023 3024 bcopy(&l, &hdr->length, sizeof(l)); 3025 m->m_pkthdr.len ++; 3026 m->m_len ++; 3027 } else 3028 hdr->length = RFCOMM_MKLEN8(length); 3029 3030 if (pf) { 3031 m->m_data[m->m_len] = credits; 3032 m->m_pkthdr.len ++; 3033 m->m_len ++; 3034 } 3035 3036 /* Add payload */ 3037 if (data != NULL) { 3038 m_cat(m, data); 3039 m->m_pkthdr.len += length; 3040 } 3041 3042 /* Put FCS back */ 3043 m_cat(m, mcrc); 3044 m->m_pkthdr.len ++; 3045 3046 NG_BTSOCKET_RFCOMM_INFO( 3047 "%s: Sending UIH state=%d, flags=%#x, address=%d, length=%d, pf=%d, " \ 3048 "credits=%d, len=%d\n", 3049 __func__, s->state, s->flags, address, length, pf, credits, 3050 m->m_pkthdr.len); 3051 3052 NG_BT_MBUFQ_ENQUEUE(&s->outq, m); 3053 3054 return (0); 3055 } /* ng_btsocket_rfcomm_send_uih */ 3056 3057 /* 3058 * Send MSC request. Caller must hold pcb->pcb_mtx and pcb->session->session_mtx 3059 */ 3060 3061 static int 3062 ng_btsocket_rfcomm_send_msc(ng_btsocket_rfcomm_pcb_p pcb) 3063 { 3064 struct mbuf *m = NULL; 3065 struct rfcomm_mcc_hdr *hdr = NULL; 3066 struct rfcomm_mcc_msc *msc = NULL; 3067 3068 mtx_assert(&pcb->session->session_mtx, MA_OWNED); 3069 mtx_assert(&pcb->pcb_mtx, MA_OWNED); 3070 3071 MGETHDR(m, M_DONTWAIT, MT_DATA); 3072 if (m == NULL) 3073 return (ENOBUFS); 3074 3075 m->m_pkthdr.len = m->m_len = sizeof(*hdr) + sizeof(*msc); 3076 3077 hdr = mtod(m, struct rfcomm_mcc_hdr *); 3078 msc = (struct rfcomm_mcc_msc *)(hdr + 1); 3079 3080 hdr->type = RFCOMM_MKMCC_TYPE(1, RFCOMM_MCC_MSC); 3081 hdr->length = RFCOMM_MKLEN8(sizeof(*msc)); 3082 3083 msc->address = RFCOMM_MKADDRESS(1, pcb->dlci); 3084 msc->modem = pcb->lmodem; 3085 3086 NG_BTSOCKET_RFCOMM_INFO( 3087 "%s: Sending MSC dlci=%d, state=%d, flags=%#x, address=%d, modem=%#x\n", 3088 __func__, pcb->dlci, pcb->state, pcb->flags, msc->address, 3089 msc->modem); 3090 3091 return (ng_btsocket_rfcomm_send_uih(pcb->session, 3092 RFCOMM_MKADDRESS(INITIATOR(pcb->session), 0), 0, 0, m)); 3093 } /* ng_btsocket_rfcomm_send_msc */ 3094 3095 /* 3096 * Send PN request. Caller must hold pcb->pcb_mtx and pcb->session->session_mtx 3097 */ 3098 3099 static int 3100 ng_btsocket_rfcomm_send_pn(ng_btsocket_rfcomm_pcb_p pcb) 3101 { 3102 struct mbuf *m = NULL; 3103 struct rfcomm_mcc_hdr *hdr = NULL; 3104 struct rfcomm_mcc_pn *pn = NULL; 3105 3106 mtx_assert(&pcb->session->session_mtx, MA_OWNED); 3107 mtx_assert(&pcb->pcb_mtx, MA_OWNED); 3108 3109 MGETHDR(m, M_DONTWAIT, MT_DATA); 3110 if (m == NULL) 3111 return (ENOBUFS); 3112 3113 m->m_pkthdr.len = m->m_len = sizeof(*hdr) + sizeof(*pn); 3114 3115 hdr = mtod(m, struct rfcomm_mcc_hdr *); 3116 pn = (struct rfcomm_mcc_pn *)(hdr + 1); 3117 3118 hdr->type = RFCOMM_MKMCC_TYPE(1, RFCOMM_MCC_PN); 3119 hdr->length = RFCOMM_MKLEN8(sizeof(*pn)); 3120 3121 pn->dlci = pcb->dlci; 3122 3123 /* 3124 * Set default DLCI priority as described in GSM 07.10 3125 * (ETSI TS 101 369) clause 5.6 page 42 3126 */ 3127 3128 pn->priority = (pcb->dlci < 56)? (((pcb->dlci >> 3) << 3) + 7) : 61; 3129 pn->ack_timer = 0; 3130 pn->mtu = htole16(pcb->mtu); 3131 pn->max_retrans = 0; 3132 3133 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) { 3134 pn->flow_control = 0xf0; 3135 pn->credits = pcb->rx_cred; 3136 } else { 3137 pn->flow_control = 0; 3138 pn->credits = 0; 3139 } 3140 3141 NG_BTSOCKET_RFCOMM_INFO( 3142 "%s: Sending PN dlci=%d, state=%d, flags=%#x, mtu=%d, flow_control=%#x, " \ 3143 "credits=%d\n", __func__, pcb->dlci, pcb->state, pcb->flags, pcb->mtu, 3144 pn->flow_control, pn->credits); 3145 3146 return (ng_btsocket_rfcomm_send_uih(pcb->session, 3147 RFCOMM_MKADDRESS(INITIATOR(pcb->session), 0), 0, 0, m)); 3148 } /* ng_btsocket_rfcomm_send_pn */ 3149 3150 /* 3151 * Calculate and send credits based on available space in receive buffer 3152 */ 3153 3154 static int 3155 ng_btsocket_rfcomm_send_credits(ng_btsocket_rfcomm_pcb_p pcb) 3156 { 3157 int error = 0; 3158 u_int8_t credits; 3159 3160 mtx_assert(&pcb->pcb_mtx, MA_OWNED); 3161 mtx_assert(&pcb->session->session_mtx, MA_OWNED); 3162 3163 NG_BTSOCKET_RFCOMM_INFO( 3164 "%s: Sending more credits, dlci=%d, state=%d, flags=%#x, mtu=%d, " \ 3165 "space=%ld, tx_cred=%d, rx_cred=%d\n", 3166 __func__, pcb->dlci, pcb->state, pcb->flags, pcb->mtu, 3167 sbspace(&pcb->so->so_rcv), pcb->tx_cred, pcb->rx_cred); 3168 3169 credits = sbspace(&pcb->so->so_rcv) / pcb->mtu; 3170 if (credits > 0) { 3171 if (pcb->rx_cred + credits > RFCOMM_MAX_CREDITS) 3172 credits = RFCOMM_MAX_CREDITS - pcb->rx_cred; 3173 3174 error = ng_btsocket_rfcomm_send_uih( 3175 pcb->session, 3176 RFCOMM_MKADDRESS(INITIATOR(pcb->session), 3177 pcb->dlci), 1, credits, NULL); 3178 if (error == 0) { 3179 pcb->rx_cred += credits; 3180 3181 NG_BTSOCKET_RFCOMM_INFO( 3182 "%s: Gave remote side %d more credits, dlci=%d, state=%d, flags=%#x, " \ 3183 "rx_cred=%d, tx_cred=%d\n", __func__, credits, pcb->dlci, pcb->state, 3184 pcb->flags, pcb->rx_cred, pcb->tx_cred); 3185 } else 3186 NG_BTSOCKET_RFCOMM_ERR( 3187 "%s: Could not send credits, error=%d, dlci=%d, state=%d, flags=%#x, " \ 3188 "mtu=%d, space=%ld, tx_cred=%d, rx_cred=%d\n", 3189 __func__, error, pcb->dlci, pcb->state, 3190 pcb->flags, pcb->mtu, sbspace(&pcb->so->so_rcv), 3191 pcb->tx_cred, pcb->rx_cred); 3192 } 3193 3194 return (error); 3195 } /* ng_btsocket_rfcomm_send_credits */ 3196 3197 /***************************************************************************** 3198 ***************************************************************************** 3199 ** RFCOMM DLCs 3200 ***************************************************************************** 3201 *****************************************************************************/ 3202 3203 /* 3204 * Send data from socket send buffer 3205 * Caller must hold pcb->pcb_mtx and pcb->session->session_mtx 3206 */ 3207 3208 static int 3209 ng_btsocket_rfcomm_pcb_send(ng_btsocket_rfcomm_pcb_p pcb, int limit) 3210 { 3211 struct mbuf *m = NULL; 3212 int sent, length, error; 3213 3214 mtx_assert(&pcb->session->session_mtx, MA_OWNED); 3215 mtx_assert(&pcb->pcb_mtx, MA_OWNED); 3216 3217 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) 3218 limit = min(limit, pcb->tx_cred); 3219 else if (!(pcb->rmodem & RFCOMM_MODEM_FC)) 3220 limit = min(limit, RFCOMM_MAX_CREDITS); /* XXX ??? */ 3221 else 3222 limit = 0; 3223 3224 if (limit == 0) { 3225 NG_BTSOCKET_RFCOMM_INFO( 3226 "%s: Could not send - remote flow control asserted, dlci=%d, flags=%#x, " \ 3227 "rmodem=%#x, tx_cred=%d\n", 3228 __func__, pcb->dlci, pcb->flags, pcb->rmodem, 3229 pcb->tx_cred); 3230 3231 return (0); 3232 } 3233 3234 for (error = 0, sent = 0; sent < limit; sent ++) { 3235 length = min(pcb->mtu, pcb->so->so_snd.sb_cc); 3236 if (length == 0) 3237 break; 3238 3239 /* Get the chunk from the socket's send buffer */ 3240 m = ng_btsocket_rfcomm_prepare_packet(&pcb->so->so_snd, length); 3241 if (m == NULL) { 3242 error = ENOBUFS; 3243 break; 3244 } 3245 3246 sbdrop(&pcb->so->so_snd, length); 3247 3248 error = ng_btsocket_rfcomm_send_uih(pcb->session, 3249 RFCOMM_MKADDRESS(INITIATOR(pcb->session), 3250 pcb->dlci), 0, 0, m); 3251 if (error != 0) 3252 break; 3253 } 3254 3255 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) 3256 pcb->tx_cred -= sent; 3257 3258 if (error == 0 && sent > 0) { 3259 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_SENDING; 3260 sowwakeup(pcb->so); 3261 } 3262 3263 return (error); 3264 } /* ng_btsocket_rfcomm_pcb_send */ 3265 3266 /* 3267 * Unlink and disconnect DLC. If ng_btsocket_rfcomm_pcb_kill() returns 3268 * non zero value than socket has no reference and has to be detached. 3269 * Caller must hold pcb->pcb_mtx and pcb->session->session_mtx 3270 */ 3271 3272 static void 3273 ng_btsocket_rfcomm_pcb_kill(ng_btsocket_rfcomm_pcb_p pcb, int error) 3274 { 3275 ng_btsocket_rfcomm_session_p s = pcb->session; 3276 3277 NG_BTSOCKET_RFCOMM_INFO( 3278 "%s: Killing DLC, so=%p, dlci=%d, state=%d, flags=%#x, error=%d\n", 3279 __func__, pcb->so, pcb->dlci, pcb->state, pcb->flags, error); 3280 3281 if (pcb->session == NULL) 3282 panic("%s: DLC without session, pcb=%p, state=%d, flags=%#x\n", 3283 __func__, pcb, pcb->state, pcb->flags); 3284 3285 mtx_assert(&pcb->session->session_mtx, MA_OWNED); 3286 mtx_assert(&pcb->pcb_mtx, MA_OWNED); 3287 3288 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO) 3289 ng_btsocket_rfcomm_untimeout(pcb); 3290 3291 /* Detach DLC from the session. Does not matter which state DLC in */ 3292 LIST_REMOVE(pcb, session_next); 3293 pcb->session = NULL; 3294 3295 /* Change DLC state and wakeup all sleepers */ 3296 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CLOSED; 3297 pcb->so->so_error = error; 3298 soisdisconnected(pcb->so); 3299 wakeup(&pcb->state); 3300 3301 /* Check if we have any DLCs left on the session */ 3302 if (LIST_EMPTY(&s->dlcs) && INITIATOR(s)) { 3303 NG_BTSOCKET_RFCOMM_INFO( 3304 "%s: Disconnecting session, state=%d, flags=%#x, mtu=%d\n", 3305 __func__, s->state, s->flags, s->mtu); 3306 3307 switch (s->state) { 3308 case NG_BTSOCKET_RFCOMM_SESSION_CLOSED: 3309 case NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING: 3310 /* 3311 * Do not have to do anything here. We can get here 3312 * when L2CAP connection was terminated or we have 3313 * received DISC on multiplexor channel 3314 */ 3315 break; 3316 3317 case NG_BTSOCKET_RFCOMM_SESSION_OPEN: 3318 /* Send DISC on multiplexor channel */ 3319 error = ng_btsocket_rfcomm_send_command(s, 3320 RFCOMM_FRAME_DISC, 0); 3321 if (error == 0) { 3322 s->state = NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING; 3323 break; 3324 } 3325 /* FALL THROUGH */ 3326 3327 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTING: 3328 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED: 3329 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED; 3330 break; 3331 3332 /* case NG_BTSOCKET_RFCOMM_SESSION_LISTENING: */ 3333 default: 3334 panic("%s: Invalid session state=%d, flags=%#x\n", 3335 __func__, s->state, s->flags); 3336 break; 3337 } 3338 3339 ng_btsocket_rfcomm_task_wakeup(); 3340 } 3341 } /* ng_btsocket_rfcomm_pcb_kill */ 3342 3343 /* 3344 * Look for RFCOMM socket with given channel and source address 3345 */ 3346 3347 static ng_btsocket_rfcomm_pcb_p 3348 ng_btsocket_rfcomm_pcb_by_channel(bdaddr_p src, int channel) 3349 { 3350 ng_btsocket_rfcomm_pcb_p pcb = NULL; 3351 3352 mtx_lock(&ng_btsocket_rfcomm_sockets_mtx); 3353 3354 LIST_FOREACH(pcb, &ng_btsocket_rfcomm_sockets, next) 3355 if (pcb->channel == channel && 3356 bcmp(&pcb->src, src, sizeof(*src)) == 0) 3357 break; 3358 3359 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx); 3360 3361 return (pcb); 3362 } /* ng_btsocket_rfcomm_pcb_by_channel */ 3363 3364 /* 3365 * Look for given dlci for given RFCOMM session. Caller must hold s->session_mtx 3366 */ 3367 3368 static ng_btsocket_rfcomm_pcb_p 3369 ng_btsocket_rfcomm_pcb_by_dlci(ng_btsocket_rfcomm_session_p s, int dlci) 3370 { 3371 ng_btsocket_rfcomm_pcb_p pcb = NULL; 3372 3373 mtx_assert(&s->session_mtx, MA_OWNED); 3374 3375 LIST_FOREACH(pcb, &s->dlcs, session_next) 3376 if (pcb->dlci == dlci) 3377 break; 3378 3379 return (pcb); 3380 } /* ng_btsocket_rfcomm_pcb_by_dlci */ 3381 3382 /* 3383 * Look for socket that listens on given src address and given channel 3384 */ 3385 3386 static ng_btsocket_rfcomm_pcb_p 3387 ng_btsocket_rfcomm_pcb_listener(bdaddr_p src, int channel) 3388 { 3389 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb1 = NULL; 3390 3391 mtx_lock(&ng_btsocket_rfcomm_sockets_mtx); 3392 3393 LIST_FOREACH(pcb, &ng_btsocket_rfcomm_sockets, next) { 3394 if (pcb->channel != channel || 3395 !(pcb->so->so_options & SO_ACCEPTCONN)) 3396 continue; 3397 3398 if (bcmp(&pcb->src, src, sizeof(*src)) == 0) 3399 break; 3400 3401 if (bcmp(&pcb->src, NG_HCI_BDADDR_ANY, sizeof(bdaddr_t)) == 0) 3402 pcb1 = pcb; 3403 } 3404 3405 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx); 3406 3407 return ((pcb != NULL)? pcb : pcb1); 3408 } /* ng_btsocket_rfcomm_pcb_listener */ 3409 3410 /***************************************************************************** 3411 ***************************************************************************** 3412 ** Misc. functions 3413 ***************************************************************************** 3414 *****************************************************************************/ 3415 3416 /* 3417 * Set timeout. Caller MUST hold pcb_mtx 3418 */ 3419 3420 static void 3421 ng_btsocket_rfcomm_timeout(ng_btsocket_rfcomm_pcb_p pcb) 3422 { 3423 mtx_assert(&pcb->pcb_mtx, MA_OWNED); 3424 3425 if (!(pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)) { 3426 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_TIMO; 3427 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT; 3428 pcb->timo = timeout(ng_btsocket_rfcomm_process_timeout, pcb, 3429 ng_btsocket_rfcomm_timo * hz); 3430 } else 3431 panic("%s: Duplicated socket timeout?!\n", __func__); 3432 } /* ng_btsocket_rfcomm_timeout */ 3433 3434 /* 3435 * Unset pcb timeout. Caller MUST hold pcb_mtx 3436 */ 3437 3438 static void 3439 ng_btsocket_rfcomm_untimeout(ng_btsocket_rfcomm_pcb_p pcb) 3440 { 3441 mtx_assert(&pcb->pcb_mtx, MA_OWNED); 3442 3443 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO) { 3444 untimeout(ng_btsocket_rfcomm_process_timeout, pcb, pcb->timo); 3445 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMO; 3446 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT; 3447 } else 3448 panic("%s: No socket timeout?!\n", __func__); 3449 } /* ng_btsocket_rfcomm_timeout */ 3450 3451 /* 3452 * Process pcb timeout 3453 */ 3454 3455 static void 3456 ng_btsocket_rfcomm_process_timeout(void *xpcb) 3457 { 3458 ng_btsocket_rfcomm_pcb_p pcb = (ng_btsocket_rfcomm_pcb_p) xpcb; 3459 3460 mtx_lock(&pcb->pcb_mtx); 3461 3462 NG_BTSOCKET_RFCOMM_INFO( 3463 "%s: Timeout, so=%p, dlci=%d, state=%d, flags=%#x\n", 3464 __func__, pcb->so, pcb->dlci, pcb->state, pcb->flags); 3465 3466 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMO; 3467 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT; 3468 3469 switch (pcb->state) { 3470 case NG_BTSOCKET_RFCOMM_DLC_CONFIGURING: 3471 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING: 3472 pcb->state = NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING; 3473 break; 3474 3475 case NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT: 3476 case NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING: 3477 break; 3478 3479 default: 3480 panic( 3481 "%s: DLC timeout in invalid state, dlci=%d, state=%d, flags=%#x\n", 3482 __func__, pcb->dlci, pcb->state, pcb->flags); 3483 break; 3484 } 3485 3486 ng_btsocket_rfcomm_task_wakeup(); 3487 3488 mtx_unlock(&pcb->pcb_mtx); 3489 } /* ng_btsocket_rfcomm_process_timeout */ 3490 3491 /* 3492 * Get up to length bytes from the socket buffer 3493 */ 3494 3495 static struct mbuf * 3496 ng_btsocket_rfcomm_prepare_packet(struct sockbuf *sb, int length) 3497 { 3498 struct mbuf *top = NULL, *m = NULL, *n = NULL, *nextpkt = NULL; 3499 int mlen, noff, len; 3500 3501 MGETHDR(top, M_DONTWAIT, MT_DATA); 3502 if (top == NULL) 3503 return (NULL); 3504 3505 top->m_pkthdr.len = length; 3506 top->m_len = 0; 3507 mlen = MHLEN; 3508 3509 m = top; 3510 n = sb->sb_mb; 3511 nextpkt = n->m_nextpkt; 3512 noff = 0; 3513 3514 while (length > 0 && n != NULL) { 3515 len = min(mlen - m->m_len, n->m_len - noff); 3516 if (len > length) 3517 len = length; 3518 3519 bcopy(mtod(n, caddr_t)+noff, mtod(m, caddr_t)+m->m_len, len); 3520 m->m_len += len; 3521 noff += len; 3522 length -= len; 3523 3524 if (length > 0 && m->m_len == mlen) { 3525 MGET(m->m_next, M_DONTWAIT, MT_DATA); 3526 if (m->m_next == NULL) { 3527 NG_FREE_M(top); 3528 return (NULL); 3529 } 3530 3531 m = m->m_next; 3532 m->m_len = 0; 3533 mlen = MLEN; 3534 } 3535 3536 if (noff == n->m_len) { 3537 noff = 0; 3538 n = n->m_next; 3539 3540 if (n == NULL) 3541 n = nextpkt; 3542 3543 nextpkt = (n != NULL)? n->m_nextpkt : NULL; 3544 } 3545 } 3546 3547 if (length < 0) 3548 panic("%s: length=%d\n", __func__, length); 3549 if (length > 0 && n == NULL) 3550 panic("%s: bogus length=%d, n=%p\n", __func__, length, n); 3551 3552 return (top); 3553 } /* ng_btsocket_rfcomm_prepare_packet */ 3554 3555