From 3ab2acdafa38154567d458fbe7b772a6557e361a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yves=20Rutschl=C3=A9?= Date: Thu, 11 Jan 2018 14:45:32 +0000 Subject: [PATCH] fix fork failure handling --- sslh-fork.c | 8 +++---- sslh-select.c | 65 ++++++++++++++++++++++++--------------------------- 2 files changed, 34 insertions(+), 39 deletions(-) diff --git a/sslh-fork.c b/sslh-fork.c index 87ca95b..5ed91d8 100644 --- a/sslh-fork.c +++ b/sslh-fork.c @@ -166,15 +166,15 @@ void main_loop(int listen_sockets[], int num_addr_listen) case -1: log_message(LOG_ERR, "fork failed: err %d: %s\n", errno, strerror(errno)); break; - /* In parent process */ - case 0: break; - /* In child process */ - default: + case 0: for (i = 0; i < num_addr_listen; ++i) close(listen_sockets[i]); start_shoveler(in_socket); exit(0); + + /* In parent process */ + default: break; } close(in_socket); } diff --git a/sslh-select.c b/sslh-select.c index 54f0419..2fa83fe 100644 --- a/sslh-select.c +++ b/sslh-select.c @@ -275,18 +275,6 @@ void connect_proxy(struct connection *cnx) exit(0); } -/* Close all connection fd except one (used when forking) */ -void keep_cnx(int index, struct connection* cnx, int num_cnx) -{ - int i, j; - - for (i = 0; i < num_cnx; i++) - if (i != index) - for (j = 0; j < 2; j++) - if (cnx[i].q[j].fd != -1) - close(cnx[i].q[j].fd); -} - /* returns true if specified fd is initialised and present in fd_set */ int is_fd_active(int fd, fd_set* set) { @@ -422,29 +410,36 @@ void main_loop(int listen_sockets[], int num_addr_listen) num_probing--; cnx[i].state = ST_SHOVELING; - /* libwrap check if required for this protocol */ - if (cnx[i].proto->service && - check_access_rights(in_socket, cnx[i].proto->service)) { - tidy_connection(&cnx[i], &fds_r, &fds_w); - res = -1; - } else if (cnx[i].proto->fork) { - switch (fork()) { - case 0: break; - case -1: log_message(LOG_ERR, "fork failed: err %d: %s\n", errno, strerror(errno)); - break; - default: - for (i = 0; i < num_addr_listen; i++) - close(listen_sockets[i]); - keep_cnx(i, cnx, num_cnx); - free(cnx); - connect_proxy(&cnx[i]); - exit(0); - } - tidy_connection(&cnx[i], &fds_r, &fds_w); - res = -1; - } else { - res = connect_queue(&cnx[i], &fds_r, &fds_w); - } + /* libwrap check if required for this protocol */ + if (cnx[i].proto->service && + check_access_rights(in_socket, cnx[i].proto->service)) { + tidy_connection(&cnx[i], &fds_r, &fds_w); + res = -1; + } else if (cnx[i].proto->fork) { + struct connection *pcnx_i = &cnx[i]; + struct connection cnx_i = *pcnx_i; + switch (fork()) { + case 0: /* child */ + for (i = 0; i < num_addr_listen; i++) + close(listen_sockets[i]); + for (i = 0; i < num_cnx; i++) + if (&cnx[i] != pcnx_i) + for (j = 0; j < 2; j++) + if (cnx[i].q[j].fd != -1) + close(cnx[i].q[j].fd); + free(cnx); + connect_proxy(&cnx_i); + exit(0); + case -1: log_message(LOG_ERR, "fork failed: err %d: %s\n", errno, strerror(errno)); + break; + default: /* parent */ + break; + } + tidy_connection(&cnx[i], &fds_r, &fds_w); + res = -1; + } else { + res = connect_queue(&cnx[i], &fds_r, &fds_w); + } if (res >= max_fd) max_fd = res + 1;;