rfcomm_session.c revision 1.17 1 1.17 plunky /* $NetBSD: rfcomm_session.c,v 1.17 2010/11/17 20:19:25 plunky 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.17 plunky __KERNEL_RCSID(0, "$NetBSD: rfcomm_session.c,v 1.17 2010/11/17 20:19:25 plunky 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.1 gdamore err = l2cap_attach(&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.1 gdamore (void)l2cap_bind(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.1 gdamore l2cap_detach(&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.1 gdamore l2cap_sockaddr(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.1 gdamore l2cap_peeraddr(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 #ifdef DIAGNOSTIC
460 1.1 gdamore if (credit == NULL) {
461 1.1 gdamore printf("%s: too many packets completed!\n", __func__);
462 1.1 gdamore break;
463 1.1 gdamore }
464 1.1 gdamore #endif
465 1.1 gdamore dlc = credit->rc_dlc;
466 1.1 gdamore if (dlc != NULL) {
467 1.1 gdamore dlc->rd_pending--;
468 1.1 gdamore (*dlc->rd_proto->complete)
469 1.1 gdamore (dlc->rd_upper, credit->rc_len);
470 1.1 gdamore
471 1.1 gdamore /*
472 1.1 gdamore * if not using credit flow control, we may push
473 1.1 gdamore * more data now
474 1.1 gdamore */
475 1.1 gdamore if ((rs->rs_flags & RFCOMM_SESSION_CFC) == 0
476 1.1 gdamore && dlc->rd_state == RFCOMM_DLC_OPEN) {
477 1.1 gdamore rfcomm_dlc_start(dlc);
478 1.1 gdamore }
479 1.1 gdamore
480 1.1 gdamore /*
481 1.1 gdamore * When shutdown is indicated, we are just waiting to
482 1.1 gdamore * clear outgoing data.
483 1.1 gdamore */
484 1.1 gdamore if ((dlc->rd_flags & RFCOMM_DLC_SHUTDOWN)
485 1.1 gdamore && dlc->rd_txbuf == NULL && dlc->rd_pending == 0) {
486 1.1 gdamore dlc->rd_state = RFCOMM_DLC_WAIT_DISCONNECT;
487 1.1 gdamore rfcomm_session_send_frame(rs, RFCOMM_FRAME_DISC,
488 1.1 gdamore dlc->rd_dlci);
489 1.1 gdamore callout_schedule(&dlc->rd_timeout,
490 1.1 gdamore rfcomm_ack_timeout * hz);
491 1.1 gdamore }
492 1.1 gdamore }
493 1.1 gdamore
494 1.1 gdamore SIMPLEQ_REMOVE_HEAD(&rs->rs_credits, rc_next);
495 1.1 gdamore pool_put(&rfcomm_credit_pool, credit);
496 1.1 gdamore }
497 1.1 gdamore
498 1.1 gdamore /*
499 1.1 gdamore * If session is closed, we are just waiting to clear the queue
500 1.1 gdamore */
501 1.1 gdamore if (rs->rs_state == RFCOMM_SESSION_CLOSED) {
502 1.1 gdamore if (SIMPLEQ_EMPTY(&rs->rs_credits))
503 1.1 gdamore l2cap_disconnect(rs->rs_l2cap, 0);
504 1.1 gdamore }
505 1.1 gdamore }
506 1.1 gdamore
507 1.1 gdamore /*
508 1.9 plunky * Link Mode changed
509 1.9 plunky *
510 1.9 plunky * This is called when a mode change is complete. Proceed with connections
511 1.9 plunky * where appropriate, or pass the new mode to any active DLCs.
512 1.9 plunky */
513 1.9 plunky static void
514 1.9 plunky rfcomm_session_linkmode(void *arg, int new)
515 1.9 plunky {
516 1.9 plunky struct rfcomm_session *rs = arg;
517 1.9 plunky struct rfcomm_dlc *dlc, *next;
518 1.9 plunky int err, mode = 0;
519 1.9 plunky
520 1.9 plunky DPRINTF("auth %s, encrypt %s, secure %s\n",
521 1.9 plunky (new & L2CAP_LM_AUTH ? "on" : "off"),
522 1.9 plunky (new & L2CAP_LM_ENCRYPT ? "on" : "off"),
523 1.9 plunky (new & L2CAP_LM_SECURE ? "on" : "off"));
524 1.9 plunky
525 1.9 plunky if (new & L2CAP_LM_AUTH)
526 1.9 plunky mode |= RFCOMM_LM_AUTH;
527 1.9 plunky
528 1.9 plunky if (new & L2CAP_LM_ENCRYPT)
529 1.9 plunky mode |= RFCOMM_LM_ENCRYPT;
530 1.9 plunky
531 1.9 plunky if (new & L2CAP_LM_SECURE)
532 1.9 plunky mode |= RFCOMM_LM_SECURE;
533 1.9 plunky
534 1.9 plunky next = LIST_FIRST(&rs->rs_dlcs);
535 1.9 plunky while ((dlc = next) != NULL) {
536 1.9 plunky next = LIST_NEXT(dlc, rd_next);
537 1.9 plunky
538 1.9 plunky switch (dlc->rd_state) {
539 1.9 plunky case RFCOMM_DLC_WAIT_SEND_SABM: /* we are connecting */
540 1.9 plunky if ((mode & dlc->rd_mode) != dlc->rd_mode) {
541 1.9 plunky rfcomm_dlc_close(dlc, ECONNABORTED);
542 1.9 plunky } else {
543 1.9 plunky err = rfcomm_session_send_frame(rs,
544 1.9 plunky RFCOMM_FRAME_SABM, dlc->rd_dlci);
545 1.9 plunky if (err) {
546 1.9 plunky rfcomm_dlc_close(dlc, err);
547 1.9 plunky } else {
548 1.9 plunky dlc->rd_state = RFCOMM_DLC_WAIT_RECV_UA;
549 1.9 plunky callout_schedule(&dlc->rd_timeout,
550 1.9 plunky rfcomm_ack_timeout * hz);
551 1.9 plunky break;
552 1.9 plunky }
553 1.9 plunky }
554 1.9 plunky
555 1.9 plunky /*
556 1.9 plunky * If we aborted the connection and there are no more DLCs
557 1.9 plunky * on the session, it is our responsibility to disconnect.
558 1.9 plunky */
559 1.9 plunky if (!LIST_EMPTY(&rs->rs_dlcs))
560 1.9 plunky break;
561 1.9 plunky
562 1.9 plunky rs->rs_state = RFCOMM_SESSION_WAIT_DISCONNECT;
563 1.9 plunky rfcomm_session_send_frame(rs, RFCOMM_FRAME_DISC, 0);
564 1.9 plunky callout_schedule(&rs->rs_timeout, rfcomm_ack_timeout * hz);
565 1.9 plunky break;
566 1.9 plunky
567 1.9 plunky case RFCOMM_DLC_WAIT_SEND_UA: /* they are connecting */
568 1.9 plunky if ((mode & dlc->rd_mode) != dlc->rd_mode) {
569 1.9 plunky rfcomm_session_send_frame(rs,
570 1.9 plunky RFCOMM_FRAME_DM, dlc->rd_dlci);
571 1.9 plunky rfcomm_dlc_close(dlc, ECONNABORTED);
572 1.9 plunky break;
573 1.9 plunky }
574 1.9 plunky
575 1.9 plunky err = rfcomm_session_send_frame(rs,
576 1.9 plunky RFCOMM_FRAME_UA, dlc->rd_dlci);
577 1.9 plunky if (err) {
578 1.9 plunky rfcomm_session_send_frame(rs,
579 1.9 plunky RFCOMM_FRAME_DM, dlc->rd_dlci);
580 1.9 plunky rfcomm_dlc_close(dlc, err);
581 1.9 plunky break;
582 1.9 plunky }
583 1.9 plunky
584 1.9 plunky err = rfcomm_dlc_open(dlc);
585 1.9 plunky if (err) {
586 1.9 plunky rfcomm_session_send_frame(rs,
587 1.9 plunky RFCOMM_FRAME_DM, dlc->rd_dlci);
588 1.9 plunky rfcomm_dlc_close(dlc, err);
589 1.9 plunky break;
590 1.9 plunky }
591 1.9 plunky
592 1.9 plunky break;
593 1.9 plunky
594 1.9 plunky case RFCOMM_DLC_WAIT_RECV_UA:
595 1.9 plunky case RFCOMM_DLC_OPEN: /* already established */
596 1.9 plunky (*dlc->rd_proto->linkmode)(dlc->rd_upper, mode);
597 1.9 plunky break;
598 1.9 plunky
599 1.9 plunky default:
600 1.9 plunky break;
601 1.9 plunky }
602 1.9 plunky }
603 1.9 plunky }
604 1.9 plunky
605 1.9 plunky /*
606 1.1 gdamore * Receive data from L2CAP layer for session. There is always exactly one
607 1.1 gdamore * RFCOMM frame contained in each L2CAP frame.
608 1.1 gdamore */
609 1.1 gdamore static void
610 1.1 gdamore rfcomm_session_input(void *arg, struct mbuf *m)
611 1.1 gdamore {
612 1.1 gdamore struct rfcomm_session *rs = arg;
613 1.1 gdamore int dlci, len, type, pf;
614 1.1 gdamore uint8_t fcs, b;
615 1.1 gdamore
616 1.1 gdamore KASSERT(m != NULL);
617 1.1 gdamore KASSERT(rs != NULL);
618 1.1 gdamore
619 1.1 gdamore /*
620 1.1 gdamore * UIH frames: FCS is only calculated on address and control fields
621 1.1 gdamore * For other frames: FCS is calculated on address, control and length
622 1.1 gdamore * Length may extend to two octets
623 1.1 gdamore */
624 1.1 gdamore fcs = 0xff;
625 1.1 gdamore
626 1.1 gdamore if (m->m_pkthdr.len < 4) {
627 1.1 gdamore DPRINTF("short frame (%d), discarded\n", m->m_pkthdr.len);
628 1.1 gdamore goto done;
629 1.1 gdamore }
630 1.1 gdamore
631 1.1 gdamore /* address - one octet */
632 1.1 gdamore m_copydata(m, 0, 1, &b);
633 1.1 gdamore m_adj(m, 1);
634 1.1 gdamore fcs = FCS(fcs, b);
635 1.1 gdamore dlci = RFCOMM_DLCI(b);
636 1.1 gdamore
637 1.1 gdamore /* control - one octet */
638 1.1 gdamore m_copydata(m, 0, 1, &b);
639 1.1 gdamore m_adj(m, 1);
640 1.1 gdamore fcs = FCS(fcs, b);
641 1.1 gdamore type = RFCOMM_TYPE(b);
642 1.1 gdamore pf = RFCOMM_PF(b);
643 1.1 gdamore
644 1.1 gdamore /* length - may be two octets */
645 1.1 gdamore m_copydata(m, 0, 1, &b);
646 1.1 gdamore m_adj(m, 1);
647 1.1 gdamore if (type != RFCOMM_FRAME_UIH)
648 1.1 gdamore fcs = FCS(fcs, b);
649 1.1 gdamore len = (b >> 1) & 0x7f;
650 1.1 gdamore
651 1.1 gdamore if (RFCOMM_EA(b) == 0) {
652 1.1 gdamore if (m->m_pkthdr.len < 2) {
653 1.1 gdamore DPRINTF("short frame (%d, EA = 0), discarded\n",
654 1.1 gdamore m->m_pkthdr.len);
655 1.1 gdamore goto done;
656 1.1 gdamore }
657 1.1 gdamore
658 1.1 gdamore m_copydata(m, 0, 1, &b);
659 1.1 gdamore m_adj(m, 1);
660 1.1 gdamore if (type != RFCOMM_FRAME_UIH)
661 1.1 gdamore fcs = FCS(fcs, b);
662 1.1 gdamore
663 1.1 gdamore len |= (b << 7);
664 1.1 gdamore }
665 1.1 gdamore
666 1.1 gdamore /* FCS byte is last octet in frame */
667 1.1 gdamore m_copydata(m, m->m_pkthdr.len - 1, 1, &b);
668 1.1 gdamore m_adj(m, -1);
669 1.1 gdamore fcs = FCS(fcs, b);
670 1.1 gdamore
671 1.1 gdamore if (fcs != 0xcf) {
672 1.1 gdamore DPRINTF("Bad FCS value (%#2.2x), frame discarded\n", fcs);
673 1.1 gdamore goto done;
674 1.1 gdamore }
675 1.1 gdamore
676 1.1 gdamore DPRINTFN(10, "dlci %d, type %2.2x, len = %d\n", dlci, type, len);
677 1.1 gdamore
678 1.1 gdamore switch (type) {
679 1.1 gdamore case RFCOMM_FRAME_SABM:
680 1.1 gdamore if (pf)
681 1.1 gdamore rfcomm_session_recv_sabm(rs, dlci);
682 1.1 gdamore break;
683 1.1 gdamore
684 1.1 gdamore case RFCOMM_FRAME_DISC:
685 1.1 gdamore if (pf)
686 1.1 gdamore rfcomm_session_recv_disc(rs, dlci);
687 1.1 gdamore break;
688 1.1 gdamore
689 1.1 gdamore case RFCOMM_FRAME_UA:
690 1.1 gdamore if (pf)
691 1.1 gdamore rfcomm_session_recv_ua(rs, dlci);
692 1.1 gdamore break;
693 1.1 gdamore
694 1.1 gdamore case RFCOMM_FRAME_DM:
695 1.1 gdamore rfcomm_session_recv_dm(rs, dlci);
696 1.1 gdamore break;
697 1.1 gdamore
698 1.1 gdamore case RFCOMM_FRAME_UIH:
699 1.1 gdamore rfcomm_session_recv_uih(rs, dlci, pf, m, len);
700 1.1 gdamore return; /* (no release) */
701 1.1 gdamore
702 1.1 gdamore default:
703 1.1 gdamore UNKNOWN(type);
704 1.1 gdamore break;
705 1.1 gdamore }
706 1.1 gdamore
707 1.1 gdamore done:
708 1.1 gdamore m_freem(m);
709 1.1 gdamore }
710 1.1 gdamore
711 1.1 gdamore /***********************************************************************
712 1.1 gdamore *
713 1.1 gdamore * RFCOMM Session receive processing
714 1.1 gdamore */
715 1.1 gdamore
716 1.1 gdamore /*
717 1.1 gdamore * rfcomm_session_recv_sabm(rfcomm_session, dlci)
718 1.1 gdamore *
719 1.1 gdamore * Set Asyncrhonous Balanced Mode - open the channel.
720 1.1 gdamore */
721 1.1 gdamore static void
722 1.1 gdamore rfcomm_session_recv_sabm(struct rfcomm_session *rs, int dlci)
723 1.1 gdamore {
724 1.1 gdamore struct rfcomm_dlc *dlc;
725 1.1 gdamore int err;
726 1.1 gdamore
727 1.1 gdamore DPRINTFN(5, "SABM(%d)\n", dlci);
728 1.1 gdamore
729 1.1 gdamore if (dlci == 0) { /* Open Session */
730 1.1 gdamore rs->rs_state = RFCOMM_SESSION_OPEN;
731 1.1 gdamore rfcomm_session_send_frame(rs, RFCOMM_FRAME_UA, 0);
732 1.1 gdamore LIST_FOREACH(dlc, &rs->rs_dlcs, rd_next) {
733 1.1 gdamore if (dlc->rd_state == RFCOMM_DLC_WAIT_SESSION)
734 1.1 gdamore rfcomm_dlc_connect(dlc);
735 1.1 gdamore }
736 1.1 gdamore return;
737 1.1 gdamore }
738 1.1 gdamore
739 1.1 gdamore if (rs->rs_state != RFCOMM_SESSION_OPEN) {
740 1.1 gdamore DPRINTF("session was not even open!\n");
741 1.1 gdamore return;
742 1.1 gdamore }
743 1.1 gdamore
744 1.1 gdamore /* validate direction bit */
745 1.1 gdamore if ((IS_INITIATOR(rs) && !RFCOMM_DIRECTION(dlci))
746 1.1 gdamore || (!IS_INITIATOR(rs) && RFCOMM_DIRECTION(dlci))) {
747 1.1 gdamore DPRINTF("Invalid direction bit on DLCI\n");
748 1.1 gdamore return;
749 1.1 gdamore }
750 1.1 gdamore
751 1.1 gdamore /*
752 1.1 gdamore * look for our DLC - this may exist if we received PN
753 1.1 gdamore * already, or we may have to fabricate a new one.
754 1.1 gdamore */
755 1.1 gdamore dlc = rfcomm_dlc_lookup(rs, dlci);
756 1.1 gdamore if (dlc == NULL) {
757 1.1 gdamore dlc = rfcomm_dlc_newconn(rs, dlci);
758 1.1 gdamore if (dlc == NULL)
759 1.1 gdamore return; /* (DM is sent) */
760 1.1 gdamore }
761 1.1 gdamore
762 1.9 plunky /*
763 1.9 plunky * ..but if this DLC is not waiting to connect, they did
764 1.9 plunky * something wrong, ignore it.
765 1.9 plunky */
766 1.9 plunky if (dlc->rd_state != RFCOMM_DLC_WAIT_CONNECT)
767 1.9 plunky return;
768 1.1 gdamore
769 1.9 plunky /* set link mode */
770 1.9 plunky err = rfcomm_dlc_setmode(dlc);
771 1.9 plunky if (err == EINPROGRESS) {
772 1.9 plunky dlc->rd_state = RFCOMM_DLC_WAIT_SEND_UA;
773 1.9 plunky (*dlc->rd_proto->connecting)(dlc->rd_upper);
774 1.1 gdamore return;
775 1.1 gdamore }
776 1.9 plunky if (err)
777 1.9 plunky goto close;
778 1.1 gdamore
779 1.9 plunky err = rfcomm_session_send_frame(rs, RFCOMM_FRAME_UA, dlci);
780 1.9 plunky if (err)
781 1.9 plunky goto close;
782 1.9 plunky
783 1.9 plunky /* and mark it open */
784 1.9 plunky err = rfcomm_dlc_open(dlc);
785 1.9 plunky if (err)
786 1.9 plunky goto close;
787 1.1 gdamore
788 1.9 plunky return;
789 1.1 gdamore
790 1.9 plunky close:
791 1.9 plunky rfcomm_dlc_close(dlc, err);
792 1.1 gdamore }
793 1.1 gdamore
794 1.1 gdamore /*
795 1.1 gdamore * Receive Disconnect Command
796 1.1 gdamore */
797 1.1 gdamore static void
798 1.1 gdamore rfcomm_session_recv_disc(struct rfcomm_session *rs, int dlci)
799 1.1 gdamore {
800 1.1 gdamore struct rfcomm_dlc *dlc;
801 1.1 gdamore
802 1.1 gdamore DPRINTFN(5, "DISC(%d)\n", dlci);
803 1.1 gdamore
804 1.1 gdamore if (dlci == 0) {
805 1.1 gdamore /*
806 1.1 gdamore * Disconnect Session
807 1.1 gdamore *
808 1.1 gdamore * We set the session state to CLOSED so that when
809 1.1 gdamore * the UA frame is clear the session will be closed
810 1.1 gdamore * automatically. We wont bother to close any DLC's
811 1.1 gdamore * just yet as there should be none. In the unlikely
812 1.1 gdamore * event that something is left, it will get flushed
813 1.1 gdamore * out as the session goes down.
814 1.1 gdamore */
815 1.1 gdamore rfcomm_session_send_frame(rs, RFCOMM_FRAME_UA, 0);
816 1.1 gdamore rs->rs_state = RFCOMM_SESSION_CLOSED;
817 1.1 gdamore return;
818 1.1 gdamore }
819 1.1 gdamore
820 1.1 gdamore dlc = rfcomm_dlc_lookup(rs, dlci);
821 1.1 gdamore if (dlc == NULL) {
822 1.1 gdamore rfcomm_session_send_frame(rs, RFCOMM_FRAME_DM, dlci);
823 1.1 gdamore return;
824 1.1 gdamore }
825 1.1 gdamore
826 1.17 plunky rfcomm_dlc_close(dlc, 0);
827 1.1 gdamore rfcomm_session_send_frame(rs, RFCOMM_FRAME_UA, dlci);
828 1.1 gdamore }
829 1.1 gdamore
830 1.1 gdamore /*
831 1.1 gdamore * Receive Unnumbered Acknowledgement Response
832 1.1 gdamore *
833 1.1 gdamore * This should be a response to a DISC or SABM frame that we
834 1.1 gdamore * have previously sent. If unexpected, ignore it.
835 1.1 gdamore */
836 1.1 gdamore static void
837 1.1 gdamore rfcomm_session_recv_ua(struct rfcomm_session *rs, int dlci)
838 1.1 gdamore {
839 1.1 gdamore struct rfcomm_dlc *dlc;
840 1.1 gdamore
841 1.1 gdamore DPRINTFN(5, "UA(%d)\n", dlci);
842 1.1 gdamore
843 1.1 gdamore if (dlci == 0) {
844 1.1 gdamore switch (rs->rs_state) {
845 1.1 gdamore case RFCOMM_SESSION_WAIT_CONNECT: /* We sent SABM */
846 1.1 gdamore callout_stop(&rs->rs_timeout);
847 1.1 gdamore rs->rs_state = RFCOMM_SESSION_OPEN;
848 1.1 gdamore LIST_FOREACH(dlc, &rs->rs_dlcs, rd_next) {
849 1.1 gdamore if (dlc->rd_state == RFCOMM_DLC_WAIT_SESSION)
850 1.1 gdamore rfcomm_dlc_connect(dlc);
851 1.1 gdamore }
852 1.1 gdamore break;
853 1.1 gdamore
854 1.1 gdamore case RFCOMM_SESSION_WAIT_DISCONNECT: /* We sent DISC */
855 1.1 gdamore callout_stop(&rs->rs_timeout);
856 1.1 gdamore rs->rs_state = RFCOMM_SESSION_CLOSED;
857 1.1 gdamore l2cap_disconnect(rs->rs_l2cap, 0);
858 1.1 gdamore break;
859 1.1 gdamore
860 1.1 gdamore default:
861 1.1 gdamore DPRINTF("Received spurious UA(0)!\n");
862 1.1 gdamore break;
863 1.1 gdamore }
864 1.1 gdamore
865 1.1 gdamore return;
866 1.1 gdamore }
867 1.1 gdamore
868 1.1 gdamore /*
869 1.1 gdamore * If we have no DLC on this dlci, we may have aborted
870 1.1 gdamore * without shutting down properly, so check if the session
871 1.1 gdamore * needs disconnecting.
872 1.1 gdamore */
873 1.1 gdamore dlc = rfcomm_dlc_lookup(rs, dlci);
874 1.1 gdamore if (dlc == NULL)
875 1.1 gdamore goto check;
876 1.1 gdamore
877 1.1 gdamore switch (dlc->rd_state) {
878 1.9 plunky case RFCOMM_DLC_WAIT_RECV_UA: /* We sent SABM */
879 1.9 plunky rfcomm_dlc_open(dlc);
880 1.1 gdamore return;
881 1.1 gdamore
882 1.1 gdamore case RFCOMM_DLC_WAIT_DISCONNECT: /* We sent DISC */
883 1.1 gdamore rfcomm_dlc_close(dlc, 0);
884 1.1 gdamore break;
885 1.1 gdamore
886 1.1 gdamore default:
887 1.1 gdamore DPRINTF("Received spurious UA(%d)!\n", dlci);
888 1.1 gdamore return;
889 1.1 gdamore }
890 1.1 gdamore
891 1.1 gdamore check: /* last one out turns out the light */
892 1.1 gdamore if (LIST_EMPTY(&rs->rs_dlcs)) {
893 1.1 gdamore rs->rs_state = RFCOMM_SESSION_WAIT_DISCONNECT;
894 1.1 gdamore rfcomm_session_send_frame(rs, RFCOMM_FRAME_DISC, 0);
895 1.1 gdamore callout_schedule(&rs->rs_timeout, rfcomm_ack_timeout * hz);
896 1.1 gdamore }
897 1.1 gdamore }
898 1.1 gdamore
899 1.1 gdamore /*
900 1.1 gdamore * Receive Disconnected Mode Response
901 1.1 gdamore *
902 1.1 gdamore * If this does not apply to a known DLC then we may ignore it.
903 1.1 gdamore */
904 1.1 gdamore static void
905 1.1 gdamore rfcomm_session_recv_dm(struct rfcomm_session *rs, int dlci)
906 1.1 gdamore {
907 1.1 gdamore struct rfcomm_dlc *dlc;
908 1.1 gdamore
909 1.1 gdamore DPRINTFN(5, "DM(%d)\n", dlci);
910 1.1 gdamore
911 1.1 gdamore dlc = rfcomm_dlc_lookup(rs, dlci);
912 1.1 gdamore if (dlc == NULL)
913 1.1 gdamore return;
914 1.1 gdamore
915 1.1 gdamore if (dlc->rd_state == RFCOMM_DLC_WAIT_CONNECT)
916 1.1 gdamore rfcomm_dlc_close(dlc, ECONNREFUSED);
917 1.1 gdamore else
918 1.1 gdamore rfcomm_dlc_close(dlc, ECONNRESET);
919 1.1 gdamore }
920 1.1 gdamore
921 1.1 gdamore /*
922 1.1 gdamore * Receive Unnumbered Information with Header check (MCC or data packet)
923 1.1 gdamore */
924 1.1 gdamore static void
925 1.1 gdamore rfcomm_session_recv_uih(struct rfcomm_session *rs, int dlci,
926 1.1 gdamore int pf, struct mbuf *m, int len)
927 1.1 gdamore {
928 1.1 gdamore struct rfcomm_dlc *dlc;
929 1.1 gdamore uint8_t credits = 0;
930 1.1 gdamore
931 1.1 gdamore DPRINTFN(10, "UIH(%d)\n", dlci);
932 1.1 gdamore
933 1.1 gdamore if (dlci == 0) {
934 1.1 gdamore rfcomm_session_recv_mcc(rs, m);
935 1.1 gdamore return;
936 1.1 gdamore }
937 1.1 gdamore
938 1.1 gdamore if (m->m_pkthdr.len != len + pf) {
939 1.1 gdamore DPRINTF("Bad Frame Length (%d), frame discarded\n",
940 1.1 gdamore m->m_pkthdr.len);
941 1.1 gdamore
942 1.1 gdamore goto discard;
943 1.1 gdamore }
944 1.1 gdamore
945 1.1 gdamore dlc = rfcomm_dlc_lookup(rs, dlci);
946 1.1 gdamore if (dlc == NULL) {
947 1.1 gdamore DPRINTF("UIH received for non existent DLC, discarded\n");
948 1.1 gdamore rfcomm_session_send_frame(rs, RFCOMM_FRAME_DM, dlci);
949 1.1 gdamore goto discard;
950 1.1 gdamore }
951 1.1 gdamore
952 1.1 gdamore if (dlc->rd_state != RFCOMM_DLC_OPEN) {
953 1.1 gdamore DPRINTF("non-open DLC (state = %d), discarded\n",
954 1.1 gdamore dlc->rd_state);
955 1.1 gdamore goto discard;
956 1.1 gdamore }
957 1.1 gdamore
958 1.1 gdamore /* if PF is set, credits were included */
959 1.1 gdamore if (rs->rs_flags & RFCOMM_SESSION_CFC) {
960 1.1 gdamore if (pf != 0) {
961 1.1 gdamore if (m->m_pkthdr.len < sizeof(credits)) {
962 1.1 gdamore DPRINTF("Bad PF value, UIH discarded\n");
963 1.1 gdamore goto discard;
964 1.1 gdamore }
965 1.1 gdamore
966 1.1 gdamore m_copydata(m, 0, sizeof(credits), &credits);
967 1.1 gdamore m_adj(m, sizeof(credits));
968 1.1 gdamore
969 1.1 gdamore dlc->rd_txcred += credits;
970 1.1 gdamore
971 1.1 gdamore if (credits > 0 && dlc->rd_txbuf != NULL)
972 1.1 gdamore rfcomm_dlc_start(dlc);
973 1.1 gdamore }
974 1.1 gdamore
975 1.1 gdamore if (len == 0)
976 1.1 gdamore goto discard;
977 1.1 gdamore
978 1.1 gdamore if (dlc->rd_rxcred == 0) {
979 1.1 gdamore DPRINTF("Credit limit reached, UIH discarded\n");
980 1.1 gdamore goto discard;
981 1.1 gdamore }
982 1.1 gdamore
983 1.1 gdamore if (len > dlc->rd_rxsize) {
984 1.1 gdamore DPRINTF("UIH frame exceeds rxsize, discarded\n");
985 1.1 gdamore goto discard;
986 1.1 gdamore }
987 1.1 gdamore
988 1.1 gdamore dlc->rd_rxcred--;
989 1.1 gdamore dlc->rd_rxsize -= len;
990 1.1 gdamore }
991 1.1 gdamore
992 1.1 gdamore (*dlc->rd_proto->input)(dlc->rd_upper, m);
993 1.1 gdamore return;
994 1.1 gdamore
995 1.1 gdamore discard:
996 1.1 gdamore m_freem(m);
997 1.1 gdamore }
998 1.1 gdamore
999 1.1 gdamore /*
1000 1.1 gdamore * Receive Multiplexer Control Command
1001 1.1 gdamore */
1002 1.1 gdamore static void
1003 1.1 gdamore rfcomm_session_recv_mcc(struct rfcomm_session *rs, struct mbuf *m)
1004 1.1 gdamore {
1005 1.1 gdamore int type, cr, len;
1006 1.1 gdamore uint8_t b;
1007 1.1 gdamore
1008 1.1 gdamore /*
1009 1.1 gdamore * Extract MCC header.
1010 1.1 gdamore *
1011 1.1 gdamore * Fields are variable length using extension bit = 1 to signify the
1012 1.1 gdamore * last octet in the sequence.
1013 1.1 gdamore *
1014 1.1 gdamore * Only single octet types are defined in TS 07.10/RFCOMM spec
1015 1.1 gdamore *
1016 1.1 gdamore * Length can realistically only use 15 bits (max RFCOMM MTU)
1017 1.1 gdamore */
1018 1.1 gdamore if (m->m_pkthdr.len < sizeof(b)) {
1019 1.1 gdamore DPRINTF("Short MCC header, discarded\n");
1020 1.1 gdamore goto release;
1021 1.1 gdamore }
1022 1.1 gdamore
1023 1.1 gdamore m_copydata(m, 0, sizeof(b), &b);
1024 1.1 gdamore m_adj(m, sizeof(b));
1025 1.1 gdamore
1026 1.1 gdamore if (RFCOMM_EA(b) == 0) { /* verify no extensions */
1027 1.9 plunky DPRINTF("MCC type EA = 0, discarded\n");
1028 1.1 gdamore goto release;
1029 1.1 gdamore }
1030 1.1 gdamore
1031 1.1 gdamore type = RFCOMM_MCC_TYPE(b);
1032 1.1 gdamore cr = RFCOMM_CR(b);
1033 1.1 gdamore
1034 1.1 gdamore len = 0;
1035 1.1 gdamore do {
1036 1.1 gdamore if (m->m_pkthdr.len < sizeof(b)) {
1037 1.1 gdamore DPRINTF("Short MCC header, discarded\n");
1038 1.1 gdamore goto release;
1039 1.1 gdamore }
1040 1.1 gdamore
1041 1.1 gdamore m_copydata(m, 0, sizeof(b), &b);
1042 1.1 gdamore m_adj(m, sizeof(b));
1043 1.1 gdamore
1044 1.1 gdamore len = (len << 7) | (b >> 1);
1045 1.1 gdamore len = min(len, RFCOMM_MTU_MAX);
1046 1.1 gdamore } while (RFCOMM_EA(b) == 0);
1047 1.1 gdamore
1048 1.1 gdamore if (len != m->m_pkthdr.len) {
1049 1.1 gdamore DPRINTF("Incorrect MCC length, discarded\n");
1050 1.1 gdamore goto release;
1051 1.1 gdamore }
1052 1.1 gdamore
1053 1.1 gdamore DPRINTFN(2, "MCC %s type %2.2x (%d bytes)\n",
1054 1.1 gdamore (cr ? "command" : "response"), type, len);
1055 1.1 gdamore
1056 1.1 gdamore /*
1057 1.1 gdamore * pass to command handler
1058 1.1 gdamore */
1059 1.1 gdamore switch(type) {
1060 1.1 gdamore case RFCOMM_MCC_TEST: /* Test */
1061 1.1 gdamore rfcomm_session_recv_mcc_test(rs, cr, m);
1062 1.1 gdamore break;
1063 1.1 gdamore
1064 1.1 gdamore case RFCOMM_MCC_FCON: /* Flow Control On */
1065 1.1 gdamore rfcomm_session_recv_mcc_fcon(rs, cr);
1066 1.1 gdamore break;
1067 1.1 gdamore
1068 1.1 gdamore case RFCOMM_MCC_FCOFF: /* Flow Control Off */
1069 1.1 gdamore rfcomm_session_recv_mcc_fcoff(rs, cr);
1070 1.1 gdamore break;
1071 1.1 gdamore
1072 1.1 gdamore case RFCOMM_MCC_MSC: /* Modem Status Command */
1073 1.1 gdamore rfcomm_session_recv_mcc_msc(rs, cr, m);
1074 1.1 gdamore break;
1075 1.1 gdamore
1076 1.1 gdamore case RFCOMM_MCC_RPN: /* Remote Port Negotiation */
1077 1.1 gdamore rfcomm_session_recv_mcc_rpn(rs, cr, m);
1078 1.1 gdamore break;
1079 1.1 gdamore
1080 1.1 gdamore case RFCOMM_MCC_RLS: /* Remote Line Status */
1081 1.1 gdamore rfcomm_session_recv_mcc_rls(rs, cr, m);
1082 1.1 gdamore break;
1083 1.1 gdamore
1084 1.1 gdamore case RFCOMM_MCC_PN: /* Parameter Negotiation */
1085 1.1 gdamore rfcomm_session_recv_mcc_pn(rs, cr, m);
1086 1.1 gdamore break;
1087 1.1 gdamore
1088 1.1 gdamore case RFCOMM_MCC_NSC: /* Non Supported Command */
1089 1.1 gdamore rfcomm_session_recv_mcc_nsc(rs, cr, m);
1090 1.1 gdamore break;
1091 1.1 gdamore
1092 1.1 gdamore default:
1093 1.1 gdamore b = RFCOMM_MKMCC_TYPE(cr, type);
1094 1.1 gdamore rfcomm_session_send_mcc(rs, 0, RFCOMM_MCC_NSC, &b, sizeof(b));
1095 1.1 gdamore }
1096 1.1 gdamore
1097 1.1 gdamore release:
1098 1.1 gdamore m_freem(m);
1099 1.1 gdamore }
1100 1.1 gdamore
1101 1.1 gdamore /*
1102 1.1 gdamore * process TEST command/response
1103 1.1 gdamore */
1104 1.1 gdamore static void
1105 1.1 gdamore rfcomm_session_recv_mcc_test(struct rfcomm_session *rs, int cr, struct mbuf *m)
1106 1.1 gdamore {
1107 1.1 gdamore void *data;
1108 1.1 gdamore int len;
1109 1.1 gdamore
1110 1.1 gdamore if (cr == 0) /* ignore ack */
1111 1.1 gdamore return;
1112 1.1 gdamore
1113 1.1 gdamore /*
1114 1.1 gdamore * we must send all the data they included back as is
1115 1.1 gdamore */
1116 1.1 gdamore
1117 1.1 gdamore len = m->m_pkthdr.len;
1118 1.1 gdamore if (len > RFCOMM_MTU_MAX)
1119 1.1 gdamore return;
1120 1.1 gdamore
1121 1.1 gdamore data = malloc(len, M_BLUETOOTH, M_NOWAIT);
1122 1.1 gdamore if (data == NULL)
1123 1.1 gdamore return;
1124 1.1 gdamore
1125 1.1 gdamore m_copydata(m, 0, len, data);
1126 1.1 gdamore rfcomm_session_send_mcc(rs, 0, RFCOMM_MCC_TEST, data, len);
1127 1.1 gdamore free(data, M_BLUETOOTH);
1128 1.1 gdamore }
1129 1.1 gdamore
1130 1.1 gdamore /*
1131 1.1 gdamore * process Flow Control ON command/response
1132 1.1 gdamore */
1133 1.1 gdamore static void
1134 1.1 gdamore rfcomm_session_recv_mcc_fcon(struct rfcomm_session *rs, int cr)
1135 1.1 gdamore {
1136 1.1 gdamore
1137 1.1 gdamore if (cr == 0) /* ignore ack */
1138 1.1 gdamore return;
1139 1.1 gdamore
1140 1.1 gdamore rs->rs_flags |= RFCOMM_SESSION_RFC;
1141 1.1 gdamore rfcomm_session_send_mcc(rs, 0, RFCOMM_MCC_FCON, NULL, 0);
1142 1.1 gdamore }
1143 1.1 gdamore
1144 1.1 gdamore /*
1145 1.1 gdamore * process Flow Control OFF command/response
1146 1.1 gdamore */
1147 1.1 gdamore static void
1148 1.1 gdamore rfcomm_session_recv_mcc_fcoff(struct rfcomm_session *rs, int cr)
1149 1.1 gdamore {
1150 1.1 gdamore
1151 1.1 gdamore if (cr == 0) /* ignore ack */
1152 1.1 gdamore return;
1153 1.1 gdamore
1154 1.1 gdamore rs->rs_flags &= ~RFCOMM_SESSION_RFC;
1155 1.1 gdamore rfcomm_session_send_mcc(rs, 0, RFCOMM_MCC_FCOFF, NULL, 0);
1156 1.1 gdamore }
1157 1.1 gdamore
1158 1.1 gdamore /*
1159 1.1 gdamore * process Modem Status Command command/response
1160 1.1 gdamore */
1161 1.1 gdamore static void
1162 1.1 gdamore rfcomm_session_recv_mcc_msc(struct rfcomm_session *rs, int cr, struct mbuf *m)
1163 1.1 gdamore {
1164 1.1 gdamore struct rfcomm_mcc_msc msc; /* (3 octets) */
1165 1.1 gdamore struct rfcomm_dlc *dlc;
1166 1.1 gdamore int len = 0;
1167 1.1 gdamore
1168 1.1 gdamore /* [ADDRESS] */
1169 1.1 gdamore if (m->m_pkthdr.len < sizeof(msc.address))
1170 1.1 gdamore return;
1171 1.1 gdamore
1172 1.1 gdamore m_copydata(m, 0, sizeof(msc.address), &msc.address);
1173 1.1 gdamore m_adj(m, sizeof(msc.address));
1174 1.1 gdamore len += sizeof(msc.address);
1175 1.1 gdamore
1176 1.1 gdamore dlc = rfcomm_dlc_lookup(rs, RFCOMM_DLCI(msc.address));
1177 1.1 gdamore
1178 1.1 gdamore if (cr == 0) { /* ignore acks */
1179 1.1 gdamore if (dlc != NULL)
1180 1.1 gdamore callout_stop(&dlc->rd_timeout);
1181 1.1 gdamore
1182 1.1 gdamore return;
1183 1.1 gdamore }
1184 1.1 gdamore
1185 1.1 gdamore if (dlc == NULL) {
1186 1.1 gdamore rfcomm_session_send_frame(rs, RFCOMM_FRAME_DM,
1187 1.1 gdamore RFCOMM_DLCI(msc.address));
1188 1.1 gdamore return;
1189 1.1 gdamore }
1190 1.1 gdamore
1191 1.1 gdamore /* [SIGNALS] */
1192 1.1 gdamore if (m->m_pkthdr.len < sizeof(msc.modem))
1193 1.1 gdamore return;
1194 1.1 gdamore
1195 1.1 gdamore m_copydata(m, 0, sizeof(msc.modem), &msc.modem);
1196 1.1 gdamore m_adj(m, sizeof(msc.modem));
1197 1.1 gdamore len += sizeof(msc.modem);
1198 1.1 gdamore
1199 1.1 gdamore dlc->rd_rmodem = msc.modem;
1200 1.7 plunky /* XXX how do we signal this upstream? */
1201 1.1 gdamore
1202 1.1 gdamore if (RFCOMM_EA(msc.modem) == 0) {
1203 1.1 gdamore if (m->m_pkthdr.len < sizeof(msc.brk))
1204 1.1 gdamore return;
1205 1.1 gdamore
1206 1.1 gdamore m_copydata(m, 0, sizeof(msc.brk), &msc.brk);
1207 1.1 gdamore m_adj(m, sizeof(msc.brk));
1208 1.1 gdamore len += sizeof(msc.brk);
1209 1.1 gdamore
1210 1.7 plunky /* XXX how do we signal this upstream? */
1211 1.1 gdamore }
1212 1.1 gdamore
1213 1.1 gdamore rfcomm_session_send_mcc(rs, 0, RFCOMM_MCC_MSC, &msc, len);
1214 1.1 gdamore }
1215 1.1 gdamore
1216 1.1 gdamore /*
1217 1.1 gdamore * process Remote Port Negotiation command/response
1218 1.1 gdamore */
1219 1.1 gdamore static void
1220 1.1 gdamore rfcomm_session_recv_mcc_rpn(struct rfcomm_session *rs, int cr, struct mbuf *m)
1221 1.1 gdamore {
1222 1.1 gdamore struct rfcomm_mcc_rpn rpn;
1223 1.1 gdamore uint16_t mask;
1224 1.1 gdamore
1225 1.1 gdamore if (cr == 0) /* ignore ack */
1226 1.1 gdamore return;
1227 1.1 gdamore
1228 1.1 gdamore /* default values */
1229 1.1 gdamore rpn.bit_rate = RFCOMM_RPN_BR_9600;
1230 1.1 gdamore rpn.line_settings = RFCOMM_RPN_8_N_1;
1231 1.1 gdamore rpn.flow_control = RFCOMM_RPN_FLOW_NONE;
1232 1.1 gdamore rpn.xon_char = RFCOMM_RPN_XON_CHAR;
1233 1.1 gdamore rpn.xoff_char = RFCOMM_RPN_XOFF_CHAR;
1234 1.1 gdamore
1235 1.1 gdamore if (m->m_pkthdr.len == sizeof(rpn)) {
1236 1.1 gdamore m_copydata(m, 0, sizeof(rpn), &rpn);
1237 1.1 gdamore rpn.param_mask = RFCOMM_RPN_PM_ALL;
1238 1.1 gdamore } else if (m->m_pkthdr.len == 1) {
1239 1.1 gdamore m_copydata(m, 0, 1, &rpn);
1240 1.1 gdamore rpn.param_mask = le16toh(rpn.param_mask);
1241 1.1 gdamore } else {
1242 1.1 gdamore DPRINTF("Bad RPN length (%d)\n", m->m_pkthdr.len);
1243 1.1 gdamore return;
1244 1.1 gdamore }
1245 1.1 gdamore
1246 1.1 gdamore mask = 0;
1247 1.1 gdamore
1248 1.1 gdamore if (rpn.param_mask & RFCOMM_RPN_PM_RATE)
1249 1.1 gdamore mask |= RFCOMM_RPN_PM_RATE;
1250 1.1 gdamore
1251 1.1 gdamore if (rpn.param_mask & RFCOMM_RPN_PM_DATA
1252 1.1 gdamore && RFCOMM_RPN_DATA_BITS(rpn.line_settings) == RFCOMM_RPN_DATA_8)
1253 1.1 gdamore mask |= RFCOMM_RPN_PM_DATA;
1254 1.1 gdamore
1255 1.1 gdamore if (rpn.param_mask & RFCOMM_RPN_PM_STOP
1256 1.1 gdamore && RFCOMM_RPN_STOP_BITS(rpn.line_settings) == RFCOMM_RPN_STOP_1)
1257 1.1 gdamore mask |= RFCOMM_RPN_PM_STOP;
1258 1.1 gdamore
1259 1.1 gdamore if (rpn.param_mask & RFCOMM_RPN_PM_PARITY
1260 1.1 gdamore && RFCOMM_RPN_PARITY(rpn.line_settings) == RFCOMM_RPN_PARITY_NONE)
1261 1.1 gdamore mask |= RFCOMM_RPN_PM_PARITY;
1262 1.1 gdamore
1263 1.1 gdamore if (rpn.param_mask & RFCOMM_RPN_PM_XON
1264 1.1 gdamore && rpn.xon_char == RFCOMM_RPN_XON_CHAR)
1265 1.1 gdamore mask |= RFCOMM_RPN_PM_XON;
1266 1.1 gdamore
1267 1.1 gdamore if (rpn.param_mask & RFCOMM_RPN_PM_XOFF
1268 1.1 gdamore && rpn.xoff_char == RFCOMM_RPN_XOFF_CHAR)
1269 1.1 gdamore mask |= RFCOMM_RPN_PM_XOFF;
1270 1.1 gdamore
1271 1.1 gdamore if (rpn.param_mask & RFCOMM_RPN_PM_FLOW
1272 1.1 gdamore && rpn.flow_control == RFCOMM_RPN_FLOW_NONE)
1273 1.1 gdamore mask |= RFCOMM_RPN_PM_FLOW;
1274 1.1 gdamore
1275 1.1 gdamore rpn.param_mask = htole16(mask);
1276 1.1 gdamore
1277 1.1 gdamore rfcomm_session_send_mcc(rs, 0, RFCOMM_MCC_RPN, &rpn, sizeof(rpn));
1278 1.1 gdamore }
1279 1.1 gdamore
1280 1.1 gdamore /*
1281 1.1 gdamore * process Remote Line Status command/response
1282 1.1 gdamore */
1283 1.1 gdamore static void
1284 1.1 gdamore rfcomm_session_recv_mcc_rls(struct rfcomm_session *rs, int cr, struct mbuf *m)
1285 1.1 gdamore {
1286 1.1 gdamore struct rfcomm_mcc_rls rls;
1287 1.1 gdamore
1288 1.1 gdamore if (cr == 0) /* ignore ack */
1289 1.1 gdamore return;
1290 1.1 gdamore
1291 1.1 gdamore if (m->m_pkthdr.len != sizeof(rls)) {
1292 1.1 gdamore DPRINTF("Bad RLS length %d\n", m->m_pkthdr.len);
1293 1.1 gdamore return;
1294 1.1 gdamore }
1295 1.1 gdamore
1296 1.1 gdamore m_copydata(m, 0, sizeof(rls), &rls);
1297 1.1 gdamore
1298 1.1 gdamore /*
1299 1.1 gdamore * So far as I can tell, we just send back what
1300 1.1 gdamore * they sent us. This signifies errors that seem
1301 1.1 gdamore * irrelevent for RFCOMM over L2CAP.
1302 1.1 gdamore */
1303 1.1 gdamore rls.address |= 0x03; /* EA = 1, CR = 1 */
1304 1.1 gdamore rls.status &= 0x0f; /* only 4 bits valid */
1305 1.1 gdamore
1306 1.1 gdamore rfcomm_session_send_mcc(rs, 0, RFCOMM_MCC_RLS, &rls, sizeof(rls));
1307 1.1 gdamore }
1308 1.1 gdamore
1309 1.1 gdamore /*
1310 1.1 gdamore * process Parameter Negotiation command/response
1311 1.1 gdamore */
1312 1.1 gdamore static void
1313 1.1 gdamore rfcomm_session_recv_mcc_pn(struct rfcomm_session *rs, int cr, struct mbuf *m)
1314 1.1 gdamore {
1315 1.1 gdamore struct rfcomm_dlc *dlc;
1316 1.1 gdamore struct rfcomm_mcc_pn pn;
1317 1.1 gdamore int err;
1318 1.1 gdamore
1319 1.1 gdamore if (m->m_pkthdr.len != sizeof(pn)) {
1320 1.1 gdamore DPRINTF("Bad PN length %d\n", m->m_pkthdr.len);
1321 1.1 gdamore return;
1322 1.1 gdamore }
1323 1.1 gdamore
1324 1.1 gdamore m_copydata(m, 0, sizeof(pn), &pn);
1325 1.1 gdamore
1326 1.1 gdamore pn.dlci &= 0x3f;
1327 1.1 gdamore pn.mtu = le16toh(pn.mtu);
1328 1.1 gdamore
1329 1.1 gdamore dlc = rfcomm_dlc_lookup(rs, pn.dlci);
1330 1.1 gdamore if (cr) { /* Command */
1331 1.1 gdamore /*
1332 1.1 gdamore * If there is no DLC present, this is a new
1333 1.1 gdamore * connection so attempt to make one
1334 1.1 gdamore */
1335 1.1 gdamore if (dlc == NULL) {
1336 1.1 gdamore dlc = rfcomm_dlc_newconn(rs, pn.dlci);
1337 1.1 gdamore if (dlc == NULL)
1338 1.1 gdamore return; /* (DM is sent) */
1339 1.1 gdamore }
1340 1.1 gdamore
1341 1.1 gdamore /* accept any valid MTU, and offer it back */
1342 1.1 gdamore pn.mtu = min(pn.mtu, RFCOMM_MTU_MAX);
1343 1.1 gdamore pn.mtu = min(pn.mtu, rs->rs_mtu);
1344 1.1 gdamore pn.mtu = max(pn.mtu, RFCOMM_MTU_MIN);
1345 1.1 gdamore dlc->rd_mtu = pn.mtu;
1346 1.1 gdamore pn.mtu = htole16(pn.mtu);
1347 1.1 gdamore
1348 1.1 gdamore /* credits are only set before DLC is open */
1349 1.1 gdamore if (dlc->rd_state == RFCOMM_DLC_WAIT_CONNECT
1350 1.1 gdamore && (pn.flow_control & 0xf0) == 0xf0) {
1351 1.1 gdamore rs->rs_flags |= RFCOMM_SESSION_CFC;
1352 1.1 gdamore dlc->rd_txcred = pn.credits & 0x07;
1353 1.1 gdamore
1354 1.1 gdamore dlc->rd_rxcred = (dlc->rd_rxsize / dlc->rd_mtu);
1355 1.1 gdamore dlc->rd_rxcred = min(dlc->rd_rxcred,
1356 1.1 gdamore RFCOMM_CREDITS_DEFAULT);
1357 1.1 gdamore
1358 1.1 gdamore pn.flow_control = 0xe0;
1359 1.1 gdamore pn.credits = dlc->rd_rxcred;
1360 1.1 gdamore } else {
1361 1.1 gdamore pn.flow_control = 0x00;
1362 1.1 gdamore pn.credits = 0x00;
1363 1.1 gdamore }
1364 1.1 gdamore
1365 1.1 gdamore /* unused fields must be ignored and set to zero */
1366 1.1 gdamore pn.ack_timer = 0;
1367 1.1 gdamore pn.max_retrans = 0;
1368 1.1 gdamore
1369 1.1 gdamore /* send our response */
1370 1.1 gdamore err = rfcomm_session_send_mcc(rs, 0,
1371 1.1 gdamore RFCOMM_MCC_PN, &pn, sizeof(pn));
1372 1.1 gdamore if (err)
1373 1.1 gdamore goto close;
1374 1.1 gdamore
1375 1.1 gdamore } else { /* Response */
1376 1.1 gdamore /* ignore responses with no matching DLC */
1377 1.1 gdamore if (dlc == NULL)
1378 1.1 gdamore return;
1379 1.1 gdamore
1380 1.1 gdamore callout_stop(&dlc->rd_timeout);
1381 1.1 gdamore
1382 1.16 plunky /* reject invalid or unacceptable MTU */
1383 1.16 plunky if (pn.mtu < RFCOMM_MTU_MIN || pn.mtu > dlc->rd_mtu) {
1384 1.1 gdamore dlc->rd_state = RFCOMM_DLC_WAIT_DISCONNECT;
1385 1.1 gdamore err = rfcomm_session_send_frame(rs, RFCOMM_FRAME_DISC,
1386 1.1 gdamore pn.dlci);
1387 1.1 gdamore if (err)
1388 1.1 gdamore goto close;
1389 1.1 gdamore
1390 1.1 gdamore callout_schedule(&dlc->rd_timeout,
1391 1.1 gdamore rfcomm_ack_timeout * hz);
1392 1.1 gdamore return;
1393 1.1 gdamore }
1394 1.1 gdamore dlc->rd_mtu = pn.mtu;
1395 1.1 gdamore
1396 1.9 plunky /* if DLC is not waiting to connect, we are done */
1397 1.9 plunky if (dlc->rd_state != RFCOMM_DLC_WAIT_CONNECT)
1398 1.9 plunky return;
1399 1.9 plunky
1400 1.9 plunky /* set initial credits according to RFCOMM spec */
1401 1.9 plunky if ((pn.flow_control & 0xf0) == 0xe0) {
1402 1.1 gdamore rs->rs_flags |= RFCOMM_SESSION_CFC;
1403 1.1 gdamore dlc->rd_txcred = (pn.credits & 0x07);
1404 1.1 gdamore }
1405 1.1 gdamore
1406 1.9 plunky callout_schedule(&dlc->rd_timeout, rfcomm_ack_timeout * hz);
1407 1.9 plunky
1408 1.9 plunky /* set link mode */
1409 1.9 plunky err = rfcomm_dlc_setmode(dlc);
1410 1.9 plunky if (err == EINPROGRESS) {
1411 1.9 plunky dlc->rd_state = RFCOMM_DLC_WAIT_SEND_SABM;
1412 1.9 plunky (*dlc->rd_proto->connecting)(dlc->rd_upper);
1413 1.9 plunky return;
1414 1.9 plunky }
1415 1.9 plunky if (err)
1416 1.9 plunky goto close;
1417 1.9 plunky
1418 1.9 plunky /* we can proceed now */
1419 1.1 gdamore err = rfcomm_session_send_frame(rs, RFCOMM_FRAME_SABM, pn.dlci);
1420 1.1 gdamore if (err)
1421 1.1 gdamore goto close;
1422 1.1 gdamore
1423 1.9 plunky dlc->rd_state = RFCOMM_DLC_WAIT_RECV_UA;
1424 1.1 gdamore }
1425 1.1 gdamore return;
1426 1.1 gdamore
1427 1.1 gdamore close:
1428 1.1 gdamore rfcomm_dlc_close(dlc, err);
1429 1.1 gdamore }
1430 1.1 gdamore
1431 1.1 gdamore /*
1432 1.1 gdamore * process Non Supported Command command/response
1433 1.1 gdamore */
1434 1.1 gdamore static void
1435 1.3 christos rfcomm_session_recv_mcc_nsc(struct rfcomm_session *rs,
1436 1.4 christos int cr, struct mbuf *m)
1437 1.1 gdamore {
1438 1.2 plunky struct rfcomm_dlc *dlc, *next;
1439 1.1 gdamore
1440 1.1 gdamore /*
1441 1.1 gdamore * Since we did nothing that is not mandatory,
1442 1.1 gdamore * we just abort the whole session..
1443 1.1 gdamore */
1444 1.2 plunky
1445 1.2 plunky next = LIST_FIRST(&rs->rs_dlcs);
1446 1.2 plunky while ((dlc = next) != NULL) {
1447 1.2 plunky next = LIST_NEXT(dlc, rd_next);
1448 1.1 gdamore rfcomm_dlc_close(dlc, ECONNABORTED);
1449 1.2 plunky }
1450 1.1 gdamore
1451 1.1 gdamore rfcomm_session_free(rs);
1452 1.1 gdamore }
1453 1.1 gdamore
1454 1.1 gdamore /***********************************************************************
1455 1.1 gdamore *
1456 1.1 gdamore * RFCOMM Session outward frame/uih/mcc building
1457 1.1 gdamore */
1458 1.1 gdamore
1459 1.1 gdamore /*
1460 1.1 gdamore * SABM/DISC/DM/UA frames are all minimal and mostly identical.
1461 1.1 gdamore */
1462 1.1 gdamore int
1463 1.1 gdamore rfcomm_session_send_frame(struct rfcomm_session *rs, int type, int dlci)
1464 1.1 gdamore {
1465 1.1 gdamore struct rfcomm_cmd_hdr *hdr;
1466 1.1 gdamore struct rfcomm_credit *credit;
1467 1.1 gdamore struct mbuf *m;
1468 1.1 gdamore uint8_t fcs, cr;
1469 1.1 gdamore
1470 1.1 gdamore credit = pool_get(&rfcomm_credit_pool, PR_NOWAIT);
1471 1.1 gdamore if (credit == NULL)
1472 1.1 gdamore return ENOMEM;
1473 1.1 gdamore
1474 1.1 gdamore m = m_gethdr(M_DONTWAIT, MT_DATA);
1475 1.1 gdamore if (m == NULL) {
1476 1.1 gdamore pool_put(&rfcomm_credit_pool, credit);
1477 1.1 gdamore return ENOMEM;
1478 1.1 gdamore }
1479 1.1 gdamore
1480 1.1 gdamore /*
1481 1.1 gdamore * The CR (command/response) bit identifies the frame either as a
1482 1.1 gdamore * commmand or a response and is used along with the DLCI to form
1483 1.1 gdamore * the address. Commands contain the non-initiator address, whereas
1484 1.1 gdamore * responses contain the initiator address, so the CR value is
1485 1.1 gdamore * also dependent on the session direction.
1486 1.1 gdamore */
1487 1.1 gdamore if (type == RFCOMM_FRAME_UA || type == RFCOMM_FRAME_DM)
1488 1.1 gdamore cr = IS_INITIATOR(rs) ? 0 : 1;
1489 1.1 gdamore else
1490 1.1 gdamore cr = IS_INITIATOR(rs) ? 1 : 0;
1491 1.1 gdamore
1492 1.1 gdamore hdr = mtod(m, struct rfcomm_cmd_hdr *);
1493 1.1 gdamore hdr->address = RFCOMM_MKADDRESS(cr, dlci);
1494 1.1 gdamore hdr->control = RFCOMM_MKCONTROL(type, 1); /* PF = 1 */
1495 1.1 gdamore hdr->length = (0x00 << 1) | 0x01; /* len = 0x00, EA = 1 */
1496 1.1 gdamore
1497 1.1 gdamore fcs = 0xff;
1498 1.1 gdamore fcs = FCS(fcs, hdr->address);
1499 1.1 gdamore fcs = FCS(fcs, hdr->control);
1500 1.1 gdamore fcs = FCS(fcs, hdr->length);
1501 1.1 gdamore fcs = 0xff - fcs; /* ones complement */
1502 1.1 gdamore hdr->fcs = fcs;
1503 1.1 gdamore
1504 1.1 gdamore m->m_pkthdr.len = m->m_len = sizeof(struct rfcomm_cmd_hdr);
1505 1.1 gdamore
1506 1.1 gdamore /* empty credit note */
1507 1.1 gdamore credit->rc_dlc = NULL;
1508 1.1 gdamore credit->rc_len = m->m_pkthdr.len;
1509 1.1 gdamore SIMPLEQ_INSERT_TAIL(&rs->rs_credits, credit, rc_next);
1510 1.1 gdamore
1511 1.1 gdamore DPRINTFN(5, "dlci %d type %2.2x (%d bytes, fcs=%#2.2x)\n",
1512 1.1 gdamore dlci, type, m->m_pkthdr.len, fcs);
1513 1.1 gdamore
1514 1.1 gdamore return l2cap_send(rs->rs_l2cap, m);
1515 1.1 gdamore }
1516 1.1 gdamore
1517 1.1 gdamore /*
1518 1.1 gdamore * rfcomm_session_send_uih(rfcomm_session, rfcomm_dlc, credits, mbuf)
1519 1.1 gdamore *
1520 1.1 gdamore * UIH frame is per DLC data or Multiplexer Control Commands
1521 1.1 gdamore * when no DLC is given. Data mbuf is optional (just credits
1522 1.1 gdamore * will be sent in that case)
1523 1.1 gdamore */
1524 1.1 gdamore int
1525 1.1 gdamore rfcomm_session_send_uih(struct rfcomm_session *rs, struct rfcomm_dlc *dlc,
1526 1.1 gdamore int credits, struct mbuf *m)
1527 1.1 gdamore {
1528 1.1 gdamore struct rfcomm_credit *credit;
1529 1.1 gdamore struct mbuf *m0 = NULL;
1530 1.1 gdamore int err, len;
1531 1.1 gdamore uint8_t fcs, *hdr;
1532 1.1 gdamore
1533 1.1 gdamore KASSERT(rs != NULL);
1534 1.1 gdamore
1535 1.1 gdamore len = (m == NULL) ? 0 : m->m_pkthdr.len;
1536 1.1 gdamore KASSERT(!(credits == 0 && len == 0));
1537 1.1 gdamore
1538 1.1 gdamore /*
1539 1.1 gdamore * Make a credit note for the completion notification
1540 1.1 gdamore */
1541 1.1 gdamore credit = pool_get(&rfcomm_credit_pool, PR_NOWAIT);
1542 1.1 gdamore if (credit == NULL)
1543 1.1 gdamore goto nomem;
1544 1.1 gdamore
1545 1.1 gdamore credit->rc_len = len;
1546 1.1 gdamore credit->rc_dlc = dlc;
1547 1.1 gdamore
1548 1.1 gdamore /*
1549 1.1 gdamore * Wrap UIH frame information around payload.
1550 1.1 gdamore *
1551 1.1 gdamore * [ADDRESS] [CONTROL] [LENGTH] [CREDITS] [...] [FCS]
1552 1.1 gdamore *
1553 1.1 gdamore * Address is one octet.
1554 1.1 gdamore * Control is one octet.
1555 1.1 gdamore * Length is one or two octets.
1556 1.1 gdamore * Credits may be one octet.
1557 1.1 gdamore *
1558 1.1 gdamore * FCS is one octet and calculated on address and
1559 1.1 gdamore * control octets only.
1560 1.1 gdamore *
1561 1.1 gdamore * If there are credits to be sent, we will set the PF
1562 1.1 gdamore * flag and include them in the frame.
1563 1.1 gdamore */
1564 1.1 gdamore m0 = m_gethdr(M_DONTWAIT, MT_DATA);
1565 1.1 gdamore if (m0 == NULL)
1566 1.1 gdamore goto nomem;
1567 1.1 gdamore
1568 1.1 gdamore MH_ALIGN(m0, 5); /* (max 5 header octets) */
1569 1.1 gdamore hdr = mtod(m0, uint8_t *);
1570 1.1 gdamore
1571 1.1 gdamore /* CR bit is set according to the initiator of the session */
1572 1.1 gdamore *hdr = RFCOMM_MKADDRESS((IS_INITIATOR(rs) ? 1 : 0),
1573 1.1 gdamore (dlc ? dlc->rd_dlci : 0));
1574 1.1 gdamore fcs = FCS(0xff, *hdr);
1575 1.1 gdamore hdr++;
1576 1.1 gdamore
1577 1.1 gdamore /* PF bit is set if credits are being sent */
1578 1.1 gdamore *hdr = RFCOMM_MKCONTROL(RFCOMM_FRAME_UIH, (credits > 0 ? 1 : 0));
1579 1.1 gdamore fcs = FCS(fcs, *hdr);
1580 1.1 gdamore hdr++;
1581 1.1 gdamore
1582 1.1 gdamore if (len < (1 << 7)) {
1583 1.1 gdamore *hdr++ = ((len << 1) & 0xfe) | 0x01; /* 7 bits, EA = 1 */
1584 1.1 gdamore } else {
1585 1.1 gdamore *hdr++ = ((len << 1) & 0xfe); /* 7 bits, EA = 0 */
1586 1.1 gdamore *hdr++ = ((len >> 7) & 0xff); /* 8 bits, no EA */
1587 1.1 gdamore }
1588 1.1 gdamore
1589 1.1 gdamore if (credits > 0)
1590 1.1 gdamore *hdr++ = (uint8_t)credits;
1591 1.1 gdamore
1592 1.1 gdamore m0->m_len = hdr - mtod(m0, uint8_t *);
1593 1.1 gdamore
1594 1.1 gdamore /* Append payload */
1595 1.1 gdamore m0->m_next = m;
1596 1.1 gdamore m = NULL;
1597 1.1 gdamore
1598 1.1 gdamore m0->m_pkthdr.len = m0->m_len + len;
1599 1.1 gdamore
1600 1.1 gdamore /* Append FCS */
1601 1.1 gdamore fcs = 0xff - fcs; /* ones complement */
1602 1.1 gdamore len = m0->m_pkthdr.len;
1603 1.1 gdamore m_copyback(m0, len, sizeof(fcs), &fcs);
1604 1.1 gdamore if (m0->m_pkthdr.len != len + sizeof(fcs))
1605 1.1 gdamore goto nomem;
1606 1.1 gdamore
1607 1.1 gdamore DPRINTFN(10, "dlci %d, pktlen %d (%d data, %d credits), fcs=%#2.2x\n",
1608 1.1 gdamore dlc ? dlc->rd_dlci : 0, m0->m_pkthdr.len, credit->rc_len,
1609 1.1 gdamore credits, fcs);
1610 1.1 gdamore
1611 1.1 gdamore /*
1612 1.1 gdamore * UIH frame ready to go..
1613 1.1 gdamore */
1614 1.1 gdamore err = l2cap_send(rs->rs_l2cap, m0);
1615 1.1 gdamore if (err)
1616 1.1 gdamore goto fail;
1617 1.1 gdamore
1618 1.1 gdamore SIMPLEQ_INSERT_TAIL(&rs->rs_credits, credit, rc_next);
1619 1.1 gdamore return 0;
1620 1.1 gdamore
1621 1.1 gdamore nomem:
1622 1.1 gdamore err = ENOMEM;
1623 1.1 gdamore
1624 1.1 gdamore if (m0 != NULL)
1625 1.1 gdamore m_freem(m0);
1626 1.1 gdamore
1627 1.1 gdamore if (m != NULL)
1628 1.1 gdamore m_freem(m);
1629 1.1 gdamore
1630 1.1 gdamore fail:
1631 1.1 gdamore if (credit != NULL)
1632 1.1 gdamore pool_put(&rfcomm_credit_pool, credit);
1633 1.1 gdamore
1634 1.1 gdamore return err;
1635 1.1 gdamore }
1636 1.1 gdamore
1637 1.1 gdamore /*
1638 1.1 gdamore * send Multiplexer Control Command (or Response) on session
1639 1.1 gdamore */
1640 1.1 gdamore int
1641 1.1 gdamore rfcomm_session_send_mcc(struct rfcomm_session *rs, int cr,
1642 1.1 gdamore uint8_t type, void *data, int len)
1643 1.1 gdamore {
1644 1.1 gdamore struct mbuf *m;
1645 1.1 gdamore uint8_t *hdr;
1646 1.1 gdamore int hlen;
1647 1.1 gdamore
1648 1.1 gdamore m = m_gethdr(M_DONTWAIT, MT_DATA);
1649 1.1 gdamore if (m == NULL)
1650 1.1 gdamore return ENOMEM;
1651 1.1 gdamore
1652 1.1 gdamore hdr = mtod(m, uint8_t *);
1653 1.1 gdamore
1654 1.1 gdamore /*
1655 1.1 gdamore * Technically the type field can extend past one octet, but none
1656 1.1 gdamore * currently defined will do that.
1657 1.1 gdamore */
1658 1.1 gdamore *hdr++ = RFCOMM_MKMCC_TYPE(cr, type);
1659 1.1 gdamore
1660 1.1 gdamore /*
1661 1.1 gdamore * In the frame, the max length size is 2 octets (15 bits) whereas
1662 1.1 gdamore * no max length size is specified for MCC commands. We must allow
1663 1.1 gdamore * for 3 octets since for MCC frames we use 7 bits + EA in each.
1664 1.1 gdamore *
1665 1.1 gdamore * Only test data can possibly be that big.
1666 1.1 gdamore *
1667 1.1 gdamore * XXX Should we check this against the MTU?
1668 1.1 gdamore */
1669 1.1 gdamore if (len < (1 << 7)) {
1670 1.1 gdamore *hdr++ = ((len << 1) & 0xfe) | 0x01; /* 7 bits, EA = 1 */
1671 1.1 gdamore } else if (len < (1 << 14)) {
1672 1.1 gdamore *hdr++ = ((len << 1) & 0xfe); /* 7 bits, EA = 0 */
1673 1.1 gdamore *hdr++ = ((len >> 6) & 0xfe) | 0x01; /* 7 bits, EA = 1 */
1674 1.1 gdamore } else if (len < (1 << 15)) {
1675 1.1 gdamore *hdr++ = ((len << 1) & 0xfe); /* 7 bits, EA = 0 */
1676 1.1 gdamore *hdr++ = ((len >> 6) & 0xfe); /* 7 bits, EA = 0 */
1677 1.1 gdamore *hdr++ = ((len >> 13) & 0x02) | 0x01; /* 1 bit, EA = 1 */
1678 1.1 gdamore } else {
1679 1.1 gdamore DPRINTF("incredible length! (%d)\n", len);
1680 1.1 gdamore m_freem(m);
1681 1.1 gdamore return EMSGSIZE;
1682 1.1 gdamore }
1683 1.1 gdamore
1684 1.1 gdamore /*
1685 1.1 gdamore * add command data (to same mbuf if possible)
1686 1.1 gdamore */
1687 1.1 gdamore hlen = hdr - mtod(m, uint8_t *);
1688 1.1 gdamore
1689 1.1 gdamore if (len > 0) {
1690 1.1 gdamore m->m_pkthdr.len = m->m_len = MHLEN;
1691 1.1 gdamore m_copyback(m, hlen, len, data);
1692 1.1 gdamore if (m->m_pkthdr.len != max(MHLEN, hlen + len)) {
1693 1.1 gdamore m_freem(m);
1694 1.1 gdamore return ENOMEM;
1695 1.1 gdamore }
1696 1.1 gdamore }
1697 1.1 gdamore
1698 1.1 gdamore m->m_pkthdr.len = hlen + len;
1699 1.1 gdamore m->m_len = min(MHLEN, m->m_pkthdr.len);
1700 1.1 gdamore
1701 1.1 gdamore DPRINTFN(5, "%s type %2.2x len %d\n",
1702 1.1 gdamore (cr ? "command" : "response"), type, m->m_pkthdr.len);
1703 1.1 gdamore
1704 1.1 gdamore return rfcomm_session_send_uih(rs, NULL, 0, m);
1705 1.1 gdamore }
1706