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