dlz_bdbhpt_driver.c
来自「非常好的dns解析软件」· C语言 代码 · 共 861 行 · 第 1/2 页
C
861 行
/* * 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_BDB#include <config.h>#include <stdio.h>#include <string.h>#include <stdlib.h>#include <dns/log.h>#include <dns/sdlz.h>#include <dns/result.h>#include <isc/mem.h>#include <isc/print.h>#include <isc/result.h>#include <isc/util.h>#include <named/globals.h>#include <dlz/dlz_bdbhpt_driver.h>#include <db.h>static dns_sdlzimplementation_t *dlz_bdbhpt = NULL;/* should the bdb driver use threads. */#ifdef ISC_PLATFORM_USETHREADS#define bdbhpt_threads DB_THREAD#else#define bdbhpt_threads 0#endif/* bdbhpt database names */#define dlz_data "dns_data"#define dlz_zone "dns_zone"#define dlz_xfr "dns_xfr"#define dlz_client "dns_client" /* This structure contains all the Berkeley DB handles * for this instance of the bdbhpt driver. */typedef struct bdbhpt_instance { DB_ENV *dbenv; /*%< bdbhpt environment */ DB *data; /*%< dns_data database handle */ DB *zone; /*%< zone database handle */ DB *xfr; /*%< zone xfr database handle */ DB *client; /*%< client database handle */ isc_mem_t *mctx; /*%< memory context */} bdbhpt_instance_t;typedef struct bdbhpt_parsed_data { char *host; char *type; int ttl; char *data;} bdbhpt_parsed_data_t;/* forward reference */static isc_result_tbdbhpt_findzone(void *driverarg, void *dbdata, const char *name);/*% * Reverses a string in place. */static char *bdbhpt_strrev(char *str){ char *p1, *p2; if (! str || ! *str) return str; for (p1 = str, p2 = str + strlen(str) - 1; p2 > p1; ++p1, --p2) { *p1 ^= *p2; *p2 ^= *p1; *p1 ^= *p2; } return str;}/*% * Parses the DBT from the Berkeley DB into a parsed_data record * The parsed_data record should be allocated before and passed into the * bdbhpt_parse_data function. The char (type & data) fields should not * be "free"d as that memory is part of the DBT data field. It will be * "free"d when the DBT is freed. */static isc_result_tbdbhpt_parse_data(char *in, bdbhpt_parsed_data_t *pd) { char *endp, *ttlStr; char *tmp = in; char *lastchar = (char *) &tmp[strlen(tmp)]; /*% * String should be formated as: * replication_id * (a space) * host_name * (a space) * ttl * (a space) * type * (a space) * remaining data * * examples: * * 9191 host 10 A 127.0.0.1 * server1_212 host 10 A 127.0.0.2 * {xxxx-xxxx-xxxx-xxxx-xxxx} host 10 MX 20 mail.example.com */ /* * we don't need the replication id, so don't * bother saving a pointer to it. */ /* find space after replication id */ tmp = strchr(tmp, ' '); /* verify we found a space */ if (tmp == NULL) return ISC_R_FAILURE; /* make sure it is safe to increment pointer */ if (++tmp > lastchar) return ISC_R_FAILURE; /* save pointer to host */ pd->host = tmp; /* find space after host and change it to a '\0' */ tmp = strchr(tmp, ' '); /* verify we found a space */ if (tmp == NULL) return ISC_R_FAILURE; /* change the space to a null (string terminator) */ tmp[0] = '\0'; /* make sure it is safe to increment pointer */ if (++tmp > lastchar) return ISC_R_FAILURE; /* save pointer to ttl string */ ttlStr = tmp; /* find space after ttl and change it to a '\0' */ tmp = strchr(tmp, ' '); /* verify we found a space */ if (tmp == NULL) return ISC_R_FAILURE; /* change the space to a null (string terminator) */ tmp[0] = '\0'; /* make sure it is safe to increment pointer */ if (++tmp > lastchar) return ISC_R_FAILURE; /* save pointer to dns type */ pd->type = tmp; /* find space after type and change it to a '\0' */ tmp = strchr(tmp, ' '); /* verify we found a space */ if (tmp == NULL) return ISC_R_FAILURE; /* change the space to a null (string terminator) */ tmp[0] = '\0'; /* make sure it is safe to increment pointer */ if (++tmp > lastchar) return ISC_R_FAILURE; /* save pointer to remainder of DNS data */ pd->data = tmp; /* convert ttl string to integer */ pd->ttl = strtol(ttlStr, &endp, 10); if (*endp != '\0' || pd->ttl < 0) { isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_ERROR, "bdbhpt driver ttl must be a postive number"); return ISC_R_FAILURE; } /* if we get this far everything should have worked. */ return ISC_R_SUCCESS;}/* * DLZ methods */static isc_result_tbdbhpt_allowzonexfr(void *driverarg, void *dbdata, const char *name, const char *client){ isc_result_t result; bdbhpt_instance_t *db = (bdbhpt_instance_t *) dbdata; DBT key, data; /* check to see if we are authoritative for the zone first. */ result = bdbhpt_findzone(driverarg, dbdata, name); if (result != ISC_R_SUCCESS) return (ISC_R_NOTFOUND); memset(&key, 0, sizeof(DBT)); key.flags = DB_DBT_MALLOC; key.data = strdup(name); if (key.data == NULL) { result = ISC_R_NOMEMORY; goto xfr_cleanup; } key.size = strlen(key.data); memset(&data, 0, sizeof(DBT)); data.flags = DB_DBT_MALLOC; data.data = strdup(client); if (data.data == NULL) { result = ISC_R_NOMEMORY; goto xfr_cleanup; } data.size = strlen(data.data); switch(db->client->get(db->client, NULL, &key, &data, DB_GET_BOTH)) { case DB_NOTFOUND: result = ISC_R_NOTFOUND; break; case 0: result = ISC_R_SUCCESS; break; default: result = ISC_R_FAILURE; } xfr_cleanup: /* free any memory duplicate string in the key field */ if (key.data != NULL) free(key.data); /* free any memory allocated to the data field. */ if (data.data != NULL) free(data.data); return result;}/*% * BDB does not allow a secondary index on a database that allows * duplicates. We have a few options: * * 1) kill speed by having lookup method use a secondary db which * is associated to the primary DB with the DNS data. Then have * another secondary db for zone transfer which also points to * the dns_data primary. NO - The point of this driver is * lookup performance. * * 2) Blow up database size by storing DNS data twice. Once for * the lookup (dns_data) database, and a second time for the zone * transfer (dns_xfr) database. NO - That would probably require * a larger cache to provide good performance. Also, that would * make the DB larger on disk potentially slowing it as well. * * 3) Loop through the dns_xfr database with a cursor to get * all the different hosts in a zone. Then use the zone & host * together to lookup the data in the dns_data database. YES - * This may slow down zone xfr's a little, but that's ok they * don't happen as often and don't need to be as fast. We can * also use this table when deleting a zone (The BDB driver * is read only - the delete would be used during replication * updates by a separate process). */static isc_result_tbdbhpt_allnodes(const char *zone, void *driverarg, void *dbdata, dns_sdlzallnodes_t *allnodes){ isc_result_t result = ISC_R_NOTFOUND; bdbhpt_instance_t *db = (bdbhpt_instance_t *) dbdata; DBC *xfr_cursor = NULL; DBC *dns_cursor = NULL; DBT xfr_key, xfr_data, dns_key, dns_data; int xfr_flags; int dns_flags; int bdbhptres; bdbhpt_parsed_data_t pd; char *tmp = NULL, *tmp_zone, *tmp_zone_host = NULL; UNUSED(driverarg); memset(&xfr_key, 0, sizeof(DBT)); memset(&xfr_data, 0, sizeof(DBT)); memset(&dns_key, 0, sizeof(DBT)); memset(&dns_data, 0, sizeof(DBT)); xfr_key.data = tmp_zone = strdup(zone); if (xfr_key.data == NULL) return (ISC_R_NOMEMORY); xfr_key.size = strlen(xfr_key.data); /* get a cursor to loop through dns_xfr table */ if (db->xfr->cursor(db->xfr, NULL, &xfr_cursor, 0) != 0) { result = ISC_R_FAILURE; goto allnodes_cleanup; } /* get a cursor to loop through dns_data table */ if (db->data->cursor(db->data, NULL, &dns_cursor, 0) != 0) { result = ISC_R_FAILURE; goto allnodes_cleanup; } xfr_flags = DB_SET; /* loop through xfr table for specified zone. */ while ((bdbhptres = xfr_cursor->c_get(xfr_cursor, &xfr_key, &xfr_data, xfr_flags)) == 0) { xfr_flags = DB_NEXT_DUP; /* +1 to allow for space between zone and host names */ dns_key.size = xfr_data.size + xfr_key.size + 1; /* +1 to allow for null term at end of string. */ dns_key.data = tmp_zone_host = malloc(dns_key.size + 1); if (dns_key.data == NULL) goto allnodes_cleanup; /* * construct search key for dns_data. * zone_name(a space)host_name */ strcpy(dns_key.data, zone); strcat(dns_key.data, " "); strncat(dns_key.data, xfr_data.data, xfr_data.size); dns_flags = DB_SET; while ((bdbhptres = dns_cursor->c_get(dns_cursor, &dns_key, &dns_data, dns_flags)) == 0) { dns_flags = DB_NEXT_DUP; /* +1 to allow for null term at end of string. */ tmp = realloc(tmp, dns_data.size + 1); if (tmp == NULL) goto allnodes_cleanup; /* copy data to tmp string, and append null term. */ strncpy(tmp, dns_data.data, dns_data.size); tmp[dns_data.size] = '\0'; /* split string into dns data parts. */ if (bdbhpt_parse_data(tmp, &pd) != ISC_R_SUCCESS) goto allnodes_cleanup; result = dns_sdlz_putnamedrr(allnodes, pd.host, pd.type, pd.ttl, pd.data); if (result != ISC_R_SUCCESS) goto allnodes_cleanup; } /* end inner while loop */ /* clean up memory */ if (tmp_zone_host != NULL) { free(tmp_zone_host); tmp_zone_host = NULL; } } /* end outer while loop */ allnodes_cleanup: /* free any memory */ if (tmp != NULL)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?