#include <config.h>
#include <dns/log.h>
#include <dns/result.h>
#include <isc/mem.h>
#include <isc/result.h>
#include <isc/string.h>
#include <isc/util.h>
#include <dlz/sdlz_helper.h>
static void
destroy_querylist(isc_mem_t *mctx, query_list_t **querylist)
{
query_segment_t *tseg = NULL;
query_segment_t *nseg = NULL;
REQUIRE(mctx != NULL);
if (*querylist == NULL)
return;
nseg = ISC_LIST_HEAD(**querylist);
while (nseg != NULL) {
tseg = nseg;
if (tseg->sql != NULL && tseg->direct == isc_boolean_true)
isc_mem_free(mctx, tseg->sql);
nseg = ISC_LIST_NEXT(nseg, link);
isc_mem_put(mctx, tseg, sizeof(query_segment_t));
}
isc_mem_put(mctx, *querylist, sizeof(query_list_t));
}
static isc_result_t
build_querylist(isc_mem_t *mctx, const char *query_str, char **zone,
char **record, char **client, query_list_t **querylist,
unsigned int flags)
{
isc_result_t result;
isc_boolean_t foundzone = isc_boolean_false;
isc_boolean_t foundrecord = isc_boolean_false;
isc_boolean_t foundclient = isc_boolean_false;
char *temp_str = NULL;
char *right_str = NULL;
query_list_t *tql;
query_segment_t *tseg = NULL;
REQUIRE(querylist != NULL && *querylist == NULL);
REQUIRE(mctx != NULL);
if (query_str == NULL || strlen(query_str) < 1) {
if ((flags & SDLZH_REQUIRE_QUERY) == 0)
return (ISC_R_SUCCESS);
else
return (ISC_R_FAILURE);
}
tql = isc_mem_get(mctx, sizeof(query_list_t));
if (tql == NULL)
return (ISC_R_NOMEMORY);
ISC_LIST_INIT(*tql);
temp_str = right_str = isc_mem_strdup(mctx, query_str);
if (right_str == NULL) {
result = ISC_R_NOMEMORY;
goto cleanup;
}
while (right_str != NULL) {
tseg = isc_mem_get(mctx, sizeof(query_segment_t));
if (tseg == NULL) {
result = ISC_R_NOMEMORY;
goto cleanup;
}
tseg->sql = NULL;
tseg->direct = isc_boolean_false;
ISC_LINK_INIT(tseg, link);
ISC_LIST_APPEND(*tql, tseg, link);
tseg->sql = isc_mem_strdup(mctx,
isc_string_separate(&right_str,
"$"));
if (tseg->sql == NULL) {
result = ISC_R_NOMEMORY;
goto cleanup;
}
tseg->direct = isc_boolean_true;
tseg->strlen = strlen(tseg->sql);
if (strcasecmp(tseg->sql, "zone") == 0) {
isc_mem_free(mctx, tseg->sql);
tseg->sql = (char**) zone;
tseg->strlen = 0;
tseg->direct = isc_boolean_false;
foundzone = isc_boolean_true;
} else if (strcasecmp(tseg->sql, "record") == 0) {
isc_mem_free(mctx, tseg->sql);
tseg->sql = (char**) record;
tseg->strlen = 0;
tseg->direct = isc_boolean_false;
foundrecord = isc_boolean_true;
} else if (strcasecmp(tseg->sql, "client") == 0) {
isc_mem_free(mctx, tseg->sql);
tseg->sql = (char**) client;
tseg->strlen = 0;
tseg->direct = isc_boolean_false;
foundclient = isc_boolean_true;
}
}
isc_mem_free(mctx, temp_str);
if (((flags & SDLZH_REQUIRE_CLIENT) != 0) && (!foundclient) ) {
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
"Required token $client$ not found.");
result = ISC_R_FAILURE;
goto flag_fail;
}
if (((flags & SDLZH_REQUIRE_RECORD) != 0) && (!foundrecord) ) {
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
"Required token $record$ not found.");
result = ISC_R_FAILURE;
goto flag_fail;
}
if (((flags & SDLZH_REQUIRE_ZONE) != 0) && (!foundzone) ) {
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
"Required token $zone$ not found.");
result = ISC_R_FAILURE;
goto flag_fail;
}
*querylist = (query_list_t *) tql;
return (ISC_R_SUCCESS);
cleanup:
if (temp_str != NULL)
isc_mem_free(mctx, temp_str);
flag_fail:
if (tql != NULL)
destroy_querylist(mctx, &tql);
return result;
}
char *
sdlzh_build_querystring(isc_mem_t *mctx, query_list_t *querylist)
{
query_segment_t *tseg = NULL;
unsigned int length = 0;
char *qs = NULL;
REQUIRE(mctx != NULL);
REQUIRE(querylist != NULL);
tseg = ISC_LIST_HEAD(*querylist);
while (tseg != NULL) {
if (tseg->direct == isc_boolean_true)
length += tseg->strlen;
else
length += strlen(* (char**) tseg->sql);
tseg = ISC_LIST_NEXT(tseg, link);
}
qs = isc_mem_allocate(mctx, length + 1);
if (qs == NULL)
return NULL;
*qs = 0;
tseg = ISC_LIST_HEAD(*querylist);
while (tseg != NULL) {
if (tseg->direct == isc_boolean_true)
strcat(qs, tseg->sql);
else
strcat(qs, * (char**) tseg->sql);
tseg = ISC_LIST_NEXT(tseg, link);
}
return qs;
}
isc_result_t
sdlzh_build_sqldbinstance(isc_mem_t *mctx, const char *allnodes_str,
const char *allowxfr_str, const char *authority_str,
const char *findzone_str, const char *lookup_str,
const char *countzone_str, dbinstance_t **dbi)
{
isc_result_t result;
dbinstance_t *db = NULL;
REQUIRE(dbi != NULL && *dbi == NULL);
REQUIRE(mctx != NULL);
db = isc_mem_get(mctx, sizeof(dbinstance_t));
if (db == NULL) {
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
"Could not allocate memory for "
"database instance object.");
return (ISC_R_NOMEMORY);
}
memset(db, 0, sizeof(dbinstance_t));
db->dbconn = NULL;
db->client = NULL;
db->record = NULL;
db->zone = NULL;
db->mctx = NULL;
db->query_buf = NULL;
db->allnodes_q = NULL;
db->allowxfr_q = NULL;
db->authority_q = NULL;
db->findzone_q = NULL;
db->countzone_q = NULL;
db->lookup_q = NULL;
isc_mem_attach(mctx, &db->mctx);
result = isc_mutex_init(&db->instance_lock);
if (result != ISC_R_SUCCESS) {
UNEXPECTED_ERROR(__FILE__, __LINE__,
"isc_mutex_init() failed: %s",
isc_result_totext(result));
goto cleanup;
}
result = build_querylist(mctx, allnodes_str, &db->zone,
&db->record, &db->client,
&db->allnodes_q, SDLZH_REQUIRE_ZONE);
if (result != ISC_R_SUCCESS) {
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
"Could not build all nodes query list");
goto cleanup;
}
result = build_querylist(mctx, allowxfr_str, &db->zone,
&db->record, &db->client,
&db->allowxfr_q,
SDLZH_REQUIRE_ZONE | SDLZH_REQUIRE_CLIENT);
if (result != ISC_R_SUCCESS) {
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
"Could not build allow xfr query list");
goto cleanup;
}
result = build_querylist(mctx, authority_str, &db->zone,
&db->record, &db->client,
&db->authority_q, SDLZH_REQUIRE_ZONE);
if (result != ISC_R_SUCCESS) {
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
"Could not build authority query list");
goto cleanup;
}
result = build_querylist(mctx, findzone_str, &db->zone,
&db->record, &db->client,
&db->findzone_q, SDLZH_REQUIRE_ZONE);
if (result != ISC_R_SUCCESS) {
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
"Could not build find zone query list");
goto cleanup;
}
result = build_querylist(mctx, countzone_str, &db->zone,
&db->record, &db->client,
&db->countzone_q, SDLZH_REQUIRE_ZONE);
if (result != ISC_R_SUCCESS) {
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
"Could not build count zone query list");
goto cleanup;
}
result = build_querylist(mctx, lookup_str, &db->zone,
&db->record, &db->client,
&db->lookup_q, SDLZH_REQUIRE_RECORD);
if (result != ISC_R_SUCCESS) {
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
"Could not build lookup query list");
goto cleanup;
}
*dbi = (dbinstance_t *) db;
return (ISC_R_SUCCESS);
cleanup:
destroy_sqldbinstance(db);
return (ISC_R_FAILURE);
}
void
sdlzh_destroy_sqldbinstance(dbinstance_t *dbi)
{
isc_mem_t *mctx;
mctx = dbi->mctx;
destroy_querylist(mctx, &dbi->allnodes_q);
destroy_querylist(mctx, &dbi->allowxfr_q);
destroy_querylist(mctx, &dbi->authority_q);
destroy_querylist(mctx, &dbi->findzone_q);
destroy_querylist(mctx, &dbi->countzone_q);
destroy_querylist(mctx, &dbi->lookup_q);
(void) isc_mutex_destroy(&dbi->instance_lock);
isc_mem_put(mctx, dbi, sizeof(dbinstance_t));
isc_mem_detach(&mctx);
}
char *
sdlzh_get_parameter_value(isc_mem_t *mctx, const char *input, const char* key)
{
int keylen;
char *keystart;
char value[255];
int i;
if (key == NULL || input == NULL || strlen(input) < 1)
return NULL;
keylen = strlen(key);
if (keylen < 1)
return NULL;
keystart = strstr(input, key);
if (keystart == NULL)
return NULL;
REQUIRE(mctx != NULL);
for (i = 0; i < 255; i++) {
value[i] = keystart[keylen + i];
if (value[i] == ' ' || value[i] == '\0') {
value[i] = '\0';
break;
}
}
return isc_mem_strdup(mctx, value);
}