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

unix.superglobalmegacorp.com

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