summaryrefslogtreecommitdiffstats
path: root/manage.c
diff options
context:
space:
mode:
authorJames Yonan <james@openvpn.net>2010-05-24 22:51:16 +0000
committerJames Yonan <james@openvpn.net>2010-05-24 22:51:16 +0000
commit3cf6c9328250061600b78c8a7deb0edc850e739b (patch)
treebc6032117107a8e801e8203c40b1d9533b657597 /manage.c
parent484e9d36d09e3494a6d964c588c353f650a61b5f (diff)
downloadopenvpn-3cf6c9328250061600b78c8a7deb0edc850e739b.tar.gz
openvpn-3cf6c9328250061600b78c8a7deb0edc850e739b.tar.xz
openvpn-3cf6c9328250061600b78c8a7deb0edc850e739b.zip
Implemented http-proxy-override and http-proxy-fallback directives to make it
easier for OpenVPN client UIs to start a pre-existing client config file with proxy options, or to adaptively fall back to a proxy connection if a direct connection fails. git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@5652 e7ae566f-a301-0410-adde-c780ea21d3b5
Diffstat (limited to 'manage.c')
-rw-r--r--manage.c118
1 files changed, 96 insertions, 22 deletions
diff --git a/manage.c b/manage.c
index 5fdfb95..2094723 100644
--- a/manage.c
+++ b/manage.c
@@ -110,6 +110,10 @@ man_help ()
msg (M_CLIENT, "username type u : Enter username u for a queried OpenVPN username.");
msg (M_CLIENT, "verb [n] : Set log verbosity level to n, or show if n is absent.");
msg (M_CLIENT, "version : Show current version number.");
+#if HTTP_PROXY_FALLBACK
+ msg (M_CLIENT, "http-proxy-fallback <server> <port> [flags] : Enter dynamic HTTP proxy fallback info.");
+ msg (M_CLIENT, "http-proxy-fallback-disable : Disable HTTP proxy fallback.");
+#endif
msg (M_CLIENT, "END");
}
@@ -204,12 +208,10 @@ man_update_io_state (struct management *man)
}
static void
-man_output_list_push (struct management *man, const char *str)
+man_output_list_push_finalize (struct management *man)
{
if (management_connected (man))
{
- if (str)
- buffer_list_push (man->connection.out, (const unsigned char *) str);
man_update_io_state (man);
if (!man->persist.standalone_disabled)
{
@@ -220,6 +222,22 @@ man_output_list_push (struct management *man, const char *str)
}
static void
+man_output_list_push_str (struct management *man, const char *str)
+{
+ if (management_connected (man) && str)
+ {
+ buffer_list_push (man->connection.out, (const unsigned char *) str);
+ }
+}
+
+static void
+man_output_list_push (struct management *man, const char *str)
+{
+ man_output_list_push_str (man, str);
+ man_output_list_push_finalize (man);
+}
+
+static void
man_prompt (struct management *man)
{
if (man_password_needed (man))
@@ -256,12 +274,13 @@ man_close_socket (struct management *man, const socket_descriptor_t sd)
static void
virtual_output_callback_func (void *arg, const unsigned int flags, const char *str)
{
+ struct management *man = (struct management *) arg;
static int recursive_level = 0; /* GLOBAL */
+ bool did_push = false;
if (!recursive_level) /* don't allow recursion */
{
struct gc_arena gc = gc_new ();
- struct management *man = (struct management *) arg;
struct log_entry e;
const char *out = NULL;
@@ -289,13 +308,17 @@ virtual_output_callback_func (void *arg, const unsigned int flags, const char *s
| LOG_PRINT_LOG_PREFIX
| LOG_PRINT_CRLF, &gc);
if (out)
- man_output_list_push (man, out);
+ {
+ man_output_list_push_str (man, out);
+ did_push = true;
+ }
if (flags & M_FATAL)
{
out = log_entry_print (&e, LOG_FATAL_NOTIFY|LOG_PRINT_CRLF, &gc);
if (out)
{
- man_output_list_push (man, out);
+ man_output_list_push_str (man, out);
+ did_push = true;
man_reset_client_socket (man, true);
}
}
@@ -304,6 +327,9 @@ virtual_output_callback_func (void *arg, const unsigned int flags, const char *s
--recursive_level;
gc_free (&gc);
}
+
+ if (did_push)
+ man_output_list_push_finalize (man);
}
/*
@@ -998,6 +1024,31 @@ man_need (struct management *man, const char **p, const int n, unsigned int flag
return true;
}
+#if HTTP_PROXY_FALLBACK
+
+static void
+man_http_proxy_fallback (struct management *man, const char *server, const char *port, const char *flags)
+{
+ if (man->persist.callback.http_proxy_fallback_cmd)
+ {
+ const bool status = (*man->persist.callback.http_proxy_fallback_cmd)(man->persist.callback.arg, server, port, flags);
+ if (status)
+ {
+ msg (M_CLIENT, "SUCCESS: proxy-fallback command succeeded");
+ }
+ else
+ {
+ msg (M_CLIENT, "ERROR: proxy-fallback command failed");
+ }
+ }
+ else
+ {
+ msg (M_CLIENT, "ERROR: The proxy-fallback command is not supported by the current daemon mode");
+ }
+}
+
+#endif
+
static void
man_dispatch_command (struct management *man, struct status_output *so, const char **p, const int nparms)
{
@@ -1210,6 +1261,17 @@ man_dispatch_command (struct management *man, struct status_output *so, const ch
man_pkcs11_id_get (man, atoi(p[1]));
}
#endif
+#if HTTP_PROXY_FALLBACK
+ else if (streq (p[0], "http-proxy-fallback"))
+ {
+ if (man_need (man, p, 2, MN_AT_LEAST))
+ man_http_proxy_fallback (man, p[1], p[2], p[3]);
+ }
+ else if (streq (p[0], "http-proxy-fallback-disable"))
+ {
+ man_http_proxy_fallback (man, NULL, NULL, NULL);
+ }
+#endif
#if 1
else if (streq (p[0], "test"))
{
@@ -2103,7 +2165,7 @@ management_clear_callback (struct management *man)
man->persist.standalone_disabled = false;
man->persist.hold_release = false;
CLEAR (man->persist.callback);
- man_output_list_push (man, NULL); /* flush output queue */
+ man_output_list_push_finalize (man); /* flush output queue */
}
void
@@ -2402,7 +2464,7 @@ management_io (struct management *man)
net_event_win32_clear_selected_events (&man->connection.ne32, FD_ACCEPT);
}
}
- else if (man->connection.state == MS_CC_WAIT_READ)
+ else if (man->connection.state == MS_CC_WAIT_READ || man->connection.state == MS_CC_WAIT_WRITE)
{
if (net_events & FD_READ)
{
@@ -2410,18 +2472,13 @@ management_io (struct management *man)
;
net_event_win32_clear_selected_events (&man->connection.ne32, FD_READ);
}
- }
- if (man->connection.state == MS_CC_WAIT_WRITE)
- {
if (net_events & FD_WRITE)
{
int status;
- /* dmsg (M_INFO, "FD_WRITE set"); */
status = man_write (man);
if (status < 0 && WSAGetLastError() == WSAEWOULDBLOCK)
{
- /* dmsg (M_INFO, "FD_WRITE cleared"); */
net_event_win32_clear_selected_events (&man->connection.ne32, FD_WRITE);
}
}
@@ -2512,7 +2569,7 @@ man_block (struct management *man, volatile int *signal_received, const time_t e
if (man_standalone_ok (man))
{
- do
+ while (true)
{
event_reset (man->connection.es);
management_socket_set (man, man->connection.es, NULL, NULL);
@@ -2530,15 +2587,18 @@ man_block (struct management *man, volatile int *signal_received, const time_t e
status = -1;
break;
}
- /* set SIGINT signal if expiration time exceeded */
- if (expire && now >= expire)
+
+ if (status > 0)
+ break;
+ else if (expire && now >= expire)
{
+ /* set SIGINT signal if expiration time exceeded */
status = 0;
if (signal_received)
*signal_received = SIGINT;
break;
}
- } while (status != 1);
+ }
}
return status;
}
@@ -2615,28 +2675,29 @@ management_event_loop_n_seconds (struct management *man, int sec)
{
volatile int signal_received = 0;
const bool standalone_disabled_save = man->persist.standalone_disabled;
- time_t expire;
+ time_t expire = 0;
man->persist.standalone_disabled = false; /* This is so M_CLIENT messages will be correctly passed through msg() */
/* set expire time */
update_time ();
- expire = now + sec;
+ if (sec)
+ expire = now + sec;
/* if no client connection, wait for one */
man_wait_for_client_connection (man, &signal_received, expire, 0);
if (signal_received)
return;
- /* run command processing event loop until we get our username/password */
- while (true)
+ /* run command processing event loop */
+ do
{
man_standalone_event_loop (man, &signal_received, expire);
if (!signal_received)
man_check_for_signals (&signal_received);
if (signal_received)
return;
- }
+ } while (expire);
/* revert state */
man->persist.standalone_disabled = standalone_disabled_save;
@@ -3028,6 +3089,19 @@ log_history_ref (const struct log_history *h, const int index)
return NULL;
}
+#if HTTP_PROXY_FALLBACK
+
+void
+management_http_proxy_fallback_notify (struct management *man, const char *type, const char *remote_ip_hint)
+{
+ if (remote_ip_hint)
+ msg (M_CLIENT, ">PROXY:%s,%s", type, remote_ip_hint);
+ else
+ msg (M_CLIENT, ">PROXY:%s", type);
+}
+
+#endif /* HTTP_PROXY_FALLBACK */
+
#else
static void dummy(void) {}
#endif /* ENABLE_MANAGEMENT */