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