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

Annotation of sys/netbt/l2cap_socket.c, Revision 1.1.1.1

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

CVSweb