void x_msg (const 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 if (flags & M_ERRNO_SOCK) e = openvpn_errno_socket (); else e = openvpn_errno (); /* * Apply muting filter. */ #ifndef HAVE_VARARG_MACROS /* the macro has checked this otherwise */ if (!dont_mute (flags)) return; #endif gc_init (&gc); mutex_lock_static (L_MSG); 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 (flags & M_OPTERR) { openvpn_snprintf (m2, ERR_BUF_SIZE, "Options error: %s", m1); SWAP; } #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 = ""; /* virtual output capability used to copy output to management subsystem */ if (!forked) { const struct virtual_output *vo = msg_get_virtual_output (); if (vo) { openvpn_snprintf (m2, ERR_BUF_SIZE, "%s%s%s", prefix, prefix_sep, m1); virtual_output_print (vo, flags, m2); } } if (!(flags & M_MSG_VIRT_OUT)) { if (use_syslog && !std_redir && !forked) { #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); if ((flags & M_NOPREFIX) || suppress_timestamps) { fprintf (fp, "%s%s%s%s", prefix, prefix_sep, m1, (flags&M_NOLF) ? "" : "\n"); } else { #ifdef USE_PTHREAD fprintf (fp, "%s [%d] %s%s%s%s", time_string (0, 0, show_usec, &gc), (int) openvpn_thread_self (), prefix, prefix_sep, m1, (flags&M_NOLF) ? "" : "\n"); #else fprintf (fp, "%s %s%s%s%s", time_string (0, 0, show_usec, &gc), prefix, prefix_sep, m1, (flags&M_NOLF) ? "" : "\n"); #endif } fflush(fp); ++x_msg_line_num; } } if (flags & M_FATAL) msg (M_INFO, "Exiting"); 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); }
int plugin_call (const struct plugin_list *pl, const int type, const struct argv *av, struct plugin_return *pr, struct env_set *es) { if (pr) plugin_return_init (pr); if (plugin_defined (pl, type)) { struct gc_arena gc = gc_new (); int i; const char **envp; const int n = plugin_n (pl); bool success = false; bool error = false; bool deferred = false; mutex_lock_static (L_PLUGIN); setenv_del (es, "script_type"); envp = make_env_array (es, false, &gc); for (i = 0; i < n; ++i) { const int status = plugin_call_item (&pl->common->plugins[i], pl->per_client.per_client_context[i], type, av, pr ? &pr->list[i] : NULL, envp); switch (status) { case OPENVPN_PLUGIN_FUNC_SUCCESS: success = true; break; case OPENVPN_PLUGIN_FUNC_DEFERRED: deferred = true; break; default: error = true; break; } } if (pr) pr->n = i; mutex_unlock_static (L_PLUGIN); gc_free (&gc); if (type == OPENVPN_PLUGIN_ENABLE_PF && success) return OPENVPN_PLUGIN_FUNC_SUCCESS; else if (error) return OPENVPN_PLUGIN_FUNC_ERROR; else if (deferred) return OPENVPN_PLUGIN_FUNC_DEFERRED; } return OPENVPN_PLUGIN_FUNC_SUCCESS; }