3 Subroutines to manipulate internet addresses in a safely portable
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.
24 * Redwood City, CA 94063
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''.
37 static char copyright
[] =
38 "$Id$ Copyright (c) 2004-2005 Internet Systems Consortium. All rights reserved.\n";
43 /* Return just the network number of an internet address... */
45 struct iaddr
subnet_number (addr
, mask
)
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.",
60 /* Both addresses must have the same length... */
61 if (addr
.len
!= mask
.len
)
65 for (i
= 0; i
< rv
.len
; i
++)
66 rv
.iabuf
[i
] = addr
.iabuf
[i
] & mask
.iabuf
[i
];
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
)
77 u_int32_t host_address
;
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.",
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. */
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)) {
104 for (k
= i
- 1; k
>= 0; k
--) {
110 rv
.iabuf
[i
+ j
] |= habuf
[i
];
113 rv
.iabuf
[i
+ j
] = habuf
[i
];
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
)
131 if (subnet
.len
> sizeof(subnet
.iabuf
))
132 log_fatal("broadcast_addr():%s:%d: Invalid addr length.", MDL
);
133 if (subnet
.len
!= mask
.len
)
134 log_fatal("broadcast_addr():%s:%d: Addr/mask length mismatch.",
137 if (subnet
.len
!= mask
.len
) {
142 for (i
= 0; i
< subnet
.len
; i
++) {
143 rv
.iabuf
[i
] = subnet
.iabuf
[i
] | (~mask
.iabuf
[i
] & 255);
150 u_int32_t
host_addr (addr
, mask
)
158 if (addr
.len
> sizeof(addr
.iabuf
))
159 log_fatal("host_addr():%s:%d: Invalid addr length.", MDL
);
160 if (addr
.len
!= mask
.len
)
161 log_fatal("host_addr():%s:%d: Addr/mask length mismatch.",
166 /* Mask out the network bits... */
168 for (i
= 0; i
< rv
.len
; i
++)
169 rv
.iabuf
[i
] = addr
.iabuf
[i
] & ~mask
.iabuf
[i
];
171 /* Copy out up to 32 bits... */
172 memcpy (&swaddr
, &rv
.iabuf
[rv
.len
- sizeof swaddr
], sizeof swaddr
);
174 /* Swap it and return it. */
175 return ntohl (swaddr
);
178 int addr_eq (addr1
, addr2
)
179 struct iaddr addr1
, addr2
;
181 if (addr1
.len
> sizeof(addr1
.iabuf
))
182 log_fatal("addr_eq():%s:%d: Invalid addr length.", MDL
);
184 if (addr1
.len
!= addr2
.len
)
186 return memcmp (addr1
.iabuf
, addr2
.iabuf
, addr1
.len
) == 0;
192 static char pbuf
[4 * 16];
196 if (addr
.len
> sizeof(addr
.iabuf
))
197 log_fatal("piaddr():%s:%d: Address length too long.", MDL
);
200 strcpy (s
, "<null address>");
202 for (i
= 0; i
< addr
.len
; i
++) {
203 sprintf (s
, "%s%d", i
? "." : "", addr
.iabuf
[i
]);
209 char *piaddrmask (struct iaddr addr
, struct iaddr mask
,
210 const char *file
, int line
)
212 char *s
, tbuf
[sizeof("255.255.255.255/32")];
214 unsigned i
, oct
, bit
;
217 log_fatal("piaddrmask():%s:%d: Address length %d invalid",
219 if (addr
.len
!= mask
.len
)
220 log_fatal("piaddrmask():%s:%d: Address and mask size mismatch",
223 /* Determine netmask width in bits. */
224 for (mw
= 32; mw
> 0; ) {
226 bit
= 0x80 >> ((mw
- 1) % 8);
227 if (!mask
.iabuf
[oct
])
229 else if (mask
.iabuf
[oct
] & bit
)
236 for (i
= 0 ; i
<= oct
; i
++) {
237 sprintf(s
, "%s%d", i
? "." : "", addr
.iabuf
[i
]);
240 sprintf(s
, "/%d", mw
);
242 s
= dmalloc (strlen(tbuf
) + 1, file
, line
);