xref: /openbsd-src/usr.sbin/dhcpd/inet.c (revision 837cddff4b95f9432151663c8b92d709c11482aa)
1*837cddffSkrw /*	$OpenBSD: inet.c,v 1.6 2016/02/06 23:50:10 krw Exp $	*/
2e853bc5dShenning 
3c824f21bShenning /*
4c824f21bShenning  * Subroutines to manipulate internet addresses in a safely portable
5c824f21bShenning  * way...
6c824f21bShenning  */
7e853bc5dShenning 
8e853bc5dShenning /*
9e853bc5dShenning  * Copyright (c) 1996 The Internet Software Consortium.  All rights reserved.
10e853bc5dShenning  *
11e853bc5dShenning  * Redistribution and use in source and binary forms, with or without
12e853bc5dShenning  * modification, are permitted provided that the following conditions
13e853bc5dShenning  * are met:
14e853bc5dShenning  *
15e853bc5dShenning  * 1. Redistributions of source code must retain the above copyright
16e853bc5dShenning  *    notice, this list of conditions and the following disclaimer.
17e853bc5dShenning  * 2. Redistributions in binary form must reproduce the above copyright
18e853bc5dShenning  *    notice, this list of conditions and the following disclaimer in the
19e853bc5dShenning  *    documentation and/or other materials provided with the distribution.
20e853bc5dShenning  * 3. Neither the name of The Internet Software Consortium nor the names
21e853bc5dShenning  *    of its contributors may be used to endorse or promote products derived
22e853bc5dShenning  *    from this software without specific prior written permission.
23e853bc5dShenning  *
24e853bc5dShenning  * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
25e853bc5dShenning  * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
26e853bc5dShenning  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
27e853bc5dShenning  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28e853bc5dShenning  * DISCLAIMED.  IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
29e853bc5dShenning  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30e853bc5dShenning  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31e853bc5dShenning  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
32e853bc5dShenning  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
33e853bc5dShenning  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
34e853bc5dShenning  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
35e853bc5dShenning  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36e853bc5dShenning  * SUCH DAMAGE.
37e853bc5dShenning  *
38e853bc5dShenning  * This software has been written for the Internet Software Consortium
39e853bc5dShenning  * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
40e853bc5dShenning  * Enterprises.  To learn more about the Internet Software Consortium,
41e853bc5dShenning  * see ``http://www.vix.com/isc''.  To learn more about Vixie
42e853bc5dShenning  * Enterprises, see ``http://www.vix.com''.
43e853bc5dShenning  */
44e853bc5dShenning 
45*837cddffSkrw #include <sys/types.h>
46*837cddffSkrw #include <sys/socket.h>
47*837cddffSkrw 
48*837cddffSkrw #include <arpa/inet.h>
49*837cddffSkrw 
50*837cddffSkrw #include <net/if.h>
51*837cddffSkrw 
52*837cddffSkrw #include <netinet/in.h>
53*837cddffSkrw 
54*837cddffSkrw #include <stdio.h>
55*837cddffSkrw #include <string.h>
56*837cddffSkrw 
57*837cddffSkrw #include "dhcp.h"
58*837cddffSkrw #include "tree.h"
59e853bc5dShenning #include "dhcpd.h"
60e853bc5dShenning 
61c824f21bShenning /*
62c824f21bShenning  * Return just the network number of an internet address...
63c824f21bShenning  */
64c824f21bShenning struct iaddr
subnet_number(struct iaddr addr,struct iaddr mask)65c824f21bShenning subnet_number(struct iaddr addr, struct iaddr mask)
66e853bc5dShenning {
67e853bc5dShenning 	struct iaddr rv;
68c824f21bShenning 	int i;
69e853bc5dShenning 
70e853bc5dShenning 	rv.len = 0;
71e853bc5dShenning 
72e853bc5dShenning 	/* Both addresses must have the same length... */
73e853bc5dShenning 	if (addr.len != mask.len)
74c824f21bShenning 		return (rv);
75e853bc5dShenning 
76e853bc5dShenning 	rv.len = addr.len;
77e853bc5dShenning 	for (i = 0; i < rv.len; i++)
78e853bc5dShenning 		rv.iabuf[i] = addr.iabuf[i] & mask.iabuf[i];
79c824f21bShenning 	return (rv);
80e853bc5dShenning }
81e853bc5dShenning 
82c824f21bShenning /*
83c824f21bShenning  * Combine a network number and a integer to produce an internet address.
84e853bc5dShenning  * This won't work for subnets with more than 32 bits of host address, but
85e853bc5dShenning  * maybe this isn't a problem.
86e853bc5dShenning  */
87c824f21bShenning struct iaddr
ip_addr(struct iaddr subnet,struct iaddr mask,u_int32_t host_address)88c824f21bShenning ip_addr(struct iaddr subnet, struct iaddr mask, u_int32_t host_address)
89e853bc5dShenning {
90e853bc5dShenning 	int i, j, k;
91e853bc5dShenning 	u_int32_t swaddr;
92c824f21bShenning 	unsigned char habuf[sizeof(swaddr)];
93e853bc5dShenning 	struct iaddr rv;
94e853bc5dShenning 
95e853bc5dShenning 	swaddr = htonl(host_address);
96c824f21bShenning 	memcpy(habuf, &swaddr, sizeof(swaddr));
97e853bc5dShenning 
98c824f21bShenning 	/*
99c824f21bShenning 	 * Combine the subnet address and the host address.   If the
100c824f21bShenning 	 * host address is bigger than can fit in the subnet, return a
101c824f21bShenning 	 * zero-length iaddr structure.
102c824f21bShenning 	 */
103e853bc5dShenning 	rv = subnet;
104c824f21bShenning 	j = rv.len - sizeof(habuf);
105c824f21bShenning 	for (i = sizeof(habuf) - 1; i >= 0; i--) {
106e853bc5dShenning 		if (mask.iabuf[i + j]) {
107e853bc5dShenning 			if (habuf[i] > (mask.iabuf[i + j] ^ 0xFF)) {
108e853bc5dShenning 				rv.len = 0;
109c824f21bShenning 				return (rv);
110e853bc5dShenning 			}
111c824f21bShenning 			for (k = i - 1; k >= 0; k--)
112e853bc5dShenning 				if (habuf[k]) {
113e853bc5dShenning 					rv.len = 0;
114c824f21bShenning 					return (rv);
115e853bc5dShenning 				}
116e853bc5dShenning 			rv.iabuf[i + j] |= habuf[i];
117e853bc5dShenning 			break;
118e853bc5dShenning 		} else
119e853bc5dShenning 			rv.iabuf[i + j] = habuf[i];
120e853bc5dShenning 	}
121e853bc5dShenning 
122c824f21bShenning 	return (rv);
123e853bc5dShenning }
124e853bc5dShenning 
125c824f21bShenning u_int32_t
host_addr(struct iaddr addr,struct iaddr mask)126c824f21bShenning host_addr(struct iaddr addr, struct iaddr mask)
127e853bc5dShenning {
128e853bc5dShenning 	int i;
129e853bc5dShenning 	u_int32_t swaddr;
130e853bc5dShenning 	struct iaddr rv;
131e853bc5dShenning 
132e853bc5dShenning 	rv.len = 0;
133e853bc5dShenning 
134e853bc5dShenning 	/* Mask out the network bits... */
135e853bc5dShenning 	rv.len = addr.len;
136e853bc5dShenning 	for (i = 0; i < rv.len; i++)
137e853bc5dShenning 		rv.iabuf[i] = addr.iabuf[i] & ~mask.iabuf[i];
138e853bc5dShenning 
139e853bc5dShenning 	/* Copy out up to 32 bits... */
140c824f21bShenning 	memcpy(&swaddr, &rv.iabuf[rv.len - sizeof(swaddr)], sizeof(swaddr));
141e853bc5dShenning 
142e853bc5dShenning 	/* Swap it and return it. */
143c824f21bShenning 	return (ntohl(swaddr));
144e853bc5dShenning }
145e853bc5dShenning 
146c824f21bShenning int
addr_eq(struct iaddr addr1,struct iaddr addr2)147c824f21bShenning addr_eq(struct iaddr addr1, struct iaddr addr2)
148e853bc5dShenning {
149e853bc5dShenning 	if (addr1.len != addr2.len)
150c824f21bShenning 		return (0);
151c824f21bShenning 	return (memcmp(addr1.iabuf, addr2.iabuf, addr1.len) == 0);
152e853bc5dShenning }
153e853bc5dShenning 
154ea507cabSderaadt char *
piaddr(struct iaddr addr)155ea507cabSderaadt piaddr(struct iaddr addr)
156e853bc5dShenning {
157e853bc5dShenning 	static char pbuf[32];
158a53ae031Sclaudio 	const char *s;
159e853bc5dShenning 
160c824f21bShenning 	if (addr.len == 0)
161e853bc5dShenning 		strlcpy(pbuf, "<null address>", sizeof(pbuf));
162e853bc5dShenning 	else {
163a53ae031Sclaudio 		s = inet_ntop(AF_INET, &addr.iabuf, pbuf, sizeof pbuf);
164a53ae031Sclaudio 		if (s == NULL)
165e853bc5dShenning 			strlcpy(pbuf, "<invalid address>", sizeof(pbuf));
166e853bc5dShenning 	}
167e853bc5dShenning 	return (pbuf);
168e853bc5dShenning }
169