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 + -
显示快捷键?