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