new upstream release (3.3.0); modify package compatibility for Stretch
[ossec-hids.git] / src / analysisd / analysisd.c
old mode 100755 (executable)
new mode 100644 (file)
index 132606a..a220f44
@@ -1,6 +1,3 @@
-/* @(#) $Id: ./src/analysisd/analysisd.c, 2012/07/26 dcid Exp $
- */
-
 /* Copyright (C) 2010-2012 Trend Micro Inc.
  * All rights reserved.
  *
@@ -8,93 +5,50 @@
  * and/or modify it under the terms of the GNU General Public
  * License (version 2) as published by the FSF - Free Software
  * Foundation.
- *
- * License details at the LICENSE file included with OSSEC or
- * online at: http://www.ossec.net/en/licensing.html
  */
 
-
-/* Part of the OSSEC
- * Available at http://www.ossec.net
- */
-
-
-/* ossec-analysisd.
- * Responsible for correlation and log decoding.
+/* ossec-analysisd
+ * Responsible for correlation and log decoding
  */
 
 #ifndef ARGV0
-   #define ARGV0 "ossec-analysisd"
+#define ARGV0 "ossec-analysisd"
 #endif
 
 #include "shared.h"
-
 #include "alerts/alerts.h"
 #include "alerts/getloglocation.h"
 #include "os_execd/execd.h"
-
 #include "os_regex/os_regex.h"
 #include "os_net/os_net.h"
-
-
-/** Local headers **/
 #include "active-response.h"
 #include "config.h"
 #include "rules.h"
 #include "stats.h"
-
 #include "eventinfo.h"
+#include "accumulator.h"
 #include "analysisd.h"
+#include "fts.h"
+#include "cleanevent.h"
+#include "dodiff.h"
+#include "output/jsonout.h"
 
-#include "picviz.h"
-
-#ifdef PRELUDE
-#include "prelude.h"
+#ifdef PRELUDE_OUTPUT_ENABLED
+#include "output/prelude.h"
 #endif
 
-#ifdef ZEROMQ_OUTPUT
-#include "zeromq_output.h"
+#ifdef ZEROMQ_OUTPUT_ENABLED
+#include "output/zeromq.h"
 #endif
 
-/** Global data **/
-
-/* execd queue */
-int execdq = 0;
-
-/* active response queue */
-int arq = 0;
-
+#ifdef SQLITE_ENABLED
+#include "syscheck-sqlite.h"
+#endif
 
-/** Internal Functions **/
+/** Prototypes **/
 void OS_ReadMSG(int m_queue);
 RuleInfo *OS_CheckIfRuleMatch(Eventinfo *lf, RuleNode *curr_node);
-
-
-/** External functions prototypes (only called here) **/
-
-/* For config  */
-int GlobalConf(char * cfgfile);
-
-
-/* For rules */
-void Rules_OP_CreateRules();
-void Lists_OP_CreateLists();
-int Rules_OP_ReadRules(char * cfgfile);
-int _setlevels(RuleNode *node, int nnode);
-int AddHash_Rule(RuleNode *node);
-
-
-/* For cleanmsg */
-int OS_CleanMSG(char *msg, Eventinfo *lf);
-
-
-/* for FTS */
-int FTS_Init();
-int FTS(Eventinfo *lf);
-int AddtoIGnore(Eventinfo *lf);
-int IGnore(Eventinfo *lf);
-int doDiff(RuleInfo *currently_rule, Eventinfo *lf);
-
+static void LoopRule(RuleNode *curr_node, FILE *flog);
 
 /* For decoders */
 void DecodeEvent(Eventinfo *lf);
@@ -102,49 +56,71 @@ int DecodeSyscheck(Eventinfo *lf);
 int DecodeRootcheck(Eventinfo *lf);
 int DecodeHostinfo(Eventinfo *lf);
 
+/* For stats */
+static void DumpLogstats(void);
+
+/** Global definitions **/
+int today;
+int thishour;
+int prev_year;
+char prev_month[4];
+int __crt_hour;
+int __crt_wday;
+time_t c_time;
+char __shost[512];
+OSDecoderInfo *NULL_Decoder;
 
-/* For Decoders */
-int ReadDecodeXML(char *file);
-int SetDecodeXML();
-
+/* execd queue */
+static int execdq = 0;
 
-/* For syscheckd (integrity checking) */
-void SyscheckInit();
-void RootcheckInit();
-void HostinfoInit();
+/* Active response queue */
+static int arq = 0;
 
+static int hourly_alerts;
+static int hourly_events;
+static int hourly_syscheck;
+static int hourly_firewall;
 
-/* For stats */
-int Start_Hour();
-int Check_Hour(Eventinfo *lf);
-void Update_Hour();
-void DumpLogstats();
-
-/* Hourly alerts */
-int hourly_alerts;
-int hourly_events;
-int hourly_syscheck;
-int hourly_firewall;
 
+/* Print help statement */
+__attribute__((noreturn))
+static void help_analysisd(void)
+{
+    print_header();
+    print_out("  %s: -[Vhdtf] [-u user] [-g group] [-c config] [-D dir]", ARGV0);
+    print_out("    -V          Version and license message");
+    print_out("    -h          This help message");
+    print_out("    -d          Execute in debug mode. This parameter");
+    print_out("                can be specified multiple times");
+    print_out("                to increase the debug level.");
+    print_out("    -t          Test configuration");
+    print_out("    -f          Run in foreground");
+    print_out("    -u <user>   User to run as (default: %s)", USER);
+    print_out("    -g <group>  Group to run as (default: %s)", GROUPGLOBAL);
+    print_out("    -c <config> Configuration file to use (default: %s)", DEFAULTCPATH);
+    print_out("    -D <dir>    Directory to chroot into (default: %s)", DEFAULTDIR);
+    print_out(" ");
+    exit(1);
+}
 
-/** int main(int argc, char **argv)
- */
 #ifndef TESTRULE
 int main(int argc, char **argv)
 #else
