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