183aacedeSHasso Tepper /* $OpenBSD: src/sys/netbt/rfcomm_socket.c,v 1.2 2008/02/24 21:34:48 uwe Exp $ */
283aacedeSHasso Tepper /* $NetBSD: rfcomm_socket.c,v 1.8 2007/10/15 18:04:34 plunky Exp $ */
30a9108ebSHasso Tepper
40a9108ebSHasso Tepper /*-
50a9108ebSHasso Tepper * Copyright (c) 2006 Itronix Inc.
60a9108ebSHasso Tepper * All rights reserved.
70a9108ebSHasso Tepper *
80a9108ebSHasso Tepper * Written by Iain Hibbert for Itronix Inc.
90a9108ebSHasso Tepper *
100a9108ebSHasso Tepper * Redistribution and use in source and binary forms, with or without
110a9108ebSHasso Tepper * modification, are permitted provided that the following conditions
120a9108ebSHasso Tepper * are met:
130a9108ebSHasso Tepper * 1. Redistributions of source code must retain the above copyright
140a9108ebSHasso Tepper * notice, this list of conditions and the following disclaimer.
150a9108ebSHasso Tepper * 2. Redistributions in binary form must reproduce the above copyright
160a9108ebSHasso Tepper * notice, this list of conditions and the following disclaimer in the
170a9108ebSHasso Tepper * documentation and/or other materials provided with the distribution.
180a9108ebSHasso Tepper * 3. The name of Itronix Inc. may not be used to endorse
190a9108ebSHasso Tepper * or promote products derived from this software without specific
200a9108ebSHasso Tepper * prior written permission.
210a9108ebSHasso Tepper *
220a9108ebSHasso Tepper * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
230a9108ebSHasso Tepper * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
240a9108ebSHasso Tepper * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
250a9108ebSHasso Tepper * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
260a9108ebSHasso Tepper * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
270a9108ebSHasso Tepper * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
280a9108ebSHasso Tepper * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
290a9108ebSHasso Tepper * ON ANY THEORY OF LIABILITY, WHETHER IN
300a9108ebSHasso Tepper * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
310a9108ebSHasso Tepper * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
320a9108ebSHasso Tepper * POSSIBILITY OF SUCH DAMAGE.
330a9108ebSHasso Tepper */
340a9108ebSHasso Tepper
350a9108ebSHasso Tepper /* load symbolic names */
360a9108ebSHasso Tepper #ifdef BLUETOOTH_DEBUG
370a9108ebSHasso Tepper #define PRUREQUESTS
380a9108ebSHasso Tepper #define PRCOREQUESTS
390a9108ebSHasso Tepper #endif
400a9108ebSHasso Tepper
410a9108ebSHasso Tepper #include <sys/param.h>
420a9108ebSHasso Tepper #include <sys/domain.h>
430a9108ebSHasso Tepper #include <sys/kernel.h>
44*c443c74fSzrj #include <sys/malloc.h> /* for M_NOWAIT */
450a9108ebSHasso Tepper #include <sys/mbuf.h>
460a9108ebSHasso Tepper #include <sys/proc.h>
470a9108ebSHasso Tepper #include <sys/protosw.h>
480a9108ebSHasso Tepper #include <sys/socket.h>
490a9108ebSHasso Tepper #include <sys/socketvar.h>
500a9108ebSHasso Tepper #include <sys/systm.h>
51002c1265SMatthew Dillon
52002c1265SMatthew Dillon #include <sys/msgport2.h>
53002c1265SMatthew Dillon
540a9108ebSHasso Tepper #include <vm/vm_zone.h>
550a9108ebSHasso Tepper
560a9108ebSHasso Tepper #include <netbt/bluetooth.h>
570a9108ebSHasso Tepper #include <netbt/hci.h> /* XXX for EPASSTHROUGH */
580a9108ebSHasso Tepper #include <netbt/rfcomm.h>
590a9108ebSHasso Tepper
600a9108ebSHasso Tepper /****************************************************************************
610a9108ebSHasso Tepper *
620a9108ebSHasso Tepper * RFCOMM SOCK_STREAM Sockets - serial line emulation
630a9108ebSHasso Tepper *
640a9108ebSHasso Tepper */
650a9108ebSHasso Tepper
660a9108ebSHasso Tepper static void rfcomm_connecting(void *);
670a9108ebSHasso Tepper static void rfcomm_connected(void *);
680a9108ebSHasso Tepper static void rfcomm_disconnected(void *, int);
690a9108ebSHasso Tepper static void *rfcomm_newconn(void *, struct sockaddr_bt *, struct sockaddr_bt *);
700a9108ebSHasso Tepper static void rfcomm_complete(void *, int);
710a9108ebSHasso Tepper static void rfcomm_linkmode(void *, int);
720a9108ebSHasso Tepper static void rfcomm_input(void *, struct mbuf *);
730a9108ebSHasso Tepper
740a9108ebSHasso Tepper static const struct btproto rfcomm_proto = {
750a9108ebSHasso Tepper rfcomm_connecting,
760a9108ebSHasso Tepper rfcomm_connected,
770a9108ebSHasso Tepper rfcomm_disconnected,
780a9108ebSHasso Tepper rfcomm_newconn,
790a9108ebSHasso Tepper rfcomm_complete,
800a9108ebSHasso Tepper rfcomm_linkmode,
810a9108ebSHasso Tepper rfcomm_input,
820a9108ebSHasso Tepper };
830a9108ebSHasso Tepper
840a9108ebSHasso Tepper /* sysctl variables */
850a9108ebSHasso Tepper int rfcomm_sendspace = 4096;
860a9108ebSHasso Tepper int rfcomm_recvspace = 4096;
870a9108ebSHasso Tepper
880a9108ebSHasso Tepper /*
890a9108ebSHasso Tepper * rfcomm_ctloutput(request, socket, level, optname, opt)
900a9108ebSHasso Tepper *
910a9108ebSHasso Tepper */
92002c1265SMatthew Dillon void
rfcomm_ctloutput(netmsg_t msg)93002c1265SMatthew Dillon rfcomm_ctloutput(netmsg_t msg)
940a9108ebSHasso Tepper {
95002c1265SMatthew Dillon struct socket *so = msg->ctloutput.base.nm_so;
96002c1265SMatthew Dillon struct sockopt *sopt = msg->ctloutput.nm_sopt;
970a9108ebSHasso Tepper struct rfcomm_dlc *pcb = (struct rfcomm_dlc *) so->so_pcb;
980a9108ebSHasso Tepper struct mbuf *m;
99002c1265SMatthew Dillon int error = 0;
1000a9108ebSHasso Tepper
1010a9108ebSHasso Tepper #ifdef notyet /* XXX */
1020a9108ebSHasso Tepper DPRINTFN(2, "%s\n", prcorequests[sopt->sopt_dir]);
1030a9108ebSHasso Tepper #endif
1040a9108ebSHasso Tepper
105002c1265SMatthew Dillon if (pcb == NULL) {
106002c1265SMatthew Dillon error = EINVAL;
107002c1265SMatthew Dillon goto out;
108002c1265SMatthew Dillon }
1090a9108ebSHasso Tepper
110002c1265SMatthew Dillon if (sopt->sopt_level != BTPROTO_RFCOMM) {
111002c1265SMatthew Dillon error = ENOPROTOOPT;
112002c1265SMatthew Dillon goto out;
113002c1265SMatthew Dillon }
1140a9108ebSHasso Tepper
1150a9108ebSHasso Tepper switch(sopt->sopt_dir) {
1160a9108ebSHasso Tepper case PRCO_GETOPT:
117b5523eacSSascha Wildner m = m_get(M_WAITOK, MT_DATA);
1180a9108ebSHasso Tepper crit_enter();
1190a9108ebSHasso Tepper m->m_len = rfcomm_getopt(pcb, sopt->sopt_name, mtod(m, void *));
1200a9108ebSHasso Tepper crit_exit();
1210a9108ebSHasso Tepper if (m->m_len == 0) {
1220a9108ebSHasso Tepper m_freem(m);
1230a9108ebSHasso Tepper m = NULL;
124002c1265SMatthew Dillon error = ENOPROTOOPT;
1250a9108ebSHasso Tepper }
126d82b71f8SAggelos Economopoulos soopt_from_kbuf(sopt, mtod(m, void *), m->m_len);
1270a9108ebSHasso Tepper break;
1280a9108ebSHasso Tepper
1290a9108ebSHasso Tepper case PRCO_SETOPT:
130002c1265SMatthew Dillon error = rfcomm_setopt2(pcb, sopt->sopt_name, so, sopt);
1310a9108ebSHasso Tepper
1320a9108ebSHasso Tepper break;
1330a9108ebSHasso Tepper
1340a9108ebSHasso Tepper default:
135002c1265SMatthew Dillon error = ENOPROTOOPT;
1360a9108ebSHasso Tepper break;
1370a9108ebSHasso Tepper }
138002c1265SMatthew Dillon out:
139002c1265SMatthew Dillon lwkt_replymsg(&msg->ctloutput.base.lmsg, error);
1400a9108ebSHasso Tepper }
1410a9108ebSHasso Tepper
1420a9108ebSHasso Tepper /**********************************************************************
1430a9108ebSHasso Tepper *
1440a9108ebSHasso Tepper * RFCOMM callbacks
1450a9108ebSHasso Tepper */
1460a9108ebSHasso Tepper
1470a9108ebSHasso Tepper static void
rfcomm_connecting(void * arg)1480a9108ebSHasso Tepper rfcomm_connecting(void *arg)
1490a9108ebSHasso Tepper {
1500a9108ebSHasso Tepper /* struct socket *so = arg; */
1510a9108ebSHasso Tepper
1520a9108ebSHasso Tepper KKASSERT(arg != NULL);
1530a9108ebSHasso Tepper DPRINTF("Connecting\n");
1540a9108ebSHasso Tepper }
1550a9108ebSHasso Tepper
1560a9108ebSHasso Tepper static void
rfcomm_connected(void * arg)1570a9108ebSHasso Tepper rfcomm_connected(void *arg)
1580a9108ebSHasso Tepper {
1590a9108ebSHasso Tepper struct socket *so = arg;
1600a9108ebSHasso Tepper
1610a9108ebSHasso Tepper KKASSERT(so != NULL);
1620a9108ebSHasso Tepper DPRINTF("Connected\n");
1630a9108ebSHasso Tepper soisconnected(so);
1640a9108ebSHasso Tepper }
1650a9108ebSHasso Tepper
1660a9108ebSHasso Tepper static void
rfcomm_disconnected(void * arg,int err)1670a9108ebSHasso Tepper rfcomm_disconnected(void *arg, int err)
1680a9108ebSHasso Tepper {
1690a9108ebSHasso Tepper struct socket *so = arg;
1700a9108ebSHasso Tepper
1710a9108ebSHasso Tepper KKASSERT(so != NULL);
1720a9108ebSHasso Tepper DPRINTF("Disconnected\n");
1730a9108ebSHasso Tepper
1740a9108ebSHasso Tepper so->so_error = err;
1750a9108ebSHasso Tepper soisdisconnected(so);
1760a9108ebSHasso Tepper }
1770a9108ebSHasso Tepper
1780a9108ebSHasso Tepper static void *
rfcomm_newconn(void * arg,struct sockaddr_bt * laddr,struct sockaddr_bt * raddr)1790a9108ebSHasso Tepper rfcomm_newconn(void *arg, struct sockaddr_bt *laddr,
1800a9108ebSHasso Tepper struct sockaddr_bt *raddr)
1810a9108ebSHasso Tepper {
1820a9108ebSHasso Tepper struct socket *so = arg;
1830a9108ebSHasso Tepper
1840a9108ebSHasso Tepper DPRINTF("New Connection\n");
1850a9108ebSHasso Tepper so = sonewconn(so, 0);
1860a9108ebSHasso Tepper if (so == NULL)
1870a9108ebSHasso Tepper return NULL;
1880a9108ebSHasso Tepper
1890a9108ebSHasso Tepper soisconnecting(so);
1900a9108ebSHasso Tepper
1910a9108ebSHasso Tepper return so->so_pcb;
1920a9108ebSHasso Tepper }
1930a9108ebSHasso Tepper
1940a9108ebSHasso Tepper /*
1950a9108ebSHasso Tepper * rfcomm_complete(rfcomm_dlc, length)
1960a9108ebSHasso Tepper *
1970a9108ebSHasso Tepper * length bytes are sent and may be removed from socket buffer
1980a9108ebSHasso Tepper */
1990a9108ebSHasso Tepper static void
rfcomm_complete(void * arg,int length)2000a9108ebSHasso Tepper rfcomm_complete(void *arg, int length)
2010a9108ebSHasso Tepper {
2020a9108ebSHasso Tepper struct socket *so = arg;
2030a9108ebSHasso Tepper
2040a9108ebSHasso Tepper sbdrop(&so->so_snd.sb, length);
2050a9108ebSHasso Tepper sowwakeup(so);
2060a9108ebSHasso Tepper }
2070a9108ebSHasso Tepper
2080a9108ebSHasso Tepper /*
2090a9108ebSHasso Tepper * rfcomm_linkmode(rfcomm_dlc, new)
2100a9108ebSHasso Tepper *
2110a9108ebSHasso Tepper * link mode change notification.
2120a9108ebSHasso Tepper */
2130a9108ebSHasso Tepper static void
rfcomm_linkmode(void * arg,int new)2140a9108ebSHasso Tepper rfcomm_linkmode(void *arg, int new)
2150a9108ebSHasso Tepper {
2160a9108ebSHasso Tepper struct socket *so = arg;
2170a9108ebSHasso Tepper int mode;
2180a9108ebSHasso Tepper
2190a9108ebSHasso Tepper DPRINTF("auth %s, encrypt %s, secure %s\n",
2200a9108ebSHasso Tepper (new & RFCOMM_LM_AUTH ? "on" : "off"),
2210a9108ebSHasso Tepper (new & RFCOMM_LM_ENCRYPT ? "on" : "off"),
2220a9108ebSHasso Tepper (new & RFCOMM_LM_SECURE ? "on" : "off"));
2230a9108ebSHasso Tepper
2240a9108ebSHasso Tepper (void)rfcomm_getopt(so->so_pcb, SO_RFCOMM_LM, &mode);
2250a9108ebSHasso Tepper if (((mode & RFCOMM_LM_AUTH) && !(new & RFCOMM_LM_AUTH))
2260a9108ebSHasso Tepper || ((mode & RFCOMM_LM_ENCRYPT) && !(new & RFCOMM_LM_ENCRYPT))
2270a9108ebSHasso Tepper || ((mode & RFCOMM_LM_SECURE) && !(new & RFCOMM_LM_SECURE)))
2280a9108ebSHasso Tepper rfcomm_disconnect(so->so_pcb, 0);
2290a9108ebSHasso Tepper }
2300a9108ebSHasso Tepper
2310a9108ebSHasso Tepper /*
2320a9108ebSHasso Tepper * rfcomm_input(rfcomm_dlc, mbuf)
2330a9108ebSHasso Tepper */
2340a9108ebSHasso Tepper static void
rfcomm_input(void * arg,struct mbuf * m)2350a9108ebSHasso Tepper rfcomm_input(void *arg, struct mbuf *m)
2360a9108ebSHasso Tepper {
2370a9108ebSHasso Tepper struct socket *so = arg;
2380a9108ebSHasso Tepper
2390a9108ebSHasso Tepper KKASSERT(so != NULL);
2400a9108ebSHasso Tepper
2410a9108ebSHasso Tepper if (m->m_pkthdr.len > sbspace(&so->so_rcv)) {
2420a9108ebSHasso Tepper kprintf("%s: %d bytes dropped (socket buffer full)\n",
2430a9108ebSHasso Tepper __func__, m->m_pkthdr.len);
2440a9108ebSHasso Tepper m_freem(m);
2450a9108ebSHasso Tepper return;
2460a9108ebSHasso Tepper }
2470a9108ebSHasso Tepper
2480a9108ebSHasso Tepper DPRINTFN(10, "received %d bytes\n", m->m_pkthdr.len);
2490a9108ebSHasso Tepper
2500a9108ebSHasso Tepper sbappendstream(&so->so_rcv.sb, m);
2510a9108ebSHasso Tepper sorwakeup(so);
2520a9108ebSHasso Tepper }
2530a9108ebSHasso Tepper
2540a9108ebSHasso Tepper /*
2550a9108ebSHasso Tepper * Implementation of usrreqs.
2560a9108ebSHasso Tepper */
257002c1265SMatthew Dillon static void
rfcomm_sdetach(netmsg_t msg)258002c1265SMatthew Dillon rfcomm_sdetach(netmsg_t msg)
2590a9108ebSHasso Tepper {
260002c1265SMatthew Dillon struct socket *so = msg->detach.base.nm_so;
261002c1265SMatthew Dillon int error;
262002c1265SMatthew Dillon
263002c1265SMatthew Dillon error = rfcomm_detach((struct rfcomm_dlc **)&so->so_pcb);
264002c1265SMatthew Dillon lwkt_replymsg(&msg->detach.base.lmsg, error);
2650a9108ebSHasso Tepper }
2660a9108ebSHasso Tepper
2676cef7136SMatthew Dillon /*
2686cef7136SMatthew Dillon * NOTE: (so) is referenced from soabort*() and netmsg_pru_abort()
2696cef7136SMatthew Dillon * will sofree() it when we return.
2706cef7136SMatthew Dillon */
271002c1265SMatthew Dillon static void
rfcomm_sabort(netmsg_t msg)272002c1265SMatthew Dillon rfcomm_sabort(netmsg_t msg)
2730a9108ebSHasso Tepper {
274002c1265SMatthew Dillon struct socket *so = msg->abort.base.nm_so;
2750a9108ebSHasso Tepper struct rfcomm_dlc *pcb = (struct rfcomm_dlc *) so->so_pcb;
2760a9108ebSHasso Tepper
2770a9108ebSHasso Tepper rfcomm_disconnect(pcb, 0);
2780a9108ebSHasso Tepper soisdisconnected(so);
279002c1265SMatthew Dillon rfcomm_sdetach(msg);
280002c1265SMatthew Dillon /* msg invalid now */
2810a9108ebSHasso Tepper }
2820a9108ebSHasso Tepper
283002c1265SMatthew Dillon static void
rfcomm_sdisconnect(netmsg_t msg)284002c1265SMatthew Dillon rfcomm_sdisconnect(netmsg_t msg)
2850a9108ebSHasso Tepper {
286002c1265SMatthew Dillon struct socket *so = msg->abort.base.nm_so;
2870a9108ebSHasso Tepper struct rfcomm_dlc *pcb = (struct rfcomm_dlc *) so->so_pcb;
288002c1265SMatthew Dillon int error;
2890a9108ebSHasso Tepper
2900a9108ebSHasso Tepper soisdisconnecting(so);
291002c1265SMatthew Dillon error = rfcomm_disconnect(pcb, so->so_linger);
292002c1265SMatthew Dillon lwkt_replymsg(&msg->disconnect.base.lmsg, error);
2930a9108ebSHasso Tepper }
2940a9108ebSHasso Tepper
295002c1265SMatthew Dillon static void
rfcomm_scontrol(netmsg_t msg)296002c1265SMatthew Dillon rfcomm_scontrol(netmsg_t msg)
2970a9108ebSHasso Tepper {
298002c1265SMatthew Dillon lwkt_replymsg(&msg->control.base.lmsg, EPASSTHROUGH);
2990a9108ebSHasso Tepper }
3000a9108ebSHasso Tepper
301002c1265SMatthew Dillon static void
rfcomm_sattach(netmsg_t msg)302002c1265SMatthew Dillon rfcomm_sattach(netmsg_t msg)
3030a9108ebSHasso Tepper {
304002c1265SMatthew Dillon struct socket *so = msg->attach.base.nm_so;
3050a9108ebSHasso Tepper struct rfcomm_dlc *pcb = (struct rfcomm_dlc *) so->so_pcb;
306002c1265SMatthew Dillon int error;
3070a9108ebSHasso Tepper
308002c1265SMatthew Dillon if (pcb != NULL) {
309002c1265SMatthew Dillon error = EINVAL;
310002c1265SMatthew Dillon goto out;
311002c1265SMatthew Dillon }
3120a9108ebSHasso Tepper
3130a9108ebSHasso Tepper /*
3140a9108ebSHasso Tepper * Since we have nothing to add, we attach the DLC
3150a9108ebSHasso Tepper * structure directly to our PCB pointer.
3160a9108ebSHasso Tepper */
317002c1265SMatthew Dillon error = soreserve(so, rfcomm_sendspace, rfcomm_recvspace, NULL);
318002c1265SMatthew Dillon if (error)
319002c1265SMatthew Dillon goto out;
32083aacedeSHasso Tepper
321002c1265SMatthew Dillon error = rfcomm_attach((struct rfcomm_dlc **)&so->so_pcb,
3220a9108ebSHasso Tepper &rfcomm_proto, so);
323002c1265SMatthew Dillon if (error)
324002c1265SMatthew Dillon goto out;
3250a9108ebSHasso Tepper
326002c1265SMatthew Dillon error = rfcomm_rcvd(so->so_pcb, sbspace(&so->so_rcv));
327002c1265SMatthew Dillon if (error)
32883aacedeSHasso Tepper rfcomm_detach((struct rfcomm_dlc **)&so->so_pcb);
329002c1265SMatthew Dillon out:
330002c1265SMatthew Dillon lwkt_replymsg(&msg->attach.base.lmsg, error);
33183aacedeSHasso Tepper }
3320a9108ebSHasso Tepper
333002c1265SMatthew Dillon static void
rfcomm_sbind(netmsg_t msg)334002c1265SMatthew Dillon rfcomm_sbind(netmsg_t msg)
3350a9108ebSHasso Tepper {
336002c1265SMatthew Dillon struct socket *so = msg->bind.base.nm_so;
337002c1265SMatthew Dillon struct sockaddr *nam = msg->bind.nm_nam;
3380a9108ebSHasso Tepper struct rfcomm_dlc *pcb = (struct rfcomm_dlc *) so->so_pcb;
3390a9108ebSHasso Tepper struct sockaddr_bt *sa;
340002c1265SMatthew Dillon int error;
3410a9108ebSHasso Tepper
3420a9108ebSHasso Tepper KKASSERT(nam != NULL);
3430a9108ebSHasso Tepper sa = (struct sockaddr_bt *)nam;
3440a9108ebSHasso Tepper
345002c1265SMatthew Dillon if (sa->bt_len != sizeof(struct sockaddr_bt)) {
346002c1265SMatthew Dillon error = EINVAL;
347002c1265SMatthew Dillon } else if (sa->bt_family != AF_BLUETOOTH) {
348002c1265SMatthew Dillon error = EAFNOSUPPORT;
349002c1265SMatthew Dillon } else {
350002c1265SMatthew Dillon error = rfcomm_bind(pcb, sa);
351002c1265SMatthew Dillon }
352002c1265SMatthew Dillon lwkt_replymsg(&msg->bind.base.lmsg, error);
3530a9108ebSHasso Tepper }
3540a9108ebSHasso Tepper
355002c1265SMatthew Dillon static void
rfcomm_sconnect(netmsg_t msg)356002c1265SMatthew Dillon rfcomm_sconnect(netmsg_t msg)
3570a9108ebSHasso Tepper {
358002c1265SMatthew Dillon struct socket *so = msg->connect.base.nm_so;
359002c1265SMatthew Dillon struct sockaddr *nam = msg->connect.nm_nam;
3600a9108ebSHasso Tepper struct rfcomm_dlc *pcb = (struct rfcomm_dlc *) so->so_pcb;
3610a9108ebSHasso Tepper struct sockaddr_bt *sa;
362002c1265SMatthew Dillon int error;
3630a9108ebSHasso Tepper
3640a9108ebSHasso Tepper KKASSERT(nam != NULL);
3650a9108ebSHasso Tepper sa = (struct sockaddr_bt *)nam;
3660a9108ebSHasso Tepper
367002c1265SMatthew Dillon if (sa->bt_len != sizeof(struct sockaddr_bt)) {
368002c1265SMatthew Dillon error = EINVAL;
369002c1265SMatthew Dillon } else if (sa->bt_family != AF_BLUETOOTH) {
370002c1265SMatthew Dillon error = EAFNOSUPPORT;
371002c1265SMatthew Dillon } else {
3720a9108ebSHasso Tepper soisconnecting(so);
373002c1265SMatthew Dillon error = rfcomm_connect(pcb, sa);
374002c1265SMatthew Dillon }
375002c1265SMatthew Dillon lwkt_replymsg(&msg->connect.base.lmsg, error);
3760a9108ebSHasso Tepper }
3770a9108ebSHasso Tepper
378002c1265SMatthew Dillon static void
rfcomm_speeraddr(netmsg_t msg)379002c1265SMatthew Dillon rfcomm_speeraddr(netmsg_t msg)
3800a9108ebSHasso Tepper {
381002c1265SMatthew Dillon struct socket *so = msg->peeraddr.base.nm_so;
382002c1265SMatthew Dillon struct sockaddr **nam = msg->peeraddr.nm_nam;
3830a9108ebSHasso Tepper struct rfcomm_dlc *pcb = (struct rfcomm_dlc *) so->so_pcb;
3840a9108ebSHasso Tepper struct sockaddr_bt *sa, ssa;
385002c1265SMatthew Dillon int error;
3860a9108ebSHasso Tepper
3870a9108ebSHasso Tepper sa = &ssa;
3880a9108ebSHasso Tepper bzero(sa, sizeof *sa);
3890a9108ebSHasso Tepper sa->bt_len = sizeof(struct sockaddr_bt);
3900a9108ebSHasso Tepper sa->bt_family = AF_BLUETOOTH;
3913598cc14SSascha Wildner error = rfcomm_peeraddr(pcb, sa);
3920a9108ebSHasso Tepper *nam = dup_sockaddr((struct sockaddr *)sa);
393002c1265SMatthew Dillon
394002c1265SMatthew Dillon lwkt_replymsg(&msg->peeraddr.base.lmsg, error);
3950a9108ebSHasso Tepper }
3960a9108ebSHasso Tepper
397002c1265SMatthew Dillon static void
rfcomm_ssockaddr(netmsg_t msg)398002c1265SMatthew Dillon rfcomm_ssockaddr(netmsg_t msg)
3990a9108ebSHasso Tepper {
400002c1265SMatthew Dillon struct socket *so = msg->sockaddr.base.nm_so;
401002c1265SMatthew Dillon struct sockaddr **nam = msg->sockaddr.nm_nam;
4020a9108ebSHasso Tepper struct rfcomm_dlc *pcb = (struct rfcomm_dlc *) so->so_pcb;
4030a9108ebSHasso Tepper struct sockaddr_bt *sa, ssa;
404002c1265SMatthew Dillon int error;
4050a9108ebSHasso Tepper
4060a9108ebSHasso Tepper sa = &ssa;
4070a9108ebSHasso Tepper bzero(sa, sizeof *sa);
4080a9108ebSHasso Tepper sa->bt_len = sizeof(struct sockaddr_bt);
4090a9108ebSHasso Tepper sa->bt_family = AF_BLUETOOTH;
4103598cc14SSascha Wildner error = rfcomm_sockaddr(pcb, sa);
4110a9108ebSHasso Tepper *nam = dup_sockaddr((struct sockaddr *)sa);
412002c1265SMatthew Dillon
413002c1265SMatthew Dillon lwkt_replymsg(&msg->sockaddr.base.lmsg, error);
4140a9108ebSHasso Tepper }
4150a9108ebSHasso Tepper
416002c1265SMatthew Dillon static void
rfcomm_sshutdown(netmsg_t msg)417002c1265SMatthew Dillon rfcomm_sshutdown(netmsg_t msg)
4180a9108ebSHasso Tepper {
419002c1265SMatthew Dillon struct socket *so = msg->shutdown.base.nm_so;
420002c1265SMatthew Dillon
4210a9108ebSHasso Tepper socantsendmore(so);
422002c1265SMatthew Dillon lwkt_replymsg(&msg->shutdown.base.lmsg, 0);
4230a9108ebSHasso Tepper }
4240a9108ebSHasso Tepper
425002c1265SMatthew Dillon static void
rfcomm_ssend(netmsg_t msg)426002c1265SMatthew Dillon rfcomm_ssend(netmsg_t msg)
4270a9108ebSHasso Tepper {
428002c1265SMatthew Dillon struct socket *so = msg->send.base.nm_so;
429002c1265SMatthew Dillon struct mbuf *m = msg->send.nm_m;
430002c1265SMatthew Dillon struct mbuf *control = msg->send.nm_control;
4310a9108ebSHasso Tepper struct rfcomm_dlc *pcb = (struct rfcomm_dlc *) so->so_pcb;
4320a9108ebSHasso Tepper struct mbuf *m0;
433002c1265SMatthew Dillon int error;
4340a9108ebSHasso Tepper
4350a9108ebSHasso Tepper KKASSERT(m != NULL);
4360a9108ebSHasso Tepper
437002c1265SMatthew Dillon /* no use for that */
438002c1265SMatthew Dillon if (control) {
4390a9108ebSHasso Tepper m_freem(control);
440002c1265SMatthew Dillon control = NULL;
4410a9108ebSHasso Tepper }
4420a9108ebSHasso Tepper
443b5523eacSSascha Wildner m0 = m_copym(m, 0, M_COPYALL, M_NOWAIT);
444002c1265SMatthew Dillon if (m0) {
445002c1265SMatthew Dillon sbappendstream(&so->so_snd.sb, m);
446002c1265SMatthew Dillon error = rfcomm_send(pcb, m0);
447002c1265SMatthew Dillon } else {
448002c1265SMatthew Dillon error = ENOMEM;
449002c1265SMatthew Dillon }
450002c1265SMatthew Dillon lwkt_replymsg(&msg->send.base.lmsg, error);
451002c1265SMatthew Dillon }
452002c1265SMatthew Dillon
453002c1265SMatthew Dillon static void
rfcomm_saccept(netmsg_t msg)454002c1265SMatthew Dillon rfcomm_saccept(netmsg_t msg)
4550a9108ebSHasso Tepper {
456002c1265SMatthew Dillon struct socket *so = msg->accept.base.nm_so;
457002c1265SMatthew Dillon struct sockaddr **nam = msg->accept.nm_nam;
4580a9108ebSHasso Tepper struct rfcomm_dlc *pcb = (struct rfcomm_dlc *) so->so_pcb;
4590a9108ebSHasso Tepper struct sockaddr_bt *sa, ssa;
460002c1265SMatthew Dillon int error;
4610a9108ebSHasso Tepper
4620a9108ebSHasso Tepper sa = &ssa;
4630a9108ebSHasso Tepper bzero(sa, sizeof *sa);
4640a9108ebSHasso Tepper sa->bt_len = sizeof(struct sockaddr_bt);
4650a9108ebSHasso Tepper sa->bt_family = AF_BLUETOOTH;
4663598cc14SSascha Wildner error = rfcomm_peeraddr(pcb, sa);
4670a9108ebSHasso Tepper *nam = dup_sockaddr((struct sockaddr *)sa);
468002c1265SMatthew Dillon
469002c1265SMatthew Dillon lwkt_replymsg(&msg->accept.base.lmsg, error);
4700a9108ebSHasso Tepper }
4710a9108ebSHasso Tepper
472002c1265SMatthew Dillon static void
rfcomm_slisten(netmsg_t msg)473002c1265SMatthew Dillon rfcomm_slisten(netmsg_t msg)
4740a9108ebSHasso Tepper {
475002c1265SMatthew Dillon struct socket *so = msg->listen.base.nm_so;
4760a9108ebSHasso Tepper struct rfcomm_dlc *pcb = (struct rfcomm_dlc *)so->so_pcb;
477002c1265SMatthew Dillon int error;
478002c1265SMatthew Dillon
479002c1265SMatthew Dillon error = rfcomm_listen(pcb);
480002c1265SMatthew Dillon lwkt_replymsg(&msg->listen.base.lmsg, error);
4810a9108ebSHasso Tepper }
4820a9108ebSHasso Tepper
483002c1265SMatthew Dillon static void
rfcomm_srcvd(netmsg_t msg)484002c1265SMatthew Dillon rfcomm_srcvd(netmsg_t msg)
4850a9108ebSHasso Tepper {
486002c1265SMatthew Dillon struct socket *so = msg->rcvd.base.nm_so;
4870a9108ebSHasso Tepper struct rfcomm_dlc *pcb = (struct rfcomm_dlc *) so->so_pcb;
488002c1265SMatthew Dillon int error;
489002c1265SMatthew Dillon
490002c1265SMatthew Dillon error = rfcomm_rcvd(pcb, sbspace(&so->so_rcv));
491002c1265SMatthew Dillon lwkt_replymsg(&msg->rcvd.base.lmsg, error);
4920a9108ebSHasso Tepper }
4930a9108ebSHasso Tepper
4940a9108ebSHasso Tepper struct pr_usrreqs rfcomm_usrreqs = {
4950a9108ebSHasso Tepper .pru_abort = rfcomm_sabort,
4960a9108ebSHasso Tepper .pru_accept = rfcomm_saccept,
4970a9108ebSHasso Tepper .pru_attach = rfcomm_sattach,
4980a9108ebSHasso Tepper .pru_bind = rfcomm_sbind,
4990a9108ebSHasso Tepper .pru_connect = rfcomm_sconnect,
500002c1265SMatthew Dillon .pru_connect2 = pr_generic_notsupp,
5010a9108ebSHasso Tepper .pru_control = rfcomm_scontrol,
5020a9108ebSHasso Tepper .pru_detach = rfcomm_sdetach,
5030a9108ebSHasso Tepper .pru_disconnect = rfcomm_sdisconnect,
5040a9108ebSHasso Tepper .pru_listen = rfcomm_slisten,
5050a9108ebSHasso Tepper .pru_peeraddr = rfcomm_speeraddr,
5060a9108ebSHasso Tepper .pru_rcvd = rfcomm_srcvd,
507002c1265SMatthew Dillon .pru_rcvoob = pr_generic_notsupp,
5080a9108ebSHasso Tepper .pru_send = rfcomm_ssend,
5090a9108ebSHasso Tepper .pru_sense = pru_sense_null,
5100a9108ebSHasso Tepper .pru_shutdown = rfcomm_sshutdown,
5110a9108ebSHasso Tepper .pru_sockaddr = rfcomm_ssockaddr,
5120a9108ebSHasso Tepper .pru_sosend = sosend,
5138b5c39bbSSamuel J. Greear .pru_soreceive = soreceive
5140a9108ebSHasso Tepper };
515