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