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
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
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.
66 #include <dns/result.h>
70 #include <isc/platform.h>
71 #include <isc/print.h>
72 #include <isc/result.h>
75 #include <named/globals.h>
77 #include <dlz/dlz_filesystem_driver.h>
79 static dns_sdlzimplementation_t
*dlz_fs
= NULL
;
81 typedef struct config_data
{
94 typedef struct dir_entry dir_entry_t
;
97 char dirpath
[ISC_DIR_PATHMAX
];
98 ISC_LINK(dir_entry_t
) link
;
101 typedef ISC_LIST(dir_entry_t
) dlist_t
;
103 /* forward reference */
106 fs_destroy(void *driverarg
, void *dbdata
);
113 is_safe(const char *input
)
116 unsigned int len
= strlen(input
);
118 /* check that only allowed characters are in the domain name */
119 for (i
=0; i
< len
; i
++) {
120 /* '.' is allowed, but has special requirements */
121 if (input
[i
] == '.') {
122 /* '.' is not allowed as first char */
125 /* '..', two dots together is not allowed. */
126 else if (input
[i
-1] == '.')
128 /* '.' is not allowed as last char */
131 /* only 1 dot in ok location, continue at next char */
134 /* '-' is allowed, continue at next char */
137 /* 0-9 is allowed, continue at next char */
138 if (input
[i
] >= '0' && input
[i
] <= '9')
140 /* A-Z uppercase is allowed, continue at next char */
141 if (input
[i
] >= 'A' && input
[i
] <= 'Z')
143 /* a-z lowercase is allowed, continue at next char */
144 if (input
[i
] >= 'a' && input
[i
] <= 'z')
148 * colon needs to be allowed for IPV6 client
149 * addresses. Not dangerous in domain names, as not a
156 * '@' needs to be allowed for in zone data. Not
157 * dangerous in domain names, as not a special char.
163 * if we reach this point we have encountered a
173 create_path_helper(char *out
, const char *in
, config_data_t
*cd
)
180 tmpString
= isc_mem_strdup(ns_g_mctx
, in
);
181 if (tmpString
== NULL
)
182 return (ISC_R_NOMEMORY
);
185 * don't forget is_safe guarantees '.' will NOT be the
188 while ((tmpPtr
= strrchr(tmpString
, '.')) != NULL
) {
190 while (tmpPtr
[i
+1] != '\0') {
191 if (cd
->splitcnt
< 1)
192 strcat(out
, (char *) &tmpPtr
[i
+1]);
194 strncat(out
, (char *) &tmpPtr
[i
+1],
196 strncat(out
, (char *) &cd
->pathsep
, 1);
197 if (cd
->splitcnt
== 0)
199 if (strlen((char *) &tmpPtr
[i
+1]) <=
200 (unsigned int) cd
->splitcnt
)
207 /* handle the "first" label properly */
210 while (tmpPtr
[i
] != '\0') {
211 if (cd
->splitcnt
< 1)
212 strcat(out
, (char *) &tmpPtr
[i
]);
214 strncat(out
, (char *) &tmpPtr
[i
], cd
->splitcnt
);
215 strncat(out
, (char *) &cd
->pathsep
, 1);
216 if (cd
->splitcnt
== 0)
218 if (strlen((char *) &tmpPtr
[i
]) <=
219 (unsigned int) cd
->splitcnt
)
224 isc_mem_free(ns_g_mctx
, tmpString
);
225 return (ISC_R_SUCCESS
);
229 * Checks to make sure zone and host are safe. If safe, then
230 * hashes zone and host strings to build a path. If zone / host
231 * are not safe an error is returned.
235 create_path(const char *zone
, const char *host
, const char *client
,
236 config_data_t
*cd
, char **path
)
244 /* we require a zone & cd parameter */
245 REQUIRE(zone
!= NULL
);
247 /* require path to be a pointer to NULL */
248 REQUIRE(path
!= NULL
&& *path
== NULL
);
250 * client and host may both be NULL, but they can't both be
253 REQUIRE( (host
== NULL
&& client
== NULL
) ||
254 (host
!= NULL
&& client
== NULL
) ||
255 (host
== NULL
&& client
!= NULL
) );
257 /* if the requested zone is "unsafe", return error */
258 if (is_safe(zone
) != ISC_TRUE
)
259 return (ISC_R_FAILURE
);
261 /* if host was passed, verify that it is safe */
262 if ((host
!= NULL
) && (is_safe(host
) != ISC_TRUE
) )
263 return (ISC_R_FAILURE
);
265 /* if host was passed, verify that it is safe */
266 if ((client
!= NULL
) && (is_safe(client
) != ISC_TRUE
) )
267 return (ISC_R_FAILURE
);
269 /* Determine how much memory the split up string will require */
271 len
= strlen(zone
) + strlen(host
);
272 else if (client
!= NULL
)
273 len
= strlen(zone
) + strlen(client
);
278 * even though datadir and xfrdir will never be in the same
279 * string we only waste a few bytes by allocating for both,
280 * and then we are safe from buffer overruns.
282 pathsize
= len
+ cd
->basedirsize
+
283 cd
->datadirsize
+ cd
->xfrdirsize
+ 4;
285 /* if we are splitting names, we will need extra space. */
286 if (cd
->splitcnt
> 0)
287 pathsize
+= len
/cd
->splitcnt
;
289 tmpPath
= isc_mem_allocate(ns_g_mctx
, pathsize
* sizeof(char));
290 if (tmpPath
== NULL
) {
291 /* write error message */
292 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_DATABASE
,
293 DNS_LOGMODULE_DLZ
, ISC_LOG_ERROR
,
294 "Filesystem driver unable to "
295 "allocate memory in create_path().");
296 result
= ISC_R_NOMEMORY
;
302 * start out with base directory.
304 strcpy(tmpPath
, cd
->basedir
);
306 /* add zone name - parsed properly */
307 if ((result
= create_path_helper(tmpPath
, zone
, cd
)) != ISC_R_SUCCESS
)
311 * When neither client or host is passed we are building a
312 * path to see if a zone is supported. We require that a zone
313 * path have the "data dir" directory contained within it so
314 * that we know this zone is really supported. Otherwise,
315 * this zone may not really be supported because we are
316 * supporting a delagated sub zone.
320 * We are supporting long.domain.com and using a splitcnt of
321 * 0. the base dir is "/base-dir/" and the data dir is
322 * "/.datadir" We want to see if we are authoritative for
323 * domain.com. Path /base-dir/com/domain/.datadir since
324 * /base-dir/com/domain/.datadir does not exist, we are not
325 * authoritative for the domain "domain.com". However we are
326 * authoritative for the domain "long.domain.com" because the
327 * path /base-dir/com/domain/long/.datadir does exist!
330 /* if client is passed append xfr dir, otherwise append data dir */
331 if (client
!= NULL
) {
332 strcat(tmpPath
, cd
->xfrdir
);
333 strncat(tmpPath
, (char *) &cd
->pathsep
, 1);
334 strcat(tmpPath
, client
);
336 strcat(tmpPath
, cd
->datadir
);
339 /* if host not null, add it. */
341 strncat(tmpPath
, (char *) &cd
->pathsep
, 1);
342 if ((result
= create_path_helper(tmpPath
, host
,
343 cd
)) != ISC_R_SUCCESS
)
347 /* return the path we built. */
351 result
= ISC_R_SUCCESS
;
356 /* free tmpPath memory */
357 if (tmpPath
!= NULL
&& result
!= ISC_R_SUCCESS
)
358 isc_mem_free(ns_g_mctx
, tmpPath
);
360 /* free tmpPath memory */
365 process_dir(isc_dir_t dir
, void *passback
, config_data_t
*cd
,
366 dlist_t
*dir_list
, unsigned int basedirlen
)
369 char tmp
[ISC_DIR_PATHMAX
+ ISC_DIR_NAMEMAX
];
372 isc_result_t result
= ISC_R_FAILURE
;
377 char host
[ISC_DIR_NAMEMAX
];
383 dir_entry_t
*direntry
;
384 isc_boolean_t foundHost
;
386 tmp
[0] = '\0'; /* set 1st byte to '\0' so strcpy works right. */
388 foundHost
= ISC_FALSE
;
390 /* copy base directory name to tmp. */
391 strcpy(tmp
, dir
.dirname
);
393 /* dir.dirname will always have '*' as the last char. */
394 astPos
= strlen(dir
.dirname
) - 1;
396 /* if dir_list != NULL, were are performing a zone xfr */
397 if (dir_list
!= NULL
) {
398 /* if splitcnt == 0, determine host from path. */
399 if (cd
->splitcnt
== 0) {
400 if (strlen(tmp
) - 3 > basedirlen
) {
401 tmp
[astPos
-1] = '\0';
402 tmpString
= (char *) &tmp
[basedirlen
+1];
403 /* handle filesystem's special wildcard "-" */
404 if (strcmp(tmpString
, "-") == 0) {
408 * not special wildcard -- normal name
410 while ((tmpPtr
= strrchr(tmpString
,
413 strcat(host
, tmpPtr
+ 1);
417 strcat(host
, tmpString
);
420 foundHost
= ISC_TRUE
;
421 /* set tmp again for use later */
422 strcpy(tmp
, dir
.dirname
);
426 * if splitcnt != 0 determine host from
427 * ".host" directory entry
429 while (isc_dir_read(&dir
) == ISC_R_SUCCESS
) {
430 if (strncasecmp(".host",
431 dir
.entry
.name
, 5) == 0) {
433 * handle filesystem's special
436 if (strcmp((char *) &dir
.entry
.name
[6],
443 foundHost
= ISC_TRUE
;
447 /* reset dir list for use later */
452 while (isc_dir_read(&dir
) == ISC_R_SUCCESS
) {
454 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_DATABASE
,
455 DNS_LOGMODULE_DLZ
, ISC_LOG_DEBUG(1),
456 "Filesystem driver Dir name:"
457 " '%s' Dir entry: '%s'\n",
458 dir
.dirname
, dir
.entry
.name
);
460 /* skip any entries starting with "." */
461 if (dir
.entry
.name
[0] == '.')
465 * get rid of '*', set to NULL. Effectively trims
466 * string from previous loop to base directory only
467 * while still leaving memory for concat to be
473 /* add name to base directory name. */
474 strcat(tmp
, dir
.entry
.name
);
476 /* make sure we can stat entry */
477 if (stat(tmp
, &sb
) == 0 ) {
478 /* if entry is a directory */
479 if ((sb
.st_mode
& S_IFDIR
) != 0) {
481 * if dir list is NOT NULL, add dir to
484 if (dir_list
!= NULL
) {
486 isc_mem_get(ns_g_mctx
,
487 sizeof(dir_entry_t
));
488 if (direntry
== NULL
)
489 return (ISC_R_NOMEMORY
);
490 strcpy(direntry
->dirpath
, tmp
);
491 ISC_LINK_INIT(direntry
, link
);
492 ISC_LIST_APPEND(*dir_list
, direntry
,
494 result
= ISC_R_SUCCESS
;
499 * if entry is a file be sure we do
500 * not add entry to DNS results if we
501 * are performing a zone xfr and we
502 * could not find a host entry.
505 } else if (dir_list
!= NULL
&&
506 foundHost
== ISC_FALSE
) {
509 } else /* if we cannot stat entry, skip it. */
512 type
= dir
.entry
.name
;
513 ttlStr
= strchr(type
, cd
->separator
);
514 if (ttlStr
== NULL
) {
515 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_DATABASE
,
516 DNS_LOGMODULE_DLZ
, ISC_LOG_ERROR
,
517 "Filesystem driver: "
518 "%s could not be parsed properly",
520 return ISC_R_FAILURE
;
523 /* replace separator char with NULL to split string */
525 /* start string after NULL of previous string */
526 ttlStr
= (char *) &ttlStr
[1];
528 data
= strchr(ttlStr
, cd
->separator
);
530 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_DATABASE
,
531 DNS_LOGMODULE_DLZ
, ISC_LOG_ERROR
,
532 "Filesystem driver: "
533 "%s could not be parsed properly",
535 return ISC_R_FAILURE
;
538 /* replace separator char with NULL to split string */
541 /* start string after NULL of previous string */
542 data
= (char *) &data
[1];
544 /* replace all cd->separator chars with a space. */
547 for (i
=0; i
< len
; i
++) {
548 if (data
[i
] == cd
->separator
)
552 /* convert text to int, make sure it worked right */
553 ttl
= strtol(ttlStr
, &endp
, 10);
554 if (*endp
!= '\0' || ttl
< 0) {
555 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_DATABASE
,
556 DNS_LOGMODULE_DLZ
, ISC_LOG_ERROR
,
558 "ttl must be a postive number");
561 /* pass data back to Bind */
562 if (dir_list
== NULL
)
563 result
= dns_sdlz_putrr((dns_sdlzlookup_t
*) passback
,
566 result
= dns_sdlz_putnamedrr((dns_sdlzallnodes_t
*)
571 /* if error, return error right away */
572 if (result
!= ISC_R_SUCCESS
)
574 } /* end of while loop */
580 * SDLZ interface methods
584 fs_allowzonexfr(void *driverarg
, void *dbdata
, const char *name
,
596 cd
= (config_data_t
*) dbdata
;
598 if (create_path(name
, NULL
, client
, cd
, &path
) != ISC_R_SUCCESS
) {
599 return (ISC_R_NOTFOUND
);
602 if (stat(path
, &sb
) != 0) {
603 result
= ISC_R_NOTFOUND
;
607 if ((sb
.st_mode
& S_IFREG
) != 0) {
608 result
= ISC_R_SUCCESS
;
612 result
= ISC_R_NOTFOUND
;
615 isc_mem_free(ns_g_mctx
, path
);
620 fs_allnodes(const char *zone
, void *driverarg
, void *dbdata
,
621 dns_sdlzallnodes_t
*allnodes
)
628 unsigned int basepathlen
;
631 dir_entry_t
*dir_entry
;
632 dir_entry_t
*next_de
;
640 cd
= (config_data_t
*) dbdata
;
642 /* allocate memory for list */
643 dir_list
= isc_mem_get(ns_g_mctx
, sizeof(dlist_t
));
644 if (dir_list
== NULL
) {
645 result
= ISC_R_NOTFOUND
;
646 goto complete_allnds
;
649 /* initialize list */
650 ISC_LIST_INIT(*dir_list
);
652 if (create_path(zone
, NULL
, NULL
, cd
, &basepath
) != ISC_R_SUCCESS
) {
653 return (ISC_R_NOTFOUND
);
656 /* remove path separator at end of path so stat works properly */
657 basepathlen
= strlen(basepath
);
659 if (stat(basepath
, &sb
) != 0) {
660 result
= ISC_R_NOTFOUND
;
661 goto complete_allnds
;
664 if ((sb
.st_mode
& S_IFDIR
) == 0) {
665 result
= ISC_R_NOTFOUND
;
666 goto complete_allnds
;
669 /* initialize and open directory */
671 result
= isc_dir_open(&dir
, basepath
);
673 /* if directory open failed, return error. */
674 if (result
!= ISC_R_SUCCESS
) {
675 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_DATABASE
,
676 DNS_LOGMODULE_DLZ
, ISC_LOG_ERROR
,
677 "Unable to open %s directory to read entries.",
679 result
= ISC_R_FAILURE
;
680 goto complete_allnds
;
683 /* process the directory */
684 result
= process_dir(dir
, allnodes
, cd
, dir_list
, basepathlen
);
686 /* close the directory */
689 if (result
!= ISC_R_SUCCESS
)
690 goto complete_allnds
;
692 /* get first dir entry from list. */
693 dir_entry
= ISC_LIST_HEAD(*dir_list
);
694 while (dir_entry
!= NULL
) {
696 result
= isc_dir_open(&dir
, dir_entry
->dirpath
);
697 /* if directory open failed, return error. */
698 if (result
!= ISC_R_SUCCESS
) {
699 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_DATABASE
,
700 DNS_LOGMODULE_DLZ
, ISC_LOG_ERROR
,
702 "directory to read entries.",
704 result
= ISC_R_FAILURE
;
705 goto complete_allnds
;
708 /* process the directory */
709 result
= process_dir(dir
, allnodes
, cd
, dir_list
, basepathlen
);
711 /* close the directory */
714 if (result
!= ISC_R_SUCCESS
)
715 goto complete_allnds
;
717 dir_entry
= ISC_LIST_NEXT(dir_entry
, link
);
721 if (dir_list
!= NULL
) {
722 /* clean up entries from list. */
723 dir_entry
= ISC_LIST_HEAD(*dir_list
);
724 while (dir_entry
!= NULL
) {
725 next_de
= ISC_LIST_NEXT(dir_entry
, link
);
726 isc_mem_put(ns_g_mctx
, dir_entry
, sizeof(dir_entry_t
));
729 isc_mem_put(ns_g_mctx
, dir_list
, sizeof(dlist_t
));
732 if (basepath
!= NULL
)
733 isc_mem_free(ns_g_mctx
, basepath
);
739 fs_findzone(void *driverarg
, void *dbdata
, const char *name
)
749 if (create_path(name
, NULL
, NULL
, (config_data_t
*) dbdata
,
750 &path
) != ISC_R_SUCCESS
) {
751 return (ISC_R_NOTFOUND
);
754 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_DATABASE
,
755 DNS_LOGMODULE_DLZ
, ISC_LOG_DEBUG(1),
756 "Filesystem driver Findzone() Checking for path: '%s'\n",
759 if (stat(path
, &sb
) != 0) {
760 result
= ISC_R_NOTFOUND
;
764 if ((sb
.st_mode
& S_IFDIR
) != 0) {
765 result
= ISC_R_SUCCESS
;
769 result
= ISC_R_NOTFOUND
;
773 isc_mem_free(ns_g_mctx
, path
);
778 fs_lookup(const char *zone
, const char *name
, void *driverarg
,
779 void *dbdata
, dns_sdlzlookup_t
*lookup
)
790 if (strcmp(name
, "*") == 0)
792 * handle filesystem's special wildcard "-"
794 result
= create_path(zone
, "-", NULL
,
795 (config_data_t
*) dbdata
, &path
);
797 result
= create_path(zone
, name
, NULL
,
798 (config_data_t
*) dbdata
, &path
);
800 if ( result
!= ISC_R_SUCCESS
) {
801 return (ISC_R_NOTFOUND
);
804 /* remove path separator at end of path so stat works properly */
805 path
[strlen(path
)-1] = '\0';
807 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_DATABASE
,
808 DNS_LOGMODULE_DLZ
, ISC_LOG_DEBUG(1),
809 "Filesystem driver lookup() Checking for path: '%s'\n",
813 if (stat(path
, &sb
) != 0) {
814 result
= ISC_R_NOTFOUND
;
818 if ((sb
.st_mode
& S_IFDIR
) == 0) {
819 result
= ISC_R_NOTFOUND
;
823 /* initialize and open directory */
825 result
= isc_dir_open(&dir
, path
);
827 /* if directory open failed, return error. */
828 if (result
!= ISC_R_SUCCESS
) {
829 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_DATABASE
,
830 DNS_LOGMODULE_DLZ
, ISC_LOG_ERROR
,
831 "Unable to open %s directory to read entries.",
833 result
= ISC_R_FAILURE
;
837 /* process any records in the directory */
838 result
= process_dir(dir
, lookup
, (config_data_t
*) dbdata
, NULL
, 0);
840 /* close the directory */
845 isc_mem_free(ns_g_mctx
, path
);
850 fs_create(const char *dlzname
, unsigned int argc
, char *argv
[],
851 void *driverarg
, void **dbdata
)
861 /* we require 5 command line args. */
863 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_DATABASE
,
864 DNS_LOGMODULE_DLZ
, ISC_LOG_ERROR
,
865 "Filesystem driver requires "
866 "6 command line args.");
867 return (ISC_R_FAILURE
);
870 if (strlen(argv
[5]) > 1) {
871 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_DATABASE
,
872 DNS_LOGMODULE_DLZ
, ISC_LOG_ERROR
,
873 "Filesystem driver can only "
874 "accept a single character for separator.");
875 return (ISC_R_FAILURE
);
878 /* verify base dir ends with '/' or '\' */
879 len
= strlen(argv
[1]);
880 if (argv
[1][len
-1] != '\\' && argv
[1][len
-1] != '/') {
881 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_DATABASE
,
882 DNS_LOGMODULE_DLZ
, ISC_LOG_ERROR
,
883 "Base dir parameter for filesystem driver "
884 "should end with %s",
885 "either '/' or '\\' ");
886 return (ISC_R_FAILURE
);
889 /* determine and save path separator for later */
890 if (argv
[1][len
-1] == '\\')
895 /* allocate memory for our config data */
896 cd
= isc_mem_get(ns_g_mctx
, sizeof(config_data_t
));
900 /* zero the memory */
901 memset(cd
, 0, sizeof(config_data_t
));
903 cd
->pathsep
= pathsep
;
905 /* get and store our base directory */
906 cd
->basedir
= isc_mem_strdup(ns_g_mctx
, argv
[1]);
907 if (cd
->basedir
== NULL
)
909 cd
->basedirsize
= strlen(cd
->basedir
);
911 /* get and store our data sub-dir */
912 cd
->datadir
= isc_mem_strdup(ns_g_mctx
, argv
[2]);
913 if (cd
->datadir
== NULL
)
915 cd
->datadirsize
= strlen(cd
->datadir
);
917 /* get and store our zone xfr sub-dir */
918 cd
->xfrdir
= isc_mem_strdup(ns_g_mctx
, argv
[3]);
919 if (cd
->xfrdir
== NULL
)
921 cd
->xfrdirsize
= strlen(cd
->xfrdir
);
923 /* get and store our directory split count */
924 cd
->splitcnt
= strtol(argv
[4], &endp
, 10);
925 if (*endp
!= '\0' || cd
->splitcnt
< 0) {
926 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_DATABASE
,
927 DNS_LOGMODULE_DLZ
, ISC_LOG_ERROR
,
928 "Directory split count must be zero (0) "
929 "or a postive number");
932 /* get and store our separator character */
933 cd
->separator
= *argv
[5];
935 /* attach config data to memory context */
936 isc_mem_attach(ns_g_mctx
, &cd
->mctx
);
938 /* pass back config data */
942 return(ISC_R_SUCCESS
);
944 /* handle no memory error */
947 /* if we allocated a config data object clean it up */
949 fs_destroy(NULL
, cd
);
951 /* write error message */
952 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_DATABASE
,
953 DNS_LOGMODULE_DLZ
, ISC_LOG_ERROR
,
954 "Filesystem driver unable to "
955 "allocate memory for config data.");
958 return (ISC_R_NOMEMORY
);
962 fs_destroy(void *driverarg
, void *dbdata
)
969 cd
= (config_data_t
*) dbdata
;
972 * free memory for each section of config data that was
975 if (cd
->basedir
!= NULL
)
976 isc_mem_free(ns_g_mctx
, cd
->basedir
);
978 if (cd
->datadir
!= NULL
)
979 isc_mem_free(ns_g_mctx
, cd
->datadir
);
981 if (cd
->xfrdir
!= NULL
)
982 isc_mem_free(ns_g_mctx
, cd
->xfrdir
);
984 /* hold memory context to use later */
987 /* free config data memory */
988 isc_mem_put(mctx
, cd
, sizeof(config_data_t
));
990 /* detach memory from context */
991 isc_mem_detach(&mctx
);
994 static dns_sdlzmethods_t dlz_fs_methods
= {
1005 * Wrapper around dns_sdlzregister().
1010 isc_result_t result
;
1013 * Write debugging message to log
1015 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_DATABASE
,
1016 DNS_LOGMODULE_DLZ
, ISC_LOG_DEBUG(2),
1017 "Registering DLZ filesystem driver.");
1019 result
= dns_sdlzregister("filesystem", &dlz_fs_methods
, NULL
,
1020 DNS_SDLZFLAG_RELATIVEOWNER
|
1021 DNS_SDLZFLAG_RELATIVERDATA
,
1022 ns_g_mctx
, &dlz_fs
);
1023 if (result
!= ISC_R_SUCCESS
) {
1024 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
1025 "dns_sdlzregister() failed: %s",
1026 isc_result_totext(result
));
1027 result
= ISC_R_UNEXPECTED
;
1034 * Wrapper around dns_sdlzunregister().
1037 dlz_fs_clear(void) {
1040 * Write debugging message to log
1042 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_DATABASE
,
1043 DNS_LOGMODULE_DLZ
, ISC_LOG_DEBUG(2),
1044 "Unregistering DLZ filesystem driver.");
1047 dns_sdlzunregister(&dlz_fs
);