Annotation of XNU/bsd/net/if.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) 1980, 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.c        8.3 (Berkeley) 1/4/94
        !            55:  */
        !            56: 
        !            57: /*
        !            58: #include "opt_compat.h"
        !            59: */
        !            60: 
        !            61: #include <sys/param.h>
        !            62: #include <sys/malloc.h>
        !            63: #include <sys/mbuf.h>
        !            64: #include <sys/systm.h>
        !            65: #include <sys/proc.h>
        !            66: #include <sys/socket.h>
        !            67: #include <sys/socketvar.h>
        !            68: #include <sys/protosw.h>
        !            69: #include <sys/kernel.h>
        !            70: #include <sys/sockio.h>
        !            71: #include <sys/syslog.h>
        !            72: #include <sys/sysctl.h>
        !            73: #include <net/if.h>
        !            74: #include <net/if_dl.h>
        !            75: #include <net/radix.h>
        !            76: #include <net/if_blue.h>
        !            77: #include <netinet/in.h>
        !            78: #include <net/dlil.h>
        !            79: 
        !            80: /*
        !            81:  * System initialization
        !            82:  */
        !            83: 
        !            84: static int ifconf __P((u_long, caddr_t));
        !            85: static void if_qflush __P((struct ifqueue *));
        !            86: static void link_rtrequest __P((int, struct rtentry *, struct sockaddr *));
        !            87: 
        !            88: MALLOC_DEFINE(M_IFADDR, "ifaddr", "interface address");
        !            89: MALLOC_DEFINE(M_IFMADDR, "ether_multi", "link-level multicast address");
        !            90: 
        !            91: int    ifqmaxlen = IFQ_MAXLEN;
        !            92: struct ifnethead ifnet;        /* depend on static init XXX */
        !            93: 
        !            94: /*
        !            95:  * Network interface utility routines.
        !            96:  *
        !            97:  * Routines with ifa_ifwith* names take sockaddr *'s as
        !            98:  * parameters.
        !            99:  *
        !           100:  * This routine assumes that it will be called at splimp() or higher.
        !           101:  */
        !           102: /* ARGSUSED*/
        !           103: 
        !           104: 
        !           105: int if_index = 0;
        !           106: struct ifaddr **ifnet_addrs;
        !           107: 
        !           108: 
        !           109: /*
        !           110:  * Attach an interface to the
        !           111:  * list of "active" interfaces.
        !           112:  */
        !           113: void
        !           114: old_if_attach(ifp)
        !           115:        struct ifnet *ifp;
        !           116: {
        !           117:        unsigned socksize, ifasize;
        !           118:        int namelen, masklen;
        !           119:        char workbuf[64];
        !           120:        register struct sockaddr_dl *sdl;
        !           121:        register struct ifaddr *ifa;
        !           122:        static int if_indexlim = 8;
        !           123: 
        !           124: 
        !           125:        if (ifp->if_snd.ifq_maxlen == 0)
        !           126:            ifp->if_snd.ifq_maxlen = ifqmaxlen;
        !           127: 
        !           128:        TAILQ_INSERT_TAIL(&ifnet, ifp, if_link);
        !           129:        ifp->if_index = ++if_index;
        !           130:        /*
        !           131:         * XXX -
        !           132:         * The old code would work if the interface passed a pre-existing
        !           133:         * chain of ifaddrs to this code.  We don't trust our callers to
        !           134:         * properly initialize the tailq, however, so we no longer allow
        !           135:         * this unlikely case.
        !           136:         */
        !           137:        TAILQ_INIT(&ifp->if_addrhead);
        !           138:        LIST_INIT(&ifp->if_multiaddrs);
        !           139:        getmicrotime(&ifp->if_lastchange);
        !           140:        if (ifnet_addrs == 0 || if_index >= if_indexlim) {
        !           141:                unsigned n = (if_indexlim <<= 1) * sizeof(ifa);
        !           142:                struct ifaddr **q = (struct ifaddr **)
        !           143:                                        _MALLOC(n, M_IFADDR, M_WAITOK);
        !           144:                bzero((caddr_t)q, n);
        !           145:                if (ifnet_addrs) {
        !           146:                        bcopy((caddr_t)ifnet_addrs, (caddr_t)q, n/2);
        !           147:                        FREE((caddr_t)ifnet_addrs, M_IFADDR);
        !           148:                }
        !           149:                ifnet_addrs = q;
        !           150:        }
        !           151:        /*
        !           152:         * create a Link Level name for this device
        !           153:         */
        !           154:        namelen = snprintf(workbuf, sizeof(workbuf),
        !           155:            "%s%d", ifp->if_name, ifp->if_unit);
        !           156: #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m))
        !           157:        masklen = _offsetof(struct sockaddr_dl, sdl_data[0]) + namelen;
        !           158:        socksize = masklen + ifp->if_addrlen;
        !           159: #define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1)))
        !           160:        if (socksize < sizeof(*sdl))
        !           161:                socksize = sizeof(*sdl);
        !           162:        socksize = ROUNDUP(socksize);
        !           163:        ifasize = sizeof(*ifa) + 2 * socksize;
        !           164:        ifa = (struct ifaddr *) _MALLOC(ifasize, M_IFADDR, M_WAITOK);
        !           165:        if (ifa) {
        !           166:                bzero((caddr_t)ifa, ifasize);
        !           167:                sdl = (struct sockaddr_dl *)(ifa + 1);
        !           168:                sdl->sdl_len = socksize;
        !           169:                sdl->sdl_family = AF_LINK;
        !           170:                bcopy(workbuf, sdl->sdl_data, namelen);
        !           171:                sdl->sdl_nlen = namelen;
        !           172:                sdl->sdl_index = ifp->if_index;
        !           173:                sdl->sdl_type = ifp->if_type;
        !           174:                ifnet_addrs[if_index - 1] = ifa;
        !           175:                ifa->ifa_ifp = ifp;
        !           176:                ifa->ifa_rtrequest = link_rtrequest;
        !           177:                ifa->ifa_addr = (struct sockaddr *)sdl;
        !           178:                sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl);
        !           179:                ifa->ifa_netmask = (struct sockaddr *)sdl;
        !           180:                sdl->sdl_len = masklen;
        !           181:                while (namelen != 0)
        !           182:                        sdl->sdl_data[--namelen] = 0xff;
        !           183:                TAILQ_INSERT_HEAD(&ifp->if_addrhead, ifa, ifa_link);
        !           184:        }
        !           185: }
        !           186: /*
        !           187:  * Locate an interface based on a complete address.
        !           188:  */
        !           189: /*ARGSUSED*/
        !           190: struct ifaddr *
        !           191: ifa_ifwithaddr(addr)
        !           192:        register struct sockaddr *addr;
        !           193: {
        !           194:        register struct ifnet *ifp;
        !           195:        register struct ifaddr *ifa;
        !           196: 
        !           197: #define        equal(a1, a2) \
        !           198:   (bcmp((caddr_t)(a1), (caddr_t)(a2), ((struct sockaddr *)(a1))->sa_len) == 0)
        !           199:        for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next)
        !           200:            for (ifa = ifp->if_addrhead.tqh_first; ifa; 
        !           201:                 ifa = ifa->ifa_link.tqe_next) {
        !           202:                if (ifa->ifa_addr->sa_family != addr->sa_family)
        !           203:                        continue;
        !           204:                if (equal(addr, ifa->ifa_addr))
        !           205:                        return (ifa);
        !           206:                if ((ifp->if_flags & IFF_BROADCAST) && ifa->ifa_broadaddr &&
        !           207:                    equal(ifa->ifa_broadaddr, addr))
        !           208:                        return (ifa);
        !           209:        }
        !           210:        return ((struct ifaddr *)0);
        !           211: }
        !           212: /*
        !           213:  * Locate the point to point interface with a given destination address.
        !           214:  */
        !           215: /*ARGSUSED*/
        !           216: struct ifaddr *
        !           217: ifa_ifwithdstaddr(addr)
        !           218:        register struct sockaddr *addr;
        !           219: {
        !           220:        register struct ifnet *ifp;
        !           221:        register struct ifaddr *ifa;
        !           222: 
        !           223:        for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next)
        !           224:            if (ifp->if_flags & IFF_POINTOPOINT)
        !           225:                for (ifa = ifp->if_addrhead.tqh_first; ifa; 
        !           226:                     ifa = ifa->ifa_link.tqe_next) {
        !           227:                        if (ifa->ifa_addr->sa_family != addr->sa_family)
        !           228:                                continue;
        !           229:                        if (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr))
        !           230:                                return (ifa);
        !           231:        }
        !           232:        return ((struct ifaddr *)0);
        !           233: }
        !           234: 
        !           235: /*
        !           236:  * Find an interface on a specific network.  If many, choice
        !           237:  * is most specific found.
        !           238:  */
        !           239: struct ifaddr *
        !           240: ifa_ifwithnet(addr)
        !           241:        struct sockaddr *addr;
        !           242: {
        !           243:        register struct ifnet *ifp;
        !           244:        register struct ifaddr *ifa;
        !           245:        struct ifaddr *ifa_maybe = (struct ifaddr *) 0;
        !           246:        u_int af = addr->sa_family;
        !           247:        char *addr_data = addr->sa_data, *cplim;
        !           248: 
        !           249:        /*
        !           250:         * AF_LINK addresses can be looked up directly by their index number,
        !           251:         * so do that if we can.
        !           252:         */
        !           253:        if (af == AF_LINK) {
        !           254:            register struct sockaddr_dl *sdl = (struct sockaddr_dl *)addr;
        !           255:            if (sdl->sdl_index && sdl->sdl_index <= if_index)
        !           256:                return (ifnet_addrs[sdl->sdl_index - 1]);
        !           257:        }
        !           258: 
        !           259:        /* 
        !           260:         * Scan though each interface, looking for ones that have
        !           261:         * addresses in this address family.
        !           262:         */
        !           263:        for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next) {
        !           264:                for (ifa = ifp->if_addrhead.tqh_first; ifa;
        !           265:                     ifa = ifa->ifa_link.tqe_next) {
        !           266:                        register char *cp, *cp2, *cp3;
        !           267: 
        !           268:                        if (ifa->ifa_addr->sa_family != af)
        !           269: next:                          continue;
        !           270:                        if (ifp->if_flags & IFF_POINTOPOINT) {
        !           271:                                /*
        !           272:                                 * This is a bit broken as it doesn't 
        !           273:                                 * take into account that the remote end may 
        !           274:                                 * be a single node in the network we are
        !           275:                                 * looking for.
        !           276:                                 * The trouble is that we don't know the 
        !           277:                                 * netmask for the remote end.
        !           278:                                 */
        !           279:                                if (ifa->ifa_dstaddr != 0
        !           280:                                    && equal(addr, ifa->ifa_dstaddr))
        !           281:                                        return (ifa);
        !           282:                        } else {
        !           283:                                /*
        !           284:                                 * if we have a special address handler,
        !           285:                                 * then use it instead of the generic one.
        !           286:                                 */
        !           287:                                if (ifa->ifa_claim_addr) {
        !           288:                                        if ((*ifa->ifa_claim_addr)(ifa, addr)) {
        !           289:                                                return (ifa);
        !           290:                                        } else {
        !           291:                                                continue;
        !           292:                                        }
        !           293:                                }
        !           294: 
        !           295:                                /*
        !           296:                                 * Scan all the bits in the ifa's address.
        !           297:                                 * If a bit dissagrees with what we are
        !           298:                                 * looking for, mask it with the netmask
        !           299:                                 * to see if it really matters.
        !           300:                                 * (A byte at a time)
        !           301:                                 */
        !           302:                                if (ifa->ifa_netmask == 0)
        !           303:                                        continue;
        !           304:                                cp = addr_data;
        !           305:                                cp2 = ifa->ifa_addr->sa_data;
        !           306:                                cp3 = ifa->ifa_netmask->sa_data;
        !           307:                                cplim = ifa->ifa_netmask->sa_len
        !           308:                                        + (char *)ifa->ifa_netmask;
        !           309:                                while (cp3 < cplim)
        !           310:                                        if ((*cp++ ^ *cp2++) & *cp3++)
        !           311:                                                goto next; /* next address! */
        !           312:                                /*
        !           313:                                 * If the netmask of what we just found
        !           314:                                 * is more specific than what we had before
        !           315:                                 * (if we had one) then remember the new one
        !           316:                                 * before continuing to search
        !           317:                                 * for an even better one.
        !           318:                                 */
        !           319:                                if (ifa_maybe == 0 ||
        !           320:                                    rn_refines((caddr_t)ifa->ifa_netmask,
        !           321:                                    (caddr_t)ifa_maybe->ifa_netmask))
        !           322:                                        ifa_maybe = ifa;
        !           323:                        }
        !           324:                }
        !           325:        }
        !           326:        return (ifa_maybe);
        !           327: }
        !           328: 
        !           329: /*
        !           330:  * Find an interface address specific to an interface best matching
        !           331:  * a given address.
        !           332:  */
        !           333: struct ifaddr *
        !           334: ifaof_ifpforaddr(addr, ifp)
        !           335:        struct sockaddr *addr;
        !           336:        register struct ifnet *ifp;
        !           337: {
        !           338:        register struct ifaddr *ifa;
        !           339:        register char *cp, *cp2, *cp3;
        !           340:        register char *cplim;
        !           341:        struct ifaddr *ifa_maybe = 0;
        !           342:        u_int af = addr->sa_family;
        !           343: 
        !           344:        if (af >= AF_MAX)
        !           345:                return (0);
        !           346:        for (ifa = ifp->if_addrhead.tqh_first; ifa; 
        !           347:             ifa = ifa->ifa_link.tqe_next) {
        !           348:                if (ifa->ifa_addr->sa_family != af)
        !           349:                        continue;
        !           350:                if (ifa_maybe == 0)
        !           351:                        ifa_maybe = ifa;
        !           352:                if (ifa->ifa_netmask == 0) {
        !           353:                        if (equal(addr, ifa->ifa_addr) ||
        !           354:                            (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr)))
        !           355:                                return (ifa);
        !           356:                        continue;
        !           357:                }
        !           358:                if (ifp->if_flags & IFF_POINTOPOINT) {
        !           359:                        if (equal(addr, ifa->ifa_dstaddr))
        !           360:                                return (ifa);
        !           361:                } else {
        !           362:                        cp = addr->sa_data;
        !           363:                        cp2 = ifa->ifa_addr->sa_data;
        !           364:                        cp3 = ifa->ifa_netmask->sa_data;
        !           365:                        cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask;
        !           366:                        for (; cp3 < cplim; cp3++)
        !           367:                                if ((*cp++ ^ *cp2++) & *cp3)
        !           368:                                        break;
        !           369:                        if (cp3 == cplim)
        !           370:                                return (ifa);
        !           371:                }
        !           372:        }
        !           373:        return (ifa_maybe);
        !           374: }
        !           375: 
        !           376: #include <net/route.h>
        !           377: 
        !           378: /*
        !           379:  * Default action when installing a route with a Link Level gateway.
        !           380:  * Lookup an appropriate real ifa to point to.
        !           381:  * This should be moved to /sys/net/link.c eventually.
        !           382:  */
        !           383: static void
        !           384: link_rtrequest(cmd, rt, sa)
        !           385:        int cmd;
        !           386:        register struct rtentry *rt;
        !           387:        struct sockaddr *sa;
        !           388: {
        !           389:        register struct ifaddr *ifa;
        !           390:        struct sockaddr *dst;
        !           391:        struct ifnet *ifp;
        !           392: 
        !           393:        if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) ||
        !           394:            ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0))
        !           395:                return;
        !           396:        ifa = ifaof_ifpforaddr(dst, ifp);
        !           397:        if (ifa) {
        !           398:                IFAFREE(rt->rt_ifa);
        !           399:                rt->rt_ifa = ifa;
        !           400:                ifa->ifa_refcnt++;
        !           401:                if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest)
        !           402:                        ifa->ifa_rtrequest(cmd, rt, sa);
        !           403:        }
        !           404: }
        !           405: 
        !           406: /*
        !           407:  * Mark an interface down and notify protocols of
        !           408:  * the transition.
        !           409:  * NOTE: must be called at splnet or eqivalent.
        !           410:  */
        !           411: void
        !           412: if_unroute(ifp, flag, fam)
        !           413:        register struct ifnet *ifp;
        !           414:        int flag, fam;
        !           415: {
        !           416:        register struct ifaddr *ifa;
        !           417: 
        !           418:        ifp->if_flags &= ~flag;
        !           419:        getmicrotime(&ifp->if_lastchange);
        !           420:        TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
        !           421:                if (fam == PF_UNSPEC || (fam == ifa->ifa_addr->sa_family))
        !           422:                        pfctlinput(PRC_IFDOWN, ifa->ifa_addr);
        !           423:        if_qflush(&ifp->if_snd);
        !           424:        rt_ifmsg(ifp);
        !           425: }
        !           426: 
        !           427: /*
        !           428:  * Mark an interface up and notify protocols of
        !           429:  * the transition.
        !           430:  * NOTE: must be called at splnet or eqivalent.
        !           431:  */
        !           432: void
        !           433: if_route(ifp, flag, fam)
        !           434:        register struct ifnet *ifp;
        !           435:        int flag, fam;
        !           436: {
        !           437:        register struct ifaddr *ifa;
        !           438: 
        !           439:        ifp->if_flags |= flag;
        !           440:        getmicrotime(&ifp->if_lastchange);
        !           441:        TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
        !           442:                if (fam == PF_UNSPEC || (fam == ifa->ifa_addr->sa_family))
        !           443:                        pfctlinput(PRC_IFUP, ifa->ifa_addr);
        !           444:        rt_ifmsg(ifp);
        !           445: }
        !           446: 
        !           447: /*
        !           448:  * Mark an interface down and notify protocols of
        !           449:  * the transition.
        !           450:  * NOTE: must be called at splnet or eqivalent.
        !           451:  */
        !           452: void
        !           453: if_down(ifp)
        !           454:        register struct ifnet *ifp;
        !           455: {
        !           456: 
        !           457:        if_unroute(ifp, IFF_UP, AF_UNSPEC);
        !           458: }
        !           459: 
        !           460: /*
        !           461:  * Mark an interface up and notify protocols of
        !           462:  * the transition.
        !           463:  * NOTE: must be called at splnet or eqivalent.
        !           464:  */
        !           465: void
        !           466: if_up(ifp)
        !           467:        register struct ifnet *ifp;
        !           468: {
        !           469: 
        !           470:        if_route(ifp, IFF_UP, AF_UNSPEC);
        !           471: }
        !           472: 
        !           473: /*
        !           474:  * Flush an interface queue.
        !           475:  */
        !           476: static void
        !           477: if_qflush(ifq)
        !           478:        register struct ifqueue *ifq;
        !           479: {
        !           480:        register struct mbuf *m, *n;
        !           481: 
        !           482:        n = ifq->ifq_head;
        !           483:        while ((m = n) != 0) {
        !           484:                n = m->m_act;
        !           485:                m_freem(m);
        !           486:        }
        !           487:        ifq->ifq_head = 0;
        !           488:        ifq->ifq_tail = 0;
        !           489:        ifq->ifq_len = 0;
        !           490: }
        !           491: 
        !           492: 
        !           493: /*
        !           494:  * Map interface name to
        !           495:  * interface structure pointer.
        !           496:  */
        !           497: struct ifnet *
        !           498: ifunit(name)
        !           499:        register char *name;
        !           500: {
        !           501:        char namebuf[IFNAMSIZ + 1];
        !           502:        register char *cp, *cp2;
        !           503:        char *end;
        !           504:        register struct ifnet *ifp;
        !           505:        int unit;
        !           506:        unsigned len;
        !           507:        register char c = '\0';
        !           508: 
        !           509:        /*
        !           510:         * Look for a non numeric part
        !           511:         */
        !           512:        end = name + IFNAMSIZ; 
        !           513:        cp2 = namebuf;
        !           514:        cp = name; 
        !           515:        while ((cp < end) && (c = *cp)) {
        !           516:                if (c >= '0' && c <= '9')
        !           517:                        break;
        !           518:                *cp2++ = c;
        !           519:                cp++;
        !           520:        }
        !           521:        if ((cp == end) || (c == '\0') || (cp == name))
        !           522:                return ((struct ifnet *)0);
        !           523:        *cp2 = '\0';
        !           524:        /*
        !           525:         * check we have a legal number (limit to 7 digits?)
        !           526:         */
        !           527:        len = cp - name + 1;
        !           528:        for (unit = 0;
        !           529:            ((c = *cp) >= '0') && (c <= '9') && (unit < 1000000); cp++ ) 
        !           530:                unit = (unit * 10) + (c - '0');
        !           531:        if (*cp != '\0')
        !           532:                return 0;       /* no trailing garbage allowed */
        !           533:        /*
        !           534:         * Now search all the interfaces for this name/number
        !           535:         */
        !           536:        for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next) {
        !           537:                if (bcmp(ifp->if_name, namebuf, len))
        !           538:                        continue;
        !           539:                if (unit == ifp->if_unit)
        !           540:                        break;
        !           541:        }
        !           542:        return (ifp);
        !           543: }
        !           544: 
        !           545: /*
        !           546:  * Interface ioctls.
        !           547:  */
        !           548: int
        !           549: ifioctl(so, cmd, data, p)
        !           550:        struct socket *so;
        !           551:        u_long cmd;
        !           552:        caddr_t data;
        !           553:        struct proc *p;
        !           554: {
        !           555:        register struct ifnet *ifp;
        !           556:        register struct ifreq *ifr;
        !           557:        int error;
        !           558:        extern int new_splitter(struct socket *);
        !           559:        void if_register(struct BlueFilter *);
        !           560: 
        !           561:        switch (cmd) {
        !           562: 
        !           563:        case SIOCGIFCONF:
        !           564:        case OSIOCGIFCONF:
        !           565:                return (ifconf(cmd, data));
        !           566:        }
        !           567:        ifr = (struct ifreq *)data;
        !           568:        ifp = ifunit(ifr->ifr_name);
        !           569:        if (ifp == 0)
        !           570:                return (ENXIO);
        !           571:        switch (cmd) {
        !           572: 
        !           573:        case SIOCSSPLITTER:
        !           574:                if ((error = new_splitter(so)))
        !           575:                        return(error);
        !           576:                break;
        !           577: 
        !           578:        case SIOCGSPLITTER:
        !           579:                ifr->ifr_data = (caddr_t)(ifp->if_flags & IFF_SPLITTER);
        !           580:                break;
        !           581: 
        !           582:        case SIOCGIFFLAGS:
        !           583:                ifr->ifr_flags = ifp->if_flags;
        !           584:                break;
        !           585: 
        !           586:        case SIOCGIFMETRIC:
        !           587:                ifr->ifr_metric = ifp->if_metric;
        !           588:                break;
        !           589: 
        !           590:        case SIOCGIFMTU:
        !           591:                ifr->ifr_mtu = ifp->if_mtu;
        !           592:                break;
        !           593: 
        !           594:        case SIOCGIFPHYS:
        !           595:                ifr->ifr_phys = ifp->if_physical;
        !           596:                break;
        !           597: 
        !           598:        case SIOCSIFFLAGS:
        !           599:                error = suser(p->p_ucred, &p->p_acflag);
        !           600:                if (error)
        !           601:                        return (error);
        !           602:                if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) {
        !           603:                        int s = splimp();
        !           604:                        if_down(ifp);
        !           605:                        splx(s);
        !           606:                }
        !           607:                if (ifr->ifr_flags & IFF_UP && (ifp->if_flags & IFF_UP) == 0) {
        !           608:                        int s = splimp();
        !           609:                        if_up(ifp);
        !           610:                        splx(s);
        !           611:                }
        !           612:                ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) |
        !           613:                        (ifr->ifr_flags &~ IFF_CANTCHANGE);
        !           614:                if (ifp->if_ioctl)
        !           615:                        dlil_ioctl(0, ifp, cmd, (caddr_t) data);
        !           616:                getmicrotime(&ifp->if_lastchange);
        !           617:                break;
        !           618: 
        !           619:        case SIOCSIFMETRIC:
        !           620:                error = suser(p->p_ucred, &p->p_acflag);
        !           621:                if (error)
        !           622:                        return (error);
        !           623:                ifp->if_metric = ifr->ifr_metric;
        !           624:                getmicrotime(&ifp->if_lastchange);
        !           625:                break;
        !           626: 
        !           627:        case SIOCSIFPHYS:
        !           628:                error = suser(p->p_ucred, &p->p_acflag);
        !           629:                if (error)
        !           630:                        return error;
        !           631:                if (!ifp->if_ioctl)
        !           632:                        return EOPNOTSUPP;
        !           633:                error = dlil_ioctl(0, ifp, cmd, (caddr_t) data);
        !           634:                if (error == 0)
        !           635:                        getmicrotime(&ifp->if_lastchange);
        !           636:                return(error);
        !           637: 
        !           638:        case SIOCSIFMTU:
        !           639:                error = suser(p->p_ucred, &p->p_acflag);
        !           640:                if (error)
        !           641:                        return (error);
        !           642:                if (ifp->if_ioctl == NULL)
        !           643:                        return (EOPNOTSUPP);
        !           644:                /*
        !           645:                 * 72 was chosen below because it is the size of a TCP/IP
        !           646:                 * header (40) + the minimum mss (32).
        !           647:                 */
        !           648:                if (ifr->ifr_mtu < 72 || ifr->ifr_mtu > 65535)
        !           649:                        return (EINVAL);
        !           650:                error = dlil_ioctl(0, ifp, cmd, (caddr_t) data);
        !           651:                if (error == 0)
        !           652:                        getmicrotime(&ifp->if_lastchange);
        !           653:                return(error);
        !           654: 
        !           655:        case SIOCADDMULTI:
        !           656:        case SIOCDELMULTI:
        !           657:                error = suser(p->p_ucred, &p->p_acflag);
        !           658:                if (error)
        !           659:                        return (error);
        !           660: 
        !           661:                /* Don't allow group membership on non-multicast interfaces. */
        !           662:                if ((ifp->if_flags & IFF_MULTICAST) == 0)
        !           663:                        return EOPNOTSUPP;
        !           664: 
        !           665: #if 0
        !           666:                /*
        !           667:                 * Don't let users change protocols' entries.
        !           668:                 */
        !           669:                if (ifr->ifr_addr.sa_family != AF_LINK)
        !           670:                        return EINVAL;
        !           671: #endif
        !           672:                if (cmd == SIOCADDMULTI) {
        !           673:                        struct ifmultiaddr *ifma;
        !           674:                        error = if_addmulti(ifp, &ifr->ifr_addr, &ifma);
        !           675:                } else {
        !           676:                        error = if_delmulti(ifp, &ifr->ifr_addr);
        !           677:                }
        !           678:                if (error == 0)
        !           679:                        getmicrotime(&ifp->if_lastchange);
        !           680:                return error;
        !           681: 
        !           682:         case SIOCSIFMEDIA:
        !           683:        case SIOCSIFGENERIC:
        !           684:                error = suser(p->p_ucred, &p->p_acflag);
        !           685:                if (error)
        !           686:                        return (error);
        !           687:                if (ifp->if_ioctl == 0)
        !           688:                        return (EOPNOTSUPP);
        !           689:                error = dlil_ioctl(0, ifp, cmd, (caddr_t) data);
        !           690:                if (error == 0)
        !           691:                        getmicrotime(&ifp->if_lastchange);
        !           692:                return error;
        !           693: 
        !           694:        case SIOCGIFMEDIA:
        !           695:        case SIOCGIFGENERIC:
        !           696:                if (ifp->if_ioctl == 0)
        !           697:                        return (EOPNOTSUPP);
        !           698:                return dlil_ioctl(0, ifp, cmd, (caddr_t) data);
        !           699: 
        !           700:        default:
        !           701:                if (so->so_proto == 0)
        !           702:                        return (EOPNOTSUPP);
        !           703: #if !COMPAT_43
        !           704:                return ((*so->so_proto->pr_usrreqs->pru_control)(so, cmd,
        !           705:                                                                 data,
        !           706:                                                                 ifp, p));
        !           707: #else
        !           708:            {
        !           709:                int ocmd = cmd;
        !           710: 
        !           711:                switch (cmd) {
        !           712: 
        !           713:                case SIOCSIFDSTADDR:
        !           714:                case SIOCSIFADDR:
        !           715:                case SIOCSIFBRDADDR:
        !           716:                case SIOCSIFNETMASK:
        !           717: #if BYTE_ORDER != BIG_ENDIAN
        !           718:                        if (ifr->ifr_addr.sa_family == 0 &&
        !           719:                            ifr->ifr_addr.sa_len < 16) {
        !           720:                                ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len;
        !           721:                                ifr->ifr_addr.sa_len = 16;
        !           722:                        }
        !           723: #else
        !           724:                        if (ifr->ifr_addr.sa_len == 0)
        !           725:                                ifr->ifr_addr.sa_len = 16;
        !           726: #endif
        !           727: #define IFR2IN(ifr) ((struct in_addr *)&(ifr->ifr_addr))->s_addr
        !           728:                        if (ifr->ifr_addr.sa_family == AF_INET)
        !           729:                        {       /*
        !           730:                                 * If we have an address, and we're 'splitting',
        !           731:                                 *  register the address.  Note that this
        !           732:                                 *  is to handle the case of addresses
        !           733:                                 *  registered after the Blue Box starts.
        !           734:                                 */
        !           735:                                if ((ifp->if_flags & IFF_SPLITTER) &&
        !           736:                                    (IFR2IN(ifr) != 0))
        !           737:                                {       struct BlueFilter filter;
        !           738: 
        !           739:                                        filter.BF_flags = (BF_ALLOC|BF_IP);
        !           740:                                        filter.BF_address = IFR2IN(ifr);
        !           741:                                        log(LOG_WARNING,
        !           742:                                            "[2]IP registering %x",
        !           743:                                            filter.BF_address);
        !           744:                                        if_register(&filter);
        !           745:                                }
        !           746:                        }
        !           747:                        /* Fall through! */
        !           748:                        break;
        !           749: 
        !           750:                case OSIOCGIFADDR:
        !           751:                        cmd = SIOCGIFADDR;
        !           752:                        break;
        !           753: 
        !           754:                case OSIOCGIFDSTADDR:
        !           755:                        cmd = SIOCGIFDSTADDR;
        !           756:                        break;
        !           757: 
        !           758:                case OSIOCGIFBRDADDR:
        !           759:                        cmd = SIOCGIFBRDADDR;
        !           760:                        break;
        !           761: 
        !           762:                case OSIOCGIFNETMASK:
        !           763:                        cmd = SIOCGIFNETMASK;
        !           764:                }
        !           765:                error =  ((*so->so_proto->pr_usrreqs->pru_control)(so,
        !           766:                                                                   cmd,
        !           767:                                                                   data,
        !           768:                                                                   ifp, p));
        !           769:                switch (ocmd) {
        !           770: 
        !           771:                case OSIOCGIFADDR:
        !           772:                case OSIOCGIFDSTADDR:
        !           773:                case OSIOCGIFBRDADDR:
        !           774:                case OSIOCGIFNETMASK:
        !           775:                        *(u_short *)&ifr->ifr_addr = ifr->ifr_addr.sa_family;
        !           776:                }
        !           777:                return (error);
        !           778: 
        !           779:            }
        !           780: #endif
        !           781:        }
        !           782:        return (0);
        !           783: }
        !           784: 
        !           785: /*
        !           786:  * Set/clear promiscuous mode on interface ifp based on the truth value
        !           787:  * of pswitch.  The calls are reference counted so that only the first
        !           788:  * "on" request actually has an effect, as does the final "off" request.
        !           789:  * Results are undefined if the "off" and "on" requests are not matched.
        !           790:  */
        !           791: int
        !           792: ifpromisc(ifp, pswitch)
        !           793:        struct ifnet *ifp;
        !           794:        int pswitch;
        !           795: {
        !           796:        struct ifreq ifr;
        !           797:        int error;
        !           798: 
        !           799:        if (pswitch) {
        !           800:                /*
        !           801:                 * If the device is not configured up, we cannot put it in
        !           802:                 * promiscuous mode.
        !           803:                 */
        !           804:                if ((ifp->if_flags & IFF_UP) == 0)
        !           805:                        return (ENETDOWN);
        !           806:                if (ifp->if_pcount++ != 0)
        !           807:                        return (0);
        !           808:                ifp->if_flags |= IFF_PROMISC;
        !           809:                log(LOG_INFO, "%s%d: promiscuous mode enabled\n",
        !           810:                    ifp->if_name, ifp->if_unit);
        !           811:        } else {
        !           812:                if (--ifp->if_pcount > 0)
        !           813:                        return (0);
        !           814:                ifp->if_flags &= ~IFF_PROMISC;
        !           815:        }
        !           816:        ifr.ifr_flags = ifp->if_flags;
        !           817:        error = dlil_ioctl(0, ifp, SIOCSIFFLAGS, (caddr_t)&ifr);
        !           818:        if (error == 0)
        !           819:                rt_ifmsg(ifp);
        !           820:        return error;
        !           821: }
        !           822: 
        !           823: /*
        !           824:  * Return interface configuration
        !           825:  * of system.  List may be used
        !           826:  * in later ioctl's (above) to get
        !           827:  * other information.
        !           828:  */
        !           829: /*ARGSUSED*/
        !           830: static int
        !           831: ifconf(cmd, data)
        !           832:        u_long cmd;
        !           833:        caddr_t data;
        !           834: {
        !           835:        register struct ifconf *ifc = (struct ifconf *)data;
        !           836:        register struct ifnet *ifp = ifnet.tqh_first;
        !           837:        register struct ifaddr *ifa;
        !           838:        struct ifreq ifr, *ifrp;
        !           839:        int space = ifc->ifc_len, error = 0;
        !           840: 
        !           841:        ifrp = ifc->ifc_req;
        !           842:        for (; space > sizeof (ifr) && ifp; ifp = ifp->if_link.tqe_next) {
        !           843:                char workbuf[64];
        !           844:                int ifnlen;
        !           845: 
        !           846:                ifnlen = snprintf(workbuf, sizeof(workbuf),
        !           847:                    "%s%d", ifp->if_name, ifp->if_unit);
        !           848:                if(ifnlen + 1 > sizeof ifr.ifr_name) {
        !           849:                        error = ENAMETOOLONG;
        !           850:                } else {
        !           851:                        strcpy(ifr.ifr_name, workbuf);
        !           852:                }
        !           853: 
        !           854:                if ((ifa = ifp->if_addrhead.tqh_first) == 0) {
        !           855:                        bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
        !           856:                        error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
        !           857:                            sizeof (ifr));
        !           858:                        if (error)
        !           859:                                break;
        !           860:                        space -= sizeof (ifr), ifrp++;
        !           861:                } else
        !           862:                    for ( ; space > sizeof (ifr) && ifa; 
        !           863:                         ifa = ifa->ifa_link.tqe_next) {
        !           864:                        register struct sockaddr *sa = ifa->ifa_addr;
        !           865: #if COMPAT_43
        !           866:                        if (cmd == OSIOCGIFCONF) {
        !           867:                                struct osockaddr *osa =
        !           868:                                         (struct osockaddr *)&ifr.ifr_addr;
        !           869:                                ifr.ifr_addr = *sa;
        !           870:                                osa->sa_family = sa->sa_family;
        !           871:                                error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
        !           872:                                                sizeof (ifr));
        !           873:                                ifrp++;
        !           874:                        } else
        !           875: #endif
        !           876:                        if (sa->sa_len <= sizeof(*sa)) {
        !           877:                                ifr.ifr_addr = *sa;
        !           878:                                error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
        !           879:                                                sizeof (ifr));
        !           880:                                ifrp++;
        !           881:                        } else {
        !           882:                                space -= sa->sa_len - sizeof(*sa);
        !           883:                                if (space < sizeof (ifr))
        !           884:                                        break;
        !           885:                                error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
        !           886:                                                sizeof (ifr.ifr_name));
        !           887:                                if (error == 0)
        !           888:                                    error = copyout((caddr_t)sa,
        !           889:                                      (caddr_t)&ifrp->ifr_addr, sa->sa_len);
        !           890:                                ifrp = (struct ifreq *)
        !           891:                                        (sa->sa_len + (caddr_t)&ifrp->ifr_addr);
        !           892:                        }
        !           893:                        if (error)
        !           894:                                break;
        !           895:                        space -= sizeof (ifr);
        !           896:                }
        !           897:        }
        !           898:        ifc->ifc_len -= space;
        !           899:        return (error);
        !           900: }
        !           901: 
        !           902: /*
        !           903:  * Just like if_promisc(), but for all-multicast-reception mode.
        !           904:  */
        !           905: int
        !           906: if_allmulti(ifp, onswitch)
        !           907:        struct ifnet *ifp;
        !           908:        int onswitch;
        !           909: {
        !           910:        int error = 0;
        !           911:        int s = splimp();
        !           912: 
        !           913:        if (onswitch) {
        !           914:                if (ifp->if_amcount++ == 0) {
        !           915:                        ifp->if_flags |= IFF_ALLMULTI;
        !           916:                        error = dlil_ioctl(0, ifp, SIOCSIFFLAGS, (caddr_t) 0);
        !           917:                }
        !           918:        } else {
        !           919:                if (ifp->if_amcount > 1) {
        !           920:                        ifp->if_amcount--;
        !           921:                } else {
        !           922:                        ifp->if_amcount = 0;
        !           923:                        ifp->if_flags &= ~IFF_ALLMULTI;
        !           924:                        error = dlil_ioctl(0, ifp, SIOCSIFFLAGS, (caddr_t) 0);
        !           925:                }
        !           926:        }
        !           927:        splx(s);
        !           928: 
        !           929:        if (error == 0)
        !           930:                rt_ifmsg(ifp);
        !           931:        return error;
        !           932: }
        !           933: 
        !           934: /*
        !           935:  * Add a multicast listenership to the interface in question.
        !           936:  * The link layer provides a routine which converts 
        !           937:  */
        !           938: int
        !           939: if_addmulti(ifp, sa, retifma)
        !           940:        struct ifnet *ifp;      /* interface to manipulate */
        !           941:        struct sockaddr *sa;    /* address to add */
        !           942:        struct ifmultiaddr **retifma;
        !           943: {
        !           944:        struct sockaddr *llsa, *dupsa;
        !           945:        int error, s;
        !           946:        struct ifmultiaddr *ifma;
        !           947: 
        !           948:        /*
        !           949:         * If the matching multicast address already exists
        !           950:         * then don't add a new one, just add a reference
        !           951:         */
        !           952:        for (ifma = ifp->if_multiaddrs.lh_first; ifma; 
        !           953:             ifma = ifma->ifma_link.le_next) {
        !           954:                if (equal(sa, ifma->ifma_addr)) {
        !           955:                        ifma->ifma_refcount++;
        !           956:                        if (retifma)
        !           957:                                *retifma = ifma;
        !           958:                        return 0;
        !           959:                }
        !           960:        }
        !           961: 
        !           962:        /*
        !           963:         * Give the link layer a chance to accept/reject it, and also
        !           964:         * find out which AF_LINK address this maps to, if it isn't one
        !           965:         * already.
        !           966:         */
        !           967:        if (ifp->if_resolvemulti) {
        !           968:                error = ifp->if_resolvemulti(ifp, &llsa, sa);
        !           969:                if (error) return error;
        !           970:        } else {
        !           971:                llsa = 0;
        !           972:        }
        !           973: 
        !           974:        MALLOC(ifma, struct ifmultiaddr *, sizeof *ifma, M_IFMADDR, M_WAITOK);
        !           975:        MALLOC(dupsa, struct sockaddr *, sa->sa_len, M_IFMADDR, M_WAITOK);
        !           976:        bcopy(sa, dupsa, sa->sa_len);
        !           977: 
        !           978:        ifma->ifma_addr = dupsa;
        !           979:        ifma->ifma_lladdr = llsa;
        !           980:        ifma->ifma_ifp = ifp;
        !           981:        ifma->ifma_refcount = 1;
        !           982:        ifma->ifma_protospec = 0;
        !           983:        rt_newmaddrmsg(RTM_NEWMADDR, ifma);
        !           984: 
        !           985:        /*
        !           986:         * Some network interfaces can scan the address list at
        !           987:         * interrupt time; lock them out.
        !           988:         */
        !           989:        s = splimp();
        !           990:        LIST_INSERT_HEAD(&ifp->if_multiaddrs, ifma, ifma_link);
        !           991:        splx(s);
        !           992:        if (retifma)
        !           993:            *retifma = ifma;
        !           994: 
        !           995:        if (llsa != 0) {
        !           996:                for (ifma = ifp->if_multiaddrs.lh_first; ifma;
        !           997:                     ifma = ifma->ifma_link.le_next) {
        !           998:                        if (equal(ifma->ifma_addr, llsa))
        !           999:                                break;
        !          1000:                }
        !          1001:                if (ifma) {
        !          1002:                        ifma->ifma_refcount++;
        !          1003:                } else {
        !          1004:                        MALLOC(ifma, struct ifmultiaddr *, sizeof *ifma,
        !          1005:                               M_IFMADDR, M_WAITOK);
        !          1006:                        MALLOC(dupsa, struct sockaddr *, llsa->sa_len,
        !          1007:                               M_IFMADDR, M_WAITOK);
        !          1008:                        bcopy(llsa, dupsa, llsa->sa_len);
        !          1009:                        ifma->ifma_addr = dupsa;
        !          1010:                        ifma->ifma_ifp = ifp;
        !          1011:                        ifma->ifma_refcount = 1;
        !          1012:                        s = splimp();
        !          1013:                        LIST_INSERT_HEAD(&ifp->if_multiaddrs, ifma, ifma_link);
        !          1014:                        splx(s);
        !          1015:                }
        !          1016:        }
        !          1017:        /*
        !          1018:         * We are certain we have added something, so call down to the
        !          1019:         * interface to let them know about it.
        !          1020:         */
        !          1021:        s = splimp();
        !          1022: 
        !          1023:        dlil_ioctl(0, ifp, SIOCADDMULTI, (caddr_t) 0);
        !          1024:        splx(s);
        !          1025: 
        !          1026:        return 0;
        !          1027: }
        !          1028: 
        !          1029: /*
        !          1030:  * Remove a reference to a multicast address on this interface.  Yell
        !          1031:  * if the request does not match an existing membership.
        !          1032:  */
        !          1033: int
        !          1034: if_delmulti(ifp, sa)
        !          1035:        struct ifnet *ifp;
        !          1036:        struct sockaddr *sa;
        !          1037: {
        !          1038:        struct ifmultiaddr *ifma;
        !          1039:        int s;
        !          1040: 
        !          1041:        for (ifma = ifp->if_multiaddrs.lh_first; ifma; 
        !          1042:             ifma = ifma->ifma_link.le_next)
        !          1043:                if (equal(sa, ifma->ifma_addr))
        !          1044:                        break;
        !          1045:        if (ifma == 0)
        !          1046:                return ENOENT;
        !          1047: 
        !          1048:        if (ifma->ifma_refcount > 1) {
        !          1049:                ifma->ifma_refcount--;
        !          1050:                return 0;
        !          1051:        }
        !          1052: 
        !          1053:        rt_newmaddrmsg(RTM_DELMADDR, ifma);
        !          1054:        sa = ifma->ifma_lladdr;
        !          1055:        s = splimp();
        !          1056:        LIST_REMOVE(ifma, ifma_link);
        !          1057:        splx(s);
        !          1058:        FREE(ifma->ifma_addr, M_IFMADDR);
        !          1059:        FREE(ifma, M_IFMADDR);
        !          1060:        if (sa == 0)
        !          1061:                return 0;
        !          1062: 
        !          1063:        /*
        !          1064:         * Now look for the link-layer address which corresponds to
        !          1065:         * this network address.  It had been squirreled away in
        !          1066:         * ifma->ifma_lladdr for this purpose (so we don't have
        !          1067:         * to call ifp->if_resolvemulti() again), and we saved that
        !          1068:         * value in sa above.  If some nasty deleted the
        !          1069:         * link-layer address out from underneath us, we can deal because
        !          1070:         * the address we stored was is not the same as the one which was
        !          1071:         * in the record for the link-layer address.  (So we don't complain
        !          1072:         * in that case.)
        !          1073:         */
        !          1074:        for (ifma = ifp->if_multiaddrs.lh_first; ifma; 
        !          1075:             ifma = ifma->ifma_link.le_next)
        !          1076:                if (equal(sa, ifma->ifma_addr))
        !          1077:                        break;
        !          1078:        if (ifma == 0)
        !          1079:                return 0;
        !          1080: 
        !          1081:        if (ifma->ifma_refcount > 1) {
        !          1082:                ifma->ifma_refcount--;
        !          1083:                return 0;
        !          1084:        }
        !          1085: 
        !          1086:        s = splimp();
        !          1087:        LIST_REMOVE(ifma, ifma_link);
        !          1088:        dlil_ioctl(0, ifp, SIOCDELMULTI, (caddr_t) 0);
        !          1089:        splx(s);
        !          1090:        FREE(ifma->ifma_addr, M_IFMADDR);
        !          1091:        FREE(sa, M_IFMADDR);
        !          1092:        FREE(ifma, M_IFMADDR);
        !          1093: 
        !          1094:        return 0;
        !          1095: }
        !          1096: 
        !          1097: struct ifmultiaddr *
        !          1098: ifmaof_ifpforaddr(sa, ifp)
        !          1099:        struct sockaddr *sa;
        !          1100:        struct ifnet *ifp;
        !          1101: {
        !          1102:        struct ifmultiaddr *ifma;
        !          1103:        
        !          1104:        for (ifma = ifp->if_multiaddrs.lh_first; ifma;
        !          1105:             ifma = ifma->ifma_link.le_next)
        !          1106:                if (equal(ifma->ifma_addr, sa))
        !          1107:                        break;
        !          1108: 
        !          1109:        return ifma;
        !          1110: }
        !          1111: 
        !          1112: SYSCTL_NODE(_net, PF_LINK, link, CTLFLAG_RW, 0, "Link layers");
        !          1113: SYSCTL_NODE(_net_link, 0, generic, CTLFLAG_RW, 0, "Generic link-management");
        !          1114: 
        !          1115: 
        !          1116: /*
        !          1117:  * Shutdown all network activity.  Used boot() when halting
        !          1118:  * system.
        !          1119:  */
        !          1120: int if_down_all(void)
        !          1121: {
        !          1122:        struct ifnet *ifp;
        !          1123:        int s;
        !          1124: 
        !          1125:        s = splnet();
        !          1126:        TAILQ_FOREACH(ifp, &ifnet, if_link)
        !          1127:                if_down(ifp);
        !          1128: 
        !          1129:        splx(s);
        !          1130:        return(0);              /* Sheesh */
        !          1131: }

unix.superglobalmegacorp.com

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