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