No empty .Rs/.Re
[netbsd-mini2440.git] / external / bsd / bind / dist / contrib / dlz / drivers / sdlz_helper.c
blobf2acf76c8dbcad6478db7ada9384a2e728b59fd4
1 /* $NetBSD$ */
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) 1999-2001 Internet Software Consortium.
41 * Permission to use, copy, modify, and distribute this software for any
42 * purpose with or without fee is hereby granted, provided that the above
43 * copyright notice and this permission notice appear in all copies.
45 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
46 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
48 * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
49 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
50 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
51 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
52 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
55 #ifdef DLZ
57 #include <config.h>
59 #include <dns/log.h>
60 #include <dns/result.h>
62 #include <isc/mem.h>
63 #include <isc/result.h>
64 #include <isc/string.h>
65 #include <isc/util.h>
67 #include <dlz/sdlz_helper.h>
70 * sdlz helper methods
73 /*%
74 * properly destroys a querylist by de-allocating the
75 * memory for each query segment, and then the list itself
78 static void
79 destroy_querylist(isc_mem_t *mctx, query_list_t **querylist)
81 query_segment_t *tseg = NULL;
82 query_segment_t *nseg = NULL;
84 REQUIRE(mctx != NULL);
86 /* if query list is null, nothing to do */
87 if (*querylist == NULL)
88 return;
90 /* start at the top of the list */
91 nseg = ISC_LIST_HEAD(**querylist);
92 while (nseg != NULL) { /* loop, until end of list */
93 tseg = nseg;
95 * free the query segment's text string but only if it
96 * was really a query segment, and not a pointer to
97 * %zone%, or %record%, or %client%
99 if (tseg->sql != NULL && tseg->direct == isc_boolean_true)
100 isc_mem_free(mctx, tseg->sql);
101 /* get the next query segment, before we destroy this one. */
102 nseg = ISC_LIST_NEXT(nseg, link);
103 /* deallocate this query segment. */
104 isc_mem_put(mctx, tseg, sizeof(query_segment_t));
106 /* deallocate the query segment list */
107 isc_mem_put(mctx, *querylist, sizeof(query_list_t));
110 /*% constructs a query list by parsing a string into query segments */
111 static isc_result_t
112 build_querylist(isc_mem_t *mctx, const char *query_str, char **zone,
113 char **record, char **client, query_list_t **querylist,
114 unsigned int flags)
116 isc_result_t result;
117 isc_boolean_t foundzone = isc_boolean_false;
118 isc_boolean_t foundrecord = isc_boolean_false;
119 isc_boolean_t foundclient = isc_boolean_false;
120 char *temp_str = NULL;
121 char *right_str = NULL;
122 query_list_t *tql;
123 query_segment_t *tseg = NULL;
125 REQUIRE(querylist != NULL && *querylist == NULL);
126 REQUIRE(mctx != NULL);
128 /* if query string is null, or zero length */
129 if (query_str == NULL || strlen(query_str) < 1) {
130 if ((flags & SDLZH_REQUIRE_QUERY) == 0)
131 /* we don't need it were ok. */
132 return (ISC_R_SUCCESS);
133 else
134 /* we did need it, PROBLEM!!! */
135 return (ISC_R_FAILURE);
138 /* allocate memory for query list */
139 tql = isc_mem_get(mctx, sizeof(query_list_t));
140 /* couldn't allocate memory. Problem!! */
141 if (tql == NULL)
142 return (ISC_R_NOMEMORY);
144 /* initialize the query segment list */
145 ISC_LIST_INIT(*tql);
147 /* make a copy of query_str so we can chop it up */
148 temp_str = right_str = isc_mem_strdup(mctx, query_str);
149 /* couldn't make a copy, problem!! */
150 if (right_str == NULL) {
151 result = ISC_R_NOMEMORY;
152 goto cleanup;
155 /* loop through the string and chop it up */
156 while (right_str != NULL) {
157 /* allocate memory for tseg */
158 tseg = isc_mem_get(mctx, sizeof(query_segment_t));
159 if (tseg == NULL) { /* no memory, clean everything up. */
160 result = ISC_R_NOMEMORY;
161 goto cleanup;
163 tseg->sql = NULL;
164 tseg->direct = isc_boolean_false;
165 /* initialize the query segment link */
166 ISC_LINK_INIT(tseg, link);
167 /* append the query segment to the list */
168 ISC_LIST_APPEND(*tql, tseg, link);
171 * split string at the first "%". set query segment to
172 * left portion
174 tseg->sql = isc_mem_strdup(mctx,
175 isc_string_separate(&right_str,
176 "%"));
177 if (tseg->sql == NULL) {
178 /* no memory, clean everything up. */
179 result = ISC_R_NOMEMORY;
180 goto cleanup;
182 /* tseg->sql points directly to a string. */
183 tseg->direct = isc_boolean_true;
184 tseg->strlen = strlen(tseg->sql);
186 /* check if we encountered "%zone%" token */
187 if (strcasecmp(tseg->sql, "zone") == 0) {
189 * we don't really need, or want the "zone"
190 * text, so get rid of it.
192 isc_mem_free(mctx, tseg->sql);
193 /* set tseg->sql to in-direct zone string */
194 tseg->sql = (char**) zone;
195 tseg->strlen = 0;
196 /* tseg->sql points in-directly to a string */
197 tseg->direct = isc_boolean_false;
198 foundzone = isc_boolean_true;
199 /* check if we encountered "%record%" token */
200 } else if (strcasecmp(tseg->sql, "record") == 0) {
202 * we don't really need, or want the "record"
203 * text, so get rid of it.
205 isc_mem_free(mctx, tseg->sql);
206 /* set tseg->sql to in-direct record string */
207 tseg->sql = (char**) record;
208 tseg->strlen = 0;
209 /* tseg->sql points in-directly poinsts to a string */
210 tseg->direct = isc_boolean_false;
211 foundrecord = isc_boolean_true;
212 /* check if we encountered "%client%" token */
213 } else if (strcasecmp(tseg->sql, "client") == 0) {
215 * we don't really need, or want the "client"
216 * text, so get rid of it.
218 isc_mem_free(mctx, tseg->sql);
219 /* set tseg->sql to in-direct record string */
220 tseg->sql = (char**) client;
221 tseg->strlen = 0;
222 /* tseg->sql points in-directly poinsts to a string */
223 tseg->direct = isc_boolean_false;
224 foundclient = isc_boolean_true;
228 /* we don't need temp_str any more */
229 isc_mem_free(mctx, temp_str);
231 * add checks later to verify zone and record are found if
232 * necessary.
235 /* if this query requires %client%, make sure we found it */
236 if (((flags & SDLZH_REQUIRE_CLIENT) != 0) && (!foundclient) ) {
237 /* Write error message to log */
238 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
239 DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
240 "Required token %%client%% not found.");
241 result = ISC_R_FAILURE;
242 goto flag_fail;
245 /* if this query requires %record%, make sure we found it */
246 if (((flags & SDLZH_REQUIRE_RECORD) != 0) && (!foundrecord) ) {
247 /* Write error message to log */
248 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
249 DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
250 "Required token %%record%% not found.");
251 result = ISC_R_FAILURE;
252 goto flag_fail;
255 /* if this query requires %zone%, make sure we found it */
256 if (((flags & SDLZH_REQUIRE_ZONE) != 0) && (!foundzone) ) {
257 /* Write error message to log */
258 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
259 DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
260 "Required token %%zone%% not found.");
261 result = ISC_R_FAILURE;
262 goto flag_fail;
265 /* pass back the query list */
266 *querylist = (query_list_t *) tql;
268 /* return success */
269 return (ISC_R_SUCCESS);
271 cleanup:
272 /* get rid of temp_str */
273 if (temp_str != NULL)
274 isc_mem_free(mctx, temp_str);
276 flag_fail:
277 /* get rid of what was build of the query list */
278 if (tql != NULL)
279 destroy_querylist(mctx, &tql);
280 return result;
284 * build a query string from query segments, and dynamic segments
285 * dynamic segments replace where the tokens %zone%, %record%, %client%
286 * used to be in our queries from named.conf
288 char *
289 sdlzh_build_querystring(isc_mem_t *mctx, query_list_t *querylist)
291 query_segment_t *tseg = NULL;
292 unsigned int length = 0;
293 char *qs = NULL;
295 REQUIRE(mctx != NULL);
296 REQUIRE(querylist != NULL);
298 /* start at the top of the list */
299 tseg = ISC_LIST_HEAD(*querylist);
300 while (tseg != NULL) {
302 * if this is a query segment, use the
303 * precalculated string length
305 if (tseg->direct == isc_boolean_true)
306 length += tseg->strlen;
307 else /* calculate string length for dynamic segments. */
308 length += strlen(* (char**) tseg->sql);
309 /* get the next segment */
310 tseg = ISC_LIST_NEXT(tseg, link);
313 /* allocate memory for the string */
314 qs = isc_mem_allocate(mctx, length + 1);
315 /* couldn't allocate memory, We need more ram! */
316 if (qs == NULL)
317 return NULL;
319 /* start at the top of the list again */
320 tseg = ISC_LIST_HEAD(*querylist);
321 /* copy the first item in the list to the query string */
322 if (tseg->direct == isc_boolean_true) /* query segment */
323 strcpy(qs, tseg->sql);
324 else
325 strcpy(qs, * (char**) tseg->sql); /* dynamic segment */
327 /* concatonate the rest of the segments */
328 while ((tseg = ISC_LIST_NEXT(tseg, link)) != NULL) {
329 if (tseg->direct == isc_boolean_true)
330 /* query segments */
331 strcat(qs, tseg->sql);
332 else
333 /* dynamic segments */
334 strcat(qs, * (char**) tseg->sql);
337 return qs;
340 /*% constructs a sql dbinstance (DBI) */
341 isc_result_t
342 sdlzh_build_sqldbinstance(isc_mem_t *mctx, const char *allnodes_str,
343 const char *allowxfr_str, const char *authority_str,
344 const char *findzone_str, const char *lookup_str,
345 const char *countzone_str, dbinstance_t **dbi)
348 isc_result_t result;
349 dbinstance_t *db = NULL;
351 REQUIRE(dbi != NULL && *dbi == NULL);
352 REQUIRE(mctx != NULL);
354 /* allocate and zero memory for driver structure */
355 db = isc_mem_get(mctx, sizeof(dbinstance_t));
356 if (db == NULL) {
357 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
358 DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
359 "Could not allocate memory for "
360 "database instance object.");
361 return (ISC_R_NOMEMORY);
363 memset(db, 0, sizeof(dbinstance_t));
364 db->dbconn = NULL;
365 db->client = NULL;
366 db->record = NULL;
367 db->zone = NULL;
368 db->mctx = NULL;
369 db->query_buf = NULL;
370 db->allnodes_q = NULL;
371 db->allowxfr_q = NULL;
372 db->authority_q = NULL;
373 db->findzone_q = NULL;
374 db->countzone_q = NULL;
375 db->lookup_q = NULL;
377 /* attach to the memory context */
378 isc_mem_attach(mctx, &db->mctx);
380 /* initialize the reference count mutex */
381 result = isc_mutex_init(&db->instance_lock);
382 if (result != ISC_R_SUCCESS) {
383 UNEXPECTED_ERROR(__FILE__, __LINE__,
384 "isc_mutex_init() failed: %s",
385 isc_result_totext(result));
386 goto cleanup;
389 /* build the all nodes query list */
390 result = build_querylist(mctx, allnodes_str, &db->zone,
391 &db->record, &db->client,
392 &db->allnodes_q, SDLZH_REQUIRE_ZONE);
393 /* if unsuccessful, log err msg and cleanup */
394 if (result != ISC_R_SUCCESS) {
395 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
396 DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
397 "Could not build all nodes query list");
398 goto cleanup;
401 /* build the allow zone transfer query list */
402 result = build_querylist(mctx, allowxfr_str, &db->zone,
403 &db->record, &db->client,
404 &db->allowxfr_q,
405 SDLZH_REQUIRE_ZONE | SDLZH_REQUIRE_CLIENT);
406 /* if unsuccessful, log err msg and cleanup */
407 if (result != ISC_R_SUCCESS) {
408 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
409 DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
410 "Could not build allow xfr query list");
411 goto cleanup;
414 /* build the authority query, query list */
415 result = build_querylist(mctx, authority_str, &db->zone,
416 &db->record, &db->client,
417 &db->authority_q, SDLZH_REQUIRE_ZONE);
418 /* if unsuccessful, log err msg and cleanup */
419 if (result != ISC_R_SUCCESS) {
420 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
421 DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
422 "Could not build authority query list");
423 goto cleanup;
426 /* build findzone query, query list */
427 result = build_querylist(mctx, findzone_str, &db->zone,
428 &db->record, &db->client,
429 &db->findzone_q, SDLZH_REQUIRE_ZONE);
430 /* if unsuccessful, log err msg and cleanup */
431 if (result != ISC_R_SUCCESS) {
432 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
433 DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
434 "Could not build find zone query list");
435 goto cleanup;
438 /* build countzone query, query list */
439 result = build_querylist(mctx, countzone_str, &db->zone,
440 &db->record, &db->client,
441 &db->countzone_q, SDLZH_REQUIRE_ZONE);
442 /* if unsuccessful, log err msg and cleanup */
443 if (result != ISC_R_SUCCESS) {
444 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
445 DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
446 "Could not build count zone query list");
447 goto cleanup;
450 /* build lookup query, query list */
451 result = build_querylist(mctx, lookup_str, &db->zone,
452 &db->record, &db->client,
453 &db->lookup_q, SDLZH_REQUIRE_RECORD);
454 /* if unsuccessful, log err msg and cleanup */
455 if (result != ISC_R_SUCCESS) {
456 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
457 DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
458 "Could not build lookup query list");
459 goto cleanup;
462 /* pass back the db instance */
463 *dbi = (dbinstance_t *) db;
465 /* return success */
466 return (ISC_R_SUCCESS);
468 cleanup:
469 /* destroy whatever was build of the db instance */
470 destroy_sqldbinstance(db);
471 /* return failure */
472 return (ISC_R_FAILURE);
475 void
476 sdlzh_destroy_sqldbinstance(dbinstance_t *dbi)
478 isc_mem_t *mctx;
480 /* save mctx for later */
481 mctx = dbi->mctx;
483 /* destroy any query lists we created */
484 destroy_querylist(mctx, &dbi->allnodes_q);
485 destroy_querylist(mctx, &dbi->allowxfr_q);
486 destroy_querylist(mctx, &dbi->authority_q);
487 destroy_querylist(mctx, &dbi->findzone_q);
488 destroy_querylist(mctx, &dbi->countzone_q);
489 destroy_querylist(mctx, &dbi->lookup_q);
491 /* get rid of the mutex */
492 isc_mutex_destroy(&dbi->instance_lock);
494 /* return, and detach the memory */
495 isc_mem_put(mctx, dbi, sizeof(dbinstance_t));
496 isc_mem_detach(&mctx);
499 char *
500 sdlzh_get_parameter_value(isc_mem_t *mctx, const char *input, const char* key)
502 int keylen;
503 char *keystart;
504 char value[255];
505 int i;
507 if (key == NULL || input == NULL || strlen(input) < 1)
508 return NULL;
510 keylen = strlen(key);
512 if (keylen < 1)
513 return NULL;
515 keystart = strstr(input, key);
517 if (keystart == NULL)
518 return NULL;
520 REQUIRE(mctx != NULL);
522 for (i = 0; i < 255; i++) {
523 value[i] = keystart[keylen + i];
524 if (value[i] == ' ' || value[i] == '\0') {
525 value[i] = '\0';
526 break;
530 return isc_mem_strdup(mctx, value);
533 #endif