dlz_filesystem_driver.c
来自「非常好的dns解析软件」· C语言 代码 · 共 1,049 行 · 第 1/2 页
C
1,049 行
/* * Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all * copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL * STICHTING NLNET BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE * USE OR PERFORMANCE OF THIS SOFTWARE. * * The development of Dynamically Loadable Zones (DLZ) for Bind 9 was * conceived and contributed by Rob Butler. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all * copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL * ROB BUTLER BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE * USE OR PERFORMANCE OF THIS SOFTWARE. *//* * Copyright (C) 1999-2001 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */#ifdef DLZ_FILESYSTEM#include <config.h>#include <stdio.h>#include <string.h>#include <stdlib.h>#include <sys/stat.h>#include <dns/log.h>#include <dns/sdlz.h>#include <dns/result.h>#include <isc/dir.h>#include <isc/mem.h>#include <isc/platform.h>#include <isc/print.h>#include <isc/result.h>#include <isc/util.h>#include <named/globals.h>#include <dlz/dlz_filesystem_driver.h>static dns_sdlzimplementation_t *dlz_fs = NULL;typedef struct config_data { char *basedir; int basedirsize; char *datadir; int datadirsize; char *xfrdir; int xfrdirsize; int splitcnt; char separator; char pathsep; isc_mem_t *mctx;} config_data_t;typedef struct dir_entry dir_entry_t;struct dir_entry { char dirpath[ISC_DIR_PATHMAX]; ISC_LINK(dir_entry_t) link;};typedef ISC_LIST(dir_entry_t) dlist_t;/* forward reference */static voidfs_destroy(void *driverarg, void *dbdata);/* * Private methods */static isc_boolean_tis_safe(const char *input){ unsigned int i; unsigned int len = strlen(input); /* check that only allowed characters are in the domain name */ for (i=0; i < len; i++) { /* '.' is allowed, but has special requirements */ if (input[i] == '.') { /* '.' is not allowed as first char */ if (i == 0) return ISC_FALSE; /* '..', two dots together is not allowed. */ else if (input[i-1] == '.') return ISC_FALSE; /* '.' is not allowed as last char */ if (i == len) return ISC_FALSE; /* only 1 dot in ok location, continue at next char */ continue; } /* '-' is allowed, continue at next char */ if (input[i] == '-') continue; /* 0-9 is allowed, continue at next char */ if (input[i] >= '0' && input[i] <= '9') continue; /* A-Z uppercase is allowed, continue at next char */ if (input[i] >= 'A' && input[i] <= 'Z') continue; /* a-z lowercase is allowed, continue at next char */ if (input[i] >= 'a' && input[i] <= 'z') continue; /* * colon needs to be allowed for IPV6 client * addresses. Not dangerous in domain names, as not a * special char. */ if (input[i] == ':') continue; /* * '@' needs to be allowed for in zone data. Not * dangerous in domain names, as not a special char. */ if (input[i] == '@') continue; /* * if we reach this point we have encountered a * disallowed char! */ return ISC_FALSE; } /* everything ok. */ return ISC_TRUE;}static isc_result_tcreate_path_helper(char *out, const char *in, config_data_t *cd){ char *tmpString; char *tmpPtr; int i; tmpString = isc_mem_strdup(ns_g_mctx, in); if (tmpString == NULL) return (ISC_R_NOMEMORY); /* * don't forget is_safe guarantees '.' will NOT be the * first/last char */ while ((tmpPtr = strrchr(tmpString, '.')) != NULL) { i = 0; while (tmpPtr[i+1] != '\0') { if (cd->splitcnt < 1) strcat(out, (char *) &tmpPtr[i+1]); else strncat(out, (char *) &tmpPtr[i+1], cd->splitcnt); strncat(out, (char *) &cd->pathsep, 1); if (cd->splitcnt == 0) break; if (strlen((char *) &tmpPtr[i+1]) <= (unsigned int) cd->splitcnt) break; i += cd->splitcnt; } tmpPtr[0] = '\0'; } /* handle the "first" label properly */ i=0; tmpPtr = tmpString; while (tmpPtr[i] != '\0') { if (cd->splitcnt < 1) strcat(out, (char *) &tmpPtr[i]); else strncat(out, (char *) &tmpPtr[i], cd->splitcnt); strncat(out, (char *) &cd->pathsep, 1); if (cd->splitcnt == 0) break; if (strlen((char *) &tmpPtr[i]) <= (unsigned int) cd->splitcnt) break; i += cd->splitcnt; } isc_mem_free(ns_g_mctx, tmpString); return (ISC_R_SUCCESS);}/*% * Checks to make sure zone and host are safe. If safe, then * hashes zone and host strings to build a path. If zone / host * are not safe an error is returned. */static isc_result_tcreate_path(const char *zone, const char *host, const char *client, config_data_t *cd, char **path){ char *tmpPath; int pathsize; int len; isc_result_t result; /* we require a zone & cd parameter */ REQUIRE(zone != NULL); REQUIRE(cd != NULL); /* require path to be a pointer to NULL */ REQUIRE(path != NULL && *path == NULL); /* * client and host may both be NULL, but they can't both be * NON-NULL */ REQUIRE( (host == NULL && client == NULL) || (host != NULL && client == NULL) || (host == NULL && client != NULL) ); /* if the requested zone is "unsafe", return error */ if (is_safe(zone) != ISC_TRUE) return (ISC_R_FAILURE); /* if host was passed, verify that it is safe */ if ((host != NULL) && (is_safe(host) != ISC_TRUE) ) return (ISC_R_FAILURE); /* if host was passed, verify that it is safe */ if ((client != NULL) && (is_safe(client) != ISC_TRUE) ) return (ISC_R_FAILURE); /* Determine how much memory the split up string will require */ if (host != NULL) len = strlen(zone) + strlen(host); else if (client != NULL) len = strlen(zone) + strlen(client); else len = strlen(zone); /* * even though datadir and xfrdir will never be in the same * string we only waste a few bytes by allocating for both, * and then we are safe from buffer overruns. */ pathsize = len + cd->basedirsize + cd->datadirsize + cd->xfrdirsize + 4; /* if we are splitting names, we will need extra space. */ if (cd->splitcnt > 0) pathsize += len/cd->splitcnt; tmpPath = isc_mem_allocate(ns_g_mctx , pathsize * sizeof(char)); if (tmpPath == NULL) { /* write error message */ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_ERROR, "Filesystem driver unable to " "allocate memory in create_path()."); result = ISC_R_NOMEMORY; goto cleanup_mem; } /* * build path string. * start out with base directory. */ strcpy(tmpPath, cd->basedir); /* add zone name - parsed properly */ if ((result = create_path_helper(tmpPath, zone, cd)) != ISC_R_SUCCESS) goto cleanup_mem; /* * When neither client or host is passed we are building a * path to see if a zone is supported. We require that a zone * path have the "data dir" directory contained within it so * that we know this zone is really supported. Otherwise, * this zone may not really be supported because we are * supporting a delagated sub zone. * * Example: * * We are supporting long.domain.com and using a splitcnt of * 0. the base dir is "/base-dir/" and the data dir is * "/.datadir" We want to see if we are authoritative for * domain.com. Path /base-dir/com/domain/.datadir since * /base-dir/com/domain/.datadir does not exist, we are not * authoritative for the domain "domain.com". However we are * authoritative for the domain "long.domain.com" because the * path /base-dir/com/domain/long/.datadir does exist! */ /* if client is passed append xfr dir, otherwise append data dir */ if (client != NULL) { strcat(tmpPath, cd->xfrdir); strncat(tmpPath, (char *) &cd->pathsep, 1); strcat(tmpPath, client); } else { strcat(tmpPath, cd->datadir); } /* if host not null, add it. */ if (host != NULL) { strncat(tmpPath, (char *) &cd->pathsep, 1); if ((result = create_path_helper(tmpPath, host, cd)) != ISC_R_SUCCESS) goto cleanup_mem; } /* return the path we built. */ *path = tmpPath; /* return success */ result = ISC_R_SUCCESS; cleanup_mem: /* cleanup memory */ /* free tmpPath memory */ if (tmpPath != NULL && result != ISC_R_SUCCESS) isc_mem_free(ns_g_mctx, tmpPath); /* free tmpPath memory */ return result;}static isc_result_tprocess_dir(isc_dir_t dir, void *passback, config_data_t *cd, dlist_t *dir_list, unsigned int basedirlen){ char tmp[ISC_DIR_PATHMAX + ISC_DIR_NAMEMAX]; int astPos; struct stat sb; isc_result_t result = ISC_R_FAILURE; char *endp; char *type; char *ttlStr; char *data; char host[ISC_DIR_NAMEMAX]; char *tmpString; char *tmpPtr; int ttl; int i; int len; dir_entry_t *direntry; isc_boolean_t foundHost; tmp[0] = '\0'; /* set 1st byte to '\0' so strcpy works right. */ host[0] = '\0'; foundHost = ISC_FALSE; /* copy base directory name to tmp. */ strcpy(tmp, dir.dirname); /* dir.dirname will always have '*' as the last char. */ astPos = strlen(dir.dirname) - 1; /* if dir_list != NULL, were are performing a zone xfr */ if (dir_list != NULL) { /* if splitcnt == 0, determine host from path. */ if (cd->splitcnt == 0) { if (strlen(tmp) - 3 > basedirlen) { tmp[astPos-1] = '\0'; tmpString = (char *) &tmp[basedirlen+1]; /* handle filesystem's special wildcard "-" */ if (strcmp(tmpString, "-") == 0) { strcpy(host, "*"); } else { /* * not special wildcard -- normal name */ while ((tmpPtr = strrchr(tmpString, cd->pathsep)) != NULL) { strcat(host, tmpPtr + 1); strcat(host, "."); tmpPtr[0] = '\0'; } strcat(host, tmpString); } foundHost = ISC_TRUE; /* set tmp again for use later */ strcpy(tmp, dir.dirname); } } else { /* * if splitcnt != 0 determine host from * ".host" directory entry */ while (isc_dir_read(&dir) == ISC_R_SUCCESS) { if (strncasecmp(".host", dir.entry.name, 5) == 0) { /* * handle filesystem's special * wildcard "-" */ if (strcmp((char *) &dir.entry.name[6], "-") == 0) strcpy(host, "*"); else strcpy(host, (char *) &dir.entry.name[6]); foundHost = ISC_TRUE; break; } } /* reset dir list for use later */ isc_dir_reset(&dir); } /* end of else */ } while (isc_dir_read(&dir) == ISC_R_SUCCESS) { isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1), "Filesystem driver Dir name:" " '%s' Dir entry: '%s'\n", dir.dirname, dir.entry.name); /* skip any entries starting with "." */ if (dir.entry.name[0] == '.') continue; /* * get rid of '*', set to NULL. Effectively trims * string from previous loop to base directory only * while still leaving memory for concat to be * performed next. */ tmp[astPos] = '\0'; /* add name to base directory name. */ strcat(tmp, dir.entry.name); /* make sure we can stat entry */ if (stat(tmp, &sb) == 0 ) { /* if entry is a directory */ if ((sb.st_mode & S_IFDIR) != 0) { /* * if dir list is NOT NULL, add dir to * dir list */ if (dir_list != NULL) { direntry = isc_mem_get(ns_g_mctx, sizeof(dir_entry_t)); if (direntry == NULL) return (ISC_R_NOMEMORY); strcpy(direntry->dirpath, tmp); ISC_LINK_INIT(direntry, link); ISC_LIST_APPEND(*dir_list, direntry, link); result = ISC_R_SUCCESS; } continue; /* * if entry is a file be sure we do * not add entry to DNS results if we * are performing a zone xfr and we * could not find a host entry. */ } else if (dir_list != NULL && foundHost == ISC_FALSE) { continue; } } else /* if we cannot stat entry, skip it. */ continue; type = dir.entry.name; ttlStr = strchr(type, cd->separator); if (ttlStr == NULL) { isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_ERROR, "Filesystem driver: " "%s could not be parsed properly", tmp); return ISC_R_FAILURE; } /* replace separator char with NULL to split string */ ttlStr[0] = '\0'; /* start string after NULL of previous string */ ttlStr = (char *) &ttlStr[1];
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?