1 /* @(#) $Id: ./src/analysisd/analysisd.c, 2012/07/26 dcid Exp $
4 /* Copyright (C) 2010-2012 Trend Micro Inc.
7 * This program is a free software; you can redistribute it
8 * and/or modify it under the terms of the GNU General Public
9 * License (version 2) as published by the FSF - Free Software
12 * License details at the LICENSE file included with OSSEC or
13 * online at: http://www.ossec.net/en/licensing.html
18 * Available at http://www.ossec.net
23 * Responsible for correlation and log decoding.
27 #define ARGV0 "ossec-analysisd"
32 #include "alerts/alerts.h"
33 #include "alerts/getloglocation.h"
34 #include "os_execd/execd.h"
36 #include "os_regex/os_regex.h"
37 #include "os_net/os_net.h"
41 #include "active-response.h"
46 #include "eventinfo.h"
47 #include "analysisd.h"
61 /* active response queue */
65 /** Internal Functions **/
66 void OS_ReadMSG(int m_queue);
67 RuleInfo *OS_CheckIfRuleMatch(Eventinfo *lf, RuleNode *curr_node);
70 /** External functions prototypes (only called here) **/
73 int GlobalConf(char * cfgfile);
77 void Rules_OP_CreateRules();
78 void Lists_OP_CreateLists();
79 int Rules_OP_ReadRules(char * cfgfile);
80 int _setlevels(RuleNode *node, int nnode);
81 int AddHash_Rule(RuleNode *node);
85 int OS_CleanMSG(char *msg, Eventinfo *lf);
90 int FTS(Eventinfo *lf);
91 int AddtoIGnore(Eventinfo *lf);
92 int IGnore(Eventinfo *lf);
93 int doDiff(RuleInfo *currently_rule, Eventinfo *lf);
97 void DecodeEvent(Eventinfo *lf);
98 int DecodeSyscheck(Eventinfo *lf);
99 int DecodeRootcheck(Eventinfo *lf);
100 int DecodeHostinfo(Eventinfo *lf);
104 int ReadDecodeXML(char *file);
108 /* For syscheckd (integrity checking) */
110 void RootcheckInit();
116 int Check_Hour(Eventinfo *lf);
127 /** int main(int argc, char **argv)
130 int main(int argc, char **argv)
132 int main_analysisd(int argc, char **argv)
135 int c = 0, m_queue = 0, test_config = 0,run_foreground = 0;
136 char *dir = DEFAULTDIR;
138 char *group = GROUPGLOBAL;
141 char *cfg = DEFAULTCPATH;
143 /* Setting the name */
149 memset(prev_month, '\0', 4);
155 while((c = getopt(argc, argv, "Vtdhfu:g:D:c:")) != -1){
171 ErrorExit("%s: -u needs an argument",ARGV0);
176 ErrorExit("%s: -g needs an argument",ARGV0);
181 ErrorExit("%s: -D needs an argument",ARGV0);
186 ErrorExit("%s: -c needs an argument",ARGV0);
200 /* Starting daemon */
201 debug1(STARTED_MSG,ARGV0);
202 DEBUG_MSG("%s: DEBUG: Starting on debug mode - %d ", ARGV0, (int)time(0));
205 /*Check if the user/group given are valid */
206 uid = Privsep_GetUser(user);
207 gid = Privsep_GetGroup(group);
208 if((uid < 0)||(gid < 0))
209 ErrorExit(USER_ERROR,ARGV0,user,group);
213 debug1(FOUND_USER, ARGV0);
216 /* Initializing Active response */
218 if(AR_ReadConfig(test_config, cfg) < 0)
220 ErrorExit(CONFIG_ERROR,ARGV0, cfg);
222 debug1(ASINIT, ARGV0);
225 /* Reading configuration file */
226 if(GlobalConf(cfg) < 0)
228 ErrorExit(CONFIG_ERROR,ARGV0, cfg);
231 debug1(READ_CONFIG, ARGV0);
234 /* Fixing Config.ar */
240 /* Getting servers hostname */
241 memset(__shost, '\0', 512);
242 if(gethostname(__shost, 512 -1) != 0)
244 strncpy(__shost, OSSEC_SERVER, 512 -1);
250 /* Remove domain part if available */
251 _ltmp = strchr(__shost, '.');
256 /* going on Daemon mode */
257 if(!test_config && !run_foreground)
264 /* Starting prelude */
268 prelude_start(Config.prelude_profile, argc, argv);
273 /* Opening the Picviz socket */
276 OS_PicvizOpen(Config.picviz_socket);
277 chown(Config.picviz_socket, uid, gid);
280 /* Setting the group */
281 if(Privsep_SetGroup(gid) < 0)
282 ErrorExit(SETGID_ERROR,ARGV0,group);
285 if(Privsep_Chroot(dir) < 0)
286 ErrorExit(CHROOT_ERROR,ARGV0,dir);
294 * Anonymous Section: Load rules, decoders, and lists
296 * As lists require two pass loading of rules that make use of list lookups
297 * are created with blank database structs, and need to be filled in after
298 * completion of all rules and lists.
302 /* Initializing the decoders list */
303 OS_CreateOSDecoderList();
306 { /* Legacy loading */
307 /* Reading decoders */
308 if(!ReadDecodeXML(XML_DECODER))
310 ErrorExit(CONFIG_ERROR, ARGV0, XML_DECODER);
313 /* Reading local ones. */
314 c = ReadDecodeXML(XML_LDECODER);
318 ErrorExit(CONFIG_ERROR, ARGV0, XML_LDECODER);
323 verbose("%s: INFO: Reading local decoder file.", ARGV0);
327 { /* New loaded based on file speified in ossec.conf */
328 char **decodersfiles;
329 decodersfiles = Config.decoders;
330 while( decodersfiles && *decodersfiles)
333 verbose("%s: INFO: Reading decoder file %s.", ARGV0, *decodersfiles);
334 if(!ReadDecodeXML(*decodersfiles))
335 ErrorExit(CONFIG_ERROR, ARGV0, *decodersfiles);
337 free(*decodersfiles);
346 /* Initializing the lists of list struct */
347 Lists_OP_CreateLists();
348 /* Load each list into list struct */
351 listfiles = Config.lists;
352 while(listfiles && *listfiles)
355 verbose("%s: INFO: Reading loading the lists file: '%s'", ARGV0, *listfiles);
356 if(Lists_OP_LoadList(*listfiles) < 0)
357 ErrorExit(LISTS_ERROR, ARGV0, *listfiles);
366 /* Creating the rules list */
367 Rules_OP_CreateRules();
369 /* Reading the rules */
372 rulesfiles = Config.includes;
373 while(rulesfiles && *rulesfiles)
376 verbose("%s: INFO: Reading rules file: '%s'", ARGV0, *rulesfiles);
377 if(Rules_OP_ReadRules(*rulesfiles) < 0)
378 ErrorExit(RULES_ERROR, ARGV0, *rulesfiles);
384 free(Config.includes);
385 Config.includes = NULL;
388 /* Find all rules with that require list lookups and attache the
389 * the correct list struct to the rule. This keeps rules from having to
390 * search thought the list of lists for the correct file during rule evaluation.
397 /* Fixing the levels/accuracy */
400 RuleNode *tmp_node = OS_GetFirstRule();
402 total_rules = _setlevels(tmp_node, 0);
404 verbose("%s: INFO: Total rules enabled: '%d'", ARGV0, total_rules);
409 /* Creating a rules hash (for reading alerts from other servers). */
411 RuleNode *tmp_node = OS_GetFirstRule();
412 Config.g_rules_hash = OSHash_Create();
413 if(!Config.g_rules_hash)
415 ErrorExit(MEM_ERROR, ARGV0);
417 AddHash_Rule(tmp_node);
422 /* Ignored files on syscheck */
425 files = Config.syscheck_ignore;
426 while(files && *files)
429 verbose("%s: INFO: Ignoring file: '%s'", ARGV0, *files);
435 /* Checking if log_fw is enabled. */
436 Config.logfw = getDefine_Int("analysisd",
441 /* Success on the configuration test */
446 /* Verbose message */
447 debug1(PRIVSEP_MSG, ARGV0, dir, user);
450 /* Signal manipulation */
454 /* Setting the user */
455 if(Privsep_SetUser(uid) < 0)
456 ErrorExit(SETUID_ERROR,ARGV0,user);
459 /* Creating the PID file */
460 if(CreatePID(ARGV0, getpid()) < 0)
461 ErrorExit(PID_ERROR,ARGV0);
464 /* Setting the queue */
465 if((m_queue = StartMQ(DEFAULTQUEUE,READ)) < 0)
466 ErrorExit(QUEUE_ERROR, ARGV0, DEFAULTQUEUE, strerror(errno));
470 if(Config.white_list == NULL)
473 verbose("%s: INFO: No IP in the white list for active reponse.", ARGV0);
481 wl = Config.white_list;
484 verbose("%s: INFO: White listing IP: '%s'",ARGV0, (*wl)->ip);
487 verbose("%s: INFO: %d IPs in the white list for active response.",
492 /* Hostname White list */
493 if(Config.hostname_white_list == NULL)
496 verbose("%s: INFO: No Hostname in the white list for active reponse.",
506 wl = Config.hostname_white_list;
509 char **tmp_pts = (*wl)->patterns;
512 verbose("%s: INFO: White listing Hostname: '%s'",ARGV0,*tmp_pts);
518 verbose("%s: INFO: %d Hostname(s) in the white list for active response.",
524 /* Start up message */
525 verbose(STARTUP_MSG, ARGV0, (int)getpid());
528 /* Going to main loop */
543 * Main function. Receives the messages(events)
544 * and analyze them all.
547 void OS_ReadMSG(int m_queue)
549 void OS_ReadMSG_analysisd(int m_queue)
553 char msg[OS_MAXSTR +1];
556 RuleInfo *stats_rule;
559 /* Null to global currently pointers */
560 currently_rule = NULL;
562 /* Initiating the logs */
566 /* Initiating the integrity database */
570 /* Initializing Rootcheck */
574 /* Initializing host info */
578 /* Creating the event list */
579 OS_CreateEventList(Config.memorysize);
582 /* Initiating the FTS list */
585 ErrorExit(FTS_LIST_ERROR, ARGV0);
589 /* Starting the active response queues */
592 /* Waiting the ARQ to settle .. */
597 if(Config.ar & REMOTE_AR)
599 if((arq = StartMQ(ARQUEUE, WRITE)) < 0)
601 merror(ARQ_ERROR, ARGV0);
603 /* If LOCAL_AR is set, keep it there */
604 if(Config.ar & LOCAL_AR)
616 verbose(CONN_TO, ARGV0, ARQUEUE, "active-response");
621 /* Only for LOCAL_ONLY installs */
622 if(Config.ar & REMOTE_AR)
624 if(Config.ar & LOCAL_AR)
636 if(Config.ar & LOCAL_AR)
638 if((execdq = StartMQ(EXECQUEUE, WRITE)) < 0)
640 merror(ARQ_ERROR, ARGV0);
642 /* If REMOTE_AR is set, keep it there */
643 if(Config.ar & REMOTE_AR)
646 Config.ar|=REMOTE_AR;
655 verbose(CONN_TO, ARGV0, EXECQUEUE, "exec");
659 debug1("%s: DEBUG: Active response Init completed.", ARGV0);
662 /* Getting currently time before starting */
666 /* Starting the hourly/weekly stats */
671 /* Initializing stats rules */
672 stats_rule = zerorulemember(
679 ErrorExit(MEM_ERROR, ARGV0);
681 stats_rule->group = "stats,";
682 stats_rule->comment = "Excessive number of events (above normal).";
686 /* Doing some cleanup */
687 memset(msg, '\0', OS_MAXSTR +1);
690 /* Initializing the logs */
692 lf = (Eventinfo *)calloc(1,sizeof(Eventinfo));
694 ErrorExit(MEM_ERROR, ARGV0);
695 lf->year = prev_year;
696 strncpy(lf->mon, prev_month, 3);
699 if(OS_GetLogLocation(lf) < 0)
701 ErrorExit("%s: Error allocating log files", ARGV0);
708 debug1("%s: DEBUG: Startup completed. Waiting for new messages..",ARGV0);
714 lf = (Eventinfo *)calloc(1,sizeof(Eventinfo));
716 /* This shouldn't happen .. */
719 ErrorExit(MEM_ERROR,ARGV0);
722 DEBUG_MSG("%s: DEBUG: Waiting for msgs - %d ", ARGV0, (int)time(0));
725 /* Receive message from queue */
726 if((i = OS_RecvUnix(m_queue, OS_MAXSTR, msg)))
728 RuleNode *rulenode_pt;
730 /* Getting the time we received the event */
734 /* Default values for the log info */
738 /* Checking for a valid message. */
741 merror(IMSG_ERROR, ARGV0, msg);
747 /* Message before extracting header */
748 DEBUG_MSG("%s: DEBUG: Received msg: %s ", ARGV0, msg);
751 /* Clean the msg appropriately */
752 if(OS_CleanMSG(msg, lf) < 0)
754 merror(IMSG_ERROR,ARGV0, msg);
761 DEBUG_MSG("%s: DEBUG: Msg cleanup: %s ", ARGV0, lf->log);
764 /* Currently rule must be null in here */
765 currently_rule = NULL;
768 /** Checking the date/hour changes **/
770 /* Update the hour */
771 if(thishour != __crt_hour)
773 /* Search all the rules and print the number
774 * of alerts that each one fired.
777 thishour = __crt_hour;
779 /* Check if the date has changed */
784 /* Update the hourly stats (done daily) */
788 if(OS_GetLogLocation(lf) < 0)
790 ErrorExit("%s: Error allocating log files", ARGV0);
794 strncpy(prev_month, lf->mon, 3);
795 prev_year = lf->year;
800 /* Incrementing number of events received */
804 /*** Running decoders ***/
806 /* Integrity check from syscheck */
807 if(msg[0] == SYSCHECK_MQ)
811 if(!DecodeSyscheck(lf))
813 /* We don't process syscheck events further */
817 /* Getting log size */
818 lf->size = strlen(lf->log);
821 /* Rootcheck decoding */
822 else if(msg[0] == ROOTCHECK_MQ)
824 if(!DecodeRootcheck(lf))
826 /* We don't process rootcheck events further */
829 lf->size = strlen(lf->log);
832 /* Host information special decoder */
833 else if(msg[0] == HOSTINFO_MQ)
835 if(!DecodeHostinfo(lf))
837 /* We don't process hostinfo events further */
840 lf->size = strlen(lf->log);
843 /* Run the general Decoders */
846 /* Getting log size */
847 lf->size = strlen(lf->log);
854 if(lf->decoder_info->type == FIREWALL)
856 /* If we could not get any information from
857 * the log, just ignore it
870 /* We only check if the last message is
871 * duplicated on syslog.
873 else if(lf->decoder_info->type == SYSLOG)
875 /* Checking if the message is duplicated */
876 if(LastMsg_Stats(lf->full_log) == 1)
879 LastMsg_Change(lf->full_log);
886 if(Check_Hour(lf) == 1)
888 void *saved_rule = lf->generated_rule;
891 /* Saving previous log */
892 saved_log = lf->full_log;
894 lf->generated_rule = stats_rule;
895 lf->full_log = __stats_comment;
898 /* alert for statistical analysis */
899 if(stats_rule->alert_opts & DO_LOGALERT)
901 __crt_ftell = ftell(_aflog);
906 /* Set lf to the old values */
907 lf->generated_rule = saved_rule;
908 lf->full_log = saved_log;
913 /* Checking the rules */
914 DEBUG_MSG("%s: DEBUG: Checking the rules - %d ",
915 ARGV0, lf->decoder_info->type);
918 /* Looping all the rules */
919 rulenode_pt = OS_GetFirstRule();
922 ErrorExit("%s: Rules in an inconsistent state. Exiting.",
929 if(lf->decoder_info->type == OSSEC_ALERT)
931 if(!lf->generated_rule)
936 /* We go ahead in here and process the alert. */
937 currently_rule = lf->generated_rule;
940 /* The categories must match */
941 else if(rulenode_pt->ruleinfo->category !=
942 lf->decoder_info->type)
947 /* Checking each rule. */
948 else if((currently_rule = OS_CheckIfRuleMatch(lf, rulenode_pt))
956 if(currently_rule->level == 0)
962 /* Checking ignore time */
963 if(currently_rule->ignore_time)
965 if(currently_rule->time_ignored == 0)
967 currently_rule->time_ignored = lf->time;
969 /* If the currently time - the time the rule was ignored
970 * is less than the time it should be ignored,
971 * leave (do not alert again).
973 else if((lf->time - currently_rule->time_ignored)
974 < currently_rule->ignore_time)
980 currently_rule->time_ignored = lf->time;
985 /* Pointer to the rule that generated it */
986 lf->generated_rule = currently_rule;
989 /* Checking if we should ignore it */
990 if(currently_rule->ckignore && IGnore(lf))
993 lf->generated_rule = NULL;
998 /* Checking if we need to add to ignore list */
999 if(currently_rule->ignore)
1005 /* Log the alert if configured to ... */
1006 if(currently_rule->alert_opts & DO_LOGALERT)
1008 __crt_ftell = ftell(_aflog);
1013 /* Log to prelude */
1017 if(Config.prelude_log_level <= currently_rule->level)
1032 /* Execute an active response */
1033 if(currently_rule->ar)
1036 active_response **rule_ar;
1038 rule_ar = currently_rule->ar;
1043 if((*rule_ar)->ar_cmd->expect & USERNAME)
1046 !OS_PRegex(lf->dstuser,"^[a-zA-Z._0-9@?-]*$"))
1049 merror(CRAFTED_USER, ARGV0, lf->dstuser);
1053 if((*rule_ar)->ar_cmd->expect & SRCIP)
1056 !OS_PRegex(lf->srcip, "^[a-zA-Z.:_0-9-]*$"))
1059 merror(CRAFTED_IP, ARGV0, lf->srcip);
1066 OS_Exec(&execdq, &arq, lf, *rule_ar);
1073 /* Copy the structure to the state memory of if_matched_sid */
1074 if(currently_rule->sid_prev_matched)
1076 if(!OSList_AddData(currently_rule->sid_prev_matched, lf))
1078 merror("%s: Unable to add data to sig list.", ARGV0);
1082 lf->sid_node_to_delete =
1083 currently_rule->sid_prev_matched->last_node;
1087 else if(currently_rule->group_prev_matched)
1091 while(i < currently_rule->group_prev_matched_sz)
1094 currently_rule->group_prev_matched[i],
1097 merror("%s: Unable to add data to grp list.",ARGV0);
1107 }while((rulenode_pt = rulenode_pt->next) != NULL);
1110 /* If configured to log all, do it */
1115 /* Cleaning the memory */
1119 /* Only clear the memory if the eventinfo was not
1120 * added to the stateful memory
1121 * -- message is free inside clean event --
1123 if(lf->generated_rule == NULL)
1136 /* CheckIfRuleMatch v0.1
1137 * Will check if the currently_rule matches the event information
1139 RuleInfo *OS_CheckIfRuleMatch(Eventinfo *lf, RuleNode *curr_node)
1144 * word match (fast regex),
1159 RuleInfo *currently_rule = curr_node->ruleinfo;
1165 merror("%s: Inconsistent state. currently rule NULL", ARGV0);
1171 if(full_output && !alert_only)
1172 print_out(" Trying rule: %d - %s", currently_rule->sigid,
1173 currently_rule->comment);
1177 /* Checking if any decoder pre-matched here */
1178 if(currently_rule->decoded_as &&
1179 currently_rule->decoded_as != lf->decoder_info->id)
1185 /* Checking program name */
1186 if(currently_rule->program_name)
1188 if(!lf->program_name)
1191 if(!OSMatch_Execute(lf->program_name,
1193 currently_rule->program_name))
1198 /* Checking for the id */
1199 if(currently_rule->id)
1206 if(!OSMatch_Execute(lf->id,
1208 currently_rule->id))
1216 /* Checking if any word to match exists */
1217 if(currently_rule->match)
1219 if(!OSMatch_Execute(lf->log, lf->size, currently_rule->match))
1225 /* Checking if exist any regex for this rule */
1226 if(currently_rule->regex)
1228 if(!OSRegex_Execute(lf->log, currently_rule->regex))
1233 /* Checking for actions */
1234 if(currently_rule->action)
1239 if(strcmp(currently_rule->action,lf->action) != 0)
1244 /* Checking for the url */
1245 if(currently_rule->url)
1252 if(!OSMatch_Execute(lf->url, strlen(lf->url), currently_rule->url))
1263 /* Getting tcp/ip packet information */
1264 if(currently_rule->alert_opts & DO_PACKETINFO)
1266 /* Checking for the srcip */
1267 if(currently_rule->srcip)
1274 if(!OS_IPFoundList(lf->srcip, currently_rule->srcip))
1283 /* Checking for the dstip */
1284 if(currently_rule->dstip)
1291 if(!OS_IPFoundList(lf->dstip, currently_rule->dstip))
1300 if(currently_rule->srcport)
1307 if(!OSMatch_Execute(lf->srcport,
1308 strlen(lf->srcport),
1309 currently_rule->srcport))
1317 if(currently_rule->dstport)
1324 if(!OSMatch_Execute(lf->dstport,
1325 strlen(lf->dstport),
1326 currently_rule->dstport))
1334 } /* END PACKET_INFO */
1337 /* Extra information from event */
1338 if(currently_rule->alert_opts & DO_EXTRAINFO)
1340 /* Checking compiled rule. */
1341 if(currently_rule->compiled_rule)
1343 if(!currently_rule->compiled_rule(lf))
1350 /* Checking if exist any user to match */
1351 if(currently_rule->user)
1355 if(!OSMatch_Execute(lf->dstuser,
1356 strlen(lf->dstuser),
1357 currently_rule->user))
1360 else if(lf->srcuser)
1362 if(!OSMatch_Execute(lf->srcuser,
1363 strlen(lf->srcuser),
1364 currently_rule->user))
1378 /* Checking if any rule related to the size exist */
1379 if(currently_rule->maxsize)
1381 if(lf->size < currently_rule->maxsize)
1386 /* Checking if we are in the right time */
1387 if(currently_rule->day_time)
1389 if(!OS_IsonTime(lf->hour, currently_rule->day_time))
1396 /* Checking week day */
1397 if(currently_rule->week_day)
1399 if(!OS_IsonDay(__crt_wday, currently_rule->week_day))
1406 /* Getting extra data */
1407 if(currently_rule->extra_data)
1412 if(!OSMatch_Execute(lf->data,
1414 currently_rule->extra_data))
1419 /* Checking hostname */
1420 if(currently_rule->hostname)
1425 if(!OSMatch_Execute(lf->hostname,
1426 strlen(lf->hostname),
1427 currently_rule->hostname))
1432 /* Checking for status */
1433 if(currently_rule->status)
1438 if(!OSMatch_Execute(lf->status,
1440 currently_rule->status))
1445 /* Do diff check. */
1446 if(currently_rule->context_opts & SAME_DODIFF)
1448 if(!doDiff(currently_rule, lf))
1455 /* Checking for the FTS flag */
1456 if(currently_rule->alert_opts & DO_FTS)
1459 if(lf->decoder_info->fts)
1461 if(lf->decoder_info->fts & FTS_DONE)
1463 /* We already did the fts in here. */
1477 if(currently_rule->lists != NULL)
1479 ListRule *list_holder=currently_rule->lists;
1482 switch(list_holder->field)
1487 if(!OS_DBSearch(list_holder,lf->srcip))
1493 if(!OS_DBSearch(list_holder,lf->srcport))
1499 if(!OS_DBSearch(list_holder,lf->dstip))
1505 if(!OS_DBSearch(list_holder,lf->dstport))
1511 if(!OS_DBSearch(list_holder,lf->srcuser))
1514 else if(lf->dstuser)
1516 if(!OS_DBSearch(list_holder,lf->dstuser))
1527 if(!OS_DBSearch(list_holder,lf->url))
1533 if(!OS_DBSearch(list_holder,lf->id))
1539 if(!OS_DBSearch(list_holder,lf->hostname))
1542 case RULE_PROGRAM_NAME:
1543 if(!lf->program_name)
1545 if(!OS_DBSearch(list_holder,lf->program_name))
1551 if(!OS_DBSearch(list_holder,lf->status))
1557 if(!OS_DBSearch(list_holder,lf->action))
1564 list_holder = list_holder->next;
1569 /* If it is a context rule, search for it */
1570 if(currently_rule->context == 1)
1572 if(!currently_rule->event_search(lf, currently_rule))
1577 if(full_output && !alert_only)
1578 print_out(" *Rule %d matched.", currently_rule->sigid);
1582 /* Search for dependent rules */
1583 if(curr_node->child)
1585 RuleNode *child_node = curr_node->child;
1586 RuleInfo *child_rule = NULL;
1589 if(full_output && !alert_only)
1590 print_out(" *Trying child rules.");
1595 child_rule = OS_CheckIfRuleMatch(lf, child_node);
1596 if(child_rule != NULL)
1601 child_node = child_node->next;
1606 /* If we are set to no alert, keep going */
1607 if(currently_rule->alert_opts & NO_ALERT)
1614 currently_rule->firedtimes++;
1616 return(currently_rule); /* Matched */
1620 /** void LoopRule(RuleNode *curr_node);
1621 * Update each rule and print it to the logs.
1623 void LoopRule(RuleNode *curr_node, FILE *flog)
1625 if(curr_node->ruleinfo->firedtimes)
1627 fprintf(flog, "%d-%d-%d-%d\n",
1629 curr_node->ruleinfo->sigid,
1630 curr_node->ruleinfo->level,
1631 curr_node->ruleinfo->firedtimes);
1632 curr_node->ruleinfo->firedtimes = 0;
1635 if(curr_node->child)
1637 RuleNode *child_node = curr_node->child;
1641 LoopRule(child_node, flog);
1642 child_node = child_node->next;
1649 /** void DumpLogstats();
1650 * Dump the hourly stats about each rule.
1654 RuleNode *rulenode_pt;
1655 char logfile[OS_FLSIZE +1];
1658 /* Opening log file */
1659 snprintf(logfile, OS_FLSIZE, "%s/%d/", STATSAVED, prev_year);
1660 if(IsDir(logfile) == -1)
1661 if(mkdir(logfile,0770) == -1)
1663 merror(MKDIR_ERROR, ARGV0, logfile);
1667 snprintf(logfile,OS_FLSIZE,"%s/%d/%s", STATSAVED, prev_year,prev_month);
1669 if(IsDir(logfile) == -1)
1670 if(mkdir(logfile,0770) == -1)
1672 merror(MKDIR_ERROR,ARGV0,logfile);
1677 /* Creating the logfile name */
1678 snprintf(logfile,OS_FLSIZE,"%s/%d/%s/ossec-%s-%02d.log",
1685 flog = fopen(logfile, "a");
1688 merror(FOPEN_ERROR, ARGV0, logfile);
1692 rulenode_pt = OS_GetFirstRule();
1696 ErrorExit("%s: Rules in an inconsistent state. Exiting.",
1700 /* Looping on all the rules and printing the stats from them */
1703 LoopRule(rulenode_pt, flog);
1704 }while((rulenode_pt = rulenode_pt->next) != NULL);
1707 /* Print total for the hour */
1708 fprintf(flog, "%d--%d--%d--%d--%d\n\n",
1710 hourly_alerts, hourly_events, hourly_syscheck,hourly_firewall);
1713 hourly_syscheck = 0;
1714 hourly_firewall = 0;