1 /* $NetBSD: inet.c,v 1.1.1.2 2014/07/12 11:57:44 spz Exp $ */
4 Subroutines to manipulate internet addresses and ports in a safely portable
8 * Copyright (c) 2011,2013,2014 by Internet Systems Consortium, Inc. ("ISC")
9 * Copyright (c) 2007-2009 by Internet Systems Consortium, Inc. ("ISC")
10 * Copyright (c) 2004,2005 by Internet Systems Consortium, Inc. ("ISC")
11 * Copyright (c) 1995-2003 by Internet Software Consortium
13 * Permission to use, copy, modify, and distribute this software for any
14 * purpose with or without fee is hereby granted, provided that the above
15 * copyright notice and this permission notice appear in all copies.
17 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
18 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
20 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
21 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
22 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
23 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25 * Internet Systems Consortium, Inc.
27 * Redwood City, CA 94063
29 * https://www.isc.org/
33 #include <sys/cdefs.h>
34 __RCSID("$NetBSD: inet.c,v 1.1.1.2 2014/07/12 11:57:44 spz Exp $");
38 /* Return just the network number of an internet address... */
40 struct iaddr
subnet_number (addr
, mask
)
47 if (addr
.len
> sizeof(addr
.iabuf
))
48 log_fatal("subnet_number():%s:%d: Invalid addr length.", MDL
);
49 if (addr
.len
!= mask
.len
)
50 log_fatal("subnet_number():%s:%d: Addr/mask length mismatch.",
55 /* Both addresses must have the same length... */
56 if (addr
.len
!= mask
.len
)
60 for (i
= 0; i
< rv
.len
; i
++)
61 rv
.iabuf
[i
] = addr
.iabuf
[i
] & mask
.iabuf
[i
];
65 /* Combine a network number and a integer to produce an internet address.
66 This won't work for subnets with more than 32 bits of host address, but
67 maybe this isn't a problem. */
69 struct iaddr
ip_addr (subnet
, mask
, host_address
)
72 u_int32_t host_address
;
77 unsigned char habuf
[sizeof swaddr
];
79 if (subnet
.len
> sizeof(subnet
.iabuf
))
80 log_fatal("ip_addr():%s:%d: Invalid addr length.", MDL
);
81 if (subnet
.len
!= mask
.len
)
82 log_fatal("ip_addr():%s:%d: Addr/mask length mismatch.",
85 swaddr
= htonl (host_address
);
86 memcpy (habuf
, &swaddr
, sizeof swaddr
);
88 /* Combine the subnet address and the host address. If
89 the host address is bigger than can fit in the subnet,
90 return a zero-length iaddr structure. */
92 j
= rv
.len
- sizeof habuf
;
93 for (i
= sizeof habuf
- 1; i
>= 0; i
--) {
94 if (mask
.iabuf
[i
+ j
]) {
95 if (habuf
[i
] > (mask
.iabuf
[i
+ j
] ^ 0xFF)) {
99 for (k
= i
- 1; k
>= 0; k
--) {
105 rv
.iabuf
[i
+ j
] |= habuf
[i
];
108 rv
.iabuf
[i
+ j
] = habuf
[i
];
114 /* Given a subnet number and netmask, return the address on that subnet
115 for which the host portion of the address is all ones (the standard
116 broadcast address). */
118 struct iaddr
broadcast_addr (subnet
, mask
)
125 if (subnet
.len
> sizeof(subnet
.iabuf
))
126 log_fatal("broadcast_addr():%s:%d: Invalid addr length.", MDL
);
127 if (subnet
.len
!= mask
.len
)
128 log_fatal("broadcast_addr():%s:%d: Addr/mask length mismatch.",
131 if (subnet
.len
!= mask
.len
) {
136 for (i
= 0; i
< subnet
.len
; i
++) {
137 rv
.iabuf
[i
] = subnet
.iabuf
[i
] | (~mask
.iabuf
[i
] & 255);
144 u_int32_t
host_addr (addr
, mask
)
152 if (addr
.len
> sizeof(addr
.iabuf
))
153 log_fatal("host_addr():%s:%d: Invalid addr length.", MDL
);
154 if (addr
.len
!= mask
.len
)
155 log_fatal("host_addr():%s:%d: Addr/mask length mismatch.",
160 /* Mask out the network bits... */
162 for (i
= 0; i
< rv
.len
; i
++)
163 rv
.iabuf
[i
] = addr
.iabuf
[i
] & ~mask
.iabuf
[i
];
165 /* Copy out up to 32 bits... */
166 memcpy (&swaddr
, &rv
.iabuf
[rv
.len
- sizeof swaddr
], sizeof swaddr
);
168 /* Swap it and return it. */
169 return ntohl (swaddr
);
172 int addr_eq (addr1
, addr2
)
173 struct iaddr addr1
, addr2
;
175 if (addr1
.len
> sizeof(addr1
.iabuf
))
176 log_fatal("addr_eq():%s:%d: Invalid addr length.", MDL
);
178 if (addr1
.len
!= addr2
.len
)
180 return memcmp (addr1
.iabuf
, addr2
.iabuf
, addr1
.len
) == 0;
185 * compares an IP address against a network/mask combination
186 * by ANDing the IP with the mask and seeing whether the result
187 * matches the masked network value.
190 addr_match(addr
, match
)
192 struct iaddrmatch
*match
;
196 if (addr
->len
!= match
->addr
.len
)
199 for (i
= 0 ; i
< addr
->len
; i
++) {
200 if ((addr
->iabuf
[i
] & match
->mask
.iabuf
[i
]) !=
201 match
->addr
.iabuf
[i
])
208 * Compares the addresses a1 and a2.
210 * If a1 < a2, returns -1.
211 * If a1 == a2, returns 0.
212 * If a1 > a2, returns 1.
214 * WARNING: if a1 and a2 differ in length, returns 0.
217 addr_cmp(const struct iaddr
*a1
, const struct iaddr
*a2
) {
220 if (a1
->len
!= a2
->len
) {
224 for (i
=0; i
<a1
->len
; i
++) {
225 if (a1
->iabuf
[i
] < a2
->iabuf
[i
]) {
228 if (a1
->iabuf
[i
] > a2
->iabuf
[i
]) {
237 * Performs a bitwise-OR of two addresses.
239 * Returns 1 if the result is non-zero, or 0 otherwise.
241 * WARNING: if a1 and a2 differ in length, returns 0.
244 addr_or(struct iaddr
*result
, const struct iaddr
*a1
, const struct iaddr
*a2
) {
248 if (a1
->len
!= a2
->len
) {
254 result
->len
= a1
->len
;
255 for (i
=0; i
<a1
->len
; i
++) {
256 result
->iabuf
[i
] = a1
->iabuf
[i
] | a2
->iabuf
[i
];
257 if (result
->iabuf
[i
] != 0) {
266 * Performs a bitwise-AND of two addresses.
268 * Returns 1 if the result is non-zero, or 0 otherwise.
270 * WARNING: if a1 and a2 differ in length, returns 0.
273 addr_and(struct iaddr
*result
, const struct iaddr
*a1
, const struct iaddr
*a2
) {
277 if (a1
->len
!= a2
->len
) {
283 result
->len
= a1
->len
;
284 for (i
=0; i
<a1
->len
; i
++) {
285 result
->iabuf
[i
] = a1
->iabuf
[i
] & a2
->iabuf
[i
];
286 if (result
->iabuf
[i
] != 0) {
295 * Check if a bitmask of the given length is valid for the address.
296 * This is not the case if any bits longer than the bitmask are 1.
306 * Because the final ".1" would get masked out by the /8.
309 is_cidr_mask_valid(const struct iaddr
*addr
, int bits
) {
317 * Check our bit boundaries.
322 if (bits
> (addr
->len
* 8)) {
327 * Figure out how many low-order bits need to be zero.
329 zero_bits
= (addr
->len
* 8) - bits
;
330 zero_bytes
= zero_bits
/ 8;
333 * Check to make sure the low-order bytes are zero.
335 for (i
=1; i
<=zero_bytes
; i
++) {
336 if (addr
->iabuf
[addr
->len
-i
] != 0) {
342 * Look to see if any bits not in right-hand bytes are
343 * non-zero, by making a byte that has these bits set to zero
344 * comparing to the original byte. If these two values are
345 * equal, then the right-hand bits are zero, and we are
348 shift_bits
= zero_bits
% 8;
349 if (shift_bits
== 0) return ISC_TRUE
;
350 byte
= addr
->iabuf
[addr
->len
-zero_bytes
-1];
351 return (((byte
>> shift_bits
) << shift_bits
) == byte
);
357 * Converts a range of IP addresses to a set of CIDR networks.
360 * 192.168.0.0 - 192.168.0.255 = 192.168.0.0/24
361 * 10.0.0.0 - 10.0.1.127 = 10.0.0.0/24, 10.0.1.0/25
362 * 255.255.255.32 - 255.255.255.255 = 255.255.255.32/27, 255.255.255.64/26,
366 range2cidr(struct iaddrcidrnetlist
**result
,
367 const struct iaddr
*lo
, const struct iaddr
*hi
) {
371 struct iaddr end_addr
;
374 struct iaddrcidrnetlist
*net
;
377 if (result
== NULL
) {
378 return DHCP_R_INVALIDARG
;
380 if (*result
!= NULL
) {
381 return DHCP_R_INVALIDARG
;
383 if ((lo
== NULL
) || (hi
== NULL
) || (lo
->len
!= hi
->len
)) {
384 return DHCP_R_INVALIDARG
;
388 * Put our start and end in the right order, if reversed.
390 if (addr_cmp(lo
, hi
) > 0) {
391 const struct iaddr
*tmp
;
398 * Theory of operation:
400 * -------------------
401 * Start at the low end, and keep trying larger networks
402 * until we get one that is too big (explained below).
404 * We keep a "mask", which is the ones-complement of a
405 * normal netmask. So, a /23 has a netmask of 255.255.254.0,
406 * and a mask of 0.0.1.255.
408 * We know when a network is too big when we bitwise-AND the
409 * mask with the starting address and we get a non-zero
412 * addr: 192.168.1.0, mask: 0.0.1.255
413 * bitwise-AND: 0.0.1.0
415 * A network is also too big if the bitwise-OR of the mask
416 * with the starting address is larger than the end address,
419 * start: 192.168.1.0, mask: 0.0.1.255, end: 192.168.0.255
420 * bitwise-OR: 192.168.1.255
422 * -------------------
423 * Once we have found a network that is too big, we add the
424 * appropriate CIDR network to our list of found networks.
426 * We then use the next IP address as our low address, and
427 * begin the process of searching for a network that is
428 * too big again, starting with an empty mask.
432 memset(&mask
, 0, sizeof(mask
));
434 while (addr_cmp(&addr
, hi
) <= 0) {
436 * Bitwise-OR mask with (1 << bit)
438 ofs
= addr
.len
- (bit
/ 8) - 1;
439 val
= 1 << (bit
% 8);
441 mask
.iabuf
[ofs
] |= val
;
445 * See if we're too big, and save this network if so.
447 addr_or(&end_addr
, &addr
, &mask
);
449 (addr_cmp(&end_addr
, hi
) > 0) ||
450 addr_and(&dummy
, &addr
, &mask
)) {
452 * Add a new prefix to our list.
454 net
= dmalloc(sizeof(*net
), MDL
);
456 while (*result
!= NULL
) {
457 net
= (*result
)->next
;
461 return ISC_R_NOMEMORY
;
463 net
->cidrnet
.lo_addr
= addr
;
464 net
->cidrnet
.bits
= (addr
.len
* 8) - bit
;
469 * Figure out our new starting address,
470 * by adding (1 << bit) to our previous
473 tmp
= addr
.iabuf
[ofs
] + val
;
474 while ((ofs
>= 0) && (tmp
> 255)) {
475 addr
.iabuf
[ofs
] = tmp
- 256;
477 tmp
= addr
.iabuf
[ofs
] + 1;
480 /* Gone past last address, we're done. */
483 addr
.iabuf
[ofs
] = tmp
;
486 * Reset our bit and mask.
489 memset(mask
.iabuf
, 0, sizeof(mask
.iabuf
));
490 memset(end_addr
.iabuf
, 0, sizeof(end_addr
.iabuf
));
493 * If we're not too big, increase our network size.
502 return ISC_R_SUCCESS
;
506 * Free a list of CIDR networks, such as returned from range2cidr().
509 free_iaddrcidrnetlist(struct iaddrcidrnetlist
**result
) {
510 struct iaddrcidrnetlist
*p
;
512 if (result
== NULL
) {
513 return DHCP_R_INVALIDARG
;
515 if (*result
== NULL
) {
516 return DHCP_R_INVALIDARG
;
519 while (*result
!= NULL
) {
525 return ISC_R_SUCCESS
;
528 /* piaddr() turns an iaddr structure into a printable address. */
529 /* XXX: should use a const pointer rather than passing the structure */
531 piaddr(const struct iaddr addr
) {
533 pbuf
[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
534 /* "255.255.255.255" */
536 /* INSIST((addr.len == 0) || (addr.len == 4) || (addr.len == 16)); */
539 return "<null address>";
542 return inet_ntop(AF_INET
, addr
.iabuf
, pbuf
, sizeof(pbuf
));
544 if (addr
.len
== 16) {
545 return inet_ntop(AF_INET6
, addr
.iabuf
, pbuf
, sizeof(pbuf
));
548 log_fatal("piaddr():%s:%d: Invalid address length %d.", MDL
,
550 /* quell compiler warnings */
554 /* piaddrmask takes an iaddr structure mask, determines the bitlength of
555 * the mask, and then returns the printable CIDR notation of the two.
558 piaddrmask(struct iaddr
*addr
, struct iaddr
*mask
) {
560 unsigned int oct
, bit
;
562 if ((addr
->len
!= 4) && (addr
->len
!= 16))
563 log_fatal("piaddrmask():%s:%d: Address length %d invalid",
565 if (addr
->len
!= mask
->len
)
566 log_fatal("piaddrmask():%s:%d: Address and mask size mismatch",
569 /* Determine netmask width in bits. */
570 for (mw
= (mask
->len
* 8) ; mw
> 0 ; ) {
572 bit
= 0x80 >> ((mw
- 1) % 8);
573 if (!mask
->iabuf
[oct
])
575 else if (mask
->iabuf
[oct
] & bit
)
582 log_fatal("Impossible condition at %s:%d.", MDL
);
584 return piaddrcidr(addr
, mw
);
587 /* Format an address and mask-length into printable CIDR notation. */
589 piaddrcidr(const struct iaddr
*addr
, unsigned int bits
) {
591 ret
[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255/128")];
592 /* "255.255.255.255/32" */
594 /* INSIST(addr != NULL); */
595 /* INSIST((addr->len == 4) || (addr->len == 16)); */
596 /* INSIST(bits <= (addr->len * 8)); */
598 if (bits
> (addr
->len
* 8))
601 sprintf(ret
, "%s/%d", piaddr(*addr
), bits
);
606 /* Validate that the string represents a valid port number and
607 * return it in network byte order
611 validate_port(char *port
) {
618 local_port
= strtol(port
, &endptr
, 10);
620 if ((*endptr
!= '\0') || (errno
== ERANGE
) || (errno
== EINVAL
))
621 log_fatal ("Invalid port number specification: %s", port
);
623 if (local_port
< lower
|| local_port
> upper
)
624 log_fatal("Port number specified is out of range (%ld-%ld).",
627 return htons((u_int16_t
)local_port
);