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