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