Annotation of XNU/bsd/net/if_loop.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: /*
        !            23:  * Copyright (c) 1982, 1986, 1993
        !            24:  *     The Regents of the University of California.  All rights reserved.
        !            25:  *
        !            26:  * Redistribution and use in source and binary forms, with or without
        !            27:  * modification, are permitted provided that the following conditions
        !            28:  * are met:
        !            29:  * 1. Redistributions of source code must retain the above copyright
        !            30:  *    notice, this list of conditions and the following disclaimer.
        !            31:  * 2. Redistributions in binary form must reproduce the above copyright
        !            32:  *    notice, this list of conditions and the following disclaimer in the
        !            33:  *    documentation and/or other materials provided with the distribution.
        !            34:  * 3. All advertising materials mentioning features or use of this software
        !            35:  *    must display the following acknowledgement:
        !            36:  *     This product includes software developed by the University of
        !            37:  *     California, Berkeley and its contributors.
        !            38:  * 4. Neither the name of the University nor the names of its contributors
        !            39:  *    may be used to endorse or promote products derived from this software
        !            40:  *    without specific prior written permission.
        !            41:  *
        !            42:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            43:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            44:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            45:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            46:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            47:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            48:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            49:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            50:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            51:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            52:  * SUCH DAMAGE.
        !            53:  *
        !            54:  *     @(#)if_loop.c   8.1 (Berkeley) 6/10/93
        !            55:  */
        !            56: 
        !            57: /*
        !            58:  * Loopback interface driver for protocol testing and timing.
        !            59:  */
        !            60: #include "loop.h"
        !            61: #if NLOOP > 0
        !            62: 
        !            63: #include <sys/param.h>
        !            64: #include <sys/systm.h>
        !            65: #include <sys/kernel.h>
        !            66: #include <sys/mbuf.h>
        !            67: #include <sys/socket.h>
        !            68: #include <sys/sockio.h>
        !            69: 
        !            70: #include <net/if.h>
        !            71: #include <net/if_types.h>
        !            72: #include <net/netisr.h>
        !            73: #include <net/route.h>
        !            74: #include <net/bpf.h>
        !            75: #include <sys/malloc.h>
        !            76: 
        !            77: #if    INET
        !            78: #include <netinet/in.h>
        !            79: #include <netinet/in_var.h>
        !            80: #endif
        !            81: 
        !            82: #if IPX
        !            83: #include <netipx/ipx.h>
        !            84: #include <netipx/ipx_if.h>
        !            85: #endif
        !            86: 
        !            87: #if NS
        !            88: #include <netns/ns.h>
        !            89: #include <netns/ns_if.h>
        !            90: #endif
        !            91: 
        !            92: #if ISO
        !            93: #include <netiso/iso.h>
        !            94: #include <netiso/iso_var.h>
        !            95: #endif
        !            96: 
        !            97: #include <net/dlil.h>
        !            98: 
        !            99: #if NETAT
        !           100: extern struct ifqueue atalkintrq;
        !           101: #endif
        !           102: 
        !           103: #include "bpfilter.h"
        !           104: #if NBPFILTER > 0
        !           105: #include <net/bpfdesc.h>
        !           106: #endif
        !           107: 
        !           108: 
        !           109: #define NLOOP_ATTACHMENTS (NLOOP * 12)
        !           110: 
        !           111: struct lo_statics_str {
        !           112:        int     bpf_mode;
        !           113:        int     (*bpf_callback)(struct ifnet *, struct mbuf *);
        !           114: };
        !           115: 
        !           116: static struct if_proto *lo_array[NLOOP_ATTACHMENTS];
        !           117: static struct lo_statics_str lo_statics[NLOOP];
        !           118: static lo_count = 0;
        !           119: 
        !           120: 
        !           121: #ifdef TINY_LOMTU
        !           122: #define        LOMTU   (1024+512)
        !           123: #else
        !           124: #define LOMTU  16384
        !           125: #endif
        !           126: 
        !           127: struct ifnet loif[NLOOP];
        !           128: 
        !           129: void lo_reg_if_mods();
        !           130: 
        !           131: 
        !           132: 
        !           133: 
        !           134: int lo_demux(ifp, m, frame_header, proto)
        !           135:     struct ifnet *ifp;
        !           136:     struct mbuf  *m;
        !           137:     char         *frame_header;
        !           138:     struct if_proto **proto;
        !           139: {
        !           140:     int i;
        !           141:     struct if_proto **proto_ptr;
        !           142: 
        !           143:     proto_ptr = mtod(m, struct if_proto **);
        !           144:     *proto = *proto_ptr;
        !           145:     m_adj(m, sizeof(u_long));
        !           146:     return 0;
        !           147: }
        !           148: 
        !           149: 
        !           150: int lo_framer(ifp, m, dest, dest_linkaddr, frame_type)
        !           151:     struct ifnet    *ifp;
        !           152:     struct mbuf     **m;
        !           153:     struct sockaddr *dest;
        !           154:     char            *dest_linkaddr;
        !           155:     char           *frame_type;
        !           156: 
        !           157: {
        !           158:     char  *to_ptr;
        !           159: 
        !           160:        M_PREPEND(*m, (4 * sizeof(u_long)), M_WAITOK);
        !           161:        to_ptr = mtod(*m, char *);
        !           162:        bcopy(dest_linkaddr, to_ptr, (4 * sizeof(u_long)));
        !           163:        return 0;
        !           164: }
        !           165: 
        !           166: static
        !           167: int  lo_add_if(struct ifnet *ifp)
        !           168: {
        !           169:     ifp->if_demux  = lo_demux;
        !           170:     ifp->if_framer = lo_framer;
        !           171:     return 0;
        !           172: }
        !           173: 
        !           174: static
        !           175: int  lo_del_if(struct ifnet *ifp)
        !           176: {
        !           177:     return 0;
        !           178: }
        !           179: 
        !           180: 
        !           181: 
        !           182: 
        !           183: static
        !           184: int  lo_add_proto(struct ddesc_head_str *desc_head, struct if_proto *proto, u_long dl_tag)
        !           185: {
        !           186:     int i;
        !           187: 
        !           188:     for (i=0; i < lo_count; i++)
        !           189:        if (lo_array[i] == 0) {
        !           190:            lo_array[lo_count] = proto;
        !           191:            return 0;
        !           192:        }
        !           193: 
        !           194:     if ((i == lo_count) && (lo_count == NLOOP_ATTACHMENTS))
        !           195:        panic("lo_add_proto -- Too many attachments\n");
        !           196: 
        !           197:     lo_array[lo_count++] = proto;
        !           198:     return 0;
        !           199: }
        !           200: 
        !           201: 
        !           202: static
        !           203: int  lo_del_proto(struct if_proto *proto, u_long dl_tag)
        !           204: {
        !           205:     int i;
        !           206: 
        !           207:     for (i=0; i < lo_count; i++)
        !           208:        if (lo_array[i] == proto) {
        !           209:            lo_array[i] = 0;
        !           210:            return 0;
        !           211:        }
        !           212: 
        !           213:     return ENOENT;
        !           214: }
        !           215: 
        !           216: static int
        !           217: lo_output(ifp, m)
        !           218:        struct ifnet *ifp;
        !           219:        register struct mbuf *m;
        !           220: {      u_int  *prepend_ptr;
        !           221:        u_int  af;
        !           222:        u_long saved_header[3];
        !           223: 
        !           224:        if ((m->m_flags & M_PKTHDR) == 0)
        !           225:                panic("lo_output: no HDR");
        !           226: 
        !           227:        m->m_pkthdr.rcvif = ifp;
        !           228:        
        !           229:        prepend_ptr = mtod(m, u_int *);
        !           230:        af = *prepend_ptr;
        !           231:        m_adj(m, sizeof(u_int));
        !           232: 
        !           233: 
        !           234: #if NBPFILTER > 0
        !           235:        if (lo_statics[ifp->if_unit].bpf_mode != BPF_TAP_DISABLE) {
        !           236:                struct mbuf m0, *n;
        !           237: 
        !           238:                bcopy(mtod(m, caddr_t), &saved_header[0], (3 * sizeof(u_long)));
        !           239:                m_adj(m, (3 * sizeof(u_long)));
        !           240: 
        !           241:                n = m;
        !           242:                if (ifp->if_bpf->bif_dlt == DLT_NULL) {
        !           243:                        /*
        !           244:                         * We need to prepend the address family as
        !           245:                         * a four byte field.  Cons up a dummy header
        !           246:                         * to pacify bpf.  This is safe because bpf
        !           247:                         * will only read from the mbuf (i.e., it won't
        !           248:                         * try to free it or keep a pointer a to it).
        !           249:                         */
        !           250:                        m0.m_next = m;
        !           251:                        m0.m_len = 4;
        !           252:                        m0.m_data = (char *)&af;
        !           253:                        n = &m0;
        !           254:                }
        !           255: 
        !           256:                (*lo_statics[ifp->if_unit].bpf_callback)(ifp, n);
        !           257: 
        !           258:                M_PREPEND(m, (3 * sizeof(u_long)), M_WAITOK);
        !           259:                bcopy(&saved_header[0], mtod(m, caddr_t), (3 * sizeof(u_long)));
        !           260: 
        !           261:        }
        !           262: #endif
        !           263: 
        !           264: /*
        !           265:  * Turn this code back on when iokit starts incrementing these counters.
        !           266: /*
        !           267: /*
        !           268:        ifp->if_ibytes += m->m_pkthdr.len;
        !           269:        ifp->if_obytes += m->m_pkthdr.len;
        !           270: */
        !           271:        ifp->if_opackets++;
        !           272:        ifp->if_ipackets++;
        !           273: 
        !           274:        return dlil_input(ifp, m, mtod(m, char *));
        !           275: }
        !           276: 
        !           277: 
        !           278: /*
        !           279:  * This is a common pre-output route used by INET, AT, etc. This could
        !           280:  * (should?) be split into separate pre-output routines for each protocol.
        !           281:  */
        !           282: 
        !           283: static int
        !           284: lo_pre_output(ifp, m, dst, route, frame_type, dst_addr, dl_tag)
        !           285:        struct ifnet *ifp;
        !           286:        register struct mbuf **m;
        !           287:        struct sockaddr *dst;
        !           288:        void                 *route;
        !           289:        char                 *frame_type;
        !           290:        char                 *dst_addr;
        !           291:        u_long               dl_tag;
        !           292: 
        !           293: {
        !           294:        int s, isr;
        !           295:        register struct ifqueue *ifq = 0;
        !           296:        u_long *prepend_ptr;
        !           297:        register struct rtentry *rt = (struct rtentry *) route;
        !           298: 
        !           299:        prepend_ptr = (u_long *) dst_addr;
        !           300:        if (((*m)->m_flags & M_PKTHDR) == 0)
        !           301:                panic("looutput no HDR");
        !           302: 
        !           303:        if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) {
        !           304:            if (rt->rt_flags & RTF_BLACKHOLE) {
        !           305:                m_freem(*m);
        !           306:                return EJUSTRETURN;
        !           307:            }
        !           308:            else
        !           309:                return ((rt->rt_flags & RTF_HOST) ? EHOSTUNREACH : ENETUNREACH);
        !           310:        }
        !           311: 
        !           312:        switch (dst->sa_family) {
        !           313: #if INET
        !           314:        case AF_INET:
        !           315:            ifq = &ipintrq;
        !           316:            isr = NETISR_IP;
        !           317:            break;
        !           318: #endif
        !           319: #if IPX
        !           320:        case AF_IPX:
        !           321:            ifq = &ipxintrq;
        !           322:            isr = NETISR_IPX;
        !           323:            break;
        !           324: #endif
        !           325: #if NS
        !           326:        case AF_NS:
        !           327:            ifq = &nsintrq;
        !           328:            isr = NETISR_NS;
        !           329:            break;
        !           330: #endif
        !           331: #if ISO
        !           332:        case AF_ISO:
        !           333:            ifq = &clnlintrq;
        !           334:            isr = NETISR_ISO;
        !           335:            break;
        !           336: #endif
        !           337: #if NETAT
        !           338:        case AF_APPLETALK:
        !           339:            ifq = &atalkintrq;
        !           340:            isr = NETISR_APPLETALK;
        !           341:            break;
        !           342: #endif NETAT
        !           343:        default:
        !           344:            return (EAFNOSUPPORT);
        !           345:        }
        !           346: 
        !           347:        *prepend_ptr++ = dst->sa_family;        /* For lo_output(BPF) */
        !           348:        *prepend_ptr++ = dlttoproto(dl_tag);    /* For lo_demux */
        !           349:        *prepend_ptr++ = (u_long) ifq;          /* For lo_input */
        !           350:        *prepend_ptr   = isr;                   /* For lo_input */
        !           351: 
        !           352:        return 0;
        !           353: }
        !           354: 
        !           355: 
        !           356: 
        !           357: 
        !           358: /*
        !           359:  *  lo_input - This should work for all attached protocols that use the
        !           360:  *             ifq/schednetisr input mechanism.
        !           361:  */
        !           362: 
        !           363: 
        !           364: int
        !           365: lo_input(m, fh, ifp, dl_tag, sync_ok)
        !           366:        register struct mbuf *m;
        !           367:        char         *fh;
        !           368:        struct ifnet *ifp;
        !           369:        u_long       dl_tag;
        !           370:        int sync_ok;
        !           371: 
        !           372: {
        !           373:        u_long *prepend_ptr;
        !           374:        int s, isr;
        !           375:        register struct ifqueue *ifq = 0;
        !           376: 
        !           377:        prepend_ptr = mtod(m, u_long *);
        !           378:        ifq = (struct ifqueue *) *prepend_ptr++;
        !           379:        isr = *prepend_ptr;
        !           380:        m_adj(m, (2 * sizeof(u_long)));
        !           381: 
        !           382:        s = splimp();
        !           383:        if (IF_QFULL(ifq)) {
        !           384:                IF_DROP(ifq);
        !           385:                m_freem(m);
        !           386:                splx(s);
        !           387:                return (EJUSTRETURN);
        !           388:        }
        !           389: 
        !           390:        IF_ENQUEUE(ifq, m);
        !           391:        schednetisr(isr);
        !           392:        splx(s);
        !           393:        return (0);
        !           394: }
        !           395: 
        !           396: 
        !           397: 
        !           398: 
        !           399: /* ARGSUSED */
        !           400: static void
        !           401: lortrequest(cmd, rt, sa)
        !           402:        int cmd;
        !           403:        struct rtentry *rt;
        !           404:        struct sockaddr *sa;
        !           405: {
        !           406:        if (rt) {
        !           407:                rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu; /* for ISO */
        !           408:                /*
        !           409:                 * For optimal performance, the send and receive buffers
        !           410:                 * should be at least twice the MTU plus a little more for
        !           411:                 * overhead.
        !           412:                 */
        !           413:                rt->rt_rmx.rmx_recvpipe = 
        !           414:                        rt->rt_rmx.rmx_sendpipe = 3 * LOMTU;
        !           415:        }
        !           416: }
        !           417: 
        !           418: /*
        !           419:  * Process an ioctl request.
        !           420:  */
        !           421: /* ARGSUSED */
        !           422: static int
        !           423: loioctl(ifp, cmd, data)
        !           424:        register struct ifnet *ifp;
        !           425:        u_long cmd;
        !           426:        void   *data;
        !           427: {
        !           428:        register struct ifaddr *ifa;
        !           429:        register struct ifreq *ifr = (struct ifreq *)data;
        !           430:        register int error = 0;
        !           431: 
        !           432:        switch (cmd) {
        !           433: 
        !           434:        case SIOCSIFADDR:
        !           435:                ifp->if_flags |= IFF_UP | IFF_RUNNING;
        !           436:                ifa = (struct ifaddr *)data;
        !           437:                ifa->ifa_rtrequest = lortrequest;
        !           438:                /*
        !           439:                 * Everything else is done at a higher level.
        !           440:                 */
        !           441:                break;
        !           442: 
        !           443:        case SIOCADDMULTI:
        !           444:        case SIOCDELMULTI:
        !           445:                if (ifr == 0) {
        !           446:                        error = EAFNOSUPPORT;           /* XXX */
        !           447:                        break;
        !           448:                }
        !           449:                switch (ifr->ifr_addr.sa_family) {
        !           450: 
        !           451: #if INET
        !           452:                case AF_INET:
        !           453:                        break;
        !           454: #endif
        !           455: 
        !           456:                default:
        !           457:                        error = EAFNOSUPPORT;
        !           458:                        break;
        !           459:                }
        !           460:                break;
        !           461: 
        !           462:        case SIOCSIFMTU:
        !           463:                ifp->if_mtu = ifr->ifr_mtu;
        !           464:                break;
        !           465: 
        !           466:        case SIOCSIFFLAGS:
        !           467:                break;
        !           468: 
        !           469:        default:
        !           470:                error = EINVAL;
        !           471:        }
        !           472:        return (error);
        !           473: }
        !           474: #endif /* NLOOP > 0 */
        !           475: 
        !           476: 
        !           477: int lo_shutdown()
        !           478: {
        !           479:     return 0;
        !           480: }
        !           481: 
        !           482: 
        !           483: void lo_reg_if_mods()
        !           484: {
        !           485: 
        !           486:     if (dlil_reg_if_modules(APPLE_IF_FAM_LOOPBACK, lo_add_if, lo_del_if,
        !           487:                        lo_add_proto, lo_del_proto,
        !           488:                        lo_shutdown))
        !           489:        panic("Couldn't register lo modules\n");
        !           490: 
        !           491: }
        !           492: 
        !           493: 
        !           494: u_long  lo_attach_inet(struct ifnet *ifp)
        !           495: {
        !           496:     struct dlil_proto_reg_str   reg;
        !           497:     struct dlil_demux_desc      desc;
        !           498:     u_long                     dl_tag=0;
        !           499:     short native=0;
        !           500:     int   stat;
        !           501:     int i;
        !           502: 
        !           503:     for (i=0; i < lo_count; i++) {
        !           504:        if ((lo_array[i]) && (lo_array[i]->ifp == ifp)) {
        !           505:            if (lo_array[i]->protocol_family == PF_INET)
        !           506:                return lo_array[i]->dl_tag;
        !           507:        }
        !           508:     }
        !           509: 
        !           510:     TAILQ_INIT(&reg.demux_desc_head);
        !           511:     desc.type = DLIL_DESC_RAW;
        !           512:     desc.variants.bitmask.proto_id_length = 0;
        !           513:     desc.variants.bitmask.proto_id = 0;
        !           514:     desc.variants.bitmask.proto_id_mask = 0;
        !           515:     desc.native_type = (char *) &native;
        !           516:     TAILQ_INSERT_TAIL(&reg.demux_desc_head, &desc, next);
        !           517:     reg.interface_family = ifp->if_family;
        !           518:     reg.unit_number      = ifp->if_unit;
        !           519:     reg.input           = lo_input;
        !           520:     reg.pre_output       = lo_pre_output;
        !           521:     reg.event            = 0;
        !           522:     reg.offer            = 0;
        !           523:     reg.ioctl            = loioctl;
        !           524:     reg.default_proto    = 0;
        !           525:     reg.protocol_family  = PF_INET;
        !           526: 
        !           527:     stat = dlil_attach_protocol(&reg, &dl_tag);
        !           528:     if (stat) {
        !           529:        panic("ether_attach_inet can't attach interface\n");
        !           530:     }
        !           531:     
        !           532:     return dl_tag;
        !           533: }
        !           534: 
        !           535: 
        !           536: int lo_set_bpf_tap(struct ifnet *ifp, int mode, int (*bpf_callback)(struct ifnet *, struct mbuf *))
        !           537: {
        !           538: 
        !           539:   /*
        !           540:    * NEED MUTEX HERE XXX
        !           541:    */
        !           542:        if (mode == BPF_TAP_DISABLE) {
        !           543:                lo_statics[ifp->if_unit].bpf_mode = mode;
        !           544:                lo_statics[ifp->if_unit].bpf_callback = bpf_callback;
        !           545:        }
        !           546:        else {
        !           547:                lo_statics[ifp->if_unit].bpf_callback = bpf_callback;
        !           548:                lo_statics[ifp->if_unit].bpf_mode = mode;               
        !           549:        }
        !           550: 
        !           551:        return 0;
        !           552: }
        !           553: 
        !           554: 
        !           555: /* ARGSUSED */
        !           556: void
        !           557: loopattach(dummy)
        !           558:        void *dummy;
        !           559: {
        !           560:        register struct ifnet *ifp;
        !           561:        register int i = 0;
        !           562: 
        !           563:        lo_reg_if_mods();
        !           564: 
        !           565:        for (ifp = loif; i < NLOOP; ifp++) {
        !           566:                lo_statics[i].bpf_callback = 0;
        !           567:                lo_statics[i].bpf_mode      = BPF_TAP_DISABLE;
        !           568:                ifp->if_name = "lo";
        !           569:                ifp->if_family = APPLE_IF_FAM_LOOPBACK;
        !           570:                ifp->if_unit = i++;
        !           571:                ifp->if_mtu = LOMTU;
        !           572:                ifp->if_flags = IFF_LOOPBACK | IFF_MULTICAST;
        !           573:                ifp->if_ioctl = 0;
        !           574:                ifp->if_set_bpf_tap = lo_set_bpf_tap;
        !           575:                ifp->if_output = lo_output;
        !           576:                ifp->if_type = IFT_LOOP;
        !           577:                dlil_if_attach(ifp);
        !           578: #if NBPFILTER > 0
        !           579:                bpfattach(ifp, DLT_NULL, sizeof(u_int));
        !           580: #endif
        !           581:        }
        !           582: }

unix.superglobalmegacorp.com

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