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