Merge from vendor branch BIND:
[dragonfly.git] / contrib / dhcp-3.0 / common / inet.c
1 /* inet.c
2
3    Subroutines to manipulate internet addresses in a safely portable
4    way... */
5
6 /*
7  * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
8  * Copyright (c) 1995-2003 by Internet Software Consortium
9  *
10  * Permission to use, copy, modify, and distribute this software for any
11  * purpose with or without fee is hereby granted, provided that the above
12  * copyright notice and this permission notice appear in all copies.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
15  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
16  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
17  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
20  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21  *
22  *   Internet Systems Consortium, Inc.
23  *   950 Charter Street
24  *   Redwood City, CA 94063
25  *   <info@isc.org>
26  *   http://www.isc.org/
27  *
28  * This software has been written for Internet Systems Consortium
29  * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
30  * To learn more about Internet Systems Consortium, see
31  * ``http://www.isc.org/''.  To learn more about Vixie Enterprises,
32  * see ``http://www.vix.com''.   To learn more about Nominum, Inc., see
33  * ``http://www.nominum.com''.
34  */
35
36 #ifndef lint
37 static char copyright[] =
38 "$Id: inet.c,v 1.8.2.5 2004/06/10 17:59:18 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium.  All rights reserved.\n";
39 #endif /* not lint */
40
41 #include "dhcpd.h"
42
43 /* Return just the network number of an internet address... */
44
45 struct iaddr subnet_number (addr, mask)
46         struct iaddr addr;
47         struct iaddr mask;
48 {
49         int i;
50         struct iaddr rv;
51
52         rv.len = 0;
53
54         /* Both addresses must have the same length... */
55         if (addr.len != mask.len)
56                 return rv;
57
58         rv.len = addr.len;
59         for (i = 0; i < rv.len; i++)
60                 rv.iabuf [i] = addr.iabuf [i] & mask.iabuf [i];
61         return rv;
62 }
63
64 /* Combine a network number and a integer to produce an internet address.
65    This won't work for subnets with more than 32 bits of host address, but
66    maybe this isn't a problem. */
67
68 struct iaddr ip_addr (subnet, mask, host_address)
69         struct iaddr subnet;
70         struct iaddr mask;
71         u_int32_t host_address;
72 {
73         int i, j, k;
74         u_int32_t swaddr;
75         struct iaddr rv;
76         unsigned char habuf [sizeof swaddr];
77
78         swaddr = htonl (host_address);
79         memcpy (habuf, &swaddr, sizeof swaddr);
80
81         /* Combine the subnet address and the host address.   If
82            the host address is bigger than can fit in the subnet,
83            return a zero-length iaddr structure. */
84         rv = subnet;
85         j = rv.len - sizeof habuf;
86         for (i = sizeof habuf - 1; i >= 0; i--) {
87                 if (mask.iabuf [i + j]) {
88                         if (habuf [i] > (mask.iabuf [i + j] ^ 0xFF)) {
89                                 rv.len = 0;
90                                 return rv;
91                         }
92                         for (k = i - 1; k >= 0; k--) {
93                                 if (habuf [k]) {
94                                         rv.len = 0;
95                                         return rv;
96                                 }
97                         }
98                         rv.iabuf [i + j] |= habuf [i];
99                         break;
100                 } else
101                         rv.iabuf [i + j] = habuf [i];
102         }
103                 
104         return rv;
105 }
106
107 /* Given a subnet number and netmask, return the address on that subnet
108    for which the host portion of the address is all ones (the standard
109    broadcast address). */
110
111 struct iaddr broadcast_addr (subnet, mask)
112         struct iaddr subnet;
113         struct iaddr mask;
114 {
115         int i, j, k;
116         struct iaddr rv;
117
118         if (subnet.len != mask.len) {
119                 rv.len = 0;
120                 return rv;
121         }
122
123         for (i = 0; i < subnet.len; i++) {
124                 rv.iabuf [i] = subnet.iabuf [i] | (~mask.iabuf [i] & 255);
125         }
126         rv.len = subnet.len;
127
128         return rv;
129 }
130
131 u_int32_t host_addr (addr, mask)
132         struct iaddr addr;
133         struct iaddr mask;
134 {
135         int i;
136         u_int32_t swaddr;
137         struct iaddr rv;
138
139         rv.len = 0;
140
141         /* Mask out the network bits... */
142         rv.len = addr.len;
143         for (i = 0; i < rv.len; i++)
144                 rv.iabuf [i] = addr.iabuf [i] & ~mask.iabuf [i];
145
146         /* Copy out up to 32 bits... */
147         memcpy (&swaddr, &rv.iabuf [rv.len - sizeof swaddr], sizeof swaddr);
148
149         /* Swap it and return it. */
150         return ntohl (swaddr);
151 }
152
153 int addr_eq (addr1, addr2)
154         struct iaddr addr1, addr2;
155 {
156         if (addr1.len != addr2.len)
157                 return 0;
158         return memcmp (addr1.iabuf, addr2.iabuf, addr1.len) == 0;
159 }
160
161 char *piaddr (addr)
162         struct iaddr addr;
163 {
164         static char pbuf [4 * 16];
165         char *s = pbuf;
166         int i;
167
168         if (addr.len == 0) {
169                 strcpy (s, "<null address>");
170         }
171         for (i = 0; i < addr.len; i++) {
172                 sprintf (s, "%s%d", i ? "." : "", addr.iabuf [i]);
173                 s += strlen (s);
174         }
175         return pbuf;
176 }
177
178 char *piaddr1 (addr)
179         struct iaddr addr;
180 {
181         static char pbuf [4 * 16];
182         char *s = pbuf;
183         int i;
184
185         if (addr.len == 0) {
186                 strcpy (s, "<null address>");
187         }
188         for (i = 0; i < addr.len; i++) {
189                 sprintf (s, "%s%d", i ? "." : "", addr.iabuf [i]);
190                 s += strlen (s);
191         }
192         return pbuf;
193 }
194
195 char *piaddrmask (struct iaddr addr, struct iaddr mask,
196                   const char *file, int line)
197 {
198         char *s, *t;
199         int i, mw;
200         unsigned len;
201
202         for (i = 0; i < 32; i++) {
203                 if (!mask.iabuf [3 - i / 8])
204                         i += 7;
205                 else if (mask.iabuf [3 - i / 8] & (1 << (i % 8)))
206                         break;
207         }
208         mw = 32 - i;
209         len = mw > 9 ? 2 : 1;
210         len += 4;       /* three dots and a slash. */
211         for (i = 0; i < (mw / 8) + 1; i++) {
212                 if (addr.iabuf [i] > 99)
213                         len += 3;
214                 else if (addr.iabuf [i] > 9)
215                         len += 2;
216                 else
217                         len++;
218         }
219         s = dmalloc (len + 1, file, line);
220         if (!s)
221                 return s;
222         t = s;
223         sprintf (t, "%d", addr.iabuf [0]);
224         t += strlen (t);
225         for (i = 1; i < (mw / 8) + 1; i++) {
226                 sprintf (t, ".%d", addr.iabuf [i]);
227                 t += strlen (t);
228         }
229         *t++ = '/';
230         sprintf (t, "%d", mw);
231         return s;
232 }
233