From ed0ad05fccab77caf9f26160c2fbd5f830e5b13c Mon Sep 17 00:00:00 2001 From: Kozlov Dmitry Date: Sat, 13 Nov 2010 15:09:35 +0300 Subject: cli: implemented tcp frontend to send batch commands --- accel-pptpd/CMakeLists.txt | 3 +- accel-pptpd/cli/cli.c | 37 ++++++---- accel-pptpd/cli/telnet.c | 153 +++++++++++++++++++++++++++-------------- accel-pptpd/cli/telnet.h | 32 --------- accel-pptpd/ctrl/pppoe/pppoe.c | 9 +++ accel-pptpd/triton/triton.c | 9 +++ 6 files changed, 146 insertions(+), 97 deletions(-) delete mode 100644 accel-pptpd/cli/telnet.h (limited to 'accel-pptpd') diff --git a/accel-pptpd/CMakeLists.txt b/accel-pptpd/CMakeLists.txt index 00be4f1..d95bcad 100644 --- a/accel-pptpd/CMakeLists.txt +++ b/accel-pptpd/CMakeLists.txt @@ -45,9 +45,10 @@ ADD_EXECUTABLE(accel-pptpd ppp/ppp_ccp.c ppp/ccp_mppe.c + cli/std_cmd.c cli/telnet.c + cli/tcp.c cli/cli.c - cli/std_cmd.c pwdb.c ipdb.c diff --git a/accel-pptpd/cli/cli.c b/accel-pptpd/cli/cli.c index c109862..534c2c8 100644 --- a/accel-pptpd/cli/cli.c +++ b/accel-pptpd/cli/cli.c @@ -5,8 +5,8 @@ #include "triton.h" -#include "telnet.h" #include "cli.h" +#include "cli_p.h" #include "log.h" #define MAX_CMD_ITEMS 100 @@ -14,6 +14,9 @@ #define MSG_INVAL_ERROR "invalid argument\r\n" #define MSG_UNKNOWN_CMD "command unknown\r\n" +char *conf_cli_passwd; +const char *conf_cli_prompt = "accel-pptp# "; + static LIST_HEAD(simple_cmd_list); static LIST_HEAD(regexp_cmd_list); @@ -62,19 +65,19 @@ void __export cli_register_regexp_cmd(struct cli_regexp_cmd_t *cmd) int __export cli_send(void *client, const char *data) { - struct client_t *cln = (struct client_t *)client; + struct cli_client_t *cln = (struct cli_client_t *)client; - return telnet_send(cln, data, strlen(data)); + return cln->send(cln, data, strlen(data)); } int __export cli_sendv(void *client, const char *fmt, ...) { - struct client_t *cln = (struct client_t *)client; + struct cli_client_t *cln = (struct cli_client_t *)client; int r; va_list ap; va_start(ap, fmt); - r = telnet_sendv(cln, fmt, ap); + r = cln->sendv(cln, fmt, ap); va_end(ap); return r; @@ -121,7 +124,7 @@ static int split(char *buf, char **ptr) return i; } -int process_cmd(struct client_t *cln) +int cli_process_cmd(struct cli_client_t *cln) { struct cli_simple_cmd_t *cmd1; struct cli_regexp_cmd_t *cmd2; @@ -153,14 +156,14 @@ int process_cmd(struct client_t *cln) r = cmd1->exec((char *)cln->cmdline, f, n, cln); switch (r) { case CLI_CMD_EXIT: - telnet_disconnect(cln); + cln->disconnect(cln); case CLI_CMD_FAILED: return -1; case CLI_CMD_SYNTAX: - telnet_send(cln, MSG_SYNTAX_ERROR, sizeof(MSG_SYNTAX_ERROR)); + cli_send(cln, MSG_SYNTAX_ERROR); return 0; case CLI_CMD_INVAL: - telnet_send(cln, MSG_INVAL_ERROR, sizeof(MSG_INVAL_ERROR)); + cli_send(cln, MSG_INVAL_ERROR); return 0; case CLI_CMD_OK: found = 1; @@ -172,12 +175,11 @@ int process_cmd(struct client_t *cln) r = cmd2->exec((char *)cln->cmdline, cln); switch (r) { case CLI_CMD_EXIT: - telnet_disconnect(cln); + cln->disconnect(cln); case CLI_CMD_FAILED: return -1; case CLI_CMD_SYNTAX: - if (telnet_send(cln, MSG_SYNTAX_ERROR, sizeof(MSG_SYNTAX_ERROR))) - return -1; + cli_send(cln, MSG_SYNTAX_ERROR); return 0; case CLI_CMD_OK: found = 1; @@ -185,10 +187,19 @@ int process_cmd(struct client_t *cln) } if (!found) { - if (telnet_send(cln, MSG_UNKNOWN_CMD, sizeof(MSG_UNKNOWN_CMD))) + if (cli_send(cln, MSG_UNKNOWN_CMD)) return -1; } return 0; } +static void __init init(void) +{ + const char *opt; + + conf_cli_passwd = conf_get_opt("cli", "passwd"); + opt = conf_get_opt("cli", "prompt"); + if (opt) + conf_cli_prompt = opt; +} diff --git a/accel-pptpd/cli/telnet.c b/accel-pptpd/cli/telnet.c index 97e85d0..69e484f 100644 --- a/accel-pptpd/cli/telnet.c +++ b/accel-pptpd/cli/telnet.c @@ -17,7 +17,7 @@ #include "list.h" #include "memdebug.h" -#include "telnet.h" +#include "cli_p.h" #define RECV_BUF_SIZE 1024 #define BANNER "accel-pptp-1.3-rc1\r\n" @@ -28,6 +28,27 @@ #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; @@ -35,21 +56,21 @@ struct buffer_t uint8_t buf[0]; }; -static const char *conf_passwd; -static const char *conf_prompt = "accel-pptp# "; - 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 void disconnect(struct client_t *cln) +static void disconnect(struct telnet_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); @@ -72,12 +93,13 @@ static void disconnect(struct client_t *cln) _free(cln); } -void telnet_disconnect(struct client_t *cln) +static void cli_client_disconnect(struct cli_client_t *tcln) { + struct telnet_client_t *cln = container_of(tcln, typeof(*cln), cli_client); disconnect(cln); } -static void queue_buffer(struct client_t *cln, struct buffer_t *b) +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); @@ -85,7 +107,7 @@ static void queue_buffer(struct client_t *cln, struct buffer_t *b) cln->xmit_buf = b; } -int telnet_send(struct client_t *cln, const void *_buf, int size) +static int telnet_send(struct telnet_client_t *cln, const void *_buf, int size) { int n, k; struct buffer_t *b; @@ -93,6 +115,14 @@ int telnet_send(struct client_t *cln, const void *_buf, int size) 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); @@ -116,8 +146,15 @@ int telnet_send(struct client_t *cln, const void *_buf, int size) return 0; } -int telnet_sendv(struct client_t *cln, const char *fmt, va_list ap) +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) { @@ -128,18 +165,18 @@ int telnet_sendv(struct client_t *cln, const char *fmt, va_list ap) return telnet_send(cln, temp_buf, r); } -static int send_banner(struct client_t *cln) +static int send_banner(struct telnet_client_t *cln) { return telnet_send(cln, BANNER, sizeof(BANNER)); } -static int send_config(struct client_t *cln) +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 client_t *cln) +static int send_password_request(struct telnet_client_t *cln) { uint8_t buf0[] = {IAC, WILL, TELOPT_ECHO}; uint8_t buf1[] = "Password: "; @@ -153,9 +190,9 @@ static int send_password_request(struct client_t *cln) return 0; } -static int send_prompt(struct client_t *cln) +static int send_prompt(struct telnet_client_t *cln) { - return telnet_send(cln, conf_prompt, strlen(conf_prompt)); + return telnet_send(cln, conf_cli_prompt, strlen(conf_cli_prompt)); } /*static void print_buf(const uint8_t *buf, int size) @@ -167,7 +204,7 @@ static int send_prompt(struct client_t *cln) log_debug("\n"); }*/ -static int send_cmdline_tail(struct client_t *cln, int corr) +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; @@ -180,7 +217,7 @@ static int send_cmdline_tail(struct client_t *cln, int corr) return 0; } -static int load_history(struct client_t *cln) +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) { @@ -202,7 +239,7 @@ static int load_history(struct client_t *cln) return 0; } -static int telnet_input_char(struct client_t *cln, uint8_t c) +static int telnet_input_char(struct telnet_client_t *cln, uint8_t c) { uint8_t buf[] = {IAC, DONT, 0}; struct buffer_t *b; @@ -219,7 +256,7 @@ static int telnet_input_char(struct client_t *cln, uint8_t c) } if (!cln->auth) { - if (strcmp((char *)cln->cmdline, conf_passwd)) { + if (strcmp((char *)cln->cmdline, conf_cli_passwd)) { if (telnet_send(cln, AUTH_FAILED, sizeof(AUTH_FAILED))) return -1; disconnect(cln); @@ -233,7 +270,7 @@ static int telnet_input_char(struct client_t *cln, uint8_t c) list_add(&b->entry, cln->history.next); cln->history_pos = cln->history.next; - if (process_cmd(cln)) + if (cli_process_cmd(&cln->cli_client)) return -1; } @@ -394,7 +431,7 @@ static int telnet_input_char(struct client_t *cln, uint8_t c) static int cln_read(struct triton_md_handler_t *h) { - struct client_t *cln = container_of(h, typeof(*cln), hnd); + struct telnet_client_t *cln = container_of(h, typeof(*cln), hnd); int i, n; while (1) { @@ -405,7 +442,7 @@ static int cln_read(struct triton_md_handler_t *h) } if (n < 0) { if (errno != EAGAIN) - log_error("cli: read: %s\n", strerror(errno)); + log_error("cli: telnet: read: %s\n", strerror(errno)); return 0; } /*log_debug("cli: read(%i): ", n); @@ -425,7 +462,7 @@ static int cln_read(struct triton_md_handler_t *h) static int cln_write(struct triton_md_handler_t *h) { - struct client_t *cln = container_of(h, typeof(*cln), hnd); + struct telnet_client_t *cln = container_of(h, typeof(*cln), hnd); int k; while (1) { @@ -435,7 +472,7 @@ static int cln_write(struct triton_md_handler_t *h) if (errno == EAGAIN) return 0; if (errno != EPIPE) - log_error("cli: write: %s\n", strerror(errno)); + log_error("cli: telnet: write: %s\n", strerror(errno)); disconnect(cln); return -1; } @@ -461,7 +498,7 @@ static int serv_read(struct triton_md_handler_t *h) struct sockaddr_in addr; socklen_t size = sizeof(addr); int sock; - struct client_t *conn; + struct telnet_client_t *conn; struct buffer_t *b; while(1) { @@ -469,14 +506,14 @@ static int serv_read(struct triton_md_handler_t *h) if (sock < 0) { if (errno == EAGAIN) return 0; - log_error("cli: accept failed: %s\n", strerror(errno)); + log_error("cli: telnet: accept failed: %s\n", strerror(errno)); continue; } - log_info("cli: new connection from %s\n", inet_ntoa(addr.sin_addr)); + log_info("cli: telnet: new connection from %s\n", inet_ntoa(addr.sin_addr)); if (fcntl(sock, F_SETFL, O_NONBLOCK)) { - log_error("cli: failed to set nonblocking mode: %s, closing connection...\n", strerror(errno)); + log_error("cli: telnet: failed to set nonblocking mode: %s, closing connection...\n", strerror(errno)); close(sock); continue; } @@ -495,16 +532,23 @@ static int serv_read(struct triton_md_handler_t *h) list_add_tail(&b->entry, &conn->history); 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_passwd) + if (conf_cli_passwd) send_password_request(conn); else { conn->auth = 1; @@ -515,6 +559,13 @@ static int serv_read(struct triton_md_handler_t *h) } 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); @@ -534,7 +585,7 @@ static void start_server(const char *host, int port) serv_hnd.fd = socket(PF_INET, SOCK_STREAM, 0); if (serv_hnd.fd < 0) { - log_emerg("cli: failed to create server socket: %s\n", strerror(errno)); + log_emerg("cli: telnet: failed to create server socket: %s\n", strerror(errno)); return; } @@ -548,19 +599,19 @@ static void start_server(const char *host, int port) 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: failed to bind socket: %s\n", strerror(errno)); + 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: failed to listen socket: %s\n", strerror(errno)); + 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: failed to set nonblocking mode: %s\n", strerror(errno)); + log_emerg("cli: telnet: failed to set nonblocking mode: %s\n", strerror(errno)); close(serv_hnd.fd); return; } @@ -578,30 +629,30 @@ static void start_server(const char *host, int port) static void __init init(void) { const char *opt; - int port = 0; - const char *host="127.0.0.1"; - - opt = conf_get_opt("cli", "port"); - if (opt && atoi(opt) > 0) - port = atoi(opt); - - opt = conf_get_opt("cli", "bind"); - if (opt) - host = opt; - - if (!port) { - log_emerg("cli: disabled\n"); - return; + char *host, *d; + int port; + + opt = conf_get_opt("cli", "telnet"); + if (opt) { + host = strdup(opt); + d = strstr(host, ":"); + if (!d) { + return; + } + *d = 0; + port = atoi(d + 1); + if (port <= 0) + goto err_fmt; } - conf_passwd = conf_get_opt("cli", "passwd"); - opt = conf_get_opt("cli", "prompt"); - if (opt) - conf_prompt = opt; - recv_buf = malloc(RECV_BUF_SIZE); temp_buf = malloc(RECV_BUF_SIZE); start_server(host, port); + + return; +err_fmt: + log_emerg("cli: telnet: invalid format\n"); + free(host); } diff --git a/accel-pptpd/cli/telnet.h b/accel-pptpd/cli/telnet.h deleted file mode 100644 index 24515d3..0000000 --- a/accel-pptpd/cli/telnet.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef __TELNET_H -#define __TELNET_H - -#include - -struct client_t -{ - 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; -}; - -int telnet_send(struct client_t *cln, const void *buf, int size); -int telnet_sendv(struct client_t *cln, const char *fmt, va_list ap); -void telnet_disconnect(struct client_t *cln); -int process_cmd(struct client_t *cln); - -#endif - diff --git a/accel-pptpd/ctrl/pppoe/pppoe.c b/accel-pptpd/ctrl/pppoe/pppoe.c index f7737cf..0761609 100644 --- a/accel-pptpd/ctrl/pppoe/pppoe.c +++ b/accel-pptpd/ctrl/pppoe/pppoe.c @@ -854,7 +854,16 @@ static void pppoe_serv_close(struct triton_context_t *ctx) struct pppoe_serv_t *serv = container_of(ctx, typeof(*serv), ctx); triton_md_disable_handler(&serv->hnd, MD_MODE_READ | MD_MODE_WRITE); + serv->stopping = 1; + + pthread_mutex_lock(&serv->lock); + if (!serv->conn_cnt) { + pthread_mutex_unlock(&serv->lock); + pppoe_server_free(serv); + return; + } + pthread_mutex_unlock(&serv->lock); } void pppoe_server_start(const char *ifname, void *cli) diff --git a/accel-pptpd/triton/triton.c b/accel-pptpd/triton/triton.c index b2aaa7b..597288b 100644 --- a/accel-pptpd/triton/triton.c +++ b/accel-pptpd/triton/triton.c @@ -317,6 +317,7 @@ void __export triton_context_unregister(struct triton_context_t *ud) triton_thread_wakeup(t); } } + void __export triton_context_schedule(struct triton_context_t *ud) { struct _triton_context_t *ctx = (struct _triton_context_t *)ud->tpd; @@ -344,6 +345,14 @@ void __export triton_context_schedule(struct triton_context_t *ud) __sync_fetch_and_add(&triton_stat.context_sleeping, 1); } +void triton_context_print(void) +{ + struct _triton_context_t *ctx; + + list_for_each_entry(ctx, &ctx_list, entry) + printf("%p\n", ctx); +} + int __export triton_context_wakeup(struct triton_context_t *ud) { struct _triton_context_t *ctx = (struct _triton_context_t *)ud->tpd; -- cgit v1.2.3