Commit 27946a98 authored by Dan McGee's avatar Dan McGee Committed by Max Kellermann

Set socket TCP keepalive option on incoming connections

If a connected host disappears without our knowledge, as can happen over wireless or a hibernating machine, we continue to hold the port open waiting for messages. Because we never try to send anything down this now-broken pipe, the connection will sit idle taking up a slot in our allowed incoming connections list. If enough of these happen, an unintended Denial of Service takes place, where all connection slots are filled with now-broken, never ending connections. Setting the TCP keepalive option at least allows these to time out after the default two hours, which is sufficient in the non-malicious case. Signed-off-by: 's avatarDan McGee <dan@archlinux.org>
parent 74617389
......@@ -160,12 +160,16 @@ server_socket_in_event(G_GNUC_UNUSED GIOChannel *source,
size_t address_length = sizeof(address);
int fd = accept_cloexec_nonblock(s->fd, (struct sockaddr*)&address,
&address_length);
if (fd >= 0)
if (fd >= 0) {
if (socket_keepalive(fd))
g_warning("Could not set TCP keepalive option: %s",
g_strerror(errno));
s->parent->callback(fd, (const struct sockaddr*)&address,
address_length, get_remote_uid(fd),
s->parent->callback_ctx);
else
} else {
g_warning("accept() failed: %s", g_strerror(errno));
}
return true;
}
......
......@@ -148,3 +148,18 @@ socket_bind_listen(int domain, int type, int protocol,
return fd;
}
int
socket_keepalive(int fd)
{
const int reuse = 1;
#ifdef WIN32
const char *optval = (const char *)&reuse;
#else
const void *optval = &reuse;
#endif
return setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE,
optval, sizeof(reuse));
}
......@@ -63,4 +63,7 @@ socket_bind_listen(int domain, int type, int protocol,
int backlog,
GError **error);
int
socket_keepalive(int fd);
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment