[BACK]Return to if.c CVS log [TXT][DIR] Up to [local] / sys / net

Annotation of sys/net/if.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: if.c,v 1.165 2007/07/06 14:00:59 naddy Exp $  */
        !             2: /*     $NetBSD: if.c,v 1.35 1996/05/07 05:26:04 thorpej Exp $  */
        !             3:
        !             4: /*
        !             5:  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
        !             6:  * All rights reserved.
        !             7:  *
        !             8:  * Redistribution and use in source and binary forms, with or without
        !             9:  * modification, are permitted provided that the following conditions
        !            10:  * are met:
        !            11:  * 1. Redistributions of source code must retain the above copyright
        !            12:  *    notice, this list of conditions and the following disclaimer.
        !            13:  * 2. Redistributions in binary form must reproduce the above copyright
        !            14:  *    notice, this list of conditions and the following disclaimer in the
        !            15:  *    documentation and/or other materials provided with the distribution.
        !            16:  * 3. Neither the name of the project nor the names of its contributors
        !            17:  *    may be used to endorse or promote products derived from this software
        !            18:  *    without specific prior written permission.
        !            19:  *
        !            20:  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
        !            21:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            22:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            23:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
        !            24:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            25:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            26:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            27:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            28:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            29:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            30:  * SUCH DAMAGE.
        !            31:  */
        !            32:
        !            33: /*
        !            34:  * Copyright (c) 1980, 1986, 1993
        !            35:  *     The Regents of the University of California.  All rights reserved.
        !            36:  *
        !            37:  * Redistribution and use in source and binary forms, with or without
        !            38:  * modification, are permitted provided that the following conditions
        !            39:  * are met:
        !            40:  * 1. Redistributions of source code must retain the above copyright
        !            41:  *    notice, this list of conditions and the following disclaimer.
        !            42:  * 2. Redistributions in binary form must reproduce the above copyright
        !            43:  *    notice, this list of conditions and the following disclaimer in the
        !            44:  *    documentation and/or other materials provided with the distribution.
        !            45:  * 3. Neither the name of the University nor the names of its contributors
        !            46:  *    may be used to endorse or promote products derived from this software
        !            47:  *    without specific prior written permission.
        !            48:  *
        !            49:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            50:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            51:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            52:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            53:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            54:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            55:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            56:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            57:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            58:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            59:  * SUCH DAMAGE.
        !            60:  *
        !            61:  *     @(#)if.c        8.3 (Berkeley) 1/4/94
        !            62:  */
        !            63:
        !            64: #include "bluetooth.h"
        !            65: #include "bpfilter.h"
        !            66: #include "bridge.h"
        !            67: #include "carp.h"
        !            68: #include "pf.h"
        !            69: #include "trunk.h"
        !            70:
        !            71: #include <sys/param.h>
        !            72: #include <sys/systm.h>
        !            73: #include <sys/mbuf.h>
        !            74: #include <sys/proc.h>
        !            75: #include <sys/socket.h>
        !            76: #include <sys/socketvar.h>
        !            77: #include <sys/protosw.h>
        !            78: #include <sys/kernel.h>
        !            79: #include <sys/ioctl.h>
        !            80: #include <sys/domain.h>
        !            81: #include <sys/sysctl.h>
        !            82:
        !            83: #include <net/if.h>
        !            84: #include <net/if_dl.h>
        !            85: #include <net/if_media.h>
        !            86: #include <net/if_types.h>
        !            87: #include <net/route.h>
        !            88: #include <net/netisr.h>
        !            89:
        !            90: #include <dev/rndvar.h>
        !            91:
        !            92: #ifdef INET
        !            93: #include <netinet/in.h>
        !            94: #include <netinet/in_var.h>
        !            95: #include <netinet/if_ether.h>
        !            96: #include <netinet/igmp.h>
        !            97: #ifdef MROUTING
        !            98: #include <netinet/ip_mroute.h>
        !            99: #endif
        !           100: #endif
        !           101:
        !           102: #ifdef INET6
        !           103: #ifndef INET
        !           104: #include <netinet/in.h>
        !           105: #endif
        !           106: #include <netinet6/in6_ifattach.h>
        !           107: #include <netinet6/nd6.h>
        !           108: #endif
        !           109:
        !           110: #if NBPFILTER > 0
        !           111: #include <net/bpf.h>
        !           112: #endif
        !           113:
        !           114: #if NTRUNK > 0
        !           115: #include <net/if_trunk.h>
        !           116: #endif
        !           117:
        !           118: #if NBRIDGE > 0
        !           119: #include <net/if_bridge.h>
        !           120: #endif
        !           121:
        !           122: #if NCARP > 0
        !           123: #include <netinet/ip_carp.h>
        !           124: #endif
        !           125:
        !           126: #if NPF > 0
        !           127: #include <net/pfvar.h>
        !           128: #endif
        !           129:
        !           130: void   if_attachsetup(struct ifnet *);
        !           131: void   if_attachdomain1(struct ifnet *);
        !           132:
        !           133: int    ifqmaxlen = IFQ_MAXLEN;
        !           134:
        !           135: void   if_detach_queues(struct ifnet *, struct ifqueue *);
        !           136: void   if_detached_start(struct ifnet *);
        !           137: int    if_detached_ioctl(struct ifnet *, u_long, caddr_t);
        !           138: int    if_detached_init(struct ifnet *);
        !           139: void   if_detached_watchdog(struct ifnet *);
        !           140:
        !           141: int    if_getgroup(caddr_t, struct ifnet *);
        !           142: int    if_getgroupmembers(caddr_t);
        !           143: int    if_getgroupattribs(caddr_t);
        !           144: int    if_setgroupattribs(caddr_t);
        !           145:
        !           146: int    if_clone_list(struct if_clonereq *);
        !           147: struct if_clone        *if_clone_lookup(const char *, int *);
        !           148:
        !           149: void   if_congestion_clear(void *);
        !           150: int    if_group_egress_build(void);
        !           151:
        !           152: TAILQ_HEAD(, ifg_group) ifg_head;
        !           153: LIST_HEAD(, if_clone) if_cloners = LIST_HEAD_INITIALIZER(if_cloners);
        !           154: int if_cloners_count;
        !           155:
        !           156: /*
        !           157:  * Network interface utility routines.
        !           158:  *
        !           159:  * Routines with ifa_ifwith* names take sockaddr *'s as
        !           160:  * parameters.
        !           161:  */
        !           162: void
        !           163: ifinit()
        !           164: {
        !           165:        static struct timeout if_slowtim;
        !           166:
        !           167:        timeout_set(&if_slowtim, if_slowtimo, &if_slowtim);
        !           168:
        !           169:        if_slowtimo(&if_slowtim);
        !           170: }
        !           171:
        !           172: static int if_index = 0;
        !           173: int if_indexlim = 0;
        !           174: struct ifaddr **ifnet_addrs = NULL;
        !           175: struct ifnet **ifindex2ifnet = NULL;
        !           176: struct ifnet_head ifnet;
        !           177: struct ifnet *lo0ifp;
        !           178:
        !           179: /*
        !           180:  * Attach an interface to the
        !           181:  * list of "active" interfaces.
        !           182:  */
        !           183: void
        !           184: if_attachsetup(struct ifnet *ifp)
        !           185: {
        !           186:        struct ifaddr *ifa;
        !           187:        int wrapped = 0;
        !           188:
        !           189:        if (ifindex2ifnet == 0)
        !           190:                if_index = 1;
        !           191:        else {
        !           192:                while (if_index < if_indexlim &&
        !           193:                    ifindex2ifnet[if_index] != NULL) {
        !           194:                        if_index++;
        !           195:                        /*
        !           196:                         * If we hit USHRT_MAX, we skip back to 1 since
        !           197:                         * there are a number of places where the value
        !           198:                         * of ifp->if_index or if_index itself is compared
        !           199:                         * to or stored in an unsigned short.  By
        !           200:                         * jumping back, we won't botch those assignments
        !           201:                         * or comparisons.
        !           202:                         */
        !           203:                        if (if_index == USHRT_MAX) {
        !           204:                                if_index = 1;
        !           205:                                /*
        !           206:                                 * However, if we have to jump back to 1
        !           207:                                 * *twice* without finding an empty
        !           208:                                 * slot in ifindex2ifnet[], then there
        !           209:                                 * there are too many (>65535) interfaces.
        !           210:                                 */
        !           211:                                if (wrapped++)
        !           212:                                        panic("too many interfaces");
        !           213:                        }
        !           214:                }
        !           215:        }
        !           216:        ifp->if_index = if_index;
        !           217:
        !           218:        /*
        !           219:         * We have some arrays that should be indexed by if_index.
        !           220:         * since if_index will grow dynamically, they should grow too.
        !           221:         *      struct ifaddr **ifnet_addrs
        !           222:         *      struct ifnet **ifindex2ifnet
        !           223:         */
        !           224:        if (ifnet_addrs == 0 || ifindex2ifnet == 0 || if_index >= if_indexlim) {
        !           225:                size_t m, n, oldlim;
        !           226:                caddr_t q;
        !           227:
        !           228:                oldlim = if_indexlim;
        !           229:                if (if_indexlim == 0)
        !           230:                        if_indexlim = 8;
        !           231:                while (if_index >= if_indexlim)
        !           232:                        if_indexlim <<= 1;
        !           233:
        !           234:                /* grow ifnet_addrs */
        !           235:                m = oldlim * sizeof(ifa);
        !           236:                n = if_indexlim * sizeof(ifa);
        !           237:                q = (caddr_t)malloc(n, M_IFADDR, M_WAITOK);
        !           238:                bzero(q, n);
        !           239:                if (ifnet_addrs) {
        !           240:                        bcopy((caddr_t)ifnet_addrs, q, m);
        !           241:                        free((caddr_t)ifnet_addrs, M_IFADDR);
        !           242:                }
        !           243:                ifnet_addrs = (struct ifaddr **)q;
        !           244:
        !           245:                /* grow ifindex2ifnet */
        !           246:                m = oldlim * sizeof(struct ifnet *);
        !           247:                n = if_indexlim * sizeof(struct ifnet *);
        !           248:                q = (caddr_t)malloc(n, M_IFADDR, M_WAITOK);
        !           249:                bzero(q, n);
        !           250:                if (ifindex2ifnet) {
        !           251:                        bcopy((caddr_t)ifindex2ifnet, q, m);
        !           252:                        free((caddr_t)ifindex2ifnet, M_IFADDR);
        !           253:                }
        !           254:                ifindex2ifnet = (struct ifnet **)q;
        !           255:        }
        !           256:
        !           257:        TAILQ_INIT(&ifp->if_groups);
        !           258:
        !           259:        if_addgroup(ifp, IFG_ALL);
        !           260:
        !           261:        ifindex2ifnet[if_index] = ifp;
        !           262:
        !           263:        if (ifp->if_snd.ifq_maxlen == 0)
        !           264:                ifp->if_snd.ifq_maxlen = ifqmaxlen;
        !           265: #ifdef ALTQ
        !           266:        ifp->if_snd.altq_type = 0;
        !           267:        ifp->if_snd.altq_disc = NULL;
        !           268:        ifp->if_snd.altq_flags &= ALTQF_CANTCHANGE;
        !           269:        ifp->if_snd.altq_tbr  = NULL;
        !           270:        ifp->if_snd.altq_ifp  = ifp;
        !           271: #endif
        !           272:
        !           273:        if (domains)
        !           274:                if_attachdomain1(ifp);
        !           275: #if NPF > 0
        !           276:        pfi_attach_ifnet(ifp);
        !           277: #endif
        !           278:
        !           279:        /* Announce the interface. */
        !           280:        rt_ifannouncemsg(ifp, IFAN_ARRIVAL);
        !           281: }
        !           282:
        !           283: /*
        !           284:  * Allocate the link level name for the specified interface.  This
        !           285:  * is an attachment helper.  It must be called after ifp->if_addrlen
        !           286:  * is initialized, which may not be the case when if_attach() is
        !           287:  * called.
        !           288:  */
        !           289: void
        !           290: if_alloc_sadl(struct ifnet *ifp)
        !           291: {
        !           292:        unsigned socksize, ifasize;
        !           293:        int namelen, masklen;
        !           294:        struct sockaddr_dl *sdl;
        !           295:        struct ifaddr *ifa;
        !           296:
        !           297:        /*
        !           298:         * If the interface already has a link name, release it
        !           299:         * now.  This is useful for interfaces that can change
        !           300:         * link types, and thus switch link names often.
        !           301:         */
        !           302:        if (ifp->if_sadl != NULL)
        !           303:                if_free_sadl(ifp);
        !           304:
        !           305:        namelen = strlen(ifp->if_xname);
        !           306: #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m))
        !           307:        masklen = _offsetof(struct sockaddr_dl, sdl_data[0]) + namelen;
        !           308:        socksize = masklen + ifp->if_addrlen;
        !           309: #define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1)))
        !           310:        if (socksize < sizeof(*sdl))
        !           311:                socksize = sizeof(*sdl);
        !           312:        socksize = ROUNDUP(socksize);
        !           313:        ifasize = sizeof(*ifa) + 2 * socksize;
        !           314:        ifa = (struct ifaddr *)malloc(ifasize, M_IFADDR, M_WAITOK);
        !           315:        bzero((caddr_t)ifa, ifasize);
        !           316:        sdl = (struct sockaddr_dl *)(ifa + 1);
        !           317:        sdl->sdl_len = socksize;
        !           318:        sdl->sdl_family = AF_LINK;
        !           319:        bcopy(ifp->if_xname, sdl->sdl_data, namelen);
        !           320:        sdl->sdl_nlen = namelen;
        !           321:        sdl->sdl_alen = ifp->if_addrlen;
        !           322:        sdl->sdl_index = ifp->if_index;
        !           323:        sdl->sdl_type = ifp->if_type;
        !           324:        ifnet_addrs[ifp->if_index] = ifa;
        !           325:        ifa->ifa_ifp = ifp;
        !           326:        ifa->ifa_rtrequest = link_rtrequest;
        !           327:        TAILQ_INSERT_HEAD(&ifp->if_addrlist, ifa, ifa_list);
        !           328:        ifa->ifa_addr = (struct sockaddr *)sdl;
        !           329:        ifp->if_sadl = sdl;
        !           330:        sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl);
        !           331:        ifa->ifa_netmask = (struct sockaddr *)sdl;
        !           332:        sdl->sdl_len = masklen;
        !           333:        while (namelen != 0)
        !           334:                sdl->sdl_data[--namelen] = 0xff;
        !           335: }
        !           336:
        !           337: /*
        !           338:  * Free the link level name for the specified interface.  This is
        !           339:  * a detach helper.  This is called from if_detach() or from
        !           340:  * link layer type specific detach functions.
        !           341:  */
        !           342: void
        !           343: if_free_sadl(struct ifnet *ifp)
        !           344: {
        !           345:        struct ifaddr *ifa;
        !           346:        int s;
        !           347:
        !           348:        ifa = ifnet_addrs[ifp->if_index];
        !           349:        if (ifa == NULL)
        !           350:                return;
        !           351:
        !           352:        s = splnet();
        !           353:        rtinit(ifa, RTM_DELETE, 0);
        !           354: #if 0
        !           355:        TAILQ_REMOVE(&ifp->if_addrlist, ifa, ifa_list);
        !           356:        ifnet_addrs[ifp->if_index] = NULL;
        !           357: #endif
        !           358:        ifp->if_sadl = NULL;
        !           359:
        !           360:        splx(s);
        !           361: }
        !           362:
        !           363: void
        !           364: if_attachdomain()
        !           365: {
        !           366:        struct ifnet *ifp;
        !           367:        int s;
        !           368:
        !           369:        s = splnet();
        !           370:        for (ifp = TAILQ_FIRST(&ifnet); ifp; ifp = TAILQ_NEXT(ifp, if_list))
        !           371:                if_attachdomain1(ifp);
        !           372:        splx(s);
        !           373: }
        !           374:
        !           375: void
        !           376: if_attachdomain1(struct ifnet *ifp)
        !           377: {
        !           378:        struct domain *dp;
        !           379:        int s;
        !           380:
        !           381:        s = splnet();
        !           382:
        !           383:        /* address family dependent data region */
        !           384:        bzero(ifp->if_afdata, sizeof(ifp->if_afdata));
        !           385:        for (dp = domains; dp; dp = dp->dom_next) {
        !           386:                if (dp->dom_ifattach)
        !           387:                        ifp->if_afdata[dp->dom_family] =
        !           388:                            (*dp->dom_ifattach)(ifp);
        !           389:        }
        !           390:
        !           391:        splx(s);
        !           392: }
        !           393:
        !           394: void
        !           395: if_attachhead(struct ifnet *ifp)
        !           396: {
        !           397:        if (if_index == 0) {
        !           398:                TAILQ_INIT(&ifnet);
        !           399:                TAILQ_INIT(&ifg_head);
        !           400:        }
        !           401:        TAILQ_INIT(&ifp->if_addrlist);
        !           402:        ifp->if_addrhooks = malloc(sizeof(*ifp->if_addrhooks),
        !           403:            M_TEMP, M_NOWAIT);
        !           404:        if (ifp->if_addrhooks == NULL)
        !           405:                panic("if_attachhead: malloc");
        !           406:        TAILQ_INIT(ifp->if_addrhooks);
        !           407:        ifp->if_linkstatehooks = malloc(sizeof(*ifp->if_linkstatehooks),
        !           408:            M_TEMP, M_NOWAIT);
        !           409:        if (ifp->if_linkstatehooks == NULL)
        !           410:                panic("if_attachhead: malloc");
        !           411:        TAILQ_INIT(ifp->if_linkstatehooks);
        !           412:        ifp->if_detachhooks = malloc(sizeof(*ifp->if_detachhooks),
        !           413:            M_TEMP, M_NOWAIT);
        !           414:        if (ifp->if_detachhooks == NULL)
        !           415:                panic("if_attachhead: malloc");
        !           416:        TAILQ_INIT(ifp->if_detachhooks);
        !           417:        TAILQ_INSERT_HEAD(&ifnet, ifp, if_list);
        !           418:        if_attachsetup(ifp);
        !           419: }
        !           420:
        !           421: void
        !           422: if_attach(struct ifnet *ifp)
        !           423: {
        !           424: #if NCARP > 0
        !           425:        struct ifnet *before = NULL;
        !           426: #endif
        !           427:
        !           428:        if (if_index == 0) {
        !           429:                TAILQ_INIT(&ifnet);
        !           430:                TAILQ_INIT(&ifg_head);
        !           431:        }
        !           432:        TAILQ_INIT(&ifp->if_addrlist);
        !           433:        ifp->if_addrhooks = malloc(sizeof(*ifp->if_addrhooks),
        !           434:            M_TEMP, M_NOWAIT);
        !           435:        if (ifp->if_addrhooks == NULL)
        !           436:                panic("if_attach: malloc");
        !           437:        TAILQ_INIT(ifp->if_addrhooks);
        !           438:        ifp->if_linkstatehooks = malloc(sizeof(*ifp->if_linkstatehooks),
        !           439:            M_TEMP, M_NOWAIT);
        !           440:        if (ifp->if_linkstatehooks == NULL)
        !           441:                panic("if_attach: malloc");
        !           442:        TAILQ_INIT(ifp->if_linkstatehooks);
        !           443:        ifp->if_detachhooks = malloc(sizeof(*ifp->if_detachhooks),
        !           444:            M_TEMP, M_NOWAIT);
        !           445:        if (ifp->if_detachhooks == NULL)
        !           446:                panic("if_attach: malloc");
        !           447:        TAILQ_INIT(ifp->if_detachhooks);
        !           448:
        !           449: #if NCARP > 0
        !           450:        if (ifp->if_type != IFT_CARP)
        !           451:                TAILQ_FOREACH(before, &ifnet, if_list)
        !           452:                        if (before->if_type == IFT_CARP)
        !           453:                                break;
        !           454:        if (before == NULL)
        !           455:                TAILQ_INSERT_TAIL(&ifnet, ifp, if_list);
        !           456:        else
        !           457:                TAILQ_INSERT_BEFORE(before, ifp, if_list);
        !           458: #else
        !           459:        TAILQ_INSERT_TAIL(&ifnet, ifp, if_list);
        !           460: #endif
        !           461:
        !           462:        if_attachsetup(ifp);
        !           463: }
        !           464:
        !           465: /*
        !           466:  * Detach an interface from everything in the kernel.  Also deallocate
        !           467:  * private resources.
        !           468:  * XXX So far only the INET protocol family has been looked over
        !           469:  * wrt resource usage that needs to be decoupled.
        !           470:  */
        !           471: void
        !           472: if_detach(struct ifnet *ifp)
        !           473: {
        !           474:        struct ifaddr *ifa;
        !           475:        struct ifg_list *ifg;
        !           476:        int s = splnet();
        !           477:        struct domain *dp;
        !           478:
        !           479:        ifp->if_flags &= ~IFF_OACTIVE;
        !           480:        ifp->if_start = if_detached_start;
        !           481:        ifp->if_ioctl = if_detached_ioctl;
        !           482:        ifp->if_init = if_detached_init;
        !           483:        ifp->if_watchdog = if_detached_watchdog;
        !           484:
        !           485:        /* Call detach hooks, ie. to remove vlan interfaces */
        !           486:        dohooks(ifp->if_detachhooks, HOOK_REMOVE | HOOK_FREE);
        !           487:
        !           488: #if NTRUNK > 0
        !           489:        if (ifp->if_type == IFT_IEEE8023ADLAG)
        !           490:                trunk_port_ifdetach(ifp);
        !           491: #endif
        !           492:
        !           493: #if NBRIDGE > 0
        !           494:        /* Remove the interface from any bridge it is part of.  */
        !           495:        if (ifp->if_bridge)
        !           496:                bridge_ifdetach(ifp);
        !           497: #endif
        !           498:
        !           499: #if NCARP > 0
        !           500:        /* Remove the interface from any carp group it is a part of.  */
        !           501:        if (ifp->if_carp && ifp->if_type != IFT_CARP)
        !           502:                carp_ifdetach(ifp);
        !           503: #endif
        !           504:
        !           505: #if NBPFILTER > 0
        !           506:        bpfdetach(ifp);
        !           507: #endif
        !           508: #ifdef ALTQ
        !           509:        if (ALTQ_IS_ENABLED(&ifp->if_snd))
        !           510:                altq_disable(&ifp->if_snd);
        !           511:        if (ALTQ_IS_ATTACHED(&ifp->if_snd))
        !           512:                altq_detach(&ifp->if_snd);
        !           513: #endif
        !           514:        rt_if_remove(ifp);
        !           515: #ifdef INET
        !           516:        rti_delete(ifp);
        !           517: #if NETHER > 0
        !           518:        myip_ifp = NULL;
        !           519: #endif
        !           520: #ifdef MROUTING
        !           521:        vif_delete(ifp);
        !           522: #endif
        !           523: #endif
        !           524: #ifdef INET6
        !           525:        in6_ifdetach(ifp);
        !           526: #endif
        !           527:
        !           528: #if NPF > 0
        !           529:        pfi_detach_ifnet(ifp);
        !           530: #endif
        !           531:
        !           532:        /*
        !           533:         * remove packets came from ifp, from software interrupt queues.
        !           534:         * net/netisr_dispatch.h is not usable, as some of them use
        !           535:         * strange queue names.
        !           536:         */
        !           537: #define IF_DETACH_QUEUES(x) \
        !           538: do { \
        !           539:        extern struct ifqueue x; \
        !           540:        if_detach_queues(ifp, & x); \
        !           541: } while (0)
        !           542: #ifdef INET
        !           543:        IF_DETACH_QUEUES(arpintrq);
        !           544:        IF_DETACH_QUEUES(ipintrq);
        !           545: #endif
        !           546: #ifdef INET6
        !           547:        IF_DETACH_QUEUES(ip6intrq);
        !           548: #endif
        !           549: #ifdef NETATALK
        !           550:        IF_DETACH_QUEUES(atintrq1);
        !           551:        IF_DETACH_QUEUES(atintrq2);
        !           552: #endif
        !           553: #ifdef NATM
        !           554:        IF_DETACH_QUEUES(natmintrq);
        !           555: #endif
        !           556: #undef IF_DETACH_QUEUES
        !           557:
        !           558:        /*
        !           559:         * XXX transient ifp refs?  inpcb.ip_moptions.imo_multicast_ifp?
        !           560:         * Other network stacks than INET?
        !           561:         */
        !           562:
        !           563:        /* Remove the interface from the list of all interfaces.  */
        !           564:        TAILQ_REMOVE(&ifnet, ifp, if_list);
        !           565:
        !           566:        /*
        !           567:         * Deallocate private resources.
        !           568:         */
        !           569:        while ((ifa = TAILQ_FIRST(&ifp->if_addrlist)) != NULL) {
        !           570:                TAILQ_REMOVE(&ifp->if_addrlist, ifa, ifa_list);
        !           571: #ifdef INET
        !           572:                if (ifa->ifa_addr->sa_family == AF_INET)
        !           573:                        TAILQ_REMOVE(&in_ifaddr, (struct in_ifaddr *)ifa,
        !           574:                            ia_list);
        !           575: #endif
        !           576:                /* XXX if_free_sadl needs this */
        !           577:                if (ifa == ifnet_addrs[ifp->if_index])
        !           578:                        continue;
        !           579:
        !           580:                ifa->ifa_ifp = NULL;
        !           581:                IFAFREE(ifa);
        !           582:        }
        !           583:
        !           584:        for (ifg = TAILQ_FIRST(&ifp->if_groups); ifg;
        !           585:            ifg = TAILQ_FIRST(&ifp->if_groups))
        !           586:                if_delgroup(ifp, ifg->ifgl_group->ifg_group);
        !           587:
        !           588:        if_free_sadl(ifp);
        !           589:
        !           590:        ifnet_addrs[ifp->if_index]->ifa_ifp = NULL;
        !           591:        IFAFREE(ifnet_addrs[ifp->if_index]);
        !           592:        ifnet_addrs[ifp->if_index] = NULL;
        !           593:
        !           594:        free(ifp->if_addrhooks, M_TEMP);
        !           595:        free(ifp->if_linkstatehooks, M_TEMP);
        !           596:        free(ifp->if_detachhooks, M_TEMP);
        !           597:
        !           598:        for (dp = domains; dp; dp = dp->dom_next) {
        !           599:                if (dp->dom_ifdetach && ifp->if_afdata[dp->dom_family])
        !           600:                        (*dp->dom_ifdetach)(ifp,
        !           601:                            ifp->if_afdata[dp->dom_family]);
        !           602:        }
        !           603:
        !           604:        /* Announce that the interface is gone. */
        !           605:        rt_ifannouncemsg(ifp, IFAN_DEPARTURE);
        !           606:
        !           607:        splx(s);
        !           608: }
        !           609:
        !           610: void
        !           611: if_detach_queues(struct ifnet *ifp, struct ifqueue *q)
        !           612: {
        !           613:        struct mbuf *m, *prev, *next;
        !           614:
        !           615:        prev = NULL;
        !           616:        for (m = q->ifq_head; m; m = next) {
        !           617:                next = m->m_nextpkt;
        !           618: #ifdef DIAGNOSTIC
        !           619:                if ((m->m_flags & M_PKTHDR) == 0) {
        !           620:                        prev = m;
        !           621:                        continue;
        !           622:                }
        !           623: #endif
        !           624:                if (m->m_pkthdr.rcvif != ifp) {
        !           625:                        prev = m;
        !           626:                        continue;
        !           627:                }
        !           628:
        !           629:                if (prev)
        !           630:                        prev->m_nextpkt = m->m_nextpkt;
        !           631:                else
        !           632:                        q->ifq_head = m->m_nextpkt;
        !           633:                if (q->ifq_tail == m)
        !           634:                        q->ifq_tail = prev;
        !           635:                q->ifq_len--;
        !           636:
        !           637:                m->m_nextpkt = NULL;
        !           638:                m_freem(m);
        !           639:                IF_DROP(q);
        !           640:        }
        !           641: }
        !           642:
        !           643: /*
        !           644:  * Create a clone network interface.
        !           645:  */
        !           646: int
        !           647: if_clone_create(const char *name)
        !           648: {
        !           649:        struct if_clone *ifc;
        !           650:        struct ifnet *ifp;
        !           651:        int unit, ret;
        !           652:
        !           653:        ifc = if_clone_lookup(name, &unit);
        !           654:        if (ifc == NULL)
        !           655:                return (EINVAL);
        !           656:
        !           657:        if (ifunit(name) != NULL)
        !           658:                return (EEXIST);
        !           659:
        !           660:        if ((ret = (*ifc->ifc_create)(ifc, unit)) == 0 &&
        !           661:            (ifp = ifunit(name)) != NULL)
        !           662:                if_addgroup(ifp, ifc->ifc_name);
        !           663:
        !           664:        return (ret);
        !           665: }
        !           666:
        !           667: /*
        !           668:  * Destroy a clone network interface.
        !           669:  */
        !           670: int
        !           671: if_clone_destroy(const char *name)
        !           672: {
        !           673:        struct if_clone *ifc;
        !           674:        struct ifnet *ifp;
        !           675:        int s, ret;
        !           676:
        !           677:        ifc = if_clone_lookup(name, NULL);
        !           678:        if (ifc == NULL)
        !           679:                return (EINVAL);
        !           680:
        !           681:        ifp = ifunit(name);
        !           682:        if (ifp == NULL)
        !           683:                return (ENXIO);
        !           684:
        !           685:        if (ifc->ifc_destroy == NULL)
        !           686:                return (EOPNOTSUPP);
        !           687:
        !           688:        if (ifp->if_flags & IFF_UP) {
        !           689:                s = splnet();
        !           690:                if_down(ifp);
        !           691:                splx(s);
        !           692:        }
        !           693:
        !           694:        if_delgroup(ifp, ifc->ifc_name);
        !           695:
        !           696:        if ((ret = (*ifc->ifc_destroy)(ifp)) != 0)
        !           697:                if_addgroup(ifp, ifc->ifc_name);
        !           698:
        !           699:        return (ret);
        !           700: }
        !           701:
        !           702: /*
        !           703:  * Look up a network interface cloner.
        !           704:  */
        !           705: struct if_clone *
        !           706: if_clone_lookup(const char *name, int *unitp)
        !           707: {
        !           708:        struct if_clone *ifc;
        !           709:        const char *cp;
        !           710:        int unit;
        !           711:
        !           712:        /* separate interface name from unit */
        !           713:        for (cp = name;
        !           714:            cp - name < IFNAMSIZ && *cp && (*cp < '0' || *cp > '9');
        !           715:            cp++)
        !           716:                continue;
        !           717:
        !           718:        if (cp == name || cp - name == IFNAMSIZ || !*cp)
        !           719:                return (NULL);  /* No name or unit number */
        !           720:
        !           721:        if (cp - name < IFNAMSIZ-1 && *cp == '0' && cp[1] != '\0')
        !           722:                return (NULL);  /* unit number 0 padded */
        !           723:
        !           724:        LIST_FOREACH(ifc, &if_cloners, ifc_list) {
        !           725:                if (strlen(ifc->ifc_name) == cp - name &&
        !           726:                    !strncmp(name, ifc->ifc_name, cp - name))
        !           727:                        break;
        !           728:        }
        !           729:
        !           730:        if (ifc == NULL)
        !           731:                return (NULL);
        !           732:
        !           733:        unit = 0;
        !           734:        while (cp - name < IFNAMSIZ && *cp) {
        !           735:                if (*cp < '0' || *cp > '9' ||
        !           736:                    unit > (INT_MAX - (*cp - '0')) / 10) {
        !           737:                        /* Bogus unit number. */
        !           738:                        return (NULL);
        !           739:                }
        !           740:                unit = (unit * 10) + (*cp++ - '0');
        !           741:        }
        !           742:
        !           743:        if (unitp != NULL)
        !           744:                *unitp = unit;
        !           745:        return (ifc);
        !           746: }
        !           747:
        !           748: /*
        !           749:  * Register a network interface cloner.
        !           750:  */
        !           751: void
        !           752: if_clone_attach(struct if_clone *ifc)
        !           753: {
        !           754:        LIST_INSERT_HEAD(&if_cloners, ifc, ifc_list);
        !           755:        if_cloners_count++;
        !           756: }
        !           757:
        !           758: /*
        !           759:  * Unregister a network interface cloner.
        !           760:  */
        !           761: void
        !           762: if_clone_detach(struct if_clone *ifc)
        !           763: {
        !           764:
        !           765:        LIST_REMOVE(ifc, ifc_list);
        !           766:        if_cloners_count--;
        !           767: }
        !           768:
        !           769: /*
        !           770:  * Provide list of interface cloners to userspace.
        !           771:  */
        !           772: int
        !           773: if_clone_list(struct if_clonereq *ifcr)
        !           774: {
        !           775:        char outbuf[IFNAMSIZ], *dst;
        !           776:        struct if_clone *ifc;
        !           777:        int count, error = 0;
        !           778:
        !           779:        ifcr->ifcr_total = if_cloners_count;
        !           780:        if ((dst = ifcr->ifcr_buffer) == NULL) {
        !           781:                /* Just asking how many there are. */
        !           782:                return (0);
        !           783:        }
        !           784:
        !           785:        if (ifcr->ifcr_count < 0)
        !           786:                return (EINVAL);
        !           787:
        !           788:        count = (if_cloners_count < ifcr->ifcr_count) ?
        !           789:            if_cloners_count : ifcr->ifcr_count;
        !           790:
        !           791:        for (ifc = LIST_FIRST(&if_cloners); ifc != NULL && count != 0;
        !           792:            ifc = LIST_NEXT(ifc, ifc_list), count--, dst += IFNAMSIZ) {
        !           793:                bzero(outbuf, sizeof outbuf);
        !           794:                strlcpy(outbuf, ifc->ifc_name, IFNAMSIZ);
        !           795:                error = copyout(outbuf, dst, IFNAMSIZ);
        !           796:                if (error)
        !           797:                        break;
        !           798:        }
        !           799:
        !           800:        return (error);
        !           801: }
        !           802:
        !           803: /*
        !           804:  * set queue congestion marker and register timeout to clear it
        !           805:  */
        !           806: void
        !           807: if_congestion(struct ifqueue *ifq)
        !           808: {
        !           809:        /* Not currently needed, all callers check this */
        !           810:        if (ifq->ifq_congestion)
        !           811:                return;
        !           812:
        !           813:        ifq->ifq_congestion = malloc(sizeof(struct timeout), M_TEMP, M_NOWAIT);
        !           814:        if (ifq->ifq_congestion == NULL)
        !           815:                return;
        !           816:        timeout_set(ifq->ifq_congestion, if_congestion_clear, ifq);
        !           817:        timeout_add(ifq->ifq_congestion, hz / 100);
        !           818: }
        !           819:
        !           820: /*
        !           821:  * clear the congestion flag
        !           822:  */
        !           823: void
        !           824: if_congestion_clear(void *arg)
        !           825: {
        !           826:        struct ifqueue *ifq = arg;
        !           827:        struct timeout *to = ifq->ifq_congestion;
        !           828:
        !           829:        ifq->ifq_congestion = NULL;
        !           830:        free(to, M_TEMP);
        !           831: }
        !           832:
        !           833: /*
        !           834:  * Locate an interface based on a complete address.
        !           835:  */
        !           836: /*ARGSUSED*/
        !           837: struct ifaddr *
        !           838: ifa_ifwithaddr(struct sockaddr *addr)
        !           839: {
        !           840:        struct ifnet *ifp;
        !           841:        struct ifaddr *ifa;
        !           842:
        !           843: #define        equal(a1, a2)   \
        !           844:        (bcmp((caddr_t)(a1), (caddr_t)(a2),     \
        !           845:        ((struct sockaddr *)(a1))->sa_len) == 0)
        !           846:        TAILQ_FOREACH(ifp, &ifnet, if_list) {
        !           847:            TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
        !           848:                if (ifa->ifa_addr->sa_family != addr->sa_family)
        !           849:                        continue;
        !           850:                if (equal(addr, ifa->ifa_addr))
        !           851:                        return (ifa);
        !           852:                if ((ifp->if_flags & IFF_BROADCAST) && ifa->ifa_broadaddr &&
        !           853:                    /* IP6 doesn't have broadcast */
        !           854:                    ifa->ifa_broadaddr->sa_len != 0 &&
        !           855:                    equal(ifa->ifa_broadaddr, addr))
        !           856:                        return (ifa);
        !           857:            }
        !           858:        }
        !           859:        return (NULL);
        !           860: }
        !           861: /*
        !           862:  * Locate the point to point interface with a given destination address.
        !           863:  */
        !           864: /*ARGSUSED*/
        !           865: struct ifaddr *
        !           866: ifa_ifwithdstaddr(struct sockaddr *addr)
        !           867: {
        !           868:        struct ifnet *ifp;
        !           869:        struct ifaddr *ifa;
        !           870:
        !           871:        TAILQ_FOREACH(ifp, &ifnet, if_list) {
        !           872:            if (ifp->if_flags & IFF_POINTOPOINT)
        !           873:                TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
        !           874:                        if (ifa->ifa_addr->sa_family != addr->sa_family ||
        !           875:                            ifa->ifa_dstaddr == NULL)
        !           876:                                continue;
        !           877:                        if (equal(addr, ifa->ifa_dstaddr))
        !           878:                                return (ifa);
        !           879:                }
        !           880:        }
        !           881:        return (NULL);
        !           882: }
        !           883:
        !           884: /*
        !           885:  * Find an interface on a specific network.  If many, choice
        !           886:  * is most specific found.
        !           887:  */
        !           888: struct ifaddr *
        !           889: ifa_ifwithnet(struct sockaddr *addr)
        !           890: {
        !           891:        struct ifnet *ifp;
        !           892:        struct ifaddr *ifa;
        !           893:        struct ifaddr *ifa_maybe = 0;
        !           894:        u_int af = addr->sa_family;
        !           895:        char *addr_data = addr->sa_data, *cplim;
        !           896:
        !           897:        if (af == AF_LINK) {
        !           898:                struct sockaddr_dl *sdl = (struct sockaddr_dl *)addr;
        !           899:                if (sdl->sdl_index && sdl->sdl_index < if_indexlim &&
        !           900:                    ifindex2ifnet[sdl->sdl_index])
        !           901:                        return (ifnet_addrs[sdl->sdl_index]);
        !           902:        }
        !           903:        TAILQ_FOREACH(ifp, &ifnet, if_list) {
        !           904:                TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
        !           905:                        char *cp, *cp2, *cp3;
        !           906:
        !           907:                        if (ifa->ifa_addr->sa_family != af ||
        !           908:                            ifa->ifa_netmask == 0)
        !           909:                                next: continue;
        !           910:                        cp = addr_data;
        !           911:                        cp2 = ifa->ifa_addr->sa_data;
        !           912:                        cp3 = ifa->ifa_netmask->sa_data;
        !           913:                        cplim = (char *)ifa->ifa_netmask +
        !           914:                                ifa->ifa_netmask->sa_len;
        !           915:                        while (cp3 < cplim)
        !           916:                                if ((*cp++ ^ *cp2++) & *cp3++)
        !           917:                                    /* want to continue for() loop */
        !           918:                                        goto next;
        !           919:                        if (ifa_maybe == 0 ||
        !           920:                            rn_refines((caddr_t)ifa->ifa_netmask,
        !           921:                            (caddr_t)ifa_maybe->ifa_netmask))
        !           922:                                ifa_maybe = ifa;
        !           923:                }
        !           924:        }
        !           925:        return (ifa_maybe);
        !           926: }
        !           927:
        !           928: /*
        !           929:  * Find an interface using a specific address family
        !           930:  */
        !           931: struct ifaddr *
        !           932: ifa_ifwithaf(int af)
        !           933: {
        !           934:        struct ifnet *ifp;
        !           935:        struct ifaddr *ifa;
        !           936:
        !           937:        TAILQ_FOREACH(ifp, &ifnet, if_list) {
        !           938:                TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
        !           939:                        if (ifa->ifa_addr->sa_family == af)
        !           940:                                return (ifa);
        !           941:                }
        !           942:        }
        !           943:        return (NULL);
        !           944: }
        !           945:
        !           946: /*
        !           947:  * Find an interface address specific to an interface best matching
        !           948:  * a given address.
        !           949:  */
        !           950: struct ifaddr *
        !           951: ifaof_ifpforaddr(struct sockaddr *addr, struct ifnet *ifp)
        !           952: {
        !           953:        struct ifaddr *ifa;
        !           954:        char *cp, *cp2, *cp3;
        !           955:        char *cplim;
        !           956:        struct ifaddr *ifa_maybe = NULL;
        !           957:        u_int af = addr->sa_family;
        !           958:
        !           959:        if (af >= AF_MAX)
        !           960:                return (NULL);
        !           961:        TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
        !           962:                if (ifa->ifa_addr->sa_family != af)
        !           963:                        continue;
        !           964:                if (ifa_maybe == NULL)
        !           965:                        ifa_maybe = ifa;
        !           966:                if (ifa->ifa_netmask == 0 || ifp->if_flags & IFF_POINTOPOINT) {
        !           967:                        if (equal(addr, ifa->ifa_addr) ||
        !           968:                            (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr)))
        !           969:                                return (ifa);
        !           970:                        continue;
        !           971:                }
        !           972:                cp = addr->sa_data;
        !           973:                cp2 = ifa->ifa_addr->sa_data;
        !           974:                cp3 = ifa->ifa_netmask->sa_data;
        !           975:                cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask;
        !           976:                for (; cp3 < cplim; cp3++)
        !           977:                        if ((*cp++ ^ *cp2++) & *cp3)
        !           978:                                break;
        !           979:                if (cp3 == cplim)
        !           980:                        return (ifa);
        !           981:        }
        !           982:        return (ifa_maybe);
        !           983: }
        !           984:
        !           985: /*
        !           986:  * Default action when installing a route with a Link Level gateway.
        !           987:  * Lookup an appropriate real ifa to point to.
        !           988:  * This should be moved to /sys/net/link.c eventually.
        !           989:  */
        !           990: void
        !           991: link_rtrequest(int cmd, struct rtentry *rt, struct rt_addrinfo *info)
        !           992: {
        !           993:        struct ifaddr *ifa;
        !           994:        struct sockaddr *dst;
        !           995:        struct ifnet *ifp;
        !           996:
        !           997:        if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) ||
        !           998:            ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0))
        !           999:                return;
        !          1000:        if ((ifa = ifaof_ifpforaddr(dst, ifp)) != NULL) {
        !          1001:                ifa->ifa_refcnt++;
        !          1002:                IFAFREE(rt->rt_ifa);
        !          1003:                rt->rt_ifa = ifa;
        !          1004:                if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest)
        !          1005:                        ifa->ifa_rtrequest(cmd, rt, info);
        !          1006:        }
        !          1007: }
        !          1008:
        !          1009: /*
        !          1010:  * Mark an interface down and notify protocols of
        !          1011:  * the transition.
        !          1012:  * NOTE: must be called at splsoftnet or equivalent.
        !          1013:  */
        !          1014: void
        !          1015: if_down(struct ifnet *ifp)
        !          1016: {
        !          1017:        struct ifaddr *ifa;
        !          1018:
        !          1019:        splassert(IPL_SOFTNET);
        !          1020:
        !          1021:        ifp->if_flags &= ~IFF_UP;
        !          1022:        microtime(&ifp->if_lastchange);
        !          1023:        TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
        !          1024:                pfctlinput(PRC_IFDOWN, ifa->ifa_addr);
        !          1025:        }
        !          1026:        IFQ_PURGE(&ifp->if_snd);
        !          1027: #if NCARP > 0
        !          1028:        if (ifp->if_carp)
        !          1029:                carp_carpdev_state(ifp);
        !          1030: #endif
        !          1031: #if NBRIDGE > 0
        !          1032:        if (ifp->if_bridge)
        !          1033:                bstp_ifstate(ifp);
        !          1034: #endif
        !          1035:        rt_ifmsg(ifp);
        !          1036: }
        !          1037:
        !          1038: /*
        !          1039:  * Mark an interface up and notify protocols of
        !          1040:  * the transition.
        !          1041:  * NOTE: must be called at splsoftnet or equivalent.
        !          1042:  */
        !          1043: void
        !          1044: if_up(struct ifnet *ifp)
        !          1045: {
        !          1046: #ifdef notyet
        !          1047:        struct ifaddr *ifa;
        !          1048: #endif
        !          1049:
        !          1050:        splassert(IPL_SOFTNET);
        !          1051:
        !          1052:        ifp->if_flags |= IFF_UP;
        !          1053:        microtime(&ifp->if_lastchange);
        !          1054: #ifdef notyet
        !          1055:        /* this has no effect on IP, and will kill all ISO connections XXX */
        !          1056:        TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
        !          1057:                pfctlinput(PRC_IFUP, ifa->ifa_addr);
        !          1058:        }
        !          1059: #endif
        !          1060: #if NCARP > 0
        !          1061:        if (ifp->if_carp)
        !          1062:                carp_carpdev_state(ifp);
        !          1063: #endif
        !          1064: #if NBRIDGE > 0
        !          1065:        if (ifp->if_bridge)
        !          1066:                bstp_ifstate(ifp);
        !          1067: #endif
        !          1068:        rt_ifmsg(ifp);
        !          1069: #ifdef INET6
        !          1070:        in6_if_up(ifp);
        !          1071: #endif
        !          1072: }
        !          1073:
        !          1074: /*
        !          1075:  * Process a link state change.
        !          1076:  * NOTE: must be called at splsoftnet or equivalent.
        !          1077:  */
        !          1078: void
        !          1079: if_link_state_change(struct ifnet *ifp)
        !          1080: {
        !          1081:        rt_ifmsg(ifp);
        !          1082:        dohooks(ifp->if_linkstatehooks, 0);
        !          1083: }
        !          1084:
        !          1085: /*
        !          1086:  * Flush an interface queue.
        !          1087:  */
        !          1088: void
        !          1089: if_qflush(struct ifqueue *ifq)
        !          1090: {
        !          1091:        struct mbuf *m, *n;
        !          1092:
        !          1093:        n = ifq->ifq_head;
        !          1094:        while ((m = n) != NULL) {
        !          1095:                n = m->m_act;
        !          1096:                m_freem(m);
        !          1097:        }
        !          1098:        ifq->ifq_head = 0;
        !          1099:        ifq->ifq_tail = 0;
        !          1100:        ifq->ifq_len = 0;
        !          1101: }
        !          1102:
        !          1103: /*
        !          1104:  * Handle interface watchdog timer routines.  Called
        !          1105:  * from softclock, we decrement timers (if set) and
        !          1106:  * call the appropriate interface routine on expiration.
        !          1107:  */
        !          1108: void
        !          1109: if_slowtimo(void *arg)
        !          1110: {
        !          1111:        struct timeout *to = (struct timeout *)arg;
        !          1112:        struct ifnet *ifp;
        !          1113:        int s = splnet();
        !          1114:
        !          1115:        TAILQ_FOREACH(ifp, &ifnet, if_list) {
        !          1116:                if (ifp->if_timer == 0 || --ifp->if_timer)
        !          1117:                        continue;
        !          1118:                if (ifp->if_watchdog)
        !          1119:                        (*ifp->if_watchdog)(ifp);
        !          1120:        }
        !          1121:        splx(s);
        !          1122:        timeout_add(to, hz / IFNET_SLOWHZ);
        !          1123: }
        !          1124:
        !          1125: /*
        !          1126:  * Map interface name to
        !          1127:  * interface structure pointer.
        !          1128:  */
        !          1129: struct ifnet *
        !          1130: ifunit(const char *name)
        !          1131: {
        !          1132:        struct ifnet *ifp;
        !          1133:
        !          1134:        TAILQ_FOREACH(ifp, &ifnet, if_list) {
        !          1135:                if (strcmp(ifp->if_xname, name) == 0)
        !          1136:                        return (ifp);
        !          1137:        }
        !          1138:        return (NULL);
        !          1139: }
        !          1140:
        !          1141: /*
        !          1142:  * Interface ioctls.
        !          1143:  */
        !          1144: int
        !          1145: ifioctl(struct socket *so, u_long cmd, caddr_t data, struct proc *p)
        !          1146: {
        !          1147:        struct ifnet *ifp;
        !          1148:        struct ifreq *ifr;
        !          1149:        struct ifaddr *ifa;
        !          1150:        struct sockaddr_dl *sdl;
        !          1151:        struct ifgroupreq *ifgr;
        !          1152:        char ifdescrbuf[IFDESCRSIZE];
        !          1153:        char ifrtlabelbuf[RTLABEL_LEN];
        !          1154:        int error = 0;
        !          1155:        size_t bytesdone;
        !          1156:        short oif_flags;
        !          1157:        const char *label;
        !          1158:
        !          1159:        switch (cmd) {
        !          1160:
        !          1161:        case SIOCGIFCONF:
        !          1162:        case OSIOCGIFCONF:
        !          1163:                return (ifconf(cmd, data));
        !          1164:        }
        !          1165:        ifr = (struct ifreq *)data;
        !          1166:
        !          1167:        switch (cmd) {
        !          1168:        case SIOCIFCREATE:
        !          1169:        case SIOCIFDESTROY:
        !          1170:                if ((error = suser(p, 0)) != 0)
        !          1171:                        return (error);
        !          1172:                return ((cmd == SIOCIFCREATE) ?
        !          1173:                    if_clone_create(ifr->ifr_name) :
        !          1174:                    if_clone_destroy(ifr->ifr_name));
        !          1175:        case SIOCIFGCLONERS:
        !          1176:                return (if_clone_list((struct if_clonereq *)data));
        !          1177:        case SIOCGIFGMEMB:
        !          1178:                return (if_getgroupmembers(data));
        !          1179:        case SIOCGIFGATTR:
        !          1180:                return (if_getgroupattribs(data));
        !          1181:        case SIOCSIFGATTR:
        !          1182:                if ((error = suser(p, 0)) != 0)
        !          1183:                        return (error);
        !          1184:                return (if_setgroupattribs(data));
        !          1185:        }
        !          1186:
        !          1187:        ifp = ifunit(ifr->ifr_name);
        !          1188:        if (ifp == 0)
        !          1189:                return (ENXIO);
        !          1190:        oif_flags = ifp->if_flags;
        !          1191:        switch (cmd) {
        !          1192:
        !          1193:        case SIOCGIFFLAGS:
        !          1194:                ifr->ifr_flags = ifp->if_flags;
        !          1195:                break;
        !          1196:
        !          1197:        case SIOCGIFMETRIC:
        !          1198:                ifr->ifr_metric = ifp->if_metric;
        !          1199:                break;
        !          1200:
        !          1201:        case SIOCGIFMTU:
        !          1202:                ifr->ifr_mtu = ifp->if_mtu;
        !          1203:                break;
        !          1204:
        !          1205:        case SIOCGIFDATA:
        !          1206:                error = copyout((caddr_t)&ifp->if_data, ifr->ifr_data,
        !          1207:                    sizeof(ifp->if_data));
        !          1208:                break;
        !          1209:
        !          1210:        case SIOCSIFFLAGS:
        !          1211:                if ((error = suser(p, 0)) != 0)
        !          1212:                        return (error);
        !          1213:                if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) {
        !          1214:                        int s = splnet();
        !          1215:                        if_down(ifp);
        !          1216:                        splx(s);
        !          1217:                }
        !          1218:                if (ifr->ifr_flags & IFF_UP && (ifp->if_flags & IFF_UP) == 0) {
        !          1219:                        int s = splnet();
        !          1220:                        if_up(ifp);
        !          1221:                        splx(s);
        !          1222:                }
        !          1223:                ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) |
        !          1224:                        (ifr->ifr_flags &~ IFF_CANTCHANGE);
        !          1225:                if (ifp->if_ioctl)
        !          1226:                        (void) (*ifp->if_ioctl)(ifp, cmd, data);
        !          1227:                break;
        !          1228:
        !          1229:        case SIOCSIFMETRIC:
        !          1230:                if ((error = suser(p, 0)) != 0)
        !          1231:                        return (error);
        !          1232:                ifp->if_metric = ifr->ifr_metric;
        !          1233:                break;
        !          1234:
        !          1235:        case SIOCSIFMTU:
        !          1236:        {
        !          1237: #ifdef INET6
        !          1238:                int oldmtu = ifp->if_mtu;
        !          1239: #endif
        !          1240:
        !          1241:                if ((error = suser(p, 0)) != 0)
        !          1242:                        return (error);
        !          1243:                if (ifp->if_ioctl == NULL)
        !          1244:                        return (EOPNOTSUPP);
        !          1245:                error = (*ifp->if_ioctl)(ifp, cmd, data);
        !          1246:
        !          1247:                /*
        !          1248:                 * If the link MTU changed, do network layer specific procedure.
        !          1249:                 */
        !          1250: #ifdef INET6
        !          1251:                if (ifp->if_mtu != oldmtu)
        !          1252:                        nd6_setmtu(ifp);
        !          1253: #endif
        !          1254:                break;
        !          1255:        }
        !          1256:
        !          1257:        case SIOCSIFPHYADDR:
        !          1258:        case SIOCDIFPHYADDR:
        !          1259: #ifdef INET6
        !          1260:        case SIOCSIFPHYADDR_IN6:
        !          1261: #endif
        !          1262:        case SIOCSLIFPHYADDR:
        !          1263:        case SIOCADDMULTI:
        !          1264:        case SIOCDELMULTI:
        !          1265:        case SIOCSIFMEDIA:
        !          1266:                if ((error = suser(p, 0)) != 0)
        !          1267:                        return (error);
        !          1268:                /* FALLTHROUGH */
        !          1269:        case SIOCGIFPSRCADDR:
        !          1270:        case SIOCGIFPDSTADDR:
        !          1271:        case SIOCGLIFPHYADDR:
        !          1272:        case SIOCGIFMEDIA:
        !          1273:                if (ifp->if_ioctl == 0)
        !          1274:                        return (EOPNOTSUPP);
        !          1275:                error = (*ifp->if_ioctl)(ifp, cmd, data);
        !          1276:                break;
        !          1277:
        !          1278:        case SIOCGIFDESCR:
        !          1279:                strlcpy(ifdescrbuf, ifp->if_description, IFDESCRSIZE);
        !          1280:                error = copyoutstr(ifdescrbuf, ifr->ifr_data, IFDESCRSIZE,
        !          1281:                    &bytesdone);
        !          1282:                break;
        !          1283:
        !          1284:        case SIOCSIFDESCR:
        !          1285:                if ((error = suser(p, 0)) != 0)
        !          1286:                        return (error);
        !          1287:                error = copyinstr(ifr->ifr_data, ifdescrbuf,
        !          1288:                    IFDESCRSIZE, &bytesdone);
        !          1289:                if (error == 0) {
        !          1290:                        (void)memset(ifp->if_description, 0, IFDESCRSIZE);
        !          1291:                        strlcpy(ifp->if_description, ifdescrbuf, IFDESCRSIZE);
        !          1292:                }
        !          1293:                break;
        !          1294:
        !          1295:        case SIOCGIFRTLABEL:
        !          1296:                label = rtlabel_id2name(ifp->if_rtlabelid);
        !          1297:                strlcpy(ifrtlabelbuf, label, RTLABEL_LEN);
        !          1298:                error = copyoutstr(ifrtlabelbuf, ifr->ifr_data, RTLABEL_LEN,
        !          1299:                    &bytesdone);
        !          1300:                break;
        !          1301:
        !          1302:        case SIOCSIFRTLABEL:
        !          1303:                if ((error = suser(p, 0)) != 0)
        !          1304:                        return (error);
        !          1305:                error = copyinstr(ifr->ifr_data, ifrtlabelbuf,
        !          1306:                    RTLABEL_LEN, &bytesdone);
        !          1307:                if (error == 0) {
        !          1308:                        rtlabel_unref(ifp->if_rtlabelid);
        !          1309:                        ifp->if_rtlabelid = rtlabel_name2id(ifrtlabelbuf);
        !          1310:                }
        !          1311:                break;
        !          1312:
        !          1313:        case SIOCAIFGROUP:
        !          1314:                if ((error = suser(p, 0)))
        !          1315:                        return (error);
        !          1316:                (*ifp->if_ioctl)(ifp, cmd, data); /* XXX error check */
        !          1317:                ifgr = (struct ifgroupreq *)data;
        !          1318:                if ((error = if_addgroup(ifp, ifgr->ifgr_group)))
        !          1319:                        return (error);
        !          1320:                break;
        !          1321:
        !          1322:        case SIOCGIFGROUP:
        !          1323:                if ((error = if_getgroup(data, ifp)))
        !          1324:                        return (error);
        !          1325:                break;
        !          1326:
        !          1327:        case SIOCDIFGROUP:
        !          1328:                if ((error = suser(p, 0)))
        !          1329:                        return (error);
        !          1330:                (*ifp->if_ioctl)(ifp, cmd, data); /* XXX error check */
        !          1331:                ifgr = (struct ifgroupreq *)data;
        !          1332:                if ((error = if_delgroup(ifp, ifgr->ifgr_group)))
        !          1333:                        return (error);
        !          1334:                break;
        !          1335:
        !          1336:        case SIOCSIFLLADDR:
        !          1337:                if ((error = suser(p, 0)))
        !          1338:                        return (error);
        !          1339:                ifa = ifnet_addrs[ifp->if_index];
        !          1340:                if (ifa == NULL)
        !          1341:                        return (EINVAL);
        !          1342:                sdl = (struct sockaddr_dl *)ifa->ifa_addr;
        !          1343:                if (sdl == NULL)
        !          1344:                        return (EINVAL);
        !          1345:                if (ifr->ifr_addr.sa_len != ETHER_ADDR_LEN)
        !          1346:                        return (EINVAL);
        !          1347:                if (ETHER_IS_MULTICAST(ifr->ifr_addr.sa_data))
        !          1348:                        return (EINVAL);
        !          1349:                switch (ifp->if_type) {
        !          1350:                case IFT_ETHER:
        !          1351:                case IFT_CARP:
        !          1352:                case IFT_FDDI:
        !          1353:                case IFT_XETHER:
        !          1354:                case IFT_ISO88025:
        !          1355:                case IFT_L2VLAN:
        !          1356:                        bcopy((caddr_t)ifr->ifr_addr.sa_data,
        !          1357:                            (caddr_t)((struct arpcom *)ifp)->ac_enaddr,
        !          1358:                            ETHER_ADDR_LEN);
        !          1359:                        bcopy((caddr_t)ifr->ifr_addr.sa_data,
        !          1360:                            LLADDR(sdl), ETHER_ADDR_LEN);
        !          1361:                        break;
        !          1362:                default:
        !          1363:                        return (ENODEV);
        !          1364:                }
        !          1365:                if (ifp->if_flags & IFF_UP) {
        !          1366:                        struct ifreq ifrq;
        !          1367:                        int s = splnet();
        !          1368:                        ifp->if_flags &= ~IFF_UP;
        !          1369:                        ifrq.ifr_flags = ifp->if_flags;
        !          1370:                        (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifrq);
        !          1371:                        ifp->if_flags |= IFF_UP;
        !          1372:                        ifrq.ifr_flags = ifp->if_flags;
        !          1373:                        (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifrq);
        !          1374:                        splx(s);
        !          1375:                        TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
        !          1376:                                if (ifa->ifa_addr != NULL &&
        !          1377:                                    ifa->ifa_addr->sa_family == AF_INET)
        !          1378:                                        arp_ifinit((struct arpcom *)ifp, ifa);
        !          1379:                        }
        !          1380:                }
        !          1381:                break;
        !          1382:
        !          1383:        default:
        !          1384:                if (so->so_proto == 0)
        !          1385:                        return (EOPNOTSUPP);
        !          1386: #if !defined(COMPAT_43) && !defined(COMPAT_LINUX) && !defined(COMPAT_SVR4)
        !          1387:                error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
        !          1388:                        (struct mbuf *) cmd, (struct mbuf *) data,
        !          1389:                        (struct mbuf *) ifp));
        !          1390: #else
        !          1391:            {
        !          1392:                u_long ocmd = cmd;
        !          1393:
        !          1394:                switch (cmd) {
        !          1395:
        !          1396:                case SIOCSIFADDR:
        !          1397:                case SIOCSIFDSTADDR:
        !          1398:                case SIOCSIFBRDADDR:
        !          1399:                case SIOCSIFNETMASK:
        !          1400: #if BYTE_ORDER != BIG_ENDIAN
        !          1401:                        if (ifr->ifr_addr.sa_family == 0 &&
        !          1402:                            ifr->ifr_addr.sa_len < 16) {
        !          1403:                                ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len;
        !          1404:                                ifr->ifr_addr.sa_len = 16;
        !          1405:                        }
        !          1406: #else
        !          1407:                        if (ifr->ifr_addr.sa_len == 0)
        !          1408:                                ifr->ifr_addr.sa_len = 16;
        !          1409: #endif
        !          1410:                        break;
        !          1411:
        !          1412:                case OSIOCGIFADDR:
        !          1413:                        cmd = SIOCGIFADDR;
        !          1414:                        break;
        !          1415:
        !          1416:                case OSIOCGIFDSTADDR:
        !          1417:                        cmd = SIOCGIFDSTADDR;
        !          1418:                        break;
        !          1419:
        !          1420:                case OSIOCGIFBRDADDR:
        !          1421:                        cmd = SIOCGIFBRDADDR;
        !          1422:                        break;
        !          1423:
        !          1424:                case OSIOCGIFNETMASK:
        !          1425:                        cmd = SIOCGIFNETMASK;
        !          1426:                }
        !          1427:                error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
        !          1428:                    (struct mbuf *) cmd, (struct mbuf *) data,
        !          1429:                    (struct mbuf *) ifp));
        !          1430:                switch (ocmd) {
        !          1431:
        !          1432:                case OSIOCGIFADDR:
        !          1433:                case OSIOCGIFDSTADDR:
        !          1434:                case OSIOCGIFBRDADDR:
        !          1435:                case OSIOCGIFNETMASK:
        !          1436:                        *(u_int16_t *)&ifr->ifr_addr = ifr->ifr_addr.sa_family;
        !          1437:                }
        !          1438:
        !          1439:            }
        !          1440: #endif
        !          1441:                break;
        !          1442:        }
        !          1443:
        !          1444:        if (((oif_flags ^ ifp->if_flags) & IFF_UP) != 0) {
        !          1445:                microtime(&ifp->if_lastchange);
        !          1446: #ifdef INET6
        !          1447:                if ((ifp->if_flags & IFF_UP) != 0) {
        !          1448:                        int s = splnet();
        !          1449:                        in6_if_up(ifp);
        !          1450:                        splx(s);
        !          1451:                }
        !          1452: #endif
        !          1453:        }
        !          1454:        return (error);
        !          1455: }
        !          1456:
        !          1457: /*
        !          1458:  * Return interface configuration
        !          1459:  * of system.  List may be used
        !          1460:  * in later ioctl's (above) to get
        !          1461:  * other information.
        !          1462:  */
        !          1463: /*ARGSUSED*/
        !          1464: int
        !          1465: ifconf(u_long cmd, caddr_t data)
        !          1466: {
        !          1467:        struct ifconf *ifc = (struct ifconf *)data;
        !          1468:        struct ifnet *ifp;
        !          1469:        struct ifaddr *ifa;
        !          1470:        struct ifreq ifr, *ifrp;
        !          1471:        int space = ifc->ifc_len, error = 0;
        !          1472:
        !          1473:        /* If ifc->ifc_len is 0, fill it in with the needed size and return. */
        !          1474:        if (space == 0) {
        !          1475:                TAILQ_FOREACH(ifp, &ifnet, if_list) {
        !          1476:                        struct sockaddr *sa;
        !          1477:
        !          1478:                        if (TAILQ_EMPTY(&ifp->if_addrlist))
        !          1479:                                space += sizeof (ifr);
        !          1480:                        else
        !          1481:                                TAILQ_FOREACH(ifa,
        !          1482:                                    &ifp->if_addrlist, ifa_list) {
        !          1483:                                        sa = ifa->ifa_addr;
        !          1484: #if defined(COMPAT_43) || defined(COMPAT_LINUX) || defined(COMPAT_SVR4)
        !          1485:                                        if (cmd != OSIOCGIFCONF)
        !          1486: #endif
        !          1487:                                        if (sa->sa_len > sizeof(*sa))
        !          1488:                                                space += sa->sa_len -
        !          1489:                                                    sizeof(*sa);
        !          1490:                                        space += sizeof(ifr);
        !          1491:                                }
        !          1492:                }
        !          1493:                ifc->ifc_len = space;
        !          1494:                return (0);
        !          1495:        }
        !          1496:
        !          1497:        ifrp = ifc->ifc_req;
        !          1498:        for (ifp = TAILQ_FIRST(&ifnet); space >= sizeof(ifr) &&
        !          1499:            ifp != TAILQ_END(&ifnet); ifp = TAILQ_NEXT(ifp, if_list)) {
        !          1500:                bcopy(ifp->if_xname, ifr.ifr_name, IFNAMSIZ);
        !          1501:                if (TAILQ_EMPTY(&ifp->if_addrlist)) {
        !          1502:                        bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
        !          1503:                        error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
        !          1504:                            sizeof(ifr));
        !          1505:                        if (error)
        !          1506:                                break;
        !          1507:                        space -= sizeof (ifr), ifrp++;
        !          1508:                } else
        !          1509:                        for (ifa = TAILQ_FIRST(&ifp->if_addrlist);
        !          1510:                            space >= sizeof (ifr) &&
        !          1511:                            ifa != TAILQ_END(&ifp->if_addrlist);
        !          1512:                            ifa = TAILQ_NEXT(ifa, ifa_list)) {
        !          1513:                                struct sockaddr *sa = ifa->ifa_addr;
        !          1514: #if defined(COMPAT_43) || defined(COMPAT_LINUX) || defined(COMPAT_SVR4)
        !          1515:                                if (cmd == OSIOCGIFCONF) {
        !          1516:                                        struct osockaddr *osa =
        !          1517:                                            (struct osockaddr *)&ifr.ifr_addr;
        !          1518:                                        ifr.ifr_addr = *sa;
        !          1519:                                        osa->sa_family = sa->sa_family;
        !          1520:                                        error = copyout((caddr_t)&ifr,
        !          1521:                                            (caddr_t)ifrp, sizeof (ifr));
        !          1522:                                        ifrp++;
        !          1523:                                } else
        !          1524: #endif
        !          1525:                                if (sa->sa_len <= sizeof(*sa)) {
        !          1526:                                        ifr.ifr_addr = *sa;
        !          1527:                                        error = copyout((caddr_t)&ifr,
        !          1528:                                            (caddr_t)ifrp, sizeof (ifr));
        !          1529:                                        ifrp++;
        !          1530:                                } else {
        !          1531:                                        space -= sa->sa_len - sizeof(*sa);
        !          1532:                                        if (space < sizeof (ifr))
        !          1533:                                                break;
        !          1534:                                        error = copyout((caddr_t)&ifr,
        !          1535:                                            (caddr_t)ifrp,
        !          1536:                                            sizeof(ifr.ifr_name));
        !          1537:                                        if (error == 0)
        !          1538:                                                error = copyout((caddr_t)sa,
        !          1539:                                                    (caddr_t)&ifrp->ifr_addr,
        !          1540:                                                    sa->sa_len);
        !          1541:                                        ifrp = (struct ifreq *)(sa->sa_len +
        !          1542:                                            (caddr_t)&ifrp->ifr_addr);
        !          1543:                                }
        !          1544:                                if (error)
        !          1545:                                        break;
        !          1546:                                space -= sizeof (ifr);
        !          1547:                        }
        !          1548:        }
        !          1549:        ifc->ifc_len -= space;
        !          1550:        return (error);
        !          1551: }
        !          1552:
        !          1553: /*
        !          1554:  * Dummy functions replaced in ifnet during detach (if protocols decide to
        !          1555:  * fiddle with the if during detach.
        !          1556:  */
        !          1557: void
        !          1558: if_detached_start(struct ifnet *ifp)
        !          1559: {
        !          1560:        struct mbuf *m;
        !          1561:
        !          1562:        while (1) {
        !          1563:                IF_DEQUEUE(&ifp->if_snd, m);
        !          1564:
        !          1565:                if (m == NULL)
        !          1566:                        return;
        !          1567:                m_freem(m);
        !          1568:        }
        !          1569: }
        !          1570:
        !          1571: int
        !          1572: if_detached_ioctl(struct ifnet *ifp, u_long a, caddr_t b)
        !          1573: {
        !          1574:        return ENODEV;
        !          1575: }
        !          1576:
        !          1577: int
        !          1578: if_detached_init(struct ifnet *ifp)
        !          1579: {
        !          1580:        return (ENXIO);
        !          1581: }
        !          1582:
        !          1583: void
        !          1584: if_detached_watchdog(struct ifnet *ifp)
        !          1585: {
        !          1586:        /* nothing */
        !          1587: }
        !          1588:
        !          1589: /*
        !          1590:  * Create interface group without members
        !          1591:  */
        !          1592: struct ifg_group *
        !          1593: if_creategroup(const char *groupname)
        !          1594: {
        !          1595:        struct ifg_group        *ifg = NULL;
        !          1596:
        !          1597:        if ((ifg = (struct ifg_group *)malloc(sizeof(struct ifg_group),
        !          1598:            M_TEMP, M_NOWAIT)) == NULL)
        !          1599:                return (NULL);
        !          1600:
        !          1601:        strlcpy(ifg->ifg_group, groupname, sizeof(ifg->ifg_group));
        !          1602:        ifg->ifg_refcnt = 0;
        !          1603:        ifg->ifg_carp_demoted = 0;
        !          1604:        TAILQ_INIT(&ifg->ifg_members);
        !          1605: #if NPF > 0
        !          1606:        pfi_attach_ifgroup(ifg);
        !          1607: #endif
        !          1608:        TAILQ_INSERT_TAIL(&ifg_head, ifg, ifg_next);
        !          1609:
        !          1610:        return (ifg);
        !          1611: }
        !          1612:
        !          1613: /*
        !          1614:  * Add a group to an interface
        !          1615:  */
        !          1616: int
        !          1617: if_addgroup(struct ifnet *ifp, const char *groupname)
        !          1618: {
        !          1619:        struct ifg_list         *ifgl;
        !          1620:        struct ifg_group        *ifg = NULL;
        !          1621:        struct ifg_member       *ifgm;
        !          1622:
        !          1623:        if (groupname[0] && groupname[strlen(groupname) - 1] >= '0' &&
        !          1624:            groupname[strlen(groupname) - 1] <= '9')
        !          1625:                return (EINVAL);
        !          1626:
        !          1627:        TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next)
        !          1628:                if (!strcmp(ifgl->ifgl_group->ifg_group, groupname))
        !          1629:                        return (EEXIST);
        !          1630:
        !          1631:        if ((ifgl = (struct ifg_list *)malloc(sizeof(struct ifg_list), M_TEMP,
        !          1632:            M_NOWAIT)) == NULL)
        !          1633:                return (ENOMEM);
        !          1634:
        !          1635:        if ((ifgm = (struct ifg_member *)malloc(sizeof(struct ifg_member),
        !          1636:            M_TEMP, M_NOWAIT)) == NULL) {
        !          1637:                free(ifgl, M_TEMP);
        !          1638:                return (ENOMEM);
        !          1639:        }
        !          1640:
        !          1641:        TAILQ_FOREACH(ifg, &ifg_head, ifg_next)
        !          1642:                if (!strcmp(ifg->ifg_group, groupname))
        !          1643:                        break;
        !          1644:
        !          1645:        if (ifg == NULL && (ifg = if_creategroup(groupname)) == NULL) {
        !          1646:                free(ifgl, M_TEMP);
        !          1647:                free(ifgm, M_TEMP);
        !          1648:                return (ENOMEM);
        !          1649:        }
        !          1650:
        !          1651:        ifg->ifg_refcnt++;
        !          1652:        ifgl->ifgl_group = ifg;
        !          1653:        ifgm->ifgm_ifp = ifp;
        !          1654:
        !          1655:        TAILQ_INSERT_TAIL(&ifg->ifg_members, ifgm, ifgm_next);
        !          1656:        TAILQ_INSERT_TAIL(&ifp->if_groups, ifgl, ifgl_next);
        !          1657:
        !          1658: #if NPF > 0
        !          1659:        pfi_group_change(groupname);
        !          1660: #endif
        !          1661:
        !          1662:        return (0);
        !          1663: }
        !          1664:
        !          1665: /*
        !          1666:  * Remove a group from an interface
        !          1667:  */
        !          1668: int
        !          1669: if_delgroup(struct ifnet *ifp, const char *groupname)
        !          1670: {
        !          1671:        struct ifg_list         *ifgl;
        !          1672:        struct ifg_member       *ifgm;
        !          1673:
        !          1674:        TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next)
        !          1675:                if (!strcmp(ifgl->ifgl_group->ifg_group, groupname))
        !          1676:                        break;
        !          1677:        if (ifgl == NULL)
        !          1678:                return (ENOENT);
        !          1679:
        !          1680:        TAILQ_REMOVE(&ifp->if_groups, ifgl, ifgl_next);
        !          1681:
        !          1682:        TAILQ_FOREACH(ifgm, &ifgl->ifgl_group->ifg_members, ifgm_next)
        !          1683:                if (ifgm->ifgm_ifp == ifp)
        !          1684:                        break;
        !          1685:
        !          1686:        if (ifgm != NULL) {
        !          1687:                TAILQ_REMOVE(&ifgl->ifgl_group->ifg_members, ifgm, ifgm_next);
        !          1688:                free(ifgm, M_TEMP);
        !          1689:        }
        !          1690:
        !          1691:        if (--ifgl->ifgl_group->ifg_refcnt == 0) {
        !          1692:                TAILQ_REMOVE(&ifg_head, ifgl->ifgl_group, ifg_next);
        !          1693: #if NPF > 0
        !          1694:                pfi_detach_ifgroup(ifgl->ifgl_group);
        !          1695: #endif
        !          1696:                free(ifgl->ifgl_group, M_TEMP);
        !          1697:        }
        !          1698:
        !          1699:        free(ifgl, M_TEMP);
        !          1700:
        !          1701: #if NPF > 0
        !          1702:        pfi_group_change(groupname);
        !          1703: #endif
        !          1704:
        !          1705:        return (0);
        !          1706: }
        !          1707:
        !          1708: /*
        !          1709:  * Stores all groups from an interface in memory pointed
        !          1710:  * to by data
        !          1711:  */
        !          1712: int
        !          1713: if_getgroup(caddr_t data, struct ifnet *ifp)
        !          1714: {
        !          1715:        int                      len, error;
        !          1716:        struct ifg_list         *ifgl;
        !          1717:        struct ifg_req           ifgrq, *ifgp;
        !          1718:        struct ifgroupreq       *ifgr = (struct ifgroupreq *)data;
        !          1719:
        !          1720:        if (ifgr->ifgr_len == 0) {
        !          1721:                TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next)
        !          1722:                        ifgr->ifgr_len += sizeof(struct ifg_req);
        !          1723:                return (0);
        !          1724:        }
        !          1725:
        !          1726:        len = ifgr->ifgr_len;
        !          1727:        ifgp = ifgr->ifgr_groups;
        !          1728:        TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next) {
        !          1729:                if (len < sizeof(ifgrq))
        !          1730:                        return (EINVAL);
        !          1731:                bzero(&ifgrq, sizeof ifgrq);
        !          1732:                strlcpy(ifgrq.ifgrq_group, ifgl->ifgl_group->ifg_group,
        !          1733:                    sizeof(ifgrq.ifgrq_group));
        !          1734:                if ((error = copyout((caddr_t)&ifgrq, (caddr_t)ifgp,
        !          1735:                    sizeof(struct ifg_req))))
        !          1736:                        return (error);
        !          1737:                len -= sizeof(ifgrq);
        !          1738:                ifgp++;
        !          1739:        }
        !          1740:
        !          1741:        return (0);
        !          1742: }
        !          1743:
        !          1744: /*
        !          1745:  * Stores all members of a group in memory pointed to by data
        !          1746:  */
        !          1747: int
        !          1748: if_getgroupmembers(caddr_t data)
        !          1749: {
        !          1750:        struct ifgroupreq       *ifgr = (struct ifgroupreq *)data;
        !          1751:        struct ifg_group        *ifg;
        !          1752:        struct ifg_member       *ifgm;
        !          1753:        struct ifg_req           ifgrq, *ifgp;
        !          1754:        int                      len, error;
        !          1755:
        !          1756:        TAILQ_FOREACH(ifg, &ifg_head, ifg_next)
        !          1757:                if (!strcmp(ifg->ifg_group, ifgr->ifgr_name))
        !          1758:                        break;
        !          1759:        if (ifg == NULL)
        !          1760:                return (ENOENT);
        !          1761:
        !          1762:        if (ifgr->ifgr_len == 0) {
        !          1763:                TAILQ_FOREACH(ifgm, &ifg->ifg_members, ifgm_next)
        !          1764:                        ifgr->ifgr_len += sizeof(ifgrq);
        !          1765:                return (0);
        !          1766:        }
        !          1767:
        !          1768:        len = ifgr->ifgr_len;
        !          1769:        ifgp = ifgr->ifgr_groups;
        !          1770:        TAILQ_FOREACH(ifgm, &ifg->ifg_members, ifgm_next) {
        !          1771:                if (len < sizeof(ifgrq))
        !          1772:                        return (EINVAL);
        !          1773:                bzero(&ifgrq, sizeof ifgrq);
        !          1774:                strlcpy(ifgrq.ifgrq_member, ifgm->ifgm_ifp->if_xname,
        !          1775:                    sizeof(ifgrq.ifgrq_member));
        !          1776:                if ((error = copyout((caddr_t)&ifgrq, (caddr_t)ifgp,
        !          1777:                    sizeof(struct ifg_req))))
        !          1778:                        return (error);
        !          1779:                len -= sizeof(ifgrq);
        !          1780:                ifgp++;
        !          1781:        }
        !          1782:
        !          1783:        return (0);
        !          1784: }
        !          1785:
        !          1786: int
        !          1787: if_getgroupattribs(caddr_t data)
        !          1788: {
        !          1789:        struct ifgroupreq       *ifgr = (struct ifgroupreq *)data;
        !          1790:        struct ifg_group        *ifg;
        !          1791:
        !          1792:        TAILQ_FOREACH(ifg, &ifg_head, ifg_next)
        !          1793:                if (!strcmp(ifg->ifg_group, ifgr->ifgr_name))
        !          1794:                        break;
        !          1795:        if (ifg == NULL)
        !          1796:                return (ENOENT);
        !          1797:
        !          1798:        ifgr->ifgr_attrib.ifg_carp_demoted = ifg->ifg_carp_demoted;
        !          1799:
        !          1800:        return (0);
        !          1801: }
        !          1802:
        !          1803: int
        !          1804: if_setgroupattribs(caddr_t data)
        !          1805: {
        !          1806:        struct ifgroupreq       *ifgr = (struct ifgroupreq *)data;
        !          1807:        struct ifg_group        *ifg;
        !          1808:        struct ifg_member       *ifgm;
        !          1809:        int                      demote;
        !          1810:
        !          1811:        TAILQ_FOREACH(ifg, &ifg_head, ifg_next)
        !          1812:                if (!strcmp(ifg->ifg_group, ifgr->ifgr_name))
        !          1813:                        break;
        !          1814:        if (ifg == NULL)
        !          1815:                return (ENOENT);
        !          1816:
        !          1817:        demote = ifgr->ifgr_attrib.ifg_carp_demoted;
        !          1818:        if (demote + ifg->ifg_carp_demoted > 0xff ||
        !          1819:            demote + ifg->ifg_carp_demoted < 0)
        !          1820:                return (ERANGE);
        !          1821:
        !          1822:        ifg->ifg_carp_demoted += demote;
        !          1823:
        !          1824:        TAILQ_FOREACH(ifgm, &ifg->ifg_members, ifgm_next)
        !          1825:                if (ifgm->ifgm_ifp->if_ioctl)
        !          1826:                        ifgm->ifgm_ifp->if_ioctl(ifgm->ifgm_ifp,
        !          1827:                            SIOCSIFGATTR, data);
        !          1828:        return (0);
        !          1829: }
        !          1830:
        !          1831: void
        !          1832: if_group_routechange(struct sockaddr *dst, struct sockaddr *mask)
        !          1833: {
        !          1834:        switch (dst->sa_family) {
        !          1835:        case AF_INET:
        !          1836:                if (satosin(dst)->sin_addr.s_addr == INADDR_ANY)
        !          1837:                        if_group_egress_build();
        !          1838:                break;
        !          1839: #ifdef INET6
        !          1840:        case AF_INET6:
        !          1841:                if (IN6_ARE_ADDR_EQUAL(&(satosin6(dst))->sin6_addr,
        !          1842:                    &in6addr_any) &&
        !          1843:                    mask && IN6_ARE_ADDR_EQUAL(&(satosin6(mask))->sin6_addr,
        !          1844:                    &in6addr_any))
        !          1845:                        if_group_egress_build();
        !          1846:                break;
        !          1847: #endif
        !          1848:        }
        !          1849: }
        !          1850:
        !          1851: int
        !          1852: if_group_egress_build(void)
        !          1853: {
        !          1854:        struct ifg_group        *ifg;
        !          1855:        struct ifg_member       *ifgm, *next;
        !          1856:        struct sockaddr_in       sa_in;
        !          1857: #ifdef INET6
        !          1858:        struct sockaddr_in6      sa_in6;
        !          1859: #endif
        !          1860:        struct radix_node       *rn;
        !          1861:        struct rtentry          *rt;
        !          1862:
        !          1863:        TAILQ_FOREACH(ifg, &ifg_head, ifg_next)
        !          1864:                if (!strcmp(ifg->ifg_group, IFG_EGRESS))
        !          1865:                        break;
        !          1866:
        !          1867:        if (ifg != NULL)
        !          1868:                for (ifgm = TAILQ_FIRST(&ifg->ifg_members); ifgm; ifgm = next) {
        !          1869:                        next = TAILQ_NEXT(ifgm, ifgm_next);
        !          1870:                        if_delgroup(ifgm->ifgm_ifp, IFG_EGRESS);
        !          1871:                }
        !          1872:
        !          1873:        bzero(&sa_in, sizeof(sa_in));
        !          1874:        sa_in.sin_len = sizeof(sa_in);
        !          1875:        sa_in.sin_family = AF_INET;
        !          1876:        if ((rn = rt_lookup(sintosa(&sa_in), sintosa(&sa_in), 0)) != NULL) {
        !          1877:                do {
        !          1878:                        rt = (struct rtentry *)rn;
        !          1879:                        if (rt->rt_ifp)
        !          1880:                                if_addgroup(rt->rt_ifp, IFG_EGRESS);
        !          1881: #ifndef SMALL_KERNEL
        !          1882:                        rn = rn_mpath_next(rn);
        !          1883: #else
        !          1884:                        rn = NULL;
        !          1885: #endif
        !          1886:                } while (rn != NULL);
        !          1887:        }
        !          1888:
        !          1889: #ifdef INET6
        !          1890:        bcopy(&sa6_any, &sa_in6, sizeof(sa_in6));
        !          1891:        if ((rn = rt_lookup(sin6tosa(&sa_in6), sin6tosa(&sa_in6), 0)) != NULL) {
        !          1892:                do {
        !          1893:                        rt = (struct rtentry *)rn;
        !          1894:                        if (rt->rt_ifp)
        !          1895:                                if_addgroup(rt->rt_ifp, IFG_EGRESS);
        !          1896: #ifndef SMALL_KERNEL
        !          1897:                        rn = rn_mpath_next(rn);
        !          1898: #else
        !          1899:                        rn = NULL;
        !          1900: #endif
        !          1901:                } while (rn != NULL);
        !          1902:        }
        !          1903: #endif
        !          1904:
        !          1905:        return (0);
        !          1906: }
        !          1907:
        !          1908: /*
        !          1909:  * Set/clear promiscuous mode on interface ifp based on the truth value
        !          1910:  * of pswitch.  The calls are reference counted so that only the first
        !          1911:  * "on" request actually has an effect, as does the final "off" request.
        !          1912:  * Results are undefined if the "off" and "on" requests are not matched.
        !          1913:  */
        !          1914: int
        !          1915: ifpromisc(struct ifnet *ifp, int pswitch)
        !          1916: {
        !          1917:        struct ifreq ifr;
        !          1918:
        !          1919:        if (pswitch) {
        !          1920:                /*
        !          1921:                 * If the device is not configured up, we cannot put it in
        !          1922:                 * promiscuous mode.
        !          1923:                 */
        !          1924:                if ((ifp->if_flags & IFF_UP) == 0)
        !          1925:                        return (ENETDOWN);
        !          1926:                if (ifp->if_pcount++ != 0)
        !          1927:                        return (0);
        !          1928:                ifp->if_flags |= IFF_PROMISC;
        !          1929:        } else {
        !          1930:                if (--ifp->if_pcount > 0)
        !          1931:                        return (0);
        !          1932:                ifp->if_flags &= ~IFF_PROMISC;
        !          1933:                /*
        !          1934:                 * If the device is not configured up, we should not need to
        !          1935:                 * turn off promiscuous mode (device should have turned it
        !          1936:                 * off when interface went down; and will look at IFF_PROMISC
        !          1937:                 * again next time interface comes up).
        !          1938:                 */
        !          1939:                if ((ifp->if_flags & IFF_UP) == 0)
        !          1940:                        return (0);
        !          1941:        }
        !          1942:        ifr.ifr_flags = ifp->if_flags;
        !          1943:        return ((*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr));
        !          1944: }
        !          1945:
        !          1946: int
        !          1947: sysctl_ifq(int *name, u_int namelen, void *oldp, size_t *oldlenp,
        !          1948:     void *newp, size_t newlen, struct ifqueue *ifq)
        !          1949: {
        !          1950:        /* All sysctl names at this level are terminal. */
        !          1951:        if (namelen != 1)
        !          1952:                return (ENOTDIR);
        !          1953:
        !          1954:        switch (name[0]) {
        !          1955:        case IFQCTL_LEN:
        !          1956:                return (sysctl_rdint(oldp, oldlenp, newp, ifq->ifq_len));
        !          1957:        case IFQCTL_MAXLEN:
        !          1958:                return (sysctl_int(oldp, oldlenp, newp, newlen,
        !          1959:                    &ifq->ifq_maxlen));
        !          1960:        case IFQCTL_DROPS:
        !          1961:                return (sysctl_rdint(oldp, oldlenp, newp, ifq->ifq_drops));
        !          1962:        default:
        !          1963:                return (EOPNOTSUPP);
        !          1964:        }
        !          1965:        /* NOTREACHED */
        !          1966: }
        !          1967:
        !          1968: void
        !          1969: netrndintr(void)
        !          1970: {
        !          1971:        add_net_randomness(0);
        !          1972: }

CVSweb