[BACK]Return to natm.c CVS log [TXT][DIR] Up to [local] / sys / netnatm

Annotation of sys/netnatm/natm.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: natm.c,v 1.7 2006/03/04 22:40:16 brad Exp $   */
                      2:
                      3: /*
                      4:  *
                      5:  * Copyright (c) 1996 Charles D. Cranor and Washington University.
                      6:  * All rights reserved.
                      7:  *
                      8:  * Redistribution and use in source and binary forms, with or without
                      9:  * modification, are permitted provided that the following conditions
                     10:  * are met:
                     11:  * 1. Redistributions of source code must retain the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer.
                     13:  * 2. Redistributions in binary form must reproduce the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer in the
                     15:  *    documentation and/or other materials provided with the distribution.
                     16:  * 3. All advertising materials mentioning features or use of this software
                     17:  *    must display the following acknowledgement:
                     18:  *      This product includes software developed by Charles D. Cranor and
                     19:  *      Washington University.
                     20:  * 4. The name of the author may not be used to endorse or promote products
                     21:  *    derived from this software without specific prior written permission.
                     22:  *
                     23:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     24:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     25:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     26:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     27:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     28:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     29:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     30:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     31:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     32:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     33:  */
                     34:
                     35: /*
                     36:  * natm.c: native mode ATM access (both aal0 and aal5).
                     37:  */
                     38:
                     39: #include <sys/param.h>
                     40: #include <sys/systm.h>
                     41: #include <sys/kernel.h>
                     42: #include <sys/domain.h>
                     43: #include <sys/ioctl.h>
                     44: #include <sys/proc.h>
                     45: #include <sys/protosw.h>
                     46: #include <sys/mbuf.h>
                     47: #include <sys/socket.h>
                     48: #include <sys/socketvar.h>
                     49:
                     50: #include <net/if.h>
                     51: #include <net/if_atm.h>
                     52: #include <net/netisr.h>
                     53: #include <net/radix.h>
                     54: #include <net/route.h>
                     55:
                     56: #include <netinet/in.h>
                     57:
                     58: #include <netnatm/natm.h>
                     59:
                     60: u_long natm5_sendspace = 16*1024;
                     61: u_long natm5_recvspace = 16*1024;
                     62:
                     63: u_long natm0_sendspace = 16*1024;
                     64: u_long natm0_recvspace = 16*1024;
                     65:
                     66: /*
                     67:  * user requests
                     68:  */
                     69:
                     70: #if defined(__NetBSD__)
                     71: int natm_usrreq(so, req, m, nam, control)
                     72: #elif defined(__OpenBSD__) || defined(__FreeBSD__)
                     73: int natm_usrreq(so, req, m, nam, control)
                     74: #endif
                     75: struct socket *so;
                     76: int req;
                     77: struct mbuf *m, *nam, *control;
                     78: #if defined(__NetBSD__)
                     79: struct proc *p;
                     80: #endif
                     81: {
                     82:   int error = 0, s, s2;
                     83:   struct natmpcb *npcb;
                     84:   struct sockaddr_natm *snatm;
                     85:   struct atm_pseudoioctl api;
                     86:   struct atm_pseudohdr *aph;
                     87:   struct atm_rawioctl ario;
                     88:   struct ifnet *ifp;
                     89:   int proto = so->so_proto->pr_protocol;
                     90:
                     91:   s = SPLSOFTNET();
                     92:
                     93:   npcb = (struct natmpcb *) so->so_pcb;
                     94:
                     95:   if (npcb == NULL && req != PRU_ATTACH) {
                     96:     error = EINVAL;
                     97:     goto done;
                     98:   }
                     99:
                    100:
                    101:   switch (req) {
                    102:     case PRU_ATTACH:                   /* attach protocol to up */
                    103:
                    104:       if (npcb) {
                    105:        error = EISCONN;
                    106:        break;
                    107:       }
                    108:
                    109:       if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
                    110:        if (proto == PROTO_NATMAAL5)
                    111:           error = soreserve(so, natm5_sendspace, natm5_recvspace);
                    112:        else
                    113:           error = soreserve(so, natm0_sendspace, natm0_recvspace);
                    114:         if (error)
                    115:           break;
                    116:       }
                    117:
                    118:       so->so_pcb = (caddr_t) (npcb = npcb_alloc(M_WAITOK));
                    119:       npcb->npcb_socket = so;
                    120:
                    121:       break;
                    122:
                    123:     case PRU_DETACH:                   /* detach protocol from up */
                    124:
                    125:       /*
                    126:        * we turn on 'drain' *before* we sofree.
                    127:        */
                    128:
                    129:       npcb_free(npcb, NPCB_DESTROY);   /* drain */
                    130:       so->so_pcb = NULL;
                    131:       sofree(so);
                    132:
                    133:       break;
                    134:
                    135:     case PRU_CONNECT:                  /* establish connection to peer */
                    136:
                    137:       /*
                    138:        * validate nam and npcb
                    139:        */
                    140:
                    141:       if (nam->m_len != sizeof(*snatm)) {
                    142:         error = EINVAL;
                    143:        break;
                    144:       }
                    145:       snatm = mtod(nam, struct sockaddr_natm *);
                    146:       if (snatm->snatm_len != sizeof(*snatm) ||
                    147:                (npcb->npcb_flags & NPCB_FREE) == 0) {
                    148:        error = EINVAL;
                    149:        break;
                    150:       }
                    151:       if (snatm->snatm_family != AF_NATM) {
                    152:        error = EAFNOSUPPORT;
                    153:        break;
                    154:       }
                    155:
                    156:       snatm->snatm_if[IFNAMSIZ-1] = '\0';  /* XXX ensure null termination
                    157:                                                since ifunit() uses strcmp */
                    158:
                    159:       /*
                    160:        * convert interface string to ifp, validate.
                    161:        */
                    162:
                    163:       ifp = ifunit(snatm->snatm_if);
                    164:       if (ifp == NULL || (ifp->if_flags & IFF_RUNNING) == 0) {
                    165:        error = ENXIO;
                    166:        break;
                    167:       }
                    168:       if (ifp->if_output != atm_output) {
                    169:        error = EAFNOSUPPORT;
                    170:        break;
                    171:       }
                    172:
                    173:
                    174:       /*
                    175:        * register us with the NATM PCB layer
                    176:        */
                    177:
                    178:       if (npcb_add(npcb, ifp, snatm->snatm_vci, snatm->snatm_vpi) != npcb) {
                    179:         error = EADDRINUSE;
                    180:         break;
                    181:       }
                    182:
                    183:       /*
                    184:        * enable rx
                    185:        */
                    186:
                    187:       ATM_PH_FLAGS(&api.aph) = (proto == PROTO_NATMAAL5) ? ATM_PH_AAL5 : 0;
                    188:       ATM_PH_VPI(&api.aph) = npcb->npcb_vpi;
                    189:       ATM_PH_SETVCI(&api.aph, npcb->npcb_vci);
                    190:       api.rxhand = npcb;
                    191:       s2 = splnet();
                    192:       if (ifp->if_ioctl == NULL ||
                    193:          ifp->if_ioctl(ifp, SIOCATMENA, (caddr_t) &api) != 0) {
                    194:        splx(s2);
                    195:        npcb_free(npcb, NPCB_REMOVE);
                    196:         error = EIO;
                    197:        break;
                    198:       }
                    199:       splx(s2);
                    200:
                    201:       soisconnected(so);
                    202:
                    203:       break;
                    204:
                    205:     case PRU_DISCONNECT:               /* disconnect from peer */
                    206:
                    207:       if ((npcb->npcb_flags & NPCB_CONNECTED) == 0) {
                    208:         printf("natm: disconnected check\n");
                    209:         error = EIO;
                    210:        break;
                    211:       }
                    212:       ifp = npcb->npcb_ifp;
                    213:
                    214:       /*
                    215:        * disable rx
                    216:        */
                    217:
                    218:       ATM_PH_FLAGS(&api.aph) = ATM_PH_AAL5;
                    219:       ATM_PH_VPI(&api.aph) = npcb->npcb_vpi;
                    220:       ATM_PH_SETVCI(&api.aph, npcb->npcb_vci);
                    221:       api.rxhand = npcb;
                    222:       s2 = splnet();
                    223:       if (ifp->if_ioctl != NULL)
                    224:          ifp->if_ioctl(ifp, SIOCATMDIS, (caddr_t) &api);
                    225:       splx(s);
                    226:
                    227:       npcb_free(npcb, NPCB_REMOVE);
                    228:       soisdisconnected(so);
                    229:
                    230:       break;
                    231:
                    232:     case PRU_SHUTDOWN:                 /* won't send any more data */
                    233:       socantsendmore(so);
                    234:       break;
                    235:
                    236:     case PRU_SEND:                     /* send this data */
                    237:       if (control && control->m_len) {
                    238:        m_freem(control);
                    239:        m_freem(m);
                    240:        error = EINVAL;
                    241:        break;
                    242:       }
                    243:
                    244:       /*
                    245:        * send the data.   we must put an atm_pseudohdr on first
                    246:        */
                    247:
                    248:       M_PREPEND(m, sizeof(*aph), M_WAITOK);
                    249:       aph = mtod(m, struct atm_pseudohdr *);
                    250:       ATM_PH_VPI(aph) = npcb->npcb_vpi;
                    251:       ATM_PH_SETVCI(aph, npcb->npcb_vci);
                    252:       ATM_PH_FLAGS(aph) = (proto == PROTO_NATMAAL5) ? ATM_PH_AAL5 : 0;
                    253:
                    254:       error = atm_output(npcb->npcb_ifp, m, NULL, NULL);
                    255:
                    256:       break;
                    257:
                    258:     case PRU_SENSE:                    /* return status into m */
                    259:       /* return zero? */
                    260:       break;
                    261:
                    262:     case PRU_PEERADDR:                 /* fetch peer's address */
                    263:       snatm = mtod(nam, struct sockaddr_natm *);
                    264:       bzero(snatm, sizeof(*snatm));
                    265:       nam->m_len = snatm->snatm_len = sizeof(*snatm);
                    266:       snatm->snatm_family = AF_NATM;
                    267: #if defined(__NetBSD__) || defined(__OpenBSD__)
                    268:       bcopy(npcb->npcb_ifp->if_xname, snatm->snatm_if, sizeof(snatm->snatm_if));
                    269: #elif defined(__FreeBSD__)
                    270:       sprintf(snatm->snatm_if, "%s%d", npcb->npcb_ifp->if_name,
                    271:        npcb->npcb_ifp->if_unit);
                    272: #endif
                    273:       snatm->snatm_vci = npcb->npcb_vci;
                    274:       snatm->snatm_vpi = npcb->npcb_vpi;
                    275:       break;
                    276:
                    277:     case PRU_CONTROL:                  /* control operations on protocol */
                    278:       /*
                    279:        * raw atm ioctl.   comes in as a SIOCRAWATM.   we convert it to
                    280:        * SIOCXRAWATM and pass it to the driver.
                    281:        */
                    282:       if ((u_long)m == SIOCRAWATM) {
                    283:         if (npcb->npcb_ifp == NULL) {
                    284:           error = ENOTCONN;
                    285:           break;
                    286:         }
                    287:         ario.npcb = npcb;
                    288:         ario.rawvalue = *((int *)nam);
                    289:         error = npcb->npcb_ifp->if_ioctl(npcb->npcb_ifp,
                    290:                                SIOCXRAWATM, (caddr_t) &ario);
                    291:        if (!error) {
                    292:           if (ario.rawvalue)
                    293:            npcb->npcb_flags |= NPCB_RAW;
                    294:          else
                    295:            npcb->npcb_flags &= ~(NPCB_RAW);
                    296:        }
                    297:
                    298:         break;
                    299:       }
                    300:
                    301:       error = EOPNOTSUPP;
                    302:       break;
                    303:
                    304:     case PRU_BIND:                     /* bind socket to address */
                    305:     case PRU_LISTEN:                   /* listen for connection */
                    306:     case PRU_ACCEPT:                   /* accept connection from peer */
                    307:     case PRU_CONNECT2:                 /* connect two sockets */
                    308:     case PRU_ABORT:                    /* abort (fast DISCONNECT, DETATCH) */
                    309:                                        /* (only happens if LISTEN socket) */
                    310:     case PRU_RCVD:                     /* have taken data; more room now */
                    311:     case PRU_FASTTIMO:                 /* 200ms timeout */
                    312:     case PRU_SLOWTIMO:                 /* 500ms timeout */
                    313:     case PRU_RCVOOB:                   /* retrieve out of band data */
                    314:     case PRU_SENDOOB:                  /* send out of band data */
                    315:     case PRU_PROTORCV:                 /* receive from below */
                    316:     case PRU_PROTOSEND:                        /* send to below */
                    317:     case PRU_SOCKADDR:                 /* fetch socket's address */
                    318: #ifdef DIAGNOSTIC
                    319:       printf("natm: PRU #%d unsupported\n", req);
                    320: #endif
                    321:       error = EOPNOTSUPP;
                    322:       break;
                    323:
                    324:     default: panic("natm usrreq");
                    325:   }
                    326:
                    327: done:
                    328:   splx(s);
                    329:   return(error);
                    330: }
                    331:
                    332: /*
                    333:  * natmintr: splsoftnet interrupt
                    334:  *
                    335:  * note: we expect a socket pointer in rcvif rather than an interface
                    336:  * pointer.    we can get the interface pointer from the so's PCB if
                    337:  * we really need it.
                    338:  */
                    339:
                    340: void
                    341: natmintr()
                    342:
                    343: {
                    344:   int s;
                    345:   struct mbuf *m;
                    346:   struct socket *so;
                    347:   struct natmpcb *npcb;
                    348:
                    349: next:
                    350:   s = splnet();
                    351:   IF_DEQUEUE(&natmintrq, m);
                    352:   splx(s);
                    353:   if (m == NULL)
                    354:     return;
                    355:
                    356: #ifdef DIAGNOSTIC
                    357:   if ((m->m_flags & M_PKTHDR) == 0)
                    358:     panic("natmintr no HDR");
                    359: #endif
                    360:
                    361:   npcb = (struct natmpcb *) m->m_pkthdr.rcvif; /* XXX: overloaded */
                    362:   so = npcb->npcb_socket;
                    363:
                    364:   s = splnet();                        /* could have atm devs @ different levels */
                    365:   npcb->npcb_inq--;
                    366:   splx(s);
                    367:
                    368:   if (npcb->npcb_flags & NPCB_DRAIN) {
                    369:     m_freem(m);
                    370:     if (npcb->npcb_inq == 0)
                    371:       FREE(npcb, M_PCB);                       /* done! */
                    372:     goto next;
                    373:   }
                    374:
                    375:   if (npcb->npcb_flags & NPCB_FREE) {
                    376:     m_freem(m);                                        /* drop */
                    377:     goto next;
                    378:   }
                    379:
                    380: #ifdef NEED_TO_RESTORE_IFP
                    381:   m->m_pkthdr.rcvif = npcb->npcb_ifp;
                    382: #else
                    383: #ifdef DIAGNOSTIC
                    384: m->m_pkthdr.rcvif = NULL;      /* null it out to be safe */
                    385: #endif
                    386: #endif
                    387:
                    388:   if (sbspace(&so->so_rcv) > m->m_pkthdr.len ||
                    389:      ((npcb->npcb_flags & NPCB_RAW) != 0 && so->so_rcv.sb_cc < NPCB_RAWCC) ) {
                    390: #ifdef NATM_STAT
                    391:     natm_sookcnt++;
                    392:     natm_sookbytes += m->m_pkthdr.len;
                    393: #endif
                    394:     sbappendrecord(&so->so_rcv, m);
                    395:     sorwakeup(so);
                    396:   } else {
                    397: #ifdef NATM_STAT
                    398:     natm_sodropcnt++;
                    399:     natm_sodropbytes += m->m_pkthdr.len;
                    400: #endif
                    401:     m_freem(m);
                    402:   }
                    403:
                    404:   goto next;
                    405: }
                    406:
                    407: #if defined(__FreeBSD__)
                    408: NETISR_SET(NETISR_NATM, natmintr);
                    409: #endif
                    410:
                    411:
                    412: /*
                    413:  * natm0_sysctl: not used, but here in case we want to add something
                    414:  * later...
                    415:  */
                    416:
                    417: int natm0_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
                    418:
                    419: int *name;
                    420: u_int namelen;
                    421: void *oldp;
                    422: size_t *oldlenp;
                    423: void *newp;
                    424: size_t newlen;
                    425:
                    426: {
                    427:   /* All sysctl names at this level are terminal. */
                    428:   if (namelen != 1)
                    429:     return (ENOTDIR);
                    430:   return (ENOPROTOOPT);
                    431: }
                    432:
                    433: /*
                    434:  * natm5_sysctl: not used, but here in case we want to add something
                    435:  * later...
                    436:  */
                    437:
                    438: int natm5_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
                    439:
                    440: int *name;
                    441: u_int namelen;
                    442: void *oldp;
                    443: size_t *oldlenp;
                    444: void *newp;
                    445: size_t newlen;
                    446:
                    447: {
                    448:   /* All sysctl names at this level are terminal. */
                    449:   if (namelen != 1)
                    450:     return (ENOTDIR);
                    451:   return (ENOPROTOOPT);
                    452: }

CVSweb