Annotation of XNU/bsd/net/if_atmsubr.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * The contents of this file constitute Original Code as defined in and
        !             7:  * are subject to the Apple Public Source License Version 1.1 (the
        !             8:  * "License").  You may not use this file except in compliance with the
        !             9:  * License.  Please obtain a copy of the License at
        !            10:  * http://www.apple.com/publicsource and read it before using this file.
        !            11:  * 
        !            12:  * This Original Code and all software distributed under the License are
        !            13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            17:  * License for the specific language governing rights and limitations
        !            18:  * under the License.
        !            19:  * 
        !            20:  * @APPLE_LICENSE_HEADER_END@
        !            21:  */
        !            22: /*      $NetBSD: if_atmsubr.c,v 1.10 1997/03/11 23:19:51 chuck Exp $       */
        !            23: 
        !            24: /*
        !            25:  *
        !            26:  * Copyright (c) 1996 Charles D. Cranor and Washington University.
        !            27:  * All rights reserved.
        !            28:  *
        !            29:  * Redistribution and use in source and binary forms, with or without
        !            30:  * modification, are permitted provided that the following conditions
        !            31:  * are met:
        !            32:  * 1. Redistributions of source code must retain the above copyright
        !            33:  *    notice, this list of conditions and the following disclaimer.
        !            34:  * 2. Redistributions in binary form must reproduce the above copyright
        !            35:  *    notice, this list of conditions and the following disclaimer in the
        !            36:  *    documentation and/or other materials provided with the distribution.
        !            37:  * 3. All advertising materials mentioning features or use of this software
        !            38:  *    must display the following acknowledgement:
        !            39:  *      This product includes software developed by Charles D. Cranor and 
        !            40:  *     Washington University.
        !            41:  * 4. The name of the author may not be used to endorse or promote products
        !            42:  *    derived from this software without specific prior written permission.
        !            43:  *
        !            44:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            45:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
        !            46:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
        !            47:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
        !            48:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
        !            49:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
        !            50:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
        !            51:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        !            52:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
        !            53:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        !            54:  */
        !            55: 
        !            56: /*
        !            57:  * if_atmsubr.c
        !            58:  */
        !            59: 
        !            60: #include "opt_inet.h"
        !            61: #include "opt_natm.h"
        !            62: 
        !            63: #include <sys/param.h>
        !            64: #include <sys/systm.h>
        !            65: #include <sys/mbuf.h>
        !            66: #include <sys/socket.h>
        !            67: #include <sys/sockio.h>
        !            68: #include <sys/malloc.h>
        !            69: #include <sys/errno.h>
        !            70: 
        !            71: 
        !            72: #include <net/if.h>
        !            73: #include <net/netisr.h>
        !            74: #include <net/route.h>
        !            75: #include <net/if_dl.h>
        !            76: #include <net/if_types.h>
        !            77: #include <net/if_atm.h>
        !            78: 
        !            79: #include <netinet/in.h>
        !            80: #include <netinet/if_atm.h>
        !            81: #include <netinet/if_ether.h> /* XXX: for ETHERTYPE_* */
        !            82: #if defined(INET) || defined(INET6)
        !            83: #include <netinet/in_var.h>
        !            84: #endif
        !            85: #if NATM
        !            86: #include <netnatm/natm.h>
        !            87: #endif
        !            88: 
        !            89: #ifndef ETHERTYPE_IPV6
        !            90: #define ETHERTYPE_IPV6 0x86dd
        !            91: #endif
        !            92: 
        !            93: #define senderr(e) { error = (e); goto bad;}
        !            94: 
        !            95: /*
        !            96:  * atm_output: ATM output routine
        !            97:  *   inputs:
        !            98:  *     "ifp" = ATM interface to output to
        !            99:  *     "m0" = the packet to output
        !           100:  *     "dst" = the sockaddr to send to (either IP addr, or raw VPI/VCI)
        !           101:  *     "rt0" = the route to use
        !           102:  *   returns: error code   [0 == ok]
        !           103:  *
        !           104:  *   note: special semantic: if (dst == NULL) then we assume "m" already
        !           105:  *             has an atm_pseudohdr on it and just send it directly.
        !           106:  *             [for native mode ATM output]   if dst is null, then
        !           107:  *             rt0 must also be NULL.
        !           108:  */
        !           109: 
        !           110: int
        !           111: atm_output(ifp, m0, dst, rt0)
        !           112:        register struct ifnet *ifp;
        !           113:        struct mbuf *m0;
        !           114:        struct sockaddr *dst;
        !           115:        struct rtentry *rt0;
        !           116: {
        !           117:        u_int16_t etype = 0;                    /* if using LLC/SNAP */
        !           118:        int s, error = 0, sz;
        !           119:        struct atm_pseudohdr atmdst, *ad;
        !           120:        register struct mbuf *m = m0;
        !           121:        register struct rtentry *rt;
        !           122:        struct atmllc *atmllc;
        !           123:        struct atmllc *llc_hdr = NULL;
        !           124:        u_int32_t atm_flags;
        !           125: 
        !           126:        if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
        !           127:                senderr(ENETDOWN);
        !           128: 
        !           129:        /*
        !           130:         * check route
        !           131:         */
        !           132:        if ((rt = rt0) != NULL) {
        !           133: 
        !           134:                if ((rt->rt_flags & RTF_UP) == 0) { /* route went down! */
        !           135:                        if ((rt0 = rt = RTALLOC1(dst, 0)) != NULL)
        !           136:                                rt->rt_refcnt--;
        !           137:                        else 
        !           138:                                senderr(EHOSTUNREACH);
        !           139:                }
        !           140: 
        !           141:                if (rt->rt_flags & RTF_GATEWAY) {
        !           142:                        if (rt->rt_gwroute == 0)
        !           143:                                goto lookup;
        !           144:                        if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) {
        !           145:                                rtfree(rt); rt = rt0;
        !           146:                        lookup: rt->rt_gwroute = RTALLOC1(rt->rt_gateway, 0);
        !           147:                                if ((rt = rt->rt_gwroute) == 0)
        !           148:                                        senderr(EHOSTUNREACH);
        !           149:                        }
        !           150:                }
        !           151: 
        !           152:                /* XXX: put RTF_REJECT code here if doing ATMARP */
        !           153: 
        !           154:        }
        !           155: 
        !           156:        /*
        !           157:         * check for non-native ATM traffic   (dst != NULL)
        !           158:         */
        !           159:        if (dst) {
        !           160:                switch (dst->sa_family) {
        !           161: #if defined(INET) || defined(INET6)
        !           162:                case AF_INET:
        !           163:                case AF_INET6:
        !           164:                        if (!atmresolve(rt, m, dst, &atmdst)) {
        !           165:                                m = NULL; 
        !           166:                                /* XXX: atmresolve already free'd it */
        !           167:                                senderr(EHOSTUNREACH);
        !           168:                                /* XXX: put ATMARP stuff here */
        !           169:                                /* XXX: watch who frees m on failure */
        !           170:                        }
        !           171:                        if (dst->sa_family == AF_INET6)
        !           172:                                etype = htons(ETHERTYPE_IPV6);
        !           173:                        else
        !           174:                                etype = htons(ETHERTYPE_IP);
        !           175:                        break;
        !           176: #endif /* INET || INET6 */
        !           177: 
        !           178:                case AF_UNSPEC:
        !           179:                        /*
        !           180:                         * XXX: bpfwrite or output from a pvc shadow if.
        !           181:                         * assuming dst contains 12 bytes (atm pseudo
        !           182:                         * header (4) + LLC/SNAP (8))
        !           183:                         */
        !           184:                        bcopy(dst->sa_data, &atmdst, sizeof(atmdst));
        !           185:                        llc_hdr = (struct atmllc *)(dst->sa_data + sizeof(atmdst));
        !           186:                        break;
        !           187:                        
        !           188:                default:
        !           189: #if defined(__NetBSD__) || defined(__OpenBSD__)
        !           190:                        printf("%s: can't handle af%d\n", ifp->if_xname, 
        !           191:                            dst->sa_family);
        !           192: #elif defined(__FreeBSD__) || defined(__bsdi__)
        !           193:                        printf("%s%d: can't handle af%d\n", ifp->if_name, 
        !           194:                            ifp->if_unit, dst->sa_family);
        !           195: #endif
        !           196:                        senderr(EAFNOSUPPORT);
        !           197:                }
        !           198: 
        !           199:                /*
        !           200:                 * must add atm_pseudohdr to data
        !           201:                 */
        !           202:                sz = sizeof(atmdst);
        !           203:                atm_flags = ATM_PH_FLAGS(&atmdst);
        !           204:                if (atm_flags & ATM_PH_LLCSNAP) sz += 8; /* sizeof snap == 8 */
        !           205:                M_PREPEND(m, sz, M_DONTWAIT);
        !           206:                if (m == 0)
        !           207:                        senderr(ENOBUFS);
        !           208:                ad = mtod(m, struct atm_pseudohdr *);
        !           209:                *ad = atmdst;
        !           210:                if (atm_flags & ATM_PH_LLCSNAP) {
        !           211:                        atmllc = (struct atmllc *)(ad + 1);
        !           212:                        if (llc_hdr == NULL) {
        !           213:                                bcopy(ATMLLC_HDR, atmllc->llchdr, 
        !           214:                                      sizeof(atmllc->llchdr));
        !           215:                                ATM_LLC_SETTYPE(atmllc, etype); 
        !           216:                                        /* note: already in network order */
        !           217:                        }
        !           218:                        else
        !           219:                                bcopy(llc_hdr, atmllc, sizeof(struct atmllc));
        !           220:                }
        !           221:        }
        !           222: 
        !           223:        /*
        !           224:         * Queue message on interface, and start output if interface
        !           225:         * not yet active.
        !           226:         */
        !           227:        s = splimp();
        !           228:        if (IF_QFULL(&ifp->if_snd)) {
        !           229:                IF_DROP(&ifp->if_snd);
        !           230:                splx(s);
        !           231:                senderr(ENOBUFS);
        !           232:        }
        !           233:        ifp->if_obytes += m->m_pkthdr.len;
        !           234:        IF_ENQUEUE(&ifp->if_snd, m);
        !           235:        if ((ifp->if_flags & IFF_OACTIVE) == 0)
        !           236:                (*ifp->if_start)(ifp);
        !           237:        splx(s);
        !           238:        return (error);
        !           239: 
        !           240: bad:
        !           241:        if (m)
        !           242:                m_freem(m);
        !           243:        return (error);
        !           244: }
        !           245: 
        !           246: /*
        !           247:  * Process a received ATM packet;
        !           248:  * the packet is in the mbuf chain m.
        !           249:  */
        !           250: void
        !           251: atm_input(ifp, ah, m, rxhand)
        !           252:        struct ifnet *ifp;
        !           253:        register struct atm_pseudohdr *ah;
        !           254:        struct mbuf *m;
        !           255:        void *rxhand;
        !           256: {
        !           257:        register struct ifqueue *inq;
        !           258:        u_int16_t etype = ETHERTYPE_IP; /* default */
        !           259:        int s;
        !           260: 
        !           261:        if ((ifp->if_flags & IFF_UP) == 0) {
        !           262:                m_freem(m);
        !           263:                return;
        !           264:        }
        !           265:        ifp->if_ibytes += m->m_pkthdr.len;
        !           266: 
        !           267: #if ATM_PVCEXT
        !           268:        if (ATM_PH_FLAGS(ah) & ATM_PH_PVCSIF) {
        !           269:                /*
        !           270:                 * when PVC shadow interface is used, pointer to
        !           271:                 * the shadow interface is passed as rxhand.
        !           272:                 * override the receive interface of the packet.
        !           273:                 */
        !           274:                m->m_pkthdr.rcvif = (struct ifnet *)rxhand;
        !           275:                rxhand = NULL;
        !           276:        }
        !           277: #endif /*  ATM_PVCEXT */
        !           278: 
        !           279:        if (rxhand) {
        !           280: #if NATM
        !           281:                struct natmpcb *npcb = rxhand;
        !           282:                s = splimp();           /* in case 2 atm cards @ diff lvls */
        !           283:                npcb->npcb_inq++;       /* count # in queue */
        !           284:                splx(s);
        !           285:                schednetisr(NETISR_NATM);
        !           286:                inq = &natmintrq;
        !           287:                m->m_pkthdr.rcvif = rxhand; /* XXX: overload */
        !           288: #else
        !           289:                printf("atm_input: NATM detected but not configured in kernel\n");
        !           290:                m_freem(m);
        !           291:                return;
        !           292: #endif
        !           293:        } else {
        !           294:                /*
        !           295:                 * handle LLC/SNAP header, if present
        !           296:                 */
        !           297:                if (ATM_PH_FLAGS(ah) & ATM_PH_LLCSNAP) {
        !           298:                        struct atmllc *alc;
        !           299:                        if (m->m_len < sizeof(*alc) &&
        !           300:                            (m = m_pullup(m, sizeof(*alc))) == 0)
        !           301:                                return; /* failed */
        !           302:                        alc = mtod(m, struct atmllc *);
        !           303:                        if (bcmp(alc, ATMLLC_HDR, 6)) {
        !           304: #if defined(__NetBSD__) || defined(__OpenBSD__)
        !           305:                                printf("%s: recv'd invalid LLC/SNAP frame [vp=%d,vc=%d]\n",
        !           306:                                       ifp->if_xname, ATM_PH_VPI(ah), ATM_PH_VCI(ah));
        !           307: #elif defined(__FreeBSD__) || defined(__bsdi__)
        !           308:                                printf("%s%d: recv'd invalid LLC/SNAP frame [vp=%d,vc=%d]\n",
        !           309:                                       ifp->if_name, ifp->if_unit, ATM_PH_VPI(ah), ATM_PH_VCI(ah));
        !           310: #endif
        !           311:                                m_freem(m);
        !           312:                                return;
        !           313:                        }
        !           314:                        etype = ATM_LLC_TYPE(alc);
        !           315:                        m_adj(m, sizeof(*alc));
        !           316:                }
        !           317: 
        !           318:                switch (etype) {
        !           319: #if INET
        !           320:                case ETHERTYPE_IP:
        !           321:                        schednetisr(NETISR_IP);
        !           322:                        inq = &ipintrq;
        !           323:                        break;
        !           324: #endif
        !           325: #if INET6
        !           326:                case ETHERTYPE_IPV6:
        !           327:                        schednetisr(NETISR_IPV6);
        !           328:                        inq = &ip6intrq;
        !           329:                        break;
        !           330: #endif
        !           331:                default:
        !           332:                        m_freem(m);
        !           333:                        return;
        !           334:                }
        !           335:        }
        !           336: 
        !           337:        s = splimp();
        !           338:        if (IF_QFULL(inq)) {
        !           339:                IF_DROP(inq);
        !           340:                m_freem(m);
        !           341:        } else
        !           342:                IF_ENQUEUE(inq, m);
        !           343:        splx(s);
        !           344: }
        !           345: 
        !           346: /*
        !           347:  * Perform common duties while attaching to interface list
        !           348:  */
        !           349: void
        !           350: atm_ifattach(ifp)
        !           351:        register struct ifnet *ifp;
        !           352: {
        !           353:        register struct ifaddr *ifa;
        !           354:        register struct sockaddr_dl *sdl;
        !           355: 
        !           356:        ifp->if_type = IFT_ATM;
        !           357:        ifp->if_addrlen = 0;
        !           358:        ifp->if_hdrlen = 0;
        !           359:        ifp->if_mtu = ATMMTU;
        !           360:        ifp->if_output = atm_output;
        !           361: 
        !           362: #if defined(__NetBSD__) || defined(__OpenBSD__)
        !           363:        for (ifa = ifp->if_addrlist.tqh_first; ifa != 0;
        !           364:            ifa = ifa->ifa_list.tqe_next)
        !           365: #elif defined(__FreeBSD__) && (__FreeBSD__ > 2)
        !           366:        for (ifa = ifp->if_addrhead.tqh_first; ifa; 
        !           367:            ifa = ifa->ifa_link.tqe_next)
        !           368: #elif defined(__FreeBSD__) || defined(__bsdi__)
        !           369:        for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 
        !           370: #endif
        !           371:                if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) &&
        !           372:                    sdl->sdl_family == AF_LINK) {
        !           373:                        sdl->sdl_type = IFT_ATM;
        !           374:                        sdl->sdl_alen = ifp->if_addrlen;
        !           375: #ifdef notyet /* if using ATMARP, store hardware address using the next line */
        !           376:                        bcopy(ifp->hw_addr, LLADDR(sdl), ifp->if_addrlen);
        !           377: #endif
        !           378:                        break;
        !           379:                }
        !           380: 
        !           381: }
        !           382: 
        !           383: #if ATM_PVCEXT
        !           384: /*
        !           385:  * ATM PVC shadow interface: a trick to assign a shadow interface
        !           386:  * to a PVC.
        !           387:  * with shadow interface, each PVC looks like an individual
        !           388:  * Point-to-Point interface.
        !           389:  * as oposed to the NBMA model, a shadow interface is inherently
        !           390:  * multicast capable (no LANE/MARS required).
        !           391:  */
        !           392: struct pvcsif {
        !           393:        struct ifnet sif_shadow;        /* shadow ifnet structure per pvc */
        !           394:        struct atm_pseudohdr sif_aph;   /* flags + vpi:vci */
        !           395:        struct ifnet *sif_ifp;          /* pointer to the genuine interface */
        !           396: };
        !           397: 
        !           398: static int pvc_output __P((struct ifnet *, struct mbuf *,
        !           399:                           struct sockaddr *, struct rtentry *));
        !           400: static int pvc_ioctl __P((struct ifnet *, u_long, caddr_t));
        !           401: 
        !           402: /*
        !           403:  * create and attach per pvc shadow interface
        !           404:  * (currently detach is not supported)
        !           405:  */
        !           406: static int pvc_number = 0;
        !           407: 
        !           408: struct ifnet *
        !           409: pvc_attach(ifp)
        !           410:        struct ifnet *ifp;
        !           411: {
        !           412:        struct pvcsif *pvcsif;
        !           413:        struct ifnet *shadow;
        !           414:        struct ifaddr *ifa;
        !           415:        struct sockaddr_dl *sdl;
        !           416:        int s;
        !           417: 
        !           418:        MALLOC(pvcsif, struct pvcsif *, sizeof(struct pvcsif),
        !           419:               M_DEVBUF, M_WAITOK);
        !           420:        bzero(pvcsif, sizeof(struct pvcsif));
        !           421: 
        !           422:        pvcsif->sif_ifp = ifp;
        !           423:        shadow = &pvcsif->sif_shadow;
        !           424: 
        !           425:        shadow->if_name = "pvc";
        !           426:        shadow->if_family = APPLE_IF_FAM_PVC;
        !           427:        shadow->if_unit = pvc_number++;
        !           428:        shadow->if_flags = ifp->if_flags | (IFF_POINTOPOINT | IFF_MULTICAST);
        !           429:        shadow->if_ioctl = pvc_ioctl;
        !           430:        shadow->if_output = pvc_output;
        !           431:        shadow->if_start = NULL;
        !           432:        shadow->if_mtu = ifp->if_mtu;
        !           433:        shadow->if_type = ifp->if_type;
        !           434:        shadow->if_addrlen = ifp->if_addrlen;
        !           435:        shadow->if_hdrlen = ifp->if_hdrlen;
        !           436:        shadow->if_softc = pvcsif;
        !           437:        shadow->if_snd.ifq_maxlen = 50; /* dummy */
        !           438: 
        !           439:        s = splimp();
        !           440:        if_attach(shadow);
        !           441: 
        !           442: #if defined(__NetBSD__) || defined(__OpenBSD__)
        !           443:        for (ifa = shadow->if_addrlist.tqh_first; ifa != 0;
        !           444:             ifa = ifa->ifa_list.tqe_next)
        !           445: #elif defined(__FreeBSD__) && (__FreeBSD__ > 2)
        !           446:        for (ifa = shadow->if_addrhead.tqh_first; ifa; 
        !           447:             ifa = ifa->ifa_link.tqe_next)
        !           448: #elif defined(__FreeBSD__) || defined(__bsdi__)
        !           449:        for (ifa = shadow->if_addrlist; ifa; ifa = ifa->ifa_next) 
        !           450: #endif
        !           451:                if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) &&
        !           452:                    sdl->sdl_family == AF_LINK) {
        !           453:                        sdl->sdl_type = IFT_ATM;
        !           454:                        sdl->sdl_alen = shadow->if_addrlen;
        !           455:                        break;
        !           456:                }
        !           457:        splx(s);
        !           458: 
        !           459:        return (shadow);
        !           460: }
        !           461: 
        !           462: /*
        !           463:  * pvc_output relays the packet to atm_output along with vpi:vci info.
        !           464:  */
        !           465: static int
        !           466: pvc_output(shadow, m, dst, rt)
        !           467:        struct ifnet *shadow;
        !           468:        struct mbuf *m;
        !           469:        struct sockaddr *dst;
        !           470:        struct rtentry *rt;
        !           471: {
        !           472:        struct pvcsif *pvcsif;
        !           473:        struct sockaddr dst_addr;
        !           474:        struct atmllc *atmllc;
        !           475:        u_int16_t etype = 0;
        !           476:        int error = 0;
        !           477: 
        !           478:        if ((shadow->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
        !           479:                senderr(ENETDOWN);
        !           480: 
        !           481:        pvcsif = shadow->if_softc;
        !           482:        if (ATM_PH_VCI(&pvcsif->sif_aph) == 0)
        !           483:                senderr(ENETDOWN);
        !           484:        
        !           485:        /*
        !           486:         * create a dummy sockaddr: (using bpfwrite interface)
        !           487:         * put atm pseudo header and llc/snap into sa_data (12 bytes)
        !           488:         * and mark it as AF_UNSPEC.
        !           489:         */
        !           490:        if (dst) {
        !           491:                switch (dst->sa_family) {
        !           492: #if defined(INET) || defined(INET6)
        !           493:                case AF_INET:
        !           494:                case AF_INET6:
        !           495:                        if (dst->sa_family == AF_INET6)
        !           496:                                etype = htons(ETHERTYPE_IPV6);
        !           497:                        else
        !           498:                                etype = htons(ETHERTYPE_IP);
        !           499:                        break;
        !           500: #endif
        !           501: 
        !           502:                default:
        !           503:                        printf("%s%d: can't handle af%d\n", shadow->if_name, 
        !           504:                               shadow->if_unit, dst->sa_family);
        !           505:                        senderr(EAFNOSUPPORT);
        !           506:                }
        !           507:        }
        !           508: 
        !           509:        dst_addr.sa_family = AF_UNSPEC;
        !           510:        bcopy(&pvcsif->sif_aph, dst_addr.sa_data,
        !           511:              sizeof(struct atm_pseudohdr));
        !           512:        atmllc = (struct atmllc *)
        !           513:                (dst_addr.sa_data + sizeof(struct atm_pseudohdr));
        !           514:        bcopy(ATMLLC_HDR, atmllc->llchdr,  sizeof(atmllc->llchdr));
        !           515:        ATM_LLC_SETTYPE(atmllc, etype);  /* note: already in network order */
        !           516: 
        !           517:        return atm_output(pvcsif->sif_ifp, m, &dst_addr, rt);
        !           518: 
        !           519: bad:
        !           520:        if (m)
        !           521:                m_freem(m);
        !           522:        return (error);
        !           523: }
        !           524: 
        !           525: static int
        !           526: pvc_ioctl(shadow, cmd, data)
        !           527:        struct ifnet *shadow;
        !           528:        u_long cmd;
        !           529:        caddr_t data;
        !           530: {
        !           531:        struct ifnet *ifp;
        !           532:        struct pvcsif *pvcsif;
        !           533:        struct ifreq *ifr = (struct ifreq *) data;
        !           534:        void (*ifa_rtrequest)(int, struct rtentry *, struct sockaddr *) = NULL;
        !           535:        int error = 0;
        !           536: 
        !           537:        pvcsif = (struct pvcsif *)shadow->if_softc;
        !           538:        ifp = pvcsif->sif_ifp;
        !           539:        if (ifp == 0 || ifp->if_ioctl == 0)
        !           540:                return (EOPNOTSUPP);
        !           541:     
        !           542:        /*
        !           543:         * pre process
        !           544:         */
        !           545:        switch (cmd) {
        !           546:        case SIOCGPVCSIF:
        !           547:                snprintf(ifr->ifr_name, sizeof(ifr->ifr_name),
        !           548:                    "%s%d", ifp->if_name, ifp->if_unit);
        !           549:                return (0);
        !           550: 
        !           551:        case SIOCGPVCTX:
        !           552:                do {
        !           553:                        struct pvctxreq *pvcreq = (struct pvctxreq *)data;
        !           554: 
        !           555:                        snprintf(pvcreq->pvc_ifname,
        !           556:                            sizeof(pvcreq->pvc_ifname), "%s%d",
        !           557:                                ifp->if_name, ifp->if_unit);
        !           558:                        pvcreq->pvc_aph = pvcsif->sif_aph;
        !           559:                } while (0);
        !           560:                break;
        !           561: 
        !           562:        case SIOCADDMULTI:
        !           563:        case SIOCDELMULTI:
        !           564:                if (ifr == 0)
        !           565:                        return (EAFNOSUPPORT);  /* XXX */
        !           566:                switch (ifr->ifr_addr.sa_family) {
        !           567: #if INET
        !           568:                case AF_INET:
        !           569:                        return (0);
        !           570: #endif
        !           571: #if INET6
        !           572:                case AF_INET6:
        !           573:                        return (0);
        !           574: #endif
        !           575:                default:
        !           576:                        return (EAFNOSUPPORT);
        !           577:                }
        !           578:                break;
        !           579:        case SIOCSIFADDR:
        !           580:                if (ifp->if_flags & IFF_UP) {
        !           581:                        /* real if is already up */
        !           582:                        shadow->if_flags = ifp->if_flags |
        !           583:                                (IFF_POINTOPOINT|IFF_MULTICAST);
        !           584:                        return (0);
        !           585:                }
        !           586:                /*
        !           587:                 * XXX: save the rtrequest field since the atm driver
        !           588:                 * overwrites this field.
        !           589:                 */
        !           590:                ifa_rtrequest = ((struct ifaddr *)data)->ifa_rtrequest;
        !           591:                break;
        !           592:                
        !           593:        case SIOCSIFFLAGS:
        !           594:                if ((shadow->if_flags & IFF_UP) == 0) {
        !           595:                        /*
        !           596:                         * interface down. don't pass this to
        !           597:                         * the real interface.
        !           598:                         */
        !           599:                        return (0);
        !           600:                }
        !           601:                if (shadow->if_flags & IFF_UP) {
        !           602:                        /*
        !           603:                         * interface up. if the real if is already up,
        !           604:                         * nothing to do.
        !           605:                         */
        !           606:                        if (ifp->if_flags & IFF_UP) {
        !           607:                                shadow->if_flags = ifp->if_flags |
        !           608:                                        (IFF_POINTOPOINT|IFF_MULTICAST);
        !           609:                                return (0);
        !           610:                        }
        !           611:                }
        !           612:                break;
        !           613:        }
        !           614: 
        !           615:        /*
        !           616:         * pass the ioctl to the genuine interface
        !           617:         */
        !           618:        error = (*ifp->if_ioctl)(ifp, cmd, data);
        !           619: 
        !           620:        /*
        !           621:         * post process
        !           622:         */
        !           623:        switch (cmd) {
        !           624:        case SIOCSIFMTU:
        !           625:                shadow->if_mtu = ifp->if_mtu;
        !           626:                break;
        !           627:        case SIOCSIFADDR:
        !           628:                /* restore rtrequest */
        !           629:                ((struct ifaddr *)data)->ifa_rtrequest = ifa_rtrequest;
        !           630:                /* fall into... */
        !           631:        case SIOCSIFFLAGS:
        !           632:                /* update if_flags */
        !           633:                shadow->if_flags = ifp->if_flags
        !           634:                        | (IFF_POINTOPOINT|IFF_MULTICAST);
        !           635:                break;
        !           636:        }
        !           637: 
        !           638:        return (error);
        !           639: }
        !           640: 
        !           641: int pvc_setaph(shadow, aph)
        !           642:        struct ifnet *shadow;
        !           643:        struct atm_pseudohdr *aph;
        !           644: {
        !           645:        struct pvcsif *pvcsif;
        !           646:     
        !           647:        pvcsif = shadow->if_softc;
        !           648:        bcopy(aph, &pvcsif->sif_aph, sizeof(struct atm_pseudohdr));
        !           649:        return (0);
        !           650: }
        !           651: 
        !           652: #endif /* ATM_PVCEXT */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.