dlz_postgres_driver.c

来自「非常好的dns解析软件」· C语言 代码 · 共 1,343 行 · 第 1/3 页

C
1,343
字号
		dbi->client = NULL;	}	/* temporary logging message */	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,	DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,		      "%d did client", dlz_thread_num);	/*	 * 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;	}	/* temporary logging message */	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,		      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,		      "%d built query", dlz_thread_num);	/* if the querystring is null, Bummer, outta RAM.  UPGRADE TIME!!!   */	if (querystring  == NULL) {		result = ISC_R_NOMEMORY;		goto cleanup;	}	/* 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);	/*	 * 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++) {		/* 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);		/* 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++) {			/* temporary logging message */			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,				      "%d resetting connection",				      dlz_thread_num);			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) {			/* temporary logging message */			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,				      "%d rs ok", dlz_thread_num);			break;		} else {			/* we got a result set object, but it's not right. */			/* temporary logging message */			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,				      "%d clearing rs", dlz_thread_num);			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 */	/* temporary logging message */	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,		      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,		      "%d cleaning up", dlz_thread_num);	/* 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	/* temporary logging message */	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,		      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,		      "%d unlocking mutex", dlz_thread_num);	/* 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 );	/* temporary logging message */	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,		      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,		      "%d returning", dlz_thread_num);	/* return result */	return result;}/*% * The processing of result sets for lookup and authority are * exactly the same.  So that functionality has been moved * into this function to minimize code. */static isc_result_tpostgres_process_rs(dns_sdlzlookup_t *lookup, PGresult *rs){	isc_result_t result;	unsigned int i;	unsigned int rows;	unsigned int fields;	unsigned int j;	unsigned int len;	char *tmpString;	char *endp;	int ttl;	rows = PQntuples(rs);	/* how many rows in result set */	fields = PQnfields(rs);	/* how many columns in result set */	for (i=0; i < rows; i++) {		switch(fields) {		case 1:			/*			 * one column in rs, it's the data field.  use			 * default type of A record, and default TTL			 * of 86400			 */			result = dns_sdlz_putrr(lookup, "a", 86400,						PQgetvalue(rs, i, 0));			break;		case 2:			/* two columns, data field, and data type.			 * use default TTL of 86400.			 */			result = dns_sdlz_putrr(lookup, PQgetvalue(rs, i, 0),						86400, PQgetvalue(rs, i, 1));			break;		case 3:			/* three columns, all data no defaults.			 * convert text to int, make sure it worked			 * right.			 */			ttl = strtol(PQgetvalue(rs, i, 0), &endp, 10);			if (*endp != '\0' || ttl < 0) {				isc_log_write(dns_lctx,					      DNS_LOGCATEGORY_DATABASE,					      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,					      "Postgres driver ttl must be "					      "a positive number");			}			result = dns_sdlz_putrr(lookup, PQgetvalue(rs, i, 1),						ttl, PQgetvalue(rs, i, 2));			break;		default:		  	/*			 * more than 3 fields, concatenate the last			 * ones together.  figure out how long to make			 * string			 */			for (j=2, len=0; j < fields; j++) {				len += strlen(PQgetvalue(rs, i, j)) + 1;			}			/*			 * allocate string memory, allow for NULL to			 * term string			 */			tmpString = isc_mem_allocate(ns_g_mctx, len + 1);			if (tmpString == NULL) {				/* major bummer, need more ram */				isc_log_write(dns_lctx,					      DNS_LOGCATEGORY_DATABASE,					      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,					      "Postgres driver unable to "					      "allocate memory for "					      "temporary string");				PQclear(rs);				return (ISC_R_FAILURE);	/* Yeah, I'd say! */			}			/* copy field to tmpString */			strcpy(tmpString, PQgetvalue(rs, i, 2));			/*			 * concat the rest of fields together, space			 * between each one.			 */			for (j=3; j < fields; j++) {				strcat(tmpString, " ");				strcat(tmpString, PQgetvalue(rs, i, j));			}			/* convert text to int, make sure it worked right */			ttl = strtol(PQgetvalue(rs, i, 0), &endp, 10);			if (*endp != '\0' || ttl < 0) {				isc_log_write(dns_lctx,					      DNS_LOGCATEGORY_DATABASE,					      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,					      "Postgres driver ttl must be "					      "a postive number");			}			/* ok, now tell Bind about it. */			result = dns_sdlz_putrr(lookup, PQgetvalue(rs, i, 1),						ttl, tmpString);			/* done, get rid of this thing. */			isc_mem_free(ns_g_mctx, tmpString);		}		/* I sure hope we were successful */		if (result != ISC_R_SUCCESS) {			/* nope, get rid of the Result set, and log a msg */			PQclear(rs);			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));			return (ISC_R_FAILURE);		}	}	/* free result set memory */	PQclear(rs);	/* if we did return results, we are successful */	if (rows > 0)		return (ISC_R_SUCCESS);	/* empty result set, no data found */	return (ISC_R_NOTFOUND);}/* * SDLZ interface methods *//*% determine if the zone is supported by (in) the database */static isc_result_tpostgres_findzone(void *driverarg, void *dbdata, const char *name){	isc_result_t result;	PGresult *rs = NULL;	unsigned int rows;	UNUSED(driverarg);	/* run the query and get the result set from the database. */	result = postgres_get_resultset(name, NULL, NULL,					FINDZONE, dbdata, &rs);	/* if we didn't get a result set, log an err msg. */	if (result != ISC_R_SUCCESS) {		if (rs != NULL)			PQclear(rs);		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,			      "Postgres driver unable to return "			      "result set for findzone query");		return (ISC_R_FAILURE);	}	/* count how many rows in result set */	rows = PQntuples(rs);	/* get rid of result set, we are done with it. */	PQclear(rs);	/* if we returned any rows, zone is supported. */	if (rows > 0)		return (ISC_R_SUCCESS);	/* no rows returned, zone is not supported. */	return (ISC_R_NOTFOUND);}/*% Determine if the client is allowed to perform a zone transfer */static isc_result_tpostgres_allowzonexfr(void *driverarg, void *dbdata, const char *name,		      const char *client){	isc_result_t result;	PGresult *rs = NULL;	unsigned int rows;	UNUSED(driverarg);	/* first check if the zone is supported by the database. */	result = postgres_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.	 */	result = postgres_get_resultset(name, NULL, client,					ALLOWXFR, dbdata, &rs);	/* 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) {		if (rs != NULL)			PQclear(rs);		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,			      "Postgres driver unable to return "			      "result set for allow xfr query");		return (ISC_R_FAILURE);	}	/* count how many rows in result set */	rows = PQntuples(rs);	/* get rid of result set, we are done with it. */	PQclear(rs);	/* if we returned any rows, zone xfr is allowed. */	if (rows > 0)		return (ISC_R_SUCCESS);	/* no rows returned, zone xfr not allowed */	return (ISC_R_NOPERM);}/*% * If the client is allowed to perform a zone transfer, the next order of * business is to get all the nodes in the zone, so bind can respond to the * query. */static isc_result_tpostgres_allnodes(const char *zone, void *driverarg, void *dbdata,		  dns_sdlzallnodes_t *allnodes){	isc_result_t result;	PGresult *rs = NULL;	unsigned int i;	unsigned int rows;	unsigned int fields;	unsigned int j;	unsigned int len;	char *tmpString;	char *endp;	int ttl;	UNUSED(driverarg);	/* run the query and get the result set from the database. */	result = postgres_get_resultset(zone, NULL, NULL,					ALLNODES, dbdata, &rs);	/* 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) {		if (rs != NULL)			PQclear(rs);		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,			      "Postgres driver unable to return "			      "result set for all nodes query");		return (ISC_R_FAILURE);	}	rows = PQntuples(rs);	/* how many rows in result set */	fields = PQnfields(rs);	/* how many columns in result set */	for (i=0; i < rows; i++) {		if (fields < 4) {	/* gotta have at least 4 columns */			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,				      "Postgres driver too few fields "				      "returned by all nodes query");		}		/* convert text to int, make sure it worked right  */		ttl = strtol(PQgetvalue(rs, i, 0), &endp, 10);		if (*endp != '\0' || ttl < 0) {			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,				      "Postgres driver ttl must be "				      "a postive number");		}		if (fields == 4) {			/* tell Bind about it. */			result = dns_sdlz_putnamedrr(allnodes,						     PQgetvalue(rs, i, 2),						     PQgetvalue(rs, i, 1),						     ttl,						     PQgetvalue(rs, i, 3));		} else {			/*			 * more than 4 fields, concatonat the last			 * ones together.  figure out how long to make			 * string			 */			for (j=3, len=0; j < fields; j++) {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?