Hi, Thanks for the changes. Looks good.
On Tue, May 3, 2022 at 9:12 AM Lev Stipakov <lstipa...@gmail.com> wrote: > From: Lev Stipakov <l...@openvpn.net> > > We use M_ERRNO flag in logging to display error code > and error message. This has been broken on Windows, > where we use error code from GetLastError() and > error description from strerror(). strerror() expects > C runtime error code, which is quite different from > last error code from WinAPI call. As a result, we got > incorrect error description. > > The ultimate fix would be introducing another flag > for WinAPI errors, like M_WINERR and use either that or > M_ERRNO depends on context. However, the change would be > quite intrusive and in some cases it is hard to say which > one to use without looking into internals. > > Instead we stick to M_ERRNO and in Windows case we > first try to obtain error code from GetLastError() and > if it returns ERROR_SUCCESS (which is 0), we assume that > we have C runtime error and use errno. To get error > description we use strerror_win32() with GetLastError() > and strerror() with errno. > > strerror_win32() uses FormatMessage() internally, which > is the right way to get WinAPI error description. > --- > v2: > - removed WSA error printing, to be implemented in a follow-up patch > - added missing crt error fallback to x_check_status() and > main_io_error() > - fixed "network unreachable" detection > > src/openvpn/error.c | 34 +++++++++++++++++++++++++++------- > src/openvpn/error.h | 39 +++++++++++++++++++++++++++++---------- > src/openvpn/forward.c | 9 ++++++++- > src/openvpn/manage.c | 5 +++-- > src/openvpn/platform.c | 2 +- > src/openvpn/tun.h | 4 ++-- > 6 files changed, 70 insertions(+), 23 deletions(-) > > diff --git a/src/openvpn/error.c b/src/openvpn/error.c > index 603d6c63..1b7f5cde 100644 > --- a/src/openvpn/error.c > +++ b/src/openvpn/error.c > @@ -220,6 +220,18 @@ x_msg(const unsigned int flags, const char *format, > ...) > va_end(arglist); > } > > +static const char* > +openvpn_strerror(int err, bool crt_error, struct gc_arena *gc) > +{ > +#ifdef _WIN32 > + if (!crt_error) > + { > + return strerror_win32(err, gc); > + } > +#endif > + return strerror(err); > +} > + > void > x_msg_va(const unsigned int flags, const char *format, va_list arglist) > { > @@ -242,7 +254,8 @@ x_msg_va(const unsigned int flags, const char *format, > va_list arglist) > return; > } > > - e = openvpn_errno(); > + bool crt_error = false; > + e = openvpn_errno_maybe_crt(&crt_error); > > /* > * Apply muting filter. > @@ -264,7 +277,7 @@ x_msg_va(const unsigned int flags, const char *format, > va_list arglist) > if ((flags & M_ERRNO) && e) > { > openvpn_snprintf(m2, ERR_BUF_SIZE, "%s: %s (errno=%d)", > - m1, strerror(e), e); > + m1, openvpn_strerror(e, crt_error, &gc), e); > SWAP; > } > > @@ -643,7 +656,6 @@ x_check_status(int status, > struct link_socket *sock, > struct tuntap *tt) > { > - const int my_errno = openvpn_errno(); > const char *extended_msg = NULL; > > msg(x_cs_verbose_level, "%s %s returned %d", > @@ -666,26 +678,34 @@ x_check_status(int status, > sock->info.mtu_changed = true; > } > } > -#elif defined(_WIN32) > +#endif /* EXTENDED_SOCKET_ERROR_CAPABILITY */ > + > +#ifdef _WIN32 > /* get possible driver error from TAP-Windows driver */ > if (tuntap_defined(tt)) > { > extended_msg = tap_win_getinfo(tt, &gc); > } > #endif > - if (!ignore_sys_error(my_errno)) > + > + bool crt_error = false; > + int my_errno = openvpn_errno_maybe_crt(&crt_error); > + > + if (!ignore_sys_error(my_errno, crt_error)) > { > if (extended_msg) > { > msg(x_cs_info_level, "%s %s [%s]: %s (fd=%d,code=%d)", > description, > sock ? proto2ascii(sock->info.proto, sock->info.af, > true) : "", > - extended_msg, strerror(my_errno), sock ? sock->sd : > -1, my_errno); > + extended_msg, openvpn_strerror(my_errno, crt_error, > &gc), > + sock ? sock->sd : -1, my_errno); > } > else > { > msg(x_cs_info_level, "%s %s: %s (fd=%d,code=%d)", > description, > sock ? proto2ascii(sock->info.proto, sock->info.af, > true) : "", > - strerror(my_errno), sock ? sock->sd : -1, my_errno); > + openvpn_strerror(my_errno, crt_error, &gc), > + sock ? sock->sd : -1, my_errno); > } > > if (x_cs_err_delay_ms) > diff --git a/src/openvpn/error.h b/src/openvpn/error.h > index ad7defe8..be8d97e5 100644 > --- a/src/openvpn/error.h > +++ b/src/openvpn/error.h > @@ -75,13 +75,10 @@ struct gc_arena; > /* String and Error functions */ > > #ifdef _WIN32 > -#define openvpn_errno() GetLastError() > -#define openvpn_strerror(e, gc) strerror_win32(e, gc) > +#define openvpn_errno() GetLastError() > const char *strerror_win32(DWORD errnum, struct gc_arena *gc); > - > #else > -#define openvpn_errno() errno > -#define openvpn_strerror(x, gc) strerror(x) > +#define openvpn_errno() errno > #endif > > /* > @@ -352,20 +349,22 @@ msg_get_virtual_output(void) > * which can be safely ignored. > */ > static inline bool > -ignore_sys_error(const int err) > +ignore_sys_error(const int err, bool crt_error) > { > - /* I/O operation pending */ > #ifdef _WIN32 > - if (err == WSAEWOULDBLOCK || err == WSAEINVAL) > + if (!crt_error && ((err == WSAEWOULDBLOCK || err == WSAEINVAL))) > { > return true; > } > #else > - if (err == EAGAIN) > + crt_error = true; > +#endif > + > + /* I/O operation pending */ > + if (crt_error && (err == EAGAIN)) > { > return true; > } > -#endif > > #if 0 /* if enabled, suppress ENOBUFS errors */ > #ifdef ENOBUFS > @@ -387,6 +386,26 @@ nonfatal(const unsigned int err) > return err & M_FATAL ? (err ^ M_FATAL) | M_NONFATAL : err; > } > > +static inline int > +openvpn_errno_maybe_crt(bool *crt_error) > +{ > + int err = 0; > + *crt_error = false; > +#ifdef _WIN32 > + err = GetLastError(); > + if (err == ERROR_SUCCESS) > + { > + /* error is likely C runtime */ > + *crt_error = true; > + err = errno; > + } > +#else > + *crt_error = true; > + err = errno; > +#endif > + return err; > +} > + > #include "errlevel.h" > > #endif /* ifndef ERROR_H */ > diff --git a/src/openvpn/forward.c b/src/openvpn/forward.c > index 8930e578..04828a5c 100644 > --- a/src/openvpn/forward.c > +++ b/src/openvpn/forward.c > @@ -1660,7 +1660,14 @@ process_outgoing_link(struct context *c) > } > > /* for unreachable network and "connecting" state switch to the > next host */ > - if (size < 0 && ENETUNREACH == error_code && c->c2.tls_multi > + > + bool unreachable = error_code == > +#ifdef _WIN32 > + WSAENETUNREACH; > +#else > + ENETUNREACH; > +#endif > + if (size < 0 && unreachable && c->c2.tls_multi > && !tls_initial_packet_received(c->c2.tls_multi) && > c->options.mode == MODE_POINT_TO_POINT) > { > msg(M_INFO, "Network unreachable, restarting"); > diff --git a/src/openvpn/manage.c b/src/openvpn/manage.c > index 9b03b057..036658b1 100644 > --- a/src/openvpn/manage.c > +++ b/src/openvpn/manage.c > @@ -2008,9 +2008,10 @@ man_process_command(struct management *man, const > char *line) > static bool > man_io_error(struct management *man, const char *prefix) > { > - const int err = openvpn_errno(); > + bool crt_error = false; > + int err = openvpn_errno_maybe_crt(&crt_error); > > - if (!ignore_sys_error(err)) > + if (!ignore_sys_error(err, crt_error)) > { > struct gc_arena gc = gc_new(); > msg(D_MANAGEMENT, "MANAGEMENT: TCP %s error: %s", prefix, > diff --git a/src/openvpn/platform.c b/src/openvpn/platform.c > index 61afee83..ae1678db 100644 > --- a/src/openvpn/platform.c > +++ b/src/openvpn/platform.c > @@ -532,7 +532,7 @@ platform_test_file(const char *filename) > } > else > { > - if (openvpn_errno() == EACCES) > + if (errno == EACCES) > { > msg( M_WARN | M_ERRNO, "Could not access file '%s'", > filename); > } > diff --git a/src/openvpn/tun.h b/src/openvpn/tun.h > index 3a7314c5..4bc35916 100644 > --- a/src/openvpn/tun.h > +++ b/src/openvpn/tun.h > @@ -446,7 +446,7 @@ tuntap_stop(int status) > */ > if (status < 0) > { > - return openvpn_errno() == ERROR_FILE_NOT_FOUND; > + return GetLastError() == ERROR_FILE_NOT_FOUND; > } > return false; > } > @@ -459,7 +459,7 @@ tuntap_abort(int status) > */ > if (status < 0) > { > - return openvpn_errno() == ERROR_OPERATION_ABORTED; > + return GetLastError() == ERROR_OPERATION_ABORTED; > } > return false; > } > Acked-by: Selva Nair <selva.n...@gmail.com>
_______________________________________________ Openvpn-devel mailing list Openvpn-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/openvpn-devel