summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/openvpn.88
-rw-r--r--src/openvpn/init.c1
-rw-r--r--src/openvpn/manage.c2
-rw-r--r--src/openvpn/options.c4
-rw-r--r--src/openvpn/options.h1
-rw-r--r--src/openvpn/socket.c31
-rw-r--r--src/openvpn/socket.h5
7 files changed, 41 insertions, 11 deletions
diff --git a/doc/openvpn.8 b/doc/openvpn.8
index d5376f9..f06d536 100644
--- a/doc/openvpn.8
+++ b/doc/openvpn.8
@@ -684,7 +684,7 @@ TCP/UDP port number or name for bind.
TCP/UDP port number or name for remote.
.\"*********************************************************
.TP
-.B \-\-bind
+.B \-\-bind [ipv6only]
Bind to local address and port. This is the default unless any of
.B \-\-proto tcp-client
,
@@ -692,6 +692,12 @@ Bind to local address and port. This is the default unless any of
or
.B \-\-socks-proxy
are used.
+
+If the
+.B ipv6only
+keyword is present OpenVPN will bind only to IPv6 (as oposed
+to IPv6 and IPv4) when a IPv6 socket is opened.
+
.\"*********************************************************
.TP
.B \-\-nobind
diff --git a/src/openvpn/init.c b/src/openvpn/init.c
index 41d6fad..ae08562 100644
--- a/src/openvpn/init.c
+++ b/src/openvpn/init.c
@@ -2690,6 +2690,7 @@ do_init_socket_1 (struct context *c, const int mode)
c->options.ce.remote_port,
c->options.ce.proto,
c->options.ce.af,
+ c->options.ce.bind_ipv6_only,
mode,
c->c2.accept_from,
#ifdef ENABLE_HTTP_PROXY
diff --git a/src/openvpn/manage.c b/src/openvpn/manage.c
index dc6293a..22dbe13 100644
--- a/src/openvpn/manage.c
+++ b/src/openvpn/manage.c
@@ -1570,7 +1570,7 @@ man_listen (struct management *man)
{
man->connection.sd_top = create_socket_tcp (AF_INET);
socket_bind (man->connection.sd_top, man->settings.local,
- AF_INET, "MANAGEMENT");
+ AF_INET, "MANAGEMENT", true);
}
/*
diff --git a/src/openvpn/options.c b/src/openvpn/options.c
index 3edab58..e8704fe 100644
--- a/src/openvpn/options.c
+++ b/src/openvpn/options.c
@@ -779,6 +779,7 @@ init_options (struct options *o, const bool init_gc)
o->topology = TOP_NET30;
o->ce.proto = PROTO_UDP;
o->ce.af = AF_UNSPEC;
+ o->ce.bind_ipv6_only = false;
o->ce.connect_retry_seconds = 5;
o->ce.connect_timeout = 10;
o->connect_retry_max = 0;
@@ -4870,6 +4871,9 @@ add_option (struct options *options,
{
VERIFY_PERMISSION (OPT_P_GENERAL|OPT_P_CONNECTION);
options->ce.bind_defined = true;
+ if (p[1] && streq (p[1], "ipv6only"))
+ options->ce.bind_ipv6_only=true;
+
}
else if (streq (p[0], "nobind"))
{
diff --git a/src/openvpn/options.h b/src/openvpn/options.h
index 86760bb..95e67df 100644
--- a/src/openvpn/options.h
+++ b/src/openvpn/options.h
@@ -95,6 +95,7 @@ struct connection_entry
const char *remote;
bool remote_float;
bool bind_defined;
+ bool bind_ipv6_only;
bool bind_local;
int connect_retry_seconds;
int connect_timeout;
diff --git a/src/openvpn/socket.c b/src/openvpn/socket.c
index 5ba1ee3..141af72 100644
--- a/src/openvpn/socket.c
+++ b/src/openvpn/socket.c
@@ -662,11 +662,10 @@ create_socket (struct link_socket *sock)
{
/* create socket, use information carried over from getaddrinfo */
const int ai_proto = sock->info.lsa->actual.ai_protocol;
- const int ai_family = sock->info.lsa->actual.ai_family;
+ int ai_family = sock->info.lsa->actual.ai_family;
ASSERT (sock->info.af == AF_UNSPEC || sock->info.af == ai_family);
-
if (ai_proto == IPPROTO_UDP)
{
sock->sd = create_socket_udp (ai_family, sock->sockflags);
@@ -880,7 +879,8 @@ void
socket_bind (socket_descriptor_t sd,
struct addrinfo *local,
int ai_family,
- const char *prefix)
+ const char *prefix,
+ bool ipv6only)
{
struct gc_arena gc = gc_new ();
@@ -891,9 +891,11 @@ socket_bind (socket_descriptor_t sd,
* What is the correct way to deal with it?
*/
- ASSERT(local);
struct addrinfo* cur;
+ ASSERT(local);
+
+
/* find the first addrinfo with correct ai_family */
for (cur = local; cur; cur=cur->ai_next)
{
@@ -904,6 +906,15 @@ socket_bind (socket_descriptor_t sd,
msg (M_FATAL, "%s: Socket bind failed: Addr to bind has no %s record",
prefix, addr_family_name(ai_family));
+ if (ai_family == AF_INET6)
+ {
+ int v6only = ipv6only ? 0: 1; /* setsockopt must have an "int" */
+
+ if (setsockopt(sd, IPPROTO_IPV6, IPV6_V6ONLY, &v6only, sizeof(v6only)))
+ {
+ msg (M_NONFATAL|M_ERRNO, "Setting IPV6_V6ONLY=%d failed", v6only);
+ }
+ }
if (bind (sd, cur->ai_addr, cur->ai_addrlen))
{
const int errnum = openvpn_errno ();
@@ -1153,11 +1164,12 @@ static void bind_local (struct link_socket *sock)
#ifdef ENABLE_SOCKS
if (sock->socks_proxy && sock->info.proto == PROTO_UDP)
socket_bind (sock->ctrl_sd, sock->info.lsa->bind_local,
- sock->info.lsa->actual.ai_family, "SOCKS");
+ sock->info.lsa->actual.ai_family, "SOCKS", false);
else
#endif
socket_bind (sock->sd, sock->info.lsa->bind_local,
- sock->info.lsa->actual.ai_family, "TCP/UDP");
+ sock->info.lsa->actual.ai_family,
+ "TCP/UDP", sock->info.bind_ipv6_only);
}
}
@@ -1294,11 +1306,12 @@ create_new_socket (struct link_socket* sock)
resolve_bind_local (sock, sock->info.af);
}
resolve_remote (sock, 1, NULL, NULL);
+
/*
* In P2P or server mode we must create the socket even when resolving
* the remote site fails/is not specified. */
- if (sock->info.af && sock->info.lsa->actual.ai_family==0 && sock->bind_local)
+ if (sock->info.lsa->actual.ai_family==0 && sock->bind_local)
{
/* Copy sock parameters from bind addr */
set_actual_address (&sock->info.lsa->actual, sock->info.lsa->bind_local);
@@ -1309,7 +1322,7 @@ create_new_socket (struct link_socket* sock)
/*
* Create the socket early if socket should be bound
*/
- if (sock->bind_local && sock->info.lsa->actual.ai_family)
+ if (sock->bind_local)
{
create_socket (sock);
@@ -1328,6 +1341,7 @@ link_socket_init_phase1 (struct link_socket *sock,
const char *remote_port,
int proto,
sa_family_t af,
+ bool bind_ipv6_only,
int mode,
const struct link_socket *accept_from,
#ifdef ENABLE_HTTP_PROXY
@@ -1388,6 +1402,7 @@ link_socket_init_phase1 (struct link_socket *sock,
sock->info.af = af;
sock->info.remote_float = remote_float;
sock->info.lsa = lsa;
+ sock->info.bind_ipv6_only = bind_ipv6_only;
sock->info.ipchange_command = ipchange_command;
sock->info.plugins = plugins;
diff --git a/src/openvpn/socket.h b/src/openvpn/socket.h
index 5c93474..e0e0fff 100644
--- a/src/openvpn/socket.h
+++ b/src/openvpn/socket.h
@@ -118,6 +118,7 @@ struct link_socket_info
bool remote_float;
int proto; /* Protocol (PROTO_x defined below) */
sa_family_t af; /* Address family like AF_INET, AF_INET6 or AF_UNSPEC*/
+ bool bind_ipv6_only;
int mtu_changed; /* Set to true when mtu value is changed */
};
@@ -289,7 +290,8 @@ struct link_socket *link_socket_new (void);
void socket_bind (socket_descriptor_t sd,
struct addrinfo *local,
int af_family,
- const char *prefix);
+ const char *prefix,
+ bool ipv6only);
int openvpn_connect (socket_descriptor_t sd,
const struct sockaddr *remote,
@@ -308,6 +310,7 @@ link_socket_init_phase1 (struct link_socket *sock,
const char *remote_port,
int proto,
sa_family_t af,
+ bool bind_ipv6_only,
int mode,
const struct link_socket *accept_from,
#ifdef ENABLE_HTTP_PROXY