diff options
Diffstat (limited to 'accel-pppd/cli')
| -rw-r--r-- | accel-pppd/cli/cli.c | 64 | ||||
| -rw-r--r-- | accel-pppd/cli/cli.h | 8 | ||||
| -rw-r--r-- | accel-pppd/cli/cli_p.h | 84 | ||||
| -rw-r--r-- | accel-pppd/cli/show_sessions.c | 20 | ||||
| -rw-r--r-- | accel-pppd/cli/std_cmd.c | 105 | ||||
| -rw-r--r-- | accel-pppd/cli/tcp.c | 52 | ||||
| -rw-r--r-- | accel-pppd/cli/telnet.c | 52 |
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, ®exp_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, ®exp_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, ®exp_cmd_list, entry) - if (pcre_exec(recmd->re, NULL, cmd, strlen(cmd), - 0, 0, NULL, 0) >= 0) { + list_for_each_entry(recmd, ®exp_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); |
