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