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