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