xref: /netbsd-src/usr.sbin/mrouted/inet.c (revision ce0bb6e8d2e560ecacbe865a848624f94498063b)
1 /*
2  * The mrouted program is covered by the license in the accompanying file
3  * named "LICENSE".  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  * from: Id: inet.c,v 1.4 1993/05/30 01:36:38 deering Exp
11  *      $Id: inet.c,v 1.1 1994/01/11 20:15:55 brezak Exp $
12  */
13 
14 #ifndef lint
15 static char rcsid[] = "$Id: inet.c,v 1.1 1994/01/11 20:15:55 brezak Exp $";
16 #endif
17 
18 #include "defs.h"
19 
20 
21 /*
22  * Exported variables.
23  */
24 char s1[16];		/* buffers to hold the string representations  */
25 char s2[16];		/* of IP addresses, to be passed to inet_fmt() */
26 char s3[16];		/* or inet_fmts().                             */
27 
28 
29 /*
30  * Verify that a given IP address is credible as a host address.
31  * (Without a mask, cannot detect addresses of the form {subnet,0} or
32  * {subnet,-1}.)
33  */
34 int inet_valid_host(naddr)
35     u_long naddr;
36 {
37     register u_long addr;
38 
39     addr = ntohl(naddr);
40 
41     return (!(IN_MULTICAST(addr) ||
42 	      IN_BADCLASS (addr) ||
43 	      (addr & 0xff000000) == 0));
44 }
45 
46 
47 /*
48  * Verify that a given subnet number and mask pair are credible.
49  */
50 int inet_valid_subnet(nsubnet, nmask)
51     u_long nsubnet, nmask;
52 {
53     register u_long subnet, mask;
54 
55     subnet = ntohl(nsubnet);
56     mask   = ntohl(nmask);
57 
58     if ((subnet & mask) != subnet) return (FALSE);
59 
60     if (IN_CLASSA(subnet)) {
61 	if (mask < 0xff000000 ||
62 	   (subnet & 0xff000000) == 0 ||
63 	   (subnet & 0xff000000) == 0x7f000000) return (FALSE);
64     }
65     else if (IN_CLASSB(subnet)) {
66 	if (mask < 0xffff0000) return (FALSE);
67     }
68     else if (IN_CLASSC(subnet)) {
69 	if (mask < 0xffffff00) return (FALSE);
70     }
71     else return (FALSE);
72 
73     return (TRUE);
74 }
75 
76 
77 /*
78  * Convert an IP address in u_long (network) format into a printable string.
79  */
80 char *inet_fmt(addr, s)
81     u_long addr;
82     char *s;
83 {
84     register u_char *a;
85 
86     a = (u_char *)&addr;
87     sprintf(s, "%u.%u.%u.%u", a[0], a[1], a[2], a[3]);
88     return (s);
89 }
90 
91 
92 /*
93  * Convert an IP subnet number in u_long (network) format into a printable
94  * string.
95  */
96 char *inet_fmts(addr, mask, s)
97     u_long addr, mask;
98     char *s;
99 {
100     register u_char *a, *m;
101 
102     a = (u_char *)&addr;
103     m = (u_char *)&mask;
104 
105     if      (m[3] != 0) sprintf(s, "%u.%u.%u.%u", a[0], a[1], a[2], a[3]);
106     else if (m[2] != 0) sprintf(s, "%u.%u.%u",    a[0], a[1], a[2]);
107     else if (m[1] != 0) sprintf(s, "%u.%u",       a[0], a[1]);
108     else                sprintf(s, "%u",          a[0]);
109 
110     return (s);
111 }
112 
113 
114 /*
115  * Convert the printable string representation of an IP address into the
116  * u_long (network) format.  Return 0xffffffff on error.  (To detect the
117  * legal address with that value, you must explicitly compare the string
118  * with "255.255.255.255".)
119  */
120 u_long inet_parse(s)
121     char *s;
122 {
123     u_long a;
124     u_int a0, a1, a2, a3;
125     char c;
126 
127     if (sscanf(s, "%u.%u.%u.%u%c", &a0, &a1, &a2, &a3, &c) != 4 ||
128 	a0 > 255 || a1 > 255 || a2 > 255 || a3 > 255)
129 	return (0xffffffff);
130 
131     ((u_char *)&a)[0] = a0;
132     ((u_char *)&a)[1] = a1;
133     ((u_char *)&a)[2] = a2;
134     ((u_char *)&a)[3] = a3;
135 
136     return (a);
137 }
138 
139 
140 /*
141  * inet_cksum extracted from:
142  *			P I N G . C
143  *
144  * Author -
145  *	Mike Muuss
146  *	U. S. Army Ballistic Research Laboratory
147  *	December, 1983
148  * Modified at Uc Berkeley
149  *
150  * (ping.c) Status -
151  *	Public Domain.  Distribution Unlimited.
152  *
153  *			I N _ C K S U M
154  *
155  * Checksum routine for Internet Protocol family headers (C Version)
156  *
157  */
158 int inet_cksum(addr, len)
159 	u_short *addr;
160 	u_int len;
161 {
162 	register int nleft = (int)len;
163 	register u_short *w = addr;
164 	u_short answer = 0;
165 	register int sum = 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 		*(u_char *) (&answer) = *(u_char *)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 	return (answer);
191 }
192