diff --git a/src/output.h b/src/output.h index 674f3c3f17..ba47dca294 100644 --- a/src/output.h +++ b/src/output.h @@ -28,6 +28,7 @@ #include "tm-threads.h" #define DEFAULT_LOG_MODE_APPEND "yes" +#define DEFAULT_LOG_FILETYPE "regular" typedef struct OutputModule_ { char *name; diff --git a/src/util-error.c b/src/util-error.c index 4dfb7e522a..a09c245966 100644 --- a/src/util-error.c +++ b/src/util-error.c @@ -181,7 +181,7 @@ const char * SCErrorToString(SCError err) CASE_CODE (SC_ERR_LIBCAP_NG_REQUIRED); CASE_CODE (SC_ERR_LIBNET11_INCOMPATIBLE_WITH_LIBCAP_NG); CASE_CODE (SC_WARN_FLOW_EMERGENCY); - CASE_CODE (SC_ERR_SVC); + CASE_CODE (SC_ERR_SVC); CASE_CODE (SC_ERR_ERF_DAG_OPEN_FAILED); CASE_CODE (SC_ERR_ERF_DAG_STREAM_OPEN_FAILED); CASE_CODE (SC_ERR_ERF_DAG_STREAM_START_FAILED); @@ -212,6 +212,7 @@ const char * SCErrorToString(SCError err) CASE_CODE (SC_ERR_CMD_LINE); CASE_CODE (SC_ERR_SIZE_PARSE); CASE_CODE (SC_ERR_RAWBYTES_FILE_DATA); + CASE_CODE (SC_ERR_SOCKET); default: return "UNKNOWN_ERROR"; diff --git a/src/util-error.h b/src/util-error.h index 3b98e4fd8b..2a6c9d96d3 100644 --- a/src/util-error.h +++ b/src/util-error.h @@ -227,6 +227,7 @@ typedef enum { SC_ERR_MAGIC_LOAD, SC_ERR_SIZE_PARSE, SC_ERR_RAWBYTES_FILE_DATA, + SC_ERR_SOCKET, } SCError; const char *SCErrorToString(SCError); diff --git a/src/util-logopenfile.c b/src/util-logopenfile.c new file mode 100644 index 0000000000..a9509a3d03 --- /dev/null +++ b/src/util-logopenfile.c @@ -0,0 +1,165 @@ +/* vi: set et ts=4: */ +/* Copyright (C) 2007-2011 Open Information Security Foundation + * + * You can copy, redistribute or modify this Program under the terms of + * the GNU General Public License version 2 as published by the Free + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/** + * \file + * + * \author Mike Pomraning + * + * File-like output for logging: regular files and sockets. + */ +#include +#include + +#include "suricata-common.h" /* errno.h, string.h, etc. */ +#include "tm-modules.h" /* LogFileCtx */ +#include "conf.h" /* ConfNode, etc. */ +#include "output.h" /* DEFAULT_LOG_* */ + +/** \brief connect to the indicated local stream socket, logging any errors + * \param path filesystem path to connect to + * \retval FILE* on success (fdopen'd wrapper of underlying socket) + * \retval NULL on error + */ +static FILE * +SCLogOpenUnixSocketFp(const char *path, int sock_type) +{ + struct sockaddr_un sun = {0}; + int s = -1; + FILE * ret = NULL; + + s = socket(PF_UNIX, sock_type, 0); + if (s < 0) goto err; + + sun.sun_family = AF_UNIX; + strncpy(sun.sun_path, path, sizeof(sun.sun_path) - 1); + + if (connect(s, (const struct sockaddr *)&sun, sizeof(sun)) < 0) + goto err; + + ret = fdopen(s, "w"); + if (ret == NULL) + goto err; + + return ret; + +err: + SCLogError(SC_ERR_SOCKET, "Error connecting to socket \"%s\": %s", + path, strerror(errno)); + + if (s >= 0) + close(s); + + return NULL; +} + +/** \brief open the indicated file, logging any errors + * \param path filesystem path to open + * \param append_setting open file with O_APPEND: "yes" or "no" + * \retval FILE* on success + * \retval NULL on error + */ +static FILE * +SCLogOpenFileFp(const char *path, const char *append_setting) +{ + FILE *ret = NULL; + + if (strcasecmp(append_setting, "yes") == 0) { + ret = fopen(path, "a"); + } else { + ret = fopen(path, "w"); + } + + if (ret == NULL) + SCLogError(SC_ERR_FOPEN, "Error opening file: \"%s\": %s", + path, strerror(errno)); + return ret; +} + +/** \brief open a generic output "log file", which may be a regular file or a socket + * \param conf ConfNode structure for the output section in question + * \param log_ctx Log file context allocated by caller + * \param default_filename Default name of file to open, if not specified in ConfNode + * \retval 0 on success + * \retval -1 on error + */ +int +SCConfLogOpenGeneric(ConfNode *conf, + LogFileCtx *log_ctx, + const char *default_filename) +{ + char log_path[PATH_MAX]; + char *log_dir; + const char *filename, *filetype; + + // Arg check + if (conf == NULL || log_ctx == NULL || default_filename == NULL) { + SCLogError(SC_ERR_INVALID_ARGUMENT, + "SCConfLogOpenGeneric(conf %p, ctx %p, default %p) " + "missing an argument", + conf, log_ctx, default_filename); + return -1; + } + if (log_ctx->fp != NULL) { + SCLogError(SC_ERR_INVALID_ARGUMENT, + "SCConfLogOpenGeneric: previously initialized Log CTX " + "encountered"); + return -1; + } + + // Resolve the given config + filename = ConfNodeLookupChildValue(conf, "filename"); + if (filename == NULL) + filename = default_filename; + + if (ConfGet("default-log-dir", &log_dir) != 1) + log_dir = DEFAULT_LOG_DIR; + + snprintf(log_path, PATH_MAX, "%s/%s", log_dir, filename); + + filetype = ConfNodeLookupChildValue(conf, "filetype"); + if (filetype == NULL) + filetype = DEFAULT_LOG_FILETYPE; + + // Now, what have we been asked to open? + if (strcasecmp(filetype, "unix_stream") == 0) { + log_ctx->fp = SCLogOpenUnixSocketFp(log_path, SOCK_STREAM); + } else if (strcasecmp(filetype, "unix_dgram") == 0) { + log_ctx->fp = SCLogOpenUnixSocketFp(log_path, SOCK_DGRAM); + } else if (strcasecmp(filetype, DEFAULT_LOG_FILETYPE) == 0) { + const char *append; + + append = ConfNodeLookupChildValue(conf, "append"); + if (append == NULL) + append = DEFAULT_LOG_MODE_APPEND; + log_ctx->fp = SCLogOpenFileFp(log_path, append); + } else { + SCLogError(SC_ERR_INVALID_YAML_CONF_ENTRY, "Invalid entry for " + "%s.type. Expected \"regular\" (default), \"unix_stream\" " + "or \"unix_dgram\"", + conf->name); + } + + if (log_ctx->fp == NULL) + return -1; // Error already logged by Open...Fp routine + + SCLogInfo("%s output device (%s) initialized: %s", conf->name, filetype, + filename); + + return 0; +} diff --git a/src/util-logopenfile.h b/src/util-logopenfile.h new file mode 100644 index 0000000000..92aa345fee --- /dev/null +++ b/src/util-logopenfile.h @@ -0,0 +1,32 @@ +/* Copyright (C) 2007-2011 Open Information Security Foundation + * + * You can copy, redistribute or modify this Program under the terms of + * the GNU General Public License version 2 as published by the Free + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/** + * \file + * + * \author Mike Pomraning + */ + +#ifndef __UTIL_LOGOPENFILE_H__ +#define __UTIL_LOGOPENFILE_H__ + +#include "conf.h" /* ConfNode */ +#include "tm-modules.h" /* LogFileCtx */ + +int SCConfLogOpenGeneric(ConfNode *conf, LogFileCtx *, const char *); + +#endif /* __UTIL_LOGOPENFILE_H__ */