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