Annotation of XNU/bsd/net/if_loop.c, revision 1.1.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.