occtl: added --json option

This allows to parse the output data using automated tools.
This commit is contained in:
Nikos Mavrogiannopoulos
2015-05-26 13:46:57 +02:00
parent 542b9b6f24
commit 1ca573ff16
10 changed files with 430 additions and 216 deletions

View File

@@ -127,7 +127,7 @@ ocpasswd-args.h: ocpasswd-args.c
occtl_SOURCES = occtl.c occtl-pager.c occtl.h occtl-time.c occtl-cache.c occtl-ip-cache.c \
occtl-nl.c ctl.h ctl.pb-c.c ctl.pb-c.h $(CCAN_SOURCES) $(COMMON_SOURCES) \
$(PROTOBUF_SOURCES)
occtl-print.c $(PROTOBUF_SOURCES)
occtl_LDADD = ../gl/libgnu.a $(LIBREADLINE_LIBS) \
$(LIBNL3_LIBS) $(LIBPROTOBUF_C_LIBS) $(LIBTALLOC_LIBS)

View File

@@ -26,6 +26,7 @@
#include <ipc.pb-c.h>
#include <talloc.h>
#include <time.h>
#include <string.h>
void _talloc_free2(void *ctx, void *ptr);
void *_talloc_size2(void *ctx, size_t size);

View File

@@ -229,7 +229,7 @@ static void method_stop(method_ctx *ctx, int cfd, uint8_t * msg,
#define IPBUF_SIZE 64
static int append_user_info(method_ctx *ctx,
UserListRep * list,
struct proc_st *ctmp, unsigned single)
struct proc_st *ctmp)
{
uint32_t tmp;
char *ipbuf;
@@ -346,7 +346,6 @@ static int append_user_info(method_ctx *ctx,
rep->has_mtu = 1;
}
if (single > 0) {
if (ctmp->config.rx_per_sec > 0)
tmp = ctmp->config.rx_per_sec;
else
@@ -397,7 +396,6 @@ static int append_user_info(method_ctx *ctx,
rep->iroutes = ctmp->config.iroutes;
rep->n_iroutes = ctmp->config.iroutes_size;
}
}
return 0;
}
@@ -413,7 +411,7 @@ static void method_list_users(method_ctx *ctx, int cfd, uint8_t * msg,
list_for_each(&ctx->s->proc_list.head, ctmp, list) {
ret = append_user_info(ctx, &rep, ctmp, 0);
ret = append_user_info(ctx, &rep, ctmp);
if (ret < 0) {
mslog(ctx->s, NULL, LOG_ERR,
"error appending user info to reply");
@@ -518,7 +516,7 @@ static void single_info_common(method_ctx *ctx, int cfd, uint8_t * msg,
}
}
ret = append_user_info(ctx, &rep, ctmp, 1);
ret = append_user_info(ctx, &rep, ctmp);
if (ret < 0) {
mslog(ctx->s, NULL, LOG_ERR,
"error appending user info to reply");

View File

@@ -84,7 +84,7 @@ DBusMessage *send_dbus_cmd(dbus_ctx *ctx,
}
int handle_status_cmd(dbus_ctx *ctx, const char *arg)
int handle_status_cmd(dbus_ctx *ctx, const char *arg, cmd_params_st *params)
{
DBusMessage *msg;
DBusMessageIter args;
@@ -169,7 +169,7 @@ int handle_status_cmd(dbus_ctx *ctx, const char *arg)
return 1;
}
int handle_reload_cmd(dbus_ctx *ctx, const char *arg)
int handle_reload_cmd(dbus_ctx *ctx, const char *arg, cmd_params_st *params)
{
DBusMessage *msg;
DBusMessageIter args;
@@ -214,7 +214,7 @@ int handle_reload_cmd(dbus_ctx *ctx, const char *arg)
return 1;
}
int handle_stop_cmd(dbus_ctx *ctx, const char *arg)
int handle_stop_cmd(dbus_ctx *ctx, const char *arg, cmd_params_st *params)
{
DBusMessage *msg;
DBusMessageIter args;
@@ -264,7 +264,7 @@ int handle_stop_cmd(dbus_ctx *ctx, const char *arg)
return 1;
}
int handle_unban_ip_cmd(struct dbus_ctx *ctx, const char *arg)
int handle_unban_ip_cmd(struct dbus_ctx *ctx, const char *arg, cmd_params_st *params)
{
int af;
struct sockaddr_storage st;
@@ -328,7 +328,7 @@ int handle_unban_ip_cmd(struct dbus_ctx *ctx, const char *arg)
return 1;
}
int handle_disconnect_user_cmd(dbus_ctx *ctx, const char *arg)
int handle_disconnect_user_cmd(dbus_ctx *ctx, const char *arg, cmd_params_st *params)
{
DBusMessage *msg;
DBusMessageIter args;
@@ -372,7 +372,7 @@ int handle_disconnect_user_cmd(dbus_ctx *ctx, const char *arg)
return 1;
}
int handle_disconnect_id_cmd(dbus_ctx *ctx, const char *arg)
int handle_disconnect_id_cmd(dbus_ctx *ctx, const char *arg, cmd_params_st *params)
{
DBusMessage *msg;
DBusMessageIter args;
@@ -423,7 +423,7 @@ int handle_disconnect_id_cmd(dbus_ctx *ctx, const char *arg)
return 1;
}
int handle_list_users_cmd(dbus_ctx *ctx, const char *arg)
int handle_list_users_cmd(dbus_ctx *ctx, const char *arg, cmd_params_st *params)
{
DBusMessage *msg;
DBusMessageIter args, suba, subs;
@@ -737,12 +737,12 @@ int handle_list_banned_cmd(struct dbus_ctx *ctx, const char *arg, unsigned point
return ret;
}
int handle_list_banned_ips_cmd(struct dbus_ctx *ctx, const char *arg)
int handle_list_banned_ips_cmd(struct dbus_ctx *ctx, const char *arg, cmd_params_st *params)
{
return handle_list_banned_cmd(ctx, arg, 0);
}
int handle_list_banned_points_cmd(struct dbus_ctx *ctx, const char *arg)
int handle_list_banned_points_cmd(struct dbus_ctx *ctx, const char *arg, cmd_params_st *params)
{
return handle_list_banned_cmd(ctx, arg, 1);
}
@@ -1084,7 +1084,7 @@ int common_info_cmd(DBusMessageIter * args)
return ret;
}
int handle_show_user_cmd(dbus_ctx *ctx, const char *arg)
int handle_show_user_cmd(dbus_ctx *ctx, const char *arg, cmd_params_st *params)
{
DBusMessage *msg;
DBusMessageIter args;
@@ -1126,7 +1126,7 @@ int handle_show_user_cmd(dbus_ctx *ctx, const char *arg)
return ret;
}
int handle_show_id_cmd(dbus_ctx *ctx, const char *arg)
int handle_show_id_cmd(dbus_ctx *ctx, const char *arg, cmd_params_st *params)
{
DBusMessage *msg;
DBusMessageIter args;

View File

@@ -77,7 +77,7 @@ unsigned long speed;
bytes2human(speed, output, output_size, "/sec");
}
void print_iface_stats(const char *iface, time_t since, FILE * out)
void print_iface_stats(const char *iface, time_t since, FILE * out, cmd_params_st *params, unsigned have_more)
{
uint64_t tx, rx;
char buf1[32], buf2[32];
@@ -102,17 +102,24 @@ void print_iface_stats(const char *iface, time_t since, FILE * out)
bytes2human(rx, buf1, sizeof(buf1), NULL);
bytes2human(tx, buf2, sizeof(buf2), NULL);
if (params->json) {
fprintf(out, " \"RX\": \"%"PRIu64"\",\n \"TX\": \"%"PRIu64"\",\n", rx, tx);
fprintf(out, " \"_RX\": \"%s\",\n \"_TX\": \"%s\",\n", buf1, buf2);
} else
fprintf(out, "\tRX: %"PRIu64" (%s) TX: %"PRIu64" (%s)\n", rx, buf1, tx, buf2);
value2speed(rx, diff, buf1, sizeof(buf1));
value2speed(tx, diff, buf2, sizeof(buf2));
if (params->json)
fprintf(out, " \"Average RX\": \"%s\",\n \"Average TX\": \"%s\"%s\n", buf1, buf2, have_more?",":"");
else
fprintf(out, "\tAverage bandwidth RX: %s TX: %s\n", buf1, buf2);
return;
}
#else
void print_iface_stats(const char *iface, time_t since, FILE * out)
void print_iface_stats(const char *iface, time_t since, FILE * out, cmd_params_st *params, unsigned have_more)
{
return;
}

149
src/occtl-print.c Normal file
View File

@@ -0,0 +1,149 @@
/*
* Copyright (C) 2014, 2015 Red Hat
*
* Author: Nikos Mavrogiannopoulos
*
* This file is part of ocserv.
*
* ocserv is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* ocserv 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. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <errno.h>
#include <signal.h>
#include <c-ctype.h>
#include <occtl.h>
#include <common.h>
#include <c-strcase.h>
int print_list_entries(FILE* out, cmd_params_st *params, const char* name, char **val, unsigned vsize, unsigned have_more)
{
const char * tmp;
unsigned int i = 0;
if (params->json) {
fprintf(out, " \"%s\":\t[", name);
for (i=0;i<vsize;i++) {
tmp = val[i];
if (tmp != NULL) {
if (i==0)
fprintf(out, "%s", tmp);
else
fprintf(out, ", %s", tmp);
}
}
fprintf(out, "]%s\n", have_more?",":"");
} else {
for (i=0;i<vsize;i++) {
tmp = val[i];
if (tmp != NULL) {
if (i==0)
fprintf(out, "\t%s: %s\n", name, tmp);
else
fprintf(out, "\t\t%s\n", tmp);
}
}
}
return i;
}
void print_start_block(FILE *out, cmd_params_st *params)
{
if (params->json)
fprintf(out, " {\n");
}
void print_end_block(FILE *out, cmd_params_st *params, unsigned have_more)
{
if (params->json)
fprintf(out, " }%s\n", have_more?",":"");
}
void print_array_block(FILE *out, cmd_params_st *params)
{
if (params->json)
fprintf(out, "[\n");
}
void print_end_array_block(FILE *out, cmd_params_st *params)
{
if (params->json)
fprintf(out, "]\n");
}
void print_separator(FILE *out, cmd_params_st *params)
{
if (!params->json)
fprintf(out, "\n");
}
void print_single_value(FILE *out, cmd_params_st *params, const char *name, const char *value, unsigned have_more)
{
if (value[0] == 0)
return;
if (params->json)
fprintf(out, " \"%s\": \"%s\"%s\n", name, value, have_more?",":"");
else
fprintf(out, "\t%s: %s\n", name, value);
}
void print_single_value_int(FILE *out, cmd_params_st *params, const char *name, long i, unsigned have_more)
{
if (params->json)
fprintf(out, " \"%s\": \%lu%s\n", name, i, have_more?",":"");
else
fprintf(out, "\t%s: %lu\n", name, i);
}
void print_single_value_ex(FILE *out, cmd_params_st *params, const char *name, const char *value, const char *ex, unsigned have_more)
{
if (value[0] == 0)
return;
if (params->json) {
fprintf(out, " \"%s\": \"%s\",\n", name, value);
fprintf(out, " \"_%s\": \"%s\"%s\n", name, ex, have_more?",":"");
} else
fprintf(out, "\t%s: %s (%s)\n", name, value, ex);
}
void print_pair_value(FILE *out, cmd_params_st *params, const char *name1, const char *value1, const char *name2, const char *value2, unsigned have_more)
{
if (params->json) {
if (value1 && value1[0] != 0)
fprintf(out, " \"%s\": \"%s\"%s\n", name1, value1, have_more?",":"");
if (value2 && value2[0] != 0)
fprintf(out, " \"%s\": \"%s\"%s\n", name2, value2, have_more?",":"");
} else {
if (value1 && value1[0] != 0)
fprintf(out, "\t%s: %s", name1, value1);
if (value2 && value2[0] != 0) {
const char *sep;
if (name1)
sep = " ";
else
sep = "\t";
fprintf(out, "%s%s: %s", sep, name2, value2);
}
if ((value1 && value1[0] != 0) || (value2 && value2[0] != 0))
fprintf(out, "\n");
}
}

View File

@@ -27,33 +27,34 @@
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <occtl.h>
#define _(x) x
/* compact 7 char format for time intervals (belongs in libproc?) */
void print_time_ival7(time_t t1, time_t t2, FILE * fout)
void print_time_ival7(char output[MAX_TMPSTR_SIZE], time_t t1, time_t t2)
{
time_t t = t1 - t2;
if ((long)t < (long)0) {
/* system clock changed? */
fprintf(fout, " ? ");
snprintf(output, MAX_TMPSTR_SIZE, " ? ");
return;
}
if (t >= 48 * 60 * 60)
/* 2 days or more */
fprintf(fout, _("%2ludays"), (long)t / (24 * 60 * 60));
snprintf(output, MAX_TMPSTR_SIZE, _("%2ludays"), (long)t / (24 * 60 * 60));
else if (t >= 60 * 60)
/* 1 hour or more */
/* Translation Hint: Hours:Minutes */
fprintf(fout, _("%2luh:%02um"), (long)t / (60 * 60),
snprintf(output, MAX_TMPSTR_SIZE, _("%2luh:%02um"), (long)t / (60 * 60),
(unsigned)((t / 60) % 60));
else if (t > 60)
/* 1 minute or more */
/* Translation Hint: Minutes:Seconds */
fprintf(fout, "%2lum:%02us", (long)t / 60, (unsigned)t % 60);
snprintf(output, MAX_TMPSTR_SIZE, "%2lum:%02us", (long)t / 60, (unsigned)t % 60);
else
/* Translation Hint: Seconds:Centiseconds */
fprintf(fout, _("%5lus"), (long)t);
snprintf(output, MAX_TMPSTR_SIZE, _("%5lus"), (long)t);
}

View File

@@ -40,6 +40,9 @@
#include <sys/socket.h>
#include <sys/un.h>
static
int common_info_cmd(UserListRep *args, FILE *out, cmd_params_st *params);
struct unix_ctx {
int fd;
int is_open;
@@ -210,18 +213,23 @@ error:
}
int handle_status_cmd(struct unix_ctx *ctx, const char *arg)
int handle_status_cmd(struct unix_ctx *ctx, const char *arg, cmd_params_st *params)
{
int ret;
struct cmd_reply_st raw;
StatusRep *rep;
char str_since[64];
char buf[MAX_TMPSTR_SIZE];
time_t t;
struct tm *tm;
PROTOBUF_ALLOCATOR(pa, ctx);
init_reply(&raw);
print_start_block(stdout, params);
if (!params->json)
printf("OpenConnect SSL VPN server\n");
ret = send_cmd(ctx, CTL_CMD_STATUS, NULL, NULL, NULL, &raw);
if (ret < 0) {
goto error_status;
@@ -231,23 +239,23 @@ int handle_status_cmd(struct unix_ctx *ctx, const char *arg)
if (rep == NULL)
goto error_status;
printf("OpenConnect SSL VPN server\n");
printf(" Status: %s\n", rep->status != 0 ? "online" : "error");
print_single_value(stdout, params, "Status", rep->status != 0 ? "online" : "error", 1);
t = rep->start_time;
tm = localtime(&t);
print_time_ival7(buf, time(0), t);
strftime(str_since, sizeof(str_since), DATE_TIME_FMT, tm);
printf(" Up since: %s (", str_since);
print_time_ival7(time(0), t, stdout);
fputs(")\n", stdout);
printf(" Clients: %u\n", (unsigned)rep->active_clients);
printf("Sec-mod client entries: %u\n", (unsigned)rep->secmod_client_entries);
printf(" IPs in ban list: %u\n", (unsigned)rep->banned_ips);
printf(" TLS DB entries: %u\n", (unsigned)rep->stored_tls_sessions);
printf("\n");
printf(" Server PID: %u\n", (unsigned)rep->pid);
printf(" Sec-mod PID: %u\n", (unsigned)rep->sec_mod_pid);
print_single_value_ex(stdout, params, "Up since", str_since, buf, 1);
print_single_value_int(stdout, params, "Clients", rep->active_clients, 1);
print_single_value_int(stdout, params, "Sec-mod client entries", rep->secmod_client_entries, 1);
print_single_value_int(stdout, params, "IPs in ban list", rep->banned_ips, 1);
print_single_value_int(stdout, params, "TLS DB entries", rep->stored_tls_sessions, 1);
print_separator(stdout, params);
print_single_value_int(stdout, params, "Server PID", rep->pid, 1);
print_single_value_int(stdout, params, "Sec-mod PID", rep->sec_mod_pid, 1);
print_end_block(stdout, params, 0);
status_rep__free_unpacked(rep, &pa);
@@ -255,8 +263,8 @@ int handle_status_cmd(struct unix_ctx *ctx, const char *arg)
goto cleanup;
error_status:
printf("OpenConnect SSL VPN server\n");
printf(" Status: offline\n");
print_single_value(stdout, params, "Status", "offline", 0);
print_end_block(stdout, params, 0);
ret = 1;
cleanup:
@@ -264,7 +272,7 @@ int handle_status_cmd(struct unix_ctx *ctx, const char *arg)
return ret;
}
int handle_reload_cmd(struct unix_ctx *ctx, const char *arg)
int handle_reload_cmd(struct unix_ctx *ctx, const char *arg, cmd_params_st *params)
{
int ret;
struct cmd_reply_st raw;
@@ -304,7 +312,7 @@ int handle_reload_cmd(struct unix_ctx *ctx, const char *arg)
return ret;
}
int handle_stop_cmd(struct unix_ctx *ctx, const char *arg)
int handle_stop_cmd(struct unix_ctx *ctx, const char *arg, cmd_params_st *params)
{
int ret;
struct cmd_reply_st raw;
@@ -344,7 +352,7 @@ int handle_stop_cmd(struct unix_ctx *ctx, const char *arg)
return ret;
}
int handle_unban_ip_cmd(struct unix_ctx *ctx, const char *arg)
int handle_unban_ip_cmd(struct unix_ctx *ctx, const char *arg, cmd_params_st *params)
{
int ret;
struct cmd_reply_st raw;
@@ -410,7 +418,7 @@ int handle_unban_ip_cmd(struct unix_ctx *ctx, const char *arg)
return ret;
}
int handle_disconnect_user_cmd(struct unix_ctx *ctx, const char *arg)
int handle_disconnect_user_cmd(struct unix_ctx *ctx, const char *arg, cmd_params_st *params)
{
int ret;
struct cmd_reply_st raw;
@@ -460,7 +468,7 @@ int handle_disconnect_user_cmd(struct unix_ctx *ctx, const char *arg)
return ret;
}
int handle_disconnect_id_cmd(struct unix_ctx *ctx, const char *arg)
int handle_disconnect_id_cmd(struct unix_ctx *ctx, const char *arg, cmd_params_st *params)
{
int ret;
struct cmd_reply_st raw;
@@ -515,7 +523,7 @@ int handle_disconnect_id_cmd(struct unix_ctx *ctx, const char *arg)
return ret;
}
int handle_list_users_cmd(struct unix_ctx *ctx, const char *arg)
int handle_list_users_cmd(struct unix_ctx *ctx, const char *arg, cmd_params_st *params)
{
int ret;
struct cmd_reply_st raw;
@@ -523,6 +531,7 @@ int handle_list_users_cmd(struct unix_ctx *ctx, const char *arg)
unsigned i;
const char *vpn_ip, *groupname, *username;
const char *dtls_ciphersuite;
char tmpbuf[MAX_TMPSTR_SIZE];
FILE *out;
time_t t;
struct tm *tm;
@@ -544,7 +553,13 @@ int handle_list_users_cmd(struct unix_ctx *ctx, const char *arg)
if (rep == NULL)
goto error;
for (i=0;i<rep->n_user;i++) {
if (params->json) {
common_info_cmd(rep, out, params);
} else for (i=0;i<rep->n_user;i++) {
username = rep->user[i]->username;
if (username == NULL || username[0] == 0)
username = NO_USER;
if (rep->user[i]->local_ip != NULL && rep->user[i]->local_ip[0] != 0)
vpn_ip = rep->user[i]->local_ip;
else
@@ -565,23 +580,19 @@ int handle_list_users_cmd(struct unix_ctx *ctx, const char *arg)
if (groupname == NULL || groupname[0] == 0)
groupname = NO_GROUP;
username = rep->user[i]->username;
if (username == NULL || username[0] == 0)
username = NO_USER;
print_time_ival7(tmpbuf, time(0), t);
fprintf(out, "%8d %8s %8s %14s %14s %6s ",
(int)rep->user[i]->id, username, groupname, rep->user[i]->ip, vpn_ip, rep->user[i]->tun);
print_time_ival7(time(0), t, out);
dtls_ciphersuite = rep->user[i]->dtls_ciphersuite;
if (dtls_ciphersuite != NULL && dtls_ciphersuite[0] != 0) {
if (strlen(dtls_ciphersuite) > 16 && strncmp(dtls_ciphersuite, "(DTLS", 5) == 0 &&
strncmp(&dtls_ciphersuite[8], ")-(RSA)-", 8) == 0)
dtls_ciphersuite += 16;
fprintf(out, " %14s %9s\n", dtls_ciphersuite, rep->user[i]->status);
fprintf(out, "%s %14s %9s\n", tmpbuf, dtls_ciphersuite, rep->user[i]->status);
} else {
fprintf(out, " %14s %9s\n", "(no dtls)", rep->user[i]->status);
fprintf(out, "%s %14s %9s\n", tmpbuf, "(no dtls)", rep->user[i]->status);
}
entries_add(ctx, username, strlen(username), rep->user[i]->id);
@@ -605,13 +616,14 @@ int handle_list_users_cmd(struct unix_ctx *ctx, const char *arg)
}
static
int handle_list_banned_cmd(struct unix_ctx *ctx, const char *arg, unsigned points)
int handle_list_banned_cmd(struct unix_ctx *ctx, const char *arg, cmd_params_st *params, unsigned points)
{
int ret;
struct cmd_reply_st raw;
BanListRep *rep = NULL;
unsigned i;
char str_since[64];
char tmpbuf[MAX_TMPSTR_SIZE];
FILE *out;
struct tm *tm;
time_t t;
@@ -632,10 +644,13 @@ int handle_list_banned_cmd(struct unix_ctx *ctx, const char *arg, unsigned point
if (rep == NULL)
goto error;
print_array_block(out, params);
for (i=0;i<rep->n_info;i++) {
if (rep->info[i]->ip == NULL)
continue;
/* add header */
if (points == 0) {
if (rep->info[i]->has_expires) {
@@ -646,28 +661,45 @@ int handle_list_banned_cmd(struct unix_ctx *ctx, const char *arg, unsigned point
continue;
}
if (i == 0) {
if (i == 0 && !params->json) {
fprintf(out, "%14s %14s %30s\n",
"IP", "score", "expires");
}
print_start_block(out, params);
fprintf(out, "%14s %14u %30s (",
rep->info[i]->ip, (unsigned)rep->info[i]->score, str_since);
print_time_ival7(t, time(0), out);
fputs(")\n", out);
print_time_ival7(tmpbuf, t, time(0));
if (params->json) {
print_single_value(out, params, "IP", rep->info[i]->ip, 1);
print_single_value_ex(out, params, "Since", str_since, tmpbuf, 1);
print_single_value_int(out, params, "Score", rep->info[i]->score, 0);
} else {
if (i == 0) {
fprintf(out, "%14s %14u %30s (%s)\n",
rep->info[i]->ip, (unsigned)rep->info[i]->score, str_since, tmpbuf);
}
} else {
if (i == 0 && !params->json) {
fprintf(out, "%14s %14s\n",
"IP", "score");
}
print_start_block(out, params);
if (params->json) {
print_single_value(out, params, "IP", rep->info[i]->ip, 1);
print_single_value_int(out, params, "Score", rep->info[i]->score, 0);
} else {
fprintf(out, "%14s %14u\n",
rep->info[i]->ip, (unsigned)rep->info[i]->score);
}
}
print_end_block(out, params, i<(rep->n_info-1)?1:0);
ip_entries_add(ctx, rep->info[i]->ip, strlen(rep->info[i]->ip));
}
print_end_array_block(out, params);
ret = 0;
goto cleanup;
@@ -685,52 +717,53 @@ int handle_list_banned_cmd(struct unix_ctx *ctx, const char *arg, unsigned point
return ret;
}
int handle_list_banned_ips_cmd(struct unix_ctx *ctx, const char *arg)
int handle_list_banned_ips_cmd(struct unix_ctx *ctx, const char *arg, cmd_params_st *params)
{
return handle_list_banned_cmd(ctx, arg, 0);
return handle_list_banned_cmd(ctx, arg, params, 0);
}
int handle_list_banned_points_cmd(struct unix_ctx *ctx, const char *arg)
int handle_list_banned_points_cmd(struct unix_ctx *ctx, const char *arg, cmd_params_st *params)
{
return handle_list_banned_cmd(ctx, arg, 1);
return handle_list_banned_cmd(ctx, arg, params, 1);
}
int print_list_entries(FILE* out, const char* name, char **val, unsigned vsize)
static char *int2str(char tmpbuf[MAX_TMPSTR_SIZE], int i)
{
const char * tmp;
unsigned int i = 0;
for (i=0;i<vsize;i++) {
tmp = val[i];
if (tmp != NULL) {
if (i==0)
fprintf(out, "%s %s\n", name, tmp);
else
fprintf(out, "\t\t%s\n", tmp);
}
}
return i;
tmpbuf[0] = 0;
snprintf(tmpbuf, MAX_TMPSTR_SIZE, "%d", i);
return tmpbuf;
}
int common_info_cmd(UserListRep * args)
static
int common_info_cmd(UserListRep * args, FILE *out, cmd_params_st *params)
{
char *username = "";
char *groupname = "";
char str_since[64];
char tmpbuf[MAX_TMPSTR_SIZE];
struct tm *tm;
time_t t;
FILE *out;
unsigned at_least_one = 0;
int ret = 1, r;
unsigned i;
unsigned init_pager = 0;
if (out == NULL) {
out = pager_start();
init_pager = 1;
}
if (params->json)
fprintf(out, "[\n");
for (i=0;i<args->n_user;i++) {
if (at_least_one > 0)
fprintf(out, "\n");
fprintf(out, "ID: %d\n", (int)args->user[i]->id);
print_start_block(out, params);
print_single_value_int(out, params, "ID", args->user[i]->id, 1);
t = args->user[i]->conn_time;
tm = localtime(&t);
@@ -740,96 +773,88 @@ int common_info_cmd(UserListRep * args)
if (username == NULL || username[0] == 0)
username = NO_USER;
fprintf(out, "\tUsername: %s ", username);
groupname = args->user[i]->groupname;
if (groupname == NULL || groupname[0] == 0)
groupname = NO_GROUP;
fprintf(out, "Groupname: %s\n", groupname);
fprintf(out, "\tState: %s ", args->user[i]->status);
fprintf(out, "Remote IP: %s\n", args->user[i]->ip);
print_pair_value(out, params, "Username", username, "Groupname", groupname, 1);
print_pair_value(out, params, "State", args->user[i]->status, "Remote IP", args->user[i]->ip, 1);
if (args->user[i]->local_ip != NULL && args->user[i]->local_ip[0] != 0 &&
args->user[i]->remote_ip != NULL && args->user[i]->remote_ip[0] != 0) {
fprintf(out, "\tIPv4: %s ", args->user[i]->local_ip);
fprintf(out, "P-t-P IPv4: %s\n", args->user[i]->remote_ip);
print_pair_value(out, params, "IPv4", args->user[i]->local_ip, "P-t-P IPv4", args->user[i]->remote_ip, 1);
}
if (args->user[i]->local_ip6 != NULL && args->user[i]->local_ip6[0] != 0 &&
args->user[i]->remote_ip6 != NULL && args->user[i]->remote_ip6[0] != 0) {
fprintf(out, "\tIPv6: %s ", args->user[i]->local_ip6);
fprintf(out, "P-t-P IPv6: %s\n", args->user[i]->remote_ip6);
print_pair_value(out, params, "IPv6", args->user[i]->local_ip6, "P-t-P IPv6", args->user[i]->remote_ip6, 1);
}
fprintf(out, "\tDevice: %s ", args->user[i]->tun);
if (args->user[i]->has_mtu != 0)
fprintf(out, "MTU: %d\n", args->user[i]->mtu);
print_pair_value(out, params, "Device", args->user[i]->tun, "MTU", int2str(tmpbuf, args->user[i]->mtu), 1);
else
fprintf(out, "\n");
print_single_value(out, params, "Device", args->user[i]->tun, 1);
if (args->user[i]->user_agent != NULL && args->user[i]->user_agent[0] != 0)
fprintf(out, "\tUser-Agent: %s\n", args->user[i]->user_agent);
print_single_value(out, params, "User-Agent", args->user[i]->user_agent, 1);
if (args->user[i]->rx_per_sec > 0 || args->user[i]->tx_per_sec > 0) {
/* print limits */
char buf[32];
char buf1[32];
char buf2[32];
if (args->user[i]->rx_per_sec > 0 && args->user[i]->tx_per_sec > 0) {
bytes2human(args->user[i]->rx_per_sec, buf, sizeof(buf), NULL);
fprintf(out, "\tLimit RX: %s/sec ", buf);
bytes2human(args->user[i]->rx_per_sec, buf1, sizeof(buf1), "/sec");
bytes2human(args->user[i]->tx_per_sec, buf2, sizeof(buf2), "/sec");
bytes2human(args->user[i]->tx_per_sec, buf, sizeof(buf), NULL);
fprintf(out, "TX: %s/sec\n", buf);
print_pair_value(out, params, "Limit RX", buf1, "TX", buf2, 1);
} else if (args->user[i]->tx_per_sec > 0) {
bytes2human(args->user[i]->tx_per_sec, buf, sizeof(buf), NULL);
fprintf(out, "\tLimit TX: %s/sec\n", buf);
bytes2human(args->user[i]->tx_per_sec, buf1, sizeof(buf1), "/sec");
print_single_value(out, params, "Limit TX", buf1, 1);
} else if (args->user[i]->rx_per_sec > 0) {
bytes2human(args->user[i]->rx_per_sec, buf, sizeof(buf), NULL);
fprintf(out, "\tLimit RX: %s/sec\n", buf);
bytes2human(args->user[i]->rx_per_sec, buf1, sizeof(buf1), "/sec");
print_single_value(out, params, "Limit RX", buf1, 1);
}
}
print_iface_stats(args->user[i]->tun, args->user[i]->conn_time, out);
print_iface_stats(args->user[i]->tun, args->user[i]->conn_time, out, params, 1);
if (args->user[i]->hostname != NULL && args->user[i]->hostname[0] != 0)
fprintf(out, "\tHostname: %s\n", args->user[i]->hostname);
print_single_value(out, params, "Hostname", args->user[i]->hostname, 1);
fprintf(out, "\tConnected at: %s (", str_since);
print_time_ival7(time(0), t, out);
fprintf(out, ")\n");
print_time_ival7(tmpbuf, time(0), t);
print_single_value_ex(out, params, "Connected at", str_since, tmpbuf, 1);
fprintf(out, "\tTLS ciphersuite: %s\n", args->user[i]->tls_ciphersuite);
if (args->user[i]->dtls_ciphersuite != NULL && args->user[i]->dtls_ciphersuite[0] != 0)
fprintf(out, "\tDTLS cipher: %s\n", args->user[i]->dtls_ciphersuite);
if (args->user[i]->cstp_compr && args->user[i]->cstp_compr[0] != 0)
fprintf(out, "\tCSTP compression: %s\n", args->user[i]->cstp_compr);
if (args->user[i]->dtls_compr != NULL && args->user[i]->dtls_compr[0] != 0)
fprintf(out, "\tDTLS compression: %s\n", args->user[i]->dtls_compr);
print_single_value(out, params, "TLS ciphersuite", args->user[i]->tls_ciphersuite, 1);
print_single_value(out, params, "DTLS cipher", args->user[i]->dtls_ciphersuite, 1);
print_pair_value(out, params, "CSTP compression", args->user[i]->cstp_compr, "DTLS compression", args->user[i]->dtls_compr, 1);
print_separator(out, params);
/* user network info */
fputs("\n", out);
if (print_list_entries(out, "\tDNS:", args->user[i]->dns, args->user[i]->n_dns) < 0)
if (print_list_entries(out, params, "DNS", args->user[i]->dns, args->user[i]->n_dns, 1) < 0)
goto error_parse;
if (print_list_entries(out, "\tNBNS:", args->user[i]->nbns, args->user[i]->n_nbns) < 0)
if (print_list_entries(out, params, "NBNS", args->user[i]->nbns, args->user[i]->n_nbns, 1) < 0)
goto error_parse;
if ((r = print_list_entries(out, "\tRoutes:", args->user[i]->routes, args->user[i]->n_routes)) < 0)
if ((r = print_list_entries(out, params, "Routes", args->user[i]->routes, args->user[i]->n_routes, 1)) < 0)
goto error_parse;
if (r == 0) {
fprintf(out, "Routes: defaultroute\n");
print_single_value(out, params, "Routes", "defaultroute", 1);
}
if ((r = print_list_entries(out, "\tNo-routes:", args->user[i]->no_routes, args->user[i]->n_no_routes)) < 0)
if ((r = print_list_entries(out, params, "No-routes", args->user[i]->no_routes, args->user[i]->n_no_routes, 1)) < 0)
goto error_parse;
if (print_list_entries(out, "\tiRoutes:", args->user[i]->iroutes, args->user[i]->n_iroutes) < 0)
if (print_list_entries(out, params, "iRoutes", args->user[i]->iroutes, args->user[i]->n_iroutes, 0) < 0)
goto error_parse;
print_end_block(out, params, i<(args->n_user-1)?1:0);
at_least_one = 1;
}
if (params->json)
fprintf(out, "]\n");
ret = 0;
goto cleanup;
@@ -838,15 +863,17 @@ int common_info_cmd(UserListRep * args)
goto cleanup;
cleanup:
if (at_least_one == 0) {
if (!params->json)
fprintf(out, "user or ID not found\n");
ret = 2;
}
if (init_pager)
pager_stop(out);
return ret;
}
int handle_show_user_cmd(struct unix_ctx *ctx, const char *arg)
int handle_show_user_cmd(struct unix_ctx *ctx, const char *arg, cmd_params_st *params)
{
int ret;
struct cmd_reply_st raw;
@@ -874,7 +901,7 @@ int handle_show_user_cmd(struct unix_ctx *ctx, const char *arg)
if (rep == NULL)
goto error;
ret = common_info_cmd(rep);
ret = common_info_cmd(rep, NULL, params);
if (ret < 0)
goto error;
@@ -891,7 +918,7 @@ int handle_show_user_cmd(struct unix_ctx *ctx, const char *arg)
return ret;
}
int handle_show_id_cmd(struct unix_ctx *ctx, const char *arg)
int handle_show_id_cmd(struct unix_ctx *ctx, const char *arg, cmd_params_st *params)
{
int ret;
struct cmd_reply_st raw;
@@ -923,7 +950,7 @@ int handle_show_id_cmd(struct unix_ctx *ctx, const char *arg)
if (rep == NULL)
goto error;
ret = common_info_cmd(rep);
ret = common_info_cmd(rep, NULL, params);
if (ret < 0)
goto error;

View File

@@ -29,9 +29,9 @@
#include <occtl.h>
#include <c-strcase.h>
static int handle_reset_cmd(CONN_TYPE * conn, const char *arg);
static int handle_help_cmd(CONN_TYPE * conn, const char *arg);
static int handle_exit_cmd(CONN_TYPE * conn, const char *arg);
static int handle_reset_cmd(CONN_TYPE * conn, const char *arg, cmd_params_st *params);
static int handle_help_cmd(CONN_TYPE * conn, const char *arg, cmd_params_st *params);
static int handle_exit_cmd(CONN_TYPE * conn, const char *arg, cmd_params_st *params);
typedef struct {
char *name;
@@ -157,6 +157,7 @@ void usage(void)
printf(" -s --socket-file Specify the server's occtl socket file\n");
printf(" -h --help Show this help\n");
printf(" -v --version Show the program's version\n");
printf(" -j --json Use JSON formatting for output\n");
printf("\n");
print_commands(0);
printf("\n");
@@ -224,13 +225,13 @@ double data;
}
}
static int handle_help_cmd(CONN_TYPE * conn, const char *arg)
static int handle_help_cmd(CONN_TYPE * conn, const char *arg, cmd_params_st *params)
{
print_commands(1);
return 0;
}
static int handle_reset_cmd(CONN_TYPE * conn, const char *arg)
static int handle_reset_cmd(CONN_TYPE * conn, const char *arg, cmd_params_st *params)
{
rl_reset_terminal(NULL);
#ifdef HAVE_ORIG_READLINE
@@ -240,7 +241,7 @@ static int handle_reset_cmd(CONN_TYPE * conn, const char *arg)
return 0;
}
static int handle_exit_cmd(CONN_TYPE * conn, const char *arg)
static int handle_exit_cmd(CONN_TYPE * conn, const char *arg, cmd_params_st *params)
{
exit(0);
}
@@ -248,8 +249,10 @@ static int handle_exit_cmd(CONN_TYPE * conn, const char *arg)
/* checks whether an input command of type " list users" maches
* the given cmd (e.g., "list users"). If yes it executes func() and returns true.
*/
static
unsigned check_cmd(const char *cmd, const char *input,
CONN_TYPE * conn, int need_preconn, cmd_func func, int *status)
CONN_TYPE * conn, int need_preconn, cmd_func func, int *status,
cmd_params_st *params)
{
char *t, *p;
unsigned len, tlen;
@@ -290,10 +293,10 @@ unsigned check_cmd(const char *cmd, const char *input,
if (conn_prehandle(conn) < 0) {
*status = 1;
} else {
*status = func(conn, p);
*status = func(conn, p, params);
}
} else {
*status = func(conn, p);
*status = func(conn, p, params);
}
ret = 1;
@@ -325,7 +328,8 @@ char *stripwhite(char *string)
return s;
}
int handle_cmd(CONN_TYPE * conn, char *line)
static
int handle_cmd(CONN_TYPE * conn, char *line, cmd_params_st *params)
{
char *cline;
unsigned int i;
@@ -344,7 +348,7 @@ int handle_cmd(CONN_TYPE * conn, char *line)
(commands[i].name, cline, conn,
commands[i].need_preconn,
commands[i].func,
&status) != 0)
&status, params) != 0)
break;
}
@@ -497,7 +501,7 @@ void initialize_readline(void)
signal(SIGINT, handle_sigint);
}
static int single_cmd(int argc, char **argv, void *pool, const char *file)
static int single_cmd(int argc, char **argv, void *pool, const char *file, cmd_params_st *params)
{
CONN_TYPE *conn;
char *line;
@@ -506,7 +510,7 @@ static int single_cmd(int argc, char **argv, void *pool, const char *file)
conn = conn_init(pool, file);
line = merge_args(argc, argv);
ret = handle_cmd(conn, line);
ret = handle_cmd(conn, line, params);
free(line);
return ret;
@@ -519,6 +523,9 @@ int main(int argc, char **argv)
CONN_TYPE *conn;
const char *file = NULL;
void *gl_pool;
cmd_params_st params;
memset(&params, 0, sizeof(params));
gl_pool = talloc_init("occtl");
if (gl_pool == NULL) {
@@ -530,28 +537,36 @@ int main(int argc, char **argv)
if (argc > 1) {
if (argv[1][0] == '-') {
if (argv[1][1] == 'v'
while (argc > 1 && argv[1][0] == '-') {
if (argv[1][1] == 'j'
|| (argv[1][1] == '-' && argv[1][2] == 'j')) {
params.json = 1;
argv += 1;
argc -= 1;
} else if (argv[1][1] == 'v'
|| (argv[1][1] == '-' && argv[1][2] == 'v')) {
version();
exit(0);
} else if (argc > 2 && (argv[1][1] == 's'
|| (argv[1][1] == '-' && argv[1][2] == 's'))) {
file = talloc_strdup(gl_pool, argv[2]);
if (argc == 3) {
goto interactive;
} else {
}
argv += 2;
argc -= 2;
exit(single_cmd(argc, argv, gl_pool, file));
}
} else {
usage();
}
exit(0);
}
}
/* handle all arguments as a command */
exit(single_cmd(argc, argv, gl_pool, file));
exit(single_cmd(argc, argv, gl_pool, file, &params));
}
interactive:
@@ -565,7 +580,7 @@ int main(int argc, char **argv)
if (line == NULL)
return 0;
handle_cmd(conn, line);
handle_cmd(conn, line, 0);
}
conn_close(conn);

View File

@@ -13,11 +13,27 @@
#endif
#define DATE_TIME_FMT "%Y-%m-%d %H:%M"
#define MAX_TMPSTR_SIZE 64
typedef struct cmd_params_st {
unsigned json;
} cmd_params_st;
FILE* pager_start(void);
void pager_stop(FILE* fp);
void print_time_ival7(time_t t1, time_t t2, FILE * fout);
void print_iface_stats(const char *iface, time_t since, FILE * out);
void print_time_ival7(char output[MAX_TMPSTR_SIZE], time_t t1, time_t t2);
void print_iface_stats(const char *iface, time_t since, FILE * out, cmd_params_st *params, unsigned have_more);
int print_list_entries(FILE* out, cmd_params_st *params, const char* name, char **val, unsigned vsize, unsigned have_more);
void print_start_block(FILE *out, cmd_params_st *params);
void print_end_block(FILE *out, cmd_params_st *params, unsigned have_more);
void print_array_block(FILE *out, cmd_params_st *params);
void print_end_array_block(FILE *out, cmd_params_st *params);
void print_separator(FILE *out, cmd_params_st *params);
void print_single_value(FILE *out, cmd_params_st *params, const char *name, const char *value, unsigned have_more);
void print_single_value_int(FILE *out, cmd_params_st *params, const char *name, long i, unsigned have_more);
void print_single_value_ex(FILE *out, cmd_params_st *params, const char *name, const char *value, const char *ex, unsigned have_more);
void print_pair_value(FILE *out, cmd_params_st *params, const char *name1, const char *value1, const char *name2, const char *value2, unsigned have_more);
void
bytes2human(unsigned long bytes, char* output, unsigned output_size, const char* suffix);
@@ -53,18 +69,18 @@ void conn_close(CONN_TYPE*);
int conn_prehandle(CONN_TYPE *ctx);
void conn_posthandle(CONN_TYPE *ctx);
typedef int (*cmd_func) (CONN_TYPE * conn, const char *arg);
typedef int (*cmd_func) (CONN_TYPE * conn, const char *arg, cmd_params_st *params);
int handle_status_cmd(CONN_TYPE * conn, const char *arg);
int handle_list_users_cmd(CONN_TYPE * conn, const char *arg);
int handle_list_banned_ips_cmd(CONN_TYPE * conn, const char *arg);
int handle_list_banned_points_cmd(CONN_TYPE * conn, const char *arg);
int handle_show_user_cmd(CONN_TYPE * conn, const char *arg);
int handle_show_id_cmd(CONN_TYPE * conn, const char *arg);
int handle_disconnect_user_cmd(CONN_TYPE * conn, const char *arg);
int handle_unban_ip_cmd(CONN_TYPE * conn, const char *arg);
int handle_disconnect_id_cmd(CONN_TYPE * conn, const char *arg);
int handle_reload_cmd(CONN_TYPE * conn, const char *arg);
int handle_stop_cmd(CONN_TYPE * conn, const char *arg);
int handle_status_cmd(CONN_TYPE * conn, const char *arg, cmd_params_st *params);
int handle_list_users_cmd(CONN_TYPE * conn, const char *arg, cmd_params_st *params);
int handle_list_banned_ips_cmd(CONN_TYPE * conn, const char *arg, cmd_params_st *params);
int handle_list_banned_points_cmd(CONN_TYPE * conn, const char *arg, cmd_params_st *params);
int handle_show_user_cmd(CONN_TYPE * conn, const char *arg, cmd_params_st *params);
int handle_show_id_cmd(CONN_TYPE * conn, const char *arg, cmd_params_st *params);
int handle_disconnect_user_cmd(CONN_TYPE * conn, const char *arg, cmd_params_st *params);
int handle_unban_ip_cmd(CONN_TYPE * conn, const char *arg, cmd_params_st *params);
int handle_disconnect_id_cmd(CONN_TYPE * conn, const char *arg, cmd_params_st *params);
int handle_reload_cmd(CONN_TYPE * conn, const char *arg, cmd_params_st *params);
int handle_stop_cmd(CONN_TYPE * conn, const char *arg, cmd_params_st *params);
#endif