From 4df3df8aebaec9a67a579b4775521a8853c5c6cc Mon Sep 17 00:00:00 2001
From: Pablo Rincon <pablo.rincon.crespo@gmail.com>
Date: Thu, 12 Nov 2009 22:55:56 +0100
Subject: [PATCH] Fixing alert unified log file rotation. Adding unittests

---
 src/alert-debuglog.c       |    3 -
 src/alert-fastlog.c        |    3 -
 src/alert-unified-alert.c  |   97 +++++++++++++++++++++++++++++++++++---------
 src/alert-unified-log.c    |   75 ++++++++++++++++++++++++++++++----
 src/alert-unified2-alert.c |   70 ++++++++++++++++++++++++++-----
 5 files changed, 202 insertions(+), 46 deletions(-)

diff --git a/src/alert-debuglog.c b/src/alert-debuglog.c
index de3a372..596bb5d 100644
--- a/src/alert-debuglog.c
+++ b/src/alert-debuglog.c
@@ -280,9 +280,6 @@ int AlertDebuglogOpenFileCtx(LogFileCtx *file_ctx, char *config_file)
             printf("ERROR: failed to open %s: %s\n", log_path, strerror(errno));
             return -1;
         }
-        if(file_ctx->config_file == NULL)
-            file_ctx->config_file = strdup("configfile.ad");
-            /** Remember the config file (or NULL if not indicated) */
     }
 
     return ret;
diff --git a/src/alert-fastlog.c b/src/alert-fastlog.c
index 51ce689..65b3db4 100644
--- a/src/alert-fastlog.c
+++ b/src/alert-fastlog.c
@@ -247,9 +247,6 @@ int AlertFastlogOpenFileCtx(LogFileCtx *file_ctx, char *config_file)
             printf("ERROR: failed to open %s: %s\n", log_path, strerror(errno));
             return -1;
         }
-        if(file_ctx->config_file == NULL)
-            file_ctx->config_file = strdup("config.af");
-            /** Remember the config file (or NULL if not indicated) */
     }
 
     return 0;
diff --git a/src/alert-unified-alert.c b/src/alert-unified-alert.c
index e00fae3..6e7dabc 100644
--- a/src/alert-unified-alert.c
+++ b/src/alert-unified-alert.c
@@ -30,13 +30,14 @@ TmEcode AlertUnifiedAlert (ThreadVars *, Packet *, void *, PacketQueue *);
 TmEcode AlertUnifiedAlertThreadInit(ThreadVars *, void *, void **);
 TmEcode AlertUnifiedAlertThreadDeinit(ThreadVars *, void *);
 int AlertUnifiedAlertOpenFileCtx(LogFileCtx *, char *);
+void AlertUnifiedAlertRegisterTests (void);
 
 void TmModuleAlertUnifiedAlertRegister (void) {
     tmm_modules[TMM_ALERTUNIFIEDALERT].name = "AlertUnifiedAlert";
     tmm_modules[TMM_ALERTUNIFIEDALERT].ThreadInit = AlertUnifiedAlertThreadInit;
     tmm_modules[TMM_ALERTUNIFIEDALERT].Func = AlertUnifiedAlert;
     tmm_modules[TMM_ALERTUNIFIEDALERT].ThreadDeinit = AlertUnifiedAlertThreadDeinit;
-    tmm_modules[TMM_ALERTUNIFIEDALERT].RegisterTests = NULL;
+    tmm_modules[TMM_ALERTUNIFIEDALERT].RegisterTests = AlertUnifiedAlertRegisterTests;
 }
 
 typedef struct AlertUnifiedAlertThread_ {
@@ -102,8 +103,13 @@ int AlertUnifiedAlertWriteFileHeader(ThreadVars *t, AlertUnifiedAlertThread *aun
 }
 
 int AlertUnifiedAlertCloseFile(ThreadVars *t, AlertUnifiedAlertThread *aun) {
-    if (aun->file_ctx->fp != NULL)
+    if (aun->file_ctx->fp != NULL) {
         fclose(aun->file_ctx->fp);
+        if (aun->file_ctx->filename != NULL) {
+            free(aun->file_ctx->filename);
+            aun->file_ctx->filename = NULL;
+        }
+    }
 
     return 0;
 }
@@ -203,6 +209,7 @@ TmEcode AlertUnifiedAlertThreadInit(ThreadVars *t, void *initdata, void **data)
     }
     /** Use the Ouptut Context (file pointer and mutex) */
     aun->file_ctx = (LogFileCtx*) initdata;
