suricata
util-debug.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2021 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * \author Anoop Saldanha <anoopsaldanha@gmail.com>
22  *
23  * Debug utility functions
24  */
25 
26 #include "suricata-common.h"
27 #include "util-debug.h"
28 
29 #include "output.h"
30 
31 #include "suricata.h"
32 
33 #include "util-conf.h"
34 #include "util-enum.h"
35 #include "util-path.h"
36 #include "util-syslog.h"
37 #include "util-time.h"
38 
39 // clang-format off
40 /* holds the string-enum mapping for the enums held in the table SCLogLevel */
42  { "Not set", SC_LOG_NOTSET },
43  { "None", SC_LOG_NONE },
44  { "Error", SC_LOG_ERROR },
45  { "Warning", SC_LOG_WARNING },
46  { "Notice", SC_LOG_NOTICE },
47  { "Info", SC_LOG_INFO },
48  { "Perf", SC_LOG_PERF },
49  { "Config", SC_LOG_CONFIG },
50  { "Debug", SC_LOG_DEBUG },
51  { NULL, -1 }
52 };
53 
55  { "Not set", SC_LOG_NOTSET },
56  { "None", SC_LOG_NONE },
57  { "E", SC_LOG_ERROR },
58  { "W", SC_LOG_WARNING },
59  { "i", SC_LOG_NOTICE },
60  { "i", SC_LOG_INFO },
61  { "i", SC_LOG_PERF },
62  { "i", SC_LOG_CONFIG },
63  { "d", SC_LOG_DEBUG },
64  { NULL, -1 }
65 };
66 
67 /* holds the string-enum mapping for the enums held in the table SCLogOPIface */
69  { "Console", SC_LOG_OP_IFACE_CONSOLE },
70  { "File", SC_LOG_OP_IFACE_FILE },
71  { "Syslog", SC_LOG_OP_IFACE_SYSLOG },
72  { NULL, -1 }
73 };
74 // clang-format on
75 
76 #if defined (OS_WIN32)
77 /**
78  * \brief Used for synchronous output on WIN32
79  */
80 static SCMutex sc_log_stream_lock;
81 #endif /* OS_WIN32 */
82 
83 /**
84  * \brief Transform the module name into display module name for logging
85  */
86 static const char *SCTransformModule(const char *module_name, int *dn_len);
87 
88 /**
89  * \brief Holds the config state for the logging module
90  */
91 static SCLogConfig *sc_log_config = NULL;
92 
93 /**
94  * \brief Returns the full path given a file and configured log dir
95  */
96 static char *SCLogGetLogFilename(const char *);
97 
98 /**
99  * \brief Holds the global log level. Is the same as sc_log_config->log_level
100  */
102 
103 /**
104  * \brief Used to indicate whether the logging module has been init or not
105  */
107 
108 /**
109  * \brief Used to indicate whether the logging module has been cleaned or not
110  */
112 
113 /**
114  * \brief Maps the SC logging level to the syslog logging level
115  *
116  * \param The SC logging level that has to be mapped to the syslog_log_level
117  *
118  * \retval syslog_log_level The mapped syslog_api_log_level, for the logging
119  * module api's internal log_level
120  */
121 static inline int SCLogMapLogLevelToSyslogLevel(int log_level)
122 {
123  int syslog_log_level = 0;
124 
125  switch (log_level) {
126  case SC_LOG_ERROR:
127  syslog_log_level = LOG_ERR;
128  break;
129  case SC_LOG_WARNING:
130  syslog_log_level = LOG_WARNING;
131  break;
132  case SC_LOG_NOTICE:
133  syslog_log_level = LOG_NOTICE;
134  break;
135  case SC_LOG_INFO:
136  syslog_log_level = LOG_INFO;
137  break;
138  case SC_LOG_CONFIG:
139  case SC_LOG_DEBUG:
140  case SC_LOG_PERF:
141  syslog_log_level = LOG_DEBUG;
142  break;
143  default:
144  syslog_log_level = LOG_EMERG;
145  break;
146  }
147 
148  return syslog_log_level;
149 }
150 
151 /**
152  * \brief Output function that logs a character string out to a file descriptor
153  *
154  * \param fd Pointer to the file descriptor
155  * \param msg Pointer to the character string that should be logged
156  */
157 static inline void SCLogPrintToStream(FILE *fd, char *msg)
158 {
159  /* Would only happen if the log file failed to re-open during rotation. */
160  if (fd == NULL) {
161  return;
162  }
163 
164 #if defined (OS_WIN32)
165  SCMutexLock(&sc_log_stream_lock);
166 #endif /* OS_WIN32 */
167 
168  if (fprintf(fd, "%s\n", msg) < 0)
169  printf("Error writing to stream using fprintf\n");
170 
171  fflush(fd);
172 
173 #if defined (OS_WIN32)
174  SCMutexUnlock(&sc_log_stream_lock);
175 #endif /* OS_WIN32 */
176 
177  return;
178 }
179 
180 /**
181  * \brief Output function that logs a character string through the syslog iface
182  *
183  * \param syslog_log_level Holds the syslog_log_level that the message should be
184  * logged as
185  * \param msg Pointer to the char string, that should be logged
186  *
187  * \todo syslog is thread-safe according to POSIX manual and glibc code, but we
188  * we will have to look into non POSIX compliant boxes like freeBSD
189  */
190 static inline void SCLogPrintToSyslog(int syslog_log_level, const char *msg)
191 {
192  //static struct syslog_data data = SYSLOG_DATA_INIT;
193  //syslog_r(syslog_log_level, NULL, "%s", msg);
194 
195  syslog(syslog_log_level, "%s", msg);
196 
197  return;
198 }
199 
200 /**
201  */
202 static int SCLogMessageJSON(SCTime_t tval, char *buffer, size_t buffer_size, SCLogLevel log_level,
203  const char *file, unsigned line, const char *function, const char *module,
204  const char *message)
205 {
206  JsonBuilder *js = jb_new_object();
207  if (unlikely(js == NULL))
208  goto error;
209 
210  char timebuf[64];
211  CreateIsoTimeString(tval, timebuf, sizeof(timebuf));
212  jb_set_string(js, "timestamp", timebuf);
213 
214  const char *s = SCMapEnumValueToName(log_level, sc_log_level_map);
215  if (s != NULL) {
216  jb_set_string(js, "log_level", s);
217  } else {
218  JB_SET_STRING(js, "log_level", "INVALID");
219  }
220 
221  JB_SET_STRING(js, "event_type", "engine");
222  jb_open_object(js, "engine");
223 
224  if (message)
225  jb_set_string(js, "message", message);
226 
227  if (t_thread_name[0] != '\0') {
228  jb_set_string(js, "thread_name", t_thread_name);
229  }
230 
231  if (module) {
232  /* Determine how much of module name to display */
233  int dn_len = 0;
234  const char *dn_name;
235  dn_name = SCTransformModule(module, &dn_len);
236  jb_set_string(js, "module", dn_name);
237  }
238 
239  if (log_level >= SC_LOG_DEBUG) {
240  if (function)
241  jb_set_string(js, "function", function);
242 
243  if (file)
244  jb_set_string(js, "file", file);
245 
246  if (line > 0)
247  jb_set_uint(js, "line", line);
248  }
249  jb_close(js); // engine
250 
251  jb_close(js);
252  memcpy(buffer, jb_ptr(js), MIN(buffer_size, jb_len(js)));
253 
254  jb_free(js);
255 
256  return 0;
257 
258 error:
259  return -1;
260 }
261 
262 static const int transform_max_segs = 2; /* The maximum segment count to display */
263 /*
264  * \brief Return a display name for the given module name for logging.
265  *
266  * The transformation is dependent upon the source code module names
267  * that use the dash character to separate incremental refinements of
268  * the subsystem.
269  *
270  * The transformation uses the local constant "transform_max_segs" to determine
271  * how many segments to display; the transformed name will never consist
272  * of more than this many segments.
273  *
274  * E.g., "detect-http-content-len" ==> "detect-http" when the max is 2
275  *
276  * \param module_name The source code module name to be transformed.
277  * \param dn_len The number of characters in the display name to print.
278  *
279  * \retval Pointer to the display name
280  */
281 static const char *SCTransformModule(const char *module_name, int *dn_len)
282 {
283  /*
284  * special case for source code module names beginning with:
285  * Prefixes skipped
286  * tm-*
287  * util-*
288  * source-*
289  * No transformation
290  * app-layer-*
291  */
292  if (strncmp("tm-", module_name, 3) == 0) {
293  *dn_len = strlen(module_name) - 3;
294  return module_name + 3;
295  } else if (strncmp("util-", module_name, 5) == 0) {
296  *dn_len = strlen(module_name) - 5;
297  return module_name + 5;
298  } else if (strncmp("source-pcap-file", module_name, 16) == 0) {
299  *dn_len = strlen("pcap");
300  return "pcap";
301  } else if (strncmp("source-", module_name, 7) == 0) {
302  *dn_len = strlen(module_name) - 7;
303  return module_name + 7;
304  } else if (strncmp("runmode-", module_name, 8) == 0) {
305  *dn_len = strlen(module_name) - 8;
306  return module_name + 8;
307  } else if (strncmp("app-layer-", module_name, 10) == 0) {
308  *dn_len = strlen(module_name);
309  return module_name;
310  } else if (strncmp("detect-engine", module_name, 13) == 0) {
311  *dn_len = strlen("detect");
312  return "detect";
313  }
314 
315  int seg_cnt = 0;
316 
317  char *last;
318  char *w = (char *)module_name;
319  while (w && (w = strchr(w, '-')) != NULL && seg_cnt < transform_max_segs) {
320  seg_cnt++;
321  last = w;
322  w++; /* skip past '-' */
323  }
324 
325  if (seg_cnt < transform_max_segs)
326  *dn_len = strlen(module_name);
327  else
328  *dn_len = last - module_name;
329 
330  return module_name;
331 }
332 
333 /**
334  * \brief Adds the global log_format to the outgoing buffer
335  *
336  * \param log_level log_level of the message that has to be logged
337  * \param msg Buffer containing the outgoing message
338  * \param file File_name from where the message originated
339  * \param function Function_name from where the message originated
340  * \param line Line_no from where the messaged originated
341  *
342  * \retval 0 on success; else a negative value on error
343  */
344 static SCError SCLogMessageGetBuffer(SCTime_t tval, bool color, SCLogOPType type, char *buffer,
345  size_t buffer_size, const char *log_format, const SCLogLevel log_level, const char *file,
346  const unsigned int line, const char *function, const char *module, const char *message)
347 {
348  if (type == SC_LOG_OP_TYPE_JSON)
349  return SCLogMessageJSON(
350  tval, buffer, buffer_size, log_level, file, line, function, module, message);
351 
352  char *temp = buffer;
353  const char *s = NULL;
354  struct tm *tms = NULL;
355 
356  const char *redb = "";
357  const char *red = "";
358  const char *yellowb = "";
359  const char *yellow = "";
360  const char *green = "";
361  const char *blue = "";
362  const char *reset = "";
363  if (color) {
364  redb = "\x1b[1;31m";
365  red = "\x1b[31m";
366  yellowb = "\x1b[1;33m";
367  yellow = "\x1b[33m";
368  green = "\x1b[32m";
369  blue = "\x1b[34m";
370  reset = "\x1b[0m";
371  }
372  /* no of characters_written(cw) by snprintf */
373  int cw = 0;
374 
376 
377  /* make a copy of the format string as it will be modified below */
378  const int add_M = strstr(log_format, "%M") == NULL;
379  char local_format[strlen(log_format) + add_M * 2 + 1];
380  strlcpy(local_format, log_format, sizeof(local_format));
381  if (add_M)
382  strlcat(local_format, "%M", sizeof(local_format));
383  char *temp_fmt = local_format;
384  char *substr = temp_fmt;
385  struct tm local_tm;
386 
387  while ((temp_fmt = strchr(temp_fmt, SC_LOG_FMT_PREFIX))) {
388  if ((temp - buffer) > SC_LOG_MAX_LOG_MSG_LEN) {
389  return 0;
390  }
391  switch(temp_fmt[1]) {
392  case SC_LOG_FMT_TIME:
393  temp_fmt[0] = '\0';
394 
395  tms = SCLocalTime(SCTIME_SECS(tval), &local_tm);
396 
397  cw = snprintf(temp, SC_LOG_MAX_LOG_MSG_LEN - (temp - buffer),
398  "%s%s%04d-%02d-%02d %02d:%02d:%02d%s", substr, green, tms->tm_year + 1900,
399  tms->tm_mon + 1, tms->tm_mday, tms->tm_hour, tms->tm_min, tms->tm_sec,
400  reset);
401  if (cw < 0)
402  return -1;
403  temp += cw;
404  temp_fmt++;
405  substr = temp_fmt;
406  substr++;
407  break;
408 
410  temp_fmt[0] = '\0';
411 
412  tms = SCLocalTime(SCTIME_SECS(tval), &local_tm);
413 
414  cw = snprintf(temp, SC_LOG_MAX_LOG_MSG_LEN - (temp - buffer),
415  "%s%s%d/%d/%04d -- %02d:%02d:%02d%s",
416  substr, green, tms->tm_mday, tms->tm_mon + 1,
417  tms->tm_year + 1900, tms->tm_hour, tms->tm_min,
418  tms->tm_sec, reset);
419  if (cw < 0)
420  return -1;
421  temp += cw;
422  temp_fmt++;
423  substr = temp_fmt;
424  substr++;
425  break;
426 
427  case SC_LOG_FMT_PID:
428  temp_fmt[0] = '\0';
429  cw = snprintf(temp, SC_LOG_MAX_LOG_MSG_LEN - (temp - buffer),
430  "%s%s%u%s", substr, yellow, getpid(), reset);
431  if (cw < 0)
432  return -1;
433  temp += cw;
434  temp_fmt++;
435  substr = temp_fmt;
436  substr++;
437  break;
438 
439  case SC_LOG_FMT_TID:
440  temp_fmt[0] = '\0';
441  cw = snprintf(temp, SC_LOG_MAX_LOG_MSG_LEN - (temp - buffer),
442  "%s%s%lu%s", substr, yellow, SCGetThreadIdLong(), reset);
443  if (cw < 0)
444  return -1;
445  temp += cw;
446  temp_fmt++;
447  substr = temp_fmt;
448  substr++;
449  break;
450 
452  case SC_LOG_FMT_TM:
453  temp_fmt[0] = '\0';
454  cw = snprintf(temp, SC_LOG_MAX_LOG_MSG_LEN - (temp - buffer), "%s%s%s%s", substr,
455  yellow, t_thread_name, reset);
456  if (cw < 0)
457  return -1;
458  temp += cw;
459  temp_fmt++;
460  substr = temp_fmt;
461  substr++;
462  break;
463 
465  temp_fmt[0] = '\0';
466  s = SCMapEnumValueToName(log_level, sc_log_level_map);
467  if (s != NULL) {
468  if (log_level <= SC_LOG_ERROR)
469  cw = snprintf(temp, SC_LOG_MAX_LOG_MSG_LEN - (temp - buffer),
470  "%s%s%s%s", substr, redb, s, reset);
471  else if (log_level == SC_LOG_WARNING)
472  cw = snprintf(temp, SC_LOG_MAX_LOG_MSG_LEN - (temp - buffer),
473  "%s%s%s%s", substr, red, s, reset);
474  else if (log_level == SC_LOG_NOTICE)
475  cw = snprintf(temp, SC_LOG_MAX_LOG_MSG_LEN - (temp - buffer),
476  "%s%s%s%s", substr, yellowb, s, reset);
477  else
478  cw = snprintf(temp, SC_LOG_MAX_LOG_MSG_LEN - (temp - buffer), "%s%s%s%s",
479  substr, yellow, s, reset);
480  } else {
481  cw = snprintf(temp, SC_LOG_MAX_LOG_MSG_LEN - (temp - buffer), "%s%s", substr,
482  "INVALID");
483  }
484  if (cw < 0)
485  return -1;
486  temp += cw;
487  temp_fmt++;
488  substr = temp_fmt;
489  substr++;
490  break;
491 
493  temp_fmt[0] = '\0';
494  s = SCMapEnumValueToName(log_level, sc_log_slevel_map);
495  if (s != NULL) {
496  if (log_level <= SC_LOG_ERROR)
497  cw = snprintf(temp, SC_LOG_MAX_LOG_MSG_LEN - (temp - buffer), "%s%s%s%s",
498  substr, redb, s, reset);
499  else if (log_level == SC_LOG_WARNING)
500  cw = snprintf(temp, SC_LOG_MAX_LOG_MSG_LEN - (temp - buffer), "%s%s%s%s",
501  substr, red, s, reset);
502  else if (log_level == SC_LOG_NOTICE)
503  cw = snprintf(temp, SC_LOG_MAX_LOG_MSG_LEN - (temp - buffer), "%s%s%s%s",
504  substr, yellowb, s, reset);
505  else
506  cw = snprintf(temp, SC_LOG_MAX_LOG_MSG_LEN - (temp - buffer),
507  "%s%s%s%s", substr, yellow, s, reset);
508  } else {
509  cw = snprintf(temp, SC_LOG_MAX_LOG_MSG_LEN - (temp - buffer),
510  "%s%s", substr, "INVALID");
511  }
512  if (cw < 0)
513  return -1;
514  temp += cw;
515  temp_fmt++;
516  substr = temp_fmt;
517  substr++;
518  break;
519 
521  temp_fmt[0] = '\0';
522  cw = snprintf(temp, SC_LOG_MAX_LOG_MSG_LEN - (temp - buffer),
523  "%s%s%s%s", substr, blue, file, reset);
524  if (cw < 0)
525  return -1;
526  temp += cw;
527  temp_fmt++;
528  substr = temp_fmt;
529  substr++;
530  break;
531 
532  case SC_LOG_FMT_LINE:
533  temp_fmt[0] = '\0';
534  cw = snprintf(temp, SC_LOG_MAX_LOG_MSG_LEN - (temp - buffer),
535  "%s%s%u%s", substr, green, line, reset);
536  if (cw < 0)
537  return -1;
538  temp += cw;
539  temp_fmt++;
540  substr = temp_fmt;
541  substr++;
542  break;
543 
545  temp_fmt[0] = '\0';
546 
547  /* Determine how much of module name to display */
548  int dn_len = 0;
549  const char *dn_name = "unknown";
550  if (module) {
551  dn_name = SCTransformModule(module, &dn_len);
552  }
553 
554  cw = snprintf(temp, SC_LOG_MAX_LOG_MSG_LEN - (temp - buffer), "%s%s%s%s", substr,
555  green, dn_name, reset);
556  if (cw < 0)
557  return -1;
558  temp += cw;
559  temp_fmt++;
560  substr = temp_fmt;
561  substr++;
562  break;
563 
564  case SC_LOG_FMT_FUNCTION:
565  temp_fmt[0] = '\0';
566  cw = snprintf(temp, SC_LOG_MAX_LOG_MSG_LEN - (temp - buffer),
567  "%s%s%s%s", substr, green, function, reset);
568  if (cw < 0)
569  return -1;
570  temp += cw;
571  temp_fmt++;
572  substr = temp_fmt;
573  substr++;
574  break;
575 
576  case SC_LOG_FMT_MESSAGE: {
577  temp_fmt[0] = '\0';
578  cw = snprintf(temp, SC_LOG_MAX_LOG_MSG_LEN - (temp - buffer), "%s", substr);
579  if (cw < 0) {
580  return -1;
581  }
582  temp += cw;
583  if ((temp - buffer) > SC_LOG_MAX_LOG_MSG_LEN) {
584  return 0;
585  }
586  const char *hi = "";
587  if (log_level <= SC_LOG_ERROR)
588  hi = red;
589  else if (log_level <= SC_LOG_NOTICE)
590  hi = yellow;
591  cw = snprintf(temp, SC_LOG_MAX_LOG_MSG_LEN - (temp - buffer), "%s%s%s", hi, message,
592  reset);
593  if (cw < 0) {
594  return -1;
595  }
596  temp += cw;
597  if ((temp - buffer) > SC_LOG_MAX_LOG_MSG_LEN) {
598  return 0;
599  }
600  temp_fmt++;
601  substr = temp_fmt;
602  substr++;
603  break;
604  }
605  }
606  temp_fmt++;
607  }
608  if ((temp - buffer) > SC_LOG_MAX_LOG_MSG_LEN) {
609  return 0;
610  }
611  cw = snprintf(temp, SC_LOG_MAX_LOG_MSG_LEN - (temp - buffer), "%s", substr);
612  if (cw < 0) {
613  return -1;
614  }
615  if (sc_log_config->op_filter_regex != NULL) {
616  if (pcre2_match(sc_log_config->op_filter_regex, (PCRE2_SPTR8)buffer, strlen(buffer), 0, 0,
617  sc_log_config->op_filter_regex_match, NULL) < 0) {
618  return -1; // bit hacky, but just return !0
619  }
620  }
621 
622  return 0;
623 }
624 
625 /** \internal
626  * \brief try to reopen file
627  * \note no error reporting here, as we're called by SCLogMessage
628  * \retval status 0 ok, -1 error */
629 static int SCLogReopen(SCLogOPIfaceCtx *op_iface_ctx)
630 {
631  if (op_iface_ctx->file == NULL) {
632  return 0;
633  }
634 
635  if (op_iface_ctx->file_d != NULL) {
636  fclose(op_iface_ctx->file_d);
637  }
638  op_iface_ctx->file_d = fopen(op_iface_ctx->file, "a");
639  if (op_iface_ctx->file_d == NULL) {
640  return -1;
641  }
642  return 0;
643 }
644 
645 /**
646  * \brief Adds the global log_format to the outgoing buffer
647  *
648  * \param log_level log_level of the message that has to be logged
649  * \param msg Buffer containing the outgoing message
650  * \param file File_name from where the message originated
651  * \param function Function_name from where the message originated
652  * \param line Line_no from where the messaged originated
653  *
654  * \retval SC_OK on success; else an error code
655  */
656 SCError SCLogMessage(const SCLogLevel log_level, const char *file, const unsigned int line,
657  const char *function, const char *module, const char *message)
658 {
659  char buffer[SC_LOG_MAX_LOG_MSG_LEN] = "";
660  SCLogOPIfaceCtx *op_iface_ctx = NULL;
661 
662  if (sc_log_module_initialized != 1) {
663  printf("Logging module not initialized. Call SCLogInitLogModule() "
664  "first before using the debug API\n");
665  return SC_OK;
666  }
667 
668  /* get ts here so we log the same ts to each output */
669  struct timeval tval;
670  gettimeofday(&tval, NULL);
672 
673  op_iface_ctx = sc_log_config->op_ifaces;
674  while (op_iface_ctx != NULL) {
675  if (log_level != SC_LOG_NOTSET && log_level > op_iface_ctx->log_level) {
676  op_iface_ctx = op_iface_ctx->next;
677  continue;
678  }
679 
680  switch (op_iface_ctx->iface) {
682  if (SCLogMessageGetBuffer(ts, op_iface_ctx->use_color, op_iface_ctx->type, buffer,
683  sizeof(buffer),
684  op_iface_ctx->log_format ? op_iface_ctx->log_format
685  : sc_log_config->log_format,
686  log_level, file, line, function, module, message) == 0) {
687  SCLogPrintToStream((log_level == SC_LOG_ERROR)? stderr: stdout, buffer);
688  }
689  break;
691  if (SCLogMessageGetBuffer(ts, 0, op_iface_ctx->type, buffer, sizeof(buffer),
692  op_iface_ctx->log_format ? op_iface_ctx->log_format
693  : sc_log_config->log_format,
694  log_level, file, line, function, module, message) == 0) {
695  int r = 0;
696  SCMutexLock(&op_iface_ctx->fp_mutex);
697  if (op_iface_ctx->rotation_flag) {
698  r = SCLogReopen(op_iface_ctx);
699  op_iface_ctx->rotation_flag = 0;
700  }
701  SCLogPrintToStream(op_iface_ctx->file_d, buffer);
702  SCMutexUnlock(&op_iface_ctx->fp_mutex);
703 
704  /* report error outside of lock to avoid recursion */
705  if (r == -1) {
706  SCLogError("re-opening file \"%s\" failed: %s", op_iface_ctx->file,
707  strerror(errno));
708  }
709  }
710  break;
712  if (SCLogMessageGetBuffer(ts, 0, op_iface_ctx->type, buffer, sizeof(buffer),
713  op_iface_ctx->log_format ? op_iface_ctx->log_format
714  : sc_log_config->log_format,
715  log_level, file, line, function, module, message) == 0) {
716  SCLogPrintToSyslog(SCLogMapLogLevelToSyslogLevel(log_level), buffer);
717  }
718  break;
719  default:
720  break;
721  }
722  op_iface_ctx = op_iface_ctx->next;
723  }
724  return SC_OK;
725 }
726 
727 void SCLog(int x, const char *file, const char *func, const int line, const char *module,
728  const char *fmt, ...)
729 {
730  if (sc_log_global_log_level >= x &&
732  SCLogMatchFGFilterWL(file, func, line) == 1 ||
733  SCLogMatchFGFilterBL(file, func, line) == 1) &&
735  SCLogMatchFDFilter(func) == 1))
736  {
738  va_list ap;
739  va_start(ap, fmt);
740  vsnprintf(msg, sizeof(msg), fmt, ap);
741  va_end(ap);
742  SCLogMessage(x, file, line, func, module, msg);
743  }
744 }
745 
746 void SCLogErr(int x, const char *file, const char *func, const int line, const char *module,
747  const char *fmt, ...)
748 {
749  if (sc_log_global_log_level >= x &&
751  SCLogMatchFGFilterWL(file, func, line) == 1 ||
752  SCLogMatchFGFilterBL(file, func, line) == 1) &&
754  SCLogMatchFDFilter(func) == 1))
755  {
757  va_list ap;
758  va_start(ap, fmt);
759  vsnprintf(msg, sizeof(msg), fmt, ap);
760  va_end(ap);
761  SCLogMessage(x, file, line, func, module, msg);
762  }
763 }
764 
765 /**
766  * \brief Returns whether debug messages are enabled to be logged or not
767  *
768  * \retval 1 if debug messages are enabled to be logged
769  * \retval 0 if debug messages are not enabled to be logged
770  */
772 {
773 #ifdef DEBUG
775  return 1;
776  else
777  return 0;
778 #else
779  return 0;
780 #endif
781 }
782 
783 /**
784  * \brief Allocates an output buffer for an output interface. Used when we
785  * want the op_interface log_format to override the global_log_format.
786  * Currently not used.
787  *
788  * \retval buffer Pointer to the newly created output_buffer
789  */
791 {
792  SCLogOPBuffer *buffer = NULL;
793 
794  if ( (buffer = SCMalloc(sc_log_config->op_ifaces_cnt *
795  sizeof(SCLogOPBuffer))) == NULL) {
796  FatalError("Fatal error encountered in SCLogAllocLogOPBuffer. Exiting...");
797  }
798 
799  SCLogOPIfaceCtx *op_iface_ctx = sc_log_config->op_ifaces;
800  for (int i = 0; i < sc_log_config->op_ifaces_cnt; i++, op_iface_ctx = op_iface_ctx->next) {
801  buffer[i].log_format = op_iface_ctx->log_format;
802  buffer[i].temp = buffer[i].msg;
803  }
804 
805  return buffer;
806 }
807 
808 /*----------------------The logging module initialization code--------------- */
809 
810 /**
811  * \brief Returns a new output_interface_context
812  *
813  * \retval iface_ctx Pointer to a newly allocated output_interface_context
814  * \initonly
815  */
816 static inline SCLogOPIfaceCtx *SCLogAllocLogOPIfaceCtx(void)
817 {
818  SCLogOPIfaceCtx *iface_ctx = NULL;
819 
820  if ((iface_ctx = SCCalloc(1, sizeof(SCLogOPIfaceCtx))) == NULL) {
821  FatalError("Fatal error encountered in SCLogallocLogOPIfaceCtx. Exiting...");
822  }
823 
824  return iface_ctx;
825 }
826 
827 /**
828  * \brief Initializes the file output interface
829  *
830  * \param file Path to the file used for logging purposes
831  * \param log_format Pointer to the log_format for this op interface, that
832  * overrides the global_log_format
833  * \param log_level Override of the global_log_level by this interface
834  *
835  * \retval iface_ctx Pointer to the file output interface context created
836  * \initonly
837  */
838 static inline SCLogOPIfaceCtx *SCLogInitFileOPIface(const char *file, uint32_t userid,
839  uint32_t groupid, const char *log_format, int log_level, SCLogOPType type)
840 {
841  SCLogOPIfaceCtx *iface_ctx = SCLogAllocLogOPIfaceCtx();
842  if (iface_ctx == NULL) {
843  FatalError("Fatal error encountered in SCLogInitFileOPIface. Exiting...");
844  }
845 
846  if (file == NULL) {
847  goto error;
848  }
849 
850  iface_ctx->iface = SC_LOG_OP_IFACE_FILE;
851  iface_ctx->type = type;
852 
853  if ( (iface_ctx->file_d = fopen(file, "a")) == NULL) {
854  SCLogWarning("error opening file %s: %s", file, strerror(errno));
855  goto error;
856  }
857 
858 #ifndef OS_WIN32
859  if (userid != 0 || groupid != 0) {
860  if (fchown(fileno(iface_ctx->file_d), userid, groupid) == -1) {
861  SCLogWarning("Failed to change ownership of file %s: %s", file, strerror(errno));
862  }
863  }
864 #endif
865 
866  if ((iface_ctx->file = SCStrdup(file)) == NULL) {
867  goto error;
868  }
869 
870  if (log_format != NULL && (iface_ctx->log_format = SCStrdup(log_format)) == NULL) {
871  goto error;
872  }
873 
874  SCMutexInit(&iface_ctx->fp_mutex, NULL);
876 
877  iface_ctx->log_level = log_level;
878 
879  return iface_ctx;
880 
881 error:
882  if (iface_ctx->file != NULL) {
883  SCFree((char *)iface_ctx->file);
884  iface_ctx->file = NULL;
885  }
886  if (iface_ctx->log_format != NULL) {
887  SCFree((char *)iface_ctx->log_format);
888  iface_ctx->log_format = NULL;
889  }
890  if (iface_ctx->file_d != NULL) {
891  fclose(iface_ctx->file_d);
892  iface_ctx->file_d = NULL;
893  }
894  SCFree(iface_ctx);
895  return NULL;
896 }
897 
898 /**
899  * \brief Initializes the console output interface and deals with possible
900  * env var overrides.
901  *
902  * \param log_format Pointer to the log_format for this op interface, that
903  * overrides the global_log_format
904  * \param log_level Override of the global_log_level by this interface
905  *
906  * \retval iface_ctx Pointer to the console output interface context created
907  * \initonly
908  */
909 static inline SCLogOPIfaceCtx *SCLogInitConsoleOPIface(const char *log_format,
910  SCLogLevel log_level, SCLogOPType type)
911 {
912  SCLogOPIfaceCtx *iface_ctx = SCLogAllocLogOPIfaceCtx();
913 
914  if (iface_ctx == NULL) {
915  FatalError("Fatal error encountered in SCLogInitConsoleOPIface. Exiting...");
916  }
917 
918  iface_ctx->iface = SC_LOG_OP_IFACE_CONSOLE;
919  iface_ctx->type = type;
920 
921  /* console log format is overridden by envvars */
922  const char *tmp_log_format = log_format;
923  const char *s = getenv(SC_LOG_ENV_LOG_FORMAT);
924  if (s != NULL) {
925 #if 0
926  printf("Overriding setting for \"console.format\" because of env "
927  "var SC_LOG_FORMAT=\"%s\".\n", s);
928 #endif
929  tmp_log_format = s;
930  }
931 
932  if (tmp_log_format != NULL &&
933  (iface_ctx->log_format = SCStrdup(tmp_log_format)) == NULL) {
934  printf("Error allocating memory\n");
935  exit(EXIT_FAILURE);
936  }
937 
938  /* console log level is overridden by envvars */
939  SCLogLevel tmp_log_level = log_level;
940  s = getenv(SC_LOG_ENV_LOG_LEVEL);
941  if (s != NULL) {
943  if (l > SC_LOG_NOTSET && l < SC_LOG_LEVEL_MAX) {
944 #if 0
945  printf("Overriding setting for \"console.level\" because of env "
946  "var SC_LOG_LEVEL=\"%s\".\n", s);
947 #endif
948  tmp_log_level = l;
949  }
950  }
951  iface_ctx->log_level = tmp_log_level;
952 
953 #ifndef OS_WIN32
954  if (isatty(fileno(stdout)) && isatty(fileno(stderr))) {
955  iface_ctx->use_color = true;
956  }
957 #endif
958 
959  return iface_ctx;
960 }
961 
962 /**
963  * \brief Initializes the syslog output interface
964  *
965  * \param facility The facility code for syslog
966  * \param log_format Pointer to the log_format for this op interface, that
967  * overrides the global_log_format
968  * \param log_level Override of the global_log_level by this interface
969  *
970  * \retval iface_ctx Pointer to the syslog output interface context created
971  */
972 static inline SCLogOPIfaceCtx *SCLogInitSyslogOPIface(int facility,
973  const char *log_format,
974  SCLogLevel log_level,
976 {
977  SCLogOPIfaceCtx *iface_ctx = SCLogAllocLogOPIfaceCtx();
978 
979  if ( iface_ctx == NULL) {
980  FatalError("Fatal error encountered in SCLogInitSyslogOPIface. Exiting...");
981  }
982 
983  iface_ctx->iface = SC_LOG_OP_IFACE_SYSLOG;
984  iface_ctx->type = type;
985 
986  if (facility == -1)
987  facility = SC_LOG_DEF_SYSLOG_FACILITY;
988  iface_ctx->facility = facility;
989 
990  if (log_format != NULL &&
991  (iface_ctx->log_format = SCStrdup(log_format)) == NULL) {
992  printf("Error allocating memory\n");
993  exit(EXIT_FAILURE);
994  }
995 
996  iface_ctx->log_level = log_level;
997 
998  openlog(NULL, LOG_NDELAY, iface_ctx->facility);
999 
1000  return iface_ctx;
1001 }
1002 
1003 /**
1004  * \brief Frees the output_interface context supplied as an argument
1005  *
1006  * \param iface_ctx Pointer to the op_interface_context to be freed
1007  */
1008 static inline void SCLogFreeLogOPIfaceCtx(SCLogOPIfaceCtx *iface_ctx)
1009 {
1010  SCLogOPIfaceCtx *temp = NULL;
1011 
1012  while (iface_ctx != NULL) {
1013  temp = iface_ctx;
1014 
1015  if (iface_ctx->file_d != NULL) {
1016  fclose(iface_ctx->file_d);
1017  SCMutexDestroy(&iface_ctx->fp_mutex);
1018  }
1019 
1020  if (iface_ctx->file != NULL)
1021  SCFree((void *)iface_ctx->file);
1022 
1023  if (iface_ctx->log_format != NULL)
1024  SCFree((void *)iface_ctx->log_format);
1025 
1026  if (iface_ctx->iface == SC_LOG_OP_IFACE_SYSLOG) {
1027  closelog();
1028  }
1029 
1030  iface_ctx = iface_ctx->next;
1031 
1032  SCFree(temp);
1033  }
1034 
1035  return;
1036 }
1037 
1038 /**
1039  * \brief Internal function used to set the logging module global_log_level
1040  * during the initialization phase
1041  *
1042  * \param sc_lid The initialization data supplied.
1043  * \param sc_lc The logging module context which has to be updated.
1044  */
1045 static inline void SCLogSetLogLevel(SCLogInitData *sc_lid, SCLogConfig *sc_lc)
1046 {
1047  SCLogLevel log_level = SC_LOG_NOTSET;
1048  const char *s = NULL;
1049 
1050  /* envvar overrides config */
1051  s = getenv(SC_LOG_ENV_LOG_LEVEL);
1052  if (s != NULL) {
1053  log_level = SCMapEnumNameToValue(s, sc_log_level_map);
1054  } else if (sc_lid != NULL) {
1055  log_level = sc_lid->global_log_level;
1056  }
1057 
1058  /* deal with the global_log_level to be used */
1059  if (log_level > SC_LOG_NOTSET && log_level < SC_LOG_LEVEL_MAX)
1060  sc_lc->log_level = log_level;
1061  else {
1063 #ifndef UNITTESTS
1064  if (sc_lid != NULL) {
1065  printf("Warning: Invalid/No global_log_level assigned by user. Falling "
1066  "back on the default_log_level \"%s\"\n",
1068  }
1069 #endif
1070  }
1071 
1072  /* we also set it to a global var, as it is easier to access it */
1074 
1075  return;
1076 }
1077 
1079 {
1080  return sc_log_global_log_level;
1081 }
1082 
1083 static inline const char *SCLogGetDefaultLogFormat(const SCLogLevel lvl)
1084 {
1085  const char *prog_ver = GetProgramVersion();
1086  if (strstr(prog_ver, "RELEASE") != NULL) {
1087  if (lvl <= SC_LOG_NOTICE)
1089  else if (lvl <= SC_LOG_INFO)
1091  else if (lvl <= SC_LOG_CONFIG)
1093  }
1095 }
1096 
1097 /**
1098  * \brief Internal function used to set the logging module global_log_format
1099  * during the initialization phase
1100  *
1101  * \param sc_lid The initialization data supplied.
1102  * \param sc_lc The logging module context which has to be updated.
1103  */
1104 static inline void SCLogSetLogFormat(SCLogInitData *sc_lid, SCLogConfig *sc_lc)
1105 {
1106  const char *format = NULL;
1107 
1108  /* envvar overrides config */
1109  format = getenv(SC_LOG_ENV_LOG_FORMAT);
1110  if (format == NULL) {
1111  if (sc_lid != NULL) {
1112  format = sc_lid->global_log_format;
1113  }
1114  }
1115 
1116  /* deal with the global log format to be used */
1117  if (format == NULL || strlen(format) > SC_LOG_MAX_LOG_FORMAT_LEN) {
1118  format = SCLogGetDefaultLogFormat(sc_lc->log_level);
1119 #ifndef UNITTESTS
1120  if (sc_lid != NULL) {
1121  printf("Warning: Invalid/No global_log_format supplied by user or format "
1122  "length exceeded limit of \"%d\" characters. Falling back on "
1123  "default log_format \"%s\"\n", SC_LOG_MAX_LOG_FORMAT_LEN,
1124  format);
1125  }
1126 #endif
1127  }
1128 
1129  if (format != NULL && (sc_lc->log_format = SCStrdup(format)) == NULL) {
1130  printf("Error allocating memory\n");
1131  exit(EXIT_FAILURE);
1132  }
1133 
1134  return;
1135 }
1136 
1137 /**
1138  * \brief Internal function used to set the logging module global_op_ifaces
1139  * during the initialization phase
1140  *
1141  * \param sc_lid The initialization data supplied.
1142  * \param sc_lc The logging module context which has to be updated.
1143  */
1144 static inline void SCLogSetOPIface(SCLogInitData *sc_lid, SCLogConfig *sc_lc)
1145 {
1146  SCLogOPIfaceCtx *op_ifaces_ctx = NULL;
1147  int op_iface = 0;
1148  const char *s = NULL;
1149 
1150  if (sc_lid != NULL && sc_lid->op_ifaces != NULL) {
1151  sc_lc->op_ifaces = sc_lid->op_ifaces;
1152  sc_lid->op_ifaces = NULL;
1153  sc_lc->op_ifaces_cnt = sc_lid->op_ifaces_cnt;
1154  } else {
1155  s = getenv(SC_LOG_ENV_LOG_OP_IFACE);
1156  if (s != NULL) {
1158 
1159  if(op_iface < 0 || op_iface >= SC_LOG_OP_IFACE_MAX) {
1160  op_iface = SC_LOG_DEF_LOG_OP_IFACE;
1161 #ifndef UNITTESTS
1162  printf("Warning: Invalid output interface supplied by user. "
1163  "Falling back on default_output_interface \"%s\"\n",
1165 #endif
1166  }
1167  }
1168  else {
1169  op_iface = SC_LOG_DEF_LOG_OP_IFACE;
1170 #ifndef UNITTESTS
1171  if (sc_lid != NULL) {
1172  printf("Warning: Output_interface not supplied by user. Falling "
1173  "back on default_output_interface \"%s\"\n",
1175  }
1176 #endif
1177  }
1178 
1179  switch (op_iface) {
1181  op_ifaces_ctx = SCLogInitConsoleOPIface(NULL, SC_LOG_LEVEL_MAX,0);
1182  break;
1183  case SC_LOG_OP_IFACE_FILE:
1184  s = getenv(SC_LOG_ENV_LOG_FILE);
1185  if (s == NULL) {
1186  char *str = SCLogGetLogFilename(SC_LOG_DEF_LOG_FILE);
1187  if (str != NULL) {
1188  op_ifaces_ctx = SCLogInitFileOPIface(str, 0, 0, NULL, SC_LOG_LEVEL_MAX, 0);
1189  SCFree(str);
1190  }
1191  } else {
1192  op_ifaces_ctx = SCLogInitFileOPIface(s, 0, 0, NULL, SC_LOG_LEVEL_MAX, 0);
1193  }
1194  break;
1196  s = getenv(SC_LOG_ENV_LOG_FACILITY);
1197  if (s == NULL)
1199 
1200  op_ifaces_ctx = SCLogInitSyslogOPIface(SCMapEnumNameToValue(s, SCSyslogGetFacilityMap()), NULL, -1,0);
1201  break;
1202  }
1203  sc_lc->op_ifaces = op_ifaces_ctx;
1204  sc_lc->op_ifaces_cnt++;
1205  }
1206  return;
1207 }
1208 
1209 /**
1210  * \brief Internal function used to set the logging module op_filter
1211  * during the initialization phase
1212  *
1213  * \param sc_lid The initialization data supplied.
1214  * \param sc_lc The logging module context which has to be updated.
1215  */
1216 static inline void SCLogSetOPFilter(SCLogInitData *sc_lid, SCLogConfig *sc_lc)
1217 {
1218  const char *filter = NULL;
1219 
1220  int opts = 0;
1221  int en;
1222  PCRE2_SIZE eo = 0;
1223 
1224  /* envvar overrides */
1225  filter = getenv(SC_LOG_ENV_LOG_OP_FILTER);
1226  if (filter == NULL) {
1227  if (sc_lid != NULL) {
1228  filter = sc_lid->op_filter;
1229  }
1230  }
1231 
1232  if (filter != NULL && strcmp(filter, "") != 0) {
1233  sc_lc->op_filter = SCStrdup(filter);
1234  if (sc_lc->op_filter == NULL) {
1235  printf("pcre filter alloc failed\n");
1236  return;
1237  }
1238  sc_lc->op_filter_regex =
1239  pcre2_compile((PCRE2_SPTR8)filter, PCRE2_ZERO_TERMINATED, opts, &en, &eo, NULL);
1240  if (sc_lc->op_filter_regex == NULL) {
1241  SCFree(sc_lc->op_filter);
1242  PCRE2_UCHAR errbuffer[256];
1243  pcre2_get_error_message(en, errbuffer, sizeof(errbuffer));
1244  printf("pcre2 compile of \"%s\" failed at offset %d : %s\n", filter, (int)eo,
1245  errbuffer);
1246  return;
1247  }
1248  sc_lc->op_filter_regex_match =
1249  pcre2_match_data_create_from_pattern(sc_lc->op_filter_regex, NULL);
1250  }
1251 
1252  return;
1253 }
1254 
1255 /**
1256  * \brief Returns a pointer to a new SCLogInitData. This is a public interface
1257  * intended to be used after the logging parameters are read from the
1258  * conf file
1259  *
1260  * \retval sc_lid Pointer to the newly created SCLogInitData
1261  * \initonly
1262  */
1264 {
1265  SCLogInitData *sc_lid = NULL;
1266 
1267  if ((sc_lid = SCCalloc(1, sizeof(SCLogInitData))) == NULL)
1268  return NULL;
1269 
1270  return sc_lid;
1271 }
1272 
1273 #ifdef UNITTESTS
1274 #ifndef OS_WIN32
1275 /**
1276  * \brief Frees a SCLogInitData
1277  *
1278  * \param sc_lid Pointer to the SCLogInitData to be freed
1279  */
1280 static void SCLogFreeLogInitData(SCLogInitData *sc_lid)
1281 {
1282  if (sc_lid != NULL) {
1283  SCLogFreeLogOPIfaceCtx(sc_lid->op_ifaces);
1284  SCFree(sc_lid);
1285  }
1286 
1287  return;
1288 }
1289 #endif
1290 #endif
1291 
1292 /**
1293  * \brief Frees the logging module context
1294  */
1295 static inline void SCLogFreeLogConfig(SCLogConfig *sc_lc)
1296 {
1297  if (sc_lc != NULL) {
1298  if (sc_lc->startup_message != NULL)
1299  SCFree(sc_lc->startup_message);
1300  if (sc_lc->log_format != NULL)
1301  SCFree(sc_lc->log_format);
1302  if (sc_lc->op_filter != NULL)
1303  SCFree(sc_lc->op_filter);
1304 
1305  if (sc_lc->op_filter_regex != NULL)
1306  pcre2_code_free(sc_lc->op_filter_regex);
1307  if (sc_lc->op_filter_regex_match)
1308  pcre2_match_data_free(sc_lc->op_filter_regex_match);
1309 
1310  SCLogFreeLogOPIfaceCtx(sc_lc->op_ifaces);
1311  SCFree(sc_lc);
1312  }
1313 
1314  return;
1315 }
1316 
1317 /**
1318  * \brief Appends an output_interface to the output_interface list sent in head
1319  *
1320  * \param iface_ctx Pointer to the output_interface that has to be added to head
1321  * \param head Pointer to the output_interface list
1322  */
1324 {
1325  SCLogOPIfaceCtx *temp = NULL, *prev = NULL;
1326  SCLogOPIfaceCtx **head = &sc_lid->op_ifaces;
1327 
1328  if (iface_ctx == NULL) {
1329 #ifdef DEBUG
1330  printf("Argument(s) to SCLogAppendOPIfaceCtx() NULL\n");
1331 #endif
1332  return;
1333  }
1334 
1335  temp = *head;
1336  while (temp != NULL) {
1337  prev = temp;
1338  temp = temp->next;
1339  }
1340 
1341  if (prev == NULL)
1342  *head = iface_ctx;
1343  else
1344  prev->next = iface_ctx;
1345 
1346  sc_lid->op_ifaces_cnt++;
1347 
1348  return;
1349 }
1350 
1351 #ifdef UNITTESTS
1352 #ifndef OS_WIN32
1353 /**
1354  * \internal
1355  * \brief Creates a new output interface based on the arguments sent. The kind
1356  * of output interface to be created is decided by the iface_name arg.
1357  * If iface_name is "file", the arg argument will hold the filename to be
1358  * used for logging purposes. If iface_name is "syslog", the arg
1359  * argument holds the facility code. If iface_name is "console", arg is
1360  * NULL.
1361  *
1362  * \param iface_name Interface name. Can be "console", "file" or "syslog"
1363  * \param log_format Override for the global_log_format
1364  * \param log_level Override for the global_log_level
1365  * \param log_level Parameter required by a particular interface. Explained in
1366  * the function description
1367  *
1368  * \retval iface_ctx Pointer to the newly created output interface
1369  */
1370 static SCLogOPIfaceCtx *SCLogInitOPIfaceCtx(
1371  const char *iface_name, const char *log_format, int log_level, const char *arg)
1372 {
1373  int iface = SCMapEnumNameToValue(iface_name, sc_log_op_iface_map);
1374 
1375  if (log_level < SC_LOG_NONE || log_level > SC_LOG_DEBUG) {
1376  printf("Warning: Supplied log_level_override for op_interface \"%s\" "
1377  "is invalid. Defaulting to not specifying an override\n",
1378  iface_name);
1379  log_level = SC_LOG_NOTSET;
1380  }
1381 
1382  switch (iface) {
1384  return SCLogInitConsoleOPIface(log_format, log_level, SC_LOG_OP_TYPE_REGULAR);
1385  case SC_LOG_OP_IFACE_FILE:
1386  return SCLogInitFileOPIface(arg, 0, 0, log_format, log_level, SC_LOG_OP_TYPE_REGULAR);
1388  return SCLogInitSyslogOPIface(SCMapEnumNameToValue(arg, SCSyslogGetFacilityMap()),
1389  log_format, log_level, SC_LOG_OP_TYPE_REGULAR);
1390  default:
1391 #ifdef DEBUG
1392  printf("Output Interface \"%s\" not supported by the logging module",
1393  iface_name);
1394 #endif
1395  return NULL;
1396  }
1397 }
1398 #endif
1399 #endif
1400 
1401 /**
1402  * \brief Initializes the logging module.
1403  *
1404  * \param sc_lid The initialization data for the logging module. If sc_lid is
1405  * NULL, we would stick to the default configuration for the
1406  * logging subsystem.
1407  * \initonly
1408  */
1410 {
1411  /* De-initialize the logging context, if it has already init by the
1412  * environment variables at the start of the engine */
1414 
1415 #if defined (OS_WIN32)
1416  if (SCMutexInit(&sc_log_stream_lock, NULL) != 0) {
1417  FatalError("Failed to initialize log mutex.");
1418  }
1419 #endif /* OS_WIN32 */
1420 
1421  /* sc_log_config is a global variable */
1422  if ((sc_log_config = SCCalloc(1, sizeof(SCLogConfig))) == NULL) {
1423  FatalError("Fatal error encountered in SCLogInitLogModule. Exiting...");
1424  }
1425 
1426  SCLogSetLogLevel(sc_lid, sc_log_config);
1427  SCLogSetLogFormat(sc_lid, sc_log_config);
1428  SCLogSetOPIface(sc_lid, sc_log_config);
1429  SCLogSetOPFilter(sc_lid, sc_log_config);
1430 
1433 
1434  //SCOutputPrint(sc_did->startup_message);
1435 
1436  rs_log_set_level(sc_log_global_log_level);
1437  return;
1438 }
1439 
1440 void SCLogLoadConfig(int daemon, int verbose, uint32_t userid, uint32_t groupid)
1441 {
1442  ConfNode *outputs;
1443  SCLogInitData *sc_lid;
1444  int have_logging = 0;
1445  int max_level = 0;
1446  SCLogLevel min_level = 0;
1447 
1448  /* If verbose logging was requested, set the minimum as
1449  * SC_LOG_NOTICE plus the extra verbosity. */
1450  if (verbose) {
1451  min_level = SC_LOG_NOTICE + verbose;
1452  }
1453 
1454  outputs = ConfGetNode("logging.outputs");
1455  if (outputs == NULL) {
1456  SCLogDebug("No logging.output configuration section found.");
1457  return;
1458  }
1459 
1460  sc_lid = SCLogAllocLogInitData();
1461  if (sc_lid == NULL) {
1462  SCLogDebug("Could not allocate memory for log init data");
1463  return;
1464  }
1465 
1466  /* Get default log level and format. */
1467  const char *default_log_level_s = NULL;
1468  if (ConfGet("logging.default-log-level", &default_log_level_s) == 1) {
1469  SCLogLevel default_log_level =
1470  SCMapEnumNameToValue(default_log_level_s, sc_log_level_map);
1471  if (default_log_level == -1) {
1472  SCLogError("Invalid default log level: %s", default_log_level_s);
1473  exit(EXIT_FAILURE);
1474  }
1475  sc_lid->global_log_level = MAX(min_level, default_log_level);
1476  }
1477  else {
1478  sc_lid->global_log_level = MAX(min_level, SC_LOG_NOTICE);
1479  }
1480 
1481  if (ConfGet("logging.default-log-format", &sc_lid->global_log_format) != 1)
1482  sc_lid->global_log_format = SCLogGetDefaultLogFormat(sc_lid->global_log_level);
1483 
1484  (void)ConfGet("logging.default-output-filter", &sc_lid->op_filter);
1485 
1486  ConfNode *seq_node, *output;
1487  TAILQ_FOREACH(seq_node, &outputs->head, next) {
1488  SCLogLevel level = sc_lid->global_log_level;
1489  SCLogOPIfaceCtx *op_iface_ctx = NULL;
1490  const char *format;
1491  const char *level_s;
1492 
1493  output = ConfNodeLookupChild(seq_node, seq_node->val);
1494  if (output == NULL)
1495  continue;
1496 
1497  /* By default an output is enabled. */
1498  const char *enabled = ConfNodeLookupChildValue(output, "enabled");
1499  if (enabled != NULL && ConfValIsFalse(enabled))
1500  continue;
1501 
1503  const char *type_s = ConfNodeLookupChildValue(output, "type");
1504  if (type_s != NULL) {
1505  if (strcmp(type_s, "regular") == 0)
1507  else if (strcmp(type_s, "json") == 0) {
1509  }
1510  }
1511 
1512  format = ConfNodeLookupChildValue(output, "format");
1513 
1514  level_s = ConfNodeLookupChildValue(output, "level");
1515  if (level_s != NULL) {
1516  level = SCMapEnumNameToValue(level_s, sc_log_level_map);
1517  if (level == -1) {
1518  SCLogError("Invalid log level: %s", level_s);
1519  exit(EXIT_FAILURE);
1520  }
1521  max_level = MAX(max_level, level);
1522  }
1523 
1524  /* Increase the level of extra verbosity was requested. */
1525  level = MAX(min_level, level);
1526 
1527  if (strcmp(output->name, "console") == 0) {
1528  op_iface_ctx = SCLogInitConsoleOPIface(format, level, type);
1529  }
1530  else if (strcmp(output->name, "file") == 0) {
1531  if (format == NULL) {
1532  format = SC_LOG_DEF_FILE_FORMAT;
1533  }
1534 
1535  const char *filename = ConfNodeLookupChildValue(output, "filename");
1536  if (filename == NULL) {
1537  FatalError("Logging to file requires a filename");
1538  }
1539  char *path = NULL;
1540  if (!(PathIsAbsolute(filename))) {
1541  path = SCLogGetLogFilename(filename);
1542  } else {
1543  path = SCStrdup(filename);
1544  }
1545  if (path == NULL)
1546  FatalError("failed to setup output to file");
1547  have_logging = 1;
1548  op_iface_ctx = SCLogInitFileOPIface(path, userid, groupid, format, level, type);
1549  SCFree(path);
1550  }
1551  else if (strcmp(output->name, "syslog") == 0) {
1552  int facility = SC_LOG_DEF_SYSLOG_FACILITY;
1553  const char *facility_s = ConfNodeLookupChildValue(output,
1554  "facility");
1555  if (facility_s != NULL) {
1556  facility = SCMapEnumNameToValue(facility_s, SCSyslogGetFacilityMap());
1557  if (facility == -1) {
1558  SCLogWarning("Invalid syslog "
1559  "facility: \"%s\", now using \"%s\" as syslog "
1560  "facility",
1561  facility_s, SC_LOG_DEF_SYSLOG_FACILITY_STR);
1562  facility = SC_LOG_DEF_SYSLOG_FACILITY;
1563  }
1564  }
1565  SCLogDebug("Initializing syslog logging with format \"%s\"", format);
1566  have_logging = 1;
1567  op_iface_ctx = SCLogInitSyslogOPIface(facility, format, level, type);
1568  }
1569  else {
1570  SCLogWarning("invalid logging method: %s, ignoring", output->name);
1571  }
1572  if (op_iface_ctx != NULL) {
1573  SCLogAppendOPIfaceCtx(op_iface_ctx, sc_lid);
1574  }
1575  }
1576 
1577  if (daemon && (have_logging == 0)) {
1578  SCLogWarning("no logging compatible with daemon mode selected,"
1579  " suricata won't be able to log. Please update "
1580  " 'logging.outputs' in the YAML.");
1581  }
1582 
1583  /* Set the global log level to that of the max level used. */
1584  sc_lid->global_log_level = MAX(sc_lid->global_log_level, max_level);
1585  SCLogInitLogModule(sc_lid);
1586 
1587  SCLogDebug("sc_log_global_log_level: %d", sc_log_global_log_level);
1588  SCLogDebug("sc_lc->log_format: %s", sc_log_config->log_format);
1589  SCLogDebug("SCLogSetOPFilter: filter: %s", sc_log_config->op_filter);
1590 
1591  if (sc_lid != NULL)
1592  SCFree(sc_lid);
1593 }
1594 
1595 /**
1596  * \brief Returns a full file path given a filename uses log dir specified in
1597  * conf or DEFAULT_LOG_DIR
1598  *
1599  * \param filearg The relative filename for which we want a full path include
1600  * log directory
1601  *
1602  * \retval log_filename The fullpath of the logfile to open
1603  */
1604 static char *SCLogGetLogFilename(const char *filearg)
1605 {
1606  const char *log_dir = ConfigGetLogDirectory();
1607  char *log_filename = SCMalloc(PATH_MAX);
1608  if (unlikely(log_filename == NULL))
1609  return NULL;
1610  snprintf(log_filename, PATH_MAX, "%s/%s", log_dir, filearg);
1611  return log_filename;
1612 }
1613 
1614 /**
1615  * \brief De-Initializes the logging module
1616  */
1618 {
1619  SCLogFreeLogConfig(sc_log_config);
1620 
1621  /* reset the global logging_module variables */
1625  sc_log_config = NULL;
1626 
1627  /* de-init the FD filters */
1629  /* de-init the FG filters */
1631 
1632 #if defined (OS_WIN32)
1633  SCMutexDestroy(&sc_log_stream_lock);
1634 #endif /* OS_WIN32 */
1635 
1636  return;
1637 }
1638 
1639 //------------------------------------Unit_Tests--------------------------------
1640 
1641 /* The logging engine should be tested to the maximum extent possible, since
1642  * logging code would be used throughout the codebase, and hence we can't afford
1643  * to have a single bug here(not that you can afford to have a bug
1644  * elsewhere ;) ). Please report a bug, if you get a slightest hint of a bug
1645  * from the logging module.
1646  */
1647 
1648 #ifdef UNITTESTS
1649 
1650 static int SCLogTestInit01(void)
1651 {
1652 #ifndef OS_WIN32
1653  /* unset any environment variables set for the logging module */
1657 
1658  SCLogInitLogModule(NULL);
1659 
1660  FAIL_IF_NULL(sc_log_config);
1661 
1662  FAIL_IF_NOT(SC_LOG_DEF_LOG_LEVEL == sc_log_config->log_level);
1663  FAIL_IF_NOT(sc_log_config->op_ifaces != NULL &&
1664  SC_LOG_DEF_LOG_OP_IFACE == sc_log_config->op_ifaces->iface);
1665  FAIL_IF_NOT(sc_log_config->log_format != NULL &&
1666  strcmp(SCLogGetDefaultLogFormat(sc_log_config->log_level),
1667  sc_log_config->log_format) == 0);
1668 
1670 
1671  setenv(SC_LOG_ENV_LOG_LEVEL, "Debug", 1);
1672  setenv(SC_LOG_ENV_LOG_OP_IFACE, "Console", 1);
1673  setenv(SC_LOG_ENV_LOG_FORMAT, "%n- %l", 1);
1674 
1675  SCLogInitLogModule(NULL);
1676 
1677  FAIL_IF_NOT(SC_LOG_DEBUG == sc_log_config->log_level);
1678  FAIL_IF_NOT(sc_log_config->op_ifaces != NULL &&
1679  SC_LOG_OP_IFACE_CONSOLE == sc_log_config->op_ifaces->iface);
1680  FAIL_IF_NOT(sc_log_config->log_format != NULL &&
1681  !strcmp("%n- %l", sc_log_config->log_format));
1682 
1686 
1688 #endif
1689  PASS;
1690 }
1691 
1692 static int SCLogTestInit02(void)
1693 {
1694 #ifndef OS_WIN32
1695  SCLogInitData *sc_lid = NULL;
1696  SCLogOPIfaceCtx *sc_iface_ctx = NULL;
1697  char *logfile = SCLogGetLogFilename("boo.txt");
1698  sc_lid = SCLogAllocLogInitData();
1699  FAIL_IF_NULL(sc_lid);
1700  sc_lid->startup_message = "Test02";
1701  sc_lid->global_log_level = SC_LOG_DEBUG;
1702  sc_lid->op_filter = "boo";
1703  sc_iface_ctx = SCLogInitOPIfaceCtx("file", "%m - %d", SC_LOG_WARNING, logfile);
1704  SCLogAppendOPIfaceCtx(sc_iface_ctx, sc_lid);
1705  sc_iface_ctx = SCLogInitOPIfaceCtx("console", NULL, SC_LOG_ERROR,
1706  NULL);
1707  SCLogAppendOPIfaceCtx(sc_iface_ctx, sc_lid);
1708 
1709  SCLogInitLogModule(sc_lid);
1710 
1711  FAIL_IF_NULL(sc_log_config);
1712 
1713  FAIL_IF_NOT(SC_LOG_DEBUG == sc_log_config->log_level);
1714  FAIL_IF_NOT(sc_log_config->op_ifaces != NULL &&
1715  SC_LOG_OP_IFACE_FILE == sc_log_config->op_ifaces->iface);
1716  FAIL_IF_NOT(sc_log_config->op_ifaces != NULL &&
1717  sc_log_config->op_ifaces->next != NULL &&
1718  SC_LOG_OP_IFACE_CONSOLE == sc_log_config->op_ifaces->next->iface);
1719  FAIL_IF_NOT(sc_log_config->log_format != NULL &&
1720  strcmp(SCLogGetDefaultLogFormat(sc_log_config->log_level),
1721  sc_log_config->log_format) == 0);
1722  FAIL_IF_NOT(sc_log_config->op_ifaces != NULL &&
1723  sc_log_config->op_ifaces->log_format != NULL &&
1724  strcmp("%m - %d", sc_log_config->op_ifaces->log_format) == 0);
1725  FAIL_IF_NOT(sc_log_config->op_ifaces != NULL &&
1726  sc_log_config->op_ifaces->next != NULL &&
1727  sc_log_config->op_ifaces->next->log_format == NULL);
1728 
1729  SCLogFreeLogInitData(sc_lid);
1731 
1732  sc_lid = SCLogAllocLogInitData();
1733  FAIL_IF_NULL(sc_lid);
1734  sc_lid->startup_message = "Test02";
1735  sc_lid->global_log_level = SC_LOG_DEBUG;
1736  sc_lid->op_filter = "boo";
1737  sc_lid->global_log_format = "kaboo";
1738 
1739  SCLogInitLogModule(sc_lid);
1740 
1741  FAIL_IF_NULL(sc_log_config);
1742 
1743  FAIL_IF_NOT(SC_LOG_DEBUG == sc_log_config->log_level);
1744  FAIL_IF_NOT(sc_log_config->op_ifaces != NULL &&
1745  SC_LOG_OP_IFACE_CONSOLE == sc_log_config->op_ifaces->iface);
1746  FAIL_IF_NOT(sc_log_config->op_ifaces != NULL &&
1747  sc_log_config->op_ifaces->next == NULL);
1748  FAIL_IF_NOT(sc_log_config->log_format != NULL &&
1749  strcmp("kaboo", sc_log_config->log_format) == 0);
1750  FAIL_IF_NOT(sc_log_config->op_ifaces != NULL &&
1751  sc_log_config->op_ifaces->log_format == NULL);
1752  FAIL_IF_NOT(sc_log_config->op_ifaces != NULL &&
1753  sc_log_config->op_ifaces->next == NULL);
1754 
1755  SCLogFreeLogInitData(sc_lid);
1757  SCFree(logfile);
1758 #endif
1759  PASS;
1760 }
1761 
1762 static int SCLogTestInit03(void)
1763 {
1764  SCLogInitLogModule(NULL);
1765 
1766  SCLogAddFGFilterBL(NULL, "bamboo", -1);
1767  SCLogAddFGFilterBL(NULL, "soo", -1);
1768  SCLogAddFGFilterBL(NULL, "dummy", -1);
1769 
1771 
1772  SCLogAddFGFilterBL(NULL, "dummy1", -1);
1773  SCLogAddFGFilterBL(NULL, "dummy2", -1);
1774 
1776 
1778 
1779  PASS;
1780 }
1781 
1782 static int SCLogTestInit04(void)
1783 {
1784  SCLogInitLogModule(NULL);
1785 
1786  SCLogAddFDFilter("bamboo");
1787  SCLogAddFDFilter("soo");
1788  SCLogAddFDFilter("foo");
1789  SCLogAddFDFilter("roo");
1790 
1792 
1793  SCLogAddFDFilter("loo");
1794  SCLogAddFDFilter("soo");
1795 
1797 
1798  SCLogRemoveFDFilter("bamboo");
1799  SCLogRemoveFDFilter("soo");
1800  SCLogRemoveFDFilter("foo");
1801  SCLogRemoveFDFilter("noo");
1802 
1804 
1806 
1807  PASS;
1808 }
1809 
1810 static int SCLogTestInit05(void)
1811 {
1812  char str[4096];
1813  memset(str, 'A', sizeof(str));
1814  SCLogInfo("%s", str);
1815 
1816  PASS;
1817 }
1818 
1819 #endif /* UNITTESTS */
1820 
1822 {
1823 
1824 #ifdef UNITTESTS
1825 
1826  UtRegisterTest("SCLogTestInit01", SCLogTestInit01);
1827  UtRegisterTest("SCLogTestInit02", SCLogTestInit02);
1828  UtRegisterTest("SCLogTestInit03", SCLogTestInit03);
1829  UtRegisterTest("SCLogTestInit04", SCLogTestInit04);
1830  UtRegisterTest("SCLogTestInit05", SCLogTestInit05);
1831 
1832 #endif /* UNITTESTS */
1833 
1834  return;
1835 }
SC_LOG_DEF_SYSLOG_FACILITY
#define SC_LOG_DEF_SYSLOG_FACILITY
Definition: util-debug.h:100
SCLogConfig_::op_ifaces
SCLogOPIfaceCtx * op_ifaces
Definition: util-debug.h:181
ts
uint64_t ts
Definition: source-erf-file.c:55
SCLogMatchFGFilterBL
int SCLogMatchFGFilterBL(const char *file, const char *function, int line)
Checks if there is a match for the incoming log_message with any of the FG filters....
Definition: util-debug-filters.c:312
SC_LOG_DEF_SYSLOG_FACILITY_STR
#define SC_LOG_DEF_SYSLOG_FACILITY_STR
Definition: util-debug.h:99
FAIL_IF_NULL
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
SC_LOG_FMT_MESSAGE
#define SC_LOG_FMT_MESSAGE
Definition: util-debug.h:199
SCLogConfig_::op_filter_regex_match
pcre2_match_data * op_filter_regex_match
Definition: util-debug.h:178
SCLog
void SCLog(int x, const char *file, const char *func, const int line, const char *module, const char *fmt,...)
Definition: util-debug.c:727
SCLogInitLogModule
void SCLogInitLogModule(SCLogInitData *sc_lid)
Initializes the logging module.
Definition: util-debug.c:1409
syslog
#define syslog(__pri, __fmt, __param)
Definition: win32-syslog.h:78
SCLogOPIfaceCtx_::log_level
SCLogLevel log_level
Definition: util-debug.h:133
sc_log_level_map
SCEnumCharMap sc_log_level_map[]
Definition: util-debug.c:41
CreateIsoTimeString
void CreateIsoTimeString(const SCTime_t ts, char *str, size_t size)
Definition: util-time.c:209
SCLogOPIfaceCtx_::facility
int facility
Definition: util-debug.h:130
SC_LOG_DEBUG
@ SC_LOG_DEBUG
Definition: util-debug.h:57
sc_log_fg_filters_present
int sc_log_fg_filters_present
Definition: util-debug-filters.c:36
ConfNode_::val
char * val
Definition: conf.h:34
unsetenv
void unsetenv(const char *name)
SC_LOG_OP_TYPE_REGULAR
@ SC_LOG_OP_TYPE_REGULAR
Definition: util-debug.h:72
SC_LOG_CONFIG
@ SC_LOG_CONFIG
Definition: util-debug.h:56
SCLogAllocLogOPBuffer
SCLogOPBuffer * SCLogAllocLogOPBuffer(void)
Allocates an output buffer for an output interface. Used when we want the op_interface log_format to ...
Definition: util-debug.c:790
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
SC_LOG_NOTSET
@ SC_LOG_NOTSET
Definition: util-debug.h:49
SC_LOG_FMT_PREFIX
#define SC_LOG_FMT_PREFIX
Definition: util-debug.h:202
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:103
SC_LOG_FMT_FILE_NAME
#define SC_LOG_FMT_FILE_NAME
Definition: util-debug.h:194
SCLogInitData_::global_log_format
const char * global_log_format
Definition: util-debug.h:156
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:269
SC_LOG_OP_TYPE_JSON
@ SC_LOG_OP_TYPE_JSON
Definition: util-debug.h:73
next
struct HtpBodyChunk_ * next
Definition: app-layer-htp.h:0
SCLogOPBuffer_
Structure to be used when log_level override support would be provided by the logging module.
Definition: util-debug.h:106
SCLogOPIfaceCtx_::fp_mutex
SCMutex fp_mutex
Definition: util-debug.h:139
SC_LOG_ENV_LOG_OP_IFACE
#define SC_LOG_ENV_LOG_OP_IFACE
Definition: util-debug.h:37
ConfGetNode
ConfNode * ConfGetNode(const char *name)
Get a ConfNode by name.
Definition: conf.c:181
SCLogOPIfaceCtx_::use_color
bool use_color
Definition: util-debug.h:118
SCLogConfig_::op_filter
char * op_filter
Definition: util-debug.h:175
util-syslog.h
SC_LOG_ENV_LOG_FACILITY
#define SC_LOG_ENV_LOG_FACILITY
Definition: util-debug.h:39
SC_LOG_DEF_LOG_FORMAT_DEBUG
#define SC_LOG_DEF_LOG_FORMAT_DEBUG
Definition: util-debug.h:81
SCLogDeInitLogModule
void SCLogDeInitLogModule(void)
De-Initializes the logging module.
Definition: util-debug.c:1617
LOG_DEBUG
#define LOG_DEBUG
Definition: win32-syslog.h:46
TAILQ_FOREACH
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:252
sc_log_module_initialized
int sc_log_module_initialized
Used to indicate whether the logging module has been init or not.
Definition: util-debug.c:106
SC_LOG_NOTICE
@ SC_LOG_NOTICE
Definition: util-debug.h:53
SCMutexLock
#define SCMutexLock(mut)
Definition: threads-debug.h:117
SC_LOG_DEF_LOG_OP_IFACE
#define SC_LOG_DEF_LOG_OP_IFACE
Definition: util-debug.h:93
MIN
#define MIN(x, y)
Definition: suricata-common.h:391
SCLogOPIfaceCtx_::log_format
const char * log_format
Definition: util-debug.h:136
SCLogInitData_
Structure containing init data, that would be passed to SCInitDebugModule()
Definition: util-debug.h:148
SC_LOG_FMT_TIME_LEGACY
#define SC_LOG_FMT_TIME_LEGACY
Definition: util-debug.h:188
SC_LOG_FMT_LOG_LEVEL
#define SC_LOG_FMT_LOG_LEVEL
Definition: util-debug.h:192
SCLogOPType
SCLogOPType
Definition: util-debug.h:71
MAX
#define MAX(x, y)
Definition: suricata-common.h:395
SCLogMatchFDFilter
int SCLogMatchFDFilter(const char *function)
Checks if there is a match for the incoming log_message with any of the FD filters.
Definition: util-debug-filters.c:479
SCLogOPIfaceCtx_::type
SCLogOPType type
Definition: util-debug.h:119
SC_LOG_LEVEL_MAX
@ SC_LOG_LEVEL_MAX
Definition: util-debug.h:58
FAIL_IF_NOT
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:82
closelog
#define closelog()
Definition: win32-syslog.h:75
t_thread_name
thread_local char t_thread_name[THREAD_NAME_LEN+1]
Definition: threads.c:32
strlcpy
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: util-strlcpyu.c:43
SCLogReleaseFGFilters
void SCLogReleaseFGFilters(void)
Definition: util-debug-filters.c:359
SC_LOG_DEF_LOG_FORMAT_REL_INFO
#define SC_LOG_DEF_LOG_FORMAT_REL_INFO
Definition: util-debug.h:79
SCLogOPIfaceCtx_
The output interface context for the logging module.
Definition: util-debug.h:115
OutputRegisterFileRotationFlag
void OutputRegisterFileRotationFlag(int *flag)
Register a flag for file rotation notification.
Definition: output.c:834
ConfGet
int ConfGet(const char *name, const char **vptr)
Retrieve the value of a configuration node.
Definition: conf.c:335
SC_LOG_INFO
@ SC_LOG_INFO
Definition: util-debug.h:54
SC_LOG_ERROR
@ SC_LOG_ERROR
Definition: util-debug.h:51
SC_LOG_ENV_LOG_LEVEL
#define SC_LOG_ENV_LOG_LEVEL
ENV vars that can be used to set the properties for the logging module.
Definition: util-debug.h:36
util-debug.h
JB_SET_STRING
#define JB_SET_STRING(jb, key, val)
Definition: rust.h:26
type
uint8_t type
Definition: decode-icmpv4.h:0
SCLogReleaseFDFilters
void SCLogReleaseFDFilters(void)
Releases all the FD filters added to the logging module.
Definition: util-debug-filters.c:723
SC_LOG_FMT_THREAD_NAME
#define SC_LOG_FMT_THREAD_NAME
Definition: util-debug.h:198
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
SCLogConfig_::op_filter_regex
pcre2_code * op_filter_regex
Definition: util-debug.h:177
strlcat
size_t strlcat(char *, const char *src, size_t siz)
Definition: util-strlcatu.c:45
SCSyslogGetFacilityMap
SCEnumCharMap * SCSyslogGetFacilityMap(void)
returns the syslog facility enum map
Definition: util-syslog.c:57
SCMutexUnlock
#define SCMutexUnlock(mut)
Definition: threads-debug.h:119
SCLogConfig_::op_ifaces_cnt
uint8_t op_ifaces_cnt
Definition: util-debug.h:183
LOG_NOTICE
#define LOG_NOTICE
Definition: win32-syslog.h:44
SCTIME_FROM_TIMEVAL
#define SCTIME_FROM_TIMEVAL(tv)
Definition: util-time.h:79
SCLogConfig_::log_level
SCLogLevel log_level
Definition: util-debug.h:172
SC_LOG_OP_IFACE_MAX
@ SC_LOG_OP_IFACE_MAX
Definition: util-debug.h:68
SCLogOPIfaceCtx_::iface
SCLogOPIface iface
Definition: util-debug.h:116
util-time.h
SCLogWarning
#define SCLogWarning(...)
Macro used to log WARNING messages.
Definition: util-debug.h:249
SCLogErr
void SCLogErr(int x, const char *file, const char *func, const int line, const char *module, const char *fmt,...)
Definition: util-debug.c:746
GetProgramVersion
const char * GetProgramVersion(void)
get string with program version
Definition: suricata.c:1128
SCLogOPBuffer_::log_format
const char * log_format
Definition: util-debug.h:109
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:300
SCLogOPIfaceCtx_::file
const char * file
Definition: util-debug.h:122
SC_LOG_ENV_LOG_FILE
#define SC_LOG_ENV_LOG_FILE
Definition: util-debug.h:38
SCLocalTime
struct tm * SCLocalTime(time_t timep, struct tm *result)
Definition: util-time.c:267
SCLogMatchFGFilterWL
int SCLogMatchFGFilterWL(const char *file, const char *function, int line)
Checks if there is a match for the incoming log_message with any of the FG filters....
Definition: util-debug-filters.c:294
sc_log_module_cleaned
int sc_log_module_cleaned
Used to indicate whether the logging module has been cleaned or not.
Definition: util-debug.c:111
SCLogConfig_::startup_message
char * startup_message
Definition: util-debug.h:171
SCLogOPBuffer_::msg
char msg[SC_LOG_MAX_LOG_MSG_LEN]
Definition: util-debug.h:107
SCLogInitData_::global_log_level
SCLogLevel global_log_level
Definition: util-debug.h:153
SC_OK
@ SC_OK
Definition: util-error.h:27
SCTime_t
Definition: util-time.h:40
SCLogRegisterTests
void SCLogRegisterTests(void)
Definition: util-debug.c:1821
SC_LOG_DEF_LOG_FILE
#define SC_LOG_DEF_LOG_FILE
Definition: util-debug.h:96
SC_LOG_OP_IFACE_FILE
@ SC_LOG_OP_IFACE_FILE
Definition: util-debug.h:66
setenv
void setenv(const char *name, const char *value, int overwrite)
SCLogInfo
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:224
SCLogLevel
SCLogLevel
The various log levels NOTE: when adding new level, don't forget to update SCLogMapLogLevelToSyslogLe...
Definition: util-debug.h:48
SCMutexInit
#define SCMutexInit(mut, mutattrs)
Definition: threads-debug.h:116
LOG_EMERG
#define LOG_EMERG
Definition: win32-syslog.h:39
SC_LOG_WARNING
@ SC_LOG_WARNING
Definition: util-debug.h:52
SCLogInitData_::op_filter
const char * op_filter
Definition: util-debug.h:159
SC_LOG_MAX_LOG_FORMAT_LEN
#define SC_LOG_MAX_LOG_FORMAT_LEN
Definition: util-debug.h:87
SCGetThreadIdLong
#define SCGetThreadIdLong(...)
Definition: threads.h:255
sc_log_op_iface_map
SCEnumCharMap sc_log_op_iface_map[]
Definition: util-debug.c:68
ConfNodeLookupChild
ConfNode * ConfNodeLookupChild(const ConfNode *node, const char *name)
Lookup a child configuration node by name.
Definition: conf.c:786
SC_LOG_FMT_SUBSYSTEM
#define SC_LOG_FMT_SUBSYSTEM
Definition: util-debug.h:197
util-conf.h
SCMapEnumValueToName
const char * SCMapEnumValueToName(int enum_value, SCEnumCharMap *table)
Maps an enum value to a string name, from the supplied table.
Definition: util-enum.c:68
SCLogPrintFDFilters
int SCLogPrintFDFilters(void)
Prints the FG filters(both WL and BL). Used for debugging purposes.
Definition: util-debug-filters.c:812
SCMapEnumNameToValue
int SCMapEnumNameToValue(const char *enum_name, SCEnumCharMap *table)
Maps a string name to an enum value from the supplied table. Please specify the last element of any m...
Definition: util-enum.c:40
SCLogMessage
SCError SCLogMessage(const SCLogLevel log_level, const char *file, const unsigned int line, const char *function, const char *module, const char *message)
Adds the global log_format to the outgoing buffer.
Definition: util-debug.c:656
suricata-common.h
util-path.h
SC_LOG_DEF_LOG_LEVEL
#define SC_LOG_DEF_LOG_LEVEL
Definition: util-debug.h:90
SCEnumCharMap_
Definition: util-enum.h:27
SC_LOG_ENV_LOG_OP_FILTER
#define SC_LOG_ENV_LOG_OP_FILTER
Definition: util-debug.h:41
SCLogConfig_::log_format
char * log_format
Definition: util-debug.h:173
ConfNode_::name
char * name
Definition: conf.h:33
SCLogOPIfaceCtx_::next
struct SCLogOPIfaceCtx_ * next
Definition: util-debug.h:141
SCTIME_SECS
#define SCTIME_SECS(t)
Definition: util-time.h:57
SCError
SCError
Definition: util-error.h:26
SC_LOG_ENV_LOG_FORMAT
#define SC_LOG_ENV_LOG_FORMAT
Definition: util-debug.h:40
PathIsAbsolute
int PathIsAbsolute(const char *path)
Check if a path is absolute.
Definition: util-path.c:44
SC_LOG_PERF
@ SC_LOG_PERF
Definition: util-debug.h:55
SCLogConfig_
Holds the config state used by the logging api.
Definition: util-debug.h:170
SC_LOG_FMT_LOG_SLEVEL
#define SC_LOG_FMT_LOG_SLEVEL
Definition: util-debug.h:193
SCLogInitData_::op_ifaces_cnt
uint8_t op_ifaces_cnt
Definition: util-debug.h:164
SCLogOPIfaceCtx_::rotation_flag
int rotation_flag
Definition: util-debug.h:127
sc_log_fd_filters_present
int sc_log_fd_filters_present
Definition: util-debug-filters.c:39
SCStrdup
#define SCStrdup(s)
Definition: util-mem.h:56
FatalError
#define FatalError(...)
Definition: util-debug.h:502
LOG_WARNING
#define LOG_WARNING
Definition: win32-syslog.h:43
SC_LOG_OP_IFACE_SYSLOG
@ SC_LOG_OP_IFACE_SYSLOG
Definition: util-debug.h:67
SCLogAllocLogInitData
SCLogInitData * SCLogAllocLogInitData(void)
Returns a pointer to a new SCLogInitData. This is a public interface intended to be used after the lo...
Definition: util-debug.c:1263
SC_LOG_DEF_LOG_FORMAT_REL_CONFIG
#define SC_LOG_DEF_LOG_FORMAT_REL_CONFIG
Definition: util-debug.h:80
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
ConfigGetLogDirectory
const char * ConfigGetLogDirectory(void)
Definition: util-conf.c:38
str
#define str(s)
Definition: suricata-common.h:291
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:261
head
Flow * head
Definition: flow-hash.h:1
SCFree
#define SCFree(p)
Definition: util-mem.h:61
ConfNode_
Definition: conf.h:32
SC_LOG_MAX_LOG_MSG_LEN
#define SC_LOG_MAX_LOG_MSG_LEN
Definition: util-debug.h:84
SCLogOPBuffer_::temp
char * temp
Definition: util-debug.h:108
SC_LOG_FMT_FUNCTION
#define SC_LOG_FMT_FUNCTION
Definition: util-debug.h:196
SC_LOG_FMT_PID
#define SC_LOG_FMT_PID
Definition: util-debug.h:189
ConfValIsFalse
int ConfValIsFalse(const char *val)
Check if a value is false.
Definition: conf.c:562
SCLogRemoveFDFilter
int SCLogRemoveFDFilter(const char *function)
Removes a Function-Dependent(FD) filter.
Definition: util-debug-filters.c:752
SCLogPrintFGFilters
int SCLogPrintFGFilters(void)
Prints the FG filters(both WL and BL). Used for debugging purposes.
Definition: util-debug-filters.c:411
SC_LOG_NONE
@ SC_LOG_NONE
Definition: util-debug.h:50
sc_log_global_log_level
SCLogLevel sc_log_global_log_level
Holds the global log level. Is the same as sc_log_config->log_level.
Definition: util-debug.c:101
SCLogAddFGFilterBL
int SCLogAddFGFilterBL(const char *file, const char *function, int line)
Adds a Blacklist(BL) fine-grained(FG) filter. A FG filter BL filter allows messages that don't match ...
Definition: util-debug-filters.c:354
SC_LOG_FMT_TID
#define SC_LOG_FMT_TID
Definition: util-debug.h:190
suricata.h
SCLogOPIfaceCtx_::file_d
FILE * file_d
Definition: util-debug.h:124
SCLogLoadConfig
void SCLogLoadConfig(int daemon, int verbose, uint32_t userid, uint32_t groupid)
Definition: util-debug.c:1440
SCLogAppendOPIfaceCtx
void SCLogAppendOPIfaceCtx(SCLogOPIfaceCtx *iface_ctx, SCLogInitData *sc_lid)
Appends an output_interface to the output_interface list sent in head.
Definition: util-debug.c:1323
SC_LOG_FMT_TIME
#define SC_LOG_FMT_TIME
Definition: util-debug.h:187
SCLogInitData_::startup_message
const char * startup_message
Definition: util-debug.h:150
SCLogAddFDFilter
int SCLogAddFDFilter(const char *function)
Adds a Function-Dependent(FD) filter.
Definition: util-debug-filters.c:664
msg
const char * msg
Definition: app-layer-htp.c:579
openlog
#define openlog(__ident, __option, __facility)
Definition: win32-syslog.h:76
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
util-enum.h
SCMutexDestroy
#define SCMutexDestroy
Definition: threads-debug.h:120
SC_LOG_FMT_LINE
#define SC_LOG_FMT_LINE
Definition: util-debug.h:195
SCLogInitData_::op_ifaces
SCLogOPIfaceCtx * op_ifaces
Definition: util-debug.h:162
SCLogGetLogLevel
SCLogLevel SCLogGetLogLevel(void)
Definition: util-debug.c:1078
SC_LOG_OP_IFACE_CONSOLE
@ SC_LOG_OP_IFACE_CONSOLE
Definition: util-debug.h:65
SCMutex
#define SCMutex
Definition: threads-debug.h:114
SCLogDebugEnabled
int SCLogDebugEnabled(void)
Returns whether debug messages are enabled to be logged or not.
Definition: util-debug.c:771
SC_LOG_DEF_FILE_FORMAT
#define SC_LOG_DEF_FILE_FORMAT
Definition: util-debug.h:77
SC_LOG_DEF_LOG_FORMAT_REL_NOTICE
#define SC_LOG_DEF_LOG_FORMAT_REL_NOTICE
Definition: util-debug.h:78
output.h
sc_log_slevel_map
SCEnumCharMap sc_log_slevel_map[]
Definition: util-debug.c:54
LOG_INFO
#define LOG_INFO
Definition: win32-syslog.h:45
LOG_ERR
#define LOG_ERR
Definition: win32-syslog.h:42
ConfNodeLookupChildValue
const char * ConfNodeLookupChildValue(const ConfNode *node, const char *name)
Lookup the value of a child configuration node by name.
Definition: conf.c:814
SC_LOG_FMT_TM
#define SC_LOG_FMT_TM
Definition: util-debug.h:191