Hi François,
This is not a full review, but as just discussed face-to-face, here are
some points from me:
1) Could we also please please enable this for non-management interface
use case? I guess it's just adding the status version number 4 in
option/config validator (and the manpage).
2) With 1), perhaps it would be more clear to use *version* in your
message/description so that it's about the --status-version option, not
the --status option.
3) I believe the output structure is not valid JSON with the "END"
string at the end.
(FYI I'm about to upload a patch to include more documentation on the
--status-version option and to include a new field as well.)
--
Gert
On 10-11-17 17:39, François Kooman wrote:
> Parsing CSV can be cumbersome in depending software, so instead
> offer JSON as well using "status 4".
>
> The "status 4" command uses the same keys/values as "status 2"
> and "status 3", just formatted as JSON.
> ---
> src/openvpn/multi.c | 96
> +++++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 96 insertions(+)
>
> diff --git a/src/openvpn/multi.c b/src/openvpn/multi.c
> index 82a0b9d9..3e82431b 100644
> --- a/src/openvpn/multi.c
> +++ b/src/openvpn/multi.c
> @@ -1014,6 +1014,102 @@ multi_print_status(struct multi_context *m, struct
> status_output *so, const int
>
> status_printf(so, "END");
> }
> + else if (version == 4)
> + {
> + /*
> + * Status file version 4 (JSON)
> + */
> + status_printf(so, "{");
> + status_printf(so, "\"TITLE\": \"%s\",", title_string);
> + status_printf(so, "\"TIME\": \"%s\",", time_string(now, 0,
> false, &gc_top));
> + /* UNIX_TIME added here instead of making it part of TIME as well
> + as in status 2/3 */
> + status_printf(so, "\"UNIX_TIME\": %u,", (unsigned int)now);
> + status_printf(so, "\"CLIENT_LIST\": [");
> +
> + /* JSON needs a "," between items, but not at the last position,
> + because I was unable to figure out how to determine if we
> + iterate over the last item, we inverse it by prepending
> + additional items with a comma */
> + int is_first = 1;
> + hash_iterator_init(m->hash, &hi);
> + while ((he = hash_iterator_next(&hi)))
> + {
> + struct gc_arena gc = gc_new();
> + const struct multi_instance *mi = (struct multi_instance *)
> he->value;
> +
> + if (!mi->halt)
> + {
> + if(0 == is_first) {
> + status_printf(so, ",");
> + } else {
> + is_first = 0;
> + }
> + status_printf(so, "{");
> + status_printf(so, "\"Common Name\": \"%s\",",
> tls_common_name(mi->context.c2.tls_multi, false));
> + status_printf(so, "\"Real Address\": \"%s\",",
> mroute_addr_print(&mi->real, &gc));
> + status_printf(so, "\"Virtual Address\": \"%s\",",
> print_in_addr_t(mi->reporting_addr, IA_EMPTY_IF_UNDEF, &gc));
> + status_printf(so, "\"Virtual IPv6 Address\": \"%s\",",
> print_in6_addr(mi->reporting_addr_ipv6, IA_EMPTY_IF_UNDEF, &gc));
> + status_printf(so, "\"Bytes Received\": " counter_format
> ",", mi->context.c2.link_read_bytes);
> + status_printf(so, "\"Bytes Sent\": " counter_format ",",
> mi->context.c2.link_write_bytes);
> + status_printf(so, "\"Connected Since\": \"%s\",",
> time_string(mi->created, 0, false, &gc));
> + status_printf(so, "\"Connected Since (time_t)\": %u,",
> (unsigned int)mi->created);
> + status_printf(so, "\"Username\": \"%s\",",
> tls_username(mi->context.c2.tls_multi, false));
> +#ifdef MANAGEMENT_DEF_AUTH
> + status_printf(so, "\"Client ID\": %lu,",
> mi->context.c2.mda_context.cid);
> +#endif
> + status_printf(so, "\"Peer ID\": %" PRIu32,
> mi->context.c2.tls_multi ? mi->context.c2.tls_multi->peer_id : UINT32_MAX);
> + status_printf(so, "}");
> + }
> + gc_free(&gc);
> + }
> + hash_iterator_free(&hi);
> +
> + status_printf(so, "],");
> + status_printf(so, "\"ROUTING_TABLE\": [");
> +
> + is_first = 1;
> + hash_iterator_init(m->vhash, &hi);
> + while ((he = hash_iterator_next(&hi)))
> + {
> + struct gc_arena gc = gc_new();
> + const struct multi_route *route = (struct multi_route *)
> he->value;
> +
> + if (multi_route_defined(m, route))
> + {
> + const struct multi_instance *mi = route->instance;
> + const struct mroute_addr *ma = &route->addr;
> + char flags[2] = {0, 0};
> +
> + if (route->flags & MULTI_ROUTE_CACHE)
> + {
> + flags[0] = 'C';
> + }
> + if(0 == is_first) {
> + status_printf(so, ",");
> + } else {
> + is_first = 0;
> + }
> + status_printf(so, "{\"Virtual Address\": \"%s%s\",",
> mroute_addr_print(ma, &gc), flags);
> + status_printf(so, "\"Common Name\": \"%s\",",
> tls_common_name(mi->context.c2.tls_multi, false));
> + status_printf(so, "\"Real Address\": \"%s\",",
> mroute_addr_print(&mi->real, &gc));
> + status_printf(so, "\"Last Ref\": \"%s\",",
> time_string(route->last_reference, 0, false, &gc));
> + status_printf(so, "\"Last Ref (time_t)\": %u}",
> (unsigned int)route->last_reference);
> + }
> + gc_free(&gc);
> + }
> + hash_iterator_free(&hi);
> + status_printf(so, "]");
> +
> + if (m->mbuf)
> + {
> + status_printf(so, ",\"GLOBAL_STATS\": {");
> + status_printf(so, "\"Max bcast/mcast queue length\": %d",
> mbuf_maximum_queued(m->mbuf));
> + status_printf(so, "}");
> + }
> + status_printf(so, "}");
> + status_printf(so, "END");
> + }
> else
> {
> status_printf(so, "ERROR: bad status format version number");
>
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Openvpn-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/openvpn-devel