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