1 /* Copyright (C) 2009 Trend Micro Inc.
4 * This program is a free software; you can redistribute it
5 * and/or modify it under the terms of the GNU General Public
6 * License (version 2) as published by the FSF - Free Software
11 #include "analysisd.h"
14 #include "error_messages/error_messages.h"
15 #include "headers/file_op.h"
16 #include "alerts/alerts.h"
17 #include "headers/debug_op.h"
19 /* Global definition */
20 char __stats_comment[192];
22 static const char *(weekdays[]) = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
26 static const char *(l_month[]) = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug",
27 "Sep", "Oct", "Nov", "Dec"
30 /* Global variables */
32 /* Hour 25 is internally used */
33 static int _RWHour[7][25];
34 static int _CWHour[7][25];
36 static int _RHour[25];
37 static int _CHour[25];
39 static int _cignorehour = 0;
40 static int _fired = 0;
41 static int _daily_errors = 0;
42 static int maxdiff = 0;
43 static int mindiff = 0;
44 static int percent_diff = 20;
46 /* Last msgs, to avoid floods */
47 static char *_lastmsg;
48 static char *_prevlast;
49 static char *_pprevlast;
52 static void print_totals(void)
55 char logfile[OS_FLSIZE + 1];
58 /* Create the path for the logs */
59 snprintf(logfile, OS_FLSIZE, "%s/%d/", STATSAVED, prev_year);
60 if (IsDir(logfile) == -1)
61 if (mkdir(logfile, 0770) == -1) {
62 merror(MKDIR_ERROR, ARGV0, logfile, errno, strerror(errno));
66 snprintf(logfile, OS_FLSIZE, "%s/%d/%s", STATSAVED, prev_year, prev_month);
68 if (IsDir(logfile) == -1)
69 if (mkdir(logfile, 0770) == -1) {
70 merror(MKDIR_ERROR, ARGV0, logfile, errno, strerror(errno));
74 /* Create the logfile name */
75 snprintf(logfile, OS_FLSIZE, "%s/%d/%s/ossec-%s-%02d.log",
82 flog = fopen(logfile, "a");
84 merror(FOPEN_ERROR, ARGV0, logfile, errno, strerror(errno));
88 /* Print the hourly stats */
89 for (i = 0; i <= 23; i++) {
90 fprintf(flog, "Hour totals - %d:%d\n", i, _CHour[i]);
93 fprintf(flog, "Total events for day:%d\n", totals);
98 /* Return the parameter (event_number + 20 % of it)
99 * If event_number < mindiff, return mindiff
100 * If event_number > maxdiff, return maxdiff
102 static int gethour(int event_number)
106 event_diff = (event_number * percent_diff) / 100;
109 if (event_diff < mindiff) {
110 return (event_number + mindiff);
111 } else if (event_diff > maxdiff) {
112 return (event_number + maxdiff);
115 return (event_number + event_diff);
118 /* Update_Hour: done daily */
124 /* Print total number of logs received per hour */
134 for (i = 0; i <= 24; i++) {
135 char _hourly[128]; /* _hourly file */
140 /* If saved hourly = 0, just copy the current hourly rate */
141 if (_CHour[i] == 0) {
145 if (_RHour[i] == 0) {
146 _RHour[i] = _CHour[i] + 20;
150 /* If we had too many errors this day */
151 if (_daily_errors >= 3) {
152 _RHour[i] = (((3 * _CHour[i]) + (inter * _RHour[i])) / (inter + 3)) + 25;
156 /* The average is going to be the number of interactions +
157 * the current hourly rate, divided by 4 */
158 _RHour[i] = ((_CHour[i] + (inter * _RHour[i])) / (inter + 1)) + 5;
163 snprintf(_hourly, 128, "%s/%d", STATQUEUE, i);
164 fp = fopen(_hourly, "w");
166 fprintf(fp, "%d", _RHour[i]);
171 merror(FOPEN_ERROR, "logstats", _hourly, errno, strerror(errno));
174 _CHour[i] = 0; /* Zero the current hour */
178 for (i = 0; i <= 6; i++) {
183 inter = _CWHour[i][24];
188 for (j = 0; j <= 24; j++) {
190 if (_CWHour[i][j] == 0) {
194 if (_RWHour[i][j] == 0) {
195 _RWHour[i][j] = _CWHour[i][j] + 20;
199 if (_daily_errors >= 3) {
200 _RWHour[i][j] = (((3 * _CWHour[i][j]) + (inter * _RWHour[i][j])) / (inter + 3)) + 25;
202 _RWHour[i][j] = ((_CWHour[i][j] + (inter * _RWHour[i][j])) / (inter + 1)) + 5;
207 snprintf(_weekly, 128, "%s/%d/%d", STATWQUEUE, i, j);
208 fp = fopen(_weekly, "w");
210 fprintf(fp, "%d", _RWHour[i][j]);
213 merror(FOPEN_ERROR, "logstats", _weekly, errno, strerror(errno));
224 /* Check Hourly stats */
227 _CHour[__crt_hour]++;
228 _CWHour[__crt_wday][__crt_hour]++;
230 if (_RHour[24] <= 2) {
234 /* Checking if any message was already fired for this hour */
235 if ((_daily_errors >= 3) || ((_fired == 1) && (_cignorehour == __crt_hour))) {
239 else if (_cignorehour != __crt_hour) {
240 _cignorehour = __crt_hour;
244 /* Check if passed the threshold */
245 if (_RHour[__crt_hour] != 0) {
246 if (_CHour[__crt_hour] > (_RHour[__crt_hour])) {
247 if (_CHour[__crt_hour] > (gethour(_RHour[__crt_hour]))) {
248 /* snprintf will null terminate */
249 snprintf(__stats_comment, 191,
250 "The average number of logs"
251 " between %d:00 and %d:00 is %d. We "
252 "reached %d.", __crt_hour, __crt_hour + 1,
253 _RHour[__crt_hour], _CHour[__crt_hour]);
263 /* We need to have at least 3 days of stats */
264 if (_RWHour[__crt_wday][24] <= 2) {
268 /* Check for the hour during a specific day of the week */
269 if (_RWHour[__crt_wday][__crt_hour] != 0) {
270 if (_CWHour[__crt_wday][__crt_hour] > _RWHour[__crt_wday][__crt_hour]) {
271 if (_CWHour[__crt_wday][__crt_hour] >
272 gethour(_RWHour[__crt_wday][__crt_hour])) {
273 snprintf(__stats_comment, 191,
274 "The average number of logs"
275 " between %d:00 and %d:00 on %s is %d. We"
276 " reached %d.", __crt_hour, __crt_hour + 1,
277 weekdays[__crt_wday],
278 _RWHour[__crt_wday][__crt_hour],
279 _CWHour[__crt_wday][__crt_hour]);
291 /* Start hourly stats and other necessary variables */
298 p = localtime(&c_time);
300 /* Other global variables */
305 thishour = p->tm_hour;
306 prev_year = p->tm_year + 1900;
307 strncpy(prev_month, l_month[p->tm_mon], 3);
308 prev_month[3] = '\0';
310 /* Clear some memory */
311 memset(__stats_comment, '\0', 192);
313 /* Get maximum/minimum diffs */
314 maxdiff = getDefine_Int("analysisd",
318 mindiff = getDefine_Int("analysisd",
322 percent_diff = getDefine_Int("analysisd",
323 "stats_percent_diff",
326 /* Last three messages
327 * They are used to keep track of the last
328 * messages received to avoid floods
334 /* They should not be null */
335 os_strdup(" ", _lastmsg);
336 os_strdup(" ", _prevlast);
337 os_strdup(" ", _pprevlast);
339 /* Create the stat queue directories */
340 if (IsDir(STATWQUEUE) == -1) {
341 if (mkdir(STATWQUEUE, 0770) == -1) {
342 merror("%s: logstat: Unable to create stat queue: %s",
348 if (IsDir(STATQUEUE) == -1) {
349 if (mkdir(STATQUEUE, 0770) == -1) {
350 merror("%s: logstat: Unable to create stat queue: %s",
356 /* Create store dir */
357 if (IsDir(STATSAVED) == -1) {
358 if (mkdir(STATSAVED, 0770) == -1) {
359 merror("%s: logstat: Unable to create stat directory: %s",
365 /* Create hourly directory (24 hour is the stats) */
366 for (i = 0; i <= 24; i++) {
368 snprintf(_hourly, 128, "%s/%d", STATQUEUE, i);
371 if (File_DateofChange(_hourly) < 0) {
377 fp = fopen(_hourly, "r");
381 if (fscanf(fp, "%d", &_RHour[i]) <= 0) {
393 /* Create weekly/hourly directories */
394 for (i = 0; i <= 6; i++) {
396 snprintf(_weekly, 128, "%s/%d", STATWQUEUE, i);
397 if (IsDir(_weekly) == -1)
398 if (mkdir(_weekly, 0770) == -1) {
399 merror("%s: logstat: Unable to create stat queue: %s",
404 for (j = 0; j <= 24; j++) {
406 snprintf(_weekly, 128, "%s/%d/%d", STATWQUEUE, i, j);
407 if (File_DateofChange(_weekly) < 0) {
411 fp = fopen(_weekly, "r");
415 if (fscanf(fp, "%d", &_RWHour[i][j]) <= 0) {
419 if (_RWHour[i][j] < 0) {
430 /* Check if the message received is repeated to avoid
431 * floods of the same message
433 int LastMsg_Stats(const char *log)
435 if (strcmp(log, _lastmsg) == 0) {
439 else if (strcmp(log, _prevlast) == 0) {
443 else if (strcmp(log, _pprevlast) == 0) {
450 /* If the message is not repeated, rearrange the last
453 void LastMsg_Change(const char *log)
455 /* Remove the last one */
458 /* Move the second to third and the last to second */
459 _pprevlast = _prevlast;
460 _prevlast = _lastmsg;
462 os_strdup(log, _lastmsg);