xref: /minix3/external/bsd/bind/dist/contrib/dlz/modules/common/dlz_dbi.c (revision 00b67f09dd46474d133c95011a48590a8e8f94c7)
1*00b67f09SDavid van Moolenbroek /*	$NetBSD: dlz_dbi.c,v 1.1.1.4 2014/12/10 03:34:31 christos Exp $	*/
2*00b67f09SDavid van Moolenbroek 
3*00b67f09SDavid van Moolenbroek /*
4*00b67f09SDavid van Moolenbroek  * Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl.
5*00b67f09SDavid van Moolenbroek  *
6*00b67f09SDavid van Moolenbroek  * Permission to use, copy, modify, and distribute this software for any
7*00b67f09SDavid van Moolenbroek  * purpose with or without fee is hereby granted, provided that the
8*00b67f09SDavid van Moolenbroek  * above copyright notice and this permission notice appear in all
9*00b67f09SDavid van Moolenbroek  * copies.
10*00b67f09SDavid van Moolenbroek  *
11*00b67f09SDavid van Moolenbroek  * THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET
12*00b67f09SDavid van Moolenbroek  * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
13*00b67f09SDavid van Moolenbroek  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
14*00b67f09SDavid van Moolenbroek  * STICHTING NLNET BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
15*00b67f09SDavid van Moolenbroek  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
16*00b67f09SDavid van Moolenbroek  * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
17*00b67f09SDavid van Moolenbroek  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
18*00b67f09SDavid van Moolenbroek  * USE OR PERFORMANCE OF THIS SOFTWARE.
19*00b67f09SDavid van Moolenbroek  *
20*00b67f09SDavid van Moolenbroek  * The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
21*00b67f09SDavid van Moolenbroek  * conceived and contributed by Rob Butler.
22*00b67f09SDavid van Moolenbroek  *
23*00b67f09SDavid van Moolenbroek  * Permission to use, copy, modify, and distribute this software for any
24*00b67f09SDavid van Moolenbroek  * purpose with or without fee is hereby granted, provided that the
25*00b67f09SDavid van Moolenbroek  * above copyright notice and this permission notice appear in all
26*00b67f09SDavid van Moolenbroek  * copies.
27*00b67f09SDavid van Moolenbroek  *
28*00b67f09SDavid van Moolenbroek  * THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER
29*00b67f09SDavid van Moolenbroek  * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
30*00b67f09SDavid van Moolenbroek  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
31*00b67f09SDavid van Moolenbroek  * ROB BUTLER BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
32*00b67f09SDavid van Moolenbroek  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
33*00b67f09SDavid van Moolenbroek  * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
34*00b67f09SDavid van Moolenbroek  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
35*00b67f09SDavid van Moolenbroek  * USE OR PERFORMANCE OF THIS SOFTWARE.
36*00b67f09SDavid van Moolenbroek  */
37*00b67f09SDavid van Moolenbroek 
38*00b67f09SDavid van Moolenbroek /*
39*00b67f09SDavid van Moolenbroek  * Copyright (C) 2013  Internet Systems Consortium, Inc. ("ISC")
40*00b67f09SDavid van Moolenbroek  * Copyright (C) 1999-2001  Internet Software Consortium.
41*00b67f09SDavid van Moolenbroek  *
42*00b67f09SDavid van Moolenbroek  * Permission to use, copy, modify, and/or distribute this software for any
43*00b67f09SDavid van Moolenbroek  * purpose with or without fee is hereby granted, provided that the above
44*00b67f09SDavid van Moolenbroek  * copyright notice and this permission notice appear in all copies.
45*00b67f09SDavid van Moolenbroek  *
46*00b67f09SDavid van Moolenbroek  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
47*00b67f09SDavid van Moolenbroek  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
48*00b67f09SDavid van Moolenbroek  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
49*00b67f09SDavid van Moolenbroek  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
50*00b67f09SDavid van Moolenbroek  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
51*00b67f09SDavid van Moolenbroek  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
52*00b67f09SDavid van Moolenbroek  * PERFORMANCE OF THIS SOFTWARE.
53*00b67f09SDavid van Moolenbroek  */
54*00b67f09SDavid van Moolenbroek 
55*00b67f09SDavid van Moolenbroek #include <stdio.h>
56*00b67f09SDavid van Moolenbroek #include <string.h>
57*00b67f09SDavid van Moolenbroek #include <stdarg.h>
58*00b67f09SDavid van Moolenbroek #include <stdint.h>
59*00b67f09SDavid van Moolenbroek #include <stdlib.h>
60*00b67f09SDavid van Moolenbroek #include <ctype.h>
61*00b67f09SDavid van Moolenbroek 
62*00b67f09SDavid van Moolenbroek #include <sys/errno.h>
63*00b67f09SDavid van Moolenbroek 
64*00b67f09SDavid van Moolenbroek #include <dlz_minimal.h>
65*00b67f09SDavid van Moolenbroek #include <dlz_list.h>
66*00b67f09SDavid van Moolenbroek #include <dlz_dbi.h>
67*00b67f09SDavid van Moolenbroek #include <dlz_pthread.h>
68*00b67f09SDavid van Moolenbroek 
69*00b67f09SDavid van Moolenbroek /*%
70*00b67f09SDavid van Moolenbroek  * properly destroys a querylist by de-allocating the
71*00b67f09SDavid van Moolenbroek  * memory for each query segment, and then the list itself
72*00b67f09SDavid van Moolenbroek  */
73*00b67f09SDavid van Moolenbroek 
74*00b67f09SDavid van Moolenbroek void
destroy_querylist(query_list_t ** querylist)75*00b67f09SDavid van Moolenbroek destroy_querylist(query_list_t **querylist) {
76*00b67f09SDavid van Moolenbroek 	query_segment_t *tseg = NULL;
77*00b67f09SDavid van Moolenbroek 	query_segment_t *nseg = NULL;
78*00b67f09SDavid van Moolenbroek 
79*00b67f09SDavid van Moolenbroek 	/* if query list is null, nothing to do */
80*00b67f09SDavid van Moolenbroek 	if (*querylist == NULL)
81*00b67f09SDavid van Moolenbroek 		return;
82*00b67f09SDavid van Moolenbroek 
83*00b67f09SDavid van Moolenbroek 	/* start at the top of the list */
84*00b67f09SDavid van Moolenbroek 	nseg = DLZ_LIST_HEAD(**querylist);
85*00b67f09SDavid van Moolenbroek 	while (nseg != NULL) {	/* loop, until end of list */
86*00b67f09SDavid van Moolenbroek 		tseg = nseg;
87*00b67f09SDavid van Moolenbroek 		/*
88*00b67f09SDavid van Moolenbroek 		 * free the query segment's text string but only if it
89*00b67f09SDavid van Moolenbroek 		 * was really a query segment, and not a pointer to
90*00b67f09SDavid van Moolenbroek 		 * %zone%, or %record%, or %client%
91*00b67f09SDavid van Moolenbroek 		*/
92*00b67f09SDavid van Moolenbroek 		if (tseg->cmd != NULL && tseg->direct == ISC_TRUE)
93*00b67f09SDavid van Moolenbroek 			free(tseg->cmd);
94*00b67f09SDavid van Moolenbroek 		/* get the next query segment, before we destroy this one. */
95*00b67f09SDavid van Moolenbroek 		nseg = DLZ_LIST_NEXT(nseg, link);
96*00b67f09SDavid van Moolenbroek 		/* deallocate this query segment. */
97*00b67f09SDavid van Moolenbroek 		free(tseg);
98*00b67f09SDavid van Moolenbroek 	}
99*00b67f09SDavid van Moolenbroek 	/* deallocate the query segment list */
100*00b67f09SDavid van Moolenbroek 	free(*querylist);
101*00b67f09SDavid van Moolenbroek }
102*00b67f09SDavid van Moolenbroek 
103*00b67f09SDavid van Moolenbroek /*% constructs a query list by parsing a string into query segments */
104*00b67f09SDavid van Moolenbroek isc_result_t
build_querylist(const char * query_str,char ** zone,char ** record,char ** client,query_list_t ** querylist,unsigned int flags,log_t log)105*00b67f09SDavid van Moolenbroek build_querylist(const char *query_str, char **zone, char **record,
106*00b67f09SDavid van Moolenbroek 		char **client, query_list_t **querylist, unsigned int flags,
107*00b67f09SDavid van Moolenbroek 		log_t log)
108*00b67f09SDavid van Moolenbroek {
109*00b67f09SDavid van Moolenbroek 	isc_result_t result;
110*00b67f09SDavid van Moolenbroek 	isc_boolean_t foundzone = ISC_FALSE;
111*00b67f09SDavid van Moolenbroek 	isc_boolean_t foundrecord = ISC_FALSE;
112*00b67f09SDavid van Moolenbroek 	isc_boolean_t foundclient = ISC_FALSE;
113*00b67f09SDavid van Moolenbroek 	char *temp_str = NULL;
114*00b67f09SDavid van Moolenbroek 	char *right_str = NULL;
115*00b67f09SDavid van Moolenbroek 	query_list_t *tql;
116*00b67f09SDavid van Moolenbroek 	query_segment_t *tseg = NULL;
117*00b67f09SDavid van Moolenbroek 
118*00b67f09SDavid van Moolenbroek 	/* if query string is null, or zero length */
119*00b67f09SDavid van Moolenbroek 	if (query_str == NULL || strlen(query_str) < 1) {
120*00b67f09SDavid van Moolenbroek 		if ((flags & REQUIRE_QUERY) == 0)
121*00b67f09SDavid van Moolenbroek 			/* we don't need it were ok. */
122*00b67f09SDavid van Moolenbroek 			return (ISC_R_SUCCESS);
123*00b67f09SDavid van Moolenbroek 		else
124*00b67f09SDavid van Moolenbroek 			/* we did need it, PROBLEM!!! */
125*00b67f09SDavid van Moolenbroek 			return (ISC_R_FAILURE);
126*00b67f09SDavid van Moolenbroek 	}
127*00b67f09SDavid van Moolenbroek 
128*00b67f09SDavid van Moolenbroek 	/* allocate memory for query list */
129*00b67f09SDavid van Moolenbroek 	tql = calloc(1, sizeof(query_list_t));
130*00b67f09SDavid van Moolenbroek 	/* couldn't allocate memory.  Problem!! */
131*00b67f09SDavid van Moolenbroek 	if (tql == NULL)
132*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOMEMORY);
133*00b67f09SDavid van Moolenbroek 
134*00b67f09SDavid van Moolenbroek 	/* initialize the query segment list */
135*00b67f09SDavid van Moolenbroek 	DLZ_LIST_INIT(*tql);
136*00b67f09SDavid van Moolenbroek 
137*00b67f09SDavid van Moolenbroek 	/* make a copy of query_str so we can chop it up */
138*00b67f09SDavid van Moolenbroek 	temp_str = right_str = strdup(query_str);
139*00b67f09SDavid van Moolenbroek 	/* couldn't make a copy, problem!! */
140*00b67f09SDavid van Moolenbroek 	if (right_str == NULL) {
141*00b67f09SDavid van Moolenbroek 		result = ISC_R_NOMEMORY;
142*00b67f09SDavid van Moolenbroek 		goto cleanup;
143*00b67f09SDavid van Moolenbroek 	}
144*00b67f09SDavid van Moolenbroek 
145*00b67f09SDavid van Moolenbroek 	/* loop through the string and chop it up */
146*00b67f09SDavid van Moolenbroek 	while (right_str != NULL) {
147*00b67f09SDavid van Moolenbroek 		/* allocate memory for tseg */
148*00b67f09SDavid van Moolenbroek 		tseg = calloc(1, sizeof(query_segment_t));
149*00b67f09SDavid van Moolenbroek 		if (tseg  == NULL) {	/* no memory, clean everything up. */
150*00b67f09SDavid van Moolenbroek 			result = ISC_R_NOMEMORY;
151*00b67f09SDavid van Moolenbroek 			goto cleanup;
152*00b67f09SDavid van Moolenbroek 		}
153*00b67f09SDavid van Moolenbroek 		tseg->cmd = NULL;
154*00b67f09SDavid van Moolenbroek 		tseg->direct = ISC_FALSE;
155*00b67f09SDavid van Moolenbroek 		/* initialize the query segment link */
156*00b67f09SDavid van Moolenbroek 		DLZ_LINK_INIT(tseg, link);
157*00b67f09SDavid van Moolenbroek 		/* append the query segment to the list */
158*00b67f09SDavid van Moolenbroek 		DLZ_LIST_APPEND(*tql, tseg, link);
159*00b67f09SDavid van Moolenbroek 
160*00b67f09SDavid van Moolenbroek 		/*
161*00b67f09SDavid van Moolenbroek 		 * split string at the first "$". set query segment to
162*00b67f09SDavid van Moolenbroek 		 * left portion
163*00b67f09SDavid van Moolenbroek 		 */
164*00b67f09SDavid van Moolenbroek 		tseg->cmd = strdup(strsep(&right_str, "$"));
165*00b67f09SDavid van Moolenbroek 		if (tseg->cmd == NULL) {
166*00b67f09SDavid van Moolenbroek 			/* no memory, clean everything up. */
167*00b67f09SDavid van Moolenbroek 			result = ISC_R_NOMEMORY;
168*00b67f09SDavid van Moolenbroek 			goto cleanup;
169*00b67f09SDavid van Moolenbroek 		}
170*00b67f09SDavid van Moolenbroek 		/* tseg->cmd points directly to a string. */
171*00b67f09SDavid van Moolenbroek 		tseg->direct = ISC_TRUE;
172*00b67f09SDavid van Moolenbroek 		tseg->strlen = strlen(tseg->cmd);
173*00b67f09SDavid van Moolenbroek 
174*00b67f09SDavid van Moolenbroek 		/* check if we encountered "$zone$" token */
175*00b67f09SDavid van Moolenbroek 		if (strcasecmp(tseg->cmd, "zone") == 0) {
176*00b67f09SDavid van Moolenbroek 			/*
177*00b67f09SDavid van Moolenbroek 			 * we don't really need, or want the "zone"
178*00b67f09SDavid van Moolenbroek 			 * text, so get rid of it.
179*00b67f09SDavid van Moolenbroek 			 */
180*00b67f09SDavid van Moolenbroek 			free(tseg->cmd);
181*00b67f09SDavid van Moolenbroek 			/* set tseg->cmd to in-direct zone string */
182*00b67f09SDavid van Moolenbroek 			tseg->cmd = (char**) zone;
183*00b67f09SDavid van Moolenbroek 			tseg->strlen = 0;
184*00b67f09SDavid van Moolenbroek 			/* tseg->cmd points in-directly to a string */
185*00b67f09SDavid van Moolenbroek 			tseg->direct = ISC_FALSE;
186*00b67f09SDavid van Moolenbroek 			foundzone = ISC_TRUE;
187*00b67f09SDavid van Moolenbroek 			/* check if we encountered "$record$" token */
188*00b67f09SDavid van Moolenbroek 		} else if (strcasecmp(tseg->cmd, "record") == 0) {
189*00b67f09SDavid van Moolenbroek 			/*
190*00b67f09SDavid van Moolenbroek 			 * we don't really need, or want the "record"
191*00b67f09SDavid van Moolenbroek 			 * text, so get rid of it.
192*00b67f09SDavid van Moolenbroek 			 */
193*00b67f09SDavid van Moolenbroek 			free(tseg->cmd);
194*00b67f09SDavid van Moolenbroek 			/* set tseg->cmd to in-direct record string */
195*00b67f09SDavid van Moolenbroek 			tseg->cmd = (char**) record;
196*00b67f09SDavid van Moolenbroek 			tseg->strlen = 0;
197*00b67f09SDavid van Moolenbroek 			/* tseg->cmd points in-directly poinsts to a string */
198*00b67f09SDavid van Moolenbroek 			tseg->direct = ISC_FALSE;
199*00b67f09SDavid van Moolenbroek 			foundrecord = ISC_TRUE;
200*00b67f09SDavid van Moolenbroek 			/* check if we encountered "$client$" token */
201*00b67f09SDavid van Moolenbroek 		} else if (strcasecmp(tseg->cmd, "client") == 0) {
202*00b67f09SDavid van Moolenbroek 			/*
203*00b67f09SDavid van Moolenbroek 			 * we don't really need, or want the "client"
204*00b67f09SDavid van Moolenbroek 			 * text, so get rid of it.
205*00b67f09SDavid van Moolenbroek 			 */
206*00b67f09SDavid van Moolenbroek 			free(tseg->cmd);
207*00b67f09SDavid van Moolenbroek 			/* set tseg->cmd to in-direct record string */
208*00b67f09SDavid van Moolenbroek 			tseg->cmd = (char**) client;
209*00b67f09SDavid van Moolenbroek 			tseg->strlen = 0;
210*00b67f09SDavid van Moolenbroek 			/* tseg->cmd points in-directly poinsts to a string */
211*00b67f09SDavid van Moolenbroek 			tseg->direct = ISC_FALSE;
212*00b67f09SDavid van Moolenbroek 			foundclient = ISC_TRUE;
213*00b67f09SDavid van Moolenbroek 		}
214*00b67f09SDavid van Moolenbroek 	}
215*00b67f09SDavid van Moolenbroek 
216*00b67f09SDavid van Moolenbroek 	/* we don't need temp_str any more */
217*00b67f09SDavid van Moolenbroek 	free(temp_str);
218*00b67f09SDavid van Moolenbroek 	/*
219*00b67f09SDavid van Moolenbroek 	 * add checks later to verify zone and record are found if
220*00b67f09SDavid van Moolenbroek 	 * necessary.
221*00b67f09SDavid van Moolenbroek 	 */
222*00b67f09SDavid van Moolenbroek 
223*00b67f09SDavid van Moolenbroek 	/* if this query requires %client%, make sure we found it */
224*00b67f09SDavid van Moolenbroek 	if (((flags & REQUIRE_CLIENT) != 0) && (!foundclient) ) {
225*00b67f09SDavid van Moolenbroek 		/* Write error message to log */
226*00b67f09SDavid van Moolenbroek 		if (log != NULL)
227*00b67f09SDavid van Moolenbroek 			log(ISC_LOG_ERROR,
228*00b67f09SDavid van Moolenbroek 			    "Required token $client$ not found.");
229*00b67f09SDavid van Moolenbroek 		result = ISC_R_FAILURE;
230*00b67f09SDavid van Moolenbroek 		goto flag_fail;
231*00b67f09SDavid van Moolenbroek 	}
232*00b67f09SDavid van Moolenbroek 
233*00b67f09SDavid van Moolenbroek 	/* if this query requires %record%, make sure we found it */
234*00b67f09SDavid van Moolenbroek 	if (((flags & REQUIRE_RECORD) != 0) && (!foundrecord) ) {
235*00b67f09SDavid van Moolenbroek 		/* Write error message to log */
236*00b67f09SDavid van Moolenbroek 		if (log != NULL)
237*00b67f09SDavid van Moolenbroek 			log(ISC_LOG_ERROR,
238*00b67f09SDavid van Moolenbroek 			    "Required token $record$ not found.");
239*00b67f09SDavid van Moolenbroek 		result = ISC_R_FAILURE;
240*00b67f09SDavid van Moolenbroek 		goto flag_fail;
241*00b67f09SDavid van Moolenbroek 	}
242*00b67f09SDavid van Moolenbroek 
243*00b67f09SDavid van Moolenbroek 	/* if this query requires %zone%, make sure we found it */
244*00b67f09SDavid van Moolenbroek 	if (((flags & REQUIRE_ZONE) != 0) && (!foundzone) ) {
245*00b67f09SDavid van Moolenbroek 		/* Write error message to log */
246*00b67f09SDavid van Moolenbroek 		if (log != NULL)
247*00b67f09SDavid van Moolenbroek 			log(ISC_LOG_ERROR, "Required token $zone$ not found.");
248*00b67f09SDavid van Moolenbroek 		result = ISC_R_FAILURE;
249*00b67f09SDavid van Moolenbroek 		goto flag_fail;
250*00b67f09SDavid van Moolenbroek 	}
251*00b67f09SDavid van Moolenbroek 
252*00b67f09SDavid van Moolenbroek 	/* pass back the query list */
253*00b67f09SDavid van Moolenbroek 	*querylist = (query_list_t *) tql;
254*00b67f09SDavid van Moolenbroek 
255*00b67f09SDavid van Moolenbroek 	/* return success */
256*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
257*00b67f09SDavid van Moolenbroek 
258*00b67f09SDavid van Moolenbroek  cleanup:
259*00b67f09SDavid van Moolenbroek 	/* get rid of temp_str */
260*00b67f09SDavid van Moolenbroek 	if (temp_str != NULL)
261*00b67f09SDavid van Moolenbroek 		free(temp_str);
262*00b67f09SDavid van Moolenbroek 
263*00b67f09SDavid van Moolenbroek  flag_fail:
264*00b67f09SDavid van Moolenbroek 	/* get rid of what was build of the query list */
265*00b67f09SDavid van Moolenbroek 	if (tql != NULL)
266*00b67f09SDavid van Moolenbroek 		destroy_querylist(&tql);
267*00b67f09SDavid van Moolenbroek 	return (result);
268*00b67f09SDavid van Moolenbroek }
269*00b67f09SDavid van Moolenbroek 
270*00b67f09SDavid van Moolenbroek /*%
271*00b67f09SDavid van Moolenbroek  * build a query string from query segments, and dynamic segments
272*00b67f09SDavid van Moolenbroek  * dynamic segments replace where the tokens %zone%, %record%, %client%
273*00b67f09SDavid van Moolenbroek  * used to be in our queries from named.conf
274*00b67f09SDavid van Moolenbroek  */
275*00b67f09SDavid van Moolenbroek char *
build_querystring(query_list_t * querylist)276*00b67f09SDavid van Moolenbroek build_querystring(query_list_t *querylist) {
277*00b67f09SDavid van Moolenbroek 	query_segment_t *tseg = NULL;
278*00b67f09SDavid van Moolenbroek 	unsigned int length = 0;
279*00b67f09SDavid van Moolenbroek 	char *qs = NULL;
280*00b67f09SDavid van Moolenbroek 
281*00b67f09SDavid van Moolenbroek 	/* start at the top of the list */
282*00b67f09SDavid van Moolenbroek 	tseg = DLZ_LIST_HEAD(*querylist);
283*00b67f09SDavid van Moolenbroek 	while (tseg != NULL) {
284*00b67f09SDavid van Moolenbroek 		/*
285*00b67f09SDavid van Moolenbroek 		 * if this is a query segment, use the
286*00b67f09SDavid van Moolenbroek 		 * precalculated string length
287*00b67f09SDavid van Moolenbroek 		 */
288*00b67f09SDavid van Moolenbroek 		if (tseg->direct == ISC_TRUE)
289*00b67f09SDavid van Moolenbroek 			length += tseg->strlen;
290*00b67f09SDavid van Moolenbroek 		else	/* calculate string length for dynamic segments. */
291*00b67f09SDavid van Moolenbroek 			length += strlen(* (char**) tseg->cmd);
292*00b67f09SDavid van Moolenbroek 		/* get the next segment */
293*00b67f09SDavid van Moolenbroek 		tseg = DLZ_LIST_NEXT(tseg, link);
294*00b67f09SDavid van Moolenbroek 	}
295*00b67f09SDavid van Moolenbroek 
296*00b67f09SDavid van Moolenbroek 	qs = malloc(length + 1);
297*00b67f09SDavid van Moolenbroek 	if (qs == NULL)
298*00b67f09SDavid van Moolenbroek 		return (NULL);
299*00b67f09SDavid van Moolenbroek 
300*00b67f09SDavid van Moolenbroek 	*qs = '\0';
301*00b67f09SDavid van Moolenbroek 	/* start at the top of the list again */
302*00b67f09SDavid van Moolenbroek 	tseg = DLZ_LIST_HEAD(*querylist);
303*00b67f09SDavid van Moolenbroek 	while (tseg != NULL) {
304*00b67f09SDavid van Moolenbroek 		if (tseg->direct == ISC_TRUE)
305*00b67f09SDavid van Moolenbroek 			/* query segments */
306*00b67f09SDavid van Moolenbroek 			strcat(qs, tseg->cmd);
307*00b67f09SDavid van Moolenbroek 		else
308*00b67f09SDavid van Moolenbroek 			/* dynamic segments */
309*00b67f09SDavid van Moolenbroek 			strcat(qs, * (char**) tseg->cmd);
310*00b67f09SDavid van Moolenbroek 		/* get the next segment */
311*00b67f09SDavid van Moolenbroek 		tseg = DLZ_LIST_NEXT(tseg, link);
312*00b67f09SDavid van Moolenbroek 	}
313*00b67f09SDavid van Moolenbroek 
314*00b67f09SDavid van Moolenbroek 	return (qs);
315*00b67f09SDavid van Moolenbroek }
316*00b67f09SDavid van Moolenbroek 
317*00b67f09SDavid van Moolenbroek /*% constructs a dbinstance (DBI) */
318*00b67f09SDavid van Moolenbroek isc_result_t
build_dbinstance(const char * allnodes_str,const char * allowxfr_str,const char * authority_str,const char * findzone_str,const char * lookup_str,const char * countzone_str,dbinstance_t ** dbi,log_t log)319*00b67f09SDavid van Moolenbroek build_dbinstance(const char *allnodes_str, const char *allowxfr_str,
320*00b67f09SDavid van Moolenbroek 		 const char *authority_str, const char *findzone_str,
321*00b67f09SDavid van Moolenbroek 		 const char *lookup_str, const char *countzone_str,
322*00b67f09SDavid van Moolenbroek 		 dbinstance_t **dbi, log_t log)
323*00b67f09SDavid van Moolenbroek {
324*00b67f09SDavid van Moolenbroek 
325*00b67f09SDavid van Moolenbroek 	isc_result_t result;
326*00b67f09SDavid van Moolenbroek 	dbinstance_t *db = NULL;
327*00b67f09SDavid van Moolenbroek 	int err;
328*00b67f09SDavid van Moolenbroek 
329*00b67f09SDavid van Moolenbroek 	/* allocate and zero memory for driver structure */
330*00b67f09SDavid van Moolenbroek 	db = calloc(1, sizeof(dbinstance_t));
331*00b67f09SDavid van Moolenbroek 	if (db == NULL) {
332*00b67f09SDavid van Moolenbroek 		if (log != NULL)
333*00b67f09SDavid van Moolenbroek 			log(ISC_LOG_ERROR,
334*00b67f09SDavid van Moolenbroek 			    "Could not allocate memory for "
335*00b67f09SDavid van Moolenbroek 			    "database instance object.");
336*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOMEMORY);
337*00b67f09SDavid van Moolenbroek 	}
338*00b67f09SDavid van Moolenbroek 	memset(db, 0, sizeof(dbinstance_t));
339*00b67f09SDavid van Moolenbroek 	db->dbconn = NULL;
340*00b67f09SDavid van Moolenbroek 	db->client = NULL;
341*00b67f09SDavid van Moolenbroek 	db->record = NULL;
342*00b67f09SDavid van Moolenbroek 	db->zone = NULL;
343*00b67f09SDavid van Moolenbroek 	db->query_buf = NULL;
344*00b67f09SDavid van Moolenbroek 	db->allnodes_q = NULL;
345*00b67f09SDavid van Moolenbroek 	db->allowxfr_q = NULL;
346*00b67f09SDavid van Moolenbroek 	db->authority_q = NULL;
347*00b67f09SDavid van Moolenbroek 	db->findzone_q = NULL;
348*00b67f09SDavid van Moolenbroek 	db->countzone_q = NULL;
349*00b67f09SDavid van Moolenbroek 	db->lookup_q = NULL;
350*00b67f09SDavid van Moolenbroek 
351*00b67f09SDavid van Moolenbroek 	/* initialize the reference count mutex */
352*00b67f09SDavid van Moolenbroek 	err = dlz_mutex_init(&db->lock, NULL);
353*00b67f09SDavid van Moolenbroek 	if (err == ENOMEM) {
354*00b67f09SDavid van Moolenbroek 		result = ISC_R_NOMEMORY;
355*00b67f09SDavid van Moolenbroek 		goto cleanup;
356*00b67f09SDavid van Moolenbroek 	} else if (err != 0) {
357*00b67f09SDavid van Moolenbroek 		result = ISC_R_UNEXPECTED;
358*00b67f09SDavid van Moolenbroek 		goto cleanup;
359*00b67f09SDavid van Moolenbroek 	}
360*00b67f09SDavid van Moolenbroek 
361*00b67f09SDavid van Moolenbroek 	/* build the all nodes query list */
362*00b67f09SDavid van Moolenbroek 	result = build_querylist(allnodes_str, &db->zone, &db->record,
363*00b67f09SDavid van Moolenbroek 				 &db->client, &db->allnodes_q,
364*00b67f09SDavid van Moolenbroek 				 REQUIRE_ZONE, log);
365*00b67f09SDavid van Moolenbroek 	/* if unsuccessful, log err msg and cleanup */
366*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
367*00b67f09SDavid van Moolenbroek 		if (log != NULL)
368*00b67f09SDavid van Moolenbroek 			log(ISC_LOG_ERROR,
369*00b67f09SDavid van Moolenbroek 			    "Could not build all nodes query list");
370*00b67f09SDavid van Moolenbroek 		goto cleanup;
371*00b67f09SDavid van Moolenbroek 	}
372*00b67f09SDavid van Moolenbroek 
373*00b67f09SDavid van Moolenbroek 	/* build the allow zone transfer query list */
374*00b67f09SDavid van Moolenbroek 	result = build_querylist(allowxfr_str, &db->zone, &db->record,
375*00b67f09SDavid van Moolenbroek 				 &db->client, &db->allowxfr_q,
376*00b67f09SDavid van Moolenbroek 				 REQUIRE_ZONE | REQUIRE_CLIENT,
377*00b67f09SDavid van Moolenbroek 				 log);
378*00b67f09SDavid van Moolenbroek 	/* if unsuccessful, log err msg and cleanup */
379*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
380*00b67f09SDavid van Moolenbroek 		if (log != NULL)
381*00b67f09SDavid van Moolenbroek 			log(ISC_LOG_ERROR,
382*00b67f09SDavid van Moolenbroek 			    "Could not build allow xfr query list");
383*00b67f09SDavid van Moolenbroek 		goto cleanup;
384*00b67f09SDavid van Moolenbroek 	}
385*00b67f09SDavid van Moolenbroek 
386*00b67f09SDavid van Moolenbroek 	/* build the authority query, query list */
387*00b67f09SDavid van Moolenbroek 	result = build_querylist(authority_str, &db->zone, &db->record,
388*00b67f09SDavid van Moolenbroek 				 &db->client, &db->authority_q,
389*00b67f09SDavid van Moolenbroek 				 REQUIRE_ZONE, log);
390*00b67f09SDavid van Moolenbroek 	/* if unsuccessful, log err msg and cleanup */
391*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
392*00b67f09SDavid van Moolenbroek 		if (log != NULL)
393*00b67f09SDavid van Moolenbroek 			log(ISC_LOG_ERROR,
394*00b67f09SDavid van Moolenbroek 			    "Could not build authority query list");
395*00b67f09SDavid van Moolenbroek 		goto cleanup;
396*00b67f09SDavid van Moolenbroek 	}
397*00b67f09SDavid van Moolenbroek 
398*00b67f09SDavid van Moolenbroek 	/* build findzone query, query list */
399*00b67f09SDavid van Moolenbroek 	result = build_querylist(findzone_str, &db->zone, &db->record,
400*00b67f09SDavid van Moolenbroek 				 &db->client, &db->findzone_q,
401*00b67f09SDavid van Moolenbroek 				 REQUIRE_ZONE, log);
402*00b67f09SDavid van Moolenbroek 	/* if unsuccessful, log err msg and cleanup */
403*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
404*00b67f09SDavid van Moolenbroek 		if (log != NULL)
405*00b67f09SDavid van Moolenbroek 			log(ISC_LOG_ERROR,
406*00b67f09SDavid van Moolenbroek 			    "Could not build find zone query list");
407*00b67f09SDavid van Moolenbroek 		goto cleanup;
408*00b67f09SDavid van Moolenbroek 	}
409*00b67f09SDavid van Moolenbroek 
410*00b67f09SDavid van Moolenbroek 	/* build countzone query, query list */
411*00b67f09SDavid van Moolenbroek 	result = build_querylist(countzone_str, &db->zone, &db->record,
412*00b67f09SDavid van Moolenbroek 				 &db->client, &db->countzone_q,
413*00b67f09SDavid van Moolenbroek 				 REQUIRE_ZONE, log);
414*00b67f09SDavid van Moolenbroek 	/* if unsuccessful, log err msg and cleanup */
415*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
416*00b67f09SDavid van Moolenbroek 		if (log != NULL)
417*00b67f09SDavid van Moolenbroek 			log(ISC_LOG_ERROR,
418*00b67f09SDavid van Moolenbroek 			    "Could not build count zone query list");
419*00b67f09SDavid van Moolenbroek 		goto cleanup;
420*00b67f09SDavid van Moolenbroek 	}
421*00b67f09SDavid van Moolenbroek 
422*00b67f09SDavid van Moolenbroek 	/* build lookup query, query list */
423*00b67f09SDavid van Moolenbroek 	result = build_querylist(lookup_str, &db->zone, &db->record,
424*00b67f09SDavid van Moolenbroek 				 &db->client, &db->lookup_q,
425*00b67f09SDavid van Moolenbroek 				 REQUIRE_RECORD, log);
426*00b67f09SDavid van Moolenbroek 	/* if unsuccessful, log err msg and cleanup */
427*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
428*00b67f09SDavid van Moolenbroek 		if (log != NULL)
429*00b67f09SDavid van Moolenbroek 			log(ISC_LOG_ERROR,
430*00b67f09SDavid van Moolenbroek 			    "Could not build lookup query list");
431*00b67f09SDavid van Moolenbroek 		goto cleanup;
432*00b67f09SDavid van Moolenbroek 	}
433*00b67f09SDavid van Moolenbroek 
434*00b67f09SDavid van Moolenbroek 	/* pass back the db instance */
435*00b67f09SDavid van Moolenbroek 	*dbi = (dbinstance_t *) db;
436*00b67f09SDavid van Moolenbroek 
437*00b67f09SDavid van Moolenbroek 	/* return success */
438*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
439*00b67f09SDavid van Moolenbroek 
440*00b67f09SDavid van Moolenbroek  cleanup:
441*00b67f09SDavid van Moolenbroek 	/* destroy whatever was build of the db instance */
442*00b67f09SDavid van Moolenbroek 	destroy_dbinstance(db);
443*00b67f09SDavid van Moolenbroek 	/* return failure */
444*00b67f09SDavid van Moolenbroek 	return (ISC_R_FAILURE);
445*00b67f09SDavid van Moolenbroek }
446*00b67f09SDavid van Moolenbroek 
447*00b67f09SDavid van Moolenbroek void
destroy_dbinstance(dbinstance_t * dbi)448*00b67f09SDavid van Moolenbroek destroy_dbinstance(dbinstance_t *dbi) {
449*00b67f09SDavid van Moolenbroek 	/* destroy any query lists we created */
450*00b67f09SDavid van Moolenbroek 	destroy_querylist(&dbi->allnodes_q);
451*00b67f09SDavid van Moolenbroek 	destroy_querylist(&dbi->allowxfr_q);
452*00b67f09SDavid van Moolenbroek 	destroy_querylist(&dbi->authority_q);
453*00b67f09SDavid van Moolenbroek 	destroy_querylist(&dbi->findzone_q);
454*00b67f09SDavid van Moolenbroek 	destroy_querylist(&dbi->countzone_q);
455*00b67f09SDavid van Moolenbroek 	destroy_querylist(&dbi->lookup_q);
456*00b67f09SDavid van Moolenbroek 
457*00b67f09SDavid van Moolenbroek 	/* get rid of the mutex */
458*00b67f09SDavid van Moolenbroek 	(void) dlz_mutex_destroy(&dbi->lock);
459*00b67f09SDavid van Moolenbroek 
460*00b67f09SDavid van Moolenbroek 	/* return, and detach the memory */
461*00b67f09SDavid van Moolenbroek 	free(dbi);
462*00b67f09SDavid van Moolenbroek }
463*00b67f09SDavid van Moolenbroek 
464*00b67f09SDavid van Moolenbroek char *
get_parameter_value(const char * input,const char * key)465*00b67f09SDavid van Moolenbroek get_parameter_value(const char *input, const char* key) {
466*00b67f09SDavid van Moolenbroek 	int keylen;
467*00b67f09SDavid van Moolenbroek 	char *keystart;
468*00b67f09SDavid van Moolenbroek 	char value[255];
469*00b67f09SDavid van Moolenbroek 	int i;
470*00b67f09SDavid van Moolenbroek 
471*00b67f09SDavid van Moolenbroek 	if (key == NULL || input == NULL || *input == '\0')
472*00b67f09SDavid van Moolenbroek 		return (NULL);
473*00b67f09SDavid van Moolenbroek 
474*00b67f09SDavid van Moolenbroek 	keylen = strlen(key);
475*00b67f09SDavid van Moolenbroek 
476*00b67f09SDavid van Moolenbroek 	if (keylen < 1)
477*00b67f09SDavid van Moolenbroek 		return (NULL);
478*00b67f09SDavid van Moolenbroek 
479*00b67f09SDavid van Moolenbroek 	keystart = strstr(input, key);
480*00b67f09SDavid van Moolenbroek 
481*00b67f09SDavid van Moolenbroek 	if (keystart == NULL)
482*00b67f09SDavid van Moolenbroek 		return (NULL);
483*00b67f09SDavid van Moolenbroek 
484*00b67f09SDavid van Moolenbroek 	for (i = 0; i < 255; i++) {
485*00b67f09SDavid van Moolenbroek 		value[i] = keystart[keylen + i];
486*00b67f09SDavid van Moolenbroek 		if (isspace(value[i]) || value[i] == '\0') {
487*00b67f09SDavid van Moolenbroek 			value[i] = '\0';
488*00b67f09SDavid van Moolenbroek 			break;
489*00b67f09SDavid van Moolenbroek 		}
490*00b67f09SDavid van Moolenbroek 	}
491*00b67f09SDavid van Moolenbroek 
492*00b67f09SDavid van Moolenbroek 	return (strdup(value));
493*00b67f09SDavid van Moolenbroek }
494