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