/*%
 * create an instance of the driver.  Remember, only 1 copy of the driver's
 * code is ever loaded, the driver has to remember which context it's
 * operating in.  This is done via use of the dbdata argument which is
 * passed into all query functions.
 */
static isc_result_t
postgres_create(const char *dlzname, unsigned int argc, char *argv[],
		void *driverarg, void **dbdata)
{
	isc_result_t result;
	dbinstance_t *dbi = NULL;
	unsigned int j;

#ifdef ISC_PLATFORM_USETHREADS
	/* if multi-threaded, we need a few extra variables. */
	int dbcount;
	db_list_t *dblist = NULL;
	int i;
	char *endp;

#endif /* ISC_PLATFORM_USETHREADS */

	UNUSED(driverarg);
	UNUSED(dlzname);

/* seed random # generator */
	srand( (unsigned)time( NULL ) );


#ifdef ISC_PLATFORM_USETHREADS
	/* if debugging, let user know we are multithreaded. */
	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
		      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1),
		      "Postgres driver running multithreaded");
#else /* ISC_PLATFORM_USETHREADS */
	/* if debugging, let user know we are single threaded. */
	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
		      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1),
		      "Postgres driver running single threaded");
#endif /* ISC_PLATFORM_USETHREADS */

	/* verify we have at least 5 arg's passed to the driver */
	if (argc < 5) {
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
			      "Postgres driver requires at least "
			      "4 command line args.");
		return (ISC_R_FAILURE);
	}

	/* no more than 8 arg's should be passed to the driver */
	if (argc > 8) {
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
			      "Postgres driver cannot accept more than "
			      "7 command line args.");
		return (ISC_R_FAILURE);
	}

	/* multithreaded build can have multiple DB connections */
#ifdef ISC_PLATFORM_USETHREADS

	/* check how many db connections we should create */
	dbcount = strtol(argv[1], &endp, 10);
	if (*endp != '\0' || dbcount < 0) {
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
			      "Postgres driver database connection count "
			      "must be positive.");
		return (ISC_R_FAILURE);
	}

	/* allocate memory for database connection list */
	dblist = isc_mem_get(ns_g_mctx, sizeof(db_list_t));
	if (dblist == NULL)
		return (ISC_R_NOMEMORY);

	/* initialize DB connection list */
	ISC_LIST_INIT(*dblist);

	/*
	 * create the appropriate number of database instances (DBI)
	 * append each new DBI to the end of the list
	 */
	for (i=0; i < dbcount; i++) {

#endif /* ISC_PLATFORM_USETHREADS */

		/* how many queries were passed in from config file? */
		switch(argc) {
		case 5:
			result = build_sqldbinstance(ns_g_mctx, NULL, NULL,
						     NULL, argv[3], argv[4],
						     NULL, &dbi);
			break;
		case 6:
			result = build_sqldbinstance(ns_g_mctx, NULL, NULL,
						     argv[5], argv[3], argv[4],
						     NULL, &dbi);
			break;
		case 7:
			result = build_sqldbinstance(ns_g_mctx, argv[6], NULL,
						     argv[5], argv[3], argv[4],
						     NULL, &dbi);
			break;
		case 8:
			result = build_sqldbinstance(ns_g_mctx, argv[6],
						     argv[7], argv[5], argv[3],
						     argv[4], NULL, &dbi);
			break;
		default:
			/* not really needed, should shut up compiler. */
			result = ISC_R_FAILURE;
		}


		if (result == ISC_R_SUCCESS) {
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
				      "Postgres driver created database "
				      "instance object.");
		} else { /* unsuccessful?, log err msg and cleanup. */
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
				      "Postgres driver could not create "
				      "database instance object.");
			goto cleanup;
		}

#ifdef ISC_PLATFORM_USETHREADS

		/* when multithreaded, build a list of DBI's */
		ISC_LINK_INIT(dbi, link);
		ISC_LIST_APPEND(*dblist, dbi, link);

