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