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