#endif

		/* create and set db connection */
		dbi->dbconn = PQconnectdb(argv[2]);
		/*
		 * if db connection cannot be created, log err msg and
		 * cleanup.
		 */
		if (dbi->dbconn == NULL) {
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
				      "Postgres driver could not allocate "
				      "memory for database connection");
			goto cleanup;
		}

		/* if we cannot connect the first time, try 3 more times. */
		for (j = 0;
		     PQstatus((PGconn *) dbi->dbconn) != CONNECTION_OK &&
			     j < 3;
		     j++)
			PQreset((PGconn *) dbi->dbconn);


#ifdef ISC_PLATFORM_USETHREADS

		/*
		 * if multi threaded, let user know which connection
		 * failed.  user could be attempting to create 10 db
		 * connections and for some reason the db backend only
		 * allows 9
		 */
		if (PQstatus((PGconn *) dbi->dbconn) != CONNECTION_OK) {
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
				      "Postgres driver failed to create "
				      "database connection number %u "
				      "after 4 attempts",
				      i + 1);
			goto cleanup;
		}

		/* set DBI = null for next loop through. */
		dbi = NULL;
	}	/* end for loop */

		/* set dbdata to the list we created. */
	*dbdata = dblist;

#else /* ISC_PLATFORM_USETHREADS */
	/* if single threaded, just let user know we couldn't connect. */
	if (PQstatus((PGconn *) dbi->dbconn) != CONNECTION_OK) {
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
			      "Postgres driver failed to create database "
			      "connection after 4 attempts");
		goto cleanup;
	}

	/*
	 * single threaded build can only use 1 db connection, return
	 * it via dbdata
	 */
	*dbdata = dbi;

#endif /* ISC_PLATFORM_USETHREADS */

	/* hey, we got through all of that ok, return success. */
	return(ISC_R_SUCCESS);

 cleanup:

#ifdef ISC_PLATFORM_USETHREADS
	/*
	 * if multithreaded, we could fail because only 1 connection
	 * couldn't be made.  We should cleanup the other successful
	 * connections properly.
	 */
	postgres_destroy_dblist(dblist);

#else /* ISC_PLATFORM_USETHREADS */
	if (dbi != NULL)
		destroy_sqldbinstance(dbi);

#endif /* ISC_PLATFORM_USETHREADS */
	return(ISC_R_FAILURE);
}
/*%
 * create an instance of the driver.  Remember, only 1 copy of the driver's
 * code is ever loaded, the driver has to remember which context it's
 * operating in.  This is done via use of the dbdata argument which is
 * passed into all query functions.
 */
static isc_result_t
odbc_create(const char *dlzname, unsigned int argc, char *argv[],
	    void *driverarg, void **dbdata)
{
	isc_result_t result;
	odbc_instance_t *odbc_inst = NULL;
	dbinstance_t *db = NULL;
	SQLRETURN sqlRes;

#ifdef ISC_PLATFORM_USETHREADS
	/* if multi-threaded, we need a few extra variables. */
	int dbcount;
	int i;
	char *endp;

#endif /* ISC_PLATFORM_USETHREADS */

	UNUSED(dlzname);
	UNUSED(driverarg);

#ifdef ISC_PLATFORM_USETHREADS
	/* if debugging, let user know we are multithreaded. */
	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
		      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1),
		      "Odbc driver running multithreaded");
#else /* ISC_PLATFORM_USETHREADS */
	/* if debugging, let user know we are single threaded. */
	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
		      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1),
		      "Odbc driver running single threaded");
#endif /* ISC_PLATFORM_USETHREADS */

	/* verify we have at least 5 arg's passed to the driver */
	if (argc < 5) {
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
			      "Odbc driver requires at least "
			      "4 command line args.");
		return (ISC_R_FAILURE);
	}

	/* no more than 8 arg's should be passed to the driver */
	if (argc > 8) {
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
			      "Odbc driver cannot accept more than "
			      "7 command line args.");
		return (ISC_R_FAILURE);
	}

	/* multithreaded build can have multiple DB connections */
