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