xref: /freebsd/sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c (revision 273c26a3c3bea87a241d6879abd4f991db180bf0)
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 = NULL;
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 	if (pcb->so->so_qlen <= pcb->so->so_qlimit) {
1175 		CURVNET_SET(pcb->so->so_vnet);
1176 		so1 = sonewconn(pcb->so, 0);
1177 		CURVNET_RESTORE();
1178 	}
1179 
1180 	mtx_unlock(&pcb->pcb_mtx);
1181 
1182 	if (so1 == NULL)
1183 		return (NULL);
1184 
1185 	/*
1186 	 * If we got here than we have created new socket. So complete the
1187 	 * connection. Set source and destination address from the session.
1188 	 */
1189 
1190 	pcb1 = so2rfcomm_pcb(so1);
1191 	if (pcb1 == NULL)
1192 		panic("%s: pcb1 == NULL\n", __func__);
1193 
1194 	mtx_lock(&pcb1->pcb_mtx);
1195 
1196 	bcopy(&l2pcb->src, &pcb1->src, sizeof(pcb1->src));
1197 	bcopy(&l2pcb->dst, &pcb1->dst, sizeof(pcb1->dst));
1198 	pcb1->channel = channel;
1199 
1200 	/* Link new DLC to the session. We already hold s->session_mtx */
1201 	LIST_INSERT_HEAD(&s->dlcs, pcb1, session_next);
1202 	pcb1->session = s;
1203 
1204 	mtx_unlock(&pcb1->pcb_mtx);
1205 
1206 	return (pcb1);
1207 } /* ng_btsocket_rfcomm_connect_ind */
1208 
1209 /*
1210  * Process RFCOMM connect confirmation. Caller must hold s->session_mtx.
1211  */
1212 
1213 static void
1214 ng_btsocket_rfcomm_connect_cfm(ng_btsocket_rfcomm_session_p s)
1215 {
1216 	ng_btsocket_rfcomm_pcb_p	pcb = NULL, pcb_next = NULL;
1217 	int				error;
1218 
1219 	mtx_assert(&s->session_mtx, MA_OWNED);
1220 
1221 	/*
1222 	 * Wake up all waiting sockets and send PN request for each of them.
1223 	 * Note that timeout already been set in ng_btsocket_rfcomm_connect()
1224 	 *
1225 	 * Note: cannot use LIST_FOREACH because ng_btsocket_rfcomm_pcb_kill
1226 	 * will unlink DLC from the session
1227 	 */
1228 
1229 	for (pcb = LIST_FIRST(&s->dlcs); pcb != NULL; ) {
1230 		mtx_lock(&pcb->pcb_mtx);
1231 		pcb_next = LIST_NEXT(pcb, session_next);
1232 
1233 		if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT) {
1234 			pcb->mtu = s->mtu;
1235 			bcopy(&so2l2cap_pcb(s->l2so)->src, &pcb->src,
1236 				sizeof(pcb->src));
1237 
1238 			error = ng_btsocket_rfcomm_send_pn(pcb);
1239 			if (error == 0)
1240 				pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONFIGURING;
1241 			else
1242 				ng_btsocket_rfcomm_pcb_kill(pcb, error);
1243 		}
1244 
1245 		mtx_unlock(&pcb->pcb_mtx);
1246 		pcb = pcb_next;
1247 	}
1248 } /* ng_btsocket_rfcomm_connect_cfm */
1249 
1250 /*****************************************************************************
1251  *****************************************************************************
1252  **                              RFCOMM sessions
1253  *****************************************************************************
1254  *****************************************************************************/
1255 
1256 /*
1257  * Create new RFCOMM session. That function WILL NOT take ownership over l2so.
1258  * Caller MUST free l2so if function failed.
1259  */
1260 
1261 static int
1262 ng_btsocket_rfcomm_session_create(ng_btsocket_rfcomm_session_p *sp,
1263 		struct socket *l2so, bdaddr_p src, bdaddr_p dst,
1264 		struct thread *td)
1265 {
1266 	ng_btsocket_rfcomm_session_p	s = NULL;
1267 	struct sockaddr_l2cap		l2sa;
1268 	struct sockopt			l2sopt;
1269 	int				error;
1270 	u_int16_t			mtu;
1271 
1272 	mtx_assert(&ng_btsocket_rfcomm_sessions_mtx, MA_OWNED);
1273 
1274 	/* Allocate the RFCOMM session */
1275         s = malloc(sizeof(*s),
1276 		M_NETGRAPH_BTSOCKET_RFCOMM, M_NOWAIT | M_ZERO);
1277         if (s == NULL)
1278                 return (ENOMEM);
1279 
1280 	/* Set defaults */
1281 	s->mtu = RFCOMM_DEFAULT_MTU;
1282 	s->flags = 0;
1283 	s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
1284 	NG_BT_MBUFQ_INIT(&s->outq, ifqmaxlen);
1285 
1286 	/*
1287 	 * XXX Mark session mutex as DUPOK to prevent "duplicated lock of
1288 	 * the same type" message. When accepting new L2CAP connection
1289 	 * ng_btsocket_rfcomm_session_accept() holds both session mutexes
1290 	 * for "old" (accepting) session and "new" (created) session.
1291 	 */
1292 
1293 	mtx_init(&s->session_mtx, "btsocks_rfcomm_session_mtx", NULL,
1294 		MTX_DEF|MTX_DUPOK);
1295 
1296 	LIST_INIT(&s->dlcs);
1297 
1298 	/* Prepare L2CAP socket */
1299 	SOCKBUF_LOCK(&l2so->so_rcv);
1300 	soupcall_set(l2so, SO_RCV, ng_btsocket_rfcomm_upcall, NULL);
1301 	SOCKBUF_UNLOCK(&l2so->so_rcv);
1302 	SOCKBUF_LOCK(&l2so->so_snd);
1303 	soupcall_set(l2so, SO_SND, ng_btsocket_rfcomm_upcall, NULL);
1304 	SOCKBUF_UNLOCK(&l2so->so_snd);
1305 	l2so->so_state |= SS_NBIO;
1306 	s->l2so = l2so;
1307 
1308 	mtx_lock(&s->session_mtx);
1309 
1310 	/*
1311 	 * "src" == NULL and "dst" == NULL means just create session.
1312 	 * caller must do the rest
1313 	 */
1314 
1315 	if (src == NULL && dst == NULL)
1316 		goto done;
1317 
1318 	/*
1319 	 * Set incoming MTU on L2CAP socket. It is RFCOMM session default MTU
1320 	 * plus 5 bytes: RFCOMM frame header, one extra byte for length and one
1321 	 * extra byte for credits.
1322 	 */
1323 
1324 	mtu = s->mtu + sizeof(struct rfcomm_frame_hdr) + 1 + 1;
1325 
1326 	l2sopt.sopt_dir = SOPT_SET;
1327 	l2sopt.sopt_level = SOL_L2CAP;
1328 	l2sopt.sopt_name = SO_L2CAP_IMTU;
1329 	l2sopt.sopt_val = (void *) &mtu;
1330 	l2sopt.sopt_valsize = sizeof(mtu);
1331 	l2sopt.sopt_td = NULL;
1332 
1333 	error = sosetopt(s->l2so, &l2sopt);
1334 	if (error != 0)
1335 		goto bad;
1336 
1337 	/* Bind socket to "src" address */
1338 	l2sa.l2cap_len = sizeof(l2sa);
1339 	l2sa.l2cap_family = AF_BLUETOOTH;
1340 	l2sa.l2cap_psm = (dst == NULL)? htole16(NG_L2CAP_PSM_RFCOMM) : 0;
1341 	bcopy(src, &l2sa.l2cap_bdaddr, sizeof(l2sa.l2cap_bdaddr));
1342 	l2sa.l2cap_cid = 0;
1343 	l2sa.l2cap_bdaddr_type = BDADDR_BREDR;
1344 
1345 	error = sobind(s->l2so, (struct sockaddr *) &l2sa, td);
1346 	if (error != 0)
1347 		goto bad;
1348 
1349 	/* If "dst" is not NULL then initiate connect(), otherwise listen() */
1350 	if (dst == NULL) {
1351 		s->flags = 0;
1352 		s->state = NG_BTSOCKET_RFCOMM_SESSION_LISTENING;
1353 
1354 		error = solisten(s->l2so, 10, td);
1355 		if (error != 0)
1356 			goto bad;
1357 	} else {
1358 		s->flags = NG_BTSOCKET_RFCOMM_SESSION_INITIATOR;
1359 		s->state = NG_BTSOCKET_RFCOMM_SESSION_CONNECTING;
1360 
1361 		l2sa.l2cap_len = sizeof(l2sa);
1362 		l2sa.l2cap_family = AF_BLUETOOTH;
1363 		l2sa.l2cap_psm = htole16(NG_L2CAP_PSM_RFCOMM);
1364 	        bcopy(dst, &l2sa.l2cap_bdaddr, sizeof(l2sa.l2cap_bdaddr));
1365 		l2sa.l2cap_cid = 0;
1366 		l2sa.l2cap_bdaddr_type = BDADDR_BREDR;
1367 
1368 		error = soconnect(s->l2so, (struct sockaddr *) &l2sa, td);
1369 		if (error != 0)
1370 			goto bad;
1371 	}
1372 
1373 done:
1374 	LIST_INSERT_HEAD(&ng_btsocket_rfcomm_sessions, s, next);
1375 	*sp = s;
1376 
1377 	mtx_unlock(&s->session_mtx);
1378 
1379 	return (0);
1380 
1381 bad:
1382 	mtx_unlock(&s->session_mtx);
1383 
1384 	/* Return L2CAP socket back to its original state */
1385 	SOCKBUF_LOCK(&l2so->so_rcv);
1386 	soupcall_clear(s->l2so, SO_RCV);
1387 	SOCKBUF_UNLOCK(&l2so->so_rcv);
1388 	SOCKBUF_LOCK(&l2so->so_snd);
1389 	soupcall_clear(s->l2so, SO_SND);
1390 	SOCKBUF_UNLOCK(&l2so->so_snd);
1391 	l2so->so_state &= ~SS_NBIO;
1392 
1393 	mtx_destroy(&s->session_mtx);
1394 	bzero(s, sizeof(*s));
1395 	free(s, M_NETGRAPH_BTSOCKET_RFCOMM);
1396 
1397 	return (error);
1398 } /* ng_btsocket_rfcomm_session_create */
1399 
1400 /*
1401  * Process accept() on RFCOMM session
1402  * XXX FIXME locking for "l2so"?
1403  */
1404 
1405 static int
1406 ng_btsocket_rfcomm_session_accept(ng_btsocket_rfcomm_session_p s0)
1407 {
1408 	struct socket			*l2so = NULL;
1409 	struct sockaddr_l2cap		*l2sa = NULL;
1410 	ng_btsocket_l2cap_pcb_t		*l2pcb = NULL;
1411 	ng_btsocket_rfcomm_session_p	 s = NULL;
1412 	int				 error = 0;
1413 
1414 	mtx_assert(&ng_btsocket_rfcomm_sessions_mtx, MA_OWNED);
1415 	mtx_assert(&s0->session_mtx, MA_OWNED);
1416 
1417 	/* Check if there is a complete L2CAP connection in the queue */
1418 	if ((error = s0->l2so->so_error) != 0) {
1419 		NG_BTSOCKET_RFCOMM_ERR(
1420 "%s: Could not accept connection on L2CAP socket, error=%d\n", __func__, error);
1421 		s0->l2so->so_error = 0;
1422 
1423 		return (error);
1424 	}
1425 
1426 	ACCEPT_LOCK();
1427 	if (TAILQ_EMPTY(&s0->l2so->so_comp)) {
1428 		ACCEPT_UNLOCK();
1429 		if (s0->l2so->so_rcv.sb_state & SBS_CANTRCVMORE)
1430 			return (ECONNABORTED);
1431 		return (EWOULDBLOCK);
1432 	}
1433 
1434 	/* Accept incoming L2CAP connection */
1435 	l2so = TAILQ_FIRST(&s0->l2so->so_comp);
1436 	if (l2so == NULL)
1437 		panic("%s: l2so == NULL\n", __func__);
1438 
1439 	TAILQ_REMOVE(&s0->l2so->so_comp, l2so, so_list);
1440 	s0->l2so->so_qlen --;
1441 	l2so->so_qstate &= ~SQ_COMP;
1442 	l2so->so_head = NULL;
1443 	SOCK_LOCK(l2so);
1444 	soref(l2so);
1445 	l2so->so_state |= SS_NBIO;
1446 	SOCK_UNLOCK(l2so);
1447 	ACCEPT_UNLOCK();
1448 
1449 	error = soaccept(l2so, (struct sockaddr **) &l2sa);
1450 	if (error != 0) {
1451 		NG_BTSOCKET_RFCOMM_ERR(
1452 "%s: soaccept() on L2CAP socket failed, error=%d\n", __func__, error);
1453 		soclose(l2so);
1454 
1455 		return (error);
1456 	}
1457 
1458 	/*
1459 	 * Check if there is already active RFCOMM session between two devices.
1460 	 * If so then close L2CAP connection. We only support one RFCOMM session
1461 	 * between each pair of devices. Note that here we assume session in any
1462 	 * state. The session even could be in the middle of disconnecting.
1463 	 */
1464 
1465 	l2pcb = so2l2cap_pcb(l2so);
1466 	s = ng_btsocket_rfcomm_session_by_addr(&l2pcb->src, &l2pcb->dst);
1467 	if (s == NULL) {
1468 		/* Create a new RFCOMM session */
1469 		error = ng_btsocket_rfcomm_session_create(&s, l2so, NULL, NULL,
1470 				curthread /* XXX */);
1471 		if (error == 0) {
1472 			mtx_lock(&s->session_mtx);
1473 
1474 			s->flags = 0;
1475 			s->state = NG_BTSOCKET_RFCOMM_SESSION_CONNECTED;
1476 
1477 			/*
1478 			 * Adjust MTU on incoming connection. Reserve 5 bytes:
1479 			 * RFCOMM frame header, one extra byte for length and
1480 			 * one extra byte for credits.
1481 			 */
1482 
1483 			s->mtu = min(l2pcb->imtu, l2pcb->omtu) -
1484 					sizeof(struct rfcomm_frame_hdr) - 1 - 1;
1485 
1486 			mtx_unlock(&s->session_mtx);
1487 		} else {
1488 			NG_BTSOCKET_RFCOMM_ALERT(
1489 "%s: Failed to create new RFCOMM session, error=%d\n", __func__, error);
1490 
1491 			soclose(l2so);
1492 		}
1493 	} else {
1494 		NG_BTSOCKET_RFCOMM_WARN(
1495 "%s: Rejecting duplicating RFCOMM session between src=%x:%x:%x:%x:%x:%x and " \
1496 "dst=%x:%x:%x:%x:%x:%x, state=%d, flags=%#x\n",	__func__,
1497 			l2pcb->src.b[5], l2pcb->src.b[4], l2pcb->src.b[3],
1498 			l2pcb->src.b[2], l2pcb->src.b[1], l2pcb->src.b[0],
1499 			l2pcb->dst.b[5], l2pcb->dst.b[4], l2pcb->dst.b[3],
1500 			l2pcb->dst.b[2], l2pcb->dst.b[1], l2pcb->dst.b[0],
1501 			s->state, s->flags);
1502 
1503 		error = EBUSY;
1504 		soclose(l2so);
1505 	}
1506 
1507 	return (error);
1508 } /* ng_btsocket_rfcomm_session_accept */
1509 
1510 /*
1511  * Process connect() on RFCOMM session
1512  * XXX FIXME locking for "l2so"?
1513  */
1514 
1515 static int
1516 ng_btsocket_rfcomm_session_connect(ng_btsocket_rfcomm_session_p s)
1517 {
1518 	ng_btsocket_l2cap_pcb_p	l2pcb = so2l2cap_pcb(s->l2so);
1519 	int			error;
1520 
1521 	mtx_assert(&s->session_mtx, MA_OWNED);
1522 
1523 	/* First check if connection has failed */
1524 	if ((error = s->l2so->so_error) != 0) {
1525 		s->l2so->so_error = 0;
1526 
1527 		NG_BTSOCKET_RFCOMM_ERR(
1528 "%s: Could not connect RFCOMM session, error=%d, state=%d, flags=%#x\n",
1529 			__func__, error, s->state, s->flags);
1530 
1531 		return (error);
1532 	}
1533 
1534 	/* Is connection still in progress? */
1535 	if (s->l2so->so_state & SS_ISCONNECTING)
1536 		return (0);
1537 
1538 	/*
1539 	 * If we got here then we are connected. Send SABM on DLCI 0 to
1540 	 * open multiplexor channel.
1541 	 */
1542 
1543 	if (error == 0) {
1544 		s->state = NG_BTSOCKET_RFCOMM_SESSION_CONNECTED;
1545 
1546 		/*
1547 		 * Adjust MTU on outgoing connection. Reserve 5 bytes: RFCOMM
1548 		 * frame header, one extra byte for length and one extra byte
1549 		 * for credits.
1550 		 */
1551 
1552 		s->mtu = min(l2pcb->imtu, l2pcb->omtu) -
1553 				sizeof(struct rfcomm_frame_hdr) - 1 - 1;
1554 
1555 		error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_SABM,0);
1556 		if (error == 0)
1557 			error = ng_btsocket_rfcomm_task_wakeup();
1558 	}
1559 
1560 	return (error);
1561 }/* ng_btsocket_rfcomm_session_connect */
1562 
1563 /*
1564  * Receive data on RFCOMM session
1565  * XXX FIXME locking for "l2so"?
1566  */
1567 
1568 static int
1569 ng_btsocket_rfcomm_session_receive(ng_btsocket_rfcomm_session_p s)
1570 {
1571 	struct mbuf	*m = NULL;
1572 	struct uio	 uio;
1573 	int		 more, flags, error;
1574 
1575 	mtx_assert(&s->session_mtx, MA_OWNED);
1576 
1577 	/* Can we read from the L2CAP socket? */
1578 	if (!soreadable(s->l2so))
1579 		return (0);
1580 
1581 	/* First check for error on L2CAP socket */
1582 	if ((error = s->l2so->so_error) != 0) {
1583 		s->l2so->so_error = 0;
1584 
1585 		NG_BTSOCKET_RFCOMM_ERR(
1586 "%s: Could not receive data from L2CAP socket, error=%d, state=%d, flags=%#x\n",
1587 			__func__, error, s->state, s->flags);
1588 
1589 		return (error);
1590 	}
1591 
1592 	/*
1593 	 * Read all packets from the L2CAP socket.
1594 	 * XXX FIXME/VERIFY is that correct? For now use m->m_nextpkt as
1595 	 * indication that there is more packets on the socket's buffer.
1596 	 * Also what should we use in uio.uio_resid?
1597 	 * May be s->mtu + sizeof(struct rfcomm_frame_hdr) + 1 + 1?
1598 	 */
1599 
1600 	for (more = 1; more; ) {
1601 		/* Try to get next packet from socket */
1602 		bzero(&uio, sizeof(uio));
1603 /*		uio.uio_td = NULL; */
1604 		uio.uio_resid = 1000000000;
1605 		flags = MSG_DONTWAIT;
1606 
1607 		m = NULL;
1608 		error = soreceive(s->l2so, NULL, &uio, &m,
1609 		    (struct mbuf **) NULL, &flags);
1610 		if (error != 0) {
1611 			if (error == EWOULDBLOCK)
1612 				return (0); /* XXX can happen? */
1613 
1614 			NG_BTSOCKET_RFCOMM_ERR(
1615 "%s: Could not receive data from L2CAP socket, error=%d\n", __func__, error);
1616 
1617 			return (error);
1618 		}
1619 
1620 		more = (m->m_nextpkt != NULL);
1621 		m->m_nextpkt = NULL;
1622 
1623 		ng_btsocket_rfcomm_receive_frame(s, m);
1624 	}
1625 
1626 	return (0);
1627 } /* ng_btsocket_rfcomm_session_receive */
1628 
1629 /*
1630  * Send data on RFCOMM session
1631  * XXX FIXME locking for "l2so"?
1632  */
1633 
1634 static int
1635 ng_btsocket_rfcomm_session_send(ng_btsocket_rfcomm_session_p s)
1636 {
1637 	struct mbuf	*m = NULL;
1638 	int		 error;
1639 
1640 	mtx_assert(&s->session_mtx, MA_OWNED);
1641 
1642 	/* Send as much as we can from the session queue */
1643 	while (sowriteable(s->l2so)) {
1644 		/* Check if socket still OK */
1645 		if ((error = s->l2so->so_error) != 0) {
1646 			s->l2so->so_error = 0;
1647 
1648 			NG_BTSOCKET_RFCOMM_ERR(
1649 "%s: Detected error=%d on L2CAP socket, state=%d, flags=%#x\n",
1650 				__func__, error, s->state, s->flags);
1651 
1652 			return (error);
1653 		}
1654 
1655 		NG_BT_MBUFQ_DEQUEUE(&s->outq, m);
1656 		if (m == NULL)
1657 			return (0); /* we are done */
1658 
1659 		/* Call send function on the L2CAP socket */
1660 		error = (*s->l2so->so_proto->pr_usrreqs->pru_send)(s->l2so,
1661 				0, m, NULL, NULL, curthread /* XXX */);
1662 		if (error != 0) {
1663 			NG_BTSOCKET_RFCOMM_ERR(
1664 "%s: Could not send data to L2CAP socket, error=%d\n", __func__, error);
1665 
1666 			return (error);
1667 		}
1668 	}
1669 
1670 	return (0);
1671 } /* ng_btsocket_rfcomm_session_send */
1672 
1673 /*
1674  * Close and disconnect all DLCs for the given session. Caller must hold
1675  * s->sesson_mtx. Will wakeup session.
1676  */
1677 
1678 static void
1679 ng_btsocket_rfcomm_session_clean(ng_btsocket_rfcomm_session_p s)
1680 {
1681 	ng_btsocket_rfcomm_pcb_p	pcb = NULL, pcb_next = NULL;
1682 	int				error;
1683 
1684 	mtx_assert(&s->session_mtx, MA_OWNED);
1685 
1686 	/*
1687 	 * Note: cannot use LIST_FOREACH because ng_btsocket_rfcomm_pcb_kill
1688 	 * will unlink DLC from the session
1689 	 */
1690 
1691 	for (pcb = LIST_FIRST(&s->dlcs); pcb != NULL; ) {
1692 		mtx_lock(&pcb->pcb_mtx);
1693 		pcb_next = LIST_NEXT(pcb, session_next);
1694 
1695 		NG_BTSOCKET_RFCOMM_INFO(
1696 "%s: Disconnecting dlci=%d, state=%d, flags=%#x\n",
1697 			__func__, pcb->dlci, pcb->state, pcb->flags);
1698 
1699 		if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONNECTED)
1700 			error = ECONNRESET;
1701 		else
1702 			error = ECONNREFUSED;
1703 
1704 		ng_btsocket_rfcomm_pcb_kill(pcb, error);
1705 
1706 		mtx_unlock(&pcb->pcb_mtx);
1707 		pcb = pcb_next;
1708 	}
1709 } /* ng_btsocket_rfcomm_session_clean */
1710 
1711 /*
1712  * Process all DLCs on the session. Caller MUST hold s->session_mtx.
1713  */
1714 
1715 static void
1716 ng_btsocket_rfcomm_session_process_pcb(ng_btsocket_rfcomm_session_p s)
1717 {
1718 	ng_btsocket_rfcomm_pcb_p	pcb = NULL, pcb_next = NULL;
1719 	int				error;
1720 
1721 	mtx_assert(&s->session_mtx, MA_OWNED);
1722 
1723 	/*
1724 	 * Note: cannot use LIST_FOREACH because ng_btsocket_rfcomm_pcb_kill
1725 	 * will unlink DLC from the session
1726 	 */
1727 
1728 	for (pcb = LIST_FIRST(&s->dlcs); pcb != NULL; ) {
1729 		mtx_lock(&pcb->pcb_mtx);
1730 		pcb_next = LIST_NEXT(pcb, session_next);
1731 
1732 		switch (pcb->state) {
1733 
1734 		/*
1735 		 * If DLC in W4_CONNECT state then we should check for both
1736 		 * timeout and detach.
1737 		 */
1738 
1739 		case NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT:
1740 			if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_DETACHED)
1741 				ng_btsocket_rfcomm_pcb_kill(pcb, 0);
1742 			else if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT)
1743 				ng_btsocket_rfcomm_pcb_kill(pcb, ETIMEDOUT);
1744 			break;
1745 
1746 		/*
1747 		 * If DLC in CONFIGURING or CONNECTING state then we only
1748 		 * should check for timeout. If detach() was called then
1749 		 * DLC will be moved into DISCONNECTING state.
1750 		 */
1751 
1752 		case NG_BTSOCKET_RFCOMM_DLC_CONFIGURING:
1753 		case NG_BTSOCKET_RFCOMM_DLC_CONNECTING:
1754 			if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT)
1755 				ng_btsocket_rfcomm_pcb_kill(pcb, ETIMEDOUT);
1756 			break;
1757 
1758 		/*
1759 		 * If DLC in CONNECTED state then we need to send data (if any)
1760 		 * from the socket's send queue. Note that we will send data
1761 		 * from either all sockets or none. This may overload session's
1762 		 * outgoing queue (but we do not check for that).
1763 		 *
1764  		 * XXX FIXME need scheduler for RFCOMM sockets
1765 		 */
1766 
1767 		case NG_BTSOCKET_RFCOMM_DLC_CONNECTED:
1768 			error = ng_btsocket_rfcomm_pcb_send(pcb, ALOT);
1769 			if (error != 0)
1770 				ng_btsocket_rfcomm_pcb_kill(pcb, error);
1771 			break;
1772 
1773 		/*
1774 		 * If DLC in DISCONNECTING state then we must send DISC frame.
1775 		 * Note that if DLC has timeout set then we do not need to
1776 		 * resend DISC frame.
1777 		 *
1778 		 * XXX FIXME need to drain all data from the socket's queue
1779 		 * if LINGER option was set
1780 		 */
1781 
1782 		case NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING:
1783 			if (!(pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)) {
1784 				error = ng_btsocket_rfcomm_send_command(
1785 						pcb->session, RFCOMM_FRAME_DISC,
1786 						pcb->dlci);
1787 				if (error == 0)
1788 					ng_btsocket_rfcomm_timeout(pcb);
1789 				else
1790 					ng_btsocket_rfcomm_pcb_kill(pcb, error);
1791 			} else if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT)
1792 				ng_btsocket_rfcomm_pcb_kill(pcb, ETIMEDOUT);
1793 			break;
1794 
1795 /*		case NG_BTSOCKET_RFCOMM_DLC_CLOSED: */
1796 		default:
1797 			panic("%s: Invalid DLC state=%d, flags=%#x\n",
1798 				__func__, pcb->state, pcb->flags);
1799 			break;
1800 		}
1801 
1802 		mtx_unlock(&pcb->pcb_mtx);
1803 		pcb = pcb_next;
1804 	}
1805 } /* ng_btsocket_rfcomm_session_process_pcb */
1806 
1807 /*
1808  * Find RFCOMM session between "src" and "dst".
1809  * Caller MUST hold ng_btsocket_rfcomm_sessions_mtx.
1810  */
1811 
1812 static ng_btsocket_rfcomm_session_p
1813 ng_btsocket_rfcomm_session_by_addr(bdaddr_p src, bdaddr_p dst)
1814 {
1815 	ng_btsocket_rfcomm_session_p	s = NULL;
1816 	ng_btsocket_l2cap_pcb_p		l2pcb = NULL;
1817 	int				any_src;
1818 
1819 	mtx_assert(&ng_btsocket_rfcomm_sessions_mtx, MA_OWNED);
1820 
1821 	any_src = (bcmp(src, NG_HCI_BDADDR_ANY, sizeof(*src)) == 0);
1822 
1823 	LIST_FOREACH(s, &ng_btsocket_rfcomm_sessions, next) {
1824 		l2pcb = so2l2cap_pcb(s->l2so);
1825 
1826 		if ((any_src || bcmp(&l2pcb->src, src, sizeof(*src)) == 0) &&
1827 		    bcmp(&l2pcb->dst, dst, sizeof(*dst)) == 0)
1828 			break;
1829 	}
1830 
1831 	return (s);
1832 } /* ng_btsocket_rfcomm_session_by_addr */
1833 
1834 /*****************************************************************************
1835  *****************************************************************************
1836  **                                  RFCOMM
1837  *****************************************************************************
1838  *****************************************************************************/
1839 
1840 /*
1841  * Process incoming RFCOMM frame. Caller must hold s->session_mtx.
1842  * XXX FIXME check frame length
1843  */
1844 
1845 static int
1846 ng_btsocket_rfcomm_receive_frame(ng_btsocket_rfcomm_session_p s,
1847 		struct mbuf *m0)
1848 {
1849 	struct rfcomm_frame_hdr	*hdr = NULL;
1850 	struct mbuf		*m = NULL;
1851 	u_int16_t		 length;
1852 	u_int8_t		 dlci, type;
1853 	int			 error = 0;
1854 
1855 	mtx_assert(&s->session_mtx, MA_OWNED);
1856 
1857 	/* Pullup as much as we can into first mbuf (for direct access) */
1858 	length = min(m0->m_pkthdr.len, MHLEN);
1859 	if (m0->m_len < length) {
1860 		if ((m0 = m_pullup(m0, length)) == NULL) {
1861 			NG_BTSOCKET_RFCOMM_ALERT(
1862 "%s: m_pullup(%d) failed\n", __func__, length);
1863 
1864 			return (ENOBUFS);
1865 		}
1866 	}
1867 
1868 	hdr = mtod(m0, struct rfcomm_frame_hdr *);
1869 	dlci = RFCOMM_DLCI(hdr->address);
1870 	type = RFCOMM_TYPE(hdr->control);
1871 
1872 	/* Test EA bit in length. If not set then we have 2 bytes of length */
1873 	if (!RFCOMM_EA(hdr->length)) {
1874 		bcopy(&hdr->length, &length, sizeof(length));
1875 		length = le16toh(length) >> 1;
1876 		m_adj(m0, sizeof(*hdr) + 1);
1877 	} else {
1878 		length = hdr->length >> 1;
1879 		m_adj(m0, sizeof(*hdr));
1880 	}
1881 
1882 	NG_BTSOCKET_RFCOMM_INFO(
1883 "%s: Got frame type=%#x, dlci=%d, length=%d, cr=%d, pf=%d, len=%d\n",
1884 		__func__, type, dlci, length, RFCOMM_CR(hdr->address),
1885 		RFCOMM_PF(hdr->control), m0->m_pkthdr.len);
1886 
1887 	/*
1888 	 * Get FCS (the last byte in the frame)
1889 	 * XXX this will not work if mbuf chain ends with empty mbuf.
1890 	 * XXX let's hope it never happens :)
1891 	 */
1892 
1893 	for (m = m0; m->m_next != NULL; m = m->m_next)
1894 		;
1895 	if (m->m_len <= 0)
1896 		panic("%s: Empty mbuf at the end of the chain, len=%d\n",
1897 			__func__, m->m_len);
1898 
1899 	/*
1900 	 * Check FCS. We only need to calculate FCS on first 2 or 3 bytes
1901 	 * and already m_pullup'ed mbuf chain, so it should be safe.
1902 	 */
1903 
1904 	if (ng_btsocket_rfcomm_check_fcs((u_int8_t *) hdr, type, m->m_data[m->m_len - 1])) {
1905 		NG_BTSOCKET_RFCOMM_ERR(
1906 "%s: Invalid RFCOMM packet. Bad checksum\n", __func__);
1907 		NG_FREE_M(m0);
1908 
1909 		return (EINVAL);
1910 	}
1911 
1912 	m_adj(m0, -1); /* Trim FCS byte */
1913 
1914 	/*
1915 	 * Process RFCOMM frame.
1916 	 *
1917 	 * From TS 07.10 spec
1918 	 *
1919 	 * "... In the case where a SABM or DISC command with the P bit set
1920 	 * to 0 is received then the received frame shall be discarded..."
1921  	 *
1922 	 * "... If a unsolicited DM response is received then the frame shall
1923 	 * be processed irrespective of the P/F setting... "
1924 	 *
1925 	 * "... The station may transmit response frames with the F bit set
1926 	 * to 0 at any opportunity on an asynchronous basis. However, in the
1927 	 * case where a UA response is received with the F bit set to 0 then
1928 	 * the received frame shall be discarded..."
1929 	 *
1930 	 * From Bluetooth spec
1931 	 *
1932 	 * "... When credit based flow control is being used, the meaning of
1933 	 * the P/F bit in the control field of the RFCOMM header is redefined
1934 	 * for UIH frames..."
1935 	 */
1936 
1937 	switch (type) {
1938 	case RFCOMM_FRAME_SABM:
1939 		if (RFCOMM_PF(hdr->control))
1940 			error = ng_btsocket_rfcomm_receive_sabm(s, dlci);
1941 		break;
1942 
1943 	case RFCOMM_FRAME_DISC:
1944 		if (RFCOMM_PF(hdr->control))
1945 			error = ng_btsocket_rfcomm_receive_disc(s, dlci);
1946 		break;
1947 
1948 	case RFCOMM_FRAME_UA:
1949 		if (RFCOMM_PF(hdr->control))
1950 			error = ng_btsocket_rfcomm_receive_ua(s, dlci);
1951 		break;
1952 
1953 	case RFCOMM_FRAME_DM:
1954 		error = ng_btsocket_rfcomm_receive_dm(s, dlci);
1955 		break;
1956 
1957 	case RFCOMM_FRAME_UIH:
1958 		if (dlci == 0)
1959 			error = ng_btsocket_rfcomm_receive_mcc(s, m0);
1960 		else
1961 			error = ng_btsocket_rfcomm_receive_uih(s, dlci,
1962 					RFCOMM_PF(hdr->control), m0);
1963 
1964 		return (error);
1965 		/* NOT REACHED */
1966 
1967 	default:
1968 		NG_BTSOCKET_RFCOMM_ERR(
1969 "%s: Invalid RFCOMM packet. Unknown type=%#x\n", __func__, type);
1970 		error = EINVAL;
1971 		break;
1972 	}
1973 
1974 	NG_FREE_M(m0);
1975 
1976 	return (error);
1977 } /* ng_btsocket_rfcomm_receive_frame */
1978 
1979 /*
1980  * Process RFCOMM SABM frame
1981  */
1982 
1983 static int
1984 ng_btsocket_rfcomm_receive_sabm(ng_btsocket_rfcomm_session_p s, int dlci)
1985 {
1986 	ng_btsocket_rfcomm_pcb_p	pcb = NULL;
1987 	int				error = 0;
1988 
1989 	mtx_assert(&s->session_mtx, MA_OWNED);
1990 
1991 	NG_BTSOCKET_RFCOMM_INFO(
1992 "%s: Got SABM, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
1993 		__func__, s->state, s->flags, s->mtu, dlci);
1994 
1995 	/* DLCI == 0 means open multiplexor channel */
1996 	if (dlci == 0) {
1997 		switch (s->state) {
1998 		case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED:
1999 		case NG_BTSOCKET_RFCOMM_SESSION_OPEN:
2000 			error = ng_btsocket_rfcomm_send_command(s,
2001 					RFCOMM_FRAME_UA, dlci);
2002 			if (error == 0) {
2003 				s->state = NG_BTSOCKET_RFCOMM_SESSION_OPEN;
2004 				ng_btsocket_rfcomm_connect_cfm(s);
2005 			} else {
2006 				s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
2007 				ng_btsocket_rfcomm_session_clean(s);
2008 			}
2009 			break;
2010 
2011 		default:
2012 			NG_BTSOCKET_RFCOMM_WARN(
2013 "%s: Got SABM for session in invalid state state=%d, flags=%#x\n",
2014 				__func__, s->state, s->flags);
2015 			error = EINVAL;
2016 			break;
2017 		}
2018 
2019 		return (error);
2020 	}
2021 
2022 	/* Make sure multiplexor channel is open */
2023 	if (s->state != NG_BTSOCKET_RFCOMM_SESSION_OPEN) {
2024 		NG_BTSOCKET_RFCOMM_ERR(
2025 "%s: Got SABM for dlci=%d with mulitplexor channel closed, state=%d, " \
2026 "flags=%#x\n",		__func__, dlci, s->state, s->flags);
2027 
2028 		return (EINVAL);
2029 	}
2030 
2031 	/*
2032 	 * Check if we have this DLCI. This might happen when remote
2033 	 * peer uses PN command before actual open (SABM) happens.
2034 	 */
2035 
2036 	pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2037 	if (pcb != NULL) {
2038 		mtx_lock(&pcb->pcb_mtx);
2039 
2040 		if (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTING) {
2041 			NG_BTSOCKET_RFCOMM_ERR(
2042 "%s: Got SABM for dlci=%d in invalid state=%d, flags=%#x\n",
2043 				__func__, dlci, pcb->state, pcb->flags);
2044 			mtx_unlock(&pcb->pcb_mtx);
2045 
2046 			return (ENOENT);
2047 		}
2048 
2049 		ng_btsocket_rfcomm_untimeout(pcb);
2050 
2051 		error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_UA,dlci);
2052 		if (error == 0)
2053 			error = ng_btsocket_rfcomm_send_msc(pcb);
2054 
2055 		if (error == 0) {
2056 			pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTED;
2057 			soisconnected(pcb->so);
2058 		} else
2059 			ng_btsocket_rfcomm_pcb_kill(pcb, error);
2060 
2061 		mtx_unlock(&pcb->pcb_mtx);
2062 
2063 		return (error);
2064 	}
2065 
2066 	/*
2067 	 * We do not have requested DLCI, so it must be an incoming connection
2068 	 * with default parameters. Try to accept it.
2069 	 */
2070 
2071 	pcb = ng_btsocket_rfcomm_connect_ind(s, RFCOMM_SRVCHANNEL(dlci));
2072 	if (pcb != NULL) {
2073 		mtx_lock(&pcb->pcb_mtx);
2074 
2075 		pcb->dlci = dlci;
2076 
2077 		error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_UA,dlci);
2078 		if (error == 0)
2079 			error = ng_btsocket_rfcomm_send_msc(pcb);
2080 
2081 		if (error == 0) {
2082 			pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTED;
2083 			soisconnected(pcb->so);
2084 		} else
2085 			ng_btsocket_rfcomm_pcb_kill(pcb, error);
2086 
2087 		mtx_unlock(&pcb->pcb_mtx);
2088 	} else
2089 		/* Nobody is listen()ing on the requested DLCI */
2090 		error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_DM,dlci);
2091 
2092 	return (error);
2093 } /* ng_btsocket_rfcomm_receive_sabm */
2094 
2095 /*
2096  * Process RFCOMM DISC frame
2097  */
2098 
2099 static int
2100 ng_btsocket_rfcomm_receive_disc(ng_btsocket_rfcomm_session_p s, int dlci)
2101 {
2102 	ng_btsocket_rfcomm_pcb_p	pcb = NULL;
2103 	int				error = 0;
2104 
2105 	mtx_assert(&s->session_mtx, MA_OWNED);
2106 
2107 	NG_BTSOCKET_RFCOMM_INFO(
2108 "%s: Got DISC, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
2109 		__func__, s->state, s->flags, s->mtu, dlci);
2110 
2111 	/* DLCI == 0 means close multiplexor channel */
2112 	if (dlci == 0) {
2113 		/* XXX FIXME assume that remote side will close the socket */
2114 		error = ng_btsocket_rfcomm_send_command(s, RFCOMM_FRAME_UA, 0);
2115 		if (error == 0) {
2116 			if (s->state == NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING)
2117 				s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED; /* XXX */
2118 			else
2119 				s->state = NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING;
2120 		} else
2121 			s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED; /* XXX */
2122 
2123 		ng_btsocket_rfcomm_session_clean(s);
2124 	} else {
2125 		pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2126 		if (pcb != NULL) {
2127 			int	err;
2128 
2129 			mtx_lock(&pcb->pcb_mtx);
2130 
2131 			NG_BTSOCKET_RFCOMM_INFO(
2132 "%s: Got DISC for dlci=%d, state=%d, flags=%#x\n",
2133 				__func__, dlci, pcb->state, pcb->flags);
2134 
2135 			error = ng_btsocket_rfcomm_send_command(s,
2136 					RFCOMM_FRAME_UA, dlci);
2137 
2138 			if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONNECTED)
2139 				err = 0;
2140 			else
2141 				err = ECONNREFUSED;
2142 
2143 			ng_btsocket_rfcomm_pcb_kill(pcb, err);
2144 
2145 			mtx_unlock(&pcb->pcb_mtx);
2146 		} else {
2147 			NG_BTSOCKET_RFCOMM_WARN(
2148 "%s: Got DISC for non-existing dlci=%d\n", __func__, dlci);
2149 
2150 			error = ng_btsocket_rfcomm_send_command(s,
2151 					RFCOMM_FRAME_DM, dlci);
2152 		}
2153 	}
2154 
2155 	return (error);
2156 } /* ng_btsocket_rfcomm_receive_disc */
2157 
2158 /*
2159  * Process RFCOMM UA frame
2160  */
2161 
2162 static int
2163 ng_btsocket_rfcomm_receive_ua(ng_btsocket_rfcomm_session_p s, int dlci)
2164 {
2165 	ng_btsocket_rfcomm_pcb_p	pcb = NULL;
2166 	int				error = 0;
2167 
2168 	mtx_assert(&s->session_mtx, MA_OWNED);
2169 
2170 	NG_BTSOCKET_RFCOMM_INFO(
2171 "%s: Got UA, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
2172 		__func__, s->state, s->flags, s->mtu, dlci);
2173 
2174 	/* dlci == 0 means multiplexor channel */
2175 	if (dlci == 0) {
2176 		switch (s->state) {
2177 		case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED:
2178 			s->state = NG_BTSOCKET_RFCOMM_SESSION_OPEN;
2179 			ng_btsocket_rfcomm_connect_cfm(s);
2180 			break;
2181 
2182 		case NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING:
2183 			s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
2184 			ng_btsocket_rfcomm_session_clean(s);
2185 			break;
2186 
2187 		default:
2188 			NG_BTSOCKET_RFCOMM_WARN(
2189 "%s: Got UA for session in invalid state=%d(%d), flags=%#x, mtu=%d\n",
2190 				__func__, s->state, INITIATOR(s), s->flags,
2191 				s->mtu);
2192 			error = ENOENT;
2193 			break;
2194 		}
2195 
2196 		return (error);
2197 	}
2198 
2199 	/* Check if we have this DLCI */
2200 	pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2201 	if (pcb != NULL) {
2202 		mtx_lock(&pcb->pcb_mtx);
2203 
2204 		NG_BTSOCKET_RFCOMM_INFO(
2205 "%s: Got UA for dlci=%d, state=%d, flags=%#x\n",
2206 			__func__, dlci, pcb->state, pcb->flags);
2207 
2208 		switch (pcb->state) {
2209 		case NG_BTSOCKET_RFCOMM_DLC_CONNECTING:
2210 			ng_btsocket_rfcomm_untimeout(pcb);
2211 
2212 			error = ng_btsocket_rfcomm_send_msc(pcb);
2213 			if (error == 0) {
2214 				pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTED;
2215 				soisconnected(pcb->so);
2216 			}
2217 			break;
2218 
2219 		case NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING:
2220 			ng_btsocket_rfcomm_pcb_kill(pcb, 0);
2221 			break;
2222 
2223 		default:
2224 			NG_BTSOCKET_RFCOMM_WARN(
2225 "%s: Got UA for dlci=%d in invalid state=%d, flags=%#x\n",
2226 				__func__, dlci, pcb->state, pcb->flags);
2227 			error = ENOENT;
2228 			break;
2229 		}
2230 
2231 		mtx_unlock(&pcb->pcb_mtx);
2232 	} else {
2233 		NG_BTSOCKET_RFCOMM_WARN(
2234 "%s: Got UA for non-existing dlci=%d\n", __func__, dlci);
2235 
2236 		error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_DM,dlci);
2237 	}
2238 
2239 	return (error);
2240 } /* ng_btsocket_rfcomm_receive_ua */
2241 
2242 /*
2243  * Process RFCOMM DM frame
2244  */
2245 
2246 static int
2247 ng_btsocket_rfcomm_receive_dm(ng_btsocket_rfcomm_session_p s, int dlci)
2248 {
2249 	ng_btsocket_rfcomm_pcb_p	pcb = NULL;
2250 	int				error;
2251 
2252 	mtx_assert(&s->session_mtx, MA_OWNED);
2253 
2254 	NG_BTSOCKET_RFCOMM_INFO(
2255 "%s: Got DM, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
2256 		__func__, s->state, s->flags, s->mtu, dlci);
2257 
2258 	/* DLCI == 0 means multiplexor channel */
2259 	if (dlci == 0) {
2260 		/* Disconnect all dlc's on the session */
2261 		s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
2262 		ng_btsocket_rfcomm_session_clean(s);
2263 	} else {
2264 		pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2265 		if (pcb != NULL) {
2266 			mtx_lock(&pcb->pcb_mtx);
2267 
2268 			NG_BTSOCKET_RFCOMM_INFO(
2269 "%s: Got DM for dlci=%d, state=%d, flags=%#x\n",
2270 				__func__, dlci, pcb->state, pcb->flags);
2271 
2272 			if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONNECTED)
2273 				error = ECONNRESET;
2274 			else
2275 				error = ECONNREFUSED;
2276 
2277 			ng_btsocket_rfcomm_pcb_kill(pcb, error);
2278 
2279 			mtx_unlock(&pcb->pcb_mtx);
2280 		} else
2281 			NG_BTSOCKET_RFCOMM_WARN(
2282 "%s: Got DM for non-existing dlci=%d\n", __func__, dlci);
2283 	}
2284 
2285 	return (0);
2286 } /* ng_btsocket_rfcomm_receive_dm */
2287 
2288 /*
2289  * Process RFCOMM UIH frame (data)
2290  */
2291 
2292 static int
2293 ng_btsocket_rfcomm_receive_uih(ng_btsocket_rfcomm_session_p s, int dlci,
2294 		int pf, struct mbuf *m0)
2295 {
2296 	ng_btsocket_rfcomm_pcb_p	pcb = NULL;
2297 	int				error = 0;
2298 
2299 	mtx_assert(&s->session_mtx, MA_OWNED);
2300 
2301 	NG_BTSOCKET_RFCOMM_INFO(
2302 "%s: Got UIH, session state=%d, flags=%#x, mtu=%d, dlci=%d, pf=%d, len=%d\n",
2303 		__func__, s->state, s->flags, s->mtu, dlci, pf,
2304 		m0->m_pkthdr.len);
2305 
2306 	/* XXX should we do it here? Check for session flow control */
2307 	if (s->flags & NG_BTSOCKET_RFCOMM_SESSION_LFC) {
2308 		NG_BTSOCKET_RFCOMM_WARN(
2309 "%s: Got UIH with session flow control asserted, state=%d, flags=%#x\n",
2310 			__func__, s->state, s->flags);
2311 		goto drop;
2312 	}
2313 
2314 	/* Check if we have this dlci */
2315 	pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2316 	if (pcb == NULL) {
2317 		NG_BTSOCKET_RFCOMM_WARN(
2318 "%s: Got UIH for non-existing dlci=%d\n", __func__, dlci);
2319 		error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_DM,dlci);
2320 		goto drop;
2321 	}
2322 
2323 	mtx_lock(&pcb->pcb_mtx);
2324 
2325 	/* Check dlci state */
2326 	if (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTED) {
2327 		NG_BTSOCKET_RFCOMM_WARN(
2328 "%s: Got UIH for dlci=%d in invalid state=%d, flags=%#x\n",
2329 			__func__, dlci, pcb->state, pcb->flags);
2330 		error = EINVAL;
2331 		goto drop1;
2332 	}
2333 
2334 	/* Check dlci flow control */
2335 	if (((pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) && pcb->rx_cred <= 0) ||
2336 	     (pcb->lmodem & RFCOMM_MODEM_FC)) {
2337 		NG_BTSOCKET_RFCOMM_ERR(
2338 "%s: Got UIH for dlci=%d with asserted flow control, state=%d, " \
2339 "flags=%#x, rx_cred=%d, lmodem=%#x\n",
2340 			__func__, dlci, pcb->state, pcb->flags,
2341 			pcb->rx_cred, pcb->lmodem);
2342 		goto drop1;
2343 	}
2344 
2345 	/* Did we get any credits? */
2346 	if ((pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) && pf) {
2347 		NG_BTSOCKET_RFCOMM_INFO(
2348 "%s: Got %d more credits for dlci=%d, state=%d, flags=%#x, " \
2349 "rx_cred=%d, tx_cred=%d\n",
2350 			__func__, *mtod(m0, u_int8_t *), dlci, pcb->state,
2351 			pcb->flags, pcb->rx_cred, pcb->tx_cred);
2352 
2353 		pcb->tx_cred += *mtod(m0, u_int8_t *);
2354 		m_adj(m0, 1);
2355 
2356 		/* Send more from the DLC. XXX check for errors? */
2357 		ng_btsocket_rfcomm_pcb_send(pcb, ALOT);
2358 	}
2359 
2360 	/* OK the of the rest of the mbuf is the data */
2361 	if (m0->m_pkthdr.len > 0) {
2362 		/* If we are using credit flow control decrease rx_cred here */
2363 		if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) {
2364 			/* Give remote peer more credits (if needed) */
2365 			if (-- pcb->rx_cred <= RFCOMM_MAX_CREDITS / 2)
2366 				ng_btsocket_rfcomm_send_credits(pcb);
2367 			else
2368 				NG_BTSOCKET_RFCOMM_INFO(
2369 "%s: Remote side still has credits, dlci=%d, state=%d, flags=%#x, " \
2370 "rx_cred=%d, tx_cred=%d\n",		__func__, dlci, pcb->state, pcb->flags,
2371 					pcb->rx_cred, pcb->tx_cred);
2372 		}
2373 
2374 		/* Check packet against mtu on dlci */
2375 		if (m0->m_pkthdr.len > pcb->mtu) {
2376 			NG_BTSOCKET_RFCOMM_ERR(
2377 "%s: Got oversized UIH for dlci=%d, state=%d, flags=%#x, mtu=%d, len=%d\n",
2378 				__func__, dlci, pcb->state, pcb->flags,
2379 				pcb->mtu, m0->m_pkthdr.len);
2380 
2381 			error = EMSGSIZE;
2382 		} else if (m0->m_pkthdr.len > sbspace(&pcb->so->so_rcv)) {
2383 
2384 			/*
2385 			 * This is really bad. Receive queue on socket does
2386 			 * not have enough space for the packet. We do not
2387 			 * have any other choice but drop the packet.
2388 			 */
2389 
2390 			NG_BTSOCKET_RFCOMM_ERR(
2391 "%s: Not enough space in socket receive queue. Dropping UIH for dlci=%d, " \
2392 "state=%d, flags=%#x, len=%d, space=%ld\n",
2393 				__func__, dlci, pcb->state, pcb->flags,
2394 				m0->m_pkthdr.len, sbspace(&pcb->so->so_rcv));
2395 
2396 			error = ENOBUFS;
2397 		} else {
2398 			/* Append packet to the socket receive queue */
2399 			sbappend(&pcb->so->so_rcv, m0, 0);
2400 			m0 = NULL;
2401 
2402 			sorwakeup(pcb->so);
2403 		}
2404 	}
2405 drop1:
2406 	mtx_unlock(&pcb->pcb_mtx);
2407 drop:
2408 	NG_FREE_M(m0); /* checks for != NULL */
2409 
2410 	return (error);
2411 } /* ng_btsocket_rfcomm_receive_uih */
2412 
2413 /*
2414  * Process RFCOMM MCC command (Multiplexor)
2415  *
2416  * From TS 07.10 spec
2417  *
2418  * "5.4.3.1 Information Data
2419  *
2420  *  ...The frames (UIH) sent by the initiating station have the C/R bit set
2421  *  to 1 and those sent by the responding station have the C/R bit set to 0..."
2422  *
2423  * "5.4.6.2 Operating procedures
2424  *
2425  *  Messages always exist in pairs; a command message and a corresponding
2426  *  response message. If the C/R bit is set to 1 the message is a command,
2427  *  if it is set to 0 the message is a response...
2428  *
2429  *  ...
2430  *
2431  *  NOTE: Notice that when UIH frames are used to convey information on DLCI 0
2432  *  there are at least two different fields that contain a C/R bit, and the
2433  *  bits are set of different form. The C/R bit in the Type field shall be set
2434  *  as it is stated above, while the C/R bit in the Address field (see subclause
2435  *  5.2.1.2) shall be set as it is described in subclause 5.4.3.1."
2436  */
2437 
2438 static int
2439 ng_btsocket_rfcomm_receive_mcc(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2440 {
2441 	struct rfcomm_mcc_hdr	*hdr = NULL;
2442 	u_int8_t		 cr, type, length;
2443 
2444 	mtx_assert(&s->session_mtx, MA_OWNED);
2445 
2446 	/*
2447 	 * We can access data directly in the first mbuf, because we have
2448 	 * m_pullup()'ed mbuf chain in ng_btsocket_rfcomm_receive_frame().
2449 	 * All MCC commands should fit into single mbuf (except probably TEST).
2450 	 */
2451 
2452 	hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2453 	cr = RFCOMM_CR(hdr->type);
2454 	type = RFCOMM_MCC_TYPE(hdr->type);
2455 	length = RFCOMM_MCC_LENGTH(hdr->length);
2456 
2457 	/* Check MCC frame length */
2458 	if (sizeof(*hdr) + length != m0->m_pkthdr.len) {
2459 		NG_BTSOCKET_RFCOMM_ERR(
2460 "%s: Invalid MCC frame length=%d, len=%d\n",
2461 			__func__, length, m0->m_pkthdr.len);
2462 		NG_FREE_M(m0);
2463 
2464 		return (EMSGSIZE);
2465 	}
2466 
2467 	switch (type) {
2468 	case RFCOMM_MCC_TEST:
2469 		return (ng_btsocket_rfcomm_receive_test(s, m0));
2470 		/* NOT REACHED */
2471 
2472 	case RFCOMM_MCC_FCON:
2473 	case RFCOMM_MCC_FCOFF:
2474 		return (ng_btsocket_rfcomm_receive_fc(s, m0));
2475 		/* NOT REACHED */
2476 
2477 	case RFCOMM_MCC_MSC:
2478 		return (ng_btsocket_rfcomm_receive_msc(s, m0));
2479 		/* NOT REACHED */
2480 
2481 	case RFCOMM_MCC_RPN:
2482 		return (ng_btsocket_rfcomm_receive_rpn(s, m0));
2483 		/* NOT REACHED */
2484 
2485 	case RFCOMM_MCC_RLS:
2486 		return (ng_btsocket_rfcomm_receive_rls(s, m0));
2487 		/* NOT REACHED */
2488 
2489 	case RFCOMM_MCC_PN:
2490 		return (ng_btsocket_rfcomm_receive_pn(s, m0));
2491 		/* NOT REACHED */
2492 
2493 	case RFCOMM_MCC_NSC:
2494 		NG_BTSOCKET_RFCOMM_ERR(
2495 "%s: Got MCC NSC, type=%#x, cr=%d, length=%d, session state=%d, flags=%#x, " \
2496 "mtu=%d, len=%d\n",	__func__, RFCOMM_MCC_TYPE(*((u_int8_t *)(hdr + 1))), cr,
2497 			 length, s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2498 		NG_FREE_M(m0);
2499 		break;
2500 
2501 	default:
2502 		NG_BTSOCKET_RFCOMM_ERR(
2503 "%s: Got unknown MCC, type=%#x, cr=%d, length=%d, session state=%d, " \
2504 "flags=%#x, mtu=%d, len=%d\n",
2505 			__func__, type, cr, length, s->state, s->flags,
2506 			s->mtu, m0->m_pkthdr.len);
2507 
2508 		/* Reuse mbuf to send NSC */
2509 		hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2510 		m0->m_pkthdr.len = m0->m_len = sizeof(*hdr);
2511 
2512 		/* Create MCC NSC header */
2513 		hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_NSC);
2514 		hdr->length = RFCOMM_MKLEN8(1);
2515 
2516 		/* Put back MCC command type we did not like */
2517 		m0->m_data[m0->m_len] = RFCOMM_MKMCC_TYPE(cr, type);
2518 		m0->m_pkthdr.len ++;
2519 		m0->m_len ++;
2520 
2521 		/* Send UIH frame */
2522 		return (ng_btsocket_rfcomm_send_uih(s,
2523 				RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0));
2524 		/* NOT REACHED */
2525 	}
2526 
2527 	return (0);
2528 } /* ng_btsocket_rfcomm_receive_mcc */
2529 
2530 /*
2531  * Receive RFCOMM TEST MCC command
2532  */
2533 
2534 static int
2535 ng_btsocket_rfcomm_receive_test(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2536 {
2537 	struct rfcomm_mcc_hdr	*hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2538 	int			 error = 0;
2539 
2540 	mtx_assert(&s->session_mtx, MA_OWNED);
2541 
2542 	NG_BTSOCKET_RFCOMM_INFO(
2543 "%s: Got MCC TEST, cr=%d, length=%d, session state=%d, flags=%#x, mtu=%d, " \
2544 "len=%d\n",	__func__, RFCOMM_CR(hdr->type), RFCOMM_MCC_LENGTH(hdr->length),
2545 		s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2546 
2547 	if (RFCOMM_CR(hdr->type)) {
2548 		hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_TEST);
2549 		error = ng_btsocket_rfcomm_send_uih(s,
2550 				RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2551 	} else
2552 		NG_FREE_M(m0); /* XXX ignore response */
2553 
2554 	return (error);
2555 } /* ng_btsocket_rfcomm_receive_test */
2556 
2557 /*
2558  * Receive RFCOMM FCON/FCOFF MCC command
2559  */
2560 
2561 static int
2562 ng_btsocket_rfcomm_receive_fc(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2563 {
2564 	struct rfcomm_mcc_hdr	*hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2565 	u_int8_t		 type = RFCOMM_MCC_TYPE(hdr->type);
2566 	int			 error = 0;
2567 
2568 	mtx_assert(&s->session_mtx, MA_OWNED);
2569 
2570 	/*
2571 	 * Turn ON/OFF aggregate flow on the entire session. When remote peer
2572 	 * asserted flow control no transmission shall occur except on dlci 0
2573 	 * (control channel).
2574 	 */
2575 
2576 	NG_BTSOCKET_RFCOMM_INFO(
2577 "%s: Got MCC FC%s, cr=%d, length=%d, session state=%d, flags=%#x, mtu=%d, " \
2578 "len=%d\n",	__func__, (type == RFCOMM_MCC_FCON)? "ON" : "OFF",
2579 		RFCOMM_CR(hdr->type), RFCOMM_MCC_LENGTH(hdr->length),
2580 		s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2581 
2582 	if (RFCOMM_CR(hdr->type)) {
2583 		if (type == RFCOMM_MCC_FCON)
2584 			s->flags &= ~NG_BTSOCKET_RFCOMM_SESSION_RFC;
2585 		else
2586 			s->flags |= NG_BTSOCKET_RFCOMM_SESSION_RFC;
2587 
2588 		hdr->type = RFCOMM_MKMCC_TYPE(0, type);
2589 		error = ng_btsocket_rfcomm_send_uih(s,
2590 				RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2591 	} else
2592 		NG_FREE_M(m0); /* XXX ignore response */
2593 
2594 	return (error);
2595 } /* ng_btsocket_rfcomm_receive_fc  */
2596 
2597 /*
2598  * Receive RFCOMM MSC MCC command
2599  */
2600 
2601 static int
2602 ng_btsocket_rfcomm_receive_msc(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2603 {
2604 	struct rfcomm_mcc_hdr		*hdr = mtod(m0, struct rfcomm_mcc_hdr*);
2605 	struct rfcomm_mcc_msc		*msc = (struct rfcomm_mcc_msc *)(hdr+1);
2606 	ng_btsocket_rfcomm_pcb_t	*pcb = NULL;
2607 	int				 error = 0;
2608 
2609 	mtx_assert(&s->session_mtx, MA_OWNED);
2610 
2611 	NG_BTSOCKET_RFCOMM_INFO(
2612 "%s: Got MCC MSC, dlci=%d, cr=%d, length=%d, session state=%d, flags=%#x, " \
2613 "mtu=%d, len=%d\n",
2614 		__func__,  RFCOMM_DLCI(msc->address), RFCOMM_CR(hdr->type),
2615 		RFCOMM_MCC_LENGTH(hdr->length), s->state, s->flags,
2616 		s->mtu, m0->m_pkthdr.len);
2617 
2618 	if (RFCOMM_CR(hdr->type)) {
2619 		pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, RFCOMM_DLCI(msc->address));
2620 		if (pcb == NULL) {
2621 			NG_BTSOCKET_RFCOMM_WARN(
2622 "%s: Got MSC command for non-existing dlci=%d\n",
2623 				__func__, RFCOMM_DLCI(msc->address));
2624 			NG_FREE_M(m0);
2625 
2626 			return (ENOENT);
2627 		}
2628 
2629 		mtx_lock(&pcb->pcb_mtx);
2630 
2631 		if (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTING &&
2632 		    pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTED) {
2633 			NG_BTSOCKET_RFCOMM_WARN(
2634 "%s: Got MSC on dlci=%d in invalid state=%d\n",
2635 				__func__, RFCOMM_DLCI(msc->address),
2636 				pcb->state);
2637 
2638 			mtx_unlock(&pcb->pcb_mtx);
2639 			NG_FREE_M(m0);
2640 
2641 			return (EINVAL);
2642 		}
2643 
2644 		pcb->rmodem = msc->modem; /* Update remote port signals */
2645 
2646 		hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_MSC);
2647 		error = ng_btsocket_rfcomm_send_uih(s,
2648 				RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2649 
2650 #if 0 /* YYY */
2651 		/* Send more data from DLC. XXX check for errors? */
2652 		if (!(pcb->rmodem & RFCOMM_MODEM_FC) &&
2653 		    !(pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC))
2654 			ng_btsocket_rfcomm_pcb_send(pcb, ALOT);
2655 #endif /* YYY */
2656 
2657 		mtx_unlock(&pcb->pcb_mtx);
2658 	} else
2659 		NG_FREE_M(m0); /* XXX ignore response */
2660 
2661 	return (error);
2662 } /* ng_btsocket_rfcomm_receive_msc */
2663 
2664 /*
2665  * Receive RFCOMM RPN MCC command
2666  * XXX FIXME do we need htole16/le16toh for RPN param_mask?
2667  */
2668 
2669 static int
2670 ng_btsocket_rfcomm_receive_rpn(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2671 {
2672 	struct rfcomm_mcc_hdr	*hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2673 	struct rfcomm_mcc_rpn	*rpn = (struct rfcomm_mcc_rpn *)(hdr + 1);
2674 	int			 error = 0;
2675 	u_int16_t		 param_mask;
2676 	u_int8_t		 bit_rate, data_bits, stop_bits, parity,
2677 				 flow_control, xon_char, xoff_char;
2678 
2679 	mtx_assert(&s->session_mtx, MA_OWNED);
2680 
2681 	NG_BTSOCKET_RFCOMM_INFO(
2682 "%s: Got MCC RPN, dlci=%d, cr=%d, length=%d, session state=%d, flags=%#x, " \
2683 "mtu=%d, len=%d\n",
2684 		__func__, RFCOMM_DLCI(rpn->dlci), RFCOMM_CR(hdr->type),
2685 		RFCOMM_MCC_LENGTH(hdr->length), s->state, s->flags,
2686 		s->mtu, m0->m_pkthdr.len);
2687 
2688 	if (RFCOMM_CR(hdr->type)) {
2689 		param_mask = RFCOMM_RPN_PM_ALL;
2690 
2691 		if (RFCOMM_MCC_LENGTH(hdr->length) == 1) {
2692 			/* Request - return default setting */
2693 			bit_rate = RFCOMM_RPN_BR_115200;
2694 			data_bits = RFCOMM_RPN_DATA_8;
2695 			stop_bits = RFCOMM_RPN_STOP_1;
2696 			parity = RFCOMM_RPN_PARITY_NONE;
2697 			flow_control = RFCOMM_RPN_FLOW_NONE;
2698 			xon_char = RFCOMM_RPN_XON_CHAR;
2699 			xoff_char = RFCOMM_RPN_XOFF_CHAR;
2700                 } else {
2701 			/*
2702 			 * Ignore/accept bit_rate, 8 bits, 1 stop bit, no
2703 			 * parity, no flow control lines, default XON/XOFF
2704 			 * chars.
2705 			 */
2706 
2707 			bit_rate = rpn->bit_rate;
2708 			rpn->param_mask = le16toh(rpn->param_mask); /* XXX */
2709 
2710 			data_bits = RFCOMM_RPN_DATA_BITS(rpn->line_settings);
2711 			if (rpn->param_mask & RFCOMM_RPN_PM_DATA &&
2712 			    data_bits != RFCOMM_RPN_DATA_8) {
2713 				data_bits = RFCOMM_RPN_DATA_8;
2714 				param_mask ^= RFCOMM_RPN_PM_DATA;
2715 			}
2716 
2717 			stop_bits = RFCOMM_RPN_STOP_BITS(rpn->line_settings);
2718 			if (rpn->param_mask & RFCOMM_RPN_PM_STOP &&
2719 			    stop_bits != RFCOMM_RPN_STOP_1) {
2720 				stop_bits = RFCOMM_RPN_STOP_1;
2721 				param_mask ^= RFCOMM_RPN_PM_STOP;
2722 			}
2723 
2724 			parity = RFCOMM_RPN_PARITY(rpn->line_settings);
2725 			if (rpn->param_mask & RFCOMM_RPN_PM_PARITY &&
2726 			    parity != RFCOMM_RPN_PARITY_NONE) {
2727 				parity = RFCOMM_RPN_PARITY_NONE;
2728 				param_mask ^= RFCOMM_RPN_PM_PARITY;
2729 			}
2730 
2731 			flow_control = rpn->flow_control;
2732 			if (rpn->param_mask & RFCOMM_RPN_PM_FLOW &&
2733 			    flow_control != RFCOMM_RPN_FLOW_NONE) {
2734 				flow_control = RFCOMM_RPN_FLOW_NONE;
2735 				param_mask ^= RFCOMM_RPN_PM_FLOW;
2736 			}
2737 
2738 			xon_char = rpn->xon_char;
2739 			if (rpn->param_mask & RFCOMM_RPN_PM_XON &&
2740 			    xon_char != RFCOMM_RPN_XON_CHAR) {
2741 				xon_char = RFCOMM_RPN_XON_CHAR;
2742 				param_mask ^= RFCOMM_RPN_PM_XON;
2743 			}
2744 
2745 			xoff_char = rpn->xoff_char;
2746 			if (rpn->param_mask & RFCOMM_RPN_PM_XOFF &&
2747 			    xoff_char != RFCOMM_RPN_XOFF_CHAR) {
2748 				xoff_char = RFCOMM_RPN_XOFF_CHAR;
2749 				param_mask ^= RFCOMM_RPN_PM_XOFF;
2750 			}
2751 		}
2752 
2753 		rpn->bit_rate = bit_rate;
2754 		rpn->line_settings = RFCOMM_MKRPN_LINE_SETTINGS(data_bits,
2755 						stop_bits, parity);
2756 		rpn->flow_control = flow_control;
2757 		rpn->xon_char = xon_char;
2758 		rpn->xoff_char = xoff_char;
2759 		rpn->param_mask = htole16(param_mask); /* XXX */
2760 
2761 		m0->m_pkthdr.len = m0->m_len = sizeof(*hdr) + sizeof(*rpn);
2762 
2763 		hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_RPN);
2764 		error = ng_btsocket_rfcomm_send_uih(s,
2765 				RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2766 	} else
2767 		NG_FREE_M(m0); /* XXX ignore response */
2768 
2769 	return (error);
2770 } /* ng_btsocket_rfcomm_receive_rpn */
2771 
2772 /*
2773  * Receive RFCOMM RLS MCC command
2774  */
2775 
2776 static int
2777 ng_btsocket_rfcomm_receive_rls(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2778 {
2779 	struct rfcomm_mcc_hdr	*hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2780 	struct rfcomm_mcc_rls	*rls = (struct rfcomm_mcc_rls *)(hdr + 1);
2781 	int			 error = 0;
2782 
2783 	mtx_assert(&s->session_mtx, MA_OWNED);
2784 
2785 	/*
2786 	 * XXX FIXME Do we have to do anything else here? Remote peer tries to
2787 	 * tell us something about DLCI. Just report what we have received and
2788 	 * return back received values as required by TS 07.10 spec.
2789 	 */
2790 
2791 	NG_BTSOCKET_RFCOMM_INFO(
2792 "%s: Got MCC RLS, dlci=%d, status=%#x, cr=%d, length=%d, session state=%d, " \
2793 "flags=%#x, mtu=%d, len=%d\n",
2794 		__func__, RFCOMM_DLCI(rls->address), rls->status,
2795 		RFCOMM_CR(hdr->type), RFCOMM_MCC_LENGTH(hdr->length),
2796 		s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2797 
2798 	if (RFCOMM_CR(hdr->type)) {
2799 		if (rls->status & 0x1)
2800 			NG_BTSOCKET_RFCOMM_ERR(
2801 "%s: Got RLS dlci=%d, error=%#x\n", __func__, RFCOMM_DLCI(rls->address),
2802 				rls->status >> 1);
2803 
2804 		hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_RLS);
2805 		error = ng_btsocket_rfcomm_send_uih(s,
2806 				RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2807 	} else
2808 		NG_FREE_M(m0); /* XXX ignore responses */
2809 
2810 	return (error);
2811 } /* ng_btsocket_rfcomm_receive_rls */
2812 
2813 /*
2814  * Receive RFCOMM PN MCC command
2815  */
2816 
2817 static int
2818 ng_btsocket_rfcomm_receive_pn(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2819 {
2820 	struct rfcomm_mcc_hdr		*hdr = mtod(m0, struct rfcomm_mcc_hdr*);
2821 	struct rfcomm_mcc_pn		*pn = (struct rfcomm_mcc_pn *)(hdr+1);
2822 	ng_btsocket_rfcomm_pcb_t	*pcb = NULL;
2823 	int				 error = 0;
2824 
2825 	mtx_assert(&s->session_mtx, MA_OWNED);
2826 
2827 	NG_BTSOCKET_RFCOMM_INFO(
2828 "%s: Got MCC PN, dlci=%d, cr=%d, length=%d, flow_control=%#x, priority=%d, " \
2829 "ack_timer=%d, mtu=%d, max_retrans=%d, credits=%d, session state=%d, " \
2830 "flags=%#x, session mtu=%d, len=%d\n",
2831 		__func__, pn->dlci, RFCOMM_CR(hdr->type),
2832 		RFCOMM_MCC_LENGTH(hdr->length), pn->flow_control, pn->priority,
2833 		pn->ack_timer, le16toh(pn->mtu), pn->max_retrans, pn->credits,
2834 		s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2835 
2836 	if (pn->dlci == 0) {
2837 		NG_BTSOCKET_RFCOMM_ERR("%s: Zero dlci in MCC PN\n", __func__);
2838 		NG_FREE_M(m0);
2839 
2840 		return (EINVAL);
2841 	}
2842 
2843 	/* Check if we have this dlci */
2844 	pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, pn->dlci);
2845 	if (pcb != NULL) {
2846 		mtx_lock(&pcb->pcb_mtx);
2847 
2848 		if (RFCOMM_CR(hdr->type)) {
2849 			/* PN Request */
2850 			ng_btsocket_rfcomm_set_pn(pcb, 1, pn->flow_control,
2851 				pn->credits, pn->mtu);
2852 
2853 			if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) {
2854 				pn->flow_control = 0xe0;
2855 				pn->credits = RFCOMM_DEFAULT_CREDITS;
2856 			} else {
2857 				pn->flow_control = 0;
2858 				pn->credits = 0;
2859 			}
2860 
2861 			hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_PN);
2862 			error = ng_btsocket_rfcomm_send_uih(s,
2863 					RFCOMM_MKADDRESS(INITIATOR(s), 0),
2864 					0, 0, m0);
2865 		} else {
2866 			/* PN Response - proceed with SABM. Timeout still set */
2867 			if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONFIGURING) {
2868 				ng_btsocket_rfcomm_set_pn(pcb, 0,
2869 					pn->flow_control, pn->credits, pn->mtu);
2870 
2871 				pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTING;
2872 				error = ng_btsocket_rfcomm_send_command(s,
2873 						RFCOMM_FRAME_SABM, pn->dlci);
2874 			} else
2875 				NG_BTSOCKET_RFCOMM_WARN(
2876 "%s: Got PN response for dlci=%d in invalid state=%d\n",
2877 					__func__, pn->dlci, pcb->state);
2878 
2879 			NG_FREE_M(m0);
2880 		}
2881 
2882 		mtx_unlock(&pcb->pcb_mtx);
2883 	} else if (RFCOMM_CR(hdr->type)) {
2884 		/* PN request to non-existing dlci - incoming connection */
2885 		pcb = ng_btsocket_rfcomm_connect_ind(s,
2886 				RFCOMM_SRVCHANNEL(pn->dlci));
2887 		if (pcb != NULL) {
2888 			mtx_lock(&pcb->pcb_mtx);
2889 
2890 			pcb->dlci = pn->dlci;
2891 
2892 			ng_btsocket_rfcomm_set_pn(pcb, 1, pn->flow_control,
2893 				pn->credits, pn->mtu);
2894 
2895 			if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) {
2896 				pn->flow_control = 0xe0;
2897 				pn->credits = RFCOMM_DEFAULT_CREDITS;
2898 			} else {
2899 				pn->flow_control = 0;
2900 				pn->credits = 0;
2901 			}
2902 
2903 			hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_PN);
2904 			error = ng_btsocket_rfcomm_send_uih(s,
2905 					RFCOMM_MKADDRESS(INITIATOR(s), 0),
2906 					0, 0, m0);
2907 
2908 			if (error == 0) {
2909 				ng_btsocket_rfcomm_timeout(pcb);
2910 				pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTING;
2911 				soisconnecting(pcb->so);
2912 			} else
2913 				ng_btsocket_rfcomm_pcb_kill(pcb, error);
2914 
2915 			mtx_unlock(&pcb->pcb_mtx);
2916 		} else {
2917 			/* Nobody is listen()ing on this channel */
2918 			error = ng_btsocket_rfcomm_send_command(s,
2919 					RFCOMM_FRAME_DM, pn->dlci);
2920 			NG_FREE_M(m0);
2921 		}
2922 	} else
2923 		NG_FREE_M(m0); /* XXX ignore response to non-existing dlci */
2924 
2925 	return (error);
2926 } /* ng_btsocket_rfcomm_receive_pn */
2927 
2928 /*
2929  * Set PN parameters for dlci. Caller must hold pcb->pcb_mtx.
2930  *
2931  * From Bluetooth spec.
2932  *
2933  * "... The CL1 - CL4 field is completely redefined. (In TS07.10 this defines
2934  *  the convergence layer to use, which is not applicable to RFCOMM. In RFCOMM,
2935  *  in Bluetooth versions up to 1.0B, this field was forced to 0).
2936  *
2937  *  In the PN request sent prior to a DLC establishment, this field must contain
2938  *  the value 15 (0xF), indicating support of credit based flow control in the
2939  *  sender. See Table 5.3 below. If the PN response contains any other value
2940  *  than 14 (0xE) in this field, it is inferred that the peer RFCOMM entity is
2941  *  not supporting the credit based flow control feature. (This is only possible
2942  *  if the peer RFCOMM implementation is only conforming to Bluetooth version
2943  *  1.0B.) If a PN request is sent on an already open DLC, then this field must
2944  *  contain the value zero; it is not possible to set initial credits  more
2945  *  than once per DLC activation. A responding implementation must set this
2946  *  field in the PN response to 14 (0xE), if (and only if) the value in the PN
2947  *  request was 15..."
2948  */
2949 
2950 static void
2951 ng_btsocket_rfcomm_set_pn(ng_btsocket_rfcomm_pcb_p pcb, u_int8_t cr,
2952 		u_int8_t flow_control, u_int8_t credits, u_int16_t mtu)
2953 {
2954 	mtx_assert(&pcb->pcb_mtx, MA_OWNED);
2955 
2956 	pcb->mtu = le16toh(mtu);
2957 
2958 	if (cr) {
2959 		if (flow_control == 0xf0) {
2960 			pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_CFC;
2961 			pcb->tx_cred = credits;
2962 		} else {
2963 			pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_CFC;
2964 			pcb->tx_cred = 0;
2965 		}
2966 	} else {
2967 		if (flow_control == 0xe0) {
2968 			pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_CFC;
2969 			pcb->tx_cred = credits;
2970 		} else {
2971 			pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_CFC;
2972 			pcb->tx_cred = 0;
2973 		}
2974 	}
2975 
2976 	NG_BTSOCKET_RFCOMM_INFO(
2977 "%s: cr=%d, dlci=%d, state=%d, flags=%#x, mtu=%d, rx_cred=%d, tx_cred=%d\n",
2978 		__func__, cr, pcb->dlci, pcb->state, pcb->flags, pcb->mtu,
2979 		pcb->rx_cred, pcb->tx_cred);
2980 } /* ng_btsocket_rfcomm_set_pn */
2981 
2982 /*
2983  * Send RFCOMM SABM/DISC/UA/DM frames. Caller must hold s->session_mtx
2984  */
2985 
2986 static int
2987 ng_btsocket_rfcomm_send_command(ng_btsocket_rfcomm_session_p s,
2988 		u_int8_t type, u_int8_t dlci)
2989 {
2990 	struct rfcomm_cmd_hdr	*hdr = NULL;
2991 	struct mbuf		*m = NULL;
2992 	int			 cr;
2993 
2994 	mtx_assert(&s->session_mtx, MA_OWNED);
2995 
2996 	NG_BTSOCKET_RFCOMM_INFO(
2997 "%s: Sending command type %#x, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
2998 		__func__, type, s->state, s->flags, s->mtu, dlci);
2999 
3000 	switch (type) {
3001 	case RFCOMM_FRAME_SABM:
3002 	case RFCOMM_FRAME_DISC:
3003 		cr = INITIATOR(s);
3004 		break;
3005 
3006 	case RFCOMM_FRAME_UA:
3007 	case RFCOMM_FRAME_DM:
3008 		cr = !INITIATOR(s);
3009 		break;
3010 
3011 	default:
3012 		panic("%s: Invalid frame type=%#x\n", __func__, type);
3013 		return (EINVAL);
3014 		/* NOT REACHED */
3015 	}
3016 
3017 	MGETHDR(m, M_NOWAIT, MT_DATA);
3018 	if (m == NULL)
3019 		return (ENOBUFS);
3020 
3021 	m->m_pkthdr.len = m->m_len = sizeof(*hdr);
3022 
3023 	hdr = mtod(m, struct rfcomm_cmd_hdr *);
3024 	hdr->address = RFCOMM_MKADDRESS(cr, dlci);
3025 	hdr->control = RFCOMM_MKCONTROL(type, 1);
3026 	hdr->length = RFCOMM_MKLEN8(0);
3027 	hdr->fcs = ng_btsocket_rfcomm_fcs3((u_int8_t *) hdr);
3028 
3029 	NG_BT_MBUFQ_ENQUEUE(&s->outq, m);
3030 
3031 	return (0);
3032 } /* ng_btsocket_rfcomm_send_command */
3033 
3034 /*
3035  * Send RFCOMM UIH frame. Caller must hold s->session_mtx
3036  */
3037 
3038 static int
3039 ng_btsocket_rfcomm_send_uih(ng_btsocket_rfcomm_session_p s, u_int8_t address,
3040 		u_int8_t pf, u_int8_t credits, struct mbuf *data)
3041 {
3042 	struct rfcomm_frame_hdr	*hdr = NULL;
3043 	struct mbuf		*m = NULL, *mcrc = NULL;
3044 	u_int16_t		 length;
3045 
3046 	mtx_assert(&s->session_mtx, MA_OWNED);
3047 
3048 	MGETHDR(m, M_NOWAIT, MT_DATA);
3049 	if (m == NULL) {
3050 		NG_FREE_M(data);
3051 		return (ENOBUFS);
3052 	}
3053 	m->m_pkthdr.len = m->m_len = sizeof(*hdr);
3054 
3055 	MGET(mcrc, M_NOWAIT, MT_DATA);
3056 	if (mcrc == NULL) {
3057 		NG_FREE_M(data);
3058 		return (ENOBUFS);
3059 	}
3060 	mcrc->m_len = 1;
3061 
3062 	/* Fill UIH frame header */
3063 	hdr = mtod(m, struct rfcomm_frame_hdr *);
3064 	hdr->address = address;
3065 	hdr->control = RFCOMM_MKCONTROL(RFCOMM_FRAME_UIH, pf);
3066 
3067 	/* Calculate FCS */
3068 	mcrc->m_data[0] = ng_btsocket_rfcomm_fcs2((u_int8_t *) hdr);
3069 
3070 	/* Put length back */
3071 	length = (data != NULL)? data->m_pkthdr.len : 0;
3072 	if (length > 127) {
3073 		u_int16_t	l = htole16(RFCOMM_MKLEN16(length));
3074 
3075 		bcopy(&l, &hdr->length, sizeof(l));
3076 		m->m_pkthdr.len ++;
3077 		m->m_len ++;
3078 	} else
3079 		hdr->length = RFCOMM_MKLEN8(length);
3080 
3081 	if (pf) {
3082 		m->m_data[m->m_len] = credits;
3083 		m->m_pkthdr.len ++;
3084 		m->m_len ++;
3085 	}
3086 
3087 	/* Add payload */
3088 	if (data != NULL) {
3089 		m_cat(m, data);
3090 		m->m_pkthdr.len += length;
3091 	}
3092 
3093 	/* Put FCS back */
3094 	m_cat(m, mcrc);
3095 	m->m_pkthdr.len ++;
3096 
3097 	NG_BTSOCKET_RFCOMM_INFO(
3098 "%s: Sending UIH state=%d, flags=%#x, address=%d, length=%d, pf=%d, " \
3099 "credits=%d, len=%d\n",
3100 		__func__, s->state, s->flags, address, length, pf, credits,
3101 		m->m_pkthdr.len);
3102 
3103 	NG_BT_MBUFQ_ENQUEUE(&s->outq, m);
3104 
3105 	return (0);
3106 } /* ng_btsocket_rfcomm_send_uih */
3107 
3108 /*
3109  * Send MSC request. Caller must hold pcb->pcb_mtx and pcb->session->session_mtx
3110  */
3111 
3112 static int
3113 ng_btsocket_rfcomm_send_msc(ng_btsocket_rfcomm_pcb_p pcb)
3114 {
3115 	struct mbuf		*m = NULL;
3116 	struct rfcomm_mcc_hdr	*hdr = NULL;
3117 	struct rfcomm_mcc_msc	*msc = NULL;
3118 
3119 	mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3120 	mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3121 
3122 	MGETHDR(m, M_NOWAIT, MT_DATA);
3123 	if (m == NULL)
3124 		return (ENOBUFS);
3125 
3126 	m->m_pkthdr.len = m->m_len = sizeof(*hdr) + sizeof(*msc);
3127 
3128 	hdr = mtod(m, struct rfcomm_mcc_hdr *);
3129 	msc = (struct rfcomm_mcc_msc *)(hdr + 1);
3130 
3131 	hdr->type = RFCOMM_MKMCC_TYPE(1, RFCOMM_MCC_MSC);
3132 	hdr->length = RFCOMM_MKLEN8(sizeof(*msc));
3133 
3134 	msc->address = RFCOMM_MKADDRESS(1, pcb->dlci);
3135 	msc->modem = pcb->lmodem;
3136 
3137 	NG_BTSOCKET_RFCOMM_INFO(
3138 "%s: Sending MSC dlci=%d, state=%d, flags=%#x, address=%d, modem=%#x\n",
3139 		__func__, pcb->dlci, pcb->state, pcb->flags, msc->address,
3140 		msc->modem);
3141 
3142 	return (ng_btsocket_rfcomm_send_uih(pcb->session,
3143 			RFCOMM_MKADDRESS(INITIATOR(pcb->session), 0), 0, 0, m));
3144 } /* ng_btsocket_rfcomm_send_msc */
3145 
3146 /*
3147  * Send PN request. Caller must hold pcb->pcb_mtx and pcb->session->session_mtx
3148  */
3149 
3150 static int
3151 ng_btsocket_rfcomm_send_pn(ng_btsocket_rfcomm_pcb_p pcb)
3152 {
3153 	struct mbuf		*m = NULL;
3154 	struct rfcomm_mcc_hdr	*hdr = NULL;
3155 	struct rfcomm_mcc_pn	*pn = NULL;
3156 
3157 	mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3158 	mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3159 
3160 	MGETHDR(m, M_NOWAIT, MT_DATA);
3161 	if (m == NULL)
3162 		return (ENOBUFS);
3163 
3164 	m->m_pkthdr.len = m->m_len = sizeof(*hdr) + sizeof(*pn);
3165 
3166 	hdr = mtod(m, struct rfcomm_mcc_hdr *);
3167 	pn = (struct rfcomm_mcc_pn *)(hdr + 1);
3168 
3169 	hdr->type = RFCOMM_MKMCC_TYPE(1, RFCOMM_MCC_PN);
3170 	hdr->length = RFCOMM_MKLEN8(sizeof(*pn));
3171 
3172 	pn->dlci = pcb->dlci;
3173 
3174 	/*
3175 	 * Set default DLCI priority as described in GSM 07.10
3176 	 * (ETSI TS 101 369) clause 5.6 page 42
3177 	 */
3178 
3179 	pn->priority = (pcb->dlci < 56)? (((pcb->dlci >> 3) << 3) + 7) : 61;
3180 	pn->ack_timer = 0;
3181 	pn->mtu = htole16(pcb->mtu);
3182 	pn->max_retrans = 0;
3183 
3184 	if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) {
3185 		pn->flow_control = 0xf0;
3186 		pn->credits = pcb->rx_cred;
3187 	} else {
3188 		pn->flow_control = 0;
3189 		pn->credits = 0;
3190 	}
3191 
3192 	NG_BTSOCKET_RFCOMM_INFO(
3193 "%s: Sending PN dlci=%d, state=%d, flags=%#x, mtu=%d, flow_control=%#x, " \
3194 "credits=%d\n",	__func__, pcb->dlci, pcb->state, pcb->flags, pcb->mtu,
3195 		pn->flow_control, pn->credits);
3196 
3197 	return (ng_btsocket_rfcomm_send_uih(pcb->session,
3198 			RFCOMM_MKADDRESS(INITIATOR(pcb->session), 0), 0, 0, m));
3199 } /* ng_btsocket_rfcomm_send_pn */
3200 
3201 /*
3202  * Calculate and send credits based on available space in receive buffer
3203  */
3204 
3205 static int
3206 ng_btsocket_rfcomm_send_credits(ng_btsocket_rfcomm_pcb_p pcb)
3207 {
3208 	int		error = 0;
3209 	u_int8_t	credits;
3210 
3211 	mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3212 	mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3213 
3214 	NG_BTSOCKET_RFCOMM_INFO(
3215 "%s: Sending more credits, dlci=%d, state=%d, flags=%#x, mtu=%d, " \
3216 "space=%ld, tx_cred=%d, rx_cred=%d\n",
3217 		__func__, pcb->dlci, pcb->state, pcb->flags, pcb->mtu,
3218 		sbspace(&pcb->so->so_rcv), pcb->tx_cred, pcb->rx_cred);
3219 
3220 	credits = sbspace(&pcb->so->so_rcv) / pcb->mtu;
3221 	if (credits > 0) {
3222 		if (pcb->rx_cred + credits > RFCOMM_MAX_CREDITS)
3223 			credits = RFCOMM_MAX_CREDITS - pcb->rx_cred;
3224 
3225 		error = ng_btsocket_rfcomm_send_uih(
3226 				pcb->session,
3227 				RFCOMM_MKADDRESS(INITIATOR(pcb->session),
3228 					pcb->dlci), 1, credits, NULL);
3229 		if (error == 0) {
3230 			pcb->rx_cred += credits;
3231 
3232 			NG_BTSOCKET_RFCOMM_INFO(
3233 "%s: Gave remote side %d more credits, dlci=%d, state=%d, flags=%#x, " \
3234 "rx_cred=%d, tx_cred=%d\n",	__func__, credits, pcb->dlci, pcb->state,
3235 				pcb->flags, pcb->rx_cred, pcb->tx_cred);
3236 		} else
3237 			NG_BTSOCKET_RFCOMM_ERR(
3238 "%s: Could not send credits, error=%d, dlci=%d, state=%d, flags=%#x, " \
3239 "mtu=%d, space=%ld, tx_cred=%d, rx_cred=%d\n",
3240 				__func__, error, pcb->dlci, pcb->state,
3241 				pcb->flags, pcb->mtu, sbspace(&pcb->so->so_rcv),
3242 				pcb->tx_cred, pcb->rx_cred);
3243 	}
3244 
3245 	return (error);
3246 } /* ng_btsocket_rfcomm_send_credits */
3247 
3248 /*****************************************************************************
3249  *****************************************************************************
3250  **                              RFCOMM DLCs
3251  *****************************************************************************
3252  *****************************************************************************/
3253 
3254 /*
3255  * Send data from socket send buffer
3256  * Caller must hold pcb->pcb_mtx and pcb->session->session_mtx
3257  */
3258 
3259 static int
3260 ng_btsocket_rfcomm_pcb_send(ng_btsocket_rfcomm_pcb_p pcb, int limit)
3261 {
3262 	struct mbuf	*m = NULL;
3263 	int		 sent, length, error;
3264 
3265 	mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3266 	mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3267 
3268 	if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC)
3269 		limit = min(limit, pcb->tx_cred);
3270 	else if (!(pcb->rmodem & RFCOMM_MODEM_FC))
3271 		limit = min(limit, RFCOMM_MAX_CREDITS); /* XXX ??? */
3272 	else
3273 		limit = 0;
3274 
3275 	if (limit == 0) {
3276 		NG_BTSOCKET_RFCOMM_INFO(
3277 "%s: Could not send - remote flow control asserted, dlci=%d, flags=%#x, " \
3278 "rmodem=%#x, tx_cred=%d\n",
3279 			__func__, pcb->dlci, pcb->flags, pcb->rmodem,
3280 			pcb->tx_cred);
3281 
3282 		return (0);
3283 	}
3284 
3285 	for (error = 0, sent = 0; sent < limit; sent ++) {
3286 		length = min(pcb->mtu, sbavail(&pcb->so->so_snd));
3287 		if (length == 0)
3288 			break;
3289 
3290 		/* Get the chunk from the socket's send buffer */
3291 		m = ng_btsocket_rfcomm_prepare_packet(&pcb->so->so_snd, length);
3292 		if (m == NULL) {
3293 			error = ENOBUFS;
3294 			break;
3295 		}
3296 
3297 		sbdrop(&pcb->so->so_snd, length);
3298 
3299 		error = ng_btsocket_rfcomm_send_uih(pcb->session,
3300 				RFCOMM_MKADDRESS(INITIATOR(pcb->session),
3301 					pcb->dlci), 0, 0, m);
3302 		if (error != 0)
3303 			break;
3304 	}
3305 
3306 	if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC)
3307 		pcb->tx_cred -= sent;
3308 
3309 	if (error == 0 && sent > 0) {
3310 		pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_SENDING;
3311 		sowwakeup(pcb->so);
3312 	}
3313 
3314 	return (error);
3315 } /* ng_btsocket_rfcomm_pcb_send */
3316 
3317 /*
3318  * Unlink and disconnect DLC. If ng_btsocket_rfcomm_pcb_kill() returns
3319  * non zero value than socket has no reference and has to be detached.
3320  * Caller must hold pcb->pcb_mtx and pcb->session->session_mtx
3321  */
3322 
3323 static void
3324 ng_btsocket_rfcomm_pcb_kill(ng_btsocket_rfcomm_pcb_p pcb, int error)
3325 {
3326 	ng_btsocket_rfcomm_session_p	s = pcb->session;
3327 
3328 	NG_BTSOCKET_RFCOMM_INFO(
3329 "%s: Killing DLC, so=%p, dlci=%d, state=%d, flags=%#x, error=%d\n",
3330 		__func__, pcb->so, pcb->dlci, pcb->state, pcb->flags, error);
3331 
3332 	if (pcb->session == NULL)
3333 		panic("%s: DLC without session, pcb=%p, state=%d, flags=%#x\n",
3334 			__func__, pcb, pcb->state, pcb->flags);
3335 
3336 	mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3337 	mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3338 
3339 	if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)
3340 		ng_btsocket_rfcomm_untimeout(pcb);
3341 
3342 	/* Detach DLC from the session. Does not matter which state DLC in */
3343 	LIST_REMOVE(pcb, session_next);
3344 	pcb->session = NULL;
3345 
3346 	/* Change DLC state and wakeup all sleepers */
3347 	pcb->state = NG_BTSOCKET_RFCOMM_DLC_CLOSED;
3348 	pcb->so->so_error = error;
3349 	soisdisconnected(pcb->so);
3350 	wakeup(&pcb->state);
3351 
3352 	/* Check if we have any DLCs left on the session */
3353 	if (LIST_EMPTY(&s->dlcs) && INITIATOR(s)) {
3354 		NG_BTSOCKET_RFCOMM_INFO(
3355 "%s: Disconnecting session, state=%d, flags=%#x, mtu=%d\n",
3356 			__func__, s->state, s->flags, s->mtu);
3357 
3358 		switch (s->state) {
3359 		case NG_BTSOCKET_RFCOMM_SESSION_CLOSED:
3360 		case NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING:
3361 			/*
3362 			 * Do not have to do anything here. We can get here
3363 			 * when L2CAP connection was terminated or we have
3364 			 * received DISC on multiplexor channel
3365 			 */
3366 			break;
3367 
3368 		case NG_BTSOCKET_RFCOMM_SESSION_OPEN:
3369 			/* Send DISC on multiplexor channel */
3370 			error = ng_btsocket_rfcomm_send_command(s,
3371 					RFCOMM_FRAME_DISC, 0);
3372 			if (error == 0) {
3373 				s->state = NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING;
3374 				break;
3375 			}
3376 			/* FALL THROUGH */
3377 
3378 		case NG_BTSOCKET_RFCOMM_SESSION_CONNECTING:
3379 		case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED:
3380 			s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
3381 			break;
3382 
3383 /*		case NG_BTSOCKET_RFCOMM_SESSION_LISTENING: */
3384 		default:
3385 			panic("%s: Invalid session state=%d, flags=%#x\n",
3386 				__func__, s->state, s->flags);
3387 			break;
3388 		}
3389 
3390 		ng_btsocket_rfcomm_task_wakeup();
3391 	}
3392 } /* ng_btsocket_rfcomm_pcb_kill */
3393 
3394 /*
3395  * Look for given dlci for given RFCOMM session. Caller must hold s->session_mtx
3396  */
3397 
3398 static ng_btsocket_rfcomm_pcb_p
3399 ng_btsocket_rfcomm_pcb_by_dlci(ng_btsocket_rfcomm_session_p s, int dlci)
3400 {
3401 	ng_btsocket_rfcomm_pcb_p	pcb = NULL;
3402 
3403 	mtx_assert(&s->session_mtx, MA_OWNED);
3404 
3405 	LIST_FOREACH(pcb, &s->dlcs, session_next)
3406 		if (pcb->dlci == dlci)
3407 			break;
3408 
3409 	return (pcb);
3410 } /* ng_btsocket_rfcomm_pcb_by_dlci */
3411 
3412 /*
3413  * Look for socket that listens on given src address and given channel
3414  */
3415 
3416 static ng_btsocket_rfcomm_pcb_p
3417 ng_btsocket_rfcomm_pcb_listener(bdaddr_p src, int channel)
3418 {
3419 	ng_btsocket_rfcomm_pcb_p	pcb = NULL, pcb1 = NULL;
3420 
3421 	mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
3422 
3423 	LIST_FOREACH(pcb, &ng_btsocket_rfcomm_sockets, next) {
3424 		if (pcb->channel != channel ||
3425 		    !(pcb->so->so_options & SO_ACCEPTCONN))
3426 			continue;
3427 
3428 		if (bcmp(&pcb->src, src, sizeof(*src)) == 0)
3429 			break;
3430 
3431 		if (bcmp(&pcb->src, NG_HCI_BDADDR_ANY, sizeof(bdaddr_t)) == 0)
3432 			pcb1 = pcb;
3433 	}
3434 
3435 	mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
3436 
3437 	return ((pcb != NULL)? pcb : pcb1);
3438 } /* ng_btsocket_rfcomm_pcb_listener */
3439 
3440 /*****************************************************************************
3441  *****************************************************************************
3442  **                              Misc. functions
3443  *****************************************************************************
3444  *****************************************************************************/
3445 
3446 /*
3447  *  Set timeout. Caller MUST hold pcb_mtx
3448  */
3449 
3450 static void
3451 ng_btsocket_rfcomm_timeout(ng_btsocket_rfcomm_pcb_p pcb)
3452 {
3453 	mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3454 
3455 	if (!(pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)) {
3456 		pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_TIMO;
3457 		pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT;
3458 		callout_reset(&pcb->timo, ng_btsocket_rfcomm_timo * hz,
3459 		    ng_btsocket_rfcomm_process_timeout, pcb);
3460 	} else
3461 		panic("%s: Duplicated socket timeout?!\n", __func__);
3462 } /* ng_btsocket_rfcomm_timeout */
3463 
3464 /*
3465  *  Unset pcb timeout. Caller MUST hold pcb_mtx
3466  */
3467 
3468 static void
3469 ng_btsocket_rfcomm_untimeout(ng_btsocket_rfcomm_pcb_p pcb)
3470 {
3471 	mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3472 
3473 	if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO) {
3474 		callout_stop(&pcb->timo);
3475 		pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMO;
3476 		pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT;
3477 	} else
3478 		panic("%s: No socket timeout?!\n", __func__);
3479 } /* ng_btsocket_rfcomm_timeout */
3480 
3481 /*
3482  * Process pcb timeout
3483  */
3484 
3485 static void
3486 ng_btsocket_rfcomm_process_timeout(void *xpcb)
3487 {
3488 	ng_btsocket_rfcomm_pcb_p	pcb = (ng_btsocket_rfcomm_pcb_p) xpcb;
3489 
3490 	mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3491 
3492 	NG_BTSOCKET_RFCOMM_INFO(
3493 "%s: Timeout, so=%p, dlci=%d, state=%d, flags=%#x\n",
3494 		__func__, pcb->so, pcb->dlci, pcb->state, pcb->flags);
3495 
3496 	pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMO;
3497 	pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT;
3498 
3499 	switch (pcb->state) {
3500 	case NG_BTSOCKET_RFCOMM_DLC_CONFIGURING:
3501 	case NG_BTSOCKET_RFCOMM_DLC_CONNECTING:
3502 		pcb->state = NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING;
3503 		break;
3504 
3505 	case NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT:
3506 	case NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING:
3507 		break;
3508 
3509 	default:
3510 		panic(
3511 "%s: DLC timeout in invalid state, dlci=%d, state=%d, flags=%#x\n",
3512 			__func__, pcb->dlci, pcb->state, pcb->flags);
3513 		break;
3514 	}
3515 
3516 	ng_btsocket_rfcomm_task_wakeup();
3517 } /* ng_btsocket_rfcomm_process_timeout */
3518 
3519 /*
3520  * Get up to length bytes from the socket buffer
3521  */
3522 
3523 static struct mbuf *
3524 ng_btsocket_rfcomm_prepare_packet(struct sockbuf *sb, int length)
3525 {
3526 	struct mbuf	*top = NULL, *m = NULL, *n = NULL, *nextpkt = NULL;
3527 	int		 mlen, noff, len;
3528 
3529 	MGETHDR(top, M_NOWAIT, MT_DATA);
3530 	if (top == NULL)
3531 		return (NULL);
3532 
3533 	top->m_pkthdr.len = length;
3534 	top->m_len = 0;
3535 	mlen = MHLEN;
3536 
3537 	m = top;
3538 	n = sb->sb_mb;
3539 	nextpkt = n->m_nextpkt;
3540 	noff = 0;
3541 
3542 	while (length > 0 && n != NULL) {
3543 		len = min(mlen - m->m_len, n->m_len - noff);
3544 		if (len > length)
3545 			len = length;
3546 
3547 		bcopy(mtod(n, caddr_t)+noff, mtod(m, caddr_t)+m->m_len, len);
3548 		m->m_len += len;
3549 		noff += len;
3550 		length -= len;
3551 
3552 		if (length > 0 && m->m_len == mlen) {
3553 			MGET(m->m_next, M_NOWAIT, MT_DATA);
3554 			if (m->m_next == NULL) {
3555 				NG_FREE_M(top);
3556 				return (NULL);
3557 			}
3558 
3559 			m = m->m_next;
3560 			m->m_len = 0;
3561 			mlen = MLEN;
3562 		}
3563 
3564 		if (noff == n->m_len) {
3565 			noff = 0;
3566 			n = n->m_next;
3567 
3568 			if (n == NULL)
3569 				n = nextpkt;
3570 
3571 			nextpkt = (n != NULL)? n->m_nextpkt : NULL;
3572 		}
3573 	}
3574 
3575 	if (length < 0)
3576 		panic("%s: length=%d\n", __func__, length);
3577 	if (length > 0 && n == NULL)
3578 		panic("%s: bogus length=%d, n=%p\n", __func__, length, n);
3579 
3580 	return (top);
3581 } /* ng_btsocket_rfcomm_prepare_packet */
3582 
3583