mirror of
https://gitlab.com/openconnect/ocserv.git
synced 2026-02-10 08:46:58 +08:00
Added occtl command 'show events', as well as the corresponding command in main
This allows the main process to handle a single listener which will get all information about new and disconnecting users.
This commit is contained in:
committed by
Nikos Mavrogiannopoulos
parent
12bc8955bd
commit
fe28fd15cd
@@ -93,6 +93,32 @@ static char tmp[32];
|
||||
}
|
||||
}
|
||||
|
||||
const char* discon_reason_to_str(unsigned reason)
|
||||
{
|
||||
static char tmp[32];
|
||||
|
||||
switch(reason) {
|
||||
case 0:
|
||||
case REASON_ANY:
|
||||
return "unspecified";
|
||||
case REASON_USER_DISCONNECT:
|
||||
return "user disconnected";
|
||||
case REASON_SERVER_DISCONNECT:
|
||||
return "server disconnected";
|
||||
case REASON_IDLE_TIMEOUT:
|
||||
return "idle timeout";
|
||||
case REASON_DPD_TIMEOUT:
|
||||
return "DPD timeout";
|
||||
case REASON_ERROR:
|
||||
return "unspecified error";
|
||||
case REASON_SESSION_TIMEOUT:
|
||||
return "session timeout";
|
||||
default:
|
||||
snprintf(tmp, sizeof(tmp), "unknown (%u)", reason);
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
|
||||
ssize_t force_write(int sockfd, const void *buf, size_t len)
|
||||
{
|
||||
int left = len;
|
||||
|
||||
@@ -69,6 +69,7 @@ int recv_socket_msg(void *pool, int fd, uint8_t cmd,
|
||||
int *socketfd, void** msg, unpack_func, unsigned timeout);
|
||||
|
||||
const char* cmd_request_to_str(unsigned cmd);
|
||||
const char* discon_reason_to_str(unsigned reason);
|
||||
|
||||
ssize_t oc_recvfrom_at(int sockfd, void *buf, size_t len, int flags,
|
||||
struct sockaddr *src_addr, socklen_t *addrlen,
|
||||
|
||||
@@ -57,6 +57,14 @@ message user_list_rep
|
||||
repeated user_info_rep user = 1;
|
||||
}
|
||||
|
||||
message top_update_rep
|
||||
{
|
||||
required uint32 connected = 1;
|
||||
optional uint32 discon_reason = 2;
|
||||
optional string discon_reason_txt = 3;
|
||||
required user_list_rep user = 4;
|
||||
}
|
||||
|
||||
message username_req
|
||||
{
|
||||
required string username = 1;
|
||||
|
||||
@@ -45,6 +45,8 @@ typedef struct method_ctx {
|
||||
void *pool;
|
||||
} method_ctx;
|
||||
|
||||
static void method_top(method_ctx *ctx, int cfd, uint8_t * msg,
|
||||
unsigned msg_size);
|
||||
static void method_status(method_ctx *ctx, int cfd, uint8_t * msg,
|
||||
unsigned msg_size);
|
||||
static void method_list_users(method_ctx *ctx, int cfd, uint8_t * msg,
|
||||
@@ -73,12 +75,17 @@ typedef struct {
|
||||
char *name;
|
||||
unsigned cmd;
|
||||
method_func func;
|
||||
unsigned indefinite; /* session remains open */
|
||||
} ctl_method_st;
|
||||
|
||||
#define ENTRY(cmd, func) \
|
||||
{#cmd, cmd, func}
|
||||
{#cmd, cmd, func, 0}
|
||||
|
||||
#define ENTRY_INDEF(cmd, func) \
|
||||
{#cmd, cmd, func, 1}
|
||||
|
||||
static const ctl_method_st methods[] = {
|
||||
ENTRY_INDEF(CTL_CMD_TOP, method_top),
|
||||
ENTRY(CTL_CMD_STATUS, method_status),
|
||||
ENTRY(CTL_CMD_RELOAD, method_reload),
|
||||
ENTRY(CTL_CMD_STOP, method_stop),
|
||||
@@ -403,7 +410,6 @@ static void method_list_users(method_ctx *ctx, int cfd, uint8_t * msg,
|
||||
|
||||
mslog(ctx->s, NULL, LOG_DEBUG, "ctl: list-users");
|
||||
|
||||
|
||||
list_for_each(&ctx->s->proc_list.head, ctmp, list) {
|
||||
ret = append_user_info(ctx, &rep, ctmp);
|
||||
if (ret < 0) {
|
||||
@@ -424,6 +430,21 @@ static void method_list_users(method_ctx *ctx, int cfd, uint8_t * msg,
|
||||
return;
|
||||
}
|
||||
|
||||
static void method_top(method_ctx *ctx, int cfd, uint8_t * msg,
|
||||
unsigned msg_size)
|
||||
{
|
||||
/* we send the initial user list, and the we send a TOP reply message
|
||||
* once a user connects/disconnects. */
|
||||
|
||||
mslog(ctx->s, NULL, LOG_DEBUG, "ctl: top");
|
||||
|
||||
/* we can only have a single top listener */
|
||||
if (ctx->s->top_fd == -1)
|
||||
ctx->s->top_fd = cfd;
|
||||
|
||||
method_list_users(ctx, cfd, msg, msg_size);
|
||||
}
|
||||
|
||||
static int append_ban_info(method_ctx *ctx,
|
||||
BanListRep *list,
|
||||
struct ban_entry_st *e)
|
||||
@@ -707,13 +728,18 @@ static void ctl_cmd_wacher_cb(EV_P_ ev_io *w, int revents)
|
||||
unsigned buffer_size;
|
||||
method_ctx ctx;
|
||||
struct ctl_watcher_st *wst = container_of(w, struct ctl_watcher_st, ctl_cmd_io);
|
||||
unsigned i;
|
||||
unsigned i, indef = 0;
|
||||
|
||||
ctx.s = s;
|
||||
ctx.pool = wst;
|
||||
ctx.pool = talloc_new(wst);
|
||||
|
||||
if (ctx.pool == NULL)
|
||||
goto fail;
|
||||
|
||||
/* read request */
|
||||
ret = recv(wst->fd, buffer, sizeof(buffer), 0);
|
||||
if (ret == 0)
|
||||
goto fail;
|
||||
|
||||
if (ret < 3) {
|
||||
if (ret == -1) {
|
||||
@@ -726,6 +752,7 @@ static void ctl_cmd_wacher_cb(EV_P_ ev_io *w, int revents)
|
||||
}
|
||||
goto fail;
|
||||
}
|
||||
|
||||
memcpy(&length, &buffer[1], 2);
|
||||
buffer_size = ret - 3;
|
||||
|
||||
@@ -743,13 +770,19 @@ static void ctl_cmd_wacher_cb(EV_P_ ev_io *w, int revents)
|
||||
(unsigned)buffer[0]);
|
||||
break;
|
||||
} else if (methods[i].cmd == buffer[0]) {
|
||||
indef = methods[i].indefinite;
|
||||
methods[i].func(&ctx, wst->fd, buffer + 3, buffer_size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
if (indef) {
|
||||
talloc_free(ctx.pool);
|
||||
return;
|
||||
}
|
||||
fail:
|
||||
if (s->top_fd == wst->fd)
|
||||
s->top_fd = -1;
|
||||
close(wst->fd);
|
||||
ev_io_stop(EV_A_ w);
|
||||
talloc_free(wst);
|
||||
@@ -810,3 +843,53 @@ void ctl_handler_run_pending(main_server_st* s, ev_io *watcher)
|
||||
|
||||
ctl_handle_commands(s);
|
||||
}
|
||||
|
||||
void ctl_handler_notify (main_server_st* s, struct proc_st *proc, unsigned connect)
|
||||
{
|
||||
TopUpdateRep rep = TOP_UPDATE_REP__INIT;
|
||||
UserListRep list = USER_LIST_REP__INIT;
|
||||
int ret;
|
||||
method_ctx ctx;
|
||||
void *pool = talloc_new(proc);
|
||||
|
||||
if (s->top_fd == -1)
|
||||
return;
|
||||
|
||||
if (pool == NULL) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ctx.s = s;
|
||||
ctx.pool = pool;
|
||||
|
||||
mslog(s, NULL, LOG_DEBUG, "ctl: top update");
|
||||
|
||||
rep.connected = connect;
|
||||
if (connect == 0 && proc->discon_reason) {
|
||||
rep.has_discon_reason = 1;
|
||||
rep.discon_reason = proc->discon_reason;
|
||||
rep.discon_reason_txt = (char*)discon_reason_to_str(proc->discon_reason);
|
||||
}
|
||||
|
||||
ret = append_user_info(&ctx, &list, proc);
|
||||
if (ret < 0) {
|
||||
mslog(s, NULL, LOG_ERR,
|
||||
"error appending user info to reply");
|
||||
goto fail;
|
||||
}
|
||||
rep.user = &list;
|
||||
|
||||
ret = send_msg(pool, s->top_fd, CTL_CMD_TOP_UPDATE_REP, &rep,
|
||||
(pack_size_func) top_update_rep__get_packed_size,
|
||||
(pack_func) top_update_rep__pack);
|
||||
if (ret < 0) {
|
||||
mslog(s, NULL, LOG_ERR, "error sending ctl reply");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
talloc_free(pool);
|
||||
return;
|
||||
fail:
|
||||
talloc_free(pool);
|
||||
s->top_fd = -1;
|
||||
}
|
||||
|
||||
@@ -9,5 +9,6 @@ void ctl_handler_deinit(main_server_st* s);
|
||||
|
||||
void ctl_handler_set_fds(main_server_st* s, ev_io *watcher);
|
||||
void ctl_handler_run_pending(main_server_st* s, ev_io *watcher);
|
||||
void ctl_handler_notify (main_server_st* s, struct proc_st *proc, unsigned connect);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -181,7 +181,8 @@ struct proc_st *ctmp;
|
||||
*/
|
||||
void remove_proc(main_server_st * s, struct proc_st *proc, unsigned flags)
|
||||
{
|
||||
mslog(s, proc, LOG_INFO, "user disconnected (rx: %"PRIu64", tx: %"PRIu64")", proc->bytes_in, proc->bytes_out);
|
||||
mslog(s, proc, LOG_INFO, "user disconnected (reason: %s, rx: %"PRIu64", tx: %"PRIu64")",
|
||||
discon_reason_to_str(proc->discon_reason), proc->bytes_in, proc->bytes_out);
|
||||
|
||||
ev_io_stop(EV_A_ &proc->io);
|
||||
ev_child_stop(EV_A_ &proc->ev_child);
|
||||
|
||||
@@ -528,6 +528,8 @@ int session_close(main_server_st * s, struct proc_st *proc)
|
||||
proc->bytes_out = msg->bytes_out;
|
||||
if (msg->has_secmod_client_entries)
|
||||
s->secmod_client_entries = msg->secmod_client_entries;
|
||||
if (msg->has_discon_reason)
|
||||
proc->discon_reason = msg->discon_reason;
|
||||
|
||||
cli_stats_msg__free_unpacked(msg, &pa);
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
#include <cookies.h>
|
||||
#include <tun.h>
|
||||
#include <main.h>
|
||||
#include <main-ctl.h>
|
||||
#include <ip-lease.h>
|
||||
#include <script-list.h>
|
||||
#include <ccan/list/list.h>
|
||||
@@ -436,6 +437,7 @@ int user_connected(main_server_st *s, struct proc_st* proc)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ctl_handler_notify(s,proc, 1);
|
||||
add_utmp_entry(s, proc);
|
||||
|
||||
ret = call_script(s, proc, 1);
|
||||
@@ -447,6 +449,7 @@ int ret;
|
||||
|
||||
void user_disconnected(main_server_st *s, struct proc_st* proc)
|
||||
{
|
||||
ctl_handler_notify(s,proc, 0);
|
||||
remove_utmp_entry(s, proc);
|
||||
call_script(s, proc, 0);
|
||||
}
|
||||
|
||||
@@ -975,6 +975,7 @@ static void listen_watcher_cb (EV_P_ ev_io *w, int revents)
|
||||
sigprocmask(SIG_SETMASK, &sig_default_set, NULL);
|
||||
close(cmd_fd[0]);
|
||||
clear_lists(s);
|
||||
if (s->top_fd != -1) close(s->top_fd);
|
||||
close(s->sec_mod_fd);
|
||||
close(s->sec_mod_fd_sync);
|
||||
|
||||
@@ -1195,6 +1196,7 @@ int main(int argc, char** argv)
|
||||
|
||||
write_pid_file();
|
||||
|
||||
s->top_fd = -1;
|
||||
s->sec_mod_fd = run_sec_mod(s, &s->sec_mod_fd_sync);
|
||||
ret = ctl_handler_init(s);
|
||||
if (ret < 0) {
|
||||
|
||||
@@ -155,6 +155,7 @@ typedef struct proc_st {
|
||||
* Cli stats message. */
|
||||
uint64_t bytes_in;
|
||||
uint64_t bytes_out;
|
||||
uint32_t discon_reason; /* filled on session close */
|
||||
|
||||
unsigned applied_iroutes; /* whether the iroutes in the config have been successfully applied */
|
||||
|
||||
@@ -223,6 +224,7 @@ typedef struct main_server_st {
|
||||
/* This one is on worker pool */
|
||||
struct worker_st *ws;
|
||||
|
||||
int top_fd;
|
||||
int ctl_fd;
|
||||
|
||||
int sec_mod_fd; /* messages are sent and received async */
|
||||
|
||||
@@ -14,6 +14,7 @@ enum {
|
||||
CTL_CMD_DISCONNECT_ID,
|
||||
CTL_CMD_LIST_BANNED,
|
||||
CTL_CMD_UNBAN_IP,
|
||||
CTL_CMD_TOP,
|
||||
|
||||
CTL_CMD_STATUS_REP = 101,
|
||||
CTL_CMD_RELOAD_REP,
|
||||
@@ -23,6 +24,7 @@ enum {
|
||||
CTL_CMD_DISCONNECT_ID_REP,
|
||||
CTL_CMD_UNBAN_IP_REP,
|
||||
CTL_CMD_LIST_BANNED_REP,
|
||||
CTL_CMD_TOP_UPDATE_REP
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Red Hat
|
||||
* Copyright (C) 2014, 2015 Red Hat
|
||||
*
|
||||
* Author: Nikos Mavrogiannopoulos
|
||||
*
|
||||
@@ -24,7 +24,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <signal.h>
|
||||
#include <system.h>
|
||||
#include <c-ctype.h>
|
||||
#include <occtl/occtl.h>
|
||||
#include <c-strcase.h>
|
||||
@@ -67,6 +67,8 @@ static const commands_st commands[] = {
|
||||
"Prints information on the specified user", 1, 1),
|
||||
ENTRY("show id", "[ID]", handle_show_id_cmd,
|
||||
"Prints information on the specified ID", 1, 1),
|
||||
ENTRY("show events", NULL, handle_events_cmd,
|
||||
"Provides information about connecting users", 1, 1),
|
||||
ENTRY("stop", "now", handle_stop_cmd,
|
||||
"Terminates the server", 1, 1),
|
||||
ENTRY("reset", NULL, handle_reset_cmd, "Resets the screen and terminal",
|
||||
@@ -498,7 +500,7 @@ void initialize_readline(void)
|
||||
#ifdef HAVE_ORIG_READLINE
|
||||
rl_clear_signals();
|
||||
#endif
|
||||
signal(SIGINT, handle_sigint);
|
||||
ocsignal(SIGINT, handle_sigint);
|
||||
}
|
||||
|
||||
static int single_cmd(int argc, char **argv, void *pool, const char *file, cmd_params_st *params)
|
||||
@@ -533,8 +535,7 @@ int main(int argc, char **argv)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
|
||||
ocsignal(SIGPIPE, SIG_IGN);
|
||||
|
||||
if (argc > 1) {
|
||||
while (argc > 1 && argv[1][0] == '-') {
|
||||
|
||||
@@ -86,5 +86,6 @@ 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);
|
||||
int handle_events_cmd(struct unix_ctx *ctx, const char *arg, cmd_params_st *params);
|
||||
|
||||
#endif
|
||||
|
||||
275
src/occtl/unix.c
275
src/occtl/unix.c
@@ -34,7 +34,12 @@
|
||||
#include <c-strcase.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <system.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#include <minmax.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/socket.h>
|
||||
@@ -56,6 +61,7 @@ static uint8_t msg_map[] = {
|
||||
[CTL_CMD_LIST] = CTL_CMD_LIST_REP,
|
||||
[CTL_CMD_LIST_BANNED] = CTL_CMD_LIST_BANNED_REP,
|
||||
[CTL_CMD_USER_INFO] = CTL_CMD_LIST_REP,
|
||||
[CTL_CMD_TOP] = CTL_CMD_LIST_REP,
|
||||
[CTL_CMD_ID_INFO] = CTL_CMD_LIST_REP,
|
||||
[CTL_CMD_DISCONNECT_NAME] = CTL_CMD_DISCONNECT_NAME_REP,
|
||||
[CTL_CMD_DISCONNECT_ID] = CTL_CMD_DISCONNECT_ID_REP,
|
||||
@@ -526,35 +532,35 @@ int handle_disconnect_id_cmd(struct unix_ctx *ctx, const char *arg, cmd_params_s
|
||||
return ret;
|
||||
}
|
||||
|
||||
int handle_list_users_cmd(struct unix_ctx *ctx, const char *arg, cmd_params_st *params)
|
||||
static const char *fix_ciphersuite(char *txt)
|
||||
{
|
||||
if (txt != NULL && txt[0] != 0) {
|
||||
if (strlen(txt) > 16 && strncmp(txt, "(DTLS", 5) == 0 &&
|
||||
strncmp(&txt[8], ")-(RSA)-", 8) == 0) {
|
||||
return txt + 16;
|
||||
}
|
||||
}
|
||||
|
||||
return "(no dtls)";
|
||||
}
|
||||
|
||||
static const char *get_ip(const char *ip1, const char *ip2)
|
||||
{
|
||||
if (ip1 != NULL && ip1[0] != 0)
|
||||
return ip1;
|
||||
else
|
||||
return ip2;
|
||||
}
|
||||
|
||||
void common_user_list(struct unix_ctx *ctx, UserListRep *rep, FILE *out, cmd_params_st *params)
|
||||
{
|
||||
int ret;
|
||||
struct cmd_reply_st raw;
|
||||
UserListRep *rep = NULL;
|
||||
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;
|
||||
char str_since[64];
|
||||
PROTOBUF_ALLOCATOR(pa, ctx);
|
||||
|
||||
init_reply(&raw);
|
||||
|
||||
entries_clear();
|
||||
|
||||
out = pager_start(params);
|
||||
|
||||
ret = send_cmd(ctx, CTL_CMD_LIST, NULL, NULL, NULL, &raw);
|
||||
if (ret < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
rep = user_list_rep__unpack(&pa, raw.data_size, raw.data);
|
||||
if (rep == NULL)
|
||||
goto error;
|
||||
|
||||
if (HAVE_JSON(params)) {
|
||||
common_info_cmd(rep, out, params);
|
||||
@@ -563,10 +569,7 @@ int handle_list_users_cmd(struct unix_ctx *ctx, const char *arg, cmd_params_st *
|
||||
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
|
||||
vpn_ip = rep->user[i]->local_ip6;
|
||||
vpn_ip = get_ip(rep->user[i]->local_ip, rep->user[i]->local_ip6);
|
||||
|
||||
/* add header */
|
||||
if (i == 0) {
|
||||
@@ -588,18 +591,38 @@ int handle_list_users_cmd(struct unix_ctx *ctx, const char *arg, cmd_params_st *
|
||||
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);
|
||||
|
||||
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, "%s %14s %9s\n", tmpbuf, dtls_ciphersuite, rep->user[i]->status);
|
||||
} else {
|
||||
fprintf(out, "%s %14s %9s\n", tmpbuf, "(no dtls)", rep->user[i]->status);
|
||||
}
|
||||
dtls_ciphersuite = fix_ciphersuite(rep->user[i]->dtls_ciphersuite);
|
||||
|
||||
fprintf(out, "%s %14s %9s\n", tmpbuf, dtls_ciphersuite, rep->user[i]->status);
|
||||
|
||||
entries_add(ctx, username, strlen(username), rep->user[i]->id);
|
||||
}
|
||||
}
|
||||
|
||||
int handle_list_users_cmd(struct unix_ctx *ctx, const char *arg, cmd_params_st *params)
|
||||
{
|
||||
int ret;
|
||||
struct cmd_reply_st raw;
|
||||
UserListRep *rep = NULL;
|
||||
FILE *out;
|
||||
PROTOBUF_ALLOCATOR(pa, ctx);
|
||||
|
||||
init_reply(&raw);
|
||||
|
||||
entries_clear();
|
||||
|
||||
out = pager_start(params);
|
||||
|
||||
ret = send_cmd(ctx, CTL_CMD_LIST, NULL, NULL, NULL, &raw);
|
||||
if (ret < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
rep = user_list_rep__unpack(&pa, raw.data_size, raw.data);
|
||||
if (rep == NULL)
|
||||
goto error;
|
||||
|
||||
common_user_list(ctx, rep, out, params);
|
||||
|
||||
ret = 0;
|
||||
goto cleanup;
|
||||
@@ -924,6 +947,8 @@ int handle_show_user_cmd(struct unix_ctx *ctx, const char *arg, cmd_params_st *p
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
||||
|
||||
|
||||
goto cleanup;
|
||||
|
||||
error:
|
||||
@@ -937,6 +962,188 @@ int handle_show_user_cmd(struct unix_ctx *ctx, const char *arg, cmd_params_st *p
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void dummy_sighandler(int signo)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
int handle_events_cmd(struct unix_ctx *ctx, const char *arg, cmd_params_st *params)
|
||||
{
|
||||
uint8_t header[3];
|
||||
int ret;
|
||||
struct cmd_reply_st raw;
|
||||
UserListRep *rep1 = NULL;
|
||||
TopUpdateRep *rep2 = NULL;
|
||||
uint16_t length;
|
||||
unsigned data_size;
|
||||
uint8_t *data = NULL;
|
||||
char *groupname;
|
||||
char tmpbuf[MAX_TMPSTR_SIZE];
|
||||
PROTOBUF_ALLOCATOR(pa, ctx);
|
||||
struct termios tio_old, tio_new;
|
||||
sighandler_t old_sighandler;
|
||||
|
||||
init_reply(&raw);
|
||||
|
||||
ret = send_cmd(ctx, CTL_CMD_TOP, NULL, 0, 0, &raw);
|
||||
if (ret < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
rep1 = user_list_rep__unpack(&pa, raw.data_size, raw.data);
|
||||
if (rep1 == NULL)
|
||||
goto error;
|
||||
|
||||
common_user_list(ctx, rep1, stdout, params);
|
||||
|
||||
user_list_rep__free_unpacked(rep1, &pa);
|
||||
rep1 = NULL;
|
||||
|
||||
fputs("\n", stdout);
|
||||
fputs("Press 'q' or CTRL+C to quit\n\n", stdout);
|
||||
|
||||
old_sighandler = ocsignal(SIGINT, dummy_sighandler);
|
||||
tcgetattr(STDIN_FILENO, &tio_old);
|
||||
tio_new = tio_old;
|
||||
tio_new.c_lflag &= ~(ICANON|ECHO);
|
||||
tcsetattr(STDIN_FILENO, TCSANOW, &tio_new);
|
||||
|
||||
/* start listening for updates */
|
||||
while(1) {
|
||||
fd_set rfds;
|
||||
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(STDIN_FILENO, &rfds);
|
||||
FD_SET(ctx->fd, &rfds);
|
||||
|
||||
ret = select(MAX(STDIN_FILENO,ctx->fd)+1, &rfds, NULL, NULL, NULL);
|
||||
if (ret == -1 && errno == EINTR) {
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret == -1) {
|
||||
int e = errno;
|
||||
fprintf(stderr, "top: select: %s\n", strerror(e));
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (FD_ISSET(STDIN_FILENO, &rfds)) {
|
||||
ret = getchar();
|
||||
if (ret == 'q' || ret == 'Q') {
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!FD_ISSET(ctx->fd, &rfds))
|
||||
continue;
|
||||
|
||||
ret = read(ctx->fd, header, 3);
|
||||
if (ret == -1) {
|
||||
int e = errno;
|
||||
fprintf(stderr, "top: read1: %s\n", strerror(e));
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
fprintf(stderr, "top: server closed the connection\n");
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret != 3) {
|
||||
fprintf(stderr, "top: short read %d\n", ret);
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (header[0] != CTL_CMD_TOP_UPDATE_REP) {
|
||||
fprintf(stderr, "top: Unexpected message '%d', expected '%d'\n", (int)header[0], (int)CTL_CMD_TOP_UPDATE_REP);
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
memcpy(&length, &header[1], 2);
|
||||
|
||||
data_size = length;
|
||||
data = talloc_size(ctx, length);
|
||||
if (data == NULL) {
|
||||
fprintf(stderr, "top: memory error\n");
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = read(ctx->fd, data, data_size);
|
||||
if (ret == -1) {
|
||||
int e = errno;
|
||||
fprintf(stderr, "top: read: %s\n", strerror(e));
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* parse and print */
|
||||
rep2 = top_update_rep__unpack(&pa, data_size, data);
|
||||
if (rep2 == NULL)
|
||||
goto error;
|
||||
|
||||
if (HAVE_JSON(params)) {
|
||||
if (rep2->connected == 0)
|
||||
rep2->user->user[0]->status = talloc_strdup(rep2, "disconnected");
|
||||
else
|
||||
rep2->user->user[0]->status = talloc_strdup(rep2, "connected");
|
||||
common_info_cmd(rep2->user, stdout, params);
|
||||
} else {
|
||||
groupname = rep2->user->user[0]->groupname;
|
||||
if (groupname == NULL || groupname[0] == 0)
|
||||
groupname = NO_GROUP;
|
||||
|
||||
if (rep2->connected) {
|
||||
printf("connected user '%s' (%u) from %s with IP %s\n",
|
||||
rep2->user->user[0]->username,
|
||||
rep2->user->user[0]->id,
|
||||
rep2->user->user[0]->ip,
|
||||
get_ip(rep2->user->user[0]->local_ip,
|
||||
rep2->user->user[0]->local_ip6));
|
||||
|
||||
entries_add(ctx, rep2->user->user[0]->username, strlen(rep2->user->user[0]->username), rep2->user->user[0]->id);
|
||||
} else {
|
||||
print_time_ival7(tmpbuf, time(0), rep2->user->user[0]->conn_time);
|
||||
printf("disconnect user '%s' (%u) from %s with IP %s (reason: %s, time: %s)\n",
|
||||
rep2->user->user[0]->username,
|
||||
rep2->user->user[0]->id,
|
||||
rep2->user->user[0]->ip,
|
||||
get_ip(rep2->user->user[0]->local_ip, rep2->user->user[0]->local_ip6),
|
||||
rep2->discon_reason_txt?rep2->discon_reason_txt:"unknown", tmpbuf);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
top_update_rep__free_unpacked(rep2, &pa);
|
||||
rep2 = NULL;
|
||||
}
|
||||
|
||||
tcsetattr(STDIN_FILENO, TCSANOW, &tio_old);
|
||||
ocsignal(SIGINT, old_sighandler);
|
||||
goto cleanup;
|
||||
|
||||
error:
|
||||
fprintf(stderr, ERR_SERVER_UNREACHABLE);
|
||||
ret = 1;
|
||||
cleanup:
|
||||
talloc_free(data);
|
||||
if (rep1 != NULL)
|
||||
user_list_rep__free_unpacked(rep1, &pa);
|
||||
if (rep2 != NULL)
|
||||
top_update_rep__free_unpacked(rep2, &pa);
|
||||
free_reply(&raw);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int handle_show_id_cmd(struct unix_ctx *ctx, const char *arg, cmd_params_st *params)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@@ -537,6 +537,8 @@ int handle_sec_auth_session_close(sec_mod_st *sec, int fd, const SecAuthSessionM
|
||||
rep.bytes_in = e->stats.bytes_in;
|
||||
rep.bytes_out = e->stats.bytes_out;
|
||||
rep.has_secmod_client_entries = 1;
|
||||
rep.has_discon_reason = 1;
|
||||
rep.discon_reason = e->discon_reason;
|
||||
rep.secmod_client_entries = sec_mod_client_db_elems(sec);
|
||||
|
||||
ret = send_msg(e, fd, SM_CMD_AUTH_CLI_STATS, &rep,
|
||||
|
||||
Reference in New Issue
Block a user