Annotation of embedaddon/pimd/inet.c, revision 1.1.1.1
1.1 misho 1: /*
2: * The mrouted program is covered by the license in the accompanying file
3: * named "LICENSE.mrouted". Use of the mrouted program represents acceptance of
4: * the terms and conditions listed in that file.
5: *
6: * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of
7: * Leland Stanford Junior University.
8: *
9: *
10: * inet.c,v 3.8.4.1 1997/01/29 19:49:33 fenner Exp
11: */
12: #define C(x) ((x) & 0xff)
13:
14: #include "defs.h"
15:
16:
17: /*
18: * Exported variables.
19: */
20: char s1[MAX_INET_BUF_LEN]; /* buffers to hold the string representations */
21: char s2[MAX_INET_BUF_LEN]; /* of IP addresses, to be passed to inet_fmt() */
22: char s3[MAX_INET_BUF_LEN];
23: char s4[MAX_INET_BUF_LEN];
24:
25:
26: /*
27: * Verify that a given IP address is credible as a host address.
28: * (Without a mask, cannot detect addresses of the form {subnet,0} or
29: * {subnet,-1}.)
30: */
31: int inet_valid_host(uint32_t naddr)
32: {
33: uint32_t addr;
34:
35: addr = ntohl(naddr);
36:
37: return !(IN_MULTICAST(addr) ||
38: IN_BADCLASS (addr) ||
39: (addr & 0xff000000) == 0);
40: }
41:
42: /*
43: * Verify that a given netmask is plausible;
44: * make sure that it is a series of 1's followed by
45: * a series of 0's with no discontiguous 1's.
46: */
47: int inet_valid_mask(uint32_t mask)
48: {
49: if (~(((mask & -mask) - 1) | mask) != 0) {
50: /* Mask is not contiguous */
51: return FALSE;
52: }
53:
54: return TRUE;
55: }
56:
57: /*
58: * Verify that a given subnet number and mask pair are credible.
59: *
60: * With CIDR, almost any subnet and mask are credible. mrouted still
61: * can't handle aggregated class A's, so we still check that, but
62: * otherwise the only requirements are that the subnet address is
63: * within the [ABC] range and that the host bits of the subnet
64: * are all 0.
65: */
66: int inet_valid_subnet(uint32_t nsubnet, uint32_t nmask)
67: {
68: uint32_t subnet, mask;
69:
70: subnet = ntohl(nsubnet);
71: mask = ntohl(nmask);
72:
73: if ((subnet & mask) != subnet)
74: return FALSE;
75:
76: if (subnet == 0)
77: return mask == 0;
78:
79: if (IN_CLASSA(subnet)) {
80: if (mask < 0xff000000 ||
81: (subnet & 0xff000000) == 0x7f000000 ||
82: (subnet & 0xff000000) == 0x00000000)
83: return FALSE;
84: }
85: else if (IN_CLASSD(subnet) || IN_BADCLASS(subnet)) {
86: /* Above Class C address space */
87: return FALSE;
88: }
89: if (subnet & ~mask) {
90: /* Host bits are set in the subnet */
91: return FALSE;
92: }
93: if (!inet_valid_mask(mask)) {
94: /* Netmask is not contiguous */
95: return FALSE;
96: }
97:
98: return TRUE;
99: }
100:
101:
102: /*
103: * Convert an IP address in uint32_t (network) format into a printable string.
104: */
105: char *inet_fmt(uint32_t addr, char *s, size_t len)
106: {
107: uint8_t *a;
108:
109: a = (uint8_t *)&addr;
110: snprintf(s, len, "%u.%u.%u.%u", a[0], a[1], a[2], a[3]);
111:
112: return s;
113: }
114:
115: /*
116: * Convert the printable string representation of an IP address into the
117: * uint32_t (network) format. Return 0xffffffff on error. (To detect the
118: * legal address with that value, you must explicitly compare the string
119: * with "255.255.255.255".)
120: * The return value is in network order.
121: */
122: uint32_t inet_parse(char *s, int n)
123: {
124: uint32_t a = 0;
125: u_int a0 = 0, a1 = 0, a2 = 0, a3 = 0;
126: int i;
127: char c;
128:
129: i = sscanf(s, "%u.%u.%u.%u%c", &a0, &a1, &a2, &a3, &c);
130: if (i < n || i > 4 || a0 > 255 || a1 > 255 || a2 > 255 || a3 > 255)
131: return 0xffffffff;
132:
133: ((uint8_t *)&a)[0] = a0;
134: ((uint8_t *)&a)[1] = a1;
135: ((uint8_t *)&a)[2] = a2;
136: ((uint8_t *)&a)[3] = a3;
137:
138: return a;
139: }
140:
141:
142: /*
143: * inet_cksum extracted from:
144: * P I N G . C
145: *
146: * Author -
147: * Mike Muuss
148: * U. S. Army Ballistic Research Laboratory
149: * December, 1983
150: * Modified at Uc Berkeley
151: *
152: * (ping.c) Status -
153: * Public Domain. Distribution Unlimited.
154: *
155: * I N _ C K S U M
156: *
157: * Checksum routine for Internet Protocol family headers (C Version)
158: *
159: */
160: int inet_cksum(uint16_t *addr, u_int len)
161: {
162: int sum = 0;
163: int nleft = (int)len;
164: uint16_t *w = addr;
165: uint16_t answer = 0;
166:
167: /*
168: * Our algorithm is simple, using a 32 bit accumulator (sum),
169: * we add sequential 16 bit words to it, and at the end, fold
170: * back all the carry bits from the top 16 bits into the lower
171: * 16 bits.
172: */
173: while (nleft > 1) {
174: sum += *w++;
175: nleft -= 2;
176: }
177:
178: /* mop up an odd byte, if necessary */
179: if (nleft == 1) {
180: *(uint8_t *) (&answer) = *(uint8_t *)w ;
181: sum += answer;
182: }
183:
184: /*
185: * add back carry outs from top 16 bits to low 16 bits
186: */
187: sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
188: sum += (sum >> 16); /* add carry */
189: answer = ~sum; /* truncate to 16 bits */
190:
191: return answer;
192: }
193:
194: /*
195: * Called by following netname() to create a mask specified network address.
196: */
197: void trimdomain(char *cp)
198: {
199: static char domain[MAXHOSTNAMELEN + 1];
200: static int first = 1;
201: char *s;
202:
203: if (first) {
204: first = 0;
205: if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
206: (s = strchr(domain, '.')))
207: (void) strlcpy(domain, s + 1, sizeof(domain));
208: else
209: domain[0] = 0;
210: }
211:
212: if (domain[0]) {
213: while ((cp = strchr(cp, '.'))) {
214: if (!strcasecmp(cp + 1, domain)) {
215: *cp = 0;
216: break;
217: }
218: cp++;
219: }
220: }
221: }
222:
223: static uint32_t forgemask(uint32_t a)
224: {
225: uint32_t m;
226:
227: if (IN_CLASSA(a))
228: m = IN_CLASSA_NET;
229: else if (IN_CLASSB(a))
230: m = IN_CLASSB_NET;
231: else
232: m = IN_CLASSC_NET;
233:
234: return (m);
235: }
236:
237: static void domask(char *dst, size_t len, uint32_t addr, uint32_t mask)
238: {
239: int b, i;
240:
241: if (!mask || (forgemask(addr) == mask)) {
242: *dst = '\0';
243: return;
244: }
245:
246: i = 0;
247: for (b = 0; b < 32; b++) {
248: if (mask & (1 << b)) {
249: int bb;
250:
251: i = b;
252: for (bb = b+1; bb < 32; bb++) {
253: if (!(mask & (1 << bb))) {
254: i = -1; /* noncontig */
255: break;
256: }
257: }
258: break;
259: }
260: }
261:
262: if (i == -1)
263: snprintf(dst, len, "&0x%x", mask);
264: else
265: snprintf(dst, len, "/%d", 32 - i);
266: }
267:
268: /*
269: * Return the name of the network whose address is given.
270: * The address is assumed to be that of a net or subnet, not a host.
271: */
272: char *netname(uint32_t addr, uint32_t mask)
273: {
274: static char line[MAXHOSTNAMELEN + 4];
275: uint32_t omask;
276: uint32_t i;
277:
278: i = ntohl(addr);
279: omask = mask = ntohl(mask);
280: if ((i & 0xffffff) == 0)
281: snprintf(line, sizeof(line), "%u", C(i >> 24));
282: else if ((i & 0xffff) == 0)
283: snprintf(line, sizeof(line), "%u.%u", C(i >> 24) , C(i >> 16));
284: else if ((i & 0xff) == 0)
285: snprintf(line, sizeof(line), "%u.%u.%u", C(i >> 24), C(i >> 16), C(i >> 8));
286: else
287: snprintf(line, sizeof(line), "%u.%u.%u.%u", C(i >> 24),
288: C(i >> 16), C(i >> 8), C(i));
289: domask(line + strlen(line), sizeof(line) - strlen(line), i, omask);
290:
291: return line;
292: }
293:
294: /**
295: * Local Variables:
296: * version-control: t
297: * indent-tabs-mode: t
298: * c-file-style: "ellemtel"
299: * c-basic-offset: 4
300: * End:
301: */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>