1 /* $NetBSD: dlz_filesystem_driver.c,v 1.6 2014/12/10 04:37:55 christos Exp $ */
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
) {
115 unsigned int len
= strlen(input
);
117 /* check that only allowed characters are in the domain name */
118 for (i
=0; i
< len
; i
++) {
119 /* '.' is allowed, but has special requirements */
120 if (input
[i
] == '.') {
121 /* '.' is not allowed as first char */
124 /* '..', two dots together is not allowed. */
125 else if (input
[i
-1] == '.')
127 /* '.' is not allowed as last char */
130 /* only 1 dot in ok location, continue at next char */
133 /* '-' is allowed, continue at next char */
136 /* 0-9 is allowed, continue at next char */
137 if (input
[i
] >= '0' && input
[i
] <= '9')
139 /* A-Z uppercase is allowed, continue at next char */
140 if (input
[i
] >= 'A' && input
[i
] <= 'Z')
142 /* a-z lowercase is allowed, continue at next char */
143 if (input
[i
] >= 'a' && input
[i
] <= 'z')
147 * colon needs to be allowed for IPV6 client
148 * addresses. Not dangerous in domain names, as not a
155 * '@' needs to be allowed for in zone data. Not
156 * dangerous in domain names, as not a special char.
162 * if we reach this point we have encountered a
172 create_path_helper(char *out
, const char *in
, config_data_t
*cd
) {
177 tmpString
= isc_mem_strdup(ns_g_mctx
, in
);
178 if (tmpString
== NULL
)
179 return (ISC_R_NOMEMORY
);
182 * don't forget is_safe guarantees '.' will NOT be the
185 while ((tmpPtr
= strrchr(tmpString
, '.')) != NULL
) {
187 while (tmpPtr
[i
+1] != '\0') {
188 if (cd
->splitcnt
< 1)
189 strcat(out
, (char *) &tmpPtr
[i
+1]);
191 strncat(out
, (char *) &tmpPtr
[i
+1],
193 strncat(out
, (char *) &cd
->pathsep
, 1);
194 if (cd
->splitcnt
== 0)
196 if (strlen((char *) &tmpPtr
[i
+1]) <=
197 (unsigned int) cd
->splitcnt
)
204 /* handle the "first" label properly */
207 while (tmpPtr
[i
] != '\0') {
208 if (cd
->splitcnt
< 1)
209 strcat(out
, (char *) &tmpPtr
[i
]);
211 strncat(out
, (char *) &tmpPtr
[i
], cd
->splitcnt
);
212 strncat(out
, (char *) &cd
->pathsep
, 1);
213 if (cd
->splitcnt
== 0)
215 if (strlen((char *) &tmpPtr
[i
]) <=
216 (unsigned int) cd
->splitcnt
)
221 isc_mem_free(ns_g_mctx
, tmpString
);
222 return (ISC_R_SUCCESS
);
226 * Checks to make sure zone and host are safe. If safe, then
227 * hashes zone and host strings to build a path. If zone / host
228 * are not safe an error is returned.
232 create_path(const char *zone
, const char *host
, const char *client
,
233 config_data_t
*cd
, char **path
)
240 isc_boolean_t isroot
= ISC_FALSE
;
242 /* we require a zone & cd parameter */
243 REQUIRE(zone
!= NULL
);
245 /* require path to be a pointer to NULL */
246 REQUIRE(path
!= NULL
&& *path
== NULL
);
248 * client and host may both be NULL, but they can't both be
251 REQUIRE( (host
== NULL
&& client
== NULL
) ||
252 (host
!= NULL
&& client
== NULL
) ||
253 (host
== NULL
&& client
!= NULL
) );
255 /* special case for root zone */
256 if (strcmp(zone
, ".") == 0)
259 /* if the requested zone is "unsafe", return error */
260 if (!isroot
&& !is_safe(zone
))
261 return (ISC_R_FAILURE
);
263 /* if host was passed, verify that it is safe */
264 if (host
!= NULL
&& !is_safe(host
))
265 return (ISC_R_FAILURE
);
267 /* if client was passed, verify that it is safe */
268 if (client
!= NULL
&& !is_safe(client
))
269 return (ISC_R_FAILURE
);
271 /* Determine how much memory the split up string will require */
273 len
= strlen(zone
) + strlen(host
);
274 else if (client
!= NULL
)
275 len
= strlen(zone
) + strlen(client
);
280 * even though datadir and xfrdir will never be in the same
281 * string we only waste a few bytes by allocating for both,
282 * and then we are safe from buffer overruns.
284 pathsize
= len
+ cd
->basedirsize
+
285 cd
->datadirsize
+ cd
->xfrdirsize
+ 4;
287 /* if we are splitting names, we will need extra space. */
288 if (cd
->splitcnt
> 0)
289 pathsize
+= len
/cd
->splitcnt
;
291 tmpPath
= isc_mem_allocate(ns_g_mctx
, pathsize
* sizeof(char));
292 if (tmpPath
== NULL
) {
293 /* write error message */
294 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_DATABASE
,
295 DNS_LOGMODULE_DLZ
, ISC_LOG_ERROR
,
296 "Filesystem driver unable to "
297 "allocate memory in create_path().");
298 result
= ISC_R_NOMEMORY
;
304 * start out with base directory.
306 strcpy(tmpPath
, cd
->basedir
);
308 /* add zone name - parsed properly */
310 result
= create_path_helper(tmpPath
, zone
, cd
);
311 if (result
!= ISC_R_SUCCESS
)
316 * When neither client or host is passed we are building a
317 * path to see if a zone is supported. We require that a zone
318 * path have the "data dir" directory contained within it so
319 * that we know this zone is really supported. Otherwise,
320 * this zone may not really be supported because we are
321 * supporting a delagated sub zone.
325 * We are supporting long.domain.com and using a splitcnt of
326 * 0. the base dir is "/base-dir/" and the data dir is
327 * "/.datadir" We want to see if we are authoritative for
328 * domain.com. Path /base-dir/com/domain/.datadir since
329 * /base-dir/com/domain/.datadir does not exist, we are not
330 * authoritative for the domain "domain.com". However we are
331 * authoritative for the domain "long.domain.com" because the
332 * path /base-dir/com/domain/long/.datadir does exist!
335 /* if client is passed append xfr dir, otherwise append data dir */
336 if (client
!= NULL
) {
337 strcat(tmpPath
, cd
->xfrdir
);
338 strncat(tmpPath
, (char *) &cd
->pathsep
, 1);
339 strcat(tmpPath
, client
);
341 strcat(tmpPath
, cd
->datadir
);
344 /* if host not null, add it. */
346 strncat(tmpPath
, (char *) &cd
->pathsep
, 1);
347 if ((result
= create_path_helper(tmpPath
, host
,
348 cd
)) != ISC_R_SUCCESS
)
352 /* return the path we built. */
356 result
= ISC_R_SUCCESS
;
361 /* free tmpPath memory */
362 if (tmpPath
!= NULL
&& result
!= ISC_R_SUCCESS
)
363 isc_mem_free(ns_g_mctx
, tmpPath
);
365 /* free tmpPath memory */
370 process_dir(isc_dir_t
*dir
, void *passback
, config_data_t
*cd
,
371 dlist_t
*dir_list
, unsigned int basedirlen
)
374 char tmp
[ISC_DIR_PATHMAX
+ ISC_DIR_NAMEMAX
];
377 isc_result_t result
= ISC_R_FAILURE
;
382 char host
[ISC_DIR_NAMEMAX
];
388 dir_entry_t
*direntry
;
389 isc_boolean_t foundHost
;
391 tmp
[0] = '\0'; /* set 1st byte to '\0' so strcpy works right. */
393 foundHost
= ISC_FALSE
;
395 /* copy base directory name to tmp. */
396 strcpy(tmp
, dir
->dirname
);
398 /* dir->dirname will always have '*' as the last char. */
399 astPos
= strlen(dir
->dirname
) - 1;
401 /* if dir_list != NULL, were are performing a zone xfr */
402 if (dir_list
!= NULL
) {
403 /* if splitcnt == 0, determine host from path. */
404 if (cd
->splitcnt
== 0) {
405 if (strlen(tmp
) - 3 > basedirlen
) {
406 tmp
[astPos
-1] = '\0';
407 tmpString
= (char *) &tmp
[basedirlen
+1];
408 /* handle filesystem's special wildcard "-" */
409 if (strcmp(tmpString
, "-") == 0) {
413 * not special wildcard -- normal name
415 while ((tmpPtr
= strrchr(tmpString
,
420 strlen(tmpPtr
+ 1) + 2)
423 strcat(host
, tmpPtr
+ 1);
428 strlen(tmpString
) + 1)
430 strcat(host
, tmpString
);
433 foundHost
= ISC_TRUE
;
434 /* set tmp again for use later */
435 strcpy(tmp
, dir
->dirname
);
439 * if splitcnt != 0 determine host from
440 * ".host" directory entry
442 while (isc_dir_read(dir
) == ISC_R_SUCCESS
) {
443 if (strncasecmp(".host",
444 dir
->entry
.name
, 5) == 0) {
446 * handle filesystem's special
449 if (strcmp((char *) &dir
->entry
.name
[6],
454 (char *) &dir
->entry
.name
[6],
458 foundHost
= ISC_TRUE
;
462 /* reset dir list for use later */
467 while (isc_dir_read(dir
) == ISC_R_SUCCESS
) {
469 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_DATABASE
,
470 DNS_LOGMODULE_DLZ
, ISC_LOG_DEBUG(1),
471 "Filesystem driver Dir name:"
472 " '%s' Dir entry: '%s'\n",
473 dir
->dirname
, dir
->entry
.name
);
475 /* skip any entries starting with "." */
476 if (dir
->entry
.name
[0] == '.')
480 * get rid of '*', set to NULL. Effectively trims
481 * string from previous loop to base directory only
482 * while still leaving memory for concat to be
488 /* add name to base directory name. */
489 strcat(tmp
, dir
->entry
.name
);
491 /* make sure we can stat entry */
492 if (stat(tmp
, &sb
) == 0 ) {
493 /* if entry is a directory */
494 if ((sb
.st_mode
& S_IFDIR
) != 0) {
496 * if dir list is NOT NULL, add dir to
499 if (dir_list
!= NULL
) {
501 isc_mem_get(ns_g_mctx
,
502 sizeof(dir_entry_t
));
503 if (direntry
== NULL
)
504 return (ISC_R_NOMEMORY
);
505 strcpy(direntry
->dirpath
, tmp
);
506 ISC_LINK_INIT(direntry
, link
);
507 ISC_LIST_APPEND(*dir_list
, direntry
,
509 result
= ISC_R_SUCCESS
;
514 * if entry is a file be sure we do
515 * not add entry to DNS results if we
516 * are performing a zone xfr and we
517 * could not find a host entry.
520 } else if (dir_list
!= NULL
&&
521 foundHost
== ISC_FALSE
) {
524 } else /* if we cannot stat entry, skip it. */
527 type
= dir
->entry
.name
;
528 ttlStr
= strchr(type
, cd
->separator
);
529 if (ttlStr
== NULL
) {
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 */
540 /* start string after NULL of previous string */
541 ttlStr
= (char *) &ttlStr
[1];
543 data
= strchr(ttlStr
, cd
->separator
);
545 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_DATABASE
,
546 DNS_LOGMODULE_DLZ
, ISC_LOG_ERROR
,
547 "Filesystem driver: "
548 "%s could not be parsed properly",
550 return (ISC_R_FAILURE
);
553 /* replace separator char with NULL to split string */
556 /* start string after NULL of previous string */
557 data
= (char *) &data
[1];
559 /* replace all cd->separator chars with a space. */
562 for (i
=0; i
< len
; i
++) {
563 if (data
[i
] == cd
->separator
)
567 /* convert text to int, make sure it worked right */
568 ttl
= strtol(ttlStr
, &endp
, 10);
569 if (*endp
!= '\0' || ttl
< 0) {
570 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_DATABASE
,
571 DNS_LOGMODULE_DLZ
, ISC_LOG_ERROR
,
573 "ttl must be a postive number");
576 /* pass data back to Bind */
577 if (dir_list
== NULL
)
578 result
= dns_sdlz_putrr((dns_sdlzlookup_t
*) passback
,
581 result
= dns_sdlz_putnamedrr((dns_sdlzallnodes_t
*)
586 /* if error, return error right away */
587 if (result
!= ISC_R_SUCCESS
)
589 } /* end of while loop */
595 * SDLZ interface methods
599 fs_allowzonexfr(void *driverarg
, void *dbdata
, const char *name
,
611 cd
= (config_data_t
*) dbdata
;
613 if (create_path(name
, NULL
, client
, cd
, &path
) != ISC_R_SUCCESS
) {
614 return (ISC_R_NOTFOUND
);
617 if (stat(path
, &sb
) != 0) {
618 result
= ISC_R_NOTFOUND
;
622 if ((sb
.st_mode
& S_IFREG
) != 0) {
623 result
= ISC_R_SUCCESS
;
627 result
= ISC_R_NOTFOUND
;
630 isc_mem_free(ns_g_mctx
, path
);
635 fs_allnodes(const char *zone
, void *driverarg
, void *dbdata
,
636 dns_sdlzallnodes_t
*allnodes
)
643 unsigned int basepathlen
;
646 dir_entry_t
*dir_entry
;
647 dir_entry_t
*next_de
;
655 cd
= (config_data_t
*) dbdata
;
657 /* allocate memory for list */
658 dir_list
= isc_mem_get(ns_g_mctx
, sizeof(dlist_t
));
659 if (dir_list
== NULL
) {
660 result
= ISC_R_NOTFOUND
;
661 goto complete_allnds
;
664 /* initialize list */
665 ISC_LIST_INIT(*dir_list
);
667 if (create_path(zone
, NULL
, NULL
, cd
, &basepath
) != ISC_R_SUCCESS
) {
668 return (ISC_R_NOTFOUND
);
671 /* remove path separator at end of path so stat works properly */
672 basepathlen
= strlen(basepath
);
674 if (stat(basepath
, &sb
) != 0) {
675 result
= ISC_R_NOTFOUND
;
676 goto complete_allnds
;
679 if ((sb
.st_mode
& S_IFDIR
) == 0) {
680 result
= ISC_R_NOTFOUND
;
681 goto complete_allnds
;
684 /* initialize and open directory */
686 result
= isc_dir_open(&dir
, basepath
);
688 /* if directory open failed, return error. */
689 if (result
!= ISC_R_SUCCESS
) {
690 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_DATABASE
,
691 DNS_LOGMODULE_DLZ
, ISC_LOG_ERROR
,
692 "Unable to open %s directory to read entries.",
694 result
= ISC_R_FAILURE
;
695 goto complete_allnds
;
698 /* process the directory */
699 result
= process_dir(&dir
, allnodes
, cd
, dir_list
, basepathlen
);
701 /* close the directory */
704 if (result
!= ISC_R_SUCCESS
)
705 goto complete_allnds
;
707 /* get first dir entry from list. */
708 dir_entry
= ISC_LIST_HEAD(*dir_list
);
709 while (dir_entry
!= NULL
) {
711 result
= isc_dir_open(&dir
, dir_entry
->dirpath
);
712 /* if directory open failed, return error. */
713 if (result
!= ISC_R_SUCCESS
) {
714 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_DATABASE
,
715 DNS_LOGMODULE_DLZ
, ISC_LOG_ERROR
,
717 "directory to read entries.",
719 result
= ISC_R_FAILURE
;
720 goto complete_allnds
;
723 /* process the directory */
724 result
= process_dir(&dir
, allnodes
, cd
, dir_list
, basepathlen
);
726 /* close the directory */
729 if (result
!= ISC_R_SUCCESS
)
730 goto complete_allnds
;
732 dir_entry
= ISC_LIST_NEXT(dir_entry
, link
);
736 if (dir_list
!= NULL
) {
737 /* clean up entries from list. */
738 dir_entry
= ISC_LIST_HEAD(*dir_list
);
739 while (dir_entry
!= NULL
) {
740 next_de
= ISC_LIST_NEXT(dir_entry
, link
);
741 isc_mem_put(ns_g_mctx
, dir_entry
, sizeof(dir_entry_t
));
744 isc_mem_put(ns_g_mctx
, dir_list
, sizeof(dlist_t
));
747 if (basepath
!= NULL
)
748 isc_mem_free(ns_g_mctx
, basepath
);
754 fs_findzone(void *driverarg
, void *dbdata
, const char *name
,
755 dns_clientinfomethods_t
*methods
, dns_clientinfo_t
*clientinfo
)
767 if (create_path(name
, NULL
, NULL
, (config_data_t
*) dbdata
,
768 &path
) != ISC_R_SUCCESS
) {
769 return (ISC_R_NOTFOUND
);
772 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_DATABASE
,
773 DNS_LOGMODULE_DLZ
, ISC_LOG_DEBUG(1),
774 "Filesystem driver Findzone() Checking for path: '%s'\n",
777 if (stat(path
, &sb
) != 0) {
778 result
= ISC_R_NOTFOUND
;
782 if ((sb
.st_mode
& S_IFDIR
) != 0) {
783 result
= ISC_R_SUCCESS
;
787 result
= ISC_R_NOTFOUND
;
791 isc_mem_free(ns_g_mctx
, path
);
796 fs_lookup(const char *zone
, const char *name
, void *driverarg
,
797 void *dbdata
, dns_sdlzlookup_t
*lookup
,
798 dns_clientinfomethods_t
*methods
, dns_clientinfo_t
*clientinfo
)
811 if (strcmp(name
, "*") == 0)
813 * handle filesystem's special wildcard "-"
815 result
= create_path(zone
, "-", NULL
,
816 (config_data_t
*) dbdata
, &path
);
818 result
= create_path(zone
, name
, NULL
,
819 (config_data_t
*) dbdata
, &path
);
821 if ( result
!= ISC_R_SUCCESS
) {
822 return (ISC_R_NOTFOUND
);
825 /* remove path separator at end of path so stat works properly */
826 path
[strlen(path
)-1] = '\0';
828 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_DATABASE
,
829 DNS_LOGMODULE_DLZ
, ISC_LOG_DEBUG(1),
830 "Filesystem driver lookup() Checking for path: '%s'\n",
834 if (stat(path
, &sb
) != 0) {
835 result
= ISC_R_NOTFOUND
;
839 if ((sb
.st_mode
& S_IFDIR
) == 0) {
840 result
= ISC_R_NOTFOUND
;
844 /* initialize and open directory */
846 result
= isc_dir_open(&dir
, path
);
848 /* if directory open failed, return error. */
849 if (result
!= ISC_R_SUCCESS
) {
850 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_DATABASE
,
851 DNS_LOGMODULE_DLZ
, ISC_LOG_ERROR
,
852 "Unable to open %s directory to read entries.",
854 result
= ISC_R_FAILURE
;
858 /* process any records in the directory */
859 result
= process_dir(&dir
, lookup
, (config_data_t
*) dbdata
, NULL
, 0);
861 /* close the directory */
866 isc_mem_free(ns_g_mctx
, path
);
871 fs_create(const char *dlzname
, unsigned int argc
, char *argv
[],
872 void *driverarg
, void **dbdata
)
882 /* we require 5 command line args. */
884 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_DATABASE
,
885 DNS_LOGMODULE_DLZ
, ISC_LOG_ERROR
,
886 "Filesystem driver requires "
887 "6 command line args.");
888 return (ISC_R_FAILURE
);
891 if (strlen(argv
[5]) > 1) {
892 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_DATABASE
,
893 DNS_LOGMODULE_DLZ
, ISC_LOG_ERROR
,
894 "Filesystem driver can only "
895 "accept a single character for separator.");
896 return (ISC_R_FAILURE
);
899 /* verify base dir ends with '/' or '\' */
900 len
= strlen(argv
[1]);
901 if (argv
[1][len
-1] != '\\' && argv
[1][len
-1] != '/') {
902 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_DATABASE
,
903 DNS_LOGMODULE_DLZ
, ISC_LOG_ERROR
,
904 "Base dir parameter for filesystem driver "
905 "should end with %s",
906 "either '/' or '\\' ");
907 return (ISC_R_FAILURE
);
910 /* determine and save path separator for later */
911 if (argv
[1][len
-1] == '\\')
916 /* allocate memory for our config data */
917 cd
= isc_mem_get(ns_g_mctx
, sizeof(config_data_t
));
921 /* zero the memory */
922 memset(cd
, 0, sizeof(config_data_t
));
924 cd
->pathsep
= pathsep
;
926 /* get and store our base directory */
927 cd
->basedir
= isc_mem_strdup(ns_g_mctx
, argv
[1]);
928 if (cd
->basedir
== NULL
)
930 cd
->basedirsize
= strlen(cd
->basedir
);
932 /* get and store our data sub-dir */
933 cd
->datadir
= isc_mem_strdup(ns_g_mctx
, argv
[2]);
934 if (cd
->datadir
== NULL
)
936 cd
->datadirsize
= strlen(cd
->datadir
);
938 /* get and store our zone xfr sub-dir */
939 cd
->xfrdir
= isc_mem_strdup(ns_g_mctx
, argv
[3]);
940 if (cd
->xfrdir
== NULL
)
942 cd
->xfrdirsize
= strlen(cd
->xfrdir
);
944 /* get and store our directory split count */
945 cd
->splitcnt
= strtol(argv
[4], &endp
, 10);
946 if (*endp
!= '\0' || cd
->splitcnt
< 0) {
947 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_DATABASE
,
948 DNS_LOGMODULE_DLZ
, ISC_LOG_ERROR
,
949 "Directory split count must be zero (0) "
950 "or a postive number");
953 /* get and store our separator character */
954 cd
->separator
= *argv
[5];
956 /* attach config data to memory context */
957 isc_mem_attach(ns_g_mctx
, &cd
->mctx
);
959 /* pass back config data */
963 return (ISC_R_SUCCESS
);
965 /* handle no memory error */
968 /* if we allocated a config data object clean it up */
970 fs_destroy(NULL
, cd
);
972 /* write error message */
973 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_DATABASE
,
974 DNS_LOGMODULE_DLZ
, ISC_LOG_ERROR
,
975 "Filesystem driver unable to "
976 "allocate memory for config data.");
979 return (ISC_R_NOMEMORY
);
983 fs_destroy(void *driverarg
, void *dbdata
)
990 cd
= (config_data_t
*) dbdata
;
993 * free memory for each section of config data that was
996 if (cd
->basedir
!= NULL
)
997 isc_mem_free(ns_g_mctx
, cd
->basedir
);
999 if (cd
->datadir
!= NULL
)
1000 isc_mem_free(ns_g_mctx
, cd
->datadir
);
1002 if (cd
->xfrdir
!= NULL
)
1003 isc_mem_free(ns_g_mctx
, cd
->xfrdir
);
1005 /* hold memory context to use later */
1008 /* free config data memory */
1009 isc_mem_put(mctx
, cd
, sizeof(config_data_t
));
1011 /* detach memory from context */
1012 isc_mem_detach(&mctx
);
1015 static dns_sdlzmethods_t dlz_fs_methods
= {
1033 * Wrapper around dns_sdlzregister().
1038 isc_result_t result
;
1041 * Write debugging message to log
1043 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_DATABASE
,
1044 DNS_LOGMODULE_DLZ
, ISC_LOG_DEBUG(2),
1045 "Registering DLZ filesystem driver.");
1047 result
= dns_sdlzregister("filesystem", &dlz_fs_methods
, NULL
,
1048 DNS_SDLZFLAG_RELATIVEOWNER
|
1049 DNS_SDLZFLAG_RELATIVERDATA
,
1050 ns_g_mctx
, &dlz_fs
);
1051 if (result
!= ISC_R_SUCCESS
) {
1052 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
1053 "dns_sdlzregister() failed: %s",
1054 isc_result_totext(result
));
1055 result
= ISC_R_UNEXPECTED
;
1062 * Wrapper around dns_sdlzunregister().
1065 dlz_fs_clear(void) {
1068 * Write debugging message to log
1070 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_DATABASE
,
1071 DNS_LOGMODULE_DLZ
, ISC_LOG_DEBUG(2),
1072 "Unregistering DLZ filesystem driver.");
1075 dns_sdlzunregister(&dlz_fs
);