[BACK]Return to if.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / net

Annotation of src/sys/net/if.c, Revision 1.39.4.3

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

CVSweb <webmaster@jp.NetBSD.org>