Home | History | Annotate | Line # | Download | only in netbt
rfcomm_session.c revision 1.29
      1  1.29    andvar /*	$NetBSD: rfcomm_session.c,v 1.29 2024/02/09 22:08:37 andvar Exp $	*/
      2   1.1   gdamore 
      3   1.1   gdamore /*-
      4   1.1   gdamore  * Copyright (c) 2006 Itronix Inc.
      5   1.1   gdamore  * All rights reserved.
      6   1.1   gdamore  *
      7   1.1   gdamore  * Written by Iain Hibbert for Itronix Inc.
      8   1.1   gdamore  *
      9   1.1   gdamore  * Redistribution and use in source and binary forms, with or without
     10   1.1   gdamore  * modification, are permitted provided that the following conditions
     11   1.1   gdamore  * are met:
     12   1.1   gdamore  * 1. Redistributions of source code must retain the above copyright
     13   1.1   gdamore  *    notice, this list of conditions and the following disclaimer.
     14   1.1   gdamore  * 2. Redistributions in binary form must reproduce the above copyright
     15   1.1   gdamore  *    notice, this list of conditions and the following disclaimer in the
     16   1.1   gdamore  *    documentation and/or other materials provided with the distribution.
     17   1.1   gdamore  * 3. The name of Itronix Inc. may not be used to endorse
     18   1.1   gdamore  *    or promote products derived from this software without specific
     19   1.1   gdamore  *    prior written permission.
     20   1.1   gdamore  *
     21   1.1   gdamore  * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
     22   1.1   gdamore  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     23   1.1   gdamore  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     24   1.1   gdamore  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
     25   1.1   gdamore  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     26   1.1   gdamore  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     27   1.1   gdamore  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     28   1.1   gdamore  * ON ANY THEORY OF LIABILITY, WHETHER IN
     29   1.1   gdamore  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     30   1.1   gdamore  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     31   1.1   gdamore  * POSSIBILITY OF SUCH DAMAGE.
     32   1.1   gdamore  */
     33   1.1   gdamore 
     34   1.1   gdamore #include <sys/cdefs.h>
     35  1.29    andvar __KERNEL_RCSID(0, "$NetBSD: rfcomm_session.c,v 1.29 2024/02/09 22:08:37 andvar Exp $");
     36   1.1   gdamore 
     37   1.1   gdamore #include <sys/param.h>
     38   1.1   gdamore #include <sys/kernel.h>
     39   1.1   gdamore #include <sys/mbuf.h>
     40   1.1   gdamore #include <sys/proc.h>
     41  1.14    plunky #include <sys/socketvar.h>
     42   1.1   gdamore #include <sys/systm.h>
     43   1.1   gdamore #include <sys/types.h>
     44   1.1   gdamore 
     45   1.1   gdamore #include <netbt/bluetooth.h>
     46   1.1   gdamore #include <netbt/hci.h>
     47   1.1   gdamore #include <netbt/l2cap.h>
     48   1.1   gdamore #include <netbt/rfcomm.h>
     49   1.1   gdamore 
     50   1.1   gdamore /******************************************************************************
     51   1.1   gdamore  *
     52   1.1   gdamore  * RFCOMM Multiplexer Sessions sit directly on L2CAP channels, and can
     53   1.1   gdamore  * multiplex up to 30 incoming and 30 outgoing connections.
     54   1.1   gdamore  * Only one Multiplexer is allowed between any two devices.
     55   1.1   gdamore  */
     56   1.1   gdamore 
     57   1.1   gdamore static void rfcomm_session_timeout(void *);
     58   1.1   gdamore static void rfcomm_session_recv_sabm(struct rfcomm_session *, int);
     59   1.1   gdamore static void rfcomm_session_recv_disc(struct rfcomm_session *, int);
     60   1.1   gdamore static void rfcomm_session_recv_ua(struct rfcomm_session *, int);
     61   1.1   gdamore static void rfcomm_session_recv_dm(struct rfcomm_session *, int);
     62   1.1   gdamore static void rfcomm_session_recv_uih(struct rfcomm_session *, int, int, struct mbuf *, int);
     63   1.1   gdamore static void rfcomm_session_recv_mcc(struct rfcomm_session *, struct mbuf *);
     64   1.1   gdamore static void rfcomm_session_recv_mcc_test(struct rfcomm_session *, int, struct mbuf *);
     65   1.1   gdamore static void rfcomm_session_recv_mcc_fcon(struct rfcomm_session *, int);
     66   1.1   gdamore static void rfcomm_session_recv_mcc_fcoff(struct rfcomm_session *, int);
     67   1.1   gdamore static void rfcomm_session_recv_mcc_msc(struct rfcomm_session *, int, struct mbuf *);
     68   1.1   gdamore static void rfcomm_session_recv_mcc_rpn(struct rfcomm_session *, int, struct mbuf *);
     69   1.1   gdamore static void rfcomm_session_recv_mcc_rls(struct rfcomm_session *, int, struct mbuf *);
     70   1.1   gdamore static void rfcomm_session_recv_mcc_pn(struct rfcomm_session *, int, struct mbuf *);
     71   1.1   gdamore static void rfcomm_session_recv_mcc_nsc(struct rfcomm_session *, int, struct mbuf *);
     72   1.1   gdamore 
     73   1.1   gdamore /* L2CAP callbacks */
     74   1.1   gdamore static void rfcomm_session_connecting(void *);
     75   1.1   gdamore static void rfcomm_session_connected(void *);
     76   1.1   gdamore static void rfcomm_session_disconnected(void *, int);
     77   1.1   gdamore static void *rfcomm_session_newconn(void *, struct sockaddr_bt *, struct sockaddr_bt *);
     78   1.1   gdamore static void rfcomm_session_complete(void *, int);
     79   1.9    plunky static void rfcomm_session_linkmode(void *, int);
     80   1.1   gdamore static void rfcomm_session_input(void *, struct mbuf *);
     81   1.1   gdamore 
     82   1.1   gdamore static const struct btproto rfcomm_session_proto = {
     83   1.1   gdamore 	rfcomm_session_connecting,
     84   1.1   gdamore 	rfcomm_session_connected,
     85   1.1   gdamore 	rfcomm_session_disconnected,
     86   1.1   gdamore 	rfcomm_session_newconn,
     87   1.1   gdamore 	rfcomm_session_complete,
     88   1.9    plunky 	rfcomm_session_linkmode,
     89   1.9    plunky 	rfcomm_session_input,
     90   1.1   gdamore };
     91   1.1   gdamore 
     92   1.1   gdamore struct rfcomm_session_list
     93   1.1   gdamore 	rfcomm_session_active = LIST_HEAD_INITIALIZER(rfcomm_session_active);
     94   1.1   gdamore 
     95   1.1   gdamore struct rfcomm_session_list
     96   1.1   gdamore 	rfcomm_session_listen = LIST_HEAD_INITIALIZER(rfcomm_session_listen);
     97   1.1   gdamore 
     98  1.15     pooka static struct pool rfcomm_credit_pool;
     99   1.1   gdamore 
    100   1.1   gdamore /*
    101   1.1   gdamore  * RFCOMM System Parameters (see section 5.3)
    102   1.1   gdamore  */
    103   1.1   gdamore int rfcomm_mtu_default = 127;	/* bytes */
    104   1.1   gdamore int rfcomm_ack_timeout = 20;	/* seconds */
    105   1.1   gdamore int rfcomm_mcc_timeout = 20;	/* seconds */
    106   1.1   gdamore 
    107   1.1   gdamore /*
    108   1.1   gdamore  * Reversed CRC table as per TS 07.10 Annex B.3.5
    109   1.1   gdamore  */
    110   1.8    plunky static const uint8_t crctable[256] = {	/* reversed, 8-bit, poly=0x07 */
    111   1.1   gdamore 	0x00, 0x91, 0xe3, 0x72, 0x07, 0x96, 0xe4, 0x75,
    112   1.1   gdamore 	0x0e, 0x9f, 0xed, 0x7c, 0x09, 0x98, 0xea, 0x7b,
    113   1.1   gdamore 	0x1c, 0x8d, 0xff, 0x6e, 0x1b, 0x8a, 0xf8, 0x69,
    114   1.1   gdamore 	0x12, 0x83, 0xf1, 0x60, 0x15, 0x84, 0xf6, 0x67,
    115   1.1   gdamore 
    116   1.1   gdamore 	0x38, 0xa9, 0xdb, 0x4a, 0x3f, 0xae, 0xdc, 0x4d,
    117   1.1   gdamore 	0x36, 0xa7, 0xd5, 0x44, 0x31, 0xa0, 0xd2, 0x43,
    118   1.1   gdamore 	0x24, 0xb5, 0xc7, 0x56, 0x23, 0xb2, 0xc0, 0x51,
    119   1.1   gdamore 	0x2a, 0xbb, 0xc9, 0x58, 0x2d, 0xbc, 0xce, 0x5f,
    120   1.1   gdamore 
    121   1.1   gdamore 	0x70, 0xe1, 0x93, 0x02, 0x77, 0xe6, 0x94, 0x05,
    122   1.1   gdamore 	0x7e, 0xef, 0x9d, 0x0c, 0x79, 0xe8, 0x9a, 0x0b,
    123   1.1   gdamore 	0x6c, 0xfd, 0x8f, 0x1e, 0x6b, 0xfa, 0x88, 0x19,
    124   1.1   gdamore 	0x62, 0xf3, 0x81, 0x10, 0x65, 0xf4, 0x86, 0x17,
    125   1.1   gdamore 
    126   1.1   gdamore 	0x48, 0xd9, 0xab, 0x3a, 0x4f, 0xde, 0xac, 0x3d,
    127   1.1   gdamore 	0x46, 0xd7, 0xa5, 0x34, 0x41, 0xd0, 0xa2, 0x33,
    128   1.1   gdamore 	0x54, 0xc5, 0xb7, 0x26, 0x53, 0xc2, 0xb0, 0x21,
    129   1.1   gdamore 	0x5a, 0xcb, 0xb9, 0x28, 0x5d, 0xcc, 0xbe, 0x2f,
    130   1.1   gdamore 
    131   1.1   gdamore 	0xe0, 0x71, 0x03, 0x92, 0xe7, 0x76, 0x04, 0x95,
    132   1.1   gdamore 	0xee, 0x7f, 0x0d, 0x9c, 0xe9, 0x78, 0x0a, 0x9b,
    133   1.1   gdamore 	0xfc, 0x6d, 0x1f, 0x8e, 0xfb, 0x6a, 0x18, 0x89,
    134   1.1   gdamore 	0xf2, 0x63, 0x11, 0x80, 0xf5, 0x64, 0x16, 0x87,
    135   1.1   gdamore 
    136   1.1   gdamore 	0xd8, 0x49, 0x3b, 0xaa, 0xdf, 0x4e, 0x3c, 0xad,
    137   1.1   gdamore 	0xd6, 0x47, 0x35, 0xa4, 0xd1, 0x40, 0x32, 0xa3,
    138   1.1   gdamore 	0xc4, 0x55, 0x27, 0xb6, 0xc3, 0x52, 0x20, 0xb1,
    139   1.1   gdamore 	0xca, 0x5b, 0x29, 0xb8, 0xcd, 0x5c, 0x2e, 0xbf,
    140   1.1   gdamore 
    141   1.1   gdamore 	0x90, 0x01, 0x73, 0xe2, 0x97, 0x06, 0x74, 0xe5,
    142   1.1   gdamore 	0x9e, 0x0f, 0x7d, 0xec, 0x99, 0x08, 0x7a, 0xeb,
    143   1.1   gdamore 	0x8c, 0x1d, 0x6f, 0xfe, 0x8b, 0x1a, 0x68, 0xf9,
    144   1.1   gdamore 	0x82, 0x13, 0x61, 0xf0, 0x85, 0x14, 0x66, 0xf7,
    145   1.1   gdamore 
    146   1.1   gdamore 	0xa8, 0x39, 0x4b, 0xda, 0xaf, 0x3e, 0x4c, 0xdd,
    147   1.1   gdamore 	0xa6, 0x37, 0x45, 0xd4, 0xa1, 0x30, 0x42, 0xd3,
    148   1.1   gdamore 	0xb4, 0x25, 0x57, 0xc6, 0xb3, 0x22, 0x50, 0xc1,
    149   1.1   gdamore 	0xba, 0x2b, 0x59, 0xc8, 0xbd, 0x2c, 0x5e, 0xcf
    150   1.1   gdamore };
    151   1.1   gdamore 
    152   1.1   gdamore #define FCS(f, d)	crctable[(f) ^ (d)]
    153   1.1   gdamore 
    154  1.15     pooka void
    155  1.15     pooka rfcomm_init(void)
    156  1.15     pooka {
    157  1.15     pooka 
    158  1.15     pooka 	pool_init(&rfcomm_credit_pool, sizeof(struct rfcomm_credit),
    159  1.15     pooka 	    0, 0, 0, "rfcomm_credit", NULL, IPL_SOFTNET);
    160  1.15     pooka }
    161  1.15     pooka 
    162   1.1   gdamore /*
    163   1.1   gdamore  * rfcomm_session_alloc(list, sockaddr)
    164   1.1   gdamore  *
    165   1.1   gdamore  * allocate a new session and fill in the blanks, then
    166   1.1   gdamore  * attach session to front of specified list (active or listen)
    167   1.1   gdamore  */
    168   1.1   gdamore struct rfcomm_session *
    169   1.1   gdamore rfcomm_session_alloc(struct rfcomm_session_list *list,
    170   1.1   gdamore 			struct sockaddr_bt *laddr)
    171   1.1   gdamore {
    172   1.1   gdamore 	struct rfcomm_session *rs;
    173  1.14    plunky 	struct sockopt sopt;
    174   1.1   gdamore 	int err;
    175   1.1   gdamore 
    176   1.1   gdamore 	rs = malloc(sizeof(*rs), M_BLUETOOTH, M_NOWAIT | M_ZERO);
    177   1.1   gdamore 	if (rs == NULL)
    178   1.1   gdamore 		return NULL;
    179   1.1   gdamore 
    180   1.1   gdamore 	rs->rs_state = RFCOMM_SESSION_CLOSED;
    181   1.1   gdamore 
    182  1.10        ad 	callout_init(&rs->rs_timeout, 0);
    183   1.1   gdamore 	callout_setfunc(&rs->rs_timeout, rfcomm_session_timeout, rs);
    184   1.1   gdamore 
    185   1.1   gdamore 	SIMPLEQ_INIT(&rs->rs_credits);
    186   1.1   gdamore 	LIST_INIT(&rs->rs_dlcs);
    187   1.1   gdamore 
    188  1.19     rmind 	err = l2cap_attach_pcb(&rs->rs_l2cap, &rfcomm_session_proto, rs);
    189   1.1   gdamore 	if (err) {
    190   1.1   gdamore 		free(rs, M_BLUETOOTH);
    191   1.1   gdamore 		return NULL;
    192   1.1   gdamore 	}
    193   1.1   gdamore 
    194  1.14    plunky 	sockopt_init(&sopt, BTPROTO_L2CAP, SO_L2CAP_OMTU, 0);
    195  1.14    plunky 	(void)l2cap_getopt(rs->rs_l2cap, &sopt);
    196  1.14    plunky 	(void)sockopt_get(&sopt, &rs->rs_mtu, sizeof(rs->rs_mtu));
    197  1.14    plunky 	sockopt_destroy(&sopt);
    198   1.1   gdamore 
    199   1.1   gdamore 	if (laddr->bt_psm == L2CAP_PSM_ANY)
    200   1.1   gdamore 		laddr->bt_psm = L2CAP_PSM_RFCOMM;
    201   1.1   gdamore 
    202  1.21       rtr 	(void)l2cap_bind_pcb(rs->rs_l2cap, laddr);
    203   1.1   gdamore 
    204   1.1   gdamore 	LIST_INSERT_HEAD(list, rs, rs_next);
    205   1.1   gdamore 
    206   1.1   gdamore 	return rs;
    207   1.1   gdamore }
    208   1.1   gdamore 
    209   1.1   gdamore /*
    210   1.1   gdamore  * rfcomm_session_free(rfcomm_session)
    211   1.1   gdamore  *
    212   1.1   gdamore  * release a session, including any cleanup
    213   1.1   gdamore  */
    214   1.1   gdamore void
    215   1.1   gdamore rfcomm_session_free(struct rfcomm_session *rs)
    216   1.1   gdamore {
    217   1.1   gdamore 	struct rfcomm_credit *credit;
    218   1.1   gdamore 
    219   1.1   gdamore 	KASSERT(rs != NULL);
    220   1.1   gdamore 	KASSERT(LIST_EMPTY(&rs->rs_dlcs));
    221   1.1   gdamore 
    222   1.1   gdamore 	rs->rs_state = RFCOMM_SESSION_CLOSED;
    223   1.1   gdamore 
    224   1.1   gdamore 	/*
    225   1.1   gdamore 	 * If the callout is already invoked we have no way to stop it,
    226   1.1   gdamore 	 * but it will call us back right away (there are no DLC's) so
    227   1.1   gdamore 	 * not to worry.
    228   1.1   gdamore 	 */
    229   1.1   gdamore 	callout_stop(&rs->rs_timeout);
    230   1.1   gdamore 	if (callout_invoking(&rs->rs_timeout))
    231   1.1   gdamore 		return;
    232   1.1   gdamore 
    233   1.1   gdamore 	/*
    234   1.1   gdamore 	 * Take care that rfcomm_session_disconnected() doesnt call
    235   1.1   gdamore 	 * us back either as it will do if the l2cap_channel has not
    236   1.1   gdamore 	 * been closed when we detach it..
    237   1.1   gdamore 	 */
    238   1.1   gdamore 	if (rs->rs_flags & RFCOMM_SESSION_FREE)
    239   1.1   gdamore 		return;
    240   1.1   gdamore 
    241   1.1   gdamore 	rs->rs_flags |= RFCOMM_SESSION_FREE;
    242   1.1   gdamore 
    243   1.1   gdamore 	/* throw away any remaining credit notes */
    244   1.1   gdamore 	while ((credit = SIMPLEQ_FIRST(&rs->rs_credits)) != NULL) {
    245   1.1   gdamore 		SIMPLEQ_REMOVE_HEAD(&rs->rs_credits, rc_next);
    246   1.1   gdamore 		pool_put(&rfcomm_credit_pool, credit);
    247   1.1   gdamore 	}
    248   1.1   gdamore 
    249   1.1   gdamore 	KASSERT(SIMPLEQ_EMPTY(&rs->rs_credits));
    250   1.1   gdamore 
    251   1.1   gdamore 	/* Goodbye! */
    252   1.1   gdamore 	LIST_REMOVE(rs, rs_next);
    253  1.19     rmind 	l2cap_detach_pcb(&rs->rs_l2cap);
    254  1.12    plunky 	callout_destroy(&rs->rs_timeout);
    255   1.1   gdamore 	free(rs, M_BLUETOOTH);
    256   1.1   gdamore }
    257   1.1   gdamore 
    258   1.1   gdamore /*
    259   1.1   gdamore  * rfcomm_session_lookup(sockaddr, sockaddr)
    260   1.1   gdamore  *
    261   1.1   gdamore  * Find active rfcomm session matching src and dest addresses
    262   1.1   gdamore  * when src is BDADDR_ANY match any local address
    263   1.1   gdamore  */
    264   1.1   gdamore struct rfcomm_session *
    265   1.1   gdamore rfcomm_session_lookup(struct sockaddr_bt *src, struct sockaddr_bt *dest)
    266   1.1   gdamore {
    267   1.1   gdamore 	struct rfcomm_session *rs;
    268   1.1   gdamore 	struct sockaddr_bt addr;
    269   1.1   gdamore 
    270   1.1   gdamore 	LIST_FOREACH(rs, &rfcomm_session_active, rs_next) {
    271   1.1   gdamore 		if (rs->rs_state == RFCOMM_SESSION_CLOSED)
    272   1.1   gdamore 			continue;
    273   1.1   gdamore 
    274  1.20       rtr 		l2cap_sockaddr_pcb(rs->rs_l2cap, &addr);
    275   1.1   gdamore 
    276   1.1   gdamore 		if (bdaddr_same(&src->bt_bdaddr, &addr.bt_bdaddr) == 0)
    277   1.1   gdamore 			if (bdaddr_any(&src->bt_bdaddr) == 0)
    278   1.1   gdamore 				continue;
    279   1.1   gdamore 
    280  1.20       rtr 		l2cap_peeraddr_pcb(rs->rs_l2cap, &addr);
    281   1.1   gdamore 
    282   1.1   gdamore 		if (addr.bt_psm != dest->bt_psm)
    283   1.1   gdamore 			continue;
    284   1.1   gdamore 
    285   1.1   gdamore 		if (bdaddr_same(&dest->bt_bdaddr, &addr.bt_bdaddr))
    286   1.1   gdamore 			break;
    287   1.1   gdamore 	}
    288   1.1   gdamore 
    289   1.1   gdamore 	return rs;
    290   1.1   gdamore }
    291   1.1   gdamore 
    292   1.1   gdamore /*
    293   1.1   gdamore  * rfcomm_session_timeout(rfcomm_session)
    294   1.1   gdamore  *
    295   1.1   gdamore  * Session timeouts are scheduled when a session is left or
    296   1.1   gdamore  * created with no DLCs, and when SABM(0) or DISC(0) are
    297   1.1   gdamore  * sent.
    298   1.1   gdamore  *
    299   1.1   gdamore  * So, if it is in an open state with DLC's attached then
    300   1.1   gdamore  * we leave it alone, otherwise the session is lost.
    301   1.1   gdamore  */
    302   1.1   gdamore static void
    303   1.1   gdamore rfcomm_session_timeout(void *arg)
    304   1.1   gdamore {
    305   1.1   gdamore 	struct rfcomm_session *rs = arg;
    306   1.1   gdamore 	struct rfcomm_dlc *dlc;
    307   1.1   gdamore 
    308   1.1   gdamore 	KASSERT(rs != NULL);
    309   1.1   gdamore 
    310  1.13        ad 	mutex_enter(bt_lock);
    311   1.1   gdamore 	callout_ack(&rs->rs_timeout);
    312   1.1   gdamore 
    313   1.1   gdamore 	if (rs->rs_state != RFCOMM_SESSION_OPEN) {
    314   1.1   gdamore 		DPRINTF("timeout\n");
    315   1.1   gdamore 		rs->rs_state = RFCOMM_SESSION_CLOSED;
    316   1.1   gdamore 
    317   1.1   gdamore 		while (!LIST_EMPTY(&rs->rs_dlcs)) {
    318   1.1   gdamore 			dlc = LIST_FIRST(&rs->rs_dlcs);
    319   1.1   gdamore 
    320   1.1   gdamore 			rfcomm_dlc_close(dlc, ETIMEDOUT);
    321   1.1   gdamore 		}
    322   1.1   gdamore 	}
    323   1.1   gdamore 
    324   1.1   gdamore 	if (LIST_EMPTY(&rs->rs_dlcs)) {
    325   1.1   gdamore 		DPRINTF("expiring\n");
    326   1.1   gdamore 		rfcomm_session_free(rs);
    327   1.1   gdamore 	}
    328  1.13        ad 	mutex_exit(bt_lock);
    329   1.1   gdamore }
    330   1.1   gdamore 
    331   1.1   gdamore /***********************************************************************
    332   1.1   gdamore  *
    333   1.1   gdamore  *	RFCOMM Session L2CAP protocol callbacks
    334   1.1   gdamore  *
    335   1.1   gdamore  */
    336   1.1   gdamore 
    337   1.1   gdamore static void
    338   1.4  christos rfcomm_session_connecting(void *arg)
    339   1.1   gdamore {
    340   1.7    plunky 	/* struct rfcomm_session *rs = arg; */
    341   1.1   gdamore 
    342   1.1   gdamore 	DPRINTF("Connecting\n");
    343   1.1   gdamore }
    344   1.1   gdamore 
    345   1.1   gdamore static void
    346   1.1   gdamore rfcomm_session_connected(void *arg)
    347   1.1   gdamore {
    348   1.1   gdamore 	struct rfcomm_session *rs = arg;
    349  1.14    plunky 	struct sockopt sopt;
    350   1.1   gdamore 
    351   1.1   gdamore 	DPRINTF("Connected\n");
    352   1.1   gdamore 
    353   1.1   gdamore 	/*
    354   1.1   gdamore 	 * L2CAP is open.
    355   1.1   gdamore 	 *
    356   1.1   gdamore 	 * If we are initiator, we can send our SABM(0)
    357   1.1   gdamore 	 * a timeout should be active?
    358   1.1   gdamore 	 *
    359   1.1   gdamore 	 * We must take note of the L2CAP MTU because currently
    360   1.1   gdamore 	 * the L2CAP implementation can only do Basic Mode.
    361   1.1   gdamore 	 */
    362  1.14    plunky 	sockopt_init(&sopt, BTPROTO_L2CAP, SO_L2CAP_OMTU, 0);
    363  1.14    plunky 	(void)l2cap_getopt(rs->rs_l2cap, &sopt);
    364  1.14    plunky 	(void)sockopt_get(&sopt, &rs->rs_mtu, sizeof(rs->rs_mtu));
    365  1.14    plunky 	sockopt_destroy(&sopt);
    366   1.1   gdamore 
    367   1.1   gdamore 	rs->rs_mtu -= 6; /* (RFCOMM overhead could be this big) */
    368   1.1   gdamore 	if (rs->rs_mtu < RFCOMM_MTU_MIN) {
    369   1.1   gdamore 		rfcomm_session_disconnected(rs, EINVAL);
    370   1.1   gdamore 		return;
    371   1.1   gdamore 	}
    372   1.1   gdamore 
    373   1.1   gdamore 	if (IS_INITIATOR(rs)) {
    374   1.1   gdamore 		int err;
    375   1.1   gdamore 
    376   1.1   gdamore 		err = rfcomm_session_send_frame(rs, RFCOMM_FRAME_SABM, 0);
    377   1.1   gdamore 		if (err)
    378   1.1   gdamore 			rfcomm_session_disconnected(rs, err);
    379   1.1   gdamore 
    380   1.1   gdamore 		callout_schedule(&rs->rs_timeout, rfcomm_ack_timeout * hz);
    381   1.1   gdamore 	}
    382   1.1   gdamore }
    383   1.1   gdamore 
    384   1.1   gdamore static void
    385   1.1   gdamore rfcomm_session_disconnected(void *arg, int err)
    386   1.1   gdamore {
    387   1.1   gdamore 	struct rfcomm_session *rs = arg;
    388   1.1   gdamore 	struct rfcomm_dlc *dlc;
    389   1.1   gdamore 
    390   1.1   gdamore 	DPRINTF("Disconnected\n");
    391   1.1   gdamore 
    392  1.17    plunky 	/*
    393  1.17    plunky 	 * If we have any DLCs outstanding in the unlikely case that the
    394  1.17    plunky 	 * L2CAP channel disconnected normally, close them with an error
    395  1.17    plunky 	 */
    396  1.17    plunky 	if (err == 0)
    397  1.17    plunky 		err = ECONNRESET;
    398  1.17    plunky 
    399   1.1   gdamore 	rs->rs_state = RFCOMM_SESSION_CLOSED;
    400   1.1   gdamore 
    401   1.1   gdamore 	while (!LIST_EMPTY(&rs->rs_dlcs)) {
    402   1.1   gdamore 		dlc = LIST_FIRST(&rs->rs_dlcs);
    403   1.1   gdamore 
    404   1.1   gdamore 		rfcomm_dlc_close(dlc, err);
    405   1.1   gdamore 	}
    406   1.1   gdamore 
    407   1.1   gdamore 	rfcomm_session_free(rs);
    408   1.1   gdamore }
    409   1.1   gdamore 
    410   1.1   gdamore static void *
    411   1.1   gdamore rfcomm_session_newconn(void *arg, struct sockaddr_bt *laddr,
    412   1.1   gdamore 				struct sockaddr_bt *raddr)
    413   1.1   gdamore {
    414   1.1   gdamore 	struct rfcomm_session *new, *rs = arg;
    415   1.1   gdamore 
    416   1.1   gdamore 	DPRINTF("New Connection\n");
    417   1.1   gdamore 
    418   1.1   gdamore 	/*
    419   1.1   gdamore 	 * Incoming session connect request. We should return a new
    420   1.1   gdamore 	 * session pointer if this is acceptable. The L2CAP layer
    421   1.1   gdamore 	 * passes local and remote addresses, which we must check as
    422   1.1   gdamore 	 * only one RFCOMM session is allowed between any two devices
    423   1.1   gdamore 	 */
    424   1.1   gdamore 	new = rfcomm_session_lookup(laddr, raddr);
    425   1.1   gdamore 	if (new != NULL)
    426   1.1   gdamore 		return NULL;
    427   1.1   gdamore 
    428   1.1   gdamore 	new = rfcomm_session_alloc(&rfcomm_session_active, laddr);
    429   1.1   gdamore 	if (new == NULL)
    430   1.1   gdamore 		return NULL;
    431   1.1   gdamore 
    432   1.1   gdamore 	new->rs_mtu = rs->rs_mtu;
    433   1.1   gdamore 	new->rs_state = RFCOMM_SESSION_WAIT_CONNECT;
    434   1.1   gdamore 
    435   1.1   gdamore 	/*
    436   1.1   gdamore 	 * schedule an expiry so that if nothing comes of it we
    437   1.1   gdamore 	 * can punt.
    438   1.1   gdamore 	 */
    439   1.1   gdamore 	callout_schedule(&new->rs_timeout, rfcomm_mcc_timeout * hz);
    440   1.1   gdamore 
    441   1.1   gdamore 	return new->rs_l2cap;
    442   1.1   gdamore }
    443   1.1   gdamore 
    444   1.1   gdamore static void
    445   1.1   gdamore rfcomm_session_complete(void *arg, int count)
    446   1.1   gdamore {
    447   1.1   gdamore 	struct rfcomm_session *rs = arg;
    448   1.1   gdamore 	struct rfcomm_credit *credit;
    449   1.1   gdamore 	struct rfcomm_dlc *dlc;
    450   1.1   gdamore 
    451   1.1   gdamore 	/*
    452   1.1   gdamore 	 * count L2CAP packets are 'complete', meaning that they are cleared
    453   1.1   gdamore 	 * our buffers (for best effort) or arrived safe (for guaranteed) so
    454   1.1   gdamore 	 * we can take it off our list and pass the message on, so that
    455   1.1   gdamore 	 * eventually the data can be removed from the sockbuf
    456   1.1   gdamore 	 */
    457   1.1   gdamore 	while (count-- > 0) {
    458   1.1   gdamore 		credit = SIMPLEQ_FIRST(&rs->rs_credits);
    459   1.1   gdamore 		if (credit == NULL) {
    460   1.1   gdamore 			printf("%s: too many packets completed!\n", __func__);
    461   1.1   gdamore 			break;
    462   1.1   gdamore 		}
    463  1.18    plunky 
    464   1.1   gdamore 		dlc = credit->rc_dlc;
    465   1.1   gdamore 		if (dlc != NULL) {
    466   1.1   gdamore 			dlc->rd_pending--;
    467   1.1   gdamore 			(*dlc->rd_proto->complete)
    468   1.1   gdamore 					(dlc->rd_upper, credit->rc_len);
    469   1.1   gdamore 
    470   1.1   gdamore 			/*
    471   1.1   gdamore 			 * if not using credit flow control, we may push
    472   1.1   gdamore 			 * more data now
    473   1.1   gdamore 			 */
    474   1.1   gdamore 			if ((rs->rs_flags & RFCOMM_SESSION_CFC) == 0
    475   1.1   gdamore 			    && dlc->rd_state == RFCOMM_DLC_OPEN) {
    476   1.1   gdamore 				rfcomm_dlc_start(dlc);
    477   1.1   gdamore 			}
    478   1.1   gdamore 
    479   1.1   gdamore 			/*
    480   1.1   gdamore 			 * When shutdown is indicated, we are just waiting to
    481   1.1   gdamore 			 * clear outgoing data.
    482   1.1   gdamore 			 */
    483   1.1   gdamore 			if ((dlc->rd_flags & RFCOMM_DLC_SHUTDOWN)
    484   1.1   gdamore 			    && dlc->rd_txbuf == NULL && dlc->rd_pending == 0) {
    485   1.1   gdamore 				dlc->rd_state = RFCOMM_DLC_WAIT_DISCONNECT;
    486   1.1   gdamore 				rfcomm_session_send_frame(rs, RFCOMM_FRAME_DISC,
    487   1.1   gdamore 							    dlc->rd_dlci);
    488   1.1   gdamore 				callout_schedule(&dlc->rd_timeout,
    489   1.1   gdamore 						    rfcomm_ack_timeout * hz);
    490   1.1   gdamore 			}
    491   1.1   gdamore 		}
    492   1.1   gdamore 
    493   1.1   gdamore 		SIMPLEQ_REMOVE_HEAD(&rs->rs_credits, rc_next);
    494   1.1   gdamore 		pool_put(&rfcomm_credit_pool, credit);
    495   1.1   gdamore 	}
    496   1.1   gdamore 
    497   1.1   gdamore 	/*
    498   1.1   gdamore 	 * If session is closed, we are just waiting to clear the queue
    499   1.1   gdamore 	 */
    500   1.1   gdamore 	if (rs->rs_state == RFCOMM_SESSION_CLOSED) {
    501   1.1   gdamore 		if (SIMPLEQ_EMPTY(&rs->rs_credits))
    502  1.22       rtr 			l2cap_disconnect_pcb(rs->rs_l2cap, 0);
    503   1.1   gdamore 	}
    504   1.1   gdamore }
    505   1.1   gdamore 
    506   1.1   gdamore /*
    507   1.9    plunky  * Link Mode changed
    508   1.9    plunky  *
    509   1.9    plunky  * This is called when a mode change is complete. Proceed with connections
    510   1.9    plunky  * where appropriate, or pass the new mode to any active DLCs.
    511   1.9    plunky  */
    512   1.9    plunky static void
    513   1.9    plunky rfcomm_session_linkmode(void *arg, int new)
    514   1.9    plunky {
    515   1.9    plunky 	struct rfcomm_session *rs = arg;
    516   1.9    plunky 	struct rfcomm_dlc *dlc, *next;
    517   1.9    plunky 	int err, mode = 0;
    518   1.9    plunky 
    519   1.9    plunky 	DPRINTF("auth %s, encrypt %s, secure %s\n",
    520   1.9    plunky 		(new & L2CAP_LM_AUTH ? "on" : "off"),
    521   1.9    plunky 		(new & L2CAP_LM_ENCRYPT ? "on" : "off"),
    522   1.9    plunky 		(new & L2CAP_LM_SECURE ? "on" : "off"));
    523   1.9    plunky 
    524   1.9    plunky 	if (new & L2CAP_LM_AUTH)
    525   1.9    plunky 		mode |= RFCOMM_LM_AUTH;
    526   1.9    plunky 
    527   1.9    plunky 	if (new & L2CAP_LM_ENCRYPT)
    528   1.9    plunky 		mode |= RFCOMM_LM_ENCRYPT;
    529   1.9    plunky 
    530   1.9    plunky 	if (new & L2CAP_LM_SECURE)
    531   1.9    plunky 		mode |= RFCOMM_LM_SECURE;
    532   1.9    plunky 
    533   1.9    plunky 	next = LIST_FIRST(&rs->rs_dlcs);
    534   1.9    plunky 	while ((dlc = next) != NULL) {
    535   1.9    plunky 		next = LIST_NEXT(dlc, rd_next);
    536   1.9    plunky 
    537   1.9    plunky 		switch (dlc->rd_state) {
    538   1.9    plunky 		case RFCOMM_DLC_WAIT_SEND_SABM:	/* we are connecting */
    539   1.9    plunky 			if ((mode & dlc->rd_mode) != dlc->rd_mode) {
    540   1.9    plunky 				rfcomm_dlc_close(dlc, ECONNABORTED);
    541   1.9    plunky 			} else {
    542   1.9    plunky 				err = rfcomm_session_send_frame(rs,
    543   1.9    plunky 					    RFCOMM_FRAME_SABM, dlc->rd_dlci);
    544   1.9    plunky 				if (err) {
    545   1.9    plunky 					rfcomm_dlc_close(dlc, err);
    546   1.9    plunky 				} else {
    547   1.9    plunky 					dlc->rd_state = RFCOMM_DLC_WAIT_RECV_UA;
    548   1.9    plunky 					callout_schedule(&dlc->rd_timeout,
    549   1.9    plunky 							rfcomm_ack_timeout * hz);
    550   1.9    plunky 					break;
    551   1.9    plunky 				}
    552   1.9    plunky 			}
    553   1.9    plunky 
    554   1.9    plunky 			/*
    555   1.9    plunky 			 * If we aborted the connection and there are no more DLCs
    556   1.9    plunky 			 * on the session, it is our responsibility to disconnect.
    557   1.9    plunky 			 */
    558   1.9    plunky 			if (!LIST_EMPTY(&rs->rs_dlcs))
    559   1.9    plunky 				break;
    560   1.9    plunky 
    561   1.9    plunky 			rs->rs_state = RFCOMM_SESSION_WAIT_DISCONNECT;
    562   1.9    plunky 			rfcomm_session_send_frame(rs, RFCOMM_FRAME_DISC, 0);
    563   1.9    plunky 			callout_schedule(&rs->rs_timeout, rfcomm_ack_timeout * hz);
    564   1.9    plunky 			break;
    565   1.9    plunky 
    566   1.9    plunky 		case RFCOMM_DLC_WAIT_SEND_UA: /* they are connecting */
    567   1.9    plunky 			if ((mode & dlc->rd_mode) != dlc->rd_mode) {
    568   1.9    plunky 				rfcomm_session_send_frame(rs,
    569   1.9    plunky 					    RFCOMM_FRAME_DM, dlc->rd_dlci);
    570   1.9    plunky 				rfcomm_dlc_close(dlc, ECONNABORTED);
    571   1.9    plunky 				break;
    572   1.9    plunky 			}
    573   1.9    plunky 
    574   1.9    plunky 			err = rfcomm_session_send_frame(rs,
    575   1.9    plunky 					    RFCOMM_FRAME_UA, dlc->rd_dlci);
    576   1.9    plunky 			if (err) {
    577   1.9    plunky 				rfcomm_session_send_frame(rs,
    578   1.9    plunky 						RFCOMM_FRAME_DM, dlc->rd_dlci);
    579   1.9    plunky 				rfcomm_dlc_close(dlc, err);
    580   1.9    plunky 				break;
    581   1.9    plunky 			}
    582   1.9    plunky 
    583   1.9    plunky 			err = rfcomm_dlc_open(dlc);
    584   1.9    plunky 			if (err) {
    585   1.9    plunky 				rfcomm_session_send_frame(rs,
    586   1.9    plunky 						RFCOMM_FRAME_DM, dlc->rd_dlci);
    587   1.9    plunky 				rfcomm_dlc_close(dlc, err);
    588   1.9    plunky 				break;
    589   1.9    plunky 			}
    590   1.9    plunky 
    591   1.9    plunky 			break;
    592   1.9    plunky 
    593   1.9    plunky 		case RFCOMM_DLC_WAIT_RECV_UA:
    594   1.9    plunky 		case RFCOMM_DLC_OPEN: /* already established */
    595   1.9    plunky 			(*dlc->rd_proto->linkmode)(dlc->rd_upper, mode);
    596   1.9    plunky 			break;
    597   1.9    plunky 
    598   1.9    plunky 		default:
    599   1.9    plunky 			break;
    600   1.9    plunky 		}
    601   1.9    plunky 	}
    602   1.9    plunky }
    603   1.9    plunky 
    604   1.9    plunky /*
    605   1.1   gdamore  * Receive data from L2CAP layer for session. There is always exactly one
    606   1.1   gdamore  * RFCOMM frame contained in each L2CAP frame.
    607   1.1   gdamore  */
    608   1.1   gdamore static void
    609   1.1   gdamore rfcomm_session_input(void *arg, struct mbuf *m)
    610   1.1   gdamore {
    611   1.1   gdamore 	struct rfcomm_session *rs = arg;
    612   1.1   gdamore 	int dlci, len, type, pf;
    613   1.1   gdamore 	uint8_t fcs, b;
    614   1.1   gdamore 
    615   1.1   gdamore 	KASSERT(m != NULL);
    616   1.1   gdamore 	KASSERT(rs != NULL);
    617   1.1   gdamore 
    618   1.1   gdamore 	/*
    619   1.1   gdamore 	 * UIH frames: FCS is only calculated on address and control fields
    620   1.1   gdamore 	 * For other frames: FCS is calculated on address, control and length
    621   1.1   gdamore 	 * Length may extend to two octets
    622   1.1   gdamore 	 */
    623   1.1   gdamore 	fcs = 0xff;
    624   1.1   gdamore 
    625   1.1   gdamore 	if (m->m_pkthdr.len < 4) {
    626   1.1   gdamore 		DPRINTF("short frame (%d), discarded\n", m->m_pkthdr.len);
    627   1.1   gdamore 		goto done;
    628   1.1   gdamore 	}
    629   1.1   gdamore 
    630   1.1   gdamore 	/* address - one octet */
    631   1.1   gdamore 	m_copydata(m, 0, 1, &b);
    632   1.1   gdamore 	m_adj(m, 1);
    633   1.1   gdamore 	fcs = FCS(fcs, b);
    634   1.1   gdamore 	dlci = RFCOMM_DLCI(b);
    635   1.1   gdamore 
    636   1.1   gdamore 	/* control - one octet */
    637   1.1   gdamore 	m_copydata(m, 0, 1, &b);
    638   1.1   gdamore 	m_adj(m, 1);
    639   1.1   gdamore 	fcs = FCS(fcs, b);
    640   1.1   gdamore 	type = RFCOMM_TYPE(b);
    641   1.1   gdamore 	pf = RFCOMM_PF(b);
    642   1.1   gdamore 
    643   1.1   gdamore 	/* length - may be two octets */
    644   1.1   gdamore 	m_copydata(m, 0, 1, &b);
    645   1.1   gdamore 	m_adj(m, 1);
    646   1.1   gdamore 	if (type != RFCOMM_FRAME_UIH)
    647   1.1   gdamore 		fcs = FCS(fcs, b);
    648   1.1   gdamore 	len = (b >> 1) & 0x7f;
    649   1.1   gdamore 
    650   1.1   gdamore 	if (RFCOMM_EA(b) == 0) {
    651   1.1   gdamore 		if (m->m_pkthdr.len < 2) {
    652   1.1   gdamore 			DPRINTF("short frame (%d, EA = 0), discarded\n",
    653   1.1   gdamore 				m->m_pkthdr.len);
    654   1.1   gdamore 			goto done;
    655   1.1   gdamore 		}
    656   1.1   gdamore 
    657   1.1   gdamore 		m_copydata(m, 0, 1, &b);
    658   1.1   gdamore 		m_adj(m, 1);
    659   1.1   gdamore 		if (type != RFCOMM_FRAME_UIH)
    660   1.1   gdamore 			fcs = FCS(fcs, b);
    661   1.1   gdamore 
    662   1.1   gdamore 		len |= (b << 7);
    663   1.1   gdamore 	}
    664   1.1   gdamore 
    665   1.1   gdamore 	/* FCS byte is last octet in frame */
    666   1.1   gdamore 	m_copydata(m, m->m_pkthdr.len - 1, 1, &b);
    667   1.1   gdamore 	m_adj(m, -1);
    668   1.1   gdamore 	fcs = FCS(fcs, b);
    669   1.1   gdamore 
    670   1.1   gdamore 	if (fcs != 0xcf) {
    671   1.1   gdamore 		DPRINTF("Bad FCS value (%#2.2x), frame discarded\n", fcs);
    672   1.1   gdamore 		goto done;
    673   1.1   gdamore 	}
    674   1.1   gdamore 
    675   1.1   gdamore 	DPRINTFN(10, "dlci %d, type %2.2x, len = %d\n", dlci, type, len);
    676   1.1   gdamore 
    677   1.1   gdamore 	switch (type) {
    678   1.1   gdamore 	case RFCOMM_FRAME_SABM:
    679   1.1   gdamore 		if (pf)
    680   1.1   gdamore 			rfcomm_session_recv_sabm(rs, dlci);
    681   1.1   gdamore 		break;
    682   1.1   gdamore 
    683   1.1   gdamore 	case RFCOMM_FRAME_DISC:
    684   1.1   gdamore 		if (pf)
    685   1.1   gdamore 			rfcomm_session_recv_disc(rs, dlci);
    686   1.1   gdamore 		break;
    687   1.1   gdamore 
    688   1.1   gdamore 	case RFCOMM_FRAME_UA:
    689   1.1   gdamore 		if (pf)
    690   1.1   gdamore 			rfcomm_session_recv_ua(rs, dlci);
    691   1.1   gdamore 		break;
    692   1.1   gdamore 
    693   1.1   gdamore 	case RFCOMM_FRAME_DM:
    694   1.1   gdamore 		rfcomm_session_recv_dm(rs, dlci);
    695   1.1   gdamore 		break;
    696   1.1   gdamore 
    697   1.1   gdamore 	case RFCOMM_FRAME_UIH:
    698   1.1   gdamore 		rfcomm_session_recv_uih(rs, dlci, pf, m, len);
    699   1.1   gdamore 		return;	/* (no release) */
    700   1.1   gdamore 
    701   1.1   gdamore 	default:
    702   1.1   gdamore 		UNKNOWN(type);
    703   1.1   gdamore 		break;
    704   1.1   gdamore 	}
    705   1.1   gdamore 
    706   1.1   gdamore done:
    707   1.1   gdamore 	m_freem(m);
    708   1.1   gdamore }
    709   1.1   gdamore 
    710   1.1   gdamore /***********************************************************************
    711   1.1   gdamore  *
    712   1.1   gdamore  *	RFCOMM Session receive processing
    713   1.1   gdamore  */
    714   1.1   gdamore 
    715   1.1   gdamore /*
    716   1.1   gdamore  * rfcomm_session_recv_sabm(rfcomm_session, dlci)
    717   1.1   gdamore  *
    718   1.1   gdamore  * Set Asyncrhonous Balanced Mode - open the channel.
    719   1.1   gdamore  */
    720   1.1   gdamore static void
    721   1.1   gdamore rfcomm_session_recv_sabm(struct rfcomm_session *rs, int dlci)
    722   1.1   gdamore {
    723   1.1   gdamore 	struct rfcomm_dlc *dlc;
    724   1.1   gdamore 	int err;
    725   1.1   gdamore 
    726   1.1   gdamore 	DPRINTFN(5, "SABM(%d)\n", dlci);
    727   1.1   gdamore 
    728   1.1   gdamore 	if (dlci == 0) {	/* Open Session */
    729   1.1   gdamore 		rs->rs_state = RFCOMM_SESSION_OPEN;
    730   1.1   gdamore 		rfcomm_session_send_frame(rs, RFCOMM_FRAME_UA, 0);
    731   1.1   gdamore 		LIST_FOREACH(dlc, &rs->rs_dlcs, rd_next) {
    732   1.1   gdamore 			if (dlc->rd_state == RFCOMM_DLC_WAIT_SESSION)
    733   1.1   gdamore 				rfcomm_dlc_connect(dlc);
    734   1.1   gdamore 		}
    735   1.1   gdamore 		return;
    736   1.1   gdamore 	}
    737   1.1   gdamore 
    738   1.1   gdamore 	if (rs->rs_state != RFCOMM_SESSION_OPEN) {
    739   1.1   gdamore 		DPRINTF("session was not even open!\n");
    740   1.1   gdamore 		return;
    741   1.1   gdamore 	}
    742   1.1   gdamore 
    743   1.1   gdamore 	/* validate direction bit */
    744   1.1   gdamore 	if ((IS_INITIATOR(rs) && !RFCOMM_DIRECTION(dlci))
    745   1.1   gdamore 	    || (!IS_INITIATOR(rs) && RFCOMM_DIRECTION(dlci))) {
    746   1.1   gdamore 		DPRINTF("Invalid direction bit on DLCI\n");
    747   1.1   gdamore 		return;
    748   1.1   gdamore 	}
    749   1.1   gdamore 
    750   1.1   gdamore 	/*
    751   1.1   gdamore 	 * look for our DLC - this may exist if we received PN
    752   1.1   gdamore 	 * already, or we may have to fabricate a new one.
    753   1.1   gdamore 	 */
    754   1.1   gdamore 	dlc = rfcomm_dlc_lookup(rs, dlci);
    755   1.1   gdamore 	if (dlc == NULL) {
    756   1.1   gdamore 		dlc = rfcomm_dlc_newconn(rs, dlci);
    757   1.1   gdamore 		if (dlc == NULL)
    758   1.1   gdamore 			return;	/* (DM is sent) */
    759   1.1   gdamore 	}
    760   1.1   gdamore 
    761   1.9    plunky 	/*
    762   1.9    plunky 	 * ..but if this DLC is not waiting to connect, they did
    763   1.9    plunky 	 * something wrong, ignore it.
    764   1.9    plunky 	 */
    765   1.9    plunky 	if (dlc->rd_state != RFCOMM_DLC_WAIT_CONNECT)
    766   1.9    plunky 		return;
    767   1.1   gdamore 
    768   1.9    plunky 	/* set link mode */
    769   1.9    plunky 	err = rfcomm_dlc_setmode(dlc);
    770   1.9    plunky 	if (err == EINPROGRESS) {
    771   1.9    plunky 		dlc->rd_state = RFCOMM_DLC_WAIT_SEND_UA;
    772   1.9    plunky 		(*dlc->rd_proto->connecting)(dlc->rd_upper);
    773   1.1   gdamore 		return;
    774   1.1   gdamore 	}
    775   1.9    plunky 	if (err)
    776   1.9    plunky 		goto close;
    777   1.1   gdamore 
    778   1.9    plunky 	err = rfcomm_session_send_frame(rs, RFCOMM_FRAME_UA, dlci);
    779   1.9    plunky 	if (err)
    780   1.9    plunky 		goto close;
    781   1.9    plunky 
    782   1.9    plunky 	/* and mark it open */
    783   1.9    plunky 	err = rfcomm_dlc_open(dlc);
    784   1.9    plunky 	if (err)
    785   1.9    plunky 		goto close;
    786   1.1   gdamore 
    787   1.9    plunky 	return;
    788   1.1   gdamore 
    789   1.9    plunky close:
    790   1.9    plunky 	rfcomm_dlc_close(dlc, err);
    791   1.1   gdamore }
    792   1.1   gdamore 
    793   1.1   gdamore /*
    794   1.1   gdamore  * Receive Disconnect Command
    795   1.1   gdamore  */
    796   1.1   gdamore static void
    797   1.1   gdamore rfcomm_session_recv_disc(struct rfcomm_session *rs, int dlci)
    798   1.1   gdamore {
    799   1.1   gdamore 	struct rfcomm_dlc *dlc;
    800   1.1   gdamore 
    801   1.1   gdamore 	DPRINTFN(5, "DISC(%d)\n", dlci);
    802   1.1   gdamore 
    803   1.1   gdamore 	if (dlci == 0) {
    804   1.1   gdamore 		/*
    805   1.1   gdamore 		 * Disconnect Session
    806   1.1   gdamore 		 *
    807   1.1   gdamore 		 * We set the session state to CLOSED so that when
    808   1.1   gdamore 		 * the UA frame is clear the session will be closed
    809   1.1   gdamore 		 * automatically. We wont bother to close any DLC's
    810   1.1   gdamore 		 * just yet as there should be none. In the unlikely
    811   1.1   gdamore 		 * event that something is left, it will get flushed
    812   1.1   gdamore 		 * out as the session goes down.
    813   1.1   gdamore 		 */
    814   1.1   gdamore 		rfcomm_session_send_frame(rs, RFCOMM_FRAME_UA, 0);
    815   1.1   gdamore 		rs->rs_state = RFCOMM_SESSION_CLOSED;
    816   1.1   gdamore 		return;
    817   1.1   gdamore 	}
    818   1.1   gdamore 
    819   1.1   gdamore 	dlc = rfcomm_dlc_lookup(rs, dlci);
    820   1.1   gdamore 	if (dlc == NULL) {
    821   1.1   gdamore 		rfcomm_session_send_frame(rs, RFCOMM_FRAME_DM, dlci);
    822   1.1   gdamore 		return;
    823   1.1   gdamore 	}
    824   1.1   gdamore 
    825  1.17    plunky 	rfcomm_dlc_close(dlc, 0);
    826   1.1   gdamore 	rfcomm_session_send_frame(rs, RFCOMM_FRAME_UA, dlci);
    827   1.1   gdamore }
    828   1.1   gdamore 
    829   1.1   gdamore /*
    830   1.1   gdamore  * Receive Unnumbered Acknowledgement Response
    831   1.1   gdamore  *
    832   1.1   gdamore  * This should be a response to a DISC or SABM frame that we
    833   1.1   gdamore  * have previously sent. If unexpected, ignore it.
    834   1.1   gdamore  */
    835   1.1   gdamore static void
    836   1.1   gdamore rfcomm_session_recv_ua(struct rfcomm_session *rs, int dlci)
    837   1.1   gdamore {
    838   1.1   gdamore 	struct rfcomm_dlc *dlc;
    839   1.1   gdamore 
    840   1.1   gdamore 	DPRINTFN(5, "UA(%d)\n", dlci);
    841   1.1   gdamore 
    842   1.1   gdamore 	if (dlci == 0) {
    843   1.1   gdamore 		switch (rs->rs_state) {
    844   1.1   gdamore 		case RFCOMM_SESSION_WAIT_CONNECT:	/* We sent SABM */
    845   1.1   gdamore 			callout_stop(&rs->rs_timeout);
    846   1.1   gdamore 			rs->rs_state = RFCOMM_SESSION_OPEN;
    847   1.1   gdamore 			LIST_FOREACH(dlc, &rs->rs_dlcs, rd_next) {
    848   1.1   gdamore 				if (dlc->rd_state == RFCOMM_DLC_WAIT_SESSION)
    849   1.1   gdamore 					rfcomm_dlc_connect(dlc);
    850   1.1   gdamore 			}
    851   1.1   gdamore 			break;
    852   1.1   gdamore 
    853   1.1   gdamore 		case RFCOMM_SESSION_WAIT_DISCONNECT:	/* We sent DISC */
    854   1.1   gdamore 			callout_stop(&rs->rs_timeout);
    855   1.1   gdamore 			rs->rs_state = RFCOMM_SESSION_CLOSED;
    856  1.22       rtr 			l2cap_disconnect_pcb(rs->rs_l2cap, 0);
    857   1.1   gdamore 			break;
    858   1.1   gdamore 
    859   1.1   gdamore 		default:
    860   1.1   gdamore 			DPRINTF("Received spurious UA(0)!\n");
    861   1.1   gdamore 			break;
    862   1.1   gdamore 		}
    863   1.1   gdamore 
    864   1.1   gdamore 		return;
    865   1.1   gdamore 	}
    866   1.1   gdamore 
    867   1.1   gdamore 	/*
    868   1.1   gdamore 	 * If we have no DLC on this dlci, we may have aborted
    869   1.1   gdamore 	 * without shutting down properly, so check if the session
    870   1.1   gdamore 	 * needs disconnecting.
    871   1.1   gdamore 	 */
    872   1.1   gdamore 	dlc = rfcomm_dlc_lookup(rs, dlci);
    873   1.1   gdamore 	if (dlc == NULL)
    874   1.1   gdamore 		goto check;
    875   1.1   gdamore 
    876   1.1   gdamore 	switch (dlc->rd_state) {
    877   1.9    plunky 	case RFCOMM_DLC_WAIT_RECV_UA:		/* We sent SABM */
    878   1.9    plunky 		rfcomm_dlc_open(dlc);
    879   1.1   gdamore 		return;
    880   1.1   gdamore 
    881   1.1   gdamore 	case RFCOMM_DLC_WAIT_DISCONNECT:	/* We sent DISC */
    882   1.1   gdamore 		rfcomm_dlc_close(dlc, 0);
    883   1.1   gdamore 		break;
    884   1.1   gdamore 
    885   1.1   gdamore 	default:
    886   1.1   gdamore 		DPRINTF("Received spurious UA(%d)!\n", dlci);
    887   1.1   gdamore 		return;
    888   1.1   gdamore 	}
    889   1.1   gdamore 
    890   1.1   gdamore check:	/* last one out turns out the light */
    891   1.1   gdamore 	if (LIST_EMPTY(&rs->rs_dlcs)) {
    892   1.1   gdamore 		rs->rs_state = RFCOMM_SESSION_WAIT_DISCONNECT;
    893   1.1   gdamore 		rfcomm_session_send_frame(rs, RFCOMM_FRAME_DISC, 0);
    894   1.1   gdamore 		callout_schedule(&rs->rs_timeout, rfcomm_ack_timeout * hz);
    895   1.1   gdamore 	}
    896   1.1   gdamore }
    897   1.1   gdamore 
    898   1.1   gdamore /*
    899   1.1   gdamore  * Receive Disconnected Mode Response
    900   1.1   gdamore  *
    901   1.1   gdamore  * If this does not apply to a known DLC then we may ignore it.
    902   1.1   gdamore  */
    903   1.1   gdamore static void
    904   1.1   gdamore rfcomm_session_recv_dm(struct rfcomm_session *rs, int dlci)
    905   1.1   gdamore {
    906   1.1   gdamore 	struct rfcomm_dlc *dlc;
    907   1.1   gdamore 
    908   1.1   gdamore 	DPRINTFN(5, "DM(%d)\n", dlci);
    909   1.1   gdamore 
    910   1.1   gdamore 	dlc = rfcomm_dlc_lookup(rs, dlci);
    911   1.1   gdamore 	if (dlc == NULL)
    912   1.1   gdamore 		return;
    913   1.1   gdamore 
    914   1.1   gdamore 	if (dlc->rd_state == RFCOMM_DLC_WAIT_CONNECT)
    915   1.1   gdamore 		rfcomm_dlc_close(dlc, ECONNREFUSED);
    916   1.1   gdamore 	else
    917   1.1   gdamore 		rfcomm_dlc_close(dlc, ECONNRESET);
    918   1.1   gdamore }
    919   1.1   gdamore 
    920   1.1   gdamore /*
    921   1.1   gdamore  * Receive Unnumbered Information with Header check (MCC or data packet)
    922   1.1   gdamore  */
    923   1.1   gdamore static void
    924   1.1   gdamore rfcomm_session_recv_uih(struct rfcomm_session *rs, int dlci,
    925   1.1   gdamore 			int pf, struct mbuf *m, int len)
    926   1.1   gdamore {
    927   1.1   gdamore 	struct rfcomm_dlc *dlc;
    928   1.1   gdamore 	uint8_t credits = 0;
    929   1.1   gdamore 
    930   1.1   gdamore 	DPRINTFN(10, "UIH(%d)\n", dlci);
    931   1.1   gdamore 
    932   1.1   gdamore 	if (dlci == 0) {
    933   1.1   gdamore 		rfcomm_session_recv_mcc(rs, m);
    934   1.1   gdamore 		return;
    935   1.1   gdamore 	}
    936   1.1   gdamore 
    937   1.1   gdamore 	if (m->m_pkthdr.len != len + pf) {
    938   1.1   gdamore 		DPRINTF("Bad Frame Length (%d), frame discarded\n",
    939   1.1   gdamore 			    m->m_pkthdr.len);
    940   1.1   gdamore 
    941   1.1   gdamore 		goto discard;
    942   1.1   gdamore 	}
    943   1.1   gdamore 
    944   1.1   gdamore 	dlc = rfcomm_dlc_lookup(rs, dlci);
    945   1.1   gdamore 	if (dlc == NULL) {
    946   1.1   gdamore 		DPRINTF("UIH received for non existent DLC, discarded\n");
    947   1.1   gdamore 		rfcomm_session_send_frame(rs, RFCOMM_FRAME_DM, dlci);
    948   1.1   gdamore 		goto discard;
    949   1.1   gdamore 	}
    950   1.1   gdamore 
    951   1.1   gdamore 	if (dlc->rd_state != RFCOMM_DLC_OPEN) {
    952   1.1   gdamore 		DPRINTF("non-open DLC (state = %d), discarded\n",
    953   1.1   gdamore 				dlc->rd_state);
    954   1.1   gdamore 		goto discard;
    955   1.1   gdamore 	}
    956   1.1   gdamore 
    957   1.1   gdamore 	/* if PF is set, credits were included */
    958   1.1   gdamore 	if (rs->rs_flags & RFCOMM_SESSION_CFC) {
    959   1.1   gdamore 		if (pf != 0) {
    960   1.1   gdamore 			if (m->m_pkthdr.len < sizeof(credits)) {
    961   1.1   gdamore 				DPRINTF("Bad PF value, UIH discarded\n");
    962   1.1   gdamore 				goto discard;
    963   1.1   gdamore 			}
    964   1.1   gdamore 
    965   1.1   gdamore 			m_copydata(m, 0, sizeof(credits), &credits);
    966   1.1   gdamore 			m_adj(m, sizeof(credits));
    967   1.1   gdamore 
    968   1.1   gdamore 			dlc->rd_txcred += credits;
    969   1.1   gdamore 
    970   1.1   gdamore 			if (credits > 0 && dlc->rd_txbuf != NULL)
    971   1.1   gdamore 				rfcomm_dlc_start(dlc);
    972   1.1   gdamore 		}
    973   1.1   gdamore 
    974   1.1   gdamore 		if (len == 0)
    975   1.1   gdamore 			goto discard;
    976   1.1   gdamore 
    977   1.1   gdamore 		if (dlc->rd_rxcred == 0) {
    978   1.1   gdamore 			DPRINTF("Credit limit reached, UIH discarded\n");
    979   1.1   gdamore 			goto discard;
    980   1.1   gdamore 		}
    981   1.1   gdamore 
    982   1.1   gdamore 		if (len > dlc->rd_rxsize) {
    983   1.1   gdamore 			DPRINTF("UIH frame exceeds rxsize, discarded\n");
    984   1.1   gdamore 			goto discard;
    985   1.1   gdamore 		}
    986   1.1   gdamore 
    987   1.1   gdamore 		dlc->rd_rxcred--;
    988   1.1   gdamore 		dlc->rd_rxsize -= len;
    989   1.1   gdamore 	}
    990   1.1   gdamore 
    991   1.1   gdamore 	(*dlc->rd_proto->input)(dlc->rd_upper, m);
    992   1.1   gdamore 	return;
    993   1.1   gdamore 
    994   1.1   gdamore discard:
    995   1.1   gdamore 	m_freem(m);
    996   1.1   gdamore }
    997   1.1   gdamore 
    998   1.1   gdamore /*
    999   1.1   gdamore  * Receive Multiplexer Control Command
   1000   1.1   gdamore  */
   1001   1.1   gdamore static void
   1002   1.1   gdamore rfcomm_session_recv_mcc(struct rfcomm_session *rs, struct mbuf *m)
   1003   1.1   gdamore {
   1004   1.1   gdamore 	int type, cr, len;
   1005   1.1   gdamore 	uint8_t b;
   1006   1.1   gdamore 
   1007   1.1   gdamore 	/*
   1008   1.1   gdamore 	 * Extract MCC header.
   1009   1.1   gdamore 	 *
   1010   1.1   gdamore 	 * Fields are variable length using extension bit = 1 to signify the
   1011   1.1   gdamore 	 * last octet in the sequence.
   1012   1.1   gdamore 	 *
   1013   1.1   gdamore 	 * Only single octet types are defined in TS 07.10/RFCOMM spec
   1014   1.1   gdamore 	 *
   1015   1.1   gdamore 	 * Length can realistically only use 15 bits (max RFCOMM MTU)
   1016   1.1   gdamore 	 */
   1017   1.1   gdamore 	if (m->m_pkthdr.len < sizeof(b)) {
   1018   1.1   gdamore 		DPRINTF("Short MCC header, discarded\n");
   1019   1.1   gdamore 		goto release;
   1020   1.1   gdamore 	}
   1021   1.1   gdamore 
   1022   1.1   gdamore 	m_copydata(m, 0, sizeof(b), &b);
   1023   1.1   gdamore 	m_adj(m, sizeof(b));
   1024   1.1   gdamore 
   1025   1.1   gdamore 	if (RFCOMM_EA(b) == 0) {	/* verify no extensions */
   1026   1.9    plunky 		DPRINTF("MCC type EA = 0, discarded\n");
   1027   1.1   gdamore 		goto release;
   1028   1.1   gdamore 	}
   1029   1.1   gdamore 
   1030   1.1   gdamore 	type = RFCOMM_MCC_TYPE(b);
   1031   1.1   gdamore 	cr = RFCOMM_CR(b);
   1032   1.1   gdamore 
   1033   1.1   gdamore 	len = 0;
   1034   1.1   gdamore 	do {
   1035   1.1   gdamore 		if (m->m_pkthdr.len < sizeof(b)) {
   1036   1.1   gdamore 			DPRINTF("Short MCC header, discarded\n");
   1037   1.1   gdamore 			goto release;
   1038   1.1   gdamore 		}
   1039   1.1   gdamore 
   1040   1.1   gdamore 		m_copydata(m, 0, sizeof(b), &b);
   1041   1.1   gdamore 		m_adj(m, sizeof(b));
   1042   1.1   gdamore 
   1043   1.1   gdamore 		len = (len << 7) | (b >> 1);
   1044  1.24  riastrad 		len = uimin(len, RFCOMM_MTU_MAX);
   1045   1.1   gdamore 	} while (RFCOMM_EA(b) == 0);
   1046   1.1   gdamore 
   1047   1.1   gdamore 	if (len != m->m_pkthdr.len) {
   1048   1.1   gdamore 		DPRINTF("Incorrect MCC length, discarded\n");
   1049   1.1   gdamore 		goto release;
   1050   1.1   gdamore 	}
   1051   1.1   gdamore 
   1052   1.1   gdamore 	DPRINTFN(2, "MCC %s type %2.2x (%d bytes)\n",
   1053   1.1   gdamore 		(cr ? "command" : "response"), type, len);
   1054   1.1   gdamore 
   1055   1.1   gdamore 	/*
   1056   1.1   gdamore 	 * pass to command handler
   1057   1.1   gdamore 	 */
   1058   1.1   gdamore 	switch(type) {
   1059   1.1   gdamore 	case RFCOMM_MCC_TEST:	/* Test */
   1060   1.1   gdamore 		rfcomm_session_recv_mcc_test(rs, cr, m);
   1061   1.1   gdamore 		break;
   1062   1.1   gdamore 
   1063   1.1   gdamore 	case RFCOMM_MCC_FCON:	/* Flow Control On */
   1064   1.1   gdamore 		rfcomm_session_recv_mcc_fcon(rs, cr);
   1065   1.1   gdamore 		break;
   1066   1.1   gdamore 
   1067   1.1   gdamore 	case RFCOMM_MCC_FCOFF:	/* Flow Control Off */
   1068   1.1   gdamore 		rfcomm_session_recv_mcc_fcoff(rs, cr);
   1069   1.1   gdamore 		break;
   1070   1.1   gdamore 
   1071   1.1   gdamore 	case RFCOMM_MCC_MSC:	/* Modem Status Command */
   1072   1.1   gdamore 		rfcomm_session_recv_mcc_msc(rs, cr, m);
   1073   1.1   gdamore 		break;
   1074   1.1   gdamore 
   1075   1.1   gdamore 	case RFCOMM_MCC_RPN:	/* Remote Port Negotiation */
   1076   1.1   gdamore 		rfcomm_session_recv_mcc_rpn(rs, cr, m);
   1077   1.1   gdamore 		break;
   1078   1.1   gdamore 
   1079   1.1   gdamore 	case RFCOMM_MCC_RLS:	/* Remote Line Status */
   1080   1.1   gdamore 		rfcomm_session_recv_mcc_rls(rs, cr, m);
   1081   1.1   gdamore 		break;
   1082   1.1   gdamore 
   1083   1.1   gdamore 	case RFCOMM_MCC_PN:	/* Parameter Negotiation */
   1084   1.1   gdamore 		rfcomm_session_recv_mcc_pn(rs, cr, m);
   1085   1.1   gdamore 		break;
   1086   1.1   gdamore 
   1087   1.1   gdamore 	case RFCOMM_MCC_NSC:	/* Non Supported Command */
   1088   1.1   gdamore 		rfcomm_session_recv_mcc_nsc(rs, cr, m);
   1089   1.1   gdamore 		break;
   1090   1.1   gdamore 
   1091   1.1   gdamore 	default:
   1092   1.1   gdamore 		b = RFCOMM_MKMCC_TYPE(cr, type);
   1093   1.1   gdamore 		rfcomm_session_send_mcc(rs, 0, RFCOMM_MCC_NSC, &b, sizeof(b));
   1094   1.1   gdamore 	}
   1095   1.1   gdamore 
   1096   1.1   gdamore release:
   1097   1.1   gdamore 	m_freem(m);
   1098   1.1   gdamore }
   1099   1.1   gdamore 
   1100   1.1   gdamore /*
   1101   1.1   gdamore  * process TEST command/response
   1102   1.1   gdamore  */
   1103   1.1   gdamore static void
   1104   1.1   gdamore rfcomm_session_recv_mcc_test(struct rfcomm_session *rs, int cr, struct mbuf *m)
   1105   1.1   gdamore {
   1106   1.1   gdamore 	void *data;
   1107   1.1   gdamore 	int len;
   1108   1.1   gdamore 
   1109   1.1   gdamore 	if (cr == 0)	/* ignore ack */
   1110   1.1   gdamore 		return;
   1111   1.1   gdamore 
   1112   1.1   gdamore 	/*
   1113   1.1   gdamore 	 * we must send all the data they included back as is
   1114   1.1   gdamore 	 */
   1115   1.1   gdamore 
   1116   1.1   gdamore 	len = m->m_pkthdr.len;
   1117   1.1   gdamore 	if (len > RFCOMM_MTU_MAX)
   1118   1.1   gdamore 		return;
   1119   1.1   gdamore 
   1120   1.1   gdamore 	data = malloc(len, M_BLUETOOTH, M_NOWAIT);
   1121   1.1   gdamore 	if (data == NULL)
   1122   1.1   gdamore 		return;
   1123   1.1   gdamore 
   1124   1.1   gdamore 	m_copydata(m, 0, len, data);
   1125   1.1   gdamore 	rfcomm_session_send_mcc(rs, 0, RFCOMM_MCC_TEST, data, len);
   1126   1.1   gdamore 	free(data, M_BLUETOOTH);
   1127   1.1   gdamore }
   1128   1.1   gdamore 
   1129   1.1   gdamore /*
   1130   1.1   gdamore  * process Flow Control ON command/response
   1131   1.1   gdamore  */
   1132   1.1   gdamore static void
   1133   1.1   gdamore rfcomm_session_recv_mcc_fcon(struct rfcomm_session *rs, int cr)
   1134   1.1   gdamore {
   1135   1.1   gdamore 
   1136   1.1   gdamore 	if (cr == 0)	/* ignore ack */
   1137   1.1   gdamore 		return;
   1138   1.1   gdamore 
   1139   1.1   gdamore 	rs->rs_flags |= RFCOMM_SESSION_RFC;
   1140   1.1   gdamore 	rfcomm_session_send_mcc(rs, 0, RFCOMM_MCC_FCON, NULL, 0);
   1141   1.1   gdamore }
   1142   1.1   gdamore 
   1143   1.1   gdamore /*
   1144   1.1   gdamore  * process Flow Control OFF command/response
   1145   1.1   gdamore  */
   1146   1.1   gdamore static void
   1147   1.1   gdamore rfcomm_session_recv_mcc_fcoff(struct rfcomm_session *rs, int cr)
   1148   1.1   gdamore {
   1149   1.1   gdamore 
   1150   1.1   gdamore 	if (cr == 0)	/* ignore ack */
   1151   1.1   gdamore 		return;
   1152   1.1   gdamore 
   1153   1.1   gdamore 	rs->rs_flags &= ~RFCOMM_SESSION_RFC;
   1154   1.1   gdamore 	rfcomm_session_send_mcc(rs, 0, RFCOMM_MCC_FCOFF, NULL, 0);
   1155   1.1   gdamore }
   1156   1.1   gdamore 
   1157   1.1   gdamore /*
   1158   1.1   gdamore  * process Modem Status Command command/response
   1159   1.1   gdamore  */
   1160   1.1   gdamore static void
   1161   1.1   gdamore rfcomm_session_recv_mcc_msc(struct rfcomm_session *rs, int cr, struct mbuf *m)
   1162   1.1   gdamore {
   1163   1.1   gdamore 	struct rfcomm_mcc_msc msc;	/* (3 octets) */
   1164   1.1   gdamore 	struct rfcomm_dlc *dlc;
   1165   1.1   gdamore 	int len = 0;
   1166   1.1   gdamore 
   1167   1.1   gdamore 	/* [ADDRESS] */
   1168   1.1   gdamore 	if (m->m_pkthdr.len < sizeof(msc.address))
   1169   1.1   gdamore 		return;
   1170   1.1   gdamore 
   1171   1.1   gdamore 	m_copydata(m, 0, sizeof(msc.address), &msc.address);
   1172   1.1   gdamore 	m_adj(m, sizeof(msc.address));
   1173   1.1   gdamore 	len += sizeof(msc.address);
   1174   1.1   gdamore 
   1175   1.1   gdamore 	dlc = rfcomm_dlc_lookup(rs, RFCOMM_DLCI(msc.address));
   1176   1.1   gdamore 
   1177   1.1   gdamore 	if (cr == 0) {	/* ignore acks */
   1178   1.1   gdamore 		if (dlc != NULL)
   1179   1.1   gdamore 			callout_stop(&dlc->rd_timeout);
   1180   1.1   gdamore 
   1181   1.1   gdamore 		return;
   1182   1.1   gdamore 	}
   1183   1.1   gdamore 
   1184   1.1   gdamore 	if (dlc == NULL) {
   1185   1.1   gdamore 		rfcomm_session_send_frame(rs, RFCOMM_FRAME_DM,
   1186   1.1   gdamore 						RFCOMM_DLCI(msc.address));
   1187   1.1   gdamore 		return;
   1188   1.1   gdamore 	}
   1189   1.1   gdamore 
   1190   1.1   gdamore 	/* [SIGNALS] */
   1191   1.1   gdamore 	if (m->m_pkthdr.len < sizeof(msc.modem))
   1192   1.1   gdamore 		return;
   1193   1.1   gdamore 
   1194   1.1   gdamore 	m_copydata(m, 0, sizeof(msc.modem), &msc.modem);
   1195   1.1   gdamore 	m_adj(m, sizeof(msc.modem));
   1196   1.1   gdamore 	len += sizeof(msc.modem);
   1197   1.1   gdamore 
   1198   1.1   gdamore 	dlc->rd_rmodem = msc.modem;
   1199   1.7    plunky 	/* XXX how do we signal this upstream? */
   1200   1.1   gdamore 
   1201   1.1   gdamore 	if (RFCOMM_EA(msc.modem) == 0) {
   1202   1.1   gdamore 		if (m->m_pkthdr.len < sizeof(msc.brk))
   1203   1.1   gdamore 			return;
   1204   1.1   gdamore 
   1205   1.1   gdamore 		m_copydata(m, 0, sizeof(msc.brk), &msc.brk);
   1206   1.1   gdamore 		m_adj(m, sizeof(msc.brk));
   1207   1.1   gdamore 		len += sizeof(msc.brk);
   1208   1.1   gdamore 
   1209   1.7    plunky 		/* XXX how do we signal this upstream? */
   1210   1.1   gdamore 	}
   1211   1.1   gdamore 
   1212   1.1   gdamore 	rfcomm_session_send_mcc(rs, 0, RFCOMM_MCC_MSC, &msc, len);
   1213   1.1   gdamore }
   1214   1.1   gdamore 
   1215   1.1   gdamore /*
   1216   1.1   gdamore  * process Remote Port Negotiation command/response
   1217   1.1   gdamore  */
   1218   1.1   gdamore static void
   1219   1.1   gdamore rfcomm_session_recv_mcc_rpn(struct rfcomm_session *rs, int cr, struct mbuf *m)
   1220   1.1   gdamore {
   1221   1.1   gdamore 	struct rfcomm_mcc_rpn rpn;
   1222   1.1   gdamore 	uint16_t mask;
   1223   1.1   gdamore 
   1224   1.1   gdamore 	if (cr == 0)	/* ignore ack */
   1225   1.1   gdamore 		return;
   1226   1.1   gdamore 
   1227   1.1   gdamore 	/* default values */
   1228   1.1   gdamore 	rpn.bit_rate = RFCOMM_RPN_BR_9600;
   1229   1.1   gdamore 	rpn.line_settings = RFCOMM_RPN_8_N_1;
   1230   1.1   gdamore 	rpn.flow_control = RFCOMM_RPN_FLOW_NONE;
   1231   1.1   gdamore 	rpn.xon_char = RFCOMM_RPN_XON_CHAR;
   1232   1.1   gdamore 	rpn.xoff_char = RFCOMM_RPN_XOFF_CHAR;
   1233   1.1   gdamore 
   1234   1.1   gdamore 	if (m->m_pkthdr.len == sizeof(rpn)) {
   1235  1.26    plunky 		/* negotiation request */
   1236   1.1   gdamore 		m_copydata(m, 0, sizeof(rpn), &rpn);
   1237  1.26    plunky 		rpn.param_mask = le16toh(rpn.param_mask);
   1238   1.1   gdamore 	} else if (m->m_pkthdr.len == 1) {
   1239  1.26    plunky 		/* current settings request */
   1240  1.27      maxv 		m_copydata(m, 0, 1, &rpn.dlci);
   1241  1.26    plunky 		rpn.param_mask = RFCOMM_RPN_PM_ALL;
   1242   1.1   gdamore 	} else {
   1243   1.1   gdamore 		DPRINTF("Bad RPN length (%d)\n", m->m_pkthdr.len);
   1244   1.1   gdamore 		return;
   1245   1.1   gdamore 	}
   1246   1.1   gdamore 
   1247   1.1   gdamore 	mask = 0;
   1248   1.1   gdamore 
   1249   1.1   gdamore 	if (rpn.param_mask & RFCOMM_RPN_PM_RATE)
   1250   1.1   gdamore 		mask |= RFCOMM_RPN_PM_RATE;
   1251   1.1   gdamore 
   1252   1.1   gdamore 	if (rpn.param_mask & RFCOMM_RPN_PM_DATA
   1253   1.1   gdamore 	    && RFCOMM_RPN_DATA_BITS(rpn.line_settings) == RFCOMM_RPN_DATA_8)
   1254   1.1   gdamore 		mask |= RFCOMM_RPN_PM_DATA;
   1255   1.1   gdamore 
   1256   1.1   gdamore 	if (rpn.param_mask & RFCOMM_RPN_PM_STOP
   1257   1.1   gdamore 	    && RFCOMM_RPN_STOP_BITS(rpn.line_settings) == RFCOMM_RPN_STOP_1)
   1258   1.1   gdamore 		mask |= RFCOMM_RPN_PM_STOP;
   1259   1.1   gdamore 
   1260   1.1   gdamore 	if (rpn.param_mask & RFCOMM_RPN_PM_PARITY
   1261   1.1   gdamore 	    && RFCOMM_RPN_PARITY(rpn.line_settings) == RFCOMM_RPN_PARITY_NONE)
   1262   1.1   gdamore 		mask |= RFCOMM_RPN_PM_PARITY;
   1263   1.1   gdamore 
   1264   1.1   gdamore 	if (rpn.param_mask & RFCOMM_RPN_PM_XON
   1265   1.1   gdamore 	    && rpn.xon_char == RFCOMM_RPN_XON_CHAR)
   1266   1.1   gdamore 		mask |= RFCOMM_RPN_PM_XON;
   1267   1.1   gdamore 
   1268   1.1   gdamore 	if (rpn.param_mask & RFCOMM_RPN_PM_XOFF
   1269   1.1   gdamore 	    && rpn.xoff_char == RFCOMM_RPN_XOFF_CHAR)
   1270   1.1   gdamore 		mask |= RFCOMM_RPN_PM_XOFF;
   1271   1.1   gdamore 
   1272   1.1   gdamore 	if (rpn.param_mask & RFCOMM_RPN_PM_FLOW
   1273   1.1   gdamore 	    && rpn.flow_control == RFCOMM_RPN_FLOW_NONE)
   1274   1.1   gdamore 		mask |= RFCOMM_RPN_PM_FLOW;
   1275   1.1   gdamore 
   1276   1.1   gdamore 	rpn.param_mask = htole16(mask);
   1277   1.1   gdamore 
   1278   1.1   gdamore 	rfcomm_session_send_mcc(rs, 0, RFCOMM_MCC_RPN, &rpn, sizeof(rpn));
   1279   1.1   gdamore }
   1280   1.1   gdamore 
   1281   1.1   gdamore /*
   1282   1.1   gdamore  * process Remote Line Status command/response
   1283   1.1   gdamore  */
   1284   1.1   gdamore static void
   1285   1.1   gdamore rfcomm_session_recv_mcc_rls(struct rfcomm_session *rs, int cr, struct mbuf *m)
   1286   1.1   gdamore {
   1287   1.1   gdamore 	struct rfcomm_mcc_rls rls;
   1288   1.1   gdamore 
   1289   1.1   gdamore 	if (cr == 0)	/* ignore ack */
   1290   1.1   gdamore 		return;
   1291   1.1   gdamore 
   1292   1.1   gdamore 	if (m->m_pkthdr.len != sizeof(rls)) {
   1293   1.1   gdamore 		DPRINTF("Bad RLS length %d\n", m->m_pkthdr.len);
   1294   1.1   gdamore 		return;
   1295   1.1   gdamore 	}
   1296   1.1   gdamore 
   1297   1.1   gdamore 	m_copydata(m, 0, sizeof(rls), &rls);
   1298   1.1   gdamore 
   1299   1.1   gdamore 	/*
   1300   1.1   gdamore 	 * So far as I can tell, we just send back what
   1301   1.1   gdamore 	 * they sent us. This signifies errors that seem
   1302  1.29    andvar 	 * irrelevant for RFCOMM over L2CAP.
   1303   1.1   gdamore 	 */
   1304   1.1   gdamore 	rls.address |= 0x03;	/* EA = 1, CR = 1 */
   1305   1.1   gdamore 	rls.status &= 0x0f;	/* only 4 bits valid */
   1306   1.1   gdamore 
   1307   1.1   gdamore 	rfcomm_session_send_mcc(rs, 0, RFCOMM_MCC_RLS, &rls, sizeof(rls));
   1308   1.1   gdamore }
   1309   1.1   gdamore 
   1310   1.1   gdamore /*
   1311   1.1   gdamore  * process Parameter Negotiation command/response
   1312   1.1   gdamore  */
   1313   1.1   gdamore static void
   1314   1.1   gdamore rfcomm_session_recv_mcc_pn(struct rfcomm_session *rs, int cr, struct mbuf *m)
   1315   1.1   gdamore {
   1316   1.1   gdamore 	struct rfcomm_dlc *dlc;
   1317   1.1   gdamore 	struct rfcomm_mcc_pn pn;
   1318   1.1   gdamore 	int err;
   1319   1.1   gdamore 
   1320   1.1   gdamore 	if (m->m_pkthdr.len != sizeof(pn)) {
   1321   1.1   gdamore 		DPRINTF("Bad PN length %d\n", m->m_pkthdr.len);
   1322   1.1   gdamore 		return;
   1323   1.1   gdamore 	}
   1324   1.1   gdamore 
   1325   1.1   gdamore 	m_copydata(m, 0, sizeof(pn), &pn);
   1326   1.1   gdamore 
   1327   1.1   gdamore 	pn.dlci &= 0x3f;
   1328   1.1   gdamore 	pn.mtu = le16toh(pn.mtu);
   1329   1.1   gdamore 
   1330   1.1   gdamore 	dlc = rfcomm_dlc_lookup(rs, pn.dlci);
   1331   1.1   gdamore 	if (cr) {	/* Command */
   1332   1.1   gdamore 		/*
   1333   1.1   gdamore 		 * If there is no DLC present, this is a new
   1334   1.1   gdamore 		 * connection so attempt to make one
   1335   1.1   gdamore 		 */
   1336   1.1   gdamore 		if (dlc == NULL) {
   1337   1.1   gdamore 			dlc = rfcomm_dlc_newconn(rs, pn.dlci);
   1338   1.1   gdamore 			if (dlc == NULL)
   1339   1.1   gdamore 				return;	/* (DM is sent) */
   1340   1.1   gdamore 		}
   1341   1.1   gdamore 
   1342   1.1   gdamore 		/* accept any valid MTU, and offer it back */
   1343  1.24  riastrad 		pn.mtu = uimin(pn.mtu, RFCOMM_MTU_MAX);
   1344  1.24  riastrad 		pn.mtu = uimin(pn.mtu, rs->rs_mtu);
   1345  1.24  riastrad 		pn.mtu = uimax(pn.mtu, RFCOMM_MTU_MIN);
   1346   1.1   gdamore 		dlc->rd_mtu = pn.mtu;
   1347   1.1   gdamore 		pn.mtu = htole16(pn.mtu);
   1348   1.1   gdamore 
   1349   1.1   gdamore 		/* credits are only set before DLC is open */
   1350   1.1   gdamore 		if (dlc->rd_state == RFCOMM_DLC_WAIT_CONNECT
   1351   1.1   gdamore 		    && (pn.flow_control & 0xf0) == 0xf0) {
   1352   1.1   gdamore 			rs->rs_flags |= RFCOMM_SESSION_CFC;
   1353   1.1   gdamore 			dlc->rd_txcred = pn.credits & 0x07;
   1354   1.1   gdamore 
   1355   1.1   gdamore 			dlc->rd_rxcred = (dlc->rd_rxsize / dlc->rd_mtu);
   1356  1.24  riastrad 			dlc->rd_rxcred = uimin(dlc->rd_rxcred,
   1357   1.1   gdamore 						RFCOMM_CREDITS_DEFAULT);
   1358   1.1   gdamore 
   1359   1.1   gdamore 			pn.flow_control = 0xe0;
   1360   1.1   gdamore 			pn.credits = dlc->rd_rxcred;
   1361   1.1   gdamore 		} else {
   1362   1.1   gdamore 			pn.flow_control = 0x00;
   1363   1.1   gdamore 			pn.credits = 0x00;
   1364   1.1   gdamore 		}
   1365   1.1   gdamore 
   1366   1.1   gdamore 		/* unused fields must be ignored and set to zero */
   1367   1.1   gdamore 		pn.ack_timer = 0;
   1368   1.1   gdamore 		pn.max_retrans = 0;
   1369   1.1   gdamore 
   1370   1.1   gdamore 		/* send our response */
   1371   1.1   gdamore 		err = rfcomm_session_send_mcc(rs, 0,
   1372   1.1   gdamore 					RFCOMM_MCC_PN, &pn, sizeof(pn));
   1373   1.1   gdamore 		if (err)
   1374   1.1   gdamore 			goto close;
   1375   1.1   gdamore 
   1376   1.1   gdamore 	} else {	/* Response */
   1377   1.1   gdamore 		/* ignore responses with no matching DLC */
   1378   1.1   gdamore 		if (dlc == NULL)
   1379   1.1   gdamore 			return;
   1380   1.1   gdamore 
   1381   1.1   gdamore 		callout_stop(&dlc->rd_timeout);
   1382   1.1   gdamore 
   1383  1.16    plunky 		/* reject invalid or unacceptable MTU */
   1384  1.16    plunky 		if (pn.mtu < RFCOMM_MTU_MIN || pn.mtu > dlc->rd_mtu) {
   1385   1.1   gdamore 			dlc->rd_state = RFCOMM_DLC_WAIT_DISCONNECT;
   1386   1.1   gdamore 			err = rfcomm_session_send_frame(rs, RFCOMM_FRAME_DISC,
   1387   1.1   gdamore 							pn.dlci);
   1388   1.1   gdamore 			if (err)
   1389   1.1   gdamore 				goto close;
   1390   1.1   gdamore 
   1391   1.1   gdamore 			callout_schedule(&dlc->rd_timeout,
   1392   1.1   gdamore 					    rfcomm_ack_timeout * hz);
   1393   1.1   gdamore 			return;
   1394   1.1   gdamore 		}
   1395   1.1   gdamore 		dlc->rd_mtu = pn.mtu;
   1396   1.1   gdamore 
   1397   1.9    plunky 		/* if DLC is not waiting to connect, we are done */
   1398   1.9    plunky 		if (dlc->rd_state != RFCOMM_DLC_WAIT_CONNECT)
   1399   1.9    plunky 			return;
   1400   1.9    plunky 
   1401   1.9    plunky 		/* set initial credits according to RFCOMM spec */
   1402   1.9    plunky 		if ((pn.flow_control & 0xf0) == 0xe0) {
   1403   1.1   gdamore 			rs->rs_flags |= RFCOMM_SESSION_CFC;
   1404   1.1   gdamore 			dlc->rd_txcred = (pn.credits & 0x07);
   1405   1.1   gdamore 		}
   1406   1.1   gdamore 
   1407   1.9    plunky 		callout_schedule(&dlc->rd_timeout, rfcomm_ack_timeout * hz);
   1408   1.9    plunky 
   1409   1.9    plunky 		/* set link mode */
   1410   1.9    plunky 		err = rfcomm_dlc_setmode(dlc);
   1411   1.9    plunky 		if (err == EINPROGRESS) {
   1412   1.9    plunky 			dlc->rd_state = RFCOMM_DLC_WAIT_SEND_SABM;
   1413   1.9    plunky 			(*dlc->rd_proto->connecting)(dlc->rd_upper);
   1414   1.9    plunky 			return;
   1415   1.9    plunky 		}
   1416   1.9    plunky 		if (err)
   1417   1.9    plunky 			goto close;
   1418   1.9    plunky 
   1419   1.9    plunky 		/* we can proceed now */
   1420   1.1   gdamore 		err = rfcomm_session_send_frame(rs, RFCOMM_FRAME_SABM, pn.dlci);
   1421   1.1   gdamore 		if (err)
   1422   1.1   gdamore 			goto close;
   1423   1.1   gdamore 
   1424   1.9    plunky 		dlc->rd_state = RFCOMM_DLC_WAIT_RECV_UA;
   1425   1.1   gdamore 	}
   1426   1.1   gdamore 	return;
   1427   1.1   gdamore 
   1428   1.1   gdamore close:
   1429   1.1   gdamore 	rfcomm_dlc_close(dlc, err);
   1430   1.1   gdamore }
   1431   1.1   gdamore 
   1432   1.1   gdamore /*
   1433   1.1   gdamore  * process Non Supported Command command/response
   1434   1.1   gdamore  */
   1435   1.1   gdamore static void
   1436   1.3  christos rfcomm_session_recv_mcc_nsc(struct rfcomm_session *rs,
   1437   1.4  christos     int cr, struct mbuf *m)
   1438   1.1   gdamore {
   1439   1.2    plunky 	struct rfcomm_dlc *dlc, *next;
   1440   1.1   gdamore 
   1441   1.1   gdamore 	/*
   1442   1.1   gdamore 	 * Since we did nothing that is not mandatory,
   1443   1.1   gdamore 	 * we just abort the whole session..
   1444   1.1   gdamore 	 */
   1445   1.2    plunky 
   1446   1.2    plunky 	next = LIST_FIRST(&rs->rs_dlcs);
   1447   1.2    plunky 	while ((dlc = next) != NULL) {
   1448   1.2    plunky 		next = LIST_NEXT(dlc, rd_next);
   1449   1.1   gdamore 		rfcomm_dlc_close(dlc, ECONNABORTED);
   1450   1.2    plunky 	}
   1451   1.1   gdamore 
   1452   1.1   gdamore 	rfcomm_session_free(rs);
   1453   1.1   gdamore }
   1454   1.1   gdamore 
   1455   1.1   gdamore /***********************************************************************
   1456   1.1   gdamore  *
   1457   1.1   gdamore  *	RFCOMM Session outward frame/uih/mcc building
   1458   1.1   gdamore  */
   1459   1.1   gdamore 
   1460   1.1   gdamore /*
   1461   1.1   gdamore  * SABM/DISC/DM/UA frames are all minimal and mostly identical.
   1462   1.1   gdamore  */
   1463   1.1   gdamore int
   1464   1.1   gdamore rfcomm_session_send_frame(struct rfcomm_session *rs, int type, int dlci)
   1465   1.1   gdamore {
   1466   1.1   gdamore 	struct rfcomm_cmd_hdr *hdr;
   1467   1.1   gdamore 	struct rfcomm_credit *credit;
   1468   1.1   gdamore 	struct mbuf *m;
   1469   1.1   gdamore 	uint8_t fcs, cr;
   1470   1.1   gdamore 
   1471   1.1   gdamore 	credit = pool_get(&rfcomm_credit_pool, PR_NOWAIT);
   1472   1.1   gdamore 	if (credit == NULL)
   1473   1.1   gdamore 		return ENOMEM;
   1474   1.1   gdamore 
   1475   1.1   gdamore 	m = m_gethdr(M_DONTWAIT, MT_DATA);
   1476   1.1   gdamore 	if (m == NULL) {
   1477   1.1   gdamore 		pool_put(&rfcomm_credit_pool, credit);
   1478   1.1   gdamore 		return ENOMEM;
   1479   1.1   gdamore 	}
   1480   1.1   gdamore 
   1481   1.1   gdamore 	/*
   1482   1.1   gdamore 	 * The CR (command/response) bit identifies the frame either as a
   1483  1.28   msaitoh 	 * command or a response and is used along with the DLCI to form
   1484   1.1   gdamore 	 * the address. Commands contain the non-initiator address, whereas
   1485   1.1   gdamore 	 * responses contain the initiator address, so the CR value is
   1486   1.1   gdamore 	 * also dependent on the session direction.
   1487   1.1   gdamore 	 */
   1488   1.1   gdamore 	if (type == RFCOMM_FRAME_UA || type == RFCOMM_FRAME_DM)
   1489   1.1   gdamore 		cr = IS_INITIATOR(rs) ? 0 : 1;
   1490   1.1   gdamore 	else
   1491   1.1   gdamore 		cr = IS_INITIATOR(rs) ? 1 : 0;
   1492   1.1   gdamore 
   1493   1.1   gdamore 	hdr = mtod(m, struct rfcomm_cmd_hdr *);
   1494   1.1   gdamore 	hdr->address = RFCOMM_MKADDRESS(cr, dlci);
   1495   1.1   gdamore 	hdr->control = RFCOMM_MKCONTROL(type, 1);   /* PF = 1 */
   1496   1.1   gdamore 	hdr->length = (0x00 << 1) | 0x01;	    /* len = 0x00, EA = 1 */
   1497   1.1   gdamore 
   1498   1.1   gdamore 	fcs = 0xff;
   1499   1.1   gdamore 	fcs = FCS(fcs, hdr->address);
   1500   1.1   gdamore 	fcs = FCS(fcs, hdr->control);
   1501   1.1   gdamore 	fcs = FCS(fcs, hdr->length);
   1502   1.1   gdamore 	fcs = 0xff - fcs;	/* ones complement */
   1503   1.1   gdamore 	hdr->fcs = fcs;
   1504   1.1   gdamore 
   1505   1.1   gdamore 	m->m_pkthdr.len = m->m_len = sizeof(struct rfcomm_cmd_hdr);
   1506   1.1   gdamore 
   1507   1.1   gdamore 	/* empty credit note */
   1508   1.1   gdamore 	credit->rc_dlc = NULL;
   1509   1.1   gdamore 	credit->rc_len = m->m_pkthdr.len;
   1510   1.1   gdamore 	SIMPLEQ_INSERT_TAIL(&rs->rs_credits, credit, rc_next);
   1511   1.1   gdamore 
   1512   1.1   gdamore 	DPRINTFN(5, "dlci %d type %2.2x (%d bytes, fcs=%#2.2x)\n",
   1513   1.1   gdamore 		dlci, type, m->m_pkthdr.len, fcs);
   1514   1.1   gdamore 
   1515  1.23       rtr 	return l2cap_send_pcb(rs->rs_l2cap, m);
   1516   1.1   gdamore }
   1517   1.1   gdamore 
   1518   1.1   gdamore /*
   1519   1.1   gdamore  * rfcomm_session_send_uih(rfcomm_session, rfcomm_dlc, credits, mbuf)
   1520   1.1   gdamore  *
   1521   1.1   gdamore  * UIH frame is per DLC data or Multiplexer Control Commands
   1522   1.1   gdamore  * when no DLC is given. Data mbuf is optional (just credits
   1523   1.1   gdamore  * will be sent in that case)
   1524   1.1   gdamore  */
   1525   1.1   gdamore int
   1526   1.1   gdamore rfcomm_session_send_uih(struct rfcomm_session *rs, struct rfcomm_dlc *dlc,
   1527   1.1   gdamore 			int credits, struct mbuf *m)
   1528   1.1   gdamore {
   1529   1.1   gdamore 	struct rfcomm_credit *credit;
   1530   1.1   gdamore 	struct mbuf *m0 = NULL;
   1531   1.1   gdamore 	int err, len;
   1532   1.1   gdamore 	uint8_t fcs, *hdr;
   1533   1.1   gdamore 
   1534   1.1   gdamore 	KASSERT(rs != NULL);
   1535   1.1   gdamore 
   1536   1.1   gdamore 	len = (m == NULL) ? 0 : m->m_pkthdr.len;
   1537   1.1   gdamore 	KASSERT(!(credits == 0 && len == 0));
   1538   1.1   gdamore 
   1539   1.1   gdamore 	/*
   1540   1.1   gdamore 	 * Make a credit note for the completion notification
   1541   1.1   gdamore 	 */
   1542   1.1   gdamore 	credit = pool_get(&rfcomm_credit_pool, PR_NOWAIT);
   1543   1.1   gdamore 	if (credit == NULL)
   1544   1.1   gdamore 		goto nomem;
   1545   1.1   gdamore 
   1546   1.1   gdamore 	credit->rc_len = len;
   1547   1.1   gdamore 	credit->rc_dlc = dlc;
   1548   1.1   gdamore 
   1549   1.1   gdamore 	/*
   1550   1.1   gdamore 	 * Wrap UIH frame information around payload.
   1551   1.1   gdamore 	 *
   1552   1.1   gdamore 	 * [ADDRESS] [CONTROL] [LENGTH] [CREDITS] [...] [FCS]
   1553   1.1   gdamore 	 *
   1554   1.1   gdamore 	 * Address is one octet.
   1555   1.1   gdamore 	 * Control is one octet.
   1556   1.1   gdamore 	 * Length is one or two octets.
   1557   1.1   gdamore 	 * Credits may be one octet.
   1558   1.1   gdamore 	 *
   1559   1.1   gdamore 	 * FCS is one octet and calculated on address and
   1560   1.1   gdamore 	 *	control octets only.
   1561   1.1   gdamore 	 *
   1562   1.1   gdamore 	 * If there are credits to be sent, we will set the PF
   1563   1.1   gdamore 	 * flag and include them in the frame.
   1564   1.1   gdamore 	 */
   1565   1.1   gdamore 	m0 = m_gethdr(M_DONTWAIT, MT_DATA);
   1566   1.1   gdamore 	if (m0 == NULL)
   1567   1.1   gdamore 		goto nomem;
   1568   1.1   gdamore 
   1569  1.25      maxv 	m_align(m0, 5);	/* (max 5 header octets) */
   1570   1.1   gdamore 	hdr = mtod(m0, uint8_t *);
   1571   1.1   gdamore 
   1572   1.1   gdamore 	/* CR bit is set according to the initiator of the session */
   1573   1.1   gdamore 	*hdr = RFCOMM_MKADDRESS((IS_INITIATOR(rs) ? 1 : 0),
   1574   1.1   gdamore 				(dlc ? dlc->rd_dlci : 0));
   1575   1.1   gdamore 	fcs = FCS(0xff, *hdr);
   1576   1.1   gdamore 	hdr++;
   1577   1.1   gdamore 
   1578   1.1   gdamore 	/* PF bit is set if credits are being sent */
   1579   1.1   gdamore 	*hdr = RFCOMM_MKCONTROL(RFCOMM_FRAME_UIH, (credits > 0 ? 1 : 0));
   1580   1.1   gdamore 	fcs = FCS(fcs, *hdr);
   1581   1.1   gdamore 	hdr++;
   1582   1.1   gdamore 
   1583   1.1   gdamore 	if (len < (1 << 7)) {
   1584   1.1   gdamore 		*hdr++ = ((len << 1) & 0xfe) | 0x01;	/* 7 bits, EA = 1 */
   1585   1.1   gdamore 	} else {
   1586   1.1   gdamore 		*hdr++ = ((len << 1) & 0xfe);		/* 7 bits, EA = 0 */
   1587   1.1   gdamore 		*hdr++ = ((len >> 7) & 0xff);		/* 8 bits, no EA */
   1588   1.1   gdamore 	}
   1589   1.1   gdamore 
   1590   1.1   gdamore 	if (credits > 0)
   1591   1.1   gdamore 		*hdr++ = (uint8_t)credits;
   1592   1.1   gdamore 
   1593   1.1   gdamore 	m0->m_len = hdr - mtod(m0, uint8_t *);
   1594   1.1   gdamore 
   1595   1.1   gdamore 	/* Append payload */
   1596   1.1   gdamore 	m0->m_next = m;
   1597   1.1   gdamore 	m = NULL;
   1598   1.1   gdamore 
   1599   1.1   gdamore 	m0->m_pkthdr.len = m0->m_len + len;
   1600   1.1   gdamore 
   1601   1.1   gdamore 	/* Append FCS */
   1602   1.1   gdamore 	fcs = 0xff - fcs;	/* ones complement */
   1603   1.1   gdamore 	len = m0->m_pkthdr.len;
   1604   1.1   gdamore 	m_copyback(m0, len, sizeof(fcs), &fcs);
   1605   1.1   gdamore 	if (m0->m_pkthdr.len != len + sizeof(fcs))
   1606   1.1   gdamore 		goto nomem;
   1607   1.1   gdamore 
   1608   1.1   gdamore 	DPRINTFN(10, "dlci %d, pktlen %d (%d data, %d credits), fcs=%#2.2x\n",
   1609   1.1   gdamore 		dlc ? dlc->rd_dlci : 0, m0->m_pkthdr.len, credit->rc_len,
   1610   1.1   gdamore 		credits, fcs);
   1611   1.1   gdamore 
   1612   1.1   gdamore 	/*
   1613   1.1   gdamore 	 * UIH frame ready to go..
   1614   1.1   gdamore 	 */
   1615  1.23       rtr 	err = l2cap_send_pcb(rs->rs_l2cap, m0);
   1616   1.1   gdamore 	if (err)
   1617   1.1   gdamore 		goto fail;
   1618   1.1   gdamore 
   1619   1.1   gdamore 	SIMPLEQ_INSERT_TAIL(&rs->rs_credits, credit, rc_next);
   1620   1.1   gdamore 	return 0;
   1621   1.1   gdamore 
   1622   1.1   gdamore nomem:
   1623   1.1   gdamore 	err = ENOMEM;
   1624   1.1   gdamore 
   1625   1.1   gdamore 	if (m0 != NULL)
   1626   1.1   gdamore 		m_freem(m0);
   1627   1.1   gdamore 
   1628   1.1   gdamore 	if (m != NULL)
   1629   1.1   gdamore 		m_freem(m);
   1630   1.1   gdamore 
   1631   1.1   gdamore fail:
   1632   1.1   gdamore 	if (credit != NULL)
   1633   1.1   gdamore 		pool_put(&rfcomm_credit_pool, credit);
   1634   1.1   gdamore 
   1635   1.1   gdamore 	return err;
   1636   1.1   gdamore }
   1637   1.1   gdamore 
   1638   1.1   gdamore /*
   1639   1.1   gdamore  * send Multiplexer Control Command (or Response) on session
   1640   1.1   gdamore  */
   1641   1.1   gdamore int
   1642   1.1   gdamore rfcomm_session_send_mcc(struct rfcomm_session *rs, int cr,
   1643   1.1   gdamore 			uint8_t type, void *data, int len)
   1644   1.1   gdamore {
   1645   1.1   gdamore 	struct mbuf *m;
   1646   1.1   gdamore 	uint8_t *hdr;
   1647   1.1   gdamore 	int hlen;
   1648   1.1   gdamore 
   1649   1.1   gdamore 	m = m_gethdr(M_DONTWAIT, MT_DATA);
   1650   1.1   gdamore 	if (m == NULL)
   1651   1.1   gdamore 		return ENOMEM;
   1652   1.1   gdamore 
   1653   1.1   gdamore 	hdr = mtod(m, uint8_t *);
   1654   1.1   gdamore 
   1655   1.1   gdamore 	/*
   1656   1.1   gdamore 	 * Technically the type field can extend past one octet, but none
   1657   1.1   gdamore 	 * currently defined will do that.
   1658   1.1   gdamore 	 */
   1659   1.1   gdamore 	*hdr++ = RFCOMM_MKMCC_TYPE(cr, type);
   1660   1.1   gdamore 
   1661   1.1   gdamore 	/*
   1662   1.1   gdamore 	 * In the frame, the max length size is 2 octets (15 bits) whereas
   1663   1.1   gdamore 	 * no max length size is specified for MCC commands. We must allow
   1664   1.1   gdamore 	 * for 3 octets since for MCC frames we use 7 bits + EA in each.
   1665   1.1   gdamore 	 *
   1666   1.1   gdamore 	 * Only test data can possibly be that big.
   1667   1.1   gdamore 	 *
   1668   1.1   gdamore 	 * XXX Should we check this against the MTU?
   1669   1.1   gdamore 	 */
   1670   1.1   gdamore 	if (len < (1 << 7)) {
   1671   1.1   gdamore 		*hdr++ = ((len << 1) & 0xfe) | 0x01;	/* 7 bits, EA = 1 */
   1672   1.1   gdamore 	} else if (len < (1 << 14)) {
   1673   1.1   gdamore 		*hdr++ = ((len << 1) & 0xfe);		/* 7 bits, EA = 0 */
   1674   1.1   gdamore 		*hdr++ = ((len >> 6) & 0xfe) | 0x01;	/* 7 bits, EA = 1 */
   1675   1.1   gdamore 	} else if (len < (1 << 15)) {
   1676   1.1   gdamore 		*hdr++ = ((len << 1) & 0xfe);		/* 7 bits, EA = 0 */
   1677   1.1   gdamore 		*hdr++ = ((len >> 6) & 0xfe);		/* 7 bits, EA = 0 */
   1678   1.1   gdamore 		*hdr++ = ((len >> 13) & 0x02) | 0x01;	/* 1 bit,  EA = 1 */
   1679   1.1   gdamore 	} else {
   1680   1.1   gdamore 		DPRINTF("incredible length! (%d)\n", len);
   1681   1.1   gdamore 		m_freem(m);
   1682   1.1   gdamore 		return EMSGSIZE;
   1683   1.1   gdamore 	}
   1684   1.1   gdamore 
   1685   1.1   gdamore 	/*
   1686   1.1   gdamore 	 * add command data (to same mbuf if possible)
   1687   1.1   gdamore 	 */
   1688   1.1   gdamore 	hlen = hdr - mtod(m, uint8_t *);
   1689   1.1   gdamore 
   1690   1.1   gdamore 	if (len > 0) {
   1691   1.1   gdamore 		m->m_pkthdr.len = m->m_len = MHLEN;
   1692   1.1   gdamore 		m_copyback(m, hlen, len, data);
   1693  1.24  riastrad 		if (m->m_pkthdr.len != uimax(MHLEN, hlen + len)) {
   1694   1.1   gdamore 			m_freem(m);
   1695   1.1   gdamore 			return ENOMEM;
   1696   1.1   gdamore 		}
   1697   1.1   gdamore 	}
   1698   1.1   gdamore 
   1699   1.1   gdamore 	m->m_pkthdr.len = hlen + len;
   1700  1.24  riastrad 	m->m_len = uimin(MHLEN, m->m_pkthdr.len);
   1701   1.1   gdamore 
   1702   1.1   gdamore 	DPRINTFN(5, "%s type %2.2x len %d\n",
   1703   1.1   gdamore 		(cr ? "command" : "response"), type, m->m_pkthdr.len);
   1704   1.1   gdamore 
   1705   1.1   gdamore 	return rfcomm_session_send_uih(rs, NULL, 0, m);
   1706   1.1   gdamore }
   1707