Expand PMF_FN_* macros.
[netbsd-mini2440.git] / dist / dhcp / common / inet.c
blob2b307d6039a64a071409280f548da711a37a8e10
1 /* inet.c
3 Subroutines to manipulate internet addresses in a safely portable
4 way... */
6 /*
7 * Copyright (c) 2004-2005 by Internet Systems Consortium, Inc. ("ISC")
8 * Copyright (c) 1995-2003 by Internet Software Consortium
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.
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.
22 * Internet Systems Consortium, Inc.
23 * 950 Charter Street
24 * Redwood City, CA 94063
25 * <info@isc.org>
26 * http://www.isc.org/
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''.
36 #ifndef lint
37 static char copyright[] =
38 "$Id: inet.c,v 1.4 2005/08/11 17:13:21 drochner Exp $ Copyright (c) 2004-2005 Internet Systems Consortium. All rights reserved.\n";
39 #endif /* not lint */
41 #include "dhcpd.h"
43 /* Return just the network number of an internet address... */
45 struct iaddr subnet_number (addr, mask)
46 struct iaddr addr;
47 struct iaddr mask;
49 int i;
50 struct iaddr rv;
52 if (addr.len > sizeof(addr.iabuf))
53 log_fatal("subnet_number():%s:%d: Invalid addr length.", MDL);
54 if (addr.len != mask.len)
55 log_fatal("subnet_number():%s:%d: Addr/mask length mismatch.",
56 MDL);
58 rv.len = 0;
60 /* Both addresses must have the same length... */
61 if (addr.len != mask.len)
62 return rv;
64 rv.len = addr.len;
65 for (i = 0; i < rv.len; i++)
66 rv.iabuf [i] = addr.iabuf [i] & mask.iabuf [i];
67 return rv;
70 /* Combine a network number and a integer to produce an internet address.
71 This won't work for subnets with more than 32 bits of host address, but
72 maybe this isn't a problem. */
74 struct iaddr ip_addr (subnet, mask, host_address)
75 struct iaddr subnet;
76 struct iaddr mask;
77 u_int32_t host_address;
79 int i, j, k;
80 u_int32_t swaddr;
81 struct iaddr rv;
82 unsigned char habuf [sizeof swaddr];
84 if (subnet.len > sizeof(subnet.iabuf))
85 log_fatal("ip_addr():%s:%d: Invalid addr length.", MDL);
86 if (subnet.len != mask.len)
87 log_fatal("ip_addr():%s:%d: Addr/mask length mismatch.",
88 MDL);
90 swaddr = htonl (host_address);
91 memcpy (habuf, &swaddr, sizeof swaddr);
93 /* Combine the subnet address and the host address. If
94 the host address is bigger than can fit in the subnet,
95 return a zero-length iaddr structure. */
96 rv = subnet;
97 j = rv.len - sizeof habuf;
98 for (i = sizeof habuf - 1; i >= 0; i--) {
99 if (mask.iabuf [i + j]) {
100 if (habuf [i] > (mask.iabuf [i + j] ^ 0xFF)) {
101 rv.len = 0;
102 return rv;
104 for (k = i - 1; k >= 0; k--) {
105 if (habuf [k]) {
106 rv.len = 0;
107 return rv;
110 rv.iabuf [i + j] |= habuf [i];
111 break;
112 } else
113 rv.iabuf [i + j] = habuf [i];
116 return rv;
119 /* Given a subnet number and netmask, return the address on that subnet
120 for which the host portion of the address is all ones (the standard
121 broadcast address). */
123 struct iaddr broadcast_addr (subnet, mask)
124 struct iaddr subnet;
125 struct iaddr mask;
127 int i;
128 struct iaddr rv;
130 if (subnet.len > sizeof(subnet.iabuf))
131 log_fatal("broadcast_addr():%s:%d: Invalid addr length.", MDL);
132 if (subnet.len != mask.len)
133 log_fatal("broadcast_addr():%s:%d: Addr/mask length mismatch.",
134 MDL);
136 if (subnet.len != mask.len) {
137 rv.len = 0;
138 return rv;
141 for (i = 0; i < subnet.len; i++) {
142 rv.iabuf [i] = subnet.iabuf [i] | (~mask.iabuf [i] & 255);
144 rv.len = subnet.len;
146 return rv;
149 u_int32_t host_addr (addr, mask)
150 struct iaddr addr;
151 struct iaddr mask;
153 int i;
154 u_int32_t swaddr;
155 struct iaddr rv;
157 if (addr.len > sizeof(addr.iabuf))
158 log_fatal("host_addr():%s:%d: Invalid addr length.", MDL);
159 if (addr.len != mask.len)
160 log_fatal("host_addr():%s:%d: Addr/mask length mismatch.",
161 MDL);
163 rv.len = 0;
165 /* Mask out the network bits... */
166 rv.len = addr.len;
167 for (i = 0; i < rv.len; i++)
168 rv.iabuf [i] = addr.iabuf [i] & ~mask.iabuf [i];
170 /* Copy out up to 32 bits... */
171 memcpy (&swaddr, &rv.iabuf [rv.len - sizeof swaddr], sizeof swaddr);
173 /* Swap it and return it. */
174 return ntohl (swaddr);
177 int addr_eq (addr1, addr2)
178 struct iaddr addr1, addr2;
180 if (addr1.len > sizeof(addr1.iabuf))
181 log_fatal("addr_eq():%s:%d: Invalid addr length.", MDL);
183 if (addr1.len != addr2.len)
184 return 0;
185 return memcmp (addr1.iabuf, addr2.iabuf, addr1.len) == 0;
188 char *piaddr (addr)
189 struct iaddr addr;
191 static char pbuf [4 * 16];
192 char *s = pbuf;
193 int i;
195 if (addr.len > sizeof(addr.iabuf))
196 log_fatal("piaddr():%s:%d: Address length too long.", MDL);
198 if (addr.len == 0) {
199 strcpy (s, "<null address>");
201 for (i = 0; i < addr.len; i++) {
202 sprintf (s, "%s%d", i ? "." : "", addr.iabuf [i]);
203 s += strlen (s);
205 return pbuf;
208 char *piaddrmask (struct iaddr addr, struct iaddr mask,
209 const char *file, int line)
211 char *s, tbuf[sizeof("255.255.255.255/32")];
212 int mw;
213 unsigned i, oct, bit;
215 if (addr.len != 4)
216 log_fatal("piaddrmask():%s:%d: Address length %d invalid",
217 MDL, addr.len);
218 if (addr.len != mask.len)
219 log_fatal("piaddrmask():%s:%d: Address and mask size mismatch",
220 MDL);
222 /* Determine netmask width in bits. */
223 for (mw = 32; mw > 0; ) {
224 oct = (mw - 1) / 8;
225 bit = 0x80 >> ((mw - 1) % 8);
226 if (!mask.iabuf [oct])
227 mw -= 8;
228 else if (mask.iabuf [oct] & bit)
229 break;
230 else
231 mw--;
234 s = tbuf;
235 for (i = 0 ; i <= oct ; i++) {
236 sprintf(s, "%s%d", i ? "." : "", addr.iabuf[i]);
237 s += strlen(s);
239 sprintf(s, "/%d", mw);
241 s = dmalloc (strlen(tbuf) + 1, file, line);
242 if (!s)
243 return s;
244 strcpy(s, tbuf);
245 return s;