diff options
author | James Yonan <james@openvpn.net> | 2010-05-24 22:51:16 +0000 |
---|---|---|
committer | James Yonan <james@openvpn.net> | 2010-05-24 22:51:16 +0000 |
commit | 3cf6c9328250061600b78c8a7deb0edc850e739b (patch) | |
tree | bc6032117107a8e801e8203c40b1d9533b657597 /options.c | |
parent | Minor fixes to recent HTTP proxy changes: (diff) | |
download | openvpn-3cf6c9328250061600b78c8a7deb0edc850e739b.tar.xz |
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 '')
-rw-r--r-- | options.c | 168 |
1 files changed, 163 insertions, 5 deletions
@@ -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; |