1 /* $OpenBSD: src/sys/netbt/rfcomm_upper.c,v 1.4 2008/02/24 21:34:48 uwe Exp $ */
2 /* $NetBSD: rfcomm_upper.c,v 1.10 2007/11/20 20:25:57 plunky Exp $ */
3
4 /*-
5 * Copyright (c) 2006 Itronix Inc.
6 * All rights reserved.
7 *
8 * Written by Iain Hibbert for Itronix Inc.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. The name of Itronix Inc. may not be used to endorse
19 * or promote products derived from this software without specific
20 * prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
25 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
26 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29 * ON ANY THEORY OF LIABILITY, WHETHER IN
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 */
34
35 #include <sys/param.h>
36 #include <sys/kernel.h>
37 #include <sys/malloc.h>
38 #include <sys/mbuf.h>
39 #include <sys/proc.h>
40 #include <sys/systm.h>
41 #include <sys/socketvar.h>
42
43 #include <netbt/bluetooth.h>
44 #include <netbt/hci.h>
45 #include <netbt/l2cap.h>
46 #include <netbt/rfcomm.h>
47
48 /****************************************************************************
49 *
50 * RFCOMM DLC - Upper Protocol API
51 *
52 * Currently the only 'Port Emulation Entity' is the RFCOMM socket code
53 * but it is should be possible to provide a pseudo-device for a direct
54 * tty interface.
55 */
56
57 /*
58 * rfcomm_attach(handle, proto, upper)
59 *
60 * attach a new RFCOMM DLC to handle, populate with reasonable defaults
61 */
62 int
rfcomm_attach(struct rfcomm_dlc ** handle,const struct btproto * proto,void * upper)63 rfcomm_attach(struct rfcomm_dlc **handle,
64 const struct btproto *proto, void *upper)
65 {
66 struct rfcomm_dlc *dlc;
67
68 KKASSERT(handle != NULL);
69 KKASSERT(proto != NULL);
70 KKASSERT(upper != NULL);
71
72 dlc = kmalloc(sizeof(*dlc), M_BLUETOOTH, M_NOWAIT | M_ZERO);
73 if (dlc == NULL)
74 return ENOMEM;
75
76 dlc->rd_state = RFCOMM_DLC_CLOSED;
77 dlc->rd_mtu = rfcomm_mtu_default;
78
79 dlc->rd_proto = proto;
80 dlc->rd_upper = upper;
81
82 dlc->rd_laddr.bt_len = sizeof(struct sockaddr_bt);
83 dlc->rd_laddr.bt_family = AF_BLUETOOTH;
84 dlc->rd_laddr.bt_psm = L2CAP_PSM_RFCOMM;
85
86 dlc->rd_raddr.bt_len = sizeof(struct sockaddr_bt);
87 dlc->rd_raddr.bt_family = AF_BLUETOOTH;
88 dlc->rd_raddr.bt_psm = L2CAP_PSM_RFCOMM;
89
90 dlc->rd_lmodem = RFCOMM_MSC_RTC | RFCOMM_MSC_RTR | RFCOMM_MSC_DV;
91
92 callout_init(&dlc->rd_timeout);
93
94 *handle = dlc;
95 return 0;
96 }
97
98 /*
99 * rfcomm_bind(dlc, sockaddr)
100 *
101 * bind DLC to local address
102 */
103 int
rfcomm_bind(struct rfcomm_dlc * dlc,struct sockaddr_bt * addr)104 rfcomm_bind(struct rfcomm_dlc *dlc, struct sockaddr_bt *addr)
105 {
106
107 memcpy(&dlc->rd_laddr, addr, sizeof(struct sockaddr_bt));
108 return 0;
109 }
110
111 /*
112 * rfcomm_sockaddr(dlc, sockaddr)
113 *
114 * return local address
115 */
116 int
rfcomm_sockaddr(struct rfcomm_dlc * dlc,struct sockaddr_bt * addr)117 rfcomm_sockaddr(struct rfcomm_dlc *dlc, struct sockaddr_bt *addr)
118 {
119
120 memcpy(addr, &dlc->rd_laddr, sizeof(struct sockaddr_bt));
121 return 0;
122 }
123
124 /*
125 * rfcomm_connect(dlc, sockaddr)
126 *
127 * Initiate connection of RFCOMM DLC to remote address.
128 */
129 int
rfcomm_connect(struct rfcomm_dlc * dlc,struct sockaddr_bt * dest)130 rfcomm_connect(struct rfcomm_dlc *dlc, struct sockaddr_bt *dest)
131 {
132 struct rfcomm_session *rs;
133 int err = 0;
134
135 if (dlc->rd_state != RFCOMM_DLC_CLOSED)
136 return EISCONN;
137
138 memcpy(&dlc->rd_raddr, dest, sizeof(struct sockaddr_bt));
139
140 if (dlc->rd_raddr.bt_channel < RFCOMM_CHANNEL_MIN
141 || dlc->rd_raddr.bt_channel > RFCOMM_CHANNEL_MAX
142 || bdaddr_any(&dlc->rd_raddr.bt_bdaddr))
143 return EDESTADDRREQ;
144
145 if (dlc->rd_raddr.bt_psm == L2CAP_PSM_ANY)
146 dlc->rd_raddr.bt_psm = L2CAP_PSM_RFCOMM;
147 else if (dlc->rd_raddr.bt_psm != L2CAP_PSM_RFCOMM
148 && (dlc->rd_raddr.bt_psm < 0x1001
149 || L2CAP_PSM_INVALID(dlc->rd_raddr.bt_psm)))
150 return EINVAL;
151
152 /*
153 * We are allowed only one RFCOMM session between any 2 Bluetooth
154 * devices, so see if there is a session already otherwise create
155 * one and set it connecting.
156 */
157 rs = rfcomm_session_lookup(&dlc->rd_laddr, &dlc->rd_raddr);
158 if (rs == NULL) {
159 rs = rfcomm_session_alloc(&rfcomm_session_active,
160 &dlc->rd_laddr);
161 if (rs == NULL)
162 return ENOMEM;
163
164 rs->rs_flags |= RFCOMM_SESSION_INITIATOR;
165 rs->rs_state = RFCOMM_SESSION_WAIT_CONNECT;
166
167 err = l2cap_connect(rs->rs_l2cap, &dlc->rd_raddr);
168 if (err) {
169 rfcomm_session_free(rs);
170 return err;
171 }
172
173 /*
174 * This session will start up automatically when its
175 * L2CAP channel is connected.
176 */
177 }
178
179 /* construct DLC */
180 dlc->rd_dlci = RFCOMM_MKDLCI(IS_INITIATOR(rs) ? 0:1, dest->bt_channel);
181 if (rfcomm_dlc_lookup(rs, dlc->rd_dlci))
182 return EBUSY;
183
184 l2cap_sockaddr(rs->rs_l2cap, &dlc->rd_laddr);
185
186 /*
187 * attach the DLC to the session and start it off
188 */
189 dlc->rd_session = rs;
190 dlc->rd_state = RFCOMM_DLC_WAIT_SESSION;
191 LIST_INSERT_HEAD(&rs->rs_dlcs, dlc, rd_next);
192
193 if (rs->rs_state == RFCOMM_SESSION_OPEN)
194 err = rfcomm_dlc_connect(dlc);
195
196 return err;
197 }
198
199 /*
200 * rfcomm_peeraddr(dlc, sockaddr)
201 *
202 * return remote address
203 */
204 int
rfcomm_peeraddr(struct rfcomm_dlc * dlc,struct sockaddr_bt * addr)205 rfcomm_peeraddr(struct rfcomm_dlc *dlc, struct sockaddr_bt *addr)
206 {
207
208 memcpy(addr, &dlc->rd_raddr, sizeof(struct sockaddr_bt));
209 return 0;
210 }
211
212 /*
213 * rfcomm_disconnect(dlc, linger)
214 *
215 * disconnect RFCOMM DLC
216 */
217 int
rfcomm_disconnect(struct rfcomm_dlc * dlc,int linger)218 rfcomm_disconnect(struct rfcomm_dlc *dlc, int linger)
219 {
220 struct rfcomm_session *rs = dlc->rd_session;
221 int err = 0;
222
223 KKASSERT(dlc != NULL);
224
225 switch (dlc->rd_state) {
226 case RFCOMM_DLC_CLOSED:
227 case RFCOMM_DLC_LISTEN:
228 return EINVAL;
229
230 case RFCOMM_DLC_WAIT_SEND_UA:
231 err = rfcomm_session_send_frame(rs,
232 RFCOMM_FRAME_DM, dlc->rd_dlci);
233
234 /* fall through */
235 case RFCOMM_DLC_WAIT_SESSION:
236 case RFCOMM_DLC_WAIT_CONNECT:
237 case RFCOMM_DLC_WAIT_SEND_SABM:
238 rfcomm_dlc_close(dlc, 0);
239 break;
240
241 case RFCOMM_DLC_OPEN:
242 if (dlc->rd_txbuf != NULL && linger != 0) {
243 dlc->rd_flags |= RFCOMM_DLC_SHUTDOWN;
244 break;
245 }
246
247 /* else fall through */
248 case RFCOMM_DLC_WAIT_RECV_UA:
249 dlc->rd_state = RFCOMM_DLC_WAIT_DISCONNECT;
250 err = rfcomm_session_send_frame(rs, RFCOMM_FRAME_DISC,
251 dlc->rd_dlci);
252 callout_reset(&dlc->rd_timeout, rfcomm_ack_timeout * hz,
253 rfcomm_dlc_timeout, dlc);
254 break;
255
256 case RFCOMM_DLC_WAIT_DISCONNECT:
257 err = EALREADY;
258 break;
259
260 default:
261 UNKNOWN(dlc->rd_state);
262 break;
263 }
264
265 return err;
266 }
267
268 /*
269 * rfcomm_detach(handle)
270 *
271 * detach RFCOMM DLC from handle
272 */
273 int
rfcomm_detach(struct rfcomm_dlc ** handle)274 rfcomm_detach(struct rfcomm_dlc **handle)
275 {
276 struct rfcomm_dlc *dlc = *handle;
277
278 if (dlc->rd_state != RFCOMM_DLC_CLOSED)
279 rfcomm_dlc_close(dlc, 0);
280
281 if (dlc->rd_txbuf != NULL) {
282 m_freem(dlc->rd_txbuf);
283 dlc->rd_txbuf = NULL;
284 }
285
286 dlc->rd_upper = NULL;
287 *handle = NULL;
288
289 /*
290 * If callout is invoking we can't free the DLC so
291 * mark it and let the callout release it.
292 */
293 if (callout_active(&dlc->rd_timeout))
294 dlc->rd_flags |= RFCOMM_DLC_DETACH;
295 else
296 kfree(dlc, M_BLUETOOTH);
297
298 return 0;
299 }
300
301 /*
302 * rfcomm_listen(dlc)
303 *
304 * This DLC is a listener. We look for an existing listening session
305 * with a matching address to attach to or else create a new one on
306 * the listeners list. If the ANY channel is given, allocate the first
307 * available for the session.
308 */
309 int
rfcomm_listen(struct rfcomm_dlc * dlc)310 rfcomm_listen(struct rfcomm_dlc *dlc)
311 {
312 struct rfcomm_session *rs;
313 struct rfcomm_dlc *used;
314 struct sockaddr_bt addr;
315 int err, channel;
316
317 if (dlc->rd_state != RFCOMM_DLC_CLOSED)
318 return EISCONN;
319
320 if (dlc->rd_laddr.bt_channel != RFCOMM_CHANNEL_ANY
321 && (dlc->rd_laddr.bt_channel < RFCOMM_CHANNEL_MIN
322 || dlc->rd_laddr.bt_channel > RFCOMM_CHANNEL_MAX))
323 return EADDRNOTAVAIL;
324
325 if (dlc->rd_laddr.bt_psm == L2CAP_PSM_ANY)
326 dlc->rd_laddr.bt_psm = L2CAP_PSM_RFCOMM;
327 else if (dlc->rd_laddr.bt_psm != L2CAP_PSM_RFCOMM
328 && (dlc->rd_laddr.bt_psm < 0x1001
329 || L2CAP_PSM_INVALID(dlc->rd_laddr.bt_psm)))
330 return EADDRNOTAVAIL;
331
332 LIST_FOREACH(rs, &rfcomm_session_listen, rs_next) {
333 l2cap_sockaddr(rs->rs_l2cap, &addr);
334
335 if (addr.bt_psm != dlc->rd_laddr.bt_psm)
336 continue;
337
338 if (bdaddr_same(&dlc->rd_laddr.bt_bdaddr, &addr.bt_bdaddr))
339 break;
340 }
341
342 if (rs == NULL) {
343 rs = rfcomm_session_alloc(&rfcomm_session_listen,
344 &dlc->rd_laddr);
345 if (rs == NULL)
346 return ENOMEM;
347
348 rs->rs_state = RFCOMM_SESSION_LISTEN;
349
350 err = l2cap_listen(rs->rs_l2cap);
351 if (err) {
352 rfcomm_session_free(rs);
353 return err;
354 }
355 }
356
357 if (dlc->rd_laddr.bt_channel == RFCOMM_CHANNEL_ANY) {
358 channel = RFCOMM_CHANNEL_MIN;
359 used = LIST_FIRST(&rs->rs_dlcs);
360
361 while (used != NULL) {
362 if (used->rd_laddr.bt_channel == channel) {
363 if (channel++ == RFCOMM_CHANNEL_MAX)
364 return EADDRNOTAVAIL;
365
366 used = LIST_FIRST(&rs->rs_dlcs);
367 } else {
368 used = LIST_NEXT(used, rd_next);
369 }
370 }
371
372 dlc->rd_laddr.bt_channel = channel;
373 }
374
375 dlc->rd_session = rs;
376 dlc->rd_state = RFCOMM_DLC_LISTEN;
377 LIST_INSERT_HEAD(&rs->rs_dlcs, dlc, rd_next);
378
379 return 0;
380 }
381
382 /*
383 * rfcomm_send(dlc, mbuf)
384 *
385 * Output data on DLC. This is streamed data, so we add it
386 * to our buffer and start the DLC, which will assemble
387 * packets and send them if it can.
388 */
389 int
rfcomm_send(struct rfcomm_dlc * dlc,struct mbuf * m)390 rfcomm_send(struct rfcomm_dlc *dlc, struct mbuf *m)
391 {
392
393 if (dlc->rd_txbuf != NULL) {
394 dlc->rd_txbuf->m_pkthdr.len += m->m_pkthdr.len;
395 m_cat(dlc->rd_txbuf, m);
396 } else {
397 dlc->rd_txbuf = m;
398 }
399
400 if (dlc->rd_state == RFCOMM_DLC_OPEN)
401 rfcomm_dlc_start(dlc);
402
403 return 0;
404 }
405
406 /*
407 * rfcomm_rcvd(dlc, space)
408 *
409 * Indicate space now available in receive buffer
410 *
411 * This should be used to give an initial value of the receive buffer
412 * size when the DLC is attached and anytime data is cleared from the
413 * buffer after that.
414 */
415 int
rfcomm_rcvd(struct rfcomm_dlc * dlc,size_t space)416 rfcomm_rcvd(struct rfcomm_dlc *dlc, size_t space)
417 {
418
419 KKASSERT(dlc != NULL);
420
421 dlc->rd_rxsize = space;
422
423 /*
424 * if we are using credit based flow control, we may
425 * want to send some credits..
426 */
427 if (dlc->rd_state == RFCOMM_DLC_OPEN
428 && (dlc->rd_session->rs_flags & RFCOMM_SESSION_CFC))
429 rfcomm_dlc_start(dlc);
430
431 return 0;
432 }
433
434 /*
435 * rfcomm_setopt(dlc, option, addr)
436 *
437 * set DLC options
438 */
439 int
rfcomm_setopt(struct rfcomm_dlc * dlc,int opt,void * addr)440 rfcomm_setopt(struct rfcomm_dlc *dlc, int opt, void *addr)
441 {
442 int mode, err = 0;
443 uint16_t mtu;
444
445 switch (opt) {
446 case SO_RFCOMM_MTU:
447 mtu = *(uint16_t *)addr;
448 if (mtu < RFCOMM_MTU_MIN || mtu > RFCOMM_MTU_MAX)
449 err = EINVAL;
450 else if (dlc->rd_state == RFCOMM_DLC_CLOSED)
451 dlc->rd_mtu = mtu;
452 else
453 err = EBUSY;
454
455 break;
456
457 case SO_RFCOMM_LM:
458 mode = *(int *)addr;
459 mode &= (RFCOMM_LM_SECURE | RFCOMM_LM_ENCRYPT | RFCOMM_LM_AUTH);
460
461 if (mode & RFCOMM_LM_SECURE)
462 mode |= RFCOMM_LM_ENCRYPT;
463
464 if (mode & RFCOMM_LM_ENCRYPT)
465 mode |= RFCOMM_LM_AUTH;
466
467 dlc->rd_mode = mode;
468
469 if (dlc->rd_state == RFCOMM_DLC_OPEN)
470 err = rfcomm_dlc_setmode(dlc);
471
472 break;
473
474 default:
475 err = ENOPROTOOPT;
476 break;
477 }
478 return err;
479 }
480
481
482 int
rfcomm_setopt2(struct rfcomm_dlc * dlc,int opt,struct socket * so,struct sockopt * sopt)483 rfcomm_setopt2(struct rfcomm_dlc *dlc, int opt, struct socket *so,
484 struct sockopt *sopt)
485 {
486 int mode, err = 0;
487 uint16_t mtu;
488
489 switch (opt) {
490 case SO_RFCOMM_MTU:
491 err = soopt_to_kbuf(sopt, &mtu, sizeof(uint16_t),
492 sizeof(uint16_t));
493 if (err) break;
494
495 if (mtu < RFCOMM_MTU_MIN || mtu > RFCOMM_MTU_MAX)
496 err = EINVAL;
497 else if (dlc->rd_state == RFCOMM_DLC_CLOSED)
498 dlc->rd_mtu = mtu;
499 else
500 err = EBUSY;
501
502 break;
503
504 case SO_RFCOMM_LM:
505 err = soopt_to_kbuf(sopt, &mode, sizeof(int), sizeof(int));
506 if (err) break;
507
508 mode &= (RFCOMM_LM_SECURE | RFCOMM_LM_ENCRYPT | RFCOMM_LM_AUTH);
509
510 if (mode & RFCOMM_LM_SECURE)
511 mode |= RFCOMM_LM_ENCRYPT;
512
513 if (mode & RFCOMM_LM_ENCRYPT)
514 mode |= RFCOMM_LM_AUTH;
515
516 dlc->rd_mode = mode;
517
518 if (dlc->rd_state == RFCOMM_DLC_OPEN)
519 err = rfcomm_dlc_setmode(dlc);
520
521 break;
522
523 default:
524 err = ENOPROTOOPT;
525 break;
526 }
527 return err;
528 }
529
530 /*
531 * rfcomm_getopt(dlc, option, addr)
532 *
533 * get DLC options
534 */
535 int
rfcomm_getopt(struct rfcomm_dlc * dlc,int opt,void * addr)536 rfcomm_getopt(struct rfcomm_dlc *dlc, int opt, void *addr)
537 {
538 struct rfcomm_fc_info *fc;
539
540 switch (opt) {
541 case SO_RFCOMM_MTU:
542 *(uint16_t *)addr = dlc->rd_mtu;
543 return sizeof(uint16_t);
544
545 case SO_RFCOMM_FC_INFO:
546 fc = addr;
547 memset(fc, 0, sizeof(*fc));
548 fc->lmodem = dlc->rd_lmodem;
549 fc->rmodem = dlc->rd_rmodem;
550 fc->tx_cred = max(dlc->rd_txcred, 0xff);
551 fc->rx_cred = max(dlc->rd_rxcred, 0xff);
552 if (dlc->rd_session
553 && (dlc->rd_session->rs_flags & RFCOMM_SESSION_CFC))
554 fc->cfc = 1;
555
556 return sizeof(*fc);
557
558 case SO_RFCOMM_LM:
559 *(int *)addr = dlc->rd_mode;
560 return sizeof(int);
561
562 default:
563 break;
564 }
565
566 return 0;
567 }
568