Test
[dragonfly.git] / sys / netbt / rfcomm_upper.c
1 /* $DragonFly: src/sys/netbt/rfcomm_upper.c,v 1.3 2008/06/20 20:52:29 aggelos Exp $ */
2 /* $OpenBSD: src/sys/netbt/rfcomm_upper.c,v 1.4 2008/02/24 21:34:48 uwe Exp $ */
3 /* $NetBSD: rfcomm_upper.c,v 1.10 2007/11/20 20:25:57 plunky Exp $ */
4
5 /*-
6  * Copyright (c) 2006 Itronix Inc.
7  * All rights reserved.
8  *
9  * Written by Iain Hibbert for Itronix Inc.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. The name of Itronix Inc. may not be used to endorse
20  *    or promote products derived from this software without specific
21  *    prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
25  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
27  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30  * ON ANY THEORY OF LIABILITY, WHETHER IN
31  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  */
35
36 #include <sys/param.h>
37 #include <sys/kernel.h>
38 #include <sys/mbuf.h>
39 #include <sys/proc.h>
40 #include <sys/systm.h>
41 #include <sys/socketvar.h>
42
43 #include <netbt/bluetooth.h>
44 #include <netbt/hci.h>
45 #include <netbt/l2cap.h>
46 #include <netbt/rfcomm.h>
47
48 /****************************************************************************
49  *
50  *      RFCOMM DLC - Upper Protocol API
51  *
52  * Currently the only 'Port Emulation Entity' is the RFCOMM socket code
53  * but it is should be possible to provide a pseudo-device for a direct
54  * tty interface.
55  */
56
57 /*
58  * rfcomm_attach(handle, proto, upper)
59  *
60  * attach a new RFCOMM DLC to handle, populate with reasonable defaults
61  */
62 int
63 rfcomm_attach(struct rfcomm_dlc **handle,
64                 const struct btproto *proto, void *upper)
65 {
66         struct rfcomm_dlc *dlc;
67
68         KKASSERT(handle != NULL);
69         KKASSERT(proto != NULL);
70         KKASSERT(upper != NULL);
71
72         dlc = kmalloc(sizeof(*dlc), M_BLUETOOTH, M_NOWAIT | M_ZERO);
73         if (dlc == NULL)
74                 return ENOMEM;
75
76         dlc->rd_state = RFCOMM_DLC_CLOSED;
77         dlc->rd_mtu = rfcomm_mtu_default;
78
79         dlc->rd_proto = proto;
80         dlc->rd_upper = upper;
81
82         dlc->rd_laddr.bt_len = sizeof(struct sockaddr_bt);
83         dlc->rd_laddr.bt_family = AF_BLUETOOTH;
84         dlc->rd_laddr.bt_psm = L2CAP_PSM_RFCOMM;
85
86         dlc->rd_raddr.bt_len = sizeof(struct sockaddr_bt);
87         dlc->rd_raddr.bt_family = AF_BLUETOOTH;
88         dlc->rd_raddr.bt_psm = L2CAP_PSM_RFCOMM;
89
90         dlc->rd_lmodem = RFCOMM_MSC_RTC | RFCOMM_MSC_RTR | RFCOMM_MSC_DV;
91
92         callout_init(&dlc->rd_timeout);
93
94         *handle = dlc;
95         return 0;
96 }
97
98 /*
99  * rfcomm_bind(dlc, sockaddr)
100  *
101  * bind DLC to local address
102  */
103 int
104 rfcomm_bind(struct rfcomm_dlc *dlc, struct sockaddr_bt *addr)
105 {
106
107         memcpy(&dlc->rd_laddr, addr, sizeof(struct sockaddr_bt));
108         return 0;
109 }
110
111 /*
112  * rfcomm_sockaddr(dlc, sockaddr)
113  *
114  * return local address
115  */
116 int
117 rfcomm_sockaddr(struct rfcomm_dlc *dlc, struct sockaddr_bt *addr)
118 {
119
120         memcpy(addr, &dlc->rd_laddr, sizeof(struct sockaddr_bt));
121         return 0;
122 }
123
124 /*
125  * rfcomm_connect(dlc, sockaddr)
126  *
127  * Initiate connection of RFCOMM DLC to remote address.
128  */
129 int
130 rfcomm_connect(struct rfcomm_dlc *dlc, struct sockaddr_bt *dest)
131 {
132         struct rfcomm_session *rs;
133         int err = 0;
134
135         if (dlc->rd_state != RFCOMM_DLC_CLOSED)
136                 return EISCONN;
137
138         memcpy(&dlc->rd_raddr, dest, sizeof(struct sockaddr_bt));
139
140         if (dlc->rd_raddr.bt_channel < RFCOMM_CHANNEL_MIN
141             || dlc->rd_raddr.bt_channel > RFCOMM_CHANNEL_MAX
142             || bdaddr_any(&dlc->rd_raddr.bt_bdaddr))
143                 return EDESTADDRREQ;
144
145         if (dlc->rd_raddr.bt_psm == L2CAP_PSM_ANY)
146                 dlc->rd_raddr.bt_psm = L2CAP_PSM_RFCOMM;
147         else if (dlc->rd_raddr.bt_psm != L2CAP_PSM_RFCOMM
148             && (dlc->rd_raddr.bt_psm < 0x1001
149             || L2CAP_PSM_INVALID(dlc->rd_raddr.bt_psm)))
150                 return EINVAL;
151
152         /*
153          * We are allowed only one RFCOMM session between any 2 Bluetooth
154          * devices, so see if there is a session already otherwise create
155          * one and set it connecting.
156          */
157         rs = rfcomm_session_lookup(&dlc->rd_laddr, &dlc->rd_raddr);
158         if (rs == NULL) {
159                 rs = rfcomm_session_alloc(&rfcomm_session_active,
160                                                 &dlc->rd_laddr);
161                 if (rs == NULL)
162                         return ENOMEM;
163
164                 rs->rs_flags |= RFCOMM_SESSION_INITIATOR;
165                 rs->rs_state = RFCOMM_SESSION_WAIT_CONNECT;
166
167                 err = l2cap_connect(rs->rs_l2cap, &dlc->rd_raddr);
168                 if (err) {
169                         rfcomm_session_free(rs);
170                         return err;
171                 }
172
173                 /*
174                  * This session will start up automatically when its
175                  * L2CAP channel is connected.
176                  */
177         }
178
179         /* construct DLC */
180         dlc->rd_dlci = RFCOMM_MKDLCI(IS_INITIATOR(rs) ? 0:1, dest->bt_channel);
181         if (rfcomm_dlc_lookup(rs, dlc->rd_dlci))
182                 return EBUSY;
183
184         l2cap_sockaddr(rs->rs_l2cap, &dlc->rd_laddr);
185
186         /*
187          * attach the DLC to the session and start it off
188          */
189         dlc->rd_session = rs;
190         dlc->rd_state = RFCOMM_DLC_WAIT_SESSION;
191         LIST_INSERT_HEAD(&rs->rs_dlcs, dlc, rd_next);
192
193         if (rs->rs_state == RFCOMM_SESSION_OPEN)
194                 err = rfcomm_dlc_connect(dlc);
195
196         return err;
197 }
198
199 /*
200  * rfcomm_peeraddr(dlc, sockaddr)
201  *
202  * return remote address
203  */
204 int
205 rfcomm_peeraddr(struct rfcomm_dlc *dlc, struct sockaddr_bt *addr)
206 {
207
208         memcpy(addr, &dlc->rd_raddr, sizeof(struct sockaddr_bt));
209         return 0;
210 }
211
212 /*
213  * rfcomm_disconnect(dlc, linger)
214  *
215  * disconnect RFCOMM DLC
216  */
217 int
218 rfcomm_disconnect(struct rfcomm_dlc *dlc, int linger)
219 {
220         struct rfcomm_session *rs = dlc->rd_session;
221         int err = 0;
222
223         KKASSERT(dlc != NULL);
224
225         switch (dlc->rd_state) {
226         case RFCOMM_DLC_CLOSED:
227         case RFCOMM_DLC_LISTEN:
228                 return EINVAL;
229
230         case RFCOMM_DLC_WAIT_SEND_UA:
231                 err = rfcomm_session_send_frame(rs,
232                                 RFCOMM_FRAME_DM, dlc->rd_dlci);
233
234                 /* fall through */
235         case RFCOMM_DLC_WAIT_SESSION:
236         case RFCOMM_DLC_WAIT_CONNECT:
237         case RFCOMM_DLC_WAIT_SEND_SABM:
238                 rfcomm_dlc_close(dlc, 0);
239                 break;
240
241         case RFCOMM_DLC_OPEN:
242                 if (dlc->rd_txbuf != NULL && linger != 0) {
243                         dlc->rd_flags |= RFCOMM_DLC_SHUTDOWN;
244                         break;
245                 }
246
247                 /* else fall through */
248         case RFCOMM_DLC_WAIT_RECV_UA:
249                 dlc->rd_state = RFCOMM_DLC_WAIT_DISCONNECT;
250                 err = rfcomm_session_send_frame(rs, RFCOMM_FRAME_DISC,
251                                                         dlc->rd_dlci);
252                 callout_reset(&dlc->rd_timeout, rfcomm_ack_timeout * hz,
253                     rfcomm_dlc_timeout, dlc);
254                 break;
255
256         case RFCOMM_DLC_WAIT_DISCONNECT:
257                 err = EALREADY;
258                 break;
259
260         default:
261                 UNKNOWN(dlc->rd_state);
262                 break;
263         }
264
265         return err;
266 }
267
268 /*
269  * rfcomm_detach(handle)
270  *
271  * detach RFCOMM DLC from handle
272  */
273 int
274 rfcomm_detach(struct rfcomm_dlc **handle)
275 {
276         struct rfcomm_dlc *dlc = *handle;
277
278         if (dlc->rd_state != RFCOMM_DLC_CLOSED)
279                 rfcomm_dlc_close(dlc, 0);
280
281         if (dlc->rd_txbuf != NULL) {
282                 m_freem(dlc->rd_txbuf);
283                 dlc->rd_txbuf = NULL;
284         }
285
286         dlc->rd_upper = NULL;
287         *handle = NULL;
288
289         /*
290          * If callout is invoking we can't free the DLC so
291          * mark it and let the callout release it.
292          */
293         if (callout_active(&dlc->rd_timeout))
294                 dlc->rd_flags |= RFCOMM_DLC_DETACH;
295         else
296                 kfree(dlc, M_BLUETOOTH);
297
298         return 0;
299 }
300
301 /*
302  * rfcomm_listen(dlc)
303  *
304  * This DLC is a listener. We look for an existing listening session
305  * with a matching address to attach to or else create a new one on
306  * the listeners list. If the ANY channel is given, allocate the first
307  * available for the session.
308  */
309 int
310 rfcomm_listen(struct rfcomm_dlc *dlc)
311 {
312         struct rfcomm_session *rs;
313         struct rfcomm_dlc *used;
314         struct sockaddr_bt addr;
315         int err, channel;
316
317         if (dlc->rd_state != RFCOMM_DLC_CLOSED)
318                 return EISCONN;
319
320         if (dlc->rd_laddr.bt_channel != RFCOMM_CHANNEL_ANY
321             && (dlc->rd_laddr.bt_channel < RFCOMM_CHANNEL_MIN
322             || dlc->rd_laddr.bt_channel > RFCOMM_CHANNEL_MAX))
323                 return EADDRNOTAVAIL;
324
325         if (dlc->rd_laddr.bt_psm == L2CAP_PSM_ANY)
326                 dlc->rd_laddr.bt_psm = L2CAP_PSM_RFCOMM;
327         else if (dlc->rd_laddr.bt_psm != L2CAP_PSM_RFCOMM
328             && (dlc->rd_laddr.bt_psm < 0x1001
329             || L2CAP_PSM_INVALID(dlc->rd_laddr.bt_psm)))
330                 return EADDRNOTAVAIL;
331
332         LIST_FOREACH(rs, &rfcomm_session_listen, rs_next) {
333                 l2cap_sockaddr(rs->rs_l2cap, &addr);
334
335                 if (addr.bt_psm != dlc->rd_laddr.bt_psm)
336                         continue;
337
338                 if (bdaddr_same(&dlc->rd_laddr.bt_bdaddr, &addr.bt_bdaddr))
339                         break;
340         }
341
342         if (rs == NULL) {
343                 rs = rfcomm_session_alloc(&rfcomm_session_listen,
344                                                 &dlc->rd_laddr);
345                 if (rs == NULL)
346                         return ENOMEM;
347
348                 rs->rs_state = RFCOMM_SESSION_LISTEN;
349
350                 err = l2cap_listen(rs->rs_l2cap);
351                 if (err) {
352                         rfcomm_session_free(rs);
353                         return err;
354                 }
355         }
356
357         if (dlc->rd_laddr.bt_channel == RFCOMM_CHANNEL_ANY) {
358                 channel = RFCOMM_CHANNEL_MIN;
359                 used = LIST_FIRST(&rs->rs_dlcs);
360
361                 while (used != NULL) {
362                         if (used->rd_laddr.bt_channel == channel) {
363                                 if (channel++ == RFCOMM_CHANNEL_MAX)
364                                         return EADDRNOTAVAIL;
365
366                                 used = LIST_FIRST(&rs->rs_dlcs);
367                         } else {
368                                 used = LIST_NEXT(used, rd_next);
369                         }
370                 }
371
372                 dlc->rd_laddr.bt_channel = channel;
373         }
374
375         dlc->rd_session = rs;
376         dlc->rd_state = RFCOMM_DLC_LISTEN;
377         LIST_INSERT_HEAD(&rs->rs_dlcs, dlc, rd_next);
378
379         return 0;
380 }
381
382 /*
383  * rfcomm_send(dlc, mbuf)
384  *
385  * Output data on DLC. This is streamed data, so we add it
386  * to our buffer and start the DLC, which will assemble
387  * packets and send them if it can.
388  */
389 int
390 rfcomm_send(struct rfcomm_dlc *dlc, struct mbuf *m)
391 {
392
393         if (dlc->rd_txbuf != NULL) {
394                 dlc->rd_txbuf->m_pkthdr.len += m->m_pkthdr.len;
395                 m_cat(dlc->rd_txbuf, m);
396         } else {
397                 dlc->rd_txbuf = m;
398         }
399
400         if (dlc->rd_state == RFCOMM_DLC_OPEN)
401                 rfcomm_dlc_start(dlc);
402
403         return 0;
404 }
405
406 /*
407  * rfcomm_rcvd(dlc, space)
408  *
409  * Indicate space now available in receive buffer
410  *
411  * This should be used to give an initial value of the receive buffer
412  * size when the DLC is attached and anytime data is cleared from the
413  * buffer after that.
414  */
415 int
416 rfcomm_rcvd(struct rfcomm_dlc *dlc, size_t space)
417 {
418
419         KKASSERT(dlc != NULL);
420
421         dlc->rd_rxsize = space;
422
423         /*
424          * if we are using credit based flow control, we may
425          * want to send some credits..
426          */
427         if (dlc->rd_state == RFCOMM_DLC_OPEN
428             && (dlc->rd_session->rs_flags & RFCOMM_SESSION_CFC))
429                 rfcomm_dlc_start(dlc);
430
431         return 0;
432 }
433
434 /*
435  * rfcomm_setopt(dlc, option, addr)
436  *
437  * set DLC options
438  */
439 int
440 rfcomm_setopt(struct rfcomm_dlc *dlc, int opt, void *addr)
441 {
442         int mode, err = 0;
443         uint16_t mtu;
444
445         switch (opt) {
446         case SO_RFCOMM_MTU:
447                 mtu = *(uint16_t *)addr;
448                 if (mtu < RFCOMM_MTU_MIN || mtu > RFCOMM_MTU_MAX)
449                         err = EINVAL;
450                 else if (dlc->rd_state == RFCOMM_DLC_CLOSED)
451                         dlc->rd_mtu = mtu;
452                 else
453                         err = EBUSY;
454
455                 break;
456
457         case SO_RFCOMM_LM:
458                 mode = *(int *)addr;
459                 mode &= (RFCOMM_LM_SECURE | RFCOMM_LM_ENCRYPT | RFCOMM_LM_AUTH);
460
461                 if (mode & RFCOMM_LM_SECURE)
462                         mode |= RFCOMM_LM_ENCRYPT;
463
464                 if (mode & RFCOMM_LM_ENCRYPT)
465                         mode |= RFCOMM_LM_AUTH;
466
467                 dlc->rd_mode = mode;
468
469                 if (dlc->rd_state == RFCOMM_DLC_OPEN)
470                         err = rfcomm_dlc_setmode(dlc);
471
472                 break;
473
474         default:
475                 err = ENOPROTOOPT;
476                 break;
477         }
478         return err;
479 }
480
481
482 int
483 rfcomm_setopt2(struct rfcomm_dlc *dlc, int opt, struct socket *so,
484     struct sockopt *sopt)
485 {
486         int mode, err = 0;
487         uint16_t mtu;
488
489         switch (opt) {
490         case SO_RFCOMM_MTU:
491                 err = soopt_to_kbuf(sopt, &mtu, sizeof(uint16_t),
492                     sizeof(uint16_t)); 
493                 if (err) break;
494
495                 if (mtu < RFCOMM_MTU_MIN || mtu > RFCOMM_MTU_MAX)
496                         err = EINVAL;
497                 else if (dlc->rd_state == RFCOMM_DLC_CLOSED)
498                         dlc->rd_mtu = mtu;
499                 else
500                         err = EBUSY;
501
502                 break;
503
504         case SO_RFCOMM_LM:
505                 err = soopt_to_kbuf(sopt, &mode, sizeof(int), sizeof(int)); 
506                 if (err) break;
507
508                 mode &= (RFCOMM_LM_SECURE | RFCOMM_LM_ENCRYPT | RFCOMM_LM_AUTH);
509
510                 if (mode & RFCOMM_LM_SECURE)
511                         mode |= RFCOMM_LM_ENCRYPT;
512
513                 if (mode & RFCOMM_LM_ENCRYPT)
514                         mode |= RFCOMM_LM_AUTH;
515
516                 dlc->rd_mode = mode;
517
518                 if (dlc->rd_state == RFCOMM_DLC_OPEN)
519                         err = rfcomm_dlc_setmode(dlc);
520
521                 break;
522
523         default:
524                 err = ENOPROTOOPT;
525                 break;
526         }
527         return err;
528 }
529
530 /*
531  * rfcomm_getopt(dlc, option, addr)
532  *
533  * get DLC options
534  */
535 int
536 rfcomm_getopt(struct rfcomm_dlc *dlc, int opt, void *addr)
537 {
538         struct rfcomm_fc_info *fc;
539
540         switch (opt) {
541         case SO_RFCOMM_MTU:
542                 *(uint16_t *)addr = dlc->rd_mtu;
543                 return sizeof(uint16_t);
544
545         case SO_RFCOMM_FC_INFO:
546                 fc = addr;
547                 memset(fc, 0, sizeof(*fc));
548                 fc->lmodem = dlc->rd_lmodem;
549                 fc->rmodem = dlc->rd_rmodem;
550                 fc->tx_cred = max(dlc->rd_txcred, 0xff);
551                 fc->rx_cred = max(dlc->rd_rxcred, 0xff);
552                 if (dlc->rd_session
553                     && (dlc->rd_session->rs_flags & RFCOMM_SESSION_CFC))
554                         fc->cfc = 1;
555
556                 return sizeof(*fc);
557
558         case SO_RFCOMM_LM:
559                 *(int *)addr = dlc->rd_mode;
560                 return sizeof(int);
561
562         default:
563                 break;
564         }
565
566         return 0;
567 }