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