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