Annotation of 43BSDTahoe/new/nntp/server/subnet.c, revision 1.1.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.