Attention is currently required from: cron2, flichtenheld, mrbff, plaisthos.
Hello cron2, flichtenheld, plaisthos,
I'd like you to reexamine a change. Please visit
http://gerrit.openvpn.net/c/openvpn/+/869?usp=email
to look at the new patch set (#6).
The following approvals got outdated and were removed:
Code-Review-1 by cron2
Change subject: PUSH_UPDATE message sender: enabling the server to send
PUSH_UPDATE control messages
......................................................................
PUSH_UPDATE message sender: enabling the server to send PUSH_UPDATE control
messages
Using the management interface you can now target one or more clients (via
broadcast,
via cid, via common name, via address) and send a PUSH_UPDATE control message
to update some options.
Change-Id: Ie82bcc7a8e583de9156b185d71d1a323ed8df3fc
Signed-off-by: Marco Baffo <[email protected]>
---
M CMakeLists.txt
M doc/management-notes.txt
M src/openvpn/manage.c
M src/openvpn/manage.h
M src/openvpn/multi.c
M src/openvpn/multi.h
M src/openvpn/push.h
M src/openvpn/push_util.c
M tests/unit_tests/openvpn/Makefile.am
M tests/unit_tests/openvpn/test_push_update_msg.c
10 files changed, 796 insertions(+), 6 deletions(-)
git pull ssh://gerrit.openvpn.net:29418/openvpn refs/changes/69/869/6
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f597a89..185a312 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -832,6 +832,7 @@
src/openvpn/push_util.c
src/openvpn/options_util.c
src/openvpn/otime.c
+ src/openvpn/list.c
)
if (TARGET test_argv)
diff --git a/doc/management-notes.txt b/doc/management-notes.txt
index f1d2930..58393da 100644
--- a/doc/management-notes.txt
+++ b/doc/management-notes.txt
@@ -1028,6 +1028,51 @@
stored outside of the filesystem (e.g. in Mac OS X Keychain)
with OpenVPN via the management interface.
+COMMAND -- push-update-broad (OpenVPN 2.7 or higher)
+----------------------------------------------------
+Send a message to every connected client to update options at runtime.
+The updatable options are: "block-ipv6", "block-outside-dns", "dhcp-option",
+"dns", "ifconfig", "ifconfig-ipv6", "redirect-gateway", "redirect-private",
+"route", "route-gateway", "route-ipv6", "route-metric", "topology",
+"tun-mtu", "keepalive". When a valid option is pushed, the receiving client
will
+delete every previous value and set new value, so the update of the option will
+not be incremental even when theoretically possible (ex. with
"redirect-gateway").
+The '-' symbol in front of an option means the option should be removed.
+When an option is used with '-', it cannot take any parameter.
+The '?' symbol in front of an option means the option's update is optional
+so if the client do not support it, that option will just be ignored without
+making fail the entire command. The '-' and '?' symbols can be used together.
+
+Option Format Ex.
+ `-?option`, `-option`, `?option parameters` are valid formats,
+ `?-option` is not a valid format.
+
+Example
+ push-update-broad "route 10.10.10.1 255.255.255.255, -dns, ?tun-mtu 1400"
+
+COMMAND -- push-update-cid (OpenVPN 2.7 or higher)
+----------------------------------------------------
+Same as push-update-broad but you must target a single client using client id.
+
+Example
+ push-update-cid 42 "route 10.10.10.1 255.255.255.255, -dns, ?tun-mtu 1400"
+
+COMMAND -- push-update-cn (OpenVPN 2.7 or higher)
+----------------------------------------------------
+Same as push-update-broad but target the clients based on the provided common
name
+(usually just one client per common name is permitted except if "duplicate-cn"
option is used).
+
+Example
+ push-update-cid Client0 "route 10.10.10.1 255.255.255.255, -dns, ?tun-mtu
1400"
+
+COMMAND -- push-update-addr (OpenVPN 2.7 or higher)
+----------------------------------------------------
+Same as push-update-broad but target only the client(s) connecting from the
+provided address (real address). Support both IPv4 and IPv6.
+
+Example
+ push-update-addr 9.9.9.9 1234 "route 10.10.10.1 255.255.255.255, -dns,
?tun-mtu 1400"
+
OUTPUT FORMAT
-------------
diff --git a/src/openvpn/manage.c b/src/openvpn/manage.c
index 0e73942..43d2097 100644
--- a/src/openvpn/manage.c
+++ b/src/openvpn/manage.c
@@ -24,7 +24,6 @@
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
-
#include "syshead.h"
#ifdef ENABLE_MANAGEMENT
@@ -42,6 +41,7 @@
#include "manage.h"
#include "openvpn.h"
#include "dco.h"
+#include "push.h"
#include "memdbg.h"
@@ -124,6 +124,11 @@
msg(M_CLIENT, "username type u : Enter username u for a queried
OpenVPN username.");
msg(M_CLIENT, "verb [n] : Set log verbosity level to n, or
show if n is absent.");
msg(M_CLIENT, "version [n] : Set client's version to n or show
current version of daemon.");
+ msg(M_CLIENT, "push-update-broad options : Broadcast a message to update
the specified options.");
+ msg(M_CLIENT, " Ex. push-update-broad \"route
something, -dns\"");
+ msg(M_CLIENT, "push-update-cid CID options : Send an update message to the
client identified by CID.");
+ msg(M_CLIENT, "push-update-cn CN options : Send an update message to the
client(s) with the specified Common Name.");
+ msg(M_CLIENT, "push-update-addr ip port options : Send an update message
to the client(s) connecting from the provided address.");
msg(M_CLIENT, "END");
}
@@ -1334,6 +1339,154 @@
}
static void
+man_push_update(struct management *man, const char **p, const push_update_type
type)
+{
+ if (type == UPT_BROADCAST)
+ {
+ if (!man->persist.callback.push_update_broadcast)
+ {
+ man_command_unsupported("push-update-broad");
+ return;
+ }
+
+ const bool status =
(*man->persist.callback.push_update_broadcast)(man->persist.callback.arg, p[1]);
+
+ if (status)
+ {
+ msg(M_CLIENT, "SUCCESS: push-update-broad command succeeded");
+ }
+ else
+ {
+ msg(M_CLIENT, "ERROR: push-update-broad command failed");
+ }
+ }
+ else if (type == UPT_BY_CID)
+ {
+ if (!man->persist.callback.push_update_by_cid)
+ {
+ man_command_unsupported("push-update-cid");
+ return;
+ }
+
+ unsigned long cid = 0;
+
+ if (!parse_cid(p[1], &cid))
+ {
+ msg(M_CLIENT, "ERROR: push-update-cid fail during cid parsing");
+ return;
+ }
+
+ const bool status =
(*man->persist.callback.push_update_by_cid)(man->persist.callback.arg, cid,
p[2]);
+
+ if (status)
+ {
+ msg(M_CLIENT, "SUCCESS: push-update-cid command succeeded");
+ }
+ else
+ {
+ msg(M_CLIENT, "ERROR: push-update-cid command failed");
+ }
+ }
+ else if (type == UPT_BY_CN)
+ {
+ if (!man->persist.callback.push_update_by_cn)
+ {
+ man_command_unsupported("push-update-cn");
+ return;
+ }
+
+ const bool status =
(*man->persist.callback.push_update_by_cn)(man->persist.callback.arg, p[1],
p[2]);
+
+ if (status)
+ {
+ msg(M_CLIENT, "SUCCESS: push-update-cn command succeeded");
+ }
+ else
+ {
+ msg(M_CLIENT, "ERROR: push-update-cn command failed");
+ }
+ }
+ else if (type == UPT_BY_ADDR)
+ {
+ if (!man->persist.callback.push_update_by_addr)
+ {
+ man_command_unsupported("push-update-addr");
+ return;
+ }
+
+ const char *ip_str = p[1];
+ const char *port_str = p[2];
+ const char *options = p[3];
+
+ if (!strlen(ip_str) || !strlen(port_str))
+ {
+ msg(M_CLIENT, "ERROR: push-update-addr parse");
+ return;
+ }
+
+ struct addrinfo *res = NULL;
+ int port = atoi(port_str);
+
+ if (port < 1 || port > 65535)
+ {
+ msg(M_CLIENT, "ERROR: port number is out of range: %s", port_str);
+ return;
+ }
+
+ int status = openvpn_getaddrinfo(GETADDR_MSG_VIRT_OUT, ip_str,
port_str, 0, NULL, AF_UNSPEC, &res);
+
+ if (status != 0 || !res)
+ {
+ msg(M_CLIENT, "ERROR: error resolving address: %s (%s)", ip_str,
gai_strerror(status));
+ return;
+ }
+
+ struct addrinfo *rp;
+ bool found_client = false;
+
+ /* Iterate through resolved addresses */
+ for (rp = res; rp != NULL; rp = rp->ai_next)
+ {
+ struct openvpn_sockaddr saddr;
+ struct mroute_addr maddr;
+
+ CLEAR(saddr);
+ switch (rp->ai_family)
+ {
+ case AF_INET:
+ saddr.addr.in4 = *((struct sockaddr_in *)rp->ai_addr);
+ break;
+
+ case AF_INET6:
+ saddr.addr.in6 = *((struct sockaddr_in6 *)rp->ai_addr);
+ break;
+
+ default:
+ continue;
+ }
+
+ if (!mroute_extract_openvpn_sockaddr(&maddr, &saddr, true))
+ {
+ continue;
+ }
+
+ if
((*man->persist.callback.push_update_by_addr)(man->persist.callback.arg,
&maddr, options))
+ {
+ msg(M_CLIENT, "SUCCESS: push-update sent to %s:%d", ip_str,
port);
+ found_client = true;
+ break;
+ }
+ }
+
+ if (!found_client)
+ {
+ msg(M_CLIENT, "ERROR: no client found at address %s:%d", ip_str,
port);
+ }
+ freeaddrinfo(res);
+ }
+}
+
+static void
man_dispatch_command(struct management *man, struct status_output *so, const
char **p, const int nparms)
{
struct gc_arena gc = gc_new();
@@ -1655,6 +1808,34 @@
man_remote(man, p);
}
}
+ else if (streq(p[0], "push-update-broad"))
+ {
+ if (man_need(man, p, 1, 0))
+ {
+ man_push_update(man, p, UPT_BROADCAST);
+ }
+ }
+ else if (streq(p[0], "push-update-cid"))
+ {
+ if (man_need(man, p, 2, 0))
+ {
+ man_push_update(man, p, UPT_BY_CID);
+ }
+ }
+ else if (streq(p[0], "push-update-cn"))
+ {
+ if (man_need(man, p, 2, 0))
+ {
+ man_push_update(man, p, UPT_BY_CN);
+ }
+ }
+ else if (streq(p[0], "push-update-addr"))
+ {
+ if (man_need(man, p, 3, 0))
+ {
+ man_push_update(man, p, UPT_BY_ADDR);
+ }
+ }
#if 1
else if (streq(p[0], "test"))
{
diff --git a/src/openvpn/manage.h b/src/openvpn/manage.h
index 02ceb82..aab0760 100644
--- a/src/openvpn/manage.h
+++ b/src/openvpn/manage.h
@@ -44,7 +44,6 @@
#define MF_EXTERNAL_KEY_PSSPAD (1<<16)
#define MF_EXTERNAL_KEY_DIGEST (1<<17)
-
#ifdef ENABLE_MANAGEMENT
#include "misc.h"
@@ -205,6 +204,10 @@
#endif
unsigned int (*remote_entry_count)(void *arg);
bool (*remote_entry_get)(void *arg, unsigned int index, char **remote);
+ bool (*push_update_broadcast)(void *arg, const char *options);
+ bool (*push_update_by_cid)(void *arg, unsigned long cid, const char
*options);
+ bool (*push_update_by_cn)(void *arg, const char *cn, const char *options);
+ bool (*push_update_by_addr)(void *arg, const struct mroute_addr *maddr,
const char *options);
};
/*
diff --git a/src/openvpn/multi.c b/src/openvpn/multi.c
index ec04369..2a8b725 100644
--- a/src/openvpn/multi.c
+++ b/src/openvpn/multi.c
@@ -4062,7 +4062,7 @@
}
}
-static struct multi_instance *
+struct multi_instance *
lookup_by_cid(struct multi_context *m, const unsigned long cid)
{
if (m)
@@ -4210,6 +4210,10 @@
cb.client_auth = management_client_auth;
cb.client_pending_auth = management_client_pending_auth;
cb.get_peer_info = management_get_peer_info;
+ cb.push_update_broadcast =
management_callback_send_push_update_broadcast;
+ cb.push_update_by_cid = management_callback_send_push_update_by_cid;
+ cb.push_update_by_cn = management_callback_send_push_update_by_cn;
+ cb.push_update_by_addr = management_callback_send_push_update_by_addr;
management_set_callback(management, &cb);
}
#endif /* ifdef ENABLE_MANAGEMENT */
diff --git a/src/openvpn/multi.h b/src/openvpn/multi.h
index e14ad60..b78bfc9 100644
--- a/src/openvpn/multi.h
+++ b/src/openvpn/multi.h
@@ -710,5 +710,10 @@
*/
void multi_assign_peer_id(struct multi_context *m, struct multi_instance *mi);
+#ifdef ENABLE_MANAGEMENT
+struct multi_instance *
+lookup_by_cid(struct multi_context *m, const unsigned long cid);
+
+#endif
#endif /* MULTI_H */
diff --git a/src/openvpn/push.h b/src/openvpn/push.h
index 4643c36..6127012 100644
--- a/src/openvpn/push.h
+++ b/src/openvpn/push.h
@@ -42,6 +42,16 @@
#define PUSH_OPT_TO_REMOVE (1<<0)
#define PUSH_OPT_OPTIONAL (1<<1)
+/* Push-update message sender modes */
+typedef enum {
+ UPT_BROADCAST = 0,
+ UPT_BY_ADDR = 1,
+ UPT_BY_CN = 2,
+#ifdef ENABLE_MANAGEMENT
+ UPT_BY_CID = 3
+#endif
+} push_update_type;
+
int process_incoming_push_request(struct context *c);
/**
@@ -134,4 +144,33 @@
void
receive_auth_pending(struct context *c, const struct buffer *buffer);
+/**
+ * @brief A function to send a PUSH_UPDATE control message from server to
client(s).
+ *
+ * @param m the multi_context, contains all the clients connected to this
server.
+ * @param target the target to which to send the message. It should be:
+ * `NULL` if `type == UPT_BROADCAST`,
+ * a `mroute_addr *` if `type == UPT_BY_ADDR`,
+ * a `char *` if `type == UPT_BY_CN`,
+ * an `unsigned long *` if `type == UPT_BY_CID`.
+ * @param msg a string containing the options to send.
+ * @param type the way to address the message (broadcast, by cid, by cn, by
address).
+ * @param push_bundle_size the maximum size of a bundle of pushed option. Just
use PUSH_BUNDLE_SIZE macro.
+ * @return the number of clients to which the message was sent.
+ */
+int
+send_push_update(struct multi_context *m, const void *target, const char *msg,
const push_update_type type, const int push_bundle_size);
+
+#ifdef ENABLE_MANAGEMENT
+
+bool management_callback_send_push_update_broadcast(void *arg, const char
*options);
+
+bool management_callback_send_push_update_by_cid(void *arg, unsigned long cid,
const char *options);
+
+bool management_callback_send_push_update_by_cn(void *arg, const char *cn,
const char *options);
+
+bool management_callback_send_push_update_by_addr(void *arg, const struct
mroute_addr *maddr, const char *options);
+
+#endif /* ifdef ENABLE_MANAGEMENT*/
+
#endif /* ifndef PUSH_H */
diff --git a/src/openvpn/push_util.c b/src/openvpn/push_util.c
index b4d1e8b..d79bf98 100644
--- a/src/openvpn/push_util.c
+++ b/src/openvpn/push_util.c
@@ -3,6 +3,8 @@
#endif
#include "push.h"
+#include "multi.h"
+#include "ssl_verify.h"
int
process_incoming_push_update(struct context *c,
@@ -42,3 +44,257 @@
return ret;
}
+
+/**
+ * Return index of last `,` or `0` if it didn't find any.
+ * If there is a comma at index `0` it's an error anyway
+ */
+static int
+find_first_comma_of_next_bundle(const char *str, int ix)
+{
+ while (ix > 0)
+ {
+ if (str[ix] == ',')
+ {
+ return ix;
+ }
+ ix--;
+ }
+ return 0;
+}
+
+/* Allocate memory and asseble the final message */
+static char *
+forge_msg(const char *src, const char *continuation, struct gc_arena *gc)
+{
+ int src_len = strlen(src);
+ int con_len = continuation ? strlen(continuation) : 0;
+ char *ret = gc_malloc((src_len + sizeof(push_update_cmd) + con_len + 2) *
sizeof(char), true, gc);
+ int i = sizeof(push_update_cmd) -1;
+
+ strcpy(ret, push_update_cmd);
+ ret[i++] = ',';
+ strcpy(&ret[i], src);
+ if (continuation)
+ {
+ i += src_len;
+ strcpy(&ret[i], continuation);
+ }
+ return ret;
+}
+
+static char *
+gc_strdup(const char *src, struct gc_arena *gc)
+{
+ char *ret = gc_malloc((strlen(src) + 1) * sizeof(char), true, gc);
+
+ strcpy(ret, src);
+ return ret;
+}
+
+/* It split the messagge (if necessay) and fill msgs with the message chunks.
+ * Return `false` on failure an `true` on success.
+ */
+static bool
+message_splitter(char *str, char **msgs, struct gc_arena *gc, const int
safe_cap)
+{
+ if (!str || !*str)
+ {
+ return false;
+ }
+
+ int i = 0;
+ int im = 0;
+
+ while (*str)
+ {
+ /* + ',' - '/0' */
+ if (strlen(str) > safe_cap)
+ {
+ int ci = find_first_comma_of_next_bundle(str, safe_cap);
+ if (!ci)
+ {
+ /* if no commas were found go to fail, do not send any message
*/
+ return false;
+ }
+ str[ci] = '\0';
+ /* copy from i to (ci -1) */
+ msgs[im] = forge_msg(str, ",push-continuation 2", gc);
+ i = ci + 1;
+ }
+ else
+ {
+ if (im)
+ {
+ msgs[im] = forge_msg(str, ",push-continuation 1", gc);
+ }
+ else
+ {
+ msgs[im] = forge_msg(str, NULL, gc);
+ }
+ i = strlen(str);
+ }
+ str = &str[i];
+ im++;
+ }
+ return true;
+}
+
+/* It actually send the already divided messagge to one single client */
+static bool
+send_single_push_update(struct context *c, char **msgs)
+{
+ if (!msgs[0] || !*msgs[0])
+ {
+ return false;
+ }
+ int i = 0;
+ while (msgs[i] && *msgs[i])
+ {
+ if (!send_control_channel_string(c, msgs[i], D_PUSH))
+ {
+ return false;
+ }
+ i++;
+ }
+ return true;
+}
+
+int
+send_push_update(struct multi_context *m, const void *target, const char *msg,
const push_update_type type, const int push_bundle_size)
+{
+ if (!msg || !*msg || !m
+ || (!target && type != UPT_BROADCAST))
+ {
+ return -EINVAL;
+ }
+
+ struct gc_arena gc = gc_new();
+ /* extra space for possible trailing ifconfig and push-continuation */
+ const int extra = 84 + sizeof(push_update_cmd);
+ /* push_bundle_size is the maximum size of a message, so if the message
+ * we want to send exceeds that size we have to split it into smaller
messages */
+ const int safe_cap = push_bundle_size - extra;
+ int msgs_num = (strlen(msg) / safe_cap) + ((strlen(msg) % safe_cap) != 0);
+ char **msgs = gc_malloc(sizeof(char *) * (msgs_num + 1), true, &gc);
+
+ msgs[msgs_num] = NULL;
+ if (!message_splitter(gc_strdup(msg, &gc), msgs, &gc, safe_cap))
+ {
+ gc_free(&gc);
+ return -EINVAL;
+ }
+
+#ifdef ENABLE_MANAGEMENT
+ if (type == UPT_BY_CID)
+ {
+ struct multi_instance *mi = lookup_by_cid(m, *((unsigned long
*)target));
+
+ if (!mi)
+ {
+ return -ENOENT;
+ }
+ if (!mi->halt
+ && send_single_push_update(&mi->context, msgs))
+ {
+ gc_free(&gc);
+ return 1;
+ }
+ else
+ {
+ gc_free(&gc);
+ return 0;
+ }
+ }
+#endif /* ifdef ENABLE_MANAGEMENT */
+
+ int count = 0;
+ struct hash_iterator hi;
+ const struct hash_element *he;
+
+ hash_iterator_init(m->iter, &hi);
+ while ((he = hash_iterator_next(&hi)))
+ {
+ struct multi_instance *curr_mi = he->value;
+
+ if (curr_mi->halt)
+ {
+ continue;
+ }
+ if (type == UPT_BY_ADDR && !mroute_addr_equal(target, &curr_mi->real))
+ {
+ continue;
+ }
+ else if (type == UPT_BY_CN)
+ {
+ const char *curr_cn =
tls_common_name(curr_mi->context.c2.tls_multi, false);
+ if (strcmp(curr_cn, target))
+ {
+ continue;
+ }
+ }
+ /* Either we found a matching client or type is UPT_BROADCAST so we
update every client */
+ if (!send_single_push_update(&curr_mi->context, msgs))
+ {
+ msg(M_CLIENT, "ERROR: Peer ID: %u has not been updated",
+ curr_mi->context.c2.tls_multi ?
curr_mi->context.c2.tls_multi->peer_id : UINT32_MAX);
+ continue;
+ }
+ count++;
+ }
+
+ hash_iterator_free(&hi);
+ gc_free(&gc);
+ return count;
+}
+
+#ifdef ENABLE_MANAGEMENT
+#define RETURN_UPDATE_STATUS(n_sent) \
+ do { \
+ if ((n_sent) > 0) { \
+ msg(M_CLIENT, "SUCCESS: %d client(s) updated", (n_sent)); \
+ return true; \
+ } else { \
+ msg(M_CLIENT, "ERROR: no client updated"); \
+ return false; \
+ } \
+ } while (0)
+
+
+bool
+management_callback_send_push_update_broadcast(void *arg, const char *options)
+{
+ int n_sent = send_push_update(arg, NULL, options, UPT_BROADCAST,
PUSH_BUNDLE_SIZE);
+
+ RETURN_UPDATE_STATUS(n_sent);
+}
+
+bool
+management_callback_send_push_update_by_cid(void *arg, unsigned long cid,
const char *options)
+{
+ int ret = send_push_update(arg, &cid, options, UPT_BY_CID,
PUSH_BUNDLE_SIZE);
+
+ if (ret == -ENOENT)
+ {
+ msg(M_CLIENT, "ERROR: no client found with CID: %lu", cid);
+ }
+
+ return (ret > 0);
+}
+
+bool
+management_callback_send_push_update_by_cn(void *arg, const char *cn, const
char *options)
+{
+ int n_sent = send_push_update(arg, cn, options, UPT_BY_CN,
PUSH_BUNDLE_SIZE);
+
+ RETURN_UPDATE_STATUS(n_sent);
+}
+
+bool
+management_callback_send_push_update_by_addr(void *arg, const struct
mroute_addr *maddr, const char *options)
+{
+ int n_sent = send_push_update(arg, maddr, options, UPT_BY_ADDR,
PUSH_BUNDLE_SIZE);
+
+ RETURN_UPDATE_STATUS(n_sent);
+}
+#endif /* ifdef ENABLE_MANAGEMENT */
diff --git a/tests/unit_tests/openvpn/Makefile.am
b/tests/unit_tests/openvpn/Makefile.am
index 6fb7843..ef9c359 100644
--- a/tests/unit_tests/openvpn/Makefile.am
+++ b/tests/unit_tests/openvpn/Makefile.am
@@ -331,4 +331,5 @@
$(top_srcdir)/src/openvpn/platform.c \
$(top_srcdir)/src/openvpn/push_util.c \
$(top_srcdir)/src/openvpn/options_util.c \
- $(top_srcdir)/src/openvpn/otime.c
\ No newline at end of file
+ $(top_srcdir)/src/openvpn/otime.c \
+ $(top_srcdir)/src/openvpn/list.c
\ No newline at end of file
diff --git a/tests/unit_tests/openvpn/test_push_update_msg.c
b/tests/unit_tests/openvpn/test_push_update_msg.c
index d0876bc..549520b 100644
--- a/tests/unit_tests/openvpn/test_push_update_msg.c
+++ b/tests/unit_tests/openvpn/test_push_update_msg.c
@@ -8,6 +8,7 @@
#include <cmocka.h>
#include "push.h"
#include "options_util.h"
+#include "multi.h"
/* mocks */
@@ -94,6 +95,49 @@
}
}
+const char *
+tls_common_name(const struct tls_multi *multi, const bool null)
+{
+ return NULL;
+}
+
+#ifndef ENABLE_MANAGEMENT
+bool
+send_control_channel_string(struct context *c, const char *str, int msglevel)
+{
+ return true;
+}
+#else /* ifndef ENABLE_MANAGEMENT */
+char **res;
+int i;
+
+bool
+send_control_channel_string(struct context *c, const char *str, int msglevel)
+{
+ if (res && res[i] && strcmp(res[i], str))
+ {
+ printf("\n\nexpected: %s\n\n actual: %s\n\n", res[i], str);
+ return false;
+ }
+ i++;
+ return true;
+}
+
+struct multi_instance *
+lookup_by_cid(struct multi_context *m, const unsigned long cid)
+{
+ return *(m->instances);
+}
+
+bool
+mroute_extract_openvpn_sockaddr(struct mroute_addr *addr,
+ const struct openvpn_sockaddr *osaddr,
+ bool use_port)
+{
+ return true;
+}
+#endif /* ifndef ENABLE_MANAGEMENT */
+
/* tests */
static void
@@ -124,7 +168,6 @@
free_buf(&buf);
}
-
static void
test_incoming_push_message_error2(void **state)
{
@@ -209,6 +252,205 @@
free_buf(&buf);
}
+#ifdef ENABLE_MANAGEMENT
+char *r0[] = {
+ "PUSH_UPDATE,redirect-gateway local,route 192.168.1.0 255.255.255.0"
+};
+char *r1[] = {
+ "PUSH_UPDATE,-dhcp-option,blablalalalalalalalalalalalalf,
lalalalalalalalalalalalalalaf,push-continuation 2",
+ "PUSH_UPDATE, akakakakakakakakakakakaf, dhcp-option DNS
8.8.8.8,redirect-gateway local,push-continuation 2",
+ "PUSH_UPDATE,route 192.168.1.0 255.255.255.0,push-continuation 1"
+};
+char *r3[] = {
+ "PUSH_UPDATE,,,"
+};
+char *r4[] = {
+ "PUSH_UPDATE,-dhcp-option, blablalalalalalalalalalalalalf,
lalalalalalalalalalalalalalaf,push-continuation 2",
+ "PUSH_UPDATE, akakakakakakakakakakakaf,dhcp-option DNS 8.8.8.8,
redirect-gateway local,push-continuation 2",
+ "PUSH_UPDATE, route 192.168.1.0 255.255.255.0,,push-continuation 1"
+};
+char *r5[] = {
+ "PUSH_UPDATE,,-dhcp-option, blablalalalalalalalalalalalalf,
lalalalalalalalalalalalalalaf,push-continuation 2",
+ "PUSH_UPDATE, akakakakakakakakakakakaf,dhcp-option DNS 8.8.8.8,
redirect-gateway local,push-continuation 2",
+ "PUSH_UPDATE, route 192.168.1.0 255.255.255.0,push-continuation 1"
+};
+char *r6[] = {
+ "PUSH_UPDATE,-dhcp-option,blablalalalalalalalalalalalalf,
lalalalalalalalalalalalalalaf,push-continuation 2",
+ "PUSH_UPDATE, akakakakakakakakakakakaf, dhcp-option DNS 8.8.8.8,
redirect-gateway 10.10.10.10,,push-continuation 2",
+ "PUSH_UPDATE, route 192.168.1.0 255.255.255.0,,push-continuation 1"
+};
+char *r7[] = {
+
"PUSH_UPDATE,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,push-continuation
2",
+ "PUSH_UPDATE,,,,,,,,,,,,,,,,,,,push-continuation 1"
+};
+char *r8[] = {
+ "PUSH_UPDATE,-dhcp-option,blablalalalalalalalalalalalalf,
lalalalalalalalalalalalalalaf,push-continuation 2",
+ "PUSH_UPDATE, akakakakakakakakakakakaf, dhcp-option DNS
8.8.8.8,redirect-gateway\n local,push-continuation 2",
+ "PUSH_UPDATE,route 192.168.1.0 255.255.255.0\n\n\n,push-continuation 1"
+};
+char *r9[] = {
+ "PUSH_UPDATE,,"
+};
+
+
+const char *msg0 = "redirect-gateway local,route 192.168.1.0 255.255.255.0";
+const char *msg1 = "-dhcp-option,blablalalalalalalalalalalalalf,
lalalalalalalalalalalalalalaf,"
+ " akakakakakakakakakakakaf, dhcp-option DNS
8.8.8.8,redirect-gateway local,route 192.168.1.0 255.255.255.0";
+const char *msg2 = "";
+const char *msg3 = ",,";
+const char *msg4 = "-dhcp-option, blablalalalalalalalalalalalalf,
lalalalalalalalalalalalalalaf,"
+ " akakakakakakakakakakakaf,dhcp-option DNS 8.8.8.8,
redirect-gateway local, route 192.168.1.0 255.255.255.0,";
+const char *msg5 = ",-dhcp-option, blablalalalalalalalalalalalalf,
lalalalalalalalalalalalalalaf,"
+ " akakakakakakakakakakakaf,dhcp-option DNS 8.8.8.8,
redirect-gateway local, route 192.168.1.0 255.255.255.0";
+const char *msg6 = "-dhcp-option,blablalalalalalalalalalalalalf,
lalalalalalalalalalalalalalaf, akakakakakakakakakakakaf,"
+ " dhcp-option DNS 8.8.8.8, redirect-gateway 10.10.10.10,,
route 192.168.1.0 255.255.255.0,";
+const char *msg7 =
",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,";
+const char *msg8 = "-dhcp-option,blablalalalalalalalalalalalalf,
lalalalalalalalalalalalalalaf, akakakakakakakakakakakaf,"
+ " dhcp-option DNS 8.8.8.8,redirect-gateway\n local,route
192.168.1.0 255.255.255.0\n\n\n";
+const char *msg9 = ",";
+const char *msg10 = "VoilĂ ! In view, a humble vaudevillian veteran cast
vicariously as both victim and villain by the vicissitudes"
+ " of Fate. This visage no mere veneer of vanity is a
vestige of the vox populi now vacant vanished. However this"
+ " valorous visitation of a by-gone vexation stands
vivified and has vowed to vanquish these venal and virulent"
+ " vermin vanguarding vice and vouchsafing the violently
vicious and voracious violation of volition. The only"
+ " verdict is vengeance; a vendetta held as a votive not in
vain for the value and veracity of such shall one"
+ " day vindicate the vigilant and the virtuous. Verily this
vichyssoise of verbiage veers most verbose so let"
+ " me simply add that it is my very good honor to meet you
and you may call me V.";
+
+#define PUSH_BUNDLE_SIZE_TEST 184
+
+static void
+test_send_push_msg0(void **state)
+{
+ i = 0;
+ res = r0;
+ struct multi_context *m = *state;
+ const unsigned long cid = 0;
+ assert_int_equal(send_push_update(m, &cid, msg0, UPT_BY_CID,
PUSH_BUNDLE_SIZE_TEST), 1);
+}
+static void
+test_send_push_msg1(void **state)
+{
+ i = 0;
+ res = r1;
+ struct multi_context *m = *state;
+ const unsigned long cid = 0;
+ assert_int_equal(send_push_update(m, &cid, msg1, UPT_BY_CID,
PUSH_BUNDLE_SIZE_TEST), 1);
+}
+
+static void
+test_send_push_msg2(void **state)
+{
+ i = 0;
+ res = NULL;
+ struct multi_context *m = *state;
+ const unsigned long cid = 0;
+ assert_int_equal(send_push_update(m, &cid, msg2, UPT_BY_CID,
PUSH_BUNDLE_SIZE_TEST), -EINVAL);
+}
+
+static void
+test_send_push_msg3(void **state)
+{
+ i = 0;
+ res = r3;
+ struct multi_context *m = *state;
+ const unsigned long cid = 0;
+ assert_int_equal(send_push_update(m, &cid, msg3, UPT_BY_CID,
PUSH_BUNDLE_SIZE_TEST), 1);
+}
+
+static void
+test_send_push_msg4(void **state)
+{
+ i = 0;
+ res = r4;
+ struct multi_context *m = *state;
+ const unsigned long cid = 0;
+ assert_int_equal(send_push_update(m, &cid, msg4, UPT_BY_CID,
PUSH_BUNDLE_SIZE_TEST), 1);
+}
+
+static void
+test_send_push_msg5(void **state)
+{
+ i = 0;
+ res = r5;
+ struct multi_context *m = *state;
+ const unsigned long cid = 0;
+ assert_int_equal(send_push_update(m, &cid, msg5, UPT_BY_CID,
PUSH_BUNDLE_SIZE_TEST), 1);
+}
+
+static void
+test_send_push_msg6(void **state)
+{
+ i = 0;
+ res = r6;
+ struct multi_context *m = *state;
+ const unsigned long cid = 0;
+ assert_int_equal(send_push_update(m, &cid, msg6, UPT_BY_CID,
PUSH_BUNDLE_SIZE_TEST), 1);
+}
+
+static void
+test_send_push_msg7(void **state)
+{
+ i = 0;
+ res = r7;
+ struct multi_context *m = *state;
+ const unsigned long cid = 0;
+ assert_int_equal(send_push_update(m, &cid, msg7, UPT_BY_CID,
PUSH_BUNDLE_SIZE_TEST), 1);
+}
+
+static void
+test_send_push_msg8(void **state)
+{
+ i = 0;
+ res = r8;
+ struct multi_context *m = *state;
+ const unsigned long cid = 0;
+ assert_int_equal(send_push_update(m, &cid, msg8, UPT_BY_CID,
PUSH_BUNDLE_SIZE_TEST), 1);
+}
+
+static void
+test_send_push_msg9(void **state)
+{
+ i = 0;
+ res = r9;
+ struct multi_context *m = *state;
+ const unsigned long cid = 0;
+ assert_int_equal(send_push_update(m, &cid, msg9, UPT_BY_CID,
PUSH_BUNDLE_SIZE_TEST), 1);
+}
+
+static void
+test_send_push_msg10(void **state)
+{
+ i = 0;
+ res = NULL;
+ struct multi_context *m = *state;
+ const unsigned long cid = 0;
+ assert_int_equal(send_push_update(m, &cid, msg10, UPT_BY_CID,
PUSH_BUNDLE_SIZE_TEST), -EINVAL);
+}
+
+#undef PUSH_BUNDLE_SIZE_TEST
+
+static int
+setup2(void **state)
+{
+ struct multi_context *m = calloc(1, sizeof(struct multi_context));
+ m->instances = calloc(1, sizeof(struct multi_instance *));
+ struct multi_instance *mi = calloc(1, sizeof(struct multi_instance));
+ *(m->instances) = mi;
+ *state = m;
+ return 0;
+}
+
+static int
+teardown2(void **state)
+{
+ struct multi_context *m = *state;
+ free(*(m->instances));
+ free(m->instances);
+ free(m);
+ return 0;
+}
+#endif /* ifdef ENABLE_MANAGEMENT */
+
static int
setup(void **state)
{
@@ -238,7 +480,20 @@
cmocka_unit_test_setup_teardown(test_incoming_push_message_1, setup,
teardown),
cmocka_unit_test_setup_teardown(test_incoming_push_message_bad_format,
setup, teardown),
cmocka_unit_test_setup_teardown(test_incoming_push_message_mix, setup,
teardown),
- cmocka_unit_test_setup_teardown(test_incoming_push_message_mix2,
setup, teardown)
+ cmocka_unit_test_setup_teardown(test_incoming_push_message_mix2,
setup, teardown),
+#ifdef ENABLE_MANAGEMENT
+ cmocka_unit_test_setup_teardown(test_send_push_msg0, setup2,
teardown2),
+ cmocka_unit_test_setup_teardown(test_send_push_msg1, setup2,
teardown2),
+ cmocka_unit_test_setup_teardown(test_send_push_msg2, setup2,
teardown2),
+ cmocka_unit_test_setup_teardown(test_send_push_msg3, setup2,
teardown2),
+ cmocka_unit_test_setup_teardown(test_send_push_msg4, setup2,
teardown2),
+ cmocka_unit_test_setup_teardown(test_send_push_msg5, setup2,
teardown2),
+ cmocka_unit_test_setup_teardown(test_send_push_msg6, setup2,
teardown2),
+ cmocka_unit_test_setup_teardown(test_send_push_msg7, setup2,
teardown2),
+ cmocka_unit_test_setup_teardown(test_send_push_msg8, setup2,
teardown2),
+ cmocka_unit_test_setup_teardown(test_send_push_msg9, setup2,
teardown2),
+ cmocka_unit_test_setup_teardown(test_send_push_msg10, setup2,
teardown2)
+#endif
};
return cmocka_run_group_tests(tests, NULL, NULL);
--
To view, visit http://gerrit.openvpn.net/c/openvpn/+/869?usp=email
To unsubscribe, or for help writing mail filters, visit
http://gerrit.openvpn.net/settings
Gerrit-Project: openvpn
Gerrit-Branch: master
Gerrit-Change-Id: Ie82bcc7a8e583de9156b185d71d1a323ed8df3fc
Gerrit-Change-Number: 869
Gerrit-PatchSet: 6
Gerrit-Owner: mrbff <[email protected]>
Gerrit-Reviewer: cron2 <[email protected]>
Gerrit-Reviewer: flichtenheld <[email protected]>
Gerrit-Reviewer: plaisthos <[email protected]>
Gerrit-CC: openvpn-devel <[email protected]>
Gerrit-Attention: plaisthos <[email protected]>
Gerrit-Attention: cron2 <[email protected]>
Gerrit-Attention: flichtenheld <[email protected]>
Gerrit-Attention: mrbff <[email protected]>
Gerrit-MessageType: newpatchset
_______________________________________________
Openvpn-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/openvpn-devel