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