#ifdef ISC_PLATFORM_USETHREADS

	/* check how many db connections we should create */
	dbcount = strtol(argv[1], &endp, 10);
	if (*endp != '\0' || dbcount < 0) {
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
			      "Odbc driver database connection count "
			      "must be positive.");
		return (ISC_R_FAILURE);
	}

#endif /* ISC_PLATFORM_USETHREADS */

	/* allocate memory for odbc instance */
	odbc_inst = isc_mem_get(ns_g_mctx, sizeof(odbc_instance_t));
	if (odbc_inst == NULL)
		return (ISC_R_NOMEMORY);
	memset(odbc_inst, 0, sizeof(odbc_instance_t));

	/* parse connection string and get paramters. */

	/* get odbc database dsn - required */
	odbc_inst->dsn = (SQLCHAR *) getParameterValue(argv[2],
						       "dsn=");
	if (odbc_inst->dsn == NULL) {
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
			      "odbc driver requires a dns parameter.");
		result = ISC_R_FAILURE;
		goto cleanup;
	}
	/* get odbc database username */
	/* if no username was passed, set odbc_inst.user = NULL; */
	odbc_inst->user = (SQLCHAR *) getParameterValue(argv[2],
							"user="******"pass="******"Odbc driver unable to allocate memory");
			result = ISC_R_NOMEMORY;
			goto cleanup;
		}
		/*set ODBC version = 3 */
		sqlRes = SQLSetEnvAttr(odbc_inst->sql_env,
				       SQL_ATTR_ODBC_VERSION,
				       (void *) SQL_OV_ODBC3, 0);
		if (!sqlOK(sqlRes)) {
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_INFO,
				      "Unable to configure ODBC environment");
			result = ISC_R_NOMEMORY;
			goto cleanup;
		}
	}

#ifdef ISC_PLATFORM_USETHREADS

	/* allocate memory for database connection list */
	odbc_inst->db = isc_mem_get(ns_g_mctx, sizeof(db_list_t));
	if (odbc_inst->db == NULL) {
		result = ISC_R_NOMEMORY;
		goto cleanup;
	}


	/* initialize DB connection list */
	ISC_LIST_INIT(*odbc_inst->db);

	/* create the appropriate number of database instances (DBI) */
	/* append each new DBI to the end of the list */
	for (i=0; i < dbcount; i++) {

#endif /* ISC_PLATFORM_USETHREADS */

		/* how many queries were passed in from config file? */
		switch(argc) {
		case 5:
			result = build_sqldbinstance(ns_g_mctx, NULL, NULL,
						     NULL, argv[3], argv[4],
						     NULL, &db);
			break;
		case 6:
			result = build_sqldbinstance(ns_g_mctx, NULL, NULL,
						     argv[5], argv[3], argv[4],
						     NULL, &db);
			break;
		case 7:
			result = build_sqldbinstance(ns_g_mctx, argv[6], NULL,
						     argv[5], argv[3], argv[4],
						     NULL, &db);
			break;
		case 8:
			result = build_sqldbinstance(ns_g_mctx, argv[6],
						     argv[7], argv[5], argv[3],
						     argv[4], NULL, &db);
			break;
		default:
			/* not really needed, should shut up compiler. */
			result = ISC_R_FAILURE;
		}

		/* unsuccessful?, log err msg and cleanup. */
		if (result != ISC_R_SUCCESS) {
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
				      "Odbc driver could not create "
				      "database instance object.");
			goto cleanup;
		}

#ifdef ISC_PLATFORM_USETHREADS

		/* when multithreaded, build a list of DBI's */
		ISC_LINK_INIT(db, link);
		ISC_LIST_APPEND(*odbc_inst->db, db, link);

#endif

		result = odbc_connect(odbc_inst, (odbc_db_t **) &(db->dbconn));

		if (result != ISC_R_SUCCESS) {

#ifdef ISC_PLATFORM_USETHREADS

			/*
			 * if multi threaded, let user know which
			 * connection failed.  user could be
			 * attempting to create 10 db connections and
			 * for some reason the db backend only allows
			 * 9.
			 */
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
				      "Odbc driver failed to create database "
				      "connection number %u after 3 attempts",
				      i+1);