+    aun->size_limit = 30;
 
     /** Write Unified header */
     int ret = AlertUnifiedAlertWriteFileHeader(t, aun);
@@ -246,24 +253,23 @@ error:
  * */
 LogFileCtx *AlertUnifiedAlertInitCtx(char *config_file)
 {
-    int ret=0;
-    LogFileCtx* file_ctx=LogFileNewCtx();
+    int ret = 0;
+    LogFileCtx *file_ctx = LogFileNewCtx();
 
-    if(file_ctx == NULL)
-    {
+    if (file_ctx == NULL) {
         printf("AlertUnifiedAlertInitCtx: Couldn't create new file_ctx\n");
         return NULL;
     }
 
     /** fill the new LogFileCtx with the specific AlertUnifiedAlert configuration */
-    ret=AlertUnifiedAlertOpenFileCtx(file_ctx, config_file);
+    ret = AlertUnifiedAlertOpenFileCtx(file_ctx, config_file);
 
-    if(ret < 0)
+    if (ret < 0)
         return NULL;
 
-    /** In AlertUnifiedAlertOpenFileCtx the second parameter should be the configuration file to use
-    * but it's not implemented yet, so passing NULL to load the default
-    * configuration
+    /** In AlertUnifiedAlertOpenFileCtx the second parameter should be
+    * the configuration file to use but it's not implemented yet, so
+    * passing NULL to load the default configuration
     */
 
     return file_ctx;
@@ -276,10 +282,9 @@ LogFileCtx *AlertUnifiedAlertInitCtx(char *config_file)
  * */
 int AlertUnifiedAlertOpenFileCtx(LogFileCtx *file_ctx, char *config_file)
 {
-    char filename[PATH_MAX]; /* XXX some sane default? */
+    char *filename = malloc(PATH_MAX); /* XXX some sane default? */
 
-    if(config_file == NULL)
-    {
+    if (config_file == NULL) {
         /** Separate config files not implemented at the moment,
         * but it must be able to load from separate config file.
         * Load the default configuration.
@@ -297,7 +302,8 @@ int AlertUnifiedAlertOpenFileCtx(LogFileCtx *file_ctx, char *config_file)
         char *log_dir;
         if (ConfGet("default-log-dir", &log_dir) != 1)
             log_dir = DEFAULT_LOG_DIR;
-        snprintf(filename, sizeof(filename), "%s/%s.%" PRIu32, log_dir, "unified.alert", (uint32_t)ts.tv_sec);
+
+        snprintf(filename, PATH_MAX, "%s/%s.%" PRIu32, log_dir, "unified.alert", (uint32_t)ts.tv_sec);
 
         /* XXX filename & location */
         file_ctx->fp = fopen(filename, "wb");
@@ -305,14 +311,65 @@ int AlertUnifiedAlertOpenFileCtx(LogFileCtx *file_ctx, char *config_file)
             printf("Error: fopen %s failed: %s\n", filename, strerror(errno)); /* XXX errno threadsafety? */
             return -1;
         }
-
-        if(file_ctx->config_file == NULL)
-            file_ctx->config_file = strdup("configfile.aua");
-            /** Remember the config file (or NULL if not indicated) */
-
+        file_ctx->filename = filename;
     }
 
     return 0;
 }
 
+#ifdef UNITTESTS
+/**
+ *  \test Test the Rotate process
+ *
+ *  \retval 1 on succces
+ *  \retval 0 on failure
+ */
+static int AlertUnifiedAlertTestRotate01(void)
+{
+    int ret = 0;
+    int r = 0;
+    ThreadVars tv;
+    LogFileCtx *lf;
+    void *data = NULL;
+
+    lf = AlertUnifiedAlertInitCtx(NULL);
+    char *filename = strdup(lf->filename);
+
+    memset(&tv, 0, sizeof(ThreadVars));
+
+    if (lf == NULL)
+        return 0;
 
+    ret = AlertUnifiedAlertThreadInit(&tv, lf, &data);
+    if (ret == TM_ECODE_FAILED) {
+        LogFileFreeCtx(lf);
+        return 0;
+    }
+
+    sleep(1);
+    ret = AlertUnifiedAlertRotateFile(&tv, data);
+    if (ret == -1)
+        goto error;
+
+    if (strcmp(filename, lf->filename) == 0)
+        goto error;
+
+    r = 1;
+
+error:
+    AlertUnifiedAlertThreadDeinit(&tv, data);
+    if (lf != NULL) LogFileFreeCtx(lf);
+    if (filename != NULL) free(filename);
+    return r;
+}
+#endif /* UNITTESTS */
+
+/**
+ * \brief this function registers unit tests for Unified2
+ */
+void AlertUnifiedAlertRegisterTests (void) {
+#ifdef UNITTESTS
+    UtRegisterTest("UnifiedAlertTestRotate01 -- Rotate File",
+                   AlertUnifiedAlertTestRotate01, 1);
+#endif /* UNITTESTS */
+}
diff --git a/src/alert-unified-log.c b/src/alert-unified-log.c
index e0d5b43..002a70c 100644
--- a/src/alert-unified-log.c
+++ b/src/alert-unified-log.c
@@ -30,13 +30,14 @@ TmEcode AlertUnifiedLog (ThreadVars *, Packet *, void *, PacketQueue *);
 TmEcode AlertUnifiedLogThreadInit(ThreadVars *, void *, void **);
 TmEcode AlertUnifiedLogThreadDeinit(ThreadVars *, void *);
 int AlertUnifiedLogOpenFileCtx(LogFileCtx *, char *);
+void AlertUnifiedLogRegisterTests(void);
 
 void TmModuleAlertUnifiedLogRegister (void) {
     tmm_modules[TMM_ALERTUNIFIEDLOG].name = "AlertUnifiedLog";
     tmm_modules[TMM_ALERTUNIFIEDLOG].ThreadInit = AlertUnifiedLogThreadInit;
     tmm_modules[TMM_ALERTUNIFIEDLOG].Func = AlertUnifiedLog;
     tmm_modules[TMM_ALERTUNIFIEDLOG].ThreadDeinit = AlertUnifiedLogThreadDeinit;
-    tmm_modules[TMM_ALERTUNIFIEDLOG].RegisterTests = NULL;
+    tmm_modules[TMM_ALERTUNIFIEDLOG].RegisterTests = AlertUnifiedLogRegisterTests;
 }
 
 typedef struct AlertUnifiedLogThread_ {
@@ -106,8 +107,13 @@ int AlertUnifiedLogWriteFileHeader(ThreadVars *t, AlertUnifiedLogThread *aun) {
 }
 
 int AlertUnifiedLogCloseFile(ThreadVars *t, AlertUnifiedLogThread *aun) {
-    if (aun->file_ctx->fp != NULL)
+    if (aun->file_ctx->fp != NULL) {
         fclose(aun->file_ctx->fp);
+        if (aun->file_ctx->filename != NULL) {
+            free(aun->file_ctx->filename);
+            aun->file_ctx->filename = NULL;
+        }
+    }
     return 0;
 }
 
@@ -293,7 +299,7 @@ LogFileCtx *AlertUnifiedLogInitCtx(char *config_file)
  * */
 int AlertUnifiedLogOpenFileCtx(LogFileCtx *file_ctx, char *config_file)
 {
-    char filename[PATH_MAX]; /* XXX some sane default? */
+    char *filename = malloc(PATH_MAX); /* XXX some sane default? */
 
     if(config_file == NULL)
     {
@@ -314,7 +320,8 @@ int AlertUnifiedLogOpenFileCtx(LogFileCtx *file_ctx, char *config_file)
         char *log_dir;
         if (ConfGet("default-log-dir", &log_dir) != 1)
             log_dir = DEFAULT_LOG_DIR;
-        snprintf(filename, sizeof(filename), "%s/%s.%" PRIu32, log_dir, "unified.log", (uint32_t)ts.tv_sec);
+
+        snprintf(filename, PATH_MAX, "%s/%s.%" PRIu32, log_dir, "unified.log", (uint32_t)ts.tv_sec);
 
         /* XXX filename & location */
         file_ctx->fp = fopen(filename, "wb");
@@ -322,14 +329,66 @@ int AlertUnifiedLogOpenFileCtx(LogFileCtx *file_ctx, char *config_file)
             printf("Error: fopen %s failed: %s\n", filename, strerror(errno)); /* XXX errno threadsafety? */
             return -1;
         }
+        file_ctx->filename = filename;
+    }
+
+    return 0;
+}
+
+#ifdef UNITTESTS
+/**
+ *  \test Test the Rotate process
+ *
+ *  \retval 1 on succces
+ *  \retval 0 on failure
+ */
+static int AlertUnifiedLogTestRotate01(void)
+{
+    int ret = 0;
+    int r = 0;
+    ThreadVars tv;
+    LogFileCtx *lf;
+    void *data = NULL;
 
-        if(file_ctx->config_file == NULL)
-            file_ctx->config_file = strdup("configfile.aul");
-            /** Remember the config file (or NULL if not indicated) */
+    lf = AlertUnifiedLogInitCtx(NULL);
+    char *filename = strdup(lf->filename);
 
+    memset(&tv, 0, sizeof(ThreadVars));
+
+    if (lf == NULL)
+        return 0;
+
+    ret = AlertUnifiedLogThreadInit(&tv, lf, &data);
+    if (ret == TM_ECODE_FAILED) {
+        LogFileFreeCtx(lf);
+        return 0;
     }
 
-    return 0;
+    sleep(1);
+    ret = AlertUnifiedLogRotateFile(&tv, data);
+    if (ret == -1)
+        goto error;
+
+    if (strcmp(filename, lf->filename) == 0)
+        goto error;
+
+    r = 1;
+
+error:
+    AlertUnifiedLogThreadDeinit(&tv, data);
+    if (lf != NULL) LogFileFreeCtx(lf);
+    if (filename != NULL) free(filename);
+    return r;
 }
+#endif /* UNITTESTS */
 
+/**
+ * \brief this function registers unit tests for Unified2
+ */
+void AlertUnifiedLogRegisterTests (void) {
+#ifdef UNITTESTS
+    UtRegisterTest("UnifiedAlertTestRotate01 -- Rotate File",
+                   AlertUnifiedLogTestRotate01, 1);
+#endif /* UNITTESTS */
+}
 
diff --git a/src/alert-unified2-alert.c b/src/alert-unified2-alert.c
index d171071..3d20660 100644
--- a/src/alert-unified2-alert.c
+++ b/src/alert-unified2-alert.c
@@ -129,8 +129,13 @@ void TmModuleUnified2AlertRegister (void) {
  */
 
 int Unified2AlertCloseFile(ThreadVars *t, Unified2AlertThread *aun) {
-    if (aun->file_ctx->fp != NULL)
+    if (aun->file_ctx->fp != NULL) {
         fclose(aun->file_ctx->fp);
+        if (aun->file_ctx->filename != NULL) {
+            free(aun->file_ctx->filename);
+            aun->file_ctx->filename = NULL;
+        }
+    }
 
     return 0;
 }
@@ -561,10 +566,9 @@ LogFileCtx *Unified2AlertInitCtx(char *config_file)
  * */
 int Unified2AlertOpenFileCtx(LogFileCtx *file_ctx, char *config_file)
 {
-    char filename[PATH_MAX]; /* XXX some sane default? */
+    char *filename = malloc(PATH_MAX); /* XXX some sane default? */
 
-    if(config_file == NULL)
-    {
+    if (config_file == NULL) {
         /** Separate config files not implemented at the moment,
         * but it must be able to load from separate config file.
         * Load the default configuration.
@@ -575,14 +579,15 @@ int Unified2AlertOpenFileCtx(LogFileCtx *file_ctx, char *config_file)
          * This is used both during init and runtime, so it must be thread
          * safe. */
         struct timeval ts;
-        memset (&ts, 0, sizeof(struct timeval));
+        memset(&ts, 0, sizeof(struct timeval));
         gettimeofday(&ts, NULL);
 
         /* create the filename to use */
         char *log_dir;
         if (ConfGet("default-log-dir", &log_dir) != 1)
             log_dir = DEFAULT_LOG_DIR;
-        snprintf(filename, sizeof(filename), "%s/%s.%" PRIu32, log_dir, "unified2.alert", (uint32_t)ts.tv_sec);
+
+        snprintf(filename, PATH_MAX, "%s/%s.%" PRIu32, log_dir, "unified2.alert", (uint32_t)ts.tv_sec);
 
         /* XXX filename & location */
         file_ctx->fp = fopen(filename, "wb");
@@ -590,11 +595,7 @@ int Unified2AlertOpenFileCtx(LogFileCtx *file_ctx, char *config_file)
             printf("Error: fopen %s failed: %s\n", filename, strerror(errno)); /* XXX errno threadsafety? */
             return -1;
         }
-
-        if(file_ctx->config_file == NULL)
-            file_ctx->config_file = strdup("configfile.au2a");
-            /** Remember the config file (or NULL if not indicated) */
-
+        file_ctx->filename = filename;
     }
 
     return 0;
@@ -929,12 +930,56 @@ static int Unified2Test05 (void)   {
 
     return 1;
 }
+
+/**
+ *  \test Test the Rotate process
+ *
+ *  \retval 1 on succces
+ *  \retval 0 on failure
+ */
+static int Unified2TestRotate01(void)
+{
+    int ret = 0;
+    int r = 0;
+    ThreadVars tv;
+    LogFileCtx *lf;
+    void *data = NULL;
+
+    lf = Unified2AlertInitCtx(NULL);
+    char *filename = strdup(lf->filename);
+
+    memset(&tv, 0, sizeof(ThreadVars));
+
+    if (lf == NULL)
+        return 0;
+
+    ret = Unified2AlertThreadInit(&tv, lf, &data);
+    if (ret == TM_ECODE_FAILED) {
+        LogFileFreeCtx(lf);
+        return 0;
+    }
+
+    sleep(1);
+    ret = Unified2AlertRotateFile(&tv, data);
+    if (ret == -1)
+        goto error;
+
+    if (strcmp(filename, lf->filename) == 0)
+        goto error;
+
+    r = 1;
+
+error:
+    Unified2AlertThreadDeinit(&tv, data);
+    if (lf != NULL) LogFileFreeCtx(lf);
+    if (filename != NULL) free(filename);
+    return r;
+}
 #endif
 
 /**
  * \brief this function registers unit tests for Unified2
  */
-
 void Unified2RegisterTests (void) {
 #ifdef UNITTESTS
     UtRegisterTest("Unified2Test01 -- Ipv4 test", Unified2Test01, 1);
@@ -942,5 +987,6 @@ void Unified2RegisterTests (void) {
     UtRegisterTest("Unified2Test03 -- GRE test", Unified2Test03, 1);
     UtRegisterTest("Unified2Test04 -- PPP test", Unified2Test04, 1);
     UtRegisterTest("Unified2Test05 -- Inline test", Unified2Test05, 1);
+    UtRegisterTest("Unified2TestRotate01 -- Rotate File", Unified2TestRotate01, 1);
 #endif /* UNITTESTS */
 }
-- 
1.6.0.4

