diff options
Diffstat (limited to 'accel-pptpd/cli')
-rw-r--r-- | accel-pptpd/cli/CMakeLists.txt | 1 | ||||
-rw-r--r-- | accel-pptpd/cli/cli.c | 227 | ||||
-rw-r--r-- | accel-pptpd/cli/cli.h | 48 | ||||
-rw-r--r-- | accel-pptpd/cli/cli_p.h | 22 | ||||
-rw-r--r-- | accel-pptpd/cli/show_sessions.c | 434 | ||||
-rw-r--r-- | accel-pptpd/cli/std_cmd.c | 324 | ||||
-rw-r--r-- | accel-pptpd/cli/tcp.c | 371 | ||||
-rw-r--r-- | accel-pptpd/cli/telnet.c | 757 |
8 files changed, 0 insertions, 2184 deletions
diff --git a/accel-pptpd/cli/CMakeLists.txt b/accel-pptpd/cli/CMakeLists.txt deleted file mode 100644 index 8b137891..00000000 --- a/accel-pptpd/cli/CMakeLists.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/accel-pptpd/cli/cli.c b/accel-pptpd/cli/cli.c deleted file mode 100644 index ef168ded..00000000 --- a/accel-pptpd/cli/cli.c +++ /dev/null @@ -1,227 +0,0 @@ -#include <stdlib.h> -#include <stdarg.h> -#include <string.h> -#include <unistd.h> - -#include "triton.h" - -#include "cli.h" -#include "cli_p.h" -#include "log.h" -#include "events.h" - -#include "memdebug.h" - -#define MAX_CMD_ITEMS 100 -#define MSG_SYNTAX_ERROR "syntax error\r\n" -#define MSG_INVAL_ERROR "invalid argument\r\n" -#define MSG_UNKNOWN_CMD "command unknown\r\n" - -char *conf_cli_passwd; -static const char *def_cli_prompt = "accel-pptp"; -char *conf_cli_prompt; - -static LIST_HEAD(simple_cmd_list); -static LIST_HEAD(regexp_cmd_list); - -void __export cli_register_simple_cmd(struct cli_simple_cmd_t *cmd) -{ - list_add_tail(&cmd->entry, &simple_cmd_list); -} - -void __export cli_register_simple_cmd2( - int (*exec)(const char *cmd, char * const *fields, int fields_cnt, void *client), - void (*help)(char * const *fields, int fields_cnt, void *client), - int hdr_len, - ... - ) -{ - struct cli_simple_cmd_t *c; - int i; - va_list ap; - - va_start(ap, hdr_len); - - c = malloc(sizeof(*c)); - memset(c, 0, sizeof(*c)); - - c->exec = exec; - c->help = help; - c->hdr_len = hdr_len; - c->hdr = malloc(hdr_len * sizeof(void*)); - - for (i = 0; i < hdr_len; i++) - c->hdr[i] = va_arg(ap, char *); - - list_add_tail(&c->entry, &simple_cmd_list); -} - -void __export cli_register_regexp_cmd(struct cli_regexp_cmd_t *cmd) -{ - int err; - cmd->re = pcre_compile2(cmd->pattern, cmd->options, &err, NULL, NULL, NULL); - if (!cmd->re) { - log_emerg("cli: failed to compile regexp %s: %i\n", cmd->pattern, err); - _exit(EXIT_FAILURE); - } - list_add_tail(&cmd->entry, &simple_cmd_list); -} - -int __export cli_send(void *client, const char *data) -{ - struct cli_client_t *cln = (struct cli_client_t *)client; - - return cln->send(cln, data, strlen(data)); -} - -int __export cli_sendv(void *client, const char *fmt, ...) -{ - struct cli_client_t *cln = (struct cli_client_t *)client; - int r; - - va_list ap; - va_start(ap, fmt); - r = cln->sendv(cln, fmt, ap); - va_end(ap); - - return r; -} - - -static char *skip_word(char *ptr) -{ - for(; *ptr; ptr++) - if (*ptr == ' ' || *ptr == '\t' || *ptr == '\n') - break; - return ptr; -} -static char *skip_space(char *ptr) -{ - for(; *ptr; ptr++) - if (*ptr != ' ' && *ptr != '\t') - break; - return ptr; -} -static int split(char *buf, char **ptr) -{ - int i; - - ptr[0] = buf; - - for (i = 1; i <= MAX_CMD_ITEMS; i++) { - buf = skip_word(buf); - if (!*buf) - return i; - - *buf = 0; - - buf = skip_space(buf + 1); - if (!*buf) - return i; - - ptr[i] = buf; - } - - buf = skip_word(buf); - *buf = 0; - - return i; -} - -int cli_process_cmd(struct cli_client_t *cln) -{ - struct cli_simple_cmd_t *cmd1; - struct cli_regexp_cmd_t *cmd2; - char *f[MAX_CMD_ITEMS]; - int r, i, n, found = 0; - - n = split((char *)cln->cmdline, f); - - if (n >= 1 && !strcmp(f[0], "help")) { - list_for_each_entry(cmd1, &simple_cmd_list, entry) - if (cmd1->help) - cmd1->help(f, n, cln); - - list_for_each_entry(cmd2, ®exp_cmd_list, entry) - if (cmd2->help) - cmd1->help(f, n, cln); - - return 0; - } - - list_for_each_entry(cmd1, &simple_cmd_list, entry) { - if (cmd1->hdr_len && n >= cmd1->hdr_len) { - for (i = 0; i < cmd1->hdr_len; i++) { - if (strcmp(cmd1->hdr[i], f[i])) - break; - } - if (i < cmd1->hdr_len) - continue; - r = cmd1->exec((char *)cln->cmdline, f, n, cln); - switch (r) { - case CLI_CMD_EXIT: - cln->disconnect(cln); - case CLI_CMD_FAILED: - return -1; - case CLI_CMD_SYNTAX: - cli_send(cln, MSG_SYNTAX_ERROR); - return 0; - case CLI_CMD_INVAL: - cli_send(cln, MSG_INVAL_ERROR); - return 0; - case CLI_CMD_OK: - found = 1; - } - } - } - - list_for_each_entry(cmd2, ®exp_cmd_list, entry) { - r = cmd2->exec((char *)cln->cmdline, cln); - switch (r) { - case CLI_CMD_EXIT: - cln->disconnect(cln); - case CLI_CMD_FAILED: - return 0; - case CLI_CMD_SYNTAX: - cli_send(cln, MSG_SYNTAX_ERROR); - return 0; - case CLI_CMD_OK: - found = 1; - } - } - - if (!found) { - if (cli_send(cln, MSG_UNKNOWN_CMD)) - return -1; - } - - return 0; -} - -static void load_config(void) -{ - const char *opt; - - if (conf_cli_passwd) - _free(conf_cli_passwd); - opt = conf_get_opt("cli", "password"); - if (opt) - conf_cli_passwd = _strdup(opt); - else - conf_cli_passwd = NULL; - - if (conf_cli_prompt && conf_cli_prompt != def_cli_prompt) - _free(conf_cli_prompt); - opt = conf_get_opt("cli", "prompt"); - if (opt) - conf_cli_prompt = _strdup(opt); - else - conf_cli_prompt = (char *)def_cli_prompt; -} - -static void __init init(void) -{ - load_config(); - - triton_event_register_handler(EV_CONFIG_RELOAD, (triton_event_func)load_config); -} diff --git a/accel-pptpd/cli/cli.h b/accel-pptpd/cli/cli.h deleted file mode 100644 index cdceb2fa..00000000 --- a/accel-pptpd/cli/cli.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef __CLI_H -#define __CLI_H - -#include <pcre.h> -#include <list.h> - -#define CLI_CMD_OK 0 -#define CLI_CMD_FAILED -1 -#define CLI_CMD_EXIT -2 -#define CLI_CMD_SYNTAX 1 -#define CLI_CMD_INVAL 2 - -struct cli_simple_cmd_t -{ - struct list_head entry; - int hdr_len; - const char **hdr; - int (*exec)(const char *cmd, char * const *fields, int fields_cnt, void *client); - void (*help)(char * const *fields, int field_cnt, void *client); -}; - -struct cli_regexp_cmd_t -{ - struct list_head entry; - pcre *re; - const char *pattern; - int options; - int (*exec)(const char *cmd, void *client); - int (*help)(char * const *fields, int field_cnt, void *client); -}; - -struct ppp_t; - -void cli_register_simple_cmd(struct cli_simple_cmd_t *cmd); -void cli_register_simple_cmd2( - int (*exec)(const char *cmd, char * const *fields, int fields_cnt, void *client), - void (*help)(char * const *fields, int fields_cnt, void *client), - int hdr_len, - ... - ); -void cli_register_regexp_cmd(struct cli_regexp_cmd_t *cmd); -void cli_show_ses_register(const char *name, const char *desc, void (*print)(const struct ppp_t *ppp, char *buf)); - -int cli_send(void *client, const char *data); -int cli_sendv(void *client, const char *fmt, ...); - -#endif - diff --git a/accel-pptpd/cli/cli_p.h b/accel-pptpd/cli/cli_p.h deleted file mode 100644 index 0fcba309..00000000 --- a/accel-pptpd/cli/cli_p.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef __CLI_P_H -#define __CLI_P_H - -#include <stdarg.h> - -#include "triton.h" - -struct cli_client_t -{ - uint8_t *cmdline; - int (*send)(struct cli_client_t *, const void *buf, int size); - int (*sendv)(struct cli_client_t *, const char *fmt, va_list ap); - void (*disconnect)(struct cli_client_t *); -}; - -int cli_process_cmd(struct cli_client_t *cln); - -extern char *conf_cli_passwd; -extern char *conf_cli_prompt; - -#endif - diff --git a/accel-pptpd/cli/show_sessions.c b/accel-pptpd/cli/show_sessions.c deleted file mode 100644 index 90aeb3fc..00000000 --- a/accel-pptpd/cli/show_sessions.c +++ /dev/null @@ -1,434 +0,0 @@ -#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); -} - diff --git a/accel-pptpd/cli/std_cmd.c b/accel-pptpd/cli/std_cmd.c deleted file mode 100644 index a49bbce6..00000000 --- a/accel-pptpd/cli/std_cmd.c +++ /dev/null @@ -1,324 +0,0 @@ -#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" - -static int show_stat_exec(const char *cmd, char * const *fields, int fields_cnt, void *client) -{ - time_t dt; - int day,hour; - char statm_fname[128]; - FILE *f; - unsigned long vmsize = 0, vmrss = 0; - unsigned long page_size_kb = sysconf(_SC_PAGE_SIZE) / 1024; - - sprintf(statm_fname, "/proc/%i/statm", getpid()); - f = fopen(statm_fname, "r"); - if (f) { - fscanf(f, "%lu %lu", &vmsize, &vmrss); - fclose(f); - } - - time(&dt); - dt -= triton_stat.start_time; - day = dt / (60 * 60 * 24); - dt %= 60 * 60 * 24; - hour = dt / (60 * 60); - dt %= 60 * 60; - - cli_sendv(client, "uptime: %i.%02i:%02i:%02i\r\n", day, hour, dt / 60, dt % 60); - cli_sendv(client, "cpu: %i%%\r\n", triton_stat.cpu); - cli_sendv(client, "mem(rss/virt): %lu/%lu kB\r\n", vmrss * page_size_kb, vmsize * page_size_kb); - cli_send(client, "core:\r\n"); - cli_sendv(client, " mempool_allocated: %u\r\n", triton_stat.mempool_allocated); - cli_sendv(client, " mempool_available: %u\r\n", triton_stat.mempool_available); - cli_sendv(client, " thread_count: %u\r\n", triton_stat.thread_count); - cli_sendv(client, " thread_active: %u\r\n", triton_stat.thread_active); - cli_sendv(client, " context_count: %u\r\n", triton_stat.context_count); - cli_sendv(client, " context_sleeping: %u\r\n", triton_stat.context_sleeping); - cli_sendv(client, " context_pending: %u\r\n", triton_stat.context_pending); - cli_sendv(client, " md_handler_count: %u\r\n", triton_stat.md_handler_count); - cli_sendv(client, " md_handler_pending: %u\r\n", triton_stat.md_handler_pending); - cli_sendv(client, " timer_count: %u\r\n", triton_stat.timer_count); - cli_sendv(client, " timer_pending: %u\r\n", triton_stat.timer_pending); - -//=========== - cli_send(client, "ppp:\r\n"); - cli_sendv(client, " staring: %u\r\n", ppp_stat.starting); - cli_sendv(client, " active: %u\r\n", ppp_stat.active); - cli_sendv(client, " finishing: %u\r\n", ppp_stat.finishing); - - return CLI_CMD_OK; -} - -static void show_stat_help(char * const *fields, int fields_cnt, void *client) -{ - cli_send(client, "show stat - shows various statistics information\r\n"); -} -//============================= - -static int exit_exec(const char *cmd, char * const *fields, int fields_cnt, void *client) -{ - return CLI_CMD_EXIT; -} - -static void exit_help(char * const *fields, int fields_cnt, void *client) -{ - cli_send(client, "exit - exit cli\r\n"); -} - -//============================= - -static void ppp_terminate_soft(struct ppp_t *ppp) -{ - ppp_terminate(ppp, TERM_NAS_REQUEST, 0); -} - -static void ppp_terminate_hard(struct ppp_t *ppp) -{ - ppp_terminate(ppp, TERM_NAS_REQUEST, 1); -} - -static int terminate_exec1(char * const *f, int f_cnt, void *cli) -{ - struct ppp_t *ppp; - int hard = 0; - pcre *re; - const char *pcre_err; - int pcre_offset; - - if (f_cnt == 5) { - if (!strcmp(f[4], "hard")) - hard = 1; - else if (strcmp(f[4], "soft")) - return CLI_CMD_SYNTAX; - } else if (f_cnt != 4) - return CLI_CMD_SYNTAX; - - re = pcre_compile2(f[3], 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; - } - - pthread_rwlock_rdlock(&ppp_lock); - list_for_each_entry(ppp, &ppp_list, entry) { - if (pcre_exec(re, NULL, ppp->username, strlen(ppp->username), 0, 0, NULL, 0) < 0) - continue; - if (hard) - triton_context_call(ppp->ctrl->ctx, (triton_event_func)ppp_terminate_hard, ppp); - else - triton_context_call(ppp->ctrl->ctx, (triton_event_func)ppp_terminate_soft, ppp); - } - pthread_rwlock_unlock(&ppp_lock); - - pcre_free(re); - - return CLI_CMD_OK; -} - -static int terminate_exec2(int key, char * const *f, int f_cnt, void *cli) -{ - struct ppp_t *ppp; - int hard = 0; - in_addr_t ipaddr = 0; - - if (f_cnt == 4) { - if (!strcmp(f[3], "hard")) - hard = 1; - else if (strcmp(f[3], "soft")) - return CLI_CMD_SYNTAX; - } else if (f_cnt != 3) - return CLI_CMD_SYNTAX; - - if (key == 1) - ipaddr = inet_addr(f[2]); - - pthread_rwlock_rdlock(&ppp_lock); - list_for_each_entry(ppp, &ppp_list, entry) { - switch (key) { - case 0: - if (strcmp(ppp->username, f[2])) - continue; - break; - case 1: - if (ppp->peer_ipaddr != ipaddr) - continue; - break; - case 2: - if (strcmp(ppp->ctrl->calling_station_id, f[2])) - continue; - break; - case 3: - if (strcmp(ppp->sessionid, f[2])) - continue; - break; - case 4: - if (strcmp(ppp->ifname, f[2])) - continue; - break; - } - if (hard) - triton_context_call(ppp->ctrl->ctx, (triton_event_func)ppp_terminate_hard, ppp); - else - triton_context_call(ppp->ctrl->ctx, (triton_event_func)ppp_terminate_soft, ppp); - break; - } - pthread_rwlock_unlock(&ppp_lock); - - return CLI_CMD_OK; -} - -static int terminate_exec(const char *cmd, char * const *fields, int fields_cnt, void *client) -{ - struct ppp_t *ppp; - int hard = 0; - - if (fields_cnt == 1) - return CLI_CMD_SYNTAX; - - if (!strcmp(fields[1], "match") && fields_cnt > 3 && !strcmp(fields[2], "username")) - return terminate_exec1(fields, fields_cnt, client); - else if (!strcmp(fields[1], "username")) - return terminate_exec2(0, fields, fields_cnt, client); - else if (!strcmp(fields[1], "ip")) - return terminate_exec2(1, fields, fields_cnt, client); - else if (!strcmp(fields[1], "csid")) - return terminate_exec2(2, fields, fields_cnt, client); - else if (!strcmp(fields[1], "sid")) - return terminate_exec2(3, fields, fields_cnt, client); - else if (!strcmp(fields[1], "if")) - return terminate_exec2(4, fields, fields_cnt, client); - else if (strcmp(fields[1], "all")) - return CLI_CMD_SYNTAX; - - if (fields_cnt == 3) { - if (!strcmp(fields[2], "hard")) - hard = 1; - else if (strcmp(fields[2], "soft")) - return CLI_CMD_SYNTAX; - } else if (fields_cnt != 2) - return CLI_CMD_SYNTAX; - - pthread_rwlock_rdlock(&ppp_lock); - list_for_each_entry(ppp, &ppp_list, entry) { - if (hard) - triton_context_call(ppp->ctrl->ctx, (triton_event_func)ppp_terminate_hard, ppp); - else - triton_context_call(ppp->ctrl->ctx, (triton_event_func)ppp_terminate_soft, ppp); - } - pthread_rwlock_unlock(&ppp_lock); - - return CLI_CMD_OK; -} - -static void terminate_help(char * const *fields, int fields_cnt, void *client) -{ - cli_send(client, "terminate if <interface> [soft|hard]- terminate session by interface name\r\n"); - cli_send(client, "\t[match] username <username> [soft|hard]- terminate session by username\r\n"); - cli_send(client, "\tip <addresss> [soft|hard]- terminate session by ip address\r\n"); - cli_send(client, "\tcsid <id> [soft|hard]- terminate session by calling station id\r\n"); - cli_send(client, "\tsid <id> [soft|hard]- terminate session by session id\r\n"); - cli_send(client, "\tall [soft|hard]- terminate all sessions\r\n"); -} - -//============================= - -static void shutdown_help(char * const *fields, int fields_cnt, void *client) -{ - cli_send(client, "shutdown [soft|hard|cancel]- shutdown daemon\r\n"); - cli_send(client, "\t\tdefault action - send termination signals to all clients and wait everybody disconnects\r\n"); - cli_send(client, "\t\tsoft - wait until all clients disconnects, don't accept new connections\r\n"); - cli_send(client, "\t\thard - shutdown now, don't wait anything\r\n"); - cli_send(client, "\t\tcancel - cancel 'shutdown soft' and return to normal operation\r\n"); -} - -static void ppp_terminate_soft2(struct ppp_t *ppp) -{ - ppp_terminate(ppp, TERM_NAS_REBOOT, 0); -} - -static void ppp_terminate_hard2(struct ppp_t *ppp) -{ - ppp_terminate(ppp, TERM_NAS_REBOOT, 1); -} - -static int shutdown_exec(const char *cmd, char * const *f, int f_cnt, void *cli) -{ - int hard = 0; - struct ppp_t *ppp; - - if (f_cnt == 2) { - if (!strcmp(f[1], "soft")) { - ppp_shutdown_soft(); - return CLI_CMD_OK; - } else if (!strcmp(f[1], "hard")) - hard = 1; - else if (!strcmp(f[1], "cancel")) { - ppp_shutdown = 0; - return CLI_CMD_OK; - } else - return CLI_CMD_SYNTAX; - } - - ppp_shutdown_soft(); - - pthread_rwlock_rdlock(&ppp_lock); - list_for_each_entry(ppp, &ppp_list, entry) { - if (hard) - triton_context_call(ppp->ctrl->ctx, (triton_event_func)ppp_terminate_hard2, ppp); - else - triton_context_call(ppp->ctrl->ctx, (triton_event_func)ppp_terminate_soft2, ppp); - } - pthread_rwlock_unlock(&ppp_lock); - - return CLI_CMD_OK; -} - -//========================== -static int conf_reload_res; -static struct triton_context_t *conf_reload_ctx; -static void conf_reload_notify(int r) -{ - if (!r) - triton_event_fire(EV_CONFIG_RELOAD, NULL); - conf_reload_res = r; - triton_context_wakeup(conf_reload_ctx); -} -static int reload_exec(const char *cmd, char * const *f, int f_cnt, void *cli) -{ - if (f_cnt == 1) { - conf_reload_ctx = triton_context_self(); - triton_conf_reload(conf_reload_notify); - triton_context_schedule(); - if (conf_reload_res) - cli_send(cli, "failed\r\n"); - return CLI_CMD_OK; - } else - return CLI_CMD_SYNTAX; -} - -static void reload_help(char * const *fields, int fields_cnt, void *client) -{ - cli_send(client, "reload - reload config file\r\n"); -} - -static void __init init(void) -{ - cli_register_simple_cmd2(show_stat_exec, show_stat_help, 2, "show", "stat"); - cli_register_simple_cmd2(terminate_exec, terminate_help, 1, "terminate"); - cli_register_simple_cmd2(reload_exec, reload_help, 1, "reload"); - cli_register_simple_cmd2(shutdown_exec, shutdown_help, 1, "shutdown"); - cli_register_simple_cmd2(exit_exec, exit_help, 1, "exit"); -} - diff --git a/accel-pptpd/cli/tcp.c b/accel-pptpd/cli/tcp.c deleted file mode 100644 index 260225f1..00000000 --- a/accel-pptpd/cli/tcp.c +++ /dev/null @@ -1,371 +0,0 @@ -#include <unistd.h> -#include <stdlib.h> -#include <stdio.h> -#include <stdarg.h> -#include <errno.h> -#include <string.h> -#include <fcntl.h> -#include <time.h> -#include <arpa/inet.h> -#include <netinet/in.h> -#include <sys/socket.h> - -#include "triton.h" -#include "log.h" -#include "list.h" -#include "memdebug.h" - -#include "cli_p.h" - -#define RECV_BUF_SIZE 1024 - -struct tcp_client_t -{ - struct cli_client_t cli_client; - struct list_head entry; - struct triton_md_handler_t hnd; - struct list_head xmit_queue; - struct buffer_t *xmit_buf; - uint8_t *cmdline; - int xmit_pos; - int recv_pos; - int auth:1; - int disconnect:1; -}; - -struct buffer_t -{ - struct list_head entry; - int size; - uint8_t buf[0]; -}; - -static struct triton_context_t serv_ctx; -static struct triton_md_handler_t serv_hnd; -static LIST_HEAD(clients); - -static uint8_t *temp_buf; - -static void disconnect(struct tcp_client_t *cln) -{ - struct buffer_t *b; - - log_debug("cli: disconnect\n"); - - list_del(&cln->entry); - - triton_md_unregister_handler(&cln->hnd); - close(cln->hnd.fd); - - if (cln->xmit_buf) - _free(cln->xmit_buf); - - while (!list_empty(&cln->xmit_queue)) { - b = list_entry(cln->xmit_queue.next, typeof(*b), entry); - list_del(&b->entry); - _free(b); - } - - _free(cln->cmdline); - _free(cln); -} - -static void cli_client_disconnect(struct cli_client_t *tcln) -{ - struct tcp_client_t *cln = container_of(tcln, typeof(*cln), cli_client); - cln->disconnect = 1; -} - -static void queue_buffer(struct tcp_client_t *cln, struct buffer_t *b) -{ - if (cln->xmit_buf) - list_add_tail(&b->entry, &cln->xmit_queue); - else - cln->xmit_buf = b; -} - -static int cli_client_send(struct cli_client_t *tcln, const void *_buf, int size) -{ - struct tcp_client_t *cln = container_of(tcln, typeof(*cln), cli_client); - int n, k; - struct buffer_t *b; - const uint8_t *buf = (const uint8_t *)_buf; - - if (cln->disconnect) - return -1; - - if (!list_empty(&cln->xmit_queue)) { - b = _malloc(sizeof(*b) + size); - b->size = size; - memcpy(b->buf, buf, size); - queue_buffer(cln, b); - return 0; - } - - for (n = 0; n < size; n += k) { - k = write(cln->hnd.fd, buf + n, size - n); - if (k < 0) { - if (errno == EAGAIN) { - b = _malloc(sizeof(*b) + size - n); - b->size = size - n; - memcpy(b->buf, buf, size - n); - queue_buffer(cln, b); - - triton_md_enable_handler(&cln->hnd, MD_MODE_WRITE); - break; - } - if (errno != EPIPE) - log_error("cli: write: %s\n", strerror(errno)); - //disconnect(cln); - cln->disconnect = 1; - return -1; - } - } - return 0; -} - -static int cli_client_sendv(struct cli_client_t *tcln, const char *fmt, va_list ap) -{ - struct tcp_client_t *cln = container_of(tcln, typeof(*cln), cli_client); - int r = vsnprintf((char *)temp_buf, RECV_BUF_SIZE, fmt, ap); - - if (r >= RECV_BUF_SIZE) { - strcpy((char *)temp_buf + RECV_BUF_SIZE - 5, "...\n"); - r = RECV_BUF_SIZE; - } - - return cli_client_send(tcln, temp_buf, r); -} - -static int cln_read(struct triton_md_handler_t *h) -{ - struct tcp_client_t *cln = container_of(h, typeof(*cln), hnd); - int n; - char *d; - - while (1) { - n = read(h->fd, cln->cmdline + cln->recv_pos, RECV_BUF_SIZE - cln->recv_pos); - if (n == 0) - break; - if (n < 0) { - if (errno != EAGAIN) - log_error("cli: read: %s\n", strerror(errno)); - return 0; - } - - cln->recv_pos += n; - - while (cln->recv_pos) { - d = strchr((char *)cln->cmdline, '\n'); - if (!d) { - if (cln->recv_pos == RECV_BUF_SIZE) { - log_warn("cli: tcp: recv buffer overflow\n"); - goto drop; - } - break; - } - - *d = 0; - - if (!cln->auth) { - if (strcmp((char *)cln->cmdline, conf_cli_passwd)) - goto drop; - cln->auth = 1; - } else - cli_process_cmd(&cln->cli_client); - - if (cln->disconnect) - goto drop; - - cln->recv_pos -= (uint8_t *)d + 1 - cln->cmdline; - memmove(cln->cmdline, d + 1, cln->recv_pos); - } - } - -drop: - disconnect(cln); - return -1; -} - -static int cln_write(struct triton_md_handler_t *h) -{ - struct tcp_client_t *cln = container_of(h, typeof(*cln), hnd); - int k; - - while (1) { - for (; cln->xmit_pos < cln->xmit_buf->size; cln->xmit_pos += k) { - k = write(cln->hnd.fd, cln->xmit_buf->buf + cln->xmit_pos, cln->xmit_buf->size - cln->xmit_pos); - if (k < 0) { - if (errno == EAGAIN) - return 0; - if (errno != EPIPE) - log_error("cli: tcp: write: %s\n", strerror(errno)); - disconnect(cln); - return -1; - } - } - - _free(cln->xmit_buf); - cln->xmit_pos = 0; - - if (list_empty(&cln->xmit_queue)) - break; - - cln->xmit_buf = list_entry(cln->xmit_queue.next, typeof(*cln->xmit_buf), entry); - list_del(&cln->xmit_buf->entry); - } - - triton_md_disable_handler(&cln->hnd, MD_MODE_WRITE); - - return 0; -} - -static int serv_read(struct triton_md_handler_t *h) -{ - struct sockaddr_in addr; - socklen_t size = sizeof(addr); - int sock; - struct tcp_client_t *conn; - - while(1) { - sock = accept(h->fd, (struct sockaddr *)&addr, &size); - if (sock < 0) { - if (errno == EAGAIN) - return 0; - log_error("cli: tcp: accept failed: %s\n", strerror(errno)); - continue; - } - - log_info2("cli: tcp: new connection from %s\n", inet_ntoa(addr.sin_addr)); - - if (fcntl(sock, F_SETFL, O_NONBLOCK)) { - log_error("cli: tcp: failed to set nonblocking mode: %s, closing connection...\n", strerror(errno)); - close(sock); - continue; - } - - conn = _malloc(sizeof(*conn)); - memset(conn, 0, sizeof(*conn)); - conn->hnd.fd = sock; - conn->hnd.read = cln_read; - conn->hnd.write = cln_write; - conn->cmdline = _malloc(RECV_BUF_SIZE); - INIT_LIST_HEAD(&conn->xmit_queue); - - conn->cli_client.cmdline = conn->cmdline; - conn->cli_client.send = cli_client_send; - conn->cli_client.sendv = cli_client_sendv; - conn->cli_client.disconnect = cli_client_disconnect; - - triton_md_register_handler(&serv_ctx, &conn->hnd); - triton_md_enable_handler(&conn->hnd,MD_MODE_READ); - - list_add_tail(&conn->entry, &clients); - - if (!conf_cli_passwd) - conn->auth = 1; - } - return 0; -} - -static void serv_close(struct triton_context_t *ctx) -{ - struct tcp_client_t *cln; - - while (!list_empty(&clients)) { - cln = list_entry(clients.next, typeof(*cln), entry); - disconnect(cln); - } - - triton_md_unregister_handler(&serv_hnd); - close(serv_hnd.fd); - triton_context_unregister(ctx); -} - -static struct triton_context_t serv_ctx = { - .close = serv_close, - .before_switch = log_switch, -}; - -static struct triton_md_handler_t serv_hnd = { - .read = serv_read, -}; - -static void start_server(const char *host, int port) -{ - struct sockaddr_in addr; - - serv_hnd.fd = socket(PF_INET, SOCK_STREAM, 0); - if (serv_hnd.fd < 0) { - log_emerg("cli: tcp: failed to create server socket: %s\n", strerror(errno)); - return; - } - - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - if (host) - addr.sin_addr.s_addr = inet_addr(host); - else - addr.sin_addr.s_addr = htonl(INADDR_ANY); - - setsockopt(serv_hnd.fd, SOL_SOCKET, SO_REUSEADDR, &serv_hnd.fd, 4); - if (bind (serv_hnd.fd, (struct sockaddr *) &addr, sizeof (addr)) < 0) { - log_emerg("cli: tcp: failed to bind socket: %s\n", strerror(errno)); - close(serv_hnd.fd); - return; - } - - if (listen (serv_hnd.fd, 1) < 0) { - log_emerg("cli: tcp: failed to listen socket: %s\n", strerror(errno)); - close(serv_hnd.fd); - return; - } - - if (fcntl(serv_hnd.fd, F_SETFL, O_NONBLOCK)) { - log_emerg("cli: tcp: failed to set nonblocking mode: %s\n", strerror(errno)); - close(serv_hnd.fd); - return; - } - - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - addr.sin_addr.s_addr = inet_addr(host); - - triton_context_register(&serv_ctx, NULL); - triton_context_set_priority(&serv_ctx, 1); - triton_md_register_handler(&serv_ctx, &serv_hnd); - triton_md_enable_handler(&serv_hnd, MD_MODE_READ); - triton_context_wakeup(&serv_ctx); -} - -static void __init init(void) -{ - const char *opt; - char *host, *d; - int port; - - opt = conf_get_opt("cli", "tcp"); - if (!opt) - return; - - host = strdup(opt); - d = strstr(host, ":"); - if (!d) - goto err_fmt; - - *d = 0; - port = atoi(d + 1); - if (port <= 0) - goto err_fmt; - - temp_buf = malloc(RECV_BUF_SIZE); - - start_server(host, port); - - return; -err_fmt: - log_emerg("cli: tcp: invalid format\n"); - free(host); -} - diff --git a/accel-pptpd/cli/telnet.c b/accel-pptpd/cli/telnet.c deleted file mode 100644 index 0ea19fb1..00000000 --- a/accel-pptpd/cli/telnet.c +++ /dev/null @@ -1,757 +0,0 @@ -#include <unistd.h> -#include <stdlib.h> -#include <stdio.h> -#include <stdarg.h> -#include <errno.h> -#include <string.h> -#include <fcntl.h> -#include <time.h> -#include <ctype.h> -#include <arpa/inet.h> -#include <arpa/telnet.h> -#include <netinet/in.h> -#include <sys/socket.h> -#include <sys/stat.h> -#include <sys/types.h> - -#include "triton.h" -#include "log.h" -#include "ppp.h" -#include "list.h" -#include "memdebug.h" - -#include "cli_p.h" - -#define RECV_BUF_SIZE 1024 - -#define MSG_AUTH_FAILED "\r\nAuthentication failed\r\n" -#define MSG_SHUTDOWN_IN_PROGRESS "note: 'shutdown soft' is in progress...\r\n" - -#define ESC_LEFT "[D" -#define ESC_RIGHT "[C" -#define ESC_UP "[A" -#define ESC_DOWN "[B" - -struct telnet_client_t -{ - struct cli_client_t cli_client; - struct list_head entry; - struct triton_md_handler_t hnd; - struct list_head xmit_queue; - struct buffer_t *xmit_buf; - int xmit_pos; - struct list_head history; - struct list_head *history_pos; - uint8_t *cmdline; - int cmdline_pos; - int cmdline_pos2; - int cmdline_len; - int auth:1; - int echo:1; - int telcmd:1; - int esc:1; - int disconnect:1; -}; - -struct buffer_t -{ - struct list_head entry; - int size; - struct buffer_t *p_buf; - uint8_t buf[0]; -}; - -static struct triton_context_t serv_ctx; -static struct triton_md_handler_t serv_hnd; -static LIST_HEAD(clients); - -static uint8_t *recv_buf; -static uint8_t *temp_buf; - -static int conf_history_len = 100; -static const char *conf_history_file = "/var/run/accel-pptp/history"; -static LIST_HEAD(history); -static int history_len; -static pthread_mutex_t history_lock = PTHREAD_MUTEX_INITIALIZER; - -static void disconnect(struct telnet_client_t *cln) -{ - struct buffer_t *b, *b2; - - log_debug("cli: disconnect\n"); - - triton_stop_collect_cpu_usage(); - - list_del(&cln->entry); - - triton_md_unregister_handler(&cln->hnd); - close(cln->hnd.fd); - - if (cln->xmit_buf) - _free(cln->xmit_buf); - - while (!list_empty(&cln->xmit_queue)) { - b = list_entry(cln->xmit_queue.next, typeof(*b), entry); - list_del(&b->entry); - _free(b); - } - - pthread_mutex_lock(&history_lock); - while (!list_empty(&cln->history)) { - b = list_entry(cln->history.prev, typeof(*b), entry); - list_del(&b->entry); - if (!b->p_buf) { - if (history_len == conf_history_len) { - b2 = list_entry(history.next, typeof(*b2), entry); - list_del(&b2->entry); - _free(b2); - } else - history_len++; - list_add_tail(&b->entry, &history); - } else - _free(b); - } - pthread_mutex_unlock(&history_lock); - - _free(cln->cmdline); - _free(cln); -} - -static void cli_client_disconnect(struct cli_client_t *tcln) -{ - struct telnet_client_t *cln = container_of(tcln, typeof(*cln), cli_client); - cln->disconnect = 1; -} - -static void queue_buffer(struct telnet_client_t *cln, struct buffer_t *b) -{ - if (cln->xmit_buf) - list_add_tail(&b->entry, &cln->xmit_queue); - else - cln->xmit_buf = b; -} - -static int telnet_send(struct telnet_client_t *cln, const void *_buf, int size) -{ - int n, k; - struct buffer_t *b; - const uint8_t *buf = (const uint8_t *)_buf; - - if (cln->disconnect) - return -1; - - if (!list_empty(&cln->xmit_queue)) { - b = _malloc(sizeof(*b) + size); - b->size = size; - memcpy(b->buf, buf, size); - queue_buffer(cln, b); - return 0; - } - - for (n = 0; n < size; n += k) { - k = write(cln->hnd.fd, buf + n, size - n); - if (k < 0) { - if (errno == EAGAIN) { - b = _malloc(sizeof(*b) + size - n); - b->size = size - n; - memcpy(b->buf, buf, size - n); - queue_buffer(cln, b); - - triton_md_enable_handler(&cln->hnd, MD_MODE_WRITE); - break; - } - if (errno != EPIPE) - log_error("cli: write: %s\n", strerror(errno)); - //disconnect(cln); - cln->disconnect = 1; - return -1; - } - } - return 0; -} - -static int cli_client_send(struct cli_client_t *tcln, const void *buf, int size) -{ - struct telnet_client_t *cln = container_of(tcln, typeof(*cln), cli_client); - return telnet_send(cln, buf, size); -} - -static int cli_client_sendv(struct cli_client_t *tcln, const char *fmt, va_list ap) -{ - struct telnet_client_t *cln = container_of(tcln, typeof(*cln), cli_client); - int r = vsnprintf((char *)temp_buf, RECV_BUF_SIZE, fmt, ap); - - if (r >= RECV_BUF_SIZE) { - strcpy((char *)temp_buf + RECV_BUF_SIZE - 6, "...\r\n"); - r = RECV_BUF_SIZE; - } - - return telnet_send(cln, temp_buf, r); -} - -static int send_banner(struct telnet_client_t *cln) -{ - if (telnet_send(cln, "accel-pptp version " ACCEL_PPTP_VERSION "\r\n", sizeof("accel-pptp version " ACCEL_PPTP_VERSION "\r\n"))) - return -1; - return 0; -} - -static int send_config(struct telnet_client_t *cln) -{ - uint8_t buf[] = {IAC, WILL, TELOPT_ECHO, IAC, WILL, TELOPT_SGA, IAC, DONT, TELOPT_LINEMODE}; - return telnet_send(cln, buf, sizeof(buf)); -} - -static int send_password_request(struct telnet_client_t *cln) -{ - uint8_t buf0[] = {IAC, WILL, TELOPT_ECHO}; - uint8_t buf1[] = "Password: "; - - if (telnet_send(cln, buf0, sizeof(buf0))) - return -1; - - if (telnet_send(cln, buf1, sizeof(buf1))) - return -1; - - return 0; -} - -static int send_prompt(struct telnet_client_t *cln) -{ - sprintf((char *)temp_buf, "%s%s# ", conf_cli_prompt, ppp_shutdown ? "(shutdown)" : ""); - return telnet_send(cln, temp_buf, strlen((char *)temp_buf)); -} - -/*static void print_buf(const uint8_t *buf, int size) -{ - int i; - - for (i = 0; i < size; i++) - log_debug("%x ", buf[i]); - log_debug("\n"); -}*/ - -static int send_cmdline_tail(struct telnet_client_t *cln, int corr) -{ - if (telnet_send(cln, cln->cmdline + cln->cmdline_pos, cln->cmdline_len - cln->cmdline_pos)) - return -1; - - memset(temp_buf, '\b', cln->cmdline_len - cln->cmdline_pos - corr); - - if (telnet_send(cln, temp_buf, cln->cmdline_len - cln->cmdline_pos - corr)) - return -1; - - return 0; -} - -static int load_history(struct telnet_client_t *cln) -{ - struct buffer_t *b = list_entry(cln->history_pos, typeof(*b), entry); - if (b->size < cln->cmdline_len) { - memset(temp_buf, '\b', cln->cmdline_len - b->size); - memset(temp_buf + cln->cmdline_len - b->size, ' ', cln->cmdline_len - b->size); - if (telnet_send(cln, temp_buf, (cln->cmdline_len - b->size) * 2)) - return -1; - } - if (telnet_send(cln, "\r", 1)) - return -1; - if (send_prompt(cln)) - return -1; - memcpy(cln->cmdline, b->p_buf ? b->p_buf->buf : b->buf, b->size); - cln->cmdline_pos = b->size; - cln->cmdline_len = b->size; - if (telnet_send(cln, b->p_buf ? b->p_buf->buf : b->buf, b->size)) - return -1; - - return 0; -} - -static int telnet_input_char(struct telnet_client_t *cln, uint8_t c) -{ - uint8_t buf[] = {IAC, DONT, 0}; - struct buffer_t *b; - - if (c == '\n') - return 0; - - if (c == '\r') { - cln->cmdline[cln->cmdline_len] = 0; - - if (cln->echo) { - if (telnet_send(cln, "\r\n", 2)) - return -1; - } - - if (!cln->auth) { - if (strcmp((char *)cln->cmdline, conf_cli_passwd)) { - if (telnet_send(cln, MSG_AUTH_FAILED, sizeof(MSG_AUTH_FAILED))) - return -1; - cln->disconnect = 1; - return -1; - } - cln->auth = 1; - if (ppp_shutdown) { - if (telnet_send(cln, MSG_SHUTDOWN_IN_PROGRESS, sizeof(MSG_SHUTDOWN_IN_PROGRESS))) - return -1; - } - } else if (cln->cmdline_len) { - b = _malloc(sizeof(*b) + cln->cmdline_len); - b->p_buf = NULL; - memcpy(b->buf, cln->cmdline, cln->cmdline_len); - b->size = cln->cmdline_len; - list_add(&b->entry, cln->history.next); - cln->history_pos = cln->history.next; - - if (cli_process_cmd(&cln->cli_client)) - return -1; - } - - cln->cmdline_pos = 0; - cln->cmdline_len = 0; - - return send_prompt(cln); - } - - if (cln->telcmd) { - if (cln->cmdline_pos2 == RECV_BUF_SIZE - 1) { - log_error("cli: buffer overflow, dropping connection ...\n"); - disconnect(cln); - return -1; - } - - cln->cmdline[cln->cmdline_pos2] = c; - cln->cmdline_pos2++; - - if (cln->cmdline[cln->cmdline_len] >= WILL && cln->cmdline[cln->cmdline_len] <= DONT && cln->cmdline_pos2 - cln->cmdline_len != 2) - return 0; - - switch (cln->cmdline[cln->cmdline_len]) { - case WILL: - case WONT: - buf[2] = c; - if (telnet_send(cln, buf, 3)) - return -1; - break; - case DO: - if (c == TELOPT_ECHO) - cln->echo = 1; - break; - case SB: - if (c != SE) - return 0; - } - - cln->telcmd = 0; - } else if (cln->esc) { - if (cln->cmdline_pos2 == RECV_BUF_SIZE - 1) { - log_error("cli: buffer overflow, dropping connection ...\n"); - disconnect(cln); - return -1; - } - - cln->cmdline[cln->cmdline_pos2] = c; - cln->cmdline_pos2++; - - if (cln->cmdline_pos2 - cln->cmdline_len != 2) - return 0; - - cln->esc = 0; - - if (cln->auth) { - if (!memcmp(cln->cmdline + cln->cmdline_len, ESC_LEFT, 2)) { - if (cln->cmdline_pos) { - if (telnet_send(cln, "\b", 1)) - return -1; - cln->cmdline_pos--; - } - } else if (!memcmp(cln->cmdline + cln->cmdline_len, ESC_RIGHT, 2)) { - if (cln->cmdline_pos < cln->cmdline_len) { - if (send_cmdline_tail(cln, 1)) - return -1; - cln->cmdline_pos++; - } - } else if (!memcmp(cln->cmdline + cln->cmdline_len, ESC_UP, 2)) { - if (cln->history_pos == cln->history.next) { - b = list_entry(cln->history_pos, typeof(*b), entry); - memcpy(b->buf, cln->cmdline, cln->cmdline_len); - b->size = cln->cmdline_len; - } - cln->history_pos = cln->history_pos->next; - if (cln->history_pos == &cln->history) { - cln->history_pos = cln->history_pos->prev; - return 0; - } - if (load_history(cln)) - return -1; - } else if (!memcmp(cln->cmdline + cln->cmdline_len, ESC_DOWN, 2)) { - cln->history_pos = cln->history_pos->prev; - if (cln->history_pos == &cln->history) { - cln->history_pos = cln->history_pos->next; - return 0; - } - if (load_history(cln)) - return -1; - } - } - } else { - switch (c) { - case 0xff: - cln->cmdline_pos2 = cln->cmdline_len; - cln->telcmd = 1; - return 0; - case 0x1b: - cln->cmdline_pos2 = cln->cmdline_len; - cln->esc = 1; - return 0; - case 0x7f: - if (cln->cmdline_pos) { - if (cln->cmdline_pos < cln->cmdline_len) { - memmove(cln->cmdline + cln->cmdline_pos - 1, cln->cmdline + cln->cmdline_pos, cln->cmdline_len - cln->cmdline_pos); - - cln->cmdline[cln->cmdline_len - 1] = ' '; - - if (telnet_send(cln, "\b", 1)) - return -1; - - cln->cmdline_pos--; - - if (send_cmdline_tail(cln, 0)) - return -1; - } else { - buf[0] = '\b'; - buf[1] = ' '; - buf[2] = '\b'; - if (telnet_send(cln, buf, 3)) - return -1; - cln->cmdline_pos--; - } - - cln->cmdline_len--; - } - return 0; - case 3: - cln->disconnect = 1; - return -1; - } - - if (isprint(c)) { - if (cln->cmdline_len == RECV_BUF_SIZE - 1) - return 0; - - if (cln->cmdline_pos < cln->cmdline_len) - memmove(cln->cmdline + cln->cmdline_pos + 1, cln->cmdline + cln->cmdline_pos, cln->cmdline_len - cln->cmdline_pos); - cln->cmdline[cln->cmdline_pos] = c; - cln->cmdline_pos++; - cln->cmdline_len++; - - if (cln->echo) { - if (!cln->auth) { - if (telnet_send(cln, "*", 1)) - return -1; - } else { - if (telnet_send(cln, &c, 1)) - return -1; - } - } - - if (cln->cmdline_pos < cln->cmdline_len) { - if (send_cmdline_tail(cln, 0)) - return -1; - } - } - } - - return 0; -} - -static int cln_read(struct triton_md_handler_t *h) -{ - struct telnet_client_t *cln = container_of(h, typeof(*cln), hnd); - int i, n; - - while (1) { - n = read(h->fd, recv_buf, RECV_BUF_SIZE); - if (n == 0) { - disconnect(cln); - return -1; - } - if (n < 0) { - if (errno != EAGAIN) - log_error("cli: telnet: read: %s\n", strerror(errno)); - return 0; - } - /*log_debug("cli: read(%i): ", n); - print_buf(cln->recv_buf + cln->recv_pos, n);*/ - for (i = 0; i < n; i++) { - if (telnet_input_char(cln, recv_buf[i])) - break; - } - if (cln->disconnect) { - disconnect(cln); - return -1; - } - } - - return 0; -} - -static int cln_write(struct triton_md_handler_t *h) -{ - struct telnet_client_t *cln = container_of(h, typeof(*cln), hnd); - int k; - - while (1) { - for (; cln->xmit_pos < cln->xmit_buf->size; cln->xmit_pos += k) { - k = write(cln->hnd.fd, cln->xmit_buf->buf + cln->xmit_pos, cln->xmit_buf->size - cln->xmit_pos); - if (k < 0) { - if (errno == EAGAIN) - return 0; - if (errno != EPIPE) - log_error("cli: telnet: write: %s\n", strerror(errno)); - disconnect(cln); - return -1; - } - } - - _free(cln->xmit_buf); - cln->xmit_pos = 0; - - if (list_empty(&cln->xmit_queue)) - break; - - cln->xmit_buf = list_entry(cln->xmit_queue.next, typeof(*cln->xmit_buf), entry); - list_del(&cln->xmit_buf->entry); - } - - triton_md_disable_handler(&cln->hnd, MD_MODE_WRITE); - - return 0; -} - -static int serv_read(struct triton_md_handler_t *h) -{ - struct sockaddr_in addr; - socklen_t size = sizeof(addr); - int sock; - struct telnet_client_t *conn; - struct buffer_t *b, *b2; - - while(1) { - sock = accept(h->fd, (struct sockaddr *)&addr, &size); - if (sock < 0) { - if (errno == EAGAIN) - return 0; - log_error("cli: telnet: accept failed: %s\n", strerror(errno)); - continue; - } - - log_info2("cli: telnet: new connection from %s\n", inet_ntoa(addr.sin_addr)); - - if (fcntl(sock, F_SETFL, O_NONBLOCK)) { - log_error("cli: telnet: failed to set nonblocking mode: %s, closing connection...\n", strerror(errno)); - close(sock); - continue; - } - - conn = _malloc(sizeof(*conn)); - memset(conn, 0, sizeof(*conn)); - conn->hnd.fd = sock; - conn->hnd.read = cln_read; - conn->hnd.write = cln_write; - conn->cmdline = _malloc(RECV_BUF_SIZE); - INIT_LIST_HEAD(&conn->xmit_queue); - INIT_LIST_HEAD(&conn->history); - - b = _malloc(sizeof(*b) + RECV_BUF_SIZE); - b->p_buf = b; - b->size = 0; - list_add_tail(&b->entry, &conn->history); - - pthread_mutex_lock(&history_lock); - list_for_each_entry(b, &history, entry) { - b2 = _malloc(sizeof(*b)); - b2->p_buf = b; - b2->size = b->size; - list_add(&b2->entry, conn->history.next); - } - pthread_mutex_unlock(&history_lock); - - conn->history_pos = conn->history.next; - - conn->cli_client.cmdline = conn->cmdline; - conn->cli_client.send = cli_client_send; - conn->cli_client.sendv = cli_client_sendv; - conn->cli_client.disconnect = cli_client_disconnect; - - triton_md_register_handler(&serv_ctx, &conn->hnd); - triton_md_enable_handler(&conn->hnd,MD_MODE_READ); - - list_add_tail(&conn->entry, &clients); - - if (send_banner(conn)) - continue; - - if (send_config(conn)) - continue; - - if (conf_cli_passwd) - send_password_request(conn); - else { - conn->auth = 1; - if (ppp_shutdown) { - if (telnet_send(conn, MSG_SHUTDOWN_IN_PROGRESS, sizeof(MSG_SHUTDOWN_IN_PROGRESS))) - continue; - } - send_prompt(conn); - } - triton_collect_cpu_usage(); - } - return 0; -} -static void serv_close(struct triton_context_t *ctx) -{ - struct telnet_client_t *cln; - - while (!list_empty(&clients)) { - cln = list_entry(clients.next, typeof(*cln), entry); - disconnect(cln); - } - - triton_md_unregister_handler(&serv_hnd); - close(serv_hnd.fd); - triton_context_unregister(ctx); -} - -static struct triton_context_t serv_ctx = { - .close = serv_close, - .before_switch = log_switch, -}; - -static struct triton_md_handler_t serv_hnd = { - .read = serv_read, -}; - -static void start_server(const char *host, int port) -{ - struct sockaddr_in addr; - - serv_hnd.fd = socket(PF_INET, SOCK_STREAM, 0); - if (serv_hnd.fd < 0) { - log_emerg("cli: telnet: failed to create server socket: %s\n", strerror(errno)); - return; - } - - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - if (host) - addr.sin_addr.s_addr = inet_addr(host); - else - addr.sin_addr.s_addr = htonl(INADDR_ANY); - - setsockopt(serv_hnd.fd, SOL_SOCKET, SO_REUSEADDR, &serv_hnd.fd, 4); - if (bind (serv_hnd.fd, (struct sockaddr *) &addr, sizeof (addr)) < 0) { - log_emerg("cli: telnet: failed to bind socket: %s\n", strerror(errno)); - close(serv_hnd.fd); - return; - } - - if (listen (serv_hnd.fd, 1) < 0) { - log_emerg("cli: telnet: failed to listen socket: %s\n", strerror(errno)); - close(serv_hnd.fd); - return; - } - - if (fcntl(serv_hnd.fd, F_SETFL, O_NONBLOCK)) { - log_emerg("cli: telnet: failed to set nonblocking mode: %s\n", strerror(errno)); - close(serv_hnd.fd); - return; - } - - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - addr.sin_addr.s_addr = inet_addr(host); - - triton_context_register(&serv_ctx, NULL); - triton_context_set_priority(&serv_ctx, 1); - triton_md_register_handler(&serv_ctx, &serv_hnd); - triton_md_enable_handler(&serv_hnd, MD_MODE_READ); - triton_context_wakeup(&serv_ctx); -} - -static void save_history_file(void) -{ - int fd; - struct buffer_t *b; - - fd = open(conf_history_file, O_WRONLY | O_TRUNC | O_CREAT, S_IREAD | S_IWRITE); - if (!fd) - return; - - list_for_each_entry(b, &history, entry) { - b->buf[b->size] = '\n'; - write(fd, b->buf, b->size + 1); - } - - close(fd); -} - -static void load_history_file(void) -{ - struct buffer_t *b; - FILE *f; - - f = fopen(conf_history_file, "r"); - if (!f) - return; - - while (fgets((char *)temp_buf, RECV_BUF_SIZE, f)) { - b = _malloc(sizeof(*b) + strlen((char *)temp_buf)); - b->p_buf = NULL; - b->size = strlen((char *)temp_buf) - 1; - memcpy(b->buf, temp_buf, b->size); - list_add_tail(&b->entry, &history); - } - - fclose(f); -} - -static void __init init(void) -{ - const char *opt; - char *host, *d; - int port; - - opt = conf_get_opt("cli", "telnet"); - if (!opt) - return; - - host = strdup(opt); - d = strstr(host, ":"); - if (!d) - goto err_fmt; - - *d = 0; - port = atoi(d + 1); - if (port <= 0) - goto err_fmt; - - opt = conf_get_opt("cli", "history-file"); - if (opt) - conf_history_file = _strdup(opt); - - recv_buf = malloc(RECV_BUF_SIZE); - temp_buf = malloc(RECV_BUF_SIZE); - - load_history_file(); - - start_server(host, port); - - atexit(save_history_file); - - return; -err_fmt: - log_emerg("cli: telnet: invalid format\n"); - free(host); -} - |