summaryrefslogtreecommitdiffstats
path: root/options.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 /options.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 'options.c')
-rw-r--r--options.c168
1 files changed, 163 insertions, 5 deletions
diff --git a/options.c b/options.c
index 0831e86..2c823db 100644
--- a/options.c
+++ b/options.c
@@ -761,7 +761,9 @@ void
uninit_options (struct options *o)
{
if (o->gc_owned)
- gc_free (&o->gc);
+ {
+ gc_free (&o->gc);
+ }
}
#ifdef ENABLE_DEBUG
@@ -1412,6 +1414,137 @@ init_http_options_if_undefined (struct options *o)
#endif
+#if HTTP_PROXY_FALLBACK
+
+static struct http_proxy_options *
+parse_http_proxy_override (const char *server,
+ const char *port,
+ const char *flags,
+ const int msglevel,
+ struct gc_arena *gc)
+{
+ if (server && port)
+ {
+ struct http_proxy_options *ho;
+ const int int_port = atoi(port);
+
+ if (!legal_ipv4_port (int_port))
+ {
+ msg (msglevel, "Bad http-proxy port number: %s", port);
+ return NULL;
+ }
+
+ ALLOC_OBJ_CLEAR_GC (ho, struct http_proxy_options, gc);
+ ho->server = string_alloc(server, gc);
+ ho->port = int_port;
+ ho->retry = true;
+ ho->timeout = 5;
+ if (flags && !strcmp(flags, "nct"))
+ ho->auth_retry = PAR_NCT;
+ else
+ ho->auth_retry = PAR_ALL;
+ ho->http_version = "1.0";
+ ho->user_agent = "OpenVPN-Autoproxy/1.0";
+ return ho;
+ }
+ else
+ return NULL;
+}
+
+struct http_proxy_options *
+parse_http_proxy_fallback (struct context *c,
+ const char *server,
+ const char *port,
+ const char *flags,
+ const int msglevel)
+{
+ struct gc_arena gc = gc_new ();
+ struct http_proxy_options *hp = parse_http_proxy_override(server, port, flags, msglevel, &gc);
+ struct hpo_store *hpos = c->options.hpo_store;
+ if (!hpos)
+ {
+ ALLOC_OBJ_CLEAR_GC (hpos, struct hpo_store, &c->options.gc);
+ c->options.hpo_store = hpos;
+ }
+ hpos->hpo = *hp;
+ hpos->hpo.server = hpos->server;
+ strncpynt(hpos->server, hp->server, sizeof(hpos->server));
+ gc_free (&gc);
+ return &hpos->hpo;
+}
+
+static void
+http_proxy_warn(const char *name)
+{
+ msg (M_WARN, "Note: option %s ignored because no TCP-based connection profiles are defined", name);
+}
+
+void
+options_postprocess_http_proxy_fallback (struct options *o)
+{
+ struct connection_list *l = o->connection_list;
+ if (l)
+ {
+ int i;
+ for (i = 0; i < l->len; ++i)
+ {
+ struct connection_entry *ce = l->array[i];
+ if (ce->proto == PROTO_TCPv4_CLIENT || ce->proto == PROTO_TCPv4)
+ {
+ if (l->len < CONNECTION_LIST_SIZE)
+ {
+ struct connection_entry *newce;
+ ALLOC_OBJ_GC (newce, struct connection_entry, &o->gc);
+ *newce = *ce;
+ newce->flags |= CE_HTTP_PROXY_FALLBACK;
+ newce->http_proxy_options = NULL;
+ newce->ce_http_proxy_fallback_timestamp = 0;
+ l->array[l->len++] = newce;
+ }
+ return;
+ }
+ }
+ }
+ http_proxy_warn("http-proxy-fallback");
+}
+
+void
+options_postprocess_http_proxy_override (struct options *o)
+{
+ const struct connection_list *l = o->connection_list;
+ if (l)
+ {
+ int i;
+ bool succeed = false;
+ for (i = 0; i < l->len; ++i)
+ {
+ struct connection_entry *ce = l->array[i];
+ if (ce->proto == PROTO_TCPv4_CLIENT || ce->proto == PROTO_TCPv4)
+ {
+ ce->http_proxy_options = o->http_proxy_override;
+ succeed = true;
+ }
+ }
+ if (succeed)
+ {
+ for (i = 0; i < l->len; ++i)
+ {
+ struct connection_entry *ce = l->array[i];
+ if (ce->proto == PROTO_UDPv4)
+ {
+ ce->flags |= CE_DISABLED;
+ }
+ }
+ }
+ else
+ {
+ http_proxy_warn("http-proxy-override");
+ }
+ }
+}
+
+#endif
+
#if ENABLE_CONNECTION
static struct connection_list *
@@ -2095,7 +2228,7 @@ options_postprocess_mutate (struct options *o)
* For compatibility with 2.0.x, map multiple --remote options
* into connection list (connection lists added in 2.1).
*/
- if (o->remote_list->len > 1)
+ if (o->remote_list->len > 1 || o->force_connection_list)
{
const struct remote_list *rl = o->remote_list;
int i;
@@ -2112,7 +2245,7 @@ options_postprocess_mutate (struct options *o)
*ace = ce;
}
}
- else if (o->remote_list->len == 1) /* one --remote option specfied */
+ else if (o->remote_list->len == 1) /* one --remote option specified */
{
connection_entry_load_re (&o->ce, o->remote_list->array[0]);
}
@@ -2126,6 +2259,13 @@ options_postprocess_mutate (struct options *o)
int i;
for (i = 0; i < o->connection_list->len; ++i)
options_postprocess_mutate_ce (o, o->connection_list->array[i]);
+
+#if HTTP_PROXY_FALLBACK
+ if (o->http_proxy_override)
+ options_postprocess_http_proxy_override(o);
+ else if (o->http_proxy_fallback)
+ options_postprocess_http_proxy_fallback(o);
+#endif
}
else
#endif
@@ -3633,11 +3773,29 @@ add_option (struct options *options,
}
}
#endif
+#ifdef ENABLE_CONNECTION
else if (streq (p[0], "remote-ip-hint") && p[1])
{
- VERIFY_PERMISSION (OPT_P_GENERAL|OPT_P_CONNECTION);
- // fixme
+ VERIFY_PERMISSION (OPT_P_GENERAL);
+ options->remote_ip_hint = p[1];
}
+#endif
+#if HTTP_PROXY_FALLBACK
+ else if (streq (p[0], "http-proxy-fallback"))
+ {
+ VERIFY_PERMISSION (OPT_P_GENERAL);
+ options->http_proxy_fallback = true;
+ options->force_connection_list = true;
+ }
+ else if (streq (p[0], "http-proxy-override") && p[1] && p[2])
+ {
+ VERIFY_PERMISSION (OPT_P_GENERAL);
+ options->http_proxy_override = parse_http_proxy_override(p[1], p[2], p[3], msglevel, &options->gc);
+ if (!options->http_proxy_override)
+ goto err;
+ options->force_connection_list = true;
+ }
+#endif
else if (streq (p[0], "remote") && p[1])
{
struct remote_entry re;