Annotation of 43BSDTahoe/new/nntp/server/subnet.c, revision 1.1

1.1     ! root        1: #ifndef lint
        !             2: static char    *sccsid = "@(#)subnet.c 1.2     (Berkeley) 10/15/87";
        !             3: #endif
        !             4: 
        !             5: 
        !             6: #include <sys/types.h>
        !             7: #include <sys/socket.h>
        !             8: #include <netinet/in.h>
        !             9: #include <net/if.h>
        !            10: #include <sys/ioctl.h>
        !            11: #include "../common/conf.h"
        !            12: 
        !            13: #ifdef SUBNET
        !            14: 
        !            15: /*
        !            16:  * The following routines provide a general interface for
        !            17:  * subnet support.  Like the library function "inet_netof",
        !            18:  * which returns the standard (i.e., non-subnet) network
        !            19:  * portion of an internet address, "inet_snetof" returns
        !            20:  * the subnetwork portion -- if there is one.  If there
        !            21:  * isn't, it returns 0.
        !            22:  *
        !            23:  * Subnets, under 4.3, are specific to a given set of
        !            24:  * machines -- right down to the network interfaces.
        !            25:  * Because of this, the function "getifconf" must be
        !            26:  * called first.  This routine builds a table listing
        !            27:  * all the (internet) interfaces present on a machine,
        !            28:  * along with their subnet masks.  Then when inet_snetof
        !            29:  * is called, it can quickly scan this table.
        !            30:  *
        !            31:  * Unfortunately, there "ain't no graceful way" to handle
        !            32:  * certain situations.  For example, the kernel permits
        !            33:  * arbitrary subnet bits -- that is, you could have a
        !            34:  * 22 bit network field and a 10 bit subnet field.
        !            35:  * However, due to braindamage at the user level, in
        !            36:  * such sterling routines as getnetbyaddr, you need to
        !            37:  * have a subnet mask which is an even multiple of 8.
        !            38:  * Unless you are running with class C subnets, in which
        !            39:  * case it should be a multiple of 4.  Because of this rot,
        !            40:  * if you have non-multiples of 4 bits of subnet, you should
        !            41:  * define DAMAGED_NETMASK when you compile.  This will round
        !            42:  * things off to a multiple of 8 bits.
        !            43:  *
        !            44:  * And even that may not work.
        !            45:  */
        !            46: 
        !            47: /*
        !            48:  * One structure for each interface, containing
        !            49:  * the network number and subnet mask, stored in HBO.
        !            50:  */
        !            51: struct in_if {
        !            52:        u_long  i_net;          /* Network number, shifted right */
        !            53:        u_long  i_subnetmask;   /* Subnet mask for this if */
        !            54:        int     i_bitshift;     /* How many bits right for outside */
        !            55: };
        !            56: 
        !            57: /*
        !            58:  * Table (eventually, once we malloc) of
        !            59:  * internet interface subnet informaiton.
        !            60:  */
        !            61: static struct in_if    *in_ifsni;
        !            62: 
        !            63: static int             if_count;
        !            64: 
        !            65: /*
        !            66:  * Get the network interface configuration,
        !            67:  * and squirrel away the network numbers and
        !            68:  * subnet masks of each interface.  Return
        !            69:  * number of interfaces found, or -1 on error.
        !            70:  * N.B.: don't call this more than once...
        !            71:  */
        !            72: 
        !            73: getifconf()
        !            74: {
        !            75:        register int    i, j;
        !            76:        int             s;
        !            77:        struct ifconf   ifc;
        !            78:        char            buf[1024];
        !            79:        register struct ifreq   *ifr;
        !            80:        u_long          inet_netof();
        !            81: 
        !            82:        /*
        !            83:         * Find out how many interfaces we have, and malloc
        !            84:         * room for information about each one.
        !            85:         */
        !            86: 
        !            87:        s = socket(AF_INET, SOCK_DGRAM, 0);
        !            88:        if (s < 0)
        !            89:                return (-1);
        !            90: 
        !            91:        ifc.ifc_buf = buf;
        !            92:        ifc.ifc_len = sizeof (buf);
        !            93: 
        !            94:        if (ioctl(s, SIOCGIFCONF, &ifc) < 0) {
        !            95:                (void) close(s);
        !            96:                return (-1);
        !            97:        }
        !            98: 
        !            99:        /*
        !           100:         * if_count here is the count of possible
        !           101:         * interfaces we may be interested in... actual
        !           102:         * interfaces may be less (some may not be internet,
        !           103:         * not all are necessarily up, etc.)
        !           104:         */
        !           105: 
        !           106:        if_count = ifc.ifc_len / sizeof (struct ifreq);
        !           107: 
        !           108:        in_ifsni = (struct in_if *) malloc(if_count * sizeof (struct in_if));
        !           109:        if (in_ifsni == 0) {
        !           110:                (void) close(s);
        !           111:                return (-1);
        !           112:        }
        !           113: 
        !           114:        for (i = j = 0; i < if_count; ++i) {
        !           115:                ifr = &ifc.ifc_req[i];
        !           116:                if (ioctl(s, SIOCGIFFLAGS, ifr) < 0)
        !           117:                        continue;
        !           118:                if ((ifr->ifr_flags & IFF_UP) == 0)
        !           119:                        continue;
        !           120:                if (ioctl(s, SIOCGIFADDR, ifr) < 0)
        !           121:                        continue;
        !           122:                if (ifr->ifr_addr.sa_family != AF_INET)
        !           123:                        continue;
        !           124:                in_ifsni[j].i_net =
        !           125:                   inet_netof((*(struct sockaddr_in *)&ifr->ifr_addr).sin_addr);
        !           126:                if (ioctl(s, SIOCGIFNETMASK, ifr) < 0)
        !           127:                        continue;
        !           128:                in_ifsni[j].i_subnetmask =
        !           129:                 ntohl((*(struct sockaddr_in *)&ifr->ifr_addr).sin_addr.s_addr);
        !           130:                /*
        !           131:                 * The following should "never happen".  But under SunOs
        !           132:                 * 3.4, along with the rest of their broken networking code,
        !           133:                 * SIOCGIFNETMASK can get a netmask which is 0.  There
        !           134:                 * really isn't anything that "right" that we can do
        !           135:                 * about it, so we'll set their subnet mask to be a class
        !           136:                 * B subnet.  Which may or may not be right.
        !           137:                 */
        !           138:                if (in_ifsni[j].i_subnetmask == 0)
        !           139:                        in_ifsni[j].i_subnetmask = IN_CLASSB_NET;
        !           140:                in_ifsni[j].i_bitshift = bsr(in_ifsni[j].i_subnetmask);
        !           141:                j++;
        !           142:        }
        !           143: 
        !           144:        if_count = j;
        !           145: 
        !           146:        (void) close(s);
        !           147: 
        !           148:        return (if_count);
        !           149: }
        !           150: 
        !           151: 
        !           152: /*
        !           153:  * Return the (sub)network number from an internet address.
        !           154:  * "in" is in NBO, return value in host byte order.
        !           155:  * If "in" is not a subnet, return 0.
        !           156:  */
        !           157: 
        !           158: u_long
        !           159: inet_snetof(in)
        !           160:        u_long  in;
        !           161: {
        !           162:        register int    j;
        !           163:        register u_long i = ntohl(in);
        !           164:        register u_long net;
        !           165:        u_long          inet_netof(), inet_lnaof();
        !           166: 
        !           167:        net = inet_netof(in);
        !           168: 
        !           169:        /*
        !           170:         * Check whether network is a subnet;
        !           171:         * if so, return subnet number.
        !           172:         */
        !           173:        for (j = 0; j < if_count; ++j)
        !           174:                if (net == in_ifsni[j].i_net) {
        !           175:                        net = i & in_ifsni[j].i_subnetmask;
        !           176:                        if (inet_lnaof(htonl(net)) == 0)
        !           177:                                return (0);
        !           178:                        else
        !           179:                                return (net >> in_ifsni[j].i_bitshift);
        !           180:                }
        !           181: 
        !           182:        return (0);
        !           183: }
        !           184: 
        !           185: 
        !           186: /*
        !           187:  * Return the number of bits required to
        !           188:  * shift right a mask into a getnetent-able entitity.
        !           189:  */
        !           190: 
        !           191: bsr(mask)
        !           192:        register int    mask;
        !           193: {
        !           194:        register int    count = 0;
        !           195: 
        !           196:        if (mask == 0)          /* "never happen", except with SunOs 3.4 */
        !           197:                return (0);
        !           198: 
        !           199:        while ((mask & 1) == 0) {
        !           200:                ++count;
        !           201:                mask >>= 1;
        !           202:        }
        !           203: #ifdef DAMAGED_NETMASK
        !           204:        count /= 8;                     /* XXX gag retch puke barf */
        !           205:        count *= 8;
        !           206: #endif
        !           207:        return (count);
        !           208: }
        !           209: 
        !           210: #endif

unix.superglobalmegacorp.com

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