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