xref: /netbsd-src/sys/netbt/rfcomm_upper.c (revision 946379e7b37692fc43f68eb0d1c10daa0a7f3b6c)
1 /*	$NetBSD: rfcomm_upper.c,v 1.22 2014/11/16 21:34:27 plunky 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.22 2014/11/16 21:34:27 plunky 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_intr_zalloc(sizeof(struct rfcomm_dlc), KM_NOSLEEP);
74 	if (dlc == NULL)
75 		return ENOMEM;
76 
77 	dlc->rd_state = RFCOMM_DLC_CLOSED;
78 	dlc->rd_mtu = rfcomm_mtu_default;
79 
80 	dlc->rd_proto = proto;
81 	dlc->rd_upper = upper;
82 
83 	dlc->rd_laddr.bt_len = sizeof(struct sockaddr_bt);
84 	dlc->rd_laddr.bt_family = AF_BLUETOOTH;
85 	dlc->rd_laddr.bt_psm = L2CAP_PSM_RFCOMM;
86 
87 	dlc->rd_raddr.bt_len = sizeof(struct sockaddr_bt);
88 	dlc->rd_raddr.bt_family = AF_BLUETOOTH;
89 	dlc->rd_raddr.bt_psm = L2CAP_PSM_RFCOMM;
90 
91 	dlc->rd_lmodem = RFCOMM_MSC_RTC | RFCOMM_MSC_RTR | RFCOMM_MSC_DV;
92 
93 	callout_init(&dlc->rd_timeout, 0);
94 	callout_setfunc(&dlc->rd_timeout, rfcomm_dlc_timeout, dlc);
95 
96 	*handle = dlc;
97 	return 0;
98 }
99 
100 /*
101  * rfcomm_bind_pcb(dlc, sockaddr)
102  *
103  * bind DLC to local address
104  */
105 int
106 rfcomm_bind_pcb(struct rfcomm_dlc *dlc, struct sockaddr_bt *addr)
107 {
108 
109 	if (dlc->rd_state != RFCOMM_DLC_CLOSED)
110 		return EINVAL;
111 
112 	memcpy(&dlc->rd_laddr, addr, sizeof(struct sockaddr_bt));
113 	return 0;
114 }
115 
116 /*
117  * rfcomm_sockaddr_pcb(dlc, sockaddr)
118  *
119  * return local address
120  */
121 int
122 rfcomm_sockaddr_pcb(struct rfcomm_dlc *dlc, struct sockaddr_bt *addr)
123 {
124 
125 	memcpy(addr, &dlc->rd_laddr, sizeof(struct sockaddr_bt));
126 	return 0;
127 }
128 
129 /*
130  * rfcomm_connect_pcb(dlc, sockaddr)
131  *
132  * Initiate connection of RFCOMM DLC to remote address.
133  */
134 int
135 rfcomm_connect_pcb(struct rfcomm_dlc *dlc, struct sockaddr_bt *dest)
136 {
137 	struct rfcomm_session *rs;
138 	int err = 0;
139 
140 	if (dlc->rd_state != RFCOMM_DLC_CLOSED)
141 		return EISCONN;
142 
143 	memcpy(&dlc->rd_raddr, dest, sizeof(struct sockaddr_bt));
144 
145 	if (dlc->rd_raddr.bt_channel < RFCOMM_CHANNEL_MIN
146 	    || dlc->rd_raddr.bt_channel > RFCOMM_CHANNEL_MAX
147 	    || bdaddr_any(&dlc->rd_raddr.bt_bdaddr))
148 		return EDESTADDRREQ;
149 
150 	if (dlc->rd_raddr.bt_psm == L2CAP_PSM_ANY)
151 		dlc->rd_raddr.bt_psm = L2CAP_PSM_RFCOMM;
152 	else if (dlc->rd_raddr.bt_psm != L2CAP_PSM_RFCOMM
153 	    && (dlc->rd_raddr.bt_psm < 0x1001
154 	    || L2CAP_PSM_INVALID(dlc->rd_raddr.bt_psm)))
155 		return EINVAL;
156 
157 	/*
158 	 * We are allowed only one RFCOMM session between any 2 Bluetooth
159 	 * devices, so see if there is a session already otherwise create
160 	 * one and set it connecting.
161 	 */
162 	rs = rfcomm_session_lookup(&dlc->rd_laddr, &dlc->rd_raddr);
163 	if (rs == NULL) {
164 		rs = rfcomm_session_alloc(&rfcomm_session_active,
165 						&dlc->rd_laddr);
166 		if (rs == NULL)
167 			return ENOMEM;
168 
169 		rs->rs_flags |= RFCOMM_SESSION_INITIATOR;
170 		rs->rs_state = RFCOMM_SESSION_WAIT_CONNECT;
171 
172 		err = l2cap_connect_pcb(rs->rs_l2cap, &dlc->rd_raddr);
173 		if (err) {
174 			rfcomm_session_free(rs);
175 			return err;
176 		}
177 
178 		/*
179 		 * This session will start up automatically when its
180 		 * L2CAP channel is connected.
181 		 */
182 	}
183 
184 	/* construct DLC */
185 	dlc->rd_dlci = RFCOMM_MKDLCI(IS_INITIATOR(rs) ? 0:1, dest->bt_channel);
186 	if (rfcomm_dlc_lookup(rs, dlc->rd_dlci))
187 		return EBUSY;
188 
189 	l2cap_sockaddr_pcb(rs->rs_l2cap, &dlc->rd_laddr);
190 
191 	/*
192 	 * attach the DLC to the session and start it off
193 	 */
194 	dlc->rd_session = rs;
195 	dlc->rd_state = RFCOMM_DLC_WAIT_SESSION;
196 	LIST_INSERT_HEAD(&rs->rs_dlcs, dlc, rd_next);
197 
198 	if (rs->rs_state == RFCOMM_SESSION_OPEN)
199 		err = rfcomm_dlc_connect(dlc);
200 
201 	return err;
202 }
203 
204 /*
205  * rfcomm_peeraddr_pcb(dlc, sockaddr)
206  *
207  * return remote address
208  */
209 int
210 rfcomm_peeraddr_pcb(struct rfcomm_dlc *dlc, struct sockaddr_bt *addr)
211 {
212 
213 	memcpy(addr, &dlc->rd_raddr, sizeof(struct sockaddr_bt));
214 	return 0;
215 }
216 
217 /*
218  * rfcomm_disconnect_pcb(dlc, linger)
219  *
220  * disconnect RFCOMM DLC
221  */
222 int
223 rfcomm_disconnect_pcb(struct rfcomm_dlc *dlc, int linger)
224 {
225 	struct rfcomm_session *rs = dlc->rd_session;
226 	int err = 0;
227 
228 	KASSERT(dlc != NULL);
229 
230 	switch (dlc->rd_state) {
231 	case RFCOMM_DLC_CLOSED:
232 	case RFCOMM_DLC_LISTEN:
233 		return EINVAL;
234 
235 	case RFCOMM_DLC_WAIT_SEND_UA:
236 		err = rfcomm_session_send_frame(rs,
237 				RFCOMM_FRAME_DM, dlc->rd_dlci);
238 
239 		/* fall through */
240 	case RFCOMM_DLC_WAIT_SESSION:
241 	case RFCOMM_DLC_WAIT_CONNECT:
242 	case RFCOMM_DLC_WAIT_SEND_SABM:
243 		rfcomm_dlc_close(dlc, 0);
244 		break;
245 
246 	case RFCOMM_DLC_OPEN:
247 		if (dlc->rd_txbuf != NULL && linger != 0) {
248 			dlc->rd_flags |= RFCOMM_DLC_SHUTDOWN;
249 			break;
250 		}
251 
252 		/* else fall through */
253 	case RFCOMM_DLC_WAIT_RECV_UA:
254 		dlc->rd_state = RFCOMM_DLC_WAIT_DISCONNECT;
255 		err = rfcomm_session_send_frame(rs, RFCOMM_FRAME_DISC,
256 							dlc->rd_dlci);
257 		callout_schedule(&dlc->rd_timeout, rfcomm_ack_timeout * hz);
258 		break;
259 
260 	case RFCOMM_DLC_WAIT_DISCONNECT:
261 		err = EALREADY;
262 		break;
263 
264 	default:
265 		UNKNOWN(dlc->rd_state);
266 		break;
267 	}
268 
269 	return err;
270 }
271 
272 /*
273  * rfcomm_detach_pcb(handle)
274  *
275  * detach RFCOMM DLC from handle
276  */
277 void
278 rfcomm_detach_pcb(struct rfcomm_dlc **handle)
279 {
280 	struct rfcomm_dlc *dlc = *handle;
281 
282 	if (dlc->rd_state != RFCOMM_DLC_CLOSED)
283 		rfcomm_dlc_close(dlc, 0);
284 
285 	if (dlc->rd_txbuf != NULL) {
286 		m_freem(dlc->rd_txbuf);
287 		dlc->rd_txbuf = NULL;
288 	}
289 
290 	dlc->rd_upper = NULL;
291 	*handle = NULL;
292 
293 	/*
294 	 * If callout is invoking we can't free the DLC so
295 	 * mark it and let the callout release it.
296 	 */
297 	if (callout_invoking(&dlc->rd_timeout))
298 		dlc->rd_flags |= RFCOMM_DLC_DETACH;
299 	else {
300 		callout_destroy(&dlc->rd_timeout);
301 		kmem_intr_free(dlc, sizeof(*dlc));
302 	}
303 }
304 
305 /*
306  * rfcomm_listen_pcb(dlc)
307  *
308  * This DLC is a listener. We look for an existing listening session
309  * with a matching address to attach to or else create a new one on
310  * the listeners list. If the ANY channel is given, allocate the first
311  * available for the session.
312  */
313 int
314 rfcomm_listen_pcb(struct rfcomm_dlc *dlc)
315 {
316 	struct rfcomm_session *rs;
317 	struct rfcomm_dlc *used;
318 	struct sockaddr_bt addr;
319 	int err, channel;
320 
321 	if (dlc->rd_state != RFCOMM_DLC_CLOSED)
322 		return EISCONN;
323 
324 	if (dlc->rd_laddr.bt_channel != RFCOMM_CHANNEL_ANY
325 	    && (dlc->rd_laddr.bt_channel < RFCOMM_CHANNEL_MIN
326 	    || dlc->rd_laddr.bt_channel > RFCOMM_CHANNEL_MAX))
327 		return EADDRNOTAVAIL;
328 
329 	if (dlc->rd_laddr.bt_psm == L2CAP_PSM_ANY)
330 		dlc->rd_laddr.bt_psm = L2CAP_PSM_RFCOMM;
331 	else if (dlc->rd_laddr.bt_psm != L2CAP_PSM_RFCOMM
332 	    && (dlc->rd_laddr.bt_psm < 0x1001
333 	    || L2CAP_PSM_INVALID(dlc->rd_laddr.bt_psm)))
334 		return EADDRNOTAVAIL;
335 
336 	LIST_FOREACH(rs, &rfcomm_session_listen, rs_next) {
337 		l2cap_sockaddr_pcb(rs->rs_l2cap, &addr);
338 
339 		if (addr.bt_psm != dlc->rd_laddr.bt_psm)
340 			continue;
341 
342 		if (bdaddr_same(&dlc->rd_laddr.bt_bdaddr, &addr.bt_bdaddr))
343 			break;
344 	}
345 
346 	if (rs == NULL) {
347 		rs = rfcomm_session_alloc(&rfcomm_session_listen,
348 						&dlc->rd_laddr);
349 		if (rs == NULL)
350 			return ENOMEM;
351 
352 		rs->rs_state = RFCOMM_SESSION_LISTEN;
353 
354 		err = l2cap_listen_pcb(rs->rs_l2cap);
355 		if (err) {
356 			rfcomm_session_free(rs);
357 			return err;
358 		}
359 	}
360 
361 	if (dlc->rd_laddr.bt_channel == RFCOMM_CHANNEL_ANY) {
362 		channel = RFCOMM_CHANNEL_MIN;
363 		used = LIST_FIRST(&rs->rs_dlcs);
364 
365 		while (used != NULL) {
366 			if (used->rd_laddr.bt_channel == channel) {
367 				if (channel++ == RFCOMM_CHANNEL_MAX)
368 					return EADDRNOTAVAIL;
369 
370 				used = LIST_FIRST(&rs->rs_dlcs);
371 			} else {
372 				used = LIST_NEXT(used, rd_next);
373 			}
374 		}
375 
376 		dlc->rd_laddr.bt_channel = channel;
377 	}
378 
379 	dlc->rd_session = rs;
380 	dlc->rd_state = RFCOMM_DLC_LISTEN;
381 	LIST_INSERT_HEAD(&rs->rs_dlcs, dlc, rd_next);
382 
383 	return 0;
384 }
385 
386 /*
387  * rfcomm_send_pcb(dlc, mbuf)
388  *
389  * Output data on DLC. This is streamed data, so we add it
390  * to our buffer and start the DLC, which will assemble
391  * packets and send them if it can.
392  */
393 int
394 rfcomm_send_pcb(struct rfcomm_dlc *dlc, struct mbuf *m)
395 {
396 
397 	if (dlc->rd_txbuf != NULL) {
398 		dlc->rd_txbuf->m_pkthdr.len += m->m_pkthdr.len;
399 		m_cat(dlc->rd_txbuf, m);
400 	} else {
401 		dlc->rd_txbuf = m;
402 	}
403 
404 	if (dlc->rd_state == RFCOMM_DLC_OPEN)
405 		rfcomm_dlc_start(dlc);
406 
407 	return 0;
408 }
409 
410 /*
411  * rfcomm_rcvd_pcb(dlc, space)
412  *
413  * Indicate space now available in receive buffer
414  *
415  * This should be used to give an initial value of the receive buffer
416  * size when the DLC is attached and anytime data is cleared from the
417  * buffer after that.
418  */
419 int
420 rfcomm_rcvd_pcb(struct rfcomm_dlc *dlc, size_t space)
421 {
422 
423 	KASSERT(dlc != NULL);
424 
425 	dlc->rd_rxsize = space;
426 
427 	/*
428 	 * if we are using credit based flow control, we may
429 	 * want to send some credits..
430 	 */
431 	if (dlc->rd_state == RFCOMM_DLC_OPEN
432 	    && (dlc->rd_session->rs_flags & RFCOMM_SESSION_CFC))
433 		rfcomm_dlc_start(dlc);
434 
435 	return 0;
436 }
437 
438 /*
439  * rfcomm_setopt(dlc, sopt)
440  *
441  * set DLC options
442  */
443 int
444 rfcomm_setopt(struct rfcomm_dlc *dlc, const struct sockopt *sopt)
445 {
446 	int mode, err = 0;
447 	uint16_t mtu;
448 
449 	switch (sopt->sopt_name) {
450 	case SO_RFCOMM_MTU:
451 		err = sockopt_get(sopt, &mtu, sizeof(mtu));
452 		if (err)
453 			break;
454 
455 		if (mtu < RFCOMM_MTU_MIN || mtu > RFCOMM_MTU_MAX)
456 			err = EINVAL;
457 		else if (dlc->rd_state == RFCOMM_DLC_CLOSED)
458 			dlc->rd_mtu = mtu;
459 		else
460 			err = EBUSY;
461 
462 		break;
463 
464 	case SO_RFCOMM_LM:
465 		err = sockopt_getint(sopt, &mode);
466 		if (err)
467 			break;
468 
469 		mode &= (RFCOMM_LM_SECURE | RFCOMM_LM_ENCRYPT | RFCOMM_LM_AUTH);
470 
471 		if (mode & RFCOMM_LM_SECURE)
472 			mode |= RFCOMM_LM_ENCRYPT;
473 
474 		if (mode & RFCOMM_LM_ENCRYPT)
475 			mode |= RFCOMM_LM_AUTH;
476 
477 		dlc->rd_mode = mode;
478 
479 		if (dlc->rd_state == RFCOMM_DLC_OPEN)
480 			err = rfcomm_dlc_setmode(dlc);
481 
482 		break;
483 
484 	default:
485 		err = ENOPROTOOPT;
486 		break;
487 	}
488 	return err;
489 }
490 
491 /*
492  * rfcomm_getopt(dlc, sopt)
493  *
494  * get DLC options
495  */
496 int
497 rfcomm_getopt(struct rfcomm_dlc *dlc, struct sockopt *sopt)
498 {
499 	struct rfcomm_fc_info fc;
500 
501 	switch (sopt->sopt_name) {
502 	case SO_RFCOMM_MTU:
503 		return sockopt_set(sopt, &dlc->rd_mtu, sizeof(uint16_t));
504 
505 	case SO_RFCOMM_FC_INFO:
506 		memset(&fc, 0, sizeof(fc));
507 		fc.lmodem = dlc->rd_lmodem;
508 		fc.rmodem = dlc->rd_rmodem;
509 		fc.tx_cred = max(dlc->rd_txcred, 0xff);
510 		fc.rx_cred = max(dlc->rd_rxcred, 0xff);
511 		if (dlc->rd_session
512 		    && (dlc->rd_session->rs_flags & RFCOMM_SESSION_CFC))
513 			fc.cfc = 1;
514 
515 		return sockopt_set(sopt, &fc, sizeof(fc));
516 
517 	case SO_RFCOMM_LM:
518 		return sockopt_setint(sopt, dlc->rd_mode);
519 
520 	default:
521 		break;
522 	}
523 
524 	return ENOPROTOOPT;
525 }
526