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