summaryrefslogtreecommitdiff
path: root/accel-pppd/cli
diff options
context:
space:
mode:
authorDenys Fedoryshchenko <denys.f@collabora.com>2026-07-14 01:08:54 +0300
committerGitHub <noreply@github.com>2026-07-14 01:08:54 +0300
commit894e2ff1d3cdc310d1075dd813ffa3d993cd4709 (patch)
tree1db7057e73697feedd34a9ded4cbc03d8b6c4de6 /accel-pppd/cli
parent3ab711d7b2f48ce05825e568239a6f172e42f079 (diff)
parentf1e2e1555dc1c0b2be45192bdd75128e37337cfb (diff)
downloadaccel-ppp-894e2ff1d3cdc310d1075dd813ffa3d993cd4709.tar.gz
accel-ppp-894e2ff1d3cdc310d1075dd813ffa3d993cd4709.zip
Merge pull request #325 from nuclearcat/cli-ipv6-fixes
cli: proper ipv6 support for cli interface
Diffstat (limited to 'accel-pppd/cli')
-rw-r--r--accel-pppd/cli/cli_p.h84
-rw-r--r--accel-pppd/cli/tcp.c52
-rw-r--r--accel-pppd/cli/telnet.c52
3 files changed, 134 insertions, 54 deletions
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/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);