summaryrefslogtreecommitdiff
path: root/accel-pppd/cli/show_sessions.c
diff options
context:
space:
mode:
Diffstat (limited to 'accel-pppd/cli/show_sessions.c')
-rw-r--r--accel-pppd/cli/show_sessions.c434
1 files changed, 434 insertions, 0 deletions
diff --git a/accel-pppd/cli/show_sessions.c b/accel-pppd/cli/show_sessions.c
new file mode 100644
index 00000000..90aeb3fc
--- /dev/null
+++ b/accel-pppd/cli/show_sessions.c
@@ -0,0 +1,434 @@
+#include <stdio.h>
+#include <time.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <arpa/inet.h>
+
+#include "triton.h"
+#include "events.h"
+#include "ppp.h"
+#include "cli.h"
+#include "utils.h"
+#include "log.h"
+#include "memdebug.h"
+
+#define CELL_SIZE 128
+#define DEF_COLUMNS "ifname,username,calling-sid,ip,rate-limit,type,state,uptime"
+
+struct column_t
+{
+ struct list_head entry;
+ const char *name;
+ const char *desc;
+ void (*print)(const struct ppp_t *ppp, char *buf);
+};
+
+struct col_t
+{
+ struct list_head entry;
+ struct column_t *column;
+ int width;
+};
+
+struct row_t
+{
+ struct list_head entry;
+ char *match_key;
+ char *order_key;
+ struct list_head cell_list;
+};
+
+struct cell_t
+{
+ struct list_head entry;
+ struct col_t *col;
+ char buf[CELL_SIZE + 1];
+};
+
+static LIST_HEAD(col_list);
+
+void __export cli_show_ses_register(const char *name, const char *desc, void (*print)(const struct ppp_t *ppp, char *buf))
+{
+ struct column_t *c = malloc(sizeof(*c));
+ c->name = name;
+ c->desc = desc;
+ c->print = print;
+ list_add_tail(&c->entry, &col_list);
+}
+
+static void show_ses_help(char * const *f, int f_cnt, void *cli)
+{
+ struct column_t *col;
+ char buf[129];
+
+ cli_send(cli, "show sessions [columns] [order <column>] [match <column> <regexp>] - shows sessions\r\n");
+ cli_send(cli, "\tcolumns:\r\n");
+
+ list_for_each_entry(col, &col_list, entry) {
+ snprintf(buf, 128, "\t\t%s - %s\r\n", col->name, col->desc);
+ cli_send(cli, buf);
+ }
+}
+
+static struct column_t *find_column(const char *name)
+{
+ struct column_t *col;
+
+ list_for_each_entry(col, &col_list, entry) {
+ if (strcmp(col->name, name))
+ continue;
+ return col;
+ }
+
+ return NULL;
+}
+
+static void free_row(struct row_t *row)
+{
+ struct cell_t *cell;
+
+ while (!list_empty(&row->cell_list)) {
+ cell = list_entry(row->cell_list.next, typeof(*cell), entry);
+ list_del(&cell->entry);
+ _free(cell);
+ }
+
+ _free(row);
+}
+
+static void insert_row(struct list_head *list, struct row_t *row)
+{
+ struct row_t *row2, *row3;
+
+ row3 = NULL;
+ list_for_each_entry(row2, list, entry) {
+ if (strcmp(row->order_key, row2->order_key) <= 0) {
+ row3 = row2;
+ break;
+ }
+ }
+ if (row3)
+ list_add_tail(&row->entry, &row3->entry);
+ else
+ list_add_tail(&row->entry, list);
+}
+
+static int show_ses_exec(const char *cmd, char * const *f, int f_cnt, void *cli)
+{
+ char *columns = NULL;
+ struct column_t *match_key = NULL;
+ char *match_pattern = NULL;
+ struct column_t *order_key = NULL;
+ pcre *re = NULL;
+ const char *pcre_err;
+ int pcre_offset;
+ struct column_t *column;
+ struct col_t *col;
+ struct row_t *row;
+ struct cell_t *cell;
+ char *ptr1, *ptr2;
+ int i, n, total_width, def_columns = 0;
+ struct ppp_t *ppp;
+ char *buf = NULL;
+ LIST_HEAD(c_list);
+ LIST_HEAD(r_list);
+ LIST_HEAD(t_list);
+
+ for (i = 2; i < f_cnt; i++) {
+ if (!strcmp(f[i], "order")) {
+ if (i == f_cnt - 1)
+ return CLI_CMD_SYNTAX;
+ order_key = find_column(f[++i]);
+ if (!order_key) {
+ cli_sendv(cli, "unknown column %s\r\n", f[i]);
+ return CLI_CMD_OK;
+ }
+ } else if (!strcmp(f[i], "match")) {
+ if (i == f_cnt - 2)
+ return CLI_CMD_SYNTAX;
+ match_key = find_column(f[++i]);
+ if (!match_key) {
+ cli_sendv(cli, "unknown column %s\r\n", f[i]);
+ return CLI_CMD_OK;
+ }
+ match_pattern = f[++i];
+ } else if (!columns)
+ columns = f[i];
+ else
+ return CLI_CMD_SYNTAX;
+ }
+
+ if (match_key) {
+ re = pcre_compile2(match_pattern, 0, NULL, &pcre_err, &pcre_offset, NULL);
+ if (!re) {
+ cli_sendv(cli, "match: %s at %i\r\n", pcre_err, pcre_offset);
+ return CLI_CMD_OK;
+ }
+ }
+
+ if (!columns) {
+ columns = DEF_COLUMNS;
+ def_columns = 1;
+ }
+
+ columns = _strdup(columns);
+ ptr1 = columns;
+ while (1) {
+ ptr2 = strchr(ptr1, ',');
+ if (ptr2)
+ *ptr2 = 0;
+ column = find_column(ptr1);
+ if (column) {
+ col = _malloc(sizeof(*col));
+ col->column = column;
+ col->width = strlen(column->name);
+ list_add_tail(&col->entry, &c_list);
+ } else {
+ if (!def_columns) {
+ cli_sendv(cli, "unknown column %s\r\n", ptr1);
+ _free(columns);
+ goto out;
+ }
+ }
+ if (!ptr2)
+ break;
+ ptr1 = ptr2 + 1;
+ }
+ _free(columns);
+
+ pthread_rwlock_rdlock(&ppp_lock);
+ list_for_each_entry(ppp, &ppp_list, entry) {
+ row = _malloc(sizeof(*row));
+ if (!row)
+ goto oom;
+ memset(row, 0, sizeof(*row));
+ INIT_LIST_HEAD(&row->cell_list);
+ if (match_key || order_key)
+ list_add_tail(&row->entry, &t_list);
+ else
+ list_add_tail(&row->entry, &r_list);
+ list_for_each_entry(col, &c_list, entry) {
+ cell = _malloc(sizeof(*cell));
+ if (!cell)
+ goto oom;
+ cell->col = col;
+ list_add_tail(&cell->entry, &row->cell_list);
+ col->column->print(ppp, cell->buf);
+ n = strlen(cell->buf);
+ if (n > col->width)
+ col->width = n;
+ if (col->column == order_key)
+ row->order_key = cell->buf;
+ if (col->column == match_key)
+ row->match_key = cell->buf;
+ }
+ }
+ pthread_rwlock_unlock(&ppp_lock);
+
+ if (order_key || match_key) {
+ while(!list_empty(&t_list)) {
+ row = list_entry(t_list.next, typeof(*row), entry);
+ list_del(&row->entry);
+ if (match_key) {
+ if (pcre_exec(re, NULL, row->match_key, strlen(row->match_key), 0, 0, NULL, 0) < 0) {
+ free_row(row);
+ continue;
+ }
+ }
+ if (order_key)
+ insert_row(&r_list, row);
+ else
+ list_add_tail(&row->entry, &r_list);
+ }
+ }
+
+ total_width = -1;
+ list_for_each_entry(col, &c_list, entry)
+ total_width += col->width + 3;
+
+ buf = _malloc(total_width + 3);
+ if (!buf)
+ goto oom;
+
+ ptr1 = buf;
+ list_for_each_entry(col, &c_list, entry) {
+ n = strlen(col->column->name);
+ if (col->width > n + 1) {
+ ptr2 = ptr1;
+ memset(ptr1, ' ', col->width/2 - n/2 + 1);
+ ptr1 += col->width/2 - n/2 + 1;
+ sprintf(ptr1, "%s", col->column->name);
+ ptr1 = strchr(ptr1, 0);
+ memset(ptr1, ' ', col->width + 2 - (ptr1 - ptr2));
+ ptr1 += col->width + 2 - (ptr1 - ptr2);
+ *ptr1 = '|';
+ ptr1++;
+ } else if (col->width > n) {
+ sprintf(ptr1, " %s |", col->column->name);
+ ptr1 = strchr(ptr1, 0);
+ } else {
+ sprintf(ptr1, " %s |", col->column->name);
+ ptr1 = strchr(ptr1, 0);
+ }
+ }
+
+ strcpy(ptr1 - 1, "\r\n");
+ cli_send(cli, buf);
+
+ ptr1 = buf;
+ list_for_each_entry(col, &c_list, entry) {
+ memset(ptr1, '-', col->width + 2);
+ ptr1 += col->width + 2;
+ *ptr1 = '+';
+ ptr1++;
+ }
+
+ strcpy(ptr1 - 1, "\r\n");
+ cli_send(cli, buf);
+
+ while (!list_empty(&r_list)) {
+ row = list_entry(r_list.next, typeof(*row), entry);
+ ptr1 = buf;
+ list_for_each_entry(cell, &row->cell_list, entry) {
+ ptr2 = ptr1;
+ sprintf(ptr1, " %s ", cell->buf);
+ ptr1 = strchr(ptr1, 0);
+ n = ptr1 - ptr2;
+ if (n - 2 < cell->col->width) {
+ memset(ptr1, ' ', cell->col->width + 2 - (ptr1 - ptr2));
+ ptr1 += cell->col->width + 2 - (ptr1 - ptr2);
+ }
+ *ptr1 = '|';
+ ptr1++;
+ }
+ strcpy(ptr1 - 1, "\r\n");
+ cli_send(cli, buf);
+ list_del(&row->entry);
+ free_row(row);
+ }
+
+ _free(buf);
+
+out:
+ while (!list_empty(&c_list)) {
+ col = list_entry(c_list.next, typeof(*col), entry);
+ list_del(&col->entry);
+ _free(col);
+ }
+
+ if (re)
+ pcre_free(re);
+
+ return CLI_CMD_OK;
+
+oom:
+ if (buf)
+ _free(buf);
+
+ while (!list_empty(&t_list)) {
+ row = list_entry(t_list.next, typeof(*row), entry);
+ list_del(&row->entry);
+ free_row(row);
+ }
+ cli_send(cli, "out of memory");
+ goto out;
+}
+
+static void print_ifname(const struct ppp_t *ppp, char *buf)
+{
+ snprintf(buf, CELL_SIZE, "%s", ppp->ifname);
+}
+
+static void print_username(const struct ppp_t *ppp, char *buf)
+{
+ if (ppp->username)
+ snprintf(buf, CELL_SIZE, "%s", ppp->username);
+}
+
+static void print_ip(const struct ppp_t *ppp, char *buf)
+{
+ char str[17];
+ u_inet_ntoa(ppp->peer_ipaddr, str);
+ sprintf(buf, "%s", str);
+}
+
+static void print_type(const struct ppp_t *ppp, char *buf)
+{
+ snprintf(buf, CELL_SIZE, "%s", ppp->ctrl->name);
+}
+
+static void print_state(const struct ppp_t *ppp, char *buf)
+{
+ char *state;
+ switch (ppp->state) {
+ case PPP_STATE_STARTING:
+ state = "start";
+ break;
+ case PPP_STATE_ACTIVE:
+ state = "active";
+ break;
+ case PPP_STATE_FINISHING:
+ state = "finish";
+ break;
+ default:
+ state = "unk";
+ }
+ sprintf(buf, "%s", state);
+}
+
+static void print_uptime(const struct ppp_t *ppp, char *buf)
+{
+ time_t uptime;
+ int day,hour,min,sec;
+ char time_str[14];
+
+ if (ppp->stop_time)
+ uptime = ppp->stop_time - ppp->start_time;
+ else {
+ time(&uptime);
+ uptime -= ppp->start_time;
+ }
+
+ day = uptime/ (24*60*60); uptime %= (24*60*60);
+ hour = uptime / (60*60); uptime %= (60*60);
+ min = uptime / 60;
+ sec = uptime % 60;
+ if (day)
+ snprintf(time_str, 13, "%i.%02i:%02i:%02i", day, hour, min, sec);
+ else
+ snprintf(time_str, 13, "%02i:%02i:%02i", hour, min, sec);
+
+ sprintf(buf, "%s", time_str);
+}
+
+static void print_calling_sid(const struct ppp_t *ppp, char *buf)
+{
+ snprintf(buf, CELL_SIZE, "%s", ppp->ctrl->calling_station_id);
+}
+
+static void print_called_sid(const struct ppp_t *ppp, char *buf)
+{
+ snprintf(buf, CELL_SIZE, "%s", ppp->ctrl->called_station_id);
+}
+
+static void print_sid(const struct ppp_t *ppp, char *buf)
+{
+ snprintf(buf, CELL_SIZE, "%s", ppp->sessionid);
+}
+
+void __init init(void)
+{
+ cli_register_simple_cmd2(show_ses_exec, show_ses_help, 2, "show", "sessions");
+
+ cli_show_ses_register("ifname", "interface name", print_ifname);
+ cli_show_ses_register("username", "user name", print_username);
+ cli_show_ses_register("ip", "IP address", print_ip);
+ cli_show_ses_register("type", "VPN type", print_type);
+ cli_show_ses_register("state", "state of session", print_state);
+ cli_show_ses_register("uptime", "uptime", print_uptime);
+ cli_show_ses_register("calling-sid", "calling station id", print_calling_sid);
+ cli_show_ses_register("called-sid", "called station id", print_called_sid);
+ cli_show_ses_register("sid", "session id", print_sid);
+}
+