[BACK]Return to in.c CVS log [TXT][DIR] Up to [local] / sys / netinet

Annotation of sys/netinet/in.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: in.c,v 1.49 2007/07/20 19:00:35 claudio Exp $ */
        !             2: /*     $NetBSD: in.c,v 1.26 1996/02/13 23:41:39 christos Exp $ */
        !             3:
        !             4: /*
        !             5:  * Copyright (C) 2001 WIDE Project.  All rights reserved.
        !             6:  *
        !             7:  * Redistribution and use in source and binary forms, with or without
        !             8:  * modification, are permitted provided that the following conditions
        !             9:  * are met:
        !            10:  * 1. Redistributions of source code must retain the above copyright
        !            11:  *    notice, this list of conditions and the following disclaimer.
        !            12:  * 2. Redistributions in binary form must reproduce the above copyright
        !            13:  *    notice, this list of conditions and the following disclaimer in the
        !            14:  *    documentation and/or other materials provided with the distribution.
        !            15:  * 3. Neither the name of the project nor the names of its contributors
        !            16:  *    may be used to endorse or promote products derived from this software
        !            17:  *    without specific prior written permission.
        !            18:  *
        !            19:  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
        !            20:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            21:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            22:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
        !            23:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            24:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            25:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            26:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            27:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            28:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            29:  * SUCH DAMAGE.
        !            30:  */
        !            31:
        !            32: /*
        !            33:  * Copyright (c) 1982, 1986, 1991, 1993
        !            34:  *     The Regents of the University of California.  All rights reserved.
        !            35:  *
        !            36:  * Redistribution and use in source and binary forms, with or without
        !            37:  * modification, are permitted provided that the following conditions
        !            38:  * are met:
        !            39:  * 1. Redistributions of source code must retain the above copyright
        !            40:  *    notice, this list of conditions and the following disclaimer.
        !            41:  * 2. Redistributions in binary form must reproduce the above copyright
        !            42:  *    notice, this list of conditions and the following disclaimer in the
        !            43:  *    documentation and/or other materials provided with the distribution.
        !            44:  * 3. Neither the name of the University nor the names of its contributors
        !            45:  *    may be used to endorse or promote products derived from this software
        !            46:  *    without specific prior written permission.
        !            47:  *
        !            48:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            49:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            50:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            51:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            52:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            53:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            54:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            55:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            56:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            57:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            58:  * SUCH DAMAGE.
        !            59:  *
        !            60:  *     @(#)in.c        8.2 (Berkeley) 11/15/93
        !            61:  */
        !            62:
        !            63: #include <sys/param.h>
        !            64: #include <sys/systm.h>
        !            65: #include <sys/ioctl.h>
        !            66: #include <sys/malloc.h>
        !            67: #include <sys/socket.h>
        !            68: #include <sys/socketvar.h>
        !            69:
        !            70: #include <net/if.h>
        !            71: #include <net/route.h>
        !            72:
        !            73: #include "carp.h"
        !            74: #if NCARP > 0
        !            75: #include <net/if_types.h>
        !            76: #endif
        !            77:
        !            78: #include <netinet/in.h>
        !            79: #include <netinet/in_var.h>
        !            80: #include <netinet/igmp_var.h>
        !            81:
        !            82: #ifdef MROUTING
        !            83: #include <netinet/ip_mroute.h>
        !            84: #endif
        !            85:
        !            86: #include "ether.h"
        !            87:
        !            88: #ifdef INET
        !            89:
        !            90: int in_mask2len(struct in_addr *);
        !            91: void in_len2mask(struct in_addr *, int);
        !            92: int in_lifaddr_ioctl(struct socket *, u_long, caddr_t,
        !            93:        struct ifnet *);
        !            94:
        !            95: int in_addprefix(struct in_ifaddr *, int);
        !            96: int in_scrubprefix(struct in_ifaddr *);
        !            97:
        !            98: #ifndef SUBNETSARELOCAL
        !            99: #define        SUBNETSARELOCAL 0
        !           100: #endif
        !           101:
        !           102: #ifndef HOSTZEROBROADCAST
        !           103: #define HOSTZEROBROADCAST 1
        !           104: #endif
        !           105:
        !           106: int subnetsarelocal = SUBNETSARELOCAL;
        !           107: int hostzeroisbroadcast = HOSTZEROBROADCAST;
        !           108:
        !           109: /*
        !           110:  * Return 1 if an internet address is for a ``local'' host
        !           111:  * (one to which we have a connection).  If subnetsarelocal
        !           112:  * is true, this includes other subnets of the local net.
        !           113:  * Otherwise, it includes only the directly-connected (sub)nets.
        !           114:  */
        !           115: int
        !           116: in_localaddr(in)
        !           117:        struct in_addr in;
        !           118: {
        !           119:        struct in_ifaddr *ia;
        !           120:
        !           121:        if (subnetsarelocal) {
        !           122:                TAILQ_FOREACH(ia, &in_ifaddr, ia_list)
        !           123:                        if ((in.s_addr & ia->ia_netmask) == ia->ia_net)
        !           124:                                return (1);
        !           125:        } else {
        !           126:                TAILQ_FOREACH(ia, &in_ifaddr, ia_list)
        !           127:                        if ((in.s_addr & ia->ia_subnetmask) == ia->ia_subnet)
        !           128:                                return (1);
        !           129:        }
        !           130:        return (0);
        !           131: }
        !           132:
        !           133: /*
        !           134:  * Determine whether an IP address is in a reserved set of addresses
        !           135:  * that may not be forwarded, or whether datagrams to that destination
        !           136:  * may be forwarded.
        !           137:  */
        !           138: int
        !           139: in_canforward(in)
        !           140:        struct in_addr in;
        !           141: {
        !           142:        u_int32_t net;
        !           143:
        !           144:        if (IN_EXPERIMENTAL(in.s_addr) || IN_MULTICAST(in.s_addr))
        !           145:                return (0);
        !           146:        if (IN_CLASSA(in.s_addr)) {
        !           147:                net = in.s_addr & IN_CLASSA_NET;
        !           148:                if (net == 0 || net == htonl(IN_LOOPBACKNET << IN_CLASSA_NSHIFT))
        !           149:                        return (0);
        !           150:        }
        !           151:        return (1);
        !           152: }
        !           153:
        !           154: /*
        !           155:  * Trim a mask in a sockaddr
        !           156:  */
        !           157: void
        !           158: in_socktrim(ap)
        !           159:        struct sockaddr_in *ap;
        !           160: {
        !           161:        char *cplim = (char *) &ap->sin_addr;
        !           162:        char *cp = (char *) (&ap->sin_addr + 1);
        !           163:
        !           164:        ap->sin_len = 0;
        !           165:        while (--cp >= cplim)
        !           166:                if (*cp) {
        !           167:                        (ap)->sin_len = cp - (char *) (ap) + 1;
        !           168:                        break;
        !           169:                }
        !           170: }
        !           171:
        !           172: int
        !           173: in_mask2len(mask)
        !           174:        struct in_addr *mask;
        !           175: {
        !           176:        int x, y;
        !           177:        u_char *p;
        !           178:
        !           179:        p = (u_char *)mask;
        !           180:        for (x = 0; x < sizeof(*mask); x++) {
        !           181:                if (p[x] != 0xff)
        !           182:                        break;
        !           183:        }
        !           184:        y = 0;
        !           185:        if (x < sizeof(*mask)) {
        !           186:                for (y = 0; y < 8; y++) {
        !           187:                        if ((p[x] & (0x80 >> y)) == 0)
        !           188:                                break;
        !           189:                }
        !           190:        }
        !           191:        return x * 8 + y;
        !           192: }
        !           193:
        !           194: void
        !           195: in_len2mask(mask, len)
        !           196:        struct in_addr *mask;
        !           197:        int len;
        !           198: {
        !           199:        int i;
        !           200:        u_char *p;
        !           201:
        !           202:        p = (u_char *)mask;
        !           203:        bzero(mask, sizeof(*mask));
        !           204:        for (i = 0; i < len / 8; i++)
        !           205:                p[i] = 0xff;
        !           206:        if (len % 8)
        !           207:                p[i] = (0xff00 >> (len % 8)) & 0xff;
        !           208: }
        !           209:
        !           210: int    in_interfaces;          /* number of external internet interfaces */
        !           211:
        !           212: /*
        !           213:  * Generic internet control operations (ioctl's).
        !           214:  * Ifp is 0 if not an interface-specific ioctl.
        !           215:  */
        !           216: /* ARGSUSED */
        !           217: int
        !           218: in_control(so, cmd, data, ifp)
        !           219:        struct socket *so;
        !           220:        u_long cmd;
        !           221:        caddr_t data;
        !           222:        struct ifnet *ifp;
        !           223: {
        !           224:        struct ifreq *ifr = (struct ifreq *)data;
        !           225:        struct in_ifaddr *ia = 0;
        !           226:        struct in_aliasreq *ifra = (struct in_aliasreq *)data;
        !           227:        struct sockaddr_in oldaddr;
        !           228:        int error, hostIsNew, maskIsNew;
        !           229:        int newifaddr;
        !           230:        int s;
        !           231:
        !           232:        switch (cmd) {
        !           233:        case SIOCALIFADDR:
        !           234:        case SIOCDLIFADDR:
        !           235:                if ((so->so_state & SS_PRIV) == 0)
        !           236:                        return (EPERM);
        !           237:                /* FALLTHROUGH */
        !           238:        case SIOCGLIFADDR:
        !           239:                if (!ifp)
        !           240:                        return EINVAL;
        !           241:                return in_lifaddr_ioctl(so, cmd, data, ifp);
        !           242:        }
        !           243:
        !           244:        /*
        !           245:         * Find address for this interface, if it exists.
        !           246:         */
        !           247:        if (ifp)
        !           248:                TAILQ_FOREACH(ia, &in_ifaddr, ia_list)
        !           249:                        if (ia->ia_ifp == ifp)
        !           250:                                break;
        !           251:
        !           252:        switch (cmd) {
        !           253:
        !           254:        case SIOCAIFADDR:
        !           255:        case SIOCDIFADDR:
        !           256:                if (ifra->ifra_addr.sin_family == AF_INET)
        !           257:                        for (; ia != TAILQ_END(&in_ifaddr);
        !           258:                            ia = TAILQ_NEXT(ia, ia_list)) {
        !           259:                                if (ia->ia_ifp == ifp &&
        !           260:                                    ia->ia_addr.sin_addr.s_addr ==
        !           261:                                        ifra->ifra_addr.sin_addr.s_addr)
        !           262:                                    break;
        !           263:                        }
        !           264:                if (cmd == SIOCDIFADDR && ia == 0)
        !           265:                        return (EADDRNOTAVAIL);
        !           266:                /* FALLTHROUGH */
        !           267:        case SIOCSIFADDR:
        !           268:        case SIOCSIFNETMASK:
        !           269:        case SIOCSIFDSTADDR:
        !           270:                if ((so->so_state & SS_PRIV) == 0)
        !           271:                        return (EPERM);
        !           272:
        !           273:                if (ifp == 0)
        !           274:                        panic("in_control");
        !           275:                if (ia == (struct in_ifaddr *)0) {
        !           276:                        ia = (struct in_ifaddr *)
        !           277:                                malloc(sizeof *ia, M_IFADDR, M_WAITOK);
        !           278:                        bzero((caddr_t)ia, sizeof *ia);
        !           279:                        s = splsoftnet();
        !           280:                        TAILQ_INSERT_TAIL(&in_ifaddr, ia, ia_list);
        !           281:                        TAILQ_INSERT_TAIL(&ifp->if_addrlist, (struct ifaddr *)ia,
        !           282:                            ifa_list);
        !           283:                        ia->ia_addr.sin_family = AF_INET;
        !           284:                        ia->ia_addr.sin_len = sizeof(ia->ia_addr);
        !           285:                        ia->ia_ifa.ifa_addr = sintosa(&ia->ia_addr);
        !           286:                        ia->ia_ifa.ifa_dstaddr = sintosa(&ia->ia_dstaddr);
        !           287:                        ia->ia_ifa.ifa_netmask = sintosa(&ia->ia_sockmask);
        !           288:                        ia->ia_sockmask.sin_len = 8;
        !           289:                        if (ifp->if_flags & IFF_BROADCAST) {
        !           290:                                ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr);
        !           291:                                ia->ia_broadaddr.sin_family = AF_INET;
        !           292:                        }
        !           293:                        ia->ia_ifp = ifp;
        !           294:                        LIST_INIT(&ia->ia_multiaddrs);
        !           295:                        if ((ifp->if_flags & IFF_LOOPBACK) == 0)
        !           296:                                in_interfaces++;
        !           297:                        splx(s);
        !           298:
        !           299:                        newifaddr = 1;
        !           300:                } else
        !           301:                        newifaddr = 0;
        !           302:                break;
        !           303:
        !           304:        case SIOCSIFBRDADDR:
        !           305:                if ((so->so_state & SS_PRIV) == 0)
        !           306:                        return (EPERM);
        !           307:                /* FALLTHROUGH */
        !           308:
        !           309:        case SIOCGIFADDR:
        !           310:        case SIOCGIFNETMASK:
        !           311:        case SIOCGIFDSTADDR:
        !           312:        case SIOCGIFBRDADDR:
        !           313:                if (ia && satosin(&ifr->ifr_addr)->sin_addr.s_addr) {
        !           314:                        struct in_ifaddr *ia2;
        !           315:
        !           316:                        for (ia2 = ia; ia2 != TAILQ_END(&in_ifaddr);
        !           317:                            ia2 = TAILQ_NEXT(ia2, ia_list)) {
        !           318:                                if (ia2->ia_ifp == ifp &&
        !           319:                                    ia2->ia_addr.sin_addr.s_addr ==
        !           320:                                    satosin(&ifr->ifr_addr)->sin_addr.s_addr)
        !           321:                                        break;
        !           322:                        }
        !           323:                        if (ia2 && ia2->ia_ifp == ifp)
        !           324:                                ia = ia2;
        !           325:                }
        !           326:                if (ia == (struct in_ifaddr *)0)
        !           327:                        return (EADDRNOTAVAIL);
        !           328:                break;
        !           329:        }
        !           330:        switch (cmd) {
        !           331:
        !           332:        case SIOCGIFADDR:
        !           333:                *satosin(&ifr->ifr_addr) = ia->ia_addr;
        !           334:                break;
        !           335:
        !           336:        case SIOCGIFBRDADDR:
        !           337:                if ((ifp->if_flags & IFF_BROADCAST) == 0)
        !           338:                        return (EINVAL);
        !           339:                *satosin(&ifr->ifr_dstaddr) = ia->ia_broadaddr;
        !           340:                break;
        !           341:
        !           342:        case SIOCGIFDSTADDR:
        !           343:                if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
        !           344:                        return (EINVAL);
        !           345:                *satosin(&ifr->ifr_dstaddr) = ia->ia_dstaddr;
        !           346:                break;
        !           347:
        !           348:        case SIOCGIFNETMASK:
        !           349:                *satosin(&ifr->ifr_addr) = ia->ia_sockmask;
        !           350:                break;
        !           351:
        !           352:        case SIOCSIFDSTADDR:
        !           353:                if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
        !           354:                        return (EINVAL);
        !           355:                s = splsoftnet();
        !           356:                oldaddr = ia->ia_dstaddr;
        !           357:                ia->ia_dstaddr = *satosin(&ifr->ifr_dstaddr);
        !           358:                if (ifp->if_ioctl && (error = (*ifp->if_ioctl)
        !           359:                                        (ifp, SIOCSIFDSTADDR, (caddr_t)ia))) {
        !           360:                        ia->ia_dstaddr = oldaddr;
        !           361:                        splx(s);
        !           362:                        return (error);
        !           363:                }
        !           364:                if (ia->ia_flags & IFA_ROUTE) {
        !           365:                        ia->ia_ifa.ifa_dstaddr = sintosa(&oldaddr);
        !           366:                        rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
        !           367:                        ia->ia_ifa.ifa_dstaddr = sintosa(&ia->ia_dstaddr);
        !           368:                        rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
        !           369:                }
        !           370:                splx(s);
        !           371:                break;
        !           372:
        !           373:        case SIOCSIFBRDADDR:
        !           374:                if ((ifp->if_flags & IFF_BROADCAST) == 0)
        !           375:                        return (EINVAL);
        !           376:                ia->ia_broadaddr = *satosin(&ifr->ifr_broadaddr);
        !           377:                break;
        !           378:
        !           379:        case SIOCSIFADDR:
        !           380:                s = splsoftnet();
        !           381:                error = in_ifinit(ifp, ia, satosin(&ifr->ifr_addr), 1);
        !           382:                if (!error)
        !           383:                        dohooks(ifp->if_addrhooks, 0);
        !           384:                else if (newifaddr) {
        !           385:                        splx(s);
        !           386:                        goto cleanup;
        !           387:                }
        !           388:                splx(s);
        !           389:                return error;
        !           390:
        !           391:        case SIOCSIFNETMASK:
        !           392:                ia->ia_subnetmask = ia->ia_sockmask.sin_addr.s_addr =
        !           393:                    ifra->ifra_addr.sin_addr.s_addr;
        !           394:                break;
        !           395:
        !           396:        case SIOCAIFADDR:
        !           397:                maskIsNew = 0;
        !           398:                hostIsNew = 1;
        !           399:                error = 0;
        !           400:                s = splsoftnet();
        !           401:                if (ia->ia_addr.sin_family == AF_INET) {
        !           402:                        if (ifra->ifra_addr.sin_len == 0) {
        !           403:                                ifra->ifra_addr = ia->ia_addr;
        !           404:                                hostIsNew = 0;
        !           405:                        } else if (ifra->ifra_addr.sin_addr.s_addr ==
        !           406:                                               ia->ia_addr.sin_addr.s_addr)
        !           407:                                hostIsNew = 0;
        !           408:                }
        !           409:                if (ifra->ifra_mask.sin_len) {
        !           410:                        in_ifscrub(ifp, ia);
        !           411:                        ia->ia_sockmask = ifra->ifra_mask;
        !           412:                        ia->ia_subnetmask = ia->ia_sockmask.sin_addr.s_addr;
        !           413:                        maskIsNew = 1;
        !           414:                }
        !           415:                if ((ifp->if_flags & IFF_POINTOPOINT) &&
        !           416:                    (ifra->ifra_dstaddr.sin_family == AF_INET)) {
        !           417:                        in_ifscrub(ifp, ia);
        !           418:                        ia->ia_dstaddr = ifra->ifra_dstaddr;
        !           419:                        maskIsNew  = 1; /* We lie; but the effect's the same */
        !           420:                }
        !           421:                if (ifra->ifra_addr.sin_family == AF_INET &&
        !           422:                    (hostIsNew || maskIsNew)) {
        !           423:                        error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0);
        !           424:                }
        !           425:                if ((ifp->if_flags & IFF_BROADCAST) &&
        !           426:                    (ifra->ifra_broadaddr.sin_family == AF_INET))
        !           427:                        ia->ia_broadaddr = ifra->ifra_broadaddr;
        !           428:                if (!error)
        !           429:                        dohooks(ifp->if_addrhooks, 0);
        !           430:                else if (newifaddr) {
        !           431:                        splx(s);
        !           432:                        goto cleanup;
        !           433:                }
        !           434:                splx(s);
        !           435:                return (error);
        !           436:
        !           437:        case SIOCDIFADDR: {
        !           438:
        !           439:                error = 0;
        !           440: cleanup:
        !           441:                /*
        !           442:                 * Even if the individual steps were safe, shouldn't
        !           443:                 * these kinds of changes happen atomically?  What
        !           444:                 * should happen to a packet that was routed after
        !           445:                 * the scrub but before the other steps?
        !           446:                 */
        !           447:                s = splsoftnet();
        !           448:                in_ifscrub(ifp, ia);
        !           449:                TAILQ_REMOVE(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list);
        !           450:                TAILQ_REMOVE(&in_ifaddr, ia, ia_list);
        !           451:                if (ia->ia_allhosts != NULL) {
        !           452:                        in_delmulti(ia->ia_allhosts);
        !           453:                        ia->ia_allhosts = NULL;
        !           454:                }
        !           455:                IFAFREE((&ia->ia_ifa));
        !           456:                dohooks(ifp->if_addrhooks, 0);
        !           457:                splx(s);
        !           458:                return (error);
        !           459:                }
        !           460:
        !           461: #ifdef MROUTING
        !           462:        case SIOCGETVIFCNT:
        !           463:        case SIOCGETSGCNT:
        !           464:                return (mrt_ioctl(so, cmd, data));
        !           465: #endif /* MROUTING */
        !           466:
        !           467:        default:
        !           468:                if (ifp == 0 || ifp->if_ioctl == 0)
        !           469:                        return (EOPNOTSUPP);
        !           470:                return ((*ifp->if_ioctl)(ifp, cmd, data));
        !           471:        }
        !           472:        return (0);
        !           473: }
        !           474:
        !           475: /*
        !           476:  * SIOC[GAD]LIFADDR.
        !           477:  *     SIOCGLIFADDR: get first address. (???)
        !           478:  *     SIOCGLIFADDR with IFLR_PREFIX:
        !           479:  *             get first address that matches the specified prefix.
        !           480:  *     SIOCALIFADDR: add the specified address.
        !           481:  *     SIOCALIFADDR with IFLR_PREFIX:
        !           482:  *             EINVAL since we can't deduce hostid part of the address.
        !           483:  *     SIOCDLIFADDR: delete the specified address.
        !           484:  *     SIOCDLIFADDR with IFLR_PREFIX:
        !           485:  *             delete the first address that matches the specified prefix.
        !           486:  * return values:
        !           487:  *     EINVAL on invalid parameters
        !           488:  *     EADDRNOTAVAIL on prefix match failed/specified address not found
        !           489:  *     other values may be returned from in_ioctl()
        !           490:  */
        !           491: int
        !           492: in_lifaddr_ioctl(so, cmd, data, ifp)
        !           493:        struct socket *so;
        !           494:        u_long cmd;
        !           495:        caddr_t data;
        !           496:        struct ifnet *ifp;
        !           497: {
        !           498:        struct if_laddrreq *iflr = (struct if_laddrreq *)data;
        !           499:        struct ifaddr *ifa;
        !           500:        struct sockaddr *sa;
        !           501:
        !           502:        /* sanity checks */
        !           503:        if (!data || !ifp) {
        !           504:                panic("invalid argument to in_lifaddr_ioctl");
        !           505:                /*NOTRECHED*/
        !           506:        }
        !           507:
        !           508:        switch (cmd) {
        !           509:        case SIOCGLIFADDR:
        !           510:                /* address must be specified on GET with IFLR_PREFIX */
        !           511:                if ((iflr->flags & IFLR_PREFIX) == 0)
        !           512:                        break;
        !           513:                /*FALLTHROUGH*/
        !           514:        case SIOCALIFADDR:
        !           515:        case SIOCDLIFADDR:
        !           516:                /* address must be specified on ADD and DELETE */
        !           517:                sa = (struct sockaddr *)&iflr->addr;
        !           518:                if (sa->sa_family != AF_INET)
        !           519:                        return EINVAL;
        !           520:                if (sa->sa_len != sizeof(struct sockaddr_in))
        !           521:                        return EINVAL;
        !           522:                /* XXX need improvement */
        !           523:                sa = (struct sockaddr *)&iflr->dstaddr;
        !           524:                if (sa->sa_family
        !           525:                 && sa->sa_family != AF_INET)
        !           526:                        return EINVAL;
        !           527:                if (sa->sa_len && sa->sa_len != sizeof(struct sockaddr_in))
        !           528:                        return EINVAL;
        !           529:                break;
        !           530:        default: /*shouldn't happen*/
        !           531: #if 0
        !           532:                panic("invalid cmd to in_lifaddr_ioctl");
        !           533:                /*NOTREACHED*/
        !           534: #else
        !           535:                return EOPNOTSUPP;
        !           536: #endif
        !           537:        }
        !           538:        if (sizeof(struct in_addr) * 8 < iflr->prefixlen)
        !           539:                return EINVAL;
        !           540:
        !           541:        switch (cmd) {
        !           542:        case SIOCALIFADDR:
        !           543:            {
        !           544:                struct in_aliasreq ifra;
        !           545:
        !           546:                if (iflr->flags & IFLR_PREFIX)
        !           547:                        return EINVAL;
        !           548:
        !           549:                /* copy args to in_aliasreq, perform ioctl(SIOCAIFADDR). */
        !           550:                bzero(&ifra, sizeof(ifra));
        !           551:                bcopy(iflr->iflr_name, ifra.ifra_name,
        !           552:                        sizeof(ifra.ifra_name));
        !           553:
        !           554:                bcopy(&iflr->addr, &ifra.ifra_addr,
        !           555:                        ((struct sockaddr *)&iflr->addr)->sa_len);
        !           556:
        !           557:                if (((struct sockaddr *)&iflr->dstaddr)->sa_family) {   /*XXX*/
        !           558:                        bcopy(&iflr->dstaddr, &ifra.ifra_dstaddr,
        !           559:                                ((struct sockaddr *)&iflr->dstaddr)->sa_len);
        !           560:                }
        !           561:
        !           562:                ifra.ifra_mask.sin_family = AF_INET;
        !           563:                ifra.ifra_mask.sin_len = sizeof(struct sockaddr_in);
        !           564:                in_len2mask(&ifra.ifra_mask.sin_addr, iflr->prefixlen);
        !           565:
        !           566:                return in_control(so, SIOCAIFADDR, (caddr_t)&ifra, ifp);
        !           567:            }
        !           568:        case SIOCGLIFADDR:
        !           569:        case SIOCDLIFADDR:
        !           570:            {
        !           571:                struct in_ifaddr *ia;
        !           572:                struct in_addr mask, candidate, match;
        !           573:                struct sockaddr_in *sin;
        !           574:                int cmp;
        !           575:
        !           576:                bzero(&mask, sizeof(mask));
        !           577:                if (iflr->flags & IFLR_PREFIX) {
        !           578:                        /* lookup a prefix rather than address. */
        !           579:                        in_len2mask(&mask, iflr->prefixlen);
        !           580:
        !           581:                        sin = (struct sockaddr_in *)&iflr->addr;
        !           582:                        match.s_addr = sin->sin_addr.s_addr;
        !           583:                        match.s_addr &= mask.s_addr;
        !           584:
        !           585:                        /* if you set extra bits, that's wrong */
        !           586:                        if (match.s_addr != sin->sin_addr.s_addr)
        !           587:                                return EINVAL;
        !           588:
        !           589:                        cmp = 1;
        !           590:                } else {
        !           591:                        if (cmd == SIOCGLIFADDR) {
        !           592:                                /* on getting an address, take the 1st match */
        !           593:                                cmp = 0;        /*XXX*/
        !           594:                        } else {
        !           595:                                /* on deleting an address, do exact match */
        !           596:                                in_len2mask(&mask, 32);
        !           597:                                sin = (struct sockaddr_in *)&iflr->addr;
        !           598:                                match.s_addr = sin->sin_addr.s_addr;
        !           599:
        !           600:                                cmp = 1;
        !           601:                        }
        !           602:                }
        !           603:
        !           604:                TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
        !           605:                        if (ifa->ifa_addr->sa_family != AF_INET)
        !           606:                                continue;
        !           607:                        if (!cmp)
        !           608:                                break;
        !           609:                        candidate.s_addr = ((struct sockaddr_in *)&ifa->ifa_addr)->sin_addr.s_addr;
        !           610:                        candidate.s_addr &= mask.s_addr;
        !           611:                        if (candidate.s_addr == match.s_addr)
        !           612:                                break;
        !           613:                }
        !           614:                if (!ifa)
        !           615:                        return EADDRNOTAVAIL;
        !           616:                ia = (struct in_ifaddr *)ifa;
        !           617:
        !           618:                if (cmd == SIOCGLIFADDR) {
        !           619:                        /* fill in the if_laddrreq structure */
        !           620:                        bcopy(&ia->ia_addr, &iflr->addr, ia->ia_addr.sin_len);
        !           621:
        !           622:                        if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
        !           623:                                bcopy(&ia->ia_dstaddr, &iflr->dstaddr,
        !           624:                                        ia->ia_dstaddr.sin_len);
        !           625:                        } else
        !           626:                                bzero(&iflr->dstaddr, sizeof(iflr->dstaddr));
        !           627:
        !           628:                        iflr->prefixlen =
        !           629:                                in_mask2len(&ia->ia_sockmask.sin_addr);
        !           630:
        !           631:                        iflr->flags = 0;        /*XXX*/
        !           632:
        !           633:                        return 0;
        !           634:                } else {
        !           635:                        struct in_aliasreq ifra;
        !           636:
        !           637:                        /* fill in_aliasreq and do ioctl(SIOCDIFADDR) */
        !           638:                        bzero(&ifra, sizeof(ifra));
        !           639:                        bcopy(iflr->iflr_name, ifra.ifra_name,
        !           640:                                sizeof(ifra.ifra_name));
        !           641:
        !           642:                        bcopy(&ia->ia_addr, &ifra.ifra_addr,
        !           643:                                ia->ia_addr.sin_len);
        !           644:                        if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
        !           645:                                bcopy(&ia->ia_dstaddr, &ifra.ifra_dstaddr,
        !           646:                                        ia->ia_dstaddr.sin_len);
        !           647:                        }
        !           648:                        bcopy(&ia->ia_sockmask, &ifra.ifra_dstaddr,
        !           649:                                ia->ia_sockmask.sin_len);
        !           650:
        !           651:                        return in_control(so, SIOCDIFADDR, (caddr_t)&ifra, ifp);
        !           652:                }
        !           653:            }
        !           654:        }
        !           655:
        !           656:        return EOPNOTSUPP;      /*just for safety*/
        !           657: }
        !           658:
        !           659: /*
        !           660:  * Delete any existing route for an interface.
        !           661:  */
        !           662: void
        !           663: in_ifscrub(ifp, ia)
        !           664:        struct ifnet *ifp;
        !           665:        struct in_ifaddr *ia;
        !           666: {
        !           667:        in_scrubprefix(ia);
        !           668: }
        !           669:
        !           670: /*
        !           671:  * Initialize an interface's internet address
        !           672:  * and routing table entry.
        !           673:  */
        !           674: int
        !           675: in_ifinit(ifp, ia, sin, scrub)
        !           676:        struct ifnet *ifp;
        !           677:        struct in_ifaddr *ia;
        !           678:        struct sockaddr_in *sin;
        !           679:        int scrub;
        !           680: {
        !           681:        u_int32_t i = sin->sin_addr.s_addr;
        !           682:        struct sockaddr_in oldaddr;
        !           683:        int s = splnet(), flags = RTF_UP, error;
        !           684:
        !           685:        oldaddr = ia->ia_addr;
        !           686:        ia->ia_addr = *sin;
        !           687:        /*
        !           688:         * Give the interface a chance to initialize
        !           689:         * if this is its first address,
        !           690:         * and to validate the address if necessary.
        !           691:         */
        !           692:        if (ifp->if_ioctl &&
        !           693:            (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) {
        !           694:                ia->ia_addr = oldaddr;
        !           695:                splx(s);
        !           696:                return (error);
        !           697:        }
        !           698:        splx(s);
        !           699:
        !           700:        /*
        !           701:         * How should a packet be routed during
        !           702:         * an address change--and is it safe?
        !           703:         * Is the "ifp" even in a consistent state?
        !           704:         * Be safe for now.
        !           705:         */
        !           706:        splassert(IPL_SOFTNET);
        !           707:
        !           708:        if (scrub) {
        !           709:                ia->ia_ifa.ifa_addr = sintosa(&oldaddr);
        !           710:                in_ifscrub(ifp, ia);
        !           711:                ia->ia_ifa.ifa_addr = sintosa(&ia->ia_addr);
        !           712:        }
        !           713:        if (IN_CLASSA(i))
        !           714:                ia->ia_netmask = IN_CLASSA_NET;
        !           715:        else if (IN_CLASSB(i))
        !           716:                ia->ia_netmask = IN_CLASSB_NET;
        !           717:        else
        !           718:                ia->ia_netmask = IN_CLASSC_NET;
        !           719:        /*
        !           720:         * The subnet mask usually includes at least the standard network part,
        !           721:         * but may may be smaller in the case of supernetting.
        !           722:         * If it is set, we believe it.
        !           723:         */
        !           724:        if (ia->ia_subnetmask == 0) {
        !           725:                ia->ia_subnetmask = ia->ia_netmask;
        !           726:                ia->ia_sockmask.sin_addr.s_addr = ia->ia_subnetmask;
        !           727:        } else
        !           728:                ia->ia_netmask &= ia->ia_subnetmask;
        !           729:        ia->ia_net = i & ia->ia_netmask;
        !           730:        ia->ia_subnet = i & ia->ia_subnetmask;
        !           731:        in_socktrim(&ia->ia_sockmask);
        !           732:        /*
        !           733:         * Add route for the network.
        !           734:         */
        !           735:        ia->ia_ifa.ifa_metric = ifp->if_metric;
        !           736:        if (ifp->if_flags & IFF_BROADCAST) {
        !           737:                ia->ia_broadaddr.sin_addr.s_addr =
        !           738:                        ia->ia_subnet | ~ia->ia_subnetmask;
        !           739:                ia->ia_netbroadcast.s_addr =
        !           740:                        ia->ia_net | ~ia->ia_netmask;
        !           741:        } else if (ifp->if_flags & IFF_LOOPBACK) {
        !           742:                ia->ia_dstaddr = ia->ia_addr;
        !           743:                flags |= RTF_HOST;
        !           744:        } else if (ifp->if_flags & IFF_POINTOPOINT) {
        !           745:                if (ia->ia_dstaddr.sin_family != AF_INET)
        !           746:                        return (0);
        !           747:                flags |= RTF_HOST;
        !           748:        }
        !           749:        error = in_addprefix(ia, flags);
        !           750:        /*
        !           751:         * If the interface supports multicast, join the "all hosts"
        !           752:         * multicast group on that interface.
        !           753:         */
        !           754:        if ((ifp->if_flags & IFF_MULTICAST) && ia->ia_allhosts == NULL) {
        !           755:                struct in_addr addr;
        !           756:
        !           757:                addr.s_addr = INADDR_ALLHOSTS_GROUP;
        !           758:                ia->ia_allhosts = in_addmulti(&addr, ifp);
        !           759:        }
        !           760:        return (error);
        !           761: }
        !           762:
        !           763: #define rtinitflags(x) \
        !           764:        ((((x)->ia_ifp->if_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) != 0) \
        !           765:            ? RTF_HOST : 0)
        !           766:
        !           767: /*
        !           768:  * add a route to prefix ("connected route" in cisco terminology).
        !           769:  * does nothing if there's some interface address with the same prefix already.
        !           770:  */
        !           771: int
        !           772: in_addprefix(target, flags)
        !           773:        struct in_ifaddr *target;
        !           774:        int flags;
        !           775: {
        !           776:        struct in_ifaddr *ia;
        !           777:        struct in_addr prefix, mask, p;
        !           778:        int error;
        !           779:
        !           780:        if ((flags & RTF_HOST) != 0)
        !           781:                prefix = target->ia_dstaddr.sin_addr;
        !           782:        else {
        !           783:                prefix = target->ia_addr.sin_addr;
        !           784:                mask = target->ia_sockmask.sin_addr;
        !           785:                prefix.s_addr &= mask.s_addr;
        !           786:        }
        !           787:
        !           788:        TAILQ_FOREACH(ia, &in_ifaddr, ia_list) {
        !           789:                if (rtinitflags(ia)) {
        !           790:                        p = ia->ia_dstaddr.sin_addr;
        !           791:                        if (prefix.s_addr != p.s_addr)
        !           792:                                continue;
        !           793:                } else {
        !           794:                        p = ia->ia_addr.sin_addr;
        !           795:                        p.s_addr &= ia->ia_sockmask.sin_addr.s_addr;
        !           796:                        if (prefix.s_addr != p.s_addr ||
        !           797:                            mask.s_addr != ia->ia_sockmask.sin_addr.s_addr)
        !           798:                                continue;
        !           799:                }
        !           800:                if ((ia->ia_flags & IFA_ROUTE) == 0)
        !           801:                        continue;
        !           802: #if NCARP > 0
        !           803:                /* move to a real interface instead of carp interface */
        !           804:                if (ia->ia_ifp->if_type == IFT_CARP &&
        !           805:                    target->ia_ifp->if_type != IFT_CARP) {
        !           806:                        rtinit(&(ia->ia_ifa), (int)RTM_DELETE,
        !           807:                            rtinitflags(ia));
        !           808:                        ia->ia_flags &= ~IFA_ROUTE;
        !           809:                        break;
        !           810:                }
        !           811: #endif
        !           812:                /*
        !           813:                 * if we got a matching prefix route inserted by other
        !           814:                 * interface adderss, we don't need to bother
        !           815:                 */
        !           816:                return 0;
        !           817:        }
        !           818:
        !           819:        /*
        !           820:         * noone seem to have prefix route.  insert it.
        !           821:         */
        !           822:        error = rtinit(&target->ia_ifa, (int)RTM_ADD, flags);
        !           823:        if (!error)
        !           824:                target->ia_flags |= IFA_ROUTE;
        !           825:        return error;
        !           826: }
        !           827:
        !           828: /*
        !           829:  * remove a route to prefix ("connected route" in cisco terminology).
        !           830:  * re-installs the route by using another interface address, if there's one
        !           831:  * with the same prefix (otherwise we lose the route mistakenly).
        !           832:  */
        !           833: int
        !           834: in_scrubprefix(target)
        !           835:        struct in_ifaddr *target;
        !           836: {
        !           837:        struct in_ifaddr *ia;
        !           838:        struct in_addr prefix, mask, p;
        !           839:        int error;
        !           840:
        !           841:        if ((target->ia_flags & IFA_ROUTE) == 0)
        !           842:                return 0;
        !           843:
        !           844:        if (rtinitflags(target))
        !           845:                prefix = target->ia_dstaddr.sin_addr;
        !           846:        else {
        !           847:                prefix = target->ia_addr.sin_addr;
        !           848:                mask = target->ia_sockmask.sin_addr;
        !           849:                prefix.s_addr &= mask.s_addr;
        !           850:        }
        !           851:
        !           852:        TAILQ_FOREACH(ia, &in_ifaddr, ia_list) {
        !           853:                if (rtinitflags(ia))
        !           854:                        p = ia->ia_dstaddr.sin_addr;
        !           855:                else {
        !           856:                        p = ia->ia_addr.sin_addr;
        !           857:                        p.s_addr &= ia->ia_sockmask.sin_addr.s_addr;
        !           858:                }
        !           859:
        !           860:                if (prefix.s_addr != p.s_addr)
        !           861:                        continue;
        !           862:
        !           863:                /*
        !           864:                 * if we got a matching prefix route, move IFA_ROUTE to him
        !           865:                 */
        !           866:                if ((ia->ia_flags & IFA_ROUTE) == 0) {
        !           867:                        rtinit(&(target->ia_ifa), (int)RTM_DELETE,
        !           868:                            rtinitflags(target));
        !           869:                        target->ia_flags &= ~IFA_ROUTE;
        !           870:
        !           871:                        error = rtinit(&ia->ia_ifa, (int)RTM_ADD,
        !           872:                            rtinitflags(ia) | RTF_UP);
        !           873:                        if (error == 0)
        !           874:                                ia->ia_flags |= IFA_ROUTE;
        !           875:                        return error;
        !           876:                }
        !           877:        }
        !           878:
        !           879:        /*
        !           880:         * noone seem to have prefix route.  remove it.
        !           881:         */
        !           882:        rtinit(&(target->ia_ifa), (int)RTM_DELETE, rtinitflags(target));
        !           883:        target->ia_flags &= ~IFA_ROUTE;
        !           884:        return 0;
        !           885: }
        !           886:
        !           887: #undef rtinitflags
        !           888:
        !           889: /*
        !           890:  * Return 1 if the address might be a local broadcast address.
        !           891:  */
        !           892: int
        !           893: in_broadcast(in, ifp)
        !           894:        struct in_addr in;
        !           895:        struct ifnet *ifp;
        !           896: {
        !           897:        struct ifnet *ifn, *if_first, *if_target;
        !           898:        struct ifaddr *ifa;
        !           899:
        !           900:        if (in.s_addr == INADDR_BROADCAST ||
        !           901:            in.s_addr == INADDR_ANY)
        !           902:                return 1;
        !           903:
        !           904:        if (ifp == NULL) {
        !           905:                if_first = TAILQ_FIRST(&ifnet);
        !           906:                if_target = 0;
        !           907:        } else {
        !           908:                if_first = ifp;
        !           909:                if_target = TAILQ_NEXT(ifp, if_list);
        !           910:        }
        !           911:
        !           912: #define ia (ifatoia(ifa))
        !           913:        /*
        !           914:         * Look through the list of addresses for a match
        !           915:         * with a broadcast address.
        !           916:         * If ifp is NULL, check against all the interfaces.
        !           917:         */
        !           918:         for (ifn = if_first; ifn != if_target; ifn = TAILQ_NEXT(ifn, if_list)) {
        !           919:                if ((ifn->if_flags & IFF_BROADCAST) == 0)
        !           920:                        continue;
        !           921:                TAILQ_FOREACH(ifa, &ifn->if_addrlist, ifa_list)
        !           922:                        if (ifa->ifa_addr->sa_family == AF_INET &&
        !           923:                            in.s_addr != ia->ia_addr.sin_addr.s_addr &&
        !           924:                            (in.s_addr == ia->ia_broadaddr.sin_addr.s_addr ||
        !           925:                             in.s_addr == ia->ia_netbroadcast.s_addr ||
        !           926:                             (hostzeroisbroadcast &&
        !           927:                              /*
        !           928:                               * Check for old-style (host 0) broadcast.
        !           929:                               */
        !           930:                              (in.s_addr == ia->ia_subnet ||
        !           931:                               in.s_addr == ia->ia_net))))
        !           932:                                return 1;
        !           933:        }
        !           934:        return (0);
        !           935: #undef ia
        !           936: }
        !           937:
        !           938: /*
        !           939:  * Add an address to the list of IP multicast addresses for a given interface.
        !           940:  */
        !           941: struct in_multi *
        !           942: in_addmulti(ap, ifp)
        !           943:        struct in_addr *ap;
        !           944:        struct ifnet *ifp;
        !           945: {
        !           946:        struct in_multi *inm;
        !           947:        struct ifreq ifr;
        !           948:        struct in_ifaddr *ia;
        !           949:        int s = splsoftnet();
        !           950:
        !           951:        /*
        !           952:         * See if address already in list.
        !           953:         */
        !           954:        IN_LOOKUP_MULTI(*ap, ifp, inm);
        !           955:        if (inm != NULL) {
        !           956:                /*
        !           957:                 * Found it; just increment the reference count.
        !           958:                 */
        !           959:                ++inm->inm_refcount;
        !           960:        } else {
        !           961:                /*
        !           962:                 * New address; allocate a new multicast record
        !           963:                 * and link it into the interface's multicast list.
        !           964:                 */
        !           965:                inm = (struct in_multi *)malloc(sizeof(*inm),
        !           966:                    M_IPMADDR, M_NOWAIT);
        !           967:                if (inm == NULL) {
        !           968:                        splx(s);
        !           969:                        return (NULL);
        !           970:                }
        !           971:                inm->inm_addr = *ap;
        !           972:                inm->inm_refcount = 1;
        !           973:                IFP_TO_IA(ifp, ia);
        !           974:                if (ia == NULL) {
        !           975:                        free(inm, M_IPMADDR);
        !           976:                        splx(s);
        !           977:                        return (NULL);
        !           978:                }
        !           979:                inm->inm_ia = ia;
        !           980:                ia->ia_ifa.ifa_refcnt++;
        !           981:                LIST_INSERT_HEAD(&ia->ia_multiaddrs, inm, inm_list);
        !           982:                /*
        !           983:                 * Ask the network driver to update its multicast reception
        !           984:                 * filter appropriately for the new address.
        !           985:                 */
        !           986:                satosin(&ifr.ifr_addr)->sin_len = sizeof(struct sockaddr_in);
        !           987:                satosin(&ifr.ifr_addr)->sin_family = AF_INET;
        !           988:                satosin(&ifr.ifr_addr)->sin_addr = *ap;
        !           989:                if ((ifp->if_ioctl == NULL) ||
        !           990:                    (*ifp->if_ioctl)(ifp, SIOCADDMULTI,(caddr_t)&ifr) != 0) {
        !           991:                        LIST_REMOVE(inm, inm_list);
        !           992:                        IFAFREE(&inm->inm_ia->ia_ifa);
        !           993:                        free(inm, M_IPMADDR);
        !           994:                        splx(s);
        !           995:                        return (NULL);
        !           996:                }
        !           997:                /*
        !           998:                 * Let IGMP know that we have joined a new IP multicast group.
        !           999:                 */
        !          1000:                igmp_joingroup(inm);
        !          1001:        }
        !          1002:        splx(s);
        !          1003:        return (inm);
        !          1004: }
        !          1005:
        !          1006: /*
        !          1007:  * Delete a multicast address record.
        !          1008:  */
        !          1009: void
        !          1010: in_delmulti(inm)
        !          1011:        struct in_multi *inm;
        !          1012: {
        !          1013:        struct ifreq ifr;
        !          1014:        struct ifnet *ifp;
        !          1015:        int s = splsoftnet();
        !          1016:
        !          1017:        if (--inm->inm_refcount == 0) {
        !          1018:                /*
        !          1019:                 * No remaining claims to this record; let IGMP know that
        !          1020:                 * we are leaving the multicast group.
        !          1021:                 */
        !          1022:                igmp_leavegroup(inm);
        !          1023:                /*
        !          1024:                 * Unlink from list.
        !          1025:                 */
        !          1026:                LIST_REMOVE(inm, inm_list);
        !          1027:                ifp = inm->inm_ia->ia_ifp;
        !          1028:                IFAFREE(&inm->inm_ia->ia_ifa);
        !          1029:
        !          1030:                if (ifp) {
        !          1031:                        /*
        !          1032:                         * Notify the network driver to update its multicast
        !          1033:                         * reception filter.
        !          1034:                         */
        !          1035:                        satosin(&ifr.ifr_addr)->sin_family = AF_INET;
        !          1036:                        satosin(&ifr.ifr_addr)->sin_addr = inm->inm_addr;
        !          1037:                        (*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)&ifr);
        !          1038:                }
        !          1039:                free(inm, M_IPMADDR);
        !          1040:        }
        !          1041:        splx(s);
        !          1042: }
        !          1043:
        !          1044: #endif

CVSweb