diff --git a/src/Makefile.am b/src/Makefile.am index dd0392e..7cd2be1 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -240,7 +240,8 @@ util-action.c util-action.h \ win32-syslog.h \ util-profiling.c util-profiling.h \ cuda-packet-batcher.c cuda-packet-batcher.h \ -util-ioctl.h util-ioctl.c +util-ioctl.h util-ioctl.c \ +util-logopenfile.h util-logopenfile.c # set the include path found by configure INCLUDES= $(all_includes) diff --git a/src/alert-debuglog.c b/src/alert-debuglog.c index 9f802fd..fb6ab28 100644 --- a/src/alert-debuglog.c +++ b/src/alert-debuglog.c @@ -50,6 +50,8 @@ #include "flow-bit.h" #include "util-var-name.h" +#include "util-logopenfile.h" + #define DEFAULT_LOG_FILENAME "alert-debug.log" #define MODULE_NAME "AlertDebugLog" @@ -444,23 +446,14 @@ OutputCtx *AlertDebugLogInitCtx(ConfNode *conf) LogFileCtx *file_ctx = NULL; file_ctx = LogFileNewCtx(); - if(file_ctx == NULL) { + if (file_ctx == NULL) { SCLogDebug("couldn't create new file_ctx"); goto error; } - const char *filename = ConfNodeLookupChildValue(conf, "filename"); - if (filename == NULL) - filename = DEFAULT_LOG_FILENAME; - - const char *mode = ConfNodeLookupChildValue(conf, "append"); - if (mode == NULL) - mode = DEFAULT_LOG_MODE_APPEND; - - /** fill the new LogFileCtx with the specific AlertDebugLog configuration */ - ret = AlertDebugLogOpenFileCtx(file_ctx, filename, mode); - if(ret < 0) + if (SCConfLogOpenGeneric(conf, file_ctx, DEFAULT_LOG_FILENAME) < 0) { goto error; + } OutputCtx *output_ctx = SCMalloc(sizeof(OutputCtx)); if (output_ctx == NULL) @@ -479,35 +472,3 @@ error: return NULL; } - -/** \brief Read the config set the file pointer, open the file - * \param file_ctx pointer to a created LogFileCtx using LogFileNewCtx() - * \param filename name of log file - * \return -1 if failure, 0 if succesful - * */ -int AlertDebugLogOpenFileCtx(LogFileCtx *file_ctx, const char *filename, const - char *mode) -{ - char log_path[PATH_MAX]; - char *log_dir; - - if (ConfGet("default-log-dir", &log_dir) != 1) - log_dir = DEFAULT_LOG_DIR; - - snprintf(log_path, PATH_MAX, "%s/%s", log_dir, filename); - - if (strcasecmp(mode, "yes") == 0) { - file_ctx->fp = fopen(log_path, "a"); - } else { - file_ctx->fp = fopen(log_path, "w"); - } - - if (file_ctx->fp == NULL) { - SCLogError(SC_ERR_FOPEN, "failed to open %s: %s", log_path, - strerror(errno)); - return -1; - } - - return 0; -} - diff --git a/src/alert-fastlog.c b/src/alert-fastlog.c index 7e11f82..8b303ff 100644 --- a/src/alert-fastlog.c +++ b/src/alert-fastlog.c @@ -58,6 +58,8 @@ #include "util-print.h" #include "util-proto-name.h" +#include "util-logopenfile.h" + #define DEFAULT_LOG_FILENAME "fast.log" #define MODULE_NAME "AlertFastLog" @@ -337,15 +339,7 @@ OutputCtx *AlertFastLogInitCtx(ConfNode *conf) return NULL; } - const char *filename = ConfNodeLookupChildValue(conf, "filename"); - if (filename == NULL) - filename = DEFAULT_LOG_FILENAME; - - const char *mode = ConfNodeLookupChildValue(conf, "append"); - if (mode == NULL) - mode = DEFAULT_LOG_MODE_APPEND; - - if (AlertFastLogOpenFileCtx(logfile_ctx, filename, mode) < 0) { + if (SCConfLogOpenGeneric(conf, logfile_ctx, DEFAULT_LOG_FILENAME) < 0) { LogFileFreeCtx(logfile_ctx); return NULL; } @@ -356,8 +350,6 @@ OutputCtx *AlertFastLogInitCtx(ConfNode *conf) output_ctx->data = logfile_ctx; output_ctx->DeInit = AlertFastLogDeInitCtx; - SCLogInfo("Fast log output initialized, filename: %s", filename); - return output_ctx; } @@ -368,38 +360,6 @@ static void AlertFastLogDeInitCtx(OutputCtx *output_ctx) free(output_ctx); } -/** \brief Read the config set the file pointer, open the file - * \param file_ctx pointer to a created LogFileCtx using LogFileNewCtx() - * \param filename name of log file - * \return -1 if failure, 0 if succesful - * */ -static int AlertFastLogOpenFileCtx(LogFileCtx *file_ctx, const char *filename, - const char *mode) -{ - char log_path[PATH_MAX]; - char *log_dir; - - if (ConfGet("default-log-dir", &log_dir) != 1) - log_dir = DEFAULT_LOG_DIR; - - snprintf(log_path, PATH_MAX, "%s/%s", log_dir, filename); - - if (strcasecmp(mode, "yes") == 0) { - file_ctx->fp = fopen(log_path, "a"); - } else { - file_ctx->fp = fopen(log_path, "w"); - } - - if (file_ctx->fp == NULL) { - SCLogError(SC_ERR_FOPEN, "failed to open %s: %s", log_path, - strerror(errno)); - return -1; - } - - return 0; -} - - /*------------------------------Unittests-------------------------------------*/ #ifdef UNITTESTS diff --git a/src/log-droplog.c b/src/log-droplog.c index 63f20a2..5cf8c8a 100644 --- a/src/log-droplog.c +++ b/src/log-droplog.c @@ -55,6 +55,8 @@ #include "util-print.h" #include "util-proto-name.h" +#include "util-logopenfile.h" + #define DEFAULT_LOG_FILENAME "drop.log" #define MODULE_NAME "LogDropLog" @@ -158,15 +160,7 @@ OutputCtx *LogDropLogInitCtx(ConfNode *conf) return NULL; } - const char *filename = ConfNodeLookupChildValue(conf, "filename"); - if (filename == NULL) - filename = DEFAULT_LOG_FILENAME; - - const char *mode = ConfNodeLookupChildValue(conf, "append"); - if (mode == NULL) - mode = DEFAULT_LOG_MODE_APPEND; - - if (LogDropLogOpenFileCtx(logfile_ctx, filename, mode) < 0) { + if (SCConfLogOpenGeneric(conf, logfile_ctx, DEFAULT_LOG_FILENAME) < 0) { LogFileFreeCtx(logfile_ctx); return NULL; } @@ -179,8 +173,6 @@ OutputCtx *LogDropLogInitCtx(ConfNode *conf) output_ctx->data = logfile_ctx; output_ctx->DeInit = LogDropLogDeInitCtx; - SCLogInfo("Drop log output initialized, filename: %s", filename); - return output_ctx; } @@ -200,37 +192,6 @@ static void LogDropLogDeInitCtx(OutputCtx *output_ctx) } } -/** \brief Read the config set the file pointer, open the file - * \param file_ctx pointer to a created LogFileCtx using LogFileNewCtx() - * \param filename name of log file - * \return -1 if failure, 0 if succesful - * */ -static int LogDropLogOpenFileCtx(LogFileCtx *file_ctx, const char *filename, - const char *mode) -{ - char log_path[PATH_MAX]; - char *log_dir; - - if (ConfGet("default-log-dir", &log_dir) != 1) - log_dir = DEFAULT_LOG_DIR; - - snprintf(log_path, PATH_MAX, "%s/%s", log_dir, filename); - - if (strcasecmp(mode, "yes") == 0) { - file_ctx->fp = fopen(log_path, "a"); - } else { - file_ctx->fp = fopen(log_path, "w"); - } - - if (file_ctx->fp == NULL) { - SCLogError(SC_ERR_FOPEN, "failed to open %s: %s", log_path, - strerror(errno)); - return -1; - } - - return 0; -} - /** \brief Function to create the time string from the packet timestamp */ static void CreateTimeString (const struct timeval *ts, char *str, size_t size) { time_t time = ts->tv_sec; diff --git a/src/log-httplog.c b/src/log-httplog.c index 647498a..0b3dd28 100644 --- a/src/log-httplog.c +++ b/src/log-httplog.c @@ -46,6 +46,8 @@ #include "app-layer.h" #include "util-privs.h" +#include "util-logopenfile.h" + #define DEFAULT_LOG_FILENAME "http.log" #define MODULE_NAME "LogHttpLog" @@ -420,18 +422,10 @@ OutputCtx *LogHttpLogInitCtx(ConfNode *conf) return NULL; } - const char *filename = ConfNodeLookupChildValue(conf, "filename"); - if (filename == NULL) - filename = DEFAULT_LOG_FILENAME; - - const char *mode = ConfNodeLookupChildValue(conf, "append"); - if (mode == NULL) - mode = DEFAULT_LOG_MODE_APPEND; - /** fill the new LogFileCtx with the specific LogHttpLog configuration */ - ret=LogHttpLogOpenFileCtx(file_ctx, filename, mode); - - if(ret < 0) + if (SCConfLogOpenGeneric(conf, file_ctx, DEFAULT_LOG_FILENAME) < 0) { + LogFileFreeCtx(file_ctx); return NULL; + } OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx)); if (output_ctx == NULL) @@ -448,35 +442,3 @@ static void LogHttpLogDeInitCtx(OutputCtx *output_ctx) LogFileFreeCtx(logfile_ctx); free(output_ctx); } - -/** \brief Read the config set the file pointer, open the file - * \param file_ctx pointer to a created LogFileCtx using LogFileNewCtx() - * \param config_file for loading separate configs - * \return -1 if failure, 0 if succesful - * */ -int LogHttpLogOpenFileCtx(LogFileCtx *file_ctx, const char *filename, const - char *mode) -{ - char log_path[PATH_MAX]; - char *log_dir; - - if (ConfGet("default-log-dir", &log_dir) != 1) - log_dir = DEFAULT_LOG_DIR; - - snprintf(log_path, PATH_MAX, "%s/%s", log_dir, filename); - - if (strcasecmp(mode, "yes") == 0) { - file_ctx->fp = fopen(log_path, "a"); - } else { - file_ctx->fp = fopen(log_path, "w"); - } - - if (file_ctx->fp == NULL) { - SCLogError(SC_ERR_FOPEN, "failed to open %s: %s", log_path, - strerror(errno)); - return -1; - } - - return 0; -} - diff --git a/src/output.h b/src/output.h index 2315705..10c3143 100644 --- a/src/output.h +++ b/src/output.h @@ -27,6 +27,7 @@ #include "suricata.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 460ec06..4a8e9f7 100644 --- a/src/util-error.c +++ b/src/util-error.c @@ -201,6 +201,7 @@ const char * SCErrorToString(SCError err) CASE_CODE (SC_ERR_HTTP_COOKIE_NEEDS_PRECEEDING_CONTENT); CASE_CODE (SC_ERR_HTTP_COOKIE_INCOMPATIBLE_WITH_RAWBYTES); CASE_CODE (SC_ERR_HTTP_COOKIE_RELATIVE_MISSING); + CASE_CODE (SC_ERR_SOCKET); default: return "UNKNOWN_ERROR"; diff --git a/src/util-error.h b/src/util-error.h index 31bb51c..bf6d194 100644 --- a/src/util-error.h +++ b/src/util-error.h @@ -212,6 +212,7 @@ typedef enum { SC_ERR_HTTP_COOKIE_NEEDS_PRECEEDING_CONTENT, SC_ERR_HTTP_COOKIE_INCOMPATIBLE_WITH_RAWBYTES, SC_ERR_HTTP_COOKIE_RELATIVE_MISSING, + 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 0000000..06f6881 --- /dev/null +++ b/src/util-logopenfile.c @@ -0,0 +1,158 @@ +/* vi: set et ts=4: */ +/* Copyright (C) 2007-2010 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 + */ +FILE * SCLogOpenSocketFp(const char *path) +{ + struct sockaddr_un sun; + FILE * ret; + int s = -1; + + s = socket(PF_UNIX, SOCK_STREAM, 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 + */ +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, "type"); + if (filetype == NULL) + filetype = DEFAULT_LOG_FILETYPE; + + // Now, what have we been asked to open? + if (strcasecmp(filetype, "socket") == 0) { + log_ctx->fp = SCLogOpenSocketFp(log_path); + } 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) or \"socket\"", + conf->name); + } + + if (log_ctx->fp == NULL) + return -1; // Error already logged by Open...Fp routine + + SCLogInfo("%s output initialized: %s", conf->name, filename); + + return 0; +} diff --git a/src/util-logopenfile.h b/src/util-logopenfile.h new file mode 100644 index 0000000..6ee2292 --- /dev/null +++ b/src/util-logopenfile.h @@ -0,0 +1,35 @@ +/* Copyright (C) 2007-2010 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 */ + +FILE * SCLogOpenFileFp(const char *, const char *); +FILE * SCLogOpenSocketFp(const char *); +int SCConfLogOpenGeneric(ConfNode *conf, LogFileCtx *, const char *); + +#endif /* __UTIL_LOGOPENFILE_H__ */ +