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