Annotation of 43BSD/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.  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.