diff -ruN bandwidthd/bandwidthd.c bandwidthd-mysql-20050912/bandwidthd.c --- bandwidthd/bandwidthd.c 2005-09-23 16:08:12.000000000 +0200 +++ bandwidthd-mysql-20050912/bandwidthd.c 2005-08-31 02:20:59.000000000 +0200 @@ -4,6 +4,11 @@ #include #endif +#ifdef HAVE_LIBMYSQLCLIENT +#include +#include +#endif + // We must call regular exit to write out profile data, but child forks are supposed to usually // call _exit? #ifdef PROFILE @@ -261,6 +266,7 @@ int Counter; char *bd_conf = NULL; struct in_addr addr, addr2; + char *tmp; signal(SIGHUP, SIG_IGN); signal(SIGTERM, SIG_IGN); @@ -303,11 +309,16 @@ config.output_cdf = FALSE; config.recover_cdf = FALSE; config.meta_refresh = CONFIG_METAREFRESH; - config.output_database = FALSE; - config.db_connect_string = NULL; + config.output_database = DB_NONE; + config.pgsql_connect_string = NULL; config.sensor_id = "unset"; config.log_dir = LOG_DIR; config.htdocs_dir = HTDOCS_DIR; + config.mysql_host = NULL; + config.mysql_user = NULL; + config.mysql_pass = NULL; + config.mysql_dbname = NULL; + config.mysql_port = 0; openlog("bandwidthd", LOG_CONS, LOG_DAEMON); @@ -350,7 +361,9 @@ { addr.s_addr = ntohl(SubnetTable[Counter].ip); addr2.s_addr = ntohl(SubnetTable[Counter].mask); - syslog(LOG_INFO, "Monitoring subnet %s with netmask %s", inet_ntoa(addr), inet_ntoa(addr2)); + tmp = strdup(inet_ntoa(addr)); + syslog(LOG_INFO, "Monitoring subnet %s with netmask %s", tmp, inet_ntoa(addr2)); + free(tmp); } #ifdef HAVE_PCAP_FINDALLDEVS @@ -679,7 +692,7 @@ while(DataStore->FirstBlock->LatestTimestamp < timestamp - config.range) { if ((!DataStore->FirstBlock->Next) && PrevDataStore) // There is no valid block of data for this ip, so unlink the whole ip - { // Don't bother unlinking the ip if it's the first one, that's to much + { // Don't bother unlinking the ip if it's the first one, that's too much // Trouble PrevDataStore->Next = DataStore->Next; // Unlink the node free(DataStore->FirstBlock->Data); // Free the memory @@ -747,7 +760,7 @@ } PQclear(res); - res = PQexec(conn, "CREATE TABLE bd_rx_total_log (sensor_id int, ip inet, timestamp timestamp with time zone DEFAULT now(), sample_duration int, total int, icmp int, udp int, tcp int, ftp int, http int, p2p int); create index bd_rx_total_log_sensor_id_timestamp_ip_idx on bd_rx_total_log (sensor_id, timestamp);"); + res = PQexec(conn, "CREATE TABLE bd_rx_total_log (sensor_id int, ip inet, timestamp timestamp with time zone DEFAULT now(), sample_duration int, total int, icmp int, udp int, tcp int, ftp int, http int, p2p int); create index bd_rx_total_log_sensor_id_timestamp_idx on bd_rx_total_log (sensor_id, timestamp);"); if (PQresultStatus(res) != PGRES_COMMAND_OK) { syslog(LOG_ERR, "Postresql create table failed: %s", PQerrorMessage(conn)); @@ -757,7 +770,7 @@ } PQclear(res); - res = PQexec(conn, "CREATE TABLE bd_tx_total_log (sensor_id int, ip inet, timestamp timestamp with time zone DEFAULT now(), sample_duration int, total int, icmp int, udp int, tcp int, ftp int, http int, p2p int); create index bd_tx_total_log_sensor_id_timestamp_ip_idx on bd_tx_total_log (sensor_id, timestamp);"); + res = PQexec(conn, "CREATE TABLE bd_tx_total_log (sensor_id int, ip inet, timestamp timestamp with time zone DEFAULT now(), sample_duration int, total int, icmp int, udp int, tcp int, ftp int, http int, p2p int); create index bd_tx_total_log_sensor_id_timestamp_idx on bd_tx_total_log (sensor_id, timestamp);"); if (PQresultStatus(res) != PGRES_COMMAND_OK) { syslog(LOG_ERR, "Postresql create table failed: %s", PQerrorMessage(conn)); @@ -812,16 +825,16 @@ paramValues[8] = Values[8]; paramValues[9] = Values[9]; - // ************ Inititialize the db if it's not already + // ************ Initialize the db if it's not already if (!conn) { /* Connect to the database */ - conn = PQconnectdb(config.db_connect_string); + conn = PQconnectdb(config.pgsql_connect_string); /* Check to see that the backend connection was successfully made */ if (PQstatus(conn) != CONNECTION_OK) { - syslog(LOG_ERR, "Connection to database '%s' failed: %s", config.db_connect_string, PQerrorMessage(conn)); + syslog(LOG_ERR, "Connection to database '%s' failed: %s", config.pgsql_connect_string, PQerrorMessage(conn)); PQfinish(conn); conn = NULL; return; @@ -1036,10 +1049,515 @@ #endif } +#ifdef HAVE_LIBMYSQLCLIENT + +MYSQL *CheckMysqlTables(MYSQL *conn) +{ + MYSQL_RES *res; + int ret; + + ret = mysql_query(conn, "SHOW TABLES LIKE 'sensors'"); + if (ret) { + syslog(LOG_ERR, "MySQL SHOW TABLES failed: %s", mysql_error(conn)); + mysql_close(conn); + return(NULL); + } + + res = mysql_store_result(conn); + if (!res) { + syslog(LOG_ERR, "MySQL store_result failed: %s", mysql_error(conn)); + mysql_close(conn); + return(NULL); + } + + if (mysql_num_rows(res) != 1) { + mysql_free_result(res); + + ret = mysql_query(conn, "CREATE TABLE bd_rx_log (sensor_id INT, ip INT UNSIGNED, timestamp TIMESTAMP, sample_duration INT, total INT, icmp INT, udp INT, tcp INT, ftp INT, http INT, p2p INT, INDEX bd_rx_log_sensors_id_ip_timestamp_idx (sensor_id, ip, timestamp), INDEX bd_rx_log_sensor_id_timestamp_idx (sensor_id, timestamp)) TYPE=innodb"); + if (ret) { + syslog(LOG_ERR, "MySQL CREATE TABLE failed: %s", mysql_error(conn)); + mysql_close(conn); + return(NULL); + } + + ret = mysql_query(conn, "CREATE TABLE bd_tx_log (sensor_id INT, ip INT UNSIGNED, timestamp TIMESTAMP, sample_duration INT, total INT, icmp INT, udp INT, tcp INT, ftp INT, http INT, p2p INT, INDEX bd_tx_log_sensors_id_ip_timestamp_idx (sensor_id, ip, timestamp), INDEX bd_tx_log_sensor_id_timestamp_idx (sensor_id, timestamp)) TYPE=innodb"); + if (ret) { + syslog(LOG_ERR, "MySQL CREATE TABLE failed: %s", mysql_error(conn)); + mysql_close(conn); + return(NULL); + } + + ret = mysql_query(conn, "CREATE TABLE bd_rx_total_log (sensor_id INT, ip INT UNSIGNED, timestamp TIMESTAMP, sample_duration INT, total INT, icmp INT, udp INT, tcp INT, ftp INT, http INT, p2p INT, INDEX bd_rx_total_log_sensors_id_timestamp_idx (sensor_id, timestamp)) TYPE=innodb"); + if (ret) { + syslog(LOG_ERR, "MySQL CREATE TABLE failed: %s", mysql_error(conn)); + mysql_close(conn); + return(NULL); + } + + ret = mysql_query(conn, "CREATE TABLE bd_tx_total_log (sensor_id INT, ip INT UNSIGNED, timestamp TIMESTAMP, sample_duration INT, total INT, icmp INT, udp INT, tcp INT, ftp INT, http INT, p2p INT, INDEX bd_tx_total_log_sensors_id_timestamp_idx (sensor_id, timestamp)) TYPE=innodb"); + if (ret) { + syslog(LOG_ERR, "MySQL CREATE TABLE failed: %s", mysql_error(conn)); + mysql_close(conn); + return(NULL); + } + + ret = mysql_query(conn, "CREATE TABLE sensors (sensor_id INT PRIMARY KEY AUTO_INCREMENT, sensor_name VARCHAR(255) UNIQUE NOT NULL, last_connection TIMESTAMP) TYPE=innodb"); + if (ret) { + syslog(LOG_ERR, "MySQL CREATE TABLE failed: %s", mysql_error(conn)); + mysql_close(conn); + return(NULL); + } + } + else + mysql_free_result(res); + + return(conn); +} + +// MySQL prepared statements queries +#define MYSQL_TX_TOTAL "INSERT INTO bd_tx_total_log (sensor_id, sample_duration, ip, total, icmp, udp, tcp, ftp, http, p2p) VALUES(?, ?, 0, ?, ?, ?, ?, ?, ?, ?)" +#define MYSQL_TX "INSERT INTO bd_tx_log (sensor_id, sample_duration, ip, total, icmp, udp, tcp, ftp, http, p2p) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" +#define MYSQL_RX_TOTAL "INSERT INTO bd_rx_total_log (sensor_id, sample_duration, ip, total, icmp, udp, tcp, ftp, http, p2p) VALUES(?, ?, 0, ?, ?, ?, ?, ?, ?, ?)" +#define MYSQL_RX "INSERT INTO bd_rx_log (sensor_id, sample_duration, ip, total, icmp, udp, tcp, ftp, http, p2p) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" + +void MysqlStmtsClose(MYSQL_STMT **stmts) +{ + mysql_stmt_close(stmts[0]); + mysql_stmt_close(stmts[1]); + mysql_stmt_close(stmts[2]); + mysql_stmt_close(stmts[3]); +} + +MYSQL *MysqlStmtsInit(MYSQL *conn, MYSQL_STMT **stmts, + unsigned long long *data, my_ulonglong *sensor_id, uint32_t *ip) +{ + unsigned int Counter; + MYSQL_BIND binds[10]; + + stmts[0] = mysql_stmt_init(conn); + if(!stmts[0]) { + syslog(LOG_ERR, "MySQL stmt_init failed: %s", mysql_error(conn)); + mysql_close(conn); + return NULL; + } + + stmts[1] = mysql_stmt_init(conn); + if(!stmts[1]) { + syslog(LOG_ERR, "MySQL stmt_init failed: %s", mysql_error(conn)); + mysql_stmt_close(stmts[0]); + mysql_close(conn); + return NULL; + } + + stmts[2] = mysql_stmt_init(conn); + if(!stmts[2]) { + syslog(LOG_ERR, "MySQL stmt_init failed: %s", mysql_error(conn)); + mysql_stmt_close(stmts[0]); + mysql_stmt_close(stmts[1]); + mysql_close(conn); + return NULL; + } + + stmts[3] = mysql_stmt_init(conn); + if(!stmts[3]) { + syslog(LOG_ERR, "MySQL stmt_init failed: %s", mysql_error(conn)); + mysql_stmt_close(stmts[0]); + mysql_stmt_close(stmts[1]); + mysql_stmt_close(stmts[2]); + mysql_close(conn); + return NULL; + } + + if(mysql_stmt_prepare(stmts[0], MYSQL_TX_TOTAL, strlen(MYSQL_TX_TOTAL))) { + syslog(LOG_ERR, "MySQL stmt_prepare failed: %s", mysql_stmt_error(stmts[0])); + MysqlStmtsClose(stmts); + mysql_close(conn); + return NULL; + } + + if(mysql_stmt_prepare(stmts[1], MYSQL_TX, strlen(MYSQL_TX))) { + syslog(LOG_ERR, "MySQL stmt_prepare failed: %s", mysql_stmt_error(stmts[1])); + MysqlStmtsClose(stmts); + mysql_close(conn); + return NULL; + } + + if(mysql_stmt_prepare(stmts[2], MYSQL_RX_TOTAL, strlen(MYSQL_RX_TOTAL))) { + syslog(LOG_ERR, "MySQL stmt_prepare failed: %s", mysql_stmt_error(stmts[2])); + MysqlStmtsClose(stmts); + mysql_close(conn); + return NULL; + } + + if(mysql_stmt_prepare(stmts[3], MYSQL_RX, strlen(MYSQL_RX))) { + syslog(LOG_ERR, "MySQL stmt_prepare failed: %s", mysql_stmt_error(stmts[3])); + MysqlStmtsClose(stmts); + mysql_close(conn); + return NULL; + } + + memset(binds, 0, sizeof(binds)); + + // sensor_id + binds[0].buffer_type = MYSQL_TYPE_LONGLONG; + binds[0].buffer = sensor_id; + binds[0].is_unsigned = TRUE; + + // sample_duration + binds[1].buffer_type = MYSQL_TYPE_LONGLONG; + binds[1].buffer = &config.interval; + binds[1].is_unsigned = TRUE; + + // statistics + for(Counter = 2; Counter < 9; Counter++) { + binds[Counter].buffer_type = MYSQL_TYPE_LONGLONG; + binds[Counter].buffer = &data[Counter-2]; + binds[Counter].is_unsigned = TRUE; + } + + if(mysql_stmt_bind_param(stmts[0], binds)) { + syslog(LOG_ERR, "MySQL bind_param failed: %s", mysql_stmt_error(stmts[0])); + MysqlStmtsClose(stmts); + mysql_close(conn); + return NULL; + } + + if(mysql_stmt_bind_param(stmts[2], binds)) { + syslog(LOG_ERR, "MySQL bind_param failed: %s", mysql_stmt_error(stmts[2])); + MysqlStmtsClose(stmts); + mysql_close(conn); + return NULL; + } + + // ip + binds[2].buffer_type = MYSQL_TYPE_LONG; + binds[2].buffer = ip; + binds[2].is_unsigned = TRUE; + + for(Counter = 3; Counter < 10; Counter++) { + binds[Counter].buffer_type = MYSQL_TYPE_LONGLONG; + binds[Counter].buffer = &data[Counter-3]; + binds[Counter].is_unsigned = TRUE; + } + + if(mysql_stmt_bind_param(stmts[1], binds)) { + syslog(LOG_ERR, "MySQL bind_param failed: %s", mysql_stmt_error(stmts[1])); + MysqlStmtsClose(stmts); + mysql_close(conn); + return NULL; + } + + if(mysql_stmt_bind_param(stmts[3], binds)) { + syslog(LOG_ERR, "MySQL bind_param failed: %s", mysql_stmt_error(stmts[3])); + MysqlStmtsClose(stmts); + mysql_close(conn); + return NULL; + } + + return conn; +} + +#endif // HAVE_LIBMYSQLCLIENT + +void StoreIPDataInMysql(struct IPData IncData[]) +{ +#ifdef HAVE_LIBMYSQLCLIENT + struct IPData *IPData; + unsigned int Counter; + struct Statistics *Stats; + + static MYSQL *conn = NULL; + static MYSQL mysql; + static MYSQL_STMT *stmts[4]; + static my_ulonglong sensor_id; + static unsigned long long data[7]; + static uint32_t ip; + MYSQL_RES *res; + MYSQL_ROW row; + unsigned long *lengths; + + int ret; + char sql[1024]; + char tmp[20]; + char *sensor_name; + + if (!config.output_database == DB_MYSQL) + return; + + // ************ Initialize the db if it's not already + if (!conn) { + if(!mysql_init(&mysql)) { + syslog(LOG_ERR, "Insufficient memory to allocate MYSQL structure"); + return; + } + + /* Connect to the database */ + conn = mysql_real_connect(&mysql, config.mysql_host, config.mysql_user, + config.mysql_pass, config.mysql_dbname, config.mysql_port, NULL, 0); + + /* Check to see that the backend connection was successfully made */ + if (!conn) { + syslog(LOG_ERR, "Connection to database '%s' on '%s' with user '%s' failed: %s", + config.mysql_dbname, config.mysql_host, config.mysql_user, mysql_error(&mysql)); + mysql_close(&mysql); // Deallocates memory used by MYSQL structure + return; + } + + conn = CheckMysqlTables(conn); + if (!conn) + return; + + conn = MysqlStmtsInit(conn, stmts, data, &sensor_id, &ip); + if (!conn) + return; + + // Escape sensor_id + sensor_name = (char *) malloc(2*strlen(config.sensor_id)+1); + mysql_real_escape_string(conn, sensor_name, config.sensor_id, strlen(config.sensor_id)); + + // Retrieve sensor_id from database + snprintf(sql, sizeof(sql), "SELECT sensor_id FROM sensors WHERE sensor_name='%s'", sensor_name); + ret = mysql_query(conn, sql); + if(ret) { + syslog(LOG_ERR, "MySQL SELECT failed: %s", mysql_error(conn)); + free(sensor_name); + MysqlStmtsClose(stmts); + mysql_close(conn); + conn = NULL; + return; + } + + res = mysql_store_result(conn); + if(!res) { + syslog(LOG_ERR, "MySQL store_result failed: %s", mysql_error(conn)); + free(sensor_name); + MysqlStmtsClose(stmts); + mysql_close(conn); + conn = NULL; + return; + } + + // Sensor is already in database + if(mysql_num_rows(res)) { + // No longer needed + free(sensor_name); + + row = mysql_fetch_row(res); + if(!row) { + syslog(LOG_ERR, "MySQL fetch_row failed: %s", mysql_error(conn)); + mysql_free_result(res); + MysqlStmtsClose(stmts); + mysql_close(conn); + conn = NULL; + return; + } + + if(!row[0]) { + syslog(LOG_ERR, "MySQL NULL value encountered"); + mysql_free_result(res); + MysqlStmtsClose(stmts); + mysql_close(conn); + conn = NULL; + return; + } + + lengths = mysql_fetch_lengths(res); + if(!lengths) { + syslog(LOG_ERR, "MySQL fetch_lengths failed: %s", mysql_error(conn)); + mysql_free_result(res); + MysqlStmtsClose(stmts); + mysql_close(conn); + return; + } + + snprintf(tmp, sizeof(tmp), "%.*s", (int) lengths[0], row[0]); + sensor_id = atoll(tmp); + + mysql_free_result(res); + } else { // First connection of this sensor, create new entry in sensors table + mysql_free_result(res); + snprintf(sql, sizeof(sql), "INSERT INTO sensors (sensor_name, last_connection, sensor_id) VALUES('%s', NOW(), NULL)", sensor_name); + free(sensor_name); + ret = mysql_query(conn, sql); + if(ret) { + syslog(LOG_ERR, "MySQL INSERT failed: %s", mysql_error(conn)); + MysqlStmtsClose(stmts); + mysql_close(conn); + conn = NULL; + return; + } + + sensor_id = mysql_insert_id(conn); + } + } + + // Begin transaction + ret = mysql_query(conn, "BEGIN"); + if(ret) { + syslog(LOG_ERR, "MySQL BEGIN failed: %s", mysql_error(conn)); + MysqlStmtsClose(stmts); + mysql_close(conn); + conn = NULL; + return; + } + + snprintf(sql, sizeof(sql), "UPDATE sensors SET last_connection = NOW() WHERE sensor_id = %llu", sensor_id); + ret = mysql_query(conn, sql); + if(ret) { + syslog(LOG_ERR, "MySQL UPDATE failed: %s", mysql_error(conn)); + MysqlStmtsClose(stmts); + mysql_close(conn); + conn = NULL; + return; + } + + for(Counter = 0; Counter < IpCount; Counter++) { + IPData = &IncData[Counter]; + + Stats = &(IPData->Send); + if (Stats->total > 512) { + data[0] = (long long unsigned int) ((((double) Stats->total) / 1024.0) + 0.5); + data[1] = (long long unsigned int) ((((double) Stats->icmp) / 1024.0) + 0.5); + data[2] = (long long unsigned int) ((((double) Stats->udp) / 1024.0) + 0.5); + data[3] = (long long unsigned int) ((((double) Stats->tcp) / 1024.0) + 0.5); + data[4] = (long long unsigned int) ((((double) Stats->ftp) / 1024.0) + 0.5); + data[5] = (long long unsigned int) ((((double) Stats->http) / 1024.0) + 0.5); + data[6] = (long long unsigned int) ((((double) Stats->p2p) / 1024.0) + 0.5); + + if (IPData->ip == 0) { + if(mysql_stmt_execute(stmts[0])) { + syslog(LOG_ERR, "MySQL INSERT failed: %s", mysql_stmt_error(stmts[0])); + if(mysql_stmt_errno(stmts[0]) == CR_SERVER_LOST) { + // First, deallocate memory from previously used prepared statements + MysqlStmtsClose(stmts); + MysqlStmtsInit(conn, stmts, data, &sensor_id, &ip); + if(mysql_stmt_execute(stmts[0])) { + syslog(LOG_ERR, "MySQL INSERT retry failed: %s", mysql_stmt_error(stmts[0])); + MysqlStmtsClose(stmts); + mysql_close(conn); + conn = NULL; + return; + } else + // Not quite reconnect since MySQL library handles it automatically, + // but rather reinitialization of prepared statements + syslog(LOG_ERR, "Reconnect succeded"); + } else { + MysqlStmtsClose(stmts); + mysql_close(conn); + conn = NULL; + return; + } + } + } + else { + ip = IPData->ip; + if(mysql_stmt_execute(stmts[1])) { + syslog(LOG_ERR, "MySQL INSERT failed: %s", mysql_stmt_error(stmts[1])); + if(mysql_stmt_errno(stmts[1]) == CR_SERVER_LOST) { + // First, deallocate memory from previously used prepared statements + MysqlStmtsClose(stmts); + MysqlStmtsInit(conn, stmts, data, &sensor_id, &ip); + if(mysql_stmt_execute(stmts[1])) { + syslog(LOG_ERR, "MySQL INSERT retry failed: %s", mysql_stmt_error(stmts[1])); + MysqlStmtsClose(stmts); + mysql_close(conn); + conn = NULL; + return; + } else + // Not quite reconnect since MySQL library handles it automatically, + // but rather reinitialization of prepared statements + syslog(LOG_ERR, "Reconnect succeded"); + } else { + MysqlStmtsClose(stmts); + mysql_close(conn); + conn = NULL; + return; + } + } + } + } + + Stats = &(IPData->Receive); + if (Stats->total > 512) { + data[0] = (long long unsigned int) ((((double) Stats->total) / 1024.0) + 0.5); + data[1] = (long long unsigned int) ((((double) Stats->icmp) / 1024.0) + 0.5); + data[2] = (long long unsigned int) ((((double) Stats->udp) / 1024.0) + 0.5); + data[3] = (long long unsigned int) ((((double) Stats->tcp) / 1024.0) + 0.5); + data[4] = (long long unsigned int) ((((double) Stats->ftp) / 1024.0) + 0.5); + data[5] = (long long unsigned int) ((((double) Stats->http) / 1024.0) + 0.5); + data[6] = (long long unsigned int) ((((double) Stats->p2p) / 1024.0) + 0.5); + if (IPData->ip == 0) { + if(mysql_stmt_execute(stmts[2])) { + syslog(LOG_ERR, "MySQL INSERT failed: %s", mysql_stmt_error(stmts[2])); + if(mysql_stmt_errno(stmts[2]) == CR_SERVER_LOST) { + // First, deallocate memory from previously used prepared statements + MysqlStmtsClose(stmts); + MysqlStmtsInit(conn, stmts, data, &sensor_id, &ip); + if(mysql_stmt_execute(stmts[2])) { + syslog(LOG_ERR, "MySQL INSERT retry failed: %s", mysql_stmt_error(stmts[2])); + MysqlStmtsClose(stmts); + mysql_close(conn); + conn = NULL; + return; + } else + // Not quite reconnect since MySQL library handles it automatically, + // but rather reinitialization of prepared statements + syslog(LOG_ERR, "Reconnect succeded"); + } else { + MysqlStmtsClose(stmts); + mysql_close(conn); + conn = NULL; + return; + } + } + } else { + ip = IPData->ip; + if(mysql_stmt_execute(stmts[3])) { + syslog(LOG_ERR, "MySQL INSERT failed: %s", mysql_stmt_error(stmts[3])); + if(mysql_stmt_errno(stmts[3]) == CR_SERVER_LOST) { + // First, deallocate memory from previously used prepared statements + MysqlStmtsClose(stmts); + MysqlStmtsInit(conn, stmts, data, &sensor_id, &ip); + if(mysql_stmt_execute(stmts[3])) { + syslog(LOG_ERR, "MySQL INSERT retry failed: %s", mysql_stmt_error(stmts[3])); + MysqlStmtsClose(stmts); + mysql_close(conn); + conn = NULL; + return; + } else + // Not quite reconnect since MySQL library handles it automatically, + // but rather reinitialization of prepared statements + syslog(LOG_ERR, "Reconnect succeded"); + } else { + MysqlStmtsClose(stmts); + mysql_close(conn); + conn = NULL; + return; + } + } + } + } + } + + ret = mysql_query(conn, "COMMIT"); + if(ret) { + syslog(LOG_ERR, "MySQL COMMIT failed: %s", mysql_error(conn)); + MysqlStmtsClose(stmts); + mysql_close(conn); + conn = NULL; + return; + } +#else + syslog(LOG_ERR, "MySQL logging selected but MySQL support is not compiled into binary. Please check the documentation in README, distributed with this software."); +#endif // HAVE_LIBMYSQLCLIENT +} + void StoreIPDataInDatabase(struct IPData IncData[]) { if (config.output_database == DB_PGSQL) - StoreIPDataInPostgresql(IncData); + StoreIPDataInPostgresql(IncData); + else if (config.output_database == DB_MYSQL) + StoreIPDataInMysql(IncData); } void StoreIPDataInCDF(struct IPData IncData[]) diff -ruN bandwidthd/bandwidthd.h bandwidthd-mysql-20050912/bandwidthd.h --- bandwidthd/bandwidthd.h 2005-09-23 16:08:12.000000000 +0200 +++ bandwidthd-mysql-20050912/bandwidthd.h 2005-08-28 16:22:19.000000000 +0200 @@ -1,3 +1,6 @@ +#ifndef BANDWIDTHD_H +#define BANDWIDTHD_H + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -100,8 +103,8 @@ #define MAX_FILENAME 1024 +#define DB_NONE 0 #define DB_PGSQL 1 -// No mysql support yet #define DB_MYSQL 2 struct config @@ -119,10 +122,15 @@ char tag; unsigned int meta_refresh; int output_database; - char *db_connect_string; + char *pgsql_connect_string; char *sensor_id; char *log_dir; char *htdocs_dir; + char *mysql_host; + char *mysql_user; + char *mysql_pass; + char *mysql_dbname; + unsigned int mysql_port; }; struct SubnetData @@ -226,3 +234,5 @@ // ************ Misc inline void DstCredit(uint32_t ipaddr, unsigned int psize); void MakeIndexPages(int NumGraphs, struct SummaryData *SummaryData[]); + +#endif // BANDWIDTHD_H diff -ruN bandwidthd/CHANGELOG bandwidthd-mysql-20050912/CHANGELOG --- bandwidthd/CHANGELOG 2005-09-23 16:08:12.000000000 +0200 +++ bandwidthd-mysql-20050912/CHANGELOG 2005-08-20 19:09:17.000000000 +0200 @@ -1,3 +1,6 @@ +Config option 'output_database' to select database type +Netmask is now correctly displayed in syslog +MySQL support Make file tweaks Adhere more strictly to GNU coding standards for directories Optional htdocs and log file locations specified at configure time diff -ruN bandwidthd/configure.in bandwidthd-mysql-20050912/configure.in --- bandwidthd/configure.in 2005-09-23 16:08:12.000000000 +0200 +++ bandwidthd-mysql-20050912/configure.in 2005-08-30 23:18:22.000000000 +0200 @@ -45,11 +45,14 @@ # Required for openbsd png library AC_CHECK_LIB(m, pow) +# Required for linux png library +AC_CHECK_LIB(z, deflate) + # Required for gd under netbsd AC_CHECK_LIB(iconv, libiconv_open) # Required Libraries -AC_CHECK_LIB(png, png_read_info, ,[AC_MSG_ERROR([Bandwidthd requires but cannot libpng])]) +AC_CHECK_LIB(png, png_read_info, ,[AC_MSG_ERROR([Bandwidthd requires but cannot find libpng])]) AC_CHECK_LIB(gd, gdImageCreate, ,[AC_MSG_ERROR([Bandwidthd requires but cannot find libgd])]) AC_CHECK_LIB(pcap, pcap_open_live, , [AC_CHECK_LIB(wpcap, pcap_open_live, ,[AC_MSG_ERROR([Bandwidthd requires but cannot find libpcap])])]) @@ -58,7 +61,16 @@ AC_CHECK_FILE(/usr/lib, LDFLAGS="$LDFLAGS -L/usr/lib") AC_CHECK_FILE(/usr/include/pgsql, CPPFLAGS="$CPPFLAGS -I/usr/include/pgsql") AC_CHECK_LIB(pq, PQconnectdb, - [AC_CHECK_LIB(pq,PQexecParams, ,AC_MSG_WARN([libpq exists but is too old... bandwidthd requires support for PQexecParams]))]) + [AC_CHECK_LIB(pq,PQexecParams, ,AC_MSG_ERROR([libpq exists but is too old... bandwidthd requires support for PQexecParams]))]) + +# MySQL support +AC_CHECK_PROG(MYSQL_CONFIG, mysql_config, yes, no) +if test "$MYSQL_CONFIG" = "yes"; then + CPPFLAGS="$CFLAGS `mysql_config --include`" + LDFLAGS="$LDFLAGS `mysql_config --libs`" +fi +AC_CHECK_LIB(mysqlclient, mysql_real_connect, + [AC_CHECK_LIB(mysqlclient, mysql_stmt_init, ,AC_MSG_ERROR([bandwidthd requires MySQL prepared statements (MySQL 4.1.x)]))]) # Checks for header files. AC_HEADER_DIRENT @@ -77,6 +89,9 @@ AC_CHECK_HEADERS([arpa/inet.h errno.h netdb.h netinet/in.h stddef.h stdlib.h string.h sys/socket.h sys/time.h sys/wait.h syslog.h unistd.h],, [AC_MSG_ERROR([Bandwidthd cannot find some header files])]) +if test "$ac_cv_lib_mysqlclient_mysql_stmt_init" = "yes"; then + AC_CHECK_HEADERS(mysql.h errmsg.h, ,[AC_MSG_ERROR([Bandwidthd cannot find MySQL headers])]) +fi #Headers missing on cygwin AC_CHECK_HEADERS([arpa/nameser.h]) diff -ruN bandwidthd/conf.l bandwidthd-mysql-20050912/conf.l --- bandwidthd/conf.l 2005-09-23 16:08:12.000000000 +0200 +++ bandwidthd-mysql-20050912/conf.l 2005-08-20 19:09:17.000000000 +0200 @@ -26,8 +26,17 @@ filter { return TOKFILTER; } meta_refresh { return TOKMETAREFRESH; } pgsql_connect_string { return TOKPGSQLCONNECTSTRING; } +mysql_host { return TOKMYSQLHOST; } +mysql_user { return TOKMYSQLUSER; } +mysql_pass { return TOKMYSQLPASS; } +mysql_dbname { return TOKMYSQLDBNAME; } +mysql_port { return TOKMYSQLPORT; } sensor_id { return TOKSENSORID; } htdocs_dir { return TOKHTDOCSDIR; } log_dir { return TOKLOGDIR; } +none { return TOKNONE; } +pgsql { return TOKPGSQL; } +mysql { return TOKMYSQL; } +output_database { return TOKOUTPUTDATABASE; } . { return TOKJUNK; } %% diff -ruN bandwidthd/conf.y bandwidthd-mysql-20050912/conf.y --- bandwidthd/conf.y 2005-09-23 16:08:12.000000000 +0200 +++ bandwidthd-mysql-20050912/conf.y 2005-08-20 19:09:17.000000000 +0200 @@ -34,6 +34,8 @@ %token TOKJUNK TOKSUBNET TOKDEV TOKSLASH TOKSKIPINTERVALS TOKGRAPHCUTOFF %token TOKPROMISC TOKOUTPUTCDF TOKRECOVERCDF TOKGRAPH TOKNEWLINE TOKFILTER %token TOKMETAREFRESH TOKPGSQLCONNECTSTRING TOKSENSORID TOKHTDOCSDIR TOKLOGDIR +%token TOKMYSQLHOST TOKMYSQLUSER TOKMYSQLPASS TOKMYSQLDBNAME TOKMYSQLPORT +%token TOKNONE TOKPGSQL TOKMYSQL TOKOUTPUTDATABASE %union { int number; @@ -81,6 +83,18 @@ htdocs_dir | log_dir + | + mysql_host + | + mysql_user + | + mysql_pass + | + mysql_dbname + | + mysql_port + | + output_database ; subnet: @@ -227,9 +241,60 @@ pgsql_connect_string: TOKPGSQLCONNECTSTRING string { - config.db_connect_string = $2; + config.pgsql_connect_string = $2; + } + ; + +mysql_host: + TOKMYSQLHOST string + { + config.mysql_host = $2; + } + ; + +mysql_user: + TOKMYSQLUSER string + { + config.mysql_user = $2; + } + ; + +mysql_pass: + TOKMYSQLPASS string + { + config.mysql_pass = $2; + } + ; + +mysql_dbname: + TOKMYSQLDBNAME string + { + config.mysql_dbname = $2; + } + ; + +mysql_port: + TOKMYSQLPORT NUMBER + { + config.mysql_port = $2; + } + ; + +output_database: + TOKOUTPUTDATABASE TOKNONE + { + config.output_database = DB_NONE; + } + | + TOKOUTPUTDATABASE TOKPGSQL + { config.output_database = DB_PGSQL; } + | + TOKOUTPUTDATABASE TOKMYSQL + { + config.output_database = DB_MYSQL; + } ; sensor_id: diff -ruN bandwidthd/graph.c bandwidthd-mysql-20050912/graph.c --- bandwidthd/graph.c 2005-09-23 16:08:12.000000000 +0200 +++ bandwidthd-mysql-20050912/graph.c 2005-08-19 20:17:17.000000000 +0200 @@ -707,8 +707,8 @@ snprintf(Buffer, 30, "Sent %.1f KBytes", (double)SummaryData->TotalSent/1024.0); else snprintf(Buffer, 30, "Sent %.1f MBytes", (double)SummaryData->TotalSent/(1024.0*1024.0)); - gdImageString(im, gdFontSmall, XOFFSET+5, YHEIGHT-20, Buffer, black); - gdImageString(im, gdFontSmall, XWIDTH/2+XOFFSET/2, YHEIGHT-20, Buffer2, black); + gdImageString(im, gdFontSmall, XOFFSET+5, YHEIGHT-20, (unsigned char *) Buffer, black); + gdImageString(im, gdFontSmall, XWIDTH/2+XOFFSET/2, YHEIGHT-20, (unsigned char *) Buffer2, black); if (ReceivedPeak < 1024/8) snprintf(Buffer2, 50, "Peak Receive Rate: %.1f Bits/sec", (double)ReceivedPeak*8); @@ -722,8 +722,8 @@ snprintf(Buffer, 30, "Received %.1f KBytes", (double)SummaryData->TotalReceived/1024.0); else snprintf(Buffer, 30, "Received %.1f MBytes", (double)SummaryData->TotalReceived/(1024.0*1024.0)); - gdImageString(im2, gdFontSmall, XOFFSET+5, YHEIGHT-20, Buffer, black2); - gdImageString(im2, gdFontSmall, XWIDTH/2+XOFFSET/2, YHEIGHT-20, Buffer2, black2); + gdImageString(im2, gdFontSmall, XOFFSET+5, YHEIGHT-20, (unsigned char *) Buffer, black2); + gdImageString(im2, gdFontSmall, XWIDTH/2+XOFFSET/2, YHEIGHT-20, (unsigned char *) Buffer2, black2); return(YMax); } @@ -772,7 +772,7 @@ gdImageLine(im, XOFFSET, y, XWIDTH, y, black); snprintf(buffer, 20, "%4.1f %cbits/s", (float)(8.0*YTic)/Divisor, YLegend); - gdImageString(im, gdFontSmall, 3, y-7, buffer, black); + gdImageString(im, gdFontSmall, 3, y-7, (unsigned char *) buffer, black); YTic += YStep; } @@ -824,7 +824,7 @@ timestruct = localtime((time_t *)&MarkTime); strftime(buffer, 100, "%a, %b %d", timestruct); - gdImageString(im, gdFontSmall, x-30, YHEIGHT-YOFFSET+10, buffer, black); + gdImageString(im, gdFontSmall, x-30, YHEIGHT-YOFFSET+10, (unsigned char *) buffer, black); // Calculate Next x MarkTime += (24*60*60); @@ -858,7 +858,7 @@ timestruct = localtime((time_t *)&MarkTime); strftime(buffer, 100, "%b", timestruct); - gdImageString(im, gdFontSmall, x-6, YHEIGHT-YOFFSET+10, buffer, black); + gdImageString(im, gdFontSmall, x-6, YHEIGHT-YOFFSET+10, (unsigned char *) buffer, black); // Calculate Next x timestruct->tm_mon++; diff -ruN bandwidthd/INSTALL.Unix bandwidthd-mysql-20050912/INSTALL.Unix --- bandwidthd/INSTALL.Unix 2005-09-23 16:08:12.000000000 +0200 +++ bandwidthd-mysql-20050912/INSTALL.Unix 2005-08-20 19:50:28.000000000 +0200 @@ -1,16 +1,42 @@ #### INSTALLATION # -You need 3 dependencies to make Bandwidthd work: +You need one dependency to make Bandwidthd work: libpcap from http://www.tcpdump.org/ -libpng from http://www.libpng.org/ + +Chances are you already have it, if in doubt +just run configure and see what it complains about. + +Additionally you will need at least one of the following three: + +1. libgd from http://www.boutell.com/gd/ +linpng from http://www.libpng.org/ + +This will enable bandwidthd to make static graphs +at specified time interval. -Chances are you already have all three, if in doubt -just run configure and see what it complains about. If -you are missing libpng, make sure you re-install libgd +If you are missing libpng, make sure you re-install libgd after you install it. +2. +MySQL from http://www.mysql.com/ +PHP from http://www.php.net/ +Apache from http://www.apache.org/ + +This will enable bandwidthd to store statistics in MySQL, +graphs will be created on demand by webpage in PHP. + +3. +PostgreSQL from http://www.postgresql.org/ +PHP from http://www.php.net/ +Apache from http://www.apache.org/ + +This will enable bandwidthd to store statistics in PostgreSQL, +graphs will be created on demand by webpage in PHP. + + + Configure and install the Bandwidthd source: ./configure && make install diff -ruN bandwidthd/README bandwidthd-mysql-20050912/README --- bandwidthd/README 2005-09-23 16:08:12.000000000 +0200 +++ bandwidthd-mysql-20050912/README 2005-08-20 19:09:17.000000000 +0200 @@ -172,7 +172,7 @@ Bandwidthd uses very little ram and CPU. In addition, multiple sensors can record to the same database. -2. The database system. Currently Bandwidthd only supports Postgresql. +2. The database system. Currently Bandwidthd supports PostgreSQL and MySQL. 3. The webserver and php application. Bundled with Bandwidthd in the "phphtdocs" directory is a php application that reports on and graphs the contents of the database. @@ -189,8 +189,8 @@ INSTRUCTIONS -As a prerequisite for these instructions, you must have Postgresql installed and working, -as well as a web server that supports php. +As a prerequisite for these instructions, you must have PostgreSQL or MySQL installed +and working, as well as a web server that supports php. Setup: 1. Create a database for Bandwidthd. You will need to create users that can access the @@ -198,9 +198,25 @@ 2. Add the following lines to your bandwidthd.conf file: +If you want to use PostgreSQL +# Database type, possible values, pgsql, mysql or none +output_database pgsql # Standard postgres connect string, just like php, see postgres docs for # details pgsql_connect_string "user = someuser dbname = mydb host = databaseserver.com" + + +If you want to use MySQL: +# Database type, possible values, pgsql, mysql or none +output_database mysql +mysql_host "localhost" +mysql_user "bandwidthd" +mysql_pass "password" +mysql_dbname "bandwidthd" +# Port 0 means, that the default port is used +#mysql_port 0 + +And some common options: # Arbitrary sensor name, I recommend the sensors fully qualified domain # name sensor_id "sensor1.mycompany.com" @@ -217,24 +233,30 @@ Web Server Setup: 1. Copy the contents of phphtdocs into your web tree some where. -2. Edit config.conf to set your db connect string +2. Edit config.conf to set your db type and parameters. You should now be able to access the web application and see you graphs. All graphing is done by graph.php, all parameters are passed to it in it's url. You can create custom urls to pull custom graphs from your own index pages, or use the canned reporting system. -In addition, you should schedule bd_pgsql_purge.sh to run every so often. I recomend -running it weekly. This script outputs sql statements that aggregate the older -data points in your database in order to reduce the amount of data that needs to -be slogged through in order to generate yearly, monthly, and weekly graphs. +In addition, you should schedule bd_pgsql_purge.sh or bd_mysql_purge.sh to run every +so often. I recomend running it weekly. This script outputs sql statements that +aggregate the older data points in your database in order to reduce the amount +of data that needs to be slogged through in order to generate yearly, monthly, +and weekly graphs. -Example: +Example for PostgreSQL: bd_pgsql_purge.sh | psql bandwidthd postgres - Will connect to the bandwidthd database on local host as the user postgres and summarize the data. +Example for MySQL: +bd_mysql_purge.sh | mysql -umysql -ppass bandwidthd +Will connect to the bandwidthd database on localhost as the user mysql +with password pass and summarize the data. + + # KNOWN BUGS AND TROUBLESHOOTING # If Bandwidthd shows you nothing but a message saying "Bandwidthd has nothing to graph", diff -ruN bandwidthd/etc/bandwidthd.conf bandwidthd-mysql-20050912/etc/bandwidthd.conf --- bandwidthd/etc/bandwidthd.conf 2005-09-23 16:08:12.000000000 +0200 +++ bandwidthd-mysql-20050912/etc/bandwidthd.conf 2005-08-20 19:09:17.000000000 +0200 @@ -57,5 +57,27 @@ #Set the static html output directory #htdocs_dir "/usr/local/var/bandwidthd/htdocs" +#################################################### +# Database options +# You should probably change both output_cdf and graph to false +# if you are using database. +# Database type, possible values, pgsql, mysql or none +#output_database none +# Arbitrary sensor name, I recommend the sensors fully qualified domain +# name +#sensor_id "sensor1" + +# PostgreSQL +# Standard postgres connect string, just like php, see postgres docs for +# details +#pgsql_connect_string "user = someuser dbname = mydb host = databaseserver.com" + +# MySQL +#mysql_host "localhost" +#mysql_user "bandwidthd" +#mysql_pass "password" +#mysql_dbname "bandwidthd" +# Port 0 means, that the default port is used +#mysql_port 0 diff -ruN bandwidthd/phphtdocs/bd_mysql_purge.sh bandwidthd-mysql-20050912/phphtdocs/bd_mysql_purge.sh --- bandwidthd/phphtdocs/bd_mysql_purge.sh 1970-01-01 01:00:00.000000000 +0100 +++ bandwidthd-mysql-20050912/phphtdocs/bd_mysql_purge.sh 2005-09-09 14:14:26.000000000 +0200 @@ -0,0 +1,59 @@ +echo -e "bd_rx_log \n bd_tx_log \n bd_rx_total_log \n bd_tx_total_log" | while read TABLE; +do +cat << EOF +BEGIN; + +INSERT INTO $TABLE (sensor_id, ip, timestamp, sample_duration, total, icmp, udp, tcp, ftp, http, p2p) +SELECT sensor_id, ip, +IF(EXTRACT(hour FROM timestamp) >= 12, DATE_FORMAT(timestamp, "%y-%m-%d 00:00:00") + INTERVAL 12 hour, + DATE_FORMAT(timestamp, "%y-%m-%d 00:00:00")) + INTERVAL 12 hour, +60*60*12, SUM(total), SUM(icmp), SUM(udp), SUM(tcp), SUM(ftp), SUM(http), SUM(p2p) +FROM $TABLE +WHERE sample_duration < 60*60*12 +AND timestamp < NOW() - INTERVAL 35 day +GROUP BY sensor_id, ip, +IF(EXTRACT(hour FROM timestamp) >= 12, DATE_FORMAT(timestamp, "%y-%m-%d 00:00:00") + INTERVAL 12 hour, + DATE_FORMAT(timestamp, "%y-%m-%d 00:00:00")); + +DELETE FROM $TABLE WHERE sample_duration < 60*60*12 AND timestamp < NOW() - INTERVAL 35 day; + +COMMIT; + + +BEGIN; + +INSERT INTO $TABLE (sensor_id, ip, timestamp, sample_duration, total, icmp, udp, tcp, ftp, http, p2p) +SELECT sensor_id, ip, +DATE_FORMAT(timestamp,"%y-%m-%d %H:00:00") + INTERVAL 1 hour, +60*60, SUM(total), SUM(icmp), SUM(udp), SUM(tcp), SUM(ftp), SUM(http), SUM(p2p) +FROM $TABLE +WHERE sample_duration < 60*60 +AND timestamp < NOW() - INTERVAL 7 day +GROUP BY sensor_id, ip, DATE_FORMAT(timestamp,"%y-%m-%d %H:00:00"); + +DELETE FROM $TABLE WHERE sample_duration < 60*60 AND timestamp < NOW() - INTERVAL 7 day; + +COMMIT; + + +BEGIN; + +INSERT INTO $TABLE (sensor_id, ip, timestamp, sample_duration, total, icmp, udp, tcp, ftp, http, p2p) +SELECT sensor_id, ip, +DATE_FORMAT(timestamp,"%y-%m-%d %H:00:00") + INTERVAL TRUNCATE(EXTRACT(minute FROM timestamp),-1) minute ++ INTERVAL 10 minute, +10*60, SUM(total), SUM(icmp), SUM(udp), SUM(tcp), SUM(ftp), SUM(http), SUM(p2p) +FROM $TABLE +WHERE sample_duration < 10*60 +AND timestamp < NOW() - INTERVAL 2 day +GROUP BY sensor_id, ip, +DATE_FORMAT(timestamp,"%y-%m-%d %H:00:00") + INTERVAL TRUNCATE(EXTRACT(minute FROM timestamp),-1) minute; + +DELETE FROM $TABLE WHERE sample_duration < 10*60 AND timestamp < NOW() - INTERVAL 2 day; + +COMMIT; + +OPTIMIZE TABLE $TABLE; +ANALYZE TABLE $TABLE; +EOF +done diff -ruN bandwidthd/phphtdocs/config.conf bandwidthd-mysql-20050912/phphtdocs/config.conf --- bandwidthd/phphtdocs/config.conf 2005-09-23 16:08:12.000000000 +0200 +++ bandwidthd-mysql-20050912/phphtdocs/config.conf 2005-08-20 20:48:03.000000000 +0200 @@ -3,5 +3,17 @@ define("DFLT_HEIGHT", 256); define("DFLT_INTERVAL", INT_DAILY); -$db_connect_string = "user = root dbname = bandwidthd" -?> \ No newline at end of file +// Select type of database you are using +// Possible values are DB_PGSQL and DB_MYSQL +$dbtype = DB_MYSQL; + +// Configuration for PostgreSQL +$pgsql_connect_string = "user = root dbname = bandwidthd"; + +// Configuration for MySQL +// You can specify port after semicolon, for example "localhost:4067" +$mysql_host = "localhost"; +$mysql_user = "bandwidthd"; +$mysql_pass = "password"; +$mysql_dbname = "bandwidthd"; +?> diff -ruN bandwidthd/phphtdocs/details.php bandwidthd-mysql-20050912/phphtdocs/details.php --- bandwidthd/phphtdocs/details.php 2005-09-23 16:08:12.000000000 +0200 +++ bandwidthd-mysql-20050912/phphtdocs/details.php 2005-09-09 15:48:24.000000000 +0200 @@ -26,7 +26,7 @@ $db = ConnectDb(); -if ($ip == "0.0.0.0/0") +if ($ip == "0.0.0.0/0" || $ip == "0/0") { $rxtable = "bd_rx_total_log"; $txtable = "bd_tx_total_log"; @@ -37,7 +37,43 @@ $txtable = "bd_tx_log"; } -$sql = "select rx.scale as rxscale, tx.scale as txscale, tx.total+rx.total as total, tx.total as sent, +if($dbtype == DB_PGSQL) { + $res = pg_query("SELECT sensor_id FROM sensors WHERE sensor_name='".bd_escape_string($sensor_name)."'"); + if(pg_num_rows($res) != 1) { + echo "No such sensor\n"; + exit; + } + $o = pg_fetch_object($res); + $sensor_id = $o->sensor_id; +} else if($dbtype == DB_MYSQL) { + $res = mysql_query("SELECT sensor_id FROM sensors WHERE sensor_name='".bd_escape_string($sensor_name)."'"); + if(mysql_num_rows($res) != 1) { + echo "No such sensor\n"; + exit; + } + $o = mysql_fetch_object($res); + $sensor_id = $o->sensor_id; +} else { + echo "Unknown database type\n"; + exit; +} + +if($dbtype == DB_PGSQL) { + $sql_ip = "and ip <<= '$ip'"; +} else if($dbtype == DB_MYSQL) { + $p = parse_addr($ip); + if($p["mask"] == ip2long("255.255.255.255")) { + $sql_ip = "and ip = ".sprintf("%u", $p["ip"]); + } else if($p["mask"] == 0) { + $sql_ip = ""; + } else { + $net = $p["ip"] & $p["mask"]; + $bcast = $net | ~$p["mask"]; + $sql_ip = "and ip between ".sprintf("%u", $net)." and ".sprintf("%u",$bcast); + } +} + +$pg_sql = "select rx.scale as rxscale, tx.scale as txscale, tx.total+rx.total as total, tx.total as sent, rx.total as received, tx.tcp+rx.tcp as tcp, tx.udp+rx.udp as udp, tx.icmp+rx.icmp as icmp, tx.http+rx.http as http, tx.p2p+rx.p2p as p2p, tx.ftp+rx.ftp as ftp @@ -45,25 +81,52 @@ (SELECT ip, max(total/sample_duration)*8 as scale, sum(total) as total, sum(tcp) as tcp, sum(udp) as udp, sum(icmp) as icmp, sum(http) as http, sum(p2p) as p2p, sum(ftp) as ftp -from sensors, $txtable -where sensor_name = '$sensor_name' -and sensors.sensor_id = ".$txtable.".sensor_id -and ip <<= '$ip' +from $txtable +where sensor_id = $sensor_id +$sql_ip group by ip) as tx, (SELECT ip, max(total/sample_duration)*8 as scale, sum(total) as total, sum(tcp) as tcp, sum(udp) as udp, sum(icmp) as icmp, sum(http) as http, sum(p2p) as p2p, sum(ftp) as ftp -from sensors, $rxtable -where sensor_name = '$sensor_name' -and sensors.sensor_id = ".$rxtable.".sensor_id -and ip <<= '$ip' +from $rxtable +where sensor_id = $sensor_id +$sql_ip group by ip) as rx where tx.ip = rx.ip;"; -//echo "
$sql
";exit(0); -$result = pg_query($sql); + +$my_sql = "select rx.scale as rxscale, tx.scale as txscale, tx.total+rx.total as total, tx.total as sent, +rx.total as received, tx.tcp+rx.tcp as tcp, tx.udp+rx.udp as udp, +tx.icmp+rx.icmp as icmp, tx.http+rx.http as http, +tx.p2p+rx.p2p as p2p, tx.ftp+rx.ftp as ftp +from + +(SELECT inet_ntoa(ip) as ip, max(total/sample_duration)*8 as scale, sum(total) as total, sum(tcp) as tcp, sum(udp) as udp, sum(icmp) as icmp, +sum(http) as http, sum(p2p) as p2p, sum(ftp) as ftp +from $txtable +where sensor_id = $sensor_id +$sql_ip +group by ip) as tx, + +(SELECT inet_ntoa(ip) as ip, max(total/sample_duration)*8 as scale, sum(total) as total, sum(tcp) as tcp, sum(udp) as udp, sum(icmp) as icmp, +sum(http) as http, sum(p2p) as p2p, sum(ftp) as ftp +from $rxtable +where sensor_id = $sensor_id +$sql_ip +group by ip) as rx + +where tx.ip = rx.ip"; +//echo "
$my_sql
";exit(0); +if($dbtype == DB_PGSQL) + $result = pg_query($pg_sql); +else if($dbtype == DB_MYSQL) + $result = mysql_query($my_sql); echo "", $Output, $Suffix)); } +$masks = array(0 => "0.0.0.0", + 1 => "128.0.0.0", + 2 => "192.0.0.0", + 3 => "224.0.0.0", + 4 => "240.0.0.0", + 5 => "248.0.0.0", + 6 => "252.0.0.0", + 7 => "254.0.0.0", + 8 => "255.0.0.0", + 9 => "255.128.0.0", + 10 => "255.192.0.0", + 11 => "255.224.0.0", + 12 => "255.240.0.0", + 13 => "255.248.0.0", + 14 => "255.252.0.0", + 15 => "255.254.0.0", + 16 => "255.255.0.0", + 17 => "255.255.128.0", + 18 => "255.255.192.0", + 19 => "255.255.224.0", + 20 => "255.255.240.0", + 21 => "255.255.248.0", + 22 => "255.255.252.0", + 23 => "255.255.254.0", + 24 => "255.255.255.0", + 25 => "255.255.255.128", + 26 => "255.255.255.192", + 27 => "255.255.255.224", + 28 => "255.255.255.240", + 29 => "255.255.255.248", + 30 => "255.255.255.252", + 31 => "255.255.255.254", + 32 => "255.255.255.255"); + +function parse_addr($addr) +{ + global $masks; + + if(!$addr) + return array("ip" => 0, "mask" => 0); + + $pos = strpos($addr, "/"); + if(!$pos) { + $ip = $addr; + $mask = "255.255.255.255"; + } + else { + $ip = substr($addr, 0, $pos); + $mask = substr($addr, $pos+1); + if(!strpos($mask, ".")) + $mask = $masks[(int)$mask]; + } + + return array("ip" => ip2long($ip), "mask" => ip2long($mask)); +} + +function bd_escape_string($string) +{ + global $dbtype; + + if($dbtype == DB_PGSQL) + return pg_escape_string($string); + else if($dbtype == DB_MYSQL) + return mysql_real_escape_string($string); + else + return $string; +} + $starttime = time(); set_time_limit(300); -?> \ No newline at end of file +?> diff -ruN bandwidthd/phphtdocs/index.php bandwidthd-mysql-20050912/phphtdocs/index.php --- bandwidthd/phphtdocs/index.php 2005-09-23 16:08:12.000000000 +0200 +++ bandwidthd-mysql-20050912/phphtdocs/index.php 2005-09-09 23:46:02.000000000 +0200 @@ -4,6 +4,8 @@ // Get variables from url +$sensor_name = ""; + if (isset($_GET['sensor_name']) && $_GET['sensor_name'] != "none") $sensor_name = $_GET['sensor_name']; @@ -19,27 +21,61 @@ if (isset($_GET['limit']) && $_GET['limit'] != "none") $limit = $_GET['limit']; - $db = ConnectDb(); ?> -> +>
IpNameTotalSentReceivedtcpudpicmphttpp2pftp"; -$r = pg_fetch_array($result); + +if($dbtype == DB_PGSQL) + $r = pg_fetch_array($result); +else if($dbtype == DB_MYSQL) + $r = mysql_fetch_array($result); echo "
"; if (strpos($ip, "/") === FALSE) echo "$ip".gethostbyaddr($ip); diff -ruN bandwidthd/phphtdocs/graph.php bandwidthd-mysql-20050912/phphtdocs/graph.php --- bandwidthd/phphtdocs/graph.php 2005-09-23 16:08:12.000000000 +0200 +++ bandwidthd-mysql-20050912/phphtdocs/graph.php 2005-09-09 15:48:24.000000000 +0200 @@ -3,7 +3,7 @@ // Returns x location of any given timestamp function ts2x($ts) - { +{ global $timestamp, $width, $interval; return(($ts-$timestamp)*(($width-XOFFSET) / $interval) + XOFFSET); } @@ -27,12 +27,26 @@ foreach ($Count as $key => $number) { + if(!isset($a_total[$key])) + $a_total[$key] = 0; $a_total[$key] += $total[$key]; + if(!isset($a_icmp[$key])) + $a_icmp[$key] = 0; $a_icmp[$key] += $icmp[$key]; + if(!isset($a_udp[$key])) + $a_udp[$key] = 0; $a_udp[$key] += $udp[$key]; + if(!isset($a_tcp[$key])) + $a_tcp[$key] = 0; $a_tcp[$key] += $tcp[$key]; + if(!isset($a_ftp[$key])) + $a_ftp[$key] = 0; $a_ftp[$key] += $ftp[$key]; + if(!isset($a_http[$key])) + $a_http[$key] = 0; $a_http[$key] += $http[$key]; + if(!isset($a_p2p[$key])) + $a_p2p[$key] = 0; $a_p2p[$key] += $p2p[$key]; if ($a_total[$key] > $YMax) @@ -112,14 +126,58 @@ $a_http = array(); $a_p2p = array(); -$sql = "select *, extract(epoch from timestamp) as ts from sensors, $table where sensors.sensor_id = ".$table.".sensor_id and ip <<= '$ip' and sensor_name = '$sensor_name' and timestamp > $timestamp::abstime and timestamp < ".($timestamp+$interval)."::abstime order by ip;"; -//echo $sql."
"; exit(1); -$result = pg_query($sql); +if($dbtype == DB_PGSQL) { + $res = pg_query("SELECT sensor_id FROM sensors WHERE sensor_name='".bd_escape_string($sensor_name)."'"); + if(pg_num_rows($res) != 1) { + echo "No such sensor\n"; + exit; + } + $o = pg_fetch_object($res); + $sensor_id = $o->sensor_id; +} else if($dbtype == DB_MYSQL) { + $res = mysql_query("SELECT sensor_id FROM sensors WHERE sensor_name='".bd_escape_string($sensor_name)."'"); + if(mysql_num_rows($res) != 1) { + echo "No such sensor\n"; + exit; + } + $o = mysql_fetch_object($res); + $sensor_id = $o->sensor_id; +} else { + echo "Unknown database type\n"; + exit; +} + +if($dbtype == DB_PGSQL) { + $sql_ip = "and ip <<= '$ip'"; +} else if($dbtype == DB_MYSQL) { + $p = parse_addr($ip); + if($p["mask"] == ip2long("255.255.255.255")) { + $sql_ip = "and ip = " .sprintf("%u", $p["ip"]); + } else if($p["mask"] == 0) { + $sql_ip = ""; + } else { + $net = $p["ip"] & $p["mask"]; + $bcast = $net | ~$p["mask"]; + $sql_ip = "and ip between ".sprintf("%u", $net)." and ".sprintf("%u",$bcast); + } +} + +$pg_sql = "select ip,total,sample_duration,icmp,udp,tcp,ftp,http,p2p,extract(epoch from timestamp) as ts from $table where sensor_id=$sensor_id $sql_ip and timestamp > $timestamp::abstime and timestamp < ".($timestamp+$interval)."::abstime order by ip;"; +$my_sql = "select ip,total,sample_duration,icmp,udp,tcp,ftp,http,p2p,unix_timestamp(timestamp) as ts from $table where sensor_id=$sensor_id $sql_ip and unix_timestamp(timestamp) > $timestamp and unix_timestamp(timestamp) < ".($timestamp+$interval)." order by ip"; +//echo $my_sql."
"; exit(1); +if($dbtype == DB_PGSQL) + $result = pg_query($pg_sql); +else if($dbtype == DB_MYSQL) + $result = mysql_query($my_sql); // The SQL statement pulls the data out of the database ordered by IP address, that way we can average each // datapoint for each IP address to provide smoothing and then toss the smoothed value into the accumulator // to provide accurate total traffic rate. +$SentPeak = ""; +$TotalSent = ""; +$last_ip = ""; +if($dbtype == DB_PGSQL) { while ($row = pg_fetch_array($result)) { if ($row['ip'] != $last_ip) @@ -132,19 +190,82 @@ $xint = (int) $x; //echo "xint: ".$xint."
"; + if(!isset($Count)) + $Count = array(); + if(!isset($Count[$xint])) + $Count[$xint] = 0; + $Count[$xint]++; + + if ($row['total']/$row['sample_duration'] > $SentPeak) + $SentPeak = $row['total']/$row['sample_duration']; + $TotalSent += $row['total']; + if(!isset($total[$xint])) + $total[$xint] = 0; + $total[$xint] += $row['total']/$row['sample_duration']; + if(!isset($icmp[$xint])) + $icmp[$xint] = 0; + $icmp[$xint] += $row['icmp']/$row['sample_duration']; + if(!isset($udp[$xint])) + $udp[$xint] = 0; + $udp[$xint] += $row['udp']/$row['sample_duration']; + if(!isset($tcp[$xint])) + $tcp[$xint] = 0; + $tcp[$xint] += $row['tcp']/$row['sample_duration']; + if(!isset($ftp[$xint])) + $ftp[$xint] = 0; + $ftp[$xint] += $row['ftp']/$row['sample_duration']; + if(!isset($http[$xint])) + $http[$xint] = 0; + $http[$xint] += $row['http']/$row['sample_duration']; + if(!isset($p2p[$xint])) + $p2p[$xint] = 0; + $p2p[$xint] += $row['p2p']/$row['sample_duration']; + } +} else if($dbtype == DB_MYSQL) { +while ($row = mysql_fetch_array($result)) + { + if ($row['ip'] != $last_ip) + { + AverageAndAccumulate(); + $last_ip = $row['ip']; + } + + $x = ($row['ts']-$timestamp)*(($width-XOFFSET)/$interval)+XOFFSET; + $xint = (int) $x; + + //echo "xint: ".$xint."
"; + if(!isset($Count)) + $Count = array(); + if(!isset($Count[$xint])) + $Count[$xint] = 0; $Count[$xint]++; if ($row['total']/$row['sample_duration'] > $SentPeak) $SentPeak = $row['total']/$row['sample_duration']; $TotalSent += $row['total']; + if(!isset($total[$xint])) + $total[$xint] = 0; $total[$xint] += $row['total']/$row['sample_duration']; + if(!isset($icmp[$xint])) + $icmp[$xint] = 0; $icmp[$xint] += $row['icmp']/$row['sample_duration']; + if(!isset($udp[$xint])) + $udp[$xint] = 0; $udp[$xint] += $row['udp']/$row['sample_duration']; + if(!isset($tcp[$xint])) + $tcp[$xint] = 0; $tcp[$xint] += $row['tcp']/$row['sample_duration']; + if(!isset($ftp[$xint])) + $ftp[$xint] = 0; $ftp[$xint] += $row['ftp']/$row['sample_duration']; + if(!isset($http[$xint])) + $http[$xint] = 0; $http[$xint] += $row['http']/$row['sample_duration']; + if(!isset($p2p[$xint])) + $p2p[$xint] = 0; $p2p[$xint] += $row['p2p']/$row['sample_duration']; } +} // One more time for the last IP AverageAndAccumulate(); diff -ruN bandwidthd/phphtdocs/include.php bandwidthd-mysql-20050912/phphtdocs/include.php --- bandwidthd/phphtdocs/include.php 2005-09-23 16:08:12.000000000 +0200 +++ bandwidthd-mysql-20050912/phphtdocs/include.php 2005-08-30 23:18:22.000000000 +0200 @@ -21,20 +21,36 @@ define("XOFFSET", 90); define("YOFFSET", 45); +define("DB_PGSQL", 1); +define("DB_MYSQL", 2); + require("config.conf"); function ConnectDb() - { - global $db_connect_string; +{ + global $dbtype; + global $pgsql_connect_string; + global $mysql_host, $mysql_user, $mysql_pass, $mysql_dbname; + + if($dbtype == DB_PGSQL) + $db = pg_pconnect($pgsql_connect_string); + else if($dbtype == DB_MYSQL) + $db = mysql_connect($mysql_host, $mysql_user, $mysql_pass); + else { + printf("DB Error, unknown database type"); + exit(1); + } + + if (!$db) { + printf("DB Error, could not connect to database"); + exit(1); + } + + if($dbtype == DB_MYSQL) + mysql_select_db($mysql_dbname); - $db = pg_pconnect($db_connect_string); - if (!$db) - { - printf("DB Error, could not connect to database"); - exit(1); - } - return($db); - } + return($db); +} function fmtb($kbytes) { @@ -63,6 +79,74 @@ return(sprintf("
%.1f%s
Collecting data..."; - exit; - } +if($dbtype == DB_PGSQL) { + $sql = "SELECT sensor_id,sensor_name,to_char(last_connection, 'Dy Mon FMDD HH24:MI:SS YYYY') as last_connection FROM sensors ORDER BY sensor_name;"; + $result = @pg_query($sql); +} +else if($dbtype == DB_MYSQL) { + $sql = "SELECT sensor_id,sensor_name,DATE_FORMAT(last_connection, '%a %b %e %k:%i:%s %Y') AS last_connection FROM sensors ORDER BY sensor_name"; + $result = @mysql_query($sql); +} +else { + echo "
DB Error, unknown database type
"; + exit; +} +if (!$result) { + echo "
Collecting data...
"; + exit; +} ?>
No such sensor
\n"; + exit(0); +} + // Print Title if (isset($limit)) @@ -86,12 +117,27 @@ else echo "

All Records - $sensor_name

"; +if(isset($last)) + echo "Last connection: " . $last . "
\n"; + // Sqlize the incomming variables -if (isset($subnet)) - $sql_subnet = "and ip <<= '$subnet'"; +if($dbtype == DB_PGSQL) { + $sql_subnet = "and ip <<= '$subnet'"; +} else if($dbtype == DB_MYSQL) { + $p = parse_addr($subnet); + if($p["mask"] == ip2long("255.255.255.255")) { + $sql_subnet = "and ip = " .sprintf("%u", $p["ip"]); + } else if($p["mask"] == 0) { + $sql_subnet = ""; + } else { + $net = $p["ip"] & $p["mask"]; + $bcast = $net | ~$p["mask"]; + $sql_subnet = "and ip between ".sprintf("%u", $net)." and ".sprintf("%u",$bcast); + } +} // Sql Statement -$sql = "select tx.ip, rx.scale as rxscale, tx.scale as txscale, tx.total+rx.total as total, tx.total as sent, +$pg_sql = "select tx.ip, rx.scale as rxscale, tx.scale as txscale, tx.total+rx.total as total, tx.total as sent, rx.total as received, tx.tcp+rx.tcp as tcp, tx.udp+rx.udp as udp, tx.icmp+rx.icmp as icmp, tx.http+rx.http as http, tx.p2p+rx.p2p as p2p, tx.ftp+rx.ftp as ftp @@ -99,18 +145,16 @@ (SELECT ip, max(total/sample_duration)*8 as scale, sum(total) as total, sum(tcp) as tcp, sum(udp) as udp, sum(icmp) as icmp, sum(http) as http, sum(p2p) as p2p, sum(ftp) as ftp -from sensors, bd_tx_log -where sensor_name = '$sensor_name' -and sensors.sensor_id = bd_tx_log.sensor_id +from bd_tx_log +where sensor_id = $sensor_id $sql_subnet and timestamp > $timestamp::abstime and timestamp < ".($timestamp+$interval)."::abstime group by ip) as tx, (SELECT ip, max(total/sample_duration)*8 as scale, sum(total) as total, sum(tcp) as tcp, sum(udp) as udp, sum(icmp) as icmp, sum(http) as http, sum(p2p) as p2p, sum(ftp) as ftp -from sensors, bd_rx_log -where sensor_name = '$sensor_name' -and sensors.sensor_id = bd_rx_log.sensor_id +from bd_rx_log +where sensor_id = $sensor_id $sql_subnet and timestamp > $timestamp::abstime and timestamp < ".($timestamp+$interval)."::abstime group by ip) as rx @@ -118,13 +162,46 @@ where tx.ip = rx.ip order by total desc;"; -//echo "
$sql
"; exit(0); -pg_query("SET sort_mem TO 30000;"); -$result = pg_query($sql); -pg_query("set sort_mem to default;"); +$my_sql = "select inet_ntoa(tx.ip) as ip, rx.scale as rxscale, tx.scale as txscale, tx.total+rx.total as total, tx.total as sent, +rx.total as received, tx.tcp+rx.tcp as tcp, tx.udp+rx.udp as udp, +tx.icmp+rx.icmp as icmp, tx.http+rx.http as http, +tx.p2p+rx.p2p as p2p, tx.ftp+rx.ftp as ftp +from -if ($limit == "all") - $limit = pg_num_rows($result); +(SELECT ip, max(total/sample_duration)*8 as scale, sum(total) as total, sum(tcp) as tcp, sum(udp) as udp, sum(icmp) as icmp, +sum(http) as http, sum(p2p) as p2p, sum(ftp) as ftp +from bd_tx_log +where sensor_id = $sensor_id +$sql_subnet +and unix_timestamp(timestamp) > $timestamp and unix_timestamp(timestamp) < ".($timestamp+$interval)." +group by ip) as tx, + +(SELECT ip, max(total/sample_duration)*8 as scale, sum(total) as total, sum(tcp) as tcp, sum(udp) as udp, sum(icmp) as icmp, +sum(http) as http, sum(p2p) as p2p, sum(ftp) as ftp +from bd_rx_log +where sensor_id = $sensor_id +$sql_subnet +and unix_timestamp(timestamp) > $timestamp and unix_timestamp(timestamp) < ".($timestamp+$interval)." +group by ip) as rx + +where tx.ip = rx.ip +order by total desc"; + +//echo "
$my_sql
"; exit(0); +if($dbtype == DB_PGSQL) { + pg_query("SET sort_mem TO 30000;"); + $result = pg_query($pg_sql); +} else if($dbtype == DB_MYSQL) + $result = mysql_query($my_sql); +if($dbtype == DB_PGSQL) + pg_query("set sort_mem to default;"); + +if ($limit == "all") { + if($dbtype == DB_PGSQL) + $limit = pg_num_rows($result); + else if($dbtype == DB_MYSQL) + $limit = mysql_num_rows($result); +} echo "
IpNameTotalSentReceivedtcpudpicmphttpp2pftp"; @@ -132,19 +209,27 @@ $subnet = "0.0.0.0/0"; // Output Total Line -echo "
Total$subnet"; -foreach (array("total", "sent", "received", "tcp", "udp", "icmp", "http", "p2p", "ftp") as $key) - { - for($Counter=0, $Total = 0; $Counter < pg_num_rows($result); $Counter++) - { - $r = pg_fetch_array($result, $Counter); - $Total += $r[$key]; - } - echo fmtb($Total); - } +echo "
Total$subnet"; +foreach (array("total", "sent", "received", "tcp", "udp", "icmp", "http", "p2p", "ftp") as $key) { + if($dbtype == DB_PGSQL) { + for($Counter=0, $Total = 0; $Counter < pg_num_rows($result); $Counter++) { + $r = pg_fetch_array($result, $Counter); + $Total += $r[$key]; + } + } else if($dbtype == DB_MYSQL) { + if(mysql_num_rows($result) > 0) + mysql_data_seek($result, 0); + for($Counter = 0, $Total = 0; $Counter < mysql_num_rows($result); $Counter++) { + $r = mysql_fetch_array($result); + $Total += $r[$key]; + } + } + echo fmtb($Total); +} echo "\n"; // Output Other Lines +if($dbtype == DB_PGSQL) { for($Counter=0; $Counter < pg_num_rows($result) && $Counter < $limit; $Counter++) { $r = pg_fetch_array($result, $Counter); @@ -155,15 +240,39 @@ fmtb($r['tcp']).fmtb($r['udp']).fmtb($r['icmp']).fmtb($r['http']). fmtb($r['p2p']).fmtb($r['ftp'])."\n"; } +} else if($dbtype == DB_MYSQL) { +if(mysql_num_rows($result) > 0) + mysql_data_seek($result, 0); +for($Counter=0; $Counter < mysql_num_rows($result) && $Counter < $limit; $Counter++) + { + $r = mysql_fetch_array($result); + echo "
"; + echo $r['ip']."".gethostbyaddr($r['ip']); + echo ""; + echo fmtb($r['total']).fmtb($r['sent']).fmtb($r['received']). + fmtb($r['tcp']).fmtb($r['udp']).fmtb($r['icmp']).fmtb($r['http']). + fmtb($r['p2p']).fmtb($r['ftp'])."\n"; + } +} echo "
"; // Output Total Graph -for($Counter=0, $Total = 0; $Counter < pg_num_rows($result); $Counter++) - { - $r = pg_fetch_array($result, $Counter); - $scale = max($r['txscale'], $scale); - $scale = max($r['rxscale'], $scale); - } +//$scale = 0; +//if($dbtype == DB_PGSQL) { +// for($Counter=0; $Counter < pg_num_rows($result); $Counter++) { +// $r = pg_fetch_array($result, $Counter); +// $scale = max($r['txscale'], $scale); +// $scale = max($r['rxscale'], $scale); +// } +//} else if($dbtype == DB_MYSQL) { +// if(mysql_num_rows($result) > 0) +// mysql_data_seek($result, 0); +// for($Counter = 0; $Counter < mysql_num_rows($result); $Counter++) { +// $r = mysql_fetch_array($result); +// $scale = max($r['txscale'], $scale); +// $scale = max($r['rxscale'], $scale); +// } +//} if ($subnet == "0.0.0.0/0") $total_table = "bd_tx_total_log"; @@ -174,7 +283,7 @@ echo ""; echo "Send:

"; echo "
\n"; -if ($subnet == "0.0.0.0/0") +if ($subnet == "0.0.0.0/0" || $subnet == "0/0") $total_table = "bd_rx_total_log"; else $total_table = "bd_rx_log"; @@ -183,6 +292,7 @@ // Output Other Graphs +if($dbtype == DB_PGSQL) { for($Counter=0; $Counter < pg_num_rows($result) && $Counter < $limit; $Counter++) { $r = pg_fetch_array($result, $Counter); @@ -197,5 +307,24 @@ echo "Receive:

"; echo "
\n"; } +} else if($dbtype == DB_MYSQL) { +if(mysql_num_rows($result) > 0) + mysql_data_seek($result, 0); +for($Counter=0; $Counter < mysql_num_rows($result) && $Counter < $limit; $Counter++) + { + $r = mysql_fetch_array($result); + echo "

"; + if ($r['ip'] == "0.0.0.0") + echo "Total - Total of all subnets

"; + else + echo $r['ip']." - ".gethostbyaddr($r['ip']).""; + echo ""; + echo "Send:

"; + echo "
\n"; + echo "Receive:

"; + echo "
\n"; + } +} -include('footer.php'); \ No newline at end of file +include('footer.php'); +?>