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