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