dlz_mysql_driver.c

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

C
1,061
字号
	if (rows > 0) {		mysql_get_resultset(name, NULL, NULL, COUNTZONE, dbdata, NULL);		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_tmysql_allowzonexfr(void *driverarg, void *dbdata, const char *name,		   const char *client){	isc_result_t result;	MYSQL_RES *rs = NULL;	my_ulonglong rows;	UNUSED(driverarg);	/* first check if the zone is supported by the database. */	result = mysql_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 = mysql_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 || rs == NULL) {		if (rs != NULL)			mysql_free_result(rs);		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,			      "mysql driver unable to return "			      "result set for allow xfr query");		return (ISC_R_FAILURE);	}	/* count how many rows in result set */	rows = mysql_num_rows(rs);	/* get rid of result set, we are done with it. */	mysql_free_result(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_tmysql_allnodes(const char *zone, void *driverarg, void *dbdata,	       dns_sdlzallnodes_t *allnodes){	isc_result_t result;	MYSQL_RES *rs = NULL;	MYSQL_ROW row;	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 = mysql_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)			mysql_free_result(rs);		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,			      "mysql driver unable to return "			      "result set for all nodes query");		return (ISC_R_FAILURE);	}	result = ISC_R_NOTFOUND;	row = mysql_fetch_row(rs);	/* get a row from the result set */	fields = mysql_num_fields(rs);	/* how many columns in result set */	while (row != NULL) {		if (fields < 4) {	/* gotta have at least 4 columns */			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,				      "mysql driver too few fields returned "				      "by all nodes query");		}		/* convert text to int, make sure it worked right  */		ttl = strtol(safeGet(row[0]), &endp, 10);		if (*endp != '\0' || ttl < 0) {			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,				      "mysql driver ttl must be "				      "a postive number");		}		if (fields == 4) {			/* tell Bind about it. */			result = dns_sdlz_putnamedrr(allnodes, safeGet(row[2]),						     safeGet(row[1]), ttl,						     safeGet(row[3]));		} else {			/*			 * more than 4 fields, concatenate the last			 * ones together.  figure out how long to make			 * string.			 */			for (j=3, len=0; j < fields; j++) {				len += strlen(safeGet(row[j])) + 1;			}			/* allocate memory, allow for NULL to term string */			tmpString = isc_mem_allocate(ns_g_mctx, len + 1);			if (tmpString == NULL) {	/* we need more ram. */				isc_log_write(dns_lctx,					      DNS_LOGCATEGORY_DATABASE,					      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,					      "mysql driver unable "					      "to allocate memory for "					      "temporary string");				mysql_free_result(rs);				return (ISC_R_FAILURE);			}			/* copy this field to tmpString */			strcpy(tmpString, safeGet(row[3]));			/* concatonate the rest, with spaces between */			for (j=4; j < fields; j++) {				strcat(tmpString, " ");				strcat(tmpString, safeGet(row[j]));			}			/* tell Bind about it. */			result = dns_sdlz_putnamedrr(allnodes, safeGet(row[2]),						     safeGet(row[1]),						     ttl, tmpString);			isc_mem_free(ns_g_mctx, tmpString);		}		/* 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;			break;		}		/* get next row from the result set */		row = mysql_fetch_row(rs);	}	/* free result set memory */	mysql_free_result(rs);	return result;}/*% if the lookup function does not return SOA or NS records for the zone, * use this function to get that information for Bind. */static isc_result_tmysql_authority(const char *zone, void *driverarg, void *dbdata,		dns_sdlzlookup_t *lookup){	isc_result_t result;	MYSQL_RES *rs = NULL;	UNUSED(driverarg);	/* run the query and get the result set from the database. */	result = mysql_get_resultset(zone, NULL, NULL, AUTHORITY, 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)			mysql_free_result(rs);		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,			      "mysql driver unable to return "			      "result set for authority query");		return (ISC_R_FAILURE);	}	/*	 * lookup and authority result sets are processed in the same	 * manner mysql_process_rs does the job for both functions.	 */	return mysql_process_rs(lookup, rs);}/*% if zone is supported, lookup up a (or multiple) record(s) in it */static isc_result_tmysql_lookup(const char *zone, const char *name, void *driverarg,	     void *dbdata, dns_sdlzlookup_t *lookup){	isc_result_t result;	MYSQL_RES *rs = NULL;	UNUSED(driverarg);	/* run the query and get the result set from the database. */	result = mysql_get_resultset(zone, name, NULL, LOOKUP, dbdata, &rs);	/* if we didn't get a result set, log an err msg. */	if (result != ISC_R_SUCCESS) {		if (rs != NULL)			mysql_free_result(rs);		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,			      "mysql driver unable to return "			      "result set for lookup query");		return (ISC_R_FAILURE);	}	/*	 * lookup and authority result sets are processed in the same manner	 * mysql_process_rs does the job for both functions.	 */	return mysql_process_rs(lookup, rs);}/*% * 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_tmysql_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;	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 full_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 = getParameterValue(argv[1], "pass=");	socket = getParameterValue(argv[1], "socket=");	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;}/*% * destroy 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. * so we really only need to clean it up since we are not using driverarg. */static voidmysql_destroy(void *driverarg, void *dbdata){	dbinstance_t *dbi;	UNUSED(driverarg);	dbi = (dbinstance_t *) dbdata;	/* release DB connection */	if (dbi->dbconn != NULL)		mysql_close((MYSQL *) dbi->dbconn);	/* destroy DB instance */	destroy_sqldbinstance(dbi);}/* pointers to all our runtime methods. *//* this is used during driver registration *//* i.e. in dlz_mysql_init below. */static dns_sdlzmethods_t dlz_mysql_methods = {	mysql_create,	mysql_destroy,	mysql_findzone,	mysql_lookup,	mysql_authority,	mysql_allnodes,	mysql_allowzonexfr};/*% * Wrapper around dns_sdlzregister(). */isc_result_tdlz_mysql_init(void) {	isc_result_t result;	/*	 * Write debugging message to log	 */	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,		      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),		      "Registering DLZ mysql driver.");	/* Driver is always threadsafe.  Because of the way MySQL handles         * threads the MySQL driver can only be used when bind is run single         * threaded.  Using MySQL with Bind running multi-threaded is not         * allowed.  When using the MySQL driver "-n1" should always be         * passed to Bind to guarantee single threaded operation.	 */	result = dns_sdlzregister("mysql", &dlz_mysql_methods, NULL,				  DNS_SDLZFLAG_RELATIVEOWNER |				  DNS_SDLZFLAG_RELATIVERDATA |				  DNS_SDLZFLAG_THREADSAFE,				  ns_g_mctx, &dlz_mysql);	/* if we can't register the driver, there are big problems. */	if (result != ISC_R_SUCCESS) {		UNEXPECTED_ERROR(__FILE__, __LINE__,				 "dns_sdlzregister() failed: %s",				 isc_result_totext(result));		result = ISC_R_UNEXPECTED;	}	return result;}/*% * Wrapper around dns_sdlzunregister(). */voiddlz_mysql_clear(void) {	/*	 * Write debugging message to log	 */	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,		      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),		      "Unregistering DLZ mysql driver.");	/* unregister the driver. */	if (dlz_mysql != NULL)		dns_sdlzunregister(&dlz_mysql);}#endif

⌨️ 快捷键说明

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