summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Yonan <james@openvpn.net>2011-10-18 08:12:51 +0000
committerDavid Sommerseth <davids@redhat.com>2011-12-14 17:03:24 +0100
commitffea644ce62a67ea06e375c17277cea4e9cb9873 (patch)
treef9d897b7b3b6d54474d846de9a54ffc1b1c7cc60
parent359adbf136e07011ad6733c3ba679b2d5cc47fdc (diff)
downloadopenvpn-ffea644ce62a67ea06e375c17277cea4e9cb9873.tar.gz
openvpn-ffea644ce62a67ea06e375c17277cea4e9cb9873.tar.xz
openvpn-ffea644ce62a67ea06e375c17277cea4e9cb9873.zip
Added "memstats" option to maintain real-time operating stats
in a memory-mapped file. Version 2.1.16 git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@7653 e7ae566f-a301-0410-adde-c780ea21d3b5
-rw-r--r--Makefile.am1
-rw-r--r--error.c5
-rw-r--r--forward.c9
-rw-r--r--init.c22
-rw-r--r--mstats.c116
-rw-r--r--mstats.h51
-rw-r--r--multi.c12
-rw-r--r--options.c10
-rw-r--r--options.h4
-rw-r--r--syshead.h7
10 files changed, 237 insertions, 0 deletions
diff --git a/Makefile.am b/Makefile.am
index 075270f..a47c0c1 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -110,6 +110,7 @@ openvpn_SOURCES = \
misc.c misc.h \
mroute.c mroute.h \
mss.c mss.h \
+ mstats.c mstats.h \
mtcp.c mtcp.h \
mtu.c mtu.h \
mudp.c mudp.h \
diff --git a/error.c b/error.c
index a0de53e..06b383f 100644
--- a/error.c
+++ b/error.c
@@ -35,6 +35,7 @@
#include "status.h"
#include "integer.h"
#include "ps.h"
+#include "mstats.h"
#ifdef USE_CRYPTO
#ifdef USE_OPENSSL
@@ -679,6 +680,10 @@ openvpn_exit (const int status)
port_share_abort (port_share);
#endif
+#ifdef ENABLE_MEMSTATS
+ mstats_close();
+#endif
+
#ifdef ABORT_ON_ERROR
if (status == OPENVPN_EXIT_STATUS_ERROR)
abort ();
diff --git a/forward.c b/forward.c
index 4592cfc..c66031f 100644
--- a/forward.c
+++ b/forward.c
@@ -39,6 +39,7 @@
#include "forward-inline.h"
#include "occ-inline.h"
#include "ping-inline.h"
+#include "mstats.h"
counter_type link_read_bytes_global; /* GLOBAL */
counter_type link_write_bytes_global; /* GLOBAL */
@@ -738,6 +739,10 @@ process_incoming_link (struct context *c)
{
c->c2.link_read_bytes += c->c2.buf.len;
link_read_bytes_global += c->c2.buf.len;
+#ifdef ENABLE_MEMSTATS
+ if (mmap_stats)
+ mmap_stats->link_read_bytes = link_read_bytes_global;
+#endif
c->c2.original_recv_size = c->c2.buf.len;
#ifdef ENABLE_MANAGEMENT
if (management)
@@ -1137,6 +1142,10 @@ process_outgoing_link (struct context *c)
c->c2.max_send_size_local = max_int (size, c->c2.max_send_size_local);
c->c2.link_write_bytes += size;
link_write_bytes_global += size;
+#ifdef ENABLE_MEMSTATS
+ if (mmap_stats)
+ mmap_stats->link_write_bytes = link_write_bytes_global;
+#endif
#ifdef ENABLE_MANAGEMENT
if (management)
{
diff --git a/init.c b/init.c
index 82c1000..a225c26 100644
--- a/init.c
+++ b/init.c
@@ -36,6 +36,7 @@
#include "ps.h"
#include "lladdr.h"
#include "ping.h"
+#include "mstats.h"
#include "memdbg.h"
@@ -815,6 +816,22 @@ init_static (void)
}
#endif
+#ifdef MSTATS_TEST
+ {
+ int i;
+ mstats_open("/dev/shm/mstats.dat");
+ for (i = 0; i < 30; ++i)
+ {
+ mmap_stats->n_clients += 1;
+ mmap_stats->link_write_bytes += 8;
+ mmap_stats->link_read_bytes += 16;
+ sleep(1);
+ }
+ mstats_close();
+ return false;
+ }
+#endif
+
return true;
}
@@ -1014,6 +1031,11 @@ do_uid_gid_chroot (struct context *c, bool no_delay)
msg (M_INFO, "NOTE: UID/GID downgrade %s", why_not);
}
+#ifdef ENABLE_MEMSTATS
+ if (c->options.memstats_fn)
+ mstats_open(c->options.memstats_fn);
+#endif
+
#ifdef HAVE_SETCON
/* Apply a SELinux context in order to restrict what OpenVPN can do
* to _only_ what it is supposed to do after initialization is complete
diff --git a/mstats.c b/mstats.c
new file mode 100644
index 0000000..2f29d94
--- /dev/null
+++ b/mstats.c
@@ -0,0 +1,116 @@
+/*
+ * OpenVPN -- An application to securely tunnel IP networks
+ * over a single TCP/UDP port, with support for SSL/TLS-based
+ * session authentication and key exchange,
+ * packet encryption, packet authentication, and
+ * packet compression.
+ *
+ * Copyright (C) 2002-2011 OpenVPN Technologies, Inc. <sales@openvpn.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program (see the file COPYING included with this
+ * distribution); if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*
+ * Maintain usage stats in a memory-mapped file
+ */
+
+#include "syshead.h"
+
+#if defined(ENABLE_MEMSTATS)
+
+#include <sys/mman.h>
+
+#include "error.h"
+#include "misc.h"
+#include "mstats.h"
+
+#include "memdbg.h"
+
+volatile struct mmap_stats *mmap_stats = NULL; /* GLOBAL */
+static char mmap_fn[128];
+
+void
+mstats_open(const char *fn)
+{
+ void *data;
+ ssize_t stat;
+ int fd;
+ struct mmap_stats ms;
+
+ if (mmap_stats) /* already called? */
+ return;
+
+ /* verify that filename is not too long */
+ if (strlen(fn) >= sizeof(mmap_fn))
+ msg (M_FATAL, "mstats_open: filename too long");
+
+ /* create file that will be memory mapped */
+ fd = open (fn, O_CREAT | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
+ if (fd < 0)
+ {
+ msg (M_ERR, "mstats_open: cannot open: %s", fn);
+ return;
+ }
+
+ /* set the file to the correct size to contain a
+ struct mmap_stats, and zero it */
+ CLEAR(ms);
+ ms.state = MSTATS_ACTIVE;
+ stat = write(fd, &ms, sizeof(ms));
+ if (stat != sizeof(ms))
+ {
+ msg (M_ERR, "mstats_open: write error: %s", fn);
+ close(fd);
+ return;
+ }
+
+ /* mmap the file */
+ data = mmap(NULL, sizeof(struct mmap_stats), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+ if (data == MAP_FAILED)
+ {
+ msg (M_ERR, "mstats_open: write error: %s", fn);
+ close(fd);
+ return;
+ }
+
+ /* close the fd (mmap now controls the file) */
+ if (close(fd))
+ {
+ msg (M_ERR, "mstats_open: close error: %s", fn);
+ }
+
+ /* save filename so we can delete it later */
+ strcpy(mmap_fn, fn);
+
+ /* save a global pointer to memory-mapped region */
+ mmap_stats = (struct mmap_stats *)data;
+
+ msg (M_INFO, "memstats data will be written to %s", fn);
+}
+
+void
+mstats_close(void)
+{
+ if (mmap_stats)
+ {
+ mmap_stats->state = MSTATS_EXPIRED;
+ if (munmap((void *)mmap_stats, sizeof(struct mmap_stats)))
+ msg (M_WARN | M_ERRNO, "mstats_close: munmap error");
+ delete_file(mmap_fn);
+ mmap_stats = NULL;
+ }
+}
+
+#endif
diff --git a/mstats.h b/mstats.h
new file mode 100644
index 0000000..dab05fe
--- /dev/null
+++ b/mstats.h
@@ -0,0 +1,51 @@
+/*
+ * OpenVPN -- An application to securely tunnel IP networks
+ * over a single TCP/UDP port, with support for SSL/TLS-based
+ * session authentication and key exchange,
+ * packet encryption, packet authentication, and
+ * packet compression.
+ *
+ * Copyright (C) 2002-2011 OpenVPN Technologies, Inc. <sales@openvpn.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program (see the file COPYING included with this
+ * distribution); if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*
+ * Maintain usage stats in a memory-mapped file
+ */
+
+#if !defined(OPENVPN_MEMSTATS_H) && defined(ENABLE_MEMSTATS)
+#define OPENVPN_MEMSTATS_H
+
+#include "basic.h"
+
+/* this struct is mapped to the file */
+struct mmap_stats {
+ counter_type link_read_bytes; /* counter_type can be assumed to be a uint64_t */
+ counter_type link_write_bytes;
+ int n_clients;
+
+# define MSTATS_UNDEF 0
+# define MSTATS_ACTIVE 1
+# define MSTATS_EXPIRED 2
+ int state;
+};
+
+extern volatile struct mmap_stats *mmap_stats; /* GLOBAL */
+
+void mstats_open(const char *fn);
+void mstats_close(void);
+
+#endif
diff --git a/multi.c b/multi.c
index 81931fa..9535f43 100644
--- a/multi.c
+++ b/multi.c
@@ -31,6 +31,7 @@
#include "misc.h"
#include "otime.h"
#include "gremlin.h"
+#include "mstats.h"
#include "memdbg.h"
@@ -60,6 +61,15 @@ set_cc_config (struct multi_instance *mi, struct buffer_list *cc_config)
}
#endif
+static inline void
+update_mstat_n_clients(const int n_clients)
+{
+#ifdef ENABLE_MEMSTATS
+ if (mmap_stats)
+ mmap_stats->n_clients = n_clients;
+#endif
+}
+
static bool
learn_address_script (const struct multi_context *m,
const struct multi_instance *mi,
@@ -510,6 +520,7 @@ multi_close_instance (struct multi_context *m,
/* adjust current client connection count */
m->n_clients += mi->n_clients_delta;
+ update_mstat_n_clients(m->n_clients);
mi->n_clients_delta = 0;
/* prevent dangling pointers */
@@ -1842,6 +1853,7 @@ multi_connection_established (struct multi_context *m, struct multi_instance *mi
/* increment number of current authenticated clients */
++m->n_clients;
+ update_mstat_n_clients(m->n_clients);
--mi->n_clients_delta;
#ifdef MANAGEMENT_DEF_AUTH
diff --git a/options.c b/options.c
index 3a819c9..27193ff 100644
--- a/options.c
+++ b/options.c
@@ -299,6 +299,9 @@ static const char usage_message[] =
" can be matched in policy routing and packetfilter rules.\n"
#endif
"--txqueuelen n : Set the tun/tap TX queue length to n (Linux only).\n"
+#ifdef ENABLE_MEMSTATS
+ "--memstats file : Write live usage stats to memory mapped binary file.\n"
+#endif
"--mlock : Disable Paging -- ensures key material and tunnel\n"
" data will never be written to disk.\n"
"--up cmd : Shell cmd to execute after successful tun device open.\n"
@@ -4602,6 +4605,13 @@ add_option (struct options *options,
options->log = true;
redirect_stdout_stderr (p[1], true);
}
+#ifdef ENABLE_MEMSTATS
+ else if (streq (p[0], "memstats") && p[1])
+ {
+ VERIFY_PERMISSION (OPT_P_GENERAL);
+ options->memstats_fn = p[1];
+ }
+#endif
else if (streq (p[0], "mlock"))
{
VERIFY_PERMISSION (OPT_P_GENERAL);
diff --git a/options.h b/options.h
index 0f80e70..06c4dcb 100644
--- a/options.h
+++ b/options.h
@@ -260,6 +260,10 @@ struct options
int fragment; /* internal fragmentation size */
+#ifdef ENABLE_MEMSTATS
+ char *memstats_fn;
+#endif
+
bool mlock;
int keepalive_ping; /* a proxy for ping/ping-restart */
diff --git a/syshead.h b/syshead.h
index f3c0ac9..38de87b 100644
--- a/syshead.h
+++ b/syshead.h
@@ -737,4 +737,11 @@ socket_defined (const socket_descriptor_t sd)
#define LZO_VERSION_NUM "STUB"
#endif
+/*
+ * Enable --memstats option
+ */
+#ifdef TARGET_LINUX
+#define ENABLE_MEMSTATS
+#endif
+
#endif