Merged connection profiles from

http://svn.openvpn.net/projects/openvpn/test/conn


git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@2993 e7ae566f-a301-0410-adde-c780ea21d3b5
This commit is contained in:
james 2008-06-11 10:48:50 +00:00
parent 90efcacba6
commit 4e9a51d78f
23 changed files with 1083 additions and 589 deletions

View file

@ -314,6 +314,26 @@ x_gc_free (struct gc_arena *a)
}
}
/*
* Transfer src arena to dest, resetting src to an empty arena.
*/
void
gc_transfer (struct gc_arena *dest, struct gc_arena *src)
{
if (dest && src)
{
struct gc_entry *e = src->list;
if (e)
{
while (e->next != NULL)
e = e->next;
e->next = dest->list;
dest->list = src->list;
src->list = NULL;
}
}
}
/*
* Hex dump -- Output a binary buffer to a hex string and return it.
*/

View file

@ -632,6 +632,8 @@ void character_class_debug (void);
* char ptrs to malloced strings.
*/
void gc_transfer (struct gc_arena *dest, struct gc_arena *src);
void x_gc_free (struct gc_arena *a);
static inline void

View file

@ -120,7 +120,7 @@
#define D_MULTI_DEBUG LOGLEV(7, 70, M_DEBUG) /* show medium-freq multi debugging info */
#define D_MSS LOGLEV(7, 70, M_DEBUG) /* show MSS adjustments */
#define D_COMP_LOW LOGLEV(7, 70, M_DEBUG) /* show adaptive compression state changes */
#define D_REMOTE_LIST LOGLEV(7, 70, M_DEBUG) /* show --remote list */
#define D_CONNECTION_LIST LOGLEV(7, 70, M_DEBUG) /* show <connection> list info */
#define D_SCRIPT LOGLEV(7, 70, M_DEBUG) /* show parms & env vars passed to scripts */
#define D_SHOW_NET LOGLEV(7, 70, M_DEBUG) /* show routing table and adapter list */
#define D_ROUTE_DEBUG LOGLEV(7, 70, M_DEBUG) /* show verbose route.[ch] output */

View file

@ -356,7 +356,7 @@ check_fragment_dowork (struct context *c)
if (lsi->mtu_changed && c->c2.ipv4_tun)
{
frame_adjust_path_mtu (&c->c2.frame_fragment, c->c2.link_socket->mtu,
c->options.proto);
c->options.ce.proto);
lsi->mtu_changed = false;
}
@ -1038,7 +1038,7 @@ process_outgoing_link (struct context *c)
#ifdef HAVE_GETTIMEOFDAY
if (c->options.shaper)
shaper_wrote_bytes (&c->c2.shaper, BLEN (&c->c2.to_link)
+ datagram_overhead (c->options.proto));
+ datagram_overhead (c->options.ce.proto));
#endif
/*
* Let the pinger know that we sent a packet.

View file

@ -281,9 +281,6 @@ helper_client_server (struct options *o)
o->push_ifconfig_constraint_network = o->server_network;
o->push_ifconfig_constraint_netmask = o->server_netmask;
}
if (o->proto == PROTO_TCPv4)
o->proto = PROTO_TCPv4_SERVER;
}
/*
@ -325,9 +322,6 @@ helper_client_server (struct options *o)
ifconfig_pool_verify_range (M_USAGE, o->ifconfig_pool_start, o->ifconfig_pool_end);
o->ifconfig_pool_netmask = o->server_bridge_netmask;
push_option (o, print_opt_route_gateway (o->server_bridge_ip, &o->gc), M_USAGE);
if (o->proto == PROTO_TCPv4)
o->proto = PROTO_TCPv4_SERVER;
}
else
#endif /* P2MP_SERVER */
@ -349,16 +343,10 @@ helper_client_server (struct options *o)
o->pull = true;
o->tls_client = true;
if (o->proto == PROTO_TCPv4)
o->proto = PROTO_TCPv4_CLIENT;
}
#endif /* P2MP */
if (o->proto == PROTO_TCPv4)
msg (M_USAGE, "--proto tcp is ambiguous in this context. Please specify --proto tcp-server or --proto tcp-client");
gc_free (&gc);
}

294
init.c
View file

