xref: /netbsd-src/usr.sbin/mrouted/inet.c (revision 2a399c6883d870daece976daec6ffa7bb7f934ce)
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