xref: /minix3/external/bsd/bind/dist/lib/irs/resconf.c (revision 00b67f09dd46474d133c95011a48590a8e8f94c7)
1*00b67f09SDavid van Moolenbroek /*	$NetBSD: resconf.c,v 1.8 2014/12/10 04:37:59 christos Exp $	*/
2*00b67f09SDavid van Moolenbroek 
3*00b67f09SDavid van Moolenbroek /*
4*00b67f09SDavid van Moolenbroek  * Copyright (C) 2009, 2011, 2012, 2014  Internet Systems Consortium, Inc. ("ISC")
5*00b67f09SDavid van Moolenbroek  *
6*00b67f09SDavid van Moolenbroek  * Permission to use, copy, modify, and/or distribute this software for any
7*00b67f09SDavid van Moolenbroek  * purpose with or without fee is hereby granted, provided that the above
8*00b67f09SDavid van Moolenbroek  * copyright notice and this permission notice appear in all copies.
9*00b67f09SDavid van Moolenbroek  *
10*00b67f09SDavid van Moolenbroek  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
11*00b67f09SDavid van Moolenbroek  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12*00b67f09SDavid van Moolenbroek  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
13*00b67f09SDavid van Moolenbroek  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14*00b67f09SDavid van Moolenbroek  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15*00b67f09SDavid van Moolenbroek  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16*00b67f09SDavid van Moolenbroek  * PERFORMANCE OF THIS SOFTWARE.
17*00b67f09SDavid van Moolenbroek  */
18*00b67f09SDavid van Moolenbroek 
19*00b67f09SDavid van Moolenbroek /* Id */
20*00b67f09SDavid van Moolenbroek 
21*00b67f09SDavid van Moolenbroek /*! \file resconf.c */
22*00b67f09SDavid van Moolenbroek 
23*00b67f09SDavid van Moolenbroek /**
24*00b67f09SDavid van Moolenbroek  * Module for parsing resolv.conf files (largely derived from lwconfig.c).
25*00b67f09SDavid van Moolenbroek  *
26*00b67f09SDavid van Moolenbroek  *    irs_resconf_load() opens the file filename and parses it to initialize
27*00b67f09SDavid van Moolenbroek  *    the configuration structure.
28*00b67f09SDavid van Moolenbroek  *
29*00b67f09SDavid van Moolenbroek  * \section lwconfig_return Return Values
30*00b67f09SDavid van Moolenbroek  *
31*00b67f09SDavid van Moolenbroek  *    irs_resconf_load() returns #IRS_R_SUCCESS if it successfully read and
32*00b67f09SDavid van Moolenbroek  *    parsed filename. It returns a non-0 error code if filename could not be
33*00b67f09SDavid van Moolenbroek  *    opened or contained incorrect resolver statements.
34*00b67f09SDavid van Moolenbroek  *
35*00b67f09SDavid van Moolenbroek  * \section lwconfig_see See Also
36*00b67f09SDavid van Moolenbroek  *
37*00b67f09SDavid van Moolenbroek  *    stdio(3), \link resolver resolver \endlink
38*00b67f09SDavid van Moolenbroek  *
39*00b67f09SDavid van Moolenbroek  * \section files Files
40*00b67f09SDavid van Moolenbroek  *
41*00b67f09SDavid van Moolenbroek  *    /etc/resolv.conf
42*00b67f09SDavid van Moolenbroek  */
43*00b67f09SDavid van Moolenbroek 
44*00b67f09SDavid van Moolenbroek #include <config.h>
45*00b67f09SDavid van Moolenbroek 
46*00b67f09SDavid van Moolenbroek #ifndef WIN32
47*00b67f09SDavid van Moolenbroek #include <sys/types.h>
48*00b67f09SDavid van Moolenbroek #include <sys/socket.h>
49*00b67f09SDavid van Moolenbroek #include <netdb.h>
50*00b67f09SDavid van Moolenbroek #endif
51*00b67f09SDavid van Moolenbroek 
52*00b67f09SDavid van Moolenbroek #include <ctype.h>
53*00b67f09SDavid van Moolenbroek #include <errno.h>
54*00b67f09SDavid van Moolenbroek #include <stdlib.h>
55*00b67f09SDavid van Moolenbroek #include <stdio.h>
56*00b67f09SDavid van Moolenbroek #include <string.h>
57*00b67f09SDavid van Moolenbroek 
58*00b67f09SDavid van Moolenbroek #include <isc/magic.h>
59*00b67f09SDavid van Moolenbroek #include <isc/mem.h>
60*00b67f09SDavid van Moolenbroek #include <isc/netaddr.h>
61*00b67f09SDavid van Moolenbroek #include <isc/sockaddr.h>
62*00b67f09SDavid van Moolenbroek #include <isc/util.h>
63*00b67f09SDavid van Moolenbroek 
64*00b67f09SDavid van Moolenbroek #include <irs/netdb.h>
65*00b67f09SDavid van Moolenbroek #include <irs/resconf.h>
66*00b67f09SDavid van Moolenbroek 
67*00b67f09SDavid van Moolenbroek #define IRS_RESCONF_MAGIC		ISC_MAGIC('R', 'E', 'S', 'c')
68*00b67f09SDavid van Moolenbroek #define IRS_RESCONF_VALID(c)		ISC_MAGIC_VALID(c, IRS_RESCONF_MAGIC)
69*00b67f09SDavid van Moolenbroek 
70*00b67f09SDavid van Moolenbroek /*!
71*00b67f09SDavid van Moolenbroek  * protocol constants
72*00b67f09SDavid van Moolenbroek  */
73*00b67f09SDavid van Moolenbroek 
74*00b67f09SDavid van Moolenbroek #if ! defined(NS_INADDRSZ)
75*00b67f09SDavid van Moolenbroek #define NS_INADDRSZ	 4
76*00b67f09SDavid van Moolenbroek #endif
77*00b67f09SDavid van Moolenbroek 
78*00b67f09SDavid van Moolenbroek #if ! defined(NS_IN6ADDRSZ)
79*00b67f09SDavid van Moolenbroek #define NS_IN6ADDRSZ	16
80*00b67f09SDavid van Moolenbroek #endif
81*00b67f09SDavid van Moolenbroek 
82*00b67f09SDavid van Moolenbroek /*!
83*00b67f09SDavid van Moolenbroek  * resolv.conf parameters
84*00b67f09SDavid van Moolenbroek  */
85*00b67f09SDavid van Moolenbroek 
86*00b67f09SDavid van Moolenbroek #define RESCONFMAXNAMESERVERS 3		/*%< max 3 "nameserver" entries */
87*00b67f09SDavid van Moolenbroek #define RESCONFMAXSEARCH 8		/*%< max 8 domains in "search" entry */
88*00b67f09SDavid van Moolenbroek #define RESCONFMAXLINELEN 256		/*%< max size of a line */
89*00b67f09SDavid van Moolenbroek #define RESCONFMAXSORTLIST 10		/*%< max 10 */
90*00b67f09SDavid van Moolenbroek 
91*00b67f09SDavid van Moolenbroek /*!
92*00b67f09SDavid van Moolenbroek  * configuration data structure
93*00b67f09SDavid van Moolenbroek  */
94*00b67f09SDavid van Moolenbroek 
95*00b67f09SDavid van Moolenbroek struct irs_resconf {
96*00b67f09SDavid van Moolenbroek 	/*
97*00b67f09SDavid van Moolenbroek 	 * The configuration data is a thread-specific object, and does not
98*00b67f09SDavid van Moolenbroek 	 * need to be locked.
99*00b67f09SDavid van Moolenbroek 	 */
100*00b67f09SDavid van Moolenbroek 	unsigned int		magic;
101*00b67f09SDavid van Moolenbroek 	isc_mem_t		*mctx;
102*00b67f09SDavid van Moolenbroek 
103*00b67f09SDavid van Moolenbroek 	isc_sockaddrlist_t	nameservers;
104*00b67f09SDavid van Moolenbroek 	unsigned int		numns; /*%< number of configured servers */
105*00b67f09SDavid van Moolenbroek 
106*00b67f09SDavid van Moolenbroek 	char	       		*domainname;
107*00b67f09SDavid van Moolenbroek 	char 	       		*search[RESCONFMAXSEARCH];
108*00b67f09SDavid van Moolenbroek 	isc_uint8_t		searchnxt; /*%< index for next free slot */
109*00b67f09SDavid van Moolenbroek 
110*00b67f09SDavid van Moolenbroek 	irs_resconf_searchlist_t searchlist;
111*00b67f09SDavid van Moolenbroek 
112*00b67f09SDavid van Moolenbroek 	struct {
113*00b67f09SDavid van Moolenbroek 		isc_netaddr_t	addr;
114*00b67f09SDavid van Moolenbroek 		/*% mask has a non-zero 'family' if set */
115*00b67f09SDavid van Moolenbroek 		isc_netaddr_t	mask;
116*00b67f09SDavid van Moolenbroek 	} sortlist[RESCONFMAXSORTLIST];
117*00b67f09SDavid van Moolenbroek 	isc_uint8_t		sortlistnxt;
118*00b67f09SDavid van Moolenbroek 
119*00b67f09SDavid van Moolenbroek 	/*%< non-zero if 'options debug' set */
120*00b67f09SDavid van Moolenbroek 	isc_uint8_t		resdebug;
121*00b67f09SDavid van Moolenbroek 	/*%< set to n in 'options ndots:n' */
122*00b67f09SDavid van Moolenbroek 	isc_uint8_t		ndots;
123*00b67f09SDavid van Moolenbroek };
124*00b67f09SDavid van Moolenbroek 
125*00b67f09SDavid van Moolenbroek static isc_result_t
126*00b67f09SDavid van Moolenbroek resconf_parsenameserver(irs_resconf_t *conf,  FILE *fp);
127*00b67f09SDavid van Moolenbroek static isc_result_t
128*00b67f09SDavid van Moolenbroek resconf_parsedomain(irs_resconf_t *conf,  FILE *fp);
129*00b67f09SDavid van Moolenbroek static isc_result_t
130*00b67f09SDavid van Moolenbroek resconf_parsesearch(irs_resconf_t *conf,  FILE *fp);
131*00b67f09SDavid van Moolenbroek static isc_result_t
132*00b67f09SDavid van Moolenbroek resconf_parsesortlist(irs_resconf_t *conf,  FILE *fp);
133*00b67f09SDavid van Moolenbroek static isc_result_t
134*00b67f09SDavid van Moolenbroek resconf_parseoption(irs_resconf_t *ctx,  FILE *fp);
135*00b67f09SDavid van Moolenbroek 
136*00b67f09SDavid van Moolenbroek /*!
137*00b67f09SDavid van Moolenbroek  * Eat characters from FP until EOL or EOF. Returns EOF or '\n'
138*00b67f09SDavid van Moolenbroek  */
139*00b67f09SDavid van Moolenbroek static int
eatline(FILE * fp)140*00b67f09SDavid van Moolenbroek eatline(FILE *fp) {
141*00b67f09SDavid van Moolenbroek 	int ch;
142*00b67f09SDavid van Moolenbroek 
143*00b67f09SDavid van Moolenbroek 	ch = fgetc(fp);
144*00b67f09SDavid van Moolenbroek 	while (ch != '\n' && ch != EOF)
145*00b67f09SDavid van Moolenbroek 		ch = fgetc(fp);
146*00b67f09SDavid van Moolenbroek 
147*00b67f09SDavid van Moolenbroek 	return (ch);
148*00b67f09SDavid van Moolenbroek }
149*00b67f09SDavid van Moolenbroek 
150*00b67f09SDavid van Moolenbroek /*!
151*00b67f09SDavid van Moolenbroek  * Eats white space up to next newline or non-whitespace character (of
152*00b67f09SDavid van Moolenbroek  * EOF). Returns the last character read. Comments are considered white
153*00b67f09SDavid van Moolenbroek  * space.
154*00b67f09SDavid van Moolenbroek  */
155*00b67f09SDavid van Moolenbroek static int
eatwhite(FILE * fp)156*00b67f09SDavid van Moolenbroek eatwhite(FILE *fp) {
157*00b67f09SDavid van Moolenbroek 	int ch;
158*00b67f09SDavid van Moolenbroek 
159*00b67f09SDavid van Moolenbroek 	ch = fgetc(fp);
160*00b67f09SDavid van Moolenbroek 	while (ch != '\n' && ch != EOF && isspace((unsigned char)ch))
161*00b67f09SDavid van Moolenbroek 		ch = fgetc(fp);
162*00b67f09SDavid van Moolenbroek 
163*00b67f09SDavid van Moolenbroek 	if (ch == ';' || ch == '#')
164*00b67f09SDavid van Moolenbroek 		ch = eatline(fp);
165*00b67f09SDavid van Moolenbroek 
166*00b67f09SDavid van Moolenbroek 	return (ch);
167*00b67f09SDavid van Moolenbroek }
168*00b67f09SDavid van Moolenbroek 
169*00b67f09SDavid van Moolenbroek /*!
170*00b67f09SDavid van Moolenbroek  * Skip over any leading whitespace and then read in the next sequence of
171*00b67f09SDavid van Moolenbroek  * non-whitespace characters. In this context newline is not considered
172*00b67f09SDavid van Moolenbroek  * whitespace. Returns EOF on end-of-file, or the character
173*00b67f09SDavid van Moolenbroek  * that caused the reading to stop.
174*00b67f09SDavid van Moolenbroek  */
175*00b67f09SDavid van Moolenbroek static int
getword(FILE * fp,char * buffer,size_t size)176*00b67f09SDavid van Moolenbroek getword(FILE *fp, char *buffer, size_t size) {
177*00b67f09SDavid van Moolenbroek 	int ch;
178*00b67f09SDavid van Moolenbroek 	char *p = buffer;
179*00b67f09SDavid van Moolenbroek 
180*00b67f09SDavid van Moolenbroek 	REQUIRE(buffer != NULL);
181*00b67f09SDavid van Moolenbroek 	REQUIRE(size > 0U);
182*00b67f09SDavid van Moolenbroek 
183*00b67f09SDavid van Moolenbroek 	*p = '\0';
184*00b67f09SDavid van Moolenbroek 
185*00b67f09SDavid van Moolenbroek 	ch = eatwhite(fp);
186*00b67f09SDavid van Moolenbroek 
187*00b67f09SDavid van Moolenbroek 	if (ch == EOF)
188*00b67f09SDavid van Moolenbroek 		return (EOF);
189*00b67f09SDavid van Moolenbroek 
190*00b67f09SDavid van Moolenbroek 	do {
191*00b67f09SDavid van Moolenbroek 		*p = '\0';
192*00b67f09SDavid van Moolenbroek 
193*00b67f09SDavid van Moolenbroek 		if (ch == EOF || isspace((unsigned char)ch))
194*00b67f09SDavid van Moolenbroek 			break;
195*00b67f09SDavid van Moolenbroek 		else if ((size_t) (p - buffer) == size - 1)
196*00b67f09SDavid van Moolenbroek 			return (EOF);	/* Not enough space. */
197*00b67f09SDavid van Moolenbroek 
198*00b67f09SDavid van Moolenbroek 		*p++ = (char)ch;
199*00b67f09SDavid van Moolenbroek 		ch = fgetc(fp);
200*00b67f09SDavid van Moolenbroek 	} while (1);
201*00b67f09SDavid van Moolenbroek 
202*00b67f09SDavid van Moolenbroek 	return (ch);
203*00b67f09SDavid van Moolenbroek }
204*00b67f09SDavid van Moolenbroek 
205*00b67f09SDavid van Moolenbroek static isc_result_t
add_server(isc_mem_t * mctx,const char * address_str,isc_sockaddrlist_t * nameservers)206*00b67f09SDavid van Moolenbroek add_server(isc_mem_t *mctx, const char *address_str,
207*00b67f09SDavid van Moolenbroek 	   isc_sockaddrlist_t *nameservers)
208*00b67f09SDavid van Moolenbroek {
209*00b67f09SDavid van Moolenbroek 	int error;
210*00b67f09SDavid van Moolenbroek 	isc_sockaddr_t *address = NULL;
211*00b67f09SDavid van Moolenbroek 	struct addrinfo hints, *res;
212*00b67f09SDavid van Moolenbroek 	isc_result_t result = ISC_R_SUCCESS;
213*00b67f09SDavid van Moolenbroek 
214*00b67f09SDavid van Moolenbroek 	res = NULL;
215*00b67f09SDavid van Moolenbroek 	memset(&hints, 0, sizeof(hints));
216*00b67f09SDavid van Moolenbroek 	hints.ai_family = AF_UNSPEC;
217*00b67f09SDavid van Moolenbroek 	hints.ai_socktype = SOCK_DGRAM;
218*00b67f09SDavid van Moolenbroek 	hints.ai_protocol = IPPROTO_UDP;
219*00b67f09SDavid van Moolenbroek 	hints.ai_flags = AI_NUMERICHOST;
220*00b67f09SDavid van Moolenbroek 	error = getaddrinfo(address_str, "53", &hints, &res);
221*00b67f09SDavid van Moolenbroek 	if (error != 0)
222*00b67f09SDavid van Moolenbroek 		return (ISC_R_BADADDRESSFORM);
223*00b67f09SDavid van Moolenbroek 
224*00b67f09SDavid van Moolenbroek 	/* XXX: special case: treat all-0 IPv4 address as loopback */
225*00b67f09SDavid van Moolenbroek 	if (res->ai_family == AF_INET) {
226*00b67f09SDavid van Moolenbroek 		struct in_addr *v4;
227*00b67f09SDavid van Moolenbroek 		unsigned char zeroaddress[] = {0, 0, 0, 0};
228*00b67f09SDavid van Moolenbroek 		unsigned char loopaddress[] = {127, 0, 0, 1};
229*00b67f09SDavid van Moolenbroek 
230*00b67f09SDavid van Moolenbroek 		v4 = &((struct sockaddr_in *)res->ai_addr)->sin_addr;
231*00b67f09SDavid van Moolenbroek 		if (memcmp(v4, zeroaddress, 4) == 0)
232*00b67f09SDavid van Moolenbroek 			memmove(v4, loopaddress, 4);
233*00b67f09SDavid van Moolenbroek 	}
234*00b67f09SDavid van Moolenbroek 
235*00b67f09SDavid van Moolenbroek 	address = isc_mem_get(mctx, sizeof(*address));
236*00b67f09SDavid van Moolenbroek 	if (address == NULL) {
237*00b67f09SDavid van Moolenbroek 		result = ISC_R_NOMEMORY;
238*00b67f09SDavid van Moolenbroek 		goto cleanup;
239*00b67f09SDavid van Moolenbroek 	}
240*00b67f09SDavid van Moolenbroek 	if (res->ai_addrlen > sizeof(address->type)) {
241*00b67f09SDavid van Moolenbroek 		isc_mem_put(mctx, address, sizeof(*address));
242*00b67f09SDavid van Moolenbroek 		result = ISC_R_RANGE;
243*00b67f09SDavid van Moolenbroek 		goto cleanup;
244*00b67f09SDavid van Moolenbroek 	}
245*00b67f09SDavid van Moolenbroek 	address->length = (unsigned int)res->ai_addrlen;
246*00b67f09SDavid van Moolenbroek 	memmove(&address->type.ss, res->ai_addr, res->ai_addrlen);
247*00b67f09SDavid van Moolenbroek 	ISC_LINK_INIT(address, link);
248*00b67f09SDavid van Moolenbroek 	ISC_LIST_APPEND(*nameservers, address, link);
249*00b67f09SDavid van Moolenbroek 
250*00b67f09SDavid van Moolenbroek   cleanup:
251*00b67f09SDavid van Moolenbroek 	freeaddrinfo(res);
252*00b67f09SDavid van Moolenbroek 
253*00b67f09SDavid van Moolenbroek 	return (result);
254*00b67f09SDavid van Moolenbroek }
255*00b67f09SDavid van Moolenbroek 
256*00b67f09SDavid van Moolenbroek static isc_result_t
create_addr(const char * buffer,isc_netaddr_t * addr,int convert_zero)257*00b67f09SDavid van Moolenbroek create_addr(const char *buffer, isc_netaddr_t *addr, int convert_zero) {
258*00b67f09SDavid van Moolenbroek 	struct in_addr v4;
259*00b67f09SDavid van Moolenbroek 	struct in6_addr v6;
260*00b67f09SDavid van Moolenbroek 
261*00b67f09SDavid van Moolenbroek 	if (inet_aton(buffer, &v4) == 1) {
262*00b67f09SDavid van Moolenbroek 		if (convert_zero) {
263*00b67f09SDavid van Moolenbroek 			unsigned char zeroaddress[] = {0, 0, 0, 0};
264*00b67f09SDavid van Moolenbroek 			unsigned char loopaddress[] = {127, 0, 0, 1};
265*00b67f09SDavid van Moolenbroek 			if (memcmp(&v4, zeroaddress, 4) == 0)
266*00b67f09SDavid van Moolenbroek 				memmove(&v4, loopaddress, 4);
267*00b67f09SDavid van Moolenbroek 		}
268*00b67f09SDavid van Moolenbroek 		addr->family = AF_INET;
269*00b67f09SDavid van Moolenbroek 		memmove(&addr->type.in, &v4, NS_INADDRSZ);
270*00b67f09SDavid van Moolenbroek 		addr->zone = 0;
271*00b67f09SDavid van Moolenbroek 	} else if (inet_pton(AF_INET6, buffer, &v6) == 1) {
272*00b67f09SDavid van Moolenbroek 		addr->family = AF_INET6;
273*00b67f09SDavid van Moolenbroek 		memmove(&addr->type.in6, &v6, NS_IN6ADDRSZ);
274*00b67f09SDavid van Moolenbroek 		addr->zone = 0;
275*00b67f09SDavid van Moolenbroek 	} else
276*00b67f09SDavid van Moolenbroek 		return (ISC_R_BADADDRESSFORM); /* Unrecognised format. */
277*00b67f09SDavid van Moolenbroek 
278*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
279*00b67f09SDavid van Moolenbroek }
280*00b67f09SDavid van Moolenbroek 
281*00b67f09SDavid van Moolenbroek static isc_result_t
resconf_parsenameserver(irs_resconf_t * conf,FILE * fp)282*00b67f09SDavid van Moolenbroek resconf_parsenameserver(irs_resconf_t *conf,  FILE *fp) {
283*00b67f09SDavid van Moolenbroek 	char word[RESCONFMAXLINELEN];
284*00b67f09SDavid van Moolenbroek 	int cp;
285*00b67f09SDavid van Moolenbroek 	isc_result_t result;
286*00b67f09SDavid van Moolenbroek 
287*00b67f09SDavid van Moolenbroek 	if (conf->numns == RESCONFMAXNAMESERVERS)
288*00b67f09SDavid van Moolenbroek 		return (ISC_R_SUCCESS);
289*00b67f09SDavid van Moolenbroek 
290*00b67f09SDavid van Moolenbroek 	cp = getword(fp, word, sizeof(word));
291*00b67f09SDavid van Moolenbroek 	if (strlen(word) == 0U)
292*00b67f09SDavid van Moolenbroek 		return (ISC_R_UNEXPECTEDEND); /* Nothing on line. */
293*00b67f09SDavid van Moolenbroek 	else if (cp == ' ' || cp == '\t')
294*00b67f09SDavid van Moolenbroek 		cp = eatwhite(fp);
295*00b67f09SDavid van Moolenbroek 
296*00b67f09SDavid van Moolenbroek 	if (cp != EOF && cp != '\n')
297*00b67f09SDavid van Moolenbroek 		return (ISC_R_UNEXPECTEDTOKEN); /* Extra junk on line. */
298*00b67f09SDavid van Moolenbroek 
299*00b67f09SDavid van Moolenbroek 	result = add_server(conf->mctx, word, &conf->nameservers);
300*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
301*00b67f09SDavid van Moolenbroek 		return (result);
302*00b67f09SDavid van Moolenbroek 	conf->numns++;
303*00b67f09SDavid van Moolenbroek 
304*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
305*00b67f09SDavid van Moolenbroek }
306*00b67f09SDavid van Moolenbroek 
307*00b67f09SDavid van Moolenbroek static isc_result_t
resconf_parsedomain(irs_resconf_t * conf,FILE * fp)308*00b67f09SDavid van Moolenbroek resconf_parsedomain(irs_resconf_t *conf,  FILE *fp) {
309*00b67f09SDavid van Moolenbroek 	char word[RESCONFMAXLINELEN];
310*00b67f09SDavid van Moolenbroek 	int res, i;
311*00b67f09SDavid van Moolenbroek 
312*00b67f09SDavid van Moolenbroek 	res = getword(fp, word, sizeof(word));
313*00b67f09SDavid van Moolenbroek 	if (strlen(word) == 0U)
314*00b67f09SDavid van Moolenbroek 		return (ISC_R_UNEXPECTEDEND); /* Nothing else on line. */
315*00b67f09SDavid van Moolenbroek 	else if (res == ' ' || res == '\t')
316*00b67f09SDavid van Moolenbroek 		res = eatwhite(fp);
317*00b67f09SDavid van Moolenbroek 
318*00b67f09SDavid van Moolenbroek 	if (res != EOF && res != '\n')
319*00b67f09SDavid van Moolenbroek 		return (ISC_R_UNEXPECTEDTOKEN); /* Extra junk on line. */
320*00b67f09SDavid van Moolenbroek 
321*00b67f09SDavid van Moolenbroek 	if (conf->domainname != NULL)
322*00b67f09SDavid van Moolenbroek 		isc_mem_free(conf->mctx, conf->domainname);
323*00b67f09SDavid van Moolenbroek 
324*00b67f09SDavid van Moolenbroek 	/*
325*00b67f09SDavid van Moolenbroek 	 * Search and domain are mutually exclusive.
326*00b67f09SDavid van Moolenbroek 	 */
327*00b67f09SDavid van Moolenbroek 	for (i = 0; i < RESCONFMAXSEARCH; i++) {
328*00b67f09SDavid van Moolenbroek 		if (conf->search[i] != NULL) {
329*00b67f09SDavid van Moolenbroek 			isc_mem_free(conf->mctx, conf->search[i]);
330*00b67f09SDavid van Moolenbroek 			conf->search[i] = NULL;
331*00b67f09SDavid van Moolenbroek 		}
332*00b67f09SDavid van Moolenbroek 	}
333*00b67f09SDavid van Moolenbroek 	conf->searchnxt = 0;
334*00b67f09SDavid van Moolenbroek 
335*00b67f09SDavid van Moolenbroek 	conf->domainname = isc_mem_strdup(conf->mctx, word);
336*00b67f09SDavid van Moolenbroek 	if (conf->domainname == NULL)
337*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOMEMORY);
338*00b67f09SDavid van Moolenbroek 
339*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
340*00b67f09SDavid van Moolenbroek }
341*00b67f09SDavid van Moolenbroek 
342*00b67f09SDavid van Moolenbroek static isc_result_t
resconf_parsesearch(irs_resconf_t * conf,FILE * fp)343*00b67f09SDavid van Moolenbroek resconf_parsesearch(irs_resconf_t *conf,  FILE *fp) {
344*00b67f09SDavid van Moolenbroek 	int idx, delim;
345*00b67f09SDavid van Moolenbroek 	char word[RESCONFMAXLINELEN];
346*00b67f09SDavid van Moolenbroek 
347*00b67f09SDavid van Moolenbroek 	if (conf->domainname != NULL) {
348*00b67f09SDavid van Moolenbroek 		/*
349*00b67f09SDavid van Moolenbroek 		 * Search and domain are mutually exclusive.
350*00b67f09SDavid van Moolenbroek 		 */
351*00b67f09SDavid van Moolenbroek 		isc_mem_free(conf->mctx, conf->domainname);
352*00b67f09SDavid van Moolenbroek 		conf->domainname = NULL;
353*00b67f09SDavid van Moolenbroek 	}
354*00b67f09SDavid van Moolenbroek 
355*00b67f09SDavid van Moolenbroek 	/*
356*00b67f09SDavid van Moolenbroek 	 * Remove any previous search definitions.
357*00b67f09SDavid van Moolenbroek 	 */
358*00b67f09SDavid van Moolenbroek 	for (idx = 0; idx < RESCONFMAXSEARCH; idx++) {
359*00b67f09SDavid van Moolenbroek 		if (conf->search[idx] != NULL) {
360*00b67f09SDavid van Moolenbroek 			isc_mem_free(conf->mctx, conf->search[idx]);
361*00b67f09SDavid van Moolenbroek 			conf->search[idx] = NULL;
362*00b67f09SDavid van Moolenbroek 		}
363*00b67f09SDavid van Moolenbroek 	}
364*00b67f09SDavid van Moolenbroek 	conf->searchnxt = 0;
365*00b67f09SDavid van Moolenbroek 
366*00b67f09SDavid van Moolenbroek 	delim = getword(fp, word, sizeof(word));
367*00b67f09SDavid van Moolenbroek 	if (strlen(word) == 0U)
368*00b67f09SDavid van Moolenbroek 		return (ISC_R_UNEXPECTEDEND); /* Nothing else on line. */
369*00b67f09SDavid van Moolenbroek 
370*00b67f09SDavid van Moolenbroek 	idx = 0;
371*00b67f09SDavid van Moolenbroek 	while (strlen(word) > 0U) {
372*00b67f09SDavid van Moolenbroek 		if (conf->searchnxt == RESCONFMAXSEARCH)
373*00b67f09SDavid van Moolenbroek 			goto ignore; /* Too many domains. */
374*00b67f09SDavid van Moolenbroek 
375*00b67f09SDavid van Moolenbroek 		conf->search[idx] = isc_mem_strdup(conf->mctx, word);
376*00b67f09SDavid van Moolenbroek 		if (conf->search[idx] == NULL)
377*00b67f09SDavid van Moolenbroek 			return (ISC_R_NOMEMORY);
378*00b67f09SDavid van Moolenbroek 		idx++;
379*00b67f09SDavid van Moolenbroek 		conf->searchnxt++;
380*00b67f09SDavid van Moolenbroek 
381*00b67f09SDavid van Moolenbroek 	ignore:
382*00b67f09SDavid van Moolenbroek 		if (delim == EOF || delim == '\n')
383*00b67f09SDavid van Moolenbroek 			break;
384*00b67f09SDavid van Moolenbroek 		else
385*00b67f09SDavid van Moolenbroek 			delim = getword(fp, word, sizeof(word));
386*00b67f09SDavid van Moolenbroek 	}
387*00b67f09SDavid van Moolenbroek 
388*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
389*00b67f09SDavid van Moolenbroek }
390*00b67f09SDavid van Moolenbroek 
391*00b67f09SDavid van Moolenbroek static isc_result_t
resconf_parsesortlist(irs_resconf_t * conf,FILE * fp)392*00b67f09SDavid van Moolenbroek resconf_parsesortlist(irs_resconf_t *conf,  FILE *fp) {
393*00b67f09SDavid van Moolenbroek 	int delim, res, idx;
394*00b67f09SDavid van Moolenbroek 	char word[RESCONFMAXLINELEN];
395*00b67f09SDavid van Moolenbroek 	char *p;
396*00b67f09SDavid van Moolenbroek 
397*00b67f09SDavid van Moolenbroek 	delim = getword(fp, word, sizeof(word));
398*00b67f09SDavid van Moolenbroek 	if (strlen(word) == 0U)
399*00b67f09SDavid van Moolenbroek 		return (ISC_R_UNEXPECTEDEND); /* Empty line after keyword. */
400*00b67f09SDavid van Moolenbroek 
401*00b67f09SDavid van Moolenbroek 	while (strlen(word) > 0U) {
402*00b67f09SDavid van Moolenbroek 		if (conf->sortlistnxt == RESCONFMAXSORTLIST)
403*00b67f09SDavid van Moolenbroek 			return (ISC_R_QUOTA); /* Too many values. */
404*00b67f09SDavid van Moolenbroek 
405*00b67f09SDavid van Moolenbroek 		p = strchr(word, '/');
406*00b67f09SDavid van Moolenbroek 		if (p != NULL)
407*00b67f09SDavid van Moolenbroek 			*p++ = '\0';
408*00b67f09SDavid van Moolenbroek 
409*00b67f09SDavid van Moolenbroek 		idx = conf->sortlistnxt;
410*00b67f09SDavid van Moolenbroek 		res = create_addr(word, &conf->sortlist[idx].addr, 1);
411*00b67f09SDavid van Moolenbroek 		if (res != ISC_R_SUCCESS)
412*00b67f09SDavid van Moolenbroek 			return (res);
413*00b67f09SDavid van Moolenbroek 
414*00b67f09SDavid van Moolenbroek 		if (p != NULL) {
415*00b67f09SDavid van Moolenbroek 			res = create_addr(p, &conf->sortlist[idx].mask, 0);
416*00b67f09SDavid van Moolenbroek 			if (res != ISC_R_SUCCESS)
417*00b67f09SDavid van Moolenbroek 				return (res);
418*00b67f09SDavid van Moolenbroek 		} else {
419*00b67f09SDavid van Moolenbroek 			/*
420*00b67f09SDavid van Moolenbroek 			 * Make up a mask. (XXX: is this correct?)
421*00b67f09SDavid van Moolenbroek 			 */
422*00b67f09SDavid van Moolenbroek 			conf->sortlist[idx].mask = conf->sortlist[idx].addr;
423*00b67f09SDavid van Moolenbroek 			memset(&conf->sortlist[idx].mask.type, 0xff,
424*00b67f09SDavid van Moolenbroek 			       sizeof(conf->sortlist[idx].mask.type));
425*00b67f09SDavid van Moolenbroek 		}
426*00b67f09SDavid van Moolenbroek 
427*00b67f09SDavid van Moolenbroek 		conf->sortlistnxt++;
428*00b67f09SDavid van Moolenbroek 
429*00b67f09SDavid van Moolenbroek 		if (delim == EOF || delim == '\n')
430*00b67f09SDavid van Moolenbroek 			break;
431*00b67f09SDavid van Moolenbroek 		else
432*00b67f09SDavid van Moolenbroek 			delim = getword(fp, word, sizeof(word));
433*00b67f09SDavid van Moolenbroek 	}
434*00b67f09SDavid van Moolenbroek 
435*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
436*00b67f09SDavid van Moolenbroek }
437*00b67f09SDavid van Moolenbroek 
438*00b67f09SDavid van Moolenbroek static isc_result_t
resconf_parseoption(irs_resconf_t * conf,FILE * fp)439*00b67f09SDavid van Moolenbroek resconf_parseoption(irs_resconf_t *conf,  FILE *fp) {
440*00b67f09SDavid van Moolenbroek 	int delim;
441*00b67f09SDavid van Moolenbroek 	long ndots;
442*00b67f09SDavid van Moolenbroek 	char *p;
443*00b67f09SDavid van Moolenbroek 	char word[RESCONFMAXLINELEN];
444*00b67f09SDavid van Moolenbroek 
445*00b67f09SDavid van Moolenbroek 	delim = getword(fp, word, sizeof(word));
446*00b67f09SDavid van Moolenbroek 	if (strlen(word) == 0U)
447*00b67f09SDavid van Moolenbroek 		return (ISC_R_UNEXPECTEDEND); /* Empty line after keyword. */
448*00b67f09SDavid van Moolenbroek 
449*00b67f09SDavid van Moolenbroek 	while (strlen(word) > 0U) {
450*00b67f09SDavid van Moolenbroek 		if (strcmp("debug", word) == 0) {
451*00b67f09SDavid van Moolenbroek 			conf->resdebug = 1;
452*00b67f09SDavid van Moolenbroek 		} else if (strncmp("ndots:", word, 6) == 0) {
453*00b67f09SDavid van Moolenbroek 			ndots = strtol(word + 6, &p, 10);
454*00b67f09SDavid van Moolenbroek 			if (*p != '\0') /* Bad string. */
455*00b67f09SDavid van Moolenbroek 				return (ISC_R_UNEXPECTEDTOKEN);
456*00b67f09SDavid van Moolenbroek 			if (ndots < 0 || ndots > 0xff) /* Out of range. */
457*00b67f09SDavid van Moolenbroek 				return (ISC_R_RANGE);
458*00b67f09SDavid van Moolenbroek 			conf->ndots = (isc_uint8_t)ndots;
459*00b67f09SDavid van Moolenbroek 		}
460*00b67f09SDavid van Moolenbroek 
461*00b67f09SDavid van Moolenbroek 		if (delim == EOF || delim == '\n')
462*00b67f09SDavid van Moolenbroek 			break;
463*00b67f09SDavid van Moolenbroek 		else
464*00b67f09SDavid van Moolenbroek 			delim = getword(fp, word, sizeof(word));
465*00b67f09SDavid van Moolenbroek 	}
466*00b67f09SDavid van Moolenbroek 
467*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
468*00b67f09SDavid van Moolenbroek }
469*00b67f09SDavid van Moolenbroek 
470*00b67f09SDavid van Moolenbroek static isc_result_t
add_search(irs_resconf_t * conf,char * domain)471*00b67f09SDavid van Moolenbroek add_search(irs_resconf_t *conf, char *domain) {
472*00b67f09SDavid van Moolenbroek 	irs_resconf_search_t *entry;
473*00b67f09SDavid van Moolenbroek 
474*00b67f09SDavid van Moolenbroek 	entry = isc_mem_get(conf->mctx, sizeof(*entry));
475*00b67f09SDavid van Moolenbroek 	if (entry == NULL)
476*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOMEMORY);
477*00b67f09SDavid van Moolenbroek 
478*00b67f09SDavid van Moolenbroek 	entry->domain = domain;
479*00b67f09SDavid van Moolenbroek 	ISC_LINK_INIT(entry, link);
480*00b67f09SDavid van Moolenbroek 	ISC_LIST_APPEND(conf->searchlist, entry, link);
481*00b67f09SDavid van Moolenbroek 
482*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
483*00b67f09SDavid van Moolenbroek }
484*00b67f09SDavid van Moolenbroek 
485*00b67f09SDavid van Moolenbroek /*% parses a file and fills in the data structure. */
486*00b67f09SDavid van Moolenbroek isc_result_t
irs_resconf_load(isc_mem_t * mctx,const char * filename,irs_resconf_t ** confp)487*00b67f09SDavid van Moolenbroek irs_resconf_load(isc_mem_t *mctx, const char *filename, irs_resconf_t **confp)
488*00b67f09SDavid van Moolenbroek {
489*00b67f09SDavid van Moolenbroek 	FILE *fp = NULL;
490*00b67f09SDavid van Moolenbroek 	char word[256];
491*00b67f09SDavid van Moolenbroek 	isc_result_t rval, ret = ISC_R_SUCCESS;
492*00b67f09SDavid van Moolenbroek 	irs_resconf_t *conf;
493*00b67f09SDavid van Moolenbroek 	int i, stopchar;
494*00b67f09SDavid van Moolenbroek 
495*00b67f09SDavid van Moolenbroek 	REQUIRE(mctx != NULL);
496*00b67f09SDavid van Moolenbroek 	REQUIRE(filename != NULL);
497*00b67f09SDavid van Moolenbroek 	REQUIRE(strlen(filename) > 0U);
498*00b67f09SDavid van Moolenbroek 	REQUIRE(confp != NULL && *confp == NULL);
499*00b67f09SDavid van Moolenbroek 
500*00b67f09SDavid van Moolenbroek 	conf = isc_mem_get(mctx, sizeof(*conf));
501*00b67f09SDavid van Moolenbroek 	if (conf == NULL)
502*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOMEMORY);
503*00b67f09SDavid van Moolenbroek 
504*00b67f09SDavid van Moolenbroek 	conf->mctx = mctx;
505*00b67f09SDavid van Moolenbroek 	ISC_LIST_INIT(conf->nameservers);
506*00b67f09SDavid van Moolenbroek 	conf->numns = 0;
507*00b67f09SDavid van Moolenbroek 	conf->domainname = NULL;
508*00b67f09SDavid van Moolenbroek 	conf->searchnxt = 0;
509*00b67f09SDavid van Moolenbroek 	conf->resdebug = 0;
510*00b67f09SDavid van Moolenbroek 	conf->ndots = 1;
511*00b67f09SDavid van Moolenbroek 	for (i = 0; i < RESCONFMAXSEARCH; i++)
512*00b67f09SDavid van Moolenbroek 		conf->search[i] = NULL;
513*00b67f09SDavid van Moolenbroek 
514*00b67f09SDavid van Moolenbroek 	errno = 0;
515*00b67f09SDavid van Moolenbroek 	if ((fp = fopen(filename, "r")) != NULL) {
516*00b67f09SDavid van Moolenbroek 		do {
517*00b67f09SDavid van Moolenbroek 			stopchar = getword(fp, word, sizeof(word));
518*00b67f09SDavid van Moolenbroek 			if (stopchar == EOF) {
519*00b67f09SDavid van Moolenbroek 				rval = ISC_R_SUCCESS;
520*00b67f09SDavid van Moolenbroek 				POST(rval);
521*00b67f09SDavid van Moolenbroek 				break;
522*00b67f09SDavid van Moolenbroek 			}
523*00b67f09SDavid van Moolenbroek 
524*00b67f09SDavid van Moolenbroek 			if (strlen(word) == 0U)
525*00b67f09SDavid van Moolenbroek 				rval = ISC_R_SUCCESS;
526*00b67f09SDavid van Moolenbroek 			else if (strcmp(word, "nameserver") == 0)
527*00b67f09SDavid van Moolenbroek 				rval = resconf_parsenameserver(conf, fp);
528*00b67f09SDavid van Moolenbroek 			else if (strcmp(word, "domain") == 0)
529*00b67f09SDavid van Moolenbroek 				rval = resconf_parsedomain(conf, fp);
530*00b67f09SDavid van Moolenbroek 			else if (strcmp(word, "search") == 0)
531*00b67f09SDavid van Moolenbroek 				rval = resconf_parsesearch(conf, fp);
532*00b67f09SDavid van Moolenbroek 			else if (strcmp(word, "sortlist") == 0)
533*00b67f09SDavid van Moolenbroek 				rval = resconf_parsesortlist(conf, fp);
534*00b67f09SDavid van Moolenbroek 			else if (strcmp(word, "options") == 0)
535*00b67f09SDavid van Moolenbroek 				rval = resconf_parseoption(conf, fp);
536*00b67f09SDavid van Moolenbroek 			else {
537*00b67f09SDavid van Moolenbroek 				/* unrecognised word. Ignore entire line */
538*00b67f09SDavid van Moolenbroek 				rval = ISC_R_SUCCESS;
539*00b67f09SDavid van Moolenbroek 				stopchar = eatline(fp);
540*00b67f09SDavid van Moolenbroek 				if (stopchar == EOF) {
541*00b67f09SDavid van Moolenbroek 					break;
542*00b67f09SDavid van Moolenbroek 				}
543*00b67f09SDavid van Moolenbroek 			}
544*00b67f09SDavid van Moolenbroek 			if (ret == ISC_R_SUCCESS && rval != ISC_R_SUCCESS)
545*00b67f09SDavid van Moolenbroek 				ret = rval;
546*00b67f09SDavid van Moolenbroek 		} while (1);
547*00b67f09SDavid van Moolenbroek 
548*00b67f09SDavid van Moolenbroek 		fclose(fp);
549*00b67f09SDavid van Moolenbroek 	} else {
550*00b67f09SDavid van Moolenbroek 		switch (errno) {
551*00b67f09SDavid van Moolenbroek 		case ENOENT:
552*00b67f09SDavid van Moolenbroek 			break;
553*00b67f09SDavid van Moolenbroek 		default:
554*00b67f09SDavid van Moolenbroek 			isc_mem_put(mctx, conf, sizeof(*conf));
555*00b67f09SDavid van Moolenbroek 			return (ISC_R_INVALIDFILE);
556*00b67f09SDavid van Moolenbroek 		}
557*00b67f09SDavid van Moolenbroek 	}
558*00b67f09SDavid van Moolenbroek 
559*00b67f09SDavid van Moolenbroek 	/* If we don't find a nameserver fall back to localhost */
560*00b67f09SDavid van Moolenbroek 	if (conf->numns == 0) {
561*00b67f09SDavid van Moolenbroek 		INSIST(ISC_LIST_EMPTY(conf->nameservers));
562*00b67f09SDavid van Moolenbroek 
563*00b67f09SDavid van Moolenbroek 		/* XXX: should we catch errors? */
564*00b67f09SDavid van Moolenbroek 		(void)add_server(conf->mctx, "127.0.0.1", &conf->nameservers);
565*00b67f09SDavid van Moolenbroek 		(void)add_server(conf->mctx, "::1", &conf->nameservers);
566*00b67f09SDavid van Moolenbroek 	}
567*00b67f09SDavid van Moolenbroek 
568*00b67f09SDavid van Moolenbroek 	/*
569*00b67f09SDavid van Moolenbroek 	 * Construct unified search list from domain or configured
570*00b67f09SDavid van Moolenbroek 	 * search list
571*00b67f09SDavid van Moolenbroek 	 */
572*00b67f09SDavid van Moolenbroek 	ISC_LIST_INIT(conf->searchlist);
573*00b67f09SDavid van Moolenbroek 	if (conf->domainname != NULL) {
574*00b67f09SDavid van Moolenbroek 		ret = add_search(conf, conf->domainname);
575*00b67f09SDavid van Moolenbroek 	} else if (conf->searchnxt > 0) {
576*00b67f09SDavid van Moolenbroek 		for (i = 0; i < conf->searchnxt; i++) {
577*00b67f09SDavid van Moolenbroek 			ret = add_search(conf, conf->search[i]);
578*00b67f09SDavid van Moolenbroek 			if (ret != ISC_R_SUCCESS)
579*00b67f09SDavid van Moolenbroek 				break;
580*00b67f09SDavid van Moolenbroek 		}
581*00b67f09SDavid van Moolenbroek 	}
582*00b67f09SDavid van Moolenbroek 
583*00b67f09SDavid van Moolenbroek 	conf->magic = IRS_RESCONF_MAGIC;
584*00b67f09SDavid van Moolenbroek 
585*00b67f09SDavid van Moolenbroek 	if (ret != ISC_R_SUCCESS)
586*00b67f09SDavid van Moolenbroek 		irs_resconf_destroy(&conf);
587*00b67f09SDavid van Moolenbroek 	else {
588*00b67f09SDavid van Moolenbroek 		if (fp == NULL)
589*00b67f09SDavid van Moolenbroek 			ret = ISC_R_FILENOTFOUND;
590*00b67f09SDavid van Moolenbroek 		*confp = conf;
591*00b67f09SDavid van Moolenbroek 	}
592*00b67f09SDavid van Moolenbroek 
593*00b67f09SDavid van Moolenbroek 	return (ret);
594*00b67f09SDavid van Moolenbroek }
595*00b67f09SDavid van Moolenbroek 
596*00b67f09SDavid van Moolenbroek void
irs_resconf_destroy(irs_resconf_t ** confp)597*00b67f09SDavid van Moolenbroek irs_resconf_destroy(irs_resconf_t **confp) {
598*00b67f09SDavid van Moolenbroek 	irs_resconf_t *conf;
599*00b67f09SDavid van Moolenbroek 	isc_sockaddr_t *address;
600*00b67f09SDavid van Moolenbroek 	irs_resconf_search_t *searchentry;
601*00b67f09SDavid van Moolenbroek 	int i;
602*00b67f09SDavid van Moolenbroek 
603*00b67f09SDavid van Moolenbroek 	REQUIRE(confp != NULL);
604*00b67f09SDavid van Moolenbroek 	conf = *confp;
605*00b67f09SDavid van Moolenbroek 	REQUIRE(IRS_RESCONF_VALID(conf));
606*00b67f09SDavid van Moolenbroek 
607*00b67f09SDavid van Moolenbroek 	while ((searchentry = ISC_LIST_HEAD(conf->searchlist)) != NULL) {
608*00b67f09SDavid van Moolenbroek 		ISC_LIST_UNLINK(conf->searchlist, searchentry, link);
609*00b67f09SDavid van Moolenbroek 		isc_mem_put(conf->mctx, searchentry, sizeof(*searchentry));
610*00b67f09SDavid van Moolenbroek 	}
611*00b67f09SDavid van Moolenbroek 
612*00b67f09SDavid van Moolenbroek 	while ((address = ISC_LIST_HEAD(conf->nameservers)) != NULL) {
613*00b67f09SDavid van Moolenbroek 		ISC_LIST_UNLINK(conf->nameservers, address, link);
614*00b67f09SDavid van Moolenbroek 		isc_mem_put(conf->mctx, address, sizeof(*address));
615*00b67f09SDavid van Moolenbroek 	}
616*00b67f09SDavid van Moolenbroek 
617*00b67f09SDavid van Moolenbroek 	if (conf->domainname != NULL)
618*00b67f09SDavid van Moolenbroek 		isc_mem_free(conf->mctx, conf->domainname);
619*00b67f09SDavid van Moolenbroek 
620*00b67f09SDavid van Moolenbroek 	for (i = 0; i < RESCONFMAXSEARCH; i++) {
621*00b67f09SDavid van Moolenbroek 		if (conf->search[i] != NULL)
622*00b67f09SDavid van Moolenbroek 			isc_mem_free(conf->mctx, conf->search[i]);
623*00b67f09SDavid van Moolenbroek 	}
624*00b67f09SDavid van Moolenbroek 
625*00b67f09SDavid van Moolenbroek 	isc_mem_put(conf->mctx, conf, sizeof(*conf));
626*00b67f09SDavid van Moolenbroek 
627*00b67f09SDavid van Moolenbroek 	*confp = NULL;
628*00b67f09SDavid van Moolenbroek }
629*00b67f09SDavid van Moolenbroek 
630*00b67f09SDavid van Moolenbroek isc_sockaddrlist_t *
irs_resconf_getnameservers(irs_resconf_t * conf)631*00b67f09SDavid van Moolenbroek irs_resconf_getnameservers(irs_resconf_t *conf) {
632*00b67f09SDavid van Moolenbroek 	REQUIRE(IRS_RESCONF_VALID(conf));
633*00b67f09SDavid van Moolenbroek 
634*00b67f09SDavid van Moolenbroek 	return (&conf->nameservers);
635*00b67f09SDavid van Moolenbroek }
636*00b67f09SDavid van Moolenbroek 
637*00b67f09SDavid van Moolenbroek irs_resconf_searchlist_t *
irs_resconf_getsearchlist(irs_resconf_t * conf)638*00b67f09SDavid van Moolenbroek irs_resconf_getsearchlist(irs_resconf_t *conf) {
639*00b67f09SDavid van Moolenbroek 	REQUIRE(IRS_RESCONF_VALID(conf));
640*00b67f09SDavid van Moolenbroek 
641*00b67f09SDavid van Moolenbroek 	return (&conf->searchlist);
642*00b67f09SDavid van Moolenbroek }
643*00b67f09SDavid van Moolenbroek 
644*00b67f09SDavid van Moolenbroek unsigned int
irs_resconf_getndots(irs_resconf_t * conf)645*00b67f09SDavid van Moolenbroek irs_resconf_getndots(irs_resconf_t *conf) {
646*00b67f09SDavid van Moolenbroek 	REQUIRE(IRS_RESCONF_VALID(conf));
647*00b67f09SDavid van Moolenbroek 
648*00b67f09SDavid van Moolenbroek 	return ((unsigned int)conf->ndots);
649*00b67f09SDavid van Moolenbroek }
650