aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPřemysl Eric Janouch <p@janouch.name>2020-10-31 17:33:11 +0100
committerPřemysl Eric Janouch <p@janouch.name>2020-10-31 17:34:32 +0100
commit32c99c9d66fb210a5ea372c4b90dfdcd96e25955 (patch)
tree42750b14a697444ed29bd90b2853c94e9b0a6415
parentcd7133e1735906d941f5f2ccc2faa083360841d6 (diff)
downloadxK-32c99c9d66fb210a5ea372c4b90dfdcd96e25955.tar.gz
xK-32c99c9d66fb210a5ea372c4b90dfdcd96e25955.tar.xz
xK-32c99c9d66fb210a5ea372c4b90dfdcd96e25955.zip
kike: avoid crash with a wildcard address
A most unfortunate 06d3b3b regression, mostly stemming from forgetting why the `break` was in place and not documenting it.
-rw-r--r--kike.c29
1 files changed, 20 insertions, 9 deletions
diff --git a/kike.c b/kike.c
index 0f57c44..e805e00 100644
--- a/kike.c
+++ b/kike.c
@@ -614,7 +614,8 @@ struct server_context
{
int *listen_fds; ///< Listening socket FD's
struct poller_fd *listen_events; ///< New connections available
- size_t n_listen_fds; ///< Number of listening sockets
+ size_t listen_len; ///< Number of listening sockets
+ size_t listen_alloc; ///< How many we've allocated
time_t started; ///< When has the server been started
@@ -695,7 +696,7 @@ server_context_free (struct server_context *self)
{
str_map_free (&self->config);
- for (size_t i = 0; i < self->n_listen_fds; i++)
+ for (size_t i = 0; i < self->listen_len; i++)
{
poller_fd_reset (&self->listen_events[i]);
xclose (self->listen_fds[i]);
@@ -746,12 +747,12 @@ irc_initiate_quit (struct server_context *ctx)
{
print_status ("shutting down");
- for (size_t i = 0; i < ctx->n_listen_fds; i++)
+ for (size_t i = 0; i < ctx->listen_len; i++)
{
poller_fd_reset (&ctx->listen_events[i]);
xclose (ctx->listen_fds[i]);
}
- ctx->n_listen_fds = 0;
+ ctx->listen_len = 0;
for (struct client *iter = ctx->clients; iter; iter = iter->next)
if (!iter->closing_link)
@@ -3852,16 +3853,19 @@ irc_listen_resolve (struct server_context *ctx,
int fd;
for (gai_iter = gai_result; gai_iter; gai_iter = gai_iter->ai_next)
{
+ if (ctx->listen_len == ctx->listen_alloc)
+ break;
+
if ((fd = irc_listen (gai_iter)) == -1)
continue;
set_blocking (fd, false);
- struct poller_fd *event = &ctx->listen_events[ctx->n_listen_fds];
+ struct poller_fd *event = &ctx->listen_events[ctx->listen_len];
*event = poller_fd_make (&ctx->poller, fd);
event->dispatcher = (poller_fd_fn) on_irc_client_available;
event->user_data = ctx;
- ctx->listen_fds[ctx->n_listen_fds++] = fd;
+ ctx->listen_fds[ctx->listen_len++] = fd;
poller_fd_set (event, POLLIN);
}
freeaddrinfo (gai_result);
@@ -3882,13 +3886,20 @@ irc_setup_listen_fds (struct server_context *ctx, struct error **e)
struct strv ports = strv_make ();
cstr_split (bind_port, ",", true, &ports);
- ctx->listen_fds = xcalloc (ports.len, sizeof *ctx->listen_fds);
- ctx->listen_events = xcalloc (ports.len, sizeof *ctx->listen_events);
+
+ // For C and simplicity's sake let's assume that the host will resolve
+ // to at most two different addresses: IPv4 and IPv6 in case it is NULL
+ ctx->listen_alloc = ports.len * 2;
+
+ ctx->listen_fds =
+ xcalloc (ctx->listen_alloc, sizeof *ctx->listen_fds);
+ ctx->listen_events =
+ xcalloc (ctx->listen_alloc, sizeof *ctx->listen_events);
for (size_t i = 0; i < ports.len; i++)
irc_listen_resolve (ctx, bind_host, ports.vector[i], &gai_hints);
strv_free (&ports);
- if (!ctx->n_listen_fds)
+ if (!ctx->listen_len)
{
error_set (e, "%s: %s",
"network setup failed", "no ports to listen on");