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

Defined functions

bsr defined in line 230; used 2 times
getifconf defined in line 83; used 1 times
inet_snetof defined in line 193; used 1 times

Defined variables

if_count defined in line 73; used 9 times
in_ifsni defined in line 71; used 20 times
sccsid defined in line 2; never used

Defined struct's

in_if defined in line 61; used 10 times
Last modified: 1988-01-05
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3431
Valid CSS Valid XHTML 1.0 Strict