From 207d4821894d9b300496ebdd4443de9fb3b353a1 Mon Sep 17 00:00:00 2001 From: yrutschle Date: Tue, 9 Nov 2021 18:27:52 +0100 Subject: [PATCH] refactor: move udp timeout management to udp module --- Makefile | 6 ++--- processes.c | 2 +- sslh-select.c | 41 --------------------------------- udp-listener.c | 61 +++++++++++++++++++++++++++++++++++++++++--------- udp-listener.h | 9 ++------ 5 files changed, 57 insertions(+), 62 deletions(-) diff --git a/Makefile b/Makefile index e06d269..d8ed217 100644 --- a/Makefile +++ b/Makefile @@ -27,10 +27,10 @@ CC ?= gcc CFLAGS ?=-Wall -DLIBPCRE -g $(CFLAGS_COV) LIBS=-lm -lpcre2-8 -OBJS=sslh-conf.o common.o log.o sslh-main.o probe.o tls.o argtable3.o udp-listener.o collection.o gap.o +OBJS=sslh-conf.o common.o log.o sslh-main.o probe.o tls.o argtable3.o collection.o gap.o FORK_OBJS=sslh-fork.o $(OBJS) -SELECT_OBJS=sslh-select.o $(OBJS) processes.o -EV_OBJS=sslh-ev.o $(OBJS) processes.o +SELECT_OBJS=sslh-select.o $(OBJS) processes.o udp-listener.o +EV_OBJS=sslh-ev.o $(OBJS) processes.o udp-listener.o CONDITIONAL_TARGETS= diff --git a/processes.c b/processes.c index 31b198c..ad79282 100644 --- a/processes.c +++ b/processes.c @@ -224,7 +224,7 @@ int cnx_accept_process(struct loop_info* fd_info, struct listen_endpoint* listen break; case SOCK_DGRAM: - new_fd = udp_c2s_forward(fd, fd_info->collection, watchers_maxfd(fd_info->watchers)); + new_fd = udp_c2s_forward(fd, fd_info); print_message(msg_fd, "new_fd %d\n", new_fd); if (new_fd == -1) return -1; diff --git a/sslh-select.c b/sslh-select.c index 3bcba86..c65847f 100644 --- a/sslh-select.c +++ b/sslh-select.c @@ -30,8 +30,6 @@ #define __LINUX__ -#include - #include "common.h" #include "probe.h" #include "udp-listener.h" @@ -113,41 +111,6 @@ static int fd_is_in_range(int fd) { -/* Check all connections to see if a UDP connections has timed out, then free - * it. At the same time, keep track of the closest, next timeout. Only do the - * search through connections if that timeout actually happened. If the - * connection that would have timed out has had activity, it doesn't matter: we - * go through connections to find the next timeout, which was needed anyway. */ -static void udp_timeouts(struct loop_info* fd_info) -{ - time_t now = time(NULL); - - if (now < fd_info->next_timeout) return; - - time_t next_timeout = INT_MAX; - - for (int i = 0; i < watchers_maxfd(fd_info->watchers); i++) { - /* if it's either in read or write set, there is a connection - * behind that file descriptor */ - struct connection* cnx = collection_get_cnx_from_fd(fd_info->collection, i); - if (cnx) { - time_t timeout = udp_timeout(cnx); - if (!timeout) continue; /* Not a UDP connection */ - if (cnx && (timeout <= now)) { - print_message(msg_fd, "timed out UDP %d\n", cnx->target_sock); - close(cnx->target_sock); - watchers_del_read(fd_info->watchers, i); - watchers_del_write(fd_info->watchers, i); - collection_remove_cnx(fd_info->collection, cnx); - } else { - if (timeout < next_timeout) next_timeout = timeout; - } - } - } - - if (next_timeout != INT_MAX) - fd_info->next_timeout = next_timeout; -} /* Main loop: the idea is as follow: * - fds_r and fds_w contain the file descriptors to monitor in read and write @@ -192,10 +155,6 @@ void main_loop(struct listen_endpoint listen_sockets[], int num_addr_listen) if (res < 0) perror("select"); - - /* UDP timeouts: clear out connections after some idle time */ - udp_timeouts(&fd_info); - /* Check main socket for new connections */ for (i = 0; i < num_addr_listen; i++) { if (FD_ISSET(listen_sockets[i].socketfd, &readfds)) { diff --git a/udp-listener.c b/udp-listener.c index 986a44c..d44cf59 100644 --- a/udp-listener.c +++ b/udp-listener.c @@ -20,12 +20,58 @@ */ +#include + #include "common.h" #include "probe.h" #include "sslh-conf.h" #include "udp-listener.h" +/* returns date at which this socket times out. */ +static int udp_timeout(struct connection* cnx) +{ + if (cnx->type != SOCK_DGRAM) return 0; /* Not a UDP connection */ + + return cnx->proto->udp_timeout + cnx->last_active; +} + +/* Check all connections to see if a UDP connections has timed out, then free + * it. At the same time, keep track of the closest, next timeout. Only do the + * search through connections if that timeout actually happened. If the + * connection that would have timed out has had activity, it doesn't matter: we + * go through connections to find the next timeout, which was needed anyway. */ +void udp_timeouts(struct loop_info* fd_info) +{ + time_t now = time(NULL); + + if (now < fd_info->next_timeout) return; + + time_t next_timeout = INT_MAX; + + for (int i = 0; i < watchers_maxfd(fd_info->watchers); i++) { + /* if it's either in read or write set, there is a connection + * behind that file descriptor */ + struct connection* cnx = collection_get_cnx_from_fd(fd_info->collection, i); + if (cnx) { + time_t timeout = udp_timeout(cnx); + if (!timeout) continue; /* Not a UDP connection */ + if (cnx && (timeout <= now)) { + print_message(msg_fd, "timed out UDP %d\n", cnx->target_sock); + close(cnx->target_sock); + watchers_del_read(fd_info->watchers, i); + watchers_del_write(fd_info->watchers, i); + collection_remove_cnx(fd_info->collection, cnx); + } else { + if (timeout < next_timeout) next_timeout = timeout; + } + } + } + + if (next_timeout != INT_MAX) + fd_info->next_timeout = next_timeout; +} + /* Find if the specified source has been seen before. -1 if not found * * TODO This is linear search and needs to be changed to something better for @@ -53,12 +99,14 @@ static int known_source(cnx_collection* collection, int max_fd, struct sockaddr* * Returns: >= 0 sockfd of newly allocated socket, for new connections * -1 otherwise * */ -int udp_c2s_forward(int sockfd, cnx_collection* collection, int max_fd) +int udp_c2s_forward(int sockfd, struct loop_info* fd_info) { char addr_str[NI_MAXHOST+1+NI_MAXSERV+1]; struct sockaddr src_addr; struct addrinfo addrinfo; struct sslhcfg_protocols_item* proto; + cnx_collection* collection = fd_info->collection; + int max_fd = watchers_maxfd(fd_info->watchers); struct connection* cnx; ssize_t len; socklen_t addrlen; @@ -67,6 +115,8 @@ int udp_c2s_forward(int sockfd, cnx_collection* collection, int max_fd) This will do. Dynamic allocation is possible with the MSG_PEEK flag in recvfrom(2), but that'd imply malloc/free overhead for each packet, when really 64K is not that much */ + udp_timeouts(fd_info); + addrlen = sizeof(src_addr); len = recvfrom(sockfd, data, sizeof(data), 0, &src_addr, &addrlen); if (len < 0) { @@ -125,12 +175,3 @@ void udp_s2c_forward(struct connection* cnx) cnx->last_active = time(NULL); } - -/* returns date at which this socket times out. */ -int udp_timeout(struct connection* cnx) -{ - if (cnx->type != SOCK_DGRAM) return 0; /* Not a UDP connection */ - - return cnx->proto->udp_timeout + cnx->last_active; -} - diff --git a/udp-listener.h b/udp-listener.h index 9439846..23a62dc 100644 --- a/udp-listener.h +++ b/udp-listener.h @@ -2,6 +2,7 @@ #define UDPLISTENER_H #include "collection.h" +#include "processes.h" #include "common.h" /* UDP listener: upon incoming packet, find where it should go @@ -15,15 +16,9 @@ void udp_listener(struct listen_endpoint* endpoint, int num_endpoints, int activ * Returns: >= 0 sockfd of newly allocated socket, for new connections * -1 otherwise * */ -int udp_c2s_forward(int sockfd, cnx_collection* collection, int max_fd); +int udp_c2s_forward(int sockfd, struct loop_info* fd_info); /* Process UDP coming from inside (server towards client) */ void udp_s2c_forward(struct connection* cnx); - -/* returns how many seconds before socket times out. Negative if timed out - * already. - */ -int udp_timeout(struct connection* cnx); - #endif /* UDPLISTENER_H */