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