summaryrefslogtreecommitdiff
path: root/app/openvpn/src/openvpn/multi.c
diff options
context:
space:
mode:
Diffstat (limited to 'app/openvpn/src/openvpn/multi.c')
-rw-r--r--app/openvpn/src/openvpn/multi.c117
1 files changed, 104 insertions, 13 deletions
diff --git a/app/openvpn/src/openvpn/multi.c b/app/openvpn/src/openvpn/multi.c
index bd5948c8..90b3d2dc 100644
--- a/app/openvpn/src/openvpn/multi.c
+++ b/app/openvpn/src/openvpn/multi.c
@@ -39,6 +39,7 @@
#include "gremlin.h"
#include "mstats.h"
#include "ssl_verify.h"
+#include <inttypes.h>
#include "memdbg.h"
@@ -402,7 +403,7 @@ multi_instance_string (const struct multi_instance *mi, bool null, struct gc_are
{
if (mi)
{
- struct buffer out = alloc_buf_gc (256, gc);
+ struct buffer out = alloc_buf_gc (MULTI_PREFIX_MAX_LENGTH, gc);
const char *cn = tls_common_name (mi->context.c2.tls_multi, true);
if (cn)
@@ -419,21 +420,27 @@ multi_instance_string (const struct multi_instance *mi, bool null, struct gc_are
void
generate_prefix (struct multi_instance *mi)
{
- mi->msg_prefix = multi_instance_string (mi, true, &mi->gc);
+ struct gc_arena gc = gc_new();
+ const char *prefix = multi_instance_string (mi, true, &gc);
+ if (prefix)
+ strncpynt(mi->msg_prefix, prefix, sizeof(mi->msg_prefix));
+ else
+ mi->msg_prefix[0] = '\0';
set_prefix (mi);
+ gc_free(&gc);
}
void
ungenerate_prefix (struct multi_instance *mi)
{
- mi->msg_prefix = NULL;
+ mi->msg_prefix[0] = '\0';
set_prefix (mi);
}
static const char *
mi_prefix (const struct multi_instance *mi)
{
- if (mi && mi->msg_prefix)
+ if (mi && mi->msg_prefix[0])
return mi->msg_prefix;
else
return "UNDEF_I";
@@ -814,8 +821,8 @@ multi_print_status (struct multi_context *m, struct status_output *so, const int
*/
status_printf (so, "TITLE%c%s", sep, title_string);
status_printf (so, "TIME%c%s%c%u", sep, time_string (now, 0, false, &gc_top), sep, (unsigned int)now);
- status_printf (so, "HEADER%cCLIENT_LIST%cCommon Name%cReal Address%cVirtual Address%cVirtual IPv6 Address%cBytes Received%cBytes Sent%cConnected Since%cConnected Since (time_t)%cUsername%cClient ID",
- sep, sep, sep, sep, sep, sep, sep, sep, sep, sep, sep);
+ status_printf (so, "HEADER%cCLIENT_LIST%cCommon Name%cReal Address%cVirtual Address%cVirtual IPv6 Address%cBytes Received%cBytes Sent%cConnected Since%cConnected Since (time_t)%cUsername%cClient ID%cPeer ID",
+ sep, sep, sep, sep, sep, sep, sep, sep, sep, sep, sep, sep);
hash_iterator_init (m->hash, &hi);
while ((he = hash_iterator_next (&hi)))
{
@@ -826,10 +833,11 @@ multi_print_status (struct multi_context *m, struct status_output *so, const int
{
status_printf (so, "CLIENT_LIST%c%s%c%s%c%s%c%s%c" counter_format "%c" counter_format "%c%s%c%u%c%s%c"
#ifdef MANAGEMENT_DEF_AUTH
- "%lu",
+ "%lu"
#else
- "",
+ ""
#endif
+ "%c%"PRIu32,
sep, tls_common_name (mi->context.c2.tls_multi, false),
sep, mroute_addr_print (&mi->real, &gc),
sep, print_in_addr_t (mi->reporting_addr, IA_EMPTY_IF_UNDEF, &gc),
@@ -840,10 +848,11 @@ multi_print_status (struct multi_context *m, struct status_output *so, const int
sep, (unsigned int)mi->created,
sep, tls_username (mi->context.c2.tls_multi, false),
#ifdef MANAGEMENT_DEF_AUTH
- sep, mi->context.c2.mda_context.cid);
+ sep, mi->context.c2.mda_context.cid,
#else
- sep);
+ sep,
#endif
+ sep, mi->context.c2.tls_multi ? mi->context.c2.tls_multi->peer_id : UINT32_MAX);
}
gc_free (&gc);
}
@@ -2104,6 +2113,70 @@ multi_process_post (struct multi_context *m, struct multi_instance *mi, const un
return ret;
}
+void multi_process_float (struct multi_context* m, struct multi_instance* mi)
+{
+ struct mroute_addr real;
+ struct hash *hash = m->hash;
+ struct gc_arena gc = gc_new ();
+
+ if (!mroute_extract_openvpn_sockaddr (&real, &m->top.c2.from.dest, true))
+ goto done;
+
+ const uint32_t hv = hash_value (hash, &real);
+ struct hash_bucket *bucket = hash_bucket (hash, hv);
+
+ struct hash_element *he = hash_lookup_fast (hash, bucket, &real, hv);
+ if (he)
+ {
+ struct multi_instance *ex_mi = (struct multi_instance *) he->value;
+
+ const char *cn = tls_common_name (mi->context.c2.tls_multi, true);
+ const char *ex_cn = tls_common_name (ex_mi->context.c2.tls_multi, true);
+ if (cn && ex_cn && strcmp (cn, ex_cn))
+ {
+ msg (D_MULTI_MEDIUM, "prevent float to %s",
+ multi_instance_string (ex_mi, false, &gc));
+
+ mi->context.c2.buf.len = 0;
+
+ goto done;
+ }
+
+ msg (D_MULTI_MEDIUM, "closing instance %s", multi_instance_string (ex_mi, false, &gc));
+ multi_close_instance(m, ex_mi, false);
+ }
+
+ msg (D_MULTI_MEDIUM, "peer %" PRIu32 " floated from %s to %s", mi->context.c2.tls_multi->peer_id,
+ mroute_addr_print (&mi->real, &gc), print_link_socket_actual (&m->top.c2.from, &gc));
+
+ ASSERT (hash_remove(m->hash, &mi->real));
+ ASSERT (hash_remove(m->iter, &mi->real));
+
+ /* change external network address of the remote peer */
+ mi->real = real;
+ generate_prefix (mi);
+
+ mi->context.c2.from = m->top.c2.from;
+ mi->context.c2.to_link_addr = &mi->context.c2.from;
+
+ /* inherit parent link_socket and link_socket_info */
+ mi->context.c2.link_socket = m->top.c2.link_socket;
+ mi->context.c2.link_socket_info->lsa->actual = m->top.c2.from;
+
+ tls_update_remote_addr (mi->context.c2.tls_multi, &mi->context.c2.from);
+
+ ASSERT (hash_add (m->hash, &mi->real, mi, false));
+ ASSERT (hash_add (m->iter, &mi->real, mi, false));
+
+#ifdef MANAGEMENT_DEF_AUTH
+ hash_remove (m->cid_hash, &mi->context.c2.mda_context.cid);
+ hash_add (m->cid_hash, &mi->context.c2.mda_context.cid, mi, false);
+#endif
+
+done:
+ gc_free (&gc);
+}
+
/*
* Process packets in the TCP/UDP socket -> TUN/TAP interface direction,
* i.e. client -> server direction.
@@ -2118,6 +2191,7 @@ multi_process_incoming_link (struct multi_context *m, struct multi_instance *ins
unsigned int mroute_flags;
struct multi_instance *mi;
bool ret = true;
+ bool floated = false;
if (m->pending)
return true;
@@ -2127,7 +2201,7 @@ multi_process_incoming_link (struct multi_context *m, struct multi_instance *ins
#ifdef MULTI_DEBUG_EVENT_LOOP
printf ("TCP/UDP -> TUN [%d]\n", BLEN (&m->top.c2.buf));
#endif
- multi_set_pending (m, multi_get_create_instance_udp (m));
+ multi_set_pending (m, multi_get_create_instance_udp (m, &floated));
}
else
multi_set_pending (m, instance);
@@ -2145,13 +2219,30 @@ multi_process_incoming_link (struct multi_context *m, struct multi_instance *ins
c->c2.buf = m->top.c2.buf;
/* transfer from-addr from top-level context buffer to instance */
- c->c2.from = m->top.c2.from;
+ if (!floated)
+ c->c2.from = m->top.c2.from;
}
if (BLEN (&c->c2.buf) > 0)
{
+ struct link_socket_info *lsi;
+ const uint8_t *orig_buf;
+
/* decrypt in instance context */
- process_incoming_link (c);
+
+ perf_push (PERF_PROC_IN_LINK);
+ lsi = get_link_socket_info (c);
+ orig_buf = c->c2.buf.data;
+ if (process_incoming_link_part1(c, lsi, floated))
+ {
+ if (floated)
+ {
+ multi_process_float (m, m->pending);
+ }
+
+ process_incoming_link_part2(c, lsi, orig_buf);
+ }
+ perf_pop ();
if (TUNNEL_TYPE (m->top.c1.tuntap) == DEV_TYPE_TUN)
{