xref: /minix3/external/bsd/dhcp/dist/common/inet.c (revision 83ee113ee0d94f3844d44065af2311604e9a30ad)
1*83ee113eSDavid van Moolenbroek /*	$NetBSD: inet.c,v 1.1.1.2 2014/07/12 11:57:44 spz Exp $	*/
2*83ee113eSDavid van Moolenbroek /* inet.c
3*83ee113eSDavid van Moolenbroek 
4*83ee113eSDavid van Moolenbroek    Subroutines to manipulate internet addresses and ports in a safely portable
5*83ee113eSDavid van Moolenbroek    way... */
6*83ee113eSDavid van Moolenbroek 
7*83ee113eSDavid van Moolenbroek /*
8*83ee113eSDavid van Moolenbroek  * Copyright (c) 2011,2013,2014 by Internet Systems Consortium, Inc. ("ISC")
9*83ee113eSDavid van Moolenbroek  * Copyright (c) 2007-2009 by Internet Systems Consortium, Inc. ("ISC")
10*83ee113eSDavid van Moolenbroek  * Copyright (c) 2004,2005 by Internet Systems Consortium, Inc. ("ISC")
11*83ee113eSDavid van Moolenbroek  * Copyright (c) 1995-2003 by Internet Software Consortium
12*83ee113eSDavid van Moolenbroek  *
13*83ee113eSDavid van Moolenbroek  * Permission to use, copy, modify, and distribute this software for any
14*83ee113eSDavid van Moolenbroek  * purpose with or without fee is hereby granted, provided that the above
15*83ee113eSDavid van Moolenbroek  * copyright notice and this permission notice appear in all copies.
16*83ee113eSDavid van Moolenbroek  *
17*83ee113eSDavid van Moolenbroek  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
18*83ee113eSDavid van Moolenbroek  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
19*83ee113eSDavid van Moolenbroek  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
20*83ee113eSDavid van Moolenbroek  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
21*83ee113eSDavid van Moolenbroek  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
22*83ee113eSDavid van Moolenbroek  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
23*83ee113eSDavid van Moolenbroek  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
24*83ee113eSDavid van Moolenbroek  *
25*83ee113eSDavid van Moolenbroek  *   Internet Systems Consortium, Inc.
26*83ee113eSDavid van Moolenbroek  *   950 Charter Street
27*83ee113eSDavid van Moolenbroek  *   Redwood City, CA 94063
28*83ee113eSDavid van Moolenbroek  *   <info@isc.org>
29*83ee113eSDavid van Moolenbroek  *   https://www.isc.org/
30*83ee113eSDavid van Moolenbroek  *
31*83ee113eSDavid van Moolenbroek  */
32*83ee113eSDavid van Moolenbroek 
33*83ee113eSDavid van Moolenbroek #include <sys/cdefs.h>
34*83ee113eSDavid van Moolenbroek __RCSID("$NetBSD: inet.c,v 1.1.1.2 2014/07/12 11:57:44 spz Exp $");
35*83ee113eSDavid van Moolenbroek 
36*83ee113eSDavid van Moolenbroek #include "dhcpd.h"
37*83ee113eSDavid van Moolenbroek 
38*83ee113eSDavid van Moolenbroek /* Return just the network number of an internet address... */
39*83ee113eSDavid van Moolenbroek 
subnet_number(addr,mask)40*83ee113eSDavid van Moolenbroek struct iaddr subnet_number (addr, mask)
41*83ee113eSDavid van Moolenbroek 	struct iaddr addr;
42*83ee113eSDavid van Moolenbroek 	struct iaddr mask;
43*83ee113eSDavid van Moolenbroek {
44*83ee113eSDavid van Moolenbroek 	int i;
45*83ee113eSDavid van Moolenbroek 	struct iaddr rv;
46*83ee113eSDavid van Moolenbroek 
47*83ee113eSDavid van Moolenbroek 	if (addr.len > sizeof(addr.iabuf))
48*83ee113eSDavid van Moolenbroek 		log_fatal("subnet_number():%s:%d: Invalid addr length.", MDL);
49*83ee113eSDavid van Moolenbroek 	if (addr.len != mask.len)
50*83ee113eSDavid van Moolenbroek 		log_fatal("subnet_number():%s:%d: Addr/mask length mismatch.",
51*83ee113eSDavid van Moolenbroek 			  MDL);
52*83ee113eSDavid van Moolenbroek 
53*83ee113eSDavid van Moolenbroek 	rv.len = 0;
54*83ee113eSDavid van Moolenbroek 
55*83ee113eSDavid van Moolenbroek 	/* Both addresses must have the same length... */
56*83ee113eSDavid van Moolenbroek 	if (addr.len != mask.len)
57*83ee113eSDavid van Moolenbroek 		return rv;
58*83ee113eSDavid van Moolenbroek 
59*83ee113eSDavid van Moolenbroek 	rv.len = addr.len;
60*83ee113eSDavid van Moolenbroek 	for (i = 0; i < rv.len; i++)
61*83ee113eSDavid van Moolenbroek 		rv.iabuf [i] = addr.iabuf [i] & mask.iabuf [i];
62*83ee113eSDavid van Moolenbroek 	return rv;
63*83ee113eSDavid van Moolenbroek }
64*83ee113eSDavid van Moolenbroek 
65*83ee113eSDavid van Moolenbroek /* Combine a network number and a integer to produce an internet address.
66*83ee113eSDavid van Moolenbroek    This won't work for subnets with more than 32 bits of host address, but
67*83ee113eSDavid van Moolenbroek    maybe this isn't a problem. */
68*83ee113eSDavid van Moolenbroek 
ip_addr(subnet,mask,host_address)69*83ee113eSDavid van Moolenbroek struct iaddr ip_addr (subnet, mask, host_address)
70*83ee113eSDavid van Moolenbroek 	struct iaddr subnet;
71*83ee113eSDavid van Moolenbroek 	struct iaddr mask;
72*83ee113eSDavid van Moolenbroek 	u_int32_t host_address;
73*83ee113eSDavid van Moolenbroek {
74*83ee113eSDavid van Moolenbroek 	int i, j, k;
75*83ee113eSDavid van Moolenbroek 	u_int32_t swaddr;
76*83ee113eSDavid van Moolenbroek 	struct iaddr rv;
77*83ee113eSDavid van Moolenbroek 	unsigned char habuf [sizeof swaddr];
78*83ee113eSDavid van Moolenbroek 
79*83ee113eSDavid van Moolenbroek 	if (subnet.len > sizeof(subnet.iabuf))
80*83ee113eSDavid van Moolenbroek 		log_fatal("ip_addr():%s:%d: Invalid addr length.", MDL);
81*83ee113eSDavid van Moolenbroek 	if (subnet.len != mask.len)
82*83ee113eSDavid van Moolenbroek 		log_fatal("ip_addr():%s:%d: Addr/mask length mismatch.",
83*83ee113eSDavid van Moolenbroek 			  MDL);
84*83ee113eSDavid van Moolenbroek 
85*83ee113eSDavid van Moolenbroek 	swaddr = htonl (host_address);
86*83ee113eSDavid van Moolenbroek 	memcpy (habuf, &swaddr, sizeof swaddr);
87*83ee113eSDavid van Moolenbroek 
88*83ee113eSDavid van Moolenbroek 	/* Combine the subnet address and the host address.   If
89*83ee113eSDavid van Moolenbroek 	   the host address is bigger than can fit in the subnet,
90*83ee113eSDavid van Moolenbroek 	   return a zero-length iaddr structure. */
91*83ee113eSDavid van Moolenbroek 	rv = subnet;
92*83ee113eSDavid van Moolenbroek 	j = rv.len - sizeof habuf;
93*83ee113eSDavid van Moolenbroek 	for (i = sizeof habuf - 1; i >= 0; i--) {
94*83ee113eSDavid van Moolenbroek 		if (mask.iabuf [i + j]) {
95*83ee113eSDavid van Moolenbroek 			if (habuf [i] > (mask.iabuf [i + j] ^ 0xFF)) {
96*83ee113eSDavid van Moolenbroek 				rv.len = 0;
97*83ee113eSDavid van Moolenbroek 				return rv;
98*83ee113eSDavid van Moolenbroek 			}
99*83ee113eSDavid van Moolenbroek 			for (k = i - 1; k >= 0; k--) {
100*83ee113eSDavid van Moolenbroek 				if (habuf [k]) {
101*83ee113eSDavid van Moolenbroek 					rv.len = 0;
102*83ee113eSDavid van Moolenbroek 					return rv;
103*83ee113eSDavid van Moolenbroek 				}
104*83ee113eSDavid van Moolenbroek 			}
105*83ee113eSDavid van Moolenbroek 			rv.iabuf [i + j] |= habuf [i];
106*83ee113eSDavid van Moolenbroek 			break;
107*83ee113eSDavid van Moolenbroek 		} else
108*83ee113eSDavid van Moolenbroek 			rv.iabuf [i + j] = habuf [i];
109*83ee113eSDavid van Moolenbroek 	}
110*83ee113eSDavid van Moolenbroek 
111*83ee113eSDavid van Moolenbroek 	return rv;
112*83ee113eSDavid van Moolenbroek }
113*83ee113eSDavid van Moolenbroek 
114*83ee113eSDavid van Moolenbroek /* Given a subnet number and netmask, return the address on that subnet
115*83ee113eSDavid van Moolenbroek    for which the host portion of the address is all ones (the standard
116*83ee113eSDavid van Moolenbroek    broadcast address). */
117*83ee113eSDavid van Moolenbroek 
broadcast_addr(subnet,mask)118*83ee113eSDavid van Moolenbroek struct iaddr broadcast_addr (subnet, mask)
119*83ee113eSDavid van Moolenbroek 	struct iaddr subnet;
120*83ee113eSDavid van Moolenbroek 	struct iaddr mask;
121*83ee113eSDavid van Moolenbroek {
122*83ee113eSDavid van Moolenbroek 	int i;
123*83ee113eSDavid van Moolenbroek 	struct iaddr rv;
124*83ee113eSDavid van Moolenbroek 
125*83ee113eSDavid van Moolenbroek 	if (subnet.len > sizeof(subnet.iabuf))
126*83ee113eSDavid van Moolenbroek 		log_fatal("broadcast_addr():%s:%d: Invalid addr length.", MDL);
127*83ee113eSDavid van Moolenbroek 	if (subnet.len != mask.len)
128*83ee113eSDavid van Moolenbroek 		log_fatal("broadcast_addr():%s:%d: Addr/mask length mismatch.",
129*83ee113eSDavid van Moolenbroek 			  MDL);
130*83ee113eSDavid van Moolenbroek 
131*83ee113eSDavid van Moolenbroek 	if (subnet.len != mask.len) {
132*83ee113eSDavid van Moolenbroek 		rv.len = 0;
133*83ee113eSDavid van Moolenbroek 		return rv;
134*83ee113eSDavid van Moolenbroek 	}
135*83ee113eSDavid van Moolenbroek 
136*83ee113eSDavid van Moolenbroek 	for (i = 0; i < subnet.len; i++) {
137*83ee113eSDavid van Moolenbroek 		rv.iabuf [i] = subnet.iabuf [i] | (~mask.iabuf [i] & 255);
138*83ee113eSDavid van Moolenbroek 	}
139*83ee113eSDavid van Moolenbroek 	rv.len = subnet.len;
140*83ee113eSDavid van Moolenbroek 
141*83ee113eSDavid van Moolenbroek 	return rv;
142*83ee113eSDavid van Moolenbroek }
143*83ee113eSDavid van Moolenbroek 
host_addr(addr,mask)144*83ee113eSDavid van Moolenbroek u_int32_t host_addr (addr, mask)
145*83ee113eSDavid van Moolenbroek 	struct iaddr addr;
146*83ee113eSDavid van Moolenbroek 	struct iaddr mask;
147*83ee113eSDavid van Moolenbroek {
148*83ee113eSDavid van Moolenbroek 	int i;
149*83ee113eSDavid van Moolenbroek 	u_int32_t swaddr;
150*83ee113eSDavid van Moolenbroek 	struct iaddr rv;
151*83ee113eSDavid van Moolenbroek 
152*83ee113eSDavid van Moolenbroek 	if (addr.len > sizeof(addr.iabuf))
153*83ee113eSDavid van Moolenbroek 		log_fatal("host_addr():%s:%d: Invalid addr length.", MDL);
154*83ee113eSDavid van Moolenbroek 	if (addr.len != mask.len)
155*83ee113eSDavid van Moolenbroek 		log_fatal("host_addr():%s:%d: Addr/mask length mismatch.",
156*83ee113eSDavid van Moolenbroek 			  MDL);
157*83ee113eSDavid van Moolenbroek 
158*83ee113eSDavid van Moolenbroek 	rv.len = 0;
159*83ee113eSDavid van Moolenbroek 
160*83ee113eSDavid van Moolenbroek 	/* Mask out the network bits... */
161*83ee113eSDavid van Moolenbroek 	rv.len = addr.len;
162*83ee113eSDavid van Moolenbroek 	for (i = 0; i < rv.len; i++)
163*83ee113eSDavid van Moolenbroek 		rv.iabuf [i] = addr.iabuf [i] & ~mask.iabuf [i];
164*83ee113eSDavid van Moolenbroek 
165*83ee113eSDavid van Moolenbroek 	/* Copy out up to 32 bits... */
166*83ee113eSDavid van Moolenbroek 	memcpy (&swaddr, &rv.iabuf [rv.len - sizeof swaddr], sizeof swaddr);
167*83ee113eSDavid van Moolenbroek 
168*83ee113eSDavid van Moolenbroek 	/* Swap it and return it. */
169*83ee113eSDavid van Moolenbroek 	return ntohl (swaddr);
170*83ee113eSDavid van Moolenbroek }
171*83ee113eSDavid van Moolenbroek 
addr_eq(addr1,addr2)172*83ee113eSDavid van Moolenbroek int addr_eq (addr1, addr2)
173*83ee113eSDavid van Moolenbroek 	struct iaddr addr1, addr2;
174*83ee113eSDavid van Moolenbroek {
175*83ee113eSDavid van Moolenbroek 	if (addr1.len > sizeof(addr1.iabuf))
176*83ee113eSDavid van Moolenbroek 		log_fatal("addr_eq():%s:%d: Invalid addr length.", MDL);
177*83ee113eSDavid van Moolenbroek 
178*83ee113eSDavid van Moolenbroek 	if (addr1.len != addr2.len)
179*83ee113eSDavid van Moolenbroek 		return 0;
180*83ee113eSDavid van Moolenbroek 	return memcmp (addr1.iabuf, addr2.iabuf, addr1.len) == 0;
181*83ee113eSDavid van Moolenbroek }
182*83ee113eSDavid van Moolenbroek 
183*83ee113eSDavid van Moolenbroek /* addr_match
184*83ee113eSDavid van Moolenbroek  *
185*83ee113eSDavid van Moolenbroek  * compares an IP address against a network/mask combination
186*83ee113eSDavid van Moolenbroek  * by ANDing the IP with the mask and seeing whether the result
187*83ee113eSDavid van Moolenbroek  * matches the masked network value.
188*83ee113eSDavid van Moolenbroek  */
189*83ee113eSDavid van Moolenbroek int
addr_match(addr,match)190*83ee113eSDavid van Moolenbroek addr_match(addr, match)
191*83ee113eSDavid van Moolenbroek 	struct iaddr *addr;
192*83ee113eSDavid van Moolenbroek 	struct iaddrmatch *match;
193*83ee113eSDavid van Moolenbroek {
194*83ee113eSDavid van Moolenbroek         int i;
195*83ee113eSDavid van Moolenbroek 
196*83ee113eSDavid van Moolenbroek 	if (addr->len != match->addr.len)
197*83ee113eSDavid van Moolenbroek 		return 0;
198*83ee113eSDavid van Moolenbroek 
199*83ee113eSDavid van Moolenbroek 	for (i = 0 ; i < addr->len ; i++) {
200*83ee113eSDavid van Moolenbroek 		if ((addr->iabuf[i] & match->mask.iabuf[i]) !=
201*83ee113eSDavid van Moolenbroek 							match->addr.iabuf[i])
202*83ee113eSDavid van Moolenbroek 			return 0;
203*83ee113eSDavid van Moolenbroek 	}
204*83ee113eSDavid van Moolenbroek 	return 1;
205*83ee113eSDavid van Moolenbroek }
206*83ee113eSDavid van Moolenbroek 
207*83ee113eSDavid van Moolenbroek /*
208*83ee113eSDavid van Moolenbroek  * Compares the addresses a1 and a2.
209*83ee113eSDavid van Moolenbroek  *
210*83ee113eSDavid van Moolenbroek  * If a1 < a2, returns -1.
211*83ee113eSDavid van Moolenbroek  * If a1 == a2, returns 0.
212*83ee113eSDavid van Moolenbroek  * If a1 > a2, returns 1.
213*83ee113eSDavid van Moolenbroek  *
214*83ee113eSDavid van Moolenbroek  * WARNING: if a1 and a2 differ in length, returns 0.
215*83ee113eSDavid van Moolenbroek  */
216*83ee113eSDavid van Moolenbroek int
addr_cmp(const struct iaddr * a1,const struct iaddr * a2)217*83ee113eSDavid van Moolenbroek addr_cmp(const struct iaddr *a1, const struct iaddr *a2) {
218*83ee113eSDavid van Moolenbroek 	int i;
219*83ee113eSDavid van Moolenbroek 
220*83ee113eSDavid van Moolenbroek 	if (a1->len != a2->len) {
221*83ee113eSDavid van Moolenbroek 		return 0;
222*83ee113eSDavid van Moolenbroek 	}
223*83ee113eSDavid van Moolenbroek 
224*83ee113eSDavid van Moolenbroek 	for (i=0; i<a1->len; i++) {
225*83ee113eSDavid van Moolenbroek 		if (a1->iabuf[i] < a2->iabuf[i]) {
226*83ee113eSDavid van Moolenbroek 			return -1;
227*83ee113eSDavid van Moolenbroek 		}
228*83ee113eSDavid van Moolenbroek 		if (a1->iabuf[i] > a2->iabuf[i]) {
229*83ee113eSDavid van Moolenbroek 			return 1;
230*83ee113eSDavid van Moolenbroek 		}
231*83ee113eSDavid van Moolenbroek 	}
232*83ee113eSDavid van Moolenbroek 
233*83ee113eSDavid van Moolenbroek 	return 0;
234*83ee113eSDavid van Moolenbroek }
235*83ee113eSDavid van Moolenbroek 
236*83ee113eSDavid van Moolenbroek /*
237*83ee113eSDavid van Moolenbroek  * Performs a bitwise-OR of two addresses.
238*83ee113eSDavid van Moolenbroek  *
239*83ee113eSDavid van Moolenbroek  * Returns 1 if the result is non-zero, or 0 otherwise.
240*83ee113eSDavid van Moolenbroek  *
241*83ee113eSDavid van Moolenbroek  * WARNING: if a1 and a2 differ in length, returns 0.
242*83ee113eSDavid van Moolenbroek  */
243*83ee113eSDavid van Moolenbroek int
addr_or(struct iaddr * result,const struct iaddr * a1,const struct iaddr * a2)244*83ee113eSDavid van Moolenbroek addr_or(struct iaddr *result, const struct iaddr *a1, const struct iaddr *a2) {
245*83ee113eSDavid van Moolenbroek 	int i;
246*83ee113eSDavid van Moolenbroek 	int all_zero;
247*83ee113eSDavid van Moolenbroek 
248*83ee113eSDavid van Moolenbroek 	if (a1->len != a2->len) {
249*83ee113eSDavid van Moolenbroek 		return 0;
250*83ee113eSDavid van Moolenbroek 	}
251*83ee113eSDavid van Moolenbroek 
252*83ee113eSDavid van Moolenbroek 	all_zero = 1;
253*83ee113eSDavid van Moolenbroek 
254*83ee113eSDavid van Moolenbroek 	result->len = a1->len;
255*83ee113eSDavid van Moolenbroek 	for (i=0; i<a1->len; i++) {
256*83ee113eSDavid van Moolenbroek 		result->iabuf[i] = a1->iabuf[i] | a2->iabuf[i];
257*83ee113eSDavid van Moolenbroek 		if (result->iabuf[i] != 0) {
258*83ee113eSDavid van Moolenbroek 			all_zero = 0;
259*83ee113eSDavid van Moolenbroek 		}
260*83ee113eSDavid van Moolenbroek 	}
261*83ee113eSDavid van Moolenbroek 
262*83ee113eSDavid van Moolenbroek 	return !all_zero;
263*83ee113eSDavid van Moolenbroek }
264*83ee113eSDavid van Moolenbroek 
265*83ee113eSDavid van Moolenbroek /*
266*83ee113eSDavid van Moolenbroek  * Performs a bitwise-AND of two addresses.
267*83ee113eSDavid van Moolenbroek  *
268*83ee113eSDavid van Moolenbroek  * Returns 1 if the result is non-zero, or 0 otherwise.
269*83ee113eSDavid van Moolenbroek  *
270*83ee113eSDavid van Moolenbroek  * WARNING: if a1 and a2 differ in length, returns 0.
271*83ee113eSDavid van Moolenbroek  */
272*83ee113eSDavid van Moolenbroek int
addr_and(struct iaddr * result,const struct iaddr * a1,const struct iaddr * a2)273*83ee113eSDavid van Moolenbroek addr_and(struct iaddr *result, const struct iaddr *a1, const struct iaddr *a2) {
274*83ee113eSDavid van Moolenbroek 	int i;
275*83ee113eSDavid van Moolenbroek 	int all_zero;
276*83ee113eSDavid van Moolenbroek 
277*83ee113eSDavid van Moolenbroek 	if (a1->len != a2->len) {
278*83ee113eSDavid van Moolenbroek 		return 0;
279*83ee113eSDavid van Moolenbroek 	}
280*83ee113eSDavid van Moolenbroek 
281*83ee113eSDavid van Moolenbroek 	all_zero = 1;
282*83ee113eSDavid van Moolenbroek 
283*83ee113eSDavid van Moolenbroek 	result->len = a1->len;
284*83ee113eSDavid van Moolenbroek 	for (i=0; i<a1->len; i++) {
285*83ee113eSDavid van Moolenbroek 		result->iabuf[i] = a1->iabuf[i] & a2->iabuf[i];
286*83ee113eSDavid van Moolenbroek 		if (result->iabuf[i] != 0) {
287*83ee113eSDavid van Moolenbroek 			all_zero = 0;
288*83ee113eSDavid van Moolenbroek 		}
289*83ee113eSDavid van Moolenbroek 	}
290*83ee113eSDavid van Moolenbroek 
291*83ee113eSDavid van Moolenbroek 	return !all_zero;
292*83ee113eSDavid van Moolenbroek }
293*83ee113eSDavid van Moolenbroek 
294*83ee113eSDavid van Moolenbroek /*
295*83ee113eSDavid van Moolenbroek  * Check if a bitmask of the given length is valid for the address.
296*83ee113eSDavid van Moolenbroek  * This is not the case if any bits longer than the bitmask are 1.
297*83ee113eSDavid van Moolenbroek  *
298*83ee113eSDavid van Moolenbroek  * So, this is valid:
299*83ee113eSDavid van Moolenbroek  *
300*83ee113eSDavid van Moolenbroek  * 127.0.0.0/8
301*83ee113eSDavid van Moolenbroek  *
302*83ee113eSDavid van Moolenbroek  * But this is not:
303*83ee113eSDavid van Moolenbroek  *
304*83ee113eSDavid van Moolenbroek  * 127.0.0.1/8
305*83ee113eSDavid van Moolenbroek  *
306*83ee113eSDavid van Moolenbroek  * Because the final ".1" would get masked out by the /8.
307*83ee113eSDavid van Moolenbroek  */
308*83ee113eSDavid van Moolenbroek isc_boolean_t
is_cidr_mask_valid(const struct iaddr * addr,int bits)309*83ee113eSDavid van Moolenbroek is_cidr_mask_valid(const struct iaddr *addr, int bits) {
310*83ee113eSDavid van Moolenbroek 	int zero_bits;
311*83ee113eSDavid van Moolenbroek 	int zero_bytes;
312*83ee113eSDavid van Moolenbroek 	int i;
313*83ee113eSDavid van Moolenbroek 	char byte;
314*83ee113eSDavid van Moolenbroek 	int shift_bits;
315*83ee113eSDavid van Moolenbroek 
316*83ee113eSDavid van Moolenbroek 	/*
317*83ee113eSDavid van Moolenbroek 	 * Check our bit boundaries.
318*83ee113eSDavid van Moolenbroek 	 */
319*83ee113eSDavid van Moolenbroek 	if (bits < 0) {
320*83ee113eSDavid van Moolenbroek 		return ISC_FALSE;
321*83ee113eSDavid van Moolenbroek 	}
322*83ee113eSDavid van Moolenbroek 	if (bits > (addr->len * 8)) {
323*83ee113eSDavid van Moolenbroek 		return ISC_FALSE;
324*83ee113eSDavid van Moolenbroek 	}
325*83ee113eSDavid van Moolenbroek 
326*83ee113eSDavid van Moolenbroek 	/*
327*83ee113eSDavid van Moolenbroek 	 * Figure out how many low-order bits need to be zero.
328*83ee113eSDavid van Moolenbroek 	 */
329*83ee113eSDavid van Moolenbroek 	zero_bits = (addr->len * 8) - bits;
330*83ee113eSDavid van Moolenbroek 	zero_bytes = zero_bits / 8;
331*83ee113eSDavid van Moolenbroek 
332*83ee113eSDavid van Moolenbroek 	/*
333*83ee113eSDavid van Moolenbroek 	 * Check to make sure the low-order bytes are zero.
334*83ee113eSDavid van Moolenbroek 	 */
335*83ee113eSDavid van Moolenbroek 	for (i=1; i<=zero_bytes; i++) {
336*83ee113eSDavid van Moolenbroek 		if (addr->iabuf[addr->len-i] != 0) {
337*83ee113eSDavid van Moolenbroek 			return ISC_FALSE;
338*83ee113eSDavid van Moolenbroek 		}
339*83ee113eSDavid van Moolenbroek 	}
340*83ee113eSDavid van Moolenbroek 
341*83ee113eSDavid van Moolenbroek 	/*
342*83ee113eSDavid van Moolenbroek 	 * Look to see if any bits not in right-hand bytes are
343*83ee113eSDavid van Moolenbroek 	 * non-zero, by making a byte that has these bits set to zero
344*83ee113eSDavid van Moolenbroek 	 * comparing to the original byte. If these two values are
345*83ee113eSDavid van Moolenbroek 	 * equal, then the right-hand bits are zero, and we are
346*83ee113eSDavid van Moolenbroek 	 * happy.
347*83ee113eSDavid van Moolenbroek 	 */
348*83ee113eSDavid van Moolenbroek 	shift_bits = zero_bits % 8;
349*83ee113eSDavid van Moolenbroek 	if (shift_bits == 0) return ISC_TRUE;
350*83ee113eSDavid van Moolenbroek 	byte = addr->iabuf[addr->len-zero_bytes-1];
351*83ee113eSDavid van Moolenbroek 	return (((byte >> shift_bits) << shift_bits) == byte);
352*83ee113eSDavid van Moolenbroek }
353*83ee113eSDavid van Moolenbroek 
354*83ee113eSDavid van Moolenbroek /*
355*83ee113eSDavid van Moolenbroek  * range2cidr
356*83ee113eSDavid van Moolenbroek  *
357*83ee113eSDavid van Moolenbroek  * Converts a range of IP addresses to a set of CIDR networks.
358*83ee113eSDavid van Moolenbroek  *
359*83ee113eSDavid van Moolenbroek  * Examples:
360*83ee113eSDavid van Moolenbroek  *  192.168.0.0 - 192.168.0.255 = 192.168.0.0/24
361*83ee113eSDavid van Moolenbroek  *  10.0.0.0 - 10.0.1.127 = 10.0.0.0/24, 10.0.1.0/25
362*83ee113eSDavid van Moolenbroek  *  255.255.255.32 - 255.255.255.255 = 255.255.255.32/27, 255.255.255.64/26,
363*83ee113eSDavid van Moolenbroek  *  				       255.255.255.128/25
364*83ee113eSDavid van Moolenbroek  */
365*83ee113eSDavid van Moolenbroek isc_result_t
range2cidr(struct iaddrcidrnetlist ** result,const struct iaddr * lo,const struct iaddr * hi)366*83ee113eSDavid van Moolenbroek range2cidr(struct iaddrcidrnetlist **result,
367*83ee113eSDavid van Moolenbroek 	   const struct iaddr *lo, const struct iaddr *hi) {
368*83ee113eSDavid van Moolenbroek 	struct iaddr addr;
369*83ee113eSDavid van Moolenbroek 	struct iaddr mask;
370*83ee113eSDavid van Moolenbroek 	int bit;
371*83ee113eSDavid van Moolenbroek 	struct iaddr end_addr;
372*83ee113eSDavid van Moolenbroek 	struct iaddr dummy;
373*83ee113eSDavid van Moolenbroek 	int ofs, val;
374*83ee113eSDavid van Moolenbroek 	struct iaddrcidrnetlist *net;
375*83ee113eSDavid van Moolenbroek 	int tmp;
376*83ee113eSDavid van Moolenbroek 
377*83ee113eSDavid van Moolenbroek 	if (result == NULL) {
378*83ee113eSDavid van Moolenbroek 		return DHCP_R_INVALIDARG;
379*83ee113eSDavid van Moolenbroek 	}
380*83ee113eSDavid van Moolenbroek 	if (*result != NULL) {
381*83ee113eSDavid van Moolenbroek 		return DHCP_R_INVALIDARG;
382*83ee113eSDavid van Moolenbroek 	}
383*83ee113eSDavid van Moolenbroek 	if ((lo == NULL) || (hi == NULL) || (lo->len != hi->len)) {
384*83ee113eSDavid van Moolenbroek 		return DHCP_R_INVALIDARG;
385*83ee113eSDavid van Moolenbroek 	}
386*83ee113eSDavid van Moolenbroek 
387*83ee113eSDavid van Moolenbroek 	/*
388*83ee113eSDavid van Moolenbroek 	 * Put our start and end in the right order, if reversed.
389*83ee113eSDavid van Moolenbroek 	 */
390*83ee113eSDavid van Moolenbroek 	if (addr_cmp(lo, hi) > 0) {
391*83ee113eSDavid van Moolenbroek 		const struct iaddr *tmp;
392*83ee113eSDavid van Moolenbroek 		tmp = lo;
393*83ee113eSDavid van Moolenbroek 		lo = hi;
394*83ee113eSDavid van Moolenbroek 		hi = tmp;
395*83ee113eSDavid van Moolenbroek 	}
396*83ee113eSDavid van Moolenbroek 
397*83ee113eSDavid van Moolenbroek 	/*
398*83ee113eSDavid van Moolenbroek 	 * Theory of operation:
399*83ee113eSDavid van Moolenbroek 	 *
400*83ee113eSDavid van Moolenbroek 	 * -------------------
401*83ee113eSDavid van Moolenbroek 	 * Start at the low end, and keep trying larger networks
402*83ee113eSDavid van Moolenbroek 	 * until we get one that is too big (explained below).
403*83ee113eSDavid van Moolenbroek 	 *
404*83ee113eSDavid van Moolenbroek 	 * We keep a "mask", which is the ones-complement of a
405*83ee113eSDavid van Moolenbroek 	 * normal netmask. So, a /23 has a netmask of 255.255.254.0,
406*83ee113eSDavid van Moolenbroek 	 * and a mask of 0.0.1.255.
407*83ee113eSDavid van Moolenbroek 	 *
408*83ee113eSDavid van Moolenbroek 	 * We know when a network is too big when we bitwise-AND the
409*83ee113eSDavid van Moolenbroek 	 * mask with the starting address and we get a non-zero
410*83ee113eSDavid van Moolenbroek 	 * result, like this:
411*83ee113eSDavid van Moolenbroek 	 *
412*83ee113eSDavid van Moolenbroek 	 *    addr: 192.168.1.0, mask: 0.0.1.255
413*83ee113eSDavid van Moolenbroek 	 *    bitwise-AND: 0.0.1.0
414*83ee113eSDavid van Moolenbroek 	 *
415*83ee113eSDavid van Moolenbroek 	 * A network is also too big if the bitwise-OR of the mask
416*83ee113eSDavid van Moolenbroek 	 * with the starting address is larger than the end address,
417*83ee113eSDavid van Moolenbroek 	 * like this:
418*83ee113eSDavid van Moolenbroek 	 *
419*83ee113eSDavid van Moolenbroek 	 *    start: 192.168.1.0, mask: 0.0.1.255, end: 192.168.0.255
420*83ee113eSDavid van Moolenbroek 	 *    bitwise-OR: 192.168.1.255
421*83ee113eSDavid van Moolenbroek 	 *
422*83ee113eSDavid van Moolenbroek 	 * -------------------
423*83ee113eSDavid van Moolenbroek 	 * Once we have found a network that is too big, we add the
424*83ee113eSDavid van Moolenbroek 	 * appropriate CIDR network to our list of found networks.
425*83ee113eSDavid van Moolenbroek 	 *
426*83ee113eSDavid van Moolenbroek 	 * We then use the next IP address as our low address, and
427*83ee113eSDavid van Moolenbroek 	 * begin the process of searching for a network that is
428*83ee113eSDavid van Moolenbroek 	 * too big again, starting with an empty mask.
429*83ee113eSDavid van Moolenbroek 	 */
430*83ee113eSDavid van Moolenbroek 	addr = *lo;
431*83ee113eSDavid van Moolenbroek 	bit = 0;
432*83ee113eSDavid van Moolenbroek 	memset(&mask, 0, sizeof(mask));
433*83ee113eSDavid van Moolenbroek 	mask.len = addr.len;
434*83ee113eSDavid van Moolenbroek 	while (addr_cmp(&addr, hi) <= 0) {
435*83ee113eSDavid van Moolenbroek 		/*
436*83ee113eSDavid van Moolenbroek 		 * Bitwise-OR mask with (1 << bit)
437*83ee113eSDavid van Moolenbroek 		 */
438*83ee113eSDavid van Moolenbroek 		ofs = addr.len - (bit / 8) - 1;
439*83ee113eSDavid van Moolenbroek 		val = 1 << (bit % 8);
440*83ee113eSDavid van Moolenbroek 		if (ofs >= 0) {
441*83ee113eSDavid van Moolenbroek 			mask.iabuf[ofs] |= val;
442*83ee113eSDavid van Moolenbroek 		}
443*83ee113eSDavid van Moolenbroek 
444*83ee113eSDavid van Moolenbroek 		/*
445*83ee113eSDavid van Moolenbroek 		 * See if we're too big, and save this network if so.
446*83ee113eSDavid van Moolenbroek 		 */
447*83ee113eSDavid van Moolenbroek 		addr_or(&end_addr, &addr, &mask);
448*83ee113eSDavid van Moolenbroek 		if ((ofs < 0) ||
449*83ee113eSDavid van Moolenbroek 		    (addr_cmp(&end_addr, hi) > 0) ||
450*83ee113eSDavid van Moolenbroek 		    addr_and(&dummy, &addr, &mask)) {
451*83ee113eSDavid van Moolenbroek 		    	/*
452*83ee113eSDavid van Moolenbroek 			 * Add a new prefix to our list.
453*83ee113eSDavid van Moolenbroek 			 */
454*83ee113eSDavid van Moolenbroek 			net = dmalloc(sizeof(*net), MDL);
455*83ee113eSDavid van Moolenbroek 			if (net == NULL) {
456*83ee113eSDavid van Moolenbroek 				while (*result != NULL) {
457*83ee113eSDavid van Moolenbroek 					net = (*result)->next;
458*83ee113eSDavid van Moolenbroek 					dfree(*result, MDL);
459*83ee113eSDavid van Moolenbroek 					*result = net;
460*83ee113eSDavid van Moolenbroek 				}
461*83ee113eSDavid van Moolenbroek 				return ISC_R_NOMEMORY;
462*83ee113eSDavid van Moolenbroek 			}
463*83ee113eSDavid van Moolenbroek 			net->cidrnet.lo_addr = addr;
464*83ee113eSDavid van Moolenbroek 			net->cidrnet.bits = (addr.len * 8) - bit;
465*83ee113eSDavid van Moolenbroek 			net->next = *result;
466*83ee113eSDavid van Moolenbroek 			*result = net;
467*83ee113eSDavid van Moolenbroek 
468*83ee113eSDavid van Moolenbroek 		    	/*
469*83ee113eSDavid van Moolenbroek 			 * Figure out our new starting address,
470*83ee113eSDavid van Moolenbroek 			 * by adding (1 << bit) to our previous
471*83ee113eSDavid van Moolenbroek 			 * starting address.
472*83ee113eSDavid van Moolenbroek 			 */
473*83ee113eSDavid van Moolenbroek 			tmp = addr.iabuf[ofs] + val;
474*83ee113eSDavid van Moolenbroek 			while ((ofs >= 0) && (tmp > 255)) {
475*83ee113eSDavid van Moolenbroek 				addr.iabuf[ofs] = tmp - 256;
476*83ee113eSDavid van Moolenbroek 				ofs--;
477*83ee113eSDavid van Moolenbroek 				tmp = addr.iabuf[ofs] + 1;
478*83ee113eSDavid van Moolenbroek 			}
479*83ee113eSDavid van Moolenbroek 			if (ofs < 0) {
480*83ee113eSDavid van Moolenbroek 				/* Gone past last address, we're done. */
481*83ee113eSDavid van Moolenbroek 				break;
482*83ee113eSDavid van Moolenbroek 			}
483*83ee113eSDavid van Moolenbroek 			addr.iabuf[ofs] = tmp;
484*83ee113eSDavid van Moolenbroek 
485*83ee113eSDavid van Moolenbroek 			/*
486*83ee113eSDavid van Moolenbroek 			 * Reset our bit and mask.
487*83ee113eSDavid van Moolenbroek 			 */
488*83ee113eSDavid van Moolenbroek 		    	bit = 0;
489*83ee113eSDavid van Moolenbroek 			memset(mask.iabuf, 0, sizeof(mask.iabuf));
490*83ee113eSDavid van Moolenbroek 			memset(end_addr.iabuf, 0, sizeof(end_addr.iabuf));
491*83ee113eSDavid van Moolenbroek 		} else {
492*83ee113eSDavid van Moolenbroek 			/*
493*83ee113eSDavid van Moolenbroek 			 * If we're not too big, increase our network size.
494*83ee113eSDavid van Moolenbroek 			 */
495*83ee113eSDavid van Moolenbroek 			bit++;
496*83ee113eSDavid van Moolenbroek 		}
497*83ee113eSDavid van Moolenbroek 	}
498*83ee113eSDavid van Moolenbroek 
499*83ee113eSDavid van Moolenbroek 	/*
500*83ee113eSDavid van Moolenbroek 	 * We're done.
501*83ee113eSDavid van Moolenbroek 	 */
502*83ee113eSDavid van Moolenbroek 	return ISC_R_SUCCESS;
503*83ee113eSDavid van Moolenbroek }
504*83ee113eSDavid van Moolenbroek 
505*83ee113eSDavid van Moolenbroek /*
506*83ee113eSDavid van Moolenbroek  * Free a list of CIDR networks, such as returned from range2cidr().
507*83ee113eSDavid van Moolenbroek  */
508*83ee113eSDavid van Moolenbroek isc_result_t
free_iaddrcidrnetlist(struct iaddrcidrnetlist ** result)509*83ee113eSDavid van Moolenbroek free_iaddrcidrnetlist(struct iaddrcidrnetlist **result) {
510*83ee113eSDavid van Moolenbroek 	struct iaddrcidrnetlist *p;
511*83ee113eSDavid van Moolenbroek 
512*83ee113eSDavid van Moolenbroek 	if (result == NULL) {
513*83ee113eSDavid van Moolenbroek 		return DHCP_R_INVALIDARG;
514*83ee113eSDavid van Moolenbroek 	}
515*83ee113eSDavid van Moolenbroek 	if (*result == NULL) {
516*83ee113eSDavid van Moolenbroek 		return DHCP_R_INVALIDARG;
517*83ee113eSDavid van Moolenbroek 	}
518*83ee113eSDavid van Moolenbroek 
519*83ee113eSDavid van Moolenbroek 	while (*result != NULL) {
520*83ee113eSDavid van Moolenbroek 		p = *result;
521*83ee113eSDavid van Moolenbroek 		*result = p->next;
522*83ee113eSDavid van Moolenbroek 		dfree(p, MDL);
523*83ee113eSDavid van Moolenbroek 	}
524*83ee113eSDavid van Moolenbroek 
525*83ee113eSDavid van Moolenbroek 	return ISC_R_SUCCESS;
526*83ee113eSDavid van Moolenbroek }
527*83ee113eSDavid van Moolenbroek 
528*83ee113eSDavid van Moolenbroek /* piaddr() turns an iaddr structure into a printable address. */
529*83ee113eSDavid van Moolenbroek /* XXX: should use a const pointer rather than passing the structure */
530*83ee113eSDavid van Moolenbroek const char *
piaddr(const struct iaddr addr)531*83ee113eSDavid van Moolenbroek piaddr(const struct iaddr addr) {
532*83ee113eSDavid van Moolenbroek 	static char
533*83ee113eSDavid van Moolenbroek 		pbuf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
534*83ee113eSDavid van Moolenbroek 			 /* "255.255.255.255" */
535*83ee113eSDavid van Moolenbroek 
536*83ee113eSDavid van Moolenbroek 	/* INSIST((addr.len == 0) || (addr.len == 4) || (addr.len == 16)); */
537*83ee113eSDavid van Moolenbroek 
538*83ee113eSDavid van Moolenbroek 	if (addr.len == 0) {
539*83ee113eSDavid van Moolenbroek 		return "<null address>";
540*83ee113eSDavid van Moolenbroek 	}
541*83ee113eSDavid van Moolenbroek 	if (addr.len == 4) {
542*83ee113eSDavid van Moolenbroek 		return inet_ntop(AF_INET, addr.iabuf, pbuf, sizeof(pbuf));
543*83ee113eSDavid van Moolenbroek 	}
544*83ee113eSDavid van Moolenbroek 	if (addr.len == 16) {
545*83ee113eSDavid van Moolenbroek 		return inet_ntop(AF_INET6, addr.iabuf, pbuf, sizeof(pbuf));
546*83ee113eSDavid van Moolenbroek 	}
547*83ee113eSDavid van Moolenbroek 
548*83ee113eSDavid van Moolenbroek 	log_fatal("piaddr():%s:%d: Invalid address length %d.", MDL,
549*83ee113eSDavid van Moolenbroek 		  addr.len);
550*83ee113eSDavid van Moolenbroek 	/* quell compiler warnings */
551*83ee113eSDavid van Moolenbroek 	return NULL;
552*83ee113eSDavid van Moolenbroek }
553*83ee113eSDavid van Moolenbroek 
554*83ee113eSDavid van Moolenbroek /* piaddrmask takes an iaddr structure mask, determines the bitlength of
555*83ee113eSDavid van Moolenbroek  * the mask, and then returns the printable CIDR notation of the two.
556*83ee113eSDavid van Moolenbroek  */
557*83ee113eSDavid van Moolenbroek char *
piaddrmask(struct iaddr * addr,struct iaddr * mask)558*83ee113eSDavid van Moolenbroek piaddrmask(struct iaddr *addr, struct iaddr *mask) {
559*83ee113eSDavid van Moolenbroek 	int mw;
560*83ee113eSDavid van Moolenbroek 	unsigned int oct, bit;
561*83ee113eSDavid van Moolenbroek 
562*83ee113eSDavid van Moolenbroek 	if ((addr->len != 4) && (addr->len != 16))
563*83ee113eSDavid van Moolenbroek 		log_fatal("piaddrmask():%s:%d: Address length %d invalid",
564*83ee113eSDavid van Moolenbroek 			  MDL, addr->len);
565*83ee113eSDavid van Moolenbroek 	if (addr->len != mask->len)
566*83ee113eSDavid van Moolenbroek 		log_fatal("piaddrmask():%s:%d: Address and mask size mismatch",
567*83ee113eSDavid van Moolenbroek 			  MDL);
568*83ee113eSDavid van Moolenbroek 
569*83ee113eSDavid van Moolenbroek 	/* Determine netmask width in bits. */
570*83ee113eSDavid van Moolenbroek 	for (mw = (mask->len * 8) ; mw > 0 ; ) {
571*83ee113eSDavid van Moolenbroek 		oct = (mw - 1) / 8;
572*83ee113eSDavid van Moolenbroek 		bit = 0x80 >> ((mw - 1) % 8);
573*83ee113eSDavid van Moolenbroek 		if (!mask->iabuf[oct])
574*83ee113eSDavid van Moolenbroek 			mw -= 8;
575*83ee113eSDavid van Moolenbroek 		else if (mask->iabuf[oct] & bit)
576*83ee113eSDavid van Moolenbroek 			break;
577*83ee113eSDavid van Moolenbroek 		else
578*83ee113eSDavid van Moolenbroek 			mw--;
579*83ee113eSDavid van Moolenbroek 	}
580*83ee113eSDavid van Moolenbroek 
581*83ee113eSDavid van Moolenbroek 	if (mw < 0)
582*83ee113eSDavid van Moolenbroek 		log_fatal("Impossible condition at %s:%d.", MDL);
583*83ee113eSDavid van Moolenbroek 
584*83ee113eSDavid van Moolenbroek 	return piaddrcidr(addr, mw);
585*83ee113eSDavid van Moolenbroek }
586*83ee113eSDavid van Moolenbroek 
587*83ee113eSDavid van Moolenbroek /* Format an address and mask-length into printable CIDR notation. */
588*83ee113eSDavid van Moolenbroek char *
piaddrcidr(const struct iaddr * addr,unsigned int bits)589*83ee113eSDavid van Moolenbroek piaddrcidr(const struct iaddr *addr, unsigned int bits) {
590*83ee113eSDavid van Moolenbroek 	static char
591*83ee113eSDavid van Moolenbroek 	    ret[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255/128")];
592*83ee113eSDavid van Moolenbroek 		    /* "255.255.255.255/32" */
593*83ee113eSDavid van Moolenbroek 
594*83ee113eSDavid van Moolenbroek 	/* INSIST(addr != NULL); */
595*83ee113eSDavid van Moolenbroek 	/* INSIST((addr->len == 4) || (addr->len == 16)); */
596*83ee113eSDavid van Moolenbroek 	/* INSIST(bits <= (addr->len * 8)); */
597*83ee113eSDavid van Moolenbroek 
598*83ee113eSDavid van Moolenbroek 	if (bits > (addr->len * 8))
599*83ee113eSDavid van Moolenbroek 		return NULL;
600*83ee113eSDavid van Moolenbroek 
601*83ee113eSDavid van Moolenbroek 	sprintf(ret, "%s/%d", piaddr(*addr), bits);
602*83ee113eSDavid van Moolenbroek 
603*83ee113eSDavid van Moolenbroek 	return ret;
604*83ee113eSDavid van Moolenbroek }
605*83ee113eSDavid van Moolenbroek 
606*83ee113eSDavid van Moolenbroek /* Validate that the string represents a valid port number and
607*83ee113eSDavid van Moolenbroek  * return it in network byte order
608*83ee113eSDavid van Moolenbroek  */
609*83ee113eSDavid van Moolenbroek 
610*83ee113eSDavid van Moolenbroek u_int16_t
validate_port(char * port)611*83ee113eSDavid van Moolenbroek validate_port(char *port) {
612*83ee113eSDavid van Moolenbroek 	long local_port = 0;
613*83ee113eSDavid van Moolenbroek 	long lower = 1;
614*83ee113eSDavid van Moolenbroek 	long upper = 65535;
615*83ee113eSDavid van Moolenbroek 	char *endptr;
616*83ee113eSDavid van Moolenbroek 
617*83ee113eSDavid van Moolenbroek 	errno = 0;
618*83ee113eSDavid van Moolenbroek 	local_port = strtol(port, &endptr, 10);
619*83ee113eSDavid van Moolenbroek 
620*83ee113eSDavid van Moolenbroek 	if ((*endptr != '\0') || (errno == ERANGE) || (errno == EINVAL))
621*83ee113eSDavid van Moolenbroek 		log_fatal ("Invalid port number specification: %s", port);
622*83ee113eSDavid van Moolenbroek 
623*83ee113eSDavid van Moolenbroek 	if (local_port < lower || local_port > upper)
624*83ee113eSDavid van Moolenbroek 		log_fatal("Port number specified is out of range (%ld-%ld).",
625*83ee113eSDavid van Moolenbroek 			  lower, upper);
626*83ee113eSDavid van Moolenbroek 
627*83ee113eSDavid van Moolenbroek 	return htons((u_int16_t)local_port);
628*83ee113eSDavid van Moolenbroek }
629