OpenVPN
error.h
Go to the documentation of this file.
1/*
2 * OpenVPN -- An application to securely tunnel IP networks
3 * over a single TCP/UDP port, with support for SSL/TLS-based
4 * session authentication and key exchange,
5 * packet encryption, packet authentication, and
6 * packet compression.
7 *
8 * Copyright (C) 2002-2026 OpenVPN Inc <sales@openvpn.net>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2
12 * as published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, see <https://www.gnu.org/licenses/>.
21 */
22
23#ifndef ERROR_H
24#define ERROR_H
25
26#include "basic.h"
27#include "syshead.h"
28
29#include <assert.h>
30
31/* #define ABORT_ON_ERROR */
32
33#if defined(ENABLE_PKCS11) || defined(ENABLE_MANAGEMENT)
34#define ERR_BUF_SIZE 10240
35#else
36#define ERR_BUF_SIZE 1280
37#endif
38
39struct gc_arena;
40
41/*
42 * Where should messages be printed before syslog is opened?
43 * Not used if OPENVPN_DEBUG_COMMAND_LINE is defined.
44 */
45#define OPENVPN_MSG_FP stdout
46#define OPENVPN_ERROR_FP stderr
47
48/*
49 * Exit status codes
50 */
51
52#define OPENVPN_EXIT_STATUS_GOOD 0
53#define OPENVPN_EXIT_STATUS_ERROR 1
54#define OPENVPN_EXIT_STATUS_USAGE 1
55#define OPENVPN_EXIT_STATUS_CANNOT_OPEN_DEBUG_FILE 1
56
57/*
58 * Special command line debugging mode.
59 * If OPENVPN_DEBUG_COMMAND_LINE
60 * is defined, contents of argc/argv will
61 * be dumped to OPENVPN_DEBUG_FILE as well
62 * as all other OpenVPN messages.
63 */
64
65/* #define OPENVPN_DEBUG_COMMAND_LINE */
66#define OPENVPN_DEBUG_FILE PACKAGE ".log"
67
68/* String and Error functions */
69
70#ifdef _WIN32
71#define openvpn_errno() GetLastError()
72const char *strerror_win32(DWORD errnum, struct gc_arena *gc);
73#else
74#define openvpn_errno() errno
75#endif
76
77typedef unsigned int msglvl_t;
78
79/*
80 * These globals should not be accessed directly,
81 * but rather through macros or inline functions defined below.
82 */
84extern int x_msg_line_num;
85
86/* msg() flags */
87
88#define M_DEBUG_LEVEL (0x0Fu) /* debug level mask */
89
90#define M_FATAL (1u << 4) /* exit program */
91#define M_NONFATAL (1u << 5) /* non-fatal error */
92#define M_WARN (1u << 6) /* call syslog with LOG_WARNING */
93#define M_DEBUG (1u << 7)
94
95#define M_ERRNO (1u << 8) /* show errno description */
96
97#define M_NOMUTE (1u << 11) /* don't do mute processing */
98#define M_NOPREFIX (1u << 12) /* don't show date/time prefix */
99#define M_USAGE_SMALL (1u << 13) /* fatal options error, call usage_small */
100#define M_MSG_VIRT_OUT (1u << 14) /* output message through msg_status_output callback */
101#define M_OPTERR (1u << 15) /* print "Options error:" prefix */
102#define M_NOLF (1u << 16) /* don't print new line */
103#define M_NOIPREFIX (1u << 17) /* don't print instance prefix */
104
105/* flag combinations which are frequently used */
106#define M_ERR (M_FATAL | M_ERRNO)
107#define M_USAGE (M_USAGE_SMALL | M_NOPREFIX | M_OPTERR)
108#define M_CLIENT (M_MSG_VIRT_OUT | M_NOMUTE | M_NOIPREFIX)
109
110/*
111 * Mute levels are designed to avoid large numbers of
112 * mostly similar messages clogging the log file.
113 *
114 * A mute level of 0 is always printed.
115 */
116#define MUTE_LEVEL_SHIFT 24
117#define MUTE_LEVEL_MASK 0xFFu
118
119#define ENCODE_MUTE_LEVEL(mute_level) (((mute_level) & MUTE_LEVEL_MASK) << MUTE_LEVEL_SHIFT)
120#define DECODE_MUTE_LEVEL(flags) (((flags) >> MUTE_LEVEL_SHIFT) & MUTE_LEVEL_MASK)
121
122/*
123 * log_level: verbosity level n (--verb n) must be >= log_level to print.
124 * mute_level: don't print more than n (--mute n) consecutive messages at
125 * a given mute level, or if 0 disable muting and print everything.
126 *
127 * Mask map:
128 * Bits 0-3: log level
129 * Bits 4-23: M_x flags
130 * Bits 24-31: mute level
131 */
132#define LOGLEV(log_level, mute_level, other) ((log_level) | ENCODE_MUTE_LEVEL(mute_level) | other)
133
134/*
135 * If compiler supports variable arguments in macros, define
136 * msg() as a macro for optimization win.
137 */
138
140bool dont_mute(msglvl_t flags);
141
142/* Macro to ensure (and teach static analysis tools) we exit on fatal errors */
143#define EXIT_FATAL(flags) \
144 do \
145 { \
146 if ((flags) & M_FATAL) \
147 { \
148 _exit(1); \
149 } \
150 } while (false)
151
152#define msg(flags, ...) \
153 do \
154 { \
155 if (msg_test(flags)) \
156 { \
157 x_msg((flags), __VA_ARGS__); \
158 } \
159 EXIT_FATAL(flags); \
160 } while (false)
161#ifdef ENABLE_DEBUG
162#define dmsg(flags, ...) \
163 do \
164 { \
165 if (msg_test(flags)) \
166 { \
167 x_msg((flags), __VA_ARGS__); \
168 } \
169 EXIT_FATAL(flags); \
170 } while (false)
171#else
172#define dmsg(flags, ...)
173#endif
174
175void x_msg(const msglvl_t flags, const char *format, ...)
176#ifdef __GNUC__
177#if __USE_MINGW_ANSI_STDIO
178 __attribute__((format(gnu_printf, 2, 3)))
179#else
180 __attribute__((format(__printf__, 2, 3)))
181#endif
182#endif
183 ; /* should be called via msg above */
184
185void x_msg_va(const msglvl_t flags, const char *format, va_list arglist);
186
187/*
188 * Function prototypes
189 */
190
191void error_reset(void);
192
193/* route errors to stderr that would normally go to stdout */
194void errors_to_stderr(void);
195
196void set_suppress_timestamps(bool suppressed);
197
198void set_machine_readable_output(bool parsable);
199
200
201#define SDL_CONSTRAIN (1 << 0)
202bool set_debug_level(const int level, const unsigned int flags);
203
204bool set_mute_cutoff(const int cutoff);
205
207
208int get_mute_cutoff(void);
209
210const char *msg_flags_string(const msglvl_t flags, struct gc_arena *gc);
211
212/*
213 * File to print messages to before syslog is opened.
214 */
215FILE *msg_fp(const msglvl_t flags);
216
217/* Fatal logic errors */
218#ifndef ENABLE_SMALL
219#define ASSERT(x) \
220 do \
221 { \
222 if (!(x)) \
223 { \
224 assert_failed(__FILE__, __LINE__, #x); \
225 } \
226 } while (false)
227#else
228#define ASSERT(x) \
229 do \
230 { \
231 if (!(x)) \
232 { \
233 assert_failed(__FILE__, __LINE__, NULL); \
234 } \
235 } while (false)
236#endif
237
238#ifdef _MSC_VER
239__declspec(noreturn)
240#endif
241void
242assert_failed(const char *filename, int line, const char *condition)
243#ifndef _MSC_VER
244 __attribute__((__noreturn__))
245#endif
246 ;
247
248/* Inline functions */
249
250static inline bool
252{
253 return (level & M_DEBUG_LEVEL) <= x_debug_level;
254}
255
257static inline bool
259{
260 return check_debug_level(flags) && dont_mute(flags);
261}
262
263#if PORT_SHARE
264/* Call if we forked */
265void msg_forked(void);
266#endif
267
268/* syslog output */
269
270void open_syslog(const char *pgmname, bool stdio_to_null);
271
272void close_syslog(void);
273
274/* log file output */
275void redirect_stdout_stderr(const char *file, bool append);
276
277#ifdef _WIN32
278/* get original stderr fd, even if redirected by --log/--log-append */
279int get_orig_stderr(void);
280
281#endif
282
283/* exit program */
284void openvpn_exit(const int status);
285
286/* exit program on out of memory error */
287void out_of_memory(void);
288
289/*
290 * Check the return status of read/write routines.
291 */
292
293struct link_socket;
294struct tuntap;
295
296extern unsigned int x_cs_info_level;
297extern unsigned int x_cs_verbose_level;
298extern unsigned int x_cs_err_delay_ms;
299
300void reset_check_status(void);
301
302void set_check_status(unsigned int info_level, unsigned int verbose_level);
303
304void x_check_status(ssize_t status, const char *description, struct link_socket *sock,
305 struct tuntap *tt);
306
307static inline void
308check_status(ssize_t status, const char *description, struct link_socket *sock, struct tuntap *tt)
309{
311 {
312 x_check_status(status, description, sock, tt);
313 }
314}
315
316static inline void
317set_check_status_error_delay(unsigned int milliseconds)
318{
319 x_cs_err_delay_ms = milliseconds;
320}
321
322/*
323 * In multiclient mode, put a client-specific prefix
324 * before each message.
325 *
326 * TODO: x_msg_prefix should be thread-local
327 */
328
329extern const char *x_msg_prefix;
330
331static inline void
332msg_set_prefix(const char *prefix)
333{
334 x_msg_prefix = prefix;
335}
336
337static inline const char *
339{
340 return x_msg_prefix;
341}
342
343/*
344 * Allow MSG to be redirected through a virtual_output object
345 */
346
347struct virtual_output;
348
349extern const struct virtual_output *x_msg_virtual_output;
350
351static inline void
353{
355}
356
357static inline const struct virtual_output *
362
363/*
364 * Return true if this is a system error
365 * which can be safely ignored.
366 */
367static inline bool
368ignore_sys_error(const int err, bool crt_error)
369{
370#ifdef _WIN32
371 if (!crt_error && ((err == WSAEWOULDBLOCK || err == WSAEINVAL)))
372 {
373 return true;
374 }
375#else
376 crt_error = true;
377#endif
378
379 /* I/O operation pending */
380 if (crt_error && (err == EAGAIN))
381 {
382 return true;
383 }
384
385#if 0 /* if enabled, suppress ENOBUFS errors */
386#ifdef ENOBUFS
387 /* No buffer space available */
388 if (err == ENOBUFS)
389 {
390 return true;
391 }
392#endif
393#endif
394
395 return false;
396}
397
398#if defined(ENABLE_CRYPTO_OPENSSL)
400static inline msglvl_t
402{
403 return (err & M_FATAL) ? (err ^ M_FATAL) | M_NONFATAL : err;
404}
405#endif
406
407static inline int
409{
410 int err = 0;
411#ifdef _WIN32
412 *crt_error = false;
413 err = GetLastError();
414 if (err == ERROR_SUCCESS)
415 {
416 /* error is likely C runtime */
417 *crt_error = true;
418 err = errno;
419 }
420#else /* ifdef _WIN32 */
421 *crt_error = true;
422 err = errno;
423#endif
424 return err;
425}
426
427#include "errlevel.h"
428
429#endif /* ifndef ERROR_H */
static SERVICE_STATUS status
Definition interactive.c:52
void x_check_status(ssize_t status, const char *description, struct link_socket *sock, struct tuntap *tt)
Definition error.c:626
void error_reset(void)
Definition error.c:157
const struct virtual_output * x_msg_virtual_output
Definition error.c:702
static bool check_debug_level(msglvl_t level)
Definition error.h:251
static void msg_set_prefix(const char *prefix)
Definition error.h:332
void out_of_memory(void)
Definition error.c:437
msglvl_t get_debug_level(void)
Definition error.c:133
void errors_to_stderr(void)
Definition error.c:181
void open_syslog(const char *pgmname, bool stdio_to_null)
Definition error.c:444
void close_syslog(void)
Definition error.c:469
static msglvl_t nonfatal(const msglvl_t err)
Convert fatal errors to nonfatal, don't touch other errors.
Definition error.h:401
unsigned int x_cs_info_level
Definition error.c:599
#define M_DEBUG_LEVEL
Definition error.h:88
void x_msg(const msglvl_t flags, const char *format,...)
Definition error.c:214
void assert_failed(const char *filename, int line, const char *condition) __attribute__((__noreturn__))
Definition error.c:419
msglvl_t x_debug_level
Definition error.c:48
static void msg_set_virtual_output(const struct virtual_output *vo)
Definition error.h:352
static const char * msg_get_prefix(void)
Definition error.h:338
const char * strerror_win32(DWORD errnum, struct gc_arena *gc)
Definition error.c:777
static bool msg_test(msglvl_t flags)
Return true if flags represent an enabled, not muted log level.
Definition error.h:258
const char * x_msg_prefix
Definition error.c:696
int x_msg_line_num
Definition error.c:211
#define M_FATAL
Definition error.h:90
bool dont_mute(msglvl_t flags)
Check muting filter.
Definition error.c:385
static void set_check_status_error_delay(unsigned int milliseconds)
Definition error.h:317
int get_orig_stderr(void)
Definition error.c:486
static void check_status(ssize_t status, const char *description, struct link_socket *sock, struct tuntap *tt)
Definition error.h:308
void redirect_stdout_stderr(const char *file, bool append)
Definition error.c:493
#define M_NONFATAL
Definition error.h:91
bool set_mute_cutoff(const int cutoff)
Definition error.c:119
static bool ignore_sys_error(const int err, bool crt_error)
Definition error.h:368
void set_check_status(unsigned int info_level, unsigned int verbose_level)
Definition error.c:611
static int openvpn_errno_maybe_crt(bool *crt_error)
Definition error.h:408
unsigned int x_cs_verbose_level
Definition error.c:600
void openvpn_exit(const int status)
Definition error.c:709
unsigned int msglvl_t
Definition error.h:77
void reset_check_status(void)
Definition error.c:604
void x_msg_va(const msglvl_t flags, const char *format, va_list arglist)
Definition error.c:235
int get_mute_cutoff(void)
Definition error.c:139
void set_suppress_timestamps(bool suppressed)
Definition error.c:145
void set_machine_readable_output(bool parsable)
Definition error.c:151
FILE * msg_fp(const msglvl_t flags)
Definition error.c:190
static const struct virtual_output * msg_get_virtual_output(void)
Definition error.h:358
bool set_debug_level(const int level, const unsigned int flags)
Definition error.c:103
const char * msg_flags_string(const msglvl_t flags, struct gc_arena *gc)
Definition error.c:748
unsigned int x_cs_err_delay_ms
Definition error.c:601
Garbage collection arena used to keep track of dynamically allocated memory.
Definition buffer.h:127
Definition tun.h:181
__attribute__((unused))
Definition test.c:42
struct gc_arena gc
Definition test_ssl.c:122