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 * $DragonFly: src/sys/netgraph7/bluetooth/socket/ng_btsocket_rfcomm.c,v 1.2 2008/06/26 23:05:40 dillon Exp $ 33 */ 34 35 #include <sys/param.h> 36 #include <sys/systm.h> 37 #include <sys/bitstring.h> 38 #include <sys/domain.h> 39 #include <sys/endian.h> 40 #include <sys/errno.h> 41 #include <sys/filedesc.h> 42 #include <sys/ioccom.h> 43 #include <sys/kernel.h> 44 #include <sys/lock.h> 45 #include <sys/malloc.h> 46 #include <sys/mbuf.h> 47 #include <sys/mutex.h> 48 #include <sys/proc.h> 49 #include <sys/protosw.h> 50 #include <sys/queue.h> 51 #include <sys/socket.h> 52 #include <sys/socketvar.h> 53 #include <sys/sysctl.h> 54 #include <sys/taskqueue.h> 55 #include <sys/uio.h> 56 #include "ng_message.h" 57 #include "netgraph.h" 58 #include "bluetooth/include/ng_bluetooth.h" 59 #include "bluetooth/include/ng_hci.h" 60 #include "bluetooth/include/ng_l2cap.h" 61 #include "bluetooth/include/ng_btsocket.h" 62 #include "bluetooth/include/ng_btsocket_l2cap.h" 63 #include "bluetooth/include/ng_btsocket_rfcomm.h" 64 65 /* MALLOC define */ 66 #ifdef NG_SEPARATE_MALLOC 67 MALLOC_DEFINE(M_NETGRAPH_BTSOCKET_RFCOMM, "netgraph_btsocks_rfcomm", 68 "Netgraph Bluetooth RFCOMM sockets"); 69 #else 70 #define M_NETGRAPH_BTSOCKET_RFCOMM M_NETGRAPH 71 #endif /* NG_SEPARATE_MALLOC */ 72 73 /* Debug */ 74 #define NG_BTSOCKET_RFCOMM_INFO \ 75 if (ng_btsocket_rfcomm_debug_level >= NG_BTSOCKET_INFO_LEVEL) \ 76 printf 77 78 #define NG_BTSOCKET_RFCOMM_WARN \ 79 if (ng_btsocket_rfcomm_debug_level >= NG_BTSOCKET_WARN_LEVEL) \ 80 printf 81 82 #define NG_BTSOCKET_RFCOMM_ERR \ 83 if (ng_btsocket_rfcomm_debug_level >= NG_BTSOCKET_ERR_LEVEL) \ 84 printf 85 86 #define NG_BTSOCKET_RFCOMM_ALERT \ 87 if (ng_btsocket_rfcomm_debug_level >= NG_BTSOCKET_ALERT_LEVEL) \ 88 printf 89 90 #define ALOT 0x7fff 91 92 /* Local prototypes */ 93 static void ng_btsocket_rfcomm_upcall 94 (struct socket *so, void *arg, int waitflag); 95 static void ng_btsocket_rfcomm_sessions_task 96 (void *ctx, int pending); 97 static void ng_btsocket_rfcomm_session_task 98 (ng_btsocket_rfcomm_session_p s); 99 #define ng_btsocket_rfcomm_task_wakeup() \ 100 taskqueue_enqueue(taskqueue_swi_giant, &ng_btsocket_rfcomm_task) 101 102 static ng_btsocket_rfcomm_pcb_p ng_btsocket_rfcomm_connect_ind 103 (ng_btsocket_rfcomm_session_p s, int channel); 104 static void ng_btsocket_rfcomm_connect_cfm 105 (ng_btsocket_rfcomm_session_p s); 106 107 static int ng_btsocket_rfcomm_session_create 108 (ng_btsocket_rfcomm_session_p *sp, struct socket *l2so, 109 bdaddr_p src, bdaddr_p dst, struct thread *td); 110 static int ng_btsocket_rfcomm_session_accept 111 (ng_btsocket_rfcomm_session_p s0); 112 static int ng_btsocket_rfcomm_session_connect 113 (ng_btsocket_rfcomm_session_p s); 114 static int ng_btsocket_rfcomm_session_receive 115 (ng_btsocket_rfcomm_session_p s); 116 static int ng_btsocket_rfcomm_session_send 117 (ng_btsocket_rfcomm_session_p s); 118 static void ng_btsocket_rfcomm_session_clean 119 (ng_btsocket_rfcomm_session_p s); 120 static void ng_btsocket_rfcomm_session_process_pcb 121 (ng_btsocket_rfcomm_session_p s); 122 static ng_btsocket_rfcomm_session_p ng_btsocket_rfcomm_session_by_addr 123 (bdaddr_p src, bdaddr_p dst); 124 125 static int ng_btsocket_rfcomm_receive_frame 126 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0); 127 static int ng_btsocket_rfcomm_receive_sabm 128 (ng_btsocket_rfcomm_session_p s, int dlci); 129 static int ng_btsocket_rfcomm_receive_disc 130 (ng_btsocket_rfcomm_session_p s, int dlci); 131 static int ng_btsocket_rfcomm_receive_ua 132 (ng_btsocket_rfcomm_session_p s, int dlci); 133 static int ng_btsocket_rfcomm_receive_dm 134 (ng_btsocket_rfcomm_session_p s, int dlci); 135 static int ng_btsocket_rfcomm_receive_uih 136 (ng_btsocket_rfcomm_session_p s, int dlci, int pf, struct mbuf *m0); 137 static int ng_btsocket_rfcomm_receive_mcc 138 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0); 139 static int ng_btsocket_rfcomm_receive_test 140 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0); 141 static int ng_btsocket_rfcomm_receive_fc 142 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0); 143 static int ng_btsocket_rfcomm_receive_msc 144 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0); 145 static int ng_btsocket_rfcomm_receive_rpn 146 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0); 147 static int ng_btsocket_rfcomm_receive_rls 148 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0); 149 static int ng_btsocket_rfcomm_receive_pn 150 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0); 151 static void ng_btsocket_rfcomm_set_pn 152 (ng_btsocket_rfcomm_pcb_p pcb, u_int8_t cr, u_int8_t flow_control, 153 u_int8_t credits, u_int16_t mtu); 154 155 static int ng_btsocket_rfcomm_send_command 156 (ng_btsocket_rfcomm_session_p s, u_int8_t type, u_int8_t dlci); 157 static int ng_btsocket_rfcomm_send_uih 158 (ng_btsocket_rfcomm_session_p s, u_int8_t address, u_int8_t pf, 159 u_int8_t credits, struct mbuf *data); 160 static int ng_btsocket_rfcomm_send_msc 161 (ng_btsocket_rfcomm_pcb_p pcb); 162 static int ng_btsocket_rfcomm_send_pn 163 (ng_btsocket_rfcomm_pcb_p pcb); 164 static int ng_btsocket_rfcomm_send_credits 165 (ng_btsocket_rfcomm_pcb_p pcb); 166 167 static int ng_btsocket_rfcomm_pcb_send 168 (ng_btsocket_rfcomm_pcb_p pcb, int limit); 169 static void ng_btsocket_rfcomm_pcb_kill 170 (ng_btsocket_rfcomm_pcb_p pcb, int error); 171 static ng_btsocket_rfcomm_pcb_p ng_btsocket_rfcomm_pcb_by_dlci 172 (ng_btsocket_rfcomm_session_p s, int dlci); 173 static ng_btsocket_rfcomm_pcb_p ng_btsocket_rfcomm_pcb_listener 174 (bdaddr_p src, int channel); 175 176 static void ng_btsocket_rfcomm_timeout 177 (ng_btsocket_rfcomm_pcb_p pcb); 178 static void ng_btsocket_rfcomm_untimeout 179 (ng_btsocket_rfcomm_pcb_p pcb); 180 static void ng_btsocket_rfcomm_process_timeout 181 (void *xpcb); 182 183 static struct mbuf * ng_btsocket_rfcomm_prepare_packet 184 (struct sockbuf *sb, int length); 185 186 /* Globals */ 187 extern int ifqmaxlen; 188 static u_int32_t ng_btsocket_rfcomm_debug_level; 189 static u_int32_t ng_btsocket_rfcomm_timo; 190 struct task ng_btsocket_rfcomm_task; 191 static LIST_HEAD(, ng_btsocket_rfcomm_session) ng_btsocket_rfcomm_sessions; 192 static struct mtx ng_btsocket_rfcomm_sessions_mtx; 193 static LIST_HEAD(, ng_btsocket_rfcomm_pcb) ng_btsocket_rfcomm_sockets; 194 static struct mtx ng_btsocket_rfcomm_sockets_mtx; 195 196 /* Sysctl tree */ 197 SYSCTL_DECL(_net_bluetooth_rfcomm_sockets); 198 SYSCTL_NODE(_net_bluetooth_rfcomm_sockets, OID_AUTO, stream, CTLFLAG_RW, 199 0, "Bluetooth STREAM RFCOMM sockets family"); 200 SYSCTL_INT(_net_bluetooth_rfcomm_sockets_stream, OID_AUTO, debug_level, 201 CTLFLAG_RW, 202 &ng_btsocket_rfcomm_debug_level, NG_BTSOCKET_INFO_LEVEL, 203 "Bluetooth STREAM RFCOMM sockets debug level"); 204 SYSCTL_INT(_net_bluetooth_rfcomm_sockets_stream, OID_AUTO, timeout, 205 CTLFLAG_RW, 206 &ng_btsocket_rfcomm_timo, 60, 207 "Bluetooth STREAM RFCOMM sockets timeout"); 208 209 /***************************************************************************** 210 ***************************************************************************** 211 ** RFCOMM CRC 212 ***************************************************************************** 213 *****************************************************************************/ 214 215 static u_int8_t ng_btsocket_rfcomm_crc_table[256] = { 216 0x00, 0x91, 0xe3, 0x72, 0x07, 0x96, 0xe4, 0x75, 217 0x0e, 0x9f, 0xed, 0x7c, 0x09, 0x98, 0xea, 0x7b, 218 0x1c, 0x8d, 0xff, 0x6e, 0x1b, 0x8a, 0xf8, 0x69, 219 0x12, 0x83, 0xf1, 0x60, 0x15, 0x84, 0xf6, 0x67, 220 221 0x38, 0xa9, 0xdb, 0x4a, 0x3f, 0xae, 0xdc, 0x4d, 222 0x36, 0xa7, 0xd5, 0x44, 0x31, 0xa0, 0xd2, 0x43, 223 0x24, 0xb5, 0xc7, 0x56, 0x23, 0xb2, 0xc0, 0x51, 224 0x2a, 0xbb, 0xc9, 0x58, 0x2d, 0xbc, 0xce, 0x5f, 225 226 0x70, 0xe1, 0x93, 0x02, 0x77, 0xe6, 0x94, 0x05, 227 0x7e, 0xef, 0x9d, 0x0c, 0x79, 0xe8, 0x9a, 0x0b, 228 0x6c, 0xfd, 0x8f, 0x1e, 0x6b, 0xfa, 0x88, 0x19, 229 0x62, 0xf3, 0x81, 0x10, 0x65, 0xf4, 0x86, 0x17, 230 231 0x48, 0xd9, 0xab, 0x3a, 0x4f, 0xde, 0xac, 0x3d, 232 0x46, 0xd7, 0xa5, 0x34, 0x41, 0xd0, 0xa2, 0x33, 233 0x54, 0xc5, 0xb7, 0x26, 0x53, 0xc2, 0xb0, 0x21, 234 0x5a, 0xcb, 0xb9, 0x28, 0x5d, 0xcc, 0xbe, 0x2f, 235 236 0xe0, 0x71, 0x03, 0x92, 0xe7, 0x76, 0x04, 0x95, 237 0xee, 0x7f, 0x0d, 0x9c, 0xe9, 0x78, 0x0a, 0x9b, 238 0xfc, 0x6d, 0x1f, 0x8e, 0xfb, 0x6a, 0x18, 0x89, 239 0xf2, 0x63, 0x11, 0x80, 0xf5, 0x64, 0x16, 0x87, 240 241 0xd8, 0x49, 0x3b, 0xaa, 0xdf, 0x4e, 0x3c, 0xad, 242 0xd6, 0x47, 0x35, 0xa4, 0xd1, 0x40, 0x32, 0xa3, 243 0xc4, 0x55, 0x27, 0xb6, 0xc3, 0x52, 0x20, 0xb1, 244 0xca, 0x5b, 0x29, 0xb8, 0xcd, 0x5c, 0x2e, 0xbf, 245 246 0x90, 0x01, 0x73, 0xe2, 0x97, 0x06, 0x74, 0xe5, 247 0x9e, 0x0f, 0x7d, 0xec, 0x99, 0x08, 0x7a, 0xeb, 248 0x8c, 0x1d, 0x6f, 0xfe, 0x8b, 0x1a, 0x68, 0xf9, 249 0x82, 0x13, 0x61, 0xf0, 0x85, 0x14, 0x66, 0xf7, 250 251 0xa8, 0x39, 0x4b, 0xda, 0xaf, 0x3e, 0x4c, 0xdd, 252 0xa6, 0x37, 0x45, 0xd4, 0xa1, 0x30, 0x42, 0xd3, 253 0xb4, 0x25, 0x57, 0xc6, 0xb3, 0x22, 0x50, 0xc1, 254 0xba, 0x2b, 0x59, 0xc8, 0xbd, 0x2c, 0x5e, 0xcf 255 }; 256 257 /* CRC */ 258 static u_int8_t 259 ng_btsocket_rfcomm_crc(u_int8_t *data, int length) 260 { 261 u_int8_t crc = 0xff; 262 263 while (length --) 264 crc = ng_btsocket_rfcomm_crc_table[crc ^ *data++]; 265 266 return (crc); 267 } /* ng_btsocket_rfcomm_crc */ 268 269 /* FCS on 2 bytes */ 270 static u_int8_t 271 ng_btsocket_rfcomm_fcs2(u_int8_t *data) 272 { 273 return (0xff - ng_btsocket_rfcomm_crc(data, 2)); 274 } /* ng_btsocket_rfcomm_fcs2 */ 275 276 /* FCS on 3 bytes */ 277 static u_int8_t 278 ng_btsocket_rfcomm_fcs3(u_int8_t *data) 279 { 280 return (0xff - ng_btsocket_rfcomm_crc(data, 3)); 281 } /* ng_btsocket_rfcomm_fcs3 */ 282 283 /* 284 * Check FCS 285 * 286 * From Bluetooth spec 287 * 288 * "... In 07.10, the frame check sequence (FCS) is calculated on different 289 * sets of fields for different frame types. These are the fields that the 290 * FCS are calculated on: 291 * 292 * For SABM, DISC, UA, DM frames: on Address, Control and length field. 293 * For UIH frames: on Address and Control field. 294 * 295 * (This is stated here for clarification, and to set the standard for RFCOMM; 296 * the fields included in FCS calculation have actually changed in version 297 * 7.0.0 of TS 07.10, but RFCOMM will not change the FCS calculation scheme 298 * from the one above.) ..." 299 */ 300 301 static int 302 ng_btsocket_rfcomm_check_fcs(u_int8_t *data, int type, u_int8_t fcs) 303 { 304 if (type != RFCOMM_FRAME_UIH) 305 return (ng_btsocket_rfcomm_fcs3(data) != fcs); 306 307 return (ng_btsocket_rfcomm_fcs2(data) != fcs); 308 } /* ng_btsocket_rfcomm_check_fcs */ 309 310 /***************************************************************************** 311 ***************************************************************************** 312 ** Socket interface 313 ***************************************************************************** 314 *****************************************************************************/ 315 316 /* 317 * Initialize everything 318 */ 319 320 void 321 ng_btsocket_rfcomm_init(void) 322 { 323 ng_btsocket_rfcomm_debug_level = NG_BTSOCKET_WARN_LEVEL; 324 ng_btsocket_rfcomm_timo = 60; 325 326 /* RFCOMM task */ 327 TASK_INIT(&ng_btsocket_rfcomm_task, 0, 328 ng_btsocket_rfcomm_sessions_task, NULL); 329 330 /* RFCOMM sessions list */ 331 LIST_INIT(&ng_btsocket_rfcomm_sessions); 332 mtx_init(&ng_btsocket_rfcomm_sessions_mtx, 333 "btsocks_rfcomm_sessions_mtx", NULL, MTX_DEF); 334 335 /* RFCOMM sockets list */ 336 LIST_INIT(&ng_btsocket_rfcomm_sockets); 337 mtx_init(&ng_btsocket_rfcomm_sockets_mtx, 338 "btsocks_rfcomm_sockets_mtx", NULL, MTX_DEF); 339 } /* ng_btsocket_rfcomm_init */ 340 341 /* 342 * Abort connection on socket 343 */ 344 345 void 346 ng_btsocket_rfcomm_abort(struct socket *so) 347 { 348 349 so->so_error = ECONNABORTED; 350 (void)ng_btsocket_rfcomm_disconnect(so); 351 } /* ng_btsocket_rfcomm_abort */ 352 353 void 354 ng_btsocket_rfcomm_close(struct socket *so) 355 { 356 357 (void)ng_btsocket_rfcomm_disconnect(so); 358 } /* ng_btsocket_rfcomm_close */ 359 360 /* 361 * Accept connection on socket. Nothing to do here, socket must be connected 362 * and ready, so just return peer address and be done with it. 363 */ 364 365 int 366 ng_btsocket_rfcomm_accept(struct socket *so, struct sockaddr **nam) 367 { 368 return (ng_btsocket_rfcomm_peeraddr(so, nam)); 369 } /* ng_btsocket_rfcomm_accept */ 370 371 /* 372 * Create and attach new socket 373 */ 374 375 int 376 ng_btsocket_rfcomm_attach(struct socket *so, int proto, struct thread *td) 377 { 378 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so); 379 int error; 380 381 /* Check socket and protocol */ 382 if (so->so_type != SOCK_STREAM) 383 return (ESOCKTNOSUPPORT); 384 385 #if 0 /* XXX sonewconn() calls "pru_attach" with proto == 0 */ 386 if (proto != 0) 387 if (proto != BLUETOOTH_PROTO_RFCOMM) 388 return (EPROTONOSUPPORT); 389 #endif /* XXX */ 390 391 if (pcb != NULL) 392 return (EISCONN); 393 394 /* Reserve send and receive space if it is not reserved yet */ 395 if ((so->so_snd.sb_hiwat == 0) || (so->so_rcv.sb_hiwat == 0)) { 396 error = soreserve(so, NG_BTSOCKET_RFCOMM_SENDSPACE, 397 NG_BTSOCKET_RFCOMM_RECVSPACE); 398 if (error != 0) 399 return (error); 400 } 401 402 /* Allocate the PCB */ 403 MALLOC(pcb, ng_btsocket_rfcomm_pcb_p, sizeof(*pcb), 404 M_NETGRAPH_BTSOCKET_RFCOMM, M_WAITOK | M_NULLOK | M_ZERO); 405 if (pcb == NULL) 406 return (ENOMEM); 407 408 /* Link the PCB and the socket */ 409 so->so_pcb = (caddr_t) pcb; 410 pcb->so = so; 411 412 /* Initialize PCB */ 413 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CLOSED; 414 pcb->flags = NG_BTSOCKET_RFCOMM_DLC_CFC; 415 416 pcb->lmodem = 417 pcb->rmodem = (RFCOMM_MODEM_RTC | RFCOMM_MODEM_RTR | RFCOMM_MODEM_DV); 418 419 pcb->mtu = RFCOMM_DEFAULT_MTU; 420 pcb->tx_cred = 0; 421 pcb->rx_cred = RFCOMM_DEFAULT_CREDITS; 422 423 mtx_init(&pcb->pcb_mtx, "btsocks_rfcomm_pcb_mtx", NULL, MTX_DEF); 424 callout_handle_init(&pcb->timo); 425 426 /* Add the PCB to the list */ 427 mtx_lock(&ng_btsocket_rfcomm_sockets_mtx); 428 LIST_INSERT_HEAD(&ng_btsocket_rfcomm_sockets, pcb, next); 429 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx); 430 431 return (0); 432 } /* ng_btsocket_rfcomm_attach */ 433 434 /* 435 * Bind socket 436 */ 437 438 int 439 ng_btsocket_rfcomm_bind(struct socket *so, struct sockaddr *nam, 440 struct thread *td) 441 { 442 ng_btsocket_rfcomm_pcb_t *pcb = so2rfcomm_pcb(so), *pcb1; 443 struct sockaddr_rfcomm *sa = (struct sockaddr_rfcomm *) nam; 444 445 if (pcb == NULL) 446 return (EINVAL); 447 448 /* Verify address */ 449 if (sa == NULL) 450 return (EINVAL); 451 if (sa->rfcomm_family != AF_BLUETOOTH) 452 return (EAFNOSUPPORT); 453 if (sa->rfcomm_len != sizeof(*sa)) 454 return (EINVAL); 455 if (sa->rfcomm_channel > 30) 456 return (EINVAL); 457 458 mtx_lock(&pcb->pcb_mtx); 459 460 if (sa->rfcomm_channel != 0) { 461 mtx_lock(&ng_btsocket_rfcomm_sockets_mtx); 462 463 LIST_FOREACH(pcb1, &ng_btsocket_rfcomm_sockets, next) { 464 if (pcb1->channel == sa->rfcomm_channel && 465 bcmp(&pcb1->src, &sa->rfcomm_bdaddr, 466 sizeof(pcb1->src)) == 0) { 467 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx); 468 mtx_unlock(&pcb->pcb_mtx); 469 470 return (EADDRINUSE); 471 } 472 } 473 474 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx); 475 } 476 477 bcopy(&sa->rfcomm_bdaddr, &pcb->src, sizeof(pcb->src)); 478 pcb->channel = sa->rfcomm_channel; 479 480 mtx_unlock(&pcb->pcb_mtx); 481 482 return (0); 483 } /* ng_btsocket_rfcomm_bind */ 484 485 /* 486 * Connect socket 487 */ 488 489 int 490 ng_btsocket_rfcomm_connect(struct socket *so, struct sockaddr *nam, 491 struct thread *td) 492 { 493 ng_btsocket_rfcomm_pcb_t *pcb = so2rfcomm_pcb(so); 494 struct sockaddr_rfcomm *sa = (struct sockaddr_rfcomm *) nam; 495 ng_btsocket_rfcomm_session_t *s = NULL; 496 struct socket *l2so = NULL; 497 int dlci, error = 0; 498 499 if (pcb == NULL) 500 return (EINVAL); 501 502 /* Verify address */ 503 if (sa == NULL) 504 return (EINVAL); 505 if (sa->rfcomm_family != AF_BLUETOOTH) 506 return (EAFNOSUPPORT); 507 if (sa->rfcomm_len != sizeof(*sa)) 508 return (EINVAL); 509 if (sa->rfcomm_channel > 30) 510 return (EINVAL); 511 if (sa->rfcomm_channel == 0 || 512 bcmp(&sa->rfcomm_bdaddr, NG_HCI_BDADDR_ANY, sizeof(bdaddr_t)) == 0) 513 return (EDESTADDRREQ); 514 515 /* 516 * XXX FIXME - This is FUBAR. socreate() will call soalloc(1), i.e. 517 * soalloc() is allowed to sleep in MALLOC. This creates "could sleep" 518 * WITNESS warnings. To work around this problem we will create L2CAP 519 * socket first and then check if we actually need it. Note that we 520 * will not check for errors in socreate() because if we failed to 521 * create L2CAP socket at this point we still might have already open 522 * session. 523 */ 524 525 error = socreate(PF_BLUETOOTH, &l2so, SOCK_SEQPACKET, 526 BLUETOOTH_PROTO_L2CAP, td->td_ucred, td); 527 528 /* 529 * Look for session between "pcb->src" and "sa->rfcomm_bdaddr" (dst) 530 */ 531 532 mtx_lock(&ng_btsocket_rfcomm_sessions_mtx); 533 534 s = ng_btsocket_rfcomm_session_by_addr(&pcb->src, &sa->rfcomm_bdaddr); 535 if (s == NULL) { 536 /* 537 * We need to create new RFCOMM session. Check if we have L2CAP 538 * socket. If l2so == NULL then error has the error code from 539 * socreate() 540 */ 541 542 if (l2so == NULL) { 543 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx); 544 return (error); 545 } 546 547 error = ng_btsocket_rfcomm_session_create(&s, l2so, 548 &pcb->src, &sa->rfcomm_bdaddr, td); 549 if (error != 0) { 550 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx); 551 soclose(l2so); 552 553 return (error); 554 } 555 } else if (l2so != NULL) 556 soclose(l2so); /* we don't need new L2CAP socket */ 557 558 /* 559 * Check if we already have the same DLCI the the same session 560 */ 561 562 mtx_lock(&s->session_mtx); 563 mtx_lock(&pcb->pcb_mtx); 564 565 dlci = RFCOMM_MKDLCI(!INITIATOR(s), sa->rfcomm_channel); 566 567 if (ng_btsocket_rfcomm_pcb_by_dlci(s, dlci) != NULL) { 568 mtx_unlock(&pcb->pcb_mtx); 569 mtx_unlock(&s->session_mtx); 570 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx); 571 572 return (EBUSY); 573 } 574 575 /* 576 * Check session state and if its not acceptable then refuse connection 577 */ 578 579 switch (s->state) { 580 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTING: 581 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED: 582 case NG_BTSOCKET_RFCOMM_SESSION_OPEN: 583 /* 584 * Update destination address and channel and attach 585 * DLC to the session 586 */ 587 588 bcopy(&sa->rfcomm_bdaddr, &pcb->dst, sizeof(pcb->dst)); 589 pcb->channel = sa->rfcomm_channel; 590 pcb->dlci = dlci; 591 592 LIST_INSERT_HEAD(&s->dlcs, pcb, session_next); 593 pcb->session = s; 594 595 ng_btsocket_rfcomm_timeout(pcb); 596 soisconnecting(pcb->so); 597 598 if (s->state == NG_BTSOCKET_RFCOMM_SESSION_OPEN) { 599 pcb->mtu = s->mtu; 600 bcopy(&so2l2cap_pcb(s->l2so)->src, &pcb->src, 601 sizeof(pcb->src)); 602 603 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONFIGURING; 604 605 error = ng_btsocket_rfcomm_send_pn(pcb); 606 if (error == 0) 607 error = ng_btsocket_rfcomm_task_wakeup(); 608 } else 609 pcb->state = NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT; 610 break; 611 612 default: 613 error = ECONNRESET; 614 break; 615 } 616 617 mtx_unlock(&pcb->pcb_mtx); 618 mtx_unlock(&s->session_mtx); 619 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx); 620 621 return (error); 622 } /* ng_btsocket_rfcomm_connect */ 623 624 /* 625 * Process ioctl's calls on socket. 626 * XXX FIXME this should provide interface to the RFCOMM multiplexor channel 627 */ 628 629 int 630 ng_btsocket_rfcomm_control(struct socket *so, u_long cmd, caddr_t data, 631 struct ifnet *ifp, struct thread *td) 632 { 633 return (EINVAL); 634 } /* ng_btsocket_rfcomm_control */ 635 636 /* 637 * Process getsockopt/setsockopt system calls 638 */ 639 640 int 641 ng_btsocket_rfcomm_ctloutput(struct socket *so, struct sockopt *sopt) 642 { 643 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so); 644 struct ng_btsocket_rfcomm_fc_info fcinfo; 645 int error = 0; 646 647 if (pcb == NULL) 648 return (EINVAL); 649 if (sopt->sopt_level != SOL_RFCOMM) 650 return (0); 651 652 mtx_lock(&pcb->pcb_mtx); 653 654 switch (sopt->sopt_dir) { 655 case SOPT_GET: 656 switch (sopt->sopt_name) { 657 case SO_RFCOMM_MTU: 658 error = sooptcopyout(sopt, &pcb->mtu, sizeof(pcb->mtu)); 659 break; 660 661 case SO_RFCOMM_FC_INFO: 662 fcinfo.lmodem = pcb->lmodem; 663 fcinfo.rmodem = pcb->rmodem; 664 fcinfo.tx_cred = pcb->tx_cred; 665 fcinfo.rx_cred = pcb->rx_cred; 666 fcinfo.cfc = (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC)? 667 1 : 0; 668 fcinfo.reserved = 0; 669 670 error = sooptcopyout(sopt, &fcinfo, sizeof(fcinfo)); 671 break; 672 673 default: 674 error = ENOPROTOOPT; 675 break; 676 } 677 break; 678 679 case SOPT_SET: 680 switch (sopt->sopt_name) { 681 default: 682 error = ENOPROTOOPT; 683 break; 684 } 685 break; 686 687 default: 688 error = EINVAL; 689 break; 690 } 691 692 mtx_unlock(&pcb->pcb_mtx); 693 694 return (error); 695 } /* ng_btsocket_rfcomm_ctloutput */ 696 697 /* 698 * Detach and destroy socket 699 */ 700 701 void 702 ng_btsocket_rfcomm_detach(struct socket *so) 703 { 704 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so); 705 706 KASSERT(pcb != NULL, ("ng_btsocket_rfcomm_detach: pcb == NULL")); 707 708 mtx_lock(&pcb->pcb_mtx); 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\n", __func__); 737 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO) 738 panic("%s: timeout on closed DLC, flags=%#x\n", 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 FREE(pcb, M_NETGRAPH_BTSOCKET_RFCOMM); 750 751 soisdisconnected(so); 752 so->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\n", 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\n", __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\n", __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 FREE(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\n", 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\n", __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 MALLOC(s, ng_btsocket_rfcomm_session_p, sizeof(*s), 1269 M_NETGRAPH_BTSOCKET_RFCOMM, 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 l2so->so_state |= 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 l2so->so_state &= ~SS_NBIO; 1385 1386 mtx_destroy(&s->session_mtx); 1387 bzero(s, sizeof(*s)); 1388 FREE(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\n", __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 l2so->so_state |= 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, 1602 (struct mbuf **) NULL, &flags); 1603 if (error != 0) { 1604 if (error == EWOULDBLOCK) 1605 return (0); /* XXX can happen? */ 1606 1607 NG_BTSOCKET_RFCOMM_ERR( 1608 "%s: Could not receive data from L2CAP socket, error=%d\n", __func__, error); 1609 1610 return (error); 1611 } 1612 1613 more = (m->m_nextpkt != NULL); 1614 m->m_nextpkt = NULL; 1615 1616 ng_btsocket_rfcomm_receive_frame(s, m); 1617 } 1618 1619 return (0); 1620 } /* ng_btsocket_rfcomm_session_receive */ 1621 1622 /* 1623 * Send data on RFCOMM session 1624 * XXX FIXME locking for "l2so"? 1625 */ 1626 1627 static int 1628 ng_btsocket_rfcomm_session_send(ng_btsocket_rfcomm_session_p s) 1629 { 1630 struct mbuf *m = NULL; 1631 int error; 1632 1633 mtx_assert(&s->session_mtx, MA_OWNED); 1634 1635 /* Send as much as we can from the session queue */ 1636 while (sowriteable(s->l2so)) { 1637 /* Check if socket still OK */ 1638 if ((error = s->l2so->so_error) != 0) { 1639 s->l2so->so_error = 0; 1640 1641 NG_BTSOCKET_RFCOMM_ERR( 1642 "%s: Detected error=%d on L2CAP socket, state=%d, flags=%#x\n", 1643 __func__, error, s->state, s->flags); 1644 1645 return (error); 1646 } 1647 1648 NG_BT_MBUFQ_DEQUEUE(&s->outq, m); 1649 if (m == NULL) 1650 return (0); /* we are done */ 1651 1652 /* Call send function on the L2CAP socket */ 1653 error = (*s->l2so->so_proto->pr_usrreqs->pru_send)(s->l2so, 1654 0, m, NULL, NULL, curthread /* XXX */); 1655 if (error != 0) { 1656 NG_BTSOCKET_RFCOMM_ERR( 1657 "%s: Could not send data to L2CAP socket, error=%d\n", __func__, error); 1658 1659 return (error); 1660 } 1661 } 1662 1663 return (0); 1664 } /* ng_btsocket_rfcomm_session_send */ 1665 1666 /* 1667 * Close and disconnect all DLCs for the given session. Caller must hold 1668 * s->sesson_mtx. Will wakeup session. 1669 */ 1670 1671 static void 1672 ng_btsocket_rfcomm_session_clean(ng_btsocket_rfcomm_session_p s) 1673 { 1674 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb_next = NULL; 1675 int error; 1676 1677 mtx_assert(&s->session_mtx, MA_OWNED); 1678 1679 /* 1680 * Note: cannot use LIST_FOREACH because ng_btsocket_rfcomm_pcb_kill 1681 * will unlink DLC from the session 1682 */ 1683 1684 for (pcb = LIST_FIRST(&s->dlcs); pcb != NULL; ) { 1685 mtx_lock(&pcb->pcb_mtx); 1686 pcb_next = LIST_NEXT(pcb, session_next); 1687 1688 NG_BTSOCKET_RFCOMM_INFO( 1689 "%s: Disconnecting dlci=%d, state=%d, flags=%#x\n", 1690 __func__, pcb->dlci, pcb->state, pcb->flags); 1691 1692 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONNECTED) 1693 error = ECONNRESET; 1694 else 1695 error = ECONNREFUSED; 1696 1697 ng_btsocket_rfcomm_pcb_kill(pcb, error); 1698 1699 mtx_unlock(&pcb->pcb_mtx); 1700 pcb = pcb_next; 1701 } 1702 } /* ng_btsocket_rfcomm_session_clean */ 1703 1704 /* 1705 * Process all DLCs on the session. Caller MUST hold s->session_mtx. 1706 */ 1707 1708 static void 1709 ng_btsocket_rfcomm_session_process_pcb(ng_btsocket_rfcomm_session_p s) 1710 { 1711 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb_next = NULL; 1712 int error; 1713 1714 mtx_assert(&s->session_mtx, MA_OWNED); 1715 1716 /* 1717 * Note: cannot use LIST_FOREACH because ng_btsocket_rfcomm_pcb_kill 1718 * will unlink DLC from the session 1719 */ 1720 1721 for (pcb = LIST_FIRST(&s->dlcs); pcb != NULL; ) { 1722 mtx_lock(&pcb->pcb_mtx); 1723 pcb_next = LIST_NEXT(pcb, session_next); 1724 1725 switch (pcb->state) { 1726 1727 /* 1728 * If DLC in W4_CONNECT state then we should check for both 1729 * timeout and detach. 1730 */ 1731 1732 case NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT: 1733 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_DETACHED) 1734 ng_btsocket_rfcomm_pcb_kill(pcb, 0); 1735 else if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT) 1736 ng_btsocket_rfcomm_pcb_kill(pcb, ETIMEDOUT); 1737 break; 1738 1739 /* 1740 * If DLC in CONFIGURING or CONNECTING state then we only 1741 * should check for timeout. If detach() was called then 1742 * DLC will be moved into DISCONNECTING state. 1743 */ 1744 1745 case NG_BTSOCKET_RFCOMM_DLC_CONFIGURING: 1746 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING: 1747 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT) 1748 ng_btsocket_rfcomm_pcb_kill(pcb, ETIMEDOUT); 1749 break; 1750 1751 /* 1752 * If DLC in CONNECTED state then we need to send data (if any) 1753 * from the socket's send queue. Note that we will send data 1754 * from either all sockets or none. This may overload session's 1755 * outgoing queue (but we do not check for that). 1756 * 1757 * XXX FIXME need scheduler for RFCOMM sockets 1758 */ 1759 1760 case NG_BTSOCKET_RFCOMM_DLC_CONNECTED: 1761 error = ng_btsocket_rfcomm_pcb_send(pcb, ALOT); 1762 if (error != 0) 1763 ng_btsocket_rfcomm_pcb_kill(pcb, error); 1764 break; 1765 1766 /* 1767 * If DLC in DISCONNECTING state then we must send DISC frame. 1768 * Note that if DLC has timeout set then we do not need to 1769 * resend DISC frame. 1770 * 1771 * XXX FIXME need to drain all data from the socket's queue 1772 * if LINGER option was set 1773 */ 1774 1775 case NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING: 1776 if (!(pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)) { 1777 error = ng_btsocket_rfcomm_send_command( 1778 pcb->session, RFCOMM_FRAME_DISC, 1779 pcb->dlci); 1780 if (error == 0) 1781 ng_btsocket_rfcomm_timeout(pcb); 1782 else 1783 ng_btsocket_rfcomm_pcb_kill(pcb, error); 1784 } else if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT) 1785 ng_btsocket_rfcomm_pcb_kill(pcb, ETIMEDOUT); 1786 break; 1787 1788 /* case NG_BTSOCKET_RFCOMM_DLC_CLOSED: */ 1789 default: 1790 panic("%s: Invalid DLC state=%d, flags=%#x\n", 1791 __func__, pcb->state, pcb->flags); 1792 break; 1793 } 1794 1795 mtx_unlock(&pcb->pcb_mtx); 1796 pcb = pcb_next; 1797 } 1798 } /* ng_btsocket_rfcomm_session_process_pcb */ 1799 1800 /* 1801 * Find RFCOMM session between "src" and "dst". 1802 * Caller MUST hold ng_btsocket_rfcomm_sessions_mtx. 1803 */ 1804 1805 static ng_btsocket_rfcomm_session_p 1806 ng_btsocket_rfcomm_session_by_addr(bdaddr_p src, bdaddr_p dst) 1807 { 1808 ng_btsocket_rfcomm_session_p s = NULL; 1809 ng_btsocket_l2cap_pcb_p l2pcb = NULL; 1810 int any_src; 1811 1812 mtx_assert(&ng_btsocket_rfcomm_sessions_mtx, MA_OWNED); 1813 1814 any_src = (bcmp(src, NG_HCI_BDADDR_ANY, sizeof(*src)) == 0); 1815 1816 LIST_FOREACH(s, &ng_btsocket_rfcomm_sessions, next) { 1817 l2pcb = so2l2cap_pcb(s->l2so); 1818 1819 if ((any_src || bcmp(&l2pcb->src, src, sizeof(*src)) == 0) && 1820 bcmp(&l2pcb->dst, dst, sizeof(*dst)) == 0) 1821 break; 1822 } 1823 1824 return (s); 1825 } /* ng_btsocket_rfcomm_session_by_addr */ 1826 1827 /***************************************************************************** 1828 ***************************************************************************** 1829 ** RFCOMM 1830 ***************************************************************************** 1831 *****************************************************************************/ 1832 1833 /* 1834 * Process incoming RFCOMM frame. Caller must hold s->session_mtx. 1835 * XXX FIXME check frame length 1836 */ 1837 1838 static int 1839 ng_btsocket_rfcomm_receive_frame(ng_btsocket_rfcomm_session_p s, 1840 struct mbuf *m0) 1841 { 1842 struct rfcomm_frame_hdr *hdr = NULL; 1843 struct mbuf *m = NULL; 1844 u_int16_t length; 1845 u_int8_t dlci, type; 1846 int error = 0; 1847 1848 mtx_assert(&s->session_mtx, MA_OWNED); 1849 1850 /* Pullup as much as we can into first mbuf (for direct access) */ 1851 length = min(m0->m_pkthdr.len, MHLEN); 1852 if (m0->m_len < length) { 1853 if ((m0 = m_pullup(m0, length)) == NULL) { 1854 NG_BTSOCKET_RFCOMM_ALERT( 1855 "%s: m_pullup(%d) failed\n", __func__, length); 1856 1857 return (ENOBUFS); 1858 } 1859 } 1860 1861 hdr = mtod(m0, struct rfcomm_frame_hdr *); 1862 dlci = RFCOMM_DLCI(hdr->address); 1863 type = RFCOMM_TYPE(hdr->control); 1864 1865 /* Test EA bit in length. If not set then we have 2 bytes of length */ 1866 if (!RFCOMM_EA(hdr->length)) { 1867 bcopy(&hdr->length, &length, sizeof(length)); 1868 length = le16toh(length) >> 1; 1869 m_adj(m0, sizeof(*hdr) + 1); 1870 } else { 1871 length = hdr->length >> 1; 1872 m_adj(m0, sizeof(*hdr)); 1873 } 1874 1875 NG_BTSOCKET_RFCOMM_INFO( 1876 "%s: Got frame type=%#x, dlci=%d, length=%d, cr=%d, pf=%d, len=%d\n", 1877 __func__, type, dlci, length, RFCOMM_CR(hdr->address), 1878 RFCOMM_PF(hdr->control), m0->m_pkthdr.len); 1879 1880 /* 1881 * Get FCS (the last byte in the frame) 1882 * XXX this will not work if mbuf chain ends with empty mbuf. 1883 * XXX let's hope it never happens :) 1884 */ 1885 1886 for (m = m0; m->m_next != NULL; m = m->m_next) 1887 ; 1888 if (m->m_len <= 0) 1889 panic("%s: Empty mbuf at the end of the chain, len=%d\n", 1890 __func__, m->m_len); 1891 1892 /* 1893 * Check FCS. We only need to calculate FCS on first 2 or 3 bytes 1894 * and already m_pullup'ed mbuf chain, so it should be safe. 1895 */ 1896 1897 if (ng_btsocket_rfcomm_check_fcs((u_int8_t *) hdr, type, m->m_data[m->m_len - 1])) { 1898 NG_BTSOCKET_RFCOMM_ERR( 1899 "%s: Invalid RFCOMM packet. Bad checksum\n", __func__); 1900 NG_FREE_M(m0); 1901 1902 return (EINVAL); 1903 } 1904 1905 m_adj(m0, -1); /* Trim FCS byte */ 1906 1907 /* 1908 * Process RFCOMM frame. 1909 * 1910 * From TS 07.10 spec 1911 * 1912 * "... In the case where a SABM or DISC command with the P bit set 1913 * to 0 is received then the received frame shall be discarded..." 1914 * 1915 * "... If a unsolicited DM response is received then the frame shall 1916 * be processed irrespective of the P/F setting... " 1917 * 1918 * "... The station may transmit response frames with the F bit set 1919 * to 0 at any opportunity on an asynchronous basis. However, in the 1920 * case where a UA response is received with the F bit set to 0 then 1921 * the received frame shall be discarded..." 1922 * 1923 * From Bluetooth spec 1924 * 1925 * "... When credit based flow control is being used, the meaning of 1926 * the P/F bit in the control field of the RFCOMM header is redefined 1927 * for UIH frames..." 1928 */ 1929 1930 switch (type) { 1931 case RFCOMM_FRAME_SABM: 1932 if (RFCOMM_PF(hdr->control)) 1933 error = ng_btsocket_rfcomm_receive_sabm(s, dlci); 1934 break; 1935 1936 case RFCOMM_FRAME_DISC: 1937 if (RFCOMM_PF(hdr->control)) 1938 error = ng_btsocket_rfcomm_receive_disc(s, dlci); 1939 break; 1940 1941 case RFCOMM_FRAME_UA: 1942 if (RFCOMM_PF(hdr->control)) 1943 error = ng_btsocket_rfcomm_receive_ua(s, dlci); 1944 break; 1945 1946 case RFCOMM_FRAME_DM: 1947 error = ng_btsocket_rfcomm_receive_dm(s, dlci); 1948 break; 1949 1950 case RFCOMM_FRAME_UIH: 1951 if (dlci == 0) 1952 error = ng_btsocket_rfcomm_receive_mcc(s, m0); 1953 else 1954 error = ng_btsocket_rfcomm_receive_uih(s, dlci, 1955 RFCOMM_PF(hdr->control), m0); 1956 1957 return (error); 1958 /* NOT REACHED */ 1959 1960 default: 1961 NG_BTSOCKET_RFCOMM_ERR( 1962 "%s: Invalid RFCOMM packet. Unknown type=%#x\n", __func__, type); 1963 error = EINVAL; 1964 break; 1965 } 1966 1967 NG_FREE_M(m0); 1968 1969 return (error); 1970 } /* ng_btsocket_rfcomm_receive_frame */ 1971 1972 /* 1973 * Process RFCOMM SABM frame 1974 */ 1975 1976 static int 1977 ng_btsocket_rfcomm_receive_sabm(ng_btsocket_rfcomm_session_p s, int dlci) 1978 { 1979 ng_btsocket_rfcomm_pcb_p pcb = NULL; 1980 int error = 0; 1981 1982 mtx_assert(&s->session_mtx, MA_OWNED); 1983 1984 NG_BTSOCKET_RFCOMM_INFO( 1985 "%s: Got SABM, session state=%d, flags=%#x, mtu=%d, dlci=%d\n", 1986 __func__, s->state, s->flags, s->mtu, dlci); 1987 1988 /* DLCI == 0 means open multiplexor channel */ 1989 if (dlci == 0) { 1990 switch (s->state) { 1991 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED: 1992 case NG_BTSOCKET_RFCOMM_SESSION_OPEN: 1993 error = ng_btsocket_rfcomm_send_command(s, 1994 RFCOMM_FRAME_UA, dlci); 1995 if (error == 0) { 1996 s->state = NG_BTSOCKET_RFCOMM_SESSION_OPEN; 1997 ng_btsocket_rfcomm_connect_cfm(s); 1998 } else { 1999 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED; 2000 ng_btsocket_rfcomm_session_clean(s); 2001 } 2002 break; 2003 2004 default: 2005 NG_BTSOCKET_RFCOMM_WARN( 2006 "%s: Got SABM for session in invalid state state=%d, flags=%#x\n", 2007 __func__, s->state, s->flags); 2008 error = EINVAL; 2009 break; 2010 } 2011 2012 return (error); 2013 } 2014 2015 /* Make sure multiplexor channel is open */ 2016 if (s->state != NG_BTSOCKET_RFCOMM_SESSION_OPEN) { 2017 NG_BTSOCKET_RFCOMM_ERR( 2018 "%s: Got SABM for dlci=%d with mulitplexor channel closed, state=%d, " \ 2019 "flags=%#x\n", __func__, dlci, s->state, s->flags); 2020 2021 return (EINVAL); 2022 } 2023 2024 /* 2025 * Check if we have this DLCI. This might happen when remote 2026 * peer uses PN command before actual open (SABM) happens. 2027 */ 2028 2029 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci); 2030 if (pcb != NULL) { 2031 mtx_lock(&pcb->pcb_mtx); 2032 2033 if (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTING) { 2034 NG_BTSOCKET_RFCOMM_ERR( 2035 "%s: Got SABM for dlci=%d in invalid state=%d, flags=%#x\n", 2036 __func__, dlci, pcb->state, pcb->flags); 2037 mtx_unlock(&pcb->pcb_mtx); 2038 2039 return (ENOENT); 2040 } 2041 2042 ng_btsocket_rfcomm_untimeout(pcb); 2043 2044 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_UA,dlci); 2045 if (error == 0) 2046 error = ng_btsocket_rfcomm_send_msc(pcb); 2047 2048 if (error == 0) { 2049 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTED; 2050 soisconnected(pcb->so); 2051 } else 2052 ng_btsocket_rfcomm_pcb_kill(pcb, error); 2053 2054 mtx_unlock(&pcb->pcb_mtx); 2055 2056 return (error); 2057 } 2058 2059 /* 2060 * We do not have requested DLCI, so it must be an incoming connection 2061 * with default parameters. Try to accept it. 2062 */ 2063 2064 pcb = ng_btsocket_rfcomm_connect_ind(s, RFCOMM_SRVCHANNEL(dlci)); 2065 if (pcb != NULL) { 2066 mtx_lock(&pcb->pcb_mtx); 2067 2068 pcb->dlci = dlci; 2069 2070 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_UA,dlci); 2071 if (error == 0) 2072 error = ng_btsocket_rfcomm_send_msc(pcb); 2073 2074 if (error == 0) { 2075 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTED; 2076 soisconnected(pcb->so); 2077 } else 2078 ng_btsocket_rfcomm_pcb_kill(pcb, error); 2079 2080 mtx_unlock(&pcb->pcb_mtx); 2081 } else 2082 /* Nobody is listen()ing on the requested DLCI */ 2083 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_DM,dlci); 2084 2085 return (error); 2086 } /* ng_btsocket_rfcomm_receive_sabm */ 2087 2088 /* 2089 * Process RFCOMM DISC frame 2090 */ 2091 2092 static int 2093 ng_btsocket_rfcomm_receive_disc(ng_btsocket_rfcomm_session_p s, int dlci) 2094 { 2095 ng_btsocket_rfcomm_pcb_p pcb = NULL; 2096 int error = 0; 2097 2098 mtx_assert(&s->session_mtx, MA_OWNED); 2099 2100 NG_BTSOCKET_RFCOMM_INFO( 2101 "%s: Got DISC, session state=%d, flags=%#x, mtu=%d, dlci=%d\n", 2102 __func__, s->state, s->flags, s->mtu, dlci); 2103 2104 /* DLCI == 0 means close multiplexor channel */ 2105 if (dlci == 0) { 2106 /* XXX FIXME assume that remote side will close the socket */ 2107 error = ng_btsocket_rfcomm_send_command(s, RFCOMM_FRAME_UA, 0); 2108 if (error == 0) { 2109 if (s->state == NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING) 2110 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED; /* XXX */ 2111 else 2112 s->state = NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING; 2113 } else 2114 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED; /* XXX */ 2115 2116 ng_btsocket_rfcomm_session_clean(s); 2117 } else { 2118 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci); 2119 if (pcb != NULL) { 2120 int err; 2121 2122 mtx_lock(&pcb->pcb_mtx); 2123 2124 NG_BTSOCKET_RFCOMM_INFO( 2125 "%s: Got DISC for dlci=%d, state=%d, flags=%#x\n", 2126 __func__, dlci, pcb->state, pcb->flags); 2127 2128 error = ng_btsocket_rfcomm_send_command(s, 2129 RFCOMM_FRAME_UA, dlci); 2130 2131 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONNECTED) 2132 err = 0; 2133 else 2134 err = ECONNREFUSED; 2135 2136 ng_btsocket_rfcomm_pcb_kill(pcb, err); 2137 2138 mtx_unlock(&pcb->pcb_mtx); 2139 } else { 2140 NG_BTSOCKET_RFCOMM_WARN( 2141 "%s: Got DISC for non-existing dlci=%d\n", __func__, dlci); 2142 2143 error = ng_btsocket_rfcomm_send_command(s, 2144 RFCOMM_FRAME_DM, dlci); 2145 } 2146 } 2147 2148 return (error); 2149 } /* ng_btsocket_rfcomm_receive_disc */ 2150 2151 /* 2152 * Process RFCOMM UA frame 2153 */ 2154 2155 static int 2156 ng_btsocket_rfcomm_receive_ua(ng_btsocket_rfcomm_session_p s, int dlci) 2157 { 2158 ng_btsocket_rfcomm_pcb_p pcb = NULL; 2159 int error = 0; 2160 2161 mtx_assert(&s->session_mtx, MA_OWNED); 2162 2163 NG_BTSOCKET_RFCOMM_INFO( 2164 "%s: Got UA, session state=%d, flags=%#x, mtu=%d, dlci=%d\n", 2165 __func__, s->state, s->flags, s->mtu, dlci); 2166 2167 /* dlci == 0 means multiplexor channel */ 2168 if (dlci == 0) { 2169 switch (s->state) { 2170 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED: 2171 s->state = NG_BTSOCKET_RFCOMM_SESSION_OPEN; 2172 ng_btsocket_rfcomm_connect_cfm(s); 2173 break; 2174 2175 case NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING: 2176 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED; 2177 ng_btsocket_rfcomm_session_clean(s); 2178 break; 2179 2180 default: 2181 NG_BTSOCKET_RFCOMM_WARN( 2182 "%s: Got UA for session in invalid state=%d(%d), flags=%#x, mtu=%d\n", 2183 __func__, s->state, INITIATOR(s), s->flags, 2184 s->mtu); 2185 error = ENOENT; 2186 break; 2187 } 2188 2189 return (error); 2190 } 2191 2192 /* Check if we have this DLCI */ 2193 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci); 2194 if (pcb != NULL) { 2195 mtx_lock(&pcb->pcb_mtx); 2196 2197 NG_BTSOCKET_RFCOMM_INFO( 2198 "%s: Got UA for dlci=%d, state=%d, flags=%#x\n", 2199 __func__, dlci, pcb->state, pcb->flags); 2200 2201 switch (pcb->state) { 2202 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING: 2203 ng_btsocket_rfcomm_untimeout(pcb); 2204 2205 error = ng_btsocket_rfcomm_send_msc(pcb); 2206 if (error == 0) { 2207 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTED; 2208 soisconnected(pcb->so); 2209 } 2210 break; 2211 2212 case NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING: 2213 ng_btsocket_rfcomm_pcb_kill(pcb, 0); 2214 break; 2215 2216 default: 2217 NG_BTSOCKET_RFCOMM_WARN( 2218 "%s: Got UA for dlci=%d in invalid state=%d, flags=%#x\n", 2219 __func__, dlci, pcb->state, pcb->flags); 2220 error = ENOENT; 2221 break; 2222 } 2223 2224 mtx_unlock(&pcb->pcb_mtx); 2225 } else { 2226 NG_BTSOCKET_RFCOMM_WARN( 2227 "%s: Got UA for non-existing dlci=%d\n", __func__, dlci); 2228 2229 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_DM,dlci); 2230 } 2231 2232 return (error); 2233 } /* ng_btsocket_rfcomm_receive_ua */ 2234 2235 /* 2236 * Process RFCOMM DM frame 2237 */ 2238 2239 static int 2240 ng_btsocket_rfcomm_receive_dm(ng_btsocket_rfcomm_session_p s, int dlci) 2241 { 2242 ng_btsocket_rfcomm_pcb_p pcb = NULL; 2243 int error; 2244 2245 mtx_assert(&s->session_mtx, MA_OWNED); 2246 2247 NG_BTSOCKET_RFCOMM_INFO( 2248 "%s: Got DM, session state=%d, flags=%#x, mtu=%d, dlci=%d\n", 2249 __func__, s->state, s->flags, s->mtu, dlci); 2250 2251 /* DLCI == 0 means multiplexor channel */ 2252 if (dlci == 0) { 2253 /* Disconnect all dlc's on the session */ 2254 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED; 2255 ng_btsocket_rfcomm_session_clean(s); 2256 } else { 2257 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci); 2258 if (pcb != NULL) { 2259 mtx_lock(&pcb->pcb_mtx); 2260 2261 NG_BTSOCKET_RFCOMM_INFO( 2262 "%s: Got DM for dlci=%d, state=%d, flags=%#x\n", 2263 __func__, dlci, pcb->state, pcb->flags); 2264 2265 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONNECTED) 2266 error = ECONNRESET; 2267 else 2268 error = ECONNREFUSED; 2269 2270 ng_btsocket_rfcomm_pcb_kill(pcb, error); 2271 2272 mtx_unlock(&pcb->pcb_mtx); 2273 } else 2274 NG_BTSOCKET_RFCOMM_WARN( 2275 "%s: Got DM for non-existing dlci=%d\n", __func__, dlci); 2276 } 2277 2278 return (0); 2279 } /* ng_btsocket_rfcomm_receive_dm */ 2280 2281 /* 2282 * Process RFCOMM UIH frame (data) 2283 */ 2284 2285 static int 2286 ng_btsocket_rfcomm_receive_uih(ng_btsocket_rfcomm_session_p s, int dlci, 2287 int pf, struct mbuf *m0) 2288 { 2289 ng_btsocket_rfcomm_pcb_p pcb = NULL; 2290 int error = 0; 2291 2292 mtx_assert(&s->session_mtx, MA_OWNED); 2293 2294 NG_BTSOCKET_RFCOMM_INFO( 2295 "%s: Got UIH, session state=%d, flags=%#x, mtu=%d, dlci=%d, pf=%d, len=%d\n", 2296 __func__, s->state, s->flags, s->mtu, dlci, pf, 2297 m0->m_pkthdr.len); 2298 2299 /* XXX should we do it here? Check for session flow control */ 2300 if (s->flags & NG_BTSOCKET_RFCOMM_SESSION_LFC) { 2301 NG_BTSOCKET_RFCOMM_WARN( 2302 "%s: Got UIH with session flow control asserted, state=%d, flags=%#x\n", 2303 __func__, s->state, s->flags); 2304 goto drop; 2305 } 2306 2307 /* Check if we have this dlci */ 2308 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci); 2309 if (pcb == NULL) { 2310 NG_BTSOCKET_RFCOMM_WARN( 2311 "%s: Got UIH for non-existing dlci=%d\n", __func__, dlci); 2312 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_DM,dlci); 2313 goto drop; 2314 } 2315 2316 mtx_lock(&pcb->pcb_mtx); 2317 2318 /* Check dlci state */ 2319 if (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTED) { 2320 NG_BTSOCKET_RFCOMM_WARN( 2321 "%s: Got UIH for dlci=%d in invalid state=%d, flags=%#x\n", 2322 __func__, dlci, pcb->state, pcb->flags); 2323 error = EINVAL; 2324 goto drop1; 2325 } 2326 2327 /* Check dlci flow control */ 2328 if (((pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) && pcb->rx_cred <= 0) || 2329 (pcb->lmodem & RFCOMM_MODEM_FC)) { 2330 NG_BTSOCKET_RFCOMM_ERR( 2331 "%s: Got UIH for dlci=%d with asserted flow control, state=%d, " \ 2332 "flags=%#x, rx_cred=%d, lmodem=%#x\n", 2333 __func__, dlci, pcb->state, pcb->flags, 2334 pcb->rx_cred, pcb->lmodem); 2335 goto drop1; 2336 } 2337 2338 /* Did we get any credits? */ 2339 if ((pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) && pf) { 2340 NG_BTSOCKET_RFCOMM_INFO( 2341 "%s: Got %d more credits for dlci=%d, state=%d, flags=%#x, " \ 2342 "rx_cred=%d, tx_cred=%d\n", 2343 __func__, *mtod(m0, u_int8_t *), dlci, pcb->state, 2344 pcb->flags, pcb->rx_cred, pcb->tx_cred); 2345 2346 pcb->tx_cred += *mtod(m0, u_int8_t *); 2347 m_adj(m0, 1); 2348 2349 /* Send more from the DLC. XXX check for errors? */ 2350 ng_btsocket_rfcomm_pcb_send(pcb, ALOT); 2351 } 2352 2353 /* OK the of the rest of the mbuf is the data */ 2354 if (m0->m_pkthdr.len > 0) { 2355 /* If we are using credit flow control decrease rx_cred here */ 2356 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) { 2357 /* Give remote peer more credits (if needed) */ 2358 if (-- pcb->rx_cred <= RFCOMM_MAX_CREDITS / 2) 2359 ng_btsocket_rfcomm_send_credits(pcb); 2360 else 2361 NG_BTSOCKET_RFCOMM_INFO( 2362 "%s: Remote side still has credits, dlci=%d, state=%d, flags=%#x, " \ 2363 "rx_cred=%d, tx_cred=%d\n", __func__, dlci, pcb->state, pcb->flags, 2364 pcb->rx_cred, pcb->tx_cred); 2365 } 2366 2367 /* Check packet against mtu on dlci */ 2368 if (m0->m_pkthdr.len > pcb->mtu) { 2369 NG_BTSOCKET_RFCOMM_ERR( 2370 "%s: Got oversized UIH for dlci=%d, state=%d, flags=%#x, mtu=%d, len=%d\n", 2371 __func__, dlci, pcb->state, pcb->flags, 2372 pcb->mtu, m0->m_pkthdr.len); 2373 2374 error = EMSGSIZE; 2375 } else if (m0->m_pkthdr.len > sbspace(&pcb->so->so_rcv)) { 2376 2377 /* 2378 * This is really bad. Receive queue on socket does 2379 * not have enough space for the packet. We do not 2380 * have any other choice but drop the packet. 2381 */ 2382 2383 NG_BTSOCKET_RFCOMM_ERR( 2384 "%s: Not enough space in socket receive queue. Dropping UIH for dlci=%d, " \ 2385 "state=%d, flags=%#x, len=%d, space=%ld\n", 2386 __func__, dlci, pcb->state, pcb->flags, 2387 m0->m_pkthdr.len, sbspace(&pcb->so->so_rcv)); 2388 2389 error = ENOBUFS; 2390 } else { 2391 /* Append packet to the socket receive queue */ 2392 sbappend(&pcb->so->so_rcv, m0); 2393 m0 = NULL; 2394 2395 sorwakeup(pcb->so); 2396 } 2397 } 2398 drop1: 2399 mtx_unlock(&pcb->pcb_mtx); 2400 drop: 2401 NG_FREE_M(m0); /* checks for != NULL */ 2402 2403 return (error); 2404 } /* ng_btsocket_rfcomm_receive_uih */ 2405 2406 /* 2407 * Process RFCOMM MCC command (Multiplexor) 2408 * 2409 * From TS 07.10 spec 2410 * 2411 * "5.4.3.1 Information Data 2412 * 2413 * ...The frames (UIH) sent by the initiating station have the C/R bit set 2414 * to 1 and those sent by the responding station have the C/R bit set to 0..." 2415 * 2416 * "5.4.6.2 Operating procedures 2417 * 2418 * Messages always exist in pairs; a command message and a corresponding 2419 * response message. If the C/R bit is set to 1 the message is a command, 2420 * if it is set to 0 the message is a response... 2421 * 2422 * ... 2423 * 2424 * NOTE: Notice that when UIH frames are used to convey information on DLCI 0 2425 * there are at least two different fields that contain a C/R bit, and the 2426 * bits are set of different form. The C/R bit in the Type field shall be set 2427 * as it is stated above, while the C/R bit in the Address field (see subclause 2428 * 5.2.1.2) shall be set as it is described in subclause 5.4.3.1." 2429 */ 2430 2431 static int 2432 ng_btsocket_rfcomm_receive_mcc(ng_btsocket_rfcomm_session_p s, struct mbuf *m0) 2433 { 2434 struct rfcomm_mcc_hdr *hdr = NULL; 2435 u_int8_t cr, type, length; 2436 2437 mtx_assert(&s->session_mtx, MA_OWNED); 2438 2439 /* 2440 * We can access data directly in the first mbuf, because we have 2441 * m_pullup()'ed mbuf chain in ng_btsocket_rfcomm_receive_frame(). 2442 * All MCC commands should fit into single mbuf (except probably TEST). 2443 */ 2444 2445 hdr = mtod(m0, struct rfcomm_mcc_hdr *); 2446 cr = RFCOMM_CR(hdr->type); 2447 type = RFCOMM_MCC_TYPE(hdr->type); 2448 length = RFCOMM_MCC_LENGTH(hdr->length); 2449 2450 /* Check MCC frame length */ 2451 if (sizeof(*hdr) + length != m0->m_pkthdr.len) { 2452 NG_BTSOCKET_RFCOMM_ERR( 2453 "%s: Invalid MCC frame length=%d, len=%d\n", 2454 __func__, length, m0->m_pkthdr.len); 2455 NG_FREE_M(m0); 2456 2457 return (EMSGSIZE); 2458 } 2459 2460 switch (type) { 2461 case RFCOMM_MCC_TEST: 2462 return (ng_btsocket_rfcomm_receive_test(s, m0)); 2463 /* NOT REACHED */ 2464 2465 case RFCOMM_MCC_FCON: 2466 case RFCOMM_MCC_FCOFF: 2467 return (ng_btsocket_rfcomm_receive_fc(s, m0)); 2468 /* NOT REACHED */ 2469 2470 case RFCOMM_MCC_MSC: 2471 return (ng_btsocket_rfcomm_receive_msc(s, m0)); 2472 /* NOT REACHED */ 2473 2474 case RFCOMM_MCC_RPN: 2475 return (ng_btsocket_rfcomm_receive_rpn(s, m0)); 2476 /* NOT REACHED */ 2477 2478 case RFCOMM_MCC_RLS: 2479 return (ng_btsocket_rfcomm_receive_rls(s, m0)); 2480 /* NOT REACHED */ 2481 2482 case RFCOMM_MCC_PN: 2483 return (ng_btsocket_rfcomm_receive_pn(s, m0)); 2484 /* NOT REACHED */ 2485 2486 case RFCOMM_MCC_NSC: 2487 NG_BTSOCKET_RFCOMM_ERR( 2488 "%s: Got MCC NSC, type=%#x, cr=%d, length=%d, session state=%d, flags=%#x, " \ 2489 "mtu=%d, len=%d\n", __func__, RFCOMM_MCC_TYPE(*((u_int8_t *)(hdr + 1))), cr, 2490 length, s->state, s->flags, s->mtu, m0->m_pkthdr.len); 2491 NG_FREE_M(m0); 2492 break; 2493 2494 default: 2495 NG_BTSOCKET_RFCOMM_ERR( 2496 "%s: Got unknown MCC, type=%#x, cr=%d, length=%d, session state=%d, " \ 2497 "flags=%#x, mtu=%d, len=%d\n", 2498 __func__, type, cr, length, s->state, s->flags, 2499 s->mtu, m0->m_pkthdr.len); 2500 2501 /* Reuse mbuf to send NSC */ 2502 hdr = mtod(m0, struct rfcomm_mcc_hdr *); 2503 m0->m_pkthdr.len = m0->m_len = sizeof(*hdr); 2504 2505 /* Create MCC NSC header */ 2506 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_NSC); 2507 hdr->length = RFCOMM_MKLEN8(1); 2508 2509 /* Put back MCC command type we did not like */ 2510 m0->m_data[m0->m_len] = RFCOMM_MKMCC_TYPE(cr, type); 2511 m0->m_pkthdr.len ++; 2512 m0->m_len ++; 2513 2514 /* Send UIH frame */ 2515 return (ng_btsocket_rfcomm_send_uih(s, 2516 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0)); 2517 /* NOT REACHED */ 2518 } 2519 2520 return (0); 2521 } /* ng_btsocket_rfcomm_receive_mcc */ 2522 2523 /* 2524 * Receive RFCOMM TEST MCC command 2525 */ 2526 2527 static int 2528 ng_btsocket_rfcomm_receive_test(ng_btsocket_rfcomm_session_p s, struct mbuf *m0) 2529 { 2530 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr *); 2531 int error = 0; 2532 2533 mtx_assert(&s->session_mtx, MA_OWNED); 2534 2535 NG_BTSOCKET_RFCOMM_INFO( 2536 "%s: Got MCC TEST, cr=%d, length=%d, session state=%d, flags=%#x, mtu=%d, " \ 2537 "len=%d\n", __func__, RFCOMM_CR(hdr->type), RFCOMM_MCC_LENGTH(hdr->length), 2538 s->state, s->flags, s->mtu, m0->m_pkthdr.len); 2539 2540 if (RFCOMM_CR(hdr->type)) { 2541 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_TEST); 2542 error = ng_btsocket_rfcomm_send_uih(s, 2543 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0); 2544 } else 2545 NG_FREE_M(m0); /* XXX ignore response */ 2546 2547 return (error); 2548 } /* ng_btsocket_rfcomm_receive_test */ 2549 2550 /* 2551 * Receive RFCOMM FCON/FCOFF MCC command 2552 */ 2553 2554 static int 2555 ng_btsocket_rfcomm_receive_fc(ng_btsocket_rfcomm_session_p s, struct mbuf *m0) 2556 { 2557 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr *); 2558 u_int8_t type = RFCOMM_MCC_TYPE(hdr->type); 2559 int error = 0; 2560 2561 mtx_assert(&s->session_mtx, MA_OWNED); 2562 2563 /* 2564 * Turn ON/OFF aggregate flow on the entire session. When remote peer 2565 * asserted flow control no transmission shall occur except on dlci 0 2566 * (control channel). 2567 */ 2568 2569 NG_BTSOCKET_RFCOMM_INFO( 2570 "%s: Got MCC FC%s, cr=%d, length=%d, session state=%d, flags=%#x, mtu=%d, " \ 2571 "len=%d\n", __func__, (type == RFCOMM_MCC_FCON)? "ON" : "OFF", 2572 RFCOMM_CR(hdr->type), RFCOMM_MCC_LENGTH(hdr->length), 2573 s->state, s->flags, s->mtu, m0->m_pkthdr.len); 2574 2575 if (RFCOMM_CR(hdr->type)) { 2576 if (type == RFCOMM_MCC_FCON) 2577 s->flags &= ~NG_BTSOCKET_RFCOMM_SESSION_RFC; 2578 else 2579 s->flags |= NG_BTSOCKET_RFCOMM_SESSION_RFC; 2580 2581 hdr->type = RFCOMM_MKMCC_TYPE(0, type); 2582 error = ng_btsocket_rfcomm_send_uih(s, 2583 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0); 2584 } else 2585 NG_FREE_M(m0); /* XXX ignore response */ 2586 2587 return (error); 2588 } /* ng_btsocket_rfcomm_receive_fc */ 2589 2590 /* 2591 * Receive RFCOMM MSC MCC command 2592 */ 2593 2594 static int 2595 ng_btsocket_rfcomm_receive_msc(ng_btsocket_rfcomm_session_p s, struct mbuf *m0) 2596 { 2597 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr*); 2598 struct rfcomm_mcc_msc *msc = (struct rfcomm_mcc_msc *)(hdr+1); 2599 ng_btsocket_rfcomm_pcb_t *pcb = NULL; 2600 int error = 0; 2601 2602 mtx_assert(&s->session_mtx, MA_OWNED); 2603 2604 NG_BTSOCKET_RFCOMM_INFO( 2605 "%s: Got MCC MSC, dlci=%d, cr=%d, length=%d, session state=%d, flags=%#x, " \ 2606 "mtu=%d, len=%d\n", 2607 __func__, RFCOMM_DLCI(msc->address), RFCOMM_CR(hdr->type), 2608 RFCOMM_MCC_LENGTH(hdr->length), s->state, s->flags, 2609 s->mtu, m0->m_pkthdr.len); 2610 2611 if (RFCOMM_CR(hdr->type)) { 2612 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, RFCOMM_DLCI(msc->address)); 2613 if (pcb == NULL) { 2614 NG_BTSOCKET_RFCOMM_WARN( 2615 "%s: Got MSC command for non-existing dlci=%d\n", 2616 __func__, RFCOMM_DLCI(msc->address)); 2617 NG_FREE_M(m0); 2618 2619 return (ENOENT); 2620 } 2621 2622 mtx_lock(&pcb->pcb_mtx); 2623 2624 if (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTING && 2625 pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTED) { 2626 NG_BTSOCKET_RFCOMM_WARN( 2627 "%s: Got MSC on dlci=%d in invalid state=%d\n", 2628 __func__, RFCOMM_DLCI(msc->address), 2629 pcb->state); 2630 2631 mtx_unlock(&pcb->pcb_mtx); 2632 NG_FREE_M(m0); 2633 2634 return (EINVAL); 2635 } 2636 2637 pcb->rmodem = msc->modem; /* Update remote port signals */ 2638 2639 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_MSC); 2640 error = ng_btsocket_rfcomm_send_uih(s, 2641 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0); 2642 2643 #if 0 /* YYY */ 2644 /* Send more data from DLC. XXX check for errors? */ 2645 if (!(pcb->rmodem & RFCOMM_MODEM_FC) && 2646 !(pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC)) 2647 ng_btsocket_rfcomm_pcb_send(pcb, ALOT); 2648 #endif /* YYY */ 2649 2650 mtx_unlock(&pcb->pcb_mtx); 2651 } else 2652 NG_FREE_M(m0); /* XXX ignore response */ 2653 2654 return (error); 2655 } /* ng_btsocket_rfcomm_receive_msc */ 2656 2657 /* 2658 * Receive RFCOMM RPN MCC command 2659 * XXX FIXME do we need htole16/le16toh for RPN param_mask? 2660 */ 2661 2662 static int 2663 ng_btsocket_rfcomm_receive_rpn(ng_btsocket_rfcomm_session_p s, struct mbuf *m0) 2664 { 2665 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr *); 2666 struct rfcomm_mcc_rpn *rpn = (struct rfcomm_mcc_rpn *)(hdr + 1); 2667 int error = 0; 2668 u_int16_t param_mask; 2669 u_int8_t bit_rate, data_bits, stop_bits, parity, 2670 flow_control, xon_char, xoff_char; 2671 2672 mtx_assert(&s->session_mtx, MA_OWNED); 2673 2674 NG_BTSOCKET_RFCOMM_INFO( 2675 "%s: Got MCC RPN, dlci=%d, cr=%d, length=%d, session state=%d, flags=%#x, " \ 2676 "mtu=%d, len=%d\n", 2677 __func__, RFCOMM_DLCI(rpn->dlci), RFCOMM_CR(hdr->type), 2678 RFCOMM_MCC_LENGTH(hdr->length), s->state, s->flags, 2679 s->mtu, m0->m_pkthdr.len); 2680 2681 if (RFCOMM_CR(hdr->type)) { 2682 param_mask = RFCOMM_RPN_PM_ALL; 2683 2684 if (RFCOMM_MCC_LENGTH(hdr->length) == 1) { 2685 /* Request - return default setting */ 2686 bit_rate = RFCOMM_RPN_BR_115200; 2687 data_bits = RFCOMM_RPN_DATA_8; 2688 stop_bits = RFCOMM_RPN_STOP_1; 2689 parity = RFCOMM_RPN_PARITY_NONE; 2690 flow_control = RFCOMM_RPN_FLOW_NONE; 2691 xon_char = RFCOMM_RPN_XON_CHAR; 2692 xoff_char = RFCOMM_RPN_XOFF_CHAR; 2693 } else { 2694 /* 2695 * Ignore/accept bit_rate, 8 bits, 1 stop bit, no 2696 * parity, no flow control lines, default XON/XOFF 2697 * chars. 2698 */ 2699 2700 bit_rate = rpn->bit_rate; 2701 rpn->param_mask = le16toh(rpn->param_mask); /* XXX */ 2702 2703 data_bits = RFCOMM_RPN_DATA_BITS(rpn->line_settings); 2704 if (rpn->param_mask & RFCOMM_RPN_PM_DATA && 2705 data_bits != RFCOMM_RPN_DATA_8) { 2706 data_bits = RFCOMM_RPN_DATA_8; 2707 param_mask ^= RFCOMM_RPN_PM_DATA; 2708 } 2709 2710 stop_bits = RFCOMM_RPN_STOP_BITS(rpn->line_settings); 2711 if (rpn->param_mask & RFCOMM_RPN_PM_STOP && 2712 stop_bits != RFCOMM_RPN_STOP_1) { 2713 stop_bits = RFCOMM_RPN_STOP_1; 2714 param_mask ^= RFCOMM_RPN_PM_STOP; 2715 } 2716 2717 parity = RFCOMM_RPN_PARITY(rpn->line_settings); 2718 if (rpn->param_mask & RFCOMM_RPN_PM_PARITY && 2719 parity != RFCOMM_RPN_PARITY_NONE) { 2720 parity = RFCOMM_RPN_PARITY_NONE; 2721 param_mask ^= RFCOMM_RPN_PM_PARITY; 2722 } 2723 2724 flow_control = rpn->flow_control; 2725 if (rpn->param_mask & RFCOMM_RPN_PM_FLOW && 2726 flow_control != RFCOMM_RPN_FLOW_NONE) { 2727 flow_control = RFCOMM_RPN_FLOW_NONE; 2728 param_mask ^= RFCOMM_RPN_PM_FLOW; 2729 } 2730 2731 xon_char = rpn->xon_char; 2732 if (rpn->param_mask & RFCOMM_RPN_PM_XON && 2733 xon_char != RFCOMM_RPN_XON_CHAR) { 2734 xon_char = RFCOMM_RPN_XON_CHAR; 2735 param_mask ^= RFCOMM_RPN_PM_XON; 2736 } 2737 2738 xoff_char = rpn->xoff_char; 2739 if (rpn->param_mask & RFCOMM_RPN_PM_XOFF && 2740 xoff_char != RFCOMM_RPN_XOFF_CHAR) { 2741 xoff_char = RFCOMM_RPN_XOFF_CHAR; 2742 param_mask ^= RFCOMM_RPN_PM_XOFF; 2743 } 2744 } 2745 2746 rpn->bit_rate = bit_rate; 2747 rpn->line_settings = RFCOMM_MKRPN_LINE_SETTINGS(data_bits, 2748 stop_bits, parity); 2749 rpn->flow_control = flow_control; 2750 rpn->xon_char = xon_char; 2751 rpn->xoff_char = xoff_char; 2752 rpn->param_mask = htole16(param_mask); /* XXX */ 2753 2754 m0->m_pkthdr.len = m0->m_len = sizeof(*hdr) + sizeof(*rpn); 2755 2756 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_RPN); 2757 error = ng_btsocket_rfcomm_send_uih(s, 2758 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0); 2759 } else 2760 NG_FREE_M(m0); /* XXX ignore response */ 2761 2762 return (error); 2763 } /* ng_btsocket_rfcomm_receive_rpn */ 2764 2765 /* 2766 * Receive RFCOMM RLS MCC command 2767 */ 2768 2769 static int 2770 ng_btsocket_rfcomm_receive_rls(ng_btsocket_rfcomm_session_p s, struct mbuf *m0) 2771 { 2772 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr *); 2773 struct rfcomm_mcc_rls *rls = (struct rfcomm_mcc_rls *)(hdr + 1); 2774 int error = 0; 2775 2776 mtx_assert(&s->session_mtx, MA_OWNED); 2777 2778 /* 2779 * XXX FIXME Do we have to do anything else here? Remote peer tries to 2780 * tell us something about DLCI. Just report what we have received and 2781 * return back received values as required by TS 07.10 spec. 2782 */ 2783 2784 NG_BTSOCKET_RFCOMM_INFO( 2785 "%s: Got MCC RLS, dlci=%d, status=%#x, cr=%d, length=%d, session state=%d, " \ 2786 "flags=%#x, mtu=%d, len=%d\n", 2787 __func__, RFCOMM_DLCI(rls->address), rls->status, 2788 RFCOMM_CR(hdr->type), RFCOMM_MCC_LENGTH(hdr->length), 2789 s->state, s->flags, s->mtu, m0->m_pkthdr.len); 2790 2791 if (RFCOMM_CR(hdr->type)) { 2792 if (rls->status & 0x1) 2793 NG_BTSOCKET_RFCOMM_ERR( 2794 "%s: Got RLS dlci=%d, error=%#x\n", __func__, RFCOMM_DLCI(rls->address), 2795 rls->status >> 1); 2796 2797 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_RLS); 2798 error = ng_btsocket_rfcomm_send_uih(s, 2799 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0); 2800 } else 2801 NG_FREE_M(m0); /* XXX ignore responses */ 2802 2803 return (error); 2804 } /* ng_btsocket_rfcomm_receive_rls */ 2805 2806 /* 2807 * Receive RFCOMM PN MCC command 2808 */ 2809 2810 static int 2811 ng_btsocket_rfcomm_receive_pn(ng_btsocket_rfcomm_session_p s, struct mbuf *m0) 2812 { 2813 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr*); 2814 struct rfcomm_mcc_pn *pn = (struct rfcomm_mcc_pn *)(hdr+1); 2815 ng_btsocket_rfcomm_pcb_t *pcb = NULL; 2816 int error = 0; 2817 2818 mtx_assert(&s->session_mtx, MA_OWNED); 2819 2820 NG_BTSOCKET_RFCOMM_INFO( 2821 "%s: Got MCC PN, dlci=%d, cr=%d, length=%d, flow_control=%#x, priority=%d, " \ 2822 "ack_timer=%d, mtu=%d, max_retrans=%d, credits=%d, session state=%d, " \ 2823 "flags=%#x, session mtu=%d, len=%d\n", 2824 __func__, pn->dlci, RFCOMM_CR(hdr->type), 2825 RFCOMM_MCC_LENGTH(hdr->length), pn->flow_control, pn->priority, 2826 pn->ack_timer, le16toh(pn->mtu), pn->max_retrans, pn->credits, 2827 s->state, s->flags, s->mtu, m0->m_pkthdr.len); 2828 2829 if (pn->dlci == 0) { 2830 NG_BTSOCKET_RFCOMM_ERR("%s: Zero dlci in MCC PN\n", __func__); 2831 NG_FREE_M(m0); 2832 2833 return (EINVAL); 2834 } 2835 2836 /* Check if we have this dlci */ 2837 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, pn->dlci); 2838 if (pcb != NULL) { 2839 mtx_lock(&pcb->pcb_mtx); 2840 2841 if (RFCOMM_CR(hdr->type)) { 2842 /* PN Request */ 2843 ng_btsocket_rfcomm_set_pn(pcb, 1, pn->flow_control, 2844 pn->credits, pn->mtu); 2845 2846 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) { 2847 pn->flow_control = 0xe0; 2848 pn->credits = RFCOMM_DEFAULT_CREDITS; 2849 } else { 2850 pn->flow_control = 0; 2851 pn->credits = 0; 2852 } 2853 2854 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_PN); 2855 error = ng_btsocket_rfcomm_send_uih(s, 2856 RFCOMM_MKADDRESS(INITIATOR(s), 0), 2857 0, 0, m0); 2858 } else { 2859 /* PN Response - proceed with SABM. Timeout still set */ 2860 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONFIGURING) { 2861 ng_btsocket_rfcomm_set_pn(pcb, 0, 2862 pn->flow_control, pn->credits, pn->mtu); 2863 2864 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTING; 2865 error = ng_btsocket_rfcomm_send_command(s, 2866 RFCOMM_FRAME_SABM, pn->dlci); 2867 } else 2868 NG_BTSOCKET_RFCOMM_WARN( 2869 "%s: Got PN response for dlci=%d in invalid state=%d\n", 2870 __func__, pn->dlci, pcb->state); 2871 2872 NG_FREE_M(m0); 2873 } 2874 2875 mtx_unlock(&pcb->pcb_mtx); 2876 } else if (RFCOMM_CR(hdr->type)) { 2877 /* PN request to non-existing dlci - incomming connection */ 2878 pcb = ng_btsocket_rfcomm_connect_ind(s, 2879 RFCOMM_SRVCHANNEL(pn->dlci)); 2880 if (pcb != NULL) { 2881 mtx_lock(&pcb->pcb_mtx); 2882 2883 pcb->dlci = pn->dlci; 2884 2885 ng_btsocket_rfcomm_set_pn(pcb, 1, pn->flow_control, 2886 pn->credits, pn->mtu); 2887 2888 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) { 2889 pn->flow_control = 0xe0; 2890 pn->credits = RFCOMM_DEFAULT_CREDITS; 2891 } else { 2892 pn->flow_control = 0; 2893 pn->credits = 0; 2894 } 2895 2896 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_PN); 2897 error = ng_btsocket_rfcomm_send_uih(s, 2898 RFCOMM_MKADDRESS(INITIATOR(s), 0), 2899 0, 0, m0); 2900 2901 if (error == 0) { 2902 ng_btsocket_rfcomm_timeout(pcb); 2903 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTING; 2904 soisconnecting(pcb->so); 2905 } else 2906 ng_btsocket_rfcomm_pcb_kill(pcb, error); 2907 2908 mtx_unlock(&pcb->pcb_mtx); 2909 } else { 2910 /* Nobody is listen()ing on this channel */ 2911 error = ng_btsocket_rfcomm_send_command(s, 2912 RFCOMM_FRAME_DM, pn->dlci); 2913 NG_FREE_M(m0); 2914 } 2915 } else 2916 NG_FREE_M(m0); /* XXX ignore response to non-existing dlci */ 2917 2918 return (error); 2919 } /* ng_btsocket_rfcomm_receive_pn */ 2920 2921 /* 2922 * Set PN parameters for dlci. Caller must hold pcb->pcb_mtx. 2923 * 2924 * From Bluetooth spec. 2925 * 2926 * "... The CL1 - CL4 field is completely redefined. (In TS07.10 this defines 2927 * the convergence layer to use, which is not applicable to RFCOMM. In RFCOMM, 2928 * in Bluetooth versions up to 1.0B, this field was forced to 0). 2929 * 2930 * In the PN request sent prior to a DLC establishment, this field must contain 2931 * the value 15 (0xF), indicating support of credit based flow control in the 2932 * sender. See Table 5.3 below. If the PN response contains any other value 2933 * than 14 (0xE) in this field, it is inferred that the peer RFCOMM entity is 2934 * not supporting the credit based flow control feature. (This is only possible 2935 * if the peer RFCOMM implementation is only conforming to Bluetooth version 2936 * 1.0B.) If a PN request is sent on an already open DLC, then this field must 2937 * contain the value zero; it is not possible to set initial credits more 2938 * than once per DLC activation. A responding implementation must set this 2939 * field in the PN response to 14 (0xE), if (and only if) the value in the PN 2940 * request was 15..." 2941 */ 2942 2943 static void 2944 ng_btsocket_rfcomm_set_pn(ng_btsocket_rfcomm_pcb_p pcb, u_int8_t cr, 2945 u_int8_t flow_control, u_int8_t credits, u_int16_t mtu) 2946 { 2947 mtx_assert(&pcb->pcb_mtx, MA_OWNED); 2948 2949 pcb->mtu = le16toh(mtu); 2950 2951 if (cr) { 2952 if (flow_control == 0xf0) { 2953 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_CFC; 2954 pcb->tx_cred = credits; 2955 } else { 2956 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_CFC; 2957 pcb->tx_cred = 0; 2958 } 2959 } else { 2960 if (flow_control == 0xe0) { 2961 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_CFC; 2962 pcb->tx_cred = credits; 2963 } else { 2964 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_CFC; 2965 pcb->tx_cred = 0; 2966 } 2967 } 2968 2969 NG_BTSOCKET_RFCOMM_INFO( 2970 "%s: cr=%d, dlci=%d, state=%d, flags=%#x, mtu=%d, rx_cred=%d, tx_cred=%d\n", 2971 __func__, cr, pcb->dlci, pcb->state, pcb->flags, pcb->mtu, 2972 pcb->rx_cred, pcb->tx_cred); 2973 } /* ng_btsocket_rfcomm_set_pn */ 2974 2975 /* 2976 * Send RFCOMM SABM/DISC/UA/DM frames. Caller must hold s->session_mtx 2977 */ 2978 2979 static int 2980 ng_btsocket_rfcomm_send_command(ng_btsocket_rfcomm_session_p s, 2981 u_int8_t type, u_int8_t dlci) 2982 { 2983 struct rfcomm_cmd_hdr *hdr = NULL; 2984 struct mbuf *m = NULL; 2985 int cr; 2986 2987 mtx_assert(&s->session_mtx, MA_OWNED); 2988 2989 NG_BTSOCKET_RFCOMM_INFO( 2990 "%s: Sending command type %#x, session state=%d, flags=%#x, mtu=%d, dlci=%d\n", 2991 __func__, type, s->state, s->flags, s->mtu, dlci); 2992 2993 switch (type) { 2994 case RFCOMM_FRAME_SABM: 2995 case RFCOMM_FRAME_DISC: 2996 cr = INITIATOR(s); 2997 break; 2998 2999 case RFCOMM_FRAME_UA: 3000 case RFCOMM_FRAME_DM: 3001 cr = !INITIATOR(s); 3002 break; 3003 3004 default: 3005 panic("%s: Invalid frame type=%#x\n", __func__, type); 3006 return (EINVAL); 3007 /* NOT REACHED */ 3008 } 3009 3010 MGETHDR(m, MB_DONTWAIT, MT_DATA); 3011 if (m == NULL) 3012 return (ENOBUFS); 3013 3014 m->m_pkthdr.len = m->m_len = sizeof(*hdr); 3015 3016 hdr = mtod(m, struct rfcomm_cmd_hdr *); 3017 hdr->address = RFCOMM_MKADDRESS(cr, dlci); 3018 hdr->control = RFCOMM_MKCONTROL(type, 1); 3019 hdr->length = RFCOMM_MKLEN8(0); 3020 hdr->fcs = ng_btsocket_rfcomm_fcs3((u_int8_t *) hdr); 3021 3022 NG_BT_MBUFQ_ENQUEUE(&s->outq, m); 3023 3024 return (0); 3025 } /* ng_btsocket_rfcomm_send_command */ 3026 3027 /* 3028 * Send RFCOMM UIH frame. Caller must hold s->session_mtx 3029 */ 3030 3031 static int 3032 ng_btsocket_rfcomm_send_uih(ng_btsocket_rfcomm_session_p s, u_int8_t address, 3033 u_int8_t pf, u_int8_t credits, struct mbuf *data) 3034 { 3035 struct rfcomm_frame_hdr *hdr = NULL; 3036 struct mbuf *m = NULL, *mcrc = NULL; 3037 u_int16_t length; 3038 3039 mtx_assert(&s->session_mtx, MA_OWNED); 3040 3041 MGETHDR(m, MB_DONTWAIT, MT_DATA); 3042 if (m == NULL) { 3043 NG_FREE_M(data); 3044 return (ENOBUFS); 3045 } 3046 m->m_pkthdr.len = m->m_len = sizeof(*hdr); 3047 3048 MGET(mcrc, MB_DONTWAIT, MT_DATA); 3049 if (mcrc == NULL) { 3050 NG_FREE_M(data); 3051 return (ENOBUFS); 3052 } 3053 mcrc->m_len = 1; 3054 3055 /* Fill UIH frame header */ 3056 hdr = mtod(m, struct rfcomm_frame_hdr *); 3057 hdr->address = address; 3058 hdr->control = RFCOMM_MKCONTROL(RFCOMM_FRAME_UIH, pf); 3059 3060 /* Calculate FCS */ 3061 mcrc->m_data[0] = ng_btsocket_rfcomm_fcs2((u_int8_t *) hdr); 3062 3063 /* Put length back */ 3064 length = (data != NULL)? data->m_pkthdr.len : 0; 3065 if (length > 127) { 3066 u_int16_t l = htole16(RFCOMM_MKLEN16(length)); 3067 3068 bcopy(&l, &hdr->length, sizeof(l)); 3069 m->m_pkthdr.len ++; 3070 m->m_len ++; 3071 } else 3072 hdr->length = RFCOMM_MKLEN8(length); 3073 3074 if (pf) { 3075 m->m_data[m->m_len] = credits; 3076 m->m_pkthdr.len ++; 3077 m->m_len ++; 3078 } 3079 3080 /* Add payload */ 3081 if (data != NULL) { 3082 m_cat(m, data); 3083 m->m_pkthdr.len += length; 3084 } 3085 3086 /* Put FCS back */ 3087 m_cat(m, mcrc); 3088 m->m_pkthdr.len ++; 3089 3090 NG_BTSOCKET_RFCOMM_INFO( 3091 "%s: Sending UIH state=%d, flags=%#x, address=%d, length=%d, pf=%d, " \ 3092 "credits=%d, len=%d\n", 3093 __func__, s->state, s->flags, address, length, pf, credits, 3094 m->m_pkthdr.len); 3095 3096 NG_BT_MBUFQ_ENQUEUE(&s->outq, m); 3097 3098 return (0); 3099 } /* ng_btsocket_rfcomm_send_uih */ 3100 3101 /* 3102 * Send MSC request. Caller must hold pcb->pcb_mtx and pcb->session->session_mtx 3103 */ 3104 3105 static int 3106 ng_btsocket_rfcomm_send_msc(ng_btsocket_rfcomm_pcb_p pcb) 3107 { 3108 struct mbuf *m = NULL; 3109 struct rfcomm_mcc_hdr *hdr = NULL; 3110 struct rfcomm_mcc_msc *msc = NULL; 3111 3112 mtx_assert(&pcb->session->session_mtx, MA_OWNED); 3113 mtx_assert(&pcb->pcb_mtx, MA_OWNED); 3114 3115 MGETHDR(m, MB_DONTWAIT, MT_DATA); 3116 if (m == NULL) 3117 return (ENOBUFS); 3118 3119 m->m_pkthdr.len = m->m_len = sizeof(*hdr) + sizeof(*msc); 3120 3121 hdr = mtod(m, struct rfcomm_mcc_hdr *); 3122 msc = (struct rfcomm_mcc_msc *)(hdr + 1); 3123 3124 hdr->type = RFCOMM_MKMCC_TYPE(1, RFCOMM_MCC_MSC); 3125 hdr->length = RFCOMM_MKLEN8(sizeof(*msc)); 3126 3127 msc->address = RFCOMM_MKADDRESS(1, pcb->dlci); 3128 msc->modem = pcb->lmodem; 3129 3130 NG_BTSOCKET_RFCOMM_INFO( 3131 "%s: Sending MSC dlci=%d, state=%d, flags=%#x, address=%d, modem=%#x\n", 3132 __func__, pcb->dlci, pcb->state, pcb->flags, msc->address, 3133 msc->modem); 3134 3135 return (ng_btsocket_rfcomm_send_uih(pcb->session, 3136 RFCOMM_MKADDRESS(INITIATOR(pcb->session), 0), 0, 0, m)); 3137 } /* ng_btsocket_rfcomm_send_msc */ 3138 3139 /* 3140 * Send PN request. Caller must hold pcb->pcb_mtx and pcb->session->session_mtx 3141 */ 3142 3143 static int 3144 ng_btsocket_rfcomm_send_pn(ng_btsocket_rfcomm_pcb_p pcb) 3145 { 3146 struct mbuf *m = NULL; 3147 struct rfcomm_mcc_hdr *hdr = NULL; 3148 struct rfcomm_mcc_pn *pn = NULL; 3149 3150 mtx_assert(&pcb->session->session_mtx, MA_OWNED); 3151 mtx_assert(&pcb->pcb_mtx, MA_OWNED); 3152 3153 MGETHDR(m, MB_DONTWAIT, MT_DATA); 3154 if (m == NULL) 3155 return (ENOBUFS); 3156 3157 m->m_pkthdr.len = m->m_len = sizeof(*hdr) + sizeof(*pn); 3158 3159 hdr = mtod(m, struct rfcomm_mcc_hdr *); 3160 pn = (struct rfcomm_mcc_pn *)(hdr + 1); 3161 3162 hdr->type = RFCOMM_MKMCC_TYPE(1, RFCOMM_MCC_PN); 3163 hdr->length = RFCOMM_MKLEN8(sizeof(*pn)); 3164 3165 pn->dlci = pcb->dlci; 3166 3167 /* 3168 * Set default DLCI priority as described in GSM 07.10 3169 * (ETSI TS 101 369) clause 5.6 page 42 3170 */ 3171 3172 pn->priority = (pcb->dlci < 56)? (((pcb->dlci >> 3) << 3) + 7) : 61; 3173 pn->ack_timer = 0; 3174 pn->mtu = htole16(pcb->mtu); 3175 pn->max_retrans = 0; 3176 3177 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) { 3178 pn->flow_control = 0xf0; 3179 pn->credits = pcb->rx_cred; 3180 } else { 3181 pn->flow_control = 0; 3182 pn->credits = 0; 3183 } 3184 3185 NG_BTSOCKET_RFCOMM_INFO( 3186 "%s: Sending PN dlci=%d, state=%d, flags=%#x, mtu=%d, flow_control=%#x, " \ 3187 "credits=%d\n", __func__, pcb->dlci, pcb->state, pcb->flags, pcb->mtu, 3188 pn->flow_control, pn->credits); 3189 3190 return (ng_btsocket_rfcomm_send_uih(pcb->session, 3191 RFCOMM_MKADDRESS(INITIATOR(pcb->session), 0), 0, 0, m)); 3192 } /* ng_btsocket_rfcomm_send_pn */ 3193 3194 /* 3195 * Calculate and send credits based on available space in receive buffer 3196 */ 3197 3198 static int 3199 ng_btsocket_rfcomm_send_credits(ng_btsocket_rfcomm_pcb_p pcb) 3200 { 3201 int error = 0; 3202 u_int8_t credits; 3203 3204 mtx_assert(&pcb->pcb_mtx, MA_OWNED); 3205 mtx_assert(&pcb->session->session_mtx, MA_OWNED); 3206 3207 NG_BTSOCKET_RFCOMM_INFO( 3208 "%s: Sending more credits, dlci=%d, state=%d, flags=%#x, mtu=%d, " \ 3209 "space=%ld, tx_cred=%d, rx_cred=%d\n", 3210 __func__, pcb->dlci, pcb->state, pcb->flags, pcb->mtu, 3211 sbspace(&pcb->so->so_rcv), pcb->tx_cred, pcb->rx_cred); 3212 3213 credits = sbspace(&pcb->so->so_rcv) / pcb->mtu; 3214 if (credits > 0) { 3215 if (pcb->rx_cred + credits > RFCOMM_MAX_CREDITS) 3216 credits = RFCOMM_MAX_CREDITS - pcb->rx_cred; 3217 3218 error = ng_btsocket_rfcomm_send_uih( 3219 pcb->session, 3220 RFCOMM_MKADDRESS(INITIATOR(pcb->session), 3221 pcb->dlci), 1, credits, NULL); 3222 if (error == 0) { 3223 pcb->rx_cred += credits; 3224 3225 NG_BTSOCKET_RFCOMM_INFO( 3226 "%s: Gave remote side %d more credits, dlci=%d, state=%d, flags=%#x, " \ 3227 "rx_cred=%d, tx_cred=%d\n", __func__, credits, pcb->dlci, pcb->state, 3228 pcb->flags, pcb->rx_cred, pcb->tx_cred); 3229 } else 3230 NG_BTSOCKET_RFCOMM_ERR( 3231 "%s: Could not send credits, error=%d, dlci=%d, state=%d, flags=%#x, " \ 3232 "mtu=%d, space=%ld, tx_cred=%d, rx_cred=%d\n", 3233 __func__, error, pcb->dlci, pcb->state, 3234 pcb->flags, pcb->mtu, sbspace(&pcb->so->so_rcv), 3235 pcb->tx_cred, pcb->rx_cred); 3236 } 3237 3238 return (error); 3239 } /* ng_btsocket_rfcomm_send_credits */ 3240 3241 /***************************************************************************** 3242 ***************************************************************************** 3243 ** RFCOMM DLCs 3244 ***************************************************************************** 3245 *****************************************************************************/ 3246 3247 /* 3248 * Send data from socket send buffer 3249 * Caller must hold pcb->pcb_mtx and pcb->session->session_mtx 3250 */ 3251 3252 static int 3253 ng_btsocket_rfcomm_pcb_send(ng_btsocket_rfcomm_pcb_p pcb, int limit) 3254 { 3255 struct mbuf *m = NULL; 3256 int sent, length, error; 3257 3258 mtx_assert(&pcb->session->session_mtx, MA_OWNED); 3259 mtx_assert(&pcb->pcb_mtx, MA_OWNED); 3260 3261 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) 3262 limit = min(limit, pcb->tx_cred); 3263 else if (!(pcb->rmodem & RFCOMM_MODEM_FC)) 3264 limit = min(limit, RFCOMM_MAX_CREDITS); /* XXX ??? */ 3265 else 3266 limit = 0; 3267 3268 if (limit == 0) { 3269 NG_BTSOCKET_RFCOMM_INFO( 3270 "%s: Could not send - remote flow control asserted, dlci=%d, flags=%#x, " \ 3271 "rmodem=%#x, tx_cred=%d\n", 3272 __func__, pcb->dlci, pcb->flags, pcb->rmodem, 3273 pcb->tx_cred); 3274 3275 return (0); 3276 } 3277 3278 for (error = 0, sent = 0; sent < limit; sent ++) { 3279 length = min(pcb->mtu, pcb->so->so_snd.sb_cc); 3280 if (length == 0) 3281 break; 3282 3283 /* Get the chunk from the socket's send buffer */ 3284 m = ng_btsocket_rfcomm_prepare_packet(&pcb->so->so_snd, length); 3285 if (m == NULL) { 3286 error = ENOBUFS; 3287 break; 3288 } 3289 3290 sbdrop(&pcb->so->so_snd, length); 3291 3292 error = ng_btsocket_rfcomm_send_uih(pcb->session, 3293 RFCOMM_MKADDRESS(INITIATOR(pcb->session), 3294 pcb->dlci), 0, 0, m); 3295 if (error != 0) 3296 break; 3297 } 3298 3299 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) 3300 pcb->tx_cred -= sent; 3301 3302 if (error == 0 && sent > 0) { 3303 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_SENDING; 3304 sowwakeup(pcb->so); 3305 } 3306 3307 return (error); 3308 } /* ng_btsocket_rfcomm_pcb_send */ 3309 3310 /* 3311 * Unlink and disconnect DLC. If ng_btsocket_rfcomm_pcb_kill() returns 3312 * non zero value than socket has no reference and has to be detached. 3313 * Caller must hold pcb->pcb_mtx and pcb->session->session_mtx 3314 */ 3315 3316 static void 3317 ng_btsocket_rfcomm_pcb_kill(ng_btsocket_rfcomm_pcb_p pcb, int error) 3318 { 3319 ng_btsocket_rfcomm_session_p s = pcb->session; 3320 3321 NG_BTSOCKET_RFCOMM_INFO( 3322 "%s: Killing DLC, so=%p, dlci=%d, state=%d, flags=%#x, error=%d\n", 3323 __func__, pcb->so, pcb->dlci, pcb->state, pcb->flags, error); 3324 3325 if (pcb->session == NULL) 3326 panic("%s: DLC without session, pcb=%p, state=%d, flags=%#x\n", 3327 __func__, pcb, pcb->state, pcb->flags); 3328 3329 mtx_assert(&pcb->session->session_mtx, MA_OWNED); 3330 mtx_assert(&pcb->pcb_mtx, MA_OWNED); 3331 3332 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO) 3333 ng_btsocket_rfcomm_untimeout(pcb); 3334 3335 /* Detach DLC from the session. Does not matter which state DLC in */ 3336 LIST_REMOVE(pcb, session_next); 3337 pcb->session = NULL; 3338 3339 /* Change DLC state and wakeup all sleepers */ 3340 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CLOSED; 3341 pcb->so->so_error = error; 3342 soisdisconnected(pcb->so); 3343 wakeup(&pcb->state); 3344 3345 /* Check if we have any DLCs left on the session */ 3346 if (LIST_EMPTY(&s->dlcs) && INITIATOR(s)) { 3347 NG_BTSOCKET_RFCOMM_INFO( 3348 "%s: Disconnecting session, state=%d, flags=%#x, mtu=%d\n", 3349 __func__, s->state, s->flags, s->mtu); 3350 3351 switch (s->state) { 3352 case NG_BTSOCKET_RFCOMM_SESSION_CLOSED: 3353 case NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING: 3354 /* 3355 * Do not have to do anything here. We can get here 3356 * when L2CAP connection was terminated or we have 3357 * received DISC on multiplexor channel 3358 */ 3359 break; 3360 3361 case NG_BTSOCKET_RFCOMM_SESSION_OPEN: 3362 /* Send DISC on multiplexor channel */ 3363 error = ng_btsocket_rfcomm_send_command(s, 3364 RFCOMM_FRAME_DISC, 0); 3365 if (error == 0) { 3366 s->state = NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING; 3367 break; 3368 } 3369 /* FALL THROUGH */ 3370 3371 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTING: 3372 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED: 3373 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED; 3374 break; 3375 3376 /* case NG_BTSOCKET_RFCOMM_SESSION_LISTENING: */ 3377 default: 3378 panic("%s: Invalid session state=%d, flags=%#x\n", 3379 __func__, s->state, s->flags); 3380 break; 3381 } 3382 3383 ng_btsocket_rfcomm_task_wakeup(); 3384 } 3385 } /* ng_btsocket_rfcomm_pcb_kill */ 3386 3387 /* 3388 * Look for given dlci for given RFCOMM session. Caller must hold s->session_mtx 3389 */ 3390 3391 static ng_btsocket_rfcomm_pcb_p 3392 ng_btsocket_rfcomm_pcb_by_dlci(ng_btsocket_rfcomm_session_p s, int dlci) 3393 { 3394 ng_btsocket_rfcomm_pcb_p pcb = NULL; 3395 3396 mtx_assert(&s->session_mtx, MA_OWNED); 3397 3398 LIST_FOREACH(pcb, &s->dlcs, session_next) 3399 if (pcb->dlci == dlci) 3400 break; 3401 3402 return (pcb); 3403 } /* ng_btsocket_rfcomm_pcb_by_dlci */ 3404 3405 /* 3406 * Look for socket that listens on given src address and given channel 3407 */ 3408 3409 static ng_btsocket_rfcomm_pcb_p 3410 ng_btsocket_rfcomm_pcb_listener(bdaddr_p src, int channel) 3411 { 3412 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb1 = NULL; 3413 3414 mtx_lock(&ng_btsocket_rfcomm_sockets_mtx); 3415 3416 LIST_FOREACH(pcb, &ng_btsocket_rfcomm_sockets, next) { 3417 if (pcb->channel != channel || 3418 !(pcb->so->so_options & SO_ACCEPTCONN)) 3419 continue; 3420 3421 if (bcmp(&pcb->src, src, sizeof(*src)) == 0) 3422 break; 3423 3424 if (bcmp(&pcb->src, NG_HCI_BDADDR_ANY, sizeof(bdaddr_t)) == 0) 3425 pcb1 = pcb; 3426 } 3427 3428 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx); 3429 3430 return ((pcb != NULL)? pcb : pcb1); 3431 } /* ng_btsocket_rfcomm_pcb_listener */ 3432 3433 /***************************************************************************** 3434 ***************************************************************************** 3435 ** Misc. functions 3436 ***************************************************************************** 3437 *****************************************************************************/ 3438 3439 /* 3440 * Set timeout. Caller MUST hold pcb_mtx 3441 */ 3442 3443 static void 3444 ng_btsocket_rfcomm_timeout(ng_btsocket_rfcomm_pcb_p pcb) 3445 { 3446 mtx_assert(&pcb->pcb_mtx, MA_OWNED); 3447 3448 if (!(pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)) { 3449 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_TIMO; 3450 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT; 3451 pcb->timo = timeout(ng_btsocket_rfcomm_process_timeout, pcb, 3452 ng_btsocket_rfcomm_timo * hz); 3453 } else 3454 panic("%s: Duplicated socket timeout?!\n", __func__); 3455 } /* ng_btsocket_rfcomm_timeout */ 3456 3457 /* 3458 * Unset pcb timeout. Caller MUST hold pcb_mtx 3459 */ 3460 3461 static void 3462 ng_btsocket_rfcomm_untimeout(ng_btsocket_rfcomm_pcb_p pcb) 3463 { 3464 mtx_assert(&pcb->pcb_mtx, MA_OWNED); 3465 3466 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO) { 3467 untimeout(ng_btsocket_rfcomm_process_timeout, pcb, pcb->timo); 3468 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMO; 3469 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT; 3470 } else 3471 panic("%s: No socket timeout?!\n", __func__); 3472 } /* ng_btsocket_rfcomm_timeout */ 3473 3474 /* 3475 * Process pcb timeout 3476 */ 3477 3478 static void 3479 ng_btsocket_rfcomm_process_timeout(void *xpcb) 3480 { 3481 ng_btsocket_rfcomm_pcb_p pcb = (ng_btsocket_rfcomm_pcb_p) xpcb; 3482 3483 mtx_lock(&pcb->pcb_mtx); 3484 3485 NG_BTSOCKET_RFCOMM_INFO( 3486 "%s: Timeout, so=%p, dlci=%d, state=%d, flags=%#x\n", 3487 __func__, pcb->so, pcb->dlci, pcb->state, pcb->flags); 3488 3489 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMO; 3490 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT; 3491 3492 switch (pcb->state) { 3493 case NG_BTSOCKET_RFCOMM_DLC_CONFIGURING: 3494 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING: 3495 pcb->state = NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING; 3496 break; 3497 3498 case NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT: 3499 case NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING: 3500 break; 3501 3502 default: 3503 panic( 3504 "%s: DLC timeout in invalid state, dlci=%d, state=%d, flags=%#x\n", 3505 __func__, pcb->dlci, pcb->state, pcb->flags); 3506 break; 3507 } 3508 3509 ng_btsocket_rfcomm_task_wakeup(); 3510 3511 mtx_unlock(&pcb->pcb_mtx); 3512 } /* ng_btsocket_rfcomm_process_timeout */ 3513 3514 /* 3515 * Get up to length bytes from the socket buffer 3516 */ 3517 3518 static struct mbuf * 3519 ng_btsocket_rfcomm_prepare_packet(struct sockbuf *sb, int length) 3520 { 3521 struct mbuf *top = NULL, *m = NULL, *n = NULL, *nextpkt = NULL; 3522 int mlen, noff, len; 3523 3524 MGETHDR(top, MB_DONTWAIT, MT_DATA); 3525 if (top == NULL) 3526 return (NULL); 3527 3528 top->m_pkthdr.len = length; 3529 top->m_len = 0; 3530 mlen = MHLEN; 3531 3532 m = top; 3533 n = sb->sb_mb; 3534 nextpkt = n->m_nextpkt; 3535 noff = 0; 3536 3537 while (length > 0 && n != NULL) { 3538 len = min(mlen - m->m_len, n->m_len - noff); 3539 if (len > length) 3540 len = length; 3541 3542 bcopy(mtod(n, caddr_t)+noff, mtod(m, caddr_t)+m->m_len, len); 3543 m->m_len += len; 3544 noff += len; 3545 length -= len; 3546 3547 if (length > 0 && m->m_len == mlen) { 3548 MGET(m->m_next, MB_DONTWAIT, MT_DATA); 3549 if (m->m_next == NULL) { 3550 NG_FREE_M(top); 3551 return (NULL); 3552 } 3553 3554 m = m->m_next; 3555 m->m_len = 0; 3556 mlen = MLEN; 3557 } 3558 3559 if (noff == n->m_len) { 3560 noff = 0; 3561 n = n->m_next; 3562 3563 if (n == NULL) 3564 n = nextpkt; 3565 3566 nextpkt = (n != NULL)? n->m_nextpkt : NULL; 3567 } 3568 } 3569 3570 if (length < 0) 3571 panic("%s: length=%d\n", __func__, length); 3572 if (length > 0 && n == NULL) 3573 panic("%s: bogus length=%d, n=%p\n", __func__, length, n); 3574 3575 return (top); 3576 } /* ng_btsocket_rfcomm_prepare_packet */ 3577 3578