|
Packit Service |
ae04f2 |
/*
|
|
Packit Service |
ae04f2 |
* Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl.
|
|
Packit Service |
ae04f2 |
*
|
|
Packit Service |
ae04f2 |
* Permission to use, copy, modify, and distribute this software for any
|
|
Packit Service |
ae04f2 |
* purpose with or without fee is hereby granted, provided that the
|
|
Packit Service |
ae04f2 |
* above copyright notice and this permission notice appear in all
|
|
Packit Service |
ae04f2 |
* copies.
|
|
Packit Service |
ae04f2 |
*
|
|
Packit Service |
ae04f2 |
* THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET
|
|
Packit Service |
ae04f2 |
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
|
|
Packit Service |
ae04f2 |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
|
Packit Service |
ae04f2 |
* STICHTING NLNET BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
|
|
Packit Service |
ae04f2 |
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
|
Packit Service |
ae04f2 |
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
|
Packit Service |
ae04f2 |
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
|
|
Packit Service |
ae04f2 |
* USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
Packit Service |
ae04f2 |
*
|
|
Packit Service |
ae04f2 |
* The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
|
|
Packit Service |
ae04f2 |
* conceived and contributed by Rob Butler.
|
|
Packit Service |
ae04f2 |
*
|
|
Packit Service |
ae04f2 |
* Permission to use, copy, modify, and distribute this software for any
|
|
Packit Service |
ae04f2 |
* purpose with or without fee is hereby granted, provided that the
|
|
Packit Service |
ae04f2 |
* above copyright notice and this permission notice appear in all
|
|
Packit Service |
ae04f2 |
* copies.
|
|
Packit Service |
ae04f2 |
*
|
|
Packit Service |
ae04f2 |
* THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER
|
|
Packit Service |
ae04f2 |
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
|
|
Packit Service |
ae04f2 |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
|
Packit Service |
ae04f2 |
* ROB BUTLER BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
|
|
Packit Service |
ae04f2 |
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
|
Packit Service |
ae04f2 |
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
|
Packit Service |
ae04f2 |
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
|
|
Packit Service |
ae04f2 |
* USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
Packit Service |
ae04f2 |
*/
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/*
|
|
Packit Service |
ae04f2 |
* Copyright (C) 1999-2001, 2016 Internet Systems Consortium, Inc. ("ISC")
|
|
Packit Service |
ae04f2 |
*
|
|
Packit Service |
ae04f2 |
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
Packit Service |
ae04f2 |
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
Packit Service |
ae04f2 |
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
Packit Service |
ae04f2 |
*/
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
#ifdef DLZ_POSTGRES
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
#include <config.h>
|
|
Packit Service |
ae04f2 |
#include <stdio.h>
|
|
Packit Service |
ae04f2 |
#include <string.h>
|
|
Packit Service |
ae04f2 |
#include <stdlib.h>
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
#include <dns/log.h>
|
|
Packit Service |
ae04f2 |
#include <dns/sdlz.h>
|
|
Packit Service |
ae04f2 |
#include <dns/result.h>
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
#include <isc/mem.h>
|
|
Packit Service |
ae04f2 |
#include <isc/platform.h>
|
|
Packit Service |
ae04f2 |
#include <isc/print.h>
|
|
Packit Service |
ae04f2 |
#include <isc/result.h>
|
|
Packit Service |
ae04f2 |
#include <isc/string.h>
|
|
Packit Service |
ae04f2 |
#include <isc/util.h>
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
#include <named/globals.h>
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
#include <dlz/sdlz_helper.h>
|
|
Packit Service |
ae04f2 |
#include <dlz/dlz_postgres_driver.h>
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/* temporarily include time. */
|
|
Packit Service |
ae04f2 |
#include <time.h>
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
#include <libpq-fe.h>
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
static dns_sdlzimplementation_t *dlz_postgres = NULL;
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
#define dbc_search_limit 30
|
|
Packit Service |
ae04f2 |
#define ALLNODES 1
|
|
Packit Service |
ae04f2 |
#define ALLOWXFR 2
|
|
Packit Service |
ae04f2 |
#define AUTHORITY 3
|
|
Packit Service |
ae04f2 |
#define FINDZONE 4
|
|
Packit Service |
ae04f2 |
#define LOOKUP 5
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/*
|
|
Packit Service |
ae04f2 |
* Private methods
|
|
Packit Service |
ae04f2 |
*/
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/* ---------------
|
|
Packit Service |
ae04f2 |
* Escaping arbitrary strings to get valid SQL strings/identifiers.
|
|
Packit Service |
ae04f2 |
*
|
|
Packit Service |
ae04f2 |
* Replaces "\\" with "\\\\" and "'" with "''".
|
|
Packit Service |
ae04f2 |
* length is the length of the buffer pointed to by
|
|
Packit Service |
ae04f2 |
* from. The buffer at to must be at least 2*length + 1 characters
|
|
Packit Service |
ae04f2 |
* long. A terminating NUL character is written.
|
|
Packit Service |
ae04f2 |
*
|
|
Packit Service |
ae04f2 |
* NOTICE!!!
|
|
Packit Service |
ae04f2 |
* This function was borrowed directly from PostgreSQL's libpq.
|
|
Packit Service |
ae04f2 |
* The function was originally called PQescapeString and renamed
|
|
Packit Service |
ae04f2 |
* to postgres_makesafe to avoid a naming collision.
|
|
Packit Service |
ae04f2 |
* PQescapeString is a new function made available in Postgres 7.2.
|
|
Packit Service |
ae04f2 |
* For some reason the function is not properly exported on Win32
|
|
Packit Service |
ae04f2 |
* builds making the function unavailable on Windows. Also, since
|
|
Packit Service |
ae04f2 |
* this function is new it would require building this driver with
|
|
Packit Service |
ae04f2 |
* the libpq 7.2. By borrowing this function the Windows problem
|
|
Packit Service |
ae04f2 |
* is solved, and the dependence on libpq 7.2 is removed. Libpq is
|
|
Packit Service |
ae04f2 |
* still required of course, but an older version should work now too.
|
|
Packit Service |
ae04f2 |
*
|
|
Packit Service |
ae04f2 |
* The copyright statements from the original file containing this
|
|
Packit Service |
ae04f2 |
* function are included below:
|
|
Packit Service |
ae04f2 |
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
|
Packit Service |
ae04f2 |
* Portions Copyright (c) 1994, Regents of the University of California
|
|
Packit Service |
ae04f2 |
* ---------------
|
|
Packit Service |
ae04f2 |
*/
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
static size_t
|
|
Packit Service |
ae04f2 |
postgres_makesafe(char *to, const char *from, size_t length)
|
|
Packit Service |
ae04f2 |
{
|
|
Packit Service |
ae04f2 |
const char *source = from;
|
|
Packit Service |
ae04f2 |
char *target = to;
|
|
Packit Service |
ae04f2 |
unsigned int remaining = length;
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
while (remaining > 0)
|
|
Packit Service |
ae04f2 |
{
|
|
Packit Service |
ae04f2 |
switch (*source)
|
|
Packit Service |
ae04f2 |
{
|
|
Packit Service |
ae04f2 |
case '\\':
|
|
Packit Service |
ae04f2 |
*target = '\\';
|
|
Packit Service |
ae04f2 |
target++;
|
|
Packit Service |
ae04f2 |
*target = '\\';
|
|
Packit Service |
ae04f2 |
/* target and remaining are updated below. */
|
|
Packit Service |
ae04f2 |
break;
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
case '\'':
|
|
Packit Service |
ae04f2 |
*target = '\'';
|
|
Packit Service |
ae04f2 |
target++;
|
|
Packit Service |
ae04f2 |
*target = '\'';
|
|
Packit Service |
ae04f2 |
/* target and remaining are updated below. */
|
|
Packit Service |
ae04f2 |
break;
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
default:
|
|
Packit Service |
ae04f2 |
*target = *source;
|
|
Packit Service |
ae04f2 |
/* target and remaining are updated below. */
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
source++;
|
|
Packit Service |
ae04f2 |
target++;
|
|
Packit Service |
ae04f2 |
remaining--;
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/* Write the terminating NUL character. */
|
|
Packit Service |
ae04f2 |
*target = '\0';
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
return target - to;
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
#ifdef ISC_PLATFORM_USETHREADS
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/*%
|
|
Packit Service |
ae04f2 |
* Properly cleans up a list of database instances.
|
|
Packit Service |
ae04f2 |
* This function is only used when the driver is compiled for
|
|
Packit Service |
ae04f2 |
* multithreaded operation.
|
|
Packit Service |
ae04f2 |
*/
|
|
Packit Service |
ae04f2 |
static void
|
|
Packit Service |
ae04f2 |
postgres_destroy_dblist(db_list_t *dblist)
|
|
Packit Service |
ae04f2 |
{
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
dbinstance_t *ndbi = NULL;
|
|
Packit Service |
ae04f2 |
dbinstance_t *dbi = NULL;
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/* get the first DBI in the list */
|
|
Packit Service |
ae04f2 |
ndbi = ISC_LIST_HEAD(*dblist);
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/* loop through the list */
|
|
Packit Service |
ae04f2 |
while (ndbi != NULL) {
|
|
Packit Service |
ae04f2 |
dbi = ndbi;
|
|
Packit Service |
ae04f2 |
/* get the next DBI in the list */
|
|
Packit Service |
ae04f2 |
ndbi = ISC_LIST_NEXT(dbi, link);
|
|
Packit Service |
ae04f2 |
/* release DB connection */
|
|
Packit Service |
ae04f2 |
if (dbi->dbconn != NULL)
|
|
Packit Service |
ae04f2 |
PQfinish((PGconn *) dbi->dbconn);
|
|
Packit Service |
ae04f2 |
/* release all memory that comprised a DBI */
|
|
Packit Service |
ae04f2 |
destroy_sqldbinstance(dbi);
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
/* release memory for the list structure */
|
|
Packit Service |
ae04f2 |
isc_mem_put(ns_g_mctx, dblist, sizeof(db_list_t));
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/*%
|
|
Packit Service |
ae04f2 |
* Loops through the list of DB instances, attempting to lock
|
|
Packit Service |
ae04f2 |
* on the mutex. If successful, the DBI is reserved for use
|
|
Packit Service |
ae04f2 |
* and the thread can perform queries against the database.
|
|
Packit Service |
ae04f2 |
* If the lock fails, the next one in the list is tried.
|
|
Packit Service |
ae04f2 |
* looping continues until a lock is obtained, or until
|
|
Packit Service |
ae04f2 |
* the list has been searched dbc_search_limit times.
|
|
Packit Service |
ae04f2 |
* This function is only used when the driver is compiled for
|
|
Packit Service |
ae04f2 |
* multithreaded operation.
|
|
Packit Service |
ae04f2 |
*/
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
static dbinstance_t *
|
|
Packit Service |
ae04f2 |
postgres_find_avail_conn(db_list_t *dblist)
|
|
Packit Service |
ae04f2 |
{
|
|
Packit Service |
ae04f2 |
dbinstance_t *dbi = NULL;
|
|
Packit Service |
ae04f2 |
dbinstance_t *head;
|
|
Packit Service |
ae04f2 |
int count = 0;
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/* get top of list */
|
|
Packit Service |
ae04f2 |
head = dbi = ISC_LIST_HEAD(*dblist);
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/* loop through list */
|
|
Packit Service |
ae04f2 |
while (count < dbc_search_limit) {
|
|
Packit Service |
ae04f2 |
/* try to lock on the mutex */
|
|
Packit Service |
ae04f2 |
if (isc_mutex_trylock(&dbi->instance_lock) == ISC_R_SUCCESS)
|
|
Packit Service |
ae04f2 |
return dbi; /* success, return the DBI for use. */
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/* not successful, keep trying */
|
|
Packit Service |
ae04f2 |
dbi = ISC_LIST_NEXT(dbi, link);
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/* check to see if we have gone to the top of the list. */
|
|
Packit Service |
ae04f2 |
if (dbi == NULL) {
|
|
Packit Service |
ae04f2 |
count++;
|
|
Packit Service |
ae04f2 |
dbi = head;
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
|
|
Packit Service |
ae04f2 |
DNS_LOGMODULE_DLZ, ISC_LOG_INFO,
|
|
Packit Service |
ae04f2 |
"Postgres driver unable to find available connection "
|
|
Packit Service |
ae04f2 |
"after searching %d times",
|
|
Packit Service |
ae04f2 |
count);
|
|
Packit Service |
ae04f2 |
return NULL;
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
#endif /* ISC_PLATFORM_USETHREADS */
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/*%
|
|
Packit Service |
ae04f2 |
* Allocates memory for a new string, and then constructs the new
|
|
Packit Service |
ae04f2 |
* string by "escaping" the input string. The new string is
|
|
Packit Service |
ae04f2 |
* safe to be used in queries. This is necessary because we cannot
|
|
Packit Service |
ae04f2 |
* be sure of what types of strings are passed to us, and we don't
|
|
Packit Service |
ae04f2 |
* want special characters in the string causing problems.
|
|
Packit Service |
ae04f2 |
*/
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
static char *
|
|
Packit Service |
ae04f2 |
postgres_escape_string(const char *instr) {
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
char *outstr;
|
|
Packit Service |
ae04f2 |
unsigned int len;
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
if (instr == NULL)
|
|
Packit Service |
ae04f2 |
return NULL;
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
len = strlen(instr);
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
outstr = isc_mem_allocate(ns_g_mctx ,(2 * len * sizeof(char)) + 1);
|
|
Packit Service |
ae04f2 |
if (outstr == NULL)
|
|
Packit Service |
ae04f2 |
return NULL;
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
postgres_makesafe(outstr, instr, len);
|
|
Packit Service |
ae04f2 |
/* PQescapeString(outstr, instr, len); */
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
return outstr;
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/*%
|
|
Packit Service |
ae04f2 |
* This function is the real core of the driver. Zone, record
|
|
Packit Service |
ae04f2 |
* and client strings are passed in (or NULL is passed if the
|
|
Packit Service |
ae04f2 |
* string is not available). The type of query we want to run
|
|
Packit Service |
ae04f2 |
* is indicated by the query flag, and the dbdata object is passed
|
|
Packit Service |
ae04f2 |
* passed in to. dbdata really holds either:
|
|
Packit Service |
ae04f2 |
* 1) a list of database instances (in multithreaded mode) OR
|
|
Packit Service |
ae04f2 |
* 2) a single database instance (in single threaded mode)
|
|
Packit Service |
ae04f2 |
* The function will construct the query and obtain an available
|
|
Packit Service |
ae04f2 |
* database instance (DBI). It will then run the query and hopefully
|
|
Packit Service |
ae04f2 |
* obtain a result set. Postgres is nice, in that once the result
|
|
Packit Service |
ae04f2 |
* set is returned, we can make the db connection available for another
|
|
Packit Service |
ae04f2 |
* thread to use, while this thread continues on. So, the DBI is made
|
|
Packit Service |
ae04f2 |
* available ASAP by unlocking the instance_lock after we have cleaned
|
|
Packit Service |
ae04f2 |
* it up properly.
|
|
Packit Service |
ae04f2 |
*/
|
|
Packit Service |
ae04f2 |
static isc_result_t
|
|
Packit Service |
ae04f2 |
postgres_get_resultset(const char *zone, const char *record,
|
|
Packit Service |
ae04f2 |
const char *client, unsigned int query,
|
|
Packit Service |
ae04f2 |
void *dbdata, PGresult **rs)
|
|
Packit Service |
ae04f2 |
{
|
|
Packit Service |
ae04f2 |
isc_result_t result;
|
|
Packit Service |
ae04f2 |
dbinstance_t *dbi = NULL;
|
|
Packit Service |
ae04f2 |
char *querystring = NULL;
|
|
Packit Service |
ae04f2 |
unsigned int i = 0;
|
|
Packit Service |
ae04f2 |
unsigned int j = 0;
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
#if 0
|
|
Packit Service |
ae04f2 |
/* temporarily get a unique thread # */
|
|
Packit Service |
ae04f2 |
unsigned int dlz_thread_num = 1+(int) (1000.0*rand()/(RAND_MAX+1.0));
|
|
Packit Service |
ae04f2 |
#endif
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
REQUIRE(*rs == NULL);
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
#if 0
|
|
Packit Service |
ae04f2 |
/* temporary logging message */
|
|
Packit Service |
ae04f2 |
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
|
|
Packit Service |
ae04f2 |
DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
|
|
Packit Service |
ae04f2 |
"%d Getting DBI", dlz_thread_num);
|
|
Packit Service |
ae04f2 |
#endif
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/* get db instance / connection */
|
|
Packit Service |
ae04f2 |
#ifdef ISC_PLATFORM_USETHREADS
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/* find an available DBI from the list */
|
|
Packit Service |
ae04f2 |
dbi = postgres_find_avail_conn((db_list_t *) dbdata);
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
#else /* ISC_PLATFORM_USETHREADS */
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/*
|
|
Packit Service |
ae04f2 |
* only 1 DBI - no need to lock instance lock either
|
|
Packit Service |
ae04f2 |
* only 1 thread in the whole process, no possible contention.
|
|
Packit Service |
ae04f2 |
*/
|
|
Packit Service |
ae04f2 |
dbi = (dbinstance_t *) dbdata;
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
#endif /* ISC_PLATFORM_USETHREADS */
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
#if 0
|
|
Packit Service |
ae04f2 |
/* temporary logging message */
|
|
Packit Service |
ae04f2 |
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
|
|
Packit Service |
ae04f2 |
DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
|
|
Packit Service |
ae04f2 |
"%d Got DBI - checking query", dlz_thread_num);
|
|
Packit Service |
ae04f2 |
#endif
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/* if DBI is null, can't do anything else */
|
|
Packit Service |
ae04f2 |
if (dbi == NULL) {
|
|
Packit Service |
ae04f2 |
result = ISC_R_FAILURE;
|
|
Packit Service |
ae04f2 |
goto cleanup;
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/* what type of query are we going to run? */
|
|
Packit Service |
ae04f2 |
switch(query) {
|
|
Packit Service |
ae04f2 |
case ALLNODES:
|
|
Packit Service |
ae04f2 |
/*
|
|
Packit Service |
ae04f2 |
* if the query was not passed in from the config file
|
|
Packit Service |
ae04f2 |
* then we can't run it. return not_implemented, so
|
|
Packit Service |
ae04f2 |
* it's like the code for that operation was never
|
|
Packit Service |
ae04f2 |
* built into the driver.... AHHH flexibility!!!
|
|
Packit Service |
ae04f2 |
*/
|
|
Packit Service |
ae04f2 |
if (dbi->allnodes_q == NULL) {
|
|
Packit Service |
ae04f2 |
result = ISC_R_NOTIMPLEMENTED;
|
|
Packit Service |
ae04f2 |
goto cleanup;
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
break;
|
|
Packit Service |
ae04f2 |
case ALLOWXFR:
|
|
Packit Service |
ae04f2 |
/* same as comments as ALLNODES */
|
|
Packit Service |
ae04f2 |
if (dbi->allowxfr_q == NULL) {
|
|
Packit Service |
ae04f2 |
result = ISC_R_NOTIMPLEMENTED;
|
|
Packit Service |
ae04f2 |
goto cleanup;
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
break;
|
|
Packit Service |
ae04f2 |
case AUTHORITY:
|
|
Packit Service |
ae04f2 |
/* same as comments as ALLNODES */
|
|
Packit Service |
ae04f2 |
if (dbi->authority_q == NULL) {
|
|
Packit Service |
ae04f2 |
result = ISC_R_NOTIMPLEMENTED;
|
|
Packit Service |
ae04f2 |
goto cleanup;
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
break;
|
|
Packit Service |
ae04f2 |
case FINDZONE:
|
|
Packit Service |
ae04f2 |
/* this is required. It's the whole point of DLZ! */
|
|
Packit Service |
ae04f2 |
if (dbi->findzone_q == NULL) {
|
|
Packit Service |
ae04f2 |
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
|
|
Packit Service |
ae04f2 |
DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
|
|
Packit Service |
ae04f2 |
"No query specified for findzone. "
|
|
Packit Service |
ae04f2 |
"Findzone requires a query");
|
|
Packit Service |
ae04f2 |
result = ISC_R_FAILURE;
|
|
Packit Service |
ae04f2 |
goto cleanup;
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
break;
|
|
Packit Service |
ae04f2 |
case LOOKUP:
|
|
Packit Service |
ae04f2 |
/* this is required. It's also a major point of DLZ! */
|
|
Packit Service |
ae04f2 |
if (dbi->lookup_q == NULL) {
|
|
Packit Service |
ae04f2 |
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
|
|
Packit Service |
ae04f2 |
DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
|
|
Packit Service |
ae04f2 |
"No query specified for lookup. "
|
|
Packit Service |
ae04f2 |
"Lookup requires a query");
|
|
Packit Service |
ae04f2 |
result = ISC_R_FAILURE;
|
|
Packit Service |
ae04f2 |
goto cleanup;
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
break;
|
|
Packit Service |
ae04f2 |
default:
|
|
Packit Service |
ae04f2 |
/*
|
|
Packit Service |
ae04f2 |
* this should never happen. If it does, the code is
|
|
Packit Service |
ae04f2 |
* screwed up!
|
|
Packit Service |
ae04f2 |
*/
|
|
Packit Service |
ae04f2 |
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
|
Packit Service |
ae04f2 |
"Incorrect query flag passed to "
|
|
Packit Service |
ae04f2 |
"postgres_get_resultset");
|
|
Packit Service |
ae04f2 |
result = ISC_R_UNEXPECTED;
|
|
Packit Service |
ae04f2 |
goto cleanup;
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
#if 0
|
|
Packit Service |
ae04f2 |
/* temporary logging message */
|
|
Packit Service |
ae04f2 |
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
|
|
Packit Service |
ae04f2 |
DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
|
|
Packit Service |
ae04f2 |
"%d checked query", dlz_thread_num);
|
|
Packit Service |
ae04f2 |
#endif
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/*
|
|
Packit Service |
ae04f2 |
* was a zone string passed? If so, make it safe for use in
|
|
Packit Service |
ae04f2 |
* queries.
|
|
Packit Service |
ae04f2 |
*/
|
|
Packit Service |
ae04f2 |
if (zone != NULL) {
|
|
Packit Service |
ae04f2 |
dbi->zone = postgres_escape_string(zone);
|
|
Packit Service |
ae04f2 |
if (dbi->zone == NULL) {
|
|
Packit Service |
ae04f2 |
result = ISC_R_NOMEMORY;
|
|
Packit Service |
ae04f2 |
goto cleanup;
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
} else { /* no string passed, set the string pointer to NULL */
|
|
Packit Service |
ae04f2 |
dbi->zone = NULL;
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
#if 0
|
|
Packit Service |
ae04f2 |
/* temporary logging message */
|
|
Packit Service |
ae04f2 |
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
|
|
Packit Service |
ae04f2 |
DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
|
|
Packit Service |
ae04f2 |
"%d did zone", dlz_thread_num);
|
|
Packit Service |
ae04f2 |
#endif
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/*
|
|
Packit Service |
ae04f2 |
* was a record string passed? If so, make it safe for use in
|
|
Packit Service |
ae04f2 |
* queries.
|
|
Packit Service |
ae04f2 |
*/
|
|
Packit Service |
ae04f2 |
if (record != NULL) {
|
|
Packit Service |
ae04f2 |
dbi->record = postgres_escape_string(record);
|
|
Packit Service |
ae04f2 |
if (dbi->record == NULL) {
|
|
Packit Service |
ae04f2 |
result = ISC_R_NOMEMORY;
|
|
Packit Service |
ae04f2 |
goto cleanup;
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
} else { /* no string passed, set the string pointer to NULL */
|
|
Packit Service |
ae04f2 |
dbi->record = NULL;
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
#if 0
|
|
Packit Service |
ae04f2 |
/* temporary logging message */
|
|
Packit Service |
ae04f2 |
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
|
|
Packit Service |
ae04f2 |
DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
|
|
Packit Service |
ae04f2 |
"%d did record", dlz_thread_num);
|
|
Packit Service |
ae04f2 |
#endif
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/*
|
|
Packit Service |
ae04f2 |
* was a client string passed? If so, make it safe for use in
|
|
Packit Service |
ae04f2 |
* queries.
|
|
Packit Service |
ae04f2 |
*/
|
|
Packit Service |
ae04f2 |
if (client != NULL) {
|
|
Packit Service |
ae04f2 |
dbi->client = postgres_escape_string(client);
|
|
Packit Service |
ae04f2 |
if (dbi->client == NULL) {
|
|
Packit Service |
ae04f2 |
result = ISC_R_NOMEMORY;
|
|
Packit Service |
ae04f2 |
goto cleanup;
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
} else { /* no string passed, set the string pointer to NULL */
|
|
Packit Service |
ae04f2 |
dbi->client = NULL;
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
#if 0
|
|
Packit Service |
ae04f2 |
/* temporary logging message */
|
|
Packit Service |
ae04f2 |
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
|
|
Packit Service |
ae04f2 |
DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
|
|
Packit Service |
ae04f2 |
"%d did client", dlz_thread_num);
|
|
Packit Service |
ae04f2 |
#endif
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/*
|
|
Packit Service |
ae04f2 |
* what type of query are we going to run?
|
|
Packit Service |
ae04f2 |
* this time we build the actual query to run.
|
|
Packit Service |
ae04f2 |
*/
|
|
Packit Service |
ae04f2 |
switch(query) {
|
|
Packit Service |
ae04f2 |
case ALLNODES:
|
|
Packit Service |
ae04f2 |
querystring = build_querystring(ns_g_mctx, dbi->allnodes_q);
|
|
Packit Service |
ae04f2 |
break;
|
|
Packit Service |
ae04f2 |
case ALLOWXFR:
|
|
Packit Service |
ae04f2 |
querystring = build_querystring(ns_g_mctx, dbi->allowxfr_q);
|
|
Packit Service |
ae04f2 |
break;
|
|
Packit Service |
ae04f2 |
case AUTHORITY:
|
|
Packit Service |
ae04f2 |
querystring = build_querystring(ns_g_mctx, dbi->authority_q);
|
|
Packit Service |
ae04f2 |
break;
|
|
Packit Service |
ae04f2 |
case FINDZONE:
|
|
Packit Service |
ae04f2 |
querystring = build_querystring(ns_g_mctx, dbi->findzone_q);
|
|
Packit Service |
ae04f2 |
break;
|
|
Packit Service |
ae04f2 |
case LOOKUP:
|
|
Packit Service |
ae04f2 |
querystring = build_querystring(ns_g_mctx, dbi->lookup_q);
|
|
Packit Service |
ae04f2 |
break;
|
|
Packit Service |
ae04f2 |
default:
|
|
Packit Service |
ae04f2 |
/*
|
|
Packit Service |
ae04f2 |
* this should never happen. If it does, the code is
|
|
Packit Service |
ae04f2 |
* screwed up!
|
|
Packit Service |
ae04f2 |
*/
|
|
Packit Service |
ae04f2 |
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
|
Packit Service |
ae04f2 |
"Incorrect query flag passed to "
|
|
Packit Service |
ae04f2 |
"postgres_get_resultset");
|
|
Packit Service |
ae04f2 |
result = ISC_R_UNEXPECTED;
|
|
Packit Service |
ae04f2 |
goto cleanup;
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
#if 0
|
|
Packit Service |
ae04f2 |
/* temporary logging message */
|
|
Packit Service |
ae04f2 |
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
|
|
Packit Service |
ae04f2 |
DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
|
|
Packit Service |
ae04f2 |
"%d built query", dlz_thread_num);
|
|
Packit Service |
ae04f2 |
#endif
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/* if the querystring is null, Bummer, outta RAM. UPGRADE TIME!!! */
|
|
Packit Service |
ae04f2 |
if (querystring == NULL) {
|
|
Packit Service |
ae04f2 |
result = ISC_R_NOMEMORY;
|
|
Packit Service |
ae04f2 |
goto cleanup;
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
#if 0
|
|
Packit Service |
ae04f2 |
/* temporary logging message */
|
|
Packit Service |
ae04f2 |
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
|
|
Packit Service |
ae04f2 |
DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
|
|
Packit Service |
ae04f2 |
"%d query is '%s'", dlz_thread_num, querystring);
|
|
Packit Service |
ae04f2 |
#endif
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/*
|
|
Packit Service |
ae04f2 |
* output the full query string during debug so we can see
|
|
Packit Service |
ae04f2 |
* what lame error the query has.
|
|
Packit Service |
ae04f2 |
*/
|
|
Packit Service |
ae04f2 |
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
|
|
Packit Service |
ae04f2 |
DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1),
|
|
Packit Service |
ae04f2 |
"\nQuery String: %s\n", querystring);
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/* attempt query up to 3 times. */
|
|
Packit Service |
ae04f2 |
for (j=0; j < 3; j++) {
|
|
Packit Service |
ae04f2 |
#if 0
|
|
Packit Service |
ae04f2 |
/* temporary logging message */
|
|
Packit Service |
ae04f2 |
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
|
|
Packit Service |
ae04f2 |
DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
|
|
Packit Service |
ae04f2 |
"%d executing query for %d time",
|
|
Packit Service |
ae04f2 |
dlz_thread_num, j);
|
|
Packit Service |
ae04f2 |
#endif
|
|
Packit Service |
ae04f2 |
/* try to get result set */
|
|
Packit Service |
ae04f2 |
*rs = PQexec((PGconn *)dbi->dbconn, querystring );
|
|
Packit Service |
ae04f2 |
result = ISC_R_SUCCESS;
|
|
Packit Service |
ae04f2 |
/*
|
|
Packit Service |
ae04f2 |
* if result set is null, reset DB connection, max 3
|
|
Packit Service |
ae04f2 |
* attempts.
|
|
Packit Service |
ae04f2 |
*/
|
|
Packit Service |
ae04f2 |
for (i=0; *rs == NULL && i < 3; i++) {
|
|
Packit Service |
ae04f2 |
#if 0
|
|
Packit Service |
ae04f2 |
/* temporary logging message */
|
|
Packit Service |
ae04f2 |
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
|
|
Packit Service |
ae04f2 |
DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
|
|
Packit Service |
ae04f2 |
"%d resetting connection",
|
|
Packit Service |
ae04f2 |
dlz_thread_num);
|
|
Packit Service |
ae04f2 |
#endif
|
|
Packit Service |
ae04f2 |
result = ISC_R_FAILURE;
|
|
Packit Service |
ae04f2 |
PQreset((PGconn *) dbi->dbconn);
|
|
Packit Service |
ae04f2 |
/* connection ok, break inner loop */
|
|
Packit Service |
ae04f2 |
if (PQstatus((PGconn *) dbi->dbconn) == CONNECTION_OK)
|
|
Packit Service |
ae04f2 |
break;
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
/* result set ok, break outer loop */
|
|
Packit Service |
ae04f2 |
if (PQresultStatus(*rs) == PGRES_TUPLES_OK) {
|
|
Packit Service |
ae04f2 |
#if 0
|
|
Packit Service |
ae04f2 |
/* temporary logging message */
|
|
Packit Service |
ae04f2 |
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
|
|
Packit Service |
ae04f2 |
DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
|
|
Packit Service |
ae04f2 |
"%d rs ok", dlz_thread_num);
|
|
Packit Service |
ae04f2 |
#endif
|
|
Packit Service |
ae04f2 |
break;
|
|
Packit Service |
ae04f2 |
} else {
|
|
Packit Service |
ae04f2 |
/* we got a result set object, but it's not right. */
|
|
Packit Service |
ae04f2 |
#if 0
|
|
Packit Service |
ae04f2 |
/* temporary logging message */
|
|
Packit Service |
ae04f2 |
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
|
|
Packit Service |
ae04f2 |
DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
|
|
Packit Service |
ae04f2 |
"%d clearing rs", dlz_thread_num);
|
|
Packit Service |
ae04f2 |
#endif
|
|
Packit Service |
ae04f2 |
PQclear(*rs); /* get rid of it */
|
|
Packit Service |
ae04f2 |
/* in case this was the last attempt */
|
|
Packit Service |
ae04f2 |
*rs = NULL;
|
|
Packit Service |
ae04f2 |
result = ISC_R_FAILURE;
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
cleanup:
|
|
Packit Service |
ae04f2 |
/* it's always good to cleanup after yourself */
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
#if 0
|
|
Packit Service |
ae04f2 |
/* temporary logging message */
|
|
Packit Service |
ae04f2 |
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
|
|
Packit Service |
ae04f2 |
DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
|
|
Packit Service |
ae04f2 |
"%d cleaning up", dlz_thread_num);
|
|
Packit Service |
ae04f2 |
#endif
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/* if we couldn't even allocate DBI, just return NULL */
|
|
Packit Service |
ae04f2 |
if (dbi == NULL)
|
|
Packit Service |
ae04f2 |
return ISC_R_FAILURE;
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/* free dbi->zone string */
|
|
Packit Service |
ae04f2 |
if (dbi->zone != NULL)
|
|
Packit Service |
ae04f2 |
isc_mem_free(ns_g_mctx, dbi->zone);
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/* free dbi->record string */
|
|
Packit Service |
ae04f2 |
if (dbi->record != NULL)
|
|
Packit Service |
ae04f2 |
isc_mem_free(ns_g_mctx, dbi->record);
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/* free dbi->client string */
|
|
Packit Service |
ae04f2 |
if (dbi->client != NULL)
|
|
Packit Service |
ae04f2 |
isc_mem_free(ns_g_mctx, dbi->client);
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
#ifdef ISC_PLATFORM_USETHREADS
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
#if 0
|
|
Packit Service |
ae04f2 |
/* temporary logging message */
|
|
Packit Service |
ae04f2 |
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
|
|
Packit Service |
ae04f2 |
DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
|
|
Packit Service |
ae04f2 |
"%d unlocking mutex", dlz_thread_num);
|
|
Packit Service |
ae04f2 |
#endif
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/* release the lock so another thread can use this dbi */
|
|
Packit Service |
ae04f2 |
isc_mutex_unlock(&dbi->instance_lock);
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
#endif /* ISC_PLATFORM_USETHREADS */
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/* release query string */
|
|
Packit Service |
ae04f2 |
if (querystring != NULL)
|
|
Packit Service |
ae04f2 |
isc_mem_free(ns_g_mctx, querystring );
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
#if 0
|
|
Packit Service |
ae04f2 |
/* temporary logging message */
|
|
Packit Service |
ae04f2 |
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
|
|
Packit Service |
ae04f2 |
DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
|
|
Packit Service |
ae04f2 |
"%d returning", dlz_thread_num);
|
|
Packit Service |
ae04f2 |
#endif
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/* return result */
|
|
Packit Service |
ae04f2 |
return result;
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/*%
|
|
Packit Service |
ae04f2 |
* The processing of result sets for lookup and authority are
|
|
Packit Service |
ae04f2 |
* exactly the same. So that functionality has been moved
|
|
Packit Service |
ae04f2 |
* into this function to minimize code.
|
|
Packit Service |
ae04f2 |
*/
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
static isc_result_t
|
|
Packit Service |
ae04f2 |
postgres_process_rs(dns_sdlzlookup_t *lookup, PGresult *rs)
|
|
Packit Service |
ae04f2 |
{
|
|
Packit Service |
ae04f2 |
isc_result_t result;
|
|
Packit Service |
ae04f2 |
unsigned int i;
|
|
Packit Service |
ae04f2 |
unsigned int rows;
|
|
Packit Service |
ae04f2 |
unsigned int fields;
|
|
Packit Service |
ae04f2 |
unsigned int j;
|
|
Packit Service |
ae04f2 |
unsigned int len;
|
|
Packit Service |
ae04f2 |
char *tmpString;
|
|
Packit Service |
ae04f2 |
char *endp;
|
|
Packit Service |
ae04f2 |
int ttl;
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
rows = PQntuples(rs); /* how many rows in result set */
|
|
Packit Service |
ae04f2 |
fields = PQnfields(rs); /* how many columns in result set */
|
|
Packit Service |
ae04f2 |
for (i=0; i < rows; i++) {
|
|
Packit Service |
ae04f2 |
switch(fields) {
|
|
Packit Service |
ae04f2 |
case 1:
|
|
Packit Service |
ae04f2 |
/*
|
|
Packit Service |
ae04f2 |
* one column in rs, it's the data field. use
|
|
Packit Service |
ae04f2 |
* default type of A record, and default TTL
|
|
Packit Service |
ae04f2 |
* of 86400
|
|
Packit Service |
ae04f2 |
*/
|
|
Packit Service |
ae04f2 |
result = dns_sdlz_putrr(lookup, "a", 86400,
|
|
Packit Service |
ae04f2 |
PQgetvalue(rs, i, 0));
|
|
Packit Service |
ae04f2 |
break;
|
|
Packit Service |
ae04f2 |
case 2:
|
|
Packit Service |
ae04f2 |
/* two columns, data field, and data type.
|
|
Packit Service |
ae04f2 |
* use default TTL of 86400.
|
|
Packit Service |
ae04f2 |
*/
|
|
Packit Service |
ae04f2 |
result = dns_sdlz_putrr(lookup, PQgetvalue(rs, i, 0),
|
|
Packit Service |
ae04f2 |
86400, PQgetvalue(rs, i, 1));
|
|
Packit Service |
ae04f2 |
break;
|
|
Packit Service |
ae04f2 |
case 3:
|
|
Packit Service |
ae04f2 |
/* three columns, all data no defaults.
|
|
Packit Service |
ae04f2 |
* convert text to int, make sure it worked
|
|
Packit Service |
ae04f2 |
* right.
|
|
Packit Service |
ae04f2 |
*/
|
|
Packit Service |
ae04f2 |
ttl = strtol(PQgetvalue(rs, i, 0), &endp, 10);
|
|
Packit Service |
ae04f2 |
if (*endp != '\0' || ttl < 0) {
|
|
Packit Service |
ae04f2 |
isc_log_write(dns_lctx,
|
|
Packit Service |
ae04f2 |
DNS_LOGCATEGORY_DATABASE,
|
|
Packit Service |
ae04f2 |
DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
|
|
Packit Service |
ae04f2 |
"Postgres driver ttl must be "
|
|
Packit Service |
ae04f2 |
"a positive number");
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
result = dns_sdlz_putrr(lookup, PQgetvalue(rs, i, 1),
|
|
Packit Service |
ae04f2 |
ttl, PQgetvalue(rs, i, 2));
|
|
Packit Service |
ae04f2 |
break;
|
|
Packit Service |
ae04f2 |
default:
|
|
Packit Service |
ae04f2 |
/*
|
|
Packit Service |
ae04f2 |
* more than 3 fields, concatenate the last
|
|
Packit Service |
ae04f2 |
* ones together. figure out how long to make
|
|
Packit Service |
ae04f2 |
* string
|
|
Packit Service |
ae04f2 |
*/
|
|
Packit Service |
ae04f2 |
for (j=2, len=0; j < fields; j++) {
|
|
Packit Service |
ae04f2 |
len += strlen(PQgetvalue(rs, i, j)) + 1;
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
/*
|
|
Packit Service |
ae04f2 |
* allocate string memory, allow for NULL to
|
|
Packit Service |
ae04f2 |
* term string
|
|
Packit Service |
ae04f2 |
*/
|
|
Packit Service |
ae04f2 |
tmpString = isc_mem_allocate(ns_g_mctx, len + 1);
|
|
Packit Service |
ae04f2 |
if (tmpString == NULL) {
|
|
Packit Service |
ae04f2 |
/* major bummer, need more ram */
|
|
Packit Service |
ae04f2 |
isc_log_write(dns_lctx,
|
|
Packit Service |
ae04f2 |
DNS_LOGCATEGORY_DATABASE,
|
|
Packit Service |
ae04f2 |
DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
|
|
Packit Service |
ae04f2 |
"Postgres driver unable to "
|
|
Packit Service |
ae04f2 |
"allocate memory for "
|
|
Packit Service |
ae04f2 |
"temporary string");
|
|
Packit Service |
ae04f2 |
PQclear(rs);
|
|
Packit Service |
ae04f2 |
return (ISC_R_FAILURE); /* Yeah, I'd say! */
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
/* copy field to tmpString */
|
|
Packit Service |
ae04f2 |
strcpy(tmpString, PQgetvalue(rs, i, 2));
|
|
Packit Service |
ae04f2 |
/*
|
|
Packit Service |
ae04f2 |
* concat the rest of fields together, space
|
|
Packit Service |
ae04f2 |
* between each one.
|
|
Packit Service |
ae04f2 |
*/
|
|
Packit Service |
ae04f2 |
for (j=3; j < fields; j++) {
|
|
Packit Service |
ae04f2 |
strcat(tmpString, " ");
|
|
Packit Service |
ae04f2 |
strcat(tmpString, PQgetvalue(rs, i, j));
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
/* convert text to int, make sure it worked right */
|
|
Packit Service |
ae04f2 |
ttl = strtol(PQgetvalue(rs, i, 0), &endp, 10);
|
|
Packit Service |
ae04f2 |
if (*endp != '\0' || ttl < 0) {
|
|
Packit Service |
ae04f2 |
isc_log_write(dns_lctx,
|
|
Packit Service |
ae04f2 |
DNS_LOGCATEGORY_DATABASE,
|
|
Packit Service |
ae04f2 |
DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
|
|
Packit Service |
ae04f2 |
"Postgres driver ttl must be "
|
|
Packit Service |
ae04f2 |
"a positive number");
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
/* ok, now tell Bind about it. */
|
|
Packit Service |
ae04f2 |
result = dns_sdlz_putrr(lookup, PQgetvalue(rs, i, 1),
|
|
Packit Service |
ae04f2 |
ttl, tmpString);
|
|
Packit Service |
ae04f2 |
/* done, get rid of this thing. */
|
|
Packit Service |
ae04f2 |
isc_mem_free(ns_g_mctx, tmpString);
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
/* I sure hope we were successful */
|
|
Packit Service |
ae04f2 |
if (result != ISC_R_SUCCESS) {
|
|
Packit Service |
ae04f2 |
/* nope, get rid of the Result set, and log a msg */
|
|
Packit Service |
ae04f2 |
PQclear(rs);
|
|
Packit Service |
ae04f2 |
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
|
|
Packit Service |
ae04f2 |
DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
|
|
Packit Service |
ae04f2 |
"dns_sdlz_putrr returned error. "
|
|
Packit Service |
ae04f2 |
"Error code was: %s",
|
|
Packit Service |
ae04f2 |
isc_result_totext(result));
|
|
Packit Service |
ae04f2 |
return (ISC_R_FAILURE);
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/* free result set memory */
|
|
Packit Service |
ae04f2 |
PQclear(rs);
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/* if we did return results, we are successful */
|
|
Packit Service |
ae04f2 |
if (rows > 0)
|
|
Packit Service |
ae04f2 |
return (ISC_R_SUCCESS);
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/* empty result set, no data found */
|
|
Packit Service |
ae04f2 |
return (ISC_R_NOTFOUND);
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/*
|
|
Packit Service |
ae04f2 |
* SDLZ interface methods
|
|
Packit Service |
ae04f2 |
*/
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/*% determine if the zone is supported by (in) the database */
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
static isc_result_t
|
|
Packit Service |
ae04f2 |
postgres_findzone(void *driverarg, void *dbdata, const char *name,
|
|
Packit Service |
ae04f2 |
dns_clientinfomethods_t *methods,
|
|
Packit Service |
ae04f2 |
dns_clientinfo_t *clientinfo)
|
|
Packit Service |
ae04f2 |
{
|
|
Packit Service |
ae04f2 |
isc_result_t result;
|
|
Packit Service |
ae04f2 |
PGresult *rs = NULL;
|
|
Packit Service |
ae04f2 |
unsigned int rows;
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
UNUSED(driverarg);
|
|
Packit Service |
ae04f2 |
UNUSED(methods);
|
|
Packit Service |
ae04f2 |
UNUSED(clientinfo);
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/* run the query and get the result set from the database. */
|
|
Packit Service |
ae04f2 |
result = postgres_get_resultset(name, NULL, NULL,
|
|
Packit Service |
ae04f2 |
FINDZONE, dbdata, &rs);
|
|
Packit Service |
ae04f2 |
/* if we didn't get a result set, log an err msg. */
|
|
Packit Service |
ae04f2 |
if (result != ISC_R_SUCCESS) {
|
|
Packit Service |
ae04f2 |
if (rs != NULL)
|
|
Packit Service |
ae04f2 |
PQclear(rs);
|
|
Packit Service |
ae04f2 |
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
|
|
Packit Service |
ae04f2 |
DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
|
|
Packit Service |
ae04f2 |
"Postgres driver unable to return "
|
|
Packit Service |
ae04f2 |
"result set for findzone query");
|
|
Packit Service |
ae04f2 |
return (ISC_R_FAILURE);
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
/* count how many rows in result set */
|
|
Packit Service |
ae04f2 |
rows = PQntuples(rs);
|
|
Packit Service |
ae04f2 |
/* get rid of result set, we are done with it. */
|
|
Packit Service |
ae04f2 |
PQclear(rs);
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/* if we returned any rows, zone is supported. */
|
|
Packit Service |
ae04f2 |
if (rows > 0)
|
|
Packit Service |
ae04f2 |
return (ISC_R_SUCCESS);
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/* no rows returned, zone is not supported. */
|
|
Packit Service |
ae04f2 |
return (ISC_R_NOTFOUND);
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/*% Determine if the client is allowed to perform a zone transfer */
|
|
Packit Service |
ae04f2 |
static isc_result_t
|
|
Packit Service |
ae04f2 |
postgres_allowzonexfr(void *driverarg, void *dbdata, const char *name,
|
|
Packit Service |
ae04f2 |
const char *client)
|
|
Packit Service |
ae04f2 |
{
|
|
Packit Service |
ae04f2 |
isc_result_t result;
|
|
Packit Service |
ae04f2 |
PGresult *rs = NULL;
|
|
Packit Service |
ae04f2 |
unsigned int rows;
|
|
Packit Service |
ae04f2 |
UNUSED(driverarg);
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/* first check if the zone is supported by the database. */
|
|
Packit Service |
ae04f2 |
result = postgres_findzone(driverarg, dbdata, name, NULL, NULL);
|
|
Packit Service |
ae04f2 |
if (result != ISC_R_SUCCESS)
|
|
Packit Service |
ae04f2 |
return (ISC_R_NOTFOUND);
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/*
|
|
Packit Service |
ae04f2 |
* if we get to this point we know the zone is supported by
|
|
Packit Service |
ae04f2 |
* the database the only questions now are is the zone
|
|
Packit Service |
ae04f2 |
* transfer is allowed for this client and did the config file
|
|
Packit Service |
ae04f2 |
* have an allow zone xfr query.
|
|
Packit Service |
ae04f2 |
*
|
|
Packit Service |
ae04f2 |
* Run our query, and get a result set from the database.
|
|
Packit Service |
ae04f2 |
*/
|
|
Packit Service |
ae04f2 |
result = postgres_get_resultset(name, NULL, client,
|
|
Packit Service |
ae04f2 |
ALLOWXFR, dbdata, &rs);
|
|
Packit Service |
ae04f2 |
/* if we get "not implemented", send it along. */
|
|
Packit Service |
ae04f2 |
if (result == ISC_R_NOTIMPLEMENTED)
|
|
Packit Service |
ae04f2 |
return result;
|
|
Packit Service |
ae04f2 |
/* if we didn't get a result set, log an err msg. */
|
|
Packit Service |
ae04f2 |
if (result != ISC_R_SUCCESS) {
|
|
Packit Service |
ae04f2 |
if (rs != NULL)
|
|
Packit Service |
ae04f2 |
PQclear(rs);
|
|
Packit Service |
ae04f2 |
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
|
|
Packit Service |
ae04f2 |
DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
|
|
Packit Service |
ae04f2 |
"Postgres driver unable to return "
|
|
Packit Service |
ae04f2 |
"result set for allow xfr query");
|
|
Packit Service |
ae04f2 |
return (ISC_R_FAILURE);
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
/* count how many rows in result set */
|
|
Packit Service |
ae04f2 |
rows = PQntuples(rs);
|
|
Packit Service |
ae04f2 |
/* get rid of result set, we are done with it. */
|
|
Packit Service |
ae04f2 |
PQclear(rs);
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/* if we returned any rows, zone xfr is allowed. */
|
|
Packit Service |
ae04f2 |
if (rows > 0)
|
|
Packit Service |
ae04f2 |
return (ISC_R_SUCCESS);
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/* no rows returned, zone xfr not allowed */
|
|
Packit Service |
ae04f2 |
return (ISC_R_NOPERM);
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/*%
|
|
Packit Service |
ae04f2 |
* If the client is allowed to perform a zone transfer, the next order of
|
|
Packit Service |
ae04f2 |
* business is to get all the nodes in the zone, so bind can respond to the
|
|
Packit Service |
ae04f2 |
* query.
|
|
Packit Service |
ae04f2 |
*/
|
|
Packit Service |
ae04f2 |
static isc_result_t
|
|
Packit Service |
ae04f2 |
postgres_allnodes(const char *zone, void *driverarg, void *dbdata,
|
|
Packit Service |
ae04f2 |
dns_sdlzallnodes_t *allnodes)
|
|
Packit Service |
ae04f2 |
{
|
|
Packit Service |
ae04f2 |
isc_result_t result;
|
|
Packit Service |
ae04f2 |
PGresult *rs = NULL;
|
|
Packit Service |
ae04f2 |
unsigned int i;
|
|
Packit Service |
ae04f2 |
unsigned int rows;
|
|
Packit Service |
ae04f2 |
unsigned int fields;
|
|
Packit Service |
ae04f2 |
unsigned int j;
|
|
Packit Service |
ae04f2 |
unsigned int len;
|
|
Packit Service |
ae04f2 |
char *tmpString;
|
|
Packit Service |
ae04f2 |
char *endp;
|
|
Packit Service |
ae04f2 |
int ttl;
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
UNUSED(driverarg);
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/* run the query and get the result set from the database. */
|
|
Packit Service |
ae04f2 |
result = postgres_get_resultset(zone, NULL, NULL,
|
|
Packit Service |
ae04f2 |
ALLNODES, dbdata, &rs);
|
|
Packit Service |
ae04f2 |
/* if we get "not implemented", send it along */
|
|
Packit Service |
ae04f2 |
if (result == ISC_R_NOTIMPLEMENTED)
|
|
Packit Service |
ae04f2 |
return result;
|
|
Packit Service |
ae04f2 |
/* if we didn't get a result set, log an err msg. */
|
|
Packit Service |
ae04f2 |
if (result != ISC_R_SUCCESS) {
|
|
Packit Service |
ae04f2 |
if (rs != NULL)
|
|
Packit Service |
ae04f2 |
PQclear(rs);
|
|
Packit Service |
ae04f2 |
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
|
|
Packit Service |
ae04f2 |
DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
|
|
Packit Service |
ae04f2 |
"Postgres driver unable to return "
|
|
Packit Service |
ae04f2 |
"result set for all nodes query");
|
|
Packit Service |
ae04f2 |
return (ISC_R_FAILURE);
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
rows = PQntuples(rs); /* how many rows in result set */
|
|
Packit Service |
ae04f2 |
fields = PQnfields(rs); /* how many columns in result set */
|
|
Packit Service |
ae04f2 |
for (i=0; i < rows; i++) {
|
|
Packit Service |
ae04f2 |
if (fields < 4) { /* gotta have at least 4 columns */
|
|
Packit Service |
ae04f2 |
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
|
|
Packit Service |
ae04f2 |
DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
|
|
Packit Service |
ae04f2 |
"Postgres driver too few fields "
|
|
Packit Service |
ae04f2 |
"returned by all nodes query");
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
/* convert text to int, make sure it worked right */
|
|
Packit Service |
ae04f2 |
ttl = strtol(PQgetvalue(rs, i, 0), &endp, 10);
|
|
Packit Service |
ae04f2 |
if (*endp != '\0' || ttl < 0) {
|
|
Packit Service |
ae04f2 |
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
|
|
Packit Service |
ae04f2 |
DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
|
|
Packit Service |
ae04f2 |
"Postgres driver ttl must be "
|
|
Packit Service |
ae04f2 |
"a positive number");
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
if (fields == 4) {
|
|
Packit Service |
ae04f2 |
/* tell Bind about it. */
|
|
Packit Service |
ae04f2 |
result = dns_sdlz_putnamedrr(allnodes,
|
|
Packit Service |
ae04f2 |
PQgetvalue(rs, i, 2),
|
|
Packit Service |
ae04f2 |
PQgetvalue(rs, i, 1),
|
|
Packit Service |
ae04f2 |
ttl,
|
|
Packit Service |
ae04f2 |
PQgetvalue(rs, i, 3));
|
|
Packit Service |
ae04f2 |
} else {
|
|
Packit Service |
ae04f2 |
/*
|
|
Packit Service |
ae04f2 |
* more than 4 fields, concatonat the last
|
|
Packit Service |
ae04f2 |
* ones together. figure out how long to make
|
|
Packit Service |
ae04f2 |
* string
|
|
Packit Service |
ae04f2 |
*/
|
|
Packit Service |
ae04f2 |
for (j=3, len=0; j < fields; j++) {
|
|
Packit Service |
ae04f2 |
len += strlen(PQgetvalue(rs, i, j)) + 1;
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
/* allocate memory, allow for NULL to term string */
|
|
Packit Service |
ae04f2 |
tmpString = isc_mem_allocate(ns_g_mctx, len + 1);
|
|
Packit Service |
ae04f2 |
if (tmpString == NULL) { /* we need more ram. */
|
|
Packit Service |
ae04f2 |
isc_log_write(dns_lctx,
|
|
Packit Service |
ae04f2 |
DNS_LOGCATEGORY_DATABASE,
|
|
Packit Service |
ae04f2 |
DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
|
|
Packit Service |
ae04f2 |
"Postgres driver unable to "
|
|
Packit Service |
ae04f2 |
"allocate memory for "
|
|
Packit Service |
ae04f2 |
"temporary string");
|
|
Packit Service |
ae04f2 |
PQclear(rs);
|
|
Packit Service |
ae04f2 |
return (ISC_R_FAILURE);
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
/* copy this field to tmpString */
|
|
Packit Service |
ae04f2 |
strcpy(tmpString, PQgetvalue(rs, i, 3));
|
|
Packit Service |
ae04f2 |
/* concatenate the rest, with spaces between */
|
|
Packit Service |
ae04f2 |
for (j=4; j < fields; j++) {
|
|
Packit Service |
ae04f2 |
strcat(tmpString, " ");
|
|
Packit Service |
ae04f2 |
strcat(tmpString, PQgetvalue(rs, i, j));
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
/* tell Bind about it. */
|
|
Packit Service |
ae04f2 |
result = dns_sdlz_putnamedrr(allnodes,
|
|
Packit Service |
ae04f2 |
PQgetvalue(rs, i, 2),
|
|
Packit Service |
ae04f2 |
PQgetvalue(rs, i, 1),
|
|
Packit Service |
ae04f2 |
ttl, tmpString);
|
|
Packit Service |
ae04f2 |
isc_mem_free(ns_g_mctx, tmpString);
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
/* if we weren't successful, log err msg */
|
|
Packit Service |
ae04f2 |
if (result != ISC_R_SUCCESS) {
|
|
Packit Service |
ae04f2 |
PQclear(rs);
|
|
Packit Service |
ae04f2 |
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
|
|
Packit Service |
ae04f2 |
DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
|
|
Packit Service |
ae04f2 |
"dns_sdlz_putnamedrr returned error. "
|
|
Packit Service |
ae04f2 |
"Error code was: %s",
|
|
Packit Service |
ae04f2 |
isc_result_totext(result));
|
|
Packit Service |
ae04f2 |
return (ISC_R_FAILURE);
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/* free result set memory */
|
|
Packit Service |
ae04f2 |
PQclear(rs);
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/* if we did return results, we are successful */
|
|
Packit Service |
ae04f2 |
if (rows > 0)
|
|
Packit Service |
ae04f2 |
return (ISC_R_SUCCESS);
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/* empty result set, no data found */
|
|
Packit Service |
ae04f2 |
return (ISC_R_NOTFOUND);
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/*%
|
|
Packit Service |
ae04f2 |
* if the lookup function does not return SOA or NS records for the zone,
|
|
Packit Service |
ae04f2 |
* use this function to get that information for Bind.
|
|
Packit Service |
ae04f2 |
*/
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
static isc_result_t
|
|
Packit Service |
ae04f2 |
postgres_authority(const char *zone, void *driverarg, void *dbdata,
|
|
Packit Service |
ae04f2 |
dns_sdlzlookup_t *lookup)
|
|
Packit Service |
ae04f2 |
{
|
|
Packit Service |
ae04f2 |
isc_result_t result;
|
|
Packit Service |
ae04f2 |
PGresult *rs = NULL;
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
UNUSED(driverarg);
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/* run the query and get the result set from the database. */
|
|
Packit Service |
ae04f2 |
result = postgres_get_resultset(zone, NULL, NULL,
|
|
Packit Service |
ae04f2 |
AUTHORITY, dbdata, &rs);
|
|
Packit Service |
ae04f2 |
/* if we get "not implemented", send it along */
|
|
Packit Service |
ae04f2 |
if (result == ISC_R_NOTIMPLEMENTED)
|
|
Packit Service |
ae04f2 |
return result;
|
|
Packit Service |
ae04f2 |
/* if we didn't get a result set, log an err msg. */
|
|
Packit Service |
ae04f2 |
if (result != ISC_R_SUCCESS) {
|
|
Packit Service |
ae04f2 |
if (rs != NULL)
|
|
Packit Service |
ae04f2 |
PQclear(rs);
|
|
Packit Service |
ae04f2 |
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
|
|
Packit Service |
ae04f2 |
DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
|
|
Packit Service |
ae04f2 |
"Postgres driver unable to return "
|
|
Packit Service |
ae04f2 |
"result set for authority query");
|
|
Packit Service |
ae04f2 |
return (ISC_R_FAILURE);
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
/*
|
|
Packit Service |
ae04f2 |
* lookup and authority result sets are processed in the same
|
|
Packit Service |
ae04f2 |
* manner postgres_process_rs does the job for both
|
|
Packit Service |
ae04f2 |
* functions.
|
|
Packit Service |
ae04f2 |
*/
|
|
Packit Service |
ae04f2 |
return postgres_process_rs(lookup, rs);
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/*% if zone is supported, lookup up a (or multiple) record(s) in it */
|
|
Packit Service |
ae04f2 |
static isc_result_t
|
|
Packit Service |
ae04f2 |
postgres_lookup(const char *zone, const char *name, void *driverarg,
|
|
Packit Service |
ae04f2 |
void *dbdata, dns_sdlzlookup_t *lookup,
|
|
Packit Service |
ae04f2 |
dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo)
|
|
Packit Service |
ae04f2 |
{
|
|
Packit Service |
ae04f2 |
isc_result_t result;
|
|
Packit Service |
ae04f2 |
PGresult *rs = NULL;
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
UNUSED(driverarg);
|
|
Packit Service |
ae04f2 |
UNUSED(methods);
|
|
Packit Service |
ae04f2 |
UNUSED(clientinfo);
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/* run the query and get the result set from the database. */
|
|
Packit Service |
ae04f2 |
result = postgres_get_resultset(zone, name, NULL, LOOKUP, dbdata, &rs);
|
|
Packit Service |
ae04f2 |
/* if we didn't get a result set, log an err msg. */
|
|
Packit Service |
ae04f2 |
if (result != ISC_R_SUCCESS) {
|
|
Packit Service |
ae04f2 |
if (rs != NULL)
|
|
Packit Service |
ae04f2 |
PQclear(rs);
|
|
Packit Service |
ae04f2 |
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
|
|
Packit Service |
ae04f2 |
DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
|
|
Packit Service |
ae04f2 |
"Postgres driver unable to "
|
|
Packit Service |
ae04f2 |
"return result set for lookup query");
|
|
Packit Service |
ae04f2 |
return (ISC_R_FAILURE);
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
/*
|
|
Packit Service |
ae04f2 |
* lookup and authority result sets are processed in the same
|
|
Packit Service |
ae04f2 |
* manner postgres_process_rs does the job for both functions.
|
|
Packit Service |
ae04f2 |
*/
|
|
Packit Service |
ae04f2 |
return postgres_process_rs(lookup, rs);
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/*%
|
|
Packit Service |
ae04f2 |
* create an instance of the driver. Remember, only 1 copy of the driver's
|
|
Packit Service |
ae04f2 |
* code is ever loaded, the driver has to remember which context it's
|
|
Packit Service |
ae04f2 |
* operating in. This is done via use of the dbdata argument which is
|
|
Packit Service |
ae04f2 |
* passed into all query functions.
|
|
Packit Service |
ae04f2 |
*/
|
|
Packit Service |
ae04f2 |
static isc_result_t
|
|
Packit Service |
ae04f2 |
postgres_create(const char *dlzname, unsigned int argc, char *argv[],
|
|
Packit Service |
ae04f2 |
void *driverarg, void **dbdata)
|
|
Packit Service |
ae04f2 |
{
|
|
Packit Service |
ae04f2 |
isc_result_t result;
|
|
Packit Service |
ae04f2 |
dbinstance_t *dbi = NULL;
|
|
Packit Service |
ae04f2 |
unsigned int j;
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
#ifdef ISC_PLATFORM_USETHREADS
|
|
Packit Service |
ae04f2 |
/* if multi-threaded, we need a few extra variables. */
|
|
Packit Service |
ae04f2 |
int dbcount;
|
|
Packit Service |
ae04f2 |
db_list_t *dblist = NULL;
|
|
Packit Service |
ae04f2 |
int i;
|
|
Packit Service |
ae04f2 |
char *endp;
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
#endif /* ISC_PLATFORM_USETHREADS */
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
UNUSED(driverarg);
|
|
Packit Service |
ae04f2 |
UNUSED(dlzname);
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/* seed random # generator */
|
|
Packit Service |
ae04f2 |
srand( (unsigned)time( NULL ) );
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
#ifdef ISC_PLATFORM_USETHREADS
|
|
Packit Service |
ae04f2 |
/* if debugging, let user know we are multithreaded. */
|
|
Packit Service |
ae04f2 |
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
|
|
Packit Service |
ae04f2 |
DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1),
|
|
Packit Service |
ae04f2 |
"Postgres driver running multithreaded");
|
|
Packit Service |
ae04f2 |
#else /* ISC_PLATFORM_USETHREADS */
|
|
Packit Service |
ae04f2 |
/* if debugging, let user know we are single threaded. */
|
|
Packit Service |
ae04f2 |
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
|
|
Packit Service |
ae04f2 |
DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1),
|
|
Packit Service |
ae04f2 |
"Postgres driver running single threaded");
|
|
Packit Service |
ae04f2 |
#endif /* ISC_PLATFORM_USETHREADS */
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/* verify we have at least 5 arg's passed to the driver */
|
|
Packit Service |
ae04f2 |
if (argc < 5) {
|
|
Packit Service |
ae04f2 |
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
|
|
Packit Service |
ae04f2 |
DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
|
|
Packit Service |
ae04f2 |
"Postgres driver requires at least "
|
|
Packit Service |
ae04f2 |
"4 command line args.");
|
|
Packit Service |
ae04f2 |
return (ISC_R_FAILURE);
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/* no more than 8 arg's should be passed to the driver */
|
|
Packit Service |
ae04f2 |
if (argc > 8) {
|
|
Packit Service |
ae04f2 |
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
|
|
Packit Service |
ae04f2 |
DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
|
|
Packit Service |
ae04f2 |
"Postgres driver cannot accept more than "
|
|
Packit Service |
ae04f2 |
"7 command line args.");
|
|
Packit Service |
ae04f2 |
return (ISC_R_FAILURE);
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/* multithreaded build can have multiple DB connections */
|
|
Packit Service |
ae04f2 |
#ifdef ISC_PLATFORM_USETHREADS
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/* check how many db connections we should create */
|
|
Packit Service |
ae04f2 |
dbcount = strtol(argv[1], &endp, 10);
|
|
Packit Service |
ae04f2 |
if (*endp != '\0' || dbcount < 0) {
|
|
Packit Service |
ae04f2 |
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
|
|
Packit Service |
ae04f2 |
DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
|
|
Packit Service |
ae04f2 |
"Postgres driver database connection count "
|
|
Packit Service |
ae04f2 |
"must be positive.");
|
|
Packit Service |
ae04f2 |
return (ISC_R_FAILURE);
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/* allocate memory for database connection list */
|
|
Packit Service |
ae04f2 |
dblist = isc_mem_get(ns_g_mctx, sizeof(db_list_t));
|
|
Packit Service |
ae04f2 |
if (dblist == NULL)
|
|
Packit Service |
ae04f2 |
return (ISC_R_NOMEMORY);
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/* initialize DB connection list */
|
|
Packit Service |
ae04f2 |
ISC_LIST_INIT(*dblist);
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/*
|
|
Packit Service |
ae04f2 |
* create the appropriate number of database instances (DBI)
|
|
Packit Service |
ae04f2 |
* append each new DBI to the end of the list
|
|
Packit Service |
ae04f2 |
*/
|
|
Packit Service |
ae04f2 |
for (i=0; i < dbcount; i++) {
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
#endif /* ISC_PLATFORM_USETHREADS */
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/* how many queries were passed in from config file? */
|
|
Packit Service |
ae04f2 |
switch(argc) {
|
|
Packit Service |
ae04f2 |
case 5:
|
|
Packit Service |
ae04f2 |
result = build_sqldbinstance(ns_g_mctx, NULL, NULL,
|
|
Packit Service |
ae04f2 |
NULL, argv[3], argv[4],
|
|
Packit Service |
ae04f2 |
NULL, &dbi;;
|
|
Packit Service |
ae04f2 |
break;
|
|
Packit Service |
ae04f2 |
case 6:
|
|
Packit Service |
ae04f2 |
result = build_sqldbinstance(ns_g_mctx, NULL, NULL,
|
|
Packit Service |
ae04f2 |
argv[5], argv[3], argv[4],
|
|
Packit Service |
ae04f2 |
NULL, &dbi;;
|
|
Packit Service |
ae04f2 |
break;
|
|
Packit Service |
ae04f2 |
case 7:
|
|
Packit Service |
ae04f2 |
result = build_sqldbinstance(ns_g_mctx, argv[6], NULL,
|
|
Packit Service |
ae04f2 |
argv[5], argv[3], argv[4],
|
|
Packit Service |
ae04f2 |
NULL, &dbi;;
|
|
Packit Service |
ae04f2 |
break;
|
|
Packit Service |
ae04f2 |
case 8:
|
|
Packit Service |
ae04f2 |
result = build_sqldbinstance(ns_g_mctx, argv[6],
|
|
Packit Service |
ae04f2 |
argv[7], argv[5], argv[3],
|
|
Packit Service |
ae04f2 |
argv[4], NULL, &dbi;;
|
|
Packit Service |
ae04f2 |
break;
|
|
Packit Service |
ae04f2 |
default:
|
|
Packit Service |
ae04f2 |
/* not really needed, should shut up compiler. */
|
|
Packit Service |
ae04f2 |
result = ISC_R_FAILURE;
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
if (result == ISC_R_SUCCESS) {
|
|
Packit Service |
ae04f2 |
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
|
|
Packit Service |
ae04f2 |
DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
|
|
Packit Service |
ae04f2 |
"Postgres driver created database "
|
|
Packit Service |
ae04f2 |
"instance object.");
|
|
Packit Service |
ae04f2 |
} else { /* unsuccessful?, log err msg and cleanup. */
|
|
Packit Service |
ae04f2 |
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
|
|
Packit Service |
ae04f2 |
DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
|
|
Packit Service |
ae04f2 |
"Postgres driver could not create "
|
|
Packit Service |
ae04f2 |
"database instance object.");
|
|
Packit Service |
ae04f2 |
goto cleanup;
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
#ifdef ISC_PLATFORM_USETHREADS
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/* when multithreaded, build a list of DBI's */
|
|
Packit Service |
ae04f2 |
ISC_LINK_INIT(dbi, link);
|
|
Packit Service |
ae04f2 |
ISC_LIST_APPEND(*dblist, dbi, link);
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
#endif
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/* create and set db connection */
|
|
Packit Service |
ae04f2 |
dbi->dbconn = PQconnectdb(argv[2]);
|
|
Packit Service |
ae04f2 |
/*
|
|
Packit Service |
ae04f2 |
* if db connection cannot be created, log err msg and
|
|
Packit Service |
ae04f2 |
* cleanup.
|
|
Packit Service |
ae04f2 |
*/
|
|
Packit Service |
ae04f2 |
if (dbi->dbconn == NULL) {
|
|
Packit Service |
ae04f2 |
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
|
|
Packit Service |
ae04f2 |
DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
|
|
Packit Service |
ae04f2 |
"Postgres driver could not allocate "
|
|
Packit Service |
ae04f2 |
"memory for database connection");
|
|
Packit Service |
ae04f2 |
goto cleanup;
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/* if we cannot connect the first time, try 3 more times. */
|
|
Packit Service |
ae04f2 |
for (j = 0;
|
|
Packit Service |
ae04f2 |
PQstatus((PGconn *) dbi->dbconn) != CONNECTION_OK &&
|
|
Packit Service |
ae04f2 |
j < 3;
|
|
Packit Service |
ae04f2 |
j++)
|
|
Packit Service |
ae04f2 |
PQreset((PGconn *) dbi->dbconn);
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
#ifdef ISC_PLATFORM_USETHREADS
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/*
|
|
Packit Service |
ae04f2 |
* if multi threaded, let user know which connection
|
|
Packit Service |
ae04f2 |
* failed. user could be attempting to create 10 db
|
|
Packit Service |
ae04f2 |
* connections and for some reason the db backend only
|
|
Packit Service |
ae04f2 |
* allows 9
|
|
Packit Service |
ae04f2 |
*/
|
|
Packit Service |
ae04f2 |
if (PQstatus((PGconn *) dbi->dbconn) != CONNECTION_OK) {
|
|
Packit Service |
ae04f2 |
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
|
|
Packit Service |
ae04f2 |
DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
|
|
Packit Service |
ae04f2 |
"Postgres driver failed to create "
|
|
Packit Service |
ae04f2 |
"database connection number %u "
|
|
Packit Service |
ae04f2 |
"after 4 attempts",
|
|
Packit Service |
ae04f2 |
i + 1);
|
|
Packit Service |
ae04f2 |
goto cleanup;
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/* set DBI = null for next loop through. */
|
|
Packit Service |
ae04f2 |
dbi = NULL;
|
|
Packit Service |
ae04f2 |
} /* end for loop */
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/* set dbdata to the list we created. */
|
|
Packit Service |
ae04f2 |
*dbdata = dblist;
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
#else /* ISC_PLATFORM_USETHREADS */
|
|
Packit Service |
ae04f2 |
/* if single threaded, just let user know we couldn't connect. */
|
|
Packit Service |
ae04f2 |
if (PQstatus((PGconn *) dbi->dbconn) != CONNECTION_OK) {
|
|
Packit Service |
ae04f2 |
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
|
|
Packit Service |
ae04f2 |
DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
|
|
Packit Service |
ae04f2 |
"Postgres driver failed to create database "
|
|
Packit Service |
ae04f2 |
"connection after 4 attempts");
|
|
Packit Service |
ae04f2 |
goto cleanup;
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/*
|
|
Packit Service |
ae04f2 |
* single threaded build can only use 1 db connection, return
|
|
Packit Service |
ae04f2 |
* it via dbdata
|
|
Packit Service |
ae04f2 |
*/
|
|
Packit Service |
ae04f2 |
*dbdata = dbi;
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
#endif /* ISC_PLATFORM_USETHREADS */
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/* hey, we got through all of that ok, return success. */
|
|
Packit Service |
ae04f2 |
return(ISC_R_SUCCESS);
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
cleanup:
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
#ifdef ISC_PLATFORM_USETHREADS
|
|
Packit Service |
ae04f2 |
/*
|
|
Packit Service |
ae04f2 |
* if multithreaded, we could fail because only 1 connection
|
|
Packit Service |
ae04f2 |
* couldn't be made. We should cleanup the other successful
|
|
Packit Service |
ae04f2 |
* connections properly.
|
|
Packit Service |
ae04f2 |
*/
|
|
Packit Service |
ae04f2 |
postgres_destroy_dblist(dblist);
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
#else /* ISC_PLATFORM_USETHREADS */
|
|
Packit Service |
ae04f2 |
if (dbi != NULL)
|
|
Packit Service |
ae04f2 |
destroy_sqldbinstance(dbi);
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
#endif /* ISC_PLATFORM_USETHREADS */
|
|
Packit Service |
ae04f2 |
return(ISC_R_FAILURE);
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/*%
|
|
Packit Service |
ae04f2 |
* destroy an instance of the driver. Remember, only 1 copy of the driver's
|
|
Packit Service |
ae04f2 |
* code is ever loaded, the driver has to remember which context it's
|
|
Packit Service |
ae04f2 |
* operating in. This is done via use of the dbdata argument.
|
|
Packit Service |
ae04f2 |
* so we really only need to clean it up since we are not using driverarg.
|
|
Packit Service |
ae04f2 |
*/
|
|
Packit Service |
ae04f2 |
static void
|
|
Packit Service |
ae04f2 |
postgres_destroy(void *driverarg, void *dbdata)
|
|
Packit Service |
ae04f2 |
{
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
#ifdef ISC_PLATFORM_USETHREADS
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
UNUSED(driverarg);
|
|
Packit Service |
ae04f2 |
/* cleanup the list of DBI's */
|
|
Packit Service |
ae04f2 |
postgres_destroy_dblist((db_list_t *) dbdata);
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
#else /* ISC_PLATFORM_USETHREADS */
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
dbinstance_t *dbi;
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
UNUSED(driverarg);
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
dbi = (dbinstance_t *) dbdata;
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/* release DB connection */
|
|
Packit Service |
ae04f2 |
if (dbi->dbconn != NULL)
|
|
Packit Service |
ae04f2 |
PQfinish((PGconn *) dbi->dbconn);
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/* destroy single DB instance */
|
|
Packit Service |
ae04f2 |
destroy_sqldbinstance(dbi);
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
#endif /* ISC_PLATFORM_USETHREADS */
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/* pointers to all our runtime methods. */
|
|
Packit Service |
ae04f2 |
/* this is used during driver registration */
|
|
Packit Service |
ae04f2 |
/* i.e. in dlz_postgres_init below. */
|
|
Packit Service |
ae04f2 |
static dns_sdlzmethods_t dlz_postgres_methods = {
|
|
Packit Service |
ae04f2 |
postgres_create,
|
|
Packit Service |
ae04f2 |
postgres_destroy,
|
|
Packit Service |
ae04f2 |
postgres_findzone,
|
|
Packit Service |
ae04f2 |
postgres_lookup,
|
|
Packit Service |
ae04f2 |
postgres_authority,
|
|
Packit Service |
ae04f2 |
postgres_allnodes,
|
|
Packit Service |
ae04f2 |
postgres_allowzonexfr,
|
|
Packit Service |
ae04f2 |
NULL,
|
|
Packit Service |
ae04f2 |
NULL,
|
|
Packit Service |
ae04f2 |
NULL,
|
|
Packit Service |
ae04f2 |
NULL,
|
|
Packit Service |
ae04f2 |
NULL,
|
|
Packit Service |
ae04f2 |
NULL,
|
|
Packit Service |
ae04f2 |
NULL,
|
|
Packit Service |
ae04f2 |
};
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/*%
|
|
Packit Service |
ae04f2 |
* Wrapper around dns_sdlzregister().
|
|
Packit Service |
ae04f2 |
*/
|
|
Packit Service |
ae04f2 |
isc_result_t
|
|
Packit Service |
ae04f2 |
dlz_postgres_init(void) {
|
|
Packit Service |
ae04f2 |
isc_result_t result;
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/*
|
|
Packit Service |
ae04f2 |
* Write debugging message to log
|
|
Packit Service |
ae04f2 |
*/
|
|
Packit Service |
ae04f2 |
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
|
|
Packit Service |
ae04f2 |
DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
|
|
Packit Service |
ae04f2 |
"Registering DLZ postgres driver.");
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/*
|
|
Packit Service |
ae04f2 |
* Driver is always threadsafe. When multithreaded all
|
|
Packit Service |
ae04f2 |
* functions use multithreaded code. When not multithreaded,
|
|
Packit Service |
ae04f2 |
* all functions can only be entered once, but only 1 thread
|
|
Packit Service |
ae04f2 |
* of operation is available in Bind. So everything is still
|
|
Packit Service |
ae04f2 |
* threadsafe.
|
|
Packit Service |
ae04f2 |
*/
|
|
Packit Service |
ae04f2 |
result = dns_sdlzregister("postgres", &dlz_postgres_methods, NULL,
|
|
Packit Service |
ae04f2 |
DNS_SDLZFLAG_RELATIVEOWNER |
|
|
Packit Service |
ae04f2 |
DNS_SDLZFLAG_RELATIVERDATA |
|
|
Packit Service |
ae04f2 |
DNS_SDLZFLAG_THREADSAFE,
|
|
Packit Service |
ae04f2 |
ns_g_mctx, &dlz_postgres);
|
|
Packit Service |
ae04f2 |
/* if we can't register the driver, there are big problems. */
|
|
Packit Service |
ae04f2 |
if (result != ISC_R_SUCCESS) {
|
|
Packit Service |
ae04f2 |
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
|
Packit Service |
ae04f2 |
"dns_sdlzregister() failed: %s",
|
|
Packit Service |
ae04f2 |
isc_result_totext(result));
|
|
Packit Service |
ae04f2 |
result = ISC_R_UNEXPECTED;
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
return result;
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/*%
|
|
Packit Service |
ae04f2 |
* Wrapper around dns_sdlzunregister().
|
|
Packit Service |
ae04f2 |
*/
|
|
Packit Service |
ae04f2 |
void
|
|
Packit Service |
ae04f2 |
dlz_postgres_clear(void) {
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/*
|
|
Packit Service |
ae04f2 |
* Write debugging message to log
|
|
Packit Service |
ae04f2 |
*/
|
|
Packit Service |
ae04f2 |
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
|
|
Packit Service |
ae04f2 |
DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
|
|
Packit Service |
ae04f2 |
"Unregistering DLZ postgres driver.");
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
/* unregister the driver. */
|
|
Packit Service |
ae04f2 |
if (dlz_postgres != NULL)
|
|
Packit Service |
ae04f2 |
dns_sdlzunregister(&dlz_postgres);
|
|
Packit Service |
ae04f2 |
}
|
|
Packit Service |
ae04f2 |
|
|
Packit Service |
ae04f2 |
#endif
|