summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog1
-rw-r--r--openvpn.815
-rw-r--r--options.c50
-rw-r--r--options.h1
-rw-r--r--socket.c42
5 files changed, 93 insertions, 16 deletions
diff --git a/ChangeLog b/ChangeLog
index 04c8567..87abbff 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -12,6 +12,7 @@ $Id$
contains a CA cert or not (Mathias Sundman).
* Merged --capath patch (Thomas Noel).
* Merged --multihome patch.
+* Added --bind option for TCP client connections (Ewan Bhamrah Harley).
* NOTE TO PACKAGE MAINTAINERS: Moved "plugin" directory to "plugins".
This is to work around a strange problem with the "make dist"
target in the automake-generated makefile, where the target tries to
diff --git a/openvpn.8 b/openvpn.8
index 4e4c81c..7655524 100644
--- a/openvpn.8
+++ b/openvpn.8
@@ -190,6 +190,7 @@ openvpn \- secure IP tunnel daemon.
[\ \fB\-\-nice\fR\ \fIn\fR\ ]
[\ \fB\-\-no\-iv\fR\ ]
[\ \fB\-\-no\-replay\fR\ ]
+[\ \fB\-\-bind\fR\ ]
[\ \fB\-\-nobind\fR\ ]
[\ \fB\-\-ns\-cert\-type\fR\ \fIclient|server\fR\ ]
[\ \fB\-\-passtos\fR\ ]
@@ -443,7 +444,7 @@ server capability.
.\"*********************************************************
.TP
.B --local host
-Local host name or IP address.
+Local host name or IP address for bind.
If specified, OpenVPN will bind to this address only.
If unspecified, OpenVPN will bind to all interfaces.
.\"*********************************************************
@@ -727,13 +728,23 @@ Previous versions used port 5000 as the default.
.\"*********************************************************
.TP
.B --lport port
-TCP/UDP port number for local.
+TCP/UDP port number for bind.
.\"*********************************************************
.TP
.B --rport port
TCP/UDP port number for remote.
.\"*********************************************************
.TP
+.B --bind
+Bind to local address and port. This is the default unless any of
+.B --proto tcp-client
+,
+.B --http-proxy
+or
+.B --socks-proxy
+are used.
+.\"*********************************************************
+.TP
.B --nobind
Do not bind to local address and port. The IP stack will allocate
a dynamic port for returning packets. Since the value of the dynamic port
diff --git a/options.c b/options.c
index c9ed15d..99e5cc0 100644
--- a/options.c
+++ b/options.c
@@ -87,7 +87,7 @@ static const char usage_message[] =
"--version : Show copyright and version information.\n"
"\n"
"Tunnel Options:\n"
- "--local host : Local host name or ip address.\n"
+ "--local host : Local host name or ip address. Implies --bind.\n"
"--remote host [port] : Remote host name or ip address.\n"
"--remote-random : If multiple --remote options specified, choose one randomly.\n"
"--mode m : Major mode, m = 'p2p' (default, point-to-point) or 'server'.\n"
@@ -121,8 +121,17 @@ static const char usage_message[] =
"--ipchange cmd : Execute shell command cmd on remote ip address initial\n"
" setting or change -- execute as: cmd ip-address port#\n"
"--port port : TCP/UDP port # for both local and remote.\n"
- "--lport port : TCP/UDP port # for local (default=%d).\n"
+ "--lport port : TCP/UDP port # for local (default=%d). Implies --bind.\n"
"--rport port : TCP/UDP port # for remote (default=%d).\n"
+ "--bind : Bind to local address and port. (This is the default unless\n"
+ " --proto tcp-client"
+#ifdef ENABLE_HTTP_PROXY
+ " or --http-proxy"
+#endif
+#ifdef ENABLE_SOCKS
+ " or --socks-proxy"
+#endif
+ " is used).\n"
"--nobind : Do not bind to local address and port.\n"
"--dev tunX|tapX : tun/tap device (X can be omitted for dynamic device.\n"
"--dev-type dt : Which device type are we using? (dt = tun or tap) Use\n"
@@ -688,6 +697,20 @@ setenv_settings (struct env_set *es, const struct options *o)
setenv_int (es, remote_port_string, o->remote_list->array[i].port);
}
}
+#ifdef ENABLE_HTTP_PROXY
+ if (o->http_proxy_options)
+ {
+ setenv_str (es, "http_proxy_server", o->http_proxy_options->server);
+ setenv_int (es, "http_proxy_port", o->http_proxy_options->port);
+ }
+#endif
+#ifdef ENABLE_SOCKS
+ if(o->socks_proxy_server)
+ {
+ setenv_str (es, "socks_proxy_server", o->socks_proxy_server);
+ setenv_int (es, "socks_proxy_port", o->socks_proxy_port);
+ }
+#endif
}
static in_addr_t
@@ -997,6 +1020,7 @@ show_settings (const struct options *o)
SHOW_INT (remote_port);
SHOW_BOOL (remote_float);
SHOW_STR (ipchange);
+ SHOW_BOOL (bind_defined);
SHOW_BOOL (bind_local);
SHOW_STR (dev);
SHOW_STR (dev_type);
@@ -1395,12 +1419,29 @@ options_postprocess (struct options *options, bool first_time)
if (string_defined_equal (options->ifconfig_local, options->ifconfig_remote_netmask))
msg (M_USAGE, "local and remote/netmask --ifconfig addresses must be different");
+ if (options->bind_defined && !options->bind_local)
+ msg (M_USAGE, "--bind and --nobind can't be used together");
+
+ if (options->local && !options->bind_local)
+ msg (M_USAGE, "--local and --nobind don't make sense when used together");
+
if (options->local_port_defined && !options->bind_local)
msg (M_USAGE, "--lport and --nobind don't make sense when used together");
if (!options->remote_list && !options->bind_local)
msg (M_USAGE, "--nobind doesn't make sense unless used with --remote");
+ if (options->proto == PROTO_TCPv4_CLIENT && !options->local && !options->local_port_defined && !options->bind_defined)
+ options->bind_local = false;
+
+#ifdef ENABLE_SOCKS
+ if (options->proto == PROTO_UDPv4 && options->socks_proxy_server && !options->local && !options->local_port_defined && !options->bind_defined)
+ options->bind_local = false;
+#endif
+
+ if (!options->bind_local)
+ options->local_port = 0;
+
/*
* Check for consistency of management options
*/
@@ -3521,6 +3562,11 @@ add_option (struct options *options,
options->port_option_used = true;
options->remote_port = port;
}
+ else if (streq (p[0], "bind"))
+ {
+ VERIFY_PERMISSION (OPT_P_GENERAL);
+ options->bind_defined = true;
+ }
else if (streq (p[0], "nobind"))
{
VERIFY_PERMISSION (OPT_P_GENERAL);
diff --git a/options.h b/options.h
index bb41759..69a2f04 100644
--- a/options.h
+++ b/options.h
@@ -120,6 +120,7 @@ struct options
struct remote_list *remote_list;
bool remote_random;
const char *ipchange;
+ bool bind_defined;
bool bind_local;
const char *dev;
const char *dev_type;
diff --git a/socket.c b/socket.c
index 35d38a1..ce54cb8 100644
--- a/socket.c
+++ b/socket.c
@@ -686,7 +686,25 @@ socket_listen_accept (socket_descriptor_t sd,
}
static void
+socket_bind (socket_descriptor_t sd,
+ struct openvpn_sockaddr *local)
+{
+ struct gc_arena gc = gc_new ();
+
+ if (bind (sd, (struct sockaddr *) &local->sa, sizeof (local->sa)))
+ {
+ const int errnum = openvpn_errno_socket ();
+ msg (M_FATAL, "TCP/UDP: Socket bind failed on local address %s: %s",
+ print_sockaddr (local, &gc),
+ strerror_ts (errnum, &gc));
+ }
+ gc_free (&gc);
+}
+
+static void
socket_connect (socket_descriptor_t *sd,
+ struct openvpn_sockaddr *local,
+ bool bind_local,
struct openvpn_sockaddr *remote,
struct remote_list *remote_list,
const char *remote_dynamic,
@@ -727,6 +745,8 @@ socket_connect (socket_descriptor_t *sd,
}
*sd = create_socket_tcp ();
+ if (bind_local)
+ socket_bind (*sd, local);
update_remote (remote_dynamic, remote, remote_changed);
}
@@ -796,14 +816,12 @@ resolve_bind_local (struct link_socket *sock)
/* bind to local address/port */
if (sock->bind_local)
{
- if (bind (sock->sd, (struct sockaddr *) &sock->info.lsa->local.sa,
- sizeof (sock->info.lsa->local.sa)))
- {
- const int errnum = openvpn_errno_socket ();
- msg (M_FATAL, "TCP/UDP: Socket bind failed on local address %s: %s",
- print_sockaddr (&sock->info.lsa->local, &gc),
- strerror_ts (errnum, &gc));
- }
+#ifdef ENABLE_SOCKS
+ if (sock->socks_proxy && sock->info.proto == PROTO_UDPv4)
+ socket_bind (sock->ctrl_sd, &sock->info.lsa->local);
+ else
+#endif
+ socket_bind (sock->sd, &sock->info.lsa->local);
}
gc_free (&gc);
}
@@ -1070,10 +1088,6 @@ link_socket_init_phase1 (struct link_socket *sock,
else
sock->bind_local = true;
}
- else if (sock->info.proto == PROTO_TCPv4_CLIENT)
- {
- sock->bind_local = false;
- }
/* were we started by inetd or xinetd? */
if (sock->inetd)
@@ -1176,6 +1190,8 @@ link_socket_init_phase2 (struct link_socket *sock,
else if (sock->info.proto == PROTO_TCPv4_CLIENT)
{
socket_connect (&sock->sd,
+ &sock->info.lsa->local,
+ sock->bind_local,
&sock->info.lsa->actual.dest,
sock->remote_list,
remote_dynamic,
@@ -1214,6 +1230,8 @@ link_socket_init_phase2 (struct link_socket *sock,
else if (sock->info.proto == PROTO_UDPv4 && sock->socks_proxy)
{
socket_connect (&sock->ctrl_sd,
+ &sock->info.lsa->local,
+ sock->bind_local,
&sock->info.lsa->actual.dest,
NULL,
remote_dynamic,