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