Home | History | Annotate | Line # | Download | only in netbt
rfcomm_upper.c revision 1.22.20.1
      1 /*	$NetBSD: rfcomm_upper.c,v 1.22.20.1 2019/06/10 22:09:47 christos 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.20.1 2019/06/10 22:09:47 christos 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 = uimax(dlc->rd_txcred, 0xff);
    510 		fc.rx_cred = uimax(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