+__attribute__((noreturn))
 int main_analysisd(int argc, char **argv)
 #endif
 {
-    int c = 0, m_queue = 0, test_config = 0,run_foreground = 0;
+    int c = 0, m_queue = 0, test_config = 0, run_foreground = 0;
     int debug_level = 0;
-    char *dir = DEFAULTDIR;
-    char *user = USER;
-    char *group = GROUPGLOBAL;
-    int uid = 0,gid = 0;
+    const char *dir = DEFAULTDIR;
+    const char *user = USER;
+    const char *group = GROUPGLOBAL;
+    uid_t uid;
+    gid_t gid;
 
-    char *cfg = DEFAULTCPATH;
+    const char *cfg = DEFAULTCPATH;
 
-    /* Setting the name */
+    /* Set the name */
     OS_SetName(ARGV0);
 
     thishour = 0;
@@ -156,13 +132,18 @@ int main_analysisd(int argc, char **argv)
     hourly_syscheck = 0;
     hourly_firewall = 0;
 
-    while((c = getopt(argc, argv, "Vtdhfu:g:D:c:")) != -1){
-        switch(c){
-           case 'V':
-               print_version();
-               break;
+#ifdef LIBGEOIP_ENABLED
+    geoipdb = NULL;
+#endif
+
+
+    while ((c = getopt(argc, argv, "Vtdhfu:g:D:c:")) != -1) {
+        switch (c) {
+            case 'V':
+                print_version();
+                break;
             case 'h':
-                help(ARGV0);
+                help_analysisd();
                 break;
             case 'd':
                 nowDebug();
@@ -172,193 +153,194 @@ int main_analysisd(int argc, char **argv)
                 run_foreground = 1;
                 break;
             case 'u':
-                if(!optarg)
-                    ErrorExit("%s: -u needs an argument",ARGV0);
+                if (!optarg) {
+                    ErrorExit("%s: -u needs an argument", ARGV0);
+                }
                 user = optarg;
                 break;
             case 'g':
-                if(!optarg)
-                    ErrorExit("%s: -g needs an argument",ARGV0);
+                if (!optarg) {
+                    ErrorExit("%s: -g needs an argument", ARGV0);
+                }
                 group = optarg;
                 break;
             case 'D':
-                if(!optarg)
-                    ErrorExit("%s: -D needs an argument",ARGV0);
+                if (!optarg) {
+                    ErrorExit("%s: -D needs an argument", ARGV0);
+                }
                 dir = optarg;
                 break;
             case 'c':
-                if(!optarg)
-                    ErrorExit("%s: -c needs an argument",ARGV0);
+                if (!optarg) {
+                    ErrorExit("%s: -c needs an argument", ARGV0);
+                }
                 cfg = optarg;
                 break;
             case 't':
                 test_config = 1;
                 break;
             default:
-                help(ARGV0);
+                help_analysisd();
                 break;
         }
 
     }
 
     /* Check current debug_level
-     * Command line setting takes precedence 
+     * Command line setting takes precedence
      */
-    if (debug_level == 0)
-    {
-        /* Getting debug level */
+    if (debug_level == 0) {
+        /* Get debug level */
         debug_level = getDefine_Int("analysisd", "debug", 0, 2);
-        while(debug_level != 0)
-        {
+        while (debug_level != 0) {
             nowDebug();
             debug_level--;
         }
     }
 
-
-    /* Starting daemon */
-    debug1(STARTED_MSG,ARGV0);
+    /* Start daemon */
+    debug1(STARTED_MSG, ARGV0);
     DEBUG_MSG("%s: DEBUG: Starting on debug mode - %d ", ARGV0, (int)time(0));
 
-
-    /*Check if the user/group given are valid */
+    /* Check if the user/group given are valid */
     uid = Privsep_GetUser(user);
     gid = Privsep_GetGroup(group);
-    if((uid < 0)||(gid < 0))
-        ErrorExit(USER_ERROR,ARGV0,user,group);
-
+    if (uid == (uid_t) - 1 || gid == (gid_t) - 1) {
+        ErrorExit(USER_ERROR, ARGV0, user, group);
+    }
 
     /* Found user */
     debug1(FOUND_USER, ARGV0);
 
-
-    /* Initializing Active response */
+    /* Initialize Active response */
     AR_Init();
-    if(AR_ReadConfig(test_config, cfg) < 0)
-    {
-        ErrorExit(CONFIG_ERROR,ARGV0, cfg);
+    if (AR_ReadConfig(cfg) < 0) {
+        ErrorExit(CONFIG_ERROR, ARGV0, cfg);
     }
     debug1(ASINIT, ARGV0);
 
-
-    /* Reading configuration file */
-    if(GlobalConf(cfg) < 0)
-    {
-        ErrorExit(CONFIG_ERROR,ARGV0, cfg);
+    /* Read configuration file */
+    if (GlobalConf(cfg) < 0) {
+        ErrorExit(CONFIG_ERROR, ARGV0, cfg);
     }
 
     debug1(READ_CONFIG, ARGV0);
 
 
-    /* Fixing Config.ar */
+#ifdef LIBGEOIP_ENABLED
+     Config.geoip_jsonout = getDefine_Int("analysisd", "geoip_jsonout", 0, 1);
+
+    /* Opening GeoIP DB */
+    if(Config.geoipdb_file) {
+        geoipdb = GeoIP_open(Config.geoipdb_file, GEOIP_INDEX_CACHE);
+        if (geoipdb == NULL)
+        {
+            merror("%s: ERROR: Unable to open GeoIP database from: %s (disabling GeoIP).", ARGV0, Config.geoipdb_file);
+        }
+    }
+#endif
+
+
+
+    /* Fix Config.ar */
     Config.ar = ar_flag;
-    if(Config.ar == -1)
+    if (Config.ar == -1) {
         Config.ar = 0;
+    }
 
-
-    /* Getting servers hostname */
+    /* Get server's hostname */
     memset(__shost, '\0', 512);
-    if(gethostname(__shost, 512 -1) != 0)
-    {
-        strncpy(__shost, OSSEC_SERVER, 512 -1);
-    }
-    else
-    {
+    if (gethostname(__shost, 512 - 1) != 0) {
+        strncpy(__shost, OSSEC_SERVER, 512 - 1);
+    } else {
         char *_ltmp;
 
         /* Remove domain part if available */
         _ltmp = strchr(__shost, '.');
-        if(_ltmp)
+        if (_ltmp) {
             *_ltmp = '\0';
+        }
     }
 
-    /* going on Daemon mode */
-    if(!test_config && !run_foreground)
-    {
+    /* Continuing in Daemon mode */
+    if (!test_config && !run_foreground) {
         nowDaemon();
         goDaemon();
     }
 
-
-    /* Starting prelude */
-    #ifdef PRELUDE
-    if(Config.prelude)
-    {
+#ifdef PRELUDE_OUTPUT_ENABLED
+    /* Start prelude */
+    if (Config.prelude) {
         prelude_start(Config.prelude_profile, argc, argv);
     }
-    #endif
+#endif
 
-    /* Starting zeromq */
-    #ifdef ZEROMQ_OUTPUT 
-    if(Config.zeromq_output)
-    {
-      zeromq_output_start(Config.zeromq_output_uri, argc, argv);
+#ifdef ZEROMQ_OUTPUT_ENABLED
+    /* Start zeromq */
+    if (Config.zeromq_output) {
+#if CZMQ_VERSION_MAJOR == 2 
+        zeromq_output_start(Config.zeromq_output_uri);
+#elif CZMQ_VERSION_MAJOR >= 3
+        zeromq_output_start(Config.zeromq_output_uri, Config.zeromq_output_client_cert, Config.zeromq_output_server_cert);
+#endif
     }
-    #endif
+#endif
 
-    /* Opening the Picviz socket */
-    if(Config.picviz)
-    {
-        OS_PicvizOpen(Config.picviz_socket);
-        chown(Config.picviz_socket, uid, gid);
+    /* Set the group */
+    if (Privsep_SetGroup(gid) < 0) {
+        ErrorExit(SETGID_ERROR, ARGV0, group, errno, strerror(errno));
     }
 
-    /* Setting the group */    
-    if(Privsep_SetGroup(gid) < 0)
-        ErrorExit(SETGID_ERROR,ARGV0,group);
-
-    /* Chrooting */
-    if(Privsep_Chroot(dir) < 0)
-        ErrorExit(CHROOT_ERROR,ARGV0,dir);
-
-
+    /* Chroot */
+    if (Privsep_Chroot(dir) < 0) {
+        ErrorExit(CHROOT_ERROR, ARGV0, dir, errno, strerror(errno));
+    }
     nowChroot();
 
+    Config.decoder_order_size = (size_t)getDefine_Int("analysisd", "decoder_order_size", 8, MAX_DECODER_ORDER_SIZE);
 
 
     /*
      * Anonymous Section: Load rules, decoders, and lists
      *
-     * As lists require two pass loading of rules that make use of list lookups
+     * As lists require two-pass loading of rules that makes use of lists, lookups
      * are created with blank database structs, and need to be filled in after
      * completion of all rules and lists.
      */
     {
         {
-            /* Initializing the decoders list */
+            /* Initialize the decoders list */
             OS_CreateOSDecoderList();
 
-            if(!Config.decoders)
-            { /* Legacy loading */
-                /* Reading decoders */
-                if(!ReadDecodeXML(XML_DECODER))
-                {
+            if (!Config.decoders) {
+                /* Legacy loading */
+                /* Read decoders */
+                if (!ReadDecodeXML(XML_DECODER)) {
                     ErrorExit(CONFIG_ERROR, ARGV0,  XML_DECODER);
                 }
 
-                /* Reading local ones. */
+                /* Read local ones */
                 c = ReadDecodeXML(XML_LDECODER);
-                if(!c)
-                {
-                    if((c != -2))
+                if (!c) {
+                    if ((c != -2)) {
                         ErrorExit(CONFIG_ERROR, ARGV0,  XML_LDECODER);
-                }
-                else
-                {
-                    if(!test_config)
+                    }
+                } else {
+                    if (!test_config) {
                         verbose("%s: INFO: Reading local decoder file.", ARGV0);
+                    }
                 }
-            }
-            else
-            { /* New loaded based on file speified in ossec.conf */
+            } else {
+                /* New loaded based on file speified in ossec.conf */
                 char **decodersfiles;
                 decodersfiles = Config.decoders;
-                while( decodersfiles && *decodersfiles)
-                {
-                    if(!test_config)
+                while ( decodersfiles && *decodersfiles) {
+                    if (!test_config) {
                         verbose("%s: INFO: Reading decoder file %s.", ARGV0, *decodersfiles);
-                    if(!ReadDecodeXML(*decodersfiles))
+                    }
+                    if (!ReadDecodeXML(*decodersfiles)) {
                         ErrorExit(CONFIG_ERROR, ARGV0, *decodersfiles);
+                    }
 
                     free(*decodersfiles);
                     decodersfiles++;
@@ -368,19 +350,21 @@ int main_analysisd(int argc, char **argv)
             /* Load decoders */
             SetDecodeXML();
         }
-        { /* Load Lists */
-            /* Initializing the lists of list struct */
+        {
+            /* Load Lists */
+            /* Initialize the lists of list struct */
             Lists_OP_CreateLists();
             /* Load each list into list struct */
             {
                 char **listfiles;
                 listfiles = Config.lists;
-                while(listfiles && *listfiles)
-                {
-                    if(!test_config)
+                while (listfiles && *listfiles) {
+                    if (!test_config) {
                         verbose("%s: INFO: Reading loading the lists file: '%s'", ARGV0, *listfiles);
-                    if(Lists_OP_LoadList(*listfiles) < 0)
+                    }
+                    if (Lists_OP_LoadList(*listfiles) < 0) {
                         ErrorExit(LISTS_ERROR, ARGV0, *listfiles);
+                    }
                     free(*listfiles);
                     listfiles++;
                 }
@@ -388,20 +372,23 @@ int main_analysisd(int argc, char **argv)
                 Config.lists = NULL;
             }
         }
-        { /* Load Rules */
-            /* Creating the rules list */
+
+        {
+            /* Load Rules */
+            /* Create the rules list */
             Rules_OP_CreateRules();
 
-            /* Reading the rules */
+            /* Read the rules */
             {
                 char **rulesfiles;
                 rulesfiles = Config.includes;
-                while(rulesfiles && *rulesfiles)
-                {
-                    if(!test_config)
+                while (rulesfiles && *rulesfiles) {
+                    if (!test_config) {
                         verbose("%s: INFO: Reading rules file: '%s'", ARGV0, *rulesfiles);
-                    if(Rules_OP_ReadRules(*rulesfiles) < 0)
+                    }
+                    if (Rules_OP_ReadRules(*rulesfiles) < 0) {
                         ErrorExit(RULES_ERROR, ARGV0, *rulesfiles);
+                    }
 
                     free(*rulesfiles);
                     rulesfiles++;
@@ -411,410 +398,348 @@ int main_analysisd(int argc, char **argv)
                 Config.includes = NULL;
             }
 
-            /* Find all rules with that require list lookups and attache the
-             * the correct list struct to the rule.  This keeps rules from having to
-             * search thought the list of lists for the correct file during rule evaluation.
+            /* Find all rules that require list lookups and attache the the
+             * correct list struct to the rule. This keeps rules from having to
+             * search thought the list of lists for the correct file during
+             * rule evaluation.
              */
             OS_ListLoadRules();
         }
     }
 
-
-    /* Fixing the levels/accuracy */
+    /* Fix the levels/accuracy */
     {
         int total_rules;
         RuleNode *tmp_node = OS_GetFirstRule();
 
         total_rules = _setlevels(tmp_node, 0);
-        if(!test_config)
+        if (!test_config) {
             verbose("%s: INFO: Total rules enabled: '%d'", ARGV0, total_rules);
+        }
     }
 
-
-
-    /* Creating a rules hash (for reading alerts from other servers). */
+    /* Create a rules hash (for reading alerts from other servers) */
     {
         RuleNode *tmp_node = OS_GetFirstRule();
         Config.g_rules_hash = OSHash_Create();
-        if(!Config.g_rules_hash)
-        {
-            ErrorExit(MEM_ERROR, ARGV0);
+        if (!Config.g_rules_hash) {
+            ErrorExit(MEM_ERROR, ARGV0, errno, strerror(errno));
         }
         AddHash_Rule(tmp_node);
     }
 
-
-
     /* Ignored files on syscheck */
     {
         char **files;
         files = Config.syscheck_ignore;
-        while(files && *files)
-        {
-            if(!test_config)
+        while (files && *files) {
+            if (!test_config) {
                 verbose("%s: INFO: Ignoring file: '%s'", ARGV0, *files);
+            }
             files++;
         }
     }
 
-
-    /* Checking if log_fw is enabled. */
-    Config.logfw = getDefine_Int("analysisd",
+    /* Check if log_fw is enabled */
+    Config.logfw = (u_int8_t) getDefine_Int("analysisd",
                                  "log_fw",
                                  0, 1);
 
-
     /* Success on the configuration test */
-    if(test_config)
+    if (test_config) {
         exit(0);
-
+    }
 
     /* Verbose message */
-    debug1(PRIVSEP_MSG, ARGV0, dir, user);
-
+    debug1(CHROOT_MSG, ARGV0, dir);
+    debug1(PRIVSEP_MSG, ARGV0, user);
 
-    /* Signal manipulation     */
+    /* Signal manipulation */
     StartSIG(ARGV0);
 
+    /* Set the user */
+    if (Privsep_SetUser(uid) < 0) {
+        ErrorExit(SETUID_ERROR, ARGV0, user, errno, strerror(errno));
+    }
 
-    /* Setting the user */
-    if(Privsep_SetUser(uid) < 0)
-        ErrorExit(SETUID_ERROR,ARGV0,user);
-
-
-    /* Creating the PID file */
-    if(CreatePID(ARGV0, getpid()) < 0)
-        ErrorExit(PID_ERROR,ARGV0);
-
+    /* Create the PID file */
+    if (CreatePID(ARGV0, getpid()) < 0) {
+        ErrorExit(PID_ERROR, ARGV0);
+    }
 
-    /* Setting the queue */
-    if((m_queue = StartMQ(DEFAULTQUEUE,READ)) < 0)
+    /* Set the queue */
+    if ((m_queue = StartMQ(DEFAULTQUEUE, READ)) < 0) {
         ErrorExit(QUEUE_ERROR, ARGV0, DEFAULTQUEUE, strerror(errno));
-
-
-    /* White list */
-    if(Config.white_list == NULL)
-    {
-        if(Config.ar)
-            verbose("%s: INFO: No IP in the white list for active reponse.", ARGV0);
     }
-    else
-    {
-        if(Config.ar)
-        {
+
+    /* allowlist */
+    if (Config.allow_list == NULL) {
+        if (Config.ar) {
+            verbose("%s: INFO: No IP in the allow list for active response.", ARGV0);
+        }
+    } else {
+        if (Config.ar) {
             os_ip **wl;
             int wlc = 0;
-            wl = Config.white_list;
-            while(*wl)
-            {
-                verbose("%s: INFO: White listing IP: '%s'",ARGV0, (*wl)->ip);
-                wl++;wlc++;
+            wl = Config.allow_list;
+            while (*wl) {
+                verbose("%s: INFO: Allow listing IP: '%s'", ARGV0, (*wl)->ip);
+                wl++;
+                wlc++;
             }
-            verbose("%s: INFO: %d IPs in the white list for active response.",
+            verbose("%s: INFO: %d IPs in the allow list for active response.",
                     ARGV0, wlc);
         }
     }
 
-    /* Hostname White list */
-    if(Config.hostname_white_list == NULL)
-    {
-        if(Config.ar)
-            verbose("%s: INFO: No Hostname in the white list for active reponse.",
-            ARGV0);
-    }
-    else
-    {
-        if(Config.ar)
-        {
+    /* Hostname allowlist */
+    if (Config.hostname_allow_list == NULL) {
+        if (Config.ar)
+            verbose("%s: INFO: No Hostname in the allow list for active response.",
+                    ARGV0);
+    } else {
+        if (Config.ar) {
             int wlc = 0;
-            OSMatch **wl;
+            char **wl;
 
-            wl = Config.hostname_white_list;
-            while(*wl)
-            {
-                char **tmp_pts = (*wl)->patterns;
-                while(*tmp_pts)
-                {
-                    verbose("%s: INFO: White listing Hostname: '%s'",ARGV0,*tmp_pts);
-                    wlc++;
-                    tmp_pts++;
-                }
+            wl = Config.hostname_allow_list;
+            while (*wl) {
+                verbose("%s: INFO: Allow listing Hostname: '%s'", ARGV0, *wl);
+                wlc++;
                 wl++;
             }
-            verbose("%s: INFO: %d Hostname(s) in the white list for active response.",
+            verbose("%s: INFO: %d Hostname(s) in the allow list for active response.",
                     ARGV0, wlc);
         }
     }
 
-
-    /* Start up message */
+    /* Startup message */
     verbose(STARTUP_MSG, ARGV0, (int)getpid());
 
-
-    /* Going to main loop */   
+    /* Going to main loop */
     OS_ReadMSG(m_queue);
 
-    if (Config.picviz)
-    {
-        OS_PicvizClose();
-    }
-
     exit(0);
-
 }
 
-
-
-/* OS_ReadMSG.
- * Main function. Receives the messages(events)
- * and analyze them all.
- */
+/* Main function. Receives the messages(events) and analyze them all */
 #ifndef TESTRULE
+__attribute__((noreturn))
 void OS_ReadMSG(int m_queue)
 #else
+__attribute__((noreturn))
 void OS_ReadMSG_analysisd(int m_queue)
 #endif
 {
     int i;
-    char msg[OS_MAXSTR +1];
+    char msg[OS_MAXSTR + 1];
     Eventinfo *lf;
 
-    RuleInfo *stats_rule;
-
+    RuleInfo *stats_rule = NULL;
 
     /* Null to global currently pointers */
     currently_rule = NULL;
 
-    /* Initiating the logs */
+    /* Initialize the logs */
     OS_InitLog();
 
-
-    /* Initiating the integrity database */
+    /* Initialize the integrity database */
     SyscheckInit();
 
-
-    /* Initializing Rootcheck */
+    /* Initialize Rootcheck */
     RootcheckInit();
 
-
-    /* Initializing host info */
+    /* Initialize host info */
     HostinfoInit();
 
-
-    /* Creating the event list */
+    /* Create the event list */
     OS_CreateEventList(Config.memorysize);
 
-
-    /* Initiating the FTS list */
-    if(!FTS_Init())
-    {
+    /* Initiate the FTS list */
+    if (!FTS_Init()) {
         ErrorExit(FTS_LIST_ERROR, ARGV0);
     }
 
+    /* Initialize the Accumulator */
+    if (!Accumulate_Init()) {
+        merror("accumulator: ERROR: Initialization failed");
+        exit(1);
+    }
 
-    /* Starting the active response queues */
-    if(Config.ar)
-    {
-        /* Waiting the ARQ to settle .. */
+    /* Start the active response queues */
+    if (Config.ar) {
+        /* Waiting the ARQ to settle */
         sleep(3);
 
-
-        #ifndef LOCAL
-        if(Config.ar & REMOTE_AR)
-        {
-            if((arq = StartMQ(ARQUEUE, WRITE)) < 0)
-            {
+#ifndef LOCAL
+        if (Config.ar & REMOTE_AR) {
+            if ((arq = StartMQ(ARQUEUE, WRITE)) < 0) {
                 merror(ARQ_ERROR, ARGV0);
 
                 /* If LOCAL_AR is set, keep it there */
-                if(Config.ar & LOCAL_AR)
-                {
+                if (Config.ar & LOCAL_AR) {
                     Config.ar = 0;
-                    Config.ar|=LOCAL_AR;
-                }
-                else
-                {
+                    Config.ar |= LOCAL_AR;
+                } else {
                     Config.ar = 0;
                 }
-            }
-            else
-            {
+            } else {
                 verbose(CONN_TO, ARGV0, ARQUEUE, "active-response");
             }
         }
-
-        #else
+#else
         /* Only for LOCAL_ONLY installs */
-        if(Config.ar & REMOTE_AR)
-        {
-            if(Config.ar & LOCAL_AR)
-            {
+        if (Config.ar & REMOTE_AR) {
+            if (Config.ar & LOCAL_AR) {
                 Config.ar = 0;
-                Config.ar|=LOCAL_AR;
-            }
-            else
-            {
+                Config.ar |= LOCAL_AR;
+            } else {
                 Config.ar = 0;
             }
         }
-        #endif
+#endif
 
-        if(Config.ar & LOCAL_AR)
-        {
-            if((execdq = StartMQ(EXECQUEUE, WRITE)) < 0)
-            {
+        if (Config.ar & LOCAL_AR) {
+            if ((execdq = StartMQ(EXECQUEUE, WRITE)) < 0) {
                 merror(ARQ_ERROR, ARGV0);
 
                 /* If REMOTE_AR is set, keep it there */
-                if(Config.ar & REMOTE_AR)
-                {
+                if (Config.ar & REMOTE_AR) {
                     Config.ar = 0;
-                    Config.ar|=REMOTE_AR;
-                }
-                else
-                {
+                    Config.ar |= REMOTE_AR;
+                } else {
                     Config.ar = 0;
                 }
-            }
-            else
-            {
+            } else {
                 verbose(CONN_TO, ARGV0, EXECQUEUE, "exec");
             }
         }
     }
     debug1("%s: DEBUG: Active response Init completed.", ARGV0);
 
-
-    /* Getting currently time before starting */
+    /* Get current time before starting */
     c_time = time(NULL);
 
-
-    /* Starting the hourly/weekly stats */
-    if(Start_Hour() < 0)
+    /* Start the hourly/weekly stats */
+    if (Start_Hour() < 0) {
         Config.stats = 0;
-    else
-    {
-        /* Initializing stats rules */
+    } else {
+        /* Initialize stats rules */
         stats_rule = zerorulemember(
-                STATS_MODULE,
-                Config.stats,
-                0,0,0,0,0,0);
+                         STATS_MODULE,
+                         Config.stats,
+                         0, 0, 0, 0, 0, 0);
 
-        if(!stats_rule)
-        {
-            ErrorExit(MEM_ERROR, ARGV0);
+        if (!stats_rule) {
+            ErrorExit(MEM_ERROR, ARGV0, errno, strerror(errno));
         }
         stats_rule->group = "stats,";
         stats_rule->comment = "Excessive number of events (above normal).";
     }
 
+    /* Do some cleanup */
+    memset(msg, '\0', OS_MAXSTR + 1);
 
-    /* Doing some cleanup */
-    memset(msg, '\0', OS_MAXSTR +1);
-
-
-    /* Initializing the logs */
+    /* Initialize the logs */
     {
-        lf = (Eventinfo *)calloc(1,sizeof(Eventinfo));
-        if(!lf)
-            ErrorExit(MEM_ERROR, ARGV0);
+        lf = (Eventinfo *)calloc(1, sizeof(Eventinfo));
+        if (!lf) {
+            ErrorExit(MEM_ERROR, ARGV0, errno, strerror(errno));
+        }
+        os_calloc(Config.decoder_order_size, sizeof(char*), lf->fields);
         lf->year = prev_year;
         strncpy(lf->mon, prev_month, 3);
         lf->day = today;
 
-        if(OS_GetLogLocation(lf) < 0)
-        {
+        if (OS_GetLogLocation(lf) < 0) {
             ErrorExit("%s: Error allocating log files", ARGV0);
         }
 
         Free_Eventinfo(lf);
     }
 
+#ifdef SQLITE_ENABLED
+    /* Open the sqlite db */
+    extern sqlite3 *conn;
+    int s_error = 0;
+    if (Config.md5_allowlist) {
+        debug2("Opening md5_allowlist: %s", Config.md5_allowlist);
+        if((s_error = sqlite3_open(Config.md5_allowlist, &conn))) {
+            merror(INVALID_IGNORE_MD5DB, ARGV0, Config.md5_allowlist);
+        }
+
+    }
+#endif
 
-    debug1("%s: DEBUG: Startup completed. Waiting for new messages..",ARGV0);
+    debug1("%s: DEBUG: Startup completed. Waiting for new messages..", ARGV0);
 
-    if(Config.custom_alert_output)
-      debug1("%s: INFO: Custom output found.!",ARGV0);
+    if (Config.custom_alert_output) {
+        debug1("%s: INFO: Custom output found.!", ARGV0);
+    }
 
     /* Daemon loop */
-    while(1)
-    {
-        lf = (Eventinfo *)calloc(1,sizeof(Eventinfo));
+    while (1) {
+        lf = (Eventinfo *)calloc(1, sizeof(Eventinfo));
+        os_calloc(Config.decoder_order_size, sizeof(char*), lf->fields);
 
-        /* This shouldn't happen .. */
-        if(lf == NULL)
-        {
-            ErrorExit(MEM_ERROR,ARGV0);
+        /* This shouldn't happen */
+        if (lf == NULL) {
+            ErrorExit(MEM_ERROR, ARGV0, errno, strerror(errno));
         }
 
         DEBUG_MSG("%s: DEBUG: Waiting for msgs - %d ", ARGV0, (int)time(0));
 
-
         /* Receive message from queue */
-        if((i = OS_RecvUnix(m_queue, OS_MAXSTR, msg)))
-        {
+        if ((i = OS_RecvUnix(m_queue, OS_MAXSTR, msg))) {
             RuleNode *rulenode_pt;
 
-            /* Getting the time we received the event */
+            /* Get the time we received the event */
             c_time = time(NULL);
 
-
             /* Default values for the log info */
             Zero_Eventinfo(lf);
 
-
-            /* Checking for a valid message. */
-            if(i < 4)
-            {
+            /* Check for a valid message */
+            if (i < 4) {
                 merror(IMSG_ERROR, ARGV0, msg);
                 Free_Eventinfo(lf);
                 continue;
             }
 
-
             /* Message before extracting header */
             DEBUG_MSG("%s: DEBUG: Received msg: %s ", ARGV0, msg);
 
-
             /* Clean the msg appropriately */
-            if(OS_CleanMSG(msg, lf) < 0)
-            {
-                merror(IMSG_ERROR,ARGV0, msg);
+            if (OS_CleanMSG(msg, lf) < 0) {
+                merror(IMSG_ERROR, ARGV0, msg);
                 Free_Eventinfo(lf);
                 continue;
             }
 
-
             /* Msg cleaned */
             DEBUG_MSG("%s: DEBUG: Msg cleanup: %s ", ARGV0, lf->log);
 
-
-            /* Currently rule must be null in here */
+            /* Current rule must be null in here */
             currently_rule = NULL;
 
-
-            /** Checking the date/hour changes **/
+            /** Check the date/hour changes **/
 
             /* Update the hour */
-            if(thishour != __crt_hour)
-            {
+            if (thishour != __crt_hour) {
                 /* Search all the rules and print the number
-                 * of alerts that each one fired.
+                 * of alerts that each one fired
                  */
                 DumpLogstats();
                 thishour = __crt_hour;
 
                 /* Check if the date has changed */
-                if(today != lf->day)
-                {
-                    if(Config.stats)
-                    {
+                if (today != lf->day) {
+                    if (Config.stats) {
                         /* Update the hourly stats (done daily) */
                         Update_Hour();
                     }
 
-                    if(OS_GetLogLocation(lf) < 0)
-                    {
+                    if (OS_GetLogLocation(lf) < 0) {
                         ErrorExit("%s: Error allocating log files", ARGV0);
                     }
 
@@ -825,32 +750,27 @@ void OS_ReadMSG_analysisd(int m_queue)
             }
 
 
-            /* Incrementing number of events received */
+            /* Increment number of events received */
             hourly_events++;
 
-
-            /***  Running decoders ***/
+            /***  Run decoders ***/
 
             /* Integrity check from syscheck */
-            if(msg[0] == SYSCHECK_MQ)
-            {
+            if (msg[0] == SYSCHECK_MQ) {
                 hourly_syscheck++;
 
-                if(!DecodeSyscheck(lf))
-                {
+                if (!DecodeSyscheck(lf)) {
                     /* We don't process syscheck events further */
                     goto CLMEM;
                 }
 
-                /* Getting log size */
+                /* Get log size */
                 lf->size = strlen(lf->log);
             }
 
             /* Rootcheck decoding */
-            else if(msg[0] == ROOTCHECK_MQ)
-            {
-                if(!DecodeRootcheck(lf))
-                {
+            else if (msg[0] == ROOTCHECK_MQ) {
+                if (!DecodeRootcheck(lf)) {
                     /* We don't process rootcheck events further */
                     goto CLMEM;
                 }
@@ -858,304 +778,247 @@ void OS_ReadMSG_analysisd(int m_queue)
             }
 
             /* Host information special decoder */
-            else if(msg[0] == HOSTINFO_MQ)
-            {
-                if(!DecodeHostinfo(lf))
-                {
+            else if (msg[0] == HOSTINFO_MQ) {
+                if (!DecodeHostinfo(lf)) {
                     /* We don't process hostinfo events further */
                     goto CLMEM;
                 }
                 lf->size = strlen(lf->log);
             }
 
-            /* Run the general Decoders  */
-            else
-            {
-                /* Getting log size */
+            /* Run the general Decoders */
+            else {
+                /* Get log size */
                 lf->size = strlen(lf->log);
 
                 DecodeEvent(lf);
             }
 
+            /* Run accumulator */
+            if ( lf->decoder_info->accumulate == 1 ) {
+                lf = Accumulate(lf);
+            }
 
             /* Firewall event */
-            if(lf->decoder_info->type == FIREWALL)
-            {
+            if (lf->decoder_info->type == FIREWALL) {
                 /* If we could not get any information from
                  * the log, just ignore it
                  */
                 hourly_firewall++;
-                if(Config.logfw)
-                {
-                    if(!FW_Log(lf))
-                    {
+                if (Config.logfw) {
+                    if (!FW_Log(lf)) {
                         goto CLMEM;
                     }
                 }
             }
 
-
             /* We only check if the last message is
-             * duplicated on syslog.
+             * duplicated on syslog
              */
-            else if(lf->decoder_info->type == SYSLOG)
-            {
-                /* Checking if the message is duplicated */
-                if(LastMsg_Stats(lf->full_log) == 1)
+            else if (lf->decoder_info->type == SYSLOG) {
+                /* Check if the message is duplicated */
+                if (LastMsg_Stats(lf->full_log) == 1) {
                     goto CLMEM;
-                else
+                } else {
                     LastMsg_Change(lf->full_log);
+                }
             }
 
-
             /* Stats checking */
-            if(Config.stats)
-            {
-                if(Check_Hour(lf) == 1)
-                {
-                    void *saved_rule = lf->generated_rule;
+            if (Config.stats) {
+                if (Check_Hour() == 1) {
+                    RuleInfo *saved_rule = lf->generated_rule;
                     char *saved_log;
 
-                    /* Saving previous log */
+                    /* Save previous log */
                     saved_log = lf->full_log;
 
                     lf->generated_rule = stats_rule;
                     lf->full_log = __stats_comment;
 
-
-                    /* alert for statistical analysis */
-                    if(stats_rule->alert_opts & DO_LOGALERT)
-                    {
+                    /* Alert for statistical analysis */
+                    if (stats_rule->alert_opts & DO_LOGALERT) {
                         __crt_ftell = ftell(_aflog);
-                        if(Config.custom_alert_output)
-                        {
-                          OS_CustomLog(lf,Config.custom_alert_output_format);
+                        if (Config.custom_alert_output) {
+                            OS_CustomLog(lf, Config.custom_alert_output_format);
+                        } else {
+                            OS_Log(lf);
                         }
-                        else
-                        {
-                          OS_Log(lf);
+                        /* Log to json file */
+                        if (Config.jsonout_output) {
+                            jsonout_output_event(lf);
                         }
 
                     }
 
-
                     /* Set lf to the old values */
                     lf->generated_rule = saved_rule;
                     lf->full_log = saved_log;
                 }
             }
 
-
-            /* Checking the rules */
+            /* Check the rules */
             DEBUG_MSG("%s: DEBUG: Checking the rules - %d ",
-                           ARGV0, lf->decoder_info->type);
-
+                      ARGV0, lf->decoder_info->type);
 
-            /* Looping all the rules */
+            /* Loop over all the rules */
             rulenode_pt = OS_GetFirstRule();
-            if(!rulenode_pt)
-            {
+            if (!rulenode_pt) {
                 ErrorExit("%s: Rules in an inconsistent state. Exiting.",
-                        ARGV0);
+                          ARGV0);
             }
 
-
-            do
-            {
-                if(lf->decoder_info->type == OSSEC_ALERT)
-                {
-                    if(!lf->generated_rule)
-                    {
+            do {
+                if (lf->decoder_info->type == OSSEC_ALERT) {
+                    if (!lf->generated_rule) {
                         goto CLMEM;
                     }
 
-                    /* We go ahead in here and process the alert. */
+                    /* Process the alert */
                     currently_rule = lf->generated_rule;
                 }
 
-                /* The categories must match */
-                else if(rulenode_pt->ruleinfo->category !=
-                        lf->decoder_info->type)
-                {
+                /* Categories must match */
+                else if (rulenode_pt->ruleinfo->category !=
+                         lf->decoder_info->type) {
                     continue;
                 }
 
-                /* Checking each rule. */
-                else if((currently_rule = OS_CheckIfRuleMatch(lf, rulenode_pt))
-                        == NULL)
-                {
+                /* Check each rule */
+                else if ((currently_rule = OS_CheckIfRuleMatch(lf, rulenode_pt))
+                         == NULL) {
                     continue;
                 }
 
-
                 /* Ignore level 0 */
-                if(currently_rule->level == 0)
-                {
+                if (currently_rule->level == 0) {
                     break;
                 }
 
-
-                /* Checking ignore time */
-                if(currently_rule->ignore_time)
-                {
-                    if(currently_rule->time_ignored == 0)
-                    {
+                /* Check ignore time */
+                if (currently_rule->ignore_time) {
+                    if (currently_rule->time_ignored == 0) {
                         currently_rule->time_ignored = lf->time;
                     }
-                    /* If the currently time - the time the rule was ignored
+                    /* If the current time - the time the rule was ignored
                      * is less than the time it should be ignored,
-                     * leave (do not alert again).
+                     * leave (do not alert again)
                      */
-                    else if((lf->time - currently_rule->time_ignored)
-                            < currently_rule->ignore_time)
-                    {
+                    else if ((lf->time - currently_rule->time_ignored)
+                             < currently_rule->ignore_time) {
                         break;
-                    }
-                    else
-                    {
+                    } else {
                         currently_rule->time_ignored = lf->time;
                     }
                 }
 
-
                 /* Pointer to the rule that generated it */
                 lf->generated_rule = currently_rule;
 
-
-                /* Checking if we should ignore it */
-                if(currently_rule->ckignore && IGnore(lf))
-                {
-                    /* Ignoring rule */
+                /* Check if we should ignore it */
+                if (currently_rule->ckignore && IGnore(lf)) {
+                    /* Ignore rule */
                     lf->generated_rule = NULL;
                     break;
                 }
 
-
-                /* Checking if we need to add to ignore list */
-                if(currently_rule->ignore)
-                {
+                /* Check if we need to add to ignore list */
+                if (currently_rule->ignore) {
                     AddtoIGnore(lf);
                 }
 
-
-                /* Log the alert if configured to ... */
-                if(currently_rule->alert_opts & DO_LOGALERT)
-                {
+                /* Log the alert if configured to */
+                if (currently_rule->alert_opts & DO_LOGALERT) {
                     __crt_ftell = ftell(_aflog);
 
-                    if(Config.custom_alert_output)
-                    {
-                      OS_CustomLog(lf,Config.custom_alert_output_format);
+                    if (Config.custom_alert_output) {
+                        OS_CustomLog(lf, Config.custom_alert_output_format);
+                    } else {
+                        OS_Log(lf);
                     }
-                    else
-                    {
-                      OS_Log(lf);
+                    /* Log to json file */
+                    if (Config.jsonout_output) {
+                        jsonout_output_event(lf);
                     }
                 }
 
-
+#ifdef PRELUDE_OUTPUT_ENABLED
                 /* Log to prelude */
-                #ifdef PRELUDE
-                if(Config.prelude)
-                {
-                    if(Config.prelude_log_level <= currently_rule->level)
-                    {
+                if (Config.prelude) {
+                    if (Config.prelude_log_level <= currently_rule->level) {
                         OS_PreludeLog(lf);
                     }
                 }
-                #endif
+#endif
 
+#ifdef ZEROMQ_OUTPUT_ENABLED
                 /* Log to zeromq */
-                #ifdef ZEROMQ_OUTPUT 
-                if(Config.zeromq_output) 
-                {
+                if (Config.zeromq_output) {
                     zeromq_output_event(lf);
                 }
-                #endif
-
-
-                /* Log to Picviz */
-                if (Config.picviz)
-                {
-                    OS_PicvizLog(lf);
-                }
+#endif
 
 
                 /* Execute an active response */
-                if(currently_rule->ar)
-                {
+                if (currently_rule->ar) {
                     int do_ar;
                     active_response **rule_ar;
 
                     rule_ar = currently_rule->ar;
 
-                    while(*rule_ar)
-                    {
+                    while (*rule_ar) {
                         do_ar = 1;
-                        if((*rule_ar)->ar_cmd->expect & USERNAME)
-                        {
-                            if(!lf->dstuser ||
-                                !OS_PRegex(lf->dstuser,"^[a-zA-Z._0-9@?-]*$"))
-                            {
-                                if(lf->dstuser)
+                        if ((*rule_ar)->ar_cmd->expect & USERNAME) {
+                            if (!lf->dstuser ||
+                                    !OS_PRegex(lf->dstuser, "^[a-zA-Z._0-9@?-]*$")) {
+                                if (lf->dstuser) {
                                     merror(CRAFTED_USER, ARGV0, lf->dstuser);
+                                }
                                 do_ar = 0;
                             }
                         }
-                        if((*rule_ar)->ar_cmd->expect & SRCIP)
-                        {
-                            if(!lf->srcip ||
-                                !OS_PRegex(lf->srcip, "^[a-zA-Z.:_0-9-]*$"))
-                            {
-                                if(lf->srcip)
+                        if ((*rule_ar)->ar_cmd->expect & SRCIP) {
+                            if (!lf->srcip ||
+                                    !OS_PRegex(lf->srcip, "^[a-zA-Z.:_0-9-]*$")) {
+                                if (lf->srcip) {
                                     merror(CRAFTED_IP, ARGV0, lf->srcip);
+                                }
                                 do_ar = 0;
                             }
                         }
-                        if((*rule_ar)->ar_cmd->expect & FILENAME)
-                        {
-                            if(!lf->filename)
-                            {
+                        if ((*rule_ar)->ar_cmd->expect & FILENAME) {
+                            if (!lf->filename) {
                                 do_ar = 0;
                             }
                         }
 
-                        if(do_ar)
-                        {
-                            OS_Exec(&execdq, &arq, lf, *rule_ar);
+                        if (do_ar && execdq > 0) {
+                            OS_Exec(execdq, arq, lf, *rule_ar);
                         }
                         rule_ar++;
                     }
                 }
 
-
                 /* Copy the structure to the state memory of if_matched_sid */
-                if(currently_rule->sid_prev_matched)
-                {
-                    if(!OSList_AddData(currently_rule->sid_prev_matched, lf))
-                    {
+                if (currently_rule->sid_prev_matched) {
+                    if (!OSList_AddData(currently_rule->sid_prev_matched, lf)) {
                         merror("%s: Unable to add data to sig list.", ARGV0);
-                    }
-                    else
-                    {
+                    } else {
                         lf->sid_node_to_delete =
                             currently_rule->sid_prev_matched->last_node;
                     }
                 }
                 /* Group list */
-                else if(currently_rule->group_prev_matched)
-                {
-                    i = 0;
-
-                    while(i < currently_rule->group_prev_matched_sz)
-                    {
-                        if(!OSList_AddData(
-                                currently_rule->group_prev_matched[i],
-                                lf))
-                        {
-                           merror("%s: Unable to add data to grp list.",ARGV0);
+                else if (currently_rule->group_prev_matched) {
+                    unsigned int j = 0;
+
+                    while (j < currently_rule->group_prev_matched_sz) {
+                        if (!OSList_AddData(
+                                    currently_rule->group_prev_matched[j],
+                                    lf)) {
+                            merror("%s: Unable to add data to grp list.", ARGV0);
                         }
-                        i++;
+                        j++;
                     }
                 }
 
@@ -1163,38 +1026,31 @@ void OS_ReadMSG_analysisd(int m_queue)
 
                 break;
 
-            }while((rulenode_pt = rulenode_pt->next) != NULL);
-
+            } while ((rulenode_pt = rulenode_pt->next) != NULL);
 
             /* If configured to log all, do it */
-            if(Config.logall)
+            if (Config.logall)
                 OS_Store(lf);
+            if (Config.logall_json)
+                jsonout_output_archive(lf);
 
-
-            /* Cleaning the memory */  
-            CLMEM:
-
+CLMEM:
+            /** Cleaning the memory **/
 
             /* Only clear the memory if the eventinfo was not
              * added to the stateful memory
              * -- message is free inside clean event --
              */
-            if(lf->generated_rule == NULL)
+            if (lf->generated_rule == NULL) {
                 Free_Eventinfo(lf);
-
-        }
-        else
-        {
+            }
+        } else {
             free(lf);
         }
     }
-    return;
 }
 
-
-/* CheckIfRuleMatch v0.1
- * Will check if the currently_rule matches the event information
- */
+/* Checks if the current_rule matches the event information */
 RuleInfo *OS_CheckIfRuleMatch(Eventinfo *lf, RuleNode *curr_node)
 {
     /* We check for:
@@ -1215,474 +1071,575 @@ RuleInfo *OS_CheckIfRuleMatch(Eventinfo *lf, RuleNode *curr_node)
      * weekday,
      * status,
      */
-    RuleInfo *currently_rule = curr_node->ruleinfo;
-
+    RuleInfo *rule = curr_node->ruleinfo;
+    int i;
 
     /* Can't be null */
-    if(!currently_rule)
-    {
+    if (!rule) {
         merror("%s: Inconsistent state. currently rule NULL", ARGV0);
-        return(NULL);
+        return (NULL);
     }
 
+#ifdef TESTRULE
+    if (full_output && !alert_only)
+        print_out("    Trying rule: %d - %s", rule->sigid,
+                  rule->comment);
+#endif
 
-    #ifdef TESTRULE
-    if(full_output && !alert_only)
-    print_out("    Trying rule: %d - %s", currently_rule->sigid,
-                                          currently_rule->comment);
-    #endif
-
-
-    /* Checking if any decoder pre-matched here */
-    if(currently_rule->decoded_as &&
-       currently_rule->decoded_as != lf->decoder_info->id)
-    {
-        return(NULL);
+    /* Check if any decoder pre-matched here */
+    if (rule->decoded_as &&
+            rule->decoded_as != lf->decoder_info->id) {
+        return (NULL);
     }
 
+    /* Check program name */
+    if (rule->program_name) {
+        if (!lf->program_name) {
+            return (NULL);
+        }
 
-    /* Checking program name */
-    if(currently_rule->program_name)
-    {
-        if(!lf->program_name)
-            return(NULL);
-
-        if(!OSMatch_Execute(lf->program_name,
-                            lf->p_name_size,
-                            currently_rule->program_name))
-                        return(NULL);
+        if (!OSMatch_Execute(lf->program_name,
+                             lf->p_name_size,
+                             rule->program_name)) {
+            return (NULL);
+        }
     }
-
-
-    /* Checking for the id */
-    if(currently_rule->id)
-    {
-        if(!lf->id)
-        {
-            return(NULL);
+    else if (rule->program_name_pcre2) {
+        if (!lf->program_name) {
+            return (NULL);
         }
 
-        if(!OSMatch_Execute(lf->id,
-                            strlen(lf->id),
-                            currently_rule->id))
-            return(NULL);
-        #ifdef CDBLOOKUP
-
-        #endif
+        if (!OSPcre2_Execute(lf->program_name,
+                             rule->program_name_pcre2)) {
+            return (NULL);
+        }
     }
 
+    /* Check for the ID */
+    if (rule->id) {
+        if (!lf->id) {
+            return (NULL);
+        }
 
-    /* Checking if any word to match exists */
-    if(currently_rule->match)
-    {
-        if(!OSMatch_Execute(lf->log, lf->size, currently_rule->match))
-            return(NULL);
-    }          
-
+        if (!OSMatch_Execute(lf->id,
+                             strlen(lf->id),
+                             rule->id)) {
+            return (NULL);
+        }
+    }
+    else if (rule->id_pcre2) {
+        if (!lf->id) {
+            return (NULL);
+        }
 
+        if (!OSPcre2_Execute(lf->id,
+                             rule->id_pcre2)) {
+            return (NULL);
+        }
+    }
 
-    /* Checking if exist any regex for this rule */
-    if(currently_rule->regex)
-    {
-        if(!OSRegex_Execute(lf->log, currently_rule->regex))
-            return(NULL);
+    /* Check if any word to match exists */
+    if (rule->match) {
+        if (!OSMatch_Execute(lf->log, lf->size, rule->match)) {
+            return (NULL);
+        }
+    }
+    else if (rule->match_pcre2) {
+        if (!OSPcre2_Execute(lf->log, rule->match_pcre2)) {
+            return (NULL);
+        }
     }
 
+    /* Check if exist any regex for this rule */
+    if (rule->regex) {
+        if (!OSRegex_Execute(lf->log, rule->regex)) {
+            return (NULL);
+        }
+    }
+    else if (rule->pcre2) {
+        if (!OSPcre2_Execute(lf->log, rule->pcre2)) {
+            return (NULL);
+        }
+    }
 
-    /* Checking for actions */
-    if(currently_rule->action)
-    {
-        if(!lf->action)
-            return(NULL);
+    /* Check for actions */
+    if (rule->action) {
+        if (!lf->action) {
+            return (NULL);
+        }
 
-        if(strcmp(currently_rule->action,lf->action) != 0)
-            return(NULL);
+        if (strcmp(rule->action, lf->action) != 0) {
+            return (NULL);
+        }
     }
 
-
-    /* Checking for the url */
-    if(currently_rule->url)
-    {
-        if(!lf->url)
-        {
-            return(NULL);
+    /* Checking for the URL */
+    if (rule->url) {
+        if (!lf->url) {
+            return (NULL);
         }
 
-        if(!OSMatch_Execute(lf->url, strlen(lf->url), currently_rule->url))
-        {
-            return(NULL);
+        if (!OSMatch_Execute(lf->url, strlen(lf->url), rule->url)) {
+            return (NULL);
+        }
+    }
+    if (rule->url_pcre2) {
+        if (!lf->url) {
+            return (NULL);
         }
-        #ifdef CDBLOOKUP
 
-        #endif
+        if (!OSPcre2_Execute(lf->url, rule->url_pcre2)) {
+            return (NULL);
+        }
     }
 
+    /* Check for dynamic fields */
+   
+    for (i = 0; i < Config.decoder_order_size && rule->fields[i]; i++) {
+        int j;
+        
+        for (j = 0; j < Config.decoder_order_size; j++)
+            if (lf->decoder_info->fields[j])
+                if (strcasecmp(lf->decoder_info->fields[j], rule->fields[i]->name) == 0)
+                    break;
 
+        if (j == Config.decoder_order_size)
 
-    /* Getting tcp/ip packet information */
-    if(currently_rule->alert_opts & DO_PACKETINFO)
-    {
-        /* Checking for the srcip */
-        if(currently_rule->srcip)
-        {
-            if(!lf->srcip)
-            {
-                return(NULL);
-            }
+            return NULL;
+        
+        if (!OSRegex_Execute(lf->fields[j], rule->fields[i]->regex))
+            return NULL;
+    }
 
-            if(!OS_IPFoundList(lf->srcip, currently_rule->srcip))
-            {
-                return(NULL);
+
+    /* Get TCP/IP packet information */
+    if (rule->alert_opts & DO_PACKETINFO) {
+        /* Check for the srcip */
+        if (rule->srcip) {
+            if (!lf->srcip) {
+                return (NULL);
             }
-            #ifdef CDBLOOKUP
 
-            #endif
+            if (!OS_IPFoundList(lf->srcip, rule->srcip)) {
+                return (NULL);
+            }
         }
 
-        /* Checking for the dstip */
-        if(currently_rule->dstip)
-        {
-            if(!lf->dstip)
-            {
-                return(NULL);
+        /* Check for the dstip */
+        if (rule->dstip) {
+            if (!lf->dstip) {
+                return (NULL);
             }
 
-            if(!OS_IPFoundList(lf->dstip, currently_rule->dstip))
-            {
-                return(NULL);
+            if (!OS_IPFoundList(lf->dstip, rule->dstip)) {
+                return (NULL);
             }
-            #ifdef CDBLOOKUP
-
-            #endif
         }
 
-        if(currently_rule->srcport)
-        {
-            if(!lf->srcport)
-            {
-                return(NULL);
+        if (rule->srcport) {
+            if (!lf->srcport) {
+                return (NULL);
             }
 
-            if(!OSMatch_Execute(lf->srcport,
-                                strlen(lf->srcport),
-                                currently_rule->srcport))
-            {
-                return(NULL);
+            if (!OSMatch_Execute(lf->srcport,
+                                 strlen(lf->srcport),
+                                 rule->srcport)) {
+                return (NULL);
+            }
+        }
+        else if (rule->srcport_pcre2) {
+            if (!lf->srcport) {
+                return (NULL);
             }
-            #ifdef CDBLOOKUP
 
-            #endif
+            if (!OSPcre2_Execute(lf->srcport,
+                                 rule->srcport_pcre2)) {
+                return (NULL);
+            }
         }
-        if(currently_rule->dstport)
-        {
-            if(!lf->dstport)
-            {
-                return(NULL);
+        if (rule->dstport) {
+            if (!lf->dstport) {
+                return (NULL);
             }
 
-            if(!OSMatch_Execute(lf->dstport,
-                                strlen(lf->dstport),
-                                currently_rule->dstport))
-            {
-                return(NULL);
+            if (!OSMatch_Execute(lf->dstport,
+                                 strlen(lf->dstport),
+                                 rule->dstport)) {
+                return (NULL);
+            }
+        }
+        else if (rule->dstport_pcre2) {
+            if (!lf->dstport) {
+                return (NULL);
             }
-            #ifdef CDBLOOKUP
 
-            #endif
+            if (!OSPcre2_Execute(lf->dstport,
+                                 rule->dstport_pcre2)) {
+                return (NULL);
+            }
         }
     } /* END PACKET_INFO */
 
-
     /* Extra information from event */
-    if(currently_rule->alert_opts & DO_EXTRAINFO)
-    {
-        /* Checking compiled rule. */
-        if(currently_rule->compiled_rule)
-        {
-            if(!currently_rule->compiled_rule(lf))
-            {
-                return(NULL);
+    if (rule->alert_opts & DO_EXTRAINFO) {
+        /* Check compiled rule */
+        if (rule->compiled_rule) {
+            if (!rule->compiled_rule(lf)) {
+                return (NULL);
             }
         }
 
-
         /* Checking if exist any user to match */
-        if(currently_rule->user)
-        {
-            if(lf->dstuser)
-            {
-                if(!OSMatch_Execute(lf->dstuser,
-                            strlen(lf->dstuser),
-                            currently_rule->user))
-                    return(NULL);
+        if (rule->user) {
+            if (lf->dstuser) {
+                if (!OSMatch_Execute(lf->dstuser,
+                                     strlen(lf->dstuser),
+                                     rule->user)) {
+                    return (NULL);
+                }
+            } else if (lf->srcuser) {
+                if (!OSMatch_Execute(lf->srcuser,
+                                     strlen(lf->srcuser),
+                                     rule->user)) {
+                    return (NULL);
+                }
+            } else {
+                /* no user set */
+                return (NULL);
             }
-            else if(lf->srcuser)
-            {
-                if(!OSMatch_Execute(lf->srcuser,
-                            strlen(lf->srcuser),
-                            currently_rule->user))
-                    return(NULL);
+        }
+        else if (rule->user_pcre2) {
+            if (lf->dstuser) {
+                if (!OSPcre2_Execute(lf->dstuser,
+                                     rule->user_pcre2)) {
+                    return (NULL);
+                }
+            } else if (lf->srcuser) {
+                if (!OSPcre2_Execute(lf->srcuser,
+                                     rule->user_pcre2)) {
+                    return (NULL);
+                }
+            } else {
+                /* no user set */
+                return (NULL);
             }
-            else
-            #ifdef CDBLOOKUP
+        }
 
-            #endif
-            {
-                /* no user set */
+        /* Adding checks for geoip. */
+        if(rule->srcgeoip) {
+            if(lf->srcgeoip) {
+                if(!OSMatch_Execute(lf->srcgeoip,
+                            strlen(lf->srcgeoip),
+                            rule->srcgeoip))
+                    return(NULL);
+            } else {
+                return(NULL);
+            }
+        }
+        else if(rule->srcgeoip_pcre2) {
+            if(lf->srcgeoip) {
+                if(!OSPcre2_Execute(lf->srcgeoip,
+                            rule->srcgeoip_pcre2))
+                    return(NULL);
+            } else {
                 return(NULL);
             }
         }
 
 
-        /* Checking if any rule related to the size exist */
-        if(currently_rule->maxsize)
-        {
-            if(lf->size < currently_rule->maxsize)
+        if(rule->dstgeoip) {
+            if(lf->dstgeoip) {
+                if(!OSMatch_Execute(lf->dstgeoip,
+                            strlen(lf->dstgeoip),
+                            rule->dstgeoip))
+                    return(NULL);
+            } else {
+                return(NULL);
+            }
+        }
+        else if(rule->dstgeoip_pcre2) {
+            if(lf->dstgeoip) {
+                if(!OSPcre2_Execute(lf->dstgeoip,
+                            rule->dstgeoip_pcre2))
+                    return(NULL);
+            } else {
                 return(NULL);
+            }
         }
 
 
-        /* Checking if we are in the right time */
-        if(currently_rule->day_time)
-        {
-            if(!OS_IsonTime(lf->hour, currently_rule->day_time))
-            {
-                return(NULL);
+        /* Check if any rule related to the size exist */
+        if (rule->maxsize) {
+            if (lf->size < rule->maxsize) {
+                return (NULL);
             }
         }
 
+        /* Check if we are in the right time */
+        if (rule->day_time) {
+            if (!OS_IsonTime(lf->hour, rule->day_time)) {
+                return (NULL);
+            }
+        }
 
-        /* Checking week day */
-        if(currently_rule->week_day)
-        {
-            if(!OS_IsonDay(__crt_wday, currently_rule->week_day))
-            {
-                return(NULL);
+        /* Check week day */
+        if (rule->week_day) {
+            if (!OS_IsonDay(__crt_wday, rule->week_day)) {
+                return (NULL);
             }
         }
 
+        /* Get extra data */
+        if (rule->extra_data) {
+            if (!lf->data) {
+                return (NULL);
+            }
 
-        /* Getting extra data */
-        if(currently_rule->extra_data)
-        {
-            if(!lf->data)
-                return(NULL);
+            if (!OSMatch_Execute(lf->data,
+                                 strlen(lf->data),
+                                 rule->extra_data)) {
+                return (NULL);
+            }
+        }
+        else if (rule->extra_data_pcre2) {
+            if (!lf->data) {
+                return (NULL);
+            }
 
-            if(!OSMatch_Execute(lf->data,
-                        strlen(lf->data),
-                        currently_rule->extra_data))
-                return(NULL);
+            if (!OSPcre2_Execute(lf->data,
+                                 rule->extra_data_pcre2)) {
+                return (NULL);
+            }
         }
 
+        /* Check hostname */
+        if (rule->hostname) {
+            if (!lf->hostname) {
+                return (NULL);
+            }
 
-        /* Checking hostname */
-        if(currently_rule->hostname)
-        {
-            if(!lf->hostname)
-                return(NULL);
+            if (!OSMatch_Execute(lf->hostname,
+                                 strlen(lf->hostname),
+                                 rule->hostname)) {
+                return (NULL);
+            }
+        }
+        else if (rule->hostname_pcre2) {
+            if (!lf->hostname) {
+                return (NULL);
+            }
 
-            if(!OSMatch_Execute(lf->hostname,
-                        strlen(lf->hostname),
-                        currently_rule->hostname))
-                return(NULL);
+            if (!OSPcre2_Execute(lf->hostname,
+                                 rule->hostname_pcre2)) {
+                return (NULL);
+            }
         }
 
+        /* Check for status */
+        if (rule->status) {
+            if (!lf->status) {
+                return (NULL);
+            }
 
-        /* Checking for status */
-        if(currently_rule->status)
-        {
-            if(!lf->status)
-                return(NULL);
+            if (!OSMatch_Execute(lf->status,
+                                 strlen(lf->status),
+                                 rule->status)) {
+                return (NULL);
+            }
+        }
+        else if (rule->status_pcre2) {
+            if (!lf->status) {
+                return (NULL);
+            }
 
-            if(!OSMatch_Execute(lf->status,
-                        strlen(lf->status),
-                        currently_rule->status))
-                return(NULL);
+            if (!OSPcre2_Execute(lf->status,
+                                 rule->status_pcre2)) {
+                return (NULL);
+            }
         }
 
 
-        /* Do diff check. */
-        if(currently_rule->context_opts & SAME_DODIFF)
-        {
-            if(!doDiff(currently_rule, lf))
-            {
-                return(NULL);
+        /* Do diff check */
+        if (rule->context_opts & SAME_DODIFF) {
+            if (!doDiff(rule, lf)) {
+                return (NULL);
             }
         }
     }
 
-    /* Checking for the FTS flag */
-    if(currently_rule->alert_opts & DO_FTS)
-    {
+    /* Check for the FTS flag */
+    if (rule->alert_opts & DO_FTS) {
         /** FTS CHECKS **/
-        if(lf->decoder_info->fts)
-        {
-            if(lf->decoder_info->fts & FTS_DONE)
-            {
-                /* We already did the fts in here. */
-            }
-            else if(!FTS(lf))
-            {
-                return(NULL);
+        if (lf->decoder_info->fts) {
+            if (lf->decoder_info->fts & FTS_DONE) {
+                /* We already did the fts in here */
+            } else if (!FTS(lf)) {
+                return (NULL);
             }
-        }
-        else
-        {
-            return(NULL);
+        } else {
+            return (NULL);
         }
     }
 
     /* List lookups */
-    if(currently_rule->lists != NULL)
-    {
-        ListRule *list_holder=currently_rule->lists;
-        while(list_holder)
-        {
-            switch(list_holder->field)
-            {
+    if (rule->lists != NULL) {
+        ListRule *list_holder = rule->lists;
+        while (list_holder) {
+            switch (list_holder->field) {
                 case RULE_SRCIP:
-                    if(!lf->srcip)
-                        return(NULL);
-                    if(!OS_DBSearch(list_holder,lf->srcip))
-                        return(NULL);
+                    if (!lf->srcip) {
+                        return (NULL);
+                    }
+                    if (!OS_DBSearch(list_holder, lf->srcip)) {
+                        return (NULL);
+                    }
                     break;
                 case RULE_SRCPORT:
-                    if(!lf->srcport)
-                        return(NULL);
-                    if(!OS_DBSearch(list_holder,lf->srcport))
-                        return(NULL);
+                    if (!lf->srcport) {
+                        return (NULL);
+                    }
+                    if (!OS_DBSearch(list_holder, lf->srcport)) {
+                        return (NULL);
+                    }
                     break;
                 case RULE_DSTIP:
-                    if(!lf->dstip)
-                        return(NULL);
-                    if(!OS_DBSearch(list_holder,lf->dstip))
-                        return(NULL);
+                    if (!lf->dstip) {
+                        return (NULL);
+                    }
+                    if (!OS_DBSearch(list_holder, lf->dstip)) {
+                        return (NULL);
+                    }
                     break;
                 case RULE_DSTPORT:
-                    if(!lf->dstport)
-                        return(NULL);
-                    if(!OS_DBSearch(list_holder,lf->dstport))
-                        return(NULL);
-                    break;
-                case RULE_USER:
-                    if(lf->srcuser)
-                    {
-                        if(!OS_DBSearch(list_holder,lf->srcuser))
-                            return(NULL);
+                    if (!lf->dstport) {
+                        return (NULL);
                     }
-                    else if(lf->dstuser)
-                    {
-                        if(!OS_DBSearch(list_holder,lf->dstuser))
-                            return(NULL);
+                    if (!OS_DBSearch(list_holder, lf->dstport)) {
+                        return (NULL);
                     }
-                    else
-                    {
-                        return(NULL);
+                    break;
+                case RULE_USER:
+                    if (lf->srcuser) {
+                        if (!OS_DBSearch(list_holder, lf->srcuser)) {
+                            return (NULL);
+                        }
+                    } else if (lf->dstuser) {
+                        if (!OS_DBSearch(list_holder, lf->dstuser)) {
+                            return (NULL);
+                        }
+                    } else {
+                        return (NULL);
                     }
                     break;
                 case RULE_URL:
-                    if(!lf->url)
-                        return(NULL);
-                    if(!OS_DBSearch(list_holder,lf->url))
-                        return(NULL);
+                    if (!lf->url) {
+                        return (NULL);
+                    }
+                    if (!OS_DBSearch(list_holder, lf->url)) {
+                        return (NULL);
+                    }
                     break;
                 case RULE_ID:
-                    if(!lf->id)
-                        return(NULL);
-                    if(!OS_DBSearch(list_holder,lf->id))
-                        return(NULL);
+                    if (!lf->id) {
+                        return (NULL);
+                    }
+                    if (!OS_DBSearch(list_holder, lf->id)) {
+                        return (NULL);
+                    }
                     break;
                 case RULE_HOSTNAME:
-                    if(!lf->hostname)
-                        return(NULL);
-                    if(!OS_DBSearch(list_holder,lf->hostname))
-                        return(NULL);
+                    if (!lf->hostname) {
+                        return (NULL);
+                    }
+                    if (!OS_DBSearch(list_holder, lf->hostname)) {
+                        return (NULL);
+                    }
                     break;
                 case RULE_PROGRAM_NAME:
-                    if(!lf->program_name)
-                        return(NULL);
-                    if(!OS_DBSearch(list_holder,lf->program_name))
-                        return(NULL);
+                    if (!lf->program_name) {
+                        return (NULL);
+                    }
+                    if (!OS_DBSearch(list_holder, lf->program_name)) {
+                        return (NULL);
+                    }
                     break;
                 case RULE_STATUS:
-                    if(!lf->status)
-                        return(NULL);
-                    if(!OS_DBSearch(list_holder,lf->status))
-                        return(NULL);
+                    if (!lf->status) {
+                        return (NULL);
+                    }
+                    if (!OS_DBSearch(list_holder, lf->status)) {
+                        return (NULL);
+                    }
                     break;
                 case RULE_ACTION:
-                    if(!lf->action)
-                        return(NULL);
-                    if(!OS_DBSearch(list_holder,lf->action))
-                        return(NULL);
+                    if (!lf->action) {
+                        return (NULL);
+                    }
+                    if (!OS_DBSearch(list_holder, lf->action)) {
+                        return (NULL);
+                    }
                     break;
                 default:
-                    return(NULL);
+                    return (NULL);
             }
 
             list_holder = list_holder->next;
         }
     }
 
-
     /* If it is a context rule, search for it */
-    if(currently_rule->context == 1)
-    {
-        if(!currently_rule->event_search(lf, currently_rule))
-            return(NULL);
+    if (rule->context == 1) {
+        if (!(rule->context_opts & SAME_DODIFF)) {
+            if (rule->event_search) {
+                if (!rule->event_search(lf, rule)) {
+                    return (NULL);
+                }
+            }
+        }
     }
 
-    #ifdef TESTRULE
-    if(full_output && !alert_only)
-    print_out("       *Rule %d matched.", currently_rule->sigid);
-    #endif
-
+#ifdef TESTRULE
+    if (full_output && !alert_only) {
+        print_out("       *Rule %d matched.", rule->sigid);
+    }
+#endif
 
     /* Search for dependent rules */
-    if(curr_node->child)
-    {
+    if (curr_node->child) {
         RuleNode *child_node = curr_node->child;
         RuleInfo *child_rule = NULL;
 
-        #ifdef TESTRULE
-        if(full_output && !alert_only)
-        print_out("       *Trying child rules.");
-        #endif
+#ifdef TESTRULE
+        if (full_output && !alert_only) {
+            print_out("       *Trying child rules.");
+        }
+#endif
 
-        while(child_node)
-        {
+        while (child_node) {
             child_rule = OS_CheckIfRuleMatch(lf, child_node);
-            if(child_rule != NULL)
-            {
-                return(child_rule);
+            if (child_rule != NULL) {
+                return (child_rule);
             }
 
             child_node = child_node->next;
         }
     }
 
-
     /* If we are set to no alert, keep going */
-    if(currently_rule->alert_opts & NO_ALERT)
-    {
-        return(NULL);
+    if (rule->alert_opts & NO_ALERT) {
+        return (NULL);
     }
 
-
     hourly_alerts++;
-    currently_rule->firedtimes++;
+    rule->firedtimes++;
 
-    return(currently_rule);  /* Matched */
+    return (rule); /* Matched */
 }
 
-
-/** void LoopRule(RuleNode *curr_node);
- *  Update each rule and print it to the logs.
- */
-void LoopRule(RuleNode *curr_node, FILE *flog)
+/*  Update each rule and print it to the logs */
+static void LoopRule(RuleNode *curr_node, FILE *flog)
 {
-    if(curr_node->ruleinfo->firedtimes)
-    {
+    if (curr_node->ruleinfo->firedtimes) {
         fprintf(flog, "%d-%d-%d-%d\n",
                 thishour,
                 curr_node->ruleinfo->sigid,
@@ -1691,12 +1648,10 @@ void LoopRule(RuleNode *curr_node, FILE *flog)
         curr_node->ruleinfo->firedtimes = 0;
     }
 
-    if(curr_node->child)
-    {
+    if (curr_node->child) {
         RuleNode *child_node = curr_node->child;
 
-        while(child_node)
-        {
+        while (child_node) {
             LoopRule(child_node, flog);
             child_node = child_node->next;
         }
@@ -1704,69 +1659,61 @@ void LoopRule(RuleNode *curr_node, FILE *flog)
     return;
 }
 
-
-/** void DumpLogstats();
- *  Dump the hourly stats about each rule.
- */
-void DumpLogstats()
+/* Dump the hourly stats about each rule */
+static void DumpLogstats()
 {
     RuleNode *rulenode_pt;
-    char logfile[OS_FLSIZE +1];
+    char logfile[OS_FLSIZE + 1];
     FILE *flog;
 
-    /* Opening log file */
+    /* Open log file */
     snprintf(logfile, OS_FLSIZE, "%s/%d/", STATSAVED, prev_year);
-    if(IsDir(logfile) == -1)
-        if(mkdir(logfile,0770) == -1)
-        {
-            merror(MKDIR_ERROR, ARGV0, logfile);
+    if (IsDir(logfile) == -1)
+        if (mkdir(logfile, 0770) == -1) {
+            merror(MKDIR_ERROR, ARGV0, logfile, errno, strerror(errno));
             return;
         }
 
-    snprintf(logfile,OS_FLSIZE,"%s/%d/%s", STATSAVED, prev_year,prev_month);
+    snprintf(logfile, OS_FLSIZE, "%s/%d/%s", STATSAVED, prev_year, prev_month);
 
-    if(IsDir(logfile) == -1)
-        if(mkdir(logfile,0770) == -1)
-        {
-            merror(MKDIR_ERROR,ARGV0,logfile);
+    if (IsDir(logfile) == -1)
+        if (mkdir(logfile, 0770) == -1) {
+            merror(MKDIR_ERROR, ARGV0, logfile, errno, strerror(errno));
             return;
         }
 
 
-    /* Creating the logfile name */
-    snprintf(logfile,OS_FLSIZE,"%s/%d/%s/ossec-%s-%02d.log",
-            STATSAVED,
-            prev_year,
-            prev_month,
-            "totals",
-            today);
+    /* Creat the logfile name */
+    snprintf(logfile, OS_FLSIZE, "%s/%d/%s/ossec-%s-%02d.log",
+             STATSAVED,
+             prev_year,
+             prev_month,
+             "totals",
+             today);
 
     flog = fopen(logfile, "a");
-    if(!flog)
-    {
-        merror(FOPEN_ERROR, ARGV0, logfile);
+    if (!flog) {
+        merror(FOPEN_ERROR, ARGV0, logfile, errno, strerror(errno));
         return;
     }
 
     rulenode_pt = OS_GetFirstRule();
 
-    if(!rulenode_pt)
-    {
+    if (!rulenode_pt) {
         ErrorExit("%s: Rules in an inconsistent state. Exiting.",
-                ARGV0);
+                  ARGV0);
     }
 
-    /* Looping on all the rules and printing the stats from them */
-    do
-    {
+    /* Loop over all the rules and print their stats */
+    do {
         LoopRule(rulenode_pt, flog);
-    }while((rulenode_pt = rulenode_pt->next) != NULL);
+    } while ((rulenode_pt = rulenode_pt->next) != NULL);
 
 
     /* Print total for the hour */
     fprintf(flog, "%d--%d--%d--%d--%d\n\n",
-                thishour,
-                hourly_alerts, hourly_events, hourly_syscheck,hourly_firewall);
+            thishour,
+            hourly_alerts, hourly_events, hourly_syscheck, hourly_firewall);
     hourly_alerts = 0;
     hourly_events = 0;
     hourly_syscheck = 0;
@@ -1775,7 +1722,3 @@ void DumpLogstats()
     fclose(flog);
 }
 
-
-
-/* EOF */
-