[Oisf-devel] proposed patch to add archive mode to pcap-log module

Roberto Martelloni roberto.martelloni at cyberlabs.it
Thu May 24 10:58:10 UTC 2012


Hello to all,

in the attachment there is a patch to suricata 1.2.1 that add a new mode 
to handle pcap-log file dump.

With this patch if you set pcap-log mode to the value "archive"
suricata check for two more variables:

- archive_temp_dir
- archive_dest_dir

archive_temp_dir is the directory path where pcap file are temporarily 
stored until they are closed.

archive_dest_dir is the path where the pcap file is rotated after it is 
closed.

Also a fix to the file name are added.
In archive mode the file name is in this format: 
hostname-YYYYMMDD-HHMMSS.pcap

I've added this mode of running to allow a software in pipe to read data 
only from NON running file dump and to allow a system administrator to 
identify which file are actually in dump and which one are already 
dumped and closed.

If this patch seams useful to other with some minor modification let me 
know and eventually I can fix it.

Also let me know if this patch can be inserted in the mainline code.

Great thanks,

-- 
Roberto Martelloni
boos @ http://boos.core-dumped.info
-------------- next part --------------
diff -Nura suricata-1.2.1-orig/src/log-pcap.c suricata-1.2.1/src/log-pcap.c
--- suricata-1.2.1-orig/src/log-pcap.c	2012-01-20 16:17:30.000000000 +0100
+++ suricata-1.2.1/src/log-pcap.c	2012-05-24 12:51:14.031994189 +0200
@@ -63,6 +63,8 @@
 
 #define LOGMODE_NORMAL                  0
 #define LOGMODE_SGUIL                   1
+#define LOGMODE_ARCHIVE                 2
+
 
 #define RING_BUFFER_MODE_DISABLED       0
 #define RING_BUFFER_MODE_ENABLED        1
@@ -84,7 +86,8 @@
  *
  * Used for storing file options.
  */
