📄 log.c
字号:
/* error logging functions * Copyright (C) 1997 Angelos D. Keromytis. * Copyright (C) 1998-2001 D. Hugh Redelmeier. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. * * 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. * * RCSID $Id: log.c,v 1.90 2004/11/15 14:34:03 mcr Exp $ */#include <stdio.h>#include <stdlib.h>#include <ctype.h>#include <stdarg.h>#include <syslog.h>#include <errno.h>#include <string.h>#include <unistd.h>#include <signal.h> /* used only if MSG_NOSIGNAL not defined */#include <sys/queue.h>#include <libgen.h>#include <sys/stat.h>#include <sys/types.h>#include <openswan.h>#include "constants.h"#include "oswlog.h"#include "defs.h"#include "log.h"#include "server.h"#include "state.h"#include "id.h"#include "x509.h"#include "pgp.h"#include "certs.h"#include "smartcard.h"#ifdef XAUTH_USEPAM#include <security/pam_appl.h>#endif#include "connections.h" /* needs id.h */#include "kernel.h" /* needs connections.h */#include "whack.h" /* needs connections.h */#include "timer.h"#include "paths.h"#include "kernel_alg.h"#include "ike_alg.h"#include "plutoalg.h"#ifndef NO_DB_OPS_STATS#define NO_DB_CONTEXT#include "db_ops.h"#endif/* close one per-peer log */static void perpeer_logclose(struct connection *c); /* forward */bool log_to_stderr = TRUE, /* should log go to stderr? */ log_to_syslog = TRUE, /* should log go to syslog? */ log_to_perpeer= FALSE; /* should log go to per-IP file? */bool logged_txt_warning = FALSE; /* should we complain about finding KEY? *//* should we complain when we find no local id */bool logged_myid_fqdn_txt_warning = FALSE, logged_myid_ip_txt_warning = FALSE, logged_myid_fqdn_key_warning = FALSE, logged_myid_ip_key_warning = FALSE;/* may include trailing / */const char *base_perpeer_logdir = PERPEERLOGDIR;static int perpeer_count = 0;/* what to put in front of debug output */char debug_prefix = '|';/* * used in some messages to distiguish * which pluto is which, when doing unit testing * gets set by "use_interface" in server.c, if it is going to be changed. * Is used by pluto_helpers in their process-title. * could be used by debug routines as well, but is not yet. */const char *pluto_ifn_inst = ""; /* from sys/queue.h */static CIRCLEQ_HEAD(,connection) perpeer_list;/* Context for logging. * * Global variables: must be carefully adjusted at transaction boundaries! * If the context provides a whack file descriptor, messages * should be copied to it -- see whack_log() */int whack_log_fd = NULL_FD; /* only set during whack_handle() */struct state *cur_state = NULL; /* current state, for diagnostics */struct connection *cur_connection = NULL; /* current connection, for diagnostics */const ip_address *cur_from = NULL; /* source of current current message */u_int16_t cur_from_port; /* host order */voidpluto_init_log(void){ set_exit_log_func(exit_log); set_paths(ipsec_dir); if (log_to_stderr) setbuf(stderr, NULL); if (log_to_syslog) openlog("pluto", LOG_CONS | LOG_NDELAY | LOG_PID, LOG_AUTHPRIV); CIRCLEQ_INIT(&perpeer_list);}/* format a string for the log, with suitable prefixes. * A format starting with ~ indicates that this is a reprocessing * of the message, so prefixing and quoting is suppressed. */static voidfmt_log(char *buf, size_t buf_len, const char *fmt, va_list ap){ bool reproc = *fmt == '~'; size_t ps; struct connection *c = cur_state != NULL ? cur_state->st_connection : cur_connection; buf[0] = '\0'; if (reproc) fmt++; /* ~ at start of format suppresses this prefix */ else if (c != NULL) { /* start with name of connection */ char *const be = buf + buf_len; char *bp = buf; snprintf(bp, be - bp, "\"%s\"", c->name); bp += strlen(bp); /* if it fits, put in any connection instance information */ if (be - bp > CONN_INST_BUF) { fmt_conn_instance(c, bp); bp += strlen(bp); } if (cur_state != NULL) { /* state number */ snprintf(bp, be - bp, " #%lu", cur_state->st_serialno); bp += strlen(bp); } snprintf(bp, be - bp, ": "); } else if (cur_from != NULL) { /* peer's IP address */ /* Note: must not use ip_str() because our caller might! */ char ab[ADDRTOT_BUF]; (void) addrtot(cur_from, 0, ab, sizeof(ab)); snprintf(buf, buf_len, "packet from %s:%u: " , ab, (unsigned)cur_from_port); } ps = strlen(buf); vsnprintf(buf + ps, buf_len - ps, fmt, ap); if (!reproc) (void)sanitize_string(buf, buf_len);}voidclose_peerlog(void){ /* exit if the circular queue has not been initialized */ if (perpeer_list.cqh_first == NULL) return; /* end of circular queue is given by pointer to "HEAD" */ while (perpeer_list.cqh_first != (void *)&perpeer_list) perpeer_logclose(perpeer_list.cqh_first);}voidclose_log(void){ if (log_to_syslog) closelog(); close_peerlog();}static voidperpeer_logclose(struct connection *c){ /* only free/close things if we had used them! */ if (c->log_file != NULL) { passert(perpeer_count > 0); CIRCLEQ_REMOVE(&perpeer_list, c, log_link); perpeer_count--; fclose(c->log_file); c->log_file=NULL; }}voidperpeer_logfree(struct connection *c){ perpeer_logclose(c); if (c->log_file_name != NULL) { pfree(c->log_file_name); c->log_file_name = NULL; c->log_file_err = FALSE; }}/* open the per-peer log */static voidopen_peerlog(struct connection *c){ syslog(LOG_INFO, "opening log file for conn %s", c->name); if (c->log_file_name == NULL) { char peername[ADDRTOT_BUF], dname[ADDRTOT_BUF]; int peernamelen, lf_len; addrtot(&c->spd.that.host_addr, 'Q', peername, sizeof(peername)); peernamelen = strlen(peername); /* copy IP address, turning : and . into / */ { char c, *p, *q; p = peername; q = dname; do { c = *p++; if (c == '.' || c == ':') c = '/'; *q++ = c; } while (c != '\0'); } lf_len = peernamelen * 2 + strlen(base_perpeer_logdir) + sizeof("//.log") + 1; c->log_file_name = alloc_bytes(lf_len, "per-peer log file name"); fprintf(stderr, "base dir |%s| dname |%s| peername |%s|" , base_perpeer_logdir, dname, peername); snprintf(c->log_file_name, lf_len, "%s/%s/%s.log" , base_perpeer_logdir, dname, peername); syslog(LOG_DEBUG, "conn %s logfile is %s", c->name, c->log_file_name); } /* now open the file, creating directories if necessary */ { /* create the directory */ char *dname; int bpl_len = strlen(base_perpeer_logdir); char *slashloc; dname = clone_str(c->log_file_name, "temp copy of file name"); dname = dirname(dname); if (access(dname, W_OK) != 0) { if (errno != ENOENT) { if (c->log_file_err) { syslog(LOG_CRIT, "can not write to %s: %s" , dname, strerror(errno)); c->log_file_err = TRUE; pfree(dname); return; } } /* directory does not exist, walk path creating dirs */ /* start at base_perpeer_logdir */ slashloc = dname + bpl_len; slashloc++; /* since, by construction there is a slash right there */ while (*slashloc != '\0') { char saveslash; /* look for next slash */ while (*slashloc != '\0' && *slashloc != '/') slashloc++; saveslash = *slashloc; *slashloc = '\0'; if (mkdir(dname, 0750) != 0 && errno != EEXIST) { syslog(LOG_CRIT, "can not create dir %s: %s" , dname, strerror(errno)); c->log_file_err = TRUE; pfree(dname); return; } syslog(LOG_DEBUG, "created new directory %s", dname); *slashloc = saveslash; slashloc++; } } pfree(dname); } c->log_file = fopen(c->log_file_name, "a"); if (c->log_file == NULL) { if (c->log_file_err) { syslog(LOG_CRIT, "logging system can not open %s: %s" , c->log_file_name, strerror(errno)); c->log_file_err = TRUE; } return; } /* look for a connection to close! */ while (perpeer_count >= MAX_PEERLOG_COUNT) { /* can not be NULL because perpeer_count > 0 */ passert(perpeer_list.cqh_last != (void *)&perpeer_list); perpeer_logclose(perpeer_list.cqh_last); } /* insert this into the list */ CIRCLEQ_INSERT_HEAD(&perpeer_list, c, log_link); passert(c->log_file != NULL); perpeer_count++;}/* log a line to cur_connection's log */static voidpeerlog(const char *prefix, const char *m){ if (cur_connection == NULL) { /* we can not log it in this case. Oh well. */ return; } if (cur_connection->log_file == NULL) { open_peerlog(cur_connection); } /* despite our attempts above, we may not be able to open the file. */ if (cur_connection->log_file != NULL) { char datebuf[32]; time_t n; struct tm *t; time(&n); t = localtime(&n); strftime(datebuf, sizeof(datebuf), "%Y-%m-%d %T", t); fprintf(cur_connection->log_file, "%s %s%s\n", datebuf, prefix, m); /* now move it to the front of the list */ CIRCLEQ_REMOVE(&perpeer_list, cur_connection, log_link); CIRCLEQ_INSERT_HEAD(&perpeer_list, cur_connection, log_link); }}voidopenswan_log(const char *message, ...){ va_list args; char m[LOG_WIDTH]; /* longer messages will be truncated */ va_start(args, message); fmt_log(m, sizeof(m), message, args); va_end(args); if (log_to_stderr) fprintf(stderr, "%s\n", m); if (log_to_syslog) syslog(LOG_WARNING, "%s", m); if (log_to_perpeer) peerlog("", m); whack_log(RC_LOG, "~%s", m);}voidloglog(int mess_no, const char *message, ...){ va_list args; char m[LOG_WIDTH]; /* longer messages will be truncated */ va_start(args, message); fmt_log(m, sizeof(m), message, args); va_end(args); if (log_to_stderr) fprintf(stderr, "%s\n", m); if (log_to_syslog) syslog(LOG_WARNING, "%s", m); if (log_to_perpeer) peerlog("", m); whack_log(mess_no, "~%s", m);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -