xref: /netbsd-src/sys/netbt/rfcomm_socket.c (revision 481d3881954fd794ca5f2d880b68c53a5db8620e)
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