📄 error.c
字号:
/* * OpenVPN -- An application to securely tunnel IP networks * over a single TCP/UDP port, with support for SSL/TLS-based * session authentication and key exchange, * packet encryption, packet authentication, and * packet compression. * * Copyright (C) 2002-2004 James Yonan <jim@yonan.net> * * 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. * * 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 * along with this program (see the file COPYING included with this * distribution); if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#ifdef WIN32#include "config-win32.h"#else#include "config.h"#endif#include "syshead.h"#include "error.h"#include "buffer.h"#include "thread.h"#include "misc.h"#include "win32.h"#include "socket.h"#include "tun.h"#include "otime.h"#ifdef USE_CRYPTO#include <openssl/err.h>#endif#include "memdbg.h"/* Globals */unsigned int x_debug_level; /* GLOBAL *//* Mute state */static int mute_cutoff; /* GLOBAL */static int mute_count; /* GLOBAL */static int mute_category; /* GLOBAL *//* * Output mode priorities are as follows: * * (1) --log-x overrides everything * (2) syslog is used if --daemon or --inetd is defined and not --log-x * (3) if OPENVPN_DEBUG_COMMAND_LINE is defined, output * to constant logfile name. * (4) Output to stdout. *//* If true, indicates that stdin/stdout/stderr have been redirected due to --log */static bool std_redir; /* GLOBAL *//* Should messages be written to the syslog? */static bool use_syslog; /* GLOBAL *//* The program name passed to syslog */static char *pgmname_syslog; /* GLOBAL *//* If non-null, messages should be written here (used for debugging only) */static FILE *msgfp; /* GLOBAL */voidset_debug_level (int level){ x_debug_level = level;}voidset_mute_cutoff (int cutoff){ mute_cutoff = cutoff;}voiderror_reset (){ use_syslog = std_redir = false; x_debug_level = 1; mute_cutoff = 0; mute_count = 0; mute_category = 0;#ifdef OPENVPN_DEBUG_COMMAND_LINE msgfp = fopen (OPENVPN_DEBUG_FILE, "w"); if (!msgfp) openvpn_exit (OPENVPN_EXIT_STATUS_CANNOT_OPEN_DEBUG_FILE); /* exit point */#else msgfp = NULL;#endif}/* * Return a file to print messages to before syslog is opened. */FILE *msg_fp(){ FILE *fp = msgfp; if (!fp) fp = OPENVPN_MSG_FP; if (!fp) openvpn_exit (OPENVPN_EXIT_STATUS_CANNOT_OPEN_DEBUG_FILE); /* exit point */ return fp;}#define SWAP { tmp = m1; m1 = m2; m2 = tmp; }#define ERR_BUF_SIZE 1024int x_msg_line_num; /* GLOBAL */void x_msg (unsigned int flags, const char *format, ...){ struct gc_arena gc; va_list arglist;#if SYSLOG_CAPABILITY int level;#endif char *m1; char *m2; char *tmp; int e; const char *prefix; const char *prefix_sep; void usage_small (void);#ifndef HAVE_VARARG_MACROS /* the macro has checked this otherwise */ if (!MSG_TEST(flags)) return;#endif gc_init (&gc); if (flags & M_ERRNO_SOCK) e = openvpn_errno_socket (); else e = openvpn_errno (); if (!(flags & M_NOLOCK)) mutex_lock_static (L_MSG); /* * Apply muting filter. */ if (mute_cutoff > 0 && !(flags & M_NOMUTE)) { const int mute_level = DECODE_MUTE_LEVEL(flags); if (mute_level > 0 && mute_level == mute_category) { if (++mute_count > mute_cutoff) { if (!(flags & M_NOLOCK)) mutex_unlock_static (L_MSG); gc_free (&gc); return; } } else { const int suppressed = mute_count - mute_cutoff; if (suppressed > 0) msg (M_INFO | M_NOLOCK | M_NOMUTE, "%d variation(s) on previous %d message(s) suppressed by --mute", suppressed, mute_cutoff); mute_count = 1; mute_category = mute_level; } } m1 = (char *) gc_malloc (ERR_BUF_SIZE, false, &gc); m2 = (char *) gc_malloc (ERR_BUF_SIZE, false, &gc); va_start (arglist, format); vsnprintf (m1, ERR_BUF_SIZE, format, arglist); va_end (arglist); m1[ERR_BUF_SIZE - 1] = 0; /* windows vsnprintf needs this */ if ((flags & (M_ERRNO|M_ERRNO_SOCK)) && e) { openvpn_snprintf (m2, ERR_BUF_SIZE, "%s: %s (errno=%d)", m1, strerror_ts (e, &gc), e); SWAP; }#ifdef USE_CRYPTO if (flags & M_SSL) { int nerrs = 0; int err; while ((err = ERR_get_error ())) { openvpn_snprintf (m2, ERR_BUF_SIZE, "%s: %s", m1, ERR_error_string (err, NULL)); SWAP; ++nerrs; } if (!nerrs) { openvpn_snprintf (m2, ERR_BUF_SIZE, "%s (OpenSSL)", m1); SWAP; } }#endif#if SYSLOG_CAPABILITY if (flags & (M_FATAL|M_NONFATAL|M_USAGE_SMALL)) level = LOG_ERR; else if (flags & M_WARN) level = LOG_WARNING; else level = LOG_NOTICE;#endif /* set up client prefix */ prefix = msg_get_prefix (); prefix_sep = " "; if (!prefix) prefix_sep = prefix = ""; if (use_syslog && !std_redir) {#if SYSLOG_CAPABILITY syslog (level, "%s%s%s", prefix, prefix_sep, m1);#endif } else { FILE *fp = msg_fp(); const bool show_usec = check_debug_level (DEBUG_LEVEL_USEC_TIME - 1); if (flags & M_NOPREFIX) { fprintf (fp, "%s%s%s\n", prefix, prefix_sep, m1); } else {#ifdef USE_PTHREAD fprintf (fp, "%s [%d] %s%s%s\n", time_string (0, 0, show_usec, &gc), (int) openvpn_thread_self (), prefix, prefix_sep, m1);#else fprintf (fp, "%s %s%s%s\n", time_string (0, 0, show_usec, &gc), prefix, prefix_sep, m1);#endif } fflush(fp); ++x_msg_line_num; } if (flags & M_FATAL) msg (M_INFO | M_NOLOCK, "Exiting"); if (!(flags & M_NOLOCK)) mutex_unlock_static (L_MSG); if (flags & M_FATAL) openvpn_exit (OPENVPN_EXIT_STATUS_ERROR); /* exit point */ if (flags & M_USAGE_SMALL) usage_small (); gc_free (&gc);}voidassert_failed (const char *filename, int line){ msg (M_FATAL, "Assertion failed at %s:%d", filename, line);}/* * Fail memory allocation. Don't use msg() because it tries * to allocate memory as part of its operation. */voidout_of_memory (void){ fprintf (stderr, "OpenVPN: Out of Memory\n"); openvpn_exit (OPENVPN_EXIT_STATUS_ERROR);}voidopen_syslog (const char *pgmname){#if SYSLOG_CAPABILITY if (!msgfp && !std_redir) { if (!use_syslog) { pgmname_syslog = string_alloc (pgmname ? pgmname : PACKAGE, NULL); openlog (pgmname_syslog, LOG_PID, LOG_DAEMON); use_syslog = true; /* Better idea: somehow pipe stdout/stderr output to msg() */ set_std_files_to_null (false); } }#else msg (M_WARN, "Warning on use of --daemon/--inetd: this operating system lacks daemon logging features, therefore when I become a daemon, I won't be able to log status or error messages");#endif}voidclose_syslog (){#if SYSLOG_CAPABILITY if (use_syslog) { closelog(); use_syslog = false; if (pgmname_syslog) { free (pgmname_syslog); pgmname_syslog = NULL; } }#endif}voidredirect_stdout_stderr (const char *file, bool append){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -