From 4f404ad36df1874d2580abc33e5c300222ec44b0 Mon Sep 17 00:00:00 2001 From: james Date: Mon, 23 Jan 2006 14:08:27 +0000 Subject: Added --management-client option to connect as a client to management GUI app rather than be connected to as a server. git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@884 e7ae566f-a301-0410-adde-c780ea21d3b5 --- ChangeLog | 6 +++ configure.ac | 2 +- init.c | 3 +- manage.c | 163 ++++++++++++++++++++++++++++++++++++++++++----------------- manage.h | 4 +- options.c | 10 +++- options.h | 1 + sig.c | 8 +++ sig.h | 1 + socket.c | 4 +- socket.h | 5 ++ 11 files changed, 155 insertions(+), 52 deletions(-) diff --git a/ChangeLog b/ChangeLog index d7f14d5..a9a0d0e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,12 @@ Copyright (C) 2002-2005 OpenVPN Solutions LLC $Id$ +2006.01.xx -- Version 2.1-beta9 + +* Added --management-client option to connect as a client + to management GUI app rather than be connected to as a + server. + 2006.01.03 -- Version 2.1-beta8 * --remap-usr1 will now also remap signals thrown during diff --git a/configure.ac b/configure.ac index 9090b2b..aeb7237 100644 --- a/configure.ac +++ b/configure.ac @@ -25,7 +25,7 @@ dnl Process this file with autoconf to produce a configure script. AC_PREREQ(2.50) -AC_INIT([OpenVPN], [2.1_beta8], [openvpn-users@lists.sourceforge.net], [openvpn]) +AC_INIT([OpenVPN], [2.1_beta8a], [openvpn-users@lists.sourceforge.net], [openvpn]) AM_CONFIG_HEADER(config.h) AC_CONFIG_SRCDIR(syshead.h) diff --git a/init.c b/init.c index 3b9931a..97bf9ec 100644 --- a/init.c +++ b/init.c @@ -2392,7 +2392,8 @@ open_management (struct context *c) c->options.management_log_history_cache, c->options.management_echo_buffer_size, c->options.management_state_buffer_size, - c->options.management_hold)) + c->options.management_hold, + c->options.management_client)) { management_set_state (management, OPENVPN_STATE_CONNECTING, diff --git a/manage.c b/manage.c index 127e933..935b18a 100644 --- a/manage.c +++ b/manage.c @@ -59,7 +59,7 @@ struct management *management; /* GLOBAL */ /* static forward declarations */ static void man_output_standalone (struct management *man, volatile int *signal_received); -static void man_reset_client_socket (struct management *man, const bool listen); +static void man_reset_client_socket (struct management *man, const bool exiting); static void man_help () @@ -259,7 +259,7 @@ virtual_output_callback_func (void *arg, const unsigned int flags, const char *s if (out) { man_output_list_push (man, out); - man_reset_client_socket (man, false); + man_reset_client_socket (man, true); } } } @@ -792,9 +792,48 @@ man_stop_ne32 (struct management *man) #endif static void -man_accept (struct management *man) +man_connection_settings_reset (struct management *man) +{ + man->connection.state_realtime = false; + man->connection.log_realtime = false; + man->connection.echo_realtime = false; + man->connection.password_verified = false; + man->connection.password_tries = 0; + man->connection.halt = false; + man->connection.state = MS_CC_WAIT_WRITE; +} + +static void +man_new_connection_post (struct management *man, const char *description) { struct gc_arena gc = gc_new (); + + set_nonblock (man->connection.sd_cli); + set_cloexec (man->connection.sd_cli); + + man_connection_settings_reset (man); + +#ifdef WIN32 + man_start_ne32 (man); +#endif + + msg (D_MANAGEMENT, "MANAGEMENT: %s %s", + description, + print_sockaddr (&man->settings.local, &gc)); + + output_list_reset (man->connection.out); + + if (!man_password_needed (man)) + man_welcome (man); + man_prompt (man); + man_update_io_state (man); + + gc_free (&gc); +} + +static void +man_accept (struct management *man) +{ struct link_socket_actual act; /* @@ -812,36 +851,8 @@ man_accept (struct management *man) #endif } - /* - * Set misc socket properties - */ - set_nonblock (man->connection.sd_cli); - set_cloexec (man->connection.sd_cli); - - man->connection.state_realtime = false; - man->connection.log_realtime = false; - man->connection.echo_realtime = false; - man->connection.password_verified = false; - man->connection.password_tries = 0; - man->connection.halt = false; - man->connection.state = MS_CC_WAIT_WRITE; - -#ifdef WIN32 - man_start_ne32 (man); -#endif - - msg (D_MANAGEMENT, "MANAGEMENT: Client connected from %s", - print_sockaddr (&man->settings.local, &gc)); - - output_list_reset (man->connection.out); - - if (!man_password_needed (man)) - man_welcome (man); - man_prompt (man); - man_update_io_state (man); + man_new_connection_post (man, "Client connected from"); } - - gc_free (&gc); } static void @@ -891,7 +902,49 @@ man_listen (struct management *man) } static void -man_reset_client_socket (struct management *man, const bool listen) +man_connect (struct management *man) +{ + struct gc_arena gc = gc_new (); + int status; + int signal_received = 0; + + /* + * Initialize state + */ + man->connection.state = MS_INITIAL; + man->connection.sd_top = SOCKET_UNDEFINED; + + man->connection.sd_cli = create_socket_tcp (); + + status = openvpn_connect (man->connection.sd_cli, + &man->settings.local, + 5, + &signal_received); + + if (signal_received) + { + throw_signal (signal_received); + goto done; + } + + if (status) + { + msg (D_LINK_ERRORS, + "MANAGEMENT: connect to %s failed: %s", + print_sockaddr (&man->settings.local, &gc), + strerror_ts (status, &gc)); + throw_signal_soft (SIGTERM, "management-connect-failed"); + goto done; + } + + man_new_connection_post (man, "Connected to management server at"); + + done: + gc_free (&gc); +} + +static void +man_reset_client_socket (struct management *man, const bool exiting) { if (socket_defined (man->connection.sd_cli)) { @@ -900,11 +953,17 @@ man_reset_client_socket (struct management *man, const bool listen) man_stop_ne32 (man); #endif man_close_socket (man, man->connection.sd_cli); + man->connection.sd_cli = SOCKET_UNDEFINED; command_line_reset (man->connection.in); output_list_reset (man->connection.out); } - if (listen) - man_listen (man); + if (!exiting) + { + if (man->settings.connect_as_client) + throw_signal_soft (SIGTERM, "management-exit"); + else + man_listen (man); + } } static void @@ -978,7 +1037,7 @@ man_read (struct management *man) len = recv (man->connection.sd_cli, buf, sizeof (buf), MSG_NOSIGNAL); if (len == 0) { - man_reset_client_socket (man, true); + man_reset_client_socket (man, false); } else if (len > 0) { @@ -1012,7 +1071,7 @@ man_read (struct management *man) */ if (man->connection.halt) { - man_reset_client_socket (man, true); + man_reset_client_socket (man, false); len = 0; } else @@ -1025,7 +1084,7 @@ man_read (struct management *man) else /* len < 0 */ { if (man_io_error (man, "recv")) - man_reset_client_socket (man, true); + man_reset_client_socket (man, false); } return len; } @@ -1048,7 +1107,7 @@ man_write (struct management *man) else if (sent < 0) { if (man_io_error (man, "send")) - man_reset_client_socket (man, true); + man_reset_client_socket (man, false); } } @@ -1139,7 +1198,8 @@ man_settings_init (struct man_settings *ms, const int log_history_cache, const int echo_buffer_size, const int state_buffer_size, - const bool hold) + const bool hold, + const bool connect_as_client) { if (!ms->defined) { @@ -1168,6 +1228,12 @@ man_settings_init (struct man_settings *ms, */ ms->hold = hold; + /* + * Should OpenVPN connect to management interface as a client + * rather than a server? + */ + ms->connect_as_client = connect_as_client; + /* * Initialize socket address */ @@ -1179,7 +1245,7 @@ man_settings_init (struct man_settings *ms, * Run management over tunnel, or * separate channel? */ - if (streq (addr, "tunnel")) + if (streq (addr, "tunnel") && !connect_as_client) { ms->management_over_tunnel = true; } @@ -1237,9 +1303,12 @@ man_connection_init (struct management *man) } /* - * Listen on socket + * Listen/connect socket */ - man_listen (man); + if (man->settings.connect_as_client) + man_connect (man); + else + man_listen (man); } } @@ -1290,7 +1359,8 @@ management_open (struct management *man, const int log_history_cache, const int echo_buffer_size, const int state_buffer_size, - const bool hold) + const bool hold, + const bool connect_as_client) { bool ret = false; @@ -1307,7 +1377,8 @@ management_open (struct management *man, log_history_cache, echo_buffer_size, state_buffer_size, - hold); + hold, + connect_as_client); /* * The log is initially sized to MANAGEMENT_LOG_HISTORY_INITIAL_SIZE, @@ -1510,7 +1581,7 @@ management_io (struct management *man) if (net_events & FD_CLOSE) { - man_reset_client_socket (man, true); + man_reset_client_socket (man, false); } else { diff --git a/manage.h b/manage.h index c492866..873bb42 100644 --- a/manage.h +++ b/manage.h @@ -200,6 +200,7 @@ struct man_settings { int state_buffer_size; bool server; bool hold; + bool connect_as_client; }; /* up_query modes */ @@ -265,7 +266,8 @@ bool management_open (struct management *man, const int log_history_cache, const int echo_buffer_size, const int state_buffer_size, - const bool hold); + const bool hold, + const bool connect_as_client); void management_close (struct management *man); diff --git a/options.c b/options.c index 903cb7d..45d0023 100644 --- a/options.c +++ b/options.c @@ -299,6 +299,8 @@ static const char usage_message[] = "--management ip port [pass] : Enable a TCP server on ip:port to handle\n" " management functions. pass is a password file\n" " or 'stdin' to prompt from console.\n" + "--management-client : Management interface will connect as a TCP client to\n" + " ip/port rather than listen as a TCP server.\n" "--management-query-passwords : Query management channel for private key\n" " and auth-user-pass passwords.\n" "--management-hold : Start " PACKAGE_NAME " in a hibernating state, until a client\n" @@ -1181,6 +1183,7 @@ show_settings (const struct options *o) SHOW_INT (management_echo_buffer_size); SHOW_BOOL (management_query_passwords); SHOW_BOOL (management_hold); + SHOW_BOOL (management_client); #endif #ifdef ENABLE_PLUGIN if (o->plugin_list) @@ -1495,7 +1498,7 @@ options_postprocess (struct options *options, bool first_time) */ #ifdef ENABLE_MANAGEMENT if (!options->management_addr && - (options->management_query_passwords || options->management_hold + (options->management_query_passwords || options->management_hold || options->management_client || options->management_log_history_cache != defaults.management_log_history_cache)) msg (M_USAGE, "--management is not specified, however one or more options which modify the behavior of --management were specified"); #endif @@ -3122,6 +3125,11 @@ add_option (struct options *options, VERIFY_PERMISSION (OPT_P_GENERAL); options->management_hold = true; } + else if (streq (p[0], "management-client")) + { + VERIFY_PERMISSION (OPT_P_GENERAL); + options->management_client = true; + } else if (streq (p[0], "management-log-cache") && p[1]) { int cache; diff --git a/options.h b/options.h index 644d7cb..ca04cab 100644 --- a/options.h +++ b/options.h @@ -279,6 +279,7 @@ struct options int management_state_buffer_size; bool management_query_passwords; bool management_hold; + bool management_client; #endif #ifdef ENABLE_PLUGIN diff --git a/sig.c b/sig.c index 7279b82..7eb120e 100644 --- a/sig.c +++ b/sig.c @@ -100,6 +100,14 @@ throw_signal (const int signum) siginfo_static.hard = true; } +void +throw_signal_soft (const int signum, const char *signal_text) +{ + siginfo_static.signal_received = signum; + siginfo_static.hard = false; + siginfo_static.signal_text = signal_text; +} + static void signal_reset (struct signal_info *si) { diff --git a/sig.h b/sig.h index dd17c40..5c32df6 100644 --- a/sig.h +++ b/sig.h @@ -49,6 +49,7 @@ int parse_signal (const char *signame); const char *signal_name (const int sig, const bool upper); const char *signal_description (const int signum, const char *sigtext); void throw_signal (const int signum); +void throw_signal_soft (const int signum, const char *signal_text); void pre_init_signal_catch (void); void post_init_signal_catch (void); diff --git a/socket.c b/socket.c index 6bc8530..38b0c15 100644 --- a/socket.c +++ b/socket.c @@ -712,7 +712,7 @@ socket_bind (socket_descriptor_t sd, gc_free (&gc); } -static int +int openvpn_connect (socket_descriptor_t sd, struct openvpn_sockaddr *remote, int connect_timeout, @@ -785,7 +785,7 @@ openvpn_connect (socket_descriptor_t sd, return status; } -static void +void socket_connect (socket_descriptor_t *sd, struct openvpn_sockaddr *local, bool bind_local, diff --git a/socket.h b/socket.h index b1a4aaa..79f06b5 100644 --- a/socket.h +++ b/socket.h @@ -272,6 +272,11 @@ void socket_bind (socket_descriptor_t sd, struct openvpn_sockaddr *local, const char *prefix); +int openvpn_connect (socket_descriptor_t sd, + struct openvpn_sockaddr *remote, + int connect_timeout, + volatile int *signal_received); + /* * Initialize link_socket object. */ -- cgit v1.2.3