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