/* SPDX-License-Identifier: LGPL-2.1+ */

#include "resolved-socket-graveyard.h"

#define SOCKET_GRAVEYARD_USEC (5 * USEC_PER_SEC)
#define SOCKET_GRAVEYARD_MAX 100

/* This implements a socket "graveyard" for UDP sockets. If a socket fd is added to the graveyard it is kept
 * open for a couple of more seconds, expecting one reply. Once the reply is received the fd is closed
 * immediately, or if none is received it is closed after the timeout. Why all this? So that if we contact a
 * DNS server, and it doesn't reply instantly, and we lose interest in the response and thus close the fd, we
 * don't end up sending back an ICMP error once the server responds but we aren't listening anymore. (See
 * https://github.com/systemd/systemd/issues/17421 for further information.)
 *
 * Note that we don't allocate any timer event source to clear up the graveyard once the socket's timeout is
 * reached. Instead we operate lazily: we close old entries when adding a new fd to the graveyard, or
 * whenever any code runs manager_socket_graveyard_process() — which the DNS transaction code does right
 * before allocating a new UDP socket. */

static SocketGraveyard* socket_graveyard_free(SocketGraveyard *g) {
        if (!g)
                return NULL;

        if (g->manager) {
                assert(g->manager->n_socket_graveyard > 0);
                g->manager->n_socket_graveyard--;

                if (g->manager->socket_graveyard_oldest == g)
                        g->manager->socket_graveyard_oldest = g->graveyard_prev;

                LIST_REMOVE(graveyard, g->manager->socket_graveyard, g);

                assert((g->manager->n_socket_graveyard > 0) == !!g->manager->socket_graveyard);
                assert((g->manager->n_socket_graveyard > 0) == !!g->manager->socket_graveyard_oldest);
        }

        if (g->io_event_source) {
                log_debug("Closing graveyard socket fd %i", sd_event_source_get_io_fd(g->io_event_source));
                sd_event_source_disable_unref(g->io_event_source);
        }

        return mfree(g);
}

DEFINE_TRIVIAL_CLEANUP_FUNC(SocketGraveyard*, socket_graveyard_free);

void manager_socket_graveyard_process(Manager *m) {
        usec_t n = USEC_INFINITY;

        assert(m);

        while (m->socket_graveyard_oldest) {
                SocketGraveyard *g = m->socket_graveyard_oldest;

                if (n == USEC_INFINITY)
                        assert_se(sd_event_now(m->event, clock_boottime_or_monotonic(), &n) >= 0);

                if (g->deadline > n)
                        break;

                socket_graveyard_free(g);
        }
}

void manager_socket_graveyard_clear(Manager *m) {
        assert(m);

        while (m->socket_graveyard)
                socket_graveyard_free(m->socket_graveyard);
}

static int on_io_event(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
        SocketGraveyard *g = userdata;

        assert(g);

        /* An IO event happened on the graveyard fd. We don't actually care which event that is, and we don't
         * read any incoming packet off the socket. We just close the fd, that's enough to not trigger the
         * ICMP unreachable port event */

        socket_graveyard_free(g);
        return 0;
}

static void manager_socket_graveyard_make_room(Manager *m) {
        assert(m);

        while (m->n_socket_graveyard >= SOCKET_GRAVEYARD_MAX)
                socket_graveyard_free(m->socket_graveyard_oldest);
}

int manager_add_socket_to_graveyard(Manager *m, int fd) {
        _cleanup_(socket_graveyard_freep) SocketGraveyard *g = NULL;
        int r;

        assert(m);
        assert(fd >= 0);

        manager_socket_graveyard_process(m);
        manager_socket_graveyard_make_room(m);

        g = new(SocketGraveyard, 1);
        if (!g)
                return log_oom();

        *g = (SocketGraveyard) {
                .manager = m,
        };

        LIST_PREPEND(graveyard, m->socket_graveyard, g);
        if (!m->socket_graveyard_oldest)
                m->socket_graveyard_oldest = g;

        m->n_socket_graveyard++;

        assert_se(sd_event_now(m->event, clock_boottime_or_monotonic(), &g->deadline) >= 0);
        g->deadline += SOCKET_GRAVEYARD_USEC;

        r = sd_event_add_io(m->event, &g->io_event_source, fd, EPOLLIN, on_io_event, g);
        if (r < 0)
                return log_error_errno(r, "Failed to create graveyard IO source: %m");

        r = sd_event_source_set_io_fd_own(g->io_event_source, true);
        if (r < 0)
                return log_error_errno(r, "Failed to enable graveyard IO source fd ownership: %m");

        (void) sd_event_source_set_description(g->io_event_source, "graveyard");

        log_debug("Added socket %i to graveyard", fd);

        TAKE_PTR(g);
        return 0;
}
