Annotation of kernel/bsd/net/if.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
        !             7:  * Reserved.  This file contains Original Code and/or Modifications of
        !             8:  * Original Code as defined in and that are subject to the Apple Public
        !             9:  * Source License Version 1.1 (the "License").  You may not use this file
        !            10:  * except in compliance with the License.  Please obtain a copy of the
        !            11:  * License at http://www.apple.com/publicsource and read it before using
        !            12:  * this file.
        !            13:  * 
        !            14:  * The Original Code and all software distributed under the License are
        !            15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            19:  * License for the specific language governing rights and limitations
        !            20:  * under the License.
        !            21:  * 
        !            22:  * @APPLE_LICENSE_HEADER_END@
        !            23:  */
        !            24: 
        !            25: /* Copyright (c) 1997, 1998 Apple Computer, Inc. All Rights Reserved */
        !            26: /*
        !            27:  * Copyright (c) 1980, 1986, 1993
        !            28:  *     The Regents of the University of California.  All rights reserved.
        !            29:  *
        !            30:  * Redistribution and use in source and binary forms, with or without
        !            31:  * modification, are permitted provided that the following conditions
        !            32:  * are met:
        !            33:  * 1. Redistributions of source code must retain the above copyright
        !            34:  *    notice, this list of conditions and the following disclaimer.
        !            35:  * 2. Redistributions in binary form must reproduce the above copyright
        !            36:  *    notice, this list of conditions and the following disclaimer in the
        !            37:  *    documentation and/or other materials provided with the distribution.
        !            38:  * 3. All advertising materials mentioning features or use of this software
        !            39:  *    must display the following acknowledgement:
        !            40:  *     This product includes software developed by the University of
        !            41:  *     California, Berkeley and its contributors.
        !            42:  * 4. Neither the name of the University nor the names of its contributors
        !            43:  *    may be used to endorse or promote products derived from this software
        !            44:  *    without specific prior written permission.
        !            45:  *
        !            46:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            47:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            48:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            49:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            50:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            51:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            52:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            53:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            54:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            55:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            56:  * SUCH DAMAGE.
        !            57:  *
        !            58:  * Justin Walker ([email protected]) Tue Sep 16 20:05:39 PDT 1997
        !            59:  * - Add filtering scheme to cut down on traffic when Y-adapter
        !            60:  *   enabled.
        !            61:  */
        !            62: 
        !            63: #include <sys/param.h>
        !            64: #include <sys/mbuf.h>
        !            65: #include <sys/systm.h>
        !            66: #include <sys/proc.h>
        !            67: #include <sys/socket.h>
        !            68: #include <sys/socketvar.h>
        !            69: #include <sys/protosw.h>
        !            70: #include <sys/kernel.h>
        !            71: #include <sys/ioctl.h>
        !            72: #include <sys/malloc.h>
        !            73: #include <sys/syslog.h>
        !            74: 
        !            75: #include <net/if.h>
        !            76: #include <net/if_dl.h>
        !            77: #include <net/if_types.h>
        !            78: 
        !            79: #if defined(ppc)
        !            80: #include <net/if_blue.h>
        !            81: #include <netinet/in.h>
        !            82: #endif /* ppc */
        !            83: 
        !            84: #include <machine/spl.h>
        !            85: 
        !            86: int    ifqmaxlen = IFQ_MAXLEN;
        !            87: struct ifnet   *ifnet;
        !            88: 
        !            89: void   if_slowtimo __P((void *arg));
        !            90: 
        !            91: /*
        !            92:  * Network interface utility routines.
        !            93:  *
        !            94:  * Routines with ifa_ifwith* names take sockaddr *'s as
        !            95:  * parameters.
        !            96:  */
        !            97: void
        !            98: ifinit()
        !            99: {
        !           100:        register struct ifnet *ifp;
        !           101: 
        !           102:        for (ifp = ifnet; ifp; ifp = ifp->if_next)
        !           103:                if (ifp->if_snd.ifq_maxlen == 0)
        !           104:                        ifp->if_snd.ifq_maxlen = ifqmaxlen;
        !           105: #ifdef not_needed
        !           106:        if_slowtimo(NULL);
        !           107: #endif 
        !           108:                
        !           109: }
        !           110: 
        !           111: int if_index = 0;
        !           112: struct ifaddr **ifnet_addrs;
        !           113: static char *sprint_d __P((u_int, char *, int));
        !           114: 
        !           115: /*
        !           116:  * Attach an interface to the
        !           117:  * list of "active" interfaces.
        !           118:  */
        !           119: void
        !           120: if_attach(ifp)
        !           121:        struct ifnet *ifp;
        !           122: {
        !           123:        unsigned socksize, ifasize;
        !           124:        int namelen, unitlen, masklen, ether_output();
        !           125:        char workbuf[12], *unitname;
        !           126:        register struct ifnet **p = &ifnet;
        !           127:        register struct sockaddr_dl *sdl;
        !           128:        register struct ifaddr *ifa;
        !           129:        static int if_indexlim = 8;
        !           130:        extern void link_rtrequest();
        !           131: 
        !           132:        while (*p)
        !           133:                p = &((*p)->if_next);
        !           134:        *p = ifp;
        !           135:        ifp->if_index = ++if_index;
        !           136:        if (ifnet_addrs == 0 || if_index >= if_indexlim) {
        !           137:                unsigned n = (if_indexlim <<= 1) * sizeof(ifa);
        !           138:                struct ifaddr **q = (struct ifaddr **)
        !           139:                        _MALLOC(n, M_IFADDR, M_WAITOK);
        !           140:                if (ifnet_addrs) {
        !           141:                        bcopy((caddr_t)ifnet_addrs, (caddr_t)q, n/2);
        !           142:                        _FREE((caddr_t)ifnet_addrs, M_IFADDR);
        !           143:                }
        !           144:                ifnet_addrs = q;
        !           145:        }
        !           146:        /*
        !           147:         * create a Link Level name for this device
        !           148:         */
        !           149:        unitname = sprint_d((u_int)ifp->if_unit, workbuf, sizeof(workbuf));
        !           150:        namelen = strlen(ifp->if_name);
        !           151:        unitlen = strlen(unitname);
        !           152: #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m))
        !           153:        masklen = _offsetof(struct sockaddr_dl, sdl_data[0]) +
        !           154:                               unitlen + namelen;
        !           155:        socksize = masklen + ifp->if_addrlen;
        !           156: #define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1)))
        !           157:        socksize = ROUNDUP(socksize);
        !           158:        if (socksize < sizeof(*sdl))
        !           159:                socksize = sizeof(*sdl);
        !           160:        ifasize = sizeof(*ifa) + 2 * socksize;
        !           161:        if ((ifa = (struct ifaddr *)_MALLOC(ifasize, M_IFADDR, M_WAITOK))) {
        !           162:                bzero((caddr_t) ifa, ifasize);
        !           163:                sdl = (struct sockaddr_dl *)(ifa + 1);
        !           164:                sdl->sdl_len = socksize;
        !           165:                sdl->sdl_family = AF_LINK;
        !           166:                bcopy(ifp->if_name, sdl->sdl_data, namelen);
        !           167:                bcopy(unitname, namelen + (caddr_t)sdl->sdl_data, unitlen);
        !           168:                sdl->sdl_nlen = (namelen += unitlen);
        !           169:                sdl->sdl_index = ifp->if_index;
        !           170:                sdl->sdl_type = ifp->if_type;
        !           171:                ifnet_addrs[if_index - 1] = ifa;
        !           172:                ifa->ifa_ifp = ifp;
        !           173:                ifa->ifa_next = ifp->if_addrlist;
        !           174:                ifa->ifa_rtrequest = link_rtrequest;
        !           175:                ifp->if_addrlist = ifa;
        !           176:                ifa->ifa_addr = (struct sockaddr *)sdl;
        !           177:                sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl);
        !           178:                ifa->ifa_netmask = (struct sockaddr *)sdl;
        !           179:                sdl->sdl_len = masklen;
        !           180:                while (namelen != 0)
        !           181:                        sdl->sdl_data[--namelen] = 0xff;
        !           182:                ifp->if_snd.ifq_maxlen = ifqmaxlen;
        !           183:        }
        !           184: }
        !           185: /*
        !           186:  * Locate an interface based on a complete address.
        !           187:  */
        !           188: /*ARGSUSED*/
        !           189: struct ifaddr *
        !           190: ifa_ifwithaddr(addr)
        !           191:        register struct sockaddr *addr;
        !           192: {
        !           193:        register struct ifnet *ifp;
        !           194:        register struct ifaddr *ifa;
        !           195: 
        !           196: #define        equal(a1, a2) \
        !           197:   (bcmp((caddr_t)(a1), (caddr_t)(a2), ((struct sockaddr *)(a1))->sa_len) == 0)
        !           198:        for (ifp = ifnet; ifp; ifp = ifp->if_next)
        !           199:            for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
        !           200:                if (ifa->ifa_addr->sa_family != addr->sa_family)
        !           201:                        continue;
        !           202:                if (equal(addr, ifa->ifa_addr))
        !           203:                        return (ifa);
        !           204:                if ((ifp->if_flags & IFF_BROADCAST) && ifa->ifa_broadaddr &&
        !           205:                    equal(ifa->ifa_broadaddr, addr))
        !           206:                        return (ifa);
        !           207:        }
        !           208:        return ((struct ifaddr *)0);
        !           209: }
        !           210: /*
        !           211:  * Locate the point to point interface with a given destination address.
        !           212:  */
        !           213: /*ARGSUSED*/
        !           214: struct ifaddr *
        !           215: ifa_ifwithdstaddr(addr)
        !           216:        register struct sockaddr *addr;
        !           217: {
        !           218:        register struct ifnet *ifp;
        !           219:        register struct ifaddr *ifa;
        !           220: 
        !           221:        for (ifp = ifnet; ifp; ifp = ifp->if_next) 
        !           222:            if (ifp->if_flags & IFF_POINTOPOINT)
        !           223:                for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
        !           224:                        if (ifa->ifa_addr->sa_family != addr->sa_family ||
        !           225:                            ifa->ifa_dstaddr == NULL)
        !           226:                                continue;
        !           227:                        if (equal(addr, ifa->ifa_dstaddr))
        !           228:                                return (ifa);
        !           229:        }
        !           230:        return ((struct ifaddr *)0);
        !           231: }
        !           232: 
        !           233: /*
        !           234:  * Find an interface on a specific network.  If many, choice
        !           235:  * is most specific found.
        !           236:  */
        !           237: struct ifaddr *
        !           238: ifa_ifwithnet(addr)
        !           239:        struct sockaddr *addr;
        !           240: {
        !           241:        register struct ifnet *ifp;
        !           242:        register struct ifaddr *ifa;
        !           243:        struct ifaddr *ifa_maybe = (struct ifaddr *) 0;
        !           244:        u_int af = addr->sa_family;
        !           245:        char *addr_data = addr->sa_data, *cplim;
        !           246:        extern int rn_refines(void *, void *);
        !           247: 
        !           248:        if (af == AF_LINK) {
        !           249:            register struct sockaddr_dl *sdl = (struct sockaddr_dl *)addr;
        !           250:            if (sdl->sdl_index && sdl->sdl_index <= if_index)
        !           251:                return (ifnet_addrs[sdl->sdl_index - 1]);
        !           252:        }
        !           253:        for (ifp = ifnet; ifp; ifp = ifp->if_next)
        !           254:            for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
        !           255:                register char *cp, *cp2, *cp3;
        !           256: 
        !           257:                if (ifa->ifa_addr->sa_family != af || ifa->ifa_netmask == 0)
        !           258:                        next: continue;
        !           259:                cp = addr_data;
        !           260:                cp2 = ifa->ifa_addr->sa_data;
        !           261:                cp3 = ifa->ifa_netmask->sa_data;
        !           262:                cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask;
        !           263:                while (cp3 < cplim)
        !           264:                        if ((*cp++ ^ *cp2++) & *cp3++)
        !           265:                                goto next;
        !           266:                if (ifa_maybe == 0 ||
        !           267:                    rn_refines((caddr_t)ifa->ifa_netmask,
        !           268:                    (caddr_t)ifa_maybe->ifa_netmask))
        !           269:                        ifa_maybe = ifa;
        !           270:            }
        !           271:        return (ifa_maybe);
        !           272: }
        !           273: 
        !           274: /*
        !           275:  * Find an interface using a specific address family
        !           276:  */
        !           277: struct ifaddr *
        !           278: ifa_ifwithaf(af)
        !           279:        register int af;
        !           280: {
        !           281:        register struct ifnet *ifp;
        !           282:        register struct ifaddr *ifa;
        !           283: 
        !           284:        for (ifp = ifnet; ifp; ifp = ifp->if_next)
        !           285:            for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
        !           286:                if (ifa->ifa_addr->sa_family == af)
        !           287:                        return (ifa);
        !           288:        return ((struct ifaddr *)0);
        !           289: }
        !           290: 
        !           291: /*
        !           292:  * Find an interface address specific to an interface best matching
        !           293:  * a given address.
        !           294:  */
        !           295: struct ifaddr *
        !           296: ifaof_ifpforaddr(addr, ifp)
        !           297:        struct sockaddr *addr;
        !           298:        register struct ifnet *ifp;
        !           299: {
        !           300:        register struct ifaddr *ifa;
        !           301:        register char *cp, *cp2, *cp3;
        !           302:        register char *cplim;
        !           303:        struct ifaddr *ifa_maybe = 0;
        !           304:        u_int af = addr->sa_family;
        !           305: 
        !           306:        if (af >= AF_MAX)
        !           307:                return (0);
        !           308:        for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
        !           309:                if (ifa->ifa_addr->sa_family != af)
        !           310:                        continue;
        !           311:                ifa_maybe = ifa;
        !           312:                if (ifa->ifa_netmask == 0) {
        !           313:                        if (equal(addr, ifa->ifa_addr) ||
        !           314:                            (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr)))
        !           315:                                return (ifa);
        !           316:                        continue;
        !           317:                }
        !           318:                cp = addr->sa_data;
        !           319:                cp2 = ifa->ifa_addr->sa_data;
        !           320:                cp3 = ifa->ifa_netmask->sa_data;
        !           321:                cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask;
        !           322:                for (; cp3 < cplim; cp3++)
        !           323:                        if ((*cp++ ^ *cp2++) & *cp3)
        !           324:                                break;
        !           325:                if (cp3 == cplim)
        !           326:                        return (ifa);
        !           327:        }
        !           328:        return (ifa_maybe);
        !           329: }
        !           330: 
        !           331: #include <net/route.h>
        !           332: 
        !           333: /*
        !           334:  * Default action when installing a route with a Link Level gateway.
        !           335:  * Lookup an appropriate real ifa to point to.
        !           336:  * This should be moved to /sys/net/link.c eventually.
        !           337:  */
        !           338: void
        !           339: link_rtrequest(cmd, rt, sa)
        !           340:        int cmd;
        !           341:        register struct rtentry *rt;
        !           342:        struct sockaddr *sa;
        !           343: {
        !           344:        register struct ifaddr *ifa;
        !           345:        struct sockaddr *dst;
        !           346:        struct ifnet *ifp;
        !           347: 
        !           348:        if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) ||
        !           349:            ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0))
        !           350:                return;
        !           351:        if ((ifa = ifaof_ifpforaddr(dst, ifp))) {
        !           352:                IFAFREE(rt->rt_ifa);
        !           353:                rt->rt_ifa = ifa;
        !           354:                ifa->ifa_refcnt++;
        !           355:                if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest)
        !           356:                        ifa->ifa_rtrequest(cmd, rt, sa);
        !           357:        }
        !           358: }
        !           359: 
        !           360: /*
        !           361:  * Mark an interface down and notify protocols of
        !           362:  * the transition.
        !           363:  * NOTE: must be called at splnet or eqivalent.
        !           364:  */
        !           365: void
        !           366: if_down(ifp)
        !           367:        register struct ifnet *ifp;
        !           368: {
        !           369:        register struct ifaddr *ifa;
        !           370:        extern void pfctlinput(int, struct sockaddr *);
        !           371: 
        !           372:        ifp->if_flags &= ~IFF_UP;
        !           373:        for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
        !           374:                pfctlinput(PRC_IFDOWN, ifa->ifa_addr);
        !           375:        if_qflush(&ifp->if_snd);
        !           376:        rt_ifmsg(ifp);
        !           377: }
        !           378: 
        !           379: /*
        !           380:  * Mark an interface up and notify protocols of
        !           381:  * the transition.
        !           382:  * NOTE: must be called at splnet or equivalent.
        !           383:  */
        !           384: void
        !           385: if_up(ifp)
        !           386:        register struct ifnet *ifp;
        !           387: {
        !           388: #ifdef notyet
        !           389:        register struct ifaddr *ifa;
        !           390: #endif
        !           391: 
        !           392:        ifp->if_flags |= IFF_UP;
        !           393: #ifdef notyet
        !           394:        /* this has no effect on IP, and will kill all ISO connections XXX */
        !           395:        for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
        !           396:                pfctlinput(PRC_IFUP, ifa->ifa_addr);
        !           397: #endif
        !           398:        rt_ifmsg(ifp);
        !           399: }
        !           400: 
        !           401: /*
        !           402:  * Flush an interface queue.
        !           403:  */
        !           404: void
        !           405: if_qflush(ifq)
        !           406:        register struct ifqueue *ifq;
        !           407: {
        !           408:        register struct mbuf *m, *n;
        !           409: 
        !           410:        n = ifq->ifq_head;
        !           411:        while ((m = n)) {
        !           412:                n = m->m_act;
        !           413:                m_freem(m);
        !           414:        }
        !           415:        ifq->ifq_head = 0;
        !           416:        ifq->ifq_tail = 0;
        !           417:        ifq->ifq_len = 0;
        !           418: }
        !           419: 
        !           420: /*
        !           421:  * Handle interface watchdog timer routines.  Called
        !           422:  * from softclock, we decrement timers (if set) and
        !           423:  * call the appropriate interface routine on expiration.
        !           424:  */
        !           425: void
        !           426: if_slowtimo(arg)
        !           427:        void *arg;
        !           428: {
        !           429:        register struct ifnet *ifp;
        !           430:        int s = splimp();
        !           431: 
        !           432:        for (ifp = ifnet; ifp; ifp = ifp->if_next) {
        !           433:                if (ifp->if_timer == 0 || --ifp->if_timer)
        !           434:                        continue;
        !           435:                if (ifp->if_watchdog)
        !           436:                        (*ifp->if_watchdog)(ifp->if_unit);
        !           437:        }
        !           438:        splx(s);
        !           439:        timeout(if_slowtimo, (void *)0, hz / IFNET_SLOWHZ);
        !           440: }
        !           441: 
        !           442: /*
        !           443:  * Map interface name to
        !           444:  * interface structure pointer.
        !           445:  */
        !           446: struct ifnet *
        !           447: ifunit(name)
        !           448:        register char *name;
        !           449: {
        !           450:        register char *cp;
        !           451:        register struct ifnet *ifp;
        !           452:        int unit;
        !           453:        unsigned len;
        !           454:        char *ep, c;
        !           455: 
        !           456:        for (cp = name; cp < name + IFNAMSIZ && *cp; cp++)
        !           457:                if (*cp >= '0' && *cp <= '9')
        !           458:                        break;
        !           459:        if (*cp == '\0' || cp == name + IFNAMSIZ)
        !           460:                return ((struct ifnet *)0);
        !           461:        /*
        !           462:         * Save first char of unit, and pointer to it,
        !           463:         * so we can put a null there to avoid matching
        !           464:         * initial substrings of interface names.
        !           465:         */
        !           466:        len = cp - name + 1;
        !           467:        c = *cp;
        !           468:        ep = cp;
        !           469:        for (unit = 0; *cp >= '0' && *cp <= '9'; )
        !           470:                unit = unit * 10 + *cp++ - '0';
        !           471:        *ep = 0;
        !           472:        for (ifp = ifnet; ifp; ifp = ifp->if_next) {
        !           473:                if (bcmp(ifp->if_name, name, len))
        !           474:                        continue;
        !           475:                if (unit == ifp->if_unit)
        !           476:                        break;
        !           477:        }
        !           478:        *ep = c;
        !           479:        return (ifp);
        !           480: }
        !           481: 
        !           482: /*
        !           483:  * Interface ioctls.
        !           484:  */
        !           485: int
        !           486: ifioctl(so, cmd, data, p)
        !           487:        struct socket *so;
        !           488:        u_long cmd;
        !           489:        caddr_t data;
        !           490:        struct proc *p;
        !           491: {
        !           492:        register struct ifnet *ifp;
        !           493:        register struct ifreq *ifr;
        !           494:        int error;
        !           495: #if defined(ppc)
        !           496:        extern int new_splitter(struct socket *);
        !           497:        void if_register(struct BlueFilter *);
        !           498: #endif /* ppc */
        !           499: 
        !           500:        switch (cmd) {
        !           501: 
        !           502:        case SIOCGIFCONF:
        !           503:        case OSIOCGIFCONF:
        !           504:                return (ifconf(cmd, data));
        !           505:        }
        !           506:        ifr = (struct ifreq *)data;
        !           507:        ifp = ifunit(ifr->ifr_name);
        !           508:        if (ifp == 0)
        !           509:                return (ENXIO);
        !           510:        switch (cmd) {
        !           511: 
        !           512: #if defined(ppc)
        !           513:        case SIOCSSPLITTER:
        !           514:                if ((error = new_splitter(so)))
        !           515:                        return(error);
        !           516:                break;
        !           517: 
        !           518:        case SIOCGSPLITTER:
        !           519:                ifr->ifr_data = (caddr_t)(ifp->if_flags & IFF_SPLITTER);
        !           520:                break;
        !           521: #endif /* ppc */
        !           522: 
        !           523:        case SIOCGIFFLAGS:
        !           524:                ifr->ifr_flags = ifp->if_flags;
        !           525:                break;
        !           526: 
        !           527:        case SIOCGIFMETRIC:
        !           528:                ifr->ifr_metric = ifp->if_metric;
        !           529:                break;
        !           530: 
        !           531:        case SIOCSIFFLAGS: 
        !           532:                if ((error = suser(p->p_ucred, &p->p_acflag)))
        !           533:                        return (error);
        !           534:                                                
        !           535:                if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) {
        !           536:                        int s = splimp();
        !           537:                        if_down(ifp);
        !           538:                        splx(s);
        !           539:                }
        !           540:                
        !           541:                if (ifr->ifr_flags & IFF_UP && (ifp->if_flags & IFF_UP) == 0) {
        !           542:                        int s = splimp();
        !           543:                        if_up(ifp);
        !           544:                        splx(s);
        !           545:                }
        !           546: 
        !           547:                ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) |
        !           548:                        (ifr->ifr_flags &~ IFF_CANTCHANGE);
        !           549:                if (ifp->if_ioctl)
        !           550:                        (void) (*ifp->if_ioctl)(ifp, cmd, data);
        !           551:                break;
        !           552: 
        !           553:        case SIOCSIFMETRIC:
        !           554:                if ((error = suser(p->p_ucred, &p->p_acflag)))
        !           555:                        return (error);
        !           556:                ifp->if_metric = ifr->ifr_metric;
        !           557:                break;
        !           558: 
        !           559:        case SIOCAUTOADDR:
        !           560:        case SIOCADDMULTI:
        !           561:        case SIOCDELMULTI:
        !           562:                if ((error = suser(p->p_ucred, &p->p_acflag)))
        !           563:                        return (error);
        !           564:                if (ifp->if_ioctl == NULL)
        !           565:                        return (EOPNOTSUPP);
        !           566:                return ((*ifp->if_ioctl)(ifp, cmd, data));
        !           567: 
        !           568:        default:
        !           569:                if (so->so_proto == 0)
        !           570:                        return (EOPNOTSUPP);
        !           571: #if !COMPAT_43
        !           572:                return ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
        !           573:                        cmd, data, ifp));
        !           574: #else
        !           575:            {
        !           576:                int ocmd = cmd;
        !           577: 
        !           578:                switch (cmd) {
        !           579: 
        !           580:                case SIOCSIFDSTADDR:
        !           581:                case SIOCSIFADDR:
        !           582:                case SIOCSIFBRDADDR:
        !           583:                case SIOCSIFNETMASK:
        !           584: #if BYTE_ORDER != BIG_ENDIAN
        !           585:                        if (ifr->ifr_addr.sa_family == 0 &&
        !           586:                            ifr->ifr_addr.sa_len < 16) {
        !           587:                                ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len;
        !           588:                                ifr->ifr_addr.sa_len = 16;
        !           589:                        }
        !           590: #else
        !           591:                        if (ifr->ifr_addr.sa_len == 0)
        !           592:                                ifr->ifr_addr.sa_len = 16;
        !           593: #endif
        !           594: #if defined(ppc)
        !           595: #define IFR2IN(ifr) ((struct in_addr *)&(ifr->ifr_addr))->s_addr
        !           596:                        if (ifr->ifr_addr.sa_family == AF_INET)
        !           597:                        {       /*
        !           598:                                 * If we have an address, and we're 'splitting',
        !           599:                                 *  register the address.  Note that this
        !           600:                                 *  is to handle the case of addresses
        !           601:                                 *  registered after the Blue Box starts.
        !           602:                                 */
        !           603:                                if ((ifp->if_flags & IFF_SPLITTER) &&
        !           604:                                    (IFR2IN(ifr) != 0))
        !           605:                                {       struct BlueFilter filter;
        !           606: 
        !           607:                                        filter.BF_flags = (BF_ALLOC|BF_IP);
        !           608:                                        filter.BF_address = IFR2IN(ifr);
        !           609:                                        log(LOG_WARNING,
        !           610:                                            "[2]IP registering %x",
        !           611:                                            filter.BF_address);
        !           612:                                        if_register(&filter);
        !           613:                                }
        !           614:                        }
        !           615: #endif
        !           616:                        /* Fall through! */
        !           617:                        break;
        !           618: 
        !           619:                case OSIOCGIFADDR:
        !           620:                        cmd = SIOCGIFADDR;
        !           621:                        break;
        !           622: 
        !           623:                case OSIOCGIFDSTADDR:
        !           624:                        cmd = SIOCGIFDSTADDR;
        !           625:                        break;
        !           626: 
        !           627:                case OSIOCGIFBRDADDR:
        !           628:                        cmd = SIOCGIFBRDADDR;
        !           629:                        break;
        !           630: 
        !           631:                case OSIOCGIFNETMASK:
        !           632:                        cmd = SIOCGIFNETMASK;
        !           633:                }
        !           634:                error =  ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
        !           635:                                                            cmd, data, ifp));
        !           636:                switch (ocmd) {
        !           637: 
        !           638:                case OSIOCGIFADDR:
        !           639:                case OSIOCGIFDSTADDR:
        !           640:                case OSIOCGIFBRDADDR:
        !           641:                case OSIOCGIFNETMASK:
        !           642:                        *(u_short *)&ifr->ifr_addr = ifr->ifr_addr.sa_family;
        !           643:                }
        !           644:                return (error);
        !           645: 
        !           646:            }
        !           647: #endif
        !           648:        }
        !           649:        return (0);
        !           650: }
        !           651: 
        !           652: /*
        !           653:  * Return interface configuration
        !           654:  * of system.  List may be used
        !           655:  * in later ioctl's (above) to get
        !           656:  * other information.
        !           657:  */
        !           658: /*ARGSUSED*/
        !           659: int
        !           660: ifconf(cmd, data)
        !           661:        u_long cmd;
        !           662:        caddr_t data;
        !           663: {
        !           664:        register struct ifconf *ifc = (struct ifconf *)data;
        !           665:        register struct ifnet *ifp = ifnet;
        !           666:        register struct ifaddr *ifa;
        !           667:        register char *cp, *ep;
        !           668:        struct ifreq ifr, *ifrp;
        !           669:        int space = ifc->ifc_len, error = 0;
        !           670: 
        !           671:        ifrp = ifc->ifc_req;
        !           672:        ep = ifr.ifr_name + sizeof (ifr.ifr_name) - 2;
        !           673:        for (; space > sizeof (ifr) && ifp; ifp = ifp->if_next) {
        !           674:                strncpy(ifr.ifr_name, ifp->if_name, sizeof(ifr.ifr_name) - 2);
        !           675:                for (cp = ifr.ifr_name; cp < ep && *cp; cp++)
        !           676:                        continue;
        !           677:                *cp++ = '0' + ifp->if_unit; *cp = '\0';
        !           678:                if ((ifa = ifp->if_addrlist) == 0) {
        !           679:                        bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
        !           680:                        error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
        !           681:                            sizeof(ifr));
        !           682:                        if (error)
        !           683:                                break;
        !           684:                        space -= sizeof (ifr), ifrp++;
        !           685:                } else 
        !           686:                    for ( ; space > sizeof (ifr) && ifa; ifa = ifa->ifa_next) {
        !           687:                        register struct sockaddr *sa = ifa->ifa_addr;
        !           688: #if COMPAT_43
        !           689: #define OLD_AF_MAX 17
        !           690:                        if (cmd == OSIOCGIFCONF) {
        !           691:                                /* We don't want to return any unknown interfaces */
        !           692:                                if (sa->sa_family < OLD_AF_MAX) {
        !           693:                                        struct osockaddr *osa =
        !           694:                                                (struct osockaddr *)&ifr.ifr_addr;
        !           695:                                        ifr.ifr_addr = *sa;
        !           696:                                        osa->sa_family = sa->sa_family;
        !           697:                                        error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
        !           698:                                                        sizeof (ifr));
        !           699:                                }
        !           700:                                ifrp++;
        !           701:                        } else
        !           702: #endif
        !           703:                        if (sa->sa_len <= sizeof(*sa)) {
        !           704:                                ifr.ifr_addr = *sa;
        !           705:                                error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
        !           706:                                                sizeof (ifr));
        !           707:                                ifrp++;
        !           708:                        } else {
        !           709:                                space -= sa->sa_len - sizeof(*sa);
        !           710:                                if (space < sizeof (ifr))
        !           711:                                        break;
        !           712:                                error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
        !           713:                                                sizeof (ifr.ifr_name));
        !           714:                                if (error == 0)
        !           715:                                    error = copyout((caddr_t)sa,
        !           716:                                      (caddr_t)&ifrp->ifr_addr, sa->sa_len);
        !           717:                                ifrp = (struct ifreq *)
        !           718:                                        (sa->sa_len + (caddr_t)&ifrp->ifr_addr);
        !           719:                        }
        !           720:                        if (error)
        !           721:                                break;
        !           722:                        space -= sizeof (ifr);
        !           723:                }
        !           724:        }
        !           725:        ifc->ifc_len -= space;
        !           726:        return (error);
        !           727: }
        !           728: 
        !           729: static char *
        !           730: sprint_d(n, buf, buflen)
        !           731:        u_int n;
        !           732:        char *buf;
        !           733:        int buflen;
        !           734: {
        !           735:        register char *cp = buf + buflen - 1;
        !           736: 
        !           737:        *cp = 0;
        !           738:        do {
        !           739:                cp--;
        !           740:                *cp = "0123456789"[n % 10];
        !           741:                n /= 10;
        !           742:        } while (n != 0);
        !           743:        return (cp);
        !           744: }
        !           745: 
        !           746: /*
        !           747:  * Shutdown all network activity.  Used boot() when halting
        !           748:  * system.
        !           749:  */
        !           750: int if_down_all(void)
        !           751: {
        !           752:        struct ifnet *ifp;
        !           753:        int s;
        !           754: 
        !           755:        s = splnet();
        !           756:        for (ifp = ifnet; ifp; ifp = ifp->if_next) {
        !           757:                if_down(ifp);
        !           758:        }
        !           759:        splx(s);
        !           760:        return(0);              /* Sheesh */
        !           761: }

unix.superglobalmegacorp.com

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