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