[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     ! 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