Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jjo/186203 to your computer and use it in GitHub Desktop.
Save jjo/186203 to your computer and use it in GitHub Desktop.
From 828996c831ee96947b785cfb8f376752ea02b69a Mon Sep 17 00:00:00 2001
From: JuanJo Ciarlante <jjo@google.com>
Date: Sun, 13 Sep 2009 13:43:04 +0200
Subject: [PATCH] * rebased openvpn-2.1_rc1b.jjo.20061206.d.patch
* passes {udp,tcp}x{v4,v6} loopback tests
* passes {udp,tcp}x{v6} remote tests
---
buffer.c | 13 ++
configure.ac | 16 ++
init.c | 36 ++--
manage.c | 10 +-
mroute.c | 60 ++++++-
mtcp.c | 1 +
multi.c | 17 ++-
occ.c | 2 +-
options.c | 42 +++--
ps.c | 6 +-
socket.c | 597 +++++++++++++++++++++++++++++++++++++++++++++++-----------
socket.h | 233 ++++++++++++++++++++---
socks.c | 18 +-
13 files changed, 857 insertions(+), 194 deletions(-)
diff --git a/buffer.c b/buffer.c
index 15ab776..1bef7d8 100644
--- a/buffer.c
+++ b/buffer.c
@@ -215,6 +215,19 @@ buf_printf (struct buffer *buf, const char *format, ...)
return ret;
}
+void buf_puts(struct buffer *buf, const char *str)
+{
+ uint8_t *ptr = BEND (buf);
+ int cap = buf_forward_capacity (buf);
+ if (cap > 0)
+ {
+ strncpynt ((char *)ptr,str, cap);
+ *(buf->data + buf->capacity - 1) = 0; /* windows vsnprintf needs this */
+ buf->len += (int) strlen ((char *)ptr);
+ }
+}
+
+
/*
* This is necessary due to certain buggy implementations of snprintf,
* that don't guarantee null termination for size > 0.
diff --git a/configure.ac b/configure.ac
index 116ff7c..6864783 100644
--- a/configure.ac
+++ b/configure.ac
@@ -135,6 +135,12 @@ AC_ARG_ENABLE(multihome,
[MULTIHOME="yes"]
)
+AC_ARG_ENABLE(ipv6,
+ [ --disable-ipv6 Disable UDP/IPv6 support],
+ [PF_INET6="$enableval"],
+ [PF_INET6="yes"]
+)
+
AC_ARG_ENABLE(port-share,
[ --disable-port-share Disable TCP server port-share support (--port-share)],
[PORT_SHARE="$enableval"],
@@ -550,6 +556,16 @@ LDFLAGS="$LDFLAGS -Wl,--fatal-warnings"
AC_CHECK_FUNC(epoll_create, AC_DEFINE(HAVE_EPOLL_CREATE, 1, [epoll_create function is defined]))
LDFLAGS="$OLDLDFLAGS"
+dnl ipv6 support
+if test "$PF_INET6" = "yes"; then
+ AC_CHECKING([for struct sockaddr_in6 for IPv6 support])
+ AC_CHECK_TYPE(
+ [struct sockaddr_in6],
+ [AC_DEFINE(USE_PF_INET6, 1, [struct sockaddr_in6 is needed for IPv6 peer support])],
+ [],
+ [#include "syshead.h"])
+fi
+
dnl
dnl check for valgrind tool
dnl
diff --git a/init.c b/init.c
index 80b2849..57ebad0 100644
--- a/init.c
+++ b/init.c
@@ -94,7 +94,7 @@ update_options_ce_post (struct options *options)
*/
if (options->pull
&& options->ping_rec_timeout_action == PING_UNDEF
- && options->ce.proto == PROTO_UDPv4)
+ && proto_is_dgram(options->ce.proto))
{
options->ping_rec_timeout = PRE_PULL_INITIAL_PING_RESTART;
options->ping_rec_timeout_action = PING_RESTART;
@@ -928,7 +928,7 @@ initialization_sequence_completed (struct context *c, const unsigned int flags)
const char *detail = "SUCCESS";
if (c->c1.tuntap)
tun_local = c->c1.tuntap->local;
- tun_remote = htonl (c->c1.link_socket_addr.actual.dest.sa.sin_addr.s_addr);
+ tun_remote = htonl (c->c1.link_socket_addr.actual.dest.addr.in4.sin_addr.s_addr);
if (flags & ISC_ERRORS)
detail = "ERROR";
management_set_state (management,
@@ -1333,7 +1333,7 @@ do_deferred_options (struct context *c, const unsigned int found)
#ifdef ENABLE_OCC
if (found & OPT_P_EXPLICIT_NOTIFY)
{
- if (c->options.ce.proto != PROTO_UDPv4 && c->options.explicit_exit_notification)
+ if (!proto_is_udp(c->options.ce.proto) && 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;
@@ -1428,13 +1428,22 @@ socket_restart_pause (struct context *c)
switch (c->options.ce.proto)
{
case PROTO_UDPv4:
+#ifdef USE_PF_INET6
+ case PROTO_UDPv6:
+#endif
if (proxy)
sec = c->options.ce.connect_retry_seconds;
break;
case PROTO_TCPv4_SERVER:
+#ifdef USE_PF_INET6
+ case PROTO_TCPv6_SERVER:
+#endif
sec = 1;
break;
case PROTO_TCPv4_CLIENT:
+#ifdef USE_PF_INET6
+ case PROTO_TCPv6_CLIENT:
+#endif
sec = c->options.ce.connect_retry_seconds;
break;
}
@@ -2565,7 +2574,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.ce.proto != PROTO_UDPv4)
+ if (!proto_is_udp(c->options.ce.proto))
msg (M_INFO, "NOTE: --fast-io is disabled since we are not using UDP");
else
{
@@ -2827,7 +2836,11 @@ init_instance (struct context *c, const struct env_set *env, const unsigned int
/* link_socket_mode allows CM_CHILD_TCP
instances to inherit acceptable fds
from a top-level parent */
+#ifdef USE_PF_INET6
+ if (c->options.ce.proto == PROTO_TCPv4_SERVER || c->options.ce.proto == PROTO_TCPv6_SERVER)
+#else
if (c->options.ce.proto == PROTO_TCPv4_SERVER)
+#endif
{
if (c->mode == CM_TOP)
link_socket_mode = LS_MODE_TCP_LISTEN;
@@ -3110,17 +3123,8 @@ inherit_context_child (struct context *dest,
{
CLEAR (*dest);
- switch (src->options.ce.proto)
- {
- case PROTO_UDPv4:
- dest->mode = CM_CHILD_UDP;
- break;
- case PROTO_TCPv4_SERVER:
- dest->mode = CM_CHILD_TCP;
- break;
- default:
- ASSERT (0);
- }
+ /* proto_is_dgram will ASSERT(0) if proto is invalid */
+ dest->mode = proto_is_dgram(src->options.ce.proto)? CM_CHILD_UDP : CM_CHILD_TCP;
dest->gc = gc_new ();
@@ -3226,7 +3230,7 @@ inherit_context_top (struct context *dest,
dest->c2.es_owned = false;
dest->c2.event_set = NULL;
- if (src->options.ce.proto == PROTO_UDPv4)
+ if (proto_is_dgram(src->options.ce.proto))
do_event_set_init (dest, false);
}
diff --git a/manage.c b/manage.c
index 97d69b4..7a1dddf 100644
--- a/manage.c
+++ b/manage.c
@@ -1874,9 +1874,9 @@ man_settings_init (struct man_settings *ms,
/*
* Initialize socket address
*/
- ms->local.sa.sin_family = AF_INET;
- ms->local.sa.sin_addr.s_addr = 0;
- ms->local.sa.sin_port = htons (port);
+ ms->local.addr.in4.sin_family = AF_INET;
+ ms->local.addr.in4.sin_addr.s_addr = 0;
+ ms->local.addr.in4.sin_port = htons (port);
/*
* Run management over tunnel, or
@@ -1888,7 +1888,7 @@ man_settings_init (struct man_settings *ms,
}
else
{
- ms->local.sa.sin_addr.s_addr = getaddr
+ ms->local.addr.in4.sin_addr.s_addr = getaddr
(GETADDR_RESOLVE|GETADDR_WARN_ON_SIGNAL|GETADDR_FATAL, addr, 0, NULL, NULL);
}
}
@@ -2255,7 +2255,7 @@ management_post_tunnel_open (struct management *man, const in_addr_t tun_local_i
&& man->connection.state == MS_INITIAL)
{
/* listen on our local TUN/TAP IP address */
- man->settings.local.sa.sin_addr.s_addr = htonl (tun_local_ip);
+ man->settings.local.addr.in4.sin_addr.s_addr = htonl (tun_local_ip);
man_connection_init (man);
}
diff --git a/mroute.c b/mroute.c
index 9d8fa66..e4abdad 100644
--- a/mroute.c
+++ b/mroute.c
@@ -226,25 +226,47 @@ bool mroute_extract_openvpn_sockaddr (struct mroute_addr *addr,
const struct openvpn_sockaddr *osaddr,
bool use_port)
{
- if (osaddr->sa.sin_family == AF_INET)
+ switch (osaddr->addr.sa.sa_family)
+ {
+ case AF_INET:
{
if (use_port)
{
addr->type = MR_ADDR_IPV4 | MR_WITH_PORT;
addr->netbits = 0;
addr->len = 6;
- memcpy (addr->addr, &osaddr->sa.sin_addr.s_addr, 4);
- memcpy (addr->addr + 4, &osaddr->sa.sin_port, 2);
+ memcpy (addr->addr, &osaddr->addr.in4.sin_addr.s_addr, 4);
+ memcpy (addr->addr + 4, &osaddr->addr.in4.sin_port, 2);
}
else
{
addr->type = MR_ADDR_IPV4;
addr->netbits = 0;
addr->len = 4;
- memcpy (addr->addr, &osaddr->sa.sin_addr.s_addr, 4);
+ memcpy (addr->addr, &osaddr->addr.in4.sin_addr.s_addr, 4);
}
return true;
}
+#ifdef USE_PF_INET6
+ case AF_INET6:
+ if (use_port)
+ {
+ addr->type = MR_ADDR_IPV6 | MR_WITH_PORT;
+ addr->netbits = 0;
+ addr->len = 18;
+ memcpy (addr->addr, &osaddr->addr.in6.sin6_addr, 16);
+ memcpy (addr->addr + 16, &osaddr->addr.in6.sin6_port, 2);
+ }
+ else
+ {
+ addr->type = MR_ADDR_IPV6;
+ addr->netbits = 0;
+ addr->len = 16;
+ memcpy (addr->addr, &osaddr->addr.in6.sin6_addr, 16);
+ }
+ return true;
+#endif
+ }
return false;
}
@@ -337,7 +359,37 @@ mroute_addr_print_ex (const struct mroute_addr *ma,
}
break;
case MR_ADDR_IPV6:
+#ifdef USE_PF_INET6
+ {
+ struct buffer buf;
+ struct sockaddr_in6 sin6;
+ int port;
+ char buf6[INET6_ADDRSTRLEN] = "";
+ memset(&sin6, 0, sizeof sin6);
+ sin6.sin6_family = AF_INET6;
+ buf_set_read (&buf, maddr.addr, maddr.len);
+ if (buf_read(&buf, &sin6.sin6_addr, sizeof (sin6.sin6_addr)))
+ {
+ if (getnameinfo((struct sockaddr *)&sin6, sizeof (struct sockaddr_in6),
+ buf6, sizeof (buf6), NULL, 0, NI_NUMERICHOST) != 0)
+ {
+ buf_printf (&out, "MR_ADDR_IPV6 getnameinfo() err");
+ break;
+ }
+ buf_puts (&out, buf6);
+ if (maddr.type & MR_WITH_NETBITS)
+ buf_printf (&out, "/%d", maddr.netbits);
+ if (maddr.type & MR_WITH_PORT)
+ {
+ port = buf_read_u16 (&buf);
+ if (port >= 0)
+ buf_printf (&out, ":%d", port);
+ }
+ }
+ }
+#else /* old pre IPV6 1-line code: */
buf_printf (&out, "IPV6");
+#endif
break;
default:
buf_printf (&out, "UNKNOWN");
diff --git a/mtcp.c b/mtcp.c
index 72c9618..f578429 100644
--- a/mtcp.c
+++ b/mtcp.c
@@ -153,6 +153,7 @@ multi_tcp_instance_specific_init (struct multi_context *m, struct multi_instance
ASSERT (mi->context.c2.link_socket);
ASSERT (mi->context.c2.link_socket->info.lsa);
ASSERT (mi->context.c2.link_socket->mode == LS_MODE_TCP_ACCEPT_FROM);
+ ASSERT (mi->context.c2.link_socket->info.lsa->actual.dest.addr.sa.sa_family == AF_INET);
if (!mroute_extract_openvpn_sockaddr (&mi->real, &mi->context.c2.link_socket->info.lsa->actual.dest, true))
{
msg (D_MULTI_ERRORS, "MULTI TCP: TCP client address is undefined");
diff --git a/multi.c b/multi.c
index f62563c..f89814a 100644
--- a/multi.c
+++ b/multi.c
@@ -1066,8 +1066,8 @@ multi_learn_in_addr_t (struct multi_context *m,
struct mroute_addr addr;
CLEAR (remote_si);
- remote_si.sa.sin_family = AF_INET;
- remote_si.sa.sin_addr.s_add
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment