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