-typedef struct PcapLogData_ {
+typedef struct PcapLogData_
+{
     uint64_t size_current;      /**< file current size */
     uint64_t size_limit;        /**< file size limit */
     struct pcap_pkthdr *h;      /**< pcap header struct */
@@ -100,14 +103,21 @@
     int use_ringbuffer;         /**< ring buffer mode enabled or disabled */
     int timestamp_format;       /**< timestamp format sec or usec */
     int use_stream_depth;       /**< use stream depth i.e. ignore packets that reach limit */
-    char dir[PATH_MAX];         /**< pcap log directory */
+
+    /* ARCHIVE related vars */
+    char *iface;                /**<iface where data are collected */
+    char hostname[HOST_NAME_MAX];/**<hostname of the current machine */
+    char tdir[PATH_MAX];        /**< temporary directory where file are dumped until they are closed */
+    char dir[PATH_MAX];         /**< closed pcap files are moved in that destination directory */
+
 } PcapLogData;
 
 static PcapLogData *pl;         /**< pcap_dumper is not thread safe */
 int PcapLogOpenFileCtx(PcapLogData *);
 static SCMutex plog_lock;
 
-typedef struct PcapFileName_ {
+typedef struct PcapFileName_
+{
     char *filename;
     char *dirname;
     TAILQ_ENTRY(PcapFileName_) next; /**< Pointer to next Pcap File for tailq. */
@@ -117,21 +127,27 @@
 static TAILQ_HEAD(, PcapFileName_) pcap_file_list =
     TAILQ_HEAD_INITIALIZER(pcap_file_list);
 
-void TmModulePcapLogRegister (void) {
+void TmModulePcapLogRegister (void)
+{
     SCMutexInit(&plog_lock, NULL);
 
     pl = SCMalloc(sizeof(PcapLogData));
-    if (pl == NULL) {
+
+    if (pl == NULL)
+    {
         SCLogError(SC_ERR_MEM_ALLOC,
-            "Failed to allocate Memory for PcapLogData");
+                   "Failed to allocate Memory for PcapLogData");
         exit(EXIT_FAILURE);
     }
+
     memset(pl, 0, sizeof(PcapLogData));
 
     pl->h = SCMalloc(sizeof(*pl->h));
-    if (pl->h == NULL) {
+
+    if (pl->h == NULL)
+    {
         SCLogError(SC_ERR_MEM_ALLOC,
-            "Failed to allocate Memory for pcap header struct");
+                   "Failed to allocate Memory for pcap header struct");
         exit(EXIT_FAILURE);
     }
 
@@ -157,17 +173,22 @@
  *  \param t Thread Variable containing  input/output queue, cpu affinity etc.
  *  \param pl PcapLog thread variable.
  */
-int PcapLogCloseFile(ThreadVars *t, PcapLogData *pl) {
-    if (pl != NULL) {
+int PcapLogCloseFile(ThreadVars *t, PcapLogData *pl)
+{
+    if (pl != NULL)
+    {
         if (pl->pcap_dumper != NULL)
             pcap_dump_close(pl->pcap_dumper);
+
         pl->size_current = 0;
         pl->pcap_dumper = NULL;
 
         if (pl->pcap_dead_handle != NULL)
             pcap_close(pl->pcap_dead_handle);
+
         pl->pcap_dead_handle = NULL;
     }
+
     return 0;
 }
 
@@ -180,68 +201,115 @@
  *  \retval 0 on succces
  *  \retval -1 on failure
  */
-int PcapLogRotateFile(ThreadVars *t, PcapLogData *pl) {
+int PcapLogRotateFile(ThreadVars *t, PcapLogData *pl)
+{
 
     PcapFileName *pf;
     PcapFileName *pfnext;
 
-    if (PcapLogCloseFile(t,pl) < 0) {
+    if (PcapLogCloseFile(t,pl) < 0)
+    {
         SCLogDebug("PcapLogCloseFile failed");
         return -1;
     }
 
-    if (pl->use_ringbuffer == RING_BUFFER_MODE_ENABLED && pl->file_cnt >= pl->max_files) {
-         pf = TAILQ_FIRST(&pcap_file_list);
-         SCLogDebug("Removing pcap file %s", pf->filename);
-
-         if (remove(pf->filename) != 0) {
-             SCLogError(SC_ERR_PCAP_FILE_DELETE_FAILED,
-                 "failed to remove log file %s: %s",
-                 pf->filename, strerror( errno ));
-             TAILQ_REMOVE(&pcap_file_list, pf, next);
-             if (pf != NULL)
-                 free(pf);
-
-             return -1;
-         }
-         else {
-             SCLogDebug("success! removed log file %s", pf->filename);
-
-             /* Remove directory if Sguil mode and no files left in sguil dir */
-             if (pl->mode == LOGMODE_SGUIL) {
-
-                  pfnext = TAILQ_NEXT(pf,next);
-
-                  if (strcmp(pf->dirname, pfnext->dirname) == 0) {
-                      SCLogDebug("Current entry dir %s and next entry %s "
-                          "are equal: not removing dir",
-                          pf->dirname, pfnext->dirname);
-                  } else {
-                      SCLogDebug("current entry %s and %s are "
-                          "not equal: removing dir",
-                          pf->dirname, pfnext->dirname);
-
-                      if (remove(pf->dirname) != 0) {
-                          SCLogError(SC_ERR_PCAP_FILE_DELETE_FAILED,
-                              "failed to remove sguil log %s: %s",
-                              pf->dirname, strerror( errno ));
-                          TAILQ_REMOVE(&pcap_file_list, pf, next);
-                          if (pf != NULL)
-                              free(pf);
-
-                          return -1;
-                      }
-                 }
-             }
-             TAILQ_REMOVE(&pcap_file_list, pf, next);
-             if (pf != NULL)
-                 free(pf);
+    if (pl->use_ringbuffer == RING_BUFFER_MODE_ENABLED && pl->file_cnt >= pl->max_files)
+    {
+        pf = TAILQ_FIRST(&pcap_file_list);
+        SCLogDebug("Removing pcap file %s", pf->filename);
+
+        if (remove(pf->filename) != 0)
+        {
+            SCLogError(SC_ERR_PCAP_FILE_DELETE_FAILED, "failed to remove log file %s: %s", pf->filename, strerror( errno ));
+            TAILQ_REMOVE(&pcap_file_list, pf, next);
+
+            if (pf != NULL)
+                free(pf);
+
+            return -1;
+        }
+
+        else
+        {
+            SCLogDebug("success! removed log file %s", pf->filename);
 
-             pl->file_cnt--;
-         }
+            /* Remove directory if Sguil mode and no files left in sguil dir */
+            if (pl->mode == LOGMODE_SGUIL)
+            {
+
+                pfnext = TAILQ_NEXT(pf,next);
+
+                if (strcmp(pf->dirname, pfnext->dirname) == 0)
+                {
+                    SCLogDebug("Current entry dir %s and next entry %s "
+                               "are equal: not removing dir",
+                               pf->dirname, pfnext->dirname);
+                }
+
+                else
+                {
+                    SCLogDebug("current entry %s and %s are "
+                               "not equal: removing dir",
+                               pf->dirname, pfnext->dirname);
+
+                    if (remove(pf->dirname) != 0)
+                    {
+                        SCLogError(SC_ERR_PCAP_FILE_DELETE_FAILED,
+                                   "failed to remove sguil log %s: %s",
+                                   pf->dirname, strerror( errno ));
+                        TAILQ_REMOVE(&pcap_file_list, pf, next);
+
+                        if (pf != NULL)
+                            free(pf);
+
+                        return -1;
+                    }
+                }
+            }
+
+            TAILQ_REMOVE(&pcap_file_list, pf, next);
+
+            if (pf != NULL)
+                free(pf);
+
+            pl->file_cnt--;
+        }
     }
 
-    if (PcapLogOpenFileCtx(pl) < 0) {
+    /* if logmode is ARCHIVE move file actually closed in the destination directory from the temporary directory */
+    if ( pl->mode == LOGMODE_ARCHIVE)
+    {
+        char *srcdir = NULL, *dstdir = NULL;
+        unsigned int filename_path_size = 0;
+
+        /* Get the absolute path name of the last closed pcap filename */
+        if ((pf = TAILQ_FIRST(&pcap_file_list)) == NULL )
+            return -1;
+
+        /* Create reference to handle absolute dst path file */
+        filename_path_size = strlen(pl->dir) + strlen(basename(pf->filename));
+
+        dstdir = SCMalloc(filename_path_size * 2);
+        snprintf(dstdir, filename_path_size * 2, "%s/%s", pl->dir, basename(pf->filename));
+
+        /* move closed file from src to dest ! */
+        if ( rename(pf->filename, dstdir) )
+        {
+            SCLogError(SC_ERR_LOGPCAP_ARCHIVE_FILE_RENAME_FAILED, "log-pcap unable to move %s to %s: %s", pf->filename, pl->dir, strerror(errno));
+            return -1;
+        }
+
+        SCFree(dstdir);
+
+        pfnext = TAILQ_NEXT(pf,next);
+        TAILQ_REMOVE(&pcap_file_list, pf, next);
+
+        if ( pf != NULL )
+			free(pf);
+    }
+
+    if (PcapLogOpenFileCtx(pl) < 0)
+    {
         SCLogError(SC_ERR_FOPEN, "opening new pcap log file failed");
         return -1;
     }
@@ -284,25 +352,32 @@
     pl->h->len = GET_PKT_LEN(p);
     len = sizeof(*pl->h) + GET_PKT_LEN(p);
 
-    if (pl->filename == NULL) {
+    if (pl->filename == NULL)
+    {
         SCLogDebug("Opening PCAP log file %s", pl->filename);
         ret = PcapLogOpenFileCtx(pl);
-        if (ret < 0) {
+
+        if (ret < 0)
+        {
             SCMutexUnlock(&plog_lock);
             return TM_ECODE_FAILED;
         }
     }
 
-    if (pl->mode == LOGMODE_SGUIL) {
+    if (pl->mode == LOGMODE_SGUIL)
+    {
         struct tm local_tm;
         struct tm *tms = (struct tm *)localtime_r(&p->ts.tv_sec, &local_tm);
-        if (tms->tm_mday != pl->prev_day) {
+
+        if (tms->tm_mday != pl->prev_day)
+        {
             rotate = 1;
             pl->prev_day = tms->tm_mday;
         }
     }
 
-    if ((pl->size_current + len) > pl->size_limit || rotate) {
+    if ((pl->size_current + len) > pl->size_limit || rotate)
+    {
         if (PcapLogRotateFile(t,pl) < 0)
         {
             SCMutexUnlock(&plog_lock);
@@ -313,11 +388,12 @@
 
     /* XXX pcap handles, nfq, pfring, can only have one link type ipfw? we do
      * this here as we don't know the link type until we get our first packet */
-    if (pl->pcap_dead_handle == NULL) {
+    if (pl->pcap_dead_handle == NULL)
+    {
         SCLogDebug("Setting pcap-log link type to %u", p->datalink);
 
         if ((pl->pcap_dead_handle = pcap_open_dead(p->datalink,
-                        LIBPCAP_SNAPLEN)) == NULL)
+                                    LIBPCAP_SNAPLEN)) == NULL)
         {
             SCLogDebug("Error opening dead pcap handle");
 
@@ -325,11 +401,13 @@
             return TM_ECODE_FAILED;
         }
     }
+
     /* XXX LogfileCtx setup currently doesn't allow thread vars so we open the
      * handle here */
-    if (pl->pcap_dumper == NULL) {
+    if (pl->pcap_dumper == NULL)
+    {
         if ((pl->pcap_dumper = pcap_dump_open(pl->pcap_dead_handle,
-                        pl->filename)) == NULL)
+                                              pl->filename)) == NULL)
         {
             SCLogInfo("Error opening dump file %s", pcap_geterr(pl->pcap_dead_handle));
 
@@ -387,9 +465,12 @@
 TmEcode PcapLogDataDeinit(ThreadVars *t, void *data)
 {
     SCMutexLock(&plog_lock);
-    if (pl == NULL) {
+
+    if (pl == NULL)
+    {
         goto error;
     }
+
     SCLogInfo("Packets seen %" PRIu64 " at exit", pl->pkt_cnt);
     /* clear memory */
     memset(pl, 0, sizeof(PcapLogData));
@@ -397,10 +478,13 @@
     return TM_ECODE_OK;
 
 error:
+
     /* clear memory */
-    if (pl != NULL) {
+    if (pl != NULL)
+    {
         memset(pl, 0, sizeof(PcapLogData));
     }
+
     SCMutexUnlock(&plog_lock);
     return TM_ECODE_FAILED;
 }
@@ -413,124 +497,241 @@
 {
     SCMutexLock(&plog_lock);
     const char *filename = NULL;
-    if (conf != NULL) { /* To faciliate unit tests. */
+
+    if (conf != NULL)   /* To faciliate unit tests. */
+    {
         filename = ConfNodeLookupChildValue(conf, "filename");
     }
+
     if (filename == NULL)
         filename = DEFAULT_LOG_FILENAME;
 
-    if ((pl->prefix = SCStrdup(filename)) == NULL) {
+    if ((pl->prefix = SCStrdup(filename)) == NULL)
+    {
 
-            SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory for directory name");
-            return NULL;
+        SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory for directory name");
+        return NULL;
     }
 
     pl->size_limit = DEFAULT_LIMIT;
-    if (conf != NULL) {
+
+    if (conf != NULL)
+    {
         const char *s_limit = NULL;
         s_limit = ConfNodeLookupChildValue(conf, "limit");
-        if (s_limit != NULL) {
-            if (ParseSizeStringU64(s_limit, &pl->size_limit) < 0) {
+
+        if (s_limit != NULL)
+        {
+            if (ParseSizeStringU64(s_limit, &pl->size_limit) < 0)
+            {
                 SCLogError(SC_ERR_INVALID_ARGUMENT,
-                    "Failed to initialize unified2 output, invalid limit: %s",
-                    s_limit);
+                           "Failed to initialize unified2 output, invalid limit: %s",
+                           s_limit);
                 exit(EXIT_FAILURE);
             }
-            if (pl->size_limit < 4096) {
-                SCLogInfo("pcap-log \"limit\" value of %"PRIu64" assumed to be pre-1.2 "
-                        "style: setting limit to %"PRIu64"mb", pl->size_limit, pl->size_limit);
+
+            if (pl->size_limit < 4096)
+            {
+                SCLogInfo("pcap-log \"limit\" value of %"PRIu64" assumed to be pre-1.2 " "style: setting limit to %"PRIu64"mb", pl->size_limit, pl->size_limit);
                 uint64_t size = pl->size_limit * 1024 * 1024;
                 pl->size_limit = size;
-            } else if (pl->size_limit < MIN_LIMIT) {
+            }
+
+            else if (pl->size_limit < MIN_LIMIT)
+            {
                 SCLogError(SC_ERR_INVALID_ARGUMENT,
-                    "Fail to initialize pcap-log output, limit less than "
-                    "allowed minimum.");
+                           "Fail to initialize pcap-log output, limit less than "
+                           "allowed minimum.");
                 exit(EXIT_FAILURE);
             }
         }
     }
 
-    if (conf != NULL) {
+    if (conf != NULL)
+    {
         const char *s_mode = NULL;
         s_mode = ConfNodeLookupChildValue(conf, "mode");
-        if (s_mode != NULL) {
-            if (strcasecmp(s_mode, "sguil") == 0) {
+
+        if (s_mode != NULL)
+        {
+            if (strcasecmp(s_mode, "sguil") == 0)
+            {
                 pl->mode = LOGMODE_SGUIL;
-            } else if (strcasecmp(s_mode, "normal") != 0) {
+            }
+            else if (strcasecmp(s_mode, "ARCHIVE") == 0 )
+            {
+                pl->mode = LOGMODE_ARCHIVE;
+            }
+
+            else if (strcasecmp(s_mode, "normal") != 0)
+            {
                 SCLogError(SC_ERR_INVALID_ARGUMENT,
-                    "log-pcap you must specify \"sguil\" or \"normal\" mode "
-                    "option to be set.");
+                           "log-pcap you must specify \"sguil\" or \"normal\" mode "
+                           "option to be set.");
                 exit(EXIT_FAILURE);
             }
         }
 
         const char *s_dir = NULL;
+
         s_dir = ConfNodeLookupChildValue(conf, "dir");
-        if (s_dir == NULL) {
+
+        if (s_dir == NULL)
+        {
             s_dir = ConfNodeLookupChildValue(conf, "sguil-base-dir");
-            if (s_dir == NULL) {
+
+            if (s_dir == NULL)
+            {
                 s_dir = ConfNodeLookupChildValue(conf, "sguil_base_dir");
             }
         }
-        if (s_dir == NULL) {
-            if (pl->mode == LOGMODE_SGUIL) {
+
+        if (s_dir == NULL)
+        {
+            if (pl->mode == LOGMODE_SGUIL)
+            {
                 SCLogError(SC_ERR_LOGPCAP_SGUIL_BASE_DIR_MISSING,
-                    "log-pcap \"sguil\" mode requires \"sguil-base-dir\" "
-                    "option to be set.");
+                           "log-pcap \"sguil\" mode requires \"sguil-base-dir\" "
+                           "option to be set.");
                 exit(EXIT_FAILURE);
-            } else {
-                char *log_dir = NULL;
-                if (ConfGet("default-log-dir", &log_dir) != 1)
-                    log_dir = DEFAULT_LOG_DIR;
+            }
 
-                strlcpy(pl->dir,
-                    log_dir, sizeof(pl->dir));
+            else
+                /* LOGMODE_ARCHIVE configuration related variables allocation */
+                if (pl->mode == LOGMODE_ARCHIVE)
+                {
+                    /* get temporary directory path */
+                    s_dir = ConfNodeLookupChildValue(conf, "archive_temp_dir");
+                    if ( s_dir == NULL )
+                    {
+                        SCLogError(SC_ERR_LOGPCAP_ARCHIVE_TEMP_DIR_MISSING, "log-pcap \"ARCHIVE\" mode requires \"archive_temp_dir\" option to be set.");
+                        exit(EXIT_FAILURE);
+                    }
+                    if (!PathIsAbsolute(s_dir))
+                    {
+                        SCLogError(SC_ERR_LOGPCAP_ARCHIVE_ABSOLUTE_PATH_DIR_REQUIRED, "log-pcap \"ARCHIVE\" mode requires only absolute path dir to be set.");
+                        exit(EXIT_FAILURE);
+                    }
+                    if ( access(s_dir, R_OK | W_OK | X_OK ) )
+                    {
+                        SCLogError(SC_ERR_LOGPCAP_ARCHIVE_TEMP_DIR_MISSING, "log-pcap \"ARCHIVE\" mode requires temp directory \"%s\" accessible, writable.", s_dir);
+                        exit(EXIT_FAILURE);
+                    }
+                    strlcpy(pl->tdir, s_dir, sizeof pl->tdir);
+
+                    /* get destination directory path */
+                    s_dir = ConfNodeLookupChildValue(conf, "archive_dest_dir");
+                    if ( s_dir == NULL )
+                    {
+                        SCLogError(SC_ERR_LOGPCAP_ARCHIVE_TEMP_DIR_MISSING, "log-pcap \"ARCHIVE\" mode requires \"archive_temp_dir\" option to be set.");
+                        exit(EXIT_FAILURE);
+                    }
+                    if (!PathIsAbsolute(s_dir))
+                    {
+                        SCLogError(SC_ERR_LOGPCAP_ARCHIVE_ABSOLUTE_PATH_DIR_REQUIRED, "log-pcap \"ARCHIVE\" mode requires only absolute path dir to be set.");
+                        exit(EXIT_FAILURE);
+                    }
+                    if ( access(s_dir, R_OK | W_OK | X_OK ) )
+                    {
+                        SCLogError(SC_ERR_LOGPCAP_ARCHIVE_TEMP_DIR_MISSING, "log-pcap \"ARCHIVE\" mode requires dump directory \"%s\" accessible, writable.", s_dir);
+                        exit(EXIT_FAILURE);
+                    }
+                    strlcpy(pl->dir, s_dir, sizeof pl->dir);
+
+                    if ( gethostname(pl->hostname, HOST_NAME_MAX) )
+                    {
+                        SCLogError(SC_ERR_LOGPCAP_ARCHIVE_HOSTNAME_REQUIRED, "log-pcap \"ARCHIVE\" mode requires that the machine have a valid hostname.");
+                        exit(EXIT_FAILURE);
+                    }
+                }
+                else
+                {
+                    char *log_dir = NULL;
+
+                    if (ConfGet("default-log-dir", &log_dir) != 1)
+                        log_dir = DEFAULT_LOG_DIR;
+
+                    strlcpy(pl->dir,
+                            log_dir, sizeof(pl->dir));
                     SCLogInfo("Using log dir %s", pl->dir);
-            }
-        } else {
-            if (PathIsAbsolute(s_dir)) {
+                }
+        }
+
+        else
+        {
+            if (PathIsAbsolute(s_dir))
+            {
                 strlcpy(pl->dir,
                         s_dir, sizeof(pl->dir));
-            } else {
+            }
+
+            else
+            {
                 char *log_dir = NULL;
+
                 if (ConfGet("default-log-dir", &log_dir) != 1)
                     log_dir = DEFAULT_LOG_DIR;
 
                 snprintf(pl->dir, sizeof(pl->dir), "%s/%s",
-                    log_dir, s_dir);
+                         log_dir, s_dir);
             }
 
             struct stat stat_buf;
-            if (stat(pl->dir, &stat_buf) != 0) {
+
+            if (stat(pl->dir, &stat_buf) != 0)
+            {
                 SCLogError(SC_ERR_LOGDIR_CONFIG, "The sguil-base-dir directory \"%s\" "
-                        "supplied doesn't exist. Shutting down the engine",
-                        pl->dir);
+                           "supplied doesn't exist. Shutting down the engine",
+                           pl->dir);
                 exit(EXIT_FAILURE);
             }
+
             SCLogInfo("Using log dir %s", pl->dir);
         }
     }
 
-    SCLogInfo("using %s logging", pl->mode == LOGMODE_SGUIL ?
-            "Sguil compatible" : "normal");
+    switch(pl->mode)
+    {
+    case LOGMODE_NORMAL:
+        SCLogInfo("using normal logging");
+        break;
+
+    case LOGMODE_SGUIL:
+        SCLogInfo("using Sguil compatible logging");
+        break;
+
+    case LOGMODE_ARCHIVE:
+        SCLogInfo("using ARCHIVE compatible logging");
+        break;
+    }
 
     uint32_t max_file_limit = DEFAULT_FILE_LIMIT;
-    if (conf != NULL) {
+
+    if (conf != NULL)
+    {
         const char *max_number_of_files_s = NULL;
         max_number_of_files_s = ConfNodeLookupChildValue(conf, "max-files");
-        if (max_number_of_files_s != NULL) {
-            if (ByteExtractStringUint32(&max_file_limit, 10, 0, max_number_of_files_s) == -1) {
+
+        if (max_number_of_files_s != NULL)
+        {
+            if (ByteExtractStringUint32(&max_file_limit, 10, 0, max_number_of_files_s) == -1)
+            {
                 SCLogError(SC_ERR_INVALID_ARGUMENT,
-                    "Failed to initialize pcap-log output, invalid number of files limit: %s",
-                    max_number_of_files_s);
+                           "Failed to initialize pcap-log output, invalid number of files limit: %s",
+                           max_number_of_files_s);
                 exit(EXIT_FAILURE);
             }
-            else if (max_file_limit < 1) {
+
+            else if (max_file_limit < 1)
+            {
                 SCLogError(SC_ERR_INVALID_ARGUMENT,
-                    "Failed to initialize pcap-log output, limit less than "
-                    "allowed minimum.");
+                           "Failed to initialize pcap-log output, limit less than "
+                           "allowed minimum.");
                 exit(EXIT_FAILURE);
-            } else {
+            }
+
+            else
+            {
                 pl->max_files = max_file_limit;
                 pl->use_ringbuffer = RING_BUFFER_MODE_ENABLED;
             }
@@ -538,42 +739,65 @@
     }
 
     const char *ts_format = NULL;
-    if (conf != NULL) { /* To faciliate unit tests. */
+
+    if (conf != NULL)   /* To faciliate unit tests. */
+    {
         ts_format = ConfNodeLookupChildValue(conf, "ts-format");
     }
-    if (ts_format != NULL) {
-        if (strcasecmp(ts_format, "usec") == 0) {
+
+    if (ts_format != NULL)
+    {
+        if (strcasecmp(ts_format, "usec") == 0)
+        {
             pl->timestamp_format = TS_FORMAT_USEC;
-        } else if (strcasecmp(ts_format, "sec") != 0) {
+        }
+
+        else if (strcasecmp(ts_format, "sec") != 0)
+        {
             SCLogError(SC_ERR_INVALID_ARGUMENT,
-                "log-pcap ts_format specified %s is invalid must be"
-                " \"sec\" or \"usec\"", ts_format);
+                       "log-pcap ts_format specified %s is invalid must be"
+                       " \"sec\" or \"usec\"", ts_format);
             exit(EXIT_FAILURE);
         }
     }
 
     const char *use_stream_depth = NULL;
-    if (conf != NULL) { /* To faciliate unit tests. */
+
+    if (conf != NULL)   /* To faciliate unit tests. */
+    {
         use_stream_depth = ConfNodeLookupChildValue(conf, "use-stream-depth");
     }
-    if (use_stream_depth != NULL) {
-        if (ConfValIsFalse(use_stream_depth)) {
+
+    if (use_stream_depth != NULL)
+    {
+        if (ConfValIsFalse(use_stream_depth))
+        {
             pl->use_stream_depth = USE_STREAM_DEPTH_DISABLED;
-        } else if (ConfValIsTrue(use_stream_depth)) {
+        }
+
+        else if (ConfValIsTrue(use_stream_depth))
+        {
             pl->use_stream_depth = USE_STREAM_DEPTH_ENABLED;
-        } else {
+        }
+
+        else
+        {
             SCLogError(SC_ERR_INVALID_ARGUMENT,
-                "log-pcap use_stream_depth specified is invalid must be");
+                       "log-pcap use_stream_depth specified is invalid must be");
             exit(EXIT_FAILURE);
         }
     }
+
     SCMutexUnlock(&plog_lock);
 
     OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx));
-    if (output_ctx == NULL) {
+
+    if (output_ctx == NULL)
+    {
         SCLogError(SC_ERR_MEM_ALLOC, "Failed to allocate memory for OutputCtx.");
         exit(EXIT_FAILURE);
     }
+
     output_ctx->data = NULL;
     output_ctx->DeInit = PcapLogFileDeInitCtx;
 
@@ -585,12 +809,14 @@
     SCMutexLock(&plog_lock);
     PcapFileName *pf;
 
-    TAILQ_FOREACH(pf, &pcap_file_list, next) {
+    TAILQ_FOREACH(pf, &pcap_file_list, next)
+    {
         SCLogDebug("PCAP files left at exit: %s\n", pf->filename);
     }
     SCMutexUnlock(&plog_lock);
 
-    if (output_ctx != NULL) {
+    if (output_ctx != NULL)
+    {
         SCFree(output_ctx);
     }
 
@@ -610,13 +836,16 @@
 
     if (pl->filename != NULL)
         filename = pl->filename;
-    else {
+    else
+    {
         filename = pl->filename = SCMalloc(PATH_MAX);
-        if (filename == NULL) {
+
+        if (filename == NULL)
+        {
             return -1;
         }
     }
-
+	
     /** get the time so we can have a filename with seconds since epoch */
     struct timeval ts;
     memset(&ts, 0x00, sizeof(struct timeval));
@@ -625,18 +854,21 @@
 
     /* Place to store the name of our PCAP file */
     PcapFileName *pf = SCMalloc(sizeof(PcapFileName));
-    if (pf == NULL) {
+
+    if (pf == NULL)
+    {
         return -1;
     }
 
-    if (pl->mode == LOGMODE_SGUIL) {
+    /* SGUIL filename creation convention */
+    if (pl->mode == LOGMODE_SGUIL)
+    {
         struct tm local_tm;
-        struct tm *tms = (struct tm *)localtime_r(&ts.tv_sec, &local_tm);
+        localtime_r(&ts.tv_sec, &local_tm);
 
         char dirname[32], dirfull[PATH_MAX] = "";
 
-        snprintf(dirname, sizeof(dirname), "%04d-%02d-%02d",
-                tms->tm_year + 1900, tms->tm_mon + 1, tms->tm_mday);
+        snprintf(dirname, sizeof(dirname), "%04d-%02d-%02d", local_tm.tm_year + 1900, local_tm.tm_mon + 1, local_tm.tm_mday);
 
         /* create the filename to use */
         snprintf(dirfull, PATH_MAX, "%s/%s", pl->dir, dirname);
@@ -647,35 +879,65 @@
 #else
         (void)mkdir(dirfull);
 #endif
-        if ((pf->dirname = SCStrdup(dirfull)) == NULL) {
+
+        if ((pf->dirname = SCStrdup(dirfull)) == NULL)
+        {
             SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory for directory name");
             return -1;
         }
 
-        if (strlen(pf->dirname) == 0) {
+        if (strlen(pf->dirname) == 0)
+        {
             SCFree(pf->dirname);
             return -1;
         }
 
-        if (pl->timestamp_format == TS_FORMAT_SEC) {
+        if (pl->timestamp_format == TS_FORMAT_SEC)
+        {
             snprintf(filename, PATH_MAX, "%s/%s.%" PRIu32, dirfull, pl->prefix, (uint32_t)ts.tv_sec);
-        } else {
+        }
+
+        else
+        {
             snprintf(filename, PATH_MAX, "%s/%s.%" PRIu32 ".%" PRIu32, dirfull, pl->prefix, (uint32_t)ts.tv_sec, (uint32_t)ts.tv_usec);
         }
 
-    } else {
+    }
+    /* ARCHIVE filename creation convention */
+    else if ( pl->mode == LOGMODE_ARCHIVE )
+    {
+        struct tm local_tm;
+
+        if ((pf->dirname = SCStrdup(pl->tdir)) == NULL )
+        {
+            SCLogError(SC_ERR_MEM_ALLOC, "pcap-log \"ARCHIVE\" mode Error allocating memory for temporary directory name");
+            return -1;
+        }
+
+        localtime_r(&ts.tv_sec, &local_tm);
+        snprintf(pl->filename, PATH_MAX, "%s/%s-%04d%02d%02d-%02d%02d%02d.pcap", pf->dirname, pl->hostname, local_tm.tm_year + 1900, local_tm.tm_mon +1, local_tm.tm_mday,
+                 local_tm.tm_hour, local_tm.tm_min, local_tm.tm_sec);
+   	}
+    else
+    {
         /* create the filename to use */
-        if (pl->timestamp_format == TS_FORMAT_SEC) {
+        if (pl->timestamp_format == TS_FORMAT_SEC)
+        {
             snprintf(filename, PATH_MAX, "%s/%s.%" PRIu32, pl->dir, pl->prefix, (uint32_t)ts.tv_sec);
-        } else {
+        }
+
+        else
+        {
             snprintf(filename, PATH_MAX, "%s/%s.%" PRIu32 ".%" PRIu32, pl->dir, pl->prefix, (uint32_t)ts.tv_sec, (uint32_t)ts.tv_usec);
         }
     }
 
-    if ((pf->filename = SCStrdup(pl->filename)) == NULL) {
+    if ((pf->filename = SCStrdup(pl->filename)) == NULL)
+    {
         SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory. For filename");
         return -1;
     }
+
     SCLogDebug("Opening pcap file log %s\n", pf->filename);
     TAILQ_INSERT_TAIL(&pcap_file_list, pf, next);
 
diff -Nura suricata-1.2.1-orig/src/Makefile.in suricata-1.2.1/src/Makefile.in
--- suricata-1.2.1-orig/src/Makefile.in	2012-01-20 16:19:01.000000000 +0100
+++ suricata-1.2.1/src/Makefile.in	2012-05-23 14:15:51.699319176 +0200
@@ -745,9 +745,9 @@
 	      exit 1;; \
 	  esac; \
 	done; \
-	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/Makefile'; \
 	$(am__cd) $(top_srcdir) && \
-	  $(AUTOMAKE) --gnu src/Makefile
+	  $(AUTOMAKE) --foreign src/Makefile
 .PRECIOUS: Makefile
 Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
 	@case '$?' in \
diff -Nura suricata-1.2.1-orig/src/util-error.h suricata-1.2.1/src/util-error.h
--- suricata-1.2.1-orig/src/util-error.h	2012-01-20 16:17:30.000000000 +0100
+++ suricata-1.2.1/src/util-error.h	2012-05-24 12:14:46.222865141 +0200
@@ -213,6 +213,11 @@
     SC_ERR_HTTP_COOKIE_INCOMPATIBLE_WITH_RAWBYTES,
     SC_ERR_HTTP_COOKIE_RELATIVE_MISSING,
     SC_ERR_LOGPCAP_SGUIL_BASE_DIR_MISSING,
+    SC_ERR_LOGPCAP_ARCHIVE_TEMP_DIR_MISSING, 
+    SC_ERR_LOGPCAP_ARCHIVE_DEST_DIR_MISSING,
+    SC_ERR_LOGPCAP_ARCHIVE_ABSOLUTE_PATH_DIR_REQUIRED,
+    SC_ERR_LOGPCAP_ARCHIVE_FILE_RENAME_FAILED,
+    SC_ERR_LOGPCAP_ARCHIVE_HOSTNAME_REQUIRED,
     SC_ERR_UNKNOWN_DECODE_EVENT,
     SC_ERR_RUNMODE,
     SC_ERR_SHUTDOWN,


More information about the Oisf-devel mailing list