3 /* Copyright (C) 2010 Trend Micro Inc.
6 * This program is a free software; you can redistribute it
7 * and/or modify it under the terms of the GNU General Public
8 * License (version 2) as published by the FSF - Free Software
11 * License details at the LICENSE file included with OSSEC or
12 * online at: http://www.ossec.net/en/licensing.html
17 * Available at http://www.ossec.net
22 * Responsible for correlation and log decoding.
26 #define ARGV0 "ossec-analysisd"
31 #include "alerts/alerts.h"
32 #include "alerts/getloglocation.h"
33 #include "os_execd/execd.h"
35 #include "os_regex/os_regex.h"
36 #include "os_net/os_net.h"
40 #include "active-response.h"
45 #include "eventinfo.h"
46 #include "analysisd.h"
60 /* active response queue */
64 /** Internal Functions **/
65 void OS_ReadMSG(int m_queue);
66 RuleInfo *OS_CheckIfRuleMatch(Eventinfo *lf, RuleNode *curr_node);
69 /** External functions prototypes (only called here) **/
72 int GlobalConf(char * cfgfile);
76 void Rules_OP_CreateRules();
77 void Lists_OP_CreateLists();
78 int Rules_OP_ReadRules(char * cfgfile);
79 int _setlevels(RuleNode *node, int nnode);
80 int AddHash_Rule(RuleNode *node);
84 int OS_CleanMSG(char *msg, Eventinfo *lf);
89 int FTS(Eventinfo *lf);
90 int AddtoIGnore(Eventinfo *lf);
91 int IGnore(Eventinfo *lf);
92 int doDiff(RuleInfo *currently_rule, Eventinfo *lf);
96 void DecodeEvent(Eventinfo *lf);
97 int DecodeSyscheck(Eventinfo *lf);
98 int DecodeRootcheck(Eventinfo *lf);
99 int DecodeHostinfo(Eventinfo *lf);
103 int ReadDecodeXML(char *file);
107 /* For syscheckd (integrity checking) */
109 void RootcheckInit();
115 int Check_Hour(Eventinfo *lf);
126 /** int main(int argc, char **argv)
129 int main(int argc, char **argv)
131 int main_analysisd(int argc, char **argv)
134 int c = 0, m_queue = 0, test_config = 0,run_foreground = 0;
135 char *dir = DEFAULTDIR;
137 char *group = GROUPGLOBAL;
140 char *cfg = DEFAULTCPATH;
142 /* Setting the name */
148 memset(prev_month, '\0', 4);
154 while((c = getopt(argc, argv, "Vtdhfu:g:D:c:")) != -1){
170 ErrorExit("%s: -u needs an argument",ARGV0);
175 ErrorExit("%s: -g needs an argument",ARGV0);
180 ErrorExit("%s: -D needs an argument",ARGV0);
184 ErrorExit("%s: -c needs an argument",ARGV0);
198 /* Starting daemon */
199 debug1(STARTED_MSG,ARGV0);
200 DEBUG_MSG("%s: DEBUG: Starting on debug mode - %d ", ARGV0, (int)time(0));
203 /*Check if the user/group given are valid */
204 uid = Privsep_GetUser(user);
205 gid = Privsep_GetGroup(group);
206 if((uid < 0)||(gid < 0))
207 ErrorExit(USER_ERROR,ARGV0,user,group);
211 debug1(FOUND_USER, ARGV0);
214 /* Initializing Active response */
216 if(AR_ReadConfig(test_config, cfg) < 0)
218 ErrorExit(CONFIG_ERROR,ARGV0, cfg);
220 debug1(ASINIT, ARGV0);
223 /* Reading configuration file */
224 if(GlobalConf(cfg) < 0)
226 ErrorExit(CONFIG_ERROR,ARGV0, cfg);
229 debug1(READ_CONFIG, ARGV0);
232 /* Fixing Config.ar */
238 /* Getting servers hostname */
239 memset(__shost, '\0', 512);
240 if(gethostname(__shost, 512 -1) != 0)
242 strncpy(__shost, OSSEC_SERVER, 512 -1);
248 /* Remove domain part if available */
249 _ltmp = strchr(__shost, '.');
254 /* going on Daemon mode */
255 if(!test_config || !run_foreground)
262 /* Starting prelude */
266 prelude_start(Config.prelude_profile, argc, argv);
271 /* Opening the Picviz socket */
274 OS_PicvizOpen(Config.picviz_socket);
275 chown(Config.picviz_socket, uid, gid);
278 /* Setting the group */
279 if(Privsep_SetGroup(gid) < 0)
280 ErrorExit(SETGID_ERROR,ARGV0,group);
283 if(Privsep_Chroot(dir) < 0)
284 ErrorExit(CHROOT_ERROR,ARGV0,dir);
292 * Anonymous Section: Load rules, decoders, and lists
294 * As lists require two pass loading of rules that make use of list lookups
295 * are created with blank database structs, and need to be filled in after
296 * completion of all rules and lists.
300 /* Initializing the decoders list */
301 OS_CreateOSDecoderList();
304 { /* Legacy loading */
305 /* Reading decoders */
306 if(!ReadDecodeXML(XML_DECODER))
308 ErrorExit(CONFIG_ERROR, ARGV0, XML_DECODER);
311 /* Reading local ones. */
312 c = ReadDecodeXML(XML_LDECODER);
316 ErrorExit(CONFIG_ERROR, ARGV0, XML_LDECODER);
321 verbose("%s: INFO: Reading local decoder file.", ARGV0);
325 { /* New loaded based on file speified in ossec.conf */
326 char **decodersfiles;
327 decodersfiles = Config.decoders;
328 while( decodersfiles && *decodersfiles)
331 verbose("%s: INFO: Reading decoder file %s.", ARGV0, *decodersfiles);
332 if(!ReadDecodeXML(*decodersfiles))
333 ErrorExit(CONFIG_ERROR, ARGV0, *decodersfiles);
335 free(*decodersfiles);
344 /* Initializing the lists of list struct */
345 Lists_OP_CreateLists();
346 /* Load each list into list struct */
349 listfiles = Config.lists;
350 while(listfiles && *listfiles)
353 verbose("%s: INFO: Reading loading the lists file: '%s'", ARGV0, *listfiles);
354 if(Lists_OP_LoadList(*listfiles) < 0)
355 ErrorExit(LISTS_ERROR, ARGV0, *listfiles);
364 /* Creating the rules list */
365 Rules_OP_CreateRules();
367 /* Reading the rules */
370 rulesfiles = Config.includes;
371 while(rulesfiles && *rulesfiles)
374 verbose("%s: INFO: Reading rules file: '%s'", ARGV0, *rulesfiles);
375 if(Rules_OP_ReadRules(*rulesfiles) < 0)
376 ErrorExit(RULES_ERROR, ARGV0, *rulesfiles);
382 free(Config.includes);
383 Config.includes = NULL;
386 /* Find all rules with that require list lookups and attache the
387 * the correct list struct to the rule. This keeps rules from having to
388 * search thought the list of lists for the correct file during rule evaluation.
395 /* Fixing the levels/accuracy */
398 RuleNode *tmp_node = OS_GetFirstRule();
400 total_rules = _setlevels(tmp_node, 0);
402 verbose("%s: INFO: Total rules enabled: '%d'", ARGV0, total_rules);
407 /* Creating a rules hash (for reading alerts from other servers). */
409 RuleNode *tmp_node = OS_GetFirstRule();
410 Config.g_rules_hash = OSHash_Create();
411 if(!Config.g_rules_hash)
413 ErrorExit(MEM_ERROR, ARGV0);
415 AddHash_Rule(tmp_node);
420 /* Ignored files on syscheck */
423 files = Config.syscheck_ignore;
424 while(files && *files)
427 verbose("%s: INFO: Ignoring file: '%s'", ARGV0, *files);
433 /* Checking if log_fw is enabled. */
434 Config.logfw = getDefine_Int("analysisd",
439 /* Success on the configuration test */
444 /* Verbose message */
445 debug1(PRIVSEP_MSG, ARGV0, dir, user);
448 /* Signal manipulation */
452 /* Setting the user */
453 if(Privsep_SetUser(uid) < 0)
454 ErrorExit(SETUID_ERROR,ARGV0,user);
457 /* Creating the PID file */
458 if(CreatePID(ARGV0, getpid()) < 0)
459 ErrorExit(PID_ERROR,ARGV0);
462 /* Setting the queue */
463 if((m_queue = StartMQ(DEFAULTQUEUE,READ)) < 0)
464 ErrorExit(QUEUE_ERROR, ARGV0, DEFAULTQUEUE, strerror(errno));
468 if(Config.white_list == NULL)
471 verbose("%s: INFO: No IP in the white list for active reponse.", ARGV0);
479 wl = Config.white_list;
482 verbose("%s: INFO: White listing IP: '%s'",ARGV0, (*wl)->ip);
485 verbose("%s: INFO: %d IPs in the white list for active response.",
490 /* Hostname White list */
491 if(Config.hostname_white_list == NULL)
494 verbose("%s: INFO: No Hostname in the white list for active reponse.",
504 wl = Config.hostname_white_list;
507 char **tmp_pts = (*wl)->patterns;
510 verbose("%s: INFO: White listing Hostname: '%s'",ARGV0,*tmp_pts);
516 verbose("%s: INFO: %d Hostname(s) in the white list for active response.",
522 /* Start up message */
523 verbose(STARTUP_MSG, ARGV0, (int)getpid());
526 /* Going to main loop */
541 * Main function. Receives the messages(events)
542 * and analyze them all.
545 void OS_ReadMSG(int m_queue)
547 void OS_ReadMSG_analysisd(int m_queue)
551 char msg[OS_MAXSTR +1];
554 RuleInfo *stats_rule;
557 /* Null to global currently pointers */
558 currently_rule = NULL;
560 /* Initiating the logs */
564 /* Initiating the integrity database */
568 /* Initializing Rootcheck */
572 /* Initializing host info */
576 /* Creating the event list */
577 OS_CreateEventList(Config.memorysize);
580 /* Initiating the FTS list */
583 ErrorExit(FTS_LIST_ERROR, ARGV0);
587 /* Starting the active response queues */
590 /* Waiting the ARQ to settle .. */
595 if(Config.ar & REMOTE_AR)
597 if((arq = StartMQ(ARQUEUE, WRITE)) < 0)
599 merror(ARQ_ERROR, ARGV0);
601 /* If LOCAL_AR is set, keep it there */
602 if(Config.ar & LOCAL_AR)
614 verbose(CONN_TO, ARGV0, ARQUEUE, "active-response");
619 /* Only for LOCAL_ONLY installs */
620 if(Config.ar & REMOTE_AR)
622 if(Config.ar & LOCAL_AR)
634 if(Config.ar & LOCAL_AR)
636 if((execdq = StartMQ(EXECQUEUE, WRITE)) < 0)
638 merror(ARQ_ERROR, ARGV0);
640 /* If REMOTE_AR is set, keep it there */
641 if(Config.ar & REMOTE_AR)
644 Config.ar|=REMOTE_AR;
653 verbose(CONN_TO, ARGV0, EXECQUEUE, "exec");
657 debug1("%s: DEBUG: Active response Init completed.", ARGV0);
660 /* Getting currently time before starting */
664 /* Starting the hourly/weekly stats */
669 /* Initializing stats rules */
670 stats_rule = zerorulemember(
677 ErrorExit(MEM_ERROR, ARGV0);
679 stats_rule->group = "stats,";
680 stats_rule->comment = "Excessive number of events (above normal).";
684 /* Doing some cleanup */
685 memset(msg, '\0', OS_MAXSTR +1);
688 /* Initializing the logs */
690 lf = (Eventinfo *)calloc(1,sizeof(Eventinfo));
692 ErrorExit(MEM_ERROR, ARGV0);
693 lf->year = prev_year;
694 strncpy(lf->mon, prev_month, 3);
697 if(OS_GetLogLocation(lf) < 0)
699 ErrorExit("%s: Error allocating log files", ARGV0);
706 debug1("%s: DEBUG: Startup completed. Waiting for new messages..",ARGV0);
712 lf = (Eventinfo *)calloc(1,sizeof(Eventinfo));
714 /* This shouldn't happen .. */
717 ErrorExit(MEM_ERROR,ARGV0);
720 DEBUG_MSG("%s: DEBUG: Waiting for msgs - %d ", ARGV0, (int)time(0));
723 /* Receive message from queue */
724 if((i = OS_RecvUnix(m_queue, OS_MAXSTR, msg)))
726 RuleNode *rulenode_pt;
728 /* Getting the time we received the event */
732 /* Default values for the log info */
736 /* Checking for a valid message. */
739 merror(IMSG_ERROR, ARGV0, msg);
745 /* Message before extracting header */
746 DEBUG_MSG("%s: DEBUG: Received msg: %s ", ARGV0, msg);
749 /* Clean the msg appropriately */
750 if(OS_CleanMSG(msg, lf) < 0)
752 merror(IMSG_ERROR,ARGV0, msg);
759 DEBUG_MSG("%s: DEBUG: Msg cleanup: %s ", ARGV0, lf->log);
762 /* Currently rule must be null in here */
763 currently_rule = NULL;
766 /** Checking the date/hour changes **/
768 /* Update the hour */
769 if(thishour != __crt_hour)
771 /* Search all the rules and print the number
772 * of alerts that each one fired.
775 thishour = __crt_hour;
777 /* Check if the date has changed */
782 /* Update the hourly stats (done daily) */
786 if(OS_GetLogLocation(lf) < 0)
788 ErrorExit("%s: Error allocating log files", ARGV0);
792 strncpy(prev_month, lf->mon, 3);
793 prev_year = lf->year;
798 /* Incrementing number of events received */
802 /*** Running decoders ***/
804 /* Integrity check from syscheck */
805 if(msg[0] == SYSCHECK_MQ)
809 if(!DecodeSyscheck(lf))
811 /* We don't process syscheck events further */
815 /* Getting log size */
816 lf->size = strlen(lf->log);
819 /* Rootcheck decoding */
820 else if(msg[0] == ROOTCHECK_MQ)
822 if(!DecodeRootcheck(lf))
824 /* We don't process rootcheck events further */
827 lf->size = strlen(lf->log);
830 /* Host information special decoder */
831 else if(msg[0] == HOSTINFO_MQ)
833 if(!DecodeHostinfo(lf))
835 /* We don't process hostinfo events further */
838 lf->size = strlen(lf->log);
841 /* Run the general Decoders */
844 /* Getting log size */
845 lf->size = strlen(lf->log);
852 if(lf->decoder_info->type == FIREWALL)
854 /* If we could not get any information from
855 * the log, just ignore it
868 /* We only check if the last message is
869 * duplicated on syslog.
871 else if(lf->decoder_info->type == SYSLOG)
873 /* Checking if the message is duplicated */
874 if(LastMsg_Stats(lf->full_log) == 1)
877 LastMsg_Change(lf->full_log);
884 if(Check_Hour(lf) == 1)
886 void *saved_rule = lf->generated_rule;
889 /* Saving previous log */
890 saved_log = lf->full_log;
892 lf->generated_rule = stats_rule;
893 lf->full_log = __stats_comment;
896 /* alert for statistical analysis */
897 if(stats_rule->alert_opts & DO_LOGALERT)
899 __crt_ftell = ftell(_aflog);
904 /* Set lf to the old values */
905 lf->generated_rule = saved_rule;
906 lf->full_log = saved_log;
911 /* Checking the rules */
912 DEBUG_MSG("%s: DEBUG: Checking the rules - %d ",
913 ARGV0, lf->decoder_info->type);
916 /* Looping all the rules */
917 rulenode_pt = OS_GetFirstRule();
920 ErrorExit("%s: Rules in an inconsistent state. Exiting.",
927 if(lf->decoder_info->type == OSSEC_ALERT)
929 if(!lf->generated_rule)
934 /* We go ahead in here and process the alert. */
935 currently_rule = lf->generated_rule;
938 /* The categories must match */
939 else if(rulenode_pt->ruleinfo->category !=
940 lf->decoder_info->type)
945 /* Checking each rule. */
946 else if((currently_rule = OS_CheckIfRuleMatch(lf, rulenode_pt))
954 if(currently_rule->level == 0)
960 /* Checking ignore time */
961 if(currently_rule->ignore_time)
963 if(currently_rule->time_ignored == 0)
965 currently_rule->time_ignored = lf->time;
967 /* If the currently time - the time the rule was ignored
968 * is less than the time it should be ignored,
969 * leave (do not alert again).
971 else if((lf->time - currently_rule->time_ignored)
972 < currently_rule->ignore_time)
978 currently_rule->time_ignored = lf->time;
983 /* Pointer to the rule that generated it */
984 lf->generated_rule = currently_rule;
987 /* Checking if we should ignore it */
988 if(currently_rule->ckignore && IGnore(lf))
991 lf->generated_rule = NULL;
996 /* Checking if we need to add to ignore list */
997 if(currently_rule->ignore)
1003 /* Log the alert if configured to ... */
1004 if(currently_rule->alert_opts & DO_LOGALERT)
1006 __crt_ftell = ftell(_aflog);
1011 /* Log to prelude */
1015 if(Config.prelude_log_level <= currently_rule->level)
1030 /* Execute an active response */
1031 if(currently_rule->ar)
1034 active_response **rule_ar;
1036 rule_ar = currently_rule->ar;
1041 if((*rule_ar)->ar_cmd->expect & USERNAME)
1044 !OS_PRegex(lf->dstuser,"^[a-zA-Z._0-9@?-]*$"))
1047 merror(CRAFTED_USER, ARGV0, lf->dstuser);
1051 if((*rule_ar)->ar_cmd->expect & SRCIP)
1054 !OS_PRegex(lf->srcip, "^[a-zA-Z.:_0-9-]*$"))
1057 merror(CRAFTED_IP, ARGV0, lf->srcip);
1064 OS_Exec(&execdq, &arq, lf, *rule_ar);
1071 /* Copy the structure to the state memory of if_matched_sid */
1072 if(currently_rule->sid_prev_matched)
1074 if(!OSList_AddData(currently_rule->sid_prev_matched, lf))
1076 merror("%s: Unable to add data to sig list.", ARGV0);
1080 lf->sid_node_to_delete =
1081 currently_rule->sid_prev_matched->last_node;
1085 else if(currently_rule->group_prev_matched)
1089 while(i < currently_rule->group_prev_matched_sz)
1092 currently_rule->group_prev_matched[i],
1095 merror("%s: Unable to add data to grp list.",ARGV0);
1105 }while((rulenode_pt = rulenode_pt->next) != NULL);
1108 /* If configured to log all, do it */
1113 /* Cleaning the memory */
1117 /* Only clear the memory if the eventinfo was not
1118 * added to the stateful memory
1119 * -- message is free inside clean event --
1121 if(lf->generated_rule == NULL)
1134 /* CheckIfRuleMatch v0.1
1135 * Will check if the currently_rule matches the event information
1137 RuleInfo *OS_CheckIfRuleMatch(Eventinfo *lf, RuleNode *curr_node)
1142 * word match (fast regex),
1157 RuleInfo *currently_rule = curr_node->ruleinfo;
1163 merror("%s: Inconsistent state. currently rule NULL", ARGV0);
1169 if(full_output && !alert_only)
1170 print_out(" Trying rule: %d - %s", currently_rule->sigid,
1171 currently_rule->comment);
1175 /* Checking if any decoder pre-matched here */
1176 if(currently_rule->decoded_as &&
1177 currently_rule->decoded_as != lf->decoder_info->id)
1183 /* Checking program name */
1184 if(currently_rule->program_name)
1186 if(!lf->program_name)
1189 if(!OSMatch_Execute(lf->program_name,
1191 currently_rule->program_name))
1196 /* Checking for the id */
1197 if(currently_rule->id)
1204 if(!OSMatch_Execute(lf->id,
1206 currently_rule->id))
1214 /* Checking if any word to match exists */
1215 if(currently_rule->match)
1217 if(!OSMatch_Execute(lf->log, lf->size, currently_rule->match))
1223 /* Checking if exist any regex for this rule */
1224 if(currently_rule->regex)
1226 if(!OSRegex_Execute(lf->log, currently_rule->regex))
1231 /* Checking for actions */
1232 if(currently_rule->action)
1237 if(strcmp(currently_rule->action,lf->action) != 0)
1242 /* Checking for the url */
1243 if(currently_rule->url)
1250 if(!OSMatch_Execute(lf->url, strlen(lf->url), currently_rule->url))
1261 /* Getting tcp/ip packet information */
1262 if(currently_rule->alert_opts & DO_PACKETINFO)
1264 /* Checking for the srcip */
1265 if(currently_rule->srcip)
1272 if(!OS_IPFoundList(lf->srcip, currently_rule->srcip))
1281 /* Checking for the dstip */
1282 if(currently_rule->dstip)
1289 if(!OS_IPFoundList(lf->dstip, currently_rule->dstip))
1298 if(currently_rule->srcport)
1305 if(!OSMatch_Execute(lf->srcport,
1306 strlen(lf->srcport),
1307 currently_rule->srcport))
1315 if(currently_rule->dstport)
1322 if(!OSMatch_Execute(lf->dstport,
1323 strlen(lf->dstport),
1324 currently_rule->dstport))
1332 } /* END PACKET_INFO */
1335 /* Extra information from event */
1336 if(currently_rule->alert_opts & DO_EXTRAINFO)
1338 /* Checking compiled rule. */
1339 if(currently_rule->compiled_rule)
1341 if(!currently_rule->compiled_rule(lf))
1348 /* Checking if exist any user to match */
1349 if(currently_rule->user)
1353 if(!OSMatch_Execute(lf->dstuser,
1354 strlen(lf->dstuser),
1355 currently_rule->user))
1358 else if(lf->srcuser)
1360 if(!OSMatch_Execute(lf->srcuser,
1361 strlen(lf->srcuser),
1362 currently_rule->user))
1376 /* Checking if any rule related to the size exist */
1377 if(currently_rule->maxsize)
1379 if(lf->size < currently_rule->maxsize)
1384 /* Checking if we are in the right time */
1385 if(currently_rule->day_time)
1387 if(!OS_IsonTime(lf->hour, currently_rule->day_time))
1394 /* Checking week day */
1395 if(currently_rule->week_day)
1397 if(!OS_IsonDay(__crt_wday, currently_rule->week_day))
1404 /* Getting extra data */
1405 if(currently_rule->extra_data)
1410 if(!OSMatch_Execute(lf->data,
1412 currently_rule->extra_data))
1417 /* Checking hostname */
1418 if(currently_rule->hostname)
1423 if(!OSMatch_Execute(lf->hostname,
1424 strlen(lf->hostname),
1425 currently_rule->hostname))
1430 /* Checking for status */
1431 if(currently_rule->status)
1436 if(!OSMatch_Execute(lf->status,
1438 currently_rule->status))
1443 /* Do diff check. */
1444 if(currently_rule->context_opts & SAME_DODIFF)
1446 if(!doDiff(currently_rule, lf))
1453 /* Checking for the FTS flag */
1454 if(currently_rule->alert_opts & DO_FTS)
1457 if(lf->decoder_info->fts)
1459 if(lf->decoder_info->fts & FTS_DONE)
1461 /* We already did the fts in here. */
1475 if(currently_rule->lists != NULL)
1477 ListRule *list_holder=currently_rule->lists;
1480 switch(list_holder->field)
1485 if(!OS_DBSearch(list_holder,lf->srcip))
1491 if(!OS_DBSearch(list_holder,lf->srcport))
1497 if(!OS_DBSearch(list_holder,lf->dstip))
1503 if(!OS_DBSearch(list_holder,lf->dstport))
1509 if(!OS_DBSearch(list_holder,lf->srcuser))
1512 else if(lf->dstuser)
1514 if(!OS_DBSearch(list_holder,lf->dstuser))
1525 if(!OS_DBSearch(list_holder,lf->url))
1531 if(!OS_DBSearch(list_holder,lf->id))
1537 if(!OS_DBSearch(list_holder,lf->hostname))
1540 case RULE_PROGRAM_NAME:
1541 if(!lf->program_name)
1543 if(!OS_DBSearch(list_holder,lf->program_name))
1549 if(!OS_DBSearch(list_holder,lf->status))
1555 if(!OS_DBSearch(list_holder,lf->action))
1562 list_holder = list_holder->next;
1567 /* If it is a context rule, search for it */
1568 if(currently_rule->context == 1)
1570 if(!currently_rule->event_search(lf, currently_rule))
1575 if(full_output && !alert_only)
1576 print_out(" *Rule %d matched.", currently_rule->sigid);
1580 /* Search for dependent rules */
1581 if(curr_node->child)
1583 RuleNode *child_node = curr_node->child;
1584 RuleInfo *child_rule = NULL;
1587 if(full_output && !alert_only)
1588 print_out(" *Trying child rules.");
1593 child_rule = OS_CheckIfRuleMatch(lf, child_node);
1594 if(child_rule != NULL)
1599 child_node = child_node->next;
1604 /* If we are set to no alert, keep going */
1605 if(currently_rule->alert_opts & NO_ALERT)
1612 currently_rule->firedtimes++;
1614 return(currently_rule); /* Matched */
1618 /** void LoopRule(RuleNode *curr_node);
1619 * Update each rule and print it to the logs.
1621 void LoopRule(RuleNode *curr_node, FILE *flog)
1623 if(curr_node->ruleinfo->firedtimes)
1625 fprintf(flog, "%d-%d-%d-%d\n",
1627 curr_node->ruleinfo->sigid,
1628 curr_node->ruleinfo->level,
1629 curr_node->ruleinfo->firedtimes);
1630 curr_node->ruleinfo->firedtimes = 0;
1633 if(curr_node->child)
1635 RuleNode *child_node = curr_node->child;
1639 LoopRule(child_node, flog);
1640 child_node = child_node->next;
1647 /** void DumpLogstats();
1648 * Dump the hourly stats about each rule.
1652 RuleNode *rulenode_pt;
1653 char logfile[OS_FLSIZE +1];
1656 /* Opening log file */
1657 snprintf(logfile, OS_FLSIZE, "%s/%d/", STATSAVED, prev_year);
1658 if(IsDir(logfile) == -1)
1659 if(mkdir(logfile,0770) == -1)
1661 merror(MKDIR_ERROR, ARGV0, logfile);
1665 snprintf(logfile,OS_FLSIZE,"%s/%d/%s", STATSAVED, prev_year,prev_month);
1667 if(IsDir(logfile) == -1)
1668 if(mkdir(logfile,0770) == -1)
1670 merror(MKDIR_ERROR,ARGV0,logfile);
1675 /* Creating the logfile name */
1676 snprintf(logfile,OS_FLSIZE,"%s/%d/%s/ossec-%s-%02d.log",
1683 flog = fopen(logfile, "a");
1686 merror(FOPEN_ERROR, ARGV0, logfile);
1690 rulenode_pt = OS_GetFirstRule();
1694 ErrorExit("%s: Rules in an inconsistent state. Exiting.",
1698 /* Looping on all the rules and printing the stats from them */
1701 LoopRule(rulenode_pt, flog);
1702 }while((rulenode_pt = rulenode_pt->next) != NULL);
1705 /* Print total for the hour */
1706 fprintf(flog, "%d--%d--%d--%d--%d\n\n",
1708 hourly_alerts, hourly_events, hourly_syscheck,hourly_firewall);
1711 hourly_syscheck = 0;
1712 hourly_firewall = 0;