#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdlib.h>
#include <ctype.h>
#include <sys/errno.h>
#include <dlz_minimal.h>
#include <dlz_list.h>
#include <dlz_dbi.h>
#include <dlz_pthread.h>
void
destroy_querylist(query_list_t **querylist) {
query_segment_t *tseg = NULL;
query_segment_t *nseg = NULL;
if (*querylist == NULL)
return;
nseg = DLZ_LIST_HEAD(**querylist);
while (nseg != NULL) {
tseg = nseg;
if (tseg->cmd != NULL && tseg->direct == ISC_TRUE)
free(tseg->cmd);
nseg = DLZ_LIST_NEXT(nseg, link);
free(tseg);
}
free(*querylist);
}
isc_result_t
build_querylist(const char *query_str, char **zone, char **record,
char **client, query_list_t **querylist, unsigned int flags,
log_t log)
{
isc_result_t result;
isc_boolean_t foundzone = ISC_FALSE;
isc_boolean_t foundrecord = ISC_FALSE;
isc_boolean_t foundclient = ISC_FALSE;
char *temp_str = NULL;
char *right_str = NULL;
query_list_t *tql;
query_segment_t *tseg = NULL;
if (query_str == NULL || strlen(query_str) < 1) {
if ((flags & REQUIRE_QUERY) == 0)
return (ISC_R_SUCCESS);
else
return (ISC_R_FAILURE);
}
tql = calloc(1, sizeof(query_list_t));
if (tql == NULL)
return (ISC_R_NOMEMORY);
DLZ_LIST_INIT(*tql);
temp_str = right_str = strdup(query_str);
if (right_str == NULL) {
result = ISC_R_NOMEMORY;
goto cleanup;
}
while (right_str != NULL) {
tseg = calloc(1, sizeof(query_segment_t));
if (tseg == NULL) {
result = ISC_R_NOMEMORY;
goto cleanup;
}
tseg->cmd = NULL;
tseg->direct = ISC_FALSE;
DLZ_LINK_INIT(tseg, link);
DLZ_LIST_APPEND(*tql, tseg, link);
tseg->cmd = strdup(strsep(&right_str, "$"));
if (tseg->cmd == NULL) {
result = ISC_R_NOMEMORY;
goto cleanup;
}
tseg->direct = ISC_TRUE;
tseg->strlen = strlen(tseg->cmd);
if (strcasecmp(tseg->cmd, "zone") == 0) {
free(tseg->cmd);
tseg->cmd = (char**) zone;
tseg->strlen = 0;
tseg->direct = ISC_FALSE;
foundzone = ISC_TRUE;
} else if (strcasecmp(tseg->cmd, "record") == 0) {
free(tseg->cmd);
tseg->cmd = (char**) record;
tseg->strlen = 0;
tseg->direct = ISC_FALSE;
foundrecord = ISC_TRUE;
} else if (strcasecmp(tseg->cmd, "client") == 0) {
free(tseg->cmd);
tseg->cmd = (char**) client;
tseg->strlen = 0;
tseg->direct = ISC_FALSE;
foundclient = ISC_TRUE;
}
}
free(temp_str);
if (((flags & REQUIRE_CLIENT) != 0) && (!foundclient) ) {
if (log != NULL)
log(ISC_LOG_ERROR,
"Required token $client$ not found.");
result = ISC_R_FAILURE;
goto flag_fail;
}
if (((flags & REQUIRE_RECORD) != 0) && (!foundrecord) ) {
if (log != NULL)
log(ISC_LOG_ERROR,
"Required token $record$ not found.");
result = ISC_R_FAILURE;
goto flag_fail;
}
if (((flags & REQUIRE_ZONE) != 0) && (!foundzone) ) {
if (log != NULL)
log(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)
free(temp_str);
flag_fail:
if (tql != NULL)
destroy_querylist(&tql);
return (result);
}
char *
build_querystring(query_list_t *querylist) {
query_segment_t *tseg = NULL;
unsigned int length = 0;
char *qs = NULL;
tseg = DLZ_LIST_HEAD(*querylist);
while (tseg != NULL) {
if (tseg->direct == ISC_TRUE)
length += tseg->strlen;
else
length += strlen(* (char**) tseg->cmd);
tseg = DLZ_LIST_NEXT(tseg, link);
}
qs = malloc(length + 1);
if (qs == NULL)
return (NULL);
*qs = '\0';
tseg = DLZ_LIST_HEAD(*querylist);
while (tseg != NULL) {
if (tseg->direct == ISC_TRUE)
strcat(qs, tseg->cmd);
else
strcat(qs, * (char**) tseg->cmd);
tseg = DLZ_LIST_NEXT(tseg, link);
}
return (qs);
}
isc_result_t
build_dbinstance(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, log_t log)
{
isc_result_t result;
dbinstance_t *db = NULL;
int err;
db = calloc(1, sizeof(dbinstance_t));
if (db == NULL) {
if (log != NULL)
log(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->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;
err = dlz_mutex_init(&db->lock, NULL);
if (err == ENOMEM) {
result = ISC_R_NOMEMORY;
goto cleanup;
} else if (err != 0) {
result = ISC_R_UNEXPECTED;
goto cleanup;
}
result = build_querylist(allnodes_str, &db->zone, &db->record,
&db->client, &db->allnodes_q,
REQUIRE_ZONE, log);
if (result != ISC_R_SUCCESS) {
if (log != NULL)
log(ISC_LOG_ERROR,
"Could not build all nodes query list");
goto cleanup;
}
result = build_querylist(allowxfr_str, &db->zone, &db->record,
&db->client, &db->allowxfr_q,
REQUIRE_ZONE | REQUIRE_CLIENT,
log);
if (result != ISC_R_SUCCESS) {
if (log != NULL)
log(ISC_LOG_ERROR,
"Could not build allow xfr query list");
goto cleanup;
}
result = build_querylist(authority_str, &db->zone, &db->record,
&db->client, &db->authority_q,
REQUIRE_ZONE, log);
if (result != ISC_R_SUCCESS) {
if (log != NULL)
log(ISC_LOG_ERROR,
"Could not build authority query list");
goto cleanup;
}
result = build_querylist(findzone_str, &db->zone, &db->record,
&db->client, &db->findzone_q,
REQUIRE_ZONE, log);
if (result != ISC_R_SUCCESS) {
if (log != NULL)
log(ISC_LOG_ERROR,
"Could not build find zone query list");
goto cleanup;
}
result = build_querylist(countzone_str, &db->zone, &db->record,
&db->client, &db->countzone_q,
REQUIRE_ZONE, log);
if (result != ISC_R_SUCCESS) {
if (log != NULL)
log(ISC_LOG_ERROR,
"Could not build count zone query list");
goto cleanup;
}
result = build_querylist(lookup_str, &db->zone, &db->record,
&db->client, &db->lookup_q,
REQUIRE_RECORD, log);
if (result != ISC_R_SUCCESS) {
if (log != NULL)
log(ISC_LOG_ERROR,
"Could not build lookup query list");
goto cleanup;
}
*dbi = (dbinstance_t *) db;
return (ISC_R_SUCCESS);
cleanup:
destroy_dbinstance(db);
return (ISC_R_FAILURE);
}
void
destroy_dbinstance(dbinstance_t *dbi) {
destroy_querylist(&dbi->allnodes_q);
destroy_querylist(&dbi->allowxfr_q);
destroy_querylist(&dbi->authority_q);
destroy_querylist(&dbi->findzone_q);
destroy_querylist(&dbi->countzone_q);
destroy_querylist(&dbi->lookup_q);
(void) dlz_mutex_destroy(&dbi->lock);
free(dbi);
}
char *
get_parameter_value(const char *input, const char* key) {
int keylen;
char *keystart;
char value[255];
int i;
if (key == NULL || input == NULL || *input == '\0')
return (NULL);
keylen = strlen(key);
if (keylen < 1)
return (NULL);
keystart = strstr(input, key);
if (keystart == NULL)
return (NULL);
for (i = 0; i < 255; i++) {
value[i] = keystart[keylen + i];
if (isspace(value[i]) || value[i] == '\0') {
value[i] = '\0';
break;
}
}
return (strdup(value));
}