|
|
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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.