Annotation of 43BSDTahoe/sys/netinet/in.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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