summaryrefslogtreecommitdiff
path: root/accel-pppd/cli
diff options
context:
space:
mode:
Diffstat (limited to 'accel-pppd/cli')
-rw-r--r--accel-pppd/cli/cli.c64
-rw-r--r--accel-pppd/cli/cli.h8
-rw-r--r--accel-pppd/cli/cli_p.h84
-rw-r--r--accel-pppd/cli/show_sessions.c20
-rw-r--r--accel-pppd/cli/std_cmd.c105
-rw-r--r--accel-pppd/cli/tcp.c52
-rw-r--r--accel-pppd/cli/telnet.c52
7 files changed, 232 insertions, 153 deletions
diff --git a/accel-pppd/cli/cli.c b/accel-pppd/cli/cli.c
index 7d440727..6b71cb04 100644
--- a/accel-pppd/cli/cli.c
+++ b/accel-pppd/cli/cli.c
@@ -63,51 +63,6 @@ void __export cli_register_simple_cmd2(
va_end(ap);
}
-void __export cli_register_regexp_cmd(struct cli_regexp_cmd_t *cmd)
-{
- int err;
- int erroffset;
- const char *errptr;
-
- if (cmd->exec == NULL) {
- log_emerg("cli: impossible to register regexp command"
- " without an execution callback function\n");
- _exit(EXIT_FAILURE);
- }
- if (cmd->pattern == NULL) {
- log_emerg("cli: impossible to register regexp command"
- " without pattern\n");
- _exit(EXIT_FAILURE);
- }
- cmd->re = pcre_compile2(cmd->pattern, cmd->options, &err,
- &errptr, &erroffset, NULL);
- if (!cmd->re) {
- log_emerg("cli: failed to compile regexp \"%s\": %s (error %i)"
- " at positon %i (unprocessed characters: \"%s\")\n",
- cmd->pattern, errptr, err, erroffset,
- cmd->pattern + erroffset);
- _exit(EXIT_FAILURE);
- }
-
- if (cmd->h_pattern) {
- cmd->h_re = pcre_compile2(cmd->h_pattern, cmd->h_options, &err,
- &errptr, &erroffset, NULL);
- if (!cmd->h_re) {
- log_emerg("cli: failed to compile help regexp \"%s\":"
- " %s (error %i) at position %i (unprocessed"
- " characters: \"%s\")\n",
- cmd->h_pattern, errptr, err, erroffset,
- cmd->h_pattern + erroffset);
- _exit(EXIT_FAILURE);
- }
- } else {
- cmd->h_re = NULL;
- cmd->h_pattern = NULL;
- }
-
- list_add_tail(&cmd->entry, &regexp_cmd_list);
-}
-
int __export cli_send(void *client, const char *data)
{
struct cli_client_t *cln = (struct cli_client_t *)client;
@@ -189,13 +144,15 @@ static int cli_process_help_cmd(struct cli_client_t *cln)
cmd_found = 1;
list_for_each_entry(recmd, &regexp_cmd_list, entry) {
+ pcre2_match_data *match_data = pcre2_match_data_create(0, NULL);
if (cmd[0] == '\0'
- || pcre_exec(recmd->h_re, NULL, cmd, strlen(cmd),
- 0, 0, NULL, 0) >= 0) {
+ || pcre2_match(recmd->h_re, (PCRE2_SPTR)cmd, strlen(cmd),
+ 0, 0, match_data, NULL) >= 0) {
cmd_found = 1;
if (recmd->help)
recmd->help(cmd, cln);
}
+ pcre2_match_data_free(match_data);
}
nb_items = split(cmd, items);
@@ -230,14 +187,19 @@ static int cli_process_regexp_cmd(struct cli_client_t *cln, int *err)
int res;
cmd = skip_space(cmd);
- list_for_each_entry(recmd, &regexp_cmd_list, entry)
- if (pcre_exec(recmd->re, NULL, cmd, strlen(cmd),
- 0, 0, NULL, 0) >= 0) {
+ list_for_each_entry(recmd, &regexp_cmd_list, entry) {
+ pcre2_match_data *match_data = pcre2_match_data_create(0, NULL);
+ if (pcre2_match(recmd->re, (PCRE2_SPTR)cmd, strlen(cmd),
+ 0, 0, match_data, NULL) >= 0) {
found = 1;
res = recmd->exec(cmd, cln);
- if (res != CLI_CMD_OK)
+ if (res != CLI_CMD_OK) {
+ pcre2_match_data_free(match_data);
break;
+ }
}
+ pcre2_match_data_free(match_data);
+ }
if (found)
*err = res;
diff --git a/accel-pppd/cli/cli.h b/accel-pppd/cli/cli.h
index 6eda5d3f..3d8069b3 100644
--- a/accel-pppd/cli/cli.h
+++ b/accel-pppd/cli/cli.h
@@ -1,7 +1,8 @@
#ifndef __CLI_H
#define __CLI_H
-#include <pcre.h>
+#define PCRE2_CODE_UNIT_WIDTH 8
+#include <pcre2.h>
#include "list.h"
@@ -23,11 +24,11 @@ struct cli_simple_cmd_t
struct cli_regexp_cmd_t
{
struct list_head entry;
- pcre *re;
+ pcre2_code *re;
const char *pattern;
int options;
int (*exec)(const char *cmd, void *client);
- pcre *h_re;
+ pcre2_code *h_re;
const char *h_pattern;
int h_options;
int (*help)(const char *cmd, void *client);
@@ -42,7 +43,6 @@ void cli_register_simple_cmd2(
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)(struct ap_session *ses, char *buf));
int cli_send(void *client, const char *data);
diff --git a/accel-pppd/cli/cli_p.h b/accel-pppd/cli/cli_p.h
index 0fcba309..79208e13 100644
--- a/accel-pppd/cli/cli_p.h
+++ b/accel-pppd/cli/cli_p.h
@@ -2,6 +2,11 @@
#define __CLI_P_H
#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
#include "triton.h"
@@ -15,6 +20,85 @@ struct cli_client_t
int cli_process_cmd(struct cli_client_t *cln);
+/* Format peer address (IPv4, IPv6 or IPv4-mapped IPv6) for logging.
+ * buf must be at least INET6_ADDRSTRLEN bytes long. */
+static inline const char *cli_addr_str(const struct sockaddr_storage *addr,
+ char *buf, size_t size)
+{
+ const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)addr;
+ const struct sockaddr_in *sin = (const struct sockaddr_in *)addr;
+
+ buf[0] = '\0';
+ if (addr->ss_family == AF_INET6) {
+ if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr))
+ inet_ntop(AF_INET, &sin6->sin6_addr.s6_addr32[3], buf, size);
+ else
+ inet_ntop(AF_INET6, &sin6->sin6_addr, buf, size);
+ } else
+ inet_ntop(AF_INET, &sin->sin_addr, buf, size);
+
+ return buf;
+}
+
+/* Parse "host:port", "[host]:port" or ":port" listener specification.
+ * str is modified in place, *host points into str afterwards (NULL for
+ * empty host). For unbracketed hosts the last ':' separates the port,
+ * so bare IPv6 addresses like "::1:2001" are accepted too.
+ * Returns 0 on success, -1 on invalid format. */
+static inline int cli_parse_hostport(char *str, const char **host, int *port)
+{
+ char *d;
+
+ if (*str == '[') {
+ ++str;
+ d = strchr(str, ']');
+ if (!d || d[1] != ':')
+ return -1;
+ *d++ = '\0';
+ } else {
+ d = strrchr(str, ':');
+ if (!d)
+ return -1;
+ }
+
+ *d = '\0';
+ *port = atoi(d + 1);
+ if (*port <= 0)
+ return -1;
+
+ *host = *str ? str : NULL;
+
+ return 0;
+}
+
+/* Fill sockaddr for binding a CLI listener. host may be an IPv4 or IPv6
+ * address; NULL host means any IPv4 address (use "::" for IPv6 wildcard).
+ * Returns 0 on success, -1 if host is not a valid address. */
+static inline int cli_bind_addr(const char *host, int port,
+ struct sockaddr_storage *addr, socklen_t *len)
+{
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr;
+ struct sockaddr_in *sin = (struct sockaddr_in *)addr;
+
+ memset(addr, 0, sizeof(*addr));
+
+ if (host && inet_pton(AF_INET6, host, &sin6->sin6_addr) > 0) {
+ sin6->sin6_family = AF_INET6;
+ sin6->sin6_port = htons(port);
+ *len = sizeof(*sin6);
+ } else {
+ sin->sin_family = AF_INET;
+ sin->sin_port = htons(port);
+ if (!host)
+ sin->sin_addr.s_addr = htonl(INADDR_ANY);
+ else if (inet_pton(AF_INET, host, &sin->sin_addr) <= 0)
+ return -1;
+ *len = sizeof(*sin);
+ }
+
+ return 0;
+}
+
extern char *conf_cli_passwd;
extern char *conf_cli_prompt;
diff --git a/accel-pppd/cli/show_sessions.c b/accel-pppd/cli/show_sessions.c
index 22f5318a..75649c4a 100644
--- a/accel-pppd/cli/show_sessions.c
+++ b/accel-pppd/cli/show_sessions.c
@@ -128,9 +128,9 @@ static int show_ses_exec(const char *cmd, char * const *f, int f_cnt, void *cli)
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;
+ pcre2_code *re = NULL;
+ int pcre_err;
+ PCRE2_SIZE pcre_offset;
struct column_t *column;
struct col_t *col;
struct row_t *row;
@@ -169,9 +169,11 @@ static int show_ses_exec(const char *cmd, char * const *f, int f_cnt, void *cli)
}
if (match_key) {
- re = pcre_compile2(match_pattern, 0, NULL, &pcre_err, &pcre_offset, NULL);
+ re = pcre2_compile((PCRE2_SPTR)match_pattern, PCRE2_ZERO_TERMINATED, 0, &pcre_err, &pcre_offset, NULL);
if (!re) {
- cli_sendv(cli, "match: %s at %i\r\n", pcre_err, pcre_offset);
+ PCRE2_UCHAR err_msg[64];
+ pcre2_get_error_message(pcre_err, err_msg, sizeof(err_msg));
+ cli_sendv(cli, "match: %s at %i\r\n", err_msg, (int)pcre_offset);
return CLI_CMD_OK;
}
}
@@ -245,6 +247,7 @@ static int show_ses_exec(const char *cmd, char * const *f, int f_cnt, void *cli)
goto oom;
cell->col = col;
list_add_tail(&cell->entry, &row->cell_list);
+ cell->buf[0] = 0;
col->column->print(ses, cell->buf);
n = strlen(cell->buf);
if (n > col->width)
@@ -262,10 +265,13 @@ static int show_ses_exec(const char *cmd, char * const *f, int f_cnt, void *cli)
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) {
+ pcre2_match_data *match_data = pcre2_match_data_create(0, NULL);
+ if (pcre2_match(re, (PCRE2_SPTR)row->match_key, strlen(row->match_key), 0, 0, match_data, NULL) < 0) {
free_row(row);
+ pcre2_match_data_free(match_data);
continue;
}
+ pcre2_match_data_free(match_data);
}
if (order_key)
insert_row(&r_list, row);
@@ -362,7 +368,7 @@ out:
}
if (re)
- pcre_free(re);
+ pcre2_code_free(re);
return CLI_CMD_OK;
diff --git a/accel-pppd/cli/std_cmd.c b/accel-pppd/cli/std_cmd.c
index fc073526..1d15a28c 100644
--- a/accel-pppd/cli/std_cmd.c
+++ b/accel-pppd/cli/std_cmd.c
@@ -5,6 +5,7 @@
#include <signal.h>
#include <malloc.h>
#include <arpa/inet.h>
+#include <inttypes.h>
#include "triton.h"
#include "events.h"
@@ -29,6 +30,9 @@ static int show_stat_exec(const char *cmd, char * const *fields, int fields_cnt,
#ifdef MEMDEBUG
struct mallinfo mi = mallinfo();
#endif
+ struct triton_stat_t stat;
+
+ triton_stat_get(&stat);
sprintf(statm_fname, "/proc/%i/statm", getpid());
f = fopen(statm_fname, "r");
@@ -38,14 +42,14 @@ static int show_stat_exec(const char *cmd, char * const *fields, int fields_cnt,
}
clock_gettime(CLOCK_MONOTONIC, &ts);
- dt = ts.tv_sec - triton_stat.start_time;
+ dt = ts.tv_sec - 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:%02lu:%02lu\r\n", day, hour, dt / 60, dt % 60);
- cli_sendv(client, "cpu: %i%%\r\n", triton_stat.cpu);
+ cli_sendv(client, "cpu: %i%%\r\n", stat.cpu);
#ifdef MEMDEBUG
cli_send(client, "memory:\r\n");
cli_sendv(client, " rss/virt: %lu/%lu kB\r\n", vmrss * page_size_kb, vmsize * page_size_kb);
@@ -57,23 +61,29 @@ static int show_stat_exec(const char *cmd, char * const *fields, int fields_cnt,
cli_sendv(client, "mem(rss/virt): %lu/%lu kB\r\n", vmrss * page_size_kb, vmsize * page_size_kb);
#endif
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_sendv(client, " mempool_allocated: %" PRIu64 "\r\n", stat.mempool_allocated);
+ cli_sendv(client, " mempool_available: %" PRIu64 "\r\n", stat.mempool_available);
+ cli_sendv(client, " thread_count: %u\r\n", stat.thread_count);
+ cli_sendv(client, " thread_active: %u\r\n", stat.thread_active);
+ cli_sendv(client, " context_count: %u\r\n", stat.context_count);
+ cli_sendv(client, " context_sleeping: %u\r\n", stat.context_sleeping);
+ cli_sendv(client, " context_pending: %u\r\n", stat.context_pending);
+ cli_sendv(client, " md_handler_count: %u\r\n", stat.md_handler_count);
+ cli_sendv(client, " md_handler_pending: %u\r\n", stat.md_handler_pending);
+ cli_sendv(client, " timer_count: %u\r\n", stat.timer_count);
+ cli_sendv(client, " timer_pending: %u\r\n", stat.timer_pending);
//===========
- cli_send(client, "sessions:\r\n");
- cli_sendv(client, " starting: %u\r\n", ap_session_stat.starting);
- cli_sendv(client, " active: %u\r\n", ap_session_stat.active);
- cli_sendv(client, " finishing: %u\r\n", ap_session_stat.finishing);
+ {
+ struct ap_session_stat ses_stat;
+
+ ap_session_stat_get(&ses_stat);
+
+ cli_send(client, "sessions:\r\n");
+ cli_sendv(client, " starting: %u\r\n", ses_stat.starting);
+ cli_sendv(client, " active: %u\r\n", ses_stat.active);
+ cli_sendv(client, " finishing: %u\r\n", ses_stat.finishing);
+ }
return CLI_CMD_OK;
}
@@ -123,9 +133,9 @@ static int terminate_exec1(char * const *f, int f_cnt, void *cli)
{
struct ap_session *ses;
int hard = 0;
- pcre *re;
- const char *pcre_err;
- int pcre_offset;
+ pcre2_code *re;
+ int pcre_err;
+ PCRE2_SIZE pcre_offset;
if (f_cnt == 5) {
if (!strcmp(f[4], "hard"))
@@ -135,9 +145,11 @@ static int terminate_exec1(char * const *f, int f_cnt, void *cli)
} else if (f_cnt != 4)
return CLI_CMD_SYNTAX;
- re = pcre_compile2(f[3], 0, NULL, &pcre_err, &pcre_offset, NULL);
+ re = pcre2_compile((PCRE2_SPTR)f[3], PCRE2_ZERO_TERMINATED, 0, &pcre_err, &pcre_offset, NULL);
if (!re) {
- cli_sendv(cli, "match: %s at %i\r\n", pcre_err, pcre_offset);
+ PCRE2_UCHAR err_msg[64];
+ pcre2_get_error_message(pcre_err, err_msg, sizeof(err_msg));
+ cli_sendv(cli, "match: %s at %i\r\n", err_msg, (int)pcre_offset);
return CLI_CMD_OK;
}
@@ -145,8 +157,12 @@ static int terminate_exec1(char * const *f, int f_cnt, void *cli)
list_for_each_entry(ses, &ses_list, entry) {
if (!ses->username)
continue;
- if (pcre_exec(re, NULL, ses->username, strlen(ses->username), 0, 0, NULL, 0) < 0)
+ pcre2_match_data *match_data = pcre2_match_data_create(0, NULL);
+ if (pcre2_match(re, (PCRE2_SPTR)ses->username, strlen(ses->username), 0, 0, match_data, NULL) < 0) {
+ pcre2_match_data_free(match_data);
continue;
+ }
+ pcre2_match_data_free(match_data);
if (hard)
triton_context_call(ses->ctrl->ctx, (triton_event_func)__terminate_hard, ses);
else
@@ -154,7 +170,7 @@ static int terminate_exec1(char * const *f, int f_cnt, void *cli)
}
pthread_rwlock_unlock(&ses_lock);
- pcre_free(re);
+ pcre2_code_free(re);
return CLI_CMD_OK;
}
@@ -324,26 +340,41 @@ static int shutdown_exec(const char *cmd, char * const *f, int f_cnt, void *cli)
}
//==========================
-static int conf_reload_res;
-static struct triton_context_t *conf_reload_ctx;
-static void conf_reload_notify(int r)
+struct conf_reload_req {
+ struct triton_context_t *ctx;
+ int res;
+};
+static void conf_reload_notify(int r, void *arg)
{
+ struct conf_reload_req *req = arg;
+
if (!r)
triton_event_fire(EV_CONFIG_RELOAD, NULL);
- conf_reload_res = r;
- triton_context_wakeup(conf_reload_ctx);
+ req->res = r;
+ triton_context_wakeup(req->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
+ struct conf_reload_req *req;
+
+ if (f_cnt != 1)
return CLI_CMD_SYNTAX;
+
+ /* heap-allocated: triton_context_schedule() can migrate this
+ * context to another worker thread's stack before notify runs */
+ req = _malloc(sizeof(*req));
+ req->ctx = triton_context_self();
+
+ if (triton_conf_reload(conf_reload_notify, req)) {
+ _free(req);
+ cli_send(cli, "reload is already in progress\r\n");
+ return CLI_CMD_OK;
+ }
+ triton_context_schedule();
+ if (req->res)
+ cli_send(cli, "failed\r\n");
+ _free(req);
+ return CLI_CMD_OK;
}
static void reload_help(char * const *fields, int fields_cnt, void *client)
diff --git a/accel-pppd/cli/tcp.c b/accel-pppd/cli/tcp.c
index 8952661a..beba16ca 100644
--- a/accel-pppd/cli/tcp.c
+++ b/accel-pppd/cli/tcp.c
@@ -24,7 +24,7 @@ struct tcp_client_t {
struct cli_client_t cli_client;
struct list_head entry;
struct triton_md_handler_t hnd;
- struct sockaddr_in addr;
+ struct sockaddr_storage addr;
struct list_head xmit_queue;
struct buffer_t *xmit_buf;
uint8_t *cmdline;
@@ -174,8 +174,10 @@ static int cln_read(struct triton_md_handler_t *h)
goto disconn_hard;
cln->auth = 1;
} else {
- if (conf_verbose == 2)
- log_info2("cli: %s: %s\n", inet_ntoa(cln->addr.sin_addr), cln->cmdline);
+ if (conf_verbose == 2) {
+ char buf[INET6_ADDRSTRLEN];
+ log_info2("cli: %s: %s\n", cli_addr_str(&cln->addr, buf, sizeof(buf)), cln->cmdline);
+ }
cli_process_cmd(&cln->cli_client);
}
@@ -248,12 +250,14 @@ disconn:
static int serv_read(struct triton_md_handler_t *h)
{
- struct sockaddr_in addr;
- socklen_t size = sizeof(addr);
+ struct sockaddr_storage addr;
+ socklen_t size;
int sock;
struct tcp_client_t *conn;
+ char buf[INET6_ADDRSTRLEN];
while(1) {
+ size = sizeof(addr);
sock = accept(h->fd, (struct sockaddr *)&addr, &size);
if (sock < 0) {
if (errno == EAGAIN)
@@ -263,7 +267,7 @@ static int serv_read(struct triton_md_handler_t *h)
}
if (conf_verbose)
- log_info2("cli: tcp: new connection from %s\n", inet_ntoa(addr.sin_addr));
+ log_info2("cli: tcp: new connection from %s\n", cli_addr_str(&addr, buf, sizeof(buf)));
if (fcntl(sock, F_SETFL, O_NONBLOCK)) {
log_error("cli: tcp: failed to set nonblocking mode: %s, closing connection...\n", strerror(errno));
@@ -320,9 +324,16 @@ static struct triton_md_handler_t serv_hnd = {
static void start_server(const char *host, int port)
{
- struct sockaddr_in addr;
+ struct sockaddr_storage addr;
+ socklen_t addrlen;
+ int f = 1;
+
+ if (cli_bind_addr(host, port, &addr, &addrlen) < 0) {
+ log_emerg("cli: tcp: invalid address '%s'\n", host);
+ return;
+ }
- serv_hnd.fd = socket(PF_INET, SOCK_STREAM, 0);
+ serv_hnd.fd = socket(addr.ss_family, SOCK_STREAM, 0);
if (serv_hnd.fd < 0) {
log_emerg("cli: tcp: failed to create server socket: %s\n", strerror(errno));
return;
@@ -330,16 +341,8 @@ static void start_server(const char *host, int port)
fcntl(serv_hnd.fd, F_SETFD, fcntl(serv_hnd.fd, F_GETFD) | FD_CLOEXEC);
- 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) {
+ setsockopt(serv_hnd.fd, SOL_SOCKET, SO_REUSEADDR, &f, sizeof(f));
+ if (bind (serv_hnd.fd, (struct sockaddr *) &addr, addrlen) < 0) {
log_emerg("cli: tcp: failed to bind socket: %s\n", strerror(errno));
close(serv_hnd.fd);
return;
@@ -378,7 +381,8 @@ static void load_config(void)
static void init(void)
{
const char *opt;
- char *host, *d;
+ const char *addr;
+ char *host;
int port;
opt = conf_get_opt("cli", "tcp");
@@ -386,20 +390,14 @@ static void init(void)
return;
host = strdup(opt);
- d = strstr(host, ":");
- if (!d)
- goto err_fmt;
-
- *d = 0;
- port = atoi(d + 1);
- if (port <= 0)
+ if (cli_parse_hostport(host, &addr, &port) < 0)
goto err_fmt;
load_config();
temp_buf = malloc(RECV_BUF_SIZE);
- start_server(host, port);
+ start_server(addr, port);
triton_event_register_handler(EV_CONFIG_RELOAD, (triton_event_func)load_config);
diff --git a/accel-pppd/cli/telnet.c b/accel-pppd/cli/telnet.c
index 7d5009c2..88a9d8b0 100644
--- a/accel-pppd/cli/telnet.c
+++ b/accel-pppd/cli/telnet.c
@@ -37,7 +37,7 @@ struct telnet_client_t {
struct cli_client_t cli_client;
struct list_head entry;
struct triton_md_handler_t hnd;
- struct sockaddr_in addr;
+ struct sockaddr_storage addr;
struct list_head xmit_queue;
struct buffer_t *xmit_buf;
int xmit_pos;
@@ -305,8 +305,10 @@ static int telnet_input_char(struct telnet_client_t *cln, uint8_t c)
list_add(&b->entry, cln->history.next);
cln->history_pos = cln->history.next;
- if (conf_verbose == 2)
- log_info2("cli: %s: %s\n", inet_ntoa(cln->addr.sin_addr), cln->cmdline);
+ if (conf_verbose == 2) {
+ char abuf[INET6_ADDRSTRLEN];
+ log_info2("cli: %s: %s\n", cli_addr_str(&cln->addr, abuf, sizeof(abuf)), cln->cmdline);
+ }
if (cli_process_cmd(&cln->cli_client))
return -1;
@@ -556,13 +558,15 @@ disconn:
static int serv_read(struct triton_md_handler_t *h)
{
- struct sockaddr_in addr;
- socklen_t size = sizeof(addr);
+ struct sockaddr_storage addr;
+ socklen_t size;
int sock;
struct telnet_client_t *conn;
struct buffer_t *b, *b2;
+ char abuf[INET6_ADDRSTRLEN];
while(1) {
+ size = sizeof(addr);
sock = accept(h->fd, (struct sockaddr *)&addr, &size);
if (sock < 0) {
if (errno == EAGAIN)
@@ -572,7 +576,7 @@ static int serv_read(struct triton_md_handler_t *h)
}
if (conf_verbose)
- log_info2("cli: telnet: new connection from %s\n", inet_ntoa(addr.sin_addr));
+ log_info2("cli: telnet: new connection from %s\n", cli_addr_str(&addr, abuf, sizeof(abuf)));
fcntl(sock, F_SETFL, O_NONBLOCK);
fcntl(sock, F_SETFD, fcntl(sock, F_GETFD) | FD_CLOEXEC);
@@ -657,9 +661,16 @@ static struct triton_md_handler_t serv_hnd = {
static void start_server(const char *host, int port)
{
- struct sockaddr_in addr;
+ struct sockaddr_storage addr;
+ socklen_t addrlen;
+ int f = 1;
+
+ if (cli_bind_addr(host, port, &addr, &addrlen) < 0) {
+ log_emerg("cli: telnet: invalid address '%s'\n", host);
+ return;
+ }
- serv_hnd.fd = socket(PF_INET, SOCK_STREAM, 0);
+ serv_hnd.fd = socket(addr.ss_family, SOCK_STREAM, 0);
if (serv_hnd.fd < 0) {
log_emerg("cli: telnet: failed to create server socket: %s\n", strerror(errno));
return;
@@ -667,16 +678,8 @@ static void start_server(const char *host, int port)
fcntl(serv_hnd.fd, F_SETFD, fcntl(serv_hnd.fd, F_GETFD) | FD_CLOEXEC);
- 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) {
+ setsockopt(serv_hnd.fd, SOL_SOCKET, SO_REUSEADDR, &f, sizeof(f));
+ if (bind (serv_hnd.fd, (struct sockaddr *) &addr, addrlen) < 0) {
log_emerg("cli: telnet: failed to bind socket: %s\n", strerror(errno));
close(serv_hnd.fd);
return;
@@ -755,7 +758,8 @@ static void load_config(void)
static void init(void)
{
const char *opt;
- char *host, *d;
+ const char *addr;
+ char *host;
int port;
opt = conf_get_opt("cli", "telnet");
@@ -763,13 +767,7 @@ static void init(void)
return;
host = strdup(opt);
- d = strstr(host, ":");
- if (!d)
- goto err_fmt;
-
- *d = 0;
- port = atoi(d + 1);
- if (port <= 0)
+ if (cli_parse_hostport(host, &addr, &port) < 0)
goto err_fmt;
opt = conf_get_opt("cli", "history-file");
@@ -783,7 +781,7 @@ static void init(void)
load_history_file();
- start_server(host, port);
+ start_server(addr, port);
atexit(save_history_file);