1*481d3881Srin /* $NetBSD: rfcomm_socket.c,v 1.39 2024/07/05 04:31:53 rin Exp $ */
2a5c89047Sgdamore
3a5c89047Sgdamore /*-
4a5c89047Sgdamore * Copyright (c) 2006 Itronix Inc.
5a5c89047Sgdamore * All rights reserved.
6a5c89047Sgdamore *
7a5c89047Sgdamore * Written by Iain Hibbert for Itronix Inc.
8a5c89047Sgdamore *
9a5c89047Sgdamore * Redistribution and use in source and binary forms, with or without
10a5c89047Sgdamore * modification, are permitted provided that the following conditions
11a5c89047Sgdamore * are met:
12a5c89047Sgdamore * 1. Redistributions of source code must retain the above copyright
13a5c89047Sgdamore * notice, this list of conditions and the following disclaimer.
14a5c89047Sgdamore * 2. Redistributions in binary form must reproduce the above copyright
15a5c89047Sgdamore * notice, this list of conditions and the following disclaimer in the
16a5c89047Sgdamore * documentation and/or other materials provided with the distribution.
17a5c89047Sgdamore * 3. The name of Itronix Inc. may not be used to endorse
18a5c89047Sgdamore * or promote products derived from this software without specific
19a5c89047Sgdamore * prior written permission.
20a5c89047Sgdamore *
21a5c89047Sgdamore * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
22a5c89047Sgdamore * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23a5c89047Sgdamore * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24a5c89047Sgdamore * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
25a5c89047Sgdamore * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26a5c89047Sgdamore * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27a5c89047Sgdamore * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28a5c89047Sgdamore * ON ANY THEORY OF LIABILITY, WHETHER IN
29a5c89047Sgdamore * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30a5c89047Sgdamore * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31a5c89047Sgdamore * POSSIBILITY OF SUCH DAMAGE.
32a5c89047Sgdamore */
33a5c89047Sgdamore
34a5c89047Sgdamore #include <sys/cdefs.h>
35*481d3881Srin __KERNEL_RCSID(0, "$NetBSD: rfcomm_socket.c,v 1.39 2024/07/05 04:31:53 rin Exp $");
36fb76dbd4Splunky
37fb76dbd4Splunky /* load symbolic names */
38fb76dbd4Splunky #ifdef BLUETOOTH_DEBUG
39fb76dbd4Splunky #define PRUREQUESTS
40fb76dbd4Splunky #define PRCOREQUESTS
41fb76dbd4Splunky #endif
42a5c89047Sgdamore
43a5c89047Sgdamore #include <sys/param.h>
44a5c89047Sgdamore #include <sys/domain.h>
45a5c89047Sgdamore #include <sys/kernel.h>
46a5c89047Sgdamore #include <sys/mbuf.h>
47a5c89047Sgdamore #include <sys/proc.h>
48a5c89047Sgdamore #include <sys/protosw.h>
49a5c89047Sgdamore #include <sys/socket.h>
50a5c89047Sgdamore #include <sys/socketvar.h>
51a5c89047Sgdamore #include <sys/systm.h>
52a5c89047Sgdamore
53a5c89047Sgdamore #include <netbt/bluetooth.h>
54a5c89047Sgdamore #include <netbt/rfcomm.h>
55a5c89047Sgdamore
56a5c89047Sgdamore /****************************************************************************
57a5c89047Sgdamore *
58a5c89047Sgdamore * RFCOMM SOCK_STREAM Sockets - serial line emulation
59a5c89047Sgdamore *
60a5c89047Sgdamore */
61a5c89047Sgdamore
62a5c89047Sgdamore static void rfcomm_connecting(void *);
63a5c89047Sgdamore static void rfcomm_connected(void *);
64a5c89047Sgdamore static void rfcomm_disconnected(void *, int);
65a5c89047Sgdamore static void *rfcomm_newconn(void *, struct sockaddr_bt *, struct sockaddr_bt *);
66a5c89047Sgdamore static void rfcomm_complete(void *, int);
67f5db72e7Splunky static void rfcomm_linkmode(void *, int);
68a5c89047Sgdamore static void rfcomm_input(void *, struct mbuf *);
69a5c89047Sgdamore
70a5c89047Sgdamore static const struct btproto rfcomm_proto = {
71a5c89047Sgdamore rfcomm_connecting,
72a5c89047Sgdamore rfcomm_connected,
73a5c89047Sgdamore rfcomm_disconnected,
74a5c89047Sgdamore rfcomm_newconn,
75a5c89047Sgdamore rfcomm_complete,
76f5db72e7Splunky rfcomm_linkmode,
77a5c89047Sgdamore rfcomm_input,
78a5c89047Sgdamore };
79a5c89047Sgdamore
80a5c89047Sgdamore /* sysctl variables */
81a5c89047Sgdamore int rfcomm_sendspace = 4096;
82a5c89047Sgdamore int rfcomm_recvspace = 4096;
83a5c89047Sgdamore
844ae03c18Srmind static int
rfcomm_attach(struct socket * so,int proto)8556a73a7dSrmind rfcomm_attach(struct socket *so, int proto)
864ae03c18Srmind {
874ae03c18Srmind int error;
884ae03c18Srmind
894ae03c18Srmind KASSERT(so->so_pcb == NULL);
904ae03c18Srmind
914ae03c18Srmind if (so->so_lock == NULL) {
924ae03c18Srmind mutex_obj_hold(bt_lock);
934ae03c18Srmind so->so_lock = bt_lock;
944ae03c18Srmind solock(so);
954ae03c18Srmind }
964ae03c18Srmind KASSERT(solocked(so));
974ae03c18Srmind
984ae03c18Srmind /*
994ae03c18Srmind * Since we have nothing to add, we attach the DLC
1004ae03c18Srmind * structure directly to our PCB pointer.
1014ae03c18Srmind */
1024ae03c18Srmind error = soreserve(so, rfcomm_sendspace, rfcomm_recvspace);
1034ae03c18Srmind if (error)
1044ae03c18Srmind return error;
1054ae03c18Srmind
10656a73a7dSrmind error = rfcomm_attach_pcb((struct rfcomm_dlc **)&so->so_pcb,
1074ae03c18Srmind &rfcomm_proto, so);
1084ae03c18Srmind if (error)
1094ae03c18Srmind return error;
1104ae03c18Srmind
111822872eaSrtr error = rfcomm_rcvd_pcb(so->so_pcb, sbspace(&so->so_rcv));
1124ae03c18Srmind if (error) {
11356a73a7dSrmind rfcomm_detach_pcb((struct rfcomm_dlc **)&so->so_pcb);
1144ae03c18Srmind return error;
1154ae03c18Srmind }
1164ae03c18Srmind return 0;
1174ae03c18Srmind }
1184ae03c18Srmind
1194ae03c18Srmind static void
rfcomm_detach(struct socket * so)12056a73a7dSrmind rfcomm_detach(struct socket *so)
1214ae03c18Srmind {
122e2e67479Smartin KASSERT(so->so_pcb != NULL);
12356a73a7dSrmind rfcomm_detach_pcb((struct rfcomm_dlc **)&so->so_pcb);
1244ae03c18Srmind KASSERT(so->so_pcb == NULL);
1254ae03c18Srmind }
1264ae03c18Srmind
127d54d7ab2Srtr static int
rfcomm_accept(struct socket * so,struct sockaddr * nam)128eddf3af3Srtr rfcomm_accept(struct socket *so, struct sockaddr *nam)
129d27b133dSrtr {
130d27b133dSrtr struct rfcomm_dlc *pcb = so->so_pcb;
131d27b133dSrtr
132d27b133dSrtr KASSERT(solocked(so));
133d27b133dSrtr KASSERT(nam != NULL);
134d27b133dSrtr
135d27b133dSrtr if (pcb == NULL)
136d27b133dSrtr return EINVAL;
137d27b133dSrtr
138eddf3af3Srtr return rfcomm_peeraddr_pcb(pcb, (struct sockaddr_bt *)nam);
139d27b133dSrtr }
140d27b133dSrtr
141d27b133dSrtr static int
rfcomm_bind(struct socket * so,struct sockaddr * nam,struct lwp * l)142a2ba5e69Srtr rfcomm_bind(struct socket *so, struct sockaddr *nam, struct lwp *l)
1436dd8eef0Srtr {
1446dd8eef0Srtr struct rfcomm_dlc *pcb = so->so_pcb;
145a2ba5e69Srtr struct sockaddr_bt *sa = (struct sockaddr_bt *)nam;
1466dd8eef0Srtr
1476dd8eef0Srtr KASSERT(solocked(so));
1486dd8eef0Srtr KASSERT(nam != NULL);
1496dd8eef0Srtr
1506dd8eef0Srtr if (pcb == NULL)
1516dd8eef0Srtr return EINVAL;
1526dd8eef0Srtr
1536dd8eef0Srtr if (sa->bt_len != sizeof(struct sockaddr_bt))
1546dd8eef0Srtr return EINVAL;
1556dd8eef0Srtr
1566dd8eef0Srtr if (sa->bt_family != AF_BLUETOOTH)
1576dd8eef0Srtr return EAFNOSUPPORT;
1586dd8eef0Srtr
1596dd8eef0Srtr return rfcomm_bind_pcb(pcb, sa);
1606dd8eef0Srtr }
1616dd8eef0Srtr
1626dd8eef0Srtr static int
rfcomm_listen(struct socket * so,struct lwp * l)163ce6a5ff6Srtr rfcomm_listen(struct socket *so, struct lwp *l)
1646dd8eef0Srtr {
1656dd8eef0Srtr struct rfcomm_dlc *pcb = so->so_pcb;
1666dd8eef0Srtr
1676dd8eef0Srtr KASSERT(solocked(so));
1686dd8eef0Srtr
1696dd8eef0Srtr if (pcb == NULL)
1706dd8eef0Srtr return EINVAL;
1716dd8eef0Srtr
1726dd8eef0Srtr return rfcomm_listen_pcb(pcb);
1736dd8eef0Srtr }
1746dd8eef0Srtr
1756dd8eef0Srtr static int
rfcomm_connect(struct socket * so,struct sockaddr * nam,struct lwp * l)176fd12cf39Srtr rfcomm_connect(struct socket *so, struct sockaddr *nam, struct lwp *l)
177ad6ae402Srtr {
178ad6ae402Srtr struct rfcomm_dlc *pcb = so->so_pcb;
179fd12cf39Srtr struct sockaddr_bt *sa = (struct sockaddr_bt *)nam;
180ad6ae402Srtr
181ad6ae402Srtr KASSERT(solocked(so));
182ad6ae402Srtr KASSERT(nam != NULL);
183ad6ae402Srtr
184ad6ae402Srtr if (pcb == NULL)
185ad6ae402Srtr return EINVAL;
186ad6ae402Srtr
187ad6ae402Srtr if (sa->bt_len != sizeof(struct sockaddr_bt))
188ad6ae402Srtr return EINVAL;
189ad6ae402Srtr
190ad6ae402Srtr if (sa->bt_family != AF_BLUETOOTH)
191ad6ae402Srtr return EAFNOSUPPORT;
192ad6ae402Srtr
193ad6ae402Srtr soisconnecting(so);
194ad6ae402Srtr return rfcomm_connect_pcb(pcb, sa);
195ad6ae402Srtr }
196ad6ae402Srtr
197ad6ae402Srtr static int
rfcomm_connect2(struct socket * so,struct socket * so2)1988cf67cc6Srtr rfcomm_connect2(struct socket *so, struct socket *so2)
1998cf67cc6Srtr {
2008cf67cc6Srtr struct rfcomm_dlc *pcb = so->so_pcb;
2018cf67cc6Srtr
2028cf67cc6Srtr KASSERT(solocked(so));
2038cf67cc6Srtr
2048cf67cc6Srtr if (pcb == NULL)
2058cf67cc6Srtr return EINVAL;
2068cf67cc6Srtr
2078cf67cc6Srtr return EOPNOTSUPP;
2088cf67cc6Srtr }
2098cf67cc6Srtr
2108cf67cc6Srtr static int
rfcomm_disconnect(struct socket * so)211892163b8Srtr rfcomm_disconnect(struct socket *so)
212892163b8Srtr {
213892163b8Srtr struct rfcomm_dlc *pcb = so->so_pcb;
214892163b8Srtr
215892163b8Srtr KASSERT(solocked(so));
216892163b8Srtr
217892163b8Srtr if (pcb == NULL)
218892163b8Srtr return EINVAL;
219892163b8Srtr
220892163b8Srtr soisdisconnecting(so);
221892163b8Srtr return rfcomm_disconnect_pcb(pcb, so->so_linger);
222892163b8Srtr }
223892163b8Srtr
224892163b8Srtr static int
rfcomm_shutdown(struct socket * so)225892163b8Srtr rfcomm_shutdown(struct socket *so)
226892163b8Srtr {
227892163b8Srtr KASSERT(solocked(so));
228892163b8Srtr
229892163b8Srtr socantsendmore(so);
230892163b8Srtr return 0;
231892163b8Srtr }
232892163b8Srtr
233892163b8Srtr static int
rfcomm_abort(struct socket * so)234892163b8Srtr rfcomm_abort(struct socket *so)
235892163b8Srtr {
236892163b8Srtr struct rfcomm_dlc *pcb = so->so_pcb;
237892163b8Srtr
238892163b8Srtr KASSERT(solocked(so));
239892163b8Srtr
240892163b8Srtr if (pcb == NULL)
241892163b8Srtr return EINVAL;
242892163b8Srtr
243892163b8Srtr rfcomm_disconnect_pcb(pcb, 0);
244892163b8Srtr soisdisconnected(so);
245892163b8Srtr rfcomm_detach(so);
246892163b8Srtr return 0;
247892163b8Srtr }
248892163b8Srtr
249892163b8Srtr static int
rfcomm_ioctl(struct socket * so,u_long cmd,void * nam,struct ifnet * ifp)250ff90c29dSrtr rfcomm_ioctl(struct socket *so, u_long cmd, void *nam, struct ifnet *ifp)
251d54d7ab2Srtr {
252d54d7ab2Srtr return EPASSTHROUGH;
253d54d7ab2Srtr }
254d54d7ab2Srtr
255a60320caSrtr static int
rfcomm_stat(struct socket * so,struct stat * ub)256a60320caSrtr rfcomm_stat(struct socket *so, struct stat *ub)
257a60320caSrtr {
258ff90c29dSrtr KASSERT(solocked(so));
259ff90c29dSrtr
260909a1fc6Srtr return 0;
261a60320caSrtr }
262a60320caSrtr
263d575eb54Srtr static int
rfcomm_peeraddr(struct socket * so,struct sockaddr * nam)264eddf3af3Srtr rfcomm_peeraddr(struct socket *so, struct sockaddr *nam)
265d575eb54Srtr {
266d575eb54Srtr struct rfcomm_dlc *pcb = so->so_pcb;
267d575eb54Srtr
268d575eb54Srtr KASSERT(solocked(so));
269d575eb54Srtr KASSERT(pcb != NULL);
270d575eb54Srtr KASSERT(nam != NULL);
271d575eb54Srtr
272eddf3af3Srtr return rfcomm_peeraddr_pcb(pcb, (struct sockaddr_bt *)nam);
273d575eb54Srtr }
274d575eb54Srtr
275d575eb54Srtr static int
rfcomm_sockaddr(struct socket * so,struct sockaddr * nam)276eddf3af3Srtr rfcomm_sockaddr(struct socket *so, struct sockaddr *nam)
277d575eb54Srtr {
278d575eb54Srtr struct rfcomm_dlc *pcb = so->so_pcb;
279d575eb54Srtr
280d575eb54Srtr KASSERT(solocked(so));
281d575eb54Srtr KASSERT(pcb != NULL);
282d575eb54Srtr KASSERT(nam != NULL);
283d575eb54Srtr
284eddf3af3Srtr return rfcomm_sockaddr_pcb(pcb, (struct sockaddr_bt *)nam);
285d575eb54Srtr }
286d575eb54Srtr
28735b22fa9Srtr static int
rfcomm_rcvd(struct socket * so,int flags,struct lwp * l)288822872eaSrtr rfcomm_rcvd(struct socket *so, int flags, struct lwp *l)
289822872eaSrtr {
290822872eaSrtr struct rfcomm_dlc *pcb = so->so_pcb;
291822872eaSrtr
292822872eaSrtr KASSERT(solocked(so));
293822872eaSrtr
294822872eaSrtr if (pcb == NULL)
295822872eaSrtr return EINVAL;
296822872eaSrtr
297822872eaSrtr return rfcomm_rcvd_pcb(pcb, sbspace(&so->so_rcv));
298822872eaSrtr }
299822872eaSrtr
300822872eaSrtr static int
rfcomm_recvoob(struct socket * so,struct mbuf * m,int flags)30135b22fa9Srtr rfcomm_recvoob(struct socket *so, struct mbuf *m, int flags)
30235b22fa9Srtr {
30335b22fa9Srtr KASSERT(solocked(so));
30435b22fa9Srtr
30535b22fa9Srtr return EOPNOTSUPP;
30635b22fa9Srtr }
30735b22fa9Srtr
30835b22fa9Srtr static int
rfcomm_send(struct socket * so,struct mbuf * m,struct sockaddr * nam,struct mbuf * control,struct lwp * l)309fd12cf39Srtr rfcomm_send(struct socket *so, struct mbuf *m, struct sockaddr *nam,
310651e5bd3Srtr struct mbuf *control, struct lwp *l)
311651e5bd3Srtr {
312651e5bd3Srtr struct rfcomm_dlc *pcb = so->so_pcb;
313651e5bd3Srtr int err = 0;
314651e5bd3Srtr struct mbuf *m0;
315651e5bd3Srtr
316651e5bd3Srtr KASSERT(solocked(so));
317651e5bd3Srtr KASSERT(m != NULL);
318651e5bd3Srtr
319*481d3881Srin m_freem(control); /* no use for that */
320651e5bd3Srtr
321651e5bd3Srtr if (pcb == NULL) {
322651e5bd3Srtr err = EINVAL;
323651e5bd3Srtr goto release;
324651e5bd3Srtr }
325651e5bd3Srtr
326651e5bd3Srtr m0 = m_copypacket(m, M_DONTWAIT);
327651e5bd3Srtr if (m0 == NULL) {
328651e5bd3Srtr err = ENOMEM;
329651e5bd3Srtr goto release;
330651e5bd3Srtr }
331651e5bd3Srtr
332651e5bd3Srtr sbappendstream(&so->so_snd, m);
333651e5bd3Srtr return rfcomm_send_pcb(pcb, m0);
334651e5bd3Srtr
335651e5bd3Srtr release:
336651e5bd3Srtr m_freem(m);
337651e5bd3Srtr return err;
338651e5bd3Srtr }
339651e5bd3Srtr
340651e5bd3Srtr static int
rfcomm_sendoob(struct socket * so,struct mbuf * m,struct mbuf * control)34135b22fa9Srtr rfcomm_sendoob(struct socket *so, struct mbuf *m, struct mbuf *control)
34235b22fa9Srtr {
34335b22fa9Srtr KASSERT(solocked(so));
34435b22fa9Srtr
34535b22fa9Srtr m_freem(m);
34635b22fa9Srtr m_freem(control);
34735b22fa9Srtr
34835b22fa9Srtr return EOPNOTSUPP;
34935b22fa9Srtr }
35035b22fa9Srtr
3518cf67cc6Srtr static int
rfcomm_purgeif(struct socket * so,struct ifnet * ifp)3528cf67cc6Srtr rfcomm_purgeif(struct socket *so, struct ifnet *ifp)
3538cf67cc6Srtr {
3548cf67cc6Srtr
3558cf67cc6Srtr return EOPNOTSUPP;
3568cf67cc6Srtr }
3578cf67cc6Srtr
358a5c89047Sgdamore /*
359fd7356a9Splunky * rfcomm_ctloutput(req, socket, sockopt)
360a5c89047Sgdamore *
361a5c89047Sgdamore */
362a5c89047Sgdamore int
rfcomm_ctloutput(int req,struct socket * so,struct sockopt * sopt)363fd7356a9Splunky rfcomm_ctloutput(int req, struct socket *so, struct sockopt *sopt)
364a5c89047Sgdamore {
365a5c89047Sgdamore struct rfcomm_dlc *pcb = so->so_pcb;
366a5c89047Sgdamore int err = 0;
367a5c89047Sgdamore
368a5c89047Sgdamore DPRINTFN(2, "%s\n", prcorequests[req]);
369a5c89047Sgdamore
370162ec756Splunky if (pcb == NULL)
371162ec756Splunky return EINVAL;
372162ec756Splunky
373fd7356a9Splunky if (sopt->sopt_level != BTPROTO_RFCOMM)
374162ec756Splunky return ENOPROTOOPT;
375a5c89047Sgdamore
376a5c89047Sgdamore switch(req) {
377a5c89047Sgdamore case PRCO_GETOPT:
378fd7356a9Splunky err = rfcomm_getopt(pcb, sopt);
379a5c89047Sgdamore break;
380a5c89047Sgdamore
381a5c89047Sgdamore case PRCO_SETOPT:
382fd7356a9Splunky err = rfcomm_setopt(pcb, sopt);
383a5c89047Sgdamore break;
384a5c89047Sgdamore
385a5c89047Sgdamore default:
386162ec756Splunky err = ENOPROTOOPT;
387a5c89047Sgdamore break;
388a5c89047Sgdamore }
389a5c89047Sgdamore
390a5c89047Sgdamore return err;
391a5c89047Sgdamore }
392a5c89047Sgdamore
393a5c89047Sgdamore /**********************************************************************
394a5c89047Sgdamore *
395a5c89047Sgdamore * RFCOMM callbacks
396a5c89047Sgdamore */
397a5c89047Sgdamore
398a5c89047Sgdamore static void
rfcomm_connecting(void * arg)399168cd830Schristos rfcomm_connecting(void *arg)
400a5c89047Sgdamore {
401a5c89047Sgdamore /* struct socket *so = arg; */
402a5c89047Sgdamore
403f21bb768Splunky KASSERT(arg != NULL);
404a5c89047Sgdamore DPRINTF("Connecting\n");
405a5c89047Sgdamore }
406a5c89047Sgdamore
407a5c89047Sgdamore static void
rfcomm_connected(void * arg)408a5c89047Sgdamore rfcomm_connected(void *arg)
409a5c89047Sgdamore {
410a5c89047Sgdamore struct socket *so = arg;
411a5c89047Sgdamore
412f21bb768Splunky KASSERT(so != NULL);
413a5c89047Sgdamore DPRINTF("Connected\n");
414a5c89047Sgdamore soisconnected(so);
415a5c89047Sgdamore }
416a5c89047Sgdamore
417a5c89047Sgdamore static void
rfcomm_disconnected(void * arg,int err)418a5c89047Sgdamore rfcomm_disconnected(void *arg, int err)
419a5c89047Sgdamore {
420a5c89047Sgdamore struct socket *so = arg;
421a5c89047Sgdamore
422f21bb768Splunky KASSERT(so != NULL);
423a5c89047Sgdamore DPRINTF("Disconnected\n");
424a5c89047Sgdamore
425a5c89047Sgdamore so->so_error = err;
426a5c89047Sgdamore soisdisconnected(so);
427a5c89047Sgdamore }
428a5c89047Sgdamore
429a5c89047Sgdamore static void *
rfcomm_newconn(void * arg,struct sockaddr_bt * laddr,struct sockaddr_bt * raddr)430168cd830Schristos rfcomm_newconn(void *arg, struct sockaddr_bt *laddr,
431168cd830Schristos struct sockaddr_bt *raddr)
432a5c89047Sgdamore {
433a5c89047Sgdamore struct socket *so = arg;
434a5c89047Sgdamore
435a5c89047Sgdamore DPRINTF("New Connection\n");
4368088e729Srmind so = sonewconn(so, false);
437a5c89047Sgdamore if (so == NULL)
438a5c89047Sgdamore return NULL;
439a5c89047Sgdamore
440a5c89047Sgdamore soisconnecting(so);
441a5c89047Sgdamore
442a5c89047Sgdamore return so->so_pcb;
443a5c89047Sgdamore }
444a5c89047Sgdamore
445a5c89047Sgdamore /*
446a5c89047Sgdamore * rfcomm_complete(rfcomm_dlc, length)
447a5c89047Sgdamore *
448a5c89047Sgdamore * length bytes are sent and may be removed from socket buffer
449a5c89047Sgdamore */
450a5c89047Sgdamore static void
rfcomm_complete(void * arg,int length)451a5c89047Sgdamore rfcomm_complete(void *arg, int length)
452a5c89047Sgdamore {
453a5c89047Sgdamore struct socket *so = arg;
454a5c89047Sgdamore
455a5c89047Sgdamore sbdrop(&so->so_snd, length);
456a5c89047Sgdamore sowwakeup(so);
457a5c89047Sgdamore }
458a5c89047Sgdamore
459a5c89047Sgdamore /*
460f5db72e7Splunky * rfcomm_linkmode(rfcomm_dlc, new)
461f5db72e7Splunky *
462f5db72e7Splunky * link mode change notification.
463f5db72e7Splunky */
464f5db72e7Splunky static void
rfcomm_linkmode(void * arg,int new)465f5db72e7Splunky rfcomm_linkmode(void *arg, int new)
466f5db72e7Splunky {
467f5db72e7Splunky struct socket *so = arg;
468fd7356a9Splunky struct sockopt sopt;
469f5db72e7Splunky int mode;
470f5db72e7Splunky
471f5db72e7Splunky DPRINTF("auth %s, encrypt %s, secure %s\n",
472f5db72e7Splunky (new & RFCOMM_LM_AUTH ? "on" : "off"),
473f5db72e7Splunky (new & RFCOMM_LM_ENCRYPT ? "on" : "off"),
474f5db72e7Splunky (new & RFCOMM_LM_SECURE ? "on" : "off"));
475f5db72e7Splunky
476fd7356a9Splunky sockopt_init(&sopt, BTPROTO_RFCOMM, SO_RFCOMM_LM, 0);
477fd7356a9Splunky (void)rfcomm_getopt(so->so_pcb, &sopt);
478fd7356a9Splunky (void)sockopt_getint(&sopt, &mode);
479fd7356a9Splunky sockopt_destroy(&sopt);
480fd7356a9Splunky
481f5db72e7Splunky if (((mode & RFCOMM_LM_AUTH) && !(new & RFCOMM_LM_AUTH))
482f5db72e7Splunky || ((mode & RFCOMM_LM_ENCRYPT) && !(new & RFCOMM_LM_ENCRYPT))
483f5db72e7Splunky || ((mode & RFCOMM_LM_SECURE) && !(new & RFCOMM_LM_SECURE)))
484892163b8Srtr rfcomm_disconnect_pcb(so->so_pcb, 0);
485f5db72e7Splunky }
486f5db72e7Splunky
487f5db72e7Splunky /*
488a5c89047Sgdamore * rfcomm_input(rfcomm_dlc, mbuf)
489a5c89047Sgdamore */
490a5c89047Sgdamore static void
rfcomm_input(void * arg,struct mbuf * m)491a5c89047Sgdamore rfcomm_input(void *arg, struct mbuf *m)
492a5c89047Sgdamore {
493a5c89047Sgdamore struct socket *so = arg;
494a5c89047Sgdamore
495f21bb768Splunky KASSERT(so != NULL);
496a5c89047Sgdamore
497a5c89047Sgdamore if (m->m_pkthdr.len > sbspace(&so->so_rcv)) {
498a5c89047Sgdamore printf("%s: %d bytes dropped (socket buffer full)\n",
499a5c89047Sgdamore __func__, m->m_pkthdr.len);
500a5c89047Sgdamore m_freem(m);
501a5c89047Sgdamore return;
502a5c89047Sgdamore }
503a5c89047Sgdamore
504a5c89047Sgdamore DPRINTFN(10, "received %d bytes\n", m->m_pkthdr.len);
505a5c89047Sgdamore
506a5c89047Sgdamore sbappendstream(&so->so_rcv, m);
507a5c89047Sgdamore sorwakeup(so);
508a5c89047Sgdamore }
50939bd8deeSrmind
510e401453fSrmind PR_WRAP_USRREQS(rfcomm)
51139bd8deeSrmind
512e401453fSrmind #define rfcomm_attach rfcomm_attach_wrapper
513e401453fSrmind #define rfcomm_detach rfcomm_detach_wrapper
514d27b133dSrtr #define rfcomm_accept rfcomm_accept_wrapper
5156dd8eef0Srtr #define rfcomm_bind rfcomm_bind_wrapper
5166dd8eef0Srtr #define rfcomm_listen rfcomm_listen_wrapper
517ad6ae402Srtr #define rfcomm_connect rfcomm_connect_wrapper
5188cf67cc6Srtr #define rfcomm_connect2 rfcomm_connect2_wrapper
519892163b8Srtr #define rfcomm_disconnect rfcomm_disconnect_wrapper
520892163b8Srtr #define rfcomm_shutdown rfcomm_shutdown_wrapper
521892163b8Srtr #define rfcomm_abort rfcomm_abort_wrapper
522d54d7ab2Srtr #define rfcomm_ioctl rfcomm_ioctl_wrapper
523a60320caSrtr #define rfcomm_stat rfcomm_stat_wrapper
524d575eb54Srtr #define rfcomm_peeraddr rfcomm_peeraddr_wrapper
525d575eb54Srtr #define rfcomm_sockaddr rfcomm_sockaddr_wrapper
526822872eaSrtr #define rfcomm_rcvd rfcomm_rcvd_wrapper
52735b22fa9Srtr #define rfcomm_recvoob rfcomm_recvoob_wrapper
528651e5bd3Srtr #define rfcomm_send rfcomm_send_wrapper
52935b22fa9Srtr #define rfcomm_sendoob rfcomm_sendoob_wrapper
5308cf67cc6Srtr #define rfcomm_purgeif rfcomm_purgeif_wrapper
53139bd8deeSrmind
53239bd8deeSrmind const struct pr_usrreqs rfcomm_usrreqs = {
53356a73a7dSrmind .pr_attach = rfcomm_attach,
53456a73a7dSrmind .pr_detach = rfcomm_detach,
535d27b133dSrtr .pr_accept = rfcomm_accept,
5366dd8eef0Srtr .pr_bind = rfcomm_bind,
5376dd8eef0Srtr .pr_listen = rfcomm_listen,
538ad6ae402Srtr .pr_connect = rfcomm_connect,
5398cf67cc6Srtr .pr_connect2 = rfcomm_connect2,
540892163b8Srtr .pr_disconnect = rfcomm_disconnect,
541892163b8Srtr .pr_shutdown = rfcomm_shutdown,
542892163b8Srtr .pr_abort = rfcomm_abort,
543d54d7ab2Srtr .pr_ioctl = rfcomm_ioctl,
544a60320caSrtr .pr_stat = rfcomm_stat,
545d575eb54Srtr .pr_peeraddr = rfcomm_peeraddr,
546d575eb54Srtr .pr_sockaddr = rfcomm_sockaddr,
547822872eaSrtr .pr_rcvd = rfcomm_rcvd,
54835b22fa9Srtr .pr_recvoob = rfcomm_recvoob,
549651e5bd3Srtr .pr_send = rfcomm_send,
55035b22fa9Srtr .pr_sendoob = rfcomm_sendoob,
5518cf67cc6Srtr .pr_purgeif = rfcomm_purgeif,
55239bd8deeSrmind };
553