Created
July 16, 2020 05:20
-
-
Save marktheunissen/197747dfeb44cf583a85fdf546364f8b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
commit 13a26e81a7d5dba116a7f4729ce977569cade34d | |
Author: Michal Trojnara <[email protected]> | |
Date: Thu Oct 2 13:09:51 2014 +0200 | |
systemd socket activation | |
diff --git a/CREDITS b/CREDITS | |
index 8ece5a7..e649af8 100644 | |
--- a/CREDITS | |
+++ b/CREDITS | |
@@ -1,9 +1,35 @@ | |
-Special thx to: | |
+stunnel code contributions | |
+ | |
+systemd socket activation in version 5.05: | |
+Copyright (c) 2014 Mark Theunissen | |
+ | |
+Permission is hereby granted, free of charge, to any person obtaining a copy of | |
+this software and associated documentation files (the "Software"), to deal in | |
+the Software without restriction, including without limitation the rights to | |
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies | |
+of the Software, and to permit persons to whom the Software is furnished to do | |
+so, subject to the following conditions: | |
+ | |
+The above copyright notice and this permission notice shall be included in all | |
+copies or substantial portions of the Software. | |
+ | |
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
+SOFTWARE. | |
+ | |
+Several bugfixes and improvements: | |
+* Brian Hatch <[email protected]> | |
+ | |
+Initial PTY support in version 3.05: | |
+* Dirk O. Siebnich <[email protected]> | |
+ | |
+Initial SSL support in versions 1.x: | |
* Adam Hernik <[email protected]> | |
* Pawel Krawczyk <[email protected]> | |
-* Brian Hatch <[email protected]> | |
-* Dirk O. Siebnich <[email protected]> for PTY support | |
and many others... | |
- | |
diff --git a/ChangeLog b/ChangeLog | |
index 3c8b991..13b14f7 100644 | |
--- a/ChangeLog | |
+++ b/ChangeLog | |
@@ -4,6 +4,7 @@ Version 5.04, unreleased, urgency: MEDIUM: | |
* New features | |
- Asynchronous communication with the GUI thread for faster | |
logging on Win32. | |
+ - systemd socket activation (thx to Mark Theunissen). | |
* Bugfixes | |
- Fixed POLLIN|POLLHUP condition handling error resulting | |
in prematurely closed (truncated) connection. | |
diff --git a/configure b/configure | |
index 65c7759..2aa1fee 100755 | |
--- a/configure | |
+++ b/configure | |
@@ -12266,6 +12266,18 @@ fi | |
done | |
+for ac_header in systemd/sd-daemon.h | |
+do : | |
+ ac_fn_c_check_header_mongrel "$LINENO" "systemd/sd-daemon.h" "ac_cv_header_systemd_sd_daemon_h" "$ac_includes_default" | |
+if test "x$ac_cv_header_systemd_sd_daemon_h" = xyes; then : | |
+ cat >>confdefs.h <<_ACEOF | |
+#define HAVE_SYSTEMD_SD_DAEMON_H 1 | |
+_ACEOF | |
+ | |
+fi | |
+ | |
+done | |
+ | |
ac_fn_c_check_member "$LINENO" "struct msghdr" "msg_control" "ac_cv_member_struct_msghdr_msg_control" " | |
$ac_includes_default | |
#include <sys/socket.h> | |
@@ -12697,6 +12709,63 @@ if test "$ac_res" != no; then : | |
fi | |
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing sd_listen_fds" >&5 | |
+$as_echo_n "checking for library containing sd_listen_fds... " >&6; } | |
+if ${ac_cv_search_sd_listen_fds+:} false; then : | |
+ $as_echo_n "(cached) " >&6 | |
+else | |
+ ac_func_search_save_LIBS=$LIBS | |
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext | |
+/* end confdefs.h. */ | |
+ | |
+/* Override any GCC internal prototype to avoid an error. | |
+ Use char because int might match the return type of a GCC | |
+ builtin and then its argument prototype would still apply. */ | |
+#ifdef __cplusplus | |
+extern "C" | |
+#endif | |
+char sd_listen_fds (); | |
+int | |
+main () | |
+{ | |
+return sd_listen_fds (); | |
+ ; | |
+ return 0; | |
+} | |
+_ACEOF | |
+for ac_lib in '' systemd-daemon; do | |
+ if test -z "$ac_lib"; then | |
+ ac_res="none required" | |
+ else | |
+ ac_res=-l$ac_lib | |
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS" | |
+ fi | |
+ if ac_fn_c_try_link "$LINENO"; then : | |
+ ac_cv_search_sd_listen_fds=$ac_res | |
+fi | |
+rm -f core conftest.err conftest.$ac_objext \ | |
+ conftest$ac_exeext | |
+ if ${ac_cv_search_sd_listen_fds+:} false; then : | |
+ break | |
+fi | |
+done | |
+if ${ac_cv_search_sd_listen_fds+:} false; then : | |
+ | |
+else | |
+ ac_cv_search_sd_listen_fds=no | |
+fi | |
+rm conftest.$ac_ext | |
+LIBS=$ac_func_search_save_LIBS | |
+fi | |
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_sd_listen_fds" >&5 | |
+$as_echo "$ac_cv_search_sd_listen_fds" >&6; } | |
+ac_res=$ac_cv_search_sd_listen_fds | |
+if test "$ac_res" != no; then : | |
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" | |
+ | |
+fi | |
+ | |
+ | |
# Add BeOS libraries | |
if test "$host_os" = "beos"; then | |
diff --git a/configure.ac b/configure.ac | |
index 6c4a1cb..4b6a741 100644 | |
--- a/configure.ac | |
+++ b/configure.ac | |
@@ -168,6 +168,7 @@ AC_MSG_NOTICE([**************************************** header files]) | |
# AC_HEADER_SYS_WAIT | |
AC_CHECK_HEADERS([malloc.h ucontext.h pthread.h poll.h tcpd.h stropts.h grp.h unistd.h util.h libutil.h pty.h]) | |
AC_CHECK_HEADERS([sys/types.h sys/select.h sys/poll.h sys/socket.h sys/un.h sys/ioctl.h sys/filio.h sys/resource.h sys/uio.h sys/syscall.h]) | |
+AC_CHECK_HEADERS([systemd/sd-daemon.h]) | |
AC_CHECK_MEMBERS([struct msghdr.msg_control], | |
[AC_DEFINE([HAVE_MSGHDR_MSG_CONTROL], [1], | |
[Define to 1 if you have 'msghdr.msg_control' structure.])], [], [ | |
@@ -192,6 +193,8 @@ AC_SEARCH_LIBS([openpty], [util]) | |
AC_SEARCH_LIBS([dlopen], [dl]) | |
AC_SEARCH_LIBS([shl_load], [dld]) | |
AC_SEARCH_LIBS([inflateEnd], [z]) | |
+AC_SEARCH_LIBS([sd_listen_fds], [systemd-daemon]) | |
+ | |
# Add BeOS libraries | |
if test "$host_os" = "beos"; then | |
diff --git a/src/common.h b/src/common.h | |
index 6b15b81..3f3394f 100644 | |
--- a/src/common.h | |
+++ b/src/common.h | |
@@ -171,6 +171,11 @@ typedef int socklen_t; | |
#define USE_LIBWRAP 1 | |
#endif | |
+/* systemd */ | |
+#ifdef HAVE_SYSTEMD_SD_DAEMON_H | |
+#include <systemd/sd-daemon.h> | |
+#endif | |
+ | |
/* must be included before sys/stat.h for Ultrix */ | |
/* must be included before sys/socket.h for OpenBSD */ | |
#include <sys/types.h> /* u_short, u_long */ | |
diff --git a/src/config.h.in b/src/config.h.in | |
index ace0015..14f14eb 100644 | |
--- a/src/config.h.in | |
+++ b/src/config.h.in | |
@@ -138,6 +138,9 @@ | |
/* Define to 1 if you have the `sysconf' function. */ | |
#undef HAVE_SYSCONF | |
+/* Define to 1 if you have the <systemd/sd-daemon.h> header file. */ | |
+#undef HAVE_SYSTEMD_SD_DAEMON_H | |
+ | |
/* Define to 1 if you have the <sys/filio.h> header file. */ | |
#undef HAVE_SYS_FILIO_H | |
diff --git a/src/stunnel.c b/src/stunnel.c | |
index 6d283a5..ccbdbb3 100644 | |
--- a/src/stunnel.c | |
+++ b/src/stunnel.c | |
@@ -84,10 +84,21 @@ int max_clients=0; | |
volatile int num_clients=-1; | |
#endif | |
s_poll_set *fds; /* file descriptors of listening sockets */ | |
+int systemd_fds; /* number of file descriptors passed by systemd */ | |
+int listen_fds_start; /* base for systemd-provided file descriptors */ | |
/**************************************** startup */ | |
void main_init() { /* one-time initialization */ | |
+#ifdef HAVE_SYSTEMD_SD_DAEMON_H | |
+ systemd_fds=sd_listen_fds(1); | |
+ if(systemd_fds<0) | |
+ fatal("systemd initialization failed"); | |
+ listen_fds_start=SD_LISTEN_FDS_START; | |
+#else | |
+ systemd_fds=0; /* no descriptors received */ | |
+ listen_fds_start=3; /* the value is not really important */ | |
+#endif | |
/* basic initialization contains essential functions required for logging | |
* subsystem to function properly, thus all errors here are fatal */ | |
if(ssl_init()) /* initialize SSL library */ | |
@@ -338,7 +349,9 @@ void unbind_ports(void) { | |
for(opt=service_options.next; opt; opt=opt->next) { | |
s_log(LOG_DEBUG, "Closing service [%s]", opt->servname); | |
if(opt->option.accept && opt->fd>=0) { | |
- closesocket(opt->fd); | |
+ if(opt->fd<listen_fds_start || | |
+ opt->fd>=listen_fds_start+systemd_fds) | |
+ closesocket(opt->fd); | |
s_log(LOG_DEBUG, "Service [%s] closed (FD=%d)", | |
opt->servname, opt->fd); | |
opt->fd=-1; | |
@@ -376,6 +389,7 @@ void unbind_ports(void) { | |
int bind_ports(void) { | |
SERVICE_OPTIONS *opt; | |
char *local_address; | |
+ int listening_section; | |
#ifdef USE_LIBWRAP | |
/* execute after options_cmdline() to know service_options.next, | |
@@ -394,12 +408,22 @@ int bind_ports(void) { | |
if(opt->option.accept) | |
opt->fd=-1; | |
+ listening_section=0; | |
for(opt=service_options.next; opt; opt=opt->next) { | |
if(opt->option.accept) { | |
- opt->fd=s_socket(opt->local_addr.sa.sa_family, | |
- SOCK_STREAM, 0, 1, "accept socket"); | |
- if(opt->fd<0) | |
- return 1; | |
+ if(listening_section<systemd_fds) { | |
+ opt->fd=listen_fds_start+listening_section; | |
+ s_log(LOG_DEBUG, | |
+ "Listening file descriptor received from systemd (FD=%d)", | |
+ opt->fd); | |
+ } else { | |
+ opt->fd=s_socket(opt->local_addr.sa.sa_family, | |
+ SOCK_STREAM, 0, 1, "accept socket"); | |
+ if(opt->fd<0) | |
+ return 1; | |
+ s_log(LOG_DEBUG, "Listening file descriptor created (FD=%d)", | |
+ opt->fd); | |
+ } | |
if(set_socket_options(opt->fd, 0)<0) { | |
closesocket(opt->fd); | |
opt->fd=-1; | |
@@ -407,26 +431,30 @@ int bind_ports(void) { | |
} | |
/* local socket can't be unnamed */ | |
local_address=s_ntop(&opt->local_addr, addr_len(&opt->local_addr)); | |
- if(bind(opt->fd, &opt->local_addr.sa, addr_len(&opt->local_addr))) { | |
- s_log(LOG_ERR, "Error binding service [%s] to %s", | |
- opt->servname, local_address); | |
- sockerror("bind"); | |
- closesocket(opt->fd); | |
- opt->fd=-1; | |
- str_free(local_address); | |
- return 1; | |
- } | |
- if(listen(opt->fd, SOMAXCONN)) { | |
- sockerror("listen"); | |
- closesocket(opt->fd); | |
- opt->fd=-1; | |
- str_free(local_address); | |
- return 1; | |
+ /* we don't bind or listen on a socket inherited from systemd */ | |
+ if(listening_section>=systemd_fds) { | |
+ if(bind(opt->fd, &opt->local_addr.sa, addr_len(&opt->local_addr))) { | |
+ s_log(LOG_ERR, "Error binding service [%s] to %s", | |
+ opt->servname, local_address); | |
+ sockerror("bind"); | |
+ closesocket(opt->fd); | |
+ opt->fd=-1; | |
+ str_free(local_address); | |
+ return 1; | |
+ } | |
+ if(listen(opt->fd, SOMAXCONN)) { | |
+ sockerror("listen"); | |
+ closesocket(opt->fd); | |
+ opt->fd=-1; | |
+ str_free(local_address); | |
+ return 1; | |
+ } | |
} | |
s_poll_add(fds, opt->fd, 1, 0); | |
s_log(LOG_DEBUG, "Service [%s] (FD=%d) bound to %s", | |
opt->servname, opt->fd, local_address); | |
str_free(local_address); | |
+ ++listening_section; | |
} else if(opt->option.program && opt->option.remote) { | |
/* create exec+connect services */ | |
/* FIXME: needs to be delayed on reload with opt->option.retry set */ | |
@@ -434,6 +462,12 @@ int bind_ports(void) { | |
alloc_client_session(opt, -1, -1), client_thread); | |
} | |
} | |
+ if(listening_section<systemd_fds) { | |
+ s_log(LOG_ERR, | |
+ "Too many listening file descriptors received from systemd, got %d", | |
+ systemd_fds); | |
+ return 1; | |
+ } | |
return 0; /* OK */ | |
} | |
@@ -591,6 +625,9 @@ void stunnel_info(int level) { | |
"SELECT" | |
#endif /* defined(USE_POLL) */ | |
",IPv%c" | |
+#ifdef HAVE_SYSTEMD_SD_DAEMON_H | |
+ ",SYSTEMD" | |
+#endif /* HAVE_SYSTEMD_SD_DAEMON_H */ | |
#if defined HAVE_OSSL_ENGINE_H || defined HAVE_OSSL_OCSP_H || defined USE_FIPS | |
" SSL:" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment