static void tx_sde(isc_task_t *task, isc_event_t *event) { isc_result_t isc_result; UNUSED(task); UNUSED(event); /* * Signal shutdown processing complete. */ isc_result = isc_mutex_lock(&Tx_mx); if (isc_result != ISC_R_SUCCESS) { t_info("isc_mutex_lock failed %s\n", isc_result_totext(isc_result)); ++Tx_nprobs; } isc_result = isc_condition_signal(&Tx_cv); if (isc_result != ISC_R_SUCCESS) { t_info("isc_condition_signal failed %s\n", isc_result_totext(isc_result)); ++Tx_nprobs; } isc_result = isc_mutex_unlock(&Tx_mx); if (isc_result != ISC_R_SUCCESS) { t_info("isc_mutex_unlock failed %s\n", isc_result_totext(isc_result)); ++Tx_nprobs; } isc_event_free(&event); }
static void t5_start_event(isc_task_t *task, isc_event_t *event) { isc_result_t isc_result; UNUSED(task); t_info("t5_start_event\n"); isc_result = isc_mutex_lock(&T5_mx); if (isc_result != ISC_R_SUCCESS) { t_info("isc_mutex_lock failed %s\n", isc_result_totext(isc_result)); ++T5_nprobs; } while (! T5_startflag) { (void) isc_condition_wait(&T5_cv, &T5_mx); } isc_result = isc_mutex_unlock(&T5_mx); if (isc_result != ISC_R_SUCCESS) { t_info("isc_mutex_unlock failed %s\n", isc_result_totext(isc_result)); ++T5_nprobs; } isc_event_free(&event); }
static isc_result_t odbc_findzone(void *driverarg, void *dbdata, const char *name) { isc_result_t result; dbinstance_t *dbi = NULL; UNUSED(driverarg); /* run the query and get the result set from the database. */ /* if result != ISC_R_SUCCESS cursor and mutex already cleaned up. */ /* so we don't have to do it here. */ result = odbc_get_resultset(name, NULL, NULL, FINDZONE, dbdata, &dbi); /* Check that we got a result set with data */ if (result == ISC_R_SUCCESS && !sqlOK(SQLFetch(((odbc_db_t *) (dbi->dbconn))->stmnt))) { result = ISC_R_NOTFOUND; } if (dbi != NULL) { /* get rid of result set, we are done with it. */ SQLCloseCursor(((odbc_db_t *) (dbi->dbconn))->stmnt); #ifdef ISC_PLATFORM_USETHREADS /* free lock on dbi so someone else can use it. */ isc_mutex_unlock(&dbi->instance_lock); #endif } return result; }
/*% Determine if the client is allowed to perform a zone transfer */ static isc_result_t odbc_allowzonexfr(void *driverarg, void *dbdata, const char *name, const char *client) { isc_result_t result; dbinstance_t *dbi = NULL; UNUSED(driverarg); /* first check if the zone is supported by the database. */ result = odbc_findzone(driverarg, dbdata, name); if (result != ISC_R_SUCCESS) return (ISC_R_NOTFOUND); /* * if we get to this point we know the zone is supported by * the database. the only questions now are is the zone * transfer is allowed for this client and did the config file * have an allow zone xfr query * * Run our query, and get a result set from the database. if * result != ISC_R_SUCCESS cursor and mutex already cleaned * up, so we don't have to do it here. */ result = odbc_get_resultset(name, NULL, client, ALLOWXFR, dbdata, &dbi); /* if we get "not implemented", send it along. */ if (result == ISC_R_NOTIMPLEMENTED) return result; /* Check that we got a result set with data */ if (result == ISC_R_SUCCESS && !sqlOK(SQLFetch(((odbc_db_t *) (dbi->dbconn))->stmnt))) { result = ISC_R_NOPERM; } if (dbi != NULL) { /* get rid of result set, we are done with it. */ SQLCloseCursor(((odbc_db_t *) (dbi->dbconn))->stmnt); #ifdef ISC_PLATFORM_USETHREADS /* free lock on dbi so someone else can use it. */ isc_mutex_unlock(&dbi->instance_lock); #endif } return result; }
static void t5_once_event(isc_task_t *task, isc_event_t *event) { isc_result_t isc_result; t_info("t5_once_event\n"); /* * Allow task1 to start processing events. */ isc_result = isc_mutex_lock(&T5_mx); if (isc_result != ISC_R_SUCCESS) { t_info("isc_mutex_lock failed %s\n", isc_result_totext(isc_result)); ++T5_nprobs; } T5_startflag = 1; isc_result = isc_condition_broadcast(&T5_cv); if (isc_result != ISC_R_SUCCESS) { t_info("isc_condition_broadcast failed %s\n", isc_result_totext(isc_result)); ++T5_nprobs; } isc_result = isc_mutex_unlock(&T5_mx); if (isc_result != ISC_R_SUCCESS) { t_info("isc_mutex_unlock failed %s\n", isc_result_totext(isc_result)); ++T5_nprobs; } isc_event_free(&event); isc_task_shutdown(task); }
static inline void CUNLOCK(void) { RUNTIME_CHECK(isc_mutex_unlock(&client_lock) == ISC_R_SUCCESS); }
/*% * This function is the real core of the driver. Zone, record * and client strings are passed in (or NULL is passed if the * string is not available). The type of query we want to run * is indicated by the query flag, and the dbdata object is passed * passed in to. dbdata really holds either: * 1) a list of database instances (in multithreaded mode) OR * 2) a single database instance (in single threaded mode) * The function will construct the query and obtain an available * database instance (DBI). It will then run the query and hopefully * obtain a result set. Postgres is nice, in that once the result * set is returned, we can make the db connection available for another * thread to use, while this thread continues on. So, the DBI is made * available ASAP by unlocking the instance_lock after we have cleaned * it up properly. */ static isc_result_t postgres_get_resultset(const char *zone, const char *record, const char *client, unsigned int query, void *dbdata, PGresult **rs) { isc_result_t result; dbinstance_t *dbi = NULL; char *querystring = NULL; unsigned int i = 0; unsigned int j = 0; /* temporarily get a unique thread # */ unsigned int dlz_thread_num = 1+(int) (1000.0*rand()/(RAND_MAX+1.0)); REQUIRE(*rs == NULL); #if 0 /* temporary logging message */ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_ERROR, "%d Getting DBI", dlz_thread_num); #endif /* get db instance / connection */ #ifdef ISC_PLATFORM_USETHREADS /* find an available DBI from the list */ dbi = postgres_find_avail_conn((db_list_t *) dbdata); #else /* ISC_PLATFORM_USETHREADS */ /* * only 1 DBI - no need to lock instance lock either * only 1 thread in the whole process, no possible contention. */ dbi = (dbinstance_t *) dbdata; #endif /* ISC_PLATFORM_USETHREADS */ #if 0 /* temporary logging message */ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_ERROR, "%d Got DBI - checking query", dlz_thread_num); #endif /* if DBI is null, can't do anything else */ if (dbi == NULL) { result = ISC_R_FAILURE; goto cleanup; } /* what type of query are we going to run? */ switch(query) { case ALLNODES: /* * if the query was not passed in from the config file * then we can't run it. return not_implemented, so * it's like the code for that operation was never * built into the driver.... AHHH flexibility!!! */ if (dbi->allnodes_q == NULL) { result = ISC_R_NOTIMPLEMENTED; goto cleanup; } break; case ALLOWXFR: /* same as comments as ALLNODES */ if (dbi->allowxfr_q == NULL) { result = ISC_R_NOTIMPLEMENTED; goto cleanup; } break; case AUTHORITY: /* same as comments as ALLNODES */ if (dbi->authority_q == NULL) { result = ISC_R_NOTIMPLEMENTED; goto cleanup; } break; case FINDZONE: /* this is required. It's the whole point of DLZ! */ if (dbi->findzone_q == NULL) { isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2), "No query specified for findzone. " "Findzone requires a query"); result = ISC_R_FAILURE; goto cleanup; } break; case LOOKUP: /* this is required. It's also a major point of DLZ! */ if (dbi->lookup_q == NULL) { isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2), "No query specified for lookup. " "Lookup requires a query"); result = ISC_R_FAILURE; goto cleanup; } break; default: /* * this should never happen. If it does, the code is * screwed up! */ UNEXPECTED_ERROR(__FILE__, __LINE__, "Incorrect query flag passed to " "postgres_get_resultset"); result = ISC_R_UNEXPECTED; goto cleanup; } #if 0 /* temporary logging message */ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_ERROR, "%d checked query", dlz_thread_num); #endif /* * was a zone string passed? If so, make it safe for use in * queries. */ if (zone != NULL) { dbi->zone = postgres_escape_string(zone); if (dbi->zone == NULL) { result = ISC_R_NOMEMORY; goto cleanup; } } else { /* no string passed, set the string pointer to NULL */ dbi->zone = NULL; } #if 0 /* temporary logging message */ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_ERROR, "%d did zone", dlz_thread_num); #endif /* * was a record string passed? If so, make it safe for use in * queries. */ if (record != NULL) { dbi->record = postgres_escape_string(record); if (dbi->record == NULL) { result = ISC_R_NOMEMORY; goto cleanup; } } else { /* no string passed, set the string pointer to NULL */ dbi->record = NULL; } #if 0 /* temporary logging message */ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_ERROR, "%d did record", dlz_thread_num); #endif /* * was a client string passed? If so, make it safe for use in * queries. */ if (client != NULL) { dbi->client = postgres_escape_string(client); if (dbi->client == NULL) { result = ISC_R_NOMEMORY; goto cleanup; } } else { /* no string passed, set the string pointer to NULL */ dbi->client = NULL; } #if 0 /* temporary logging message */ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_ERROR, "%d did client", dlz_thread_num); #endif /* * what type of query are we going to run? * this time we build the actual query to run. */ switch(query) { case ALLNODES: querystring = build_querystring(ns_g_mctx, dbi->allnodes_q); break; case ALLOWXFR: querystring = build_querystring(ns_g_mctx, dbi->allowxfr_q); break; case AUTHORITY: querystring = build_querystring(ns_g_mctx, dbi->authority_q); break; case FINDZONE: querystring = build_querystring(ns_g_mctx, dbi->findzone_q); break; case LOOKUP: querystring = build_querystring(ns_g_mctx, dbi->lookup_q); break; default: /* * this should never happen. If it does, the code is * screwed up! */ UNEXPECTED_ERROR(__FILE__, __LINE__, "Incorrect query flag passed to " "postgres_get_resultset"); result = ISC_R_UNEXPECTED; goto cleanup; } #if 0 /* temporary logging message */ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_ERROR, "%d built query", dlz_thread_num); #endif /* if the querystring is null, Bummer, outta RAM. UPGRADE TIME!!! */ if (querystring == NULL) { result = ISC_R_NOMEMORY; goto cleanup; } #if 0 /* temporary logging message */ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_ERROR, "%d query is '%s'", dlz_thread_num, querystring); #endif /* * output the full query string during debug so we can see * what lame error the query has. */ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1), "\nQuery String: %s\n", querystring); /* attempt query up to 3 times. */ for (j=0; j < 3; j++) { #if 0 /* temporary logging message */ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_ERROR, "%d executing query for %d time", dlz_thread_num, j); #endif /* try to get result set */ *rs = PQexec((PGconn *)dbi->dbconn, querystring ); result = ISC_R_SUCCESS; /* * if result set is null, reset DB connection, max 3 * attempts. */ for (i=0; *rs == NULL && i < 3; i++) { #if 0 /* temporary logging message */ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_ERROR, "%d resetting connection", dlz_thread_num); #endif result = ISC_R_FAILURE; PQreset((PGconn *) dbi->dbconn); /* connection ok, break inner loop */ if (PQstatus((PGconn *) dbi->dbconn) == CONNECTION_OK) break; } /* result set ok, break outter loop */ if (PQresultStatus(*rs) == PGRES_TUPLES_OK) { #if 0 /* temporary logging message */ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_ERROR, "%d rs ok", dlz_thread_num); #endif break; } else { /* we got a result set object, but it's not right. */ #if 0 /* temporary logging message */ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_ERROR, "%d clearing rs", dlz_thread_num); #endif PQclear(*rs); /* get rid of it */ /* in case this was the last attempt */ result = ISC_R_FAILURE; } } cleanup: /* it's always good to cleanup after yourself */ #if 0 /* temporary logging message */ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_ERROR, "%d cleaning up", dlz_thread_num); #endif /* if we couldn't even allocate DBI, just return NULL */ if (dbi == NULL) return ISC_R_FAILURE; /* free dbi->zone string */ if (dbi->zone != NULL) isc_mem_free(ns_g_mctx, dbi->zone); /* free dbi->record string */ if (dbi->record != NULL) isc_mem_free(ns_g_mctx, dbi->record); /* free dbi->client string */ if (dbi->client != NULL) isc_mem_free(ns_g_mctx, dbi->client); #ifdef ISC_PLATFORM_USETHREADS #if 0 /* temporary logging message */ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_ERROR, "%d unlocking mutex", dlz_thread_num); #endif /* release the lock so another thread can use this dbi */ isc_mutex_unlock(&dbi->instance_lock); #endif /* ISC_PLATFORM_USETHREADS */ /* release query string */ if (querystring != NULL) isc_mem_free(ns_g_mctx, querystring ); #if 0 /* temporary logging message */ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_ERROR, "%d returning", dlz_thread_num); #endif /* return result */ return result; }
static int t_timers5(void) { char *p; int result; isc_mem_t *mctx; isc_taskmgr_t *tmgr; unsigned int workers; isc_result_t isc_result; isc_timermgr_t *timermgr; isc_event_t *event; isc_time_t expires; isc_interval_t interval; T5_startflag = 0; T5_shutdownflag = 0; T5_eventcnt = 0; workers = 2; p = t_getenv("ISC_TASK_WORKERS"); if (p != NULL) workers = atoi(p); mctx = NULL; isc_result = isc_mem_create(0, 0, &mctx); if (isc_result != ISC_R_SUCCESS) { t_info("isc_mem_create failed %s\n", isc_result_totext(isc_result)); return(T_UNRESOLVED); } isc_result = isc_mutex_init(&T5_mx); if (isc_result != ISC_R_SUCCESS) { t_info("isc_mutex_init failed %s\n", isc_result_totext(isc_result)); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } isc_result = isc_condition_init(&T5_cv); if (isc_result != ISC_R_SUCCESS) { t_info("isc_condition_init failed %s\n", isc_result_totext(isc_result)); DESTROYLOCK(&T5_mx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } tmgr = NULL; isc_result = isc_taskmgr_create(mctx, workers, 0, &tmgr); if (isc_result != ISC_R_SUCCESS) { t_info("isc_taskmgr_create failed %s\n", isc_result_totext(isc_result)); DESTROYLOCK(&T5_mx); (void) isc_condition_destroy(&T5_cv); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } timermgr = NULL; isc_result = isc_timermgr_create(mctx, &timermgr); if (isc_result != ISC_R_SUCCESS) { t_info("isc_timermgr_create failed %s\n", isc_result_totext(isc_result)); isc_taskmgr_destroy(&tmgr); DESTROYLOCK(&T5_mx); (void) isc_condition_destroy(&T5_cv); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } T5_task1 = NULL; isc_result = isc_task_create(tmgr, 0, &T5_task1); if (isc_result != ISC_R_SUCCESS) { t_info("isc_task_create failed %s\n", isc_result_totext(isc_result)); isc_timermgr_destroy(&timermgr); isc_taskmgr_destroy(&tmgr); DESTROYLOCK(&T5_mx); (void) isc_condition_destroy(&T5_cv); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } isc_result = isc_task_onshutdown(T5_task1, t5_shutdown_event, NULL); if (isc_result != ISC_R_SUCCESS) { t_info("isc_task_onshutdown failed %s\n", isc_result_totext(isc_result)); isc_timermgr_destroy(&timermgr); isc_task_destroy(&T5_task1); isc_taskmgr_destroy(&tmgr); DESTROYLOCK(&T5_mx); (void) isc_condition_destroy(&T5_cv); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } T5_task2 = NULL; isc_result = isc_task_create(tmgr, 0, &T5_task2); if (isc_result != ISC_R_SUCCESS) { t_info("isc_task_create failed %s\n", isc_result_totext(isc_result)); isc_timermgr_destroy(&timermgr); isc_task_destroy(&T5_task1); isc_taskmgr_destroy(&tmgr); DESTROYLOCK(&T5_mx); (void) isc_condition_destroy(&T5_cv); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } isc_result = isc_mutex_lock(&T5_mx); if (isc_result != ISC_R_SUCCESS) { t_info("isc_mutex_lock failed %s\n", isc_result_totext(isc_result)); isc_timermgr_destroy(&timermgr); isc_taskmgr_destroy(&tmgr); DESTROYLOCK(&T5_mx); (void) isc_condition_destroy(&T5_cv); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } event = isc_event_allocate(mctx, (void *)1 , (isc_eventtype_t)1, t5_start_event, NULL, sizeof(*event)); isc_task_send(T5_task1, &event); isc_time_settoepoch(&expires); isc_interval_set(&interval, T5_SECONDS, 0); T5_tickertimer = NULL; isc_result = isc_timer_create(timermgr, isc_timertype_ticker, &expires, &interval, T5_task1, t5_tick_event, NULL, &T5_tickertimer); if (isc_result != ISC_R_SUCCESS) { isc_timermgr_destroy(&timermgr); (void) isc_condition_signal(&T5_cv); (void) isc_mutex_unlock(&T5_mx); isc_task_destroy(&T5_task1); isc_task_destroy(&T5_task2); isc_taskmgr_destroy(&tmgr); DESTROYLOCK(&T5_mx); (void) isc_condition_destroy(&T5_cv); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } T5_oncetimer = NULL; isc_interval_set(&interval, (T5_SECONDS * T5_NTICKS) + 2, 0); isc_result = isc_time_nowplusinterval(&expires, &interval); if (isc_result != ISC_R_SUCCESS) { isc_timer_detach(&T5_tickertimer); isc_timermgr_destroy(&timermgr); (void)isc_condition_signal(&T5_cv); (void)isc_mutex_unlock(&T5_mx); isc_task_destroy(&T5_task1); isc_task_destroy(&T5_task2); isc_taskmgr_destroy(&tmgr); DESTROYLOCK(&T5_mx); (void) isc_condition_destroy(&T5_cv); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } isc_interval_set(&interval, 0, 0); isc_result = isc_timer_create(timermgr, isc_timertype_once, &expires, &interval, T5_task2, t5_once_event, NULL, &T5_oncetimer); if (isc_result != ISC_R_SUCCESS) { isc_timer_detach(&T5_tickertimer); isc_timermgr_destroy(&timermgr); (void) isc_condition_signal(&T5_cv); (void) isc_mutex_unlock(&T5_mx); isc_task_destroy(&T5_task1); isc_task_destroy(&T5_task2); isc_taskmgr_destroy(&tmgr); DESTROYLOCK(&T5_mx); (void) isc_condition_destroy(&T5_cv); isc_mem_destroy(&mctx); ++T5_nprobs; return(T_UNRESOLVED); } /* * Wait for shutdown processing to complete. */ while (! T5_shutdownflag) { isc_result = isc_condition_wait(&T5_cv, &T5_mx); if (isc_result != ISC_R_SUCCESS) { t_info("isc_condition_waituntil failed %s\n", isc_result_totext(isc_result)); ++T5_nprobs; } } isc_result = isc_mutex_unlock(&T5_mx); if (isc_result != ISC_R_SUCCESS) { t_info("isc_mutex_unlock failed %s\n", isc_result_totext(isc_result)); ++T5_nprobs; } if (T5_eventcnt != 1) { t_info("processed %d events\n", T5_eventcnt); ++T5_nfails; } isc_timer_detach(&T5_tickertimer); isc_timer_detach(&T5_oncetimer); isc_timermgr_destroy(&timermgr); isc_task_destroy(&T5_task1); isc_task_destroy(&T5_task2); isc_taskmgr_destroy(&tmgr); DESTROYLOCK(&T5_mx); (void) isc_condition_destroy(&T5_cv); isc_mem_destroy(&mctx); result = T_UNRESOLVED; if ((T5_nfails == 0) && (T5_nprobs == 0)) result = T_PASS; else if (T5_nfails) result = T_FAIL; return (result); }
static void t_timers_x(isc_timertype_t timertype, isc_time_t *expires, isc_interval_t *interval, void (*action)(isc_task_t *, isc_event_t *)) { char *p; isc_mem_t *mctx; isc_taskmgr_t *tmgr; isc_task_t *task; unsigned int workers; isc_result_t isc_result; isc_timermgr_t *timermgr; Tx_eventcnt = 0; isc_time_settoepoch(&Tx_endtime); workers = 2; p = t_getenv("ISC_TASK_WORKERS"); if (p != NULL) workers = atoi(p); mctx = NULL; isc_result = isc_mem_create(0, 0, &mctx); if (isc_result != ISC_R_SUCCESS) { t_info("isc_mem_create failed %s\n", isc_result_totext(isc_result)); ++Tx_nprobs; return; } isc_result = isc_mutex_init(&Tx_mx); if (isc_result != ISC_R_SUCCESS) { t_info("isc_mutex_init failed %s\n", isc_result_totext(isc_result)); isc_mem_destroy(&mctx); ++Tx_nprobs; return; } isc_result = isc_condition_init(&Tx_cv); if (isc_result != ISC_R_SUCCESS) { t_info("isc_condition_init failed %s\n", isc_result_totext(isc_result)); DESTROYLOCK(&Tx_mx); isc_mem_destroy(&mctx); ++Tx_nprobs; return; } tmgr = NULL; isc_result = isc_taskmgr_create(mctx, workers, 0, &tmgr); if (isc_result != ISC_R_SUCCESS) { t_info("isc_taskmgr_create failed %s\n", isc_result_totext(isc_result)); DESTROYLOCK(&Tx_mx); (void) isc_condition_destroy(&Tx_cv); isc_mem_destroy(&mctx); ++Tx_nprobs; return; } timermgr = NULL; isc_result = isc_timermgr_create(mctx, &timermgr); if (isc_result != ISC_R_SUCCESS) { t_info("isc_timermgr_create failed %s\n", isc_result_totext(isc_result)); isc_taskmgr_destroy(&tmgr); DESTROYLOCK(&Tx_mx); (void) isc_condition_destroy(&Tx_cv); isc_mem_destroy(&mctx); ++Tx_nprobs; return; } isc_result = isc_mutex_lock(&Tx_mx); if (isc_result != ISC_R_SUCCESS) { t_info("isc_mutex_lock failed %s\n", isc_result_totext(isc_result)); isc_timermgr_destroy(&timermgr); isc_taskmgr_destroy(&tmgr); DESTROYLOCK(&Tx_mx); (void) isc_condition_destroy(&Tx_cv); isc_mem_destroy(&mctx); ++Tx_nprobs; return; } task = NULL; isc_result = isc_task_create(tmgr, 0, &task); if (isc_result != ISC_R_SUCCESS) { t_info("isc_task_create failed %s\n", isc_result_totext(isc_result)); isc_timermgr_destroy(&timermgr); isc_taskmgr_destroy(&tmgr); DESTROYLOCK(&Tx_mx); (void) isc_condition_destroy(&Tx_cv); isc_mem_destroy(&mctx); ++Tx_nprobs; return; } isc_result = isc_task_onshutdown(task, tx_sde, NULL); if (isc_result != ISC_R_SUCCESS) { t_info("isc_task_onshutdown failed %s\n", isc_result_totext(isc_result)); isc_timermgr_destroy(&timermgr); isc_task_destroy(&task); isc_taskmgr_destroy(&tmgr); DESTROYLOCK(&Tx_mx); (void) isc_condition_destroy(&Tx_cv); isc_mem_destroy(&mctx); ++Tx_nprobs; return; } isc_result = isc_time_now(&Tx_lasttime); if (isc_result != ISC_R_SUCCESS) { isc_timermgr_destroy(&timermgr); isc_task_destroy(&task); isc_taskmgr_destroy(&tmgr); DESTROYLOCK(&Tx_mx); (void) isc_condition_destroy(&Tx_cv); isc_mem_destroy(&mctx); ++Tx_nprobs; return; } Tx_timer = NULL; isc_result = isc_timer_create(timermgr, timertype, expires, interval, task, action, (void *)timertype, &Tx_timer); if (isc_result != ISC_R_SUCCESS) { isc_timermgr_destroy(&timermgr); isc_task_destroy(&task); isc_taskmgr_destroy(&tmgr); DESTROYLOCK(&Tx_mx); (void) isc_condition_destroy(&Tx_cv); isc_mem_destroy(&mctx); ++Tx_nprobs; return; } /* * Wait for shutdown processing to complete. */ while (Tx_eventcnt != Tx_nevents) { isc_result = isc_condition_wait(&Tx_cv, &Tx_mx); if (isc_result != ISC_R_SUCCESS) { t_info("isc_condition_waituntil failed %s\n", isc_result_totext(isc_result)); ++Tx_nprobs; } } isc_result = isc_mutex_unlock(&Tx_mx); if (isc_result != ISC_R_SUCCESS) { t_info("isc_mutex_unlock failed %s\n", isc_result_totext(isc_result)); ++Tx_nprobs; } isc_task_detach(&task); isc_taskmgr_destroy(&tmgr); isc_timermgr_destroy(&timermgr); DESTROYLOCK(&Tx_mx); (void) isc_condition_destroy(&Tx_cv); isc_mem_destroy(&mctx); }
static isc_result_t odbc_process_rs(dns_sdlzlookup_t *lookup, dbinstance_t *dbi) { isc_result_t result; SQLSMALLINT fields; SQLHSTMT *stmnt; char *ttl_s; char *type; char *data; char *endp; int ttl; REQUIRE(dbi != NULL); stmnt = ((odbc_db_t *) (dbi->dbconn))->stmnt; /* get number of columns */ if (!sqlOK(SQLNumResultCols(stmnt, &fields))) { isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_ERROR, "Odbc driver unable to process result set"); result = ISC_R_FAILURE; goto process_rs_cleanup; } /* get things ready for processing */ result = ISC_R_FAILURE; while (sqlOK(SQLFetch(stmnt))) { /* set to null for next pass through */ data = type = ttl_s = NULL; switch(fields) { case 1: /* * one column in rs, it's the data field. use * default type of A record, and default TTL * of 86400. attempt to get data, & tell bind * about it. */ if ((result = odbc_getField(stmnt, 1, &data)) == ISC_R_SUCCESS) { result = dns_sdlz_putrr(lookup, "a", 86400, data); } break; case 2: /* * two columns, data field, and data type. * use default TTL of 86400. attempt to get * DNS type & data, then tell bind about it. */ if ((result = odbc_getField(stmnt, 1, &type)) == ISC_R_SUCCESS && (result = odbc_getField(stmnt, 2, &data)) == ISC_R_SUCCESS) { result = dns_sdlz_putrr(lookup, type, 86400, data); } break; default: /* * 3 fields or more, concatenate the last ones * together. attempt to get DNS ttl, type, * data then tell Bind about them. */ if ((result = odbc_getField(stmnt, 1, &ttl_s)) == ISC_R_SUCCESS && (result = odbc_getField(stmnt, 2, &type)) == ISC_R_SUCCESS && (result = odbc_getManyFields(stmnt, 3, fields, &data)) == ISC_R_SUCCESS) { /* try to convert ttl string to int */ ttl = strtol(ttl_s, &endp, 10); /* failure converting ttl. */ if (*endp != '\0' || ttl < 0) { isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_ERROR, "Odbc driver ttl must " "be a postive number"); result = ISC_R_FAILURE; } else { /* * successful converting TTL, * tell Bind everything */ result = dns_sdlz_putrr(lookup, type, ttl, data); } } /* closes bid if () */ } /* closes switch(fields) */ /* clean up mem */ if (ttl_s != NULL) isc_mem_free(ns_g_mctx, ttl_s); if (type != NULL) isc_mem_free(ns_g_mctx, type); if (data != NULL) isc_mem_free(ns_g_mctx, data); /* I sure hope we were successful */ if (result != ISC_R_SUCCESS) { isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_ERROR, "dns_sdlz_putrr returned error. " "Error code was: %s", isc_result_totext(result)); result = ISC_R_FAILURE; goto process_rs_cleanup; } } /* closes while loop */ process_rs_cleanup: /* close cursor */ SQLCloseCursor(((odbc_db_t *) (dbi->dbconn))->stmnt); #ifdef ISC_PLATFORM_USETHREADS /* free lock on dbi so someone else can use it. */ isc_mutex_unlock(&dbi->instance_lock); #endif return result; }
static isc_result_t odbc_get_resultset(const char *zone, const char *record, const char *client, unsigned int query, void *dbdata, dbinstance_t **r_dbi) { isc_result_t result; dbinstance_t *dbi = NULL; char *querystring = NULL; unsigned int j = 0; SQLRETURN sqlRes; REQUIRE(*r_dbi == NULL); /* get db instance / connection */ #ifdef ISC_PLATFORM_USETHREADS /* find an available DBI from the list */ dbi = odbc_find_avail_conn(((odbc_instance_t *) dbdata)->db); #else /* ISC_PLATFORM_USETHREADS */ /* * only 1 DBI - no need to lock instance lock either * only 1 thread in the whole process, no possible contention. */ dbi = (dbinstance_t *) ((odbc_instance_t *) dbdata)->db; #endif /* ISC_PLATFORM_USETHREADS */ /* if DBI is null, can't do anything else */ if (dbi == NULL) { result = ISC_R_FAILURE; goto cleanup; } /* what type of query are we going to run? */ switch(query) { case ALLNODES: /* * if the query was not passed in from the config file * then we can't run it. return not_implemented, so * it's like the code for that operation was never * built into the driver.... AHHH flexibility!!! */ if (dbi->allnodes_q == NULL) { result = ISC_R_NOTIMPLEMENTED; goto cleanup; } break; case ALLOWXFR: /* same as comments as ALLNODES */ if (dbi->allowxfr_q == NULL) { result = ISC_R_NOTIMPLEMENTED; goto cleanup; } break; case AUTHORITY: /* same as comments as ALLNODES */ if (dbi->authority_q == NULL) { result = ISC_R_NOTIMPLEMENTED; goto cleanup; } break; case FINDZONE: /* this is required. It's the whole point of DLZ! */ if (dbi->findzone_q == NULL) { isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2), "No query specified for findzone. " "Findzone requires a query"); result = ISC_R_FAILURE; goto cleanup; } break; case LOOKUP: /* this is required. It's also a major point of DLZ! */ if (dbi->lookup_q == NULL) { isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2), "No query specified for lookup. " "Lookup requires a query"); result = ISC_R_FAILURE; goto cleanup; } break; default: /* * this should never happen. If it does, the code is * screwed up! */ UNEXPECTED_ERROR(__FILE__, __LINE__, "Incorrect query flag passed to " "odbc_get_resultset"); result = ISC_R_UNEXPECTED; goto cleanup; } /* * was a zone string passed? If so, make it safe for use in * queries. */ if (zone != NULL) { dbi->zone = odbc_escape_string(zone); if (dbi->zone == NULL) { result = ISC_R_NOMEMORY; goto cleanup; } } else { /* no string passed, set the string pointer to NULL */ dbi->zone = NULL; } /* * was a record string passed? If so, make it safe for use in * queries. */ if (record != NULL) { dbi->record = odbc_escape_string(record); if (dbi->record == NULL) { result = ISC_R_NOMEMORY; goto cleanup; } } else { /* no string passed, set the string pointer to NULL */ dbi->record = NULL; } /* * was a client string passed? If so, make it safe for use in * queries. */ if (client != NULL) { dbi->client = odbc_escape_string(client); if (dbi->client == NULL) { result = ISC_R_NOMEMORY; goto cleanup; } } else { /* no string passed, set the string pointer to NULL */ dbi->client = NULL; } /* * what type of query are we going to run? * this time we build the actual query to run. */ switch(query) { case ALLNODES: querystring = build_querystring(ns_g_mctx, dbi->allnodes_q); break; case ALLOWXFR: querystring = build_querystring(ns_g_mctx, dbi->allowxfr_q); break; case AUTHORITY: querystring = build_querystring(ns_g_mctx, dbi->authority_q); break; case FINDZONE: querystring = build_querystring(ns_g_mctx, dbi->findzone_q); break; case LOOKUP: querystring = build_querystring(ns_g_mctx, dbi->lookup_q); break; default: /* * this should never happen. If it does, the code is * screwed up! */ UNEXPECTED_ERROR(__FILE__, __LINE__, "Incorrect query flag passed to " "odbc_get_resultset"); result = ISC_R_UNEXPECTED; goto cleanup; } /* if the querystring is null, Bummer, outta RAM. UPGRADE TIME!!! */ if (querystring == NULL) { result = ISC_R_NOMEMORY; goto cleanup; } /* output the full query string during debug so we can see */ /* what lame error the query has. */ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1), "\nQuery String: %s\n", querystring); /* attempt query up to 3 times. */ for (j=0; j < 3; j++) { /* try to get result set */ sqlRes = SQLExecDirect(((odbc_db_t *) dbi->dbconn)->stmnt, (SQLCHAR *) querystring, (SQLINTEGER) strlen(querystring)); /* if error, reset DB connection */ if (!sqlOK(sqlRes)) { /* close cursor */ SQLCloseCursor(((odbc_db_t *) dbi->dbconn)->stmnt); /* attempt to reconnect */ result = odbc_connect((odbc_instance_t *) dbdata, (odbc_db_t **) &(dbi->dbconn)); /* check if we reconnected */ if (result != ISC_R_SUCCESS) break; /* incase this is the last time through the loop */ result = ISC_R_FAILURE; } else { result = ISC_R_SUCCESS; /* return dbi */ *r_dbi = dbi; /* result set ok, break loop */ break; } } /* end for loop */ cleanup: /* it's always good to cleanup after yourself */ /* if we couldn't even allocate DBI, just return NULL */ if (dbi == NULL) return ISC_R_FAILURE; /* free dbi->zone string */ if (dbi->zone != NULL) isc_mem_free(ns_g_mctx, dbi->zone); /* free dbi->record string */ if (dbi->record != NULL) isc_mem_free(ns_g_mctx, dbi->record); /* free dbi->client string */ if (dbi->client != NULL) isc_mem_free(ns_g_mctx, dbi->client); #ifdef ISC_PLATFORM_USETHREADS /* if we are done using this dbi, release the lock */ if (result != ISC_R_SUCCESS) isc_mutex_unlock(&dbi->instance_lock); #endif /* ISC_PLATFORM_USETHREADS */ /* release query string */ if (querystring != NULL) isc_mem_free(ns_g_mctx, querystring ); /* return result */ return result; }
static isc_result_t odbc_allnodes(const char *zone, void *driverarg, void *dbdata, dns_sdlzallnodes_t *allnodes) { isc_result_t result; dbinstance_t *dbi = NULL; SQLHSTMT *stmnt; SQLSMALLINT fields; char *data; char *type; char *ttl_s; int ttl; char *host; char *endp; UNUSED(driverarg); /* run the query and get the result set from the database. */ result = odbc_get_resultset(zone, NULL, NULL, ALLNODES, dbdata, &dbi); /* if we get "not implemented", send it along */ if (result == ISC_R_NOTIMPLEMENTED) return result; /* if we didn't get a result set, log an err msg. */ if (result != ISC_R_SUCCESS) { isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_ERROR, "Odbc driver unable to return " "result set for all nodes query"); return (ISC_R_FAILURE); } stmnt = ((odbc_db_t *) (dbi->dbconn))->stmnt; /* get number of columns */ if (!sqlOK(SQLNumResultCols(stmnt, &fields))) { isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_ERROR, "Odbc driver unable to process result set"); result = ISC_R_FAILURE; goto allnodes_cleanup; } if (fields < 4) { /* gotta have at least 4 columns */ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_ERROR, "Odbc driver too few fields returned by " "all nodes query"); result = ISC_R_FAILURE; goto allnodes_cleanup; } /* get things ready for processing */ result = ISC_R_FAILURE; while (sqlOK(SQLFetch(stmnt))) { /* set to null for next pass through */ data = host = type = ttl_s = NULL; /* * attempt to get DNS ttl, type, host, data then tell * Bind about them */ if ((result = odbc_getField(stmnt, 1, &ttl_s)) == ISC_R_SUCCESS && (result = odbc_getField(stmnt, 2, &type)) == ISC_R_SUCCESS && (result = odbc_getField(stmnt, 3, &host)) == ISC_R_SUCCESS && (result = odbc_getManyFields(stmnt, 4, fields, &data)) == ISC_R_SUCCESS) { /* convert ttl string to int */ ttl = strtol(ttl_s, &endp, 10); /* failure converting ttl. */ if (*endp != '\0' || ttl < 0) { isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_ERROR, "Odbc driver ttl must be " "a postive number"); result = ISC_R_FAILURE; } else { /* successful converting TTL, tell Bind */ result = dns_sdlz_putnamedrr(allnodes, host, type, ttl, data); } } /* closes big if () */ /* clean up mem */ if (ttl_s != NULL) isc_mem_free(ns_g_mctx, ttl_s); if (type != NULL) isc_mem_free(ns_g_mctx, type); if (host != NULL) isc_mem_free(ns_g_mctx, host); if (data != NULL) isc_mem_free(ns_g_mctx, data); /* if we weren't successful, log err msg */ if (result != ISC_R_SUCCESS) { isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_ERROR, "dns_sdlz_putnamedrr returned error. " "Error code was: %s", isc_result_totext(result)); result = ISC_R_FAILURE; goto allnodes_cleanup; } } /* closes while loop */ allnodes_cleanup: /* close cursor */ SQLCloseCursor(((odbc_db_t *) (dbi->dbconn))->stmnt); #ifdef ISC_PLATFORM_USETHREADS /* free lock on dbi so someone else can use it. */ isc_mutex_unlock(&dbi->instance_lock); #endif return result; }
/*% * This function is the real core of the driver. Zone, record * and client strings are passed in (or NULL is passed if the * string is not available). The type of query we want to run * is indicated by the query flag, and the dbdata object is passed * passed in to. dbdata really holds either: * 1) a list of database instances (in multithreaded mode) OR * 2) a single database instance (in single threaded mode) * The function will construct the query and obtain an available * database instance (DBI). It will then run the query and hopefully * obtain a result set. */ static isc_result_t ldap_get_results(const char *zone, const char *record, const char *client, unsigned int query, void *dbdata, void *ptr) { isc_result_t result; dbinstance_t *dbi = NULL; char *querystring = NULL; LDAPURLDesc *ldap_url = NULL; int ldap_result = 0; LDAPMessage *ldap_msg = NULL; int i; int entries; /* get db instance / connection */ #ifdef ISC_PLATFORM_USETHREADS /* find an available DBI from the list */ dbi = ldap_find_avail_conn((db_list_t *) ((ldap_instance_t *)dbdata)->db); #else /* ISC_PLATFORM_USETHREADS */ /* * only 1 DBI - no need to lock instance lock either * only 1 thread in the whole process, no possible contention. */ dbi = (dbinstance_t *) ((ldap_instance_t *)dbdata)->db; #endif /* ISC_PLATFORM_USETHREADS */ /* if DBI is null, can't do anything else */ if (dbi == NULL) return (ISC_R_FAILURE); /* set fields */ if (zone != NULL) { dbi->zone = isc_mem_strdup(ns_g_mctx, zone); if (dbi->zone == NULL) { result = ISC_R_NOMEMORY; goto cleanup; } } else { dbi->zone = NULL; } if (record != NULL) { dbi->record = isc_mem_strdup(ns_g_mctx, record); if (dbi->record == NULL) { result = ISC_R_NOMEMORY; goto cleanup; } } else { dbi->record = NULL; } if (client != NULL) { dbi->client = isc_mem_strdup(ns_g_mctx, client); if (dbi->client == NULL) { result = ISC_R_NOMEMORY; goto cleanup; } } else { dbi->client = NULL; } /* what type of query are we going to run? */ switch(query) { case ALLNODES: /* * if the query was not passed in from the config file * then we can't run it. return not_implemented, so * it's like the code for that operation was never * built into the driver.... AHHH flexibility!!! */ if (dbi->allnodes_q == NULL) { result = ISC_R_NOTIMPLEMENTED; goto cleanup; } else { querystring = build_querystring(ns_g_mctx, dbi->allnodes_q); } break; case ALLOWXFR: /* same as comments as ALLNODES */ if (dbi->allowxfr_q == NULL) { result = ISC_R_NOTIMPLEMENTED; goto cleanup; } else { querystring = build_querystring(ns_g_mctx, dbi->allowxfr_q); } break; case AUTHORITY: /* same as comments as ALLNODES */ if (dbi->authority_q == NULL) { result = ISC_R_NOTIMPLEMENTED; goto cleanup; } else { querystring = build_querystring(ns_g_mctx, dbi->authority_q); } break; case FINDZONE: /* this is required. It's the whole point of DLZ! */ if (dbi->findzone_q == NULL) { isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2), "No query specified for findzone. " "Findzone requires a query"); result = ISC_R_FAILURE; goto cleanup; } else { querystring = build_querystring(ns_g_mctx, dbi->findzone_q); } break; case LOOKUP: /* this is required. It's also a major point of DLZ! */ if (dbi->lookup_q == NULL) { isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2), "No query specified for lookup. " "Lookup requires a query"); result = ISC_R_FAILURE; goto cleanup; } else { querystring = build_querystring(ns_g_mctx, dbi->lookup_q); } break; default: /* * this should never happen. If it does, the code is * screwed up! */ UNEXPECTED_ERROR(__FILE__, __LINE__, "Incorrect query flag passed to " "ldap_get_results"); result = ISC_R_UNEXPECTED; goto cleanup; } /* if the querystring is null, Bummer, outta RAM. UPGRADE TIME!!! */ if (querystring == NULL) { result = ISC_R_NOMEMORY; goto cleanup; } /* * output the full query string during debug so we can see * what lame error the query has. */ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1), "\nQuery String: %s\n", querystring); /* break URL down into it's component parts, if error cleanup */ ldap_result = ldap_url_parse(querystring, &ldap_url); if (ldap_result != LDAP_SUCCESS || ldap_url == NULL) { result = ISC_R_FAILURE; goto cleanup; } for (i = 0; i < 3; i++) { /* * dbi->dbconn may be null if trying to reconnect on a * previous query failed. */ if (dbi->dbconn == NULL) { isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_INFO, "LDAP driver attempting to re-connect"); result = dlz_ldap_connect((ldap_instance_t *) dbdata, dbi); if (result != ISC_R_SUCCESS) { result = ISC_R_FAILURE; continue; } } /* perform ldap search syncronously */ ldap_result = ldap_search_s((LDAP *) dbi->dbconn, ldap_url->lud_dn, ldap_url->lud_scope, ldap_url->lud_filter, ldap_url->lud_attrs, 0, &ldap_msg); /* * check return code. No such object is ok, just * didn't find what we wanted */ switch(ldap_result) { case LDAP_NO_SUCH_OBJECT: isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1), "No object found matching " "query requirements"); result = ISC_R_NOTFOUND; goto cleanup; break; case LDAP_SUCCESS: /* on success do nothing */ result = ISC_R_SUCCESS; i = 3; break; case LDAP_SERVER_DOWN: isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_INFO, "LDAP driver attempting to re-connect"); result = dlz_ldap_connect((ldap_instance_t *) dbdata, dbi); if (result != ISC_R_SUCCESS) result = ISC_R_FAILURE; break; default: /* * other errors not ok. Log error message and * get out */ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_ERROR, "LDAP error: %s", ldap_err2string(ldap_result)); result = ISC_R_FAILURE; goto cleanup; break; } /* close switch(ldap_result) */ } /* end for (int i = 0 i < 3; i++) */ if (result != ISC_R_SUCCESS) goto cleanup; switch(query) { case ALLNODES: result = ldap_process_results((LDAP *) dbi->dbconn, ldap_msg, ldap_url->lud_attrs, ptr, isc_boolean_true); break; case AUTHORITY: case LOOKUP: result = ldap_process_results((LDAP *) dbi->dbconn, ldap_msg, ldap_url->lud_attrs, ptr, isc_boolean_false); break; case ALLOWXFR: entries = ldap_count_entries((LDAP *) dbi->dbconn, ldap_msg); if (entries == 0) result = ISC_R_NOPERM; else if (entries > 0) result = ISC_R_SUCCESS; else result = ISC_R_FAILURE; break; case FINDZONE: entries = ldap_count_entries((LDAP *) dbi->dbconn, ldap_msg); if (entries == 0) result = ISC_R_NOTFOUND; else if (entries > 0) result = ISC_R_SUCCESS; else result = ISC_R_FAILURE; break; default: /* * this should never happen. If it does, the code is * screwed up! */ UNEXPECTED_ERROR(__FILE__, __LINE__, "Incorrect query flag passed to " "ldap_get_results"); result = ISC_R_UNEXPECTED; } cleanup: /* it's always good to cleanup after yourself */ /* if we retrieved results, free them */ if (ldap_msg != NULL) ldap_msgfree(ldap_msg); if (ldap_url != NULL) ldap_free_urldesc(ldap_url); /* cleanup */ if (dbi->zone != NULL) isc_mem_free(ns_g_mctx, dbi->zone); if (dbi->record != NULL) isc_mem_free(ns_g_mctx, dbi->record); if (dbi->client != NULL) isc_mem_free(ns_g_mctx, dbi->client); #ifdef ISC_PLATFORM_USETHREADS /* release the lock so another thread can use this dbi */ isc_mutex_unlock(&dbi->instance_lock); #endif /* ISC_PLATFORM_USETHREADS */ /* release query string */ if (querystring != NULL) isc_mem_free(ns_g_mctx, querystring ); /* return result */ return (result); }