@ -78,23 +78,100 @@ context_clear_all_except_first_time (struct context *c)
}
/*
* Initialize and possibly randomize remote list.
* Should be called after options->ce is modified at the top
* of a SIGUSR1 restart.
*/
static void
init_remote_list (struct context *c)
update_options_ce_post (struct options *options)
{
c->c1.remote_list = NULL;
if (c->options.remote_list)
#if P2MP
/*
* In pull mode, we usually import --ping/--ping-restart parameters from
* the server. However we should also set an initial default --ping-restart
* for the period of time before we pull the --ping-restart parameter
* from the server.
*/
if (options->pull
&& options->ping_rec_timeout_action == PING_UNDEF
&& options->ce.proto == PROTO_UDPv4)
{
options->ping_rec_timeout = PRE_PULL_INITIAL_PING_RESTART;
options->ping_rec_timeout_action = PING_RESTART;
}
#endif
#ifdef USE_CRYPTO
/*
* Don't use replay window for TCP mode (i.e. require that packets be strictly in sequence).
*/
if (link_socket_proto_connection_oriented (options->ce.proto))
options->replay_window = options->replay_time = 0;
#endif
}
/*
* Initialize and possibly randomize connection list.
*/
static void
init_connection_list (struct context *c)
{
#ifdef ENABLE_CONNECTION
struct connection_list *l = c->options.connection_list;
if (l)
{
struct remote_list *l;
ALLOC_OBJ_GC (c->c1.remote_list, struct remote_list, &c->gc);
l = c->c1.remote_list;
*l = *c->options.remote_list;
l->current = -1;
if (c->options.remote_random)
remote_list_randomize (l);
{
int i;
for (i = 0; i < l->len; ++i)
{
const int j = get_random () % l->len;
if (i != j)
{
struct connection_entry *tmp;
tmp = l->array[i];
l->array[i] = l->array[j];
l->array[j] = tmp;
}
}
}
}
#endif
}
/*
* Increment to next connection entry
*/
static void
next_connection_entry (struct context *c)
{
#ifdef ENABLE_CONNECTION
struct connection_list *l = c->options.connection_list;
if (l)
{
if (l->no_advance && l->current >= 0)
{
l->no_advance = false;
}
else
{
int i;
if (++l->current >= l->len)
l->current = 0;
dmsg (D_CONNECTION_LIST, "CONNECTION_LIST len=%d current=%d",
l->len, l->current);
for (i = 0; i < l->len; ++i)
{
dmsg (D_CONNECTION_LIST, "[%d] %s:%d",
i,
l->array[i]->remote,
l->array[i]->remote_port);
}
}
c->options.ce = *l->array[l->current];
}
#endif
update_options_ce_post (&c->options);
}
/*
@ -116,8 +193,41 @@ init_query_passwords (struct context *c)
#endif
}
void
context_init_1 (struct context *c)
/*
* Initialize/Uninitialize HTTP or SOCKS proxy
*/
#ifdef GENERAL_PROXY_SUPPORT
static int
proxy_scope (struct context *c)
{
return connection_list_defined (&c->options) ? 2 : 1;
}
static void
uninit_proxy_dowork (struct context *c)
{
#ifdef ENABLE_HTTP_PROXY
if (c->c1.http_proxy_owned && c->c1.http_proxy)
{
http_proxy_close (c->c1.http_proxy);
c->c1.http_proxy = NULL;
c->c1.http_proxy_owned = false;
}
#endif
#ifdef ENABLE_SOCKS
if (c->c1.socks_proxy_owned && c->c1.socks_proxy)
{
socks_proxy_close (c->c1.socks_proxy);
c->c1.socks_proxy = NULL;
c->c1.socks_proxy_owned = false;
}
#endif
}
static void
init_proxy_dowork (struct context *c)
{
#ifdef ENABLE_HTTP_PROXY
bool did_http = false;
@ -125,10 +235,73 @@ context_init_1 (struct context *c)
const bool did_http = false;
#endif
uninit_proxy_dowork (c);
#ifdef ENABLE_HTTP_PROXY
if (c->options.ce.http_proxy_options || c->options.auto_proxy_info)
{
/* Possible HTTP proxy user/pass input */
c->c1.http_proxy = http_proxy_new (c->options.ce.http_proxy_options,
c->options.auto_proxy_info);
if (c->c1.http_proxy)
{
did_http = true;
c->c1.http_proxy_owned = true;
}
}
#endif
#ifdef ENABLE_SOCKS
if (!did_http && (c->options.ce.socks_proxy_server || c->options.auto_proxy_info))
{
c->c1.socks_proxy = socks_proxy_new (c->options.ce.socks_proxy_server,
c->options.ce.socks_proxy_port,
c->options.ce.socks_proxy_retry,
c->options.auto_proxy_info);
if (c->c1.socks_proxy)
{
c->c1.socks_proxy_owned = true;
}
}
#endif
}
static void
init_proxy (struct context *c, const int scope)
{
if (scope == proxy_scope (c))
init_proxy_dowork (c);
}
static void
uninit_proxy (struct context *c)
{
if (c->sig->signal_received != SIGUSR1 || proxy_scope (c) == 2)
uninit_proxy_dowork (c);
}
#else
static inline void
init_proxy (struct context *c, const int scope)
{
}
static inline void
uninit_proxy (struct context *c, const int scope)
{
}
#endif
void
context_init_1 (struct context *c)
{
context_clear_1 (c);
packet_id_persist_init (&c->c1.pid_persist);
init_remote_list (c);
init_connection_list (c);
init_query_passwords (c);
@ -156,28 +329,8 @@ context_init_1 (struct context *c)
}
#endif
#ifdef ENABLE_HTTP_PROXY
if (c->options.http_proxy_options || c->options.auto_proxy_info)
{
/* Possible HTTP proxy user/pass input */
c->c1.http_proxy = new_http_proxy (c->options.http_proxy_options,
c->options.auto_proxy_info,
&c->gc);
if (c->c1.http_proxy)
did_http = true;
}
#endif
#ifdef ENABLE_SOCKS
if (!did_http && (c->options.socks_proxy_server || c->options.auto_proxy_info))
{
c->c1.socks_proxy = new_socks_proxy (c->options.socks_proxy_server,
c->options.socks_proxy_port,
c->options.socks_proxy_retry,
c->options.auto_proxy_info,
&c->gc);
}
#endif
/* initialize HTTP or SOCKS proxy object at scope level 1 */
init_proxy (c, 1);
}
void
@ -407,7 +560,7 @@ do_persist_tuntap (const struct options *options)
{
/* sanity check on options for --mktun or --rmtun */
notnull (options->dev, "TUN/TAP device (--dev)");
if (options->remote_list || options->ifconfig_local
if (options->ce.remote || options->ifconfig_local
|| options->ifconfig_remote_netmask
#ifdef USE_CRYPTO
|| options->shared_secret_file
@ -684,9 +837,9 @@ initialization_sequence_completed (struct context *c, const unsigned int flags)
else
msg (M_INFO, "%s", message);
/* Flag remote_list that we initialized */
if ((flags & (ISC_ERRORS|ISC_SERVER)) == 0 && c->c1.remote_list && c->c1.remote_list->len > 1)
c->c1.remote_list->no_advance = true;
/* Flag connection_list that we initialized */
if ((flags & (ISC_ERRORS|ISC_SERVER)) == 0 && connection_list_defined (&c->options))
connection_list_set_no_advance (&c->options);
#ifdef ENABLE_MANAGEMENT
/* Tell management interface that we initialized */
@ -1099,7 +1252,7 @@ do_deferred_options (struct context *c, const unsigned int found)
#ifdef ENABLE_OCC
if (found & OPT_P_EXPLICIT_NOTIFY)
{
if (c->options.proto != PROTO_UDPv4 && c->options.explicit_exit_notification)
if (c->options.ce.proto != PROTO_UDPv4 && c->options.explicit_exit_notification)
{
msg (D_PUSH, "OPTIONS IMPORT: --explicit-exit-notify can only be used with --proto udp");
c->options.explicit_exit_notification = 0;
@ -1183,25 +1336,25 @@ socket_restart_pause (struct context *c)
int sec = 2;
#ifdef ENABLE_HTTP_PROXY
if (c->options.http_proxy_options)
if (c->options.ce.http_proxy_options)
proxy = true;
#endif
#ifdef ENABLE_SOCKS
if (c->options.socks_proxy_server)
if (c->options.ce.socks_proxy_server)
proxy = true;
#endif
switch (c->options.proto)
switch (c->options.ce.proto)
{
case PROTO_UDPv4:
if (proxy)
sec = c->options.connect_retry_seconds;
sec = c->options.ce.connect_retry_seconds;
break;
case PROTO_TCPv4_SERVER:
sec = 1;
break;
case PROTO_TCPv4_CLIENT:
sec = c->options.connect_retry_seconds;
sec = c->options.ce.connect_retry_seconds;
break;
}
@ -1537,7 +1690,7 @@ do_init_crypto_tls (struct context *c, const unsigned int flags)
/* should we not xmit any packets until we get an initial
response from client? */
if (to.server && options->proto == PROTO_TCPv4_SERVER)
if (to.server && options->ce.proto == PROTO_TCPv4_SERVER)
to.xmit_hold = true;
#ifdef ENABLE_OCC
@ -1584,7 +1737,7 @@ do_init_crypto_tls (struct context *c, const unsigned int flags)
/* If we are running over TCP, allow for
length prefix */
socket_adjust_frame_parameters (&to.frame, options->proto);
socket_adjust_frame_parameters (&to.frame, options->ce.proto);
/*
* Initialize OpenVPN's master TLS-mode object.
@ -1682,8 +1835,8 @@ do_init_frame (struct context *c)
/*
* Adjust frame size for UDP Socks support.
*/
if (c->options.socks_proxy_server)
socks_adjust_frame_parameters (&c->c2.frame, c->options.proto);
if (c->options.ce.socks_proxy_server)
socks_adjust_frame_parameters (&c->c2.frame, c->options.ce.proto);
#endif
/*
@ -1697,7 +1850,7 @@ do_init_frame (struct context *c)
* (Since TCP is a stream protocol, we need to insert
* a packet length uint16_t in the buffer.)
*/
socket_adjust_frame_parameters (&c->c2.frame, c->options.proto);
socket_adjust_frame_parameters (&c->c2.frame, c->options.ce.proto);
/*
* Fill in the blanks in the frame parameters structure,
@ -1739,7 +1892,7 @@ do_option_warnings (struct context *c)
const struct options *o = &c->options;
#if 1 /* JYFIXME -- port warning */
if (!o->port_option_used && (o->local_port == OPENVPN_PORT && o->remote_port == OPENVPN_PORT))
if (!o->ce.port_option_used && (o->ce.local_port == OPENVPN_PORT && o->ce.remote_port == OPENVPN_PORT))
msg (M_WARN, "IMPORTANT: OpenVPN's default port number is now %d, based on an official port number assignment by IANA. OpenVPN 2.0-beta16 and earlier used 5000 as the default port.",
OPENVPN_PORT);
#endif
@ -1793,7 +1946,7 @@ do_option_warnings (struct context *c)
#endif
#ifndef CONNECT_NONBLOCK
if (o->connect_timeout_defined)
if (o->ce.connect_timeout_defined)
msg (M_WARN, "NOTE: --connect-timeout option is not supported on this OS");
#endif
}
@ -1918,10 +2071,12 @@ do_init_socket_1 (struct context *c, const int mode)
#endif
link_socket_init_phase1 (c->c2.link_socket,
c->options.local,
c->c1.remote_list,
c->options.local_port,
c->options.proto,
connection_list_defined (&c->options),
c->options.ce.local,
c->options.ce.local_port,
c->options.ce.remote,
c->options.ce.remote_port,
c->options.ce.proto,
mode,
c->c2.accept_from,
#ifdef ENABLE_HTTP_PROXY
@ -1933,16 +2088,16 @@ do_init_socket_1 (struct context *c, const int mode)
#ifdef ENABLE_DEBUG
c->options.gremlin,
#endif
c->options.bind_local,
c->options.remote_float,
c->options.ce.bind_local,
c->options.ce.remote_float,
c->options.inetd,
&c->c1.link_socket_addr,
c->options.ipchange,
c->plugins,
c->options.resolve_retry_seconds,
c->options.connect_retry_seconds,
c->options.connect_timeout,
c->options.connect_retry_max,
c->options.ce.connect_retry_seconds,
c->options.ce.connect_timeout,
c->options.ce.connect_retry_max,
c->options.mtu_discover_type,
c->options.rcvbuf,
c->options.sndbuf,
@ -2302,7 +2457,7 @@ do_setup_fast_io (struct context *c)
#ifdef WIN32
msg (M_INFO, "NOTE: --fast-io is disabled since we are running on Windows");
#else
if (c->options.proto != PROTO_UDPv4)
if (c->options.ce.proto != PROTO_UDPv4)
msg (M_INFO, "NOTE: --fast-io is disabled since we are not using UDP");
else
{
@ -2556,10 +2711,13 @@ init_instance (struct context *c, const struct env_set *env, const unsigned int
c->sig->signal_text = NULL;
c->sig->hard = false;
/* map in current connection entry */
next_connection_entry (c);
/* link_socket_mode allows CM_CHILD_TCP
instances to inherit acceptable fds
from a top-level parent */
if (c->options.proto == PROTO_TCPv4_SERVER)
if (c->options.ce.proto == PROTO_TCPv4_SERVER)
{
if (c->mode == CM_TOP)
link_socket_mode = LS_MODE_TCP_LISTEN;
@ -2633,6 +2791,9 @@ init_instance (struct context *c, const struct env_set *env, const unsigned int
else if (c->mode == CM_CHILD_TCP)
do_event_set_init (c, false);
/* initialize HTTP or SOCKS proxy object at scope level 2 */
init_proxy (c, 2);
/* allocate our socket object */
if (c->mode == CM_P2P || c->mode == CM_TOP || c->mode == CM_CHILD_TCP)
do_link_socket_new (c);
@ -2825,6 +2986,9 @@ close_instance (struct context *c)
/* free up environmental variable store */
do_env_set_destroy (c);
/* close HTTP or SOCKS proxy */
uninit_proxy (c);
/* garbage collect */
gc_free (&c->c2.gc);
}
@ -2836,7 +3000,7 @@ inherit_context_child (struct context *dest,
{
CLEAR (*dest);
switch (src->options.proto)
switch (src->options.ce.proto)
{
case PROTO_UDPv4:
dest->mode = CM_CHILD_UDP;
@ -2952,7 +3116,7 @@ inherit_context_top (struct context *dest,
dest->c2.es_owned = false;
dest->c2.event_set = NULL;
if (src->options.proto == PROTO_UDPv4)
if (src->options.ce.proto == PROTO_UDPv4)
do_event_set_init (dest, false);
}

33
misc.c
View file

@ -940,6 +940,7 @@ setenv_str_ex (struct env_set *es,
{
const char *str = construct_name_value (name_tmp, val_tmp, &gc);
env_set_add (es, str);
/*msg (M_INFO, "SETENV_ES '%s'", str);*/
}
else
env_set_del (es, name_tmp);
@ -974,6 +975,38 @@ setenv_str_ex (struct env_set *es,
gc_free (&gc);
}
/*
* Setenv functions that append an integer index to the name
*/
static const char *
setenv_format_indexed_name (const char *name, const int i, struct gc_arena *gc)
{
struct buffer out = alloc_buf_gc (strlen (name) + 16, gc);
if (i >= 0)
buf_printf (&out, "%s_%d", name, i);
else
buf_printf (&out, "%s", name);
return BSTR (&out);
}
void
setenv_int_i (struct env_set *es, const char *name, const int value, const int i)
{
struct gc_arena gc = gc_new ();
const char *name_str = setenv_format_indexed_name (name, i, &gc);
setenv_int (es, name_str, value);
gc_free (&gc);
}
void
setenv_str_i (struct env_set *es, const char *name, const char *value, const int i)
{
struct gc_arena gc = gc_new ();
const char *name_str = setenv_format_indexed_name (name, i, &gc);
setenv_str (es, name_str, value);
gc_free (&gc);
}
/*
* taken from busybox networking/ifupdown.c
*/

3
misc.h
View file

@ -165,6 +165,9 @@ void setenv_str (struct env_set *es, const char *name, const char *value);
void setenv_str_safe (struct env_set *es, const char *name, const char *value);
void setenv_del (struct env_set *es, const char *name);
void setenv_int_i (struct env_set *es, const char *name, const int value, const int i);
void setenv_str_i (struct env_set *es, const char *name, const char *value, const int i);
/* struct env_set functions */
struct env_set *env_set_create (struct gc_arena *gc);

View file

@ -2619,7 +2619,7 @@ tunnel_server (struct context *top)
{
ASSERT (top->options.mode == MODE_SERVER);
switch (top->options.proto) {
switch (top->options.ce.proto) {
case PROTO_UDPv4:
tunnel_server_udp (top);
break;

4
occ.c
View file

@ -149,7 +149,7 @@ check_send_occ_req_dowork (struct context *c)
{
if (++c->c2.occ_n_tries >= OCC_N_TRIES)
{
if (c->options.remote_list)
if (c->options.ce.remote)
/*
* No OCC_REPLY from peer after repeated attempts.
* Give up.
@ -369,7 +369,7 @@ process_received_occ_msg (struct context *c)
c->c2.max_send_size_remote,
c->c2.max_recv_size_local);
if (!c->options.fragment
&& c->options.proto == PROTO_UDPv4
&& c->options.ce.proto == PROTO_UDPv4
&& c->c2.max_send_size_local > TUN_MTU_MIN
&& (c->c2.max_recv_size_remote < c->c2.max_send_size_local
|| c->c2.max_recv_size_local < c->c2.max_send_size_remote))

129
openvpn.8
View file

@ -466,11 +466,16 @@ If specified, OpenVPN will bind to this address only.
If unspecified, OpenVPN will bind to all interfaces.
.\"*********************************************************
.TP
.B --remote host [port]
.B --remote host [port] [proto]
Remote host name or IP address. On the client, multiple
.B --remote
options may be specified for redundancy, each referring
to a different OpenVPN server.
to a different OpenVPN server. Specifying multiple
.B --remote
options for this purpose is a special case of the more
general connection-profile feature. See the
.B <connection>
documentation below.
The OpenVPN client will try to connect to a server at
.B host:port
@ -478,6 +483,10 @@ in the order specified by the list of
.B --remote
options.
.B proto
indicates the protocol to use when connecting with the
remote, and may be "tcp" or "udp".
The client will move on to the next host in the list,
in the event of connection failure.
Note that at any given time, the OpenVPN client
@ -525,12 +534,126 @@ is a DNS name which resolves to multiple IP addresses,
one will be randomly
chosen, providing a sort of basic load-balancing and
failover capability.
.\"*********************************************************
.TP
.B <connection>
Define a client connection
profile. Client connection profiles are groups of OpenVPN options that
describe how to connect to a given OpenVPN server. Client connection
profiles are specified within an OpenVPN configuration file, and
each profile is bracketed by
.B <connection>
and
.B </connection>.
An OpenVPN client will try each connection profile sequentially
until it achieves a successful connection.
.B --remote-random
can be used to initially "scramble" the connection
list.
Here is an example of connection profile usage:
.RS
.ft 3
.nf
.sp
client
dev tun
<connection>
remote 198.19.34.56 1194 udp
</connection>
<connection>
remote 198.19.34.56 443 tcp
</connection>
<connection>
remote 198.19.34.56 443 tcp
http-proxy 192.168.0.8 8080
http-proxy-retry
</connection>
<connection>
remote 198.19.36.99 443 tcp
http-proxy 192.168.0.8 8080
http-proxy-retry
</connection>
persist-key
persist-tun
pkcs12 client.p12
ns-cert-type server
verb 3
.ft
.LP
.RE
.fi
First we try to connect to a server at 198.19.34.56:1194 using UDP.
If that fails, we then try to connect to 198.19.34.56:443 using TCP.
If that also fails, then try connecting through an HTTP proxy at
192.168.0.8:8080 to 198.19.34.56:443 using TCP. Finally, try to
connect through the same proxy to a server at 198.19.36.99:443
using TCP.
The following OpenVPN options may be used inside of
a
.B <connection>
block:
.B bind,
.B connect-retry,
.B connect-retry-max,
.B connect-timeout,
.B float,
.B http-proxy,
.B http-proxy-option,
.B http-proxy-retry,
.B http-proxy-timeout,
.B local,
.B lport,
.B nobind,
.B port,
.B proto,
.B remote,
.B rport,
.B socks-proxy, and
.B socks-proxy-retry.
A defaulting mechanism exists for specifying options to apply to
all
.B <connection>
profiles. If any of the above options (with the exception of
.B remote
) appear outside of a
.B <connection>
block, but in a configuration file which has one or more
.B <connection>
blocks, the option setting will be used as a default for
.B <connection>
blocks which follow it in the configuration file.
For example, suppose the
.B nobind
option were placed in the sample configuration file above, near
the top of the file, before the first
.B <connection>
block. The effect would be as if
.B nobind
were declared in all
.B <connection>
blocks below it.
.\"*********************************************************
.TP
.B --remote-random
When multiple
.B --remote
address/ports are specified, initially randomize the order of the list
address/ports are specified, or if connection profiles are being
used, initially randomize the order of the list
as a kind of basic load-balancing measure.
.\"*********************************************************
.TP

View file

@ -138,7 +138,7 @@ main (int argc, char *argv[])
#endif
/* initialize options to default state */
init_options (&c.options);
init_options (&c.options, true);
/* parse command line options, and read configuration file */
parse_argv (&c.options, argc, argv, M_USAGE, OPT_P_DEFAULT, NULL, c.es);
@ -169,7 +169,7 @@ main (int argc, char *argv[])
break;
/* sanity check on options */
options_postprocess (&c.options, c.first_time);
options_postprocess (&c.options);
/* show all option settings */
show_settings (&c.options);

View file

@ -158,9 +158,6 @@ struct context_1
/* persist crypto sequence number to/from file */
struct packet_id_persist pid_persist;
/* array of remote addresses */
struct remote_list *remote_list;
/* TUN/TAP interface */
struct tuntap *tuntap;
bool tuntap_owned;
@ -175,11 +172,13 @@ struct context_1
#ifdef ENABLE_HTTP_PROXY
/* HTTP proxy object */
struct http_proxy_info *http_proxy;
bool http_proxy_owned;
#endif
#ifdef ENABLE_SOCKS
/* SOCKS proxy object */
struct socks_proxy_info *socks_proxy;
bool socks_proxy_owned;
#endif
#if P2MP

839
options.c

File diff suppressed because it is too large Load diff

123
options.h
View file

@ -82,10 +82,65 @@ struct options_pre_pull
#endif
struct connection_entry
{
int proto;
int local_port;
bool local_port_defined;
int remote_port;
bool port_option_used;
const char *local;
const char *remote;
bool remote_float;
bool bind_defined;
bool bind_local;
int connect_retry_seconds;
bool connect_retry_defined;
int connect_retry_max;
int connect_timeout;
bool connect_timeout_defined;
#ifdef ENABLE_HTTP_PROXY
struct http_proxy_options *http_proxy_options;
#endif
#ifdef ENABLE_SOCKS
const char *socks_proxy_server;
int socks_proxy_port;
bool socks_proxy_retry;
#endif
};
struct remote_entry
{
const char *remote;
int remote_port;
int proto;
};
#ifdef ENABLE_CONNECTION
#define CONNECTION_LIST_SIZE 64
struct connection_list
{
int len;
int current;
bool no_advance;
struct connection_entry *array[CONNECTION_LIST_SIZE];
};
struct remote_list
{
int len;
struct remote_entry *array[CONNECTION_LIST_SIZE];
};
#endif
/* Command line options */
struct options
{
struct gc_arena gc;
bool gc_owned;
/* first config file */
const char *config;
@ -111,17 +166,19 @@ struct options
#endif
/* Networking parms */
const char *local;
int local_port;
bool local_port_defined;
int remote_port;
bool port_option_used;
bool remote_float;
struct connection_entry ce;
#ifdef ENABLE_CONNECTION
struct connection_list *connection_list;
struct remote_list *remote_list;
#endif
#ifdef GENERAL_PROXY_SUPPORT
struct auto_proxy_info *auto_proxy_info;
#endif
bool remote_random;
const char *ipchange;
bool bind_defined;
bool bind_local;
const char *dev;
const char *dev_type;
const char *dev_node;
@ -141,14 +198,6 @@ struct options
bool tun_mtu_defined; /* true if user overriding parm with command line option */
bool link_mtu_defined; /* true if user overriding parm with command line option */
/* Protocol type (PROTO_UDP or PROTO_TCP) */
int proto;
int connect_retry_seconds;
int connect_retry_max;
bool connect_retry_defined;
int connect_timeout;
bool connect_timeout_defined;
/* Advanced MTU negotiation and datagram fragmentation options */
int mtu_discover_type; /* used if OS supports setting Path MTU discovery options on socket */
@ -254,21 +303,6 @@ struct options
struct route_option_list *routes;
bool route_nopull;
#ifdef GENERAL_PROXY_SUPPORT
struct auto_proxy_info *auto_proxy_info;
#endif
#ifdef ENABLE_HTTP_PROXY
struct http_proxy_options *http_proxy_options;
#endif
#ifdef ENABLE_SOCKS
/* socks proxy */
const char *socks_proxy_server;
int socks_proxy_port;
bool socks_proxy_retry;
#endif
#ifdef ENABLE_OCC
/* Enable options consistency check between peers */
bool occ;
@ -499,6 +533,7 @@ struct options
#define OPT_P_PLUGIN (1<<24)
#define OPT_P_SOCKBUF (1<<25)
#define OPT_P_SOCKFLAGS (1<<26)
#define OPT_P_CONNECTION (1<<27)
#define OPT_P_DEFAULT (~(OPT_P_INSTANCE|OPT_P_PULL_MODE))
@ -553,7 +588,7 @@ void notnull (const char *arg, const char *description);
void usage_small (void);
void init_options (struct options *o);
void init_options (struct options *o, const bool init_gc);
void uninit_options (struct options *o);
void setenv_settings (struct env_set *es, const struct options *o);
@ -578,7 +613,7 @@ void options_warning (char *actual, const char *expected);
#endif
void options_postprocess (struct options *options, bool first_time);
void options_postprocess (struct options *options);
void pre_pull_save (struct options *o);
void pre_pull_restore (struct options *o);
@ -643,4 +678,26 @@ void options_string_import (struct options *options,
unsigned int *option_types_found,
struct env_set *es);
/*
* inline functions
*/
static inline bool
connection_list_defined (const struct options *o)
{
#ifdef ENABLE_CONNECTION
return o->connection_list != NULL;
#else
return false;
#endif
}
static inline void
connection_list_set_no_advance (struct options *o)
{
#ifdef ENABLE_CONNECTION
if (o->connection_list)
o->connection_list->no_advance = true;
#endif
}
#endif

13
proxy.c
View file

@ -229,9 +229,8 @@ get_user_pass_http (struct http_proxy_info *p, const bool force)
}
struct http_proxy_info *
new_http_proxy (const struct http_proxy_options *o,
struct auto_proxy_info *auto_proxy_info,
struct gc_arena *gc)
http_proxy_new (const struct http_proxy_options *o,
struct auto_proxy_info *auto_proxy_info)
{
struct http_proxy_info *p;
struct http_proxy_options opt;
@ -275,7 +274,7 @@ new_http_proxy (const struct http_proxy_options *o,
ASSERT (legal_ipv4_port (o->port));
ALLOC_OBJ_CLEAR_GC (p, struct http_proxy_info, gc);
ALLOC_OBJ_CLEAR (p, struct http_proxy_info);
p->options = *o;
/* parse authentication method */
@ -310,6 +309,12 @@ new_http_proxy (const struct http_proxy_options *o,
return p;
}
void
http_proxy_close (struct http_proxy_info *hp)
{
free (hp);
}
bool
establish_http_proxy_passthru (struct http_proxy_info *p,
socket_descriptor_t sd, /* already open to proxy */

View file

@ -80,9 +80,10 @@ struct http_proxy_info {
struct user_pass up;
};
struct http_proxy_info *new_http_proxy (const struct http_proxy_options *o,
struct auto_proxy_info *auto_proxy_info,
struct gc_arena *gc);
struct http_proxy_info *http_proxy_new (const struct http_proxy_options *o,
struct auto_proxy_info *auto_proxy_info);
void http_proxy_close (struct http_proxy_info *hp);
bool establish_http_proxy_passthru (struct http_proxy_info *p,
socket_descriptor_t sd, /* already open to proxy */

111
socket.c
View file

@ -402,77 +402,6 @@ link_socket_update_buffer_sizes (struct link_socket *ls, int rcvbuf, int sndbuf)
}
}
/*
* Remote list code allows clients to specify a list of
* potential remote server addresses.
*/
static void
remote_list_next (struct remote_list *l)
{
if (l)
{
if (l->no_advance && l->current >= 0)
{
l->no_advance = false;
}
else
{
int i;
if (++l->current >= l->len)
l->current = 0;
dmsg (D_REMOTE_LIST, "REMOTE_LIST len=%d current=%d",
l->len, l->current);
for (i = 0; i < l->len; ++i)
{
dmsg (D_REMOTE_LIST, "[%d] %s:%d",
i,
l->array[i].hostname,
l->array[i].port);
}
}
}
}
void
remote_list_randomize (struct remote_list *l)
{
int i;
if (l)
{
for (i = 0; i < l->len; ++i)
{
const int j = get_random () % l->len;
if (i != j)
{
struct remote_entry tmp;
tmp = l->array[i];
l->array[i] = l->array[j];
l->array[j] = tmp;
}
}
}
}
static const char *
remote_list_host (const struct remote_list *rl)
{
if (rl)
return rl->array[rl->current].hostname;
else
return NULL;
}
static int
remote_list_port (const struct remote_list *rl)
{
if (rl)
return rl->array[rl->current].port;
else
return 0;
}
/*
* SOCKET INITALIZATION CODE.
* Create a TCP/UDP socket
@ -813,7 +742,7 @@ socket_connect (socket_descriptor_t *sd,
struct openvpn_sockaddr *local,
bool bind_local,
struct openvpn_sockaddr *remote,
struct remote_list *remote_list,
const bool connection_profiles_defined,
const char *remote_dynamic,
bool *remote_changed,
const int connect_retry_seconds,
@ -865,7 +794,7 @@ socket_connect (socket_descriptor_t *sd,
openvpn_close_socket (*sd);
*sd = SOCKET_UNDEFINED;
if (connect_retry_max > 0 && ++retry >= connect_retry_max)
if ((connect_retry_max > 0 && ++retry >= connect_retry_max) || connection_profiles_defined)
{
*signal_received = SIGUSR1;
goto done;
@ -877,14 +806,6 @@ socket_connect (socket_descriptor_t *sd,
if (*signal_received)
goto done;
if (remote_list)
{
remote_list_next (remote_list);
remote_dynamic = remote_list_host (remote_list);
remote->sa.sin_port = htons (remote_list_port (remote_list));
*remote_changed = true;
}
*sd = create_socket_tcp ();
if (bind_local)
socket_bind (*sd, local, "TCP Client");
@ -996,7 +917,7 @@ resolve_remote (struct link_socket *sock,
int retry = 0;
bool status = false;
if (remote_list_len (sock->remote_list) > 1 && sock->resolve_retry_seconds == RESOLV_RETRY_INFINITE)
if (sock->connection_profiles_defined && sock->resolve_retry_seconds == RESOLV_RETRY_INFINITE)
{
if (phase == 2)
flags |= (GETADDR_TRY_ONCE | GETADDR_FATAL);
@ -1099,9 +1020,11 @@ link_socket_new (void)
/* bind socket if necessary */
void
link_socket_init_phase1 (struct link_socket *sock,
const bool connection_profiles_defined,
const char *local_host,
struct remote_list *remote_list,
int local_port,
const char *remote_host,
int remote_port,
int proto,
int mode,
const struct link_socket *accept_from,
@ -1129,18 +1052,14 @@ link_socket_init_phase1 (struct link_socket *sock,
int sndbuf,
unsigned int sockflags)
{
const char *remote_host;
int remote_port;
ASSERT (sock);
sock->remote_list = remote_list;
remote_list_next (remote_list);
remote_host = remote_list_host (remote_list);
remote_port = remote_list_port (remote_list);
sock->connection_profiles_defined = connection_profiles_defined;
sock->local_host = local_host;
sock->local_port = local_port;
sock->remote_host = remote_host;
sock->remote_port = remote_port;
#ifdef ENABLE_HTTP_PROXY
sock->http_proxy = http_proxy;
@ -1198,10 +1117,6 @@ link_socket_init_phase1 (struct link_socket *sock,
/* the OpenVPN server we will use the proxy to connect to */
sock->proxy_dest_host = remote_host;
sock->proxy_dest_port = remote_port;
/* this is needed so that connection retries will go to the proxy server,
not the remote OpenVPN address */
sock->remote_list = NULL;
}
#endif
#ifdef ENABLE_SOCKS
@ -1218,10 +1133,6 @@ link_socket_init_phase1 (struct link_socket *sock,
/* the OpenVPN server we will use the proxy to connect to */
sock->proxy_dest_host = remote_host;
sock->proxy_dest_port = remote_port;
/* this is needed so that connection retries will go to the proxy server,
not the remote OpenVPN address */
sock->remote_list = NULL;
}
#endif
else
@ -1357,7 +1268,7 @@ link_socket_init_phase2 (struct link_socket *sock,
&sock->info.lsa->local,
sock->bind_local,
&sock->info.lsa->actual.dest,
sock->remote_list,
sock->connection_profiles_defined,
remote_dynamic,
&remote_changed,
sock->connect_retry_seconds,
@ -1405,7 +1316,7 @@ link_socket_init_phase2 (struct link_socket *sock,
&sock->info.lsa->local,
sock->bind_local,
&sock->info.lsa->actual.dest,
NULL,
sock->connection_profiles_defined,
remote_dynamic,
&remote_changed,
sock->connect_retry_seconds,

View file

@ -47,22 +47,6 @@
*/
#define RESOLV_RETRY_INFINITE 1000000000
#define REMOTE_LIST_SIZE 64
struct remote_entry
{
const char *hostname;
int port;
};
struct remote_list
{
int len;
int current;
bool no_advance;
struct remote_entry array[REMOTE_LIST_SIZE];
};
/*
* packet_size_type is used to communicate packet size
* over the wire when stream oriented protocols are
@ -175,8 +159,9 @@ struct link_socket
/* used for long-term queueing of pre-accepted socket listen */
bool listen_persistent_queued;
/* set on initial call to init phase 1 */
struct remote_list *remote_list;
/* Does config file contain any <connection> ... </connection> blocks? */
bool connection_profiles_defined;
const char *remote_host;
int remote_port;
const char *local_host;
@ -290,9 +275,11 @@ int openvpn_connect (socket_descriptor_t sd,
void
link_socket_init_phase1 (struct link_socket *sock,
const bool connection_profiles_defined,
const char *local_host,
struct remote_list *remote_list,
int local_port,
const char *remote_host,
int remote_port,
int proto,
int mode,
const struct link_socket *accept_from,
@ -391,8 +378,6 @@ void link_socket_bad_outgoing_addr (void);
void setenv_trusted (struct env_set *es, const struct link_socket_info *info);
void remote_list_randomize (struct remote_list *l);
bool link_socket_update_flags (struct link_socket *ls, unsigned int sockflags);
void link_socket_update_buffer_sizes (struct link_socket *ls, int rcvbuf, int sndbuf);
@ -467,15 +452,6 @@ datagram_overhead (int proto)
* Misc inline functions
*/
static inline int
remote_list_len (const struct remote_list *rl)
{
if (rl)
return rl->len;
else
return 0;
}
static inline bool
legal_ipv4_port (int port)
{

13
socks.c
View file

@ -51,11 +51,10 @@ socks_adjust_frame_parameters (struct frame *frame, int proto)
}
struct socks_proxy_info *
new_socks_proxy (const char *server,
socks_proxy_new (const char *server,
int port,
bool retry,
struct auto_proxy_info *auto_proxy_info,
struct gc_arena *gc)
struct auto_proxy_info *auto_proxy_info)
{
struct socks_proxy_info *p;
@ -71,7 +70,7 @@ new_socks_proxy (const char *server,
}
}
ALLOC_OBJ_CLEAR_GC (p, struct socks_proxy_info, gc);
ALLOC_OBJ_CLEAR (p, struct socks_proxy_info);
ASSERT (server);
ASSERT (legal_ipv4_port (port));
@ -84,6 +83,12 @@ new_socks_proxy (const char *server,
return p;
}
void
socks_proxy_close (struct socks_proxy_info *sp)
{
free (sp);
}
static bool
socks_handshake (socket_descriptor_t sd, volatile int *signal_received)
{

View file

@ -47,11 +47,12 @@ struct socks_proxy_info {
void socks_adjust_frame_parameters (struct frame *frame, int proto);
struct socks_proxy_info *new_socks_proxy (const char *server,
struct socks_proxy_info *socks_proxy_new (const char *server,
int port,
bool retry,
struct auto_proxy_info *auto_proxy_info,
struct gc_arena *gc);
struct auto_proxy_info *auto_proxy_info);
void socks_proxy_close (struct socks_proxy_info *sp);
void establish_socks_proxy_passthru (struct socks_proxy_info *p,
socket_descriptor_t sd, /* already open to proxy */

View file

@ -605,4 +605,11 @@ socket_defined (const socket_descriptor_t sd)
#define AUTO_USERID 0
#endif
/*
* Support "connection" directive
*/
#if ENABLE_INLINE_FILES
#define ENABLE_CONNECTION 1
#endif
#endif

View file

@ -1,5 +1,5 @@
dnl define the OpenVPN version
define(PRODUCT_VERSION,[2.1_rc7e])
define(PRODUCT_VERSION,[2.1_rc7f])
dnl define the TAP version
define(PRODUCT_TAP_ID,[tap0901])
define(PRODUCT_TAP_WIN32_MIN_MAJOR,[9])