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