|
|
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.