suricata
util-logopenfile.c
Go to the documentation of this file.
1 /* vi: set et ts=4: */
2 /* Copyright (C) 2007-2014 Open Information Security Foundation
3  *
4  * You can copy, redistribute or modify this Program under the terms of
5  * the GNU General Public License version 2 as published by the Free
6  * Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * version 2 along with this program; if not, write to the Free Software
15  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16  * 02110-1301, USA.
17  */
18 
19 /**
20  * \file
21  *
22  * \author Mike Pomraning <mpomraning@qualys.com>
23  *
24  * File-like output for logging: regular files and sockets.
25  */
26 
27 #include "suricata-common.h" /* errno.h, string.h, etc. */
28 #include "tm-modules.h" /* LogFileCtx */
29 #include "conf.h" /* ConfNode, etc. */
30 #include "output.h" /* DEFAULT_LOG_* */
31 #include "util-byte.h"
32 #include "util-path.h"
33 #include "util-logopenfile.h"
34 #include "util-logopenfile-tile.h"
35 
36 #if defined(HAVE_SYS_UN_H) && defined(HAVE_SYS_SOCKET_H) && defined(HAVE_SYS_TYPES_H)
37 #define BUILD_WITH_UNIXSOCKET
38 #include <sys/types.h>
39 #include <sys/socket.h>
40 #include <sys/un.h>
41 #endif
42 
43 #ifdef HAVE_LIBHIREDIS
44 #include "util-log-redis.h"
45 #endif /* HAVE_LIBHIREDIS */
46 
47 #ifdef BUILD_WITH_UNIXSOCKET
48 /** \brief connect to the indicated local stream socket, logging any errors
49  * \param path filesystem path to connect to
50  * \param log_err, non-zero if connect failure should be logged.
51  * \retval FILE* on success (fdopen'd wrapper of underlying socket)
52  * \retval NULL on error
53  */
54 static FILE *
55 SCLogOpenUnixSocketFp(const char *path, int sock_type, int log_err)
56 {
57  struct sockaddr_un saun;
58  int s = -1;
59  FILE * ret = NULL;
60 
61  memset(&saun, 0x00, sizeof(saun));
62 
63  s = socket(PF_UNIX, sock_type, 0);
64  if (s < 0) goto err;
65 
66  saun.sun_family = AF_UNIX;
67  strlcpy(saun.sun_path, path, sizeof(saun.sun_path));
68 
69  if (connect(s, (const struct sockaddr *)&saun, sizeof(saun)) < 0)
70  goto err;
71 
72  ret = fdopen(s, "w");
73  if (ret == NULL)
74  goto err;
75 
76  return ret;
77 
78 err:
79  if (log_err)
81  "Error connecting to socket \"%s\": %s (will keep trying)",
82  path, strerror(errno));
83 
84  if (s >= 0)
85  close(s);
86 
87  return NULL;
88 }
89 
90 /**
91  * \brief Attempt to reconnect a disconnected (or never-connected) Unix domain socket.
92  * \retval 1 if it is now connected; otherwise 0
93  */
94 static int SCLogUnixSocketReconnect(LogFileCtx *log_ctx)
95 {
96  int disconnected = 0;
97  if (log_ctx->fp) {
99  "Write error on Unix socket \"%s\": %s; reconnecting...",
100  log_ctx->filename, strerror(errno));
101  fclose(log_ctx->fp);
102  log_ctx->fp = NULL;
103  log_ctx->reconn_timer = 0;
104  disconnected = 1;
105  }
106 
107  struct timeval tv;
108  uint64_t now;
109  gettimeofday(&tv, NULL);
110  now = (uint64_t)tv.tv_sec * 1000;
111  now += tv.tv_usec / 1000; /* msec resolution */
112  if (log_ctx->reconn_timer != 0 &&
113  (now - log_ctx->reconn_timer) < LOGFILE_RECONN_MIN_TIME) {
114  /* Don't bother to try reconnecting too often. */
115  return 0;
116  }
117  log_ctx->reconn_timer = now;
118 
119  log_ctx->fp = SCLogOpenUnixSocketFp(log_ctx->filename, log_ctx->sock_type, 0);
120  if (log_ctx->fp) {
121  /* Connected at last (or reconnected) */
122  SCLogNotice("Reconnected socket \"%s\"", log_ctx->filename);
123  } else if (disconnected) {
124  SCLogWarning(SC_ERR_SOCKET, "Reconnect failed: %s (will keep trying)",
125  strerror(errno));
126  }
127 
128  return log_ctx->fp ? 1 : 0;
129 }
130 
131 static int SCLogFileWriteSocket(const char *buffer, int buffer_len,
132  LogFileCtx *ctx)
133 {
134  int tries = 0;
135  int ret = 0;
136  bool reopen = false;
137 #ifdef BUILD_WITH_UNIXSOCKET
138  if (ctx->fp == NULL && ctx->is_sock) {
139  SCLogUnixSocketReconnect(ctx);
140  }
141 #endif
142 tryagain:
143  ret = -1;
144  reopen = 0;
145  errno = 0;
146  if (ctx->fp != NULL) {
147  int fd = fileno(ctx->fp);
148  ssize_t size = send(fd, buffer, buffer_len, ctx->send_flags);
149  if (size > -1) {
150  ret = 0;
151  } else {
152  if (errno == EAGAIN || errno == EWOULDBLOCK) {
153  SCLogDebug("Socket would block, dropping event.");
154  } else if (errno == EINTR) {
155  if (tries++ == 0) {
156  SCLogDebug("Interrupted system call, trying again.");
157  goto tryagain;
158  }
159  SCLogDebug("Too many interrupted system calls, "
160  "dropping event.");
161  } else {
162  /* Some other error. Assume badness and reopen. */
163  SCLogDebug("Send failed: %s", strerror(errno));
164  reopen = true;
165  }
166  }
167  }
168 
169  if (reopen && tries++ == 0) {
170  if (SCLogUnixSocketReconnect(ctx)) {
171  goto tryagain;
172  }
173  }
174 
175  if (ret == -1) {
176  ctx->dropped++;
177  }
178 
179  return ret;
180 }
181 #endif /* BUILD_WITH_UNIXSOCKET */
182 
183 /**
184  * \brief Write buffer to log file.
185  * \retval 0 on failure; otherwise, the return value of fwrite (number of
186  * characters successfully written).
187  */
188 static int SCLogFileWrite(const char *buffer, int buffer_len, LogFileCtx *log_ctx)
189 {
190  SCMutexLock(&log_ctx->fp_mutex);
191  int ret = 0;
192 
193 #ifdef BUILD_WITH_UNIXSOCKET
194  if (log_ctx->is_sock) {
195  ret = SCLogFileWriteSocket(buffer, buffer_len, log_ctx);
196  } else
197 #endif
198  {
199 
200  /* Check for rotation. */
201  if (log_ctx->rotation_flag) {
202  log_ctx->rotation_flag = 0;
203  SCConfLogReopen(log_ctx);
204  }
205 
206  if (log_ctx->flags & LOGFILE_ROTATE_INTERVAL) {
207  time_t now = time(NULL);
208  if (now >= log_ctx->rotate_time) {
209  SCConfLogReopen(log_ctx);
210  log_ctx->rotate_time = now + log_ctx->rotate_interval;
211  }
212  }
213 
214  if (log_ctx->fp) {
215  clearerr(log_ctx->fp);
216  ret = fwrite(buffer, buffer_len, 1, log_ctx->fp);
217  fflush(log_ctx->fp);
218  }
219  }
220 
221  SCMutexUnlock(&log_ctx->fp_mutex);
222 
223  return ret;
224 }
225 
226 /** \brief generate filename based on pattern
227  * \param pattern pattern to use
228  * \retval char* on success
229  * \retval NULL on error
230  */
231 static char *SCLogFilenameFromPattern(const char *pattern)
232 {
233  char *filename = SCMalloc(PATH_MAX);
234  if (filename == NULL) {
235  return NULL;
236  }
237 
238  int rc = SCTimeToStringPattern(time(NULL), pattern, filename, PATH_MAX);
239  if (rc != 0) {
240  SCFree(filename);
241  return NULL;
242  }
243 
244  return filename;
245 }
246 
247 static void SCLogFileClose(LogFileCtx *log_ctx)
248 {
249  if (log_ctx->fp)
250  fclose(log_ctx->fp);
251 }
252 
253 /** \brief open the indicated file, logging any errors
254  * \param path filesystem path to open
255  * \param append_setting open file with O_APPEND: "yes" or "no"
256  * \param mode permissions to set on file
257  * \retval FILE* on success
258  * \retval NULL on error
259  */
260 static FILE *
261 SCLogOpenFileFp(const char *path, const char *append_setting, uint32_t mode)
262 {
263  FILE *ret = NULL;
264 
265  char *filename = SCLogFilenameFromPattern(path);
266  if (filename == NULL) {
267  return NULL;
268  }
269 
270  int rc = SCCreateDirectoryTree(filename, false);
271  if (rc < 0) {
272  SCFree(filename);
273  return NULL;
274  }
275 
276  if (ConfValIsTrue(append_setting)) {
277  ret = fopen(filename, "a");
278  } else {
279  ret = fopen(filename, "w");
280  }
281 
282  if (ret == NULL) {
283  SCLogError(SC_ERR_FOPEN, "Error opening file: \"%s\": %s",
284  filename, strerror(errno));
285  } else {
286  if (mode != 0) {
287  int r = chmod(filename, mode);
288  if (r < 0) {
289  SCLogWarning(SC_WARN_CHMOD, "Could not chmod %s to %u: %s",
290  filename, mode, strerror(errno));
291  }
292  }
293  }
294 
295  SCFree(filename);
296  return ret;
297 }
298 
299 /** \brief open the indicated file remotely over PCIe to a host
300  * \param path filesystem path to open
301  * \param append_setting open file with O_APPEND: "yes" or "no"
302  * \retval FILE* on success
303  * \retval NULL on error
304  */
305 static PcieFile *SCLogOpenPcieFp(LogFileCtx *log_ctx, const char *path,
306  const char *append_setting)
307 {
308 #ifndef __tile__
310  "PCIe logging only supported on Tile-Gx Architecture.");
311  return NULL;
312 #else
313  return TileOpenPcieFp(log_ctx, path, append_setting);
314 #endif
315 }
316 
317 /** \brief open a generic output "log file", which may be a regular file or a socket
318  * \param conf ConfNode structure for the output section in question
319  * \param log_ctx Log file context allocated by caller
320  * \param default_filename Default name of file to open, if not specified in ConfNode
321  * \param rotate Register the file for rotation in HUP.
322  * \retval 0 on success
323  * \retval -1 on error
324  */
325 int
327  LogFileCtx *log_ctx,
328  const char *default_filename,
329  int rotate)
330 {
331  char log_path[PATH_MAX];
332  const char *log_dir;
333  const char *filename, *filetype;
334 
335  // Arg check
336  if (conf == NULL || log_ctx == NULL || default_filename == NULL) {
338  "SCConfLogOpenGeneric(conf %p, ctx %p, default %p) "
339  "missing an argument",
340  conf, log_ctx, default_filename);
341  return -1;
342  }
343  if (log_ctx->fp != NULL) {
345  "SCConfLogOpenGeneric: previously initialized Log CTX "
346  "encountered");
347  return -1;
348  }
349 
350  // Resolve the given config
351  filename = ConfNodeLookupChildValue(conf, "filename");
352  if (filename == NULL)
353  filename = default_filename;
354 
355  log_dir = ConfigGetLogDirectory();
356 
357  if (PathIsAbsolute(filename)) {
358  snprintf(log_path, PATH_MAX, "%s", filename);
359  } else {
360  snprintf(log_path, PATH_MAX, "%s/%s", log_dir, filename);
361  }
362 
363  /* Rotate log file based on time */
364  const char *rotate_int = ConfNodeLookupChildValue(conf, "rotate-interval");
365  if (rotate_int != NULL) {
366  time_t now = time(NULL);
367  log_ctx->flags |= LOGFILE_ROTATE_INTERVAL;
368 
369  /* Use a specific time */
370  if (strcmp(rotate_int, "minute") == 0) {
371  log_ctx->rotate_time = now + SCGetSecondsUntil(rotate_int, now);
372  log_ctx->rotate_interval = 60;
373  } else if (strcmp(rotate_int, "hour") == 0) {
374  log_ctx->rotate_time = now + SCGetSecondsUntil(rotate_int, now);
375  log_ctx->rotate_interval = 3600;
376  } else if (strcmp(rotate_int, "day") == 0) {
377  log_ctx->rotate_time = now + SCGetSecondsUntil(rotate_int, now);
378  log_ctx->rotate_interval = 86400;
379  }
380 
381  /* Use a timer */
382  else {
383  log_ctx->rotate_interval = SCParseTimeSizeString(rotate_int);
384  if (log_ctx->rotate_interval == 0) {
386  "invalid rotate-interval value");
387  exit(EXIT_FAILURE);
388  }
389  log_ctx->rotate_time = now + log_ctx->rotate_interval;
390  }
391  }
392 
393  filetype = ConfNodeLookupChildValue(conf, "filetype");
394  if (filetype == NULL)
395  filetype = DEFAULT_LOG_FILETYPE;
396 
397  const char *filemode = ConfNodeLookupChildValue(conf, "filemode");
398  uint32_t mode = 0;
399  if (filemode != NULL &&
400  ByteExtractStringUint32(&mode, 8, strlen(filemode),
401  filemode) > 0) {
402  log_ctx->filemode = mode;
403  }
404 
405  const char *append = ConfNodeLookupChildValue(conf, "append");
406  if (append == NULL)
407  append = DEFAULT_LOG_MODE_APPEND;
408 
409  /* JSON flags */
410 #ifdef HAVE_LIBJANSSON
411  log_ctx->json_flags = JSON_PRESERVE_ORDER|JSON_COMPACT|
412  JSON_ENSURE_ASCII|JSON_ESCAPE_SLASH;
413 
414  ConfNode *json_flags = ConfNodeLookupChild(conf, "json");
415 
416  if (json_flags != 0) {
417  const char *preserve_order = ConfNodeLookupChildValue(json_flags,
418  "preserve-order");
419  if (preserve_order != NULL && ConfValIsFalse(preserve_order))
420  log_ctx->json_flags &= ~(JSON_PRESERVE_ORDER);
421 
422  const char *compact = ConfNodeLookupChildValue(json_flags, "compact");
423  if (compact != NULL && ConfValIsFalse(compact))
424  log_ctx->json_flags &= ~(JSON_COMPACT);
425 
426  const char *ensure_ascii = ConfNodeLookupChildValue(json_flags,
427  "ensure-ascii");
428  if (ensure_ascii != NULL && ConfValIsFalse(ensure_ascii))
429  log_ctx->json_flags &= ~(JSON_ENSURE_ASCII);
430 
431  const char *escape_slash = ConfNodeLookupChildValue(json_flags,
432  "escape-slash");
433  if (escape_slash != NULL && ConfValIsFalse(escape_slash))
434  log_ctx->json_flags &= ~(JSON_ESCAPE_SLASH);
435  }
436 #endif /* HAVE_LIBJANSSON */
437 
438  // Now, what have we been asked to open?
439  if (strcasecmp(filetype, "unix_stream") == 0) {
440 #ifdef BUILD_WITH_UNIXSOCKET
441  /* Don't bail. May be able to connect later. */
442  log_ctx->is_sock = 1;
443  log_ctx->sock_type = SOCK_STREAM;
444  log_ctx->fp = SCLogOpenUnixSocketFp(log_path, SOCK_STREAM, 1);
445 #else
446  return -1;
447 #endif
448  } else if (strcasecmp(filetype, "unix_dgram") == 0) {
449 #ifdef BUILD_WITH_UNIXSOCKET
450  /* Don't bail. May be able to connect later. */
451  log_ctx->is_sock = 1;
452  log_ctx->sock_type = SOCK_DGRAM;
453  log_ctx->fp = SCLogOpenUnixSocketFp(log_path, SOCK_DGRAM, 1);
454 #else
455  return -1;
456 #endif
457  } else if (strcasecmp(filetype, DEFAULT_LOG_FILETYPE) == 0 ||
458  strcasecmp(filetype, "file") == 0) {
459  log_ctx->fp = SCLogOpenFileFp(log_path, append, log_ctx->filemode);
460  if (log_ctx->fp == NULL)
461  return -1; // Error already logged by Open...Fp routine
462  log_ctx->is_regular = 1;
463  if (rotate) {
465  }
466  } else if (strcasecmp(filetype, "pcie") == 0) {
467  log_ctx->pcie_fp = SCLogOpenPcieFp(log_ctx, log_path, append);
468  if (log_ctx->pcie_fp == NULL)
469  return -1; // Error already logged by Open...Fp routine
470 #ifdef HAVE_LIBHIREDIS
471  } else if (strcasecmp(filetype, "redis") == 0) {
472  ConfNode *redis_node = ConfNodeLookupChild(conf, "redis");
473  if (SCConfLogOpenRedis(redis_node, log_ctx) < 0) {
474  SCLogError(SC_ERR_REDIS, "failed to open redis output");
475  return -1;
476  }
477  log_ctx->type = LOGFILE_TYPE_REDIS;
478 #endif
479  } else {
480  SCLogError(SC_ERR_INVALID_YAML_CONF_ENTRY, "Invalid entry for "
481  "%s.filetype. Expected \"regular\" (default), \"unix_stream\", "
482  "\"pcie\" "
483  "or \"unix_dgram\"",
484  conf->name);
485  }
486  log_ctx->filename = SCStrdup(log_path);
487  if (unlikely(log_ctx->filename == NULL)) {
489  "Failed to allocate memory for filename");
490  return -1;
491  }
492 
493 #ifdef BUILD_WITH_UNIXSOCKET
494  /* If a socket and running live, do non-blocking writes. */
495  if (log_ctx->is_sock && !IsRunModeOffline(RunmodeGetCurrent())) {
496  SCLogInfo("Setting logging socket of non-blocking in live mode.");
497  log_ctx->send_flags |= MSG_DONTWAIT;
498  }
499 #endif
500  SCLogInfo("%s output device (%s) initialized: %s", conf->name, filetype,
501  filename);
502 
503  return 0;
504 }
505 
506 /**
507  * \brief Reopen a regular log file with the side-affect of truncating it.
508  *
509  * This is useful to clear the log file and start a new one, or to
510  * re-open the file after its been moved by something external
511  * (eg. logrotate).
512  */
514 {
515  if (!log_ctx->is_regular) {
516  /* Not supported and not needed on non-regular files. */
517  return 0;
518  }
519 
520  if (log_ctx->filename == NULL) {
522  "Can't re-open LogFileCtx without a filename.");
523  return -1;
524  }
525 
526  fclose(log_ctx->fp);
527 
528  /* Reopen the file. Append is forced in case the file was not
529  * moved as part of a rotation process. */
530  SCLogDebug("Reopening log file %s.", log_ctx->filename);
531  log_ctx->fp = SCLogOpenFileFp(log_ctx->filename, "yes", log_ctx->filemode);
532  if (log_ctx->fp == NULL) {
533  return -1; // Already logged by Open..Fp routine.
534  }
535 
536  return 0;
537 }
538 
539 /** \brief LogFileNewCtx() Get a new LogFileCtx
540  * \retval LogFileCtx * pointer if succesful, NULL if error
541  * */
543 {
544  LogFileCtx* lf_ctx;
545  lf_ctx = (LogFileCtx*)SCMalloc(sizeof(LogFileCtx));
546 
547  if (lf_ctx == NULL)
548  return NULL;
549  memset(lf_ctx, 0, sizeof(LogFileCtx));
550 
551  SCMutexInit(&lf_ctx->fp_mutex,NULL);
552 
553  // Default Write and Close functions
554  lf_ctx->Write = SCLogFileWrite;
555  lf_ctx->Close = SCLogFileClose;
556 
557  return lf_ctx;
558 }
559 
560 /** \brief LogFileFreeCtx() Destroy a LogFileCtx (Close the file and free memory)
561  * \param motcx pointer to the OutputCtx
562  * \retval int 1 if succesful, 0 if error
563  * */
565 {
566  if (lf_ctx == NULL) {
567  SCReturnInt(0);
568  }
569 
570  if (lf_ctx->fp != NULL) {
571  SCMutexLock(&lf_ctx->fp_mutex);
572  lf_ctx->Close(lf_ctx);
573  SCMutexUnlock(&lf_ctx->fp_mutex);
574  }
575 
576  SCMutexDestroy(&lf_ctx->fp_mutex);
577 
578  if (lf_ctx->prefix != NULL) {
579  SCFree(lf_ctx->prefix);
580  lf_ctx->prefix_len = 0;
581  }
582 
583  if(lf_ctx->filename != NULL)
584  SCFree(lf_ctx->filename);
585 
586  if (lf_ctx->sensor_name)
587  SCFree(lf_ctx->sensor_name);
588 
590 
591  SCFree(lf_ctx);
592 
593  SCReturnInt(1);
594 }
595 
596 int LogFileWrite(LogFileCtx *file_ctx, MemBuffer *buffer)
597 {
598  if (file_ctx->type == LOGFILE_TYPE_SYSLOG) {
599  syslog(file_ctx->syslog_setup.alert_syslog_level, "%s",
600  (const char *)MEMBUFFER_BUFFER(buffer));
601  } else if (file_ctx->type == LOGFILE_TYPE_FILE ||
602  file_ctx->type == LOGFILE_TYPE_UNIX_DGRAM ||
603  file_ctx->type == LOGFILE_TYPE_UNIX_STREAM)
604  {
605  /* append \n for files only */
606  MemBufferWriteString(buffer, "\n");
607  file_ctx->Write((const char *)MEMBUFFER_BUFFER(buffer),
608  MEMBUFFER_OFFSET(buffer), file_ctx);
609  }
610 #ifdef HAVE_LIBHIREDIS
611  else if (file_ctx->type == LOGFILE_TYPE_REDIS) {
612  SCMutexLock(&file_ctx->fp_mutex);
613  LogFileWriteRedis(file_ctx, (const char *)MEMBUFFER_BUFFER(buffer),
614  MEMBUFFER_OFFSET(buffer));
615  SCMutexUnlock(&file_ctx->fp_mutex);
616  }
617 #endif
618 
619  return 0;
620 }
#define LOGFILE_RECONN_MIN_TIME
PcieFile * pcie_fp
#define SCLogDebug(...)
Definition: util-debug.h:335
#define SCMutexDestroy(x)
#define MemBufferWriteString(dst,...)
Write a string buffer to the Membuffer dst.
Definition: util-buffer.h:162
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: util-strlcpyu.c:43
#define unlikely(expr)
Definition: util-optimize.h:35
time_t rotate_time
SyslogSetup syslog_setup
uint64_t SCGetSecondsUntil(const char *str, time_t epoch)
Get seconds until a time unit changes.
Definition: util-time.c:589
uint8_t is_regular
int LogFileWrite(LogFileCtx *file_ctx, MemBuffer *buffer)
int ByteExtractStringUint32(uint32_t *res, int base, uint16_t len, const char *str)
Definition: util-byte.c:196
ConfNode * ConfNodeLookupChild(const ConfNode *node, const char *name)
Lookup a child configuration node by name.
Definition: conf.c:815
void(* Close)(struct LogFileCtx_ *fp)
int SCTimeToStringPattern(time_t epoch, const char *pattern, char *str, size_t size)
Convert epoch time to string pattern.
Definition: util-time.c:509
const char * ConfNodeLookupChildValue(const ConfNode *node, const char *name)
Lookup the value of a child configuration node by name.
Definition: conf.c:843
void OutputRegisterFileRotationFlag(int *flag)
Register a flag for file rotation notification.
Definition: output.c:868
#define SCMutexUnlock(mut)
#define SCMutexInit(mut, mutattr)
enum LogFileType type
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:294
#define DEFAULT_LOG_FILETYPE
Definition: output.h:31
PcieFile * TileOpenPcieFp(LogFileCtx *log_ctx, const char *path, const char *append_setting)
void OutputUnregisterFileRotationFlag(int *flag)
Unregister a file rotation flag.
Definition: output.c:890
SCMutex fp_mutex
uint32_t filemode
int ConfValIsFalse(const char *val)
Check if a value is false.
Definition: conf.c:591
LogFileCtx * LogFileNewCtx(void)
LogFileNewCtx() Get a new LogFileCtx.
int SCConfLogOpenGeneric(ConfNode *conf, LogFileCtx *log_ctx, const char *default_filename, int rotate)
open a generic output "log file", which may be a regular file or a socket
int PathIsAbsolute(const char *path)
Check if a path is absolute.
Definition: util-path.c:39
char * sensor_name
#define SCReturnInt(x)
Definition: util-debug.h:341
#define SCLogWarning(err_code,...)
Macro used to log WARNING messages.
Definition: util-debug.h:281
#define MEMBUFFER_BUFFER(mem_buffer)
Get the MemBuffers underlying buffer.
Definition: util-buffer.h:50
int ConfValIsTrue(const char *val)
Check if a value is true.
Definition: conf.c:566
uint64_t rotate_interval
Definition: conf.h:32
int(* Write)(const char *buffer, int buffer_len, struct LogFileCtx_ *fp)
const char * ConfigGetLogDirectory()
Definition: util-conf.c:36
#define SCMalloc(a)
Definition: util-mem.h:174
#define DEFAULT_LOG_MODE_APPEND
Definition: output.h:30
int LogFileFreeCtx(LogFileCtx *lf_ctx)
LogFileFreeCtx() Destroy a LogFileCtx (Close the file and free memory)
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:254
#define SCFree(a)
Definition: util-mem.h:236
#define SCLogNotice(...)
Macro used to log NOTICE messages.
Definition: util-debug.h:269
#define MEMBUFFER_OFFSET(mem_buffer)
Get the MemBuffers current offset.
Definition: util-buffer.h:55
bool IsRunModeOffline(int run_mode_to_check)
Definition: runmodes.c:500
char * name
Definition: conf.h:33
int RunmodeGetCurrent(void)
Definition: suricata.c:269
#define SCMutexLock(mut)
uint8_t send_flags
int SCConfLogReopen(LogFileCtx *log_ctx)
Reopen a regular log file with the side-affect of truncating it.
#define syslog(__pri, __fmt, __param)
Definition: win32-syslog.h:78
uint64_t reconn_timer
#define SCStrdup(a)
Definition: util-mem.h:220
uint64_t dropped
int SCCreateDirectoryTree(const char *path, const bool final)
Recursively create a directory.
Definition: util-path.c:86
#define LOGFILE_ROTATE_INTERVAL
uint64_t SCParseTimeSizeString(const char *str)
Parse string containing time size (1m, 1h, etc).
Definition: util-time.c:538