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