39#ifdef ASIO_HAS_LOCAL_SOCKETS
43#if defined(OPENVPN_PLATFORM_WIN)
101 std::ostringstream
os;
106 for (
auto &line :
extra)
116 const size_t max_size_arg)
131 const std::string arg1 = o.
get_default(1, 16,
"1");
139 else if (!arg2.empty())
143 else if (arg1 ==
"all")
147 else if (arg1 ==
"off")
161 catch (
const option_error &)
165 catch (
const std::exception &e)
167 return "ERROR: " +
type +
" processing error: " + e.what() +
"\r\n";
179 return std::string();
183 std::string
show(
size_t n)
const
185 std::string
ret =
"";
186 n = std::min(n,
hist.size());
187 for (
size_t i = 0; i < n; ++i)
200 std::string
ret =
"SUCCESS: real-time " +
type +
" notification set to ";
211 return "ERROR: " +
type +
" parameter must be 'on' or 'off' or some number n or 'all'\r\n";
220 OMICore(openvpn_io::io_context &io_context_arg)
230#if defined(OPENVPN_PLATFORM_WIN)
247 const std::string config_fn = opt.
get(
"config", 1, 256);
254 const std::string addr = o.
get(1, 256);
255 const std::string
port = o.
get(2, 16);
256 const std::string password_file = o.
get_optional(3, 256);
258 if (password_file ==
"stdin")
261 std::cout <<
"Enter Management Password:";
272 const size_t low_water = o->
get_num<
size_t>(1, 0, 0, 1000000);
273 const size_t high_water = o->
get_num<
size_t>(2, 0, 0, 1000000);
283 if (o->
get(1, 64) ==
"root")
286 throw Exception(
"only --management-client-user root supported");
290 if (opt.
exists(
"management-client"))
294 OPENVPN_LOG(
"OMI Connecting to " << addr <<
" [unix]");
299 OPENVPN_LOG(
"OMI Connecting to [" << addr <<
"]:" <<
port <<
" [tcp]");
307 OPENVPN_LOG(
"OMI Listening on " << addr <<
" [unix]");
359 const time_t now = ::time(NULL);
362#if defined(OPENVPN_PLATFORM_WIN)
363 if (log_handle.defined())
367 std::cout <<
date_time(now) <<
' ' << text << std::flush;
434 const size_t high_water_arg)
439 throw Exception(
"bad management-queue-limit values");
471 const std::string arg0 = cmd->option.get_optional(0, 64);
474 if (!cmd->valid_utf8)
480 if (arg0 ==
"bytecount")
505 bool release =
false;
538 if (arg0 ==
"signal")
548 catch (
const std::exception &e)
550 std::string err_ref =
"option";
552 err_ref = cmd->option.err_ref();
553 send(
"ERROR: error processing " + err_ref +
" : " + e.what() +
"\r\n");
571 return "SUCCESS: hold=1\r\n";
573 return "SUCCESS: hold=0\r\n";
575 else if (arg1 ==
"on")
578 return "SUCCESS: hold flag set to ON\r\n";
580 else if (arg1 ==
"off")
583 return "SUCCESS: hold flag set to OFF\r\n";
585 else if (arg1 ==
"release")
588 return "SUCCESS: hold release succeeded\r\n";
591 catch (
const option_error &)
594 return "ERROR: bad hold command parameter\r\n";
601 send(
">HOLD:Waiting for hold release\r\n");
618 send(
"SUCCESS: bytecount interval changed\r\n");
623 const std::string type = o.
get(1, 16);
624 if (type ==
"SIGTERM")
626 send(
"SUCCESS: signal SIGTERM thrown\r\n");
631 send(
"SUCCESS: signal SIGHUP thrown\r\n");
635 send(
"ERROR: signal not supported\r\n");
665 self->stop_omi_client(eof); });
684 send(
">INFO:OpenVPN Management Interface Version 1 -- type 'help' for more info\r\n");
689 send(
"ENTER PASSWORD:");
694 send(
"SUCCESS: password is correct\r\n");
731 throw omi_error(
"process_in_line: internal error");
775 a->local_endpoint.address(ip_addr.
to_asio());
779 a->acceptor.open(a->local_endpoint.protocol());
782 a->set_socket_options(0);
785 a->acceptor.bind(a->local_endpoint);
788 a->acceptor.listen();
799#ifdef ASIO_HAS_LOCAL_SOCKETS
804 a->pre_listen(socket_path);
805 a->local_endpoint.path(socket_path);
808 a->acceptor.open(a->local_endpoint.protocol());
811 a->acceptor.bind(a->local_endpoint);
814 a->set_socket_permissions(socket_path, 0777);
817 a->acceptor.listen();
825 throw Exception(
"unix sockets not supported on this platform");
837#ifdef ASIO_HAS_LOCAL_SOCKETS
856 throw Exception(
"accept/connect failed: " + error.message());
858 throw Exception(
"client already connected");
862 sock->non_blocking(
true);
878 catch (
const std::exception &e)
880 const std::string
msg =
"exception in accept/connect handler: " + std::string(e.what()) +
'\n';
882 std::cerr <<
msg << std::flush;
894 s->
socket.async_connect(ep,
895 [self =
Ptr(
this), sock](
const openvpn_io::error_code &error)
mutable
898 self->handle_accept(std::move(sock), error);
904#ifdef ASIO_HAS_LOCAL_SOCKETS
905 openvpn_io::local::stream_protocol::endpoint ep(socket_path);
906 AsioPolySock::Unix *s =
new AsioPolySock::Unix(
io_context, 0);
908 s->socket.async_connect(ep,
909 [self =
Ptr(
this), sock](
const openvpn_io::error_code &error)
mutable
912 self->handle_accept(std::move(sock), error);
915 throw Exception(
"unix sockets not supported on this platform");
924 socket->async_receive(buf->mutable_buffer_clamp(),
925 [self =
Ptr(
this), sock =
socket, buf](
const openvpn_io::error_code &error,
const size_t bytes_recvd)
927 self->handle_recv(error, bytes_recvd, std::move(buf), sock.get());
933 const size_t bytes_recvd,
942 const bool eof = (error == openvpn_io::error::eof);
944 OPENVPN_LOG(
"client socket recv error: " << error.message());
948 buf->set_size(bytes_recvd);
957 const char c = (char)
in_buf->pop_front();
966 catch (
const std::exception &e)
968 send(
"ERROR: in OMI command: " + std::string(e.what()) +
"\r\n");
984 socket->async_send(buf.const_buffer_clamp(),
985 [self =
Ptr(
this), sock =
socket](
const openvpn_io::error_code &error,
const size_t bytes_sent)
987 self->handle_send(error, bytes_sent, sock.get());
992 const size_t bytes_sent,
1000 OPENVPN_LOG(
"client socket send error: " << error.message());
1006 if (bytes_sent == buf->size())
1012 else if (bytes_sent < buf->size())
1013 buf->advance(bytes_sent);
1016 OPENVPN_LOG(
"client socket unexpected send size: " << bytes_sent <<
'/' << buf->size());
1062#if defined(OPENVPN_PLATFORM_WIN)
std::size_t expires_after(const Time::Duration &d)
void async_wait(F &&func)
static Addr from_string(const std::string &ipstr, const TITLE &title, const Version required_version)
openvpn_io::ip::address to_asio() const
BufferThrottle(const size_t low_water_arg, const size_t high_water_arg)
void size_change(const size_t size)
bool is_cmd(const Option &o) const
std::string notify(const std::string &msg)
History(const std::string &type_arg, const size_t max_size_arg)
std::string real_time_status() const
std::string show(size_t n) const
std::string error() const
std::deque< std::string > hist
std::string process_cmd(const Option &o)
std::string notify_prefix() const
virtual void omi_start_connection()=0
void send_password_prompt()
bool is_errors_to_stderr() const
void listen_unix(const std::string &socket_path)
virtual void omi_sigterm()=0
OPENVPN_EXCEPTION(omi_error)
void verify_sock_peer(AsioPolySock::Base &sock)
virtual void omi_sighup()
void log_setup(const LogFn &log)
unsigned int get_bytecount() const
bool command_is_multiline(const Option &o)
AsioPolySock::Base::Ptr socket
void listen_tcp(const std::string &addr, const std::string &port)
void connect_tcp(const std::string &addr, const std::string &port)
void send_password_correct()
void start(const OptionList &opt)
void state_line(const std::string &line)
OMICore(openvpn_io::io_context &io_context_arg)
void log_full(const std::string &text)
void send_title_message()
void send(const std::string &str)
virtual bool omi_command_in(const std::string &arg0, const Command &cmd)=0
void start_connection_if_not_hold()
std::unique_ptr< BufferThrottle > content_out_throttle
void handle_accept(AsioPolySock::Base::Ptr sock, const openvpn_io::error_code &error) override
void process_signal_cmd(const Option &o)
virtual bool omi_command_is_multiline(const std::string &arg0, const Option &option)=0
bool is_hold_cmd(const Option &o) const
virtual bool omi_is_sighup_implemented()
bool command_in(std::unique_ptr< Command > cmd)
static std::string get_config(const OptionList &opt)
std::deque< BufferPtr > content_out
volatile bool stop_called
openvpn_io::io_context & io_context
virtual void omi_done(const bool eof)=0
bool is_sock_open() const
void log_timestamp(const time_t timestamp, const std::string &text)
void conditional_stop(const bool eof)
bool management_client_root
void handle_recv(const openvpn_io::error_code &error, const size_t bytes_recvd, BufferPtr buf, const AsioPolySock::Base *queued_socket)
std::string hold_cmd(const Option &o, bool &release)
void process_bytecount_cmd(const Option &o)
void stop_omi_client(const bool eof)
void echo_line(const std::string &line)
static std::string read_config(const std::string &fn)
std::unique_ptr< Command > command
virtual bool omi_stop()=0
std::unique_ptr< AsioWork > asio_work
void log_line(const std::string &line)
void stop_omi_client(const bool eof, const unsigned int milliseconds)
void connect_unix(const std::string &socket_path)
Acceptor::Base::Ptr acceptor
void handle_send(const openvpn_io::error_code &error, const size_t bytes_sent, const AsioPolySock::Base *queued_socket)
std::string get_optional(const std::string &name, size_t index, const size_t max_len) const
static Option parse_option_from_line(const std::string &line, Limits *lim)
const Option & get(const std::string &name) const
const Option * get_ptr(const std::string &name) const
bool exists(const std::string &name) const
std::string get_default(const size_t index, const size_t max_len, const std::string &default_value) const
std::string get_optional(const size_t index, const size_t max_len) const
const std::string & get(const size_t index, const size_t max_len) const
T get_num(const size_t idx) const
std::string render(const unsigned int flags) const
T * get() const noexcept
Returns the raw pointer to the object T, or nullptr.
static Ptr Create(ArgsT &&...args)
Creates a new instance of RcEnable with the given arguments.
static constexpr int FLAGS_OVERWRITE
static constexpr mode_t MODE_ALL
static constexpr int FLAGS_APPEND
#define OPENVPN_LOG(args)
#define OPENVPN_LOG_STRING(str)
unsigned short parse_port(const std::string &port, const std::string &title)
bool is_valid_utf8(const STRING &str, const size_t max_len_flags=0)
void log(const HANDLE file, const std::string &str)
ScopedHANDLE create_file(const std::string &fn, const std::string &sddl_string, bool append)
void trim_crlf(STRING &str)
std::string unix2dos(const std::string &str, const bool force_eol=false)
std::string to_upper_copy(const std::string &str)
std::string read_text_utf8(const std::string &filename, const std::uint64_t max_size=0)
std::string to_string(const T &t)
Convert a value to a string.
bool parse_number(const char *str, T &retval, const bool nondigit_term=false)
BufferPtr buf_from_string(const std::string &str)
openvpn_io::ip::tcp::socket socket
std::string to_string() const
std::vector< std::string > extra
LogFn(const OptionList &opt)
void redirect() noexcept override
os<< "Session Name: "<< tbc-> session_name<< '\n';os<< "Layer: "<< tbc-> layer str()<< '\n'