Module Name: src Committed By: tls Date: Sun Aug 10 06:56:23 UTC 2014
Modified Files: src/sys/netbt [tls-earlyentropy]: bluetooth.h bt_proto.c hci.h hci_ioctl.c hci_link.c hci_socket.c hci_unit.c l2cap.h l2cap_lower.c l2cap_socket.c l2cap_upper.c rfcomm.h rfcomm_dlc.c rfcomm_session.c rfcomm_socket.c rfcomm_upper.c sco.h sco_socket.c sco_upper.c Log Message: Rebase. To generate a diff of this commit: cvs rdiff -u -r1.11 -r1.11.28.1 src/sys/netbt/bluetooth.h cvs rdiff -u -r1.12 -r1.12.36.1 src/sys/netbt/bt_proto.c cvs rdiff -u -r1.35 -r1.35.26.1 src/sys/netbt/hci.h cvs rdiff -u -r1.10 -r1.10.32.1 src/sys/netbt/hci_ioctl.c cvs rdiff -u -r1.23 -r1.23.26.1 src/sys/netbt/hci_link.c cvs rdiff -u -r1.20 -r1.20.28.1 src/sys/netbt/hci_socket.c cvs rdiff -u -r1.13 -r1.13.26.1 src/sys/netbt/hci_unit.c cvs rdiff -u -r1.10 -r1.10.28.1 src/sys/netbt/l2cap.h cvs rdiff -u -r1.9 -r1.9.54.1 src/sys/netbt/l2cap_lower.c cvs rdiff -u -r1.10 -r1.10.2.1 src/sys/netbt/l2cap_socket.c cvs rdiff -u -r1.11 -r1.11.36.1 src/sys/netbt/l2cap_upper.c cvs rdiff -u -r1.9 -r1.9.36.1 src/sys/netbt/rfcomm.h \ src/sys/netbt/sco_upper.c cvs rdiff -u -r1.7 -r1.7.26.1 src/sys/netbt/rfcomm_dlc.c cvs rdiff -u -r1.18 -r1.18.26.1 src/sys/netbt/rfcomm_session.c cvs rdiff -u -r1.11 -r1.11.2.1 src/sys/netbt/rfcomm_socket.c cvs rdiff -u -r1.13 -r1.13.36.1 src/sys/netbt/rfcomm_upper.c cvs rdiff -u -r1.3 -r1.3.54.1 src/sys/netbt/sco.h cvs rdiff -u -r1.12 -r1.12.2.1 src/sys/netbt/sco_socket.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/netbt/bluetooth.h diff -u src/sys/netbt/bluetooth.h:1.11 src/sys/netbt/bluetooth.h:1.11.28.1 --- src/sys/netbt/bluetooth.h:1.11 Wed Apr 27 00:36:48 2011 +++ src/sys/netbt/bluetooth.h Sun Aug 10 06:56:23 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: bluetooth.h,v 1.11 2011/04/27 00:36:48 rmind Exp $ */ +/* $NetBSD: bluetooth.h,v 1.11.28.1 2014/08/10 06:56:23 tls Exp $ */ /*- * Copyright (c) 2005 Iain Hibbert. @@ -103,6 +103,8 @@ struct sockaddr_bt { #ifdef _KERNEL +#include <sys/protosw.h> + #include <sys/mallocvar.h> MALLOC_DECLARE(M_BLUETOOTH); @@ -120,6 +122,13 @@ struct btproto { void (*input)(void *, struct mbuf *); }; +extern const struct pr_usrreqs hci_usrreqs; +extern const struct pr_usrreqs sco_usrreqs; +extern const struct pr_usrreqs l2cap_usrreqs; +extern const struct pr_usrreqs rfcomm_usrreqs; + +extern kmutex_t *bt_lock; + /* * Debugging stuff */ @@ -147,8 +156,6 @@ extern int bluetooth_debug; # define UNKNOWN(x) ((void)0) #endif /* BLUETOOTH_DEBUG */ -extern kmutex_t *bt_lock; - #endif /* _KERNEL */ #endif /* _NETBT_BLUETOOTH_H_ */ Index: src/sys/netbt/bt_proto.c diff -u src/sys/netbt/bt_proto.c:1.12 src/sys/netbt/bt_proto.c:1.12.36.1 --- src/sys/netbt/bt_proto.c:1.12 Sun Sep 13 18:45:11 2009 +++ src/sys/netbt/bt_proto.c Sun Aug 10 06:56:23 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: bt_proto.c,v 1.12 2009/09/13 18:45:11 pooka Exp $ */ +/* $NetBSD: bt_proto.c,v 1.12.36.1 2014/08/10 06:56:23 tls Exp $ */ /*- * Copyright (c) 2005 Iain Hibbert. @@ -31,7 +31,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: bt_proto.c,v 1.12 2009/09/13 18:45:11 pooka Exp $"); +__KERNEL_RCSID(0, "$NetBSD: bt_proto.c,v 1.12.36.1 2014/08/10 06:56:23 tls Exp $"); #include <sys/param.h> #include <sys/domain.h> @@ -62,17 +62,7 @@ PR_WRAP_CTLOUTPUT(rfcomm_ctloutput) #define l2cap_ctloutput l2cap_ctloutput_wrapper #define rfcomm_ctloutput rfcomm_ctloutput_wrapper -PR_WRAP_USRREQ(hci_usrreq) -PR_WRAP_USRREQ(sco_usrreq) -PR_WRAP_USRREQ(l2cap_usrreq) -PR_WRAP_USRREQ(rfcomm_usrreq) - -#define hci_usrreq hci_usrreq_wrapper -#define sco_usrreq sco_usrreq_wrapper -#define l2cap_usrreq l2cap_usrreq_wrapper -#define rfcomm_usrreq rfcomm_usrreq_wrapper - -const struct protosw btsw[] = { +static const struct protosw btsw[] = { { /* raw HCI commands */ .pr_type = SOCK_RAW, .pr_domain = &btdomain, @@ -80,7 +70,7 @@ const struct protosw btsw[] = { .pr_flags = (PR_ADDR | PR_ATOMIC), .pr_init = hci_init, .pr_ctloutput = hci_ctloutput, - .pr_usrreq = hci_usrreq, + .pr_usrreqs = &hci_usrreqs, }, { /* HCI SCO data (audio) */ .pr_type = SOCK_SEQPACKET, @@ -88,7 +78,7 @@ const struct protosw btsw[] = { .pr_protocol = BTPROTO_SCO, .pr_flags = (PR_CONNREQUIRED | PR_ATOMIC | PR_LISTEN), .pr_ctloutput = sco_ctloutput, - .pr_usrreq = sco_usrreq, + .pr_usrreqs = &sco_usrreqs, }, { /* L2CAP Connection Oriented */ .pr_type = SOCK_SEQPACKET, @@ -96,7 +86,7 @@ const struct protosw btsw[] = { .pr_protocol = BTPROTO_L2CAP, .pr_flags = (PR_CONNREQUIRED | PR_ATOMIC | PR_LISTEN), .pr_ctloutput = l2cap_ctloutput, - .pr_usrreq = l2cap_usrreq, + .pr_usrreqs = &l2cap_usrreqs, .pr_init = l2cap_init, }, { /* RFCOMM */ @@ -105,7 +95,7 @@ const struct protosw btsw[] = { .pr_protocol = BTPROTO_RFCOMM, .pr_flags = (PR_CONNREQUIRED | PR_LISTEN | PR_WANTRCVD), .pr_ctloutput = rfcomm_ctloutput, - .pr_usrreq = rfcomm_usrreq, + .pr_usrreqs = &rfcomm_usrreqs, .pr_init = rfcomm_init, }, }; Index: src/sys/netbt/hci.h diff -u src/sys/netbt/hci.h:1.35 src/sys/netbt/hci.h:1.35.26.1 --- src/sys/netbt/hci.h:1.35 Sat Sep 17 08:23:36 2011 +++ src/sys/netbt/hci.h Sun Aug 10 06:56:23 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: hci.h,v 1.35 2011/09/17 08:23:36 plunky Exp $ */ +/* $NetBSD: hci.h,v 1.35.26.1 2014/08/10 06:56:23 tls Exp $ */ /*- * Copyright (c) 2005 Iain Hibbert. @@ -54,7 +54,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: hci.h,v 1.35 2011/09/17 08:23:36 plunky Exp $ + * $Id: hci.h,v 1.35.26.1 2014/08/10 06:56:23 tls Exp $ * $FreeBSD: src/sys/netgraph/bluetooth/include/ng_hci.h,v 1.6 2005/01/07 01:45:43 imp Exp $ */ @@ -2536,7 +2536,7 @@ extern SIMPLEQ_HEAD(hci_unit_list, hci_u void hci_event(struct mbuf *, struct hci_unit *); /* hci_ioctl.c */ -int hci_ioctl(unsigned long, void *, struct lwp *); +int hci_ioctl_pcb(unsigned long, void *); /* hci_link.c */ struct hci_link *hci_acl_open(struct hci_unit *, bdaddr_t *); @@ -2567,13 +2567,12 @@ void hci_memo_free(struct hci_memo *); /* hci_socket.c */ void hci_drop(void *); void hci_init(void); -int hci_usrreq(struct socket *, int, struct mbuf *, struct mbuf *, struct mbuf *, struct lwp *); int hci_ctloutput(int, struct socket *, struct sockopt *); void hci_mtap(struct mbuf *, struct hci_unit *); /* hci_unit.c */ -struct hci_unit *hci_attach(const struct hci_if *, device_t, uint16_t); -void hci_detach(struct hci_unit *); +struct hci_unit *hci_attach_pcb(const struct hci_if *, device_t, uint16_t); +void hci_detach_pcb(struct hci_unit *); int hci_enable(struct hci_unit *); void hci_disable(struct hci_unit *); struct hci_unit *hci_unit_lookup(const bdaddr_t *); Index: src/sys/netbt/hci_ioctl.c diff -u src/sys/netbt/hci_ioctl.c:1.10 src/sys/netbt/hci_ioctl.c:1.10.32.1 --- src/sys/netbt/hci_ioctl.c:1.10 Mon Nov 22 19:56:51 2010 +++ src/sys/netbt/hci_ioctl.c Sun Aug 10 06:56:23 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: hci_ioctl.c,v 1.10 2010/11/22 19:56:51 plunky Exp $ */ +/* $NetBSD: hci_ioctl.c,v 1.10.32.1 2014/08/10 06:56:23 tls Exp $ */ /*- * Copyright (c) 2005 Iain Hibbert. @@ -31,7 +31,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: hci_ioctl.c,v 1.10 2010/11/22 19:56:51 plunky Exp $"); +__KERNEL_RCSID(0, "$NetBSD: hci_ioctl.c,v 1.10.32.1 2014/08/10 06:56:23 tls Exp $"); #include <sys/param.h> #include <sys/domain.h> @@ -132,7 +132,7 @@ hci_dump(void) #endif int -hci_ioctl(unsigned long cmd, void *data, struct lwp *l) +hci_ioctl_pcb(unsigned long cmd, void *data) { struct btreq *btr = data; struct hci_unit *unit; @@ -225,7 +225,7 @@ hci_ioctl(unsigned long cmd, void *data, break; case SIOCSBTFLAGS: /* set unit flags (privileged) */ - err = kauth_authorize_device(l->l_cred, + err = kauth_authorize_device(curlwp->l_cred, KAUTH_DEVICE_BLUETOOTH_SETPRIV, unit, KAUTH_ARG(cmd), btr, NULL); if (err) @@ -253,7 +253,7 @@ hci_ioctl(unsigned long cmd, void *data, break; case SIOCSBTPOLICY: /* set unit link policy (privileged) */ - err = kauth_authorize_device(l->l_cred, + err = kauth_authorize_device(curlwp->l_cred, KAUTH_DEVICE_BLUETOOTH_SETPRIV, unit, KAUTH_ARG(cmd), btr, NULL); if (err) @@ -265,7 +265,7 @@ hci_ioctl(unsigned long cmd, void *data, break; case SIOCSBTPTYPE: /* set unit packet types (privileged) */ - err = kauth_authorize_device(l->l_cred, + err = kauth_authorize_device(curlwp->l_cred, KAUTH_DEVICE_BLUETOOTH_SETPRIV, unit, KAUTH_ARG(cmd), btr, NULL); if (err) @@ -281,7 +281,7 @@ hci_ioctl(unsigned long cmd, void *data, break; case SIOCZBTSTATS: /* get & reset unit statistics */ - err = kauth_authorize_device(l->l_cred, + err = kauth_authorize_device(curlwp->l_cred, KAUTH_DEVICE_BLUETOOTH_SETPRIV, unit, KAUTH_ARG(cmd), btr, NULL); if (err) @@ -297,7 +297,7 @@ hci_ioctl(unsigned long cmd, void *data, * sent to USB bluetooth controllers that are not an * integer number of frame sizes, the USB bus locks up. */ - err = kauth_authorize_device(l->l_cred, + err = kauth_authorize_device(curlwp->l_cred, KAUTH_DEVICE_BLUETOOTH_SETPRIV, unit, KAUTH_ARG(cmd), btr, NULL); if (err) Index: src/sys/netbt/hci_link.c diff -u src/sys/netbt/hci_link.c:1.23 src/sys/netbt/hci_link.c:1.23.26.1 --- src/sys/netbt/hci_link.c:1.23 Wed Jul 27 10:25:09 2011 +++ src/sys/netbt/hci_link.c Sun Aug 10 06:56:23 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: hci_link.c,v 1.23 2011/07/27 10:25:09 plunky Exp $ */ +/* $NetBSD: hci_link.c,v 1.23.26.1 2014/08/10 06:56:23 tls Exp $ */ /*- * Copyright (c) 2005 Iain Hibbert. @@ -31,7 +31,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: hci_link.c,v 1.23 2011/07/27 10:25:09 plunky Exp $"); +__KERNEL_RCSID(0, "$NetBSD: hci_link.c,v 1.23.26.1 2014/08/10 06:56:23 tls Exp $"); #include <sys/param.h> #include <sys/kernel.h> @@ -799,7 +799,7 @@ hci_sco_newconn(struct hci_unit *unit, b sco = hci_link_alloc(unit, bdaddr, HCI_LINK_SCO); if (sco == NULL) { - sco_detach(&new); + sco_detach_pcb(&new); return NULL; } Index: src/sys/netbt/hci_socket.c diff -u src/sys/netbt/hci_socket.c:1.20 src/sys/netbt/hci_socket.c:1.20.28.1 --- src/sys/netbt/hci_socket.c:1.20 Sun Jan 30 17:23:23 2011 +++ src/sys/netbt/hci_socket.c Sun Aug 10 06:56:23 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: hci_socket.c,v 1.20 2011/01/30 17:23:23 plunky Exp $ */ +/* $NetBSD: hci_socket.c,v 1.20.28.1 2014/08/10 06:56:23 tls Exp $ */ /*- * Copyright (c) 2005 Iain Hibbert. @@ -31,7 +31,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: hci_socket.c,v 1.20 2011/01/30 17:23:23 plunky Exp $"); +__KERNEL_RCSID(0, "$NetBSD: hci_socket.c,v 1.20.28.1 2014/08/10 06:56:23 tls Exp $"); /* load symbolic names */ #ifdef BLUETOOTH_DEBUG @@ -43,6 +43,7 @@ __KERNEL_RCSID(0, "$NetBSD: hci_socket.c #include <sys/domain.h> #include <sys/kauth.h> #include <sys/kernel.h> +#include <sys/kmem.h> #include <sys/mbuf.h> #include <sys/proc.h> #include <sys/protosw.h> @@ -352,7 +353,7 @@ hci_cmdwait_flush(struct socket *so) * This came from userland, so check it out. */ static int -hci_send(struct hci_pcb *pcb, struct mbuf *m, bdaddr_t *addr) +hci_send_pcb(struct hci_pcb *pcb, struct mbuf *m, bdaddr_t *addr) { struct hci_unit *unit; struct mbuf *m0; @@ -425,206 +426,352 @@ bad: return err; } -/* - * User Request. - * up is socket - * m is either - * optional mbuf chain containing message - * ioctl command (PRU_CONTROL) - * nam is either - * optional mbuf chain containing an address - * ioctl data (PRU_CONTROL) - * optionally, protocol number (PRU_ATTACH) - * ctl is optional mbuf chain containing socket options - * l is pointer to process requesting action (if any) - * - * we are responsible for disposing of m and ctl if - * they are mbuf chains - */ -int -hci_usrreq(struct socket *up, int req, struct mbuf *m, - struct mbuf *nam, struct mbuf *ctl, struct lwp *l) +static int +hci_attach(struct socket *so, int proto) +{ + struct hci_pcb *pcb; + int error; + + KASSERT(so->so_pcb == NULL); + + if (so->so_lock == NULL) { + mutex_obj_hold(bt_lock); + so->so_lock = bt_lock; + solock(so); + } + KASSERT(solocked(so)); + + error = soreserve(so, hci_sendspace, hci_recvspace); + if (error) { + return error; + } + + pcb = kmem_zalloc(sizeof(struct hci_pcb), KM_SLEEP); + pcb->hp_cred = kauth_cred_dup(curlwp->l_cred); + pcb->hp_socket = so; + + /* + * Set default user filter. By default, socket only passes + * Command_Complete and Command_Status Events. + */ + hci_filter_set(HCI_EVENT_COMMAND_COMPL, &pcb->hp_efilter); + hci_filter_set(HCI_EVENT_COMMAND_STATUS, &pcb->hp_efilter); + hci_filter_set(HCI_EVENT_PKT, &pcb->hp_pfilter); + + LIST_INSERT_HEAD(&hci_pcb, pcb, hp_next); + so->so_pcb = pcb; + + return 0; +} + +static void +hci_detach(struct socket *so) +{ + struct hci_pcb *pcb; + + pcb = (struct hci_pcb *)so->so_pcb; + KASSERT(pcb != NULL); + + if (so->so_snd.sb_mb != NULL) + hci_cmdwait_flush(so); + + if (pcb->hp_cred != NULL) + kauth_cred_free(pcb->hp_cred); + + so->so_pcb = NULL; + LIST_REMOVE(pcb, hp_next); + kmem_free(pcb, sizeof(*pcb)); +} + +static int +hci_accept(struct socket *so, struct mbuf *nam) +{ + KASSERT(solocked(so)); + + return EOPNOTSUPP; +} + +static int +hci_bind(struct socket *so, struct mbuf *nam, struct lwp *l) { - struct hci_pcb *pcb = (struct hci_pcb *)up->so_pcb; + struct hci_pcb *pcb = so->so_pcb; struct sockaddr_bt *sa; - int err = 0; - DPRINTFN(2, "%s\n", prurequests[req]); + KASSERT(solocked(so)); + KASSERT(pcb != NULL); + KASSERT(nam != NULL); - switch(req) { - case PRU_CONTROL: - mutex_enter(bt_lock); - err = hci_ioctl((unsigned long)m, (void *)nam, l); - mutex_exit(bt_lock); - return err; - - case PRU_PURGEIF: - return EOPNOTSUPP; - - case PRU_ATTACH: - if (up->so_lock == NULL) { - mutex_obj_hold(bt_lock); - up->so_lock = bt_lock; - solock(up); - } - KASSERT(solocked(up)); - if (pcb) - return EINVAL; - err = soreserve(up, hci_sendspace, hci_recvspace); - if (err) - return err; - - pcb = malloc(sizeof(struct hci_pcb), M_PCB, M_NOWAIT | M_ZERO); - if (pcb == NULL) - return ENOMEM; + sa = mtod(nam, struct sockaddr_bt *); + if (sa->bt_len != sizeof(struct sockaddr_bt)) + return EINVAL; - up->so_pcb = pcb; - pcb->hp_socket = up; + if (sa->bt_family != AF_BLUETOOTH) + return EAFNOSUPPORT; - if (l != NULL) - pcb->hp_cred = kauth_cred_dup(l->l_cred); + bdaddr_copy(&pcb->hp_laddr, &sa->bt_bdaddr); - /* - * Set default user filter. By default, socket only passes - * Command_Complete and Command_Status Events. - */ - hci_filter_set(HCI_EVENT_COMMAND_COMPL, &pcb->hp_efilter); - hci_filter_set(HCI_EVENT_COMMAND_STATUS, &pcb->hp_efilter); - hci_filter_set(HCI_EVENT_PKT, &pcb->hp_pfilter); + if (bdaddr_any(&sa->bt_bdaddr)) + pcb->hp_flags |= HCI_PROMISCUOUS; + else + pcb->hp_flags &= ~HCI_PROMISCUOUS; - LIST_INSERT_HEAD(&hci_pcb, pcb, hp_next); + return 0; +} - return 0; - } +static int +hci_listen(struct socket *so, struct lwp *l) +{ + KASSERT(solocked(so)); - /* anything after here *requires* a pcb */ - if (pcb == NULL) { - err = EINVAL; - goto release; - } + return EOPNOTSUPP; +} - switch(req) { - case PRU_DISCONNECT: - bdaddr_copy(&pcb->hp_raddr, BDADDR_ANY); +static int +hci_connect(struct socket *so, struct mbuf *nam, struct lwp *l) +{ + struct hci_pcb *pcb = so->so_pcb; + struct sockaddr_bt *sa; - /* XXX we cannot call soisdisconnected() here, as it sets - * SS_CANTRCVMORE and SS_CANTSENDMORE. The problem being, - * that soisconnected() does not clear these and if you - * try to reconnect this socket (which is permitted) you - * get a broken pipe when you try to write any data. - */ - up->so_state &= ~SS_ISCONNECTED; - break; + KASSERT(solocked(so)); + KASSERT(pcb != NULL); + KASSERT(nam != NULL); - case PRU_ABORT: - soisdisconnected(up); - /* fall through to */ - case PRU_DETACH: - if (up->so_snd.sb_mb != NULL) - hci_cmdwait_flush(up); - - if (pcb->hp_cred != NULL) - kauth_cred_free(pcb->hp_cred); - - up->so_pcb = NULL; - LIST_REMOVE(pcb, hp_next); - free(pcb, M_PCB); - return 0; + sa = mtod(nam, struct sockaddr_bt *); + if (sa->bt_len != sizeof(struct sockaddr_bt)) + return EINVAL; - case PRU_BIND: - KASSERT(nam != NULL); - sa = mtod(nam, struct sockaddr_bt *); + if (sa->bt_family != AF_BLUETOOTH) + return EAFNOSUPPORT; - if (sa->bt_len != sizeof(struct sockaddr_bt)) - return EINVAL; + if (hci_unit_lookup(&sa->bt_bdaddr) == NULL) + return EADDRNOTAVAIL; - if (sa->bt_family != AF_BLUETOOTH) - return EAFNOSUPPORT; + bdaddr_copy(&pcb->hp_raddr, &sa->bt_bdaddr); + soisconnected(so); + return 0; +} - bdaddr_copy(&pcb->hp_laddr, &sa->bt_bdaddr); +static int +hci_connect2(struct socket *so, struct socket *so2) +{ + KASSERT(solocked(so)); - if (bdaddr_any(&sa->bt_bdaddr)) - pcb->hp_flags |= HCI_PROMISCUOUS; - else - pcb->hp_flags &= ~HCI_PROMISCUOUS; + return EOPNOTSUPP; +} - return 0; +static int +hci_disconnect(struct socket *so) +{ + struct hci_pcb *pcb = so->so_pcb; - case PRU_CONNECT: - KASSERT(nam != NULL); - sa = mtod(nam, struct sockaddr_bt *); + KASSERT(solocked(so)); + KASSERT(pcb != NULL); - if (sa->bt_len != sizeof(struct sockaddr_bt)) - return EINVAL; + bdaddr_copy(&pcb->hp_raddr, BDADDR_ANY); - if (sa->bt_family != AF_BLUETOOTH) - return EAFNOSUPPORT; + /* XXX we cannot call soisdisconnected() here, as it sets + * SS_CANTRCVMORE and SS_CANTSENDMORE. The problem being, + * that soisconnected() does not clear these and if you + * try to reconnect this socket (which is permitted) you + * get a broken pipe when you try to write any data. + */ + so->so_state &= ~SS_ISCONNECTED; + return 0; +} - if (hci_unit_lookup(&sa->bt_bdaddr) == NULL) - return EADDRNOTAVAIL; +static int +hci_shutdown(struct socket *so) +{ + KASSERT(solocked(so)); - bdaddr_copy(&pcb->hp_raddr, &sa->bt_bdaddr); - soisconnected(up); - return 0; + socantsendmore(so); + return 0; +} - case PRU_PEERADDR: - KASSERT(nam != NULL); - sa = mtod(nam, struct sockaddr_bt *); +static int +hci_abort(struct socket *so) +{ + KASSERT(solocked(so)); - memset(sa, 0, sizeof(struct sockaddr_bt)); - nam->m_len = - sa->bt_len = sizeof(struct sockaddr_bt); - sa->bt_family = AF_BLUETOOTH; - bdaddr_copy(&sa->bt_bdaddr, &pcb->hp_raddr); - return 0; + soisdisconnected(so); + hci_detach(so); + return 0; +} - case PRU_SOCKADDR: - KASSERT(nam != NULL); - sa = mtod(nam, struct sockaddr_bt *); +static int +hci_ioctl(struct socket *so, u_long cmd, void *nam, struct ifnet *ifp) +{ + int err; + mutex_enter(bt_lock); + err = hci_ioctl_pcb(cmd, nam); + mutex_exit(bt_lock); + return err; +} - memset(sa, 0, sizeof(struct sockaddr_bt)); - nam->m_len = - sa->bt_len = sizeof(struct sockaddr_bt); - sa->bt_family = AF_BLUETOOTH; - bdaddr_copy(&sa->bt_bdaddr, &pcb->hp_laddr); - return 0; +static int +hci_stat(struct socket *so, struct stat *ub) +{ + KASSERT(solocked(so)); - case PRU_SHUTDOWN: - socantsendmore(up); - break; + return 0; +} - case PRU_SEND: - sa = NULL; - if (nam) { - sa = mtod(nam, struct sockaddr_bt *); - - if (sa->bt_len != sizeof(struct sockaddr_bt)) { - err = EINVAL; - goto release; - } +static int +hci_peeraddr(struct socket *so, struct mbuf *nam) +{ + struct hci_pcb *pcb = (struct hci_pcb *)so->so_pcb; + struct sockaddr_bt *sa; - if (sa->bt_family != AF_BLUETOOTH) { - err = EAFNOSUPPORT; - goto release; - } + KASSERT(solocked(so)); + KASSERT(pcb != NULL); + KASSERT(nam != NULL); + + sa = mtod(nam, struct sockaddr_bt *); + memset(sa, 0, sizeof(struct sockaddr_bt)); + nam->m_len = + sa->bt_len = sizeof(struct sockaddr_bt); + sa->bt_family = AF_BLUETOOTH; + bdaddr_copy(&sa->bt_bdaddr, &pcb->hp_raddr); + return 0; +} + +static int +hci_sockaddr(struct socket *so, struct mbuf *nam) +{ + struct hci_pcb *pcb = (struct hci_pcb *)so->so_pcb; + struct sockaddr_bt *sa; + + KASSERT(solocked(so)); + KASSERT(pcb != NULL); + KASSERT(nam != NULL); + + sa = mtod(nam, struct sockaddr_bt *); + memset(sa, 0, sizeof(struct sockaddr_bt)); + nam->m_len = + sa->bt_len = sizeof(struct sockaddr_bt); + sa->bt_family = AF_BLUETOOTH; + bdaddr_copy(&sa->bt_bdaddr, &pcb->hp_laddr); + return 0; +} + +static int +hci_rcvd(struct socket *so, int flags, struct lwp *l) +{ + KASSERT(solocked(so)); + + return EOPNOTSUPP; +} + +static int +hci_recvoob(struct socket *so, struct mbuf *m, int flags) +{ + KASSERT(solocked(so)); + + return EOPNOTSUPP; +} + +static int +hci_send(struct socket *so, struct mbuf *m, struct mbuf *nam, + struct mbuf *control, struct lwp *l) +{ + struct hci_pcb *pcb = so->so_pcb; + struct sockaddr_bt * sa = NULL; + int err = 0; + + KASSERT(solocked(so)); + KASSERT(pcb != NULL); + + if (control) /* have no use for this */ + m_freem(control); + + if (nam) { + sa = mtod(nam, struct sockaddr_bt *); + + if (sa->bt_len != sizeof(struct sockaddr_bt)) { + err = EINVAL; + goto release; + } + + if (sa->bt_family != AF_BLUETOOTH) { + err = EAFNOSUPPORT; + goto release; } + } + + return hci_send_pcb(pcb, m, (sa ? &sa->bt_bdaddr : &pcb->hp_raddr)); + +release: + if (m) + m_freem(m); + + return err; +} + +static int +hci_sendoob(struct socket *so, struct mbuf *m, struct mbuf *control) +{ + KASSERT(solocked(so)); + + if (m) + m_freem(m); + if (control) + m_freem(control); + + return EOPNOTSUPP; +} + +static int +hci_purgeif(struct socket *so, struct ifnet *ifp) +{ + + return EOPNOTSUPP; +} - if (ctl) /* have no use for this */ - m_freem(ctl); +/* + * User Request. + * up is socket + * m is optional mbuf chain containing message + * nam is optional mbuf chain containing an address + * ctl is optional mbuf chain containing socket options + * l is pointer to process requesting action (if any) + * + * we are responsible for disposing of m and ctl + */ +static int +hci_usrreq(struct socket *up, int req, struct mbuf *m, + struct mbuf *nam, struct mbuf *ctl, struct lwp *l) +{ + struct hci_pcb *pcb = up->so_pcb; + int err = 0; - return hci_send(pcb, m, (sa ? &sa->bt_bdaddr : &pcb->hp_raddr)); + DPRINTFN(2, "%s\n", prurequests[req]); + KASSERT(req != PRU_ATTACH); + KASSERT(req != PRU_DETACH); + KASSERT(req != PRU_ACCEPT); + KASSERT(req != PRU_BIND); + KASSERT(req != PRU_LISTEN); + KASSERT(req != PRU_CONNECT); + KASSERT(req != PRU_CONNECT2); + KASSERT(req != PRU_DISCONNECT); + KASSERT(req != PRU_SHUTDOWN); + KASSERT(req != PRU_ABORT); + KASSERT(req != PRU_CONTROL); + KASSERT(req != PRU_SENSE); + KASSERT(req != PRU_PEERADDR); + KASSERT(req != PRU_SOCKADDR); + KASSERT(req != PRU_RCVD); + KASSERT(req != PRU_RCVOOB); + KASSERT(req != PRU_SEND); + KASSERT(req != PRU_SENDOOB); + KASSERT(req != PRU_PURGEIF); - case PRU_SENSE: - return 0; /* (no sense - Doh!) */ + /* anything after here *requires* a pcb */ + if (pcb == NULL) { + err = EINVAL; + goto release; + } - case PRU_RCVD: - case PRU_RCVOOB: - return EOPNOTSUPP; /* (no release) */ - - case PRU_ACCEPT: - case PRU_CONNECT2: - case PRU_LISTEN: - case PRU_SENDOOB: + switch(req) { case PRU_FASTTIMO: case PRU_SLOWTIMO: case PRU_PROTORCV: @@ -849,3 +996,49 @@ hci_mtap(struct mbuf *m, struct hci_unit } } } + +PR_WRAP_USRREQS(hci) + +#define hci_attach hci_attach_wrapper +#define hci_detach hci_detach_wrapper +#define hci_accept hci_accept_wrapper +#define hci_bind hci_bind_wrapper +#define hci_listen hci_listen_wrapper +#define hci_connect hci_connect_wrapper +#define hci_connect2 hci_connect2_wrapper +#define hci_disconnect hci_disconnect_wrapper +#define hci_shutdown hci_shutdown_wrapper +#define hci_abort hci_abort_wrapper +#define hci_ioctl hci_ioctl_wrapper +#define hci_stat hci_stat_wrapper +#define hci_peeraddr hci_peeraddr_wrapper +#define hci_sockaddr hci_sockaddr_wrapper +#define hci_rcvd hci_rcvd_wrapper +#define hci_recvoob hci_recvoob_wrapper +#define hci_send hci_send_wrapper +#define hci_sendoob hci_sendoob_wrapper +#define hci_purgeif hci_purgeif_wrapper +#define hci_usrreq hci_usrreq_wrapper + +const struct pr_usrreqs hci_usrreqs = { + .pr_attach = hci_attach, + .pr_detach = hci_detach, + .pr_accept = hci_accept, + .pr_bind = hci_bind, + .pr_listen = hci_listen, + .pr_connect = hci_connect, + .pr_connect2 = hci_connect2, + .pr_disconnect = hci_disconnect, + .pr_shutdown = hci_shutdown, + .pr_abort = hci_abort, + .pr_ioctl = hci_ioctl, + .pr_stat = hci_stat, + .pr_peeraddr = hci_peeraddr, + .pr_sockaddr = hci_sockaddr, + .pr_rcvd = hci_rcvd, + .pr_recvoob = hci_recvoob, + .pr_send = hci_send, + .pr_sendoob = hci_sendoob, + .pr_purgeif = hci_purgeif, + .pr_generic = hci_usrreq, +}; Index: src/sys/netbt/hci_unit.c diff -u src/sys/netbt/hci_unit.c:1.13 src/sys/netbt/hci_unit.c:1.13.26.1 --- src/sys/netbt/hci_unit.c:1.13 Sat Sep 17 08:23:37 2011 +++ src/sys/netbt/hci_unit.c Sun Aug 10 06:56:23 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: hci_unit.c,v 1.13 2011/09/17 08:23:37 plunky Exp $ */ +/* $NetBSD: hci_unit.c,v 1.13.26.1 2014/08/10 06:56:23 tls Exp $ */ /*- * Copyright (c) 2005 Iain Hibbert. @@ -31,7 +31,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: hci_unit.c,v 1.13 2011/09/17 08:23:37 plunky Exp $"); +__KERNEL_RCSID(0, "$NetBSD: hci_unit.c,v 1.13.26.1 2014/08/10 06:56:23 tls Exp $"); #include <sys/param.h> #include <sys/conf.h> @@ -81,7 +81,7 @@ static const uint8_t hci_cmds_v10[HCI_CO static void hci_intr (void *); struct hci_unit * -hci_attach(const struct hci_if *hci_if, device_t dev, uint16_t flags) +hci_attach_pcb(const struct hci_if *hci_if, device_t dev, uint16_t flags) { struct hci_unit *unit; @@ -120,7 +120,7 @@ hci_attach(const struct hci_if *hci_if, } void -hci_detach(struct hci_unit *unit) +hci_detach_pcb(struct hci_unit *unit) { mutex_enter(bt_lock); Index: src/sys/netbt/l2cap.h diff -u src/sys/netbt/l2cap.h:1.10 src/sys/netbt/l2cap.h:1.10.28.1 --- src/sys/netbt/l2cap.h:1.10 Sun Feb 6 18:50:59 2011 +++ src/sys/netbt/l2cap.h Sun Aug 10 06:56:23 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: l2cap.h,v 1.10 2011/02/06 18:50:59 plunky Exp $ */ +/* $NetBSD: l2cap.h,v 1.10.28.1 2014/08/10 06:56:23 tls Exp $ */ /*- * Copyright (c) 2005 Iain Hibbert. @@ -54,7 +54,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: l2cap.h,v 1.10 2011/02/06 18:50:59 plunky Exp $ + * $Id: l2cap.h,v 1.10.28.1 2014/08/10 06:56:23 tls Exp $ * $FreeBSD: src/sys/netgraph/bluetooth/include/l2cap.h,v 1.4 2005/08/31 18:13:23 emax Exp $ */ @@ -458,19 +458,18 @@ int l2cap_send_disconnect_req(struct l2c int l2cap_send_connect_rsp(struct hci_link *, uint8_t, uint16_t, uint16_t, uint16_t); /* l2cap_socket.c */ -int l2cap_usrreq(struct socket *, int, struct mbuf *, struct mbuf *, struct mbuf *, struct lwp *); int l2cap_ctloutput(int, struct socket *, struct sockopt *); /* l2cap_upper.c */ -int l2cap_attach(struct l2cap_channel **, const struct btproto *, void *); -int l2cap_bind(struct l2cap_channel *, struct sockaddr_bt *); -int l2cap_sockaddr(struct l2cap_channel *, struct sockaddr_bt *); -int l2cap_connect(struct l2cap_channel *, struct sockaddr_bt *); -int l2cap_peeraddr(struct l2cap_channel *, struct sockaddr_bt *); -int l2cap_disconnect(struct l2cap_channel *, int); -int l2cap_detach(struct l2cap_channel **); -int l2cap_listen(struct l2cap_channel *); -int l2cap_send(struct l2cap_channel *, struct mbuf *); +int l2cap_attach_pcb(struct l2cap_channel **, const struct btproto *, void *); +int l2cap_bind_pcb(struct l2cap_channel *, struct sockaddr_bt *); +int l2cap_sockaddr_pcb(struct l2cap_channel *, struct sockaddr_bt *); +int l2cap_connect_pcb(struct l2cap_channel *, struct sockaddr_bt *); +int l2cap_peeraddr_pcb(struct l2cap_channel *, struct sockaddr_bt *); +int l2cap_disconnect_pcb(struct l2cap_channel *, int); +void l2cap_detach_pcb(struct l2cap_channel **); +int l2cap_listen_pcb(struct l2cap_channel *); +int l2cap_send_pcb(struct l2cap_channel *, struct mbuf *); int l2cap_setopt(struct l2cap_channel *, const struct sockopt *); int l2cap_getopt(struct l2cap_channel *, struct sockopt *); Index: src/sys/netbt/l2cap_lower.c diff -u src/sys/netbt/l2cap_lower.c:1.9 src/sys/netbt/l2cap_lower.c:1.9.54.1 --- src/sys/netbt/l2cap_lower.c:1.9 Tue Aug 5 13:08:31 2008 +++ src/sys/netbt/l2cap_lower.c Sun Aug 10 06:56:23 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: l2cap_lower.c,v 1.9 2008/08/05 13:08:31 plunky Exp $ */ +/* $NetBSD: l2cap_lower.c,v 1.9.54.1 2014/08/10 06:56:23 tls Exp $ */ /*- * Copyright (c) 2005 Iain Hibbert. @@ -31,7 +31,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: l2cap_lower.c,v 1.9 2008/08/05 13:08:31 plunky Exp $"); +__KERNEL_RCSID(0, "$NetBSD: l2cap_lower.c,v 1.9.54.1 2014/08/10 06:56:23 tls Exp $"); #include <sys/param.h> #include <sys/kernel.h> @@ -150,7 +150,7 @@ failed: } /* - * Start another L2CAP packet on its way. This is called from l2cap_send + * Start another L2CAP packet on its way. This is called from l2cap_send_pcb * (when no PDU is pending) and hci_acl_start (when PDU has been placed on * device queue). Thus we can have more than one PDU waiting at the device * if space is available but no single channel will hog the link. Index: src/sys/netbt/l2cap_socket.c diff -u src/sys/netbt/l2cap_socket.c:1.10 src/sys/netbt/l2cap_socket.c:1.10.2.1 --- src/sys/netbt/l2cap_socket.c:1.10 Thu Aug 29 17:49:21 2013 +++ src/sys/netbt/l2cap_socket.c Sun Aug 10 06:56:23 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: l2cap_socket.c,v 1.10 2013/08/29 17:49:21 rmind Exp $ */ +/* $NetBSD: l2cap_socket.c,v 1.10.2.1 2014/08/10 06:56:23 tls Exp $ */ /*- * Copyright (c) 2005 Iain Hibbert. @@ -31,7 +31,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: l2cap_socket.c,v 1.10 2013/08/29 17:49:21 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: l2cap_socket.c,v 1.10.2.1 2014/08/10 06:56:23 tls Exp $"); /* load symbolic names */ #ifdef BLUETOOTH_DEBUG @@ -82,63 +82,326 @@ static const struct btproto l2cap_proto int l2cap_sendspace = 4096; int l2cap_recvspace = 4096; +static int +l2cap_attach(struct socket *so, int proto) +{ + int error; + + KASSERT(so->so_pcb == NULL); + + if (so->so_lock == NULL) { + mutex_obj_hold(bt_lock); + so->so_lock = bt_lock; + solock(so); + } + KASSERT(solocked(so)); + + /* + * For L2CAP socket PCB we just use an l2cap_channel structure + * since we have nothing to add.. + */ + error = soreserve(so, l2cap_sendspace, l2cap_recvspace); + if (error) + return error; + + return l2cap_attach_pcb((struct l2cap_channel **)&so->so_pcb, + &l2cap_proto, so); +} + +static void +l2cap_detach(struct socket *so) +{ + KASSERT(so->so_pcb != NULL); + l2cap_detach_pcb((struct l2cap_channel **)&so->so_pcb); + KASSERT(so->so_pcb == NULL); +} + +static int +l2cap_accept(struct socket *so, struct mbuf *nam) +{ + struct l2cap_channel *pcb = so->so_pcb; + struct sockaddr_bt *sa; + + KASSERT(solocked(so)); + KASSERT(nam != NULL); + + if (pcb == NULL) + return EINVAL; + + sa = mtod(nam, struct sockaddr_bt *); + nam->m_len = sizeof(struct sockaddr_bt); + return l2cap_peeraddr_pcb(pcb, sa); +} + +static int +l2cap_bind(struct socket *so, struct mbuf *nam, struct lwp *l) +{ + struct l2cap_channel *pcb = so->so_pcb; + struct sockaddr_bt *sa; + + KASSERT(solocked(so)); + KASSERT(nam != NULL); + + if (pcb == NULL) + return EINVAL; + + sa = mtod(nam, struct sockaddr_bt *); + if (sa->bt_len != sizeof(struct sockaddr_bt)) + return EINVAL; + + if (sa->bt_family != AF_BLUETOOTH) + return EAFNOSUPPORT; + + return l2cap_bind_pcb(pcb, sa); +} + +static int +l2cap_listen(struct socket *so, struct lwp *l) +{ + struct l2cap_channel *pcb = so->so_pcb; + + KASSERT(solocked(so)); + + if (pcb == NULL) + return EINVAL; + + return l2cap_listen_pcb(pcb); +} + +static int +l2cap_connect(struct socket *so, struct mbuf *nam, struct lwp *l) +{ + struct l2cap_channel *pcb = so->so_pcb; + struct sockaddr_bt *sa; + + KASSERT(solocked(so)); + KASSERT(nam != NULL); + + if (pcb == NULL) + return EINVAL; + + sa = mtod(nam, struct sockaddr_bt *); + if (sa->bt_len != sizeof(struct sockaddr_bt)) + return EINVAL; + + if (sa->bt_family != AF_BLUETOOTH) + return EAFNOSUPPORT; + + soisconnecting(so); + return l2cap_connect_pcb(pcb, sa); +} + +static int +l2cap_connect2(struct socket *so, struct socket *so2) +{ + KASSERT(solocked(so)); + + if (so->so_pcb == NULL) + return EINVAL; + + return EOPNOTSUPP; +} + +static int +l2cap_disconnect(struct socket *so) +{ + struct l2cap_channel *pcb = so->so_pcb; + + KASSERT(solocked(so)); + + if (pcb == NULL) + return EINVAL; + + soisdisconnecting(so); + return l2cap_disconnect_pcb(pcb, so->so_linger); +} + +static int +l2cap_shutdown(struct socket *so) +{ + KASSERT(solocked(so)); + + socantsendmore(so); + return 0; +} + +static int +l2cap_abort(struct socket *so) +{ + struct l2cap_channel *pcb = so->so_pcb; + + KASSERT(solocked(so)); + + if (pcb == NULL) + return EINVAL; + + l2cap_disconnect_pcb(pcb, 0); + soisdisconnected(so); + l2cap_detach(so); + return 0; +} + +static int +l2cap_ioctl(struct socket *so, u_long cmd, void *nam, struct ifnet *ifp) +{ + return EPASSTHROUGH; +} + +static int +l2cap_stat(struct socket *so, struct stat *ub) +{ + KASSERT(solocked(so)); + + return 0; +} + +static int +l2cap_peeraddr(struct socket *so, struct mbuf *nam) +{ + struct l2cap_channel *pcb = so->so_pcb; + struct sockaddr_bt *sa; + + KASSERT(solocked(so)); + KASSERT(pcb != NULL); + KASSERT(nam != NULL); + + sa = mtod(nam, struct sockaddr_bt *); + nam->m_len = sizeof(struct sockaddr_bt); + return l2cap_peeraddr_pcb(pcb, sa); +} + +static int +l2cap_sockaddr(struct socket *so, struct mbuf *nam) +{ + struct l2cap_channel *pcb = so->so_pcb; + struct sockaddr_bt *sa; + + KASSERT(solocked(so)); + KASSERT(pcb != NULL); + KASSERT(nam != NULL); + + sa = mtod(nam, struct sockaddr_bt *); + nam->m_len = sizeof(struct sockaddr_bt); + return l2cap_sockaddr_pcb(pcb, sa); +} + +static int +l2cap_rcvd(struct socket *so, int flags, struct lwp *l) +{ + KASSERT(solocked(so)); + + return EOPNOTSUPP; +} + +static int +l2cap_recvoob(struct socket *so, struct mbuf *m, int flags) +{ + KASSERT(solocked(so)); + + return EOPNOTSUPP; +} + +static int +l2cap_send(struct socket *so, struct mbuf *m, struct mbuf *nam, + struct mbuf *control, struct lwp *l) +{ + struct l2cap_channel *pcb = so->so_pcb; + struct mbuf *m0; + int error = 0; + + KASSERT(solocked(so)); + KASSERT(m != NULL); + + if (control) + m_freem(control); + + if (pcb == NULL) { + error = EINVAL; + goto release; + } + + if (m->m_pkthdr.len == 0) + goto release; + + if (m->m_pkthdr.len > pcb->lc_omtu) { + error = EMSGSIZE; + goto release; + } + + m0 = m_copypacket(m, M_DONTWAIT); + if (m0 == NULL) { + error = ENOMEM; + goto release; + } + + sbappendrecord(&so->so_snd, m); + return l2cap_send_pcb(pcb, m0); + +release: + if (m) + m_freem(m); + + return error; +} + +static int +l2cap_sendoob(struct socket *so, struct mbuf *m, struct mbuf *control) +{ + KASSERT(solocked(so)); + + if (m) + m_freem(m); + if (control) + m_freem(control); + + return EOPNOTSUPP; +} + +static int +l2cap_purgeif(struct socket *so, struct ifnet *ifp) +{ + + return EOPNOTSUPP; +} + /* * User Request. * up is socket - * m is either - * optional mbuf chain containing message - * ioctl command (PRU_CONTROL) - * nam is either - * optional mbuf chain containing an address - * ioctl data (PRU_CONTROL) - * optionally protocol number (PRU_ATTACH) - * message flags (PRU_RCVD) + * m is optional mbuf chain containing message * ctl is either * optional mbuf chain containing socket options - * optional interface pointer (PRU_CONTROL, PRU_PURGEIF) * l is pointer to process requesting action (if any) * * we are responsible for disposing of m and ctl if * they are mbuf chains */ -int +static int l2cap_usrreq(struct socket *up, int req, struct mbuf *m, struct mbuf *nam, struct mbuf *ctl, struct lwp *l) { struct l2cap_channel *pcb = up->so_pcb; - struct sockaddr_bt *sa; - struct mbuf *m0; int err = 0; DPRINTFN(2, "%s\n", prurequests[req]); - - switch (req) { - case PRU_CONTROL: - return EPASSTHROUGH; - - case PRU_PURGEIF: - return EOPNOTSUPP; - - case PRU_ATTACH: - if (up->so_lock == NULL) { - mutex_obj_hold(bt_lock); - up->so_lock = bt_lock; - solock(up); - } - KASSERT(solocked(up)); - if (pcb != NULL) - return EINVAL; - /* - * For L2CAP socket PCB we just use an l2cap_channel structure - * since we have nothing to add.. - */ - err = soreserve(up, l2cap_sendspace, l2cap_recvspace); - if (err) - return err; - - return l2cap_attach((struct l2cap_channel **)&up->so_pcb, - &l2cap_proto, up); - } + KASSERT(req != PRU_ATTACH); + KASSERT(req != PRU_DETACH); + KASSERT(req != PRU_ACCEPT); + KASSERT(req != PRU_BIND); + KASSERT(req != PRU_LISTEN); + KASSERT(req != PRU_CONNECT); + KASSERT(req != PRU_CONNECT2); + KASSERT(req != PRU_DISCONNECT); + KASSERT(req != PRU_SHUTDOWN); + KASSERT(req != PRU_ABORT); + KASSERT(req != PRU_CONTROL); + KASSERT(req != PRU_SENSE); + KASSERT(req != PRU_PEERADDR); + KASSERT(req != PRU_SOCKADDR); + KASSERT(req != PRU_RCVD); + KASSERT(req != PRU_RCVOOB); + KASSERT(req != PRU_SEND); + KASSERT(req != PRU_SENDOOB); + KASSERT(req != PRU_PURGEIF); if (pcb == NULL) { err = EINVAL; @@ -146,98 +409,6 @@ l2cap_usrreq(struct socket *up, int req, } switch(req) { - case PRU_DISCONNECT: - soisdisconnecting(up); - return l2cap_disconnect(pcb, up->so_linger); - - case PRU_ABORT: - l2cap_disconnect(pcb, 0); - soisdisconnected(up); - /* fall through to */ - case PRU_DETACH: - return l2cap_detach((struct l2cap_channel **)&up->so_pcb); - - case PRU_BIND: - KASSERT(nam != NULL); - sa = mtod(nam, struct sockaddr_bt *); - - if (sa->bt_len != sizeof(struct sockaddr_bt)) - return EINVAL; - - if (sa->bt_family != AF_BLUETOOTH) - return EAFNOSUPPORT; - - return l2cap_bind(pcb, sa); - - case PRU_CONNECT: - KASSERT(nam != NULL); - sa = mtod(nam, struct sockaddr_bt *); - - if (sa->bt_len != sizeof(struct sockaddr_bt)) - return EINVAL; - - if (sa->bt_family != AF_BLUETOOTH) - return EAFNOSUPPORT; - - soisconnecting(up); - return l2cap_connect(pcb, sa); - - case PRU_PEERADDR: - KASSERT(nam != NULL); - sa = mtod(nam, struct sockaddr_bt *); - nam->m_len = sizeof(struct sockaddr_bt); - return l2cap_peeraddr(pcb, sa); - - case PRU_SOCKADDR: - KASSERT(nam != NULL); - sa = mtod(nam, struct sockaddr_bt *); - nam->m_len = sizeof(struct sockaddr_bt); - return l2cap_sockaddr(pcb, sa); - - case PRU_SHUTDOWN: - socantsendmore(up); - break; - - case PRU_SEND: - KASSERT(m != NULL); - if (m->m_pkthdr.len == 0) - break; - - if (m->m_pkthdr.len > pcb->lc_omtu) { - err = EMSGSIZE; - break; - } - - m0 = m_copypacket(m, M_DONTWAIT); - if (m0 == NULL) { - err = ENOMEM; - break; - } - - if (ctl) /* no use for that */ - m_freem(ctl); - - sbappendrecord(&up->so_snd, m); - return l2cap_send(pcb, m0); - - case PRU_SENSE: - return 0; /* (no release) */ - - case PRU_RCVD: - case PRU_RCVOOB: - return EOPNOTSUPP; /* (no release) */ - - case PRU_LISTEN: - return l2cap_listen(pcb); - - case PRU_ACCEPT: - KASSERT(nam != NULL); - sa = mtod(nam, struct sockaddr_bt *); - nam->m_len = sizeof(struct sockaddr_bt); - return l2cap_peeraddr(pcb, sa); - - case PRU_CONNECT2: - case PRU_SENDOOB: case PRU_FASTTIMO: case PRU_SLOWTIMO: case PRU_PROTORCV: @@ -376,7 +547,7 @@ l2cap_linkmode(void *arg, int new) if (((mode & L2CAP_LM_AUTH) && !(new & L2CAP_LM_AUTH)) || ((mode & L2CAP_LM_ENCRYPT) && !(new & L2CAP_LM_ENCRYPT)) || ((mode & L2CAP_LM_SECURE) && !(new & L2CAP_LM_SECURE))) - l2cap_disconnect(so->so_pcb, 0); + l2cap_disconnect_pcb(so->so_pcb, 0); } static void @@ -396,3 +567,49 @@ l2cap_input(void *arg, struct mbuf *m) sbappendrecord(&so->so_rcv, m); sorwakeup(so); } + +PR_WRAP_USRREQS(l2cap) + +#define l2cap_attach l2cap_attach_wrapper +#define l2cap_detach l2cap_detach_wrapper +#define l2cap_accept l2cap_accept_wrapper +#define l2cap_bind l2cap_bind_wrapper +#define l2cap_listen l2cap_listen_wrapper +#define l2cap_connect l2cap_connect_wrapper +#define l2cap_connect2 l2cap_connect2_wrapper +#define l2cap_disconnect l2cap_disconnect_wrapper +#define l2cap_shutdown l2cap_shutdown_wrapper +#define l2cap_abort l2cap_abort_wrapper +#define l2cap_ioctl l2cap_ioctl_wrapper +#define l2cap_stat l2cap_stat_wrapper +#define l2cap_peeraddr l2cap_peeraddr_wrapper +#define l2cap_sockaddr l2cap_sockaddr_wrapper +#define l2cap_rcvd l2cap_rcvd_wrapper +#define l2cap_recvoob l2cap_recvoob_wrapper +#define l2cap_send l2cap_send_wrapper +#define l2cap_sendoob l2cap_sendoob_wrapper +#define l2cap_purgeif l2cap_purgeif_wrapper +#define l2cap_usrreq l2cap_usrreq_wrapper + +const struct pr_usrreqs l2cap_usrreqs = { + .pr_attach = l2cap_attach, + .pr_detach = l2cap_detach, + .pr_accept = l2cap_accept, + .pr_bind = l2cap_bind, + .pr_listen = l2cap_listen, + .pr_connect = l2cap_connect, + .pr_connect2 = l2cap_connect2, + .pr_disconnect = l2cap_disconnect, + .pr_shutdown = l2cap_shutdown, + .pr_abort = l2cap_abort, + .pr_ioctl = l2cap_ioctl, + .pr_stat = l2cap_stat, + .pr_peeraddr = l2cap_peeraddr, + .pr_sockaddr = l2cap_sockaddr, + .pr_rcvd = l2cap_rcvd, + .pr_recvoob = l2cap_recvoob, + .pr_send = l2cap_send, + .pr_sendoob = l2cap_sendoob, + .pr_purgeif = l2cap_purgeif, + .pr_generic = l2cap_usrreq, +}; Index: src/sys/netbt/l2cap_upper.c diff -u src/sys/netbt/l2cap_upper.c:1.11 src/sys/netbt/l2cap_upper.c:1.11.36.1 --- src/sys/netbt/l2cap_upper.c:1.11 Mon Jan 4 19:20:05 2010 +++ src/sys/netbt/l2cap_upper.c Sun Aug 10 06:56:23 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: l2cap_upper.c,v 1.11 2010/01/04 19:20:05 plunky Exp $ */ +/* $NetBSD: l2cap_upper.c,v 1.11.36.1 2014/08/10 06:56:23 tls Exp $ */ /*- * Copyright (c) 2005 Iain Hibbert. @@ -31,7 +31,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: l2cap_upper.c,v 1.11 2010/01/04 19:20:05 plunky Exp $"); +__KERNEL_RCSID(0, "$NetBSD: l2cap_upper.c,v 1.11.36.1 2014/08/10 06:56:23 tls Exp $"); #include <sys/param.h> #include <sys/kernel.h> @@ -52,13 +52,13 @@ __KERNEL_RCSID(0, "$NetBSD: l2cap_upper. */ /* - * l2cap_attach(handle, btproto, upper) + * l2cap_attach_pcb(handle, btproto, upper) * * attach new l2cap_channel to handle, populate * with reasonable defaults */ int -l2cap_attach(struct l2cap_channel **handle, +l2cap_attach_pcb(struct l2cap_channel **handle, const struct btproto *proto, void *upper) { struct l2cap_channel *chan; @@ -102,12 +102,12 @@ l2cap_attach(struct l2cap_channel **hand } /* - * l2cap_bind(l2cap_channel, sockaddr) + * l2cap_bind_pcb(l2cap_channel, sockaddr) * * set local address of channel */ int -l2cap_bind(struct l2cap_channel *chan, struct sockaddr_bt *addr) +l2cap_bind_pcb(struct l2cap_channel *chan, struct sockaddr_bt *addr) { if (chan->lc_lcid != L2CAP_NULL_CID) @@ -118,12 +118,12 @@ l2cap_bind(struct l2cap_channel *chan, s } /* - * l2cap_sockaddr(l2cap_channel, sockaddr) + * l2cap_sockaddr_pcb(l2cap_channel, sockaddr) * * get local address of channel */ int -l2cap_sockaddr(struct l2cap_channel *chan, struct sockaddr_bt *addr) +l2cap_sockaddr_pcb(struct l2cap_channel *chan, struct sockaddr_bt *addr) { memcpy(addr, &chan->lc_laddr, sizeof(struct sockaddr_bt)); @@ -131,7 +131,7 @@ l2cap_sockaddr(struct l2cap_channel *cha } /* - * l2cap_connect(l2cap_channel, sockaddr) + * l2cap_connect_pcb(l2cap_channel, sockaddr) * * Initiate a connection to destination. This corresponds to * "Open Channel Request" in the L2CAP specification and will @@ -144,7 +144,7 @@ l2cap_sockaddr(struct l2cap_channel *cha * proto->connecting(upper) */ int -l2cap_connect(struct l2cap_channel *chan, struct sockaddr_bt *dest) +l2cap_connect_pcb(struct l2cap_channel *chan, struct sockaddr_bt *dest) { struct hci_unit *unit; int err; @@ -209,12 +209,12 @@ fail: } /* - * l2cap_peeraddr(l2cap_channel, sockaddr) + * l2cap_peeraddr_pcb(l2cap_channel, sockaddr) * * get remote address of channel */ int -l2cap_peeraddr(struct l2cap_channel *chan, struct sockaddr_bt *addr) +l2cap_peeraddr_pcb(struct l2cap_channel *chan, struct sockaddr_bt *addr) { memcpy(addr, &chan->lc_raddr, sizeof(struct sockaddr_bt)); @@ -222,7 +222,7 @@ l2cap_peeraddr(struct l2cap_channel *cha } /* - * l2cap_disconnect(l2cap_channel, linger) + * l2cap_disconnect_pcb(l2cap_channel, linger) * * Initiate L2CAP disconnection. This corresponds to * "Close Channel Request" in the L2CAP specification @@ -235,7 +235,7 @@ l2cap_peeraddr(struct l2cap_channel *cha * the queue. */ int -l2cap_disconnect(struct l2cap_channel *chan, int linger) +l2cap_disconnect_pcb(struct l2cap_channel *chan, int linger) { int err = 0; @@ -260,12 +260,12 @@ l2cap_disconnect(struct l2cap_channel *c } /* - * l2cap_detach(handle) + * l2cap_detach_pcb(handle) * * Detach l2cap channel from handle & close it down */ -int -l2cap_detach(struct l2cap_channel **handle) +void +l2cap_detach_pcb(struct l2cap_channel **handle) { struct l2cap_channel *chan; @@ -288,11 +288,10 @@ l2cap_detach(struct l2cap_channel **hand */ free(chan, M_BLUETOOTH); - return 0; } /* - * l2cap_listen(l2cap_channel) + * l2cap_listen_pcb(l2cap_channel) * * Use this channel as a listening post (until detached). This will * result in calls to: @@ -309,7 +308,7 @@ l2cap_detach(struct l2cap_channel **hand * You cannot use this channel for anything else subsequent to this call */ int -l2cap_listen(struct l2cap_channel *chan) +l2cap_listen_pcb(struct l2cap_channel *chan) { struct l2cap_channel *used, *prev = NULL; uint32_t psm; @@ -373,7 +372,7 @@ l2cap_listen(struct l2cap_channel *chan) } /* - * l2cap_send(l2cap_channel, mbuf) + * l2cap_send_pcb(l2cap_channel, mbuf) * * Output SDU on channel described by channel. This corresponds * to "Send Data Request" in the L2CAP specification. The upper @@ -395,7 +394,7 @@ l2cap_listen(struct l2cap_channel *chan) * B-Frame header and start sending if we are not already */ int -l2cap_send(struct l2cap_channel *chan, struct mbuf *m) +l2cap_send_pcb(struct l2cap_channel *chan, struct mbuf *m) { l2cap_hdr_t *hdr; int plen; Index: src/sys/netbt/rfcomm.h diff -u src/sys/netbt/rfcomm.h:1.9 src/sys/netbt/rfcomm.h:1.9.36.1 --- src/sys/netbt/rfcomm.h:1.9 Sun Sep 13 18:45:11 2009 +++ src/sys/netbt/rfcomm.h Sun Aug 10 06:56:23 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: rfcomm.h,v 1.9 2009/09/13 18:45:11 pooka Exp $ */ +/* $NetBSD: rfcomm.h,v 1.9.36.1 2014/08/10 06:56:23 tls Exp $ */ /*- * Copyright (c) 2006 Itronix Inc. @@ -55,7 +55,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: rfcomm.h,v 1.9 2009/09/13 18:45:11 pooka Exp $ + * $Id: rfcomm.h,v 1.9.36.1 2014/08/10 06:56:23 tls Exp $ * $FreeBSD: src/sys/netgraph/bluetooth/include/ng_btsocket_rfcomm.h,v 1.4 2005/01/11 01:39:53 emax Exp $ */ @@ -404,20 +404,19 @@ int rfcomm_session_send_mcc(struct rfcom void rfcomm_init(void); /* rfcomm_socket.c */ -int rfcomm_usrreq(struct socket *, int, struct mbuf *, struct mbuf *, struct mbuf *, struct lwp *); int rfcomm_ctloutput(int, struct socket *, struct sockopt *); /* rfcomm_upper.c */ -int rfcomm_attach(struct rfcomm_dlc **, const struct btproto *, void *); -int rfcomm_bind(struct rfcomm_dlc *, struct sockaddr_bt *); -int rfcomm_sockaddr(struct rfcomm_dlc *, struct sockaddr_bt *); -int rfcomm_connect(struct rfcomm_dlc *, struct sockaddr_bt *); -int rfcomm_peeraddr(struct rfcomm_dlc *, struct sockaddr_bt *); -int rfcomm_disconnect(struct rfcomm_dlc *, int); -int rfcomm_detach(struct rfcomm_dlc **); -int rfcomm_listen(struct rfcomm_dlc *); -int rfcomm_send(struct rfcomm_dlc *, struct mbuf *); -int rfcomm_rcvd(struct rfcomm_dlc *, size_t); +int rfcomm_attach_pcb(struct rfcomm_dlc **, const struct btproto *, void *); +int rfcomm_bind_pcb(struct rfcomm_dlc *, struct sockaddr_bt *); +int rfcomm_sockaddr_pcb(struct rfcomm_dlc *, struct sockaddr_bt *); +int rfcomm_connect_pcb(struct rfcomm_dlc *, struct sockaddr_bt *); +int rfcomm_peeraddr_pcb(struct rfcomm_dlc *, struct sockaddr_bt *); +int rfcomm_disconnect_pcb(struct rfcomm_dlc *, int); +void rfcomm_detach_pcb(struct rfcomm_dlc **); +int rfcomm_listen_pcb(struct rfcomm_dlc *); +int rfcomm_send_pcb(struct rfcomm_dlc *, struct mbuf *); +int rfcomm_rcvd_pcb(struct rfcomm_dlc *, size_t); int rfcomm_setopt(struct rfcomm_dlc *, const struct sockopt *); int rfcomm_getopt(struct rfcomm_dlc *, struct sockopt *); Index: src/sys/netbt/sco_upper.c diff -u src/sys/netbt/sco_upper.c:1.9 src/sys/netbt/sco_upper.c:1.9.36.1 --- src/sys/netbt/sco_upper.c:1.9 Mon Jan 4 19:20:05 2010 +++ src/sys/netbt/sco_upper.c Sun Aug 10 06:56:23 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: sco_upper.c,v 1.9 2010/01/04 19:20:05 plunky Exp $ */ +/* $NetBSD: sco_upper.c,v 1.9.36.1 2014/08/10 06:56:23 tls Exp $ */ /*- * Copyright (c) 2006 Itronix Inc. @@ -32,7 +32,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: sco_upper.c,v 1.9 2010/01/04 19:20:05 plunky Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sco_upper.c,v 1.9.36.1 2014/08/10 06:56:23 tls Exp $"); #include <sys/param.h> #include <sys/kernel.h> @@ -53,12 +53,12 @@ __KERNEL_RCSID(0, "$NetBSD: sco_upper.c, struct sco_pcb_list sco_pcb = LIST_HEAD_INITIALIZER(sco_pcb); /* - * sco_attach(handle, proto, upper) + * sco_attach_pcb(handle, proto, upper) * * Attach a new instance of SCO pcb to handle */ int -sco_attach(struct sco_pcb **handle, +sco_attach_pcb(struct sco_pcb **handle, const struct btproto *proto, void *upper) { struct sco_pcb *pcb; @@ -82,12 +82,12 @@ sco_attach(struct sco_pcb **handle, } /* - * sco_bind(pcb, sockaddr) + * sco_bind_pcb(pcb, sockaddr) * * Bind SCO pcb to local address */ int -sco_bind(struct sco_pcb *pcb, struct sockaddr_bt *addr) +sco_bind_pcb(struct sco_pcb *pcb, struct sockaddr_bt *addr) { if (pcb->sp_link != NULL || pcb->sp_flags & SP_LISTENING) @@ -98,12 +98,12 @@ sco_bind(struct sco_pcb *pcb, struct soc } /* - * sco_sockaddr(pcb, sockaddr) + * sco_sockaddr_pcb(pcb, sockaddr) * * Copy local address of PCB to sockaddr */ int -sco_sockaddr(struct sco_pcb *pcb, struct sockaddr_bt *addr) +sco_sockaddr_pcb(struct sco_pcb *pcb, struct sockaddr_bt *addr) { memset(addr, 0, sizeof(struct sockaddr_bt)); @@ -114,12 +114,12 @@ sco_sockaddr(struct sco_pcb *pcb, struct } /* - * sco_connect(pcb, sockaddr) + * sco_connect_pcb(pcb, sockaddr) * * Initiate a SCO connection to the destination address. */ int -sco_connect(struct sco_pcb *pcb, struct sockaddr_bt *dest) +sco_connect_pcb(struct sco_pcb *pcb, struct sockaddr_bt *dest) { hci_add_sco_con_cp cp; struct hci_unit *unit; @@ -177,12 +177,12 @@ sco_connect(struct sco_pcb *pcb, struct } /* - * sco_peeraddr(pcb, sockaddr) + * sco_peeraddr_pcb(pcb, sockaddr) * * Copy remote address of SCO pcb to sockaddr */ int -sco_peeraddr(struct sco_pcb *pcb, struct sockaddr_bt *addr) +sco_peeraddr_pcb(struct sco_pcb *pcb, struct sockaddr_bt *addr) { memset(addr, 0, sizeof(struct sockaddr_bt)); @@ -193,12 +193,12 @@ sco_peeraddr(struct sco_pcb *pcb, struct } /* - * sco_disconnect(pcb, linger) + * sco_disconnect_pcb(pcb, linger) * * Initiate disconnection of connected SCO pcb */ int -sco_disconnect(struct sco_pcb *pcb, int linger) +sco_disconnect_pcb(struct sco_pcb *pcb, int linger) { hci_discon_cp cp; struct hci_link *sco; @@ -222,12 +222,12 @@ sco_disconnect(struct sco_pcb *pcb, int } /* - * sco_detach(handle) + * sco_detach_pcb(handle) * * Detach SCO pcb from handle and clear up */ -int -sco_detach(struct sco_pcb **handle) +void +sco_detach_pcb(struct sco_pcb **handle) { struct sco_pcb *pcb; @@ -235,26 +235,22 @@ sco_detach(struct sco_pcb **handle) pcb = *handle; *handle = NULL; - if (pcb == NULL) - return EINVAL; - if (pcb->sp_link != NULL) { - sco_disconnect(pcb, 0); + sco_disconnect_pcb(pcb, 0); pcb->sp_link = NULL; } LIST_REMOVE(pcb, sp_next); free(pcb, M_BLUETOOTH); - return 0; } /* - * sco_listen(pcb) + * sco_listen_pcb(pcb) * * Mark pcb as a listener. */ int -sco_listen(struct sco_pcb *pcb) +sco_listen_pcb(struct sco_pcb *pcb) { if (pcb->sp_link != NULL) @@ -265,7 +261,7 @@ sco_listen(struct sco_pcb *pcb) } /* - * sco_send(pcb, mbuf) + * sco_send_pcb(pcb, mbuf) * * Send data on SCO pcb. * @@ -275,7 +271,7 @@ sco_listen(struct sco_pcb *pcb) * we can drop a record from the socket buffer. */ int -sco_send(struct sco_pcb *pcb, struct mbuf *m) +sco_send_pcb(struct sco_pcb *pcb, struct mbuf *m) { hci_scodata_hdr_t *hdr; int plen; Index: src/sys/netbt/rfcomm_dlc.c diff -u src/sys/netbt/rfcomm_dlc.c:1.7 src/sys/netbt/rfcomm_dlc.c:1.7.26.1 --- src/sys/netbt/rfcomm_dlc.c:1.7 Sun Aug 21 14:20:34 2011 +++ src/sys/netbt/rfcomm_dlc.c Sun Aug 10 06:56:23 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: rfcomm_dlc.c,v 1.7 2011/08/21 14:20:34 plunky Exp $ */ +/* $NetBSD: rfcomm_dlc.c,v 1.7.26.1 2014/08/10 06:56:23 tls Exp $ */ /*- * Copyright (c) 2006 Itronix Inc. @@ -32,7 +32,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: rfcomm_dlc.c,v 1.7 2011/08/21 14:20:34 plunky Exp $"); +__KERNEL_RCSID(0, "$NetBSD: rfcomm_dlc.c,v 1.7.26.1 2014/08/10 06:56:23 tls Exp $"); #include <sys/param.h> #include <sys/kernel.h> @@ -84,14 +84,14 @@ rfcomm_dlc_newconn(struct rfcomm_session * a note of the best address and BDADDR_ANY matches in order to find * the oldest and most specific match. */ - l2cap_sockaddr(rs->rs_l2cap, &laddr); - l2cap_peeraddr(rs->rs_l2cap, &raddr); + l2cap_sockaddr_pcb(rs->rs_l2cap, &laddr); + l2cap_peeraddr_pcb(rs->rs_l2cap, &raddr); chan = RFCOMM_CHANNEL(dlci); new = NULL; any = best = NULL; LIST_FOREACH(ls, &rfcomm_session_listen, rs_next) { - l2cap_sockaddr(ls->rs_l2cap, &addr); + l2cap_sockaddr_pcb(ls->rs_l2cap, &addr); if (addr.bt_psm != laddr.bt_psm) continue; Index: src/sys/netbt/rfcomm_session.c diff -u src/sys/netbt/rfcomm_session.c:1.18 src/sys/netbt/rfcomm_session.c:1.18.26.1 --- src/sys/netbt/rfcomm_session.c:1.18 Wed Jul 27 10:25:09 2011 +++ src/sys/netbt/rfcomm_session.c Sun Aug 10 06:56:23 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: rfcomm_session.c,v 1.18 2011/07/27 10:25:09 plunky Exp $ */ +/* $NetBSD: rfcomm_session.c,v 1.18.26.1 2014/08/10 06:56:23 tls Exp $ */ /*- * Copyright (c) 2006 Itronix Inc. @@ -32,7 +32,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: rfcomm_session.c,v 1.18 2011/07/27 10:25:09 plunky Exp $"); +__KERNEL_RCSID(0, "$NetBSD: rfcomm_session.c,v 1.18.26.1 2014/08/10 06:56:23 tls Exp $"); #include <sys/param.h> #include <sys/kernel.h> @@ -185,7 +185,7 @@ rfcomm_session_alloc(struct rfcomm_sessi SIMPLEQ_INIT(&rs->rs_credits); LIST_INIT(&rs->rs_dlcs); - err = l2cap_attach(&rs->rs_l2cap, &rfcomm_session_proto, rs); + err = l2cap_attach_pcb(&rs->rs_l2cap, &rfcomm_session_proto, rs); if (err) { free(rs, M_BLUETOOTH); return NULL; @@ -199,7 +199,7 @@ rfcomm_session_alloc(struct rfcomm_sessi if (laddr->bt_psm == L2CAP_PSM_ANY) laddr->bt_psm = L2CAP_PSM_RFCOMM; - (void)l2cap_bind(rs->rs_l2cap, laddr); + (void)l2cap_bind_pcb(rs->rs_l2cap, laddr); LIST_INSERT_HEAD(list, rs, rs_next); @@ -250,7 +250,7 @@ rfcomm_session_free(struct rfcomm_sessio /* Goodbye! */ LIST_REMOVE(rs, rs_next); - l2cap_detach(&rs->rs_l2cap); + l2cap_detach_pcb(&rs->rs_l2cap); callout_destroy(&rs->rs_timeout); free(rs, M_BLUETOOTH); } @@ -271,13 +271,13 @@ rfcomm_session_lookup(struct sockaddr_bt if (rs->rs_state == RFCOMM_SESSION_CLOSED) continue; - l2cap_sockaddr(rs->rs_l2cap, &addr); + l2cap_sockaddr_pcb(rs->rs_l2cap, &addr); if (bdaddr_same(&src->bt_bdaddr, &addr.bt_bdaddr) == 0) if (bdaddr_any(&src->bt_bdaddr) == 0) continue; - l2cap_peeraddr(rs->rs_l2cap, &addr); + l2cap_peeraddr_pcb(rs->rs_l2cap, &addr); if (addr.bt_psm != dest->bt_psm) continue; @@ -499,7 +499,7 @@ rfcomm_session_complete(void *arg, int c */ if (rs->rs_state == RFCOMM_SESSION_CLOSED) { if (SIMPLEQ_EMPTY(&rs->rs_credits)) - l2cap_disconnect(rs->rs_l2cap, 0); + l2cap_disconnect_pcb(rs->rs_l2cap, 0); } } @@ -853,7 +853,7 @@ rfcomm_session_recv_ua(struct rfcomm_ses case RFCOMM_SESSION_WAIT_DISCONNECT: /* We sent DISC */ callout_stop(&rs->rs_timeout); rs->rs_state = RFCOMM_SESSION_CLOSED; - l2cap_disconnect(rs->rs_l2cap, 0); + l2cap_disconnect_pcb(rs->rs_l2cap, 0); break; default: @@ -1510,7 +1510,7 @@ rfcomm_session_send_frame(struct rfcomm_ DPRINTFN(5, "dlci %d type %2.2x (%d bytes, fcs=%#2.2x)\n", dlci, type, m->m_pkthdr.len, fcs); - return l2cap_send(rs->rs_l2cap, m); + return l2cap_send_pcb(rs->rs_l2cap, m); } /* @@ -1610,7 +1610,7 @@ rfcomm_session_send_uih(struct rfcomm_se /* * UIH frame ready to go.. */ - err = l2cap_send(rs->rs_l2cap, m0); + err = l2cap_send_pcb(rs->rs_l2cap, m0); if (err) goto fail; Index: src/sys/netbt/rfcomm_socket.c diff -u src/sys/netbt/rfcomm_socket.c:1.11 src/sys/netbt/rfcomm_socket.c:1.11.2.1 --- src/sys/netbt/rfcomm_socket.c:1.11 Thu Aug 29 17:49:21 2013 +++ src/sys/netbt/rfcomm_socket.c Sun Aug 10 06:56:23 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: rfcomm_socket.c,v 1.11 2013/08/29 17:49:21 rmind Exp $ */ +/* $NetBSD: rfcomm_socket.c,v 1.11.2.1 2014/08/10 06:56:23 tls Exp $ */ /*- * Copyright (c) 2006 Itronix Inc. @@ -32,7 +32,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: rfcomm_socket.c,v 1.11 2013/08/29 17:49:21 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: rfcomm_socket.c,v 1.11.2.1 2014/08/10 06:56:23 tls Exp $"); /* load symbolic names */ #ifdef BLUETOOTH_DEBUG @@ -81,73 +81,332 @@ static const struct btproto rfcomm_proto int rfcomm_sendspace = 4096; int rfcomm_recvspace = 4096; +static int +rfcomm_attach(struct socket *so, int proto) +{ + int error; + + KASSERT(so->so_pcb == NULL); + + if (so->so_lock == NULL) { + mutex_obj_hold(bt_lock); + so->so_lock = bt_lock; + solock(so); + } + KASSERT(solocked(so)); + + /* + * Since we have nothing to add, we attach the DLC + * structure directly to our PCB pointer. + */ + error = soreserve(so, rfcomm_sendspace, rfcomm_recvspace); + if (error) + return error; + + error = rfcomm_attach_pcb((struct rfcomm_dlc **)&so->so_pcb, + &rfcomm_proto, so); + if (error) + return error; + + error = rfcomm_rcvd_pcb(so->so_pcb, sbspace(&so->so_rcv)); + if (error) { + rfcomm_detach_pcb((struct rfcomm_dlc **)&so->so_pcb); + return error; + } + return 0; +} + +static void +rfcomm_detach(struct socket *so) +{ + KASSERT(so->so_pcb != NULL); + rfcomm_detach_pcb((struct rfcomm_dlc **)&so->so_pcb); + KASSERT(so->so_pcb == NULL); +} + +static int +rfcomm_accept(struct socket *so, struct mbuf *nam) +{ + struct rfcomm_dlc *pcb = so->so_pcb; + struct sockaddr_bt *sa; + + KASSERT(solocked(so)); + KASSERT(nam != NULL); + + if (pcb == NULL) + return EINVAL; + + sa = mtod(nam, struct sockaddr_bt *); + nam->m_len = sizeof(struct sockaddr_bt); + return rfcomm_peeraddr_pcb(pcb, sa); +} + +static int +rfcomm_bind(struct socket *so, struct mbuf *nam, struct lwp *l) +{ + struct rfcomm_dlc *pcb = so->so_pcb; + struct sockaddr_bt *sa; + + KASSERT(solocked(so)); + KASSERT(nam != NULL); + + if (pcb == NULL) + return EINVAL; + + sa = mtod(nam, struct sockaddr_bt *); + if (sa->bt_len != sizeof(struct sockaddr_bt)) + return EINVAL; + + if (sa->bt_family != AF_BLUETOOTH) + return EAFNOSUPPORT; + + return rfcomm_bind_pcb(pcb, sa); +} + +static int +rfcomm_listen(struct socket *so, struct lwp *l) +{ + struct rfcomm_dlc *pcb = so->so_pcb; + + KASSERT(solocked(so)); + + if (pcb == NULL) + return EINVAL; + + return rfcomm_listen_pcb(pcb); +} + +static int +rfcomm_connect(struct socket *so, struct mbuf *nam, struct lwp *l) +{ + struct rfcomm_dlc *pcb = so->so_pcb; + struct sockaddr_bt *sa; + + KASSERT(solocked(so)); + KASSERT(nam != NULL); + + if (pcb == NULL) + return EINVAL; + + sa = mtod(nam, struct sockaddr_bt *); + if (sa->bt_len != sizeof(struct sockaddr_bt)) + return EINVAL; + + if (sa->bt_family != AF_BLUETOOTH) + return EAFNOSUPPORT; + + soisconnecting(so); + return rfcomm_connect_pcb(pcb, sa); +} + +static int +rfcomm_connect2(struct socket *so, struct socket *so2) +{ + struct rfcomm_dlc *pcb = so->so_pcb; + + KASSERT(solocked(so)); + + if (pcb == NULL) + return EINVAL; + + return EOPNOTSUPP; +} + +static int +rfcomm_disconnect(struct socket *so) +{ + struct rfcomm_dlc *pcb = so->so_pcb; + + KASSERT(solocked(so)); + + if (pcb == NULL) + return EINVAL; + + soisdisconnecting(so); + return rfcomm_disconnect_pcb(pcb, so->so_linger); +} + +static int +rfcomm_shutdown(struct socket *so) +{ + KASSERT(solocked(so)); + + socantsendmore(so); + return 0; +} + +static int +rfcomm_abort(struct socket *so) +{ + struct rfcomm_dlc *pcb = so->so_pcb; + + KASSERT(solocked(so)); + + if (pcb == NULL) + return EINVAL; + + rfcomm_disconnect_pcb(pcb, 0); + soisdisconnected(so); + rfcomm_detach(so); + return 0; +} + +static int +rfcomm_ioctl(struct socket *so, u_long cmd, void *nam, struct ifnet *ifp) +{ + return EPASSTHROUGH; +} + +static int +rfcomm_stat(struct socket *so, struct stat *ub) +{ + KASSERT(solocked(so)); + + return 0; +} + +static int +rfcomm_peeraddr(struct socket *so, struct mbuf *nam) +{ + struct rfcomm_dlc *pcb = so->so_pcb; + struct sockaddr_bt *sa; + + KASSERT(solocked(so)); + KASSERT(pcb != NULL); + KASSERT(nam != NULL); + + sa = mtod(nam, struct sockaddr_bt *); + nam->m_len = sizeof(struct sockaddr_bt); + return rfcomm_peeraddr_pcb(pcb, sa); +} + +static int +rfcomm_sockaddr(struct socket *so, struct mbuf *nam) +{ + struct rfcomm_dlc *pcb = so->so_pcb; + struct sockaddr_bt *sa; + + KASSERT(solocked(so)); + KASSERT(pcb != NULL); + KASSERT(nam != NULL); + + sa = mtod(nam, struct sockaddr_bt *); + nam->m_len = sizeof(struct sockaddr_bt); + return rfcomm_sockaddr_pcb(pcb, sa); +} + +static int +rfcomm_rcvd(struct socket *so, int flags, struct lwp *l) +{ + struct rfcomm_dlc *pcb = so->so_pcb; + + KASSERT(solocked(so)); + + if (pcb == NULL) + return EINVAL; + + return rfcomm_rcvd_pcb(pcb, sbspace(&so->so_rcv)); +} + +static int +rfcomm_recvoob(struct socket *so, struct mbuf *m, int flags) +{ + KASSERT(solocked(so)); + + return EOPNOTSUPP; +} + +static int +rfcomm_send(struct socket *so, struct mbuf *m, struct mbuf *nam, + struct mbuf *control, struct lwp *l) +{ + struct rfcomm_dlc *pcb = so->so_pcb; + int err = 0; + struct mbuf *m0; + + KASSERT(solocked(so)); + KASSERT(m != NULL); + + if (control) /* no use for that */ + m_freem(control); + + if (pcb == NULL) { + err = EINVAL; + goto release; + } + + m0 = m_copypacket(m, M_DONTWAIT); + if (m0 == NULL) { + err = ENOMEM; + goto release; + } + + sbappendstream(&so->so_snd, m); + return rfcomm_send_pcb(pcb, m0); + +release: + m_freem(m); + return err; +} + +static int +rfcomm_sendoob(struct socket *so, struct mbuf *m, struct mbuf *control) +{ + KASSERT(solocked(so)); + + if (m) + m_freem(m); + if (control) + m_freem(control); + + return EOPNOTSUPP; +} + +static int +rfcomm_purgeif(struct socket *so, struct ifnet *ifp) +{ + + return EOPNOTSUPP; +} + /* * User Request. * up is socket - * m is either - * optional mbuf chain containing message - * ioctl command (PRU_CONTROL) - * nam is either - * optional mbuf chain containing an address - * ioctl data (PRU_CONTROL) - * optionally protocol number (PRU_ATTACH) - * message flags (PRU_RCVD) + * m is optional mbuf chain containing message * ctl is either * optional mbuf chain containing socket options - * optional interface pointer (PRU_CONTROL, PRU_PURGEIF) * l is pointer to process requesting action (if any) * * we are responsible for disposing of m and ctl if * they are mbuf chains */ -int +static int rfcomm_usrreq(struct socket *up, int req, struct mbuf *m, struct mbuf *nam, struct mbuf *ctl, struct lwp *l) { struct rfcomm_dlc *pcb = up->so_pcb; - struct sockaddr_bt *sa; - struct mbuf *m0; int err = 0; DPRINTFN(2, "%s\n", prurequests[req]); - - switch (req) { - case PRU_CONTROL: - return EPASSTHROUGH; - - case PRU_PURGEIF: - return EOPNOTSUPP; - - case PRU_ATTACH: - if (up->so_lock == NULL) { - mutex_obj_hold(bt_lock); - up->so_lock = bt_lock; - solock(up); - } - KASSERT(solocked(up)); - if (pcb != NULL) - return EINVAL; - /* - * Since we have nothing to add, we attach the DLC - * structure directly to our PCB pointer. - */ - err = soreserve(up, rfcomm_sendspace, rfcomm_recvspace); - if (err) - return err; - - err = rfcomm_attach((struct rfcomm_dlc **)&up->so_pcb, - &rfcomm_proto, up); - if (err) - return err; - - err = rfcomm_rcvd(up->so_pcb, sbspace(&up->so_rcv)); - if (err) { - rfcomm_detach((struct rfcomm_dlc **)&up->so_pcb); - return err; - } - - return 0; - } + KASSERT(req != PRU_ATTACH); + KASSERT(req != PRU_DETACH); + KASSERT(req != PRU_ACCEPT); + KASSERT(req != PRU_BIND); + KASSERT(req != PRU_LISTEN); + KASSERT(req != PRU_CONNECT); + KASSERT(req != PRU_CONNECT2); + KASSERT(req != PRU_DISCONNECT); + KASSERT(req != PRU_SHUTDOWN); + KASSERT(req != PRU_ABORT); + KASSERT(req != PRU_CONTROL); + KASSERT(req != PRU_SENSE); + KASSERT(req != PRU_PEERADDR); + KASSERT(req != PRU_SOCKADDR); + KASSERT(req != PRU_RCVD); + KASSERT(req != PRU_RCVOOB); + KASSERT(req != PRU_SEND); + KASSERT(req != PRU_SENDOOB); + KASSERT(req != PRU_PURGEIF); if (pcb == NULL) { err = EINVAL; @@ -155,92 +414,6 @@ rfcomm_usrreq(struct socket *up, int req } switch(req) { - case PRU_DISCONNECT: - soisdisconnecting(up); - return rfcomm_disconnect(pcb, up->so_linger); - - case PRU_ABORT: - rfcomm_disconnect(pcb, 0); - soisdisconnected(up); - /* fall through to */ - case PRU_DETACH: - return rfcomm_detach((struct rfcomm_dlc **)&up->so_pcb); - - case PRU_BIND: - KASSERT(nam != NULL); - sa = mtod(nam, struct sockaddr_bt *); - - if (sa->bt_len != sizeof(struct sockaddr_bt)) - return EINVAL; - - if (sa->bt_family != AF_BLUETOOTH) - return EAFNOSUPPORT; - - return rfcomm_bind(pcb, sa); - - case PRU_CONNECT: - KASSERT(nam != NULL); - sa = mtod(nam, struct sockaddr_bt *); - - if (sa->bt_len != sizeof(struct sockaddr_bt)) - return EINVAL; - - if (sa->bt_family != AF_BLUETOOTH) - return EAFNOSUPPORT; - - soisconnecting(up); - return rfcomm_connect(pcb, sa); - - case PRU_PEERADDR: - KASSERT(nam != NULL); - sa = mtod(nam, struct sockaddr_bt *); - nam->m_len = sizeof(struct sockaddr_bt); - return rfcomm_peeraddr(pcb, sa); - - case PRU_SOCKADDR: - KASSERT(nam != NULL); - sa = mtod(nam, struct sockaddr_bt *); - nam->m_len = sizeof(struct sockaddr_bt); - return rfcomm_sockaddr(pcb, sa); - - case PRU_SHUTDOWN: - socantsendmore(up); - break; - - case PRU_SEND: - KASSERT(m != NULL); - - if (ctl) /* no use for that */ - m_freem(ctl); - - m0 = m_copypacket(m, M_DONTWAIT); - if (m0 == NULL) - return ENOMEM; - - sbappendstream(&up->so_snd, m); - - return rfcomm_send(pcb, m0); - - case PRU_SENSE: - return 0; /* (no release) */ - - case PRU_RCVD: - return rfcomm_rcvd(pcb, sbspace(&up->so_rcv)); - - case PRU_RCVOOB: - return EOPNOTSUPP; /* (no release) */ - - case PRU_LISTEN: - return rfcomm_listen(pcb); - - case PRU_ACCEPT: - KASSERT(nam != NULL); - sa = mtod(nam, struct sockaddr_bt *); - nam->m_len = sizeof(struct sockaddr_bt); - return rfcomm_peeraddr(pcb, sa); - - case PRU_CONNECT2: - case PRU_SENDOOB: case PRU_FASTTIMO: case PRU_SLOWTIMO: case PRU_PROTORCV: @@ -386,7 +559,7 @@ rfcomm_linkmode(void *arg, int new) if (((mode & RFCOMM_LM_AUTH) && !(new & RFCOMM_LM_AUTH)) || ((mode & RFCOMM_LM_ENCRYPT) && !(new & RFCOMM_LM_ENCRYPT)) || ((mode & RFCOMM_LM_SECURE) && !(new & RFCOMM_LM_SECURE))) - rfcomm_disconnect(so->so_pcb, 0); + rfcomm_disconnect_pcb(so->so_pcb, 0); } /* @@ -411,3 +584,49 @@ rfcomm_input(void *arg, struct mbuf *m) sbappendstream(&so->so_rcv, m); sorwakeup(so); } + +PR_WRAP_USRREQS(rfcomm) + +#define rfcomm_attach rfcomm_attach_wrapper +#define rfcomm_detach rfcomm_detach_wrapper +#define rfcomm_accept rfcomm_accept_wrapper +#define rfcomm_bind rfcomm_bind_wrapper +#define rfcomm_listen rfcomm_listen_wrapper +#define rfcomm_connect rfcomm_connect_wrapper +#define rfcomm_connect2 rfcomm_connect2_wrapper +#define rfcomm_disconnect rfcomm_disconnect_wrapper +#define rfcomm_shutdown rfcomm_shutdown_wrapper +#define rfcomm_abort rfcomm_abort_wrapper +#define rfcomm_ioctl rfcomm_ioctl_wrapper +#define rfcomm_stat rfcomm_stat_wrapper +#define rfcomm_peeraddr rfcomm_peeraddr_wrapper +#define rfcomm_sockaddr rfcomm_sockaddr_wrapper +#define rfcomm_rcvd rfcomm_rcvd_wrapper +#define rfcomm_recvoob rfcomm_recvoob_wrapper +#define rfcomm_send rfcomm_send_wrapper +#define rfcomm_sendoob rfcomm_sendoob_wrapper +#define rfcomm_purgeif rfcomm_purgeif_wrapper +#define rfcomm_usrreq rfcomm_usrreq_wrapper + +const struct pr_usrreqs rfcomm_usrreqs = { + .pr_attach = rfcomm_attach, + .pr_detach = rfcomm_detach, + .pr_accept = rfcomm_accept, + .pr_bind = rfcomm_bind, + .pr_listen = rfcomm_listen, + .pr_connect = rfcomm_connect, + .pr_connect2 = rfcomm_connect2, + .pr_disconnect = rfcomm_disconnect, + .pr_shutdown = rfcomm_shutdown, + .pr_abort = rfcomm_abort, + .pr_ioctl = rfcomm_ioctl, + .pr_stat = rfcomm_stat, + .pr_peeraddr = rfcomm_peeraddr, + .pr_sockaddr = rfcomm_sockaddr, + .pr_rcvd = rfcomm_rcvd, + .pr_recvoob = rfcomm_recvoob, + .pr_send = rfcomm_send, + .pr_sendoob = rfcomm_sendoob, + .pr_purgeif = rfcomm_purgeif, + .pr_generic = rfcomm_usrreq, +}; Index: src/sys/netbt/rfcomm_upper.c diff -u src/sys/netbt/rfcomm_upper.c:1.13 src/sys/netbt/rfcomm_upper.c:1.13.36.1 --- src/sys/netbt/rfcomm_upper.c:1.13 Mon Jan 4 19:20:05 2010 +++ src/sys/netbt/rfcomm_upper.c Sun Aug 10 06:56:23 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: rfcomm_upper.c,v 1.13 2010/01/04 19:20:05 plunky Exp $ */ +/* $NetBSD: rfcomm_upper.c,v 1.13.36.1 2014/08/10 06:56:23 tls Exp $ */ /*- * Copyright (c) 2006 Itronix Inc. @@ -32,12 +32,12 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: rfcomm_upper.c,v 1.13 2010/01/04 19:20:05 plunky Exp $"); +__KERNEL_RCSID(0, "$NetBSD: rfcomm_upper.c,v 1.13.36.1 2014/08/10 06:56:23 tls Exp $"); #include <sys/param.h> #include <sys/kernel.h> #include <sys/mbuf.h> -#include <sys/proc.h> +#include <sys/kmem.h> #include <sys/socketvar.h> #include <sys/systm.h> @@ -56,12 +56,12 @@ __KERNEL_RCSID(0, "$NetBSD: rfcomm_upper */ /* - * rfcomm_attach(handle, proto, upper) + * rfcomm_attach_pcb(handle, proto, upper) * * attach a new RFCOMM DLC to handle, populate with reasonable defaults */ int -rfcomm_attach(struct rfcomm_dlc **handle, +rfcomm_attach_pcb(struct rfcomm_dlc **handle, const struct btproto *proto, void *upper) { struct rfcomm_dlc *dlc; @@ -70,9 +70,7 @@ rfcomm_attach(struct rfcomm_dlc **handle KASSERT(proto != NULL); KASSERT(upper != NULL); - dlc = malloc(sizeof(struct rfcomm_dlc), M_BLUETOOTH, M_NOWAIT | M_ZERO); - if (dlc == NULL) - return ENOMEM; + dlc = kmem_zalloc(sizeof(struct rfcomm_dlc), KM_SLEEP); dlc->rd_state = RFCOMM_DLC_CLOSED; dlc->rd_mtu = rfcomm_mtu_default; @@ -98,12 +96,12 @@ rfcomm_attach(struct rfcomm_dlc **handle } /* - * rfcomm_bind(dlc, sockaddr) + * rfcomm_bind_pcb(dlc, sockaddr) * * bind DLC to local address */ int -rfcomm_bind(struct rfcomm_dlc *dlc, struct sockaddr_bt *addr) +rfcomm_bind_pcb(struct rfcomm_dlc *dlc, struct sockaddr_bt *addr) { if (dlc->rd_state != RFCOMM_DLC_CLOSED) @@ -114,12 +112,12 @@ rfcomm_bind(struct rfcomm_dlc *dlc, stru } /* - * rfcomm_sockaddr(dlc, sockaddr) + * rfcomm_sockaddr_pcb(dlc, sockaddr) * * return local address */ int -rfcomm_sockaddr(struct rfcomm_dlc *dlc, struct sockaddr_bt *addr) +rfcomm_sockaddr_pcb(struct rfcomm_dlc *dlc, struct sockaddr_bt *addr) { memcpy(addr, &dlc->rd_laddr, sizeof(struct sockaddr_bt)); @@ -127,12 +125,12 @@ rfcomm_sockaddr(struct rfcomm_dlc *dlc, } /* - * rfcomm_connect(dlc, sockaddr) + * rfcomm_connect_pcb(dlc, sockaddr) * * Initiate connection of RFCOMM DLC to remote address. */ int -rfcomm_connect(struct rfcomm_dlc *dlc, struct sockaddr_bt *dest) +rfcomm_connect_pcb(struct rfcomm_dlc *dlc, struct sockaddr_bt *dest) { struct rfcomm_session *rs; int err = 0; @@ -169,7 +167,7 @@ rfcomm_connect(struct rfcomm_dlc *dlc, s rs->rs_flags |= RFCOMM_SESSION_INITIATOR; rs->rs_state = RFCOMM_SESSION_WAIT_CONNECT; - err = l2cap_connect(rs->rs_l2cap, &dlc->rd_raddr); + err = l2cap_connect_pcb(rs->rs_l2cap, &dlc->rd_raddr); if (err) { rfcomm_session_free(rs); return err; @@ -186,7 +184,7 @@ rfcomm_connect(struct rfcomm_dlc *dlc, s if (rfcomm_dlc_lookup(rs, dlc->rd_dlci)) return EBUSY; - l2cap_sockaddr(rs->rs_l2cap, &dlc->rd_laddr); + l2cap_sockaddr_pcb(rs->rs_l2cap, &dlc->rd_laddr); /* * attach the DLC to the session and start it off @@ -202,12 +200,12 @@ rfcomm_connect(struct rfcomm_dlc *dlc, s } /* - * rfcomm_peeraddr(dlc, sockaddr) + * rfcomm_peeraddr_pcb(dlc, sockaddr) * * return remote address */ int -rfcomm_peeraddr(struct rfcomm_dlc *dlc, struct sockaddr_bt *addr) +rfcomm_peeraddr_pcb(struct rfcomm_dlc *dlc, struct sockaddr_bt *addr) { memcpy(addr, &dlc->rd_raddr, sizeof(struct sockaddr_bt)); @@ -215,12 +213,12 @@ rfcomm_peeraddr(struct rfcomm_dlc *dlc, } /* - * rfcomm_disconnect(dlc, linger) + * rfcomm_disconnect_pcb(dlc, linger) * * disconnect RFCOMM DLC */ int -rfcomm_disconnect(struct rfcomm_dlc *dlc, int linger) +rfcomm_disconnect_pcb(struct rfcomm_dlc *dlc, int linger) { struct rfcomm_session *rs = dlc->rd_session; int err = 0; @@ -270,12 +268,12 @@ rfcomm_disconnect(struct rfcomm_dlc *dlc } /* - * rfcomm_detach(handle) + * rfcomm_detach_pcb(handle) * * detach RFCOMM DLC from handle */ -int -rfcomm_detach(struct rfcomm_dlc **handle) +void +rfcomm_detach_pcb(struct rfcomm_dlc **handle) { struct rfcomm_dlc *dlc = *handle; @@ -298,14 +296,12 @@ rfcomm_detach(struct rfcomm_dlc **handle dlc->rd_flags |= RFCOMM_DLC_DETACH; else { callout_destroy(&dlc->rd_timeout); - free(dlc, M_BLUETOOTH); + kmem_free(dlc, sizeof(*dlc)); } - - return 0; } /* - * rfcomm_listen(dlc) + * rfcomm_listen_pcb(dlc) * * This DLC is a listener. We look for an existing listening session * with a matching address to attach to or else create a new one on @@ -313,7 +309,7 @@ rfcomm_detach(struct rfcomm_dlc **handle * available for the session. */ int -rfcomm_listen(struct rfcomm_dlc *dlc) +rfcomm_listen_pcb(struct rfcomm_dlc *dlc) { struct rfcomm_session *rs; struct rfcomm_dlc *used; @@ -336,7 +332,7 @@ rfcomm_listen(struct rfcomm_dlc *dlc) return EADDRNOTAVAIL; LIST_FOREACH(rs, &rfcomm_session_listen, rs_next) { - l2cap_sockaddr(rs->rs_l2cap, &addr); + l2cap_sockaddr_pcb(rs->rs_l2cap, &addr); if (addr.bt_psm != dlc->rd_laddr.bt_psm) continue; @@ -353,7 +349,7 @@ rfcomm_listen(struct rfcomm_dlc *dlc) rs->rs_state = RFCOMM_SESSION_LISTEN; - err = l2cap_listen(rs->rs_l2cap); + err = l2cap_listen_pcb(rs->rs_l2cap); if (err) { rfcomm_session_free(rs); return err; @@ -386,14 +382,14 @@ rfcomm_listen(struct rfcomm_dlc *dlc) } /* - * rfcomm_send(dlc, mbuf) + * rfcomm_send_pcb(dlc, mbuf) * * Output data on DLC. This is streamed data, so we add it * to our buffer and start the DLC, which will assemble * packets and send them if it can. */ int -rfcomm_send(struct rfcomm_dlc *dlc, struct mbuf *m) +rfcomm_send_pcb(struct rfcomm_dlc *dlc, struct mbuf *m) { if (dlc->rd_txbuf != NULL) { @@ -410,7 +406,7 @@ rfcomm_send(struct rfcomm_dlc *dlc, stru } /* - * rfcomm_rcvd(dlc, space) + * rfcomm_rcvd_pcb(dlc, space) * * Indicate space now available in receive buffer * @@ -419,7 +415,7 @@ rfcomm_send(struct rfcomm_dlc *dlc, stru * buffer after that. */ int -rfcomm_rcvd(struct rfcomm_dlc *dlc, size_t space) +rfcomm_rcvd_pcb(struct rfcomm_dlc *dlc, size_t space) { KASSERT(dlc != NULL); Index: src/sys/netbt/sco.h diff -u src/sys/netbt/sco.h:1.3 src/sys/netbt/sco.h:1.3.54.1 --- src/sys/netbt/sco.h:1.3 Wed Aug 6 15:01:24 2008 +++ src/sys/netbt/sco.h Sun Aug 10 06:56:23 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: sco.h,v 1.3 2008/08/06 15:01:24 plunky Exp $ */ +/* $NetBSD: sco.h,v 1.3.54.1 2014/08/10 06:56:23 tls Exp $ */ /*- * Copyright (c) 2006 Itronix Inc. @@ -65,20 +65,18 @@ struct sockopt; /* sco_socket.c */ extern int sco_sendspace; extern int sco_recvspace; -int sco_usrreq(struct socket *, int, struct mbuf *, - struct mbuf *, struct mbuf *, struct lwp *); int sco_ctloutput(int, struct socket *, struct sockopt *); /* sco_upper.c */ -int sco_attach(struct sco_pcb **, const struct btproto *, void *); -int sco_bind(struct sco_pcb *, struct sockaddr_bt *); -int sco_sockaddr(struct sco_pcb *, struct sockaddr_bt *); -int sco_connect(struct sco_pcb *, struct sockaddr_bt *); -int sco_peeraddr(struct sco_pcb *, struct sockaddr_bt *); -int sco_disconnect(struct sco_pcb *, int); -int sco_detach(struct sco_pcb **); -int sco_listen(struct sco_pcb *); -int sco_send(struct sco_pcb *, struct mbuf *); +int sco_attach_pcb(struct sco_pcb **, const struct btproto *, void *); +int sco_bind_pcb(struct sco_pcb *, struct sockaddr_bt *); +int sco_sockaddr_pcb(struct sco_pcb *, struct sockaddr_bt *); +int sco_connect_pcb(struct sco_pcb *, struct sockaddr_bt *); +int sco_peeraddr_pcb(struct sco_pcb *, struct sockaddr_bt *); +int sco_disconnect_pcb(struct sco_pcb *, int); +void sco_detach_pcb(struct sco_pcb **); +int sco_listen_pcb(struct sco_pcb *); +int sco_send_pcb(struct sco_pcb *, struct mbuf *); int sco_setopt(struct sco_pcb *, const struct sockopt *); int sco_getopt(struct sco_pcb *, struct sockopt *); Index: src/sys/netbt/sco_socket.c diff -u src/sys/netbt/sco_socket.c:1.12 src/sys/netbt/sco_socket.c:1.12.2.1 --- src/sys/netbt/sco_socket.c:1.12 Thu Aug 29 17:49:21 2013 +++ src/sys/netbt/sco_socket.c Sun Aug 10 06:56:23 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: sco_socket.c,v 1.12 2013/08/29 17:49:21 rmind Exp $ */ +/* $NetBSD: sco_socket.c,v 1.12.2.1 2014/08/10 06:56:23 tls Exp $ */ /*- * Copyright (c) 2006 Itronix Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: sco_socket.c,v 1.12 2013/08/29 17:49:21 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sco_socket.c,v 1.12.2.1 2014/08/10 06:56:23 tls Exp $"); /* load symbolic names */ #ifdef BLUETOOTH_DEBUG @@ -78,56 +78,321 @@ static const struct btproto sco_proto = int sco_sendspace = 4096; int sco_recvspace = 4096; +static int +sco_attach(struct socket *so, int proto) +{ + int error; + + KASSERT(so->so_pcb == NULL); + + if (so->so_lock == NULL) { + mutex_obj_hold(bt_lock); + so->so_lock = bt_lock; + solock(so); + } + KASSERT(solocked(so)); + + error = soreserve(so, sco_sendspace, sco_recvspace); + if (error) { + return error; + } + return sco_attach_pcb((struct sco_pcb **)&so->so_pcb, &sco_proto, so); +} + +static void +sco_detach(struct socket *so) +{ + KASSERT(so->so_pcb != NULL); + sco_detach_pcb((struct sco_pcb **)&so->so_pcb); + KASSERT(so->so_pcb == NULL); +} + +static int +sco_accept(struct socket *so, struct mbuf *nam) +{ + struct sco_pcb *pcb = so->so_pcb; + struct sockaddr_bt *sa; + + KASSERT(solocked(so)); + KASSERT(nam != NULL); + + if (pcb == NULL) + return EINVAL; + + sa = mtod(nam, struct sockaddr_bt *); + nam->m_len = sizeof(struct sockaddr_bt); + return sco_peeraddr_pcb(pcb, sa); +} + +static int +sco_bind(struct socket *so, struct mbuf *nam, struct lwp *l) +{ + struct sco_pcb *pcb = so->so_pcb; + struct sockaddr_bt *sa; + + KASSERT(solocked(so)); + KASSERT(nam != NULL); + + if (pcb == NULL) + return EINVAL; + + sa = mtod(nam, struct sockaddr_bt *); + if (sa->bt_len != sizeof(struct sockaddr_bt)) + return EINVAL; + + if (sa->bt_family != AF_BLUETOOTH) + return EAFNOSUPPORT; + + return sco_bind_pcb(pcb, sa); +} + +static int +sco_listen(struct socket *so, struct lwp *l) +{ + struct sco_pcb *pcb = so->so_pcb; + + KASSERT(solocked(so)); + + if (pcb == NULL) + return EINVAL; + + return sco_listen_pcb(pcb); +} + +static int +sco_connect(struct socket *so, struct mbuf *nam, struct lwp *l) +{ + struct sco_pcb *pcb = so->so_pcb; + struct sockaddr_bt *sa; + + KASSERT(solocked(so)); + KASSERT(nam != NULL); + + if (pcb == NULL) + return EINVAL; + + sa = mtod(nam, struct sockaddr_bt *); + if (sa->bt_len != sizeof(struct sockaddr_bt)) + return EINVAL; + + if (sa->bt_family != AF_BLUETOOTH) + return EAFNOSUPPORT; + + soisconnecting(so); + return sco_connect_pcb(pcb, sa); +} + +static int +sco_connect2(struct socket *so, struct socket *so2) +{ + struct sco_pcb *pcb = so->so_pcb; + + KASSERT(solocked(so)); + + if (pcb == NULL) + return EINVAL; + + return EOPNOTSUPP; +} + +static int +sco_disconnect(struct socket *so) +{ + struct sco_pcb *pcb = so->so_pcb; + + KASSERT(solocked(so)); + + if (pcb == NULL) + return EINVAL; + + soisdisconnecting(so); + return sco_disconnect_pcb(pcb, so->so_linger); +} + +static int +sco_shutdown(struct socket *so) +{ + KASSERT(solocked(so)); + + socantsendmore(so); + return 0; +} + +static int +sco_abort(struct socket *so) +{ + struct sco_pcb *pcb = so->so_pcb; + + KASSERT(solocked(so)); + + if (pcb == NULL) + return EINVAL; + + sco_disconnect_pcb(pcb, 0); + soisdisconnected(so); + sco_detach(so); + return 0; +} + +static int +sco_ioctl(struct socket *so, u_long cmd, void *nam, struct ifnet *ifp) +{ + return EOPNOTSUPP; +} + +static int +sco_stat(struct socket *so, struct stat *ub) +{ + KASSERT(solocked(so)); + + return 0; +} + +static int +sco_peeraddr(struct socket *so, struct mbuf *nam) +{ + struct sco_pcb *pcb = (struct sco_pcb *)so->so_pcb; + struct sockaddr_bt *sa; + + KASSERT(solocked(so)); + KASSERT(pcb != NULL); + KASSERT(nam != NULL); + + sa = mtod(nam, struct sockaddr_bt *); + nam->m_len = sizeof(struct sockaddr_bt); + return sco_peeraddr_pcb(pcb, sa); +} + +static int +sco_sockaddr(struct socket *so, struct mbuf *nam) +{ + struct sco_pcb *pcb = (struct sco_pcb *)so->so_pcb; + struct sockaddr_bt *sa; + + KASSERT(solocked(so)); + KASSERT(pcb != NULL); + KASSERT(nam != NULL); + + sa = mtod(nam, struct sockaddr_bt *); + nam->m_len = sizeof(struct sockaddr_bt); + return sco_sockaddr_pcb(pcb, sa); +} + +static int +sco_rcvd(struct socket *so, int flags, struct lwp *l) +{ + KASSERT(solocked(so)); + + return EOPNOTSUPP; +} + +static int +sco_recvoob(struct socket *so, struct mbuf *m, int flags) +{ + KASSERT(solocked(so)); + + return EOPNOTSUPP; +} + +static int +sco_send(struct socket *so, struct mbuf *m, struct mbuf *nam, + struct mbuf *control, struct lwp *l) +{ + struct sco_pcb *pcb = so->so_pcb; + int err = 0; + struct mbuf *m0; + + KASSERT(solocked(so)); + KASSERT(m != NULL); + + if (control) /* no use for that */ + m_freem(control); + + if (pcb == NULL) { + err = EINVAL; + goto release; + } + + if (m->m_pkthdr.len == 0) + goto release; + + if (m->m_pkthdr.len > pcb->sp_mtu) { + err = EMSGSIZE; + goto release; + } + + m0 = m_copypacket(m, M_DONTWAIT); + if (m0 == NULL) { + err = ENOMEM; + goto release; + } + + sbappendrecord(&so->so_snd, m); + return sco_send_pcb(pcb, m0); + +release: + m_freem(m); + return err; +} + +static int +sco_sendoob(struct socket *so, struct mbuf *m, struct mbuf *control) +{ + KASSERT(solocked(so)); + + if (m) + m_freem(m); + if (control) + m_freem(control); + + return EOPNOTSUPP; +} + +static int +sco_purgeif(struct socket *so, struct ifnet *ifp) +{ + + return EOPNOTSUPP; +} + /* * User Request. * up is socket - * m is either - * optional mbuf chain containing message - * ioctl command (PRU_CONTROL) - * nam is either - * optional mbuf chain containing an address - * ioctl data (PRU_CONTROL) - * optionally, protocol number (PRU_ATTACH) + * m is optional mbuf chain containing message + * nam is optional mbuf chain containing an address * ctl is optional mbuf chain containing socket options * l is pointer to process requesting action (if any) * * we are responsible for disposing of m and ctl if * they are mbuf chains */ -int +static int sco_usrreq(struct socket *up, int req, struct mbuf *m, struct mbuf *nam, struct mbuf *ctl, struct lwp *l) { - struct sco_pcb *pcb = (struct sco_pcb *)up->so_pcb; - struct sockaddr_bt *sa; - struct mbuf *m0; + struct sco_pcb *pcb = up->so_pcb; int err = 0; DPRINTFN(2, "%s\n", prurequests[req]); - - switch(req) { - case PRU_CONTROL: - return EOPNOTSUPP; - - case PRU_PURGEIF: - return EOPNOTSUPP; - - case PRU_ATTACH: - if (up->so_lock == NULL) { - mutex_obj_hold(bt_lock); - up->so_lock = bt_lock; - solock(up); - } - KASSERT(solocked(up)); - if (pcb) - return EINVAL; - err = soreserve(up, sco_sendspace, sco_recvspace); - if (err) - return err; - - return sco_attach((struct sco_pcb **)&up->so_pcb, - &sco_proto, up); - } + KASSERT(req != PRU_ATTACH); + KASSERT(req != PRU_DETACH); + KASSERT(req != PRU_ACCEPT); + KASSERT(req != PRU_BIND); + KASSERT(req != PRU_LISTEN); + KASSERT(req != PRU_CONNECT); + KASSERT(req != PRU_CONNECT2); + KASSERT(req != PRU_DISCONNECT); + KASSERT(req != PRU_SHUTDOWN); + KASSERT(req != PRU_ABORT); + KASSERT(req != PRU_CONTROL); + KASSERT(req != PRU_SENSE); + KASSERT(req != PRU_PEERADDR); + KASSERT(req != PRU_SOCKADDR); + KASSERT(req != PRU_RCVD); + KASSERT(req != PRU_RCVOOB); + KASSERT(req != PRU_SEND); + KASSERT(req != PRU_SENDOOB); + KASSERT(req != PRU_PURGEIF); /* anything after here *requires* a pcb */ if (pcb == NULL) { @@ -136,98 +401,6 @@ sco_usrreq(struct socket *up, int req, s } switch(req) { - case PRU_DISCONNECT: - soisdisconnecting(up); - return sco_disconnect(pcb, up->so_linger); - - case PRU_ABORT: - sco_disconnect(pcb, 0); - soisdisconnected(up); - /* fall through to */ - case PRU_DETACH: - return sco_detach((struct sco_pcb **)&up->so_pcb); - - case PRU_BIND: - KASSERT(nam != NULL); - sa = mtod(nam, struct sockaddr_bt *); - - if (sa->bt_len != sizeof(struct sockaddr_bt)) - return EINVAL; - - if (sa->bt_family != AF_BLUETOOTH) - return EAFNOSUPPORT; - - return sco_bind(pcb, sa); - - case PRU_CONNECT: - KASSERT(nam != NULL); - sa = mtod(nam, struct sockaddr_bt *); - - if (sa->bt_len != sizeof(struct sockaddr_bt)) - return EINVAL; - - if (sa->bt_family != AF_BLUETOOTH) - return EAFNOSUPPORT; - - soisconnecting(up); - return sco_connect(pcb, sa); - - case PRU_PEERADDR: - KASSERT(nam != NULL); - sa = mtod(nam, struct sockaddr_bt *); - nam->m_len = sizeof(struct sockaddr_bt); - return sco_peeraddr(pcb, sa); - - case PRU_SOCKADDR: - KASSERT(nam != NULL); - sa = mtod(nam, struct sockaddr_bt *); - nam->m_len = sizeof(struct sockaddr_bt); - return sco_sockaddr(pcb, sa); - - case PRU_SHUTDOWN: - socantsendmore(up); - break; - - case PRU_SEND: - KASSERT(m != NULL); - if (m->m_pkthdr.len == 0) - break; - - if (m->m_pkthdr.len > pcb->sp_mtu) { - err = EMSGSIZE; - break; - } - - m0 = m_copypacket(m, M_DONTWAIT); - if (m0 == NULL) { - err = ENOMEM; - break; - } - - if (ctl) /* no use for that */ - m_freem(ctl); - - sbappendrecord(&up->so_snd, m); - return sco_send(pcb, m0); - - case PRU_SENSE: - return 0; /* (no sense - Doh!) */ - - case PRU_RCVD: - case PRU_RCVOOB: - return EOPNOTSUPP; /* (no release) */ - - case PRU_LISTEN: - return sco_listen(pcb); - - case PRU_ACCEPT: - KASSERT(nam != NULL); - sa = mtod(nam, struct sockaddr_bt *); - nam->m_len = sizeof(struct sockaddr_bt); - return sco_peeraddr(pcb, sa); - - case PRU_CONNECT2: - case PRU_SENDOOB: case PRU_FASTTIMO: case PRU_SLOWTIMO: case PRU_PROTORCV: @@ -365,3 +538,49 @@ sco_input(void *arg, struct mbuf *m) sbappendrecord(&so->so_rcv, m); sorwakeup(so); } + +PR_WRAP_USRREQS(sco) + +#define sco_attach sco_attach_wrapper +#define sco_detach sco_detach_wrapper +#define sco_accept sco_accept_wrapper +#define sco_bind sco_bind_wrapper +#define sco_listen sco_listen_wrapper +#define sco_connect sco_connect_wrapper +#define sco_connect2 sco_connect2_wrapper +#define sco_disconnect sco_disconnect_wrapper +#define sco_shutdown sco_shutdown_wrapper +#define sco_abort sco_abort_wrapper +#define sco_ioctl sco_ioctl_wrapper +#define sco_stat sco_stat_wrapper +#define sco_peeraddr sco_peeraddr_wrapper +#define sco_sockaddr sco_sockaddr_wrapper +#define sco_rcvd sco_rcvd_wrapper +#define sco_recvoob sco_recvoob_wrapper +#define sco_send sco_send_wrapper +#define sco_sendoob sco_sendoob_wrapper +#define sco_purgeif sco_purgeif_wrapper +#define sco_usrreq sco_usrreq_wrapper + +const struct pr_usrreqs sco_usrreqs = { + .pr_attach = sco_attach, + .pr_detach = sco_detach, + .pr_accept = sco_accept, + .pr_bind = sco_bind, + .pr_listen = sco_listen, + .pr_connect = sco_connect, + .pr_connect2 = sco_connect2, + .pr_disconnect = sco_disconnect, + .pr_shutdown = sco_shutdown, + .pr_abort = sco_abort, + .pr_ioctl = sco_ioctl, + .pr_stat = sco_stat, + .pr_peeraddr = sco_peeraddr, + .pr_sockaddr = sco_sockaddr, + .pr_rcvd = sco_rcvd, + .pr_recvoob = sco_recvoob, + .pr_send = sco_send, + .pr_sendoob = sco_sendoob, + .pr_purgeif = sco_purgeif, + .pr_generic = sco_usrreq, +};