Annotation of 43BSD/sys/netinet/in.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1982, 1986 Regents of the University of California.
        !             3:  * All rights reserved.  The Berkeley software License Agreement
        !             4:  * specifies the terms and conditions for redistribution.
        !             5:  *
        !             6:  *     @(#)in.c        7.2 (Berkeley) 11/23/86
        !             7:  */
        !             8: 
        !             9: #include "param.h"
        !            10: #include "ioctl.h"
        !            11: #include "mbuf.h"
        !            12: #include "protosw.h"
        !            13: #include "socket.h"
        !            14: #include "socketvar.h"
        !            15: #include "uio.h"
        !            16: #include "dir.h"
        !            17: #include "user.h"
        !            18: #include "in_systm.h"
        !            19: #include "../net/if.h"
        !            20: #include "../net/route.h"
        !            21: #include "../net/af.h"
        !            22: #include "in.h"
        !            23: #include "in_var.h"
        !            24: 
        !            25: #ifdef INET
        !            26: inet_hash(sin, hp)
        !            27:        register struct sockaddr_in *sin;
        !            28:        struct afhash *hp;
        !            29: {
        !            30:        register u_long n;
        !            31: 
        !            32:        n = in_netof(sin->sin_addr);
        !            33:        if (n)
        !            34:            while ((n & 0xff) == 0)
        !            35:                n >>= 8;
        !            36:        hp->afh_nethash = n;
        !            37:        hp->afh_hosthash = ntohl(sin->sin_addr.s_addr);
        !            38: }
        !            39: 
        !            40: inet_netmatch(sin1, sin2)
        !            41:        struct sockaddr_in *sin1, *sin2;
        !            42: {
        !            43: 
        !            44:        return (in_netof(sin1->sin_addr) == in_netof(sin2->sin_addr));
        !            45: }
        !            46: 
        !            47: /*
        !            48:  * Formulate an Internet address from network + host.
        !            49:  */
        !            50: struct in_addr
        !            51: in_makeaddr(net, host)
        !            52:        u_long net, host;
        !            53: {
        !            54:        register struct in_ifaddr *ia;
        !            55:        register u_long mask;
        !            56:        u_long addr;
        !            57: 
        !            58:        if (IN_CLASSA(net))
        !            59:                mask = IN_CLASSA_HOST;
        !            60:        else if (IN_CLASSB(net))
        !            61:                mask = IN_CLASSB_HOST;
        !            62:        else
        !            63:                mask = IN_CLASSC_HOST;
        !            64:        for (ia = in_ifaddr; ia; ia = ia->ia_next)
        !            65:                if ((ia->ia_netmask & net) == ia->ia_net) {
        !            66:                        mask = ~ia->ia_subnetmask;
        !            67:                        break;
        !            68:                }
        !            69:        addr = htonl(net | (host & mask));
        !            70:        return (*(struct in_addr *)&addr);
        !            71: }
        !            72: 
        !            73: /*
        !            74:  * Return the network number from an internet address.
        !            75:  */
        !            76: u_long
        !            77: in_netof(in)
        !            78:        struct in_addr in;
        !            79: {
        !            80:        register u_long i = ntohl(in.s_addr);
        !            81:        register u_long net;
        !            82:        register struct in_ifaddr *ia;
        !            83: 
        !            84:        if (IN_CLASSA(i))
        !            85:                net = i & IN_CLASSA_NET;
        !            86:        else if (IN_CLASSB(i))
        !            87:                net = i & IN_CLASSB_NET;
        !            88:        else
        !            89:                net = i & IN_CLASSC_NET;
        !            90: 
        !            91:        /*
        !            92:         * Check whether network is a subnet;
        !            93:         * if so, return subnet number.
        !            94:         */
        !            95:        for (ia = in_ifaddr; ia; ia = ia->ia_next)
        !            96:                if (net == ia->ia_net)
        !            97:                        return (i & ia->ia_subnetmask);
        !            98:        return (net);
        !            99: }
        !           100: 
        !           101: /*
        !           102:  * Return the host portion of an internet address.
        !           103:  */
        !           104: u_long
        !           105: in_lnaof(in)
        !           106:        struct in_addr in;
        !           107: {
        !           108:        register u_long i = ntohl(in.s_addr);
        !           109:        register u_long net, host;
        !           110:        register struct in_ifaddr *ia;
        !           111: 
        !           112:        if (IN_CLASSA(i)) {
        !           113:                net = i & IN_CLASSA_NET;
        !           114:                host = i & IN_CLASSA_HOST;
        !           115:        } else if (IN_CLASSB(i)) {
        !           116:                net = i & IN_CLASSB_NET;
        !           117:                host = i & IN_CLASSB_HOST;
        !           118:        } else {
        !           119:                net = i & IN_CLASSC_NET;
        !           120:                host = i & IN_CLASSC_HOST;
        !           121:        }
        !           122: 
        !           123:        /*
        !           124:         * Check whether network is a subnet;
        !           125:         * if so, use the modified interpretation of `host'.
        !           126:         */
        !           127:        for (ia = in_ifaddr; ia; ia = ia->ia_next)
        !           128:                if (net == ia->ia_net)
        !           129:                        return (host &~ ia->ia_subnetmask);
        !           130:        return (host);
        !           131: }
        !           132: 
        !           133: #ifndef SUBNETSARELOCAL
        !           134: #define        SUBNETSARELOCAL 1
        !           135: #endif
        !           136: int subnetsarelocal = SUBNETSARELOCAL;
        !           137: /*
        !           138:  * Return 1 if an internet address is for a ``local'' host
        !           139:  * (one to which we have a connection).  If subnetsarelocal
        !           140:  * is true, this includes other subnets of the local net.
        !           141:  * Otherwise, it includes only the directly-connected (sub)nets.
        !           142:  */
        !           143: in_localaddr(in)
        !           144:        struct in_addr in;
        !           145: {
        !           146:        register u_long i = ntohl(in.s_addr);
        !           147:        register u_long net;
        !           148:        register struct in_ifaddr *ia;
        !           149: 
        !           150:        if (IN_CLASSA(i))
        !           151:                net = i & IN_CLASSA_NET;
        !           152:        else if (IN_CLASSB(i))
        !           153:                net = i & IN_CLASSB_NET;
        !           154:        else
        !           155:                net = i & IN_CLASSC_NET;
        !           156: 
        !           157:        for (ia = in_ifaddr; ia; ia = ia->ia_next)
        !           158:                if (net == (subnetsarelocal ? ia->ia_net : ia->ia_subnet))
        !           159:                        return (1);
        !           160:        return (0);
        !           161: }
        !           162: 
        !           163: int    in_interfaces;          /* number of external internet interfaces */
        !           164: extern struct ifnet loif;
        !           165: 
        !           166: /*
        !           167:  * Generic internet control operations (ioctl's).
        !           168:  * Ifp is 0 if not an interface-specific ioctl.
        !           169:  */
        !           170: /* ARGSUSED */
        !           171: in_control(so, cmd, data, ifp)
        !           172:        struct socket *so;
        !           173:        int cmd;
        !           174:        caddr_t data;
        !           175:        register struct ifnet *ifp;
        !           176: {
        !           177:        register struct ifreq *ifr = (struct ifreq *)data;
        !           178:        register struct in_ifaddr *ia = 0;
        !           179:        u_long tmp;
        !           180:        struct ifaddr *ifa;
        !           181:        struct mbuf *m;
        !           182:        int error;
        !           183: 
        !           184:        /*
        !           185:         * Find address for this interface, if it exists.
        !           186:         */
        !           187:        if (ifp)
        !           188:                for (ia = in_ifaddr; ia; ia = ia->ia_next)
        !           189:                        if (ia->ia_ifp == ifp)
        !           190:                                break;
        !           191: 
        !           192:        switch (cmd) {
        !           193: 
        !           194:        case SIOCSIFADDR:
        !           195:        case SIOCSIFNETMASK:
        !           196:        case SIOCSIFDSTADDR:
        !           197:                if (!suser())
        !           198:                        return (u.u_error);
        !           199: 
        !           200:                if (ifp == 0)
        !           201:                        panic("in_control");
        !           202:                if (ia == (struct in_ifaddr *)0) {
        !           203:                        m = m_getclr(M_WAIT, MT_IFADDR);
        !           204:                        if (m == (struct mbuf *)NULL)
        !           205:                                return (ENOBUFS);
        !           206:                        if (ia = in_ifaddr) {
        !           207:                                for ( ; ia->ia_next; ia = ia->ia_next)
        !           208:                                        ;
        !           209:                                ia->ia_next = mtod(m, struct in_ifaddr *);
        !           210:                        } else
        !           211:                                in_ifaddr = mtod(m, struct in_ifaddr *);
        !           212:                        ia = mtod(m, struct in_ifaddr *);
        !           213:                        if (ifa = ifp->if_addrlist) {
        !           214:                                for ( ; ifa->ifa_next; ifa = ifa->ifa_next)
        !           215:                                        ;
        !           216:                                ifa->ifa_next = (struct ifaddr *) ia;
        !           217:                        } else
        !           218:                                ifp->if_addrlist = (struct ifaddr *) ia;
        !           219:                        ia->ia_ifp = ifp;
        !           220:                        IA_SIN(ia)->sin_family = AF_INET;
        !           221:                        if (ifp != &loif)
        !           222:                                in_interfaces++;
        !           223:                }
        !           224:                break;
        !           225: 
        !           226:        case SIOCSIFBRDADDR:
        !           227:                if (!suser())
        !           228:                        return (u.u_error);
        !           229:                /* FALLTHROUGH */
        !           230: 
        !           231:        default:
        !           232:                if (ia == (struct in_ifaddr *)0)
        !           233:                        return (EADDRNOTAVAIL);
        !           234:                break;
        !           235:        }
        !           236: 
        !           237:        switch (cmd) {
        !           238: 
        !           239:        case SIOCGIFADDR:
        !           240:                ifr->ifr_addr = ia->ia_addr;
        !           241:                break;
        !           242: 
        !           243:        case SIOCGIFBRDADDR:
        !           244:                if ((ifp->if_flags & IFF_BROADCAST) == 0)
        !           245:                        return (EINVAL);
        !           246:                ifr->ifr_dstaddr = ia->ia_broadaddr;
        !           247:                break;
        !           248: 
        !           249:        case SIOCGIFDSTADDR:
        !           250:                if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
        !           251:                        return (EINVAL);
        !           252:                ifr->ifr_dstaddr = ia->ia_dstaddr;
        !           253:                break;
        !           254: 
        !           255:        case SIOCGIFNETMASK:
        !           256: #define        satosin(sa)     ((struct sockaddr_in *)(sa))
        !           257:                satosin(&ifr->ifr_addr)->sin_family = AF_INET;
        !           258:                satosin(&ifr->ifr_addr)->sin_addr.s_addr = htonl(ia->ia_subnetmask);
        !           259:                break;
        !           260: 
        !           261:        case SIOCSIFDSTADDR:
        !           262:            {
        !           263:                struct sockaddr oldaddr;
        !           264: 
        !           265:                if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
        !           266:                        return (EINVAL);
        !           267:                oldaddr = ia->ia_dstaddr;
        !           268:                ia->ia_dstaddr = ifr->ifr_dstaddr;
        !           269:                if (ifp->if_ioctl &&
        !           270:                    (error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, ia))) {
        !           271:                        ia->ia_dstaddr = oldaddr;
        !           272:                        return (error);
        !           273:                }
        !           274:                if (ia->ia_flags & IFA_ROUTE) {
        !           275:                        rtinit(&oldaddr, &ia->ia_addr, (int)SIOCDELRT,
        !           276:                            RTF_HOST);
        !           277:                        rtinit(&ia->ia_dstaddr, &ia->ia_addr, (int)SIOCADDRT,
        !           278:                            RTF_HOST|RTF_UP);
        !           279:                }
        !           280:            }
        !           281:                break;
        !           282: 
        !           283:        case SIOCSIFBRDADDR:
        !           284:                if ((ifp->if_flags & IFF_BROADCAST) == 0)
        !           285:                        return (EINVAL);
        !           286:                ia->ia_broadaddr = ifr->ifr_broadaddr;
        !           287:                tmp = ntohl(satosin(&ia->ia_broadaddr)->sin_addr.s_addr);
        !           288:                if ((tmp &~ ia->ia_subnetmask) == ~ia->ia_subnetmask)
        !           289:                        tmp |= ~ia->ia_netmask;
        !           290:                else if ((tmp &~ ia->ia_subnetmask) == 0)
        !           291:                        tmp &= ia->ia_netmask;
        !           292:                ia->ia_netbroadcast.s_addr = htonl(tmp);
        !           293:                break;
        !           294: 
        !           295:        case SIOCSIFADDR:
        !           296:                return (in_ifinit(ifp, ia, &ifr->ifr_addr));
        !           297: 
        !           298:        case SIOCSIFNETMASK:
        !           299:                ia->ia_subnetmask = ntohl(satosin(&ifr->ifr_addr)->sin_addr.s_addr);
        !           300:                break;
        !           301: 
        !           302:        default:
        !           303:                if (ifp == 0 || ifp->if_ioctl == 0)
        !           304:                        return (EOPNOTSUPP);
        !           305:                return ((*ifp->if_ioctl)(ifp, cmd, data));
        !           306:        }
        !           307:        return (0);
        !           308: }
        !           309: 
        !           310: /*
        !           311:  * Initialize an interface's internet address
        !           312:  * and routing table entry.
        !           313:  */
        !           314: in_ifinit(ifp, ia, sin)
        !           315:        register struct ifnet *ifp;
        !           316:        register struct in_ifaddr *ia;
        !           317:        struct sockaddr_in *sin;
        !           318: {
        !           319:        register u_long i = ntohl(sin->sin_addr.s_addr);
        !           320:        struct sockaddr oldaddr;
        !           321:        struct sockaddr_in netaddr;
        !           322:        int s = splimp(), error;
        !           323: 
        !           324:        oldaddr = ia->ia_addr;
        !           325:        ia->ia_addr = *(struct sockaddr *)sin;
        !           326: 
        !           327:        /*
        !           328:         * Give the interface a chance to initialize
        !           329:         * if this is its first address,
        !           330:         * and to validate the address if necessary.
        !           331:         */
        !           332:        if (ifp->if_ioctl && (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) {
        !           333:                splx(s);
        !           334:                ia->ia_addr = oldaddr;
        !           335:                return (error);
        !           336:        }
        !           337: 
        !           338:        /*
        !           339:         * Delete any previous route for an old address.
        !           340:         */
        !           341:        bzero((caddr_t)&netaddr, sizeof (netaddr));
        !           342:        netaddr.sin_family = AF_INET;
        !           343:        if (ia->ia_flags & IFA_ROUTE) {
        !           344:                if (ifp->if_flags & IFF_LOOPBACK)
        !           345:                        rtinit(&oldaddr, &oldaddr, (int)SIOCDELRT, RTF_HOST);
        !           346:                else if (ifp->if_flags & IFF_POINTOPOINT)
        !           347:                        rtinit(&ia->ia_dstaddr, &oldaddr, (int)SIOCDELRT,
        !           348:                            RTF_HOST);
        !           349:                else {
        !           350:                        netaddr.sin_addr = in_makeaddr(ia->ia_subnet,
        !           351:                            INADDR_ANY);
        !           352:                        rtinit((struct sockaddr *)&netaddr, &oldaddr, 
        !           353:                            (int)SIOCDELRT, 0);
        !           354:                }
        !           355:                ia->ia_flags &= ~IFA_ROUTE;
        !           356:        }
        !           357:        if (IN_CLASSA(i))
        !           358:                ia->ia_netmask = IN_CLASSA_NET;
        !           359:        else if (IN_CLASSB(i))
        !           360:                ia->ia_netmask = IN_CLASSB_NET;
        !           361:        else
        !           362:                ia->ia_netmask = IN_CLASSC_NET;
        !           363:        ia->ia_net = i & ia->ia_netmask;
        !           364:        /*
        !           365:         * The subnet mask includes at least the standard network part,
        !           366:         * but may already have been set to a larger value.
        !           367:         */
        !           368:        ia->ia_subnetmask |= ia->ia_netmask;
        !           369:        ia->ia_subnet = i & ia->ia_subnetmask;
        !           370:        if (ifp->if_flags & IFF_BROADCAST) {
        !           371:                ia->ia_broadaddr.sa_family = AF_INET;
        !           372:                ((struct sockaddr_in *)(&ia->ia_broadaddr))->sin_addr =
        !           373:                        in_makeaddr(ia->ia_subnet, INADDR_BROADCAST);
        !           374:                ia->ia_netbroadcast.s_addr =
        !           375:                    htonl(ia->ia_net | (INADDR_BROADCAST &~ ia->ia_netmask));
        !           376:        }
        !           377:        splx(s);
        !           378:        /*
        !           379:         * Add route for the network.
        !           380:         */
        !           381:        if (ifp->if_flags & IFF_LOOPBACK)
        !           382:                rtinit(&ia->ia_addr, &ia->ia_addr, (int)SIOCADDRT,
        !           383:                    RTF_HOST|RTF_UP);
        !           384:        else if (ifp->if_flags & IFF_POINTOPOINT)
        !           385:                rtinit(&ia->ia_dstaddr, &ia->ia_addr, (int)SIOCADDRT,
        !           386:                    RTF_HOST|RTF_UP);
        !           387:        else {
        !           388:                netaddr.sin_addr = in_makeaddr(ia->ia_subnet, INADDR_ANY);
        !           389:                rtinit((struct sockaddr *)&netaddr, &ia->ia_addr,
        !           390:                    (int)SIOCADDRT, RTF_UP);
        !           391:        }
        !           392:        ia->ia_flags |= IFA_ROUTE;
        !           393:        return (0);
        !           394: }
        !           395: 
        !           396: /*
        !           397:  * Return address info for specified internet network.
        !           398:  */
        !           399: struct in_ifaddr *
        !           400: in_iaonnetof(net)
        !           401:        u_long net;
        !           402: {
        !           403:        register struct in_ifaddr *ia;
        !           404: 
        !           405:        for (ia = in_ifaddr; ia; ia = ia->ia_next)
        !           406:                if (ia->ia_subnet == net)
        !           407:                        return (ia);
        !           408:        return ((struct in_ifaddr *)0);
        !           409: }
        !           410: 
        !           411: /*
        !           412:  * Return 1 if the address is a local broadcast address.
        !           413:  */
        !           414: in_broadcast(in)
        !           415:        struct in_addr in;
        !           416: {
        !           417:        register struct in_ifaddr *ia;
        !           418: 
        !           419:        /*
        !           420:         * Look through the list of addresses for a match
        !           421:         * with a broadcast address.
        !           422:         */
        !           423:        for (ia = in_ifaddr; ia; ia = ia->ia_next)
        !           424:            if (((struct sockaddr_in *)&ia->ia_broadaddr)->sin_addr.s_addr ==
        !           425:                in.s_addr && (ia->ia_ifp->if_flags & IFF_BROADCAST))
        !           426:                     return (1);
        !           427:        return (0);
        !           428: }
        !           429: #endif

unix.superglobalmegacorp.com

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