Home | History | Annotate | Line # | Download | only in netbt
      1 /*	$NetBSD: rfcomm_dlc.c,v 1.9 2018/09/03 16:29:36 riastradh 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_dlc.c,v 1.9 2018/09/03 16:29:36 riastradh Exp $");
     36 
     37 #include <sys/param.h>
     38 #include <sys/kernel.h>
     39 #include <sys/mbuf.h>
     40 #include <sys/proc.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  * rfcomm_dlc_lookup(rfcomm_session, dlci)
     51  *
     52  * Find DLC on session with matching dlci
     53  */
     54 struct rfcomm_dlc *
     55 rfcomm_dlc_lookup(struct rfcomm_session *rs, int dlci)
     56 {
     57 	struct rfcomm_dlc *dlc;
     58 
     59 	LIST_FOREACH(dlc, &rs->rs_dlcs, rd_next) {
     60 		if (dlc->rd_dlci == dlci)
     61 			break;
     62 	}
     63 
     64 	return dlc;
     65 }
     66 
     67 /*
     68  * rfcomm_dlc_newconn(rfcomm_session, dlci)
     69  *
     70  * handle a new dlc request (since its called from a couple of places)
     71  */
     72 struct rfcomm_dlc *
     73 rfcomm_dlc_newconn(struct rfcomm_session *rs, int dlci)
     74 {
     75 	struct rfcomm_session *ls;
     76 	struct rfcomm_dlc *new, *dlc, *any, *best;
     77 	struct sockaddr_bt laddr, raddr, addr;
     78 	int chan;
     79 
     80 	/*
     81 	 * Search amongst the listening DLC community for the best match for
     82 	 * address & channel. We keep listening DLC's hanging on listening
     83 	 * sessions in a last first order, so scan the entire bunch and keep
     84 	 * a note of the best address and BDADDR_ANY matches in order to find
     85 	 * the oldest and most specific match.
     86 	 */
     87 	l2cap_sockaddr_pcb(rs->rs_l2cap, &laddr);
     88 	l2cap_peeraddr_pcb(rs->rs_l2cap, &raddr);
     89 	chan = RFCOMM_CHANNEL(dlci);
     90 	new = NULL;
     91 
     92 	any = best = NULL;
     93 	LIST_FOREACH(ls, &rfcomm_session_listen, rs_next) {
     94 		l2cap_sockaddr_pcb(ls->rs_l2cap, &addr);
     95 
     96 		if (addr.bt_psm != laddr.bt_psm)
     97 			continue;
     98 
     99 		if (bdaddr_same(&laddr.bt_bdaddr, &addr.bt_bdaddr)) {
    100 			LIST_FOREACH(dlc, &ls->rs_dlcs, rd_next) {
    101 				if (dlc->rd_laddr.bt_channel == chan)
    102 					best = dlc;
    103 			}
    104 		}
    105 
    106 		if (bdaddr_any(&addr.bt_bdaddr)) {
    107 			LIST_FOREACH(dlc, &ls->rs_dlcs, rd_next) {
    108 				if (dlc->rd_laddr.bt_channel == chan)
    109 					any = dlc;
    110 			}
    111 		}
    112 	}
    113 
    114 	dlc = best ? best : any;
    115 
    116 	/* XXX
    117 	 * Note that if this fails, we could have missed a chance to open
    118 	 * a connection - really need to rewrite the strategy for storing
    119 	 * listening DLC's so all can be checked in turn..
    120 	 */
    121 	if (dlc != NULL)
    122 		new = (*dlc->rd_proto->newconn)(dlc->rd_upper, &laddr, &raddr);
    123 
    124 	if (new == NULL) {
    125 		rfcomm_session_send_frame(rs, RFCOMM_FRAME_DM, dlci);
    126 		return NULL;
    127 	}
    128 
    129 	new->rd_dlci = dlci;
    130 	new->rd_mtu = rfcomm_mtu_default;
    131 	new->rd_mode = dlc->rd_mode;
    132 
    133 	memcpy(&new->rd_laddr, &laddr, sizeof(struct sockaddr_bt));
    134 	new->rd_laddr.bt_channel = chan;
    135 
    136 	memcpy(&new->rd_raddr, &raddr, sizeof(struct sockaddr_bt));
    137 	new->rd_raddr.bt_channel = chan;
    138 
    139 	new->rd_session = rs;
    140 	new->rd_state = RFCOMM_DLC_WAIT_CONNECT;
    141 	LIST_INSERT_HEAD(&rs->rs_dlcs, new, rd_next);
    142 
    143 	return new;
    144 }
    145 
    146 /*
    147  * rfcomm_dlc_close(dlc, error)
    148  *
    149  * detach DLC from session and clean up
    150  */
    151 void
    152 rfcomm_dlc_close(struct rfcomm_dlc *dlc, int err)
    153 {
    154 	struct rfcomm_session *rs;
    155 	struct rfcomm_credit *credit;
    156 
    157 	KASSERT(dlc->rd_state != RFCOMM_DLC_CLOSED);
    158 
    159 	/* Clear credit history */
    160 	rs = dlc->rd_session;
    161 	SIMPLEQ_FOREACH(credit, &rs->rs_credits, rc_next)
    162 		if (credit->rc_dlc == dlc)
    163 			credit->rc_dlc = NULL;
    164 
    165 	callout_stop(&dlc->rd_timeout);
    166 
    167 	LIST_REMOVE(dlc, rd_next);
    168 	dlc->rd_session = NULL;
    169 	dlc->rd_state = RFCOMM_DLC_CLOSED;
    170 
    171 	(*dlc->rd_proto->disconnected)(dlc->rd_upper, err);
    172 
    173 	/*
    174 	 * It is the responsibility of the party who sends the last
    175 	 * DISC(dlci) to disconnect the session, but we will schedule
    176 	 * an expiry just in case that doesnt happen..
    177 	 */
    178 	if (LIST_EMPTY(&rs->rs_dlcs)) {
    179 		if (rs->rs_state == RFCOMM_SESSION_LISTEN)
    180 			rfcomm_session_free(rs);
    181 		else
    182 			callout_schedule(&rs->rs_timeout,
    183 					rfcomm_ack_timeout * hz);
    184 	}
    185 }
    186 
    187 /*
    188  * rfcomm_dlc_timeout(dlc)
    189  *
    190  * DLC timeout function is scheduled when we sent any of SABM,
    191  * DISC, MCC_MSC, or MCC_PN and should be cancelled when we get
    192  * the relevant response. There is nothing to do but shut this
    193  * DLC down.
    194  */
    195 void
    196 rfcomm_dlc_timeout(void *arg)
    197 {
    198 	struct rfcomm_dlc *dlc = arg;
    199 
    200 	mutex_enter(bt_lock);
    201 	callout_ack(&dlc->rd_timeout);
    202 
    203 	if (dlc->rd_state != RFCOMM_DLC_CLOSED)
    204 		rfcomm_dlc_close(dlc, ETIMEDOUT);
    205 	else if (dlc->rd_flags & RFCOMM_DLC_DETACH) {
    206 		callout_destroy(&dlc->rd_timeout);
    207 		free(dlc, M_BLUETOOTH);
    208 	}
    209 
    210 	mutex_exit(bt_lock);
    211 }
    212 
    213 /*
    214  * rfcomm_dlc_setmode(rfcomm_dlc)
    215  *
    216  * Set link mode for DLC.  This is only called when the session is
    217  * already open, so we don't need to worry about any previous mode
    218  * settings.
    219  */
    220 int
    221 rfcomm_dlc_setmode(struct rfcomm_dlc *dlc)
    222 {
    223 	struct sockopt sopt;
    224 	int mode = 0, err;
    225 
    226 	KASSERT(dlc->rd_session != NULL);
    227 	KASSERT(dlc->rd_session->rs_state == RFCOMM_SESSION_OPEN);
    228 
    229 	DPRINTF("dlci %d, auth %s, encrypt %s, secure %s\n", dlc->rd_dlci,
    230 		(dlc->rd_mode & RFCOMM_LM_AUTH ? "yes" : "no"),
    231 		(dlc->rd_mode & RFCOMM_LM_ENCRYPT ? "yes" : "no"),
    232 		(dlc->rd_mode & RFCOMM_LM_SECURE ? "yes" : "no"));
    233 
    234 	if (dlc->rd_mode & RFCOMM_LM_AUTH)
    235 		mode |= L2CAP_LM_AUTH;
    236 
    237 	if (dlc->rd_mode & RFCOMM_LM_ENCRYPT)
    238 		mode |= L2CAP_LM_ENCRYPT;
    239 
    240 	if (dlc->rd_mode & RFCOMM_LM_SECURE)
    241 		mode |= L2CAP_LM_SECURE;
    242 
    243 	sockopt_init(&sopt, BTPROTO_L2CAP, SO_L2CAP_LM, 0);
    244 	sockopt_setint(&sopt, mode);
    245 	err = l2cap_setopt(dlc->rd_session->rs_l2cap, &sopt);
    246 	sockopt_destroy(&sopt);
    247 
    248 	return err;
    249 }
    250 
    251 /*
    252  * rfcomm_dlc_connect(rfcomm_dlc)
    253  *
    254  * initiate DLC connection (session is already connected)
    255  */
    256 int
    257 rfcomm_dlc_connect(struct rfcomm_dlc *dlc)
    258 {
    259 	struct rfcomm_mcc_pn pn;
    260 	int err = 0;
    261 
    262 	KASSERT(dlc->rd_session != NULL);
    263 	KASSERT(dlc->rd_session->rs_state == RFCOMM_SESSION_OPEN);
    264 	KASSERT(dlc->rd_state == RFCOMM_DLC_WAIT_SESSION);
    265 
    266 	/*
    267 	 * If we have not already sent a PN on the session, we must send
    268 	 * a PN to negotiate Credit Flow Control, and this setting will
    269 	 * apply to all future connections for this session. We ask for
    270 	 * this every time, in order to establish initial credits.
    271 	 */
    272 	memset(&pn, 0, sizeof(pn));
    273 	pn.dlci = dlc->rd_dlci;
    274 	pn.priority = dlc->rd_dlci | 0x07;
    275 	pn.mtu = htole16(dlc->rd_mtu);
    276 
    277 	pn.flow_control = 0xf0;
    278 	dlc->rd_rxcred = (dlc->rd_rxsize / dlc->rd_mtu);
    279 	dlc->rd_rxcred = uimin(dlc->rd_rxcred, RFCOMM_CREDITS_DEFAULT);
    280 	pn.credits = dlc->rd_rxcred;
    281 
    282 	err = rfcomm_session_send_mcc(dlc->rd_session, 1,
    283 					RFCOMM_MCC_PN, &pn, sizeof(pn));
    284 	if (err)
    285 		return err;
    286 
    287 	dlc->rd_state = RFCOMM_DLC_WAIT_CONNECT;
    288 	callout_schedule(&dlc->rd_timeout, rfcomm_mcc_timeout * hz);
    289 
    290 	return 0;
    291 }
    292 
    293 /*
    294  * rfcomm_dlc_open(rfcomm_dlc)
    295  *
    296  * send "Modem Status Command" and mark DLC as open.
    297  */
    298 int
    299 rfcomm_dlc_open(struct rfcomm_dlc *dlc)
    300 {
    301 	struct rfcomm_mcc_msc msc;
    302 	int err;
    303 
    304 	KASSERT(dlc->rd_session != NULL);
    305 	KASSERT(dlc->rd_session->rs_state == RFCOMM_SESSION_OPEN);
    306 
    307 	memset(&msc, 0, sizeof(msc));
    308 	msc.address = RFCOMM_MKADDRESS(1, dlc->rd_dlci);
    309 	msc.modem = dlc->rd_lmodem & 0xfe;	/* EA = 0 */
    310 	msc.brk =	0x00	   | 0x01;	/* EA = 1 */
    311 
    312 	err = rfcomm_session_send_mcc(dlc->rd_session, 1,
    313 				RFCOMM_MCC_MSC, &msc, sizeof(msc));
    314 	if (err)
    315 		return err;
    316 
    317 	callout_schedule(&dlc->rd_timeout, rfcomm_mcc_timeout * hz);
    318 
    319 	dlc->rd_state = RFCOMM_DLC_OPEN;
    320 	(*dlc->rd_proto->connected)(dlc->rd_upper);
    321 
    322 	return 0;
    323 }
    324 
    325 /*
    326  * rfcomm_dlc_start(rfcomm_dlc)
    327  *
    328  * Start sending data (and/or credits) for DLC. Our strategy is to
    329  * send anything we can down to the l2cap layer. When credits run
    330  * out, data will naturally bunch up. When not using credit flow
    331  * control, we limit the number of packets we have pending to reduce
    332  * flow control lag.
    333  * We should deal with channel priority somehow.
    334  */
    335 void
    336 rfcomm_dlc_start(struct rfcomm_dlc *dlc)
    337 {
    338 	struct rfcomm_session *rs = dlc->rd_session;
    339 	struct mbuf *m;
    340 	int len, credits;
    341 
    342 	KASSERT(rs != NULL);
    343 	KASSERT(rs->rs_state == RFCOMM_SESSION_OPEN);
    344 	KASSERT(dlc->rd_state == RFCOMM_DLC_OPEN);
    345 
    346 	for (;;) {
    347 		credits = 0;
    348 		len = dlc->rd_mtu;
    349 		if (rs->rs_flags & RFCOMM_SESSION_CFC) {
    350 			credits = (dlc->rd_rxsize / dlc->rd_mtu);
    351 			credits -= dlc->rd_rxcred;
    352 			credits = uimin(credits, RFCOMM_CREDITS_MAX);
    353 
    354 			if (credits > 0)
    355 				len--;
    356 
    357 			if (dlc->rd_txcred == 0)
    358 				len = 0;
    359 		} else {
    360 			if (rs->rs_flags & RFCOMM_SESSION_RFC)
    361 				break;
    362 
    363 			if (dlc->rd_rmodem & RFCOMM_MSC_FC)
    364 				break;
    365 
    366 			if (dlc->rd_pending > RFCOMM_CREDITS_DEFAULT)
    367 				break;
    368 		}
    369 
    370 		if (dlc->rd_txbuf == NULL)
    371 			len = 0;
    372 
    373 		if (len == 0) {
    374 			if (credits == 0)
    375 				break;
    376 
    377 			/*
    378 			 * No need to send small numbers of credits on their
    379 			 * own unless the other end hasn't many left.
    380 			 */
    381 			if (credits < RFCOMM_CREDITS_DEFAULT
    382 			    && dlc->rd_rxcred > RFCOMM_CREDITS_DEFAULT)
    383 				break;
    384 
    385 			m = NULL;
    386 		} else {
    387 			/*
    388 			 * take what data we can from (front of) txbuf
    389 			 */
    390 			m = dlc->rd_txbuf;
    391 			if (len < m->m_pkthdr.len) {
    392 				dlc->rd_txbuf = m_split(m, len, M_DONTWAIT);
    393 				if (dlc->rd_txbuf == NULL) {
    394 					dlc->rd_txbuf = m;
    395 					break;
    396 				}
    397 			} else {
    398 				dlc->rd_txbuf = NULL;
    399 				len = m->m_pkthdr.len;
    400 			}
    401 		}
    402 
    403 		DPRINTFN(10, "dlci %d send %d bytes, %d credits, rxcred = %d\n",
    404 			dlc->rd_dlci, len, credits, dlc->rd_rxcred);
    405 
    406 		if (rfcomm_session_send_uih(rs, dlc, credits, m)) {
    407 			printf("%s: lost %d bytes on DLCI %d\n",
    408 				__func__, len, dlc->rd_dlci);
    409 
    410 			break;
    411 		}
    412 
    413 		dlc->rd_pending++;
    414 
    415 		if (rs->rs_flags & RFCOMM_SESSION_CFC) {
    416 			if (len > 0)
    417 				dlc->rd_txcred--;
    418 
    419 			if (credits > 0)
    420 				dlc->rd_rxcred += credits;
    421 		}
    422 	}
    423 }
    424