1 /*
2 * ng_btsocket_rfcomm.c
3 */
4
5 /*-
6 * Copyright (c) 2001-2003 Maksim Yevmenkin <m_evmenkin@yahoo.com>
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 *
30 * $Id: ng_btsocket_rfcomm.c,v 1.28 2003/09/14 23:29:06 max Exp $
31 * $FreeBSD: src/sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c,v 1.27 2007/10/29 19:06:47 emax Exp $
32 */
33
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/bitstring.h>
37 #include <sys/domain.h>
38 #include <sys/endian.h>
39 #include <sys/errno.h>
40 #include <sys/filedesc.h>
41 #include <sys/kernel.h>
42 #include <sys/lock.h>
43 #include <sys/malloc.h>
44 #include <sys/mbuf.h>
45 #include <sys/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
ng_btsocket_rfcomm_crc(u_int8_t * data,int length)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
ng_btsocket_rfcomm_fcs2(u_int8_t * data)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
ng_btsocket_rfcomm_fcs3(u_int8_t * data)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
ng_btsocket_rfcomm_check_fcs(u_int8_t * data,int type,u_int8_t fcs)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
ng_btsocket_rfcomm_init(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
ng_btsocket_rfcomm_abort(netmsg_t msg)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
ng_btsocket_rfcomm_accept(netmsg_t msg)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
ng_btsocket_rfcomm_attach(netmsg_t msg)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
ng_btsocket_rfcomm_bind(netmsg_t msg)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
ng_btsocket_rfcomm_connect(netmsg_t msg)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
ng_btsocket_rfcomm_control(netmsg_t msg)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
ng_btsocket_rfcomm_ctloutput(netmsg_t msg)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
ng_btsocket_rfcomm_detach(netmsg_t msg)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
ng_btsocket_rfcomm_disconnect(netmsg_t msg)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
ng_btsocket_rfcomm_listen(netmsg_t msg)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
ng_btsocket_rfcomm_peeraddr(netmsg_t msg)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
ng_btsocket_rfcomm_send(netmsg_t msg)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
ng_btsocket_rfcomm_sockaddr(netmsg_t msg)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
ng_btsocket_rfcomm_upcall(struct socket * so,void * arg,int waitflag)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
ng_btsocket_rfcomm_sessions_task(void * ctx,int pending)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
ng_btsocket_rfcomm_session_task(ng_btsocket_rfcomm_session_p s)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
ng_btsocket_rfcomm_connect_ind(ng_btsocket_rfcomm_session_p s,int channel)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
ng_btsocket_rfcomm_connect_cfm(ng_btsocket_rfcomm_session_p s)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
ng_btsocket_rfcomm_session_create(ng_btsocket_rfcomm_session_p * sp,struct socket * l2so,bdaddr_p src,bdaddr_p dst,struct thread * td)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
ng_btsocket_rfcomm_session_accept(ng_btsocket_rfcomm_session_p s0)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
ng_btsocket_rfcomm_session_connect(ng_btsocket_rfcomm_session_p s)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
ng_btsocket_rfcomm_session_receive(ng_btsocket_rfcomm_session_p s)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
ng_btsocket_rfcomm_session_send(ng_btsocket_rfcomm_session_p s)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
ng_btsocket_rfcomm_session_clean(ng_btsocket_rfcomm_session_p s)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
ng_btsocket_rfcomm_session_process_pcb(ng_btsocket_rfcomm_session_p s)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
ng_btsocket_rfcomm_session_by_addr(bdaddr_p src,bdaddr_p dst)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
ng_btsocket_rfcomm_receive_frame(ng_btsocket_rfcomm_session_p s,struct mbuf * m0)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
ng_btsocket_rfcomm_receive_sabm(ng_btsocket_rfcomm_session_p s,int dlci)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
ng_btsocket_rfcomm_receive_disc(ng_btsocket_rfcomm_session_p s,int dlci)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
ng_btsocket_rfcomm_receive_ua(ng_btsocket_rfcomm_session_p s,int dlci)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
ng_btsocket_rfcomm_receive_dm(ng_btsocket_rfcomm_session_p s,int dlci)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
ng_btsocket_rfcomm_receive_uih(ng_btsocket_rfcomm_session_p s,int dlci,int pf,struct mbuf * m0)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
ng_btsocket_rfcomm_receive_mcc(ng_btsocket_rfcomm_session_p s,struct mbuf * m0)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
ng_btsocket_rfcomm_receive_test(ng_btsocket_rfcomm_session_p s,struct mbuf * m0)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
ng_btsocket_rfcomm_receive_fc(ng_btsocket_rfcomm_session_p s,struct mbuf * m0)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
ng_btsocket_rfcomm_receive_msc(ng_btsocket_rfcomm_session_p s,struct mbuf * m0)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
ng_btsocket_rfcomm_receive_rpn(ng_btsocket_rfcomm_session_p s,struct mbuf * m0)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
ng_btsocket_rfcomm_receive_rls(ng_btsocket_rfcomm_session_p s,struct mbuf * m0)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
ng_btsocket_rfcomm_receive_pn(ng_btsocket_rfcomm_session_p s,struct mbuf * m0)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
ng_btsocket_rfcomm_set_pn(ng_btsocket_rfcomm_pcb_p pcb,u_int8_t cr,u_int8_t flow_control,u_int8_t credits,u_int16_t mtu)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
ng_btsocket_rfcomm_send_command(ng_btsocket_rfcomm_session_p s,u_int8_t type,u_int8_t dlci)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
ng_btsocket_rfcomm_send_uih(ng_btsocket_rfcomm_session_p s,u_int8_t address,u_int8_t pf,u_int8_t credits,struct mbuf * data)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
ng_btsocket_rfcomm_send_msc(ng_btsocket_rfcomm_pcb_p pcb)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
ng_btsocket_rfcomm_send_pn(ng_btsocket_rfcomm_pcb_p pcb)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
ng_btsocket_rfcomm_send_credits(ng_btsocket_rfcomm_pcb_p pcb)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
ng_btsocket_rfcomm_pcb_send(ng_btsocket_rfcomm_pcb_p pcb,int limit)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
ng_btsocket_rfcomm_pcb_kill(ng_btsocket_rfcomm_pcb_p pcb,int error)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
ng_btsocket_rfcomm_pcb_by_dlci(ng_btsocket_rfcomm_session_p s,int dlci)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
ng_btsocket_rfcomm_pcb_listener(bdaddr_p src,int channel)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
ng_btsocket_rfcomm_timeout(ng_btsocket_rfcomm_pcb_p pcb)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
ng_btsocket_rfcomm_untimeout(ng_btsocket_rfcomm_pcb_p pcb)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
ng_btsocket_rfcomm_process_timeout(void * xpcb)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 *
ng_btsocket_rfcomm_prepare_packet(struct sockbuf * sb,int length)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