<p>Max has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/12763">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">Add OpenVPN probe<br><br>This adds support for OpenVPN status probe which uses OpenVPN's<br>management interface (configured via 'management 127.0.0.1 1234' in<br>OpenVPN's config).<br><br>The output looks as follows:<br>...<br> OpenVPN<br> 127.0.0.1:1234<br> status: CONNECTED<br> tunnel: 10.8.0.15<br> remote: 144.76.43.77:1194<br> localhost:4242<br> status: management interface incompatible<br> 127.0.0.1:4444<br> status: management interface unavailable<br>...<br><br>We show tunnel's IP (if available) as well as remote (OpenVPN server<br>itself) address/port in addition to general connection status. If<br>management interface is unavailable it's reported as such. If we've<br>managed to establish connection with a given management interface but<br>are unable to obtain expected information than we report this<br>incompatibility as well.<br><br>Related: SYS#2655<br>Change-Id: I4493e19b9a09dcebd289457eacd1719f7f8cc31c<br>---<br>M src/Makefile.am<br>M src/osysmon.h<br>M src/osysmon_main.c<br>A src/osysmon_openvpn.c<br>4 files changed, 307 insertions(+), 0 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/osmo-sysmon refs/changes/63/12763/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/src/Makefile.am b/src/Makefile.am</span><br><span>index e38b70e..f9b79f2 100644</span><br><span>--- a/src/Makefile.am</span><br><span>+++ b/src/Makefile.am</span><br><span>@@ -29,6 +29,7 @@</span><br><span> </span><br><span> osmo_sysmon_LDADD = $(LDADD) \</span><br><span> $(LIBOSMOVTY_LIBS) \</span><br><span style="color: hsl(120, 100%, 40%);">+ $(LIBOSMONETIF_LIBS) \</span><br><span> $(LIBMNL_LIBS) \</span><br><span> $(LIBOPING_LIBS) \</span><br><span> $(NULL)</span><br><span>@@ -40,6 +41,7 @@</span><br><span> osysmon_rtnl.c \</span><br><span> osysmon_file.c \</span><br><span> osysmon_ping.c \</span><br><span style="color: hsl(120, 100%, 40%);">+ osysmon_openvpn.c \</span><br><span> osysmon_main.c \</span><br><span> $(NULL)</span><br><span> </span><br><span>diff --git a/src/osysmon.h b/src/osysmon.h</span><br><span>index df8bf8d..2f82c47 100644</span><br><span>--- a/src/osysmon.h</span><br><span>+++ b/src/osysmon.h</span><br><span>@@ -15,6 +15,8 @@</span><br><span> struct rtnl_client_state *rcs;</span><br><span> /* list of 'struct ctrl client' */</span><br><span> struct llist_head ctrl_clients;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* list of 'struct openvpn_client' */</span><br><span style="color: hsl(120, 100%, 40%);">+ struct llist_head openvpn_clients;</span><br><span> /* list of 'struct netdev' */</span><br><span> struct llist_head netdevs;</span><br><span> /* list of 'struct osysmon_file' */</span><br><span>@@ -30,6 +32,7 @@</span><br><span> CTRL_CLIENT_NODE = _LAST_OSMOVTY_NODE + 1,</span><br><span> CTRL_CLIENT_GETVAR_NODE,</span><br><span> NETDEV_NODE,</span><br><span style="color: hsl(120, 100%, 40%);">+ OPENVPN_NODE,</span><br><span> PING_NODE,</span><br><span> };</span><br><span> </span><br><span>@@ -48,5 +51,8 @@</span><br><span> int osysmon_ping_init();</span><br><span> int osysmon_ping_poll(struct value_node *parent);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+int osysmon_openvpn_init();</span><br><span style="color: hsl(120, 100%, 40%);">+int osysmon_openvpn_poll(struct value_node *parent);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> int osysmon_file_init();</span><br><span> int osysmon_file_poll(struct value_node *parent);</span><br><span>diff --git a/src/osysmon_main.c b/src/osysmon_main.c</span><br><span>index eb4f50b..6d72786 100644</span><br><span>--- a/src/osysmon_main.c</span><br><span>+++ b/src/osysmon_main.c</span><br><span>@@ -199,6 +199,7 @@</span><br><span> </span><br><span> g_oss = talloc_zero(NULL, struct osysmon_state);</span><br><span> INIT_LLIST_HEAD(&g_oss->ctrl_clients);</span><br><span style="color: hsl(120, 100%, 40%);">+ INIT_LLIST_HEAD(&g_oss->openvpn_clients);</span><br><span> INIT_LLIST_HEAD(&g_oss->netdevs);</span><br><span> INIT_LLIST_HEAD(&g_oss->files);</span><br><span> </span><br><span>@@ -206,6 +207,7 @@</span><br><span> handle_options(argc, argv);</span><br><span> osysmon_sysinfo_init();</span><br><span> osysmon_ctrl_init();</span><br><span style="color: hsl(120, 100%, 40%);">+ osysmon_openvpn_init();</span><br><span> osysmon_rtnl_init();</span><br><span> ping_init = osysmon_ping_init();</span><br><span> osysmon_file_init();</span><br><span>@@ -239,9 +241,11 @@</span><br><span> osysmon_ping_poll(root);</span><br><span> </span><br><span> osysmon_file_poll(root);</span><br><span style="color: hsl(120, 100%, 40%);">+ osysmon_openvpn_poll(root);</span><br><span> </span><br><span> display_update(root);</span><br><span> value_node_del(root);</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_select_main(0);</span><br><span> sleep(1);</span><br><span> }</span><br><span> </span><br><span>diff --git a/src/osysmon_openvpn.c b/src/osysmon_openvpn.c</span><br><span>new file mode 100644</span><br><span>index 0000000..6edb143</span><br><span>--- /dev/null</span><br><span>+++ b/src/osysmon_openvpn.c</span><br><span>@@ -0,0 +1,295 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/* Simple Osmocom System Monitor (osysmon): Support for OpenVPN monitoring */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* (C) 2019 by sysmocom - s.f.m.c. GmbH.</span><br><span style="color: hsl(120, 100%, 40%);">+ * Author: Max Suraev</span><br><span style="color: hsl(120, 100%, 40%);">+ * All Rights Reserved.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * SPDX-License-Identifier: GPL-2.0+</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or modify</span><br><span style="color: hsl(120, 100%, 40%);">+ * it under the terms of the GNU General Public License as published by</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Free Software Foundation; either version 2 of the License, or</span><br><span style="color: hsl(120, 100%, 40%);">+ * (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * You should have received a copy of the GNU General Public License</span><br><span style="color: hsl(120, 100%, 40%);">+ * along with this program; if not, write to the Free Software</span><br><span style="color: hsl(120, 100%, 40%);">+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,</span><br><span style="color: hsl(120, 100%, 40%);">+ * MA 02110-1301, USA.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <string.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdbool.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <ctype.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <errno.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/utils.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/vty/vty.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/vty/command.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/msgb.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/netif/stream.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include "osysmon.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "client.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "value_node.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/***********************************************************************</span><br><span style="color: hsl(120, 100%, 40%);">+ * Data model</span><br><span style="color: hsl(120, 100%, 40%);">+ ***********************************************************************/</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* max number of csv in response */</span><br><span style="color: hsl(120, 100%, 40%);">+#define MAX_RESP_COMPONENTS 6</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* a single OpenVPN management interface client */</span><br><span style="color: hsl(120, 100%, 40%);">+struct openvpn_client {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* links to osysmon.openvpn_clients */</span><br><span style="color: hsl(120, 100%, 40%);">+ struct llist_head list;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct host_cfg *cfg;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct osmo_stream_cli *mgmt;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* fields below are parsed from response to 'state' command on mgmt interface */</span><br><span style="color: hsl(120, 100%, 40%);">+ struct host_cfg *rem_cfg;</span><br><span style="color: hsl(120, 100%, 40%);">+ char *tun_ip;</span><br><span style="color: hsl(120, 100%, 40%);">+ bool connected;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static char *parse_state(const struct msgb *msg, struct openvpn_client *vpn)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ char tmp[128];</span><br><span style="color: hsl(120, 100%, 40%);">+ char *tok;</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned int i = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t *m = msgb_data(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (msgb_length(msg) > 128)</span><br><span style="color: hsl(120, 100%, 40%);">+ fprintf(stderr, "[%s] received message too long (%d > %u), truncating...\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ get_authority(NULL, vpn->cfg), msgb_length(msg), 128);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (msgb_length(msg) > 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!isdigit(m[0])) /* skip OpenVPN greetings and alike */</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ fprintf(stderr, "[%s] received message is empty, ignoring...\n", get_authority(NULL, vpn->cfg));</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ memcpy(tmp, m, OSMO_MIN(sizeof(tmp) - 1, msgb_length(msg)));</span><br><span style="color: hsl(120, 100%, 40%);">+ tmp[sizeof(tmp) - 1] = '\0';</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ for (tok = strtok(tmp, ","); tok && i < MAX_RESP_COMPONENTS; tok = strtok(NULL, ",")) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (tok)</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case 1:</span><br><span style="color: hsl(120, 100%, 40%);">+ update_name(vpn->rem_cfg, tok);</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case 3:</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_talloc_replace_string(vpn->rem_cfg, &vpn->tun_ip, tok);</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case 4:</span><br><span style="color: hsl(120, 100%, 40%);">+ update_host(vpn->rem_cfg, tok);</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case 5:</span><br><span style="color: hsl(120, 100%, 40%);">+ vpn->rem_cfg->remote_port = atoi(tok);</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static struct openvpn_client *openvpn_client_find(const struct osysmon_state *os, const char *host, uint16_t port)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct openvpn_client *vpn;</span><br><span style="color: hsl(120, 100%, 40%);">+ llist_for_each_entry(vpn, &os->openvpn_clients, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (match_config(vpn->cfg, host, MATCH_HOST) && vpn->cfg->remote_port == port)</span><br><span style="color: hsl(120, 100%, 40%);">+ return vpn;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int connect_cb(struct osmo_stream_cli *conn)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct openvpn_client *vpn = osmo_stream_cli_get_data(conn);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ update_name(vpn->rem_cfg, "management interface incompatible");</span><br><span style="color: hsl(120, 100%, 40%);">+ vpn->connected = true; /* FIXME: there's no callback for lost connection to drop this flag */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int read_cb(struct osmo_stream_cli *conn)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ int bytes;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct openvpn_client *vpn = osmo_stream_cli_get_data(conn);</span><br><span style="color: hsl(120, 100%, 40%);">+ struct msgb *msg = msgb_alloc(1024, "OpenVPN");</span><br><span style="color: hsl(120, 100%, 40%);">+ if (msg == NULL) {</span><br><span style="color: hsl(120, 100%, 40%);">+ fprintf(stderr, "[%s] unable to allocate message in callback\n", get_authority(NULL, vpn->cfg));</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ bytes = osmo_stream_cli_recv(conn, msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (bytes < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ fprintf(stderr, "[%s] unable to receive message in callback\n", get_authority(NULL, vpn->cfg));</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ parse_state(msg, vpn);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_free(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static bool openvpn_client_create(struct osysmon_state *os, const char *name, const char *host, uint16_t port)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct openvpn_client *vpn = openvpn_client_find(os, host, port);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (vpn)</span><br><span style="color: hsl(120, 100%, 40%);">+ return true;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ vpn = talloc_zero(os, struct openvpn_client);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!vpn)</span><br><span style="color: hsl(120, 100%, 40%);">+ return false;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ vpn->connected = false;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ vpn->cfg = make_config(vpn, name, host, port);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!vpn->cfg) {</span><br><span style="color: hsl(120, 100%, 40%);">+ talloc_free(vpn);</span><br><span style="color: hsl(120, 100%, 40%);">+ return false;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ vpn->rem_cfg = make_config(vpn, "management interface unavailable", NULL, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!vpn->cfg) {</span><br><span style="color: hsl(120, 100%, 40%);">+ talloc_free(vpn);</span><br><span style="color: hsl(120, 100%, 40%);">+ return false;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ vpn->mgmt = make_tcp_client(vpn->cfg);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!vpn->mgmt)</span><br><span style="color: hsl(120, 100%, 40%);">+ {//FIXME: log error via same macro as ctrl client?</span><br><span style="color: hsl(120, 100%, 40%);">+ talloc_free(vpn);</span><br><span style="color: hsl(120, 100%, 40%);">+ fprintf(stderr, "OpenVPN: ERROR: failed to create TCP client for %s:%u\n", host, port);</span><br><span style="color: hsl(120, 100%, 40%);">+ return false;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Wait for 1 minute before attempting to reconnect to management interface */</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_stream_cli_set_reconnect_timeout(vpn->mgmt, 60); /* FIXME: this seems to be ignored by libosmo-netif */</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_stream_cli_set_read_cb(vpn->mgmt, read_cb);</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_stream_cli_set_connect_cb(vpn->mgmt, connect_cb);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (osmo_stream_cli_open(vpn->mgmt) < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ fprintf(stderr, "OpenVPN: ERROR: failed to connect to %s:%u\n", host, port);</span><br><span style="color: hsl(120, 100%, 40%);">+ talloc_free(vpn);</span><br><span style="color: hsl(120, 100%, 40%);">+ return false;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_stream_cli_set_data(vpn->mgmt, vpn);</span><br><span style="color: hsl(120, 100%, 40%);">+ llist_add_tail(&vpn->list, &os->openvpn_clients);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return true;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void openvpn_client_destroy(struct openvpn_client *vpn)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!vpn)</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_stream_cli_destroy(vpn->mgmt);</span><br><span style="color: hsl(120, 100%, 40%);">+ llist_del(&vpn->list);</span><br><span style="color: hsl(120, 100%, 40%);">+ talloc_free(vpn);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/***********************************************************************</span><br><span style="color: hsl(120, 100%, 40%);">+ * VTY</span><br><span style="color: hsl(120, 100%, 40%);">+ ***********************************************************************/</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define OPENVPN_STR "Configure OpenVPN management interface address\n"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+DEFUN(cfg_openvpn, cfg_openvpn_cmd,</span><br><span style="color: hsl(120, 100%, 40%);">+ "openvpn HOST <1-65535>",</span><br><span style="color: hsl(120, 100%, 40%);">+ OPENVPN_STR "Name of the host to connect to\n" "Management interface port\n")</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ uint16_t port = atoi(argv[1]);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!openvpn_client_create(g_oss, "OpenVPN", argv[0], port)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ vty_out(vty, "Failed to create OpenVPN client for %s:%u%s", argv[0], port, VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+ return CMD_WARNING;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return CMD_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+DEFUN(cfg_no_openvpn, cfg_no_openvpn_cmd,</span><br><span style="color: hsl(120, 100%, 40%);">+ "no openvpn HOST <1-65535>",</span><br><span style="color: hsl(120, 100%, 40%);">+ NO_STR OPENVPN_STR "Name of the host to connect to\n" "Management interface port\n")</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ uint16_t port = atoi(argv[1]);</span><br><span style="color: hsl(120, 100%, 40%);">+ struct openvpn_client *vpn = openvpn_client_find(g_oss, argv[0], port);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!vpn) {</span><br><span style="color: hsl(120, 100%, 40%);">+ vty_out(vty, "OpenVPN client %s:%u doesn't exist%s", argv[0], port, VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+ return CMD_WARNING;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ openvpn_client_destroy(vpn);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return CMD_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/***********************************************************************</span><br><span style="color: hsl(120, 100%, 40%);">+ * Runtime Code</span><br><span style="color: hsl(120, 100%, 40%);">+ ***********************************************************************/</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int openvpn_client_poll(struct openvpn_client *vpn, struct value_node *parent)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ char *remote = get_authority(parent, vpn->rem_cfg);</span><br><span style="color: hsl(120, 100%, 40%);">+ struct value_node *vn_host = value_node_find_or_add(parent, get_authority(parent, vpn->cfg));</span><br><span style="color: hsl(120, 100%, 40%);">+ struct msgb *msg = msgb_alloc(128, "state");</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!msg) {</span><br><span style="color: hsl(120, 100%, 40%);">+ value_node_add(vn_host, "msgb", "memory allocation failure");</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (vpn->rem_cfg->name)</span><br><span style="color: hsl(120, 100%, 40%);">+ value_node_add(vn_host, "status", vpn->rem_cfg->name);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (vpn->tun_ip)</span><br><span style="color: hsl(120, 100%, 40%);">+ value_node_add(vn_host, "tunnel", vpn->tun_ip);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (remote)</span><br><span style="color: hsl(120, 100%, 40%);">+ value_node_add(vn_host, "remote", remote);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* FIXME: there's no way to check client state so this might be triggered even while it's reconnecting */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (vpn->connected) { /* re-trigger state command */</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_printf(msg, "state\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_stream_cli_send(vpn->mgmt, msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* called once on startup before config file parsing */</span><br><span style="color: hsl(120, 100%, 40%);">+int osysmon_openvpn_init()</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ install_element(CONFIG_NODE, &cfg_openvpn_cmd);</span><br><span style="color: hsl(120, 100%, 40%);">+ install_element(CONFIG_NODE, &cfg_no_openvpn_cmd);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* called periodically */</span><br><span style="color: hsl(120, 100%, 40%);">+int osysmon_openvpn_poll(struct value_node *parent)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct value_node *vn_vpn;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (llist_count(&g_oss->openvpn_clients)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct openvpn_client *vpn;</span><br><span style="color: hsl(120, 100%, 40%);">+ vn_vpn = value_node_add(parent, "OpenVPN", NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ llist_for_each_entry(vpn, &g_oss->openvpn_clients, list)</span><br><span style="color: hsl(120, 100%, 40%);">+ openvpn_client_poll(vpn, vn_vpn);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/12763">change 12763</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/12763"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: osmo-sysmon </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: I4493e19b9a09dcebd289457eacd1719f7f8cc31c </div>
<div style="display:none"> Gerrit-Change-Number: 12763 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Max <msuraev@sysmocom.de> </div>