558 lines
13 KiB
C
558 lines
13 KiB
C
/*
|
|
* logging.c - logging support
|
|
*/
|
|
|
|
/*
|
|
* Copyright (c) 2000 Japan Network Information Center. All rights reserved.
|
|
*
|
|
* By using this file, you agree to the terms and conditions set forth bellow.
|
|
*
|
|
* LICENSE TERMS AND CONDITIONS
|
|
*
|
|
* The following License Terms and Conditions apply, unless a different
|
|
* license is obtained from Japan Network Information Center ("JPNIC"),
|
|
* a Japanese association, Fuundo Bldg., 1-2 Kanda Ogawamachi, Chiyoda-ku,
|
|
* Tokyo, Japan.
|
|
*
|
|
* 1. Use, Modification and Redistribution (including distribution of any
|
|
* modified or derived work) in source and/or binary forms is permitted
|
|
* under this License Terms and Conditions.
|
|
*
|
|
* 2. Redistribution of source code must retain the copyright notices as they
|
|
* appear in each source code file, this License Terms and Conditions.
|
|
*
|
|
* 3. Redistribution in binary form must reproduce the Copyright Notice,
|
|
* this License Terms and Conditions, in the documentation and/or other
|
|
* materials provided with the distribution. For the purposes of binary
|
|
* distribution the "Copyright Notice" refers to the following language:
|
|
* "Copyright (c) Japan Network Information Center. All rights reserved."
|
|
*
|
|
* 4. Neither the name of JPNIC may be used to endorse or promote products
|
|
* derived from this Software without specific prior written approval of
|
|
* JPNIC.
|
|
*
|
|
* 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
|
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
|
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
|
*
|
|
* 6. Indemnification by Licensee
|
|
* Any person or entities using and/or redistributing this Software under
|
|
* this License Terms and Conditions shall defend indemnify and hold
|
|
* harmless JPNIC from and against any and all judgements damages,
|
|
* expenses, settlement liabilities, cost and other liabilities of any
|
|
* kind as a result of use and redistribution of this Software or any
|
|
* claim, suite, action, litigation or proceeding by any third party
|
|
* arising out of or relates to this License Terms and Conditions.
|
|
*
|
|
* 7. Governing Law, Jurisdiction and Venue
|
|
* This License Terms and Conditions shall be governed by and and
|
|
* construed in accordance with the law of Japan. Any person or entities
|
|
* using and/or redistributing this Software under this License Terms and
|
|
* Conditions hereby agrees and consent to the personal and exclusive
|
|
* jurisdiction and venue of Tokyo District Court of Japan.
|
|
*/
|
|
|
|
#ifndef lint
|
|
static char *rcsid = "$Id: logging.c,v 1.1 2001/06/09 00:30:35 tale Exp $";
|
|
#endif
|
|
|
|
#include <config.h>
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdarg.h>
|
|
#include <time.h>
|
|
|
|
#ifdef HAVE_SYSLOG
|
|
#include <syslog.h>
|
|
#endif
|
|
|
|
#include <mdn/log.h>
|
|
#include <mdn/version.h>
|
|
|
|
#include "mdnsproxy.h"
|
|
|
|
#define DEFAULT_LOGFILE "mdnsproxy.log"
|
|
|
|
#ifdef DEBUG
|
|
#define DEFAULT_LOG_LEVEL LOGLEVEL_TRACE
|
|
#else
|
|
#define DEFAULT_LOG_LEVEL LOGLEVEL_WARN
|
|
#endif
|
|
|
|
#ifndef LOGDIR
|
|
#define LOGDIR "/var/mdnsproxy"
|
|
#endif
|
|
|
|
/*
|
|
* Logging Control Variables
|
|
*/
|
|
|
|
static char logFname[256] = { 0 } ;
|
|
static FILE *logFptr = NULL ;
|
|
static int logMode = LOGMODE_FILE;
|
|
static int logFacility;
|
|
static int logLevel = DEFAULT_LOG_LEVEL ;
|
|
static int timeToTurnOver = 0 ;
|
|
|
|
/*
|
|
* log_default_path -- get default log file pathname
|
|
*/
|
|
|
|
static void log_default_path(void)
|
|
{
|
|
#ifdef UNIX
|
|
sprintf(logFname, "%s/%s", LOGDIR, DEFAULT_LOGFILE) ;
|
|
#endif
|
|
#if defined(WIN32) || defined(OS2)
|
|
{
|
|
char *env;
|
|
if ((env = getenv("TEMP")) == NULL)
|
|
env = getenv("TMP");
|
|
if (env != NULL &&
|
|
strlen(env) + strlen(DEFAULT_LOGFILE) + 1 < sizeof(logFname)) {
|
|
(void)strcpy(logFname, env);
|
|
(void)strcat(logFname, "\\");
|
|
(void)strcat(logFname, DEFAULT_LOGFILE);
|
|
}
|
|
}
|
|
#endif
|
|
} const char *name;
|
|
|
|
|
|
/*
|
|
* log_setlevel - set log level
|
|
*/
|
|
void log_setlevel(int level)
|
|
{
|
|
logLevel = level;
|
|
}
|
|
|
|
/*
|
|
* log_strtolevel - string to log level
|
|
*/
|
|
int log_strtolevel(char *s)
|
|
{
|
|
if ('0' <= s[0] && s[0] <= '9') {
|
|
return atoi(s) ;
|
|
} else if (!strcmp(s, "none")) {
|
|
return LOGLEVEL_NONE;
|
|
} else if (!strcmp(s, "fatal")) {
|
|
return LOGLEVEL_FATAL;
|
|
} else if (!strcmp(s, "warn") || !strcmp(s, "warning")) {
|
|
return LOGLEVEL_WARN;
|
|
} else if (!strcmp(s, "trace")) {
|
|
return LOGLEVEL_TRACE;
|
|
} else {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
typedef struct {
|
|
const char *name;
|
|
int value;
|
|
} syslog_facility_t;
|
|
|
|
static const syslog_facility_t facility_table[] = {
|
|
#ifdef LOG_AUTH
|
|
{"auth", LOG_AUTH},
|
|
#endif
|
|
#ifdef LOG_AUTHPRIV
|
|
{"authpriv", LOG_AUTHPRIV},
|
|
#endif
|
|
#ifdef LOG_CRON
|
|
{"cron", LOG_CRON},
|
|
#endif
|
|
#ifdef LOG_DAEMON
|
|
{"daemon", LOG_DAEMON},
|
|
#endif
|
|
#ifdef LOG_FTP
|
|
{"ftp", LOG_FTP},
|
|
#endif
|
|
#ifdef LOG_KERN
|
|
{"kern", LOG_KERN},
|
|
#endif
|
|
#ifdef LOG_LOCAL0
|
|
{"local0", LOG_LOCAL0},
|
|
#endif
|
|
#ifdef LOG_LOCAL1
|
|
{"local1", LOG_LOCAL1},
|
|
#endif
|
|
#ifdef LOG_LOCAL2
|
|
{"local2", LOG_LOCAL2},
|
|
#endif
|
|
#ifdef LOG_LOCAL3
|
|
{"local3", LOG_LOCAL3},
|
|
#endif
|
|
#ifdef LOG_LOCAL4
|
|
{"local4", LOG_LOCAL4},
|
|
#endif
|
|
#ifdef LOG_LOCAL5
|
|
{"local5", LOG_LOCAL5},
|
|
#endif
|
|
#ifdef LOG_LOCAL6
|
|
{"local6", LOG_LOCAL6},
|
|
#endif
|
|
#ifdef LOG_LOCAL7
|
|
{"local7", LOG_LOCAL7},
|
|
#endif
|
|
#ifdef LOG_LPR
|
|
{"lpr", LOG_LPR},
|
|
#endif
|
|
#ifdef LOG_MAIL
|
|
{"mail", LOG_MAIL},
|
|
#endif
|
|
#ifdef LOG_NEWS
|
|
{"news", LOG_NEWS},
|
|
#endif
|
|
#ifdef LOG_SYSLOG
|
|
{"syslog", LOG_SYSLOG},
|
|
#endif
|
|
#ifdef LOG_USER
|
|
{"user", LOG_USER},
|
|
#endif
|
|
#ifdef LOG_UUCP
|
|
{"uucp", LOG_UUCP},
|
|
#endif
|
|
{NULL, 0}
|
|
};
|
|
|
|
/*
|
|
* log_strtofacility - string to log facility
|
|
*/
|
|
static int log_strtofacility(char *name, int *value)
|
|
{
|
|
const syslog_facility_t *p;
|
|
|
|
for (p = facility_table; p->name != NULL; p++) {
|
|
if (strcmp(name, p->name) == 0) {
|
|
*value = p->value;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* log_terminate - terminate logging
|
|
*/
|
|
|
|
void log_terminate(void)
|
|
{
|
|
if (logMode == LOGMODE_FILE && logFptr != NULL) {
|
|
fclose(logFptr) ;
|
|
logFptr = NULL ;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* log_turnover_request - request turning over log
|
|
* this function is intended for calling from singnal handler.
|
|
*/
|
|
|
|
void log_turnover_request(void)
|
|
{
|
|
timeToTurnOver = 1;
|
|
}
|
|
|
|
/*
|
|
* log_turnover - turn over log if requested
|
|
*/
|
|
|
|
void log_turnover(void)
|
|
{
|
|
if (timeToTurnOver && logMode == LOGMODE_FILE) {
|
|
timeToTurnOver = 0;
|
|
log_trace_printf("--- log file turned over\n");
|
|
log_terminate() ;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* libmdn_logproc_file - log hander for libmdn
|
|
* output message to a regular log file.
|
|
*/
|
|
static void
|
|
libmdn_logproc_file(int level, const char *buf)
|
|
{
|
|
switch (level) {
|
|
case mdn_log_level_fatal:
|
|
FATAL((char *)buf);
|
|
break;
|
|
case mdn_log_level_warning:
|
|
case mdn_log_level_info:
|
|
WARN((char *)buf);
|
|
break;
|
|
case mdn_log_level_trace:
|
|
case mdn_log_level_dump:
|
|
TRACE((char *)buf);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* libmdn_logproc_syslog - log hander for libmdn.
|
|
* output message to syslog.
|
|
*/
|
|
static void
|
|
libmdn_logproc_syslog(int level, const char *buf)
|
|
{
|
|
#ifdef HAVE_SYSLOG
|
|
switch (level) {
|
|
case mdn_log_level_fatal:
|
|
syslog(LOG_ERR, "[FATAL] %s", buf);
|
|
break;
|
|
case mdn_log_level_error:
|
|
syslog(LOG_ERR, "[ERROR] %s", buf);
|
|
break;
|
|
case mdn_log_level_warning:
|
|
syslog(LOG_WARNING, "[WARNING] %s", buf);
|
|
break;
|
|
case mdn_log_level_info:
|
|
syslog(LOG_INFO, "[INFO] %s", buf);
|
|
break;
|
|
case mdn_log_level_trace:
|
|
syslog(LOG_DEBUG, "[TRACE] %s", buf);
|
|
break;
|
|
case mdn_log_level_dump:
|
|
syslog(LOG_DEBUG, "[DUMP] %s", buf);
|
|
break;
|
|
default:
|
|
syslog(LOG_NOTICE, "[LEVEL%d] %s", level, buf);
|
|
break;
|
|
}
|
|
#endif /* HAVE_SYSLOG */
|
|
}
|
|
|
|
/*
|
|
* libmdn_string_to_loglevel - convert log level name to value.
|
|
*/
|
|
|
|
static int
|
|
libmdn_string_to_loglevel(char *s)
|
|
{
|
|
if ('0' <= s[0] && s[0] <= '9')
|
|
return atoi(s);
|
|
else if (!strcmp(s, "fatal"))
|
|
return mdn_log_level_fatal;
|
|
else if (!strcmp(s, "error"))
|
|
return mdn_log_level_error;
|
|
else if (!strcmp(s, "warning"))
|
|
return mdn_log_level_warning;
|
|
else if (!strcmp(s, "info"))
|
|
return mdn_log_level_info;
|
|
else if (!strcmp(s, "trace"))
|
|
return mdn_log_level_trace;
|
|
else if (!strcmp(s, "dump"))
|
|
return mdn_log_level_dump;
|
|
else
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
* log_vprintf - as name describes
|
|
*/
|
|
|
|
static void log_vprintf(int level, char *fmt, va_list arg_ptr)
|
|
{
|
|
char buff[512] ;
|
|
|
|
if (logLevel < level) {
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* format message
|
|
*/
|
|
|
|
vsprintf(buff, fmt, arg_ptr) ;
|
|
|
|
#ifdef DEBUG
|
|
printf("%s", buff) ;
|
|
fflush(stdout) ;
|
|
#endif
|
|
|
|
if (logMode == LOGMODE_SYSLOG) {
|
|
#ifdef HAVE_SYSLOG
|
|
switch (level) {
|
|
case LOGLEVEL_FATAL:
|
|
syslog(LOG_ERR, buff);
|
|
break;
|
|
case LOGLEVEL_WARN:
|
|
syslog(LOG_WARNING, buff);
|
|
break;
|
|
case LOGLEVEL_TRACE:
|
|
syslog(LOG_DEBUG, buff);
|
|
break;
|
|
}
|
|
#endif /* HAVE_SYSLOG */
|
|
} else if (logFptr != NULL) {
|
|
fputs(buff, logFptr) ;
|
|
fflush(logFptr) ;
|
|
}
|
|
|
|
#ifdef WIN32 /* For NT, having trouble with */
|
|
fclose(logFptr) ; /* reading open'd logging file */
|
|
logFptr = NULL ; /* so, close and re-open it */
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
* log_fatal_printf, log_warn_printf, log_trace_printf - write out
|
|
* fatal/warning/trace log to the log file
|
|
*/
|
|
|
|
void log_fatal_printf(char *fmt, ...)
|
|
{
|
|
va_list arg_ptr ;
|
|
|
|
va_start(arg_ptr, fmt) ;
|
|
log_vprintf(LOGLEVEL_FATAL, fmt, arg_ptr) ;
|
|
va_end(arg_ptr) ;
|
|
}
|
|
|
|
void log_warn_printf(char *fmt, ...)
|
|
{
|
|
va_list arg_ptr ;
|
|
|
|
va_start(arg_ptr, fmt) ;
|
|
log_vprintf(LOGLEVEL_WARN, fmt, arg_ptr) ;
|
|
va_end(arg_ptr) ;
|
|
}
|
|
|
|
void log_trace_printf(char *fmt, ...)
|
|
{
|
|
va_list arg_ptr ;
|
|
|
|
va_start(arg_ptr, fmt) ;
|
|
log_vprintf(LOGLEVEL_TRACE, fmt, arg_ptr) ;
|
|
va_end(arg_ptr) ;
|
|
}
|
|
|
|
/*
|
|
* log_configure - configure logging (must be called after 'config_load')
|
|
*/
|
|
|
|
BOOL log_configure(int ac, char *av[])
|
|
{
|
|
int i, nArgs ;
|
|
char **aArgs ;
|
|
char *fn = NULL ;
|
|
int lineNo;
|
|
|
|
log_default_path();
|
|
|
|
#ifdef HAVE_SYSLOG
|
|
logFacility = LOG_DAEMON;
|
|
#endif
|
|
|
|
for (i = 1 ; i < ac ; i++) {
|
|
if (strcmp(av[i], CMDOPT_LOGFILE) == 0) {
|
|
fn = av[i+=1] ;
|
|
}
|
|
}
|
|
if (fn != NULL) {
|
|
if (strlen(fn) + 1 < sizeof(logFname)) {
|
|
WARN("log_configure - too long log file name \"%.100s...\"\n",
|
|
fn);
|
|
return FALSE;
|
|
}
|
|
strcpy(logFname, fn) ;
|
|
|
|
} else if (config_query_value(KW_LOG_FILE, &nArgs, &aArgs, &lineNo)) {
|
|
if (nArgs != 2) {
|
|
WARN("log_configure - wrong # of args for \"%s\", line %d\n",
|
|
KW_LOG_FILE, lineNo);
|
|
return FALSE;
|
|
}
|
|
strcpy(logFname, aArgs[1]) ;
|
|
}
|
|
|
|
if (config_query_value(KW_LOG_LEVEL, &nArgs, &aArgs, &lineNo) == TRUE) {
|
|
int level ;
|
|
|
|
if (nArgs != 2) {
|
|
WARN("log_configure - wrong # of args for \"%s\", line %d\n",
|
|
KW_LOG_LEVEL, lineNo);
|
|
return FALSE;
|
|
}
|
|
if ((level = log_strtolevel(aArgs[1])) < 0) {
|
|
WARN("log_configure - invalid log level \"%.100s\", line %d\n",
|
|
aArgs[1], lineNo);
|
|
return FALSE;
|
|
}
|
|
log_setlevel(level);
|
|
}
|
|
|
|
if (config_query_value(KW_MDN_LOG_LEVEL, &nArgs, &aArgs, &lineNo)) {
|
|
int level;
|
|
|
|
if (nArgs != 2) {
|
|
WARN("wrong # of args for \"%s\", line %d\n", KW_MDN_LOG_LEVEL,
|
|
lineNo);
|
|
return FALSE;
|
|
}
|
|
if ((level = libmdn_string_to_loglevel(aArgs[1])) < 0) {
|
|
WARN("unknown mdn log level \"%.100s\", line %d\n", aArgs[1],
|
|
lineNo);
|
|
return FALSE;
|
|
}
|
|
mdn_log_setlevel(level);
|
|
}
|
|
|
|
#ifdef HAVE_SYSLOG
|
|
if (config_query_value(KW_SYSLOG_FACILITY, &nArgs, &aArgs, &lineNo)
|
|
== TRUE) {
|
|
if (nArgs != 2) {
|
|
WARN("log_configure - wrong # of args for \"%s\", line %d\n",
|
|
KW_LOG_LEVEL, lineNo);
|
|
return FALSE;
|
|
} else if (!log_strtofacility(aArgs[1], &logFacility)) {
|
|
WARN("log_configure - unknown syslog facility \"%.100s\", "
|
|
"line %d\n", aArgs[1], lineNo);
|
|
return FALSE;
|
|
}
|
|
}
|
|
#endif /* HAVE_SYSLOG */
|
|
|
|
if (*logFname == '\0') {
|
|
WARN("log_configure - no logging file specified\n");
|
|
return FALSE;
|
|
}
|
|
|
|
if (strcmp(logFname, "syslog") == 0) {
|
|
#ifdef HAVE_SYSLOG
|
|
logMode = LOGMODE_SYSLOG;
|
|
logFptr = NULL;
|
|
openlog("mdnsproxy", LOG_NDELAY | LOG_PID, logFacility);
|
|
mdn_log_setproc(libmdn_logproc_syslog);
|
|
syslog(LOG_NOTICE, "** mdnsproxy version %s", mdn_version_getstring());
|
|
#else /* not HAVE_SYSLOG */
|
|
WARN("log_configure - syslog is unavailable\n");
|
|
return FALSE;
|
|
#endif /* not HAVE_SYSLOG */
|
|
} else {
|
|
logMode = LOGMODE_FILE;
|
|
logFptr = fopen(logFname, "a") ;
|
|
mdn_log_setproc(libmdn_logproc_file);
|
|
if (logFptr == NULL) {
|
|
WARN("log_configure - cannot open, the log file\"%.100s\"\n",
|
|
logFname);
|
|
return FALSE;
|
|
}
|
|
WARN("** mdnsproxy version %s\n", mdn_version_getstring());
|
|
}
|
|
|
|
return TRUE;
|
|
}
|