[BACK]Return to rfcomm_socket.c CVS log [TXT][DIR] Up to [local] / sys / netbt

Annotation of sys/netbt/rfcomm_socket.c, Revision 1.1.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