Annotation of Net2/net/if.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1980, 1986 Regents of the University of California.
        !             3:  * All rights reserved.
        !             4:  *
        !             5:  * Redistribution and use in source and binary forms, with or without
        !             6:  * modification, are permitted provided that the following conditions
        !             7:  * are met:
        !             8:  * 1. Redistributions of source code must retain the above copyright
        !             9:  *    notice, this list of conditions and the following disclaimer.
        !            10:  * 2. Redistributions in binary form must reproduce the above copyright
        !            11:  *    notice, this list of conditions and the following disclaimer in the
        !            12:  *    documentation and/or other materials provided with the distribution.
        !            13:  * 3. All advertising materials mentioning features or use of this software
        !            14:  *    must display the following acknowledgement:
        !            15:  *     This product includes software developed by the University of
        !            16:  *     California, Berkeley and its contributors.
        !            17:  * 4. Neither the name of the University nor the names of its contributors
        !            18:  *    may be used to endorse or promote products derived from this software
        !            19:  *    without specific prior written permission.
        !            20:  *
        !            21:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            22:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            23:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            24:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            25:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            26:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            27:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            28:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            29:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            30:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            31:  * SUCH DAMAGE.
        !            32:  *
        !            33:  *     @(#)if.c        7.14 (Berkeley) 4/20/91
        !            34:  */
        !            35: 
        !            36: #include "param.h"
        !            37: #include "mbuf.h"
        !            38: #include "systm.h"
        !            39: #include "socket.h"
        !            40: #include "socketvar.h"
        !            41: #include "protosw.h"
        !            42: #include "proc.h"
        !            43: #include "kernel.h"
        !            44: #include "ioctl.h"
        !            45: 
        !            46: #include "if.h"
        !            47: #include "af.h"
        !            48: #include "if_dl.h"
        !            49: #include "if_types.h"
        !            50: 
        !            51: #include "ether.h"
        !            52: 
        !            53: int    ifqmaxlen = IFQ_MAXLEN;
        !            54: 
        !            55: /*
        !            56:  * Network interface utility routines.
        !            57:  *
        !            58:  * Routines with ifa_ifwith* names take sockaddr *'s as
        !            59:  * parameters.
        !            60:  */
        !            61: 
        !            62: ifinit()
        !            63: {
        !            64:        register struct ifnet *ifp;
        !            65: 
        !            66:        for (ifp = ifnet; ifp; ifp = ifp->if_next)
        !            67:                if (ifp->if_snd.ifq_maxlen == 0)
        !            68:                        ifp->if_snd.ifq_maxlen = ifqmaxlen;
        !            69:        if_slowtimo();
        !            70: }
        !            71: 
        !            72: #ifdef vax
        !            73: /*
        !            74:  * Call each interface on a Unibus reset.
        !            75:  */
        !            76: ifubareset(uban)
        !            77:        int uban;
        !            78: {
        !            79:        register struct ifnet *ifp;
        !            80: 
        !            81:        for (ifp = ifnet; ifp; ifp = ifp->if_next)
        !            82:                if (ifp->if_reset)
        !            83:                        (*ifp->if_reset)(ifp->if_unit, uban);
        !            84: }
        !            85: #endif
        !            86: 
        !            87: int if_index = 0;
        !            88: struct ifaddr **ifnet_addrs;
        !            89: static char *sprint_d();
        !            90: 
        !            91: /*
        !            92:  * Attach an interface to the
        !            93:  * list of "active" interfaces.
        !            94:  */
        !            95: if_attach(ifp)
        !            96:        struct ifnet *ifp;
        !            97: {
        !            98:        unsigned socksize, ifasize;
        !            99:        int namelen, unitlen;
        !           100:        char workbuf[12], *unitname;
        !           101:        register struct ifnet **p = &ifnet;
        !           102:        register struct sockaddr_dl *sdl;
        !           103:        register struct ifaddr *ifa;
        !           104:        static int if_indexlim = 8;
        !           105:        extern link_rtrequest(), ether_output();
        !           106: 
        !           107:        while (*p)
        !           108:                p = &((*p)->if_next);
        !           109:        *p = ifp;
        !           110:        ifp->if_index = ++if_index;
        !           111:        if (ifnet_addrs == 0 || if_index >= if_indexlim) {
        !           112:                unsigned n = (if_indexlim <<= 1) * sizeof(ifa);
        !           113:                struct ifaddr **q = (struct ifaddr **)
        !           114:                                        malloc(n, M_IFADDR, M_WAITOK);
        !           115:                if (ifnet_addrs) {
        !           116:                        bcopy((caddr_t)ifnet_addrs, (caddr_t)q, n/2);
        !           117:                        free((caddr_t)ifnet_addrs, M_IFADDR);
        !           118:                }
        !           119:                ifnet_addrs = q;
        !           120:        }
        !           121:        /* XXX -- Temporary fix before changing 10 ethernet drivers */
        !           122:        if (ifp->if_output == ether_output) {
        !           123:                ifp->if_type = IFT_ETHER;
        !           124:                ifp->if_addrlen = 6;
        !           125:                ifp->if_hdrlen = 14;
        !           126:        }
        !           127:        /*
        !           128:         * create a Link Level name for this device
        !           129:         */
        !           130:        unitname = sprint_d((u_int)ifp->if_unit, workbuf, sizeof(workbuf));
        !           131:        namelen = strlen(ifp->if_name);
        !           132:        unitlen = strlen(unitname);
        !           133: #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m))
        !           134:        socksize = _offsetof(struct sockaddr_dl, sdl_data[0]) +
        !           135:                               unitlen + namelen + ifp->if_addrlen;
        !           136: #define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1)))
        !           137:        socksize = ROUNDUP(socksize);
        !           138:        if (socksize < sizeof(*sdl))
        !           139:                socksize = sizeof(*sdl);
        !           140:        ifasize = sizeof(*ifa) + 2 * socksize;
        !           141:        ifa = (struct ifaddr *)malloc(ifasize, M_IFADDR, M_WAITOK);
        !           142:        if (ifa == 0)
        !           143:                return;
        !           144:        ifnet_addrs[if_index - 1] = ifa;
        !           145:        bzero((caddr_t)ifa, ifasize);
        !           146:        sdl = (struct sockaddr_dl *)(ifa + 1);
        !           147:        ifa->ifa_addr = (struct sockaddr *)sdl;
        !           148:        ifa->ifa_ifp = ifp;
        !           149:        sdl->sdl_len = socksize;
        !           150:        sdl->sdl_family = AF_LINK;
        !           151:        bcopy(ifp->if_name, sdl->sdl_data, namelen);
        !           152:        bcopy(unitname, namelen + (caddr_t)sdl->sdl_data, unitlen);
        !           153:        sdl->sdl_nlen = (namelen += unitlen);
        !           154:        sdl->sdl_index = ifp->if_index;
        !           155:        sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl);
        !           156:        ifa->ifa_netmask = (struct sockaddr *)sdl;
        !           157:        sdl->sdl_len = socksize - ifp->if_addrlen;
        !           158:        while (namelen != 0)
        !           159:                sdl->sdl_data[--namelen] = 0xff;
        !           160:        ifa->ifa_next = ifp->if_addrlist;
        !           161:        ifa->ifa_rtrequest = link_rtrequest;
        !           162:        ifp->if_addrlist = ifa;
        !           163: }
        !           164: /*
        !           165:  * Locate an interface based on a complete address.
        !           166:  */
        !           167: /*ARGSUSED*/
        !           168: struct ifaddr *
        !           169: ifa_ifwithaddr(addr)
        !           170:        register struct sockaddr *addr;
        !           171: {
        !           172:        register struct ifnet *ifp;
        !           173:        register struct ifaddr *ifa;
        !           174: 
        !           175: #define        equal(a1, a2) \
        !           176:   (bcmp((caddr_t)(a1), (caddr_t)(a2), ((struct sockaddr *)(a1))->sa_len) == 0)
        !           177:        for (ifp = ifnet; ifp; ifp = ifp->if_next)
        !           178:            for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
        !           179:                if (ifa->ifa_addr->sa_family != addr->sa_family)
        !           180:                        continue;
        !           181:                if (equal(addr, ifa->ifa_addr))
        !           182:                        return (ifa);
        !           183:                if ((ifp->if_flags & IFF_BROADCAST) && ifa->ifa_broadaddr &&
        !           184:                    equal(ifa->ifa_broadaddr, addr))
        !           185:                        return (ifa);
        !           186:        }
        !           187:        return ((struct ifaddr *)0);
        !           188: }
        !           189: /*
        !           190:  * Locate the point to point interface with a given destination address.
        !           191:  */
        !           192: /*ARGSUSED*/
        !           193: struct ifaddr *
        !           194: ifa_ifwithdstaddr(addr)
        !           195:        register struct sockaddr *addr;
        !           196: {
        !           197:        register struct ifnet *ifp;
        !           198:        register struct ifaddr *ifa;
        !           199: 
        !           200:        for (ifp = ifnet; ifp; ifp = ifp->if_next) 
        !           201:            if (ifp->if_flags & IFF_POINTOPOINT)
        !           202:                for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
        !           203:                        if (ifa->ifa_addr->sa_family != addr->sa_family)
        !           204:                                continue;
        !           205:                        if (equal(addr, ifa->ifa_dstaddr))
        !           206:                                return (ifa);
        !           207:        }
        !           208:        return ((struct ifaddr *)0);
        !           209: }
        !           210: 
        !           211: /*
        !           212:  * Find an interface on a specific network.  If many, choice
        !           213:  * is first found.
        !           214:  */
        !           215: struct ifaddr *
        !           216: ifa_ifwithnet(addr)
        !           217:        struct sockaddr *addr;
        !           218: {
        !           219:        register struct ifnet *ifp;
        !           220:        register struct ifaddr *ifa;
        !           221:        u_int af = addr->sa_family;
        !           222: 
        !           223:        if (af >= AF_MAX)
        !           224:                return (0);
        !           225:        if (af == AF_LINK) {
        !           226:            register struct sockaddr_dl *sdl = (struct sockaddr_dl *)addr;
        !           227:            if (sdl->sdl_index && sdl->sdl_index <= if_index)
        !           228:                return (ifnet_addrs[sdl->sdl_index - 1]);
        !           229:        }
        !           230:        for (ifp = ifnet; ifp; ifp = ifp->if_next)
        !           231:            for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
        !           232:                register char *cp, *cp2, *cp3;
        !           233:                register char *cplim;
        !           234:                if (ifa->ifa_addr->sa_family != af || ifa->ifa_netmask == 0)
        !           235:                        continue;
        !           236:                cp = addr->sa_data;
        !           237:                cp2 = ifa->ifa_addr->sa_data;
        !           238:                cp3 = ifa->ifa_netmask->sa_data;
        !           239:                cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask;
        !           240:                for (; cp3 < cplim; cp3++)
        !           241:                        if ((*cp++ ^ *cp2++) & *cp3)
        !           242:                                break;
        !           243:                if (cp3 == cplim)
        !           244:                        return (ifa);
        !           245:            }
        !           246:        return ((struct ifaddr *)0);
        !           247: }
        !           248: 
        !           249: /*
        !           250:  * Find an interface using a specific address family
        !           251:  */
        !           252: struct ifaddr *
        !           253: ifa_ifwithaf(af)
        !           254:        register int af;
        !           255: {
        !           256:        register struct ifnet *ifp;
        !           257:        register struct ifaddr *ifa;
        !           258: 
        !           259:        for (ifp = ifnet; ifp; ifp = ifp->if_next)
        !           260:            for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
        !           261:                if (ifa->ifa_addr->sa_family == af)
        !           262:                        return (ifa);
        !           263:        return ((struct ifaddr *)0);
        !           264: }
        !           265: 
        !           266: /*
        !           267:  * Find an interface address specific to an interface best matching
        !           268:  * a given address.
        !           269:  */
        !           270: struct ifaddr *
        !           271: ifaof_ifpforaddr(addr, ifp)
        !           272:        struct sockaddr *addr;
        !           273:        register struct ifnet *ifp;
        !           274: {
        !           275:        register struct ifaddr *ifa;
        !           276:        register char *cp, *cp2, *cp3;
        !           277:        register char *cplim;
        !           278:        struct ifaddr *ifa_maybe = 0;
        !           279:        u_int af = addr->sa_family;
        !           280: 
        !           281:        if (af >= AF_MAX)
        !           282:                return (0);
        !           283:        for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
        !           284:                if (ifa->ifa_addr->sa_family != af)
        !           285:                        continue;
        !           286:                ifa_maybe = ifa;
        !           287:                if (ifa->ifa_netmask == 0) {
        !           288:                        if (equal(addr, ifa->ifa_addr) ||
        !           289:                            (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr)))
        !           290:                                return (ifa);
        !           291:                        continue;
        !           292:                }
        !           293:                cp = addr->sa_data;
        !           294:                cp2 = ifa->ifa_addr->sa_data;
        !           295:                cp3 = ifa->ifa_netmask->sa_data;
        !           296:                cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask;
        !           297:                for (; cp3 < cplim; cp3++)
        !           298:                        if ((*cp++ ^ *cp2++) & *cp3)
        !           299:                                break;
        !           300:                if (cp3 == cplim)
        !           301:                        return (ifa);
        !           302:        }
        !           303:        return (ifa_maybe);
        !           304: }
        !           305: #include "route.h"
        !           306: /*
        !           307:  * Default action when installing a route with a Link Level gateway.
        !           308:  * Lookup an appropriate real ifa to point to.
        !           309:  * This should be moved to /sys/net/link.c eventually.
        !           310:  */
        !           311: link_rtrequest(cmd, rt, sa)
        !           312: register struct rtentry *rt;
        !           313: struct sockaddr *sa;
        !           314: {
        !           315:        register struct ifaddr *ifa;
        !           316:        struct sockaddr *dst;
        !           317:        struct ifnet *ifp, *oldifnet = ifnet;
        !           318: 
        !           319:        if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) ||
        !           320:            ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0))
        !           321:                return;
        !           322:        if (ifa = ifaof_ifpforaddr(dst, ifp)) {
        !           323:                rt->rt_ifa = ifa;
        !           324:                if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest)
        !           325:                        ifa->ifa_rtrequest(cmd, rt, sa);
        !           326:        }
        !           327: }
        !           328: 
        !           329: /*
        !           330:  * Mark an interface down and notify protocols of
        !           331:  * the transition.
        !           332:  * NOTE: must be called at splnet or eqivalent.
        !           333:  */
        !           334: if_down(ifp)
        !           335:        register struct ifnet *ifp;
        !           336: {
        !           337:        register struct ifaddr *ifa;
        !           338: 
        !           339:        ifp->if_flags &= ~IFF_UP;
        !           340:        for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
        !           341:                pfctlinput(PRC_IFDOWN, ifa->ifa_addr);
        !           342:        if_qflush(&ifp->if_snd);
        !           343: }
        !           344: 
        !           345: /*
        !           346:  * Flush an interface queue.
        !           347:  */
        !           348: if_qflush(ifq)
        !           349:        register struct ifqueue *ifq;
        !           350: {
        !           351:        register struct mbuf *m, *n;
        !           352: 
        !           353:        n = ifq->ifq_head;
        !           354:        while (m = n) {
        !           355:                n = m->m_act;
        !           356:                m_freem(m);
        !           357:        }
        !           358:        ifq->ifq_head = 0;
        !           359:        ifq->ifq_tail = 0;
        !           360:        ifq->ifq_len = 0;
        !           361: }
        !           362: 
        !           363: /*
        !           364:  * Handle interface watchdog timer routines.  Called
        !           365:  * from softclock, we decrement timers (if set) and
        !           366:  * call the appropriate interface routine on expiration.
        !           367:  */
        !           368: if_slowtimo()
        !           369: {
        !           370:        register struct ifnet *ifp;
        !           371:        int s = splimp();
        !           372: 
        !           373:        for (ifp = ifnet; ifp; ifp = ifp->if_next) {
        !           374:                if (ifp->if_timer == 0 || --ifp->if_timer)
        !           375:                        continue;
        !           376:                if (ifp->if_watchdog)
        !           377:                        (*ifp->if_watchdog)(ifp->if_unit);
        !           378:        }
        !           379:        splx(s);
        !           380:        timeout(if_slowtimo, (caddr_t)0, hz / IFNET_SLOWHZ);
        !           381: }
        !           382: 
        !           383: /*
        !           384:  * Map interface name to
        !           385:  * interface structure pointer.
        !           386:  */
        !           387: struct ifnet *
        !           388: ifunit(name)
        !           389:        register char *name;
        !           390: {
        !           391:        register char *cp;
        !           392:        register struct ifnet *ifp;
        !           393:        int unit;
        !           394:        unsigned len;
        !           395:        char *ep, c;
        !           396: 
        !           397:        for (cp = name; cp < name + IFNAMSIZ && *cp; cp++)
        !           398:                if (*cp >= '0' && *cp <= '9')
        !           399:                        break;
        !           400:        if (*cp == '\0' || cp == name + IFNAMSIZ)
        !           401:                return ((struct ifnet *)0);
        !           402:        /*
        !           403:         * Save first char of unit, and pointer to it,
        !           404:         * so we can put a null there to avoid matching
        !           405:         * initial substrings of interface names.
        !           406:         */
        !           407:        len = cp - name + 1;
        !           408:        c = *cp;
        !           409:        ep = cp;
        !           410:        for (unit = 0; *cp >= '0' && *cp <= '9'; )
        !           411:                unit = unit * 10 + *cp++ - '0';
        !           412:        *ep = 0;
        !           413:        for (ifp = ifnet; ifp; ifp = ifp->if_next) {
        !           414:                if (bcmp(ifp->if_name, name, len))
        !           415:                        continue;
        !           416:                if (unit == ifp->if_unit)
        !           417:                        break;
        !           418:        }
        !           419:        *ep = c;
        !           420:        return (ifp);
        !           421: }
        !           422: 
        !           423: /*
        !           424:  * Interface ioctls.
        !           425:  */
        !           426: ifioctl(so, cmd, data, p)
        !           427:        struct socket *so;
        !           428:        int cmd;
        !           429:        caddr_t data;
        !           430:        struct proc *p;
        !           431: {
        !           432:        register struct ifnet *ifp;
        !           433:        register struct ifreq *ifr;
        !           434:        int error;
        !           435: 
        !           436:        switch (cmd) {
        !           437: 
        !           438:        case SIOCGIFCONF:
        !           439:        case OSIOCGIFCONF:
        !           440:                return (ifconf(cmd, data));
        !           441: 
        !           442: #if defined(INET) && NETHER > 0
        !           443:        case SIOCSARP:
        !           444:        case SIOCDARP:
        !           445:                if (error = suser(p->p_ucred, &p->p_acflag))
        !           446:                        return (error);
        !           447:                /* FALL THROUGH */
        !           448:        case SIOCGARP:
        !           449:        case OSIOCGARP:
        !           450:                return (arpioctl(cmd, data));
        !           451: #endif
        !           452:        }
        !           453:        ifr = (struct ifreq *)data;
        !           454:        ifp = ifunit(ifr->ifr_name);
        !           455:        if (ifp == 0)
        !           456:                return (ENXIO);
        !           457:        switch (cmd) {
        !           458: 
        !           459:        case SIOCGIFFLAGS:
        !           460:                ifr->ifr_flags = ifp->if_flags;
        !           461:                break;
        !           462: 
        !           463:        case SIOCGIFMETRIC:
        !           464:                ifr->ifr_metric = ifp->if_metric;
        !           465:                break;
        !           466: 
        !           467:        case SIOCSIFFLAGS:
        !           468:                if (error = suser(p->p_ucred, &p->p_acflag))
        !           469:                        return (error);
        !           470:                if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) {
        !           471:                        int s = splimp();
        !           472:                        if_down(ifp);
        !           473:                        splx(s);
        !           474:                }
        !           475:                ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) |
        !           476:                        (ifr->ifr_flags &~ IFF_CANTCHANGE);
        !           477:                if (ifp->if_ioctl)
        !           478:                        (void) (*ifp->if_ioctl)(ifp, cmd, data);
        !           479:                break;
        !           480: 
        !           481:        case SIOCSIFMETRIC:
        !           482:                if (error = suser(p->p_ucred, &p->p_acflag))
        !           483:                        return (error);
        !           484:                ifp->if_metric = ifr->ifr_metric;
        !           485:                break;
        !           486: 
        !           487:        default:
        !           488:                if (so->so_proto == 0)
        !           489:                        return (EOPNOTSUPP);
        !           490: #ifndef COMPAT_43
        !           491:                return ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
        !           492:                        cmd, data, ifp));
        !           493: #else
        !           494:            {
        !           495:                int ocmd = cmd;
        !           496: 
        !           497:                switch (cmd) {
        !           498: 
        !           499:                case SIOCSIFDSTADDR:
        !           500:                case SIOCSIFADDR:
        !           501:                case SIOCSIFBRDADDR:
        !           502:                case SIOCSIFNETMASK:
        !           503: #if BYTE_ORDER != BIG_ENDIAN
        !           504:                        if (ifr->ifr_addr.sa_family == 0 &&
        !           505:                            ifr->ifr_addr.sa_len < 16) {
        !           506:                                ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len;
        !           507:                                ifr->ifr_addr.sa_len = 16;
        !           508:                        }
        !           509: #else
        !           510:                        if (ifr->ifr_addr.sa_len == 0)
        !           511:                                ifr->ifr_addr.sa_len = 16;
        !           512: #endif
        !           513:                        break;
        !           514: 
        !           515:                case OSIOCGIFADDR:
        !           516:                        cmd = SIOCGIFADDR;
        !           517:                        break;
        !           518: 
        !           519:                case OSIOCGIFDSTADDR:
        !           520:                        cmd = SIOCGIFDSTADDR;
        !           521:                        break;
        !           522: 
        !           523:                case OSIOCGIFBRDADDR:
        !           524:                        cmd = SIOCGIFBRDADDR;
        !           525:                        break;
        !           526: 
        !           527:                case OSIOCGIFNETMASK:
        !           528:                        cmd = SIOCGIFNETMASK;
        !           529:                }
        !           530:                error =  ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
        !           531:                                                            cmd, data, ifp));
        !           532:                switch (ocmd) {
        !           533: 
        !           534:                case OSIOCGIFADDR:
        !           535:                case OSIOCGIFDSTADDR:
        !           536:                case OSIOCGIFBRDADDR:
        !           537:                case OSIOCGIFNETMASK:
        !           538:                        *(u_short *)&ifr->ifr_addr = ifr->ifr_addr.sa_family;
        !           539:                }
        !           540:                return (error);
        !           541: 
        !           542:            }
        !           543: #endif
        !           544:        }
        !           545:        return (0);
        !           546: }
        !           547: 
        !           548: /*
        !           549:  * Return interface configuration
        !           550:  * of system.  List may be used
        !           551:  * in later ioctl's (above) to get
        !           552:  * other information.
        !           553:  */
        !           554: /*ARGSUSED*/
        !           555: ifconf(cmd, data)
        !           556:        int cmd;
        !           557:        caddr_t data;
        !           558: {
        !           559:        register struct ifconf *ifc = (struct ifconf *)data;
        !           560:        register struct ifnet *ifp = ifnet;
        !           561:        register struct ifaddr *ifa;
        !           562:        register char *cp, *ep;
        !           563:        struct ifreq ifr, *ifrp;
        !           564:        int space = ifc->ifc_len, error = 0;
        !           565: 
        !           566:        ifrp = ifc->ifc_req;
        !           567:        ep = ifr.ifr_name + sizeof (ifr.ifr_name) - 2;
        !           568:        for (; space > sizeof (ifr) && ifp; ifp = ifp->if_next) {
        !           569:                bcopy(ifp->if_name, ifr.ifr_name, sizeof (ifr.ifr_name) - 2);
        !           570:                for (cp = ifr.ifr_name; cp < ep && *cp; cp++)
        !           571:                        ;
        !           572:                *cp++ = '0' + ifp->if_unit; *cp = '\0';
        !           573:                if ((ifa = ifp->if_addrlist) == 0) {
        !           574:                        bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
        !           575:                        error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof (ifr));
        !           576:                        if (error)
        !           577:                                break;
        !           578:                        space -= sizeof (ifr), ifrp++;
        !           579:                } else 
        !           580:                    for ( ; space > sizeof (ifr) && ifa; ifa = ifa->ifa_next) {
        !           581:                        register struct sockaddr *sa = ifa->ifa_addr;
        !           582: #ifdef COMPAT_43
        !           583:                        if (cmd == OSIOCGIFCONF) {
        !           584:                                struct osockaddr *osa =
        !           585:                                         (struct osockaddr *)&ifr.ifr_addr;
        !           586:                                ifr.ifr_addr = *sa;
        !           587:                                osa->sa_family = sa->sa_family;
        !           588:                                error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
        !           589:                                                sizeof (ifr));
        !           590:                                ifrp++;
        !           591:                        } else
        !           592: #endif
        !           593:                        if (sa->sa_len <= sizeof(*sa)) {
        !           594:                                ifr.ifr_addr = *sa;
        !           595:                                error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
        !           596:                                                sizeof (ifr));
        !           597:                                ifrp++;
        !           598:                        } else {
        !           599:                                space -= sa->sa_len - sizeof(*sa);
        !           600:                                if (space < sizeof (ifr))
        !           601:                                        break;
        !           602:                                error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
        !           603:                                                sizeof (ifr.ifr_name));
        !           604:                                if (error == 0)
        !           605:                                    error = copyout((caddr_t)sa,
        !           606:                                      (caddr_t)&ifrp->ifr_addr, sa->sa_len);
        !           607:                                ifrp = (struct ifreq *)
        !           608:                                        (sa->sa_len + (caddr_t)&ifrp->ifr_addr);
        !           609:                        }
        !           610:                        if (error)
        !           611:                                break;
        !           612:                        space -= sizeof (ifr);
        !           613:                }
        !           614:        }
        !           615:        ifc->ifc_len -= space;
        !           616:        return (error);
        !           617: }
        !           618: 
        !           619: static char *
        !           620: sprint_d(n, buf, buflen)
        !           621:        u_int n;
        !           622:        char *buf;
        !           623:        int buflen;
        !           624: {
        !           625:        register char *cp = buf + buflen - 1;
        !           626: 
        !           627:        *cp = 0;
        !           628:        do {
        !           629:                cp--;
        !           630:                *cp = "0123456789"[n % 10];
        !           631:                n /= 10;
        !           632:        } while (n != 0);
        !           633:        return (cp);
        !           634: }

unix.superglobalmegacorp.com

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