Annotation of sys/netbt/rfcomm_socket.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: rfcomm_socket.c,v 1.1 2007/06/01 02:46:12 uwe Exp $ */
! 2: /* $NetBSD: rfcomm_socket.c,v 1.7 2007/04/21 06:15:23 plunky Exp $ */
! 3:
! 4: /*-
! 5: * Copyright (c) 2006 Itronix Inc.
! 6: * All rights reserved.
! 7: *
! 8: * Written by Iain Hibbert for Itronix Inc.
! 9: *
! 10: * Redistribution and use in source and binary forms, with or without
! 11: * modification, are permitted provided that the following conditions
! 12: * are met:
! 13: * 1. Redistributions of source code must retain the above copyright
! 14: * notice, this list of conditions and the following disclaimer.
! 15: * 2. Redistributions in binary form must reproduce the above copyright
! 16: * notice, this list of conditions and the following disclaimer in the
! 17: * documentation and/or other materials provided with the distribution.
! 18: * 3. The name of Itronix Inc. may not be used to endorse
! 19: * or promote products derived from this software without specific
! 20: * prior written permission.
! 21: *
! 22: * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
! 23: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
! 24: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
! 25: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
! 26: * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
! 27: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
! 28: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
! 29: * ON ANY THEORY OF LIABILITY, WHETHER IN
! 30: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
! 31: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
! 32: * POSSIBILITY OF SUCH DAMAGE.
! 33: */
! 34:
! 35: #include <sys/cdefs.h>
! 36:
! 37: /* load symbolic names */
! 38: #ifdef BLUETOOTH_DEBUG
! 39: #define PRUREQUESTS
! 40: #define PRCOREQUESTS
! 41: #endif
! 42:
! 43: #include <sys/param.h>
! 44: #include <sys/domain.h>
! 45: #include <sys/kernel.h>
! 46: #include <sys/mbuf.h>
! 47: #include <sys/proc.h>
! 48: #include <sys/protosw.h>
! 49: #include <sys/socket.h>
! 50: #include <sys/socketvar.h>
! 51: #include <sys/systm.h>
! 52:
! 53: #include <netbt/bluetooth.h>
! 54: #include <netbt/hci.h> /* XXX for EPASSTHROUGH */
! 55: #include <netbt/rfcomm.h>
! 56:
! 57: /****************************************************************************
! 58: *
! 59: * RFCOMM SOCK_STREAM Sockets - serial line emulation
! 60: *
! 61: */
! 62:
! 63: static void rfcomm_connecting(void *);
! 64: static void rfcomm_connected(void *);
! 65: static void rfcomm_disconnected(void *, int);
! 66: static void *rfcomm_newconn(void *, struct sockaddr_bt *, struct sockaddr_bt *);
! 67: static void rfcomm_complete(void *, int);
! 68: static void rfcomm_linkmode(void *, int);
! 69: static void rfcomm_input(void *, struct mbuf *);
! 70:
! 71: static const struct btproto rfcomm_proto = {
! 72: rfcomm_connecting,
! 73: rfcomm_connected,
! 74: rfcomm_disconnected,
! 75: rfcomm_newconn,
! 76: rfcomm_complete,
! 77: rfcomm_linkmode,
! 78: rfcomm_input,
! 79: };
! 80:
! 81: /* sysctl variables */
! 82: int rfcomm_sendspace = 4096;
! 83: int rfcomm_recvspace = 4096;
! 84:
! 85: /*
! 86: * User Request.
! 87: * up is socket
! 88: * m is either
! 89: * optional mbuf chain containing message
! 90: * ioctl command (PRU_CONTROL)
! 91: * nam is either
! 92: * optional mbuf chain containing an address
! 93: * ioctl data (PRU_CONTROL)
! 94: * optionally protocol number (PRU_ATTACH)
! 95: * message flags (PRU_RCVD)
! 96: * ctl is either
! 97: * optional mbuf chain containing socket options
! 98: * optional interface pointer (PRU_CONTROL, PRU_PURGEIF)
! 99: * l is pointer to process requesting action (if any)
! 100: *
! 101: * we are responsible for disposing of m and ctl if
! 102: * they are mbuf chains
! 103: */
! 104: int
! 105: rfcomm_usrreq(struct socket *up, int req, struct mbuf *m,
! 106: struct mbuf *nam, struct mbuf *ctl)
! 107: {
! 108: struct rfcomm_dlc *pcb = up->so_pcb;
! 109: struct sockaddr_bt *sa;
! 110: struct mbuf *m0;
! 111: int err = 0;
! 112:
! 113: #ifdef notyet /* XXX */
! 114: DPRINTFN(2, "%s\n", prurequests[req]);
! 115: #endif
! 116:
! 117: switch (req) {
! 118: case PRU_CONTROL:
! 119: return EPASSTHROUGH;
! 120:
! 121: #ifdef notyet /* XXX */
! 122: case PRU_PURGEIF:
! 123: return EOPNOTSUPP;
! 124: #endif
! 125:
! 126: case PRU_ATTACH:
! 127: if (pcb != NULL)
! 128: return EINVAL;
! 129:
! 130: /*
! 131: * Since we have nothing to add, we attach the DLC
! 132: * structure directly to our PCB pointer.
! 133: */
! 134: err = rfcomm_attach((struct rfcomm_dlc **)&up->so_pcb,
! 135: &rfcomm_proto, up);
! 136: if (err)
! 137: return err;
! 138:
! 139: err = soreserve(up, rfcomm_sendspace, rfcomm_recvspace);
! 140: if (err)
! 141: return err;
! 142:
! 143: err = rfcomm_rcvd(up->so_pcb, sbspace(&up->so_rcv));
! 144: if (err)
! 145: return err;
! 146:
! 147: return 0;
! 148: }
! 149:
! 150: if (pcb == NULL) {
! 151: err = EINVAL;
! 152: goto release;
! 153: }
! 154:
! 155: switch(req) {
! 156: case PRU_DISCONNECT:
! 157: soisdisconnecting(up);
! 158: return rfcomm_disconnect(pcb, up->so_linger);
! 159:
! 160: case PRU_ABORT:
! 161: rfcomm_disconnect(pcb, 0);
! 162: soisdisconnected(up);
! 163: /* fall through to */
! 164: case PRU_DETACH:
! 165: return rfcomm_detach((struct rfcomm_dlc **)&up->so_pcb);
! 166:
! 167: case PRU_BIND:
! 168: KASSERT(nam != NULL);
! 169: sa = mtod(nam, struct sockaddr_bt *);
! 170:
! 171: if (sa->bt_len != sizeof(struct sockaddr_bt))
! 172: return EINVAL;
! 173:
! 174: if (sa->bt_family != AF_BLUETOOTH)
! 175: return EAFNOSUPPORT;
! 176:
! 177: return rfcomm_bind(pcb, sa);
! 178:
! 179: case PRU_CONNECT:
! 180: KASSERT(nam != NULL);
! 181: sa = mtod(nam, struct sockaddr_bt *);
! 182:
! 183: if (sa->bt_len != sizeof(struct sockaddr_bt))
! 184: return EINVAL;
! 185:
! 186: if (sa->bt_family != AF_BLUETOOTH)
! 187: return EAFNOSUPPORT;
! 188:
! 189: soisconnecting(up);
! 190: return rfcomm_connect(pcb, sa);
! 191:
! 192: case PRU_PEERADDR:
! 193: KASSERT(nam != NULL);
! 194: sa = mtod(nam, struct sockaddr_bt *);
! 195: nam->m_len = sizeof(struct sockaddr_bt);
! 196: return rfcomm_peeraddr(pcb, sa);
! 197:
! 198: case PRU_SOCKADDR:
! 199: KASSERT(nam != NULL);
! 200: sa = mtod(nam, struct sockaddr_bt *);
! 201: nam->m_len = sizeof(struct sockaddr_bt);
! 202: return rfcomm_sockaddr(pcb, sa);
! 203:
! 204: case PRU_SHUTDOWN:
! 205: socantsendmore(up);
! 206: break;
! 207:
! 208: case PRU_SEND:
! 209: KASSERT(m != NULL);
! 210:
! 211: if (ctl) /* no use for that */
! 212: m_freem(ctl);
! 213:
! 214: m0 = m_copym(m, 0, M_COPYALL, M_DONTWAIT);
! 215: if (m0 == NULL)
! 216: return ENOMEM;
! 217:
! 218: sbappendstream(&up->so_snd, m);
! 219:
! 220: return rfcomm_send(pcb, m0);
! 221:
! 222: case PRU_SENSE:
! 223: return 0; /* (no release) */
! 224:
! 225: case PRU_RCVD:
! 226: return rfcomm_rcvd(pcb, sbspace(&up->so_rcv));
! 227:
! 228: case PRU_RCVOOB:
! 229: return EOPNOTSUPP; /* (no release) */
! 230:
! 231: case PRU_LISTEN:
! 232: return rfcomm_listen(pcb);
! 233:
! 234: case PRU_ACCEPT:
! 235: KASSERT(nam != NULL);
! 236: sa = mtod(nam, struct sockaddr_bt *);
! 237: nam->m_len = sizeof(struct sockaddr_bt);
! 238: return rfcomm_peeraddr(pcb, sa);
! 239:
! 240: case PRU_CONNECT2:
! 241: case PRU_SENDOOB:
! 242: case PRU_FASTTIMO:
! 243: case PRU_SLOWTIMO:
! 244: case PRU_PROTORCV:
! 245: case PRU_PROTOSEND:
! 246: err = EOPNOTSUPP;
! 247: break;
! 248:
! 249: default:
! 250: UNKNOWN(req);
! 251: err = EOPNOTSUPP;
! 252: break;
! 253: }
! 254:
! 255: release:
! 256: if (m) m_freem(m);
! 257: if (ctl) m_freem(ctl);
! 258: return err;
! 259: }
! 260:
! 261: /*
! 262: * rfcomm_ctloutput(request, socket, level, optname, opt)
! 263: *
! 264: */
! 265: int
! 266: rfcomm_ctloutput(int req, struct socket *so, int level,
! 267: int optname, struct mbuf **opt)
! 268: {
! 269: struct rfcomm_dlc *pcb = so->so_pcb;
! 270: struct mbuf *m;
! 271: int err = 0;
! 272:
! 273: #ifdef notyet /* XXX */
! 274: DPRINTFN(2, "%s\n", prcorequests[req]);
! 275: #endif
! 276:
! 277: if (pcb == NULL)
! 278: return EINVAL;
! 279:
! 280: if (level != BTPROTO_RFCOMM)
! 281: return ENOPROTOOPT;
! 282:
! 283: switch(req) {
! 284: case PRCO_GETOPT:
! 285: m = m_get(M_WAIT, MT_SOOPTS);
! 286: m->m_len = rfcomm_getopt(pcb, optname, mtod(m, void *));
! 287: if (m->m_len == 0) {
! 288: m_freem(m);
! 289: m = NULL;
! 290: err = ENOPROTOOPT;
! 291: }
! 292: *opt = m;
! 293: break;
! 294:
! 295: case PRCO_SETOPT:
! 296: m = *opt;
! 297: KASSERT(m != NULL);
! 298: err = rfcomm_setopt(pcb, optname, mtod(m, void *));
! 299: m_freem(m);
! 300: break;
! 301:
! 302: default:
! 303: err = ENOPROTOOPT;
! 304: break;
! 305: }
! 306:
! 307: return err;
! 308: }
! 309:
! 310: /**********************************************************************
! 311: *
! 312: * RFCOMM callbacks
! 313: */
! 314:
! 315: static void
! 316: rfcomm_connecting(void *arg)
! 317: {
! 318: /* struct socket *so = arg; */
! 319:
! 320: KASSERT(arg != NULL);
! 321: DPRINTF("Connecting\n");
! 322: }
! 323:
! 324: static void
! 325: rfcomm_connected(void *arg)
! 326: {
! 327: struct socket *so = arg;
! 328:
! 329: KASSERT(so != NULL);
! 330: DPRINTF("Connected\n");
! 331: soisconnected(so);
! 332: }
! 333:
! 334: static void
! 335: rfcomm_disconnected(void *arg, int err)
! 336: {
! 337: struct socket *so = arg;
! 338:
! 339: KASSERT(so != NULL);
! 340: DPRINTF("Disconnected\n");
! 341:
! 342: so->so_error = err;
! 343: soisdisconnected(so);
! 344: }
! 345:
! 346: static void *
! 347: rfcomm_newconn(void *arg, struct sockaddr_bt *laddr,
! 348: struct sockaddr_bt *raddr)
! 349: {
! 350: struct socket *so = arg;
! 351:
! 352: DPRINTF("New Connection\n");
! 353: so = sonewconn(so, 0);
! 354: if (so == NULL)
! 355: return NULL;
! 356:
! 357: soisconnecting(so);
! 358:
! 359: return so->so_pcb;
! 360: }
! 361:
! 362: /*
! 363: * rfcomm_complete(rfcomm_dlc, length)
! 364: *
! 365: * length bytes are sent and may be removed from socket buffer
! 366: */
! 367: static void
! 368: rfcomm_complete(void *arg, int length)
! 369: {
! 370: struct socket *so = arg;
! 371:
! 372: sbdrop(&so->so_snd, length);
! 373: sowwakeup(so);
! 374: }
! 375:
! 376: /*
! 377: * rfcomm_linkmode(rfcomm_dlc, new)
! 378: *
! 379: * link mode change notification.
! 380: */
! 381: static void
! 382: rfcomm_linkmode(void *arg, int new)
! 383: {
! 384: struct socket *so = arg;
! 385: int mode;
! 386:
! 387: DPRINTF("auth %s, encrypt %s, secure %s\n",
! 388: (new & RFCOMM_LM_AUTH ? "on" : "off"),
! 389: (new & RFCOMM_LM_ENCRYPT ? "on" : "off"),
! 390: (new & RFCOMM_LM_SECURE ? "on" : "off"));
! 391:
! 392: (void)rfcomm_getopt(so->so_pcb, SO_RFCOMM_LM, &mode);
! 393: if (((mode & RFCOMM_LM_AUTH) && !(new & RFCOMM_LM_AUTH))
! 394: || ((mode & RFCOMM_LM_ENCRYPT) && !(new & RFCOMM_LM_ENCRYPT))
! 395: || ((mode & RFCOMM_LM_SECURE) && !(new & RFCOMM_LM_SECURE)))
! 396: rfcomm_disconnect(so->so_pcb, 0);
! 397: }
! 398:
! 399: /*
! 400: * rfcomm_input(rfcomm_dlc, mbuf)
! 401: */
! 402: static void
! 403: rfcomm_input(void *arg, struct mbuf *m)
! 404: {
! 405: struct socket *so = arg;
! 406:
! 407: KASSERT(so != NULL);
! 408:
! 409: if (m->m_pkthdr.len > sbspace(&so->so_rcv)) {
! 410: printf("%s: %d bytes dropped (socket buffer full)\n",
! 411: __func__, m->m_pkthdr.len);
! 412: m_freem(m);
! 413: return;
! 414: }
! 415:
! 416: DPRINTFN(10, "received %d bytes\n", m->m_pkthdr.len);
! 417:
! 418: sbappendstream(&so->so_rcv, m);
! 419: sorwakeup(so);
! 420: }
CVSweb