03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews/*
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl.
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews *
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * Permission to use, copy, modify, and distribute this software for any
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * purpose with or without fee is hereby granted, provided that the
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * above copyright notice and this permission notice appear in all
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * copies.
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews *
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * STICHTING NLNET BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * USE OR PERFORMANCE OF THIS SOFTWARE.
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews *
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * conceived and contributed by Rob Butler.
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews *
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * Permission to use, copy, modify, and distribute this software for any
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * purpose with or without fee is hereby granted, provided that the
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * above copyright notice and this permission notice appear in all
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * copies.
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews *
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * ROB BUTLER BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * USE OR PERFORMANCE OF THIS SOFTWARE.
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews/*
02d54949f0f1db4729e14c3322b207f58d2578a4Mark Andrews * Copyright (C) 1999-2001, 2016 Internet Systems Consortium, Inc. ("ISC")
02d54949f0f1db4729e14c3322b207f58d2578a4Mark Andrews *
02d54949f0f1db4729e14c3322b207f58d2578a4Mark Andrews * This Source Code Form is subject to the terms of the Mozilla Public
02d54949f0f1db4729e14c3322b207f58d2578a4Mark Andrews * License, v. 2.0. If a copy of the MPL was not distributed with this
02d54949f0f1db4729e14c3322b207f58d2578a4Mark Andrews * file, You can obtain one at http://mozilla.org/MPL/2.0/.
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#ifdef DLZ_ODBC
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#include <config.h>
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#include <stdio.h>
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#include <string.h>
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#include <stdlib.h>
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#include <dns/log.h>
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#include <dns/sdlz.h>
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#include <dns/result.h>
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#include <isc/mem.h>
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#include <isc/platform.h>
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#include <isc/print.h>
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#include <isc/result.h>
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#include <isc/string.h>
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#include <isc/util.h>
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#include <named/globals.h>
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#include <dlz/sdlz_helper.h>
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#include <dlz/dlz_odbc_driver.h>
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#include <sql.h>
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#include <sqlext.h>
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#include <sqltypes.h>
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrewsstatic dns_sdlzimplementation_t *dlz_odbc = NULL;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#define dbc_search_limit 30
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#define ALLNODES 1
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#define ALLOWXFR 2
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#define AUTHORITY 3
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#define FINDZONE 4
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#define LOOKUP 5
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#define sqlOK(a) ((a == SQL_SUCCESS || a == SQL_SUCCESS_WITH_INFO) ? -1 : 0)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews/*
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * Private Structures
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews/*
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * structure to hold ODBC connection & statement
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrewstypedef struct{
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews SQLHDBC dbc;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews SQLHSTMT stmnt;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews} odbc_db_t;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews/*
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * Structure to hold everthing needed by this "instance" of the odbc driver
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * remember, the driver code is only loaded once, but may have many separate
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * instances
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrewstypedef struct {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#ifdef ISC_PLATFORM_USETHREADS
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews db_list_t *db; /* handle to a list of DB */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#else
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews dbinstance_t *db; /* handle to db */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#endif
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews SQLHENV sql_env; /* handle to SQL environment */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews SQLCHAR *dsn;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews SQLCHAR *user;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews SQLCHAR *pass;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews} odbc_instance_t;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews/* forward reference */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrewsstatic size_t
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrewsodbc_makesafe(char *to, const char *from, size_t length);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews/*
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * Private methods
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrewsstatic SQLSMALLINT
03e200df5dc283f24a6a349f0b31d3eab26da893Mark AndrewssafeLen(void *a) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (a == NULL)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews return 0;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews return strlen((char *) a);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews}
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews/*% propertly cleans up an odbc_instance_t */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrewsstatic void
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrewsdestroy_odbc_instance(odbc_instance_t *odbc_inst) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#ifdef ISC_PLATFORM_USETHREADS
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews dbinstance_t *ndbi = NULL;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews dbinstance_t *dbi = NULL;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* get the first DBI in the list */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews ndbi = ISC_LIST_HEAD(*odbc_inst->db);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* loop through the list */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews while (ndbi != NULL) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews dbi = ndbi;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* get the next DBI in the list */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews ndbi = ISC_LIST_NEXT(dbi, link);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* if we have a connection / statement object in memory */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (dbi->dbconn != NULL) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* free statement handle */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (((odbc_db_t *) (dbi->dbconn))->stmnt != NULL) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews SQLFreeHandle(SQL_HANDLE_STMT,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews ((odbc_db_t *)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews (dbi->dbconn))->stmnt);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews ((odbc_db_t *) (dbi->dbconn))->stmnt = NULL;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* disconnect from database & free connection handle */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (((odbc_db_t *) (dbi->dbconn))->dbc != NULL) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews SQLDisconnect(((odbc_db_t *)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews dbi->dbconn)->dbc);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews SQLFreeHandle(SQL_HANDLE_DBC,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews ((odbc_db_t *)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews (dbi->dbconn))->dbc);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews ((odbc_db_t *) (dbi->dbconn))->dbc = NULL;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* free memory that held connection & statement. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_mem_free(ns_g_mctx, dbi->dbconn);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* release all memory that comprised a DBI */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews destroy_sqldbinstance(dbi);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* release memory for the list structure */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_mem_put(ns_g_mctx, odbc_inst->db, sizeof(db_list_t));
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#else /* ISC_PLATFORM_USETHREADS */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* free statement handle */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (((odbc_db_t *) (odbc_inst->db->dbconn))->stmnt != NULL) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews SQLFreeHandle(SQL_HANDLE_STMT,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews ((odbc_db_t *) (odbc_inst->db->dbconn))->stmnt);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews ((odbc_db_t *) (odbc_inst->db->dbconn))->stmnt = NULL;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* disconnect from database, free connection handle */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (((odbc_db_t *) (odbc_inst->db->dbconn))->dbc != NULL) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews SQLDisconnect(((odbc_db_t *) (odbc_inst->db->dbconn))->dbc);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews SQLFreeHandle(SQL_HANDLE_DBC,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews ((odbc_db_t *) (odbc_inst->db->dbconn))->dbc);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews ((odbc_db_t *) (odbc_inst->db->dbconn))->dbc = NULL;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* free mem for the odbc_db_t structure held in db */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (((odbc_db_t *) odbc_inst->db->dbconn) != NULL) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_mem_free(ns_g_mctx, odbc_inst->db->dbconn);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews odbc_inst->db->dbconn = NULL;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (odbc_inst->db != NULL)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews destroy_sqldbinstance(odbc_inst->db);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#endif /* ISC_PLATFORM_USETHREADS */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* free sql environment */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (odbc_inst->sql_env != NULL)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews SQLFreeHandle(SQL_HANDLE_ENV, odbc_inst->sql_env);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* free ODBC instance strings */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (odbc_inst->dsn != NULL)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_mem_free(ns_g_mctx, odbc_inst->dsn);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (odbc_inst->pass != NULL)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_mem_free(ns_g_mctx, odbc_inst->pass);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (odbc_inst->user != NULL)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_mem_free(ns_g_mctx, odbc_inst->user);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* free memory for odbc_inst */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (odbc_inst != NULL)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_mem_put(ns_g_mctx, odbc_inst, sizeof(odbc_instance_t));
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews}
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews/*% Connects to database, and creates ODBC statements */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrewsstatic isc_result_t
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrewsodbc_connect(odbc_instance_t *dbi, odbc_db_t **dbc) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews odbc_db_t *ndb = *dbc;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews SQLRETURN sqlRes;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_result_t result = ISC_R_SUCCESS;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (ndb != NULL) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /*
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * if db != null, we have to do some cleanup
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * if statement handle != null free it
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (ndb->stmnt != NULL) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews SQLFreeHandle(SQL_HANDLE_STMT, ndb->stmnt);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews ndb->stmnt = NULL;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* if connection handle != null free it */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (ndb->dbc != NULL) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews SQLFreeHandle(SQL_HANDLE_DBC, ndb->dbc);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews ndb->dbc = NULL;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews } else {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews ndb = isc_mem_allocate(ns_g_mctx, sizeof(odbc_db_t));
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (ndb == NULL) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "Odbc driver unable to allocate memory");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews return ISC_R_NOMEMORY;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews memset(ndb, 0, sizeof(odbc_db_t));
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews sqlRes = SQLAllocHandle(SQL_HANDLE_DBC, dbi->sql_env, &(ndb->dbc));
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (!sqlOK(sqlRes)) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "Odbc driver unable to allocate memory");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = ISC_R_NOMEMORY;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews goto cleanup;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews sqlRes = SQLConnect(ndb->dbc, dbi->dsn, safeLen(dbi->dsn), dbi->user,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews safeLen(dbi->user), dbi->pass, safeLen(dbi->pass));
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (!sqlOK(sqlRes)) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "Odbc driver unable to connect");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = ISC_R_FAILURE;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews goto cleanup;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews sqlRes = SQLAllocHandle(SQL_HANDLE_STMT, ndb->dbc, &(ndb->stmnt));
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (!sqlOK(sqlRes)) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "Odbc driver unable to allocate memory");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = ISC_R_NOMEMORY;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews goto cleanup;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews *dbc = ndb;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews return ISC_R_SUCCESS;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews cleanup:
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (ndb != NULL) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* if statement handle != null free it */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (ndb->stmnt != NULL) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews SQLFreeHandle(SQL_HANDLE_STMT, ndb->stmnt);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews ndb->stmnt = NULL;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* if connection handle != null free it */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (ndb->dbc != NULL) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews SQLDisconnect(ndb->dbc);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews SQLFreeHandle(SQL_HANDLE_DBC, ndb->dbc);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews ndb->dbc = NULL;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* free memory holding ndb */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_mem_free(ns_g_mctx, ndb);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews return result;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews}
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews/*%
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * Loops through the list of DB instances, attempting to lock
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * on the mutex. If successful, the DBI is reserved for use
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * and the thread can perform queries against the database.
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * If the lock fails, the next one in the list is tried.
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * looping continues until a lock is obtained, or until
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * the list has been searched dbc_search_limit times.
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * This function is only used when the driver is compiled for
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * multithreaded operation.
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#ifdef ISC_PLATFORM_USETHREADS
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrewsstatic dbinstance_t *
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrewsodbc_find_avail_conn(db_list_t *dblist)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews{
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews dbinstance_t *dbi = NULL;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews dbinstance_t *head;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews int count = 0;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* get top of list */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews head = dbi = ISC_LIST_HEAD(*dblist);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* loop through list */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews while (count < dbc_search_limit) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* try to lock on the mutex */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (isc_mutex_trylock(&dbi->instance_lock) == ISC_R_SUCCESS)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews return dbi; /* success, return the DBI for use. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* not successful, keep trying */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews dbi = ISC_LIST_NEXT(dbi, link);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* check to see if we have gone to the top of the list. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (dbi == NULL) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews count++;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews dbi = head;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews DNS_LOGMODULE_DLZ, ISC_LOG_INFO,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "Odbc driver unable to find available "
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "connection after searching %d times",
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews count);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews return NULL;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews}
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#endif /* ISC_PLATFORM_USETHREADS */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews/*% Allocates memory for a new string, and then constructs the new
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * string by "escaping" the input string. The new string is
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * safe to be used in queries. This is necessary because we cannot
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * be sure of what types of strings are passed to us, and we don't
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * want special characters in the string causing problems.
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrewsstatic char *
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrewsodbc_escape_string(const char *instr) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews char *outstr;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews unsigned int len;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (instr == NULL)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews return NULL;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews len = strlen(instr);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews outstr = isc_mem_allocate(ns_g_mctx ,(2 * len * sizeof(char)) + 1);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (outstr == NULL)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews return NULL;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews odbc_makesafe(outstr, instr, len);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews return outstr;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews}
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews/* ---------------
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * Escaping arbitrary strings to get valid SQL strings/identifiers.
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews *
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * Replaces "\\" with "\\\\" and "'" with "''".
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * length is the length of the buffer pointed to by
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * from. The buffer at to must be at least 2*length + 1 characters
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * long. A terminating NUL character is written.
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews *
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * NOTICE!!!
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * This function was borrowed directly from PostgreSQL's libpq.
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews *
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * The copyright statements from the original file containing this
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * function are included below:
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * Portions Copyright (c) 1994, Regents of the University of California
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * ---------------
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrewsstatic size_t
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrewsodbc_makesafe(char *to, const char *from, size_t length)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews{
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews const char *source = from;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews char *target = to;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews unsigned int remaining = length;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews while (remaining > 0)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews switch (*source)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews case '\\':
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews *target = '\\';
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews target++;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews *target = '\\';
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* target and remaining are updated below. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews break;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews case '\'':
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews *target = '\'';
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews target++;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews *target = '\'';
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* target and remaining are updated below. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews break;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews default:
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews *target = *source;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* target and remaining are updated below. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews source++;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews target++;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews remaining--;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* Write the terminating NUL character. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews *target = '\0';
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews return target - to;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews}
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews/*%
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * This function is the real core of the driver. Zone, record
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * and client strings are passed in (or NULL is passed if the
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * string is not available). The type of query we want to run
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * is indicated by the query flag, and the dbdata object is passed
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * passed in to. dbdata really holds either:
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * 1) a list of database instances (in multithreaded mode) OR
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * 2) a single database instance (in single threaded mode)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * The function will construct the query and obtain an available
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * database instance (DBI). It will then run the query and hopefully
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * obtain a result set. The data base instance that is used is returned
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * to the caller so they can get the data from the result set from it.
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * If successfull, it will be the responsibility of the caller to close
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * the cursor, and unlock the mutex of the DBI when they are done with it.
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * If not successfull, this function will perform all the cleanup.
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrewsstatic isc_result_t
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrewsodbc_get_resultset(const char *zone, const char *record,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews const char *client, unsigned int query,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews void *dbdata, dbinstance_t **r_dbi)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews{
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_result_t result;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews dbinstance_t *dbi = NULL;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews char *querystring = NULL;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews unsigned int j = 0;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews SQLRETURN sqlRes;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews REQUIRE(*r_dbi == NULL);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* get db instance / connection */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#ifdef ISC_PLATFORM_USETHREADS
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* find an available DBI from the list */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews dbi = odbc_find_avail_conn(((odbc_instance_t *) dbdata)->db);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#else /* ISC_PLATFORM_USETHREADS */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /*
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * only 1 DBI - no need to lock instance lock either
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * only 1 thread in the whole process, no possible contention.
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews dbi = (dbinstance_t *) ((odbc_instance_t *) dbdata)->db;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#endif /* ISC_PLATFORM_USETHREADS */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* if DBI is null, can't do anything else */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (dbi == NULL) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = ISC_R_FAILURE;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews goto cleanup;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* what type of query are we going to run? */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews switch(query) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews case ALLNODES:
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /*
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * if the query was not passed in from the config file
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * then we can't run it. return not_implemented, so
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * it's like the code for that operation was never
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * built into the driver.... AHHH flexibility!!!
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (dbi->allnodes_q == NULL) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = ISC_R_NOTIMPLEMENTED;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews goto cleanup;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews break;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews case ALLOWXFR:
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* same as comments as ALLNODES */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (dbi->allowxfr_q == NULL) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = ISC_R_NOTIMPLEMENTED;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews goto cleanup;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews break;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews case AUTHORITY:
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* same as comments as ALLNODES */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (dbi->authority_q == NULL) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = ISC_R_NOTIMPLEMENTED;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews goto cleanup;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews break;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews case FINDZONE:
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* this is required. It's the whole point of DLZ! */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (dbi->findzone_q == NULL) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "No query specified for findzone. "
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "Findzone requires a query");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = ISC_R_FAILURE;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews goto cleanup;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews break;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews case LOOKUP:
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* this is required. It's also a major point of DLZ! */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (dbi->lookup_q == NULL) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "No query specified for lookup. "
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "Lookup requires a query");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = ISC_R_FAILURE;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews goto cleanup;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews break;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews default:
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /*
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * this should never happen. If it does, the code is
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * screwed up!
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews UNEXPECTED_ERROR(__FILE__, __LINE__,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "Incorrect query flag passed to "
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "odbc_get_resultset");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = ISC_R_UNEXPECTED;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews goto cleanup;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /*
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * was a zone string passed? If so, make it safe for use in
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * queries.
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (zone != NULL) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews dbi->zone = odbc_escape_string(zone);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (dbi->zone == NULL) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = ISC_R_NOMEMORY;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews goto cleanup;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews } else { /* no string passed, set the string pointer to NULL */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews dbi->zone = NULL;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /*
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * was a record string passed? If so, make it safe for use in
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * queries.
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (record != NULL) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews dbi->record = odbc_escape_string(record);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (dbi->record == NULL) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = ISC_R_NOMEMORY;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews goto cleanup;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews } else { /* no string passed, set the string pointer to NULL */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews dbi->record = NULL;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /*
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * was a client string passed? If so, make it safe for use in
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * queries.
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (client != NULL) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews dbi->client = odbc_escape_string(client);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (dbi->client == NULL) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = ISC_R_NOMEMORY;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews goto cleanup;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews } else { /* no string passed, set the string pointer to NULL */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews dbi->client = NULL;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /*
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * what type of query are we going to run?
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * this time we build the actual query to run.
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews switch(query) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews case ALLNODES:
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews querystring = build_querystring(ns_g_mctx, dbi->allnodes_q);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews break;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews case ALLOWXFR:
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews querystring = build_querystring(ns_g_mctx, dbi->allowxfr_q);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews break;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews case AUTHORITY:
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews querystring = build_querystring(ns_g_mctx, dbi->authority_q);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews break;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews case FINDZONE:
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews querystring = build_querystring(ns_g_mctx, dbi->findzone_q);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews break;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews case LOOKUP:
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews querystring = build_querystring(ns_g_mctx, dbi->lookup_q);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews break;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews default:
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /*
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * this should never happen. If it does, the code is
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * screwed up!
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews UNEXPECTED_ERROR(__FILE__, __LINE__,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "Incorrect query flag passed to "
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "odbc_get_resultset");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = ISC_R_UNEXPECTED;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews goto cleanup;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* if the querystring is null, Bummer, outta RAM. UPGRADE TIME!!! */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (querystring == NULL) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = ISC_R_NOMEMORY;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews goto cleanup;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* output the full query string during debug so we can see */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* what lame error the query has. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1),
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "\nQuery String: %s\n", querystring);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* attempt query up to 3 times. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews for (j=0; j < 3; j++) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* try to get result set */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews sqlRes = SQLExecDirect(((odbc_db_t *) dbi->dbconn)->stmnt,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews (SQLCHAR *) querystring,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews (SQLINTEGER) strlen(querystring));
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* if error, reset DB connection */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (!sqlOK(sqlRes)) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* close cursor */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews SQLCloseCursor(((odbc_db_t *) dbi->dbconn)->stmnt);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* attempt to reconnect */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = odbc_connect((odbc_instance_t *) dbdata,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews (odbc_db_t **) &(dbi->dbconn));
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* check if we reconnected */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (result != ISC_R_SUCCESS)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews break;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* incase this is the last time through the loop */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = ISC_R_FAILURE;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews } else {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = ISC_R_SUCCESS;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* return dbi */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews *r_dbi = dbi;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* result set ok, break loop */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews break;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews } /* end for loop */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews cleanup: /* it's always good to cleanup after yourself */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* if we couldn't even allocate DBI, just return NULL */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (dbi == NULL)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews return ISC_R_FAILURE;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* free dbi->zone string */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (dbi->zone != NULL)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_mem_free(ns_g_mctx, dbi->zone);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* free dbi->record string */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (dbi->record != NULL)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_mem_free(ns_g_mctx, dbi->record);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* free dbi->client string */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (dbi->client != NULL)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_mem_free(ns_g_mctx, dbi->client);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#ifdef ISC_PLATFORM_USETHREADS
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* if we are done using this dbi, release the lock */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (result != ISC_R_SUCCESS)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_mutex_unlock(&dbi->instance_lock);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#endif /* ISC_PLATFORM_USETHREADS */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* release query string */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (querystring != NULL)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_mem_free(ns_g_mctx, querystring );
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* return result */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews return result;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews}
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews/*%
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * Gets a single field from the ODBC statement. The memory for the
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * returned data is dynamically allocated. If this method is successful
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * it is the reponsibility of the caller to free the memory using
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * isc_mem_free(ns_g_mctx, *ptr);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrewsstatic isc_result_t
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrewsodbc_getField(SQLHSTMT *stmnt, SQLSMALLINT field, char **data) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
41e55d04032c0eefd39d74ffb73657b04fb821ecEvan Hunt SQLLEN size;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews REQUIRE(data != NULL && *data == NULL);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (sqlOK(SQLColAttribute(stmnt, field, SQL_DESC_DISPLAY_SIZE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews NULL, 0, NULL, &size)) && size > 0) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews *data = isc_mem_allocate(ns_g_mctx, size + 1);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (data != NULL) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (sqlOK(SQLGetData(stmnt, field, SQL_C_CHAR,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews *data, size + 1,&size)))
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews return ISC_R_SUCCESS;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_mem_free(ns_g_mctx, *data);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews return ISC_R_FAILURE;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews}
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews/*%
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * Gets multiple fields from the ODBC statement. The memory for the
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * returned data is dynamically allocated. If this method is successful
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * it is the reponsibility of the caller to free the memory using
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * isc_mem_free(ns_g_mctx, *ptr);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrewsstatic isc_result_t
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrewsodbc_getManyFields(SQLHSTMT *stmnt, SQLSMALLINT startField,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews SQLSMALLINT endField, char **retData) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_result_t result;
41e55d04032c0eefd39d74ffb73657b04fb821ecEvan Hunt SQLLEN size;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews int totSize = 0;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews SQLSMALLINT i;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews int j = 0;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews char *data;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews REQUIRE(retData != NULL && *retData == NULL);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews REQUIRE(startField > 0 && startField <= endField);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* determine how large the data is */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews for (i=startField; i <= endField; i++)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (sqlOK(SQLColAttribute(stmnt, i, SQL_DESC_DISPLAY_SIZE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews NULL, 0, NULL, &size)) && size > 0) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* always allow for a " " (space) character */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews totSize += (size + 1);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* after the data item */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (totSize < 1)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews return ISC_R_FAILURE;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* allow for a "\n" at the end of the string/ */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews data = isc_mem_allocate(ns_g_mctx, ++totSize);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (data == NULL)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews return ISC_R_NOMEMORY;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = ISC_R_FAILURE;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* get the data and concat all fields into a large string */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews for (i=startField; i <= endField; i++) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (sqlOK(SQLGetData(stmnt, i, SQL_C_CHAR, &(data[j]),
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews totSize - j, &size))) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (size > 0) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews j += size;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews data[j++] = ' ';
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews data[j] = '\0';
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = ISC_R_SUCCESS;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews } else {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_mem_free(ns_g_mctx, data);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews return ISC_R_FAILURE;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (result != ISC_R_SUCCESS) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_mem_free(ns_g_mctx, data);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews return result;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews *retData = data;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews return ISC_R_SUCCESS;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews}
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews/*%
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * The processing of result sets for lookup and authority are
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * exactly the same. So that functionality has been moved
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * into this function to minimize code.
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrewsstatic isc_result_t
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrewsodbc_process_rs(dns_sdlzlookup_t *lookup, dbinstance_t *dbi)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews{
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_result_t result;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews SQLSMALLINT fields;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews SQLHSTMT *stmnt;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews char *ttl_s;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews char *type;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews char *data;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews char *endp;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews int ttl;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews REQUIRE(dbi != NULL);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews stmnt = ((odbc_db_t *) (dbi->dbconn))->stmnt;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* get number of columns */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (!sqlOK(SQLNumResultCols(stmnt, &fields))) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "Odbc driver unable to process result set");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = ISC_R_FAILURE;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews goto process_rs_cleanup;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* get things ready for processing */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = ISC_R_FAILURE;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews while (sqlOK(SQLFetch(stmnt))) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* set to null for next pass through */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews data = type = ttl_s = NULL;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews switch(fields) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews case 1:
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /*
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * one column in rs, it's the data field. use
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * default type of A record, and default TTL
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * of 86400. attempt to get data, & tell bind
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * about it.
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if ((result = odbc_getField(stmnt, 1,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews &data)) == ISC_R_SUCCESS) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = dns_sdlz_putrr(lookup, "a",
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews 86400, data);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews break;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews case 2:
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /*
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * two columns, data field, and data type.
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * use default TTL of 86400. attempt to get
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * DNS type & data, then tell bind about it.
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if ((result = odbc_getField(stmnt, 1,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews &type)) == ISC_R_SUCCESS &&
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews (result = odbc_getField(stmnt, 2,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews &data)) == ISC_R_SUCCESS) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = dns_sdlz_putrr(lookup, type,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews 86400, data);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews break;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews default:
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /*
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * 3 fields or more, concatenate the last ones
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * together. attempt to get DNS ttl, type,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * data then tell Bind about them.
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if ((result = odbc_getField(stmnt, 1, &ttl_s))
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews == ISC_R_SUCCESS &&
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews (result = odbc_getField(stmnt, 2, &type))
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews == ISC_R_SUCCESS &&
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews (result = odbc_getManyFields(stmnt, 3,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews fields, &data))
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews == ISC_R_SUCCESS) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* try to convert ttl string to int */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews ttl = strtol(ttl_s, &endp, 10);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* failure converting ttl. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (*endp != '\0' || ttl < 0) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews DNS_LOGMODULE_DLZ,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews ISC_LOG_ERROR,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "Odbc driver ttl must "
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "be a postive number");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = ISC_R_FAILURE;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews } else {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /*
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * successful converting TTL,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * tell Bind everything
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = dns_sdlz_putrr(lookup, type,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews ttl, data);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews } /* closes bid if () */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews } /* closes switch(fields) */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* clean up mem */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (ttl_s != NULL)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_mem_free(ns_g_mctx, ttl_s);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (type != NULL)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_mem_free(ns_g_mctx, type);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (data != NULL)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_mem_free(ns_g_mctx, data);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* I sure hope we were successful */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (result != ISC_R_SUCCESS) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "dns_sdlz_putrr returned error. "
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "Error code was: %s",
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_result_totext(result));
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = ISC_R_FAILURE;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews goto process_rs_cleanup;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews } /* closes while loop */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews process_rs_cleanup:
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* close cursor */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews SQLCloseCursor(((odbc_db_t *) (dbi->dbconn))->stmnt);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#ifdef ISC_PLATFORM_USETHREADS
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* free lock on dbi so someone else can use it. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_mutex_unlock(&dbi->instance_lock);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#endif
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews return result;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews}
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews/*
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * SDLZ interface methods
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews/*% determine if the zone is supported by (in) the database */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrewsstatic isc_result_t
abff0f462a758383d012887d3a97da4dac0c5a94Evan Huntodbc_findzone(void *driverarg, void *dbdata, const char *name,
abff0f462a758383d012887d3a97da4dac0c5a94Evan Hunt dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews{
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_result_t result;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews dbinstance_t *dbi = NULL;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews UNUSED(driverarg);
abff0f462a758383d012887d3a97da4dac0c5a94Evan Hunt UNUSED(methods);
abff0f462a758383d012887d3a97da4dac0c5a94Evan Hunt UNUSED(clientinfo);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* run the query and get the result set from the database. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* if result != ISC_R_SUCCESS cursor and mutex already cleaned up. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* so we don't have to do it here. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = odbc_get_resultset(name, NULL, NULL, FINDZONE, dbdata, &dbi);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* Check that we got a result set with data */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (result == ISC_R_SUCCESS &&
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews !sqlOK(SQLFetch(((odbc_db_t *) (dbi->dbconn))->stmnt))) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = ISC_R_NOTFOUND;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (dbi != NULL) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* get rid of result set, we are done with it. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews SQLCloseCursor(((odbc_db_t *) (dbi->dbconn))->stmnt);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#ifdef ISC_PLATFORM_USETHREADS
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* free lock on dbi so someone else can use it. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_mutex_unlock(&dbi->instance_lock);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#endif
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews return result;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews}
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews/*% Determine if the client is allowed to perform a zone transfer */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrewsstatic isc_result_t
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrewsodbc_allowzonexfr(void *driverarg, void *dbdata, const char *name,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews const char *client)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews{
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_result_t result;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews dbinstance_t *dbi = NULL;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews UNUSED(driverarg);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* first check if the zone is supported by the database. */
abff0f462a758383d012887d3a97da4dac0c5a94Evan Hunt result = odbc_findzone(driverarg, dbdata, name, NULL, NULL);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (result != ISC_R_SUCCESS)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews return (ISC_R_NOTFOUND);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /*
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * if we get to this point we know the zone is supported by
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * the database. the only questions now are is the zone
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * transfer is allowed for this client and did the config file
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * have an allow zone xfr query
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews *
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * Run our query, and get a result set from the database. if
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * result != ISC_R_SUCCESS cursor and mutex already cleaned
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * up, so we don't have to do it here.
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = odbc_get_resultset(name, NULL, client, ALLOWXFR,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews dbdata, &dbi);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* if we get "not implemented", send it along. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (result == ISC_R_NOTIMPLEMENTED)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews return result;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* Check that we got a result set with data */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (result == ISC_R_SUCCESS &&
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews !sqlOK(SQLFetch(((odbc_db_t *) (dbi->dbconn))->stmnt))) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = ISC_R_NOPERM;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (dbi != NULL) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* get rid of result set, we are done with it. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews SQLCloseCursor(((odbc_db_t *) (dbi->dbconn))->stmnt);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#ifdef ISC_PLATFORM_USETHREADS
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* free lock on dbi so someone else can use it. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_mutex_unlock(&dbi->instance_lock);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#endif
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews return result;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews}
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews/*%
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * If the client is allowed to perform a zone transfer, the next order of
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * business is to get all the nodes in the zone, so bind can respond to the
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * query.
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrewsstatic isc_result_t
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrewsodbc_allnodes(const char *zone, void *driverarg, void *dbdata,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews dns_sdlzallnodes_t *allnodes)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews{
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_result_t result;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews dbinstance_t *dbi = NULL;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews SQLHSTMT *stmnt;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews SQLSMALLINT fields;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews char *data;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews char *type;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews char *ttl_s;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews int ttl;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews char *host;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews char *endp;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews UNUSED(driverarg);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* run the query and get the result set from the database. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = odbc_get_resultset(zone, NULL, NULL, ALLNODES, dbdata, &dbi);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* if we get "not implemented", send it along */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (result == ISC_R_NOTIMPLEMENTED)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews return result;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* if we didn't get a result set, log an err msg. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (result != ISC_R_SUCCESS) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "Odbc driver unable to return "
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "result set for all nodes query");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews return (ISC_R_FAILURE);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews stmnt = ((odbc_db_t *) (dbi->dbconn))->stmnt;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* get number of columns */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (!sqlOK(SQLNumResultCols(stmnt, &fields))) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "Odbc driver unable to process result set");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = ISC_R_FAILURE;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews goto allnodes_cleanup;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (fields < 4) { /* gotta have at least 4 columns */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "Odbc driver too few fields returned by "
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "all nodes query");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = ISC_R_FAILURE;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews goto allnodes_cleanup;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* get things ready for processing */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = ISC_R_FAILURE;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews while (sqlOK(SQLFetch(stmnt))) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* set to null for next pass through */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews data = host = type = ttl_s = NULL;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /*
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * attempt to get DNS ttl, type, host, data then tell
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * Bind about them
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if ((result = odbc_getField(stmnt, 1,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews &ttl_s)) == ISC_R_SUCCESS &&
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews (result = odbc_getField(stmnt, 2,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews &type)) == ISC_R_SUCCESS &&
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews (result = odbc_getField(stmnt, 3,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews &host)) == ISC_R_SUCCESS &&
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews (result = odbc_getManyFields(stmnt, 4, fields,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews &data)) == ISC_R_SUCCESS) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* convert ttl string to int */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews ttl = strtol(ttl_s, &endp, 10);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* failure converting ttl. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (*endp != '\0' || ttl < 0) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "Odbc driver ttl must be "
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "a postive number");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = ISC_R_FAILURE;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews } else {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* successful converting TTL, tell Bind */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = dns_sdlz_putnamedrr(allnodes, host,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews type, ttl, data);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews } /* closes big if () */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* clean up mem */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (ttl_s != NULL)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_mem_free(ns_g_mctx, ttl_s);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (type != NULL)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_mem_free(ns_g_mctx, type);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (host != NULL)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_mem_free(ns_g_mctx, host);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (data != NULL)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_mem_free(ns_g_mctx, data);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* if we weren't successful, log err msg */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (result != ISC_R_SUCCESS) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "dns_sdlz_putnamedrr returned error. "
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "Error code was: %s",
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_result_totext(result));
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = ISC_R_FAILURE;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews goto allnodes_cleanup;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews } /* closes while loop */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews allnodes_cleanup:
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* close cursor */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews SQLCloseCursor(((odbc_db_t *) (dbi->dbconn))->stmnt);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#ifdef ISC_PLATFORM_USETHREADS
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* free lock on dbi so someone else can use it. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_mutex_unlock(&dbi->instance_lock);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#endif
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews return result;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews}
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews/*%
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * if the lookup function does not return SOA or NS records for the zone,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * use this function to get that information for Bind.
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrewsstatic isc_result_t
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrewsodbc_authority(const char *zone, void *driverarg, void *dbdata,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews dns_sdlzlookup_t *lookup)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews{
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_result_t result;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews dbinstance_t *dbi = NULL;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews UNUSED(driverarg);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* run the query and get the result set from the database. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = odbc_get_resultset(zone, NULL, NULL, AUTHORITY, dbdata, &dbi);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* if we get "not implemented", send it along */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (result == ISC_R_NOTIMPLEMENTED)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews return result;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* if we didn't get a result set, log an err msg. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (result != ISC_R_SUCCESS) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "Odbc driver unable to return "
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "result set for authority query");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews return (ISC_R_FAILURE);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* lookup and authority result sets are processed in the same manner */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* odbc_process_rs does the job for both functions. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews return odbc_process_rs(lookup, dbi);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews}
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews/*% if zone is supported, lookup up a (or multiple) record(s) in it */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrewsstatic isc_result_t
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrewsodbc_lookup(const char *zone, const char *name, void *driverarg,
793814f80703afdd69b59ade91e63efa81ae4178Evan Hunt void *dbdata, dns_sdlzlookup_t *lookup,
793814f80703afdd69b59ade91e63efa81ae4178Evan Hunt dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews{
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_result_t result;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews dbinstance_t *dbi = NULL;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews UNUSED(driverarg);
793814f80703afdd69b59ade91e63efa81ae4178Evan Hunt UNUSED(methods);
793814f80703afdd69b59ade91e63efa81ae4178Evan Hunt UNUSED(clientinfo);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* run the query and get the result set from the database. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = odbc_get_resultset(zone, name, NULL, LOOKUP, dbdata, &dbi);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* if we didn't get a result set, log an err msg. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (result != ISC_R_SUCCESS) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "Odbc driver unable to return "
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "result set for lookup query");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews return (ISC_R_FAILURE);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* lookup and authority result sets are processed in the same manner */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* odbc_process_rs does the job for both functions. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews return odbc_process_rs(lookup, dbi);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews}
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews/*%
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * create an instance of the driver. Remember, only 1 copy of the driver's
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * code is ever loaded, the driver has to remember which context it's
1425217e5c3a2cbab7f8344e600e0c16047289ffMark Andrews * operating in. This is done via use of the dbdata argument which is
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * passed into all query functions.
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrewsstatic isc_result_t
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrewsodbc_create(const char *dlzname, unsigned int argc, char *argv[],
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews void *driverarg, void **dbdata)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews{
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_result_t result;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews odbc_instance_t *odbc_inst = NULL;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews dbinstance_t *db = NULL;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews SQLRETURN sqlRes;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#ifdef ISC_PLATFORM_USETHREADS
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* if multi-threaded, we need a few extra variables. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews int dbcount;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews int i;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews char *endp;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#endif /* ISC_PLATFORM_USETHREADS */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews UNUSED(dlzname);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews UNUSED(driverarg);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#ifdef ISC_PLATFORM_USETHREADS
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* if debugging, let user know we are multithreaded. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1),
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "Odbc driver running multithreaded");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#else /* ISC_PLATFORM_USETHREADS */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* if debugging, let user know we are single threaded. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1),
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "Odbc driver running single threaded");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#endif /* ISC_PLATFORM_USETHREADS */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* verify we have at least 5 arg's passed to the driver */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (argc < 5) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "Odbc driver requires at least "
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "4 command line args.");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews return (ISC_R_FAILURE);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* no more than 8 arg's should be passed to the driver */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (argc > 8) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "Odbc driver cannot accept more than "
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "7 command line args.");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews return (ISC_R_FAILURE);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* multithreaded build can have multiple DB connections */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#ifdef ISC_PLATFORM_USETHREADS
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* check how many db connections we should create */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews dbcount = strtol(argv[1], &endp, 10);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (*endp != '\0' || dbcount < 0) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "Odbc driver database connection count "
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "must be positive.");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews return (ISC_R_FAILURE);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#endif /* ISC_PLATFORM_USETHREADS */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* allocate memory for odbc instance */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews odbc_inst = isc_mem_get(ns_g_mctx, sizeof(odbc_instance_t));
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (odbc_inst == NULL)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews return (ISC_R_NOMEMORY);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews memset(odbc_inst, 0, sizeof(odbc_instance_t));
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* parse connection string and get paramters. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* get odbc database dsn - required */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews odbc_inst->dsn = (SQLCHAR *) getParameterValue(argv[2],
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "dsn=");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (odbc_inst->dsn == NULL) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "odbc driver requires a dns parameter.");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = ISC_R_FAILURE;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews goto cleanup;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* get odbc database username */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* if no username was passed, set odbc_inst.user = NULL; */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews odbc_inst->user = (SQLCHAR *) getParameterValue(argv[2],
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "user=");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* get odbc database password */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* if no password was passed, set odbc_inst.pass = NULL; */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews odbc_inst->pass = (SQLCHAR *) getParameterValue(argv[2], "pass=");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* create odbc environment & set environment to ODBC V3 */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (odbc_inst->sql_env == NULL) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* create environment handle */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews sqlRes = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews &(odbc_inst->sql_env));
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (!sqlOK(sqlRes)) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews DNS_LOGMODULE_DLZ, ISC_LOG_INFO,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "Odbc driver unable to allocate memory");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = ISC_R_NOMEMORY;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews goto cleanup;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /*set ODBC version = 3 */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews sqlRes = SQLSetEnvAttr(odbc_inst->sql_env,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews SQL_ATTR_ODBC_VERSION,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews (void *) SQL_OV_ODBC3, 0);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (!sqlOK(sqlRes)) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews DNS_LOGMODULE_DLZ, ISC_LOG_INFO,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "Unable to configure ODBC environment");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = ISC_R_NOMEMORY;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews goto cleanup;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#ifdef ISC_PLATFORM_USETHREADS
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* allocate memory for database connection list */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews odbc_inst->db = isc_mem_get(ns_g_mctx, sizeof(db_list_t));
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (odbc_inst->db == NULL) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = ISC_R_NOMEMORY;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews goto cleanup;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* initialize DB connection list */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews ISC_LIST_INIT(*odbc_inst->db);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* create the appropriate number of database instances (DBI) */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* append each new DBI to the end of the list */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews for (i=0; i < dbcount; i++) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#endif /* ISC_PLATFORM_USETHREADS */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* how many queries were passed in from config file? */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews switch(argc) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews case 5:
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = build_sqldbinstance(ns_g_mctx, NULL, NULL,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews NULL, argv[3], argv[4],
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews NULL, &db);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews break;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews case 6:
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = build_sqldbinstance(ns_g_mctx, NULL, NULL,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews argv[5], argv[3], argv[4],
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews NULL, &db);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews break;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews case 7:
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = build_sqldbinstance(ns_g_mctx, argv[6], NULL,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews argv[5], argv[3], argv[4],
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews NULL, &db);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews break;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews case 8:
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = build_sqldbinstance(ns_g_mctx, argv[6],
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews argv[7], argv[5], argv[3],
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews argv[4], NULL, &db);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews break;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews default:
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* not really needed, should shut up compiler. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = ISC_R_FAILURE;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* unsuccessful?, log err msg and cleanup. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (result != ISC_R_SUCCESS) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "Odbc driver could not create "
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "database instance object.");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews goto cleanup;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#ifdef ISC_PLATFORM_USETHREADS
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* when multithreaded, build a list of DBI's */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews ISC_LINK_INIT(db, link);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews ISC_LIST_APPEND(*odbc_inst->db, db, link);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#endif
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = odbc_connect(odbc_inst, (odbc_db_t **) &(db->dbconn));
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (result != ISC_R_SUCCESS) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#ifdef ISC_PLATFORM_USETHREADS
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /*
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * if multi threaded, let user know which
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * connection failed. user could be
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * attempting to create 10 db connections and
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * for some reason the db backend only allows
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * 9.
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "Odbc driver failed to create database "
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "connection number %u after 3 attempts",
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews i+1);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#else
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "Odbc driver failed to create database "
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "connection after 3 attempts");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#endif
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews goto cleanup;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#ifdef ISC_PLATFORM_USETHREADS
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* set DB = null for next loop through. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews db = NULL;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews } /* end for loop */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#else
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* tell odbc_inst about the db connection we just created. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews odbc_inst->db = db;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#endif
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* set dbdata to the odbc_instance we created. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews *dbdata = odbc_inst;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* hey, we got through all of that ok, return success. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews return(ISC_R_SUCCESS);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews cleanup:
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews destroy_odbc_instance(odbc_inst);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews return result;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews}
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews/*%
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * destroy an instance of the driver. Remember, only 1 copy of the driver's
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * code is ever loaded, the driver has to remember which context it's
1425217e5c3a2cbab7f8344e600e0c16047289ffMark Andrews * operating in. This is done via use of the dbdata argument.
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * so we really only need to clean it up since we are not using driverarg.
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrewsstatic void
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrewsodbc_destroy(void *driverarg, void *dbdata)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews{
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews UNUSED(driverarg);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews destroy_odbc_instance((odbc_instance_t *) dbdata);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews}
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews/* pointers to all our runtime methods. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews/* this is used during driver registration */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews/* i.e. in dlz_odbc_init below. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrewsstatic dns_sdlzmethods_t dlz_odbc_methods = {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews odbc_create,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews odbc_destroy,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews odbc_findzone,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews odbc_lookup,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews odbc_authority,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews odbc_allnodes,
71bd858d8ed62672e7c23999dc7c02fd16a55089Evan Hunt odbc_allowzonexfr,
71bd858d8ed62672e7c23999dc7c02fd16a55089Evan Hunt NULL,
71bd858d8ed62672e7c23999dc7c02fd16a55089Evan Hunt NULL,
71bd858d8ed62672e7c23999dc7c02fd16a55089Evan Hunt NULL,
71bd858d8ed62672e7c23999dc7c02fd16a55089Evan Hunt NULL,
71bd858d8ed62672e7c23999dc7c02fd16a55089Evan Hunt NULL,
71bd858d8ed62672e7c23999dc7c02fd16a55089Evan Hunt NULL,
71bd858d8ed62672e7c23999dc7c02fd16a55089Evan Hunt NULL,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews};
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews/*%
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * Wrapper around dns_sdlzregister().
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrewsisc_result_t
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrewsdlz_odbc_init(void) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_result_t result;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /*
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * Write debugging message to log
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "Registering DLZ odbc driver.");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /*
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * Driver is always threadsafe. When multithreaded all
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * functions use multithreaded code. When not multithreaded,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * all functions can only be entered once, but only 1 thread
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * of operation is available in Bind. So everything is still
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * threadsafe.
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = dns_sdlzregister("odbc", &dlz_odbc_methods, NULL,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews DNS_SDLZFLAG_RELATIVEOWNER |
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews DNS_SDLZFLAG_RELATIVERDATA |
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews DNS_SDLZFLAG_THREADSAFE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews ns_g_mctx, &dlz_odbc);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* if we can't register the driver, there are big problems. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (result != ISC_R_SUCCESS) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews UNEXPECTED_ERROR(__FILE__, __LINE__,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "dns_sdlzregister() failed: %s",
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_result_totext(result));
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = ISC_R_UNEXPECTED;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews }
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews return result;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews}
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews/*%
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * Wrapper around dns_sdlzunregister().
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrewsvoid
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrewsdlz_odbc_clear(void) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /*
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * Write debugging message to log
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "Unregistering DLZ odbc driver.");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* unregister the driver. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (dlz_odbc != NULL)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews dns_sdlzunregister(&dlz_odbc);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews}
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#endif