diff --git a/configfile.c b/configfile.c index 73ff3ae..1314bb3 100644 --- a/configfile.c +++ b/configfile.c @@ -36,13 +36,13 @@ struct conf_section { struct list_head list; struct list_head tupel_list; - char *name; + const char *name; }; struct conf_tupel { struct list_head list; - char *option; - char *parameter; + const char *option; + const char *parameter; }; static LIST_HEAD(config_list); @@ -142,6 +142,23 @@ int config_parse(const char *config) return 0; } +void config_free(void) +{ + struct conf_section *section, *section_tmp; + struct conf_tupel *tupel, *tupel_tmp; + + list_for_each_entry_safe(section, section_tmp, &config_list, list) { + list_for_each_entry_safe(tupel, tupel_tmp, §ion->tupel_list, list) { + list_del(&tupel->list); + free((char *)tupel->option); + free((char *)tupel->parameter); + free(tupel); + } + list_del(§ion->list); + free(section); + } +} + static struct conf_section * config_get_section(const char *name) { struct conf_section *section; @@ -153,7 +170,7 @@ static struct conf_section * config_get_section(const char *name) return NULL; } -char * config_get_string(const char *section_str, const char *option, char *def) +const char * config_get_string(const char *section_str, const char *option, const char *def) { struct conf_section *section = config_get_section(section_str); if (section != NULL) { @@ -172,7 +189,7 @@ char * config_get_string(const char *section_str, const char *option, char *def) int config_get_int(const char *section, const char *option, int def) { - char *ret = config_get_string(section, option, NULL); + const char *ret = config_get_string(section, option, NULL); if (ret == NULL) { log_print(LOG_WARN, "config [%s:%s] not found, using default: '%d'", section, option, def); diff --git a/configfile.h b/configfile.h index 6528459..9a2b669 100644 --- a/configfile.h +++ b/configfile.h @@ -1,11 +1,10 @@ #ifndef _CONFIG_H_ #define _CONFIG_H_ -#include - int config_parse(const char *config); +void config_free(void); -char * config_get_string(const char *section_str, const char *option, char *def); +const char * config_get_string(const char *section_str, const char *option, const char *def); int config_get_int(const char *section, const char *option, int def); diff --git a/conntrack.c b/conntrack.c index 93b026b..1013f8f 100644 --- a/conntrack.c +++ b/conntrack.c @@ -63,7 +63,7 @@ struct hash_table * conntrack_get_hash(void) int conntrack_init(void) { - char *mask = config_get_string("global", "netmask", DEFAULT_NETMASK); + const char *mask = config_get_string("global", "netmask", DEFAULT_NETMASK); if (inet_aton(mask, &netmask) == 0) { log_print(LOG_ERROR, "conntrack_init: invalid netmask"); return -1; @@ -116,6 +116,9 @@ int conntrack_start_event_thread(void) int conntrack_close(void) { + if (ct_thread) + pthread_cancel(ct_thread); + destroy_hash(table[1]); destroy_hash(table[0]); diff --git a/ctstats.c b/ctstats.c index b448ee1..c9ec8d6 100644 --- a/ctstats.c +++ b/ctstats.c @@ -4,6 +4,8 @@ #include #include +#include +#include #include "configfile.h" #include "conntrack.h" @@ -21,6 +23,13 @@ static struct option opts[] = { {0, 0, 0, 0} }; +static int sig_received = 0; + +static void my_sighandler(int s) +{ + sig_received = 1; +} + int main(int argc, char *argv[]) { char *config = DEFAULT_CONFIG; @@ -72,29 +81,41 @@ int main(int argc, char *argv[]) } /* check logfile */ - char *logfile = config_get_string("global", "logfile", DEFAULT_LOGFILE); + const char *logfile = config_get_string("global", "logfile", DEFAULT_LOGFILE); if (logfile != NULL && debug == 0) { /* start logging */ - if (!log_init(logfile)) + if (log_init(logfile)) exit(1); /* zum daemon mutieren */ daemon(-1, 0); } + log_print(LOG_EVERYTIME, "ctstats started (pid: %d)", getpid()); + + signal(SIGINT, my_sighandler); + signal(SIGTERM, my_sighandler); + /* start event listener */ conntrack_start_event_thread(); int intervall = config_get_int("global", "intervall", DEFAULT_INTERVALL); - while (1) { - sleep(intervall); - /* parse hashes, fill database */ + struct timeval tv; + tv.tv_sec = intervall; + tv.tv_usec = 0; + + while (sig_received == 0) { + select(0, NULL, NULL, NULL, &tv); + errno = 0; + + tv.tv_sec = intervall; + tv.tv_usec = 0; database_analyse(); } - /* how to stop? */ database_close(); conntrack_close(); + log_close(); return 0; } diff --git a/database.c b/database.c index eac8fd3..8a97040 100644 --- a/database.c +++ b/database.c @@ -13,7 +13,7 @@ static MYSQL *dbh; -static void purge_hash_cb(struct hash_entry *entry, void *privdata) +static void purge_hash_cb(const struct hash_entry *entry, void *privdata) { int long *now = (long *)privdata; char query[256]; @@ -50,9 +50,9 @@ int database_init(void) return -1; } - char *hostname = config_get_string("mysql", "hostname", NULL); - char *username = config_get_string("mysql", "username", NULL); - char *password = config_get_string("mysql", "password", NULL); + const char *hostname = config_get_string("mysql", "hostname", NULL); + const char *username = config_get_string("mysql", "username", NULL); + const char *password = config_get_string("mysql", "password", NULL); MYSQL *ret = mysql_real_connect(dbh, hostname, username, password, NULL, 0, NULL, 0); if (ret != dbh) { log_print(LOG_ERROR, "database_init: mysql_real_connect(): %s", mysql_error(dbh)); @@ -60,7 +60,7 @@ int database_init(void) return -1; } - char *database = config_get_string("mysql", "database", NULL); + const char *database = config_get_string("mysql", "database", NULL); if (mysql_select_db(dbh, database) != 0) { log_print(LOG_ERROR, "database_init: mysql_select_db(): %s", mysql_error(dbh)); mysql_close(dbh); diff --git a/hashtable.c b/hashtable.c index 353ee16..30c8fde 100644 --- a/hashtable.c +++ b/hashtable.c @@ -41,7 +41,7 @@ struct hash_table * create_hash(uint32_t buckets) } void purge_hash(struct hash_table *table, - void (*callback)(struct hash_entry *entry, void *privdata), + void (*callback)(const struct hash_entry *entry, void *privdata), void *privdata) { uint32_t i; @@ -71,7 +71,7 @@ void destroy_hash(struct hash_table *table) free(table); } -static uint32_t calc_hashkey(struct hash_entry *entry, uint32_t initval) +static uint32_t calc_hashkey(const struct hash_entry *entry, uint32_t initval) { uint32_t a = entry->src_ip; uint32_t b = entry->protonum; @@ -86,7 +86,7 @@ static uint32_t calc_hashkey(struct hash_entry *entry, uint32_t initval) return c; } -static int cmp_entry(struct hash_entry *a, struct hash_entry *b) +static int cmp_entry(const struct hash_entry *a, const struct hash_entry *b) { return (a->src_ip ^ b->src_ip) | (a->protonum ^ b->protonum) | diff --git a/hashtable.h b/hashtable.h index 06ddbc2..fdb23bc 100644 --- a/hashtable.h +++ b/hashtable.h @@ -25,7 +25,7 @@ struct hash_table { struct hash_table * create_hash(uint32_t buckets); void purge_hash(struct hash_table *table, - void (*callback)(struct hash_entry *entry, void *privdata), + void (*callback)(const struct hash_entry *entry, void *privdata), void *privdata); void destroy_hash(struct hash_table *table); diff --git a/logging.c b/logging.c index d4fd706..61dcfcf 100644 --- a/logging.c +++ b/logging.c @@ -29,75 +29,74 @@ #define BUFSIZE 8192 static FILE *log_fd = NULL; +static int log_prio = LOG_EVERYTIME; static char *buffer = NULL; -void log_print(int prio, const char *fmt, ...) +int log_print(int prio, const char *fmt, ...) { va_list az; - int len; + int len = 0, retval; + + if (prio < log_prio) + return 0; if (buffer == NULL) { buffer = malloc(BUFSIZE); if (buffer == NULL) { - fprintf(stderr, "log_print: out of memory\nBailing out!\n"); - exit(-1); + fprintf(stderr, "log_print(): out of memory\n"); + return -1; } } + if (log_fd != NULL) { + time_t tzgr; + time(&tzgr); + + len += strftime(buffer, BUFSIZE, "%b %d %H:%M:%S :", localtime(&tzgr)); + } + va_start(az, fmt); - len = vsnprintf(buffer, BUFSIZE, fmt, az); + len += vsnprintf(buffer + len, BUFSIZE - len, fmt, az); va_end(az); if (len < 0 || len >= BUFSIZE) { - log_print(LOG_ERROR, "log_print: arguments too long"); errno = 0; - return; + return log_print(LOG_ERROR, "log_print: arguments too long"); } if (errno) { - strncpy(buffer + len, ": ", BUFSIZE - len); - len += 2; - strncpy(buffer + len, strerror(errno), BUFSIZE - len); + len += snprintf(buffer + len, BUFSIZE - len, ": %s", strerror(errno)); + errno = 0; } - if (log_fd) { - char tbuf[64]; - time_t tzgr; - - time(&tzgr); - strftime(tbuf, sizeof(tbuf), "%b %d %H:%M:%S :", localtime(&tzgr)); - - fprintf(log_fd, "%s %s\n", tbuf, buffer); - fflush(log_fd); - - } else { - fprintf(stderr, "%s\n", buffer); - } - - errno = 0; + retval = fprintf((log_fd ? log_fd : stderr), "%s\n", buffer); + fflush(log_fd); + return retval; } -static void log_close(void) +void log_close(void) { if (buffer) free(buffer); - fclose(log_fd); + if (log_fd) + fclose(log_fd); } -int log_init(char *logfile) +int log_init(const char *logfile) { + if (log_fd != NULL) + log_close(); + log_fd = fopen(logfile, "a"); if (log_fd == NULL) { - log_print(LOG_ERROR, "log_open('%s'): %s", logfile); - return 0; + fprintf(stderr, "log_init(): can not open logfile"); + return -1; } - - if (atexit(log_close) != 0) { - log_print(LOG_ERROR, "log_open(): atexit()"); - return 0; - } - - log_print(LOG_EVERYTIME, "=========================="); - return 1; + return 0; +} + +void log_setprio(int prio) +{ + log_prio = prio; } diff --git a/logging.h b/logging.h index c6e32c0..82d028d 100644 --- a/logging.h +++ b/logging.h @@ -10,7 +10,10 @@ #define LOG_EVERYTIME 0 -int log_init(char *logfile); -void log_print(int prio, const char *fmt, ... ); +int log_init(const char *logfile); +void log_close(void); +void log_setprio(int prio); + +int log_print(int prio, const char *fmt, ... ); #endif /* _LOGGING_H_ */