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