xref: /netbsd-src/sys/netbt/rfcomm_upper.c (revision b7b7574d3bf8eeb51a1fa3977b59142ec6434a55)
1 /*	$NetBSD: rfcomm_upper.c,v 1.15 2014/05/20 18:25:54 rmind 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.15 2014/05/20 18:25:54 rmind 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(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 	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(dlc, sockaddr)
116  *
117  * return local address
118  */
119 int
120 rfcomm_sockaddr(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(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(dlc, sockaddr)
204  *
205  * return remote address
206  */
207 int
208 rfcomm_peeraddr(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(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(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(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(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