Hi,
I've created a patch to Stunnel that reloads all accepting connections
from the config file. This will not work for privileged ports in the
current implementation. Test at your own risk :)
Feedback welcome.
Best regards,
Matthew
diff -urb stunnel-orig/stunnel-4.20/src/stunnel.c stunnel-4.20/src/stunnel.c
--- stunnel-orig/stunnel-4.20/src/stunnel.c 2006-11-30 15:47:45.000000000 -0500
+++ stunnel-4.20/src/stunnel.c 2006-12-12 03:34:36.000000000 -0500
@@ -53,12 +53,12 @@
#endif
int volatile num_clients=0; /* Current number of clients */
+int volatile conf_updated=0; /* Conf updated ? */
/* Functions */
#ifndef USE_WIN32
int main(int argc, char* argv[]) { /* execution begins here 8-) */
-
main_initialize(argc>1 ? argv[1] : NULL, argc>2 ? argv[2] : NULL);
signal(SIGPIPE, SIG_IGN); /* avoid 'broken pipe' signal */
@@ -78,12 +78,17 @@
}
#endif
+char *cfg_arg1 = NULL;
+char *cfg_arg2 = NULL;
+
void main_initialize(char *arg1, char *arg2) {
ssl_init(); /* initialize SSL library */
sthreads_init(); /* initialize critical sections & SSL callbacks */
parse_config(arg1, arg2);
log_open();
stunnel_info(0);
+ cfg_arg1 = arg1;
+ cfg_arg2 = arg2;
}
void main_execute(void) {
@@ -105,6 +110,7 @@
SOCKADDR_UNION addr;
s_poll_set fds;
LOCAL_OPTIONS *opt;
+ int i;
get_limits();
s_poll_zero(&fds);
#if !defined(USE_WIN32) && !defined(USE_OS2)
@@ -173,6 +179,42 @@
accept_connection(opt);
}
+ if(conf_updated) {
+ for(i=0; i<fds.nfds; i++)
+ close(fds.ufds[i].fd);
+
+ /* re-bind local ports */
+ for(opt=local_options.next; opt; opt=opt->next) {
+ if(!opt->option.accept) /* no need to bind this service */
+ continue;
+ memcpy(&addr, &opt->local_addr.addr[0], sizeof(SOCKADDR_UNION));
+ if((opt->fd=socket(addr.sa.sa_family, SOCK_STREAM, 0))<0) {
+ sockerror("local socket");
+ exit(1);
+ }
+ if(alloc_fd(opt->fd))
+ exit(1);
+ if(set_socket_options(opt->fd, 0)<0)
+ exit(1);
+ s_ntop(opt->local_address, &addr);
+ if(bind(opt->fd, &addr.sa, addr_len(addr))) {
+ s_log(LOG_ERR, "Error binding %s to %s",
+ opt->servname, opt->local_address);
+ sockerror("bind");
+ exit(1);
+ }
+ s_log(LOG_DEBUG, "%s bound to %s", opt->servname, opt->local_address);
+ if(listen(opt->fd, 5)) {
+ sockerror("listen");
+ exit(1);
+ }
+#ifdef FD_CLOEXEC
+ fcntl(opt->fd, F_SETFD, FD_CLOEXEC); /* close socket in child execvp */
+#endif
+ s_poll_add(&fds, opt->fd, 1, 0);
+ }
+ conf_updated = 0;
+ }
}
s_log(LOG_ERR, "INTERNAL ERROR: End of infinite loop 8-)");
}
@@ -413,9 +455,16 @@
}
static void signal_handler(int sig) { /* signal handler */
+ if((sig==SIGHUP) && local_options.next) { /* only in service mode */
+ s_log(LOG_NOTICE, "Re-reading configuration");
+ parse_config(cfg_arg1, cfg_arg2);
+ conf_updated = 1;
+ }
+ else {
s_log(sig==SIGTERM ? LOG_NOTICE : LOG_ERR,
"Received signal %d; terminating", sig);
exit(3);
+ }
}
#endif /* !defined USE_WIN32 */