xref: /dragonfly/sys/netbt/rfcomm_upper.c (revision c3b249e6)
1 /* $DragonFly: src/sys/netbt/rfcomm_upper.c,v 1.3 2008/06/20 20:52:29 aggelos Exp $ */
2 /* $OpenBSD: src/sys/netbt/rfcomm_upper.c,v 1.4 2008/02/24 21:34:48 uwe Exp $ */
3 /* $NetBSD: rfcomm_upper.c,v 1.10 2007/11/20 20:25:57 plunky Exp $ */
4 
5 /*-
6  * Copyright (c) 2006 Itronix Inc.
7  * All rights reserved.
8  *
9  * Written by Iain Hibbert for Itronix Inc.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. The name of Itronix Inc. may not be used to endorse
20  *    or promote products derived from this software without specific
21  *    prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
25  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
27  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30  * ON ANY THEORY OF LIABILITY, WHETHER IN
31  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 #include <sys/param.h>
37 #include <sys/kernel.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
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
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
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
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
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
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
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
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
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
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
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
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
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