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
... | ... |
@@ -707,12 +707,17 @@ process_incoming_link (struct context *c) |
707 | 707 |
c->c2.original_recv_size = c->c2.buf.len; |
708 | 708 |
#ifdef ENABLE_MANAGEMENT |
709 | 709 |
if (management) |
710 |
- management_bytes_in (management, c->c2.buf.len); |
|
710 |
+ { |
|
711 |
+ management_bytes_in (management, c->c2.buf.len); |
|
712 |
+#ifdef MANAGEMENT_DEF_AUTH |
|
713 |
+ management_bytes_server (management, &c->c2.link_read_bytes, &c->c2.link_write_bytes, &c->c2.mda_context); |
|
714 |
+#endif |
|
715 |
+ } |
|
711 | 716 |
#endif |
712 | 717 |
} |
713 | 718 |
else |
714 | 719 |
c->c2.original_recv_size = 0; |
715 |
- |
|
720 |
+ |
|
716 | 721 |
#ifdef ENABLE_DEBUG |
717 | 722 |
/* take action to corrupt packet if we are in gremlin test mode */ |
718 | 723 |
if (c->options.gremlin) { |
... | ... |
@@ -1100,7 +1105,12 @@ process_outgoing_link (struct context *c) |
1100 | 1100 |
c->c2.link_write_bytes += size; |
1101 | 1101 |
#ifdef ENABLE_MANAGEMENT |
1102 | 1102 |
if (management) |
1103 |
- management_bytes_out (management, size); |
|
1103 |
+ { |
|
1104 |
+ management_bytes_out (management, size); |
|
1105 |
+#ifdef MANAGEMENT_DEF_AUTH |
|
1106 |
+ management_bytes_server (management, &c->c2.link_read_bytes, &c->c2.link_write_bytes, &c->c2.mda_context); |
|
1107 |
+#endif |
|
1108 |
+ } |
|
1104 | 1109 |
#endif |
1105 | 1110 |
} |
1106 | 1111 |
} |
... | ... |
@@ -367,11 +367,15 @@ man_status (struct management *man, const int version, struct status_output *so) |
367 | 367 |
static void |
368 | 368 |
man_bytecount (struct management *man, const int update_seconds) |
369 | 369 |
{ |
370 |
- man->connection.bytecount_update_seconds = update_seconds; |
|
370 |
+ if (update_seconds >= 0) |
|
371 |
+ man->connection.bytecount_update_seconds = update_seconds; |
|
372 |
+ else |
|
373 |
+ man->connection.bytecount_update_seconds = 0; |
|
374 |
+ msg (M_CLIENT, "SUCCESS: bytecount interval changed"); |
|
371 | 375 |
} |
372 | 376 |
|
373 | 377 |
void |
374 |
-man_bytecount_output (struct management *man) |
|
378 |
+man_bytecount_output_client (struct management *man) |
|
375 | 379 |
{ |
376 | 380 |
char in[32]; |
377 | 381 |
char out[32]; |
... | ... |
@@ -382,6 +386,25 @@ man_bytecount_output (struct management *man) |
382 | 382 |
man->connection.bytecount_last_update = now; |
383 | 383 |
} |
384 | 384 |
|
385 |
+#ifdef MANAGEMENT_DEF_AUTH |
|
386 |
+ |
|
387 |
+void |
|
388 |
+man_bytecount_output_server (struct management *man, |
|
389 |
+ const counter_type *bytes_in_total, |
|
390 |
+ const counter_type *bytes_out_total, |
|
391 |
+ struct man_def_auth_context *mdac) |
|
392 |
+{ |
|
393 |
+ char in[32]; |
|
394 |
+ char out[32]; |
|
395 |
+ /* do in a roundabout way to work around possible mingw or mingw-glibc bug */ |
|
396 |
+ openvpn_snprintf (in, sizeof (in), counter_format, *bytes_in_total); |
|
397 |
+ openvpn_snprintf (out, sizeof (out), counter_format, *bytes_out_total); |
|
398 |
+ msg (M_CLIENT, ">BYTECOUNT_CLI:%lu,%s,%s", mdac->cid, in, out); |
|
399 |
+ mdac->bytecount_last_update = now; |
|
400 |
+} |
|
401 |
+ |
|
402 |
+#endif |
|
403 |
+ |
|
385 | 404 |
static void |
386 | 405 |
man_kill (struct management *man, const char *victim) |
387 | 406 |
{ |
... | ... |
@@ -51,6 +51,8 @@ struct man_def_auth_context { |
51 | 51 |
unsigned int flags; |
52 | 52 |
|
53 | 53 |
unsigned int mda_key_id_counter; |
54 |
+ |
|
55 |
+ time_t bytecount_last_update; |
|
54 | 56 |
}; |
55 | 57 |
#endif |
56 | 58 |
|
... | ... |
@@ -143,6 +145,10 @@ log_history_capacity (const struct log_history *h) |
143 | 143 |
struct management_callback |
144 | 144 |
{ |
145 | 145 |
void *arg; |
146 |
+ |
|
147 |
+# define MCF_SERVER (1<<0) /* is OpenVPN being run as a server? */ |
|
148 |
+ unsigned int flags; |
|
149 |
+ |
|
146 | 150 |
void (*status) (void *arg, const int version, struct status_output *so); |
147 | 151 |
void (*show_net) (void *arg, const int msglevel); |
148 | 152 |
int (*kill_by_cn) (void *arg, const char *common_name); |
... | ... |
@@ -432,31 +438,65 @@ void management_auth_failure (struct management *man, const char *type); |
432 | 432 |
* These functions drive the bytecount in/out counters. |
433 | 433 |
*/ |
434 | 434 |
|
435 |
-void man_bytecount_output (struct management *man); |
|
435 |
+void man_bytecount_output_client (struct management *man); |
|
436 | 436 |
|
437 | 437 |
static inline void |
438 |
-man_bytecount_possible_output (struct management *man) |
|
438 |
+man_bytecount_possible_output_client (struct management *man) |
|
439 | 439 |
{ |
440 | 440 |
if (man->connection.bytecount_update_seconds > 0 |
441 | 441 |
&& now >= man->connection.bytecount_last_update |
442 | 442 |
+ man->connection.bytecount_update_seconds) |
443 |
- man_bytecount_output (man); |
|
443 |
+ man_bytecount_output_client (man); |
|
444 | 444 |
} |
445 | 445 |
|
446 | 446 |
static inline void |
447 |
-management_bytes_out (struct management *man, const int size) |
|
447 |
+management_bytes_out_client (struct management *man, const int size) |
|
448 | 448 |
{ |
449 | 449 |
man->persist.bytes_out += size; |
450 |
- man_bytecount_possible_output (man); |
|
450 |
+ man_bytecount_possible_output_client (man); |
|
451 | 451 |
} |
452 | 452 |
|
453 | 453 |
static inline void |
454 |
-management_bytes_in (struct management *man, const int size) |
|
454 |
+management_bytes_in_client (struct management *man, const int size) |
|
455 | 455 |
{ |
456 | 456 |
man->persist.bytes_in += size; |
457 |
- man_bytecount_possible_output (man); |
|
457 |
+ man_bytecount_possible_output_client (man); |
|
458 | 458 |
} |
459 | 459 |
|
460 |
-#endif |
|
460 |
+static inline void |
|
461 |
+management_bytes_out (struct management *man, const int size) |
|
462 |
+{ |
|
463 |
+ if (!(man->persist.callback.flags & MCF_SERVER)) |
|
464 |
+ management_bytes_out_client (man, size); |
|
465 |
+} |
|
461 | 466 |
|
467 |
+static inline void |
|
468 |
+management_bytes_in (struct management *man, const int size) |
|
469 |
+{ |
|
470 |
+ if (!(man->persist.callback.flags & MCF_SERVER)) |
|
471 |
+ management_bytes_in_client (man, size); |
|
472 |
+} |
|
473 |
+ |
|
474 |
+#ifdef MANAGEMENT_DEF_AUTH |
|
475 |
+ |
|
476 |
+static inline void |
|
477 |
+management_bytes_server (struct management *man, |
|
478 |
+ const counter_type *bytes_in_total, |
|
479 |
+ const counter_type *bytes_out_total, |
|
480 |
+ struct man_def_auth_context *mdac) |
|
481 |
+{ |
|
482 |
+ void man_bytecount_output_server (struct management *man, |
|
483 |
+ const counter_type *bytes_in_total, |
|
484 |
+ const counter_type *bytes_out_total, |
|
485 |
+ struct man_def_auth_context *mdac); |
|
486 |
+ |
|
487 |
+ if (man->connection.bytecount_update_seconds > 0 |
|
488 |
+ && now >= mdac->bytecount_last_update + man->connection.bytecount_update_seconds |
|
489 |
+ && (mdac->flags & (DAF_CONNECTION_ESTABLISHED|DAF_CONNECTION_CLOSED)) == DAF_CONNECTION_ESTABLISHED) |
|
490 |
+ man_bytecount_output_server (man, bytes_in_total, bytes_out_total, mdac); |
|
491 |
+} |
|
492 |
+ |
|
493 |
+#endif /* MANAGEMENT_DEF_AUTH */ |
|
494 |
+ |
|
495 |
+#endif |
|
462 | 496 |
#endif |
... | ... |
@@ -3,26 +3,24 @@ OpenVPN Management Interface Notes |
3 | 3 |
|
4 | 4 |
The OpenVPN Management interface allows OpenVPN to |
5 | 5 |
be administratively controlled from an external program via |
6 |
-a TCP socket. |
|
6 |
+a TCP or unix domain socket. |
|
7 | 7 |
|
8 |
-The interface has been specifically designed for GUI developers |
|
9 |
-and those who would like to programmatically or remotely control |
|
10 |
-an OpenVPN daemon. |
|
8 |
+The interface has been specifically designed for developers |
|
9 |
+who would like to programmatically or remotely control |
|
10 |
+an OpenVPN daemon, and can be used when OpenVPN is running |
|
11 |
+as a client or server. |
|
11 | 12 |
|
12 | 13 |
The management interface is implemented using a client/server TCP |
13 |
-connection, where OpenVPN will listen on a provided IP address |
|
14 |
-and port for incoming management client connections. |
|
14 |
+connection or unix domain socket where OpenVPN will listen on a |
|
15 |
+provided IP address and port for incoming management client connections. |
|
15 | 16 |
|
16 | 17 |
The management protocol is currently cleartext without an explicit |
17 | 18 |
security layer. For this reason, it is recommended that the |
18 |
-management interface either listen on localhost (127.0.0.1) |
|
19 |
-or on the local VPN address. It's possible to remotely connect |
|
20 |
-to the management interface over the VPN itself, though some |
|
21 |
-capabilities will be limited in this mode, such as the ability |
|
22 |
-to provide private key passwords. |
|
23 |
- |
|
24 |
-Future versions of the management interface may allow out-of-band |
|
25 |
-connections (i.e. not over the VPN) and secured with SSL/TLS. |
|
19 |
+management interface either listen on a unix domain socket, |
|
20 |
+localhost (127.0.0.1), or on the local VPN address. It's possible |
|
21 |
+to remotely connect to the management interface over the VPN itself, |
|
22 |
+though some capabilities will be limited in this mode, such as the |
|
23 |
+ability to provide private key passwords. |
|
26 | 24 |
|
27 | 25 |
The management interface is enabled in the OpenVPN |
28 | 26 |
configuration file using the following directive: |
... | ... |
@@ -39,6 +37,44 @@ a telnet client which understands "raw" mode). |
39 | 39 |
Once connected to the management port, you can use |
40 | 40 |
the "help" command to list all commands. |
41 | 41 |
|
42 |
+COMMAND -- bytecount |
|
43 |
+-------------------- |
|
44 |
+ |
|
45 |
+The bytecount command is used to request real-time notification |
|
46 |
+of OpenVPN bandwidth usage. |
|
47 |
+ |
|
48 |
+Command syntax: |
|
49 |
+ |
|
50 |
+ bytecount n (where n > 0) -- set up automatic notification of |
|
51 |
+ bandwidth usage once every n seconds |
|
52 |
+ bytecount 0 -- turn off bytecount notifications |
|
53 |
+ |
|
54 |
+If OpenVPN is running as a client, the bytecount notification |
|
55 |
+will look like this: |
|
56 |
+ |
|
57 |
+ >BYTECOUNT:{BYTES_IN},{BYTES_OUT} |
|
58 |
+ |
|
59 |
+BYTES_IN is the number of bytes that have been received from |
|
60 |
+the server and BYTES_OUT is the number of bytes that have been |
|
61 |
+sent to the server. |
|
62 |
+ |
|
63 |
+If OpenVPN is running as a server, the bytecount notification |
|
64 |
+will look like this: |
|
65 |
+ |
|
66 |
+ >BYTECOUNT_CLI:{CID},{BYTES_IN},{BYTES_OUT} |
|
67 |
+ |
|
68 |
+CID is the Client ID, BYTES_IN is the number of bytes that have |
|
69 |
+been received from the client and BYTES_OUT is the number of |
|
70 |
+bytes that have been sent to the client. |
|
71 |
+ |
|
72 |
+Note that when the bytecount command is used on the server, every |
|
73 |
+connected client will report its bandwidth numbers once every n |
|
74 |
+seconds. |
|
75 |
+ |
|
76 |
+When the client disconnects, the final bandwidth numbers will be |
|
77 |
+placed in the 'bytes_received' and 'bytes_sent' environmental variables |
|
78 |
+as included in the >CLIENT:DISCONNECT notification. |
|
79 |
+ |
|
42 | 80 |
COMMAND -- echo |
43 | 81 |
--------------- |
44 | 82 |
|
... | ... |
@@ -661,6 +697,14 @@ column and are immediately followed by a type keyword |
661 | 661 |
indicating the type of real-time message. The following |
662 | 662 |
types are currently defined: |
663 | 663 |
|
664 |
+BYTECOUNT -- Real-time bandwidth usage notification, as enabled |
|
665 |
+ by "bytecount" command when OpenVPN is running as |
|
666 |
+ a client. |
|
667 |
+ |
|
668 |
+BYTECOUNT_CLI -- Real-time bandwidth usage notification per-client, |
|
669 |
+ as enabled by "bytecount" command when OpenVPN is |
|
670 |
+ running as a server. |
|
671 |
+ |
|
664 | 672 |
CLIENT -- Notification of client connections and disconnections |
665 | 673 |
on an OpenVPN server. Enabled when OpenVPN is started |
666 | 674 |
with the --management-client-auth option. CLIENT |
... | ... |
@@ -437,6 +437,13 @@ multi_del_iroutes (struct multi_context *m, |
437 | 437 |
} |
438 | 438 |
|
439 | 439 |
static void |
440 |
+setenv_stats (struct context *c) |
|
441 |
+{ |
|
442 |
+ setenv_counter (c->c2.es, "bytes_received", c->c2.link_read_bytes); |
|
443 |
+ setenv_counter (c->c2.es, "bytes_sent", c->c2.link_write_bytes); |
|
444 |
+} |
|
445 |
+ |
|
446 |
+static void |
|
440 | 447 |
multi_client_disconnect_setenv (struct multi_context *m, |
441 | 448 |
struct multi_instance *mi) |
442 | 449 |
{ |
... | ... |
@@ -444,8 +451,7 @@ multi_client_disconnect_setenv (struct multi_context *m, |
444 | 444 |
setenv_trusted (mi->context.c2.es, get_link_socket_info (&mi->context)); |
445 | 445 |
|
446 | 446 |
/* setenv stats */ |
447 |
- setenv_counter (mi->context.c2.es, "bytes_received", mi->context.c2.link_read_bytes); |
|
448 |
- setenv_counter (mi->context.c2.es, "bytes_sent", mi->context.c2.link_write_bytes); |
|
447 |
+ setenv_stats (&mi->context); |
|
449 | 448 |
|
450 | 449 |
/* setenv connection duration */ |
451 | 450 |
{ |
... | ... |
@@ -2583,6 +2589,7 @@ init_management_callback_multi (struct multi_context *m) |
2583 | 2583 |
struct management_callback cb; |
2584 | 2584 |
CLEAR (cb); |
2585 | 2585 |
cb.arg = m; |
2586 |
+ cb.flags = MCF_SERVER; |
|
2586 | 2587 |
cb.status = management_callback_status; |
2587 | 2588 |
cb.show_net = management_show_net_callback; |
2588 | 2589 |
cb.kill_by_cn = management_callback_kill_by_cn; |