summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKozlov Dmitry <dima@server>2010-11-13 15:09:35 +0300
committerKozlov Dmitry <dima@server>2010-11-13 15:09:35 +0300
commited0ad05fccab77caf9f26160c2fbd5f830e5b13c (patch)
treef57122d492c8c60531cb4ce21e2c9fa22df70094
parent1873cf67a900b521021ccd4ae87c0821a64a408d (diff)
downloadaccel-ppp-ed0ad05fccab77caf9f26160c2fbd5f830e5b13c.tar.gz
accel-ppp-ed0ad05fccab77caf9f26160c2fbd5f830e5b13c.zip
cli: implemented tcp frontend to send batch commands
-rw-r--r--accel-pptpd/CMakeLists.txt3
-rw-r--r--accel-pptpd/cli/cli.c37
-rw-r--r--accel-pptpd/cli/telnet.c153
-rw-r--r--accel-pptpd/cli/telnet.h32
-rw-r--r--accel-pptpd/ctrl/pppoe/pppoe.c9
-rw-r--r--accel-pptpd/triton/triton.c9
6 files changed, 146 insertions, 97 deletions
diff --git a/accel-pptpd/CMakeLists.txt b/accel-pptpd/CMakeLists.txt
index 00be4f12..d95bcad4 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 c109862d..534c2c85 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 97e85d0c..69e484f5 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 24515d3e..00000000
--- a/accel-pptpd/cli/telnet.h
+++ /dev/null
@@ -1,32 +0,0 @@
-#ifndef __TELNET_H
-#define __TELNET_H
-
-#include <stdarg.h>
-
-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 f7737cf3..0761609e 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 b2aaa7bb..597288be 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;