Annotation of kernel/bsd/netinet/in.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
        !             7:  * Reserved.  This file contains Original Code and/or Modifications of
        !             8:  * Original Code as defined in and that are subject to the Apple Public
        !             9:  * Source License Version 1.1 (the "License").  You may not use this file
        !            10:  * except in compliance with the License.  Please obtain a copy of the
        !            11:  * License at http://www.apple.com/publicsource and read it before using
        !            12:  * this file.
        !            13:  * 
        !            14:  * The Original Code and all software distributed under the License are
        !            15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            19:  * License for the specific language governing rights and limitations
        !            20:  * under the License.
        !            21:  * 
        !            22:  * @APPLE_LICENSE_HEADER_END@
        !            23:  */
        !            24: 
        !            25: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
        !            26: /*
        !            27:  * Copyright (c) 1982, 1986, 1991, 1993
        !            28:  *     The Regents of the University of California.  All rights reserved.
        !            29:  *
        !            30:  * Redistribution and use in source and binary forms, with or without
        !            31:  * modification, are permitted provided that the following conditions
        !            32:  * are met:
        !            33:  * 1. Redistributions of source code must retain the above copyright
        !            34:  *    notice, this list of conditions and the following disclaimer.
        !            35:  * 2. Redistributions in binary form must reproduce the above copyright
        !            36:  *    notice, this list of conditions and the following disclaimer in the
        !            37:  *    documentation and/or other materials provided with the distribution.
        !            38:  * 3. All advertising materials mentioning features or use of this software
        !            39:  *    must display the following acknowledgement:
        !            40:  *     This product includes software developed by the University of
        !            41:  *     California, Berkeley and its contributors.
        !            42:  * 4. Neither the name of the University nor the names of its contributors
        !            43:  *    may be used to endorse or promote products derived from this software
        !            44:  *    without specific prior written permission.
        !            45:  *
        !            46:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            47:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            48:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            49:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            50:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            51:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            52:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            53:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            54:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            55:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            56:  * SUCH DAMAGE.
        !            57:  *
        !            58:  *     @(#)in.c        8.4 (Berkeley) 1/9/95
        !            59:  */
        !            60: 
        !            61: #import        <sys/param.h>
        !            62: #import        <sys/systm.h>
        !            63: #import        <sys/ioctl.h>
        !            64: #import        <sys/errno.h>
        !            65: #import        <sys/malloc.h>
        !            66: #import        <sys/socket.h>
        !            67: #import        <sys/socketvar.h>
        !            68: 
        !            69: #import        <net/if.h>
        !            70: #import        <net/route.h>
        !            71: 
        !            72: #import        <netinet/in_systm.h>
        !            73: #import        <netinet/in.h>
        !            74: #import        <netinet/in_var.h>
        !            75: #import        <netinet/if_ether.h>
        !            76: #import <netinet/ip.h>
        !            77: #import         <netinet/ip_icmp.h>
        !            78: 
        !            79: #import        "ether.h"
        !            80: 
        !            81: #if NeXT
        !            82: /*
        !            83:  * Returns a printable string version of an internet address.
        !            84:  */
        !            85: char *
        !            86: inet_ntoa(
        !            87:          struct in_addr *inp
        !            88:          )
        !            89: {
        !            90:        register unsigned char *p;
        !            91:        register char *b;
        !            92:        static char buf[20];
        !            93:        int i;
        !            94:        struct in_addr ina;
        !            95:        
        !            96:        ina = *inp;
        !            97:        p = (unsigned char *)&ina;
        !            98:        b = buf;
        !            99:        for (i=0; i<4; i++) {
        !           100:                if (i) *b++ = '.';
        !           101:                if (*p > 99) {
        !           102:                        *b++ = '0' + (*p / 100);
        !           103:                        if ((*p % 100) / 10 == 0)
        !           104:                                *b++ = '0';
        !           105:                        *p %= 100;
        !           106:                }
        !           107:                if (*p > 9) {
        !           108:                        *b++ = '0' + (*p / 10);
        !           109:                        *p %= 10;
        !           110:                }
        !           111:                *b++ = '0' + *p;
        !           112:                p++;
        !           113:        }
        !           114:        *b++ = 0;
        !           115:        return(buf);
        !           116: }
        !           117: #endif NeXT
        !           118: 
        !           119: #if INET
        !           120: /*
        !           121:  * Return the network number from an internet address.
        !           122:  */
        !           123: u_long
        !           124: in_netof(in)
        !           125:        struct in_addr in;
        !           126: {
        !           127:        register u_long i = ntohl(in.s_addr);
        !           128:        register u_long net;
        !           129:        register struct in_ifaddr *ia;
        !           130: 
        !           131:        if (IN_CLASSA(i))
        !           132:                net = i & IN_CLASSA_NET;
        !           133:        else if (IN_CLASSB(i))
        !           134:                net = i & IN_CLASSB_NET;
        !           135:        else if (IN_CLASSC(i))
        !           136:                net = i & IN_CLASSC_NET;
        !           137:        else if (IN_CLASSD(i))
        !           138:                net = i & IN_CLASSD_NET;
        !           139:        else
        !           140:                return (0);
        !           141: 
        !           142:        /*
        !           143:         * Check whether network is a subnet;
        !           144:         * if so, return subnet number.
        !           145:         */
        !           146:        for (ia = in_ifaddr; ia; ia = ia->ia_next)
        !           147:                if (net == ia->ia_net)
        !           148:                        return (i & ia->ia_subnetmask);
        !           149:        return (net);
        !           150: }
        !           151: 
        !           152: #ifndef SUBNETSARELOCAL
        !           153: #define        SUBNETSARELOCAL 1
        !           154: #endif
        !           155: int subnetsarelocal = SUBNETSARELOCAL;
        !           156: /*
        !           157:  * Return 1 if an internet address is for a ``local'' host
        !           158:  * (one to which we have a connection).  If subnetsarelocal
        !           159:  * is true, this includes other subnets of the local net.
        !           160:  * Otherwise, it includes only the directly-connected (sub)nets.
        !           161:  */
        !           162: int
        !           163: in_localaddr(in)
        !           164:        struct in_addr in;
        !           165: {
        !           166:        register u_long i = ntohl(in.s_addr);
        !           167:        register struct in_ifaddr *ia;
        !           168: 
        !           169:        if (subnetsarelocal) {
        !           170:                for (ia = in_ifaddr; ia; ia = ia->ia_next)
        !           171:                        if ((i & ia->ia_netmask) == ia->ia_net)
        !           172:                                return (1);
        !           173:        } else {
        !           174:                for (ia = in_ifaddr; ia; ia = ia->ia_next)
        !           175:                        if ((i & ia->ia_subnetmask) == ia->ia_subnet)
        !           176:                                return (1);
        !           177:        }
        !           178:        return (0);
        !           179: }
        !           180: 
        !           181: /*
        !           182:  * Determine whether an IP address is in a reserved set of addresses
        !           183:  * that may not be forwarded, or whether datagrams to that destination
        !           184:  * may be forwarded.
        !           185:  */
        !           186: int
        !           187: in_canforward(in)
        !           188:        struct in_addr in;
        !           189: {
        !           190:        register u_long i = ntohl(in.s_addr);
        !           191:        register u_long net;
        !           192: 
        !           193:        if (IN_EXPERIMENTAL(i) || IN_MULTICAST(i))
        !           194:                return (0);
        !           195:        if (IN_CLASSA(i)) {
        !           196:                net = i & IN_CLASSA_NET;
        !           197:                if (net == 0 || net == (IN_LOOPBACKNET << IN_CLASSA_NSHIFT))
        !           198:                        return (0);
        !           199:        }
        !           200:        return (1);
        !           201: }
        !           202: 
        !           203: /*
        !           204:  * Trim a mask in a sockaddr
        !           205:  */
        !           206: void
        !           207: in_socktrim(ap)
        !           208: struct sockaddr_in *ap;
        !           209: {
        !           210:     register char *cplim = (char *) &ap->sin_addr;
        !           211:     register char *cp = (char *) (&ap->sin_addr + 1);
        !           212: 
        !           213:     ap->sin_len = 0;
        !           214:     while (--cp >= cplim)
        !           215:         if (*cp) {
        !           216:            (ap)->sin_len = cp - (char *) (ap) + 1;
        !           217:            break;
        !           218:        }
        !           219: }
        !           220: 
        !           221: int    in_interfaces;          /* number of external internet interfaces */
        !           222: extern struct ifnet loif;
        !           223: 
        !           224: /*
        !           225:  * Generic internet control operations (ioctl's).
        !           226:  * Ifp is 0 if not an interface-specific ioctl.
        !           227:  */
        !           228: /* ARGSUSED */
        !           229: int
        !           230: in_control(so, cmd, data, ifp)
        !           231:        struct socket *so;
        !           232:        u_long cmd;
        !           233:        caddr_t data;
        !           234:        register struct ifnet *ifp;
        !           235: {
        !           236:        register struct ifreq *ifr = (struct ifreq *)data;
        !           237:        register struct in_ifaddr *ia = 0;
        !           238:        register struct ifaddr *ifa;
        !           239:        struct in_ifaddr *oia;
        !           240:        struct in_aliasreq *ifra = (struct in_aliasreq *)data;
        !           241:        struct sockaddr_in oldaddr;
        !           242:        int error, hostIsNew, maskIsNew;
        !           243:        u_long i;
        !           244: 
        !           245:        /*
        !           246:         * Find address for this interface, if it exists.
        !           247:         */
        !           248:        if (ifp)
        !           249:                for (ia = in_ifaddr; ia; ia = ia->ia_next)
        !           250:                        if (ia->ia_ifp == ifp)
        !           251:                                break;
        !           252: 
        !           253:        switch (cmd) {
        !           254: 
        !           255:        case SIOCAIFADDR:
        !           256:        case SIOCDIFADDR:
        !           257:                if (ifra->ifra_addr.sin_family == AF_INET)
        !           258:                    for (oia = ia; ia; ia = ia->ia_next) {
        !           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    NeXT
        !           271:        case SIOCAUTONETMASK:
        !           272: #endif NeXT
        !           273:                if ((so->so_state & SS_PRIV) == 0)
        !           274:                        return (EPERM);
        !           275: 
        !           276:                if (ifp == 0)
        !           277:                        panic("in_control");
        !           278:                if (ia == (struct in_ifaddr *)0) {
        !           279:                        oia = (struct in_ifaddr *)
        !           280:                                _MALLOC(sizeof *oia, M_IFADDR, M_WAITOK);
        !           281:                        if (oia == (struct in_ifaddr *)NULL)
        !           282:                                return (ENOBUFS);
        !           283:                        bzero((caddr_t)oia, sizeof *oia);
        !           284:                        if (ia = in_ifaddr) {
        !           285:                                for ( ; ia->ia_next; ia = ia->ia_next)
        !           286:                                        continue;
        !           287:                                ia->ia_next = oia;
        !           288:                        } else
        !           289:                                in_ifaddr = oia;
        !           290:                        ia = oia;
        !           291:                        if (ifa = ifp->if_addrlist) {
        !           292:                                for ( ; ifa->ifa_next; ifa = ifa->ifa_next)
        !           293:                                        continue;
        !           294:                                ifa->ifa_next = (struct ifaddr *) ia;
        !           295:                        } else
        !           296:                                ifp->if_addrlist = (struct ifaddr *) ia;
        !           297:                        ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
        !           298:                        ia->ia_ifa.ifa_dstaddr
        !           299:                                        = (struct sockaddr *)&ia->ia_dstaddr;
        !           300:                        ia->ia_ifa.ifa_netmask
        !           301:                                        = (struct sockaddr *)&ia->ia_sockmask;
        !           302:                        ia->ia_sockmask.sin_len = 8;
        !           303:                        if (ifp->if_flags & IFF_BROADCAST) {
        !           304:                                ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr);
        !           305:                                ia->ia_broadaddr.sin_family = AF_INET;
        !           306:                        }
        !           307:                        ia->ia_ifp = ifp;
        !           308:                        if (ifp != &loif)
        !           309:                                in_interfaces++;
        !           310:                }
        !           311:                break;
        !           312: 
        !           313:        case SIOCSIFBRDADDR:
        !           314:                if ((so->so_state & SS_PRIV) == 0)
        !           315:                        return (EPERM);
        !           316:                /* FALLTHROUGH */
        !           317: 
        !           318:        case SIOCGIFADDR:
        !           319:        case SIOCGIFNETMASK:
        !           320:        case SIOCGIFDSTADDR:
        !           321:        case SIOCGIFBRDADDR:
        !           322:                if (ia == (struct in_ifaddr *)0)
        !           323:                        return (EADDRNOTAVAIL);
        !           324:                break;
        !           325: #if    NeXT
        !           326:        case SIOCAUTOADDR:
        !           327:                break;
        !           328: #endif NeXT
        !           329:        }
        !           330:        switch (cmd) {
        !           331: 
        !           332:        case SIOCGIFADDR:
        !           333:                *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_addr;
        !           334:                break;
        !           335: 
        !           336:        case SIOCGIFBRDADDR:
        !           337:                if ((ifp->if_flags & IFF_BROADCAST) == 0)
        !           338:                        return (EINVAL);
        !           339:                *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_broadaddr;
        !           340:                break;
        !           341: 
        !           342:        case SIOCGIFDSTADDR:
        !           343:                if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
        !           344:                        return (EINVAL);
        !           345:                *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_dstaddr;
        !           346:                break;
        !           347: 
        !           348:        case SIOCGIFNETMASK:
        !           349:                *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_sockmask;
        !           350:                break;
        !           351: 
        !           352:        case SIOCSIFDSTADDR:
        !           353:                if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
        !           354:                        return (EINVAL);
        !           355:                oldaddr = ia->ia_dstaddr;
        !           356:                ia->ia_dstaddr = *(struct sockaddr_in *)&ifr->ifr_dstaddr;
        !           357:                if (ifp->if_ioctl && (error = (*ifp->if_ioctl)
        !           358:                                        (ifp, SIOCSIFDSTADDR, (caddr_t)ia))) {
        !           359:                        ia->ia_dstaddr = oldaddr;
        !           360:                        return (error);
        !           361:                }
        !           362:                if (ia->ia_flags & IFA_ROUTE) {
        !           363:                        ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&oldaddr;
        !           364:                        rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
        !           365:                        ia->ia_ifa.ifa_dstaddr =
        !           366:                                        (struct sockaddr *)&ia->ia_dstaddr;
        !           367:                        rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
        !           368:                }
        !           369:                break;
        !           370: 
        !           371:        case SIOCSIFBRDADDR:
        !           372:                if ((ifp->if_flags & IFF_BROADCAST) == 0)
        !           373:                        return (EINVAL);
        !           374:                ia->ia_broadaddr = *(struct sockaddr_in *)&ifr->ifr_broadaddr;
        !           375:                break;
        !           376: 
        !           377:        case SIOCSIFADDR:
        !           378:                ifp->if_eflags &= ~(IFEF_AUTOCONF_DONE);
        !           379:                return (in_ifinit(ifp, ia,
        !           380:                    (struct sockaddr_in *) &ifr->ifr_addr, 1));
        !           381: 
        !           382:        case SIOCSIFNETMASK:
        !           383:                i = ifra->ifra_addr.sin_addr.s_addr;
        !           384:                ia->ia_subnetmask = ntohl(ia->ia_sockmask.sin_addr.s_addr = i);
        !           385:                break;
        !           386: 
        !           387:        case SIOCAIFADDR:
        !           388:                ifp->if_eflags &= ~(IFEF_AUTOCONF_DONE);
        !           389:                maskIsNew = 0;
        !           390:                hostIsNew = 1;
        !           391:                error = 0;
        !           392:                if (ia->ia_addr.sin_family == AF_INET) {
        !           393:                        if (ifra->ifra_addr.sin_len == 0) {
        !           394:                                ifra->ifra_addr = ia->ia_addr;
        !           395:                                hostIsNew = 0;
        !           396:                        } else if (ifra->ifra_addr.sin_addr.s_addr ==
        !           397:                                               ia->ia_addr.sin_addr.s_addr)
        !           398:                                hostIsNew = 0;
        !           399:                }
        !           400:                if (ifra->ifra_mask.sin_len) {
        !           401:                        in_ifscrub(ifp, ia);
        !           402:                        ia->ia_sockmask = ifra->ifra_mask;
        !           403:                        ia->ia_subnetmask =
        !           404:                             ntohl(ia->ia_sockmask.sin_addr.s_addr);
        !           405:                        maskIsNew = 1;
        !           406:                }
        !           407:                if ((ifp->if_flags & IFF_POINTOPOINT) &&
        !           408:                    (ifra->ifra_dstaddr.sin_family == AF_INET)) {
        !           409:                        in_ifscrub(ifp, ia);
        !           410:                        ia->ia_dstaddr = ifra->ifra_dstaddr;
        !           411:                        maskIsNew  = 1; /* We lie; but the effect's the same */
        !           412:                }
        !           413:                if (ifra->ifra_addr.sin_family == AF_INET &&
        !           414:                    (hostIsNew || maskIsNew))
        !           415:                        error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0);
        !           416:                if ((ifp->if_flags & IFF_BROADCAST) &&
        !           417:                    (ifra->ifra_broadaddr.sin_family == AF_INET))
        !           418:                        ia->ia_broadaddr = ifra->ifra_broadaddr;
        !           419:                return (error);
        !           420: 
        !           421:        case SIOCDIFADDR:
        !           422:                in_ifscrub(ifp, ia);
        !           423:                if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia)
        !           424:                        ifp->if_addrlist = ifa->ifa_next;
        !           425:                else {
        !           426:                        while (ifa->ifa_next &&
        !           427:                               (ifa->ifa_next != (struct ifaddr *)ia))
        !           428:                                    ifa = ifa->ifa_next;
        !           429:                        if (ifa->ifa_next)
        !           430:                                ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next;
        !           431:                        else
        !           432:                                printf("Couldn't unlink inifaddr from ifp\n");
        !           433:                }
        !           434:                oia = ia;
        !           435:                if (oia == (ia = in_ifaddr))
        !           436:                        in_ifaddr = ia->ia_next;
        !           437:                else {
        !           438:                        while (ia->ia_next && (ia->ia_next != oia))
        !           439:                                ia = ia->ia_next;
        !           440:                        if (ia->ia_next)
        !           441:                                ia->ia_next = oia->ia_next;
        !           442:                        else
        !           443:                                printf("Didn't unlink inifadr from list\n");
        !           444:                }
        !           445:                IFAFREE((&oia->ia_ifa));
        !           446:                break;
        !           447: #if    NeXT
        !           448:        case SIOCAUTONETMASK:
        !           449:        {
        !           450:                int retry;
        !           451: 
        !           452:                ifp->if_eflags &= ~(IFEF_NETMASK_AUTH);
        !           453:                if ((ifp->if_flags & IFF_UP) == 0) {
        !           454:                        return (ENETDOWN);
        !           455:                }
        !           456:                ifp->if_eflags |= IFEF_AWAITING_NETMASK;
        !           457:                for (retry = 0; retry < ICMP_NETMASK_RETRY_MAX; retry++) {
        !           458:                        /* Exponential retransmit backoff */
        !           459:                        /* 0, 1, 2, 4, 8, 16, 32, 32, 32... seconds */
        !           460:                        error = icmp_sendMaskPacket(ifp, ICMP_MASKREQ,
        !           461:                                                    ((retry > 5) ? 32 : (( 1 << retry) >> 1)));
        !           462:                        if (error != 0)
        !           463:                            return (error);
        !           464:                        if ((ifp->if_eflags & IFEF_AWAITING_NETMASK) == 0)
        !           465:                            return (0);
        !           466:                }
        !           467:                return (ENETDOWN);
        !           468:        }
        !           469: #endif NeXT
        !           470: 
        !           471:        default:
        !           472:                if (ifp == 0 || ifp->if_ioctl == 0)
        !           473:                        return (EOPNOTSUPP);
        !           474:                return ((*ifp->if_ioctl)(ifp, cmd, data));
        !           475:        }
        !           476:        return (0);
        !           477: }
        !           478: 
        !           479: /*
        !           480:  * Delete any existing route for an interface.
        !           481:  */
        !           482: void
        !           483: in_ifscrub(ifp, ia)
        !           484:        register struct ifnet *ifp;
        !           485:        register struct in_ifaddr *ia;
        !           486: {
        !           487: 
        !           488:        if ((ia->ia_flags & IFA_ROUTE) == 0)
        !           489:                return;
        !           490:        if (ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT))
        !           491:                rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
        !           492:        else
        !           493:                rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0);
        !           494:        ia->ia_flags &= ~IFA_ROUTE;
        !           495: }
        !           496: 
        !           497: /*
        !           498:  * Initialize an interface's internet address
        !           499:  * and routing table entry.
        !           500:  */
        !           501: int
        !           502: in_ifinit(ifp, ia, sin, scrub)
        !           503:        register struct ifnet *ifp;
        !           504:        register struct in_ifaddr *ia;
        !           505:        struct sockaddr_in *sin;
        !           506:        int scrub;
        !           507: {
        !           508:        register u_long i = ntohl(sin->sin_addr.s_addr);
        !           509:        struct sockaddr_in oldaddr;
        !           510:        int s = splimp(), flags = RTF_UP, error, ether_output();
        !           511: 
        !           512:        oldaddr = ia->ia_addr;
        !           513:        ia->ia_addr = *sin;
        !           514:        /*
        !           515:         * Give the interface a chance to initialize
        !           516:         * if this is its first address,
        !           517:         * and to validate the address if necessary.
        !           518:         */
        !           519:        if (ifp->if_ioctl &&
        !           520:            (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) {
        !           521:                splx(s);
        !           522:                ia->ia_addr = oldaddr;
        !           523:                return (error);
        !           524:        }
        !           525: #if NETHER > 0
        !           526:        if (ifp->if_output == ether_output) { /* XXX: Another Kludge */
        !           527:                ia->ia_ifa.ifa_rtrequest = arp_rtrequest;
        !           528:                ia->ia_ifa.ifa_flags |= RTF_CLONING;
        !           529:        }
        !           530: #endif
        !           531:        splx(s);
        !           532:        if (scrub) {
        !           533:                ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
        !           534:                in_ifscrub(ifp, ia);
        !           535:                ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
        !           536:        }
        !           537: 
        !           538:        /* DWS: Nov. 4th, 1997
        !           539:         * Mark the interface as "auto-configuring" if the all-zeroes IP address
        !           540:         * is assigned.  An interface in this state allows BOOTP packets to pass
        !           541:         * up that would normally get rejected (see ip_input.c) because the interface
        !           542:         * hasn't been assigned a valid IP address yet.
        !           543:         */
        !           544:        if (i == 0) {
        !           545:            ifp->if_eflags |= IFEF_AUTOCONF;
        !           546:        }
        !           547:        else {
        !           548:            ifp->if_eflags &= ~(IFEF_AUTOCONF);
        !           549:        }
        !           550:            
        !           551:        if (IN_CLASSA(i))
        !           552:                ia->ia_netmask = IN_CLASSA_NET;
        !           553:        else if (IN_CLASSB(i))
        !           554:                ia->ia_netmask = IN_CLASSB_NET;
        !           555:        else
        !           556:                ia->ia_netmask = IN_CLASSC_NET;
        !           557:        /*
        !           558:         * The subnet mask usually includes at least the standard network part,
        !           559:         * but may may be smaller in the case of supernetting.
        !           560:         * If it is set, we believe it.
        !           561:         */
        !           562:        if (ia->ia_subnetmask == 0) {
        !           563:                ia->ia_subnetmask = ia->ia_netmask;
        !           564:                ia->ia_sockmask.sin_addr.s_addr = htonl(ia->ia_subnetmask);
        !           565:        } 
        !           566:        else {
        !           567:                ia->ia_netmask &= ia->ia_subnetmask;
        !           568:        }
        !           569:        ia->ia_net = i & ia->ia_netmask;
        !           570:        ia->ia_subnet = i & ia->ia_subnetmask;
        !           571:        in_socktrim(&ia->ia_sockmask);
        !           572:        /*
        !           573:         * Add route for the network.
        !           574:         */
        !           575:        ia->ia_ifa.ifa_metric = ifp->if_metric;
        !           576:        if (ifp->if_flags & IFF_BROADCAST) {
        !           577:                ia->ia_broadaddr.sin_addr.s_addr =
        !           578:                        htonl(ia->ia_subnet | ~ia->ia_subnetmask);
        !           579:                ia->ia_netbroadcast.s_addr =
        !           580:                        htonl(ia->ia_net | ~ ia->ia_netmask);
        !           581:        } else if (ifp->if_flags & IFF_LOOPBACK) {
        !           582:                ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr;
        !           583:                flags |= RTF_HOST;
        !           584:        } else if (ifp->if_flags & IFF_POINTOPOINT) {
        !           585:                if (ia->ia_dstaddr.sin_family != AF_INET)
        !           586:                        return (0);
        !           587:                flags |= RTF_HOST;
        !           588:        }
        !           589:        if ((error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, flags)) == 0)
        !           590:                ia->ia_flags |= IFA_ROUTE;
        !           591:        /*
        !           592:         * If the interface supports multicast, join the "all hosts"
        !           593:         * multicast group on that interface.
        !           594:         */
        !           595:        if (ifp->if_flags & IFF_MULTICAST) {
        !           596:                struct in_addr addr;
        !           597: 
        !           598:                addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP);
        !           599:                in_addmulti(&addr, ifp);
        !           600:        }
        !           601:        return (error);
        !           602: }
        !           603: 
        !           604: 
        !           605: /*
        !           606:  * Return 1 if the address might be a local broadcast address.
        !           607:  */
        !           608: int
        !           609: in_broadcast(in, ifp)
        !           610:        struct in_addr in;
        !           611:        struct ifnet *ifp;
        !           612: {
        !           613:        register struct ifaddr *ifa;
        !           614:        u_long t;
        !           615: 
        !           616:        if (in.s_addr == INADDR_BROADCAST ||
        !           617:            in.s_addr == INADDR_ANY)
        !           618:                return 1;
        !           619:        if ((ifp->if_flags & IFF_BROADCAST) == 0)
        !           620:                return 0;
        !           621:        t = ntohl(in.s_addr);
        !           622:        /*
        !           623:         * Look through the list of addresses for a match
        !           624:         * with a broadcast address.
        !           625:         */
        !           626: #define ia ((struct in_ifaddr *)ifa)
        !           627:        for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
        !           628:                if (ifa->ifa_addr->sa_family == AF_INET &&
        !           629:                    (in.s_addr == ia->ia_broadaddr.sin_addr.s_addr ||
        !           630:                     in.s_addr == ia->ia_netbroadcast.s_addr ||
        !           631:                     /*
        !           632:                      * Check for old-style (host 0) broadcast.
        !           633:                      */
        !           634:                     t == ia->ia_subnet || t == ia->ia_net))
        !           635:                            return 1;
        !           636:        return (0);
        !           637: #undef ia
        !           638: }
        !           639: 
        !           640: /*
        !           641:  * Add an address to the list of IP multicast addresses for a given interface.
        !           642:  */
        !           643: struct in_multi *
        !           644: in_addmulti(ap, ifp)
        !           645:        register struct in_addr *ap;
        !           646:        register struct ifnet *ifp;
        !           647: {
        !           648:        register struct in_multi *inm;
        !           649:        struct ifreq ifr;
        !           650:        struct in_ifaddr *ia;
        !           651:        int s = splnet();
        !           652: 
        !           653:        /*
        !           654:         * See if address already in list.
        !           655:         */
        !           656:        IN_LOOKUP_MULTI(*ap, ifp, inm);
        !           657:        if (inm != NULL) {
        !           658:                /*
        !           659:                 * Found it; just increment the reference count.
        !           660:                 */
        !           661:                ++inm->inm_refcount;
        !           662:        }
        !           663:        else {
        !           664:                /*
        !           665:                 * New address; allocate a new multicast record
        !           666:                 * and link it into the interface's multicast list.
        !           667:                 */
        !           668:                MALLOC(inm, struct in_multi *, sizeof(*inm), M_IPMADDR, M_NOWAIT); 
        !           669:                if (inm == NULL) {
        !           670:                        splx(s);
        !           671:                        return (NULL);
        !           672:                }
        !           673:                inm->inm_addr = *ap;
        !           674:                inm->inm_ifp = ifp;
        !           675:                inm->inm_refcount = 1;
        !           676:                IFP_TO_IA(ifp, ia);
        !           677:                if (ia == NULL) {
        !           678:                        _FREE(inm, M_IPMADDR);
        !           679:                        splx(s);
        !           680:                        return (NULL);
        !           681:                }
        !           682:                inm->inm_ia = ia;
        !           683:                inm->inm_next = ia->ia_multiaddrs;
        !           684:                ia->ia_multiaddrs = inm;
        !           685:                /*
        !           686:                 * Ask the network driver to update its multicast reception
        !           687:                 * filter appropriately for the new address.
        !           688:                 */
        !           689:                ((struct sockaddr_in *)&ifr.ifr_addr)->sin_family = AF_INET;
        !           690:                ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr = *ap;
        !           691:                if ((ifp->if_ioctl == NULL) ||
        !           692:                    (*ifp->if_ioctl)(ifp, SIOCADDMULTI,(caddr_t)&ifr) != 0) {
        !           693:                        ia->ia_multiaddrs = inm->inm_next;
        !           694:                        _FREE(inm, M_IPMADDR);
        !           695:                        splx(s);
        !           696:                        return (NULL);
        !           697:                }
        !           698:                /*
        !           699:                 * Let IGMP know that we have joined a new IP multicast group.
        !           700:                 */
        !           701:                igmp_joingroup(inm);
        !           702:        }
        !           703:        splx(s);
        !           704:        return (inm);
        !           705: }
        !           706: 
        !           707: /*
        !           708:  * Delete a multicast address record.
        !           709:  */
        !           710: int
        !           711: in_delmulti(inm)
        !           712:        register struct in_multi *inm;
        !           713: {
        !           714:        register struct in_multi **p;
        !           715:        struct ifreq ifr;
        !           716:        int s = splnet();
        !           717: 
        !           718:        if (--inm->inm_refcount == 0) {
        !           719:                /*
        !           720:                 * No remaining claims to this record; let IGMP know that
        !           721:                 * we are leaving the multicast group.
        !           722:                 */
        !           723:                igmp_leavegroup(inm);
        !           724:                /*
        !           725:                 * Unlink from list.
        !           726:                 */
        !           727:                for (p = &inm->inm_ia->ia_multiaddrs;
        !           728:                     *p != inm;
        !           729:                     p = &(*p)->inm_next)
        !           730:                         continue;
        !           731:                *p = (*p)->inm_next;
        !           732:                /*
        !           733:                 * Notify the network driver to update its multicast reception
        !           734:                 * filter.
        !           735:                 */
        !           736:                ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_family = AF_INET;
        !           737:                ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_addr =
        !           738:                                                                inm->inm_addr;
        !           739:                (*inm->inm_ifp->if_ioctl)(inm->inm_ifp, SIOCDELMULTI,
        !           740:                                                             (caddr_t)&ifr);
        !           741:                _FREE(inm, M_IPMADDR);
        !           742:        }
        !           743:        splx(s);
        !           744: }
        !           745: #endif

unix.superglobalmegacorp.com

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