#else
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
				      "Odbc driver failed to create database "
				      "connection after 3 attempts");
#endif
			goto cleanup;
		}

#ifdef ISC_PLATFORM_USETHREADS

		/* set DB = null for next loop through. */
		db = NULL;

	}	/* end for loop */

#else
	/* tell odbc_inst about the db connection we just created. */
	odbc_inst->db = db;

#endif

	/* set dbdata to the odbc_instance we created. */
	*dbdata = odbc_inst;

	/* hey, we got through all of that ok, return success. */
	return(ISC_R_SUCCESS);

 cleanup:

	destroy_odbc_instance(odbc_inst);

	return result;
}
/*%
 * create an instance of the driver.  Remember, only 1 copy of the driver's
 * code is ever loaded, the driver has to remember which context it's
 * operating in.  This is done via use of the dbdata argument which is
 * passed into all query functions.
 */
static isc_result_t
mysql_create(const char *dlzname, unsigned int argc, char *argv[],
	     void *driverarg, void **dbdata)
{
	isc_result_t result;
	dbinstance_t *dbi = NULL;
	char *tmp = NULL;
	char *dbname = NULL;
	char *host = NULL;
	char *user = NULL;
	char *pass = NULL;
	char *socket = NULL;
	int port;
	MYSQL *dbc;
	char *endp;
	int j;
	unsigned int flags = 0;
#if MYSQL_VERSION_ID >= 50000
        my_bool auto_reconnect = 1;
#endif

	UNUSED(driverarg);
	UNUSED(dlzname);

	/* verify we have at least 4 arg's passed to the driver */
	if (argc < 4) {
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
			      "mysql driver requires "
			      "at least 4 command line args.");
		return (ISC_R_FAILURE);
	}

	/* no more than 8 arg's should be passed to the driver */
	if (argc > 8) {
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
			      "mysql driver cannot accept "
			      "more than 7 command line args.");
		return (ISC_R_FAILURE);
	}

	/* parse connection string and get paramters. */

	/* get db name - required */
	dbname = getParameterValue(argv[1], "dbname=");
	if (dbname == NULL) {
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
			      "mysql driver requires a dbname parameter.");
		result = ISC_R_FAILURE;
		goto full_cleanup;
	}

	/* get db port.  Not required, but must be > 0 if specified */
	tmp = getParameterValue(argv[1], "port=");
	if (tmp == NULL) {
		port = 0;
	} else {
		port = strtol(tmp, &endp, 10);
		if (*endp != '\0' || port < 0) {
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
				      "Mysql driver port "
				      "must be a positive number.");
			isc_mem_free(ns_g_mctx, tmp);
			result = ISC_R_FAILURE;
			goto full_cleanup;
		}
		isc_mem_free(ns_g_mctx, tmp);
	}

	/* how many queries were passed in from config file? */
	switch(argc) {
	case 4:
		result = build_sqldbinstance(ns_g_mctx, NULL, NULL, NULL,
					     argv[2], argv[3], NULL, &dbi);
		break;
	case 5:
		result = build_sqldbinstance(ns_g_mctx, NULL, NULL, argv[4],
					     argv[2], argv[3], NULL, &dbi);
		break;
	case 6:
		result = build_sqldbinstance(ns_g_mctx, argv[5], NULL, argv[4],
					     argv[2], argv[3], NULL, &dbi);
		break;
	case 7:
		result = build_sqldbinstance(ns_g_mctx, argv[5],
					     argv[6], argv[4],
					     argv[2], argv[3], NULL, &dbi);
		break;
	case 8:
		result = build_sqldbinstance(ns_g_mctx, argv[5],
					     argv[6], argv[4],
					     argv[2], argv[3], argv[7], &dbi);
		break;
	default:
		/* not really needed, should shut up compiler. */
		result = ISC_R_FAILURE;
	}

	/* unsuccessful?, log err msg and cleanup. */
	if (result != ISC_R_SUCCESS) {
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
			      "mysql driver could not create "
			      "database instance object.");
		result = ISC_R_FAILURE;
		goto cleanup;
	}

	/* create and set db connection */
	dbi->dbconn = mysql_init(NULL);

	/* if db connection cannot be created, log err msg and cleanup. */
	if (dbi->dbconn == NULL) {
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
			      "mysql driver could not allocate "
			      "memory for database connection");
		result = ISC_R_FAILURE;
		goto full_cleanup;
	}

	tmp = getParameterValue(argv[1], "compress=");
	if (tmp != NULL) {
		if (strcasecmp(tmp, "true") == 0)
			flags = CLIENT_COMPRESS;
		isc_mem_free(ns_g_mctx, tmp);
	}

	tmp = getParameterValue(argv[1], "ssl=");
	if (tmp != NULL) {
		if (strcasecmp(tmp, "true") == 0)
			flags = flags | CLIENT_SSL;
		isc_mem_free(ns_g_mctx, tmp);
	}

	tmp = getParameterValue(argv[1], "space=");
	if (tmp != NULL) {
		if (strcasecmp(tmp, "ignore") == 0)
			flags = flags | CLIENT_IGNORE_SPACE;
		isc_mem_free(ns_g_mctx, tmp);
	}

	dbc = NULL;
	host = getParameterValue(argv[1], "host=");
	user = getParameterValue(argv[1], "user="******"pass="******"socket=");

#if MYSQL_VERSION_ID >= 50000
	/* enable automatic reconnection. */
        if (mysql_options((MYSQL *) dbi->dbconn, MYSQL_OPT_RECONNECT,
			  &auto_reconnect) != 0) {
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_WARNING,
			      "mysql driver failed to set "
			      "MYSQL_OPT_RECONNECT option, continuing");
	}
#endif

	for (j=0; dbc == NULL && j < 4; j++)
		dbc = mysql_real_connect((MYSQL *) dbi->dbconn, host,
					 user, pass, dbname, port, socket,
					 flags);

	/* let user know if we couldn't connect. */
	if (dbc == NULL) {
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
			      "mysql driver failed to create "
			      "database connection after 4 attempts");
		result = ISC_R_FAILURE;
		goto full_cleanup;
	}

	/* return db connection via dbdata */
	*dbdata = dbi;

	result = ISC_R_SUCCESS;
	goto cleanup;

 full_cleanup:

	destroy_sqldbinstance(dbi);

 cleanup:

	if (dbname != NULL)
		isc_mem_free(ns_g_mctx, dbname);
	if (host != NULL)
		isc_mem_free(ns_g_mctx, host);
	if (user != NULL)
		isc_mem_free(ns_g_mctx, user);
	if (pass != NULL)
		isc_mem_free(ns_g_mctx, pass);
	if (socket != NULL)
		isc_mem_free(ns_g_mctx, socket);


	return result;
}
Exemple #4
0
static isc_result_t
dlz_ldap_create(const char *dlzname, unsigned int argc, char *argv[],
		void *driverarg, void **dbdata)
{
	isc_result_t result;
	ldap_instance_t *ldap_inst = NULL;
	dbinstance_t *dbi = NULL;
	int protocol;
	int method;

#ifdef ISC_PLATFORM_USETHREADS
	/* if multi-threaded, we need a few extra variables. */
	int dbcount;
	char *endp;
/* db_list_t *dblist = NULL; */
	int i;

#endif /* ISC_PLATFORM_USETHREADS */

	UNUSED(dlzname);
	UNUSED(driverarg);

#ifdef ISC_PLATFORM_USETHREADS
	/* if debugging, let user know we are multithreaded. */
	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
		      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1),
		      "LDAP driver running multithreaded");
#else /* ISC_PLATFORM_USETHREADS */
	/* if debugging, let user know we are single threaded. */
	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
		      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1),
		      "LDAP driver running single threaded");
#endif /* ISC_PLATFORM_USETHREADS */

	if (argc < 9) {
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
			      "LDAP driver requires at least "
			      "8 command line args.");
		return (ISC_R_FAILURE);
	}

	/* no more than 13 arg's should be passed to the driver */
	if (argc > 12) {
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
			      "LDAP driver cannot accept more than "
			      "11 command line args.");
		return (ISC_R_FAILURE);
	}

	/* determine protocol version. */
	if (strncasecmp(argv[2], V2, strlen(V2)) == 0) {
		protocol = 2;
	} else if (strncasecmp(argv[2], V3, strlen(V3)) == 0) {
		protocol = 3;
	} else {
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
			      "LDAP driver protocol must be either %s or %s",
			      V2, V3);
		return (ISC_R_FAILURE);
	}

	/* determine connection method. */
	if (strncasecmp(argv[3], SIMPLE, strlen(SIMPLE)) == 0) {
		method = LDAP_AUTH_SIMPLE;
	} else if (strncasecmp(argv[3], KRB41, strlen(KRB41)) == 0) {
		method = LDAP_AUTH_KRBV41;
	} else if (strncasecmp(argv[3], KRB42, strlen(KRB42)) == 0) {
		method = LDAP_AUTH_KRBV42;
	} else {
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
			      "LDAP driver authentication method must be "
			      "one of %s, %s or %s",
			      SIMPLE, KRB41, KRB42);
		return (ISC_R_FAILURE);
	}

	/* multithreaded build can have multiple DB connections */
#ifdef ISC_PLATFORM_USETHREADS

	/* check how many db connections we should create */
	dbcount = strtol(argv[1], &endp, 10);
	if (*endp != '\0' || dbcount < 0) {
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
			      "LDAP driver database connection count "
			      "must be positive.");
		return (ISC_R_FAILURE);
	}
#endif

	/* check that LDAP URL parameters make sense */
	switch(argc) {
	case 12:
		result = dlz_ldap_checkURL(argv[11], 0, "allow zone transfer");
		if (result != ISC_R_SUCCESS)
			return (result);
	case 11:
		result = dlz_ldap_checkURL(argv[10], 3, "all nodes");
		if (result != ISC_R_SUCCESS)
			return (result);
	case 10:
		if (strlen(argv[9]) > 0) {
			result = dlz_ldap_checkURL(argv[9], 3, "authority");
			if (result != ISC_R_SUCCESS)
				return (result);
		}
	case 9:
		result = dlz_ldap_checkURL(argv[8], 3, "lookup");
		if (result != ISC_R_SUCCESS)
			return (result);
		result = dlz_ldap_checkURL(argv[7], 0, "find zone");
		if (result != ISC_R_SUCCESS)
			return (result);
		break;
	default:
		/* not really needed, should shut up compiler. */
		result = ISC_R_FAILURE;
	}

	/* allocate memory for LDAP instance */
	ldap_inst = isc_mem_get(ns_g_mctx, sizeof(ldap_instance_t));
	if (ldap_inst == NULL)
		return (ISC_R_NOMEMORY);
	memset(ldap_inst, 0, sizeof(ldap_instance_t));

	/* store info needed to automatically re-connect. */
	ldap_inst->protocol = protocol;
	ldap_inst->method = method;
	ldap_inst->hosts = isc_mem_strdup(ns_g_mctx, argv[6]);
	if (ldap_inst->hosts == NULL) {
		result = ISC_R_NOMEMORY;
		goto cleanup;
	}
	ldap_inst->user = isc_mem_strdup(ns_g_mctx, argv[4]);
	if (ldap_inst->user == NULL) {
		result = ISC_R_NOMEMORY;
		goto cleanup;
	}
	ldap_inst->cred = isc_mem_strdup(ns_g_mctx, argv[5]);
	if (ldap_inst->cred == NULL) {
		result = ISC_R_NOMEMORY;
		goto cleanup;
	}

#ifdef ISC_PLATFORM_USETHREADS
	/* allocate memory for database connection list */
	ldap_inst->db = isc_mem_get(ns_g_mctx, sizeof(db_list_t));
	if (ldap_inst->db == NULL) {
		result = ISC_R_NOMEMORY;
		goto cleanup;
	}

	/* initialize DB connection list */
	ISC_LIST_INIT(*(ldap_inst->db));

	/*
	 * create the appropriate number of database instances (DBI)
	 * append each new DBI to the end of the list
	 */
	for (i = 0; i < dbcount; i++) {

#endif /* ISC_PLATFORM_USETHREADS */

		/* how many queries were passed in from config file? */
		switch(argc) {
		case 9:
			result = build_sqldbinstance(ns_g_mctx, NULL, NULL,
						     NULL, argv[7], argv[8],
						     NULL, &dbi);
			break;
		case 10:
			result = build_sqldbinstance(ns_g_mctx, NULL, NULL,
						     argv[9], argv[7], argv[8],
						     NULL, &dbi);
			break;
		case 11:
			result = build_sqldbinstance(ns_g_mctx, argv[10], NULL,
						     argv[9], argv[7], argv[8],
						     NULL, &dbi);
			break;
		case 12:
			result = build_sqldbinstance(ns_g_mctx, argv[10],
						     argv[11], argv[9],
						     argv[7], argv[8],
						     NULL, &dbi);
			break;
		default:
			/* not really needed, should shut up compiler. */
			result = ISC_R_FAILURE;
		}

		if (result == ISC_R_SUCCESS) {
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
				      "LDAP driver created "
				      "database instance object.");
		} else { /* unsuccessful?, log err msg and cleanup. */
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
				      "LDAP driver could not create "
				      "database instance object.");
			goto cleanup;
		}

#ifdef ISC_PLATFORM_USETHREADS
		/* when multithreaded, build a list of DBI's */
		ISC_LINK_INIT(dbi, link);
		ISC_LIST_APPEND(*(ldap_inst->db), dbi, link);
#else
		/*
		 * when single threaded, hold onto the one connection
		 * instance.
		 */
		ldap_inst->db = dbi;

#endif
		/* attempt to connect */
		result = dlz_ldap_connect(ldap_inst, dbi);

		/*
		 * if db connection cannot be created, log err msg and
		 * cleanup.
		 */
		switch(result) {
			/* success, do nothing */
		case ISC_R_SUCCESS:
			break;
			/*
			 * no memory means ldap_init could not
			 * allocate memory
			 */
		case ISC_R_NOMEMORY:
#ifdef ISC_PLATFORM_USETHREADS
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
				      "LDAP driver could not allocate memory "
				      "for connection number %u",
				      i+1);
#else
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
				      "LDAP driver could not allocate memory "
				      "for connection");
#endif
			goto cleanup;
			break;
			/*
			 * no perm means ldap_set_option could not set
			 * protocol version
			 */
		case ISC_R_NOPERM:
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
				      "LDAP driver could not "
				      "set protocol version.");
			result = ISC_R_FAILURE;
			goto cleanup;
			break;
			/* failure means couldn't connect to ldap server */
		case ISC_R_FAILURE:
#ifdef ISC_PLATFORM_USETHREADS
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
				      "LDAP driver could not "
				      "bind connection number %u to server.",
				      i+1);
#else
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
				      "LDAP driver could not "
				      "bind connection to server.");
#endif
			goto cleanup;
			break;
			/*
			 * default should never happen.  If it does,
			 * major errors.
			 */
		default:
			UNEXPECTED_ERROR(__FILE__, __LINE__,
					 "dlz_ldap_create() failed: %s",
					 isc_result_totext(result));
			result = ISC_R_UNEXPECTED;
			goto cleanup;
			break;
		} /* end switch(result) */


#ifdef ISC_PLATFORM_USETHREADS

		/* set DBI = null for next loop through. */
		dbi = NULL;
	}	/* end for loop */

#endif /* ISC_PLATFORM_USETHREADS */


	/* set dbdata to the ldap_instance we created. */
	*dbdata = ldap_inst;

	/* hey, we got through all of that ok, return success. */
	return(ISC_R_SUCCESS);

 cleanup:
	dlz_ldap_destroy(NULL, ldap_inst);

	return(ISC_R_FAILURE);
}