aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--forward.c16
-rw-r--r--manage.c27
-rw-r--r--manage.h56
-rw-r--r--management/management-notes.txt72
-rw-r--r--multi.c11
5 files changed, 153 insertions, 29 deletions
diff --git a/forward.c b/forward.c
index beec09d..fd1b8cf 100644
--- a/forward.c
+++ b/forward.c
@@ -707,12 +707,17 @@ process_incoming_link (struct context *c)
c->c2.original_recv_size = c->c2.buf.len;
#ifdef ENABLE_MANAGEMENT
if (management)
- management_bytes_in (management, c->c2.buf.len);
+ {
+ management_bytes_in (management, c->c2.buf.len);
+#ifdef MANAGEMENT_DEF_AUTH
+ management_bytes_server (management, &c->c2.link_read_bytes, &c->c2.link_write_bytes, &c->c2.mda_context);
+#endif
+ }
#endif
}
else
c->c2.original_recv_size = 0;
-
+
#ifdef ENABLE_DEBUG
/* take action to corrupt packet if we are in gremlin test mode */
if (c->options.gremlin) {
@@ -1100,7 +1105,12 @@ process_outgoing_link (struct context *c)
c->c2.link_write_bytes += size;
#ifdef ENABLE_MANAGEMENT
if (management)
- management_bytes_out (management, size);
+ {
+ management_bytes_out (management, size);
+#ifdef MANAGEMENT_DEF_AUTH
+ management_bytes_server (management, &c->c2.link_read_bytes, &c->c2.link_write_bytes, &c->c2.mda_context);
+#endif
+ }
#endif
}
}
diff --git a/manage.c b/manage.c
index 129e19e..a1de027 100644
--- a/manage.c
+++ b/manage.c
@@ -367,11 +367,15 @@ man_status (struct management *man, const int version, struct status_output *so)
static void
man_bytecount (struct management *man, const int update_seconds)
{
- man->connection.bytecount_update_seconds = update_seconds;
+ if (update_seconds >= 0)
+ man->connection.bytecount_update_seconds = update_seconds;
+ else
+ man->connection.bytecount_update_seconds = 0;
+ msg (M_CLIENT, "SUCCESS: bytecount interval changed");
}
void
-man_bytecount_output (struct management *man)
+man_bytecount_output_client (struct management *man)
{
char in[32];
char out[32];
@@ -382,6 +386,25 @@ man_bytecount_output (struct management *man)
man->connection.bytecount_last_update = now;
}
+#ifdef MANAGEMENT_DEF_AUTH
+
+void
+man_bytecount_output_server (struct management *man,
+ const counter_type *bytes_in_total,
+ const counter_type *bytes_out_total,
+ struct man_def_auth_context *mdac)
+{
+ char in[32];
+ char out[32];
+ /* do in a roundabout way to work around possible mingw or mingw-glibc bug */
+ openvpn_snprintf (in, sizeof (in), counter_format, *bytes_in_total);
+ openvpn_snprintf (out, sizeof (out), counter_format, *bytes_out_total);
+ msg (M_CLIENT, ">BYTECOUNT_CLI:%lu,%s,%s", mdac->cid, in, out);
+ mdac->bytecount_last_update = now;
+}
+
+#endif
+
static void
man_kill (struct management *man, const char *victim)
{
diff --git a/manage.h b/manage.h
index 7dd4e1d..e8ae93b 100644
--- a/manage.h
+++ b/manage.h
@@ -51,6 +51,8 @@ struct man_def_auth_context {
unsigned int flags;
unsigned int mda_key_id_counter;
+
+ time_t bytecount_last_update;
};
#endif
@@ -143,6 +145,10 @@ log_history_capacity (const struct log_history *h)
struct management_callback
{
void *arg;
+
+# define MCF_SERVER (1<<0) /* is OpenVPN being run as a server? */
+ unsigned int flags;
+
void (*status) (void *arg, const int version, struct status_output *so);
void (*show_net) (void *arg, const int msglevel);
int (*kill_by_cn) (void *arg, const char *common_name);
@@ -432,31 +438,65 @@ void management_auth_failure (struct management *man, const char *type);
* These functions drive the bytecount in/out counters.
*/
-void man_bytecount_output (struct management *man);
+void man_bytecount_output_client (struct management *man);
static inline void
-man_bytecount_possible_output (struct management *man)
+man_bytecount_possible_output_client (struct management *man)
{
if (man->connection.bytecount_update_seconds > 0
&& now >= man->connection.bytecount_last_update
+ man->connection.bytecount_update_seconds)
- man_bytecount_output (man);
+ man_bytecount_output_client (man);
}
static inline void
-management_bytes_out (struct management *man, const int size)
+management_bytes_out_client (struct management *man, const int size)
{
man->persist.bytes_out += size;
- man_bytecount_possible_output (man);
+ man_bytecount_possible_output_client (man);
}
static inline void
-management_bytes_in (struct management *man, const int size)
+management_bytes_in_client (struct management *man, const int size)
{
man->persist.bytes_in += size;
- man_bytecount_possible_output (man);
+ man_bytecount_possible_output_client (man);
}
-#endif
+static inline void
+management_bytes_out (struct management *man, const int size)
+{
+ if (!(man->persist.callback.flags & MCF_SERVER))
+ management_bytes_out_client (man, size);
+}
+static inline void
+management_bytes_in (struct management *man, const int size)
+{
+ if (!(man->persist.callback.flags & MCF_SERVER))
+ management_bytes_in_client (man, size);
+}
+
+#ifdef MANAGEMENT_DEF_AUTH
+
+static inline void
+management_bytes_server (struct management *man,
+ const counter_type *bytes_in_total,
+ const counter_type *bytes_out_total,
+ struct man_def_auth_context *mdac)
+{
+ void man_bytecount_output_server (struct management *man,
+ const counter_type *bytes_in_total,
+ const counter_type *bytes_out_total,
+ struct man_def_auth_context *mdac);
+
+ if (man->connection.bytecount_update_seconds > 0
+ && now >= mdac->bytecount_last_update + man->connection.bytecount_update_seconds
+ && (mdac->flags & (DAF_CONNECTION_ESTABLISHED|DAF_CONNECTION_CLOSED)) == DAF_CONNECTION_ESTABLISHED)
+ man_bytecount_output_server (man, bytes_in_total, bytes_out_total, mdac);
+}
+
+#endif /* MANAGEMENT_DEF_AUTH */
+
+#endif
#endif
diff --git a/management/management-notes.txt b/management/management-notes.txt
index 4d86111..5327338 100644
--- a/management/management-notes.txt
+++ b/management/management-notes.txt
@@ -3,26 +3,24 @@ OpenVPN Management Interface Notes
The OpenVPN Management interface allows OpenVPN to
be administratively controlled from an external program via
-a TCP socket.
+a TCP or unix domain socket.
-The interface has been specifically designed for GUI developers
-and those who would like to programmatically or remotely control
-an OpenVPN daemon.
+The interface has been specifically designed for developers
+who would like to programmatically or remotely control
+an OpenVPN daemon, and can be used when OpenVPN is running
+as a client or server.
The management interface is implemented using a client/server TCP
-connection, where OpenVPN will listen on a provided IP address
-and port for incoming management client connections.
+connection or unix domain socket where OpenVPN will listen on a
+provided IP address and port for incoming management client connections.
The management protocol is currently cleartext without an explicit
security layer. For this reason, it is recommended that the
-management interface either listen on localhost (127.0.0.1)
-or on the local VPN address. It's possible to remotely connect
-to the management interface over the VPN itself, though some
-capabilities will be limited in this mode, such as the ability
-to provide private key passwords.
-
-Future versions of the management interface may allow out-of-band
-connections (i.e. not over the VPN) and secured with SSL/TLS.
+management interface either listen on a unix domain socket,
+localhost (127.0.0.1), or on the local VPN address. It's possible
+to remotely connect to the management interface over the VPN itself,
+though some capabilities will be limited in this mode, such as the
+ability to provide private key passwords.
The management interface is enabled in the OpenVPN
configuration file using the following directive:
@@ -39,6 +37,44 @@ a telnet client which understands "raw" mode).
Once connected to the management port, you can use
the "help" command to list all commands.
+COMMAND -- bytecount
+--------------------
+
+The bytecount command is used to request real-time notification
+of OpenVPN bandwidth usage.
+
+Command syntax:
+
+ bytecount n (where n > 0) -- set up automatic notification of
+ bandwidth usage once every n seconds
+ bytecount 0 -- turn off bytecount notifications
+
+If OpenVPN is running as a client, the bytecount notification
+will look like this:
+
+ >BYTECOUNT:{BYTES_IN},{BYTES_OUT}
+
+BYTES_IN is the number of bytes that have been received from
+the server and BYTES_OUT is the number of bytes that have been
+sent to the server.
+
+If OpenVPN is running as a server, the bytecount notification
+will look like this:
+
+ >BYTECOUNT_CLI:{CID},{BYTES_IN},{BYTES_OUT}
+
+CID is the Client ID, BYTES_IN is the number of bytes that have
+been received from the client and BYTES_OUT is the number of
+bytes that have been sent to the client.
+
+Note that when the bytecount command is used on the server, every
+connected client will report its bandwidth numbers once every n
+seconds.
+
+When the client disconnects, the final bandwidth numbers will be
+placed in the 'bytes_received' and 'bytes_sent' environmental variables
+as included in the >CLIENT:DISCONNECT notification.
+
COMMAND -- echo
---------------
@@ -661,6 +697,14 @@ column and are immediately followed by a type keyword
indicating the type of real-time message. The following
types are currently defined:
+BYTECOUNT -- Real-time bandwidth usage notification, as enabled
+ by "bytecount" command when OpenVPN is running as
+ a client.
+
+BYTECOUNT_CLI -- Real-time bandwidth usage notification per-client,
+ as enabled by "bytecount" command when OpenVPN is
+ running as a server.
+
CLIENT -- Notification of client connections and disconnections
on an OpenVPN server. Enabled when OpenVPN is started
with the --management-client-auth option. CLIENT
diff --git a/multi.c b/multi.c
index e19101f..4898b44 100644
--- a/multi.c
+++ b/multi.c
@@ -437,6 +437,13 @@ multi_del_iroutes (struct multi_context *m,
}
static void
+setenv_stats (struct context *c)
+{
+ setenv_counter (c->c2.es, "bytes_received", c->c2.link_read_bytes);
+ setenv_counter (c->c2.es, "bytes_sent", c->c2.link_write_bytes);
+}
+
+static void
multi_client_disconnect_setenv (struct multi_context *m,
struct multi_instance *mi)
{
@@ -444,8 +451,7 @@ multi_client_disconnect_setenv (struct multi_context *m,
setenv_trusted (mi->context.c2.es, get_link_socket_info (&mi->context));
/* setenv stats */
- setenv_counter (mi->context.c2.es, "bytes_received", mi->context.c2.link_read_bytes);
- setenv_counter (mi->context.c2.es, "bytes_sent", mi->context.c2.link_write_bytes);
+ setenv_stats (&mi->context);
/* setenv connection duration */
{
@@ -2583,6 +2589,7 @@ init_management_callback_multi (struct multi_context *m)
struct management_callback cb;
CLEAR (cb);
cb.arg = m;
+ cb.flags = MCF_SERVER;
cb.status = management_callback_status;
cb.show_net = management_show_net_callback;
cb.kill_by_cn = management_callback_kill_by_cn;