]> git.ipfire.org Git - thirdparty/openvpn.git/commitdiff
Extended Management Interface "bytecount" command
authorjames <james@e7ae566f-a301-0410-adde-c780ea21d3b5>
Fri, 24 Oct 2008 09:21:40 +0000 (09:21 +0000)
committerjames <james@e7ae566f-a301-0410-adde-c780ea21d3b5>
Fri, 24 Oct 2008 09:21:40 +0000 (09:21 +0000)
to work when OpenVPN is running as a server.

Documented Management Interface "bytecount" command in
management/management-notes.txt.

git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@3452 e7ae566f-a301-0410-adde-c780ea21d3b5

forward.c
manage.c
manage.h
management/management-notes.txt
multi.c

index beec09d83ba33870c765c9cbb8ec5986e8260277..fd1b8cfbae8cdcb64d7a7031095d72df1d345723 100644 (file)
--- 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
            }
        }
index 129e19eaea4649c60337af897553a67a584811dc..a1de02715b226140018774aa7925dcbbbe8551fc 100644 (file)
--- 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)
 {
index 7dd4e1ded773a07f9dbc6d312b5ada4cd971c746..e8ae93b31845f84cd679261c9913a95a1ce2c321 100644 (file)
--- 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
index 4d8611145f9c4e3c7ac2b8a6b69bd3d1aa2dfd6c..5327338dc2f47eb815b6bcc856598b2231be0d22 100644 (file)
@@ -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 e19101f54c0191305e64c2784247935a33efd23c..4898b44d3c7a2282bd0391cbf444d6297500fd55 100644 (file)
--- a/multi.c
+++ b/multi.c
@@ -436,6 +436,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;