inet.c revision 1.4 1 /* $NetBSD: inet.c,v 1.4 1995/12/10 10:07:03 mycroft Exp $ */
2
3 /*
4 * The mrouted program is covered by the license in the accompanying file
5 * named "LICENSE". Use of the mrouted program represents acceptance of
6 * the terms and conditions listed in that file.
7 *
8 * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of
9 * Leland Stanford Junior University.
10 */
11
12
13 #include "defs.h"
14
15
16 /*
17 * Exported variables.
18 */
19 char s1[19]; /* buffers to hold the string representations */
20 char s2[19]; /* of IP addresses, to be passed to inet_fmt() */
21 char s3[19]; /* or inet_fmts(). */
22 char s4[19];
23
24
25 /*
26 * Verify that a given IP address is credible as a host address.
27 * (Without a mask, cannot detect addresses of the form {subnet,0} or
28 * {subnet,-1}.)
29 */
30 int
31 inet_valid_host(naddr)
32 u_int32_t naddr;
33 {
34 register u_int32_t addr;
35
36 addr = ntohl(naddr);
37
38 return (!(IN_MULTICAST(addr) ||
39 IN_BADCLASS (addr) ||
40 (addr & 0xff000000) == 0));
41 }
42
43 /*
44 * Verify that a given netmask is plausible;
45 * make sure that it is a series of 1's followed by
46 * a series of 0's with no discontiguous 1's.
47 */
48 int
49 inet_valid_mask(mask)
50 u_int32_t mask;
51 {
52 if (~(((mask & -mask) - 1) | mask) != 0) {
53 /* Mask is not contiguous */
54 return (FALSE);
55 }
56
57 return (TRUE);
58 }
59
60 /*
61 * Verify that a given subnet number and mask pair are credible.
62 *
63 * With CIDR, almost any subnet and mask are credible. mrouted still
64 * can't handle aggregated class A's, so we still check that, but
65 * otherwise the only requirements are that the subnet address is
66 * within the [ABC] range and that the host bits of the subnet
67 * are all 0.
68 */
69 int
70 inet_valid_subnet(nsubnet, nmask)
71 u_int32_t nsubnet, nmask;
72 {
73 register u_int32_t subnet, mask;
74
75 subnet = ntohl(nsubnet);
76 mask = ntohl(nmask);
77
78 if ((subnet & mask) != subnet) return (FALSE);
79
80 if (subnet == 0)
81 return (mask == 0);
82
83 if (IN_CLASSA(subnet)) {
84 if (mask < 0xff000000 ||
85 (subnet & 0xff000000) == 0x7f000000 ||
86 (subnet & 0xff000000) == 0x00000000) return (FALSE);
87 }
88 else if (IN_CLASSD(subnet) || IN_BADCLASS(subnet)) {
89 /* Above Class C address space */
90 return (FALSE);
91 }
92 if (subnet & ~mask) {
93 /* Host bits are set in the subnet */
94 return (FALSE);
95 }
96 if (!inet_valid_mask(mask)) {
97 /* Netmask is not contiguous */
98 return (FALSE);
99 }
100
101 return (TRUE);
102 }
103
104
105 /*
106 * Convert an IP address in u_long (network) format into a printable string.
107 */
108 char *
109 inet_fmt(addr, s)
110 u_int32_t addr;
111 char *s;
112 {
113 register u_char *a;
114
115 a = (u_char *)&addr;
116 sprintf(s, "%u.%u.%u.%u", a[0], a[1], a[2], a[3]);
117 return (s);
118 }
119
120
121 /*
122 * Convert an IP subnet number in u_long (network) format into a printable
123 * string including the netmask as a number of bits.
124 */
125 char *
126 inet_fmts(addr, mask, s)
127 u_int32_t addr, mask;
128 char *s;
129 {
130 register u_char *a, *m;
131 int bits;
132
133 if ((addr == 0) && (mask == 0)) {
134 sprintf(s, "default");
135 return (s);
136 }
137 a = (u_char *)&addr;
138 m = (u_char *)&mask;
139 bits = 33 - ffs(ntohl(mask));
140
141 if (m[3] != 0) sprintf(s, "%u.%u.%u.%u/%d", a[0], a[1], a[2], a[3],
142 bits);
143 else if (m[2] != 0) sprintf(s, "%u.%u.%u/%d", a[0], a[1], a[2], bits);
144 else if (m[1] != 0) sprintf(s, "%u.%u/%d", a[0], a[1], bits);
145 else sprintf(s, "%u/%d", a[0], bits);
146
147 return (s);
148 }
149
150 /*
151 * Convert the printable string representation of an IP address into the
152 * u_long (network) format. Return 0xffffffff on error. (To detect the
153 * legal address with that value, you must explicitly compare the string
154 * with "255.255.255.255".)
155 */
156 u_int32_t
157 inet_parse(s)
158 char *s;
159 {
160 u_int32_t a = 0;
161 u_int a0, a1, a2, a3;
162 char c;
163
164 if (sscanf(s, "%u.%u.%u.%u%c", &a0, &a1, &a2, &a3, &c) != 4 ||
165 a0 > 255 || a1 > 255 || a2 > 255 || a3 > 255)
166 return (0xffffffff);
167
168 ((u_char *)&a)[0] = a0;
169 ((u_char *)&a)[1] = a1;
170 ((u_char *)&a)[2] = a2;
171 ((u_char *)&a)[3] = a3;
172
173 return (a);
174 }
175
176
177 /*
178 * inet_cksum extracted from:
179 * P I N G . C
180 *
181 * Author -
182 * Mike Muuss
183 * U. S. Army Ballistic Research Laboratory
184 * December, 1983
185 * Modified at Uc Berkeley
186 *
187 * (ping.c) Status -
188 * Public Domain. Distribution Unlimited.
189 *
190 * I N _ C K S U M
191 *
192 * Checksum routine for Internet Protocol family headers (C Version)
193 *
194 */
195 int
196 inet_cksum(addr, len)
197 u_short *addr;
198 u_int len;
199 {
200 register int nleft = (int)len;
201 register u_short *w = addr;
202 u_short answer = 0;
203 register int sum = 0;
204
205 /*
206 * Our algorithm is simple, using a 32 bit accumulator (sum),
207 * we add sequential 16 bit words to it, and at the end, fold
208 * back all the carry bits from the top 16 bits into the lower
209 * 16 bits.
210 */
211 while (nleft > 1) {
212 sum += *w++;
213 nleft -= 2;
214 }
215
216 /* mop up an odd byte, if necessary */
217 if (nleft == 1) {
218 *(u_char *) (&answer) = *(u_char *)w ;
219 sum += answer;
220 }
221
222 /*
223 * add back carry outs from top 16 bits to low 16 bits
224 */
225 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
226 sum += (sum >> 16); /* add carry */
227 answer = ~sum; /* truncate to 16 bits */
228 return (answer);
229 }
230