From: Ruediger Pluem Date: Wed, 4 Jun 2025 09:41:25 +0000 (+0000) Subject: Merge r1511033, r1528032, r1608686, r1608694, r1608703, r1899784, r1916312, r1916344... X-Git-Tag: 2.4.64-rc1-candidate~44 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=22ce169f2c46fb5372482d31c56ac7120b8fb17d;p=thirdparty%2Fapache%2Fhttpd.git Merge r1511033, r1528032, r1608686, r1608694, r1608703, r1899784, r1916312, r1916344, r1838271, r1926091 from trunk: Add support for systemd socket activation to listener sockets. * configure.in: Simplify/fix systemd detection: move later to fix autoconf warnings; define HAVE_SYSTEMD rather than using CPPFLAGS. * server/listen.c: Use HAVE_SYSTEMD for systemd #define. * modules/arch/unix/config5.m4: Update systemd headers check. * server/listen.c: duplicate sockets correctly when using systemd socket activation, fix addrlen in getsockname() call. Follow up r1608686, pass process to alloc_systemd_listener. * server/listen.c: detect systemd socket activation using sd_listen_fds(), drop the support for "Listen systemd" and use standard Listen syntax instead. This allows using the same configuration file with or without socket activation and allows setting protocol when using socket activation. Remove libsystemd dependency from main httpd binary Until this change httpd was linking libsystemd to the main httpd binary. If you want to run lightweight version of httpd in container, sometimes you just want to install httpd binary with as little dependencies as possible to make container small in size and do not pull uncencessary dependencies and libraries. This change will move all systemd library calls from listen.c to mod_systemd module and remove systemd linking from the main httpd bin. Fixed mixed declaration and wrongly declared variable. Submitted by: Luboš Uhliarik mod_systemd: Axe APR_OPTIONAL_FN redeclarations to avoid compiler warning. ap_find_systemd_socket() and ap_systemd_listen_fds() are already declared in "ap_listen.h", so just include them. mod_systemd: if SELinux is available and enabled, log the SELinux context at startup, since this may vary when httpd is started via systemd vs being started directly. * modules/arch/unix/mod_systemd.c (systemd_post_config): Do nothing for the pre-config iteration. Log the SELinux context if available. * modules/arch/unix/config5.m4: Detect libselinux. Have at least one CI job build mod_systemd. Fix a cppcheck warning. Remove some dead code. Updating 'last' is pointless here. Ensure that ALL fields of the ap_listen_rec structure are initialized alloc_listener initializes more fields in the created ap_listen_rec structure than alloc_systemd_listener as it has more data to add to this structure. Ensure that all fields of the ap_listen_rec structure are initialized at least with 0 as later code using this structure depends on this. Reviewed by: rpluem, jorton, ylavic Github: closes #515 git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1926113 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index 529a2c96bf9..1b3a6c9ce1a 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,68 @@ -*- coding: utf-8 -*- Changes with Apache 2.4.64 + *) mod_systemd: Systemd socket activation can now be enabled at + build time but disabled at run time, if mod_systemd is not + loaded. [Lubos Uhliarik ] + + *) mod_systemd: Log the SELinux context at startup if available and + enabled. [Joe Orton] + + *) mod_http2: update to version 2.0.32 + The code setting the connection window size was set wrong, + preventing `H2WindowSize` to work. + Fixed . + [Stefan Eissing, Michael Kaufmann] + + *) mod_http2: update to version 2.0.30 + - Fixed bug in handling over long response headers. When the 64 KB limit + of nghttp2 was exceeded, the request was not reset and the client was + left hanging, waiting for it. Now the stream is reset. + - Added new directive `H2MaxHeaderBlockLen` to set the limit on response + header sizes. + - Fixed handling of Timeout vs. KeepAliveTimeout when first request on a + connection was reset. + + *) mod_lua: Fix memory handling in LuaOutputFilter. PR 69590. + [Guillermo Grandes ] + + * mod_proxy_http2: revert r1912193 for detecting broken backend connections + as this interferes with backend selection who a node is unresponsive. + PR69624. + + *) mod_proxy_balancer: Fix a regression that caused stickysession keys no + longer be recognized if they are provided as query parameter in the URL. + PR 69443 [Ruediger Pluem] + + *) mod_md: update to version 2.5.2 + - Fixed TLS-ALPN-01 challenges when multiple `MDPrivateKeys` are specified + with EC keys before RSA ones. Fixes #377. [Stefan Eissing] + - Fixed missing newlines in the status page output. [Andreas Groth] + + *) mod_dav: Add API to expose DavBasePath setting. [Joe Orton] + + *) mod_md: update to version 2.5.1 + - Added support for ACME profiles with new directives MDProfile and + MDProfileMandatory. + - When installing a custom CA file via `MDCACertificateFile`, also set the + libcurl option CURLSSLOPT_NO_REVOKE that suppresses complains by Schannel + (when curl is linked with it) about missing CRL/OCSP in certificates. + - Fixed handling of corrupted httpd.json and added test 300_30 for it. + File is removed on error and written again. Fixes #369. + - Added explanation in log for how to proceed when md_store.json could not be + parsed and prevented the server start. + - restored fixed to #336 and #337 which got lost in a sync with Apache svn + - Add Issue Name/Uris to certificate information in md-status handler + - MDomains with static certificate files have MDRenewMode "manual", unless + "always" is configured. + + *) core: Report invalid Options= argument when parsing AllowOverride + directives. + Github #310 [Zhou Qingyang ] + + *) scoreboard/mod_http2: record durations of HTTP/2 requests. + PR 69579 [Pierre Brochard ] + Changes with Apache 2.4.63 *) mod_dav: Update redirect-carefully example BrowserMatch config diff --git a/STATUS b/STATUS index de4f4a96db9..5d3b206e519 100644 --- a/STATUS +++ b/STATUS @@ -183,28 +183,6 @@ PATCHES ACCEPTED TO BACKPORT FROM TRUNK: https://patch-diff.githubusercontent.com/raw/apache/httpd/pull/533.diff +1 covener, rpluem, jorton - *) mod_systemd: Add systemd socket activation - Trunk version of patch: - https://svn.apache.org/r1511033 - https://svn.apache.org/r1528032 - https://svn.apache.org/r1608686 - https://svn.apache.org/r1608694 - https://svn.apache.org/r1608703 - https://svn.apache.org/r1838271 - https://svn.apache.org/r1899784 - https://svn.apache.org/r1916312 - https://svn.apache.org/r1916344 - https://svn.apache.org/r1926091 - Backport version for 2.4.x of patch: - https://patch-diff.githubusercontent.com/raw/apache/httpd/pull/515.diff - Can be applied via apply_backport_pr.sh 515 - +1: rpluem, jorton, ylavic - jailletc36: Should the apr_palloc() in alloc_systemd_listener() be - apr_pcalloc() so that all fields are 0? - make_sock() uses the 'flags' field that would be - undefined otherwise. - rpluem says: Good catch. Added r1926091 and reset votes. - PATCHES PROPOSED TO BACKPORT FROM TRUNK: [ New proposals should be added at the end of the list ] diff --git a/changes-entries/dav-get-base-path.txt b/changes-entries/dav-get-base-path.txt deleted file mode 100644 index e24e41dd897..00000000000 --- a/changes-entries/dav-get-base-path.txt +++ /dev/null @@ -1,2 +0,0 @@ - *) mod_dav: Add API to expose DavBasePath setting. [Joe Orton] - diff --git a/changes-entries/github 310.txt b/changes-entries/github 310.txt deleted file mode 100644 index 2d966cd488d..00000000000 --- a/changes-entries/github 310.txt +++ /dev/null @@ -1,3 +0,0 @@ - *) core: Report invalid Options= argument when parsing AllowOverride - directives. - Github #310 [Zhou Qingyang ] diff --git a/changes-entries/h2_v2.0.30.txt b/changes-entries/h2_v2.0.30.txt deleted file mode 100644 index edd12afef57..00000000000 --- a/changes-entries/h2_v2.0.30.txt +++ /dev/null @@ -1,8 +0,0 @@ - *) mod_http2: update to version 2.0.30 - - Fixed bug in handling over long response headers. When the 64 KB limit - of nghttp2 was exceeded, the request was not reset and the client was - left hanging, waiting for it. Now the stream is reset. - - Added new directive `H2MaxHeaderBlockLen` to set the limit on response - header sizes. - - Fixed handling of Timeout vs. KeepAliveTimeout when first request on a - connection was reset. diff --git a/changes-entries/h2_v2.0.32.txt b/changes-entries/h2_v2.0.32.txt deleted file mode 100644 index a1597cda50d..00000000000 --- a/changes-entries/h2_v2.0.32.txt +++ /dev/null @@ -1,5 +0,0 @@ - *) mod_http2: update to version 2.0.32 - The code setting the connection window size was set wrong, - preventing `H2WindowSize` to work. - Fixed . - [Stefan Eissing, Michael Kaufmann] diff --git a/changes-entries/md_v2.5.1.txt b/changes-entries/md_v2.5.1.txt deleted file mode 100644 index 051f2aa940c..00000000000 --- a/changes-entries/md_v2.5.1.txt +++ /dev/null @@ -1,14 +0,0 @@ - *) mod_md: update to version 2.5.1 - - Added support for ACME profiles with new directives MDProfile and - MDProfileMandatory. - - When installing a custom CA file via `MDCACertificateFile`, also set the - libcurl option CURLSSLOPT_NO_REVOKE that suppresses complains by Schannel - (when curl is linked with it) about missing CRL/OCSP in certificates. - - Fixed handling of corrupted httpd.json and added test 300_30 for it. - File is removed on error and written again. Fixes #369. - - Added explanation in log for how to proceed when md_store.json could not be - parsed and prevented the server start. - - restored fixed to #336 and #337 which got lost in a sync with Apache svn - - Add Issue Name/Uris to certificate information in md-status handler - - MDomains with static certificate files have MDRenewMode "manual", unless - "always" is configured. diff --git a/changes-entries/md_v2.5.2.txt b/changes-entries/md_v2.5.2.txt deleted file mode 100644 index 1b4922b8be2..00000000000 --- a/changes-entries/md_v2.5.2.txt +++ /dev/null @@ -1,4 +0,0 @@ - *) mod_md: update to version 2.5.2 - - Fixed TLS-ALPN-01 challenges when multiple `MDPrivateKeys` are specified - with EC keys before RSA ones. Fixes #377. [Stefan Eissing] - - Fixed missing newlines in the status page output. [Andreas Groth] diff --git a/changes-entries/pr69443.txt b/changes-entries/pr69443.txt deleted file mode 100644 index 97de7693937..00000000000 --- a/changes-entries/pr69443.txt +++ /dev/null @@ -1,3 +0,0 @@ - *) mod_proxy_balancer: Fix a regression that caused stickysession keys no - longer be recognized if they are provided as query parameter in the URL. - PR 69443 [Ruediger Pluem] diff --git a/changes-entries/pr69579.txt b/changes-entries/pr69579.txt deleted file mode 100644 index 0b91a0da748..00000000000 --- a/changes-entries/pr69579.txt +++ /dev/null @@ -1,2 +0,0 @@ - *) scoreboard/mod_http2: record durations of HTTP/2 requests. - PR 69579 [Pierre Brochard ] diff --git a/changes-entries/pr69590.txt b/changes-entries/pr69590.txt deleted file mode 100644 index ebf3f1a5b04..00000000000 --- a/changes-entries/pr69590.txt +++ /dev/null @@ -1,2 +0,0 @@ - *) mod_lua: Fix memory handling in LuaOutputFilter. PR 69590. - [Guillermo Grandes ] diff --git a/changes-entries/pr69624.txt b/changes-entries/pr69624.txt deleted file mode 100644 index 74ee63a6eda..00000000000 --- a/changes-entries/pr69624.txt +++ /dev/null @@ -1,3 +0,0 @@ - * mod_proxy_http2: revert r1912193 for detecting broken backend connections - as this interferes with backend selection who a node is unresponsive. - PR69624. diff --git a/include/ap_listen.h b/include/ap_listen.h index 58c2574ff40..d5ed9685c54 100644 --- a/include/ap_listen.h +++ b/include/ap_listen.h @@ -29,6 +29,7 @@ #include "apr_network_io.h" #include "httpd.h" #include "http_config.h" +#include "apr_optional.h" #ifdef __cplusplus extern "C" { @@ -143,6 +144,15 @@ AP_DECLARE_NONSTD(const char *) ap_set_receive_buffer_size(cmd_parms *cmd, void *dummy, const char *arg); +#ifdef HAVE_SYSTEMD +APR_DECLARE_OPTIONAL_FN(int, + ap_find_systemd_socket, (process_rec *, apr_port_t)); + +APR_DECLARE_OPTIONAL_FN(int, + ap_systemd_listen_fds, (int)); +#endif + + #define LISTEN_COMMANDS \ AP_INIT_TAKE1("ListenBacklog", ap_set_listenbacklog, NULL, RSRC_CONF, \ "Maximum length of the queue of pending connections, as used by listen(2)"), \ diff --git a/modules/arch/unix/config5.m4 b/modules/arch/unix/config5.m4 index 3d099f86b75..7ee06663b60 100644 --- a/modules/arch/unix/config5.m4 +++ b/modules/arch/unix/config5.m4 @@ -23,6 +23,11 @@ APACHE_MODULE(systemd, Systemd support, , , no, [ AC_MSG_WARN([Your system does not support systemd.]) enable_systemd="no" else + AC_CHECK_LIB(selinux, is_selinux_enabled, [ + AC_DEFINE(HAVE_SELINUX, 1, [Defined if SELinux is supported]) + APR_ADDTO(MOD_SYSTEMD_LDADD, [-lselinux]) + ]) + APR_ADDTO(MOD_SYSTEMD_LDADD, [$SYSTEMD_LIBS]) fi ]) diff --git a/modules/arch/unix/mod_systemd.c b/modules/arch/unix/mod_systemd.c index c3e7082df1f..22482fd6bbc 100644 --- a/modules/arch/unix/mod_systemd.c +++ b/modules/arch/unix/mod_systemd.c @@ -18,6 +18,7 @@ #include #include #include "ap_mpm.h" +#include "ap_listen.h" #include #include #include @@ -28,6 +29,10 @@ #include "scoreboard.h" #include "mpm_common.h" +#ifdef HAVE_SELINUX +#include +#endif + #include "systemd/sd-daemon.h" #if APR_HAVE_UNISTD_H @@ -44,6 +49,20 @@ static int systemd_pre_config(apr_pool_t *pconf, apr_pool_t *plog, return OK; } +#ifdef HAVE_SELINUX +static void log_selinux_context(void) +{ + char *con; + + if (is_selinux_enabled() && getcon(&con) == 0) { + ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, NULL, + APLOGNO(10497) "SELinux is enabled; " + "httpd running as context %s", con); + freecon(con); + } +} +#endif + /* Report the service is ready in post_config, which could be during * startup or after a reload. The server could still hit a fatal * startup error after this point during ap_run_mpm(), so this is @@ -51,9 +70,16 @@ static int systemd_pre_config(apr_pool_t *pconf, apr_pool_t *plog, * the TCP ports so new connections will not be rejected. There will * always be a possible async failure event simultaneous to the * service reporting "ready", so this should be good enough. */ -static int systemd_post_config(apr_pool_t *p, apr_pool_t *plog, +static int systemd_post_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *main_server) { + if (ap_state_query(AP_SQ_MAIN_STATE) == AP_SQ_MS_CREATE_PRE_CONFIG) + return OK; + +#ifdef HAVE_SELINUX + log_selinux_context(); +#endif + sd_notify(0, "READY=1\n" "STATUS=Configuration loaded.\n"); return OK; @@ -96,8 +122,42 @@ static int systemd_monitor(apr_pool_t *p, server_rec *s) return DECLINED; } +static int ap_find_systemd_socket(process_rec * process, apr_port_t port) { + int fdcount, fd; + int sdc = sd_listen_fds(0); + + if (sdc < 0) { + ap_log_perror(APLOG_MARK, APLOG_CRIT, sdc, process->pool, APLOGNO(02486) + "find_systemd_socket: Error parsing enviroment, sd_listen_fds returned %d", + sdc); + return -1; + } + + if (sdc == 0) { + ap_log_perror(APLOG_MARK, APLOG_CRIT, sdc, process->pool, APLOGNO(02487) + "find_systemd_socket: At least one socket must be set."); + return -1; + } + + fdcount = atoi(getenv("LISTEN_FDS")); + for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + fdcount; fd++) { + if (sd_is_socket_inet(fd, 0, 0, -1, port) > 0) { + return fd; + } + } + + return -1; +} + +static int ap_systemd_listen_fds(int unset_environment){ + return sd_listen_fds(unset_environment); +} + static void systemd_register_hooks(apr_pool_t *p) { + APR_REGISTER_OPTIONAL_FN(ap_systemd_listen_fds); + APR_REGISTER_OPTIONAL_FN(ap_find_systemd_socket); + /* Enable ap_extended_status. */ ap_hook_pre_config(systemd_pre_config, NULL, NULL, APR_HOOK_LAST); /* Signal service is ready. */ diff --git a/server/listen.c b/server/listen.c index 9577d60269a..cb7e59eb34c 100644 --- a/server/listen.c +++ b/server/listen.c @@ -60,9 +60,12 @@ static int ap_listenbacklog; static int ap_listencbratio; static int send_buffer_size; static int receive_buffer_size; +#ifdef HAVE_SYSTEMD +static int use_systemd = -1; +#endif /* TODO: make_sock is just begging and screaming for APR abstraction */ -static apr_status_t make_sock(apr_pool_t *p, ap_listen_rec *server) +static apr_status_t make_sock(apr_pool_t *p, ap_listen_rec *server, int do_bind_listen) { apr_socket_t *s = server->sd; int one = 1; @@ -95,20 +98,6 @@ static apr_status_t make_sock(apr_pool_t *p, ap_listen_rec *server) return stat; } -#if APR_HAVE_IPV6 - if (server->bind_addr->family == APR_INET6) { - stat = apr_socket_opt_set(s, APR_IPV6_V6ONLY, v6only_setting); - if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) { - ap_log_perror(APLOG_MARK, APLOG_CRIT, stat, p, APLOGNO(00069) - "make_sock: for address %pI, apr_socket_opt_set: " - "(IPV6_V6ONLY)", - server->bind_addr); - apr_socket_close(s); - return stat; - } - } -#endif - /* * To send data over high bandwidth-delay connections at full * speed we must force the TCP window to open wide enough to keep the @@ -170,21 +159,37 @@ static apr_status_t make_sock(apr_pool_t *p, ap_listen_rec *server) } #endif - if ((stat = apr_socket_bind(s, server->bind_addr)) != APR_SUCCESS) { - ap_log_perror(APLOG_MARK, APLOG_STARTUP|APLOG_CRIT, stat, p, APLOGNO(00072) - "make_sock: could not bind to address %pI", - server->bind_addr); - apr_socket_close(s); - return stat; - } + if (do_bind_listen) { +#if APR_HAVE_IPV6 + if (server->bind_addr->family == APR_INET6) { + stat = apr_socket_opt_set(s, APR_IPV6_V6ONLY, v6only_setting); + if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) { + ap_log_perror(APLOG_MARK, APLOG_CRIT, stat, p, APLOGNO(00069) + "make_sock: for address %pI, apr_socket_opt_set: " + "(IPV6_V6ONLY)", + server->bind_addr); + apr_socket_close(s); + return stat; + } + } +#endif - if ((stat = apr_socket_listen(s, ap_listenbacklog)) != APR_SUCCESS) { - ap_log_perror(APLOG_MARK, APLOG_STARTUP|APLOG_ERR, stat, p, APLOGNO(00073) - "make_sock: unable to listen for connections " - "on address %pI", - server->bind_addr); - apr_socket_close(s); - return stat; + if ((stat = apr_socket_bind(s, server->bind_addr)) != APR_SUCCESS) { + ap_log_perror(APLOG_MARK, APLOG_STARTUP|APLOG_CRIT, stat, p, APLOGNO(00072) + "make_sock: could not bind to address %pI", + server->bind_addr); + apr_socket_close(s); + return stat; + } + + if ((stat = apr_socket_listen(s, ap_listenbacklog)) != APR_SUCCESS) { + ap_log_perror(APLOG_MARK, APLOG_STARTUP|APLOG_ERR, stat, p, APLOGNO(00073) + "make_sock: unable to listen for connections " + "on address %pI", + server->bind_addr); + apr_socket_close(s); + return stat; + } } #ifdef WIN32 @@ -278,6 +283,101 @@ static apr_status_t close_listeners_on_exec(void *v) return APR_SUCCESS; } +#ifdef HAVE_SYSTEMD + +static apr_status_t alloc_systemd_listener(process_rec * process, + int fd, const char *proto, + ap_listen_rec **out_rec) +{ + apr_status_t rv; + struct sockaddr sa; + socklen_t len = sizeof(struct sockaddr); + apr_os_sock_info_t si; + ap_listen_rec *rec; + *out_rec = NULL; + + memset(&si, 0, sizeof(si)); + + rv = getsockname(fd, &sa, &len); + + if (rv != 0) { + rv = apr_get_netos_error(); + ap_log_perror(APLOG_MARK, APLOG_CRIT, rv, process->pool, APLOGNO(02489) + "getsockname on %d failed.", fd); + return rv; + } + + si.os_sock = &fd; + si.family = sa.sa_family; + si.local = &sa; + si.type = SOCK_STREAM; + si.protocol = APR_PROTO_TCP; + + rec = apr_pcalloc(process->pool, sizeof(ap_listen_rec)); + + + rv = apr_os_sock_make(&rec->sd, &si, process->pool); + if (rv != APR_SUCCESS) { + ap_log_perror(APLOG_MARK, APLOG_CRIT, rv, process->pool, APLOGNO(02490) + "apr_os_sock_make on %d failed.", fd); + return rv; + } + + rv = apr_socket_addr_get(&rec->bind_addr, APR_LOCAL, rec->sd); + if (rv != APR_SUCCESS) { + ap_log_perror(APLOG_MARK, APLOG_CRIT, rv, process->pool, APLOGNO(02491) + "apr_socket_addr_get on %d failed.", fd); + return rv; + } + + rec->protocol = apr_pstrdup(process->pool, proto); + + *out_rec = rec; + + return make_sock(process->pool, rec, 0); +} + +static const char *set_systemd_listener(process_rec *process, apr_port_t port, + const char *proto) +{ + ap_listen_rec *last, *new; + apr_status_t rv; + APR_OPTIONAL_FN_TYPE(ap_find_systemd_socket) *find_systemd_socket; + int fd; + + find_systemd_socket = APR_RETRIEVE_OPTIONAL_FN(ap_find_systemd_socket); + + if (!find_systemd_socket) + return "Systemd socket activation is used, but mod_systemd is probably " + "not loaded"; + + fd = find_systemd_socket(process, port); + if (fd < 0) { + return "Systemd socket activation is used, but this port is not " + "configured in systemd"; + } + + last = ap_listeners; + while (last && last->next) { + last = last->next; + } + + rv = alloc_systemd_listener(process, fd, proto, &new); + if (rv != APR_SUCCESS) { + return "Failed to setup socket passed by systemd using socket activation"; + } + + if (last == NULL) { + ap_listeners = new; + } + else { + last->next = new; + } + + return NULL; +} +#endif /* HAVE_SYSTEMD */ + /* Returns non-zero if socket address SA matches hostname, port and * scope_id. p is used for temporary allocations. */ static int match_address(const apr_sockaddr_t *sa, @@ -529,7 +629,7 @@ static int open_listeners(apr_pool_t *pool) } } #endif - if (make_sock(pool, lr) == APR_SUCCESS) { + if (make_sock(pool, lr, 1) == APR_SUCCESS) { ++num_open; } else { @@ -615,6 +715,9 @@ AP_DECLARE(int) ap_setup_listeners(server_rec *s) int num_listeners = 0; const char* proto; int found; +#ifdef HAVE_SYSTEMD + APR_OPTIONAL_FN_TYPE(ap_systemd_listen_fds) *systemd_listen_fds; +#endif for (ls = s; ls; ls = ls->next) { proto = ap_get_server_protocol(ls); @@ -641,8 +744,32 @@ AP_DECLARE(int) ap_setup_listeners(server_rec *s) } } - if (open_listeners(s->process->pool)) { - return 0; + +#ifdef HAVE_SYSTEMD + if (use_systemd) { + const char *userdata_key = "ap_open_systemd_listeners"; + void *data; + /* clear the enviroment on our second run + * so that none of our future children get confused. + */ + apr_pool_userdata_get(&data, userdata_key, s->process->pool); + if (!data) { + apr_pool_userdata_set((const void *)1, userdata_key, + apr_pool_cleanup_null, s->process->pool); + } + else { + systemd_listen_fds = APR_RETRIEVE_OPTIONAL_FN(ap_systemd_listen_fds); + if (systemd_listen_fds != NULL) { + systemd_listen_fds(1); + } + } + } + else +#endif + { + if (open_listeners(s->process->pool)) { + return 0; + } } for (lr = ap_listeners; lr; lr = lr->next) { @@ -715,24 +842,36 @@ AP_DECLARE(apr_status_t) ap_duplicate_listeners(apr_pool_t *p, server_rec *s, char *hostname; apr_port_t port; apr_sockaddr_t *sa; - duplr = apr_palloc(p, sizeof(ap_listen_rec)); - duplr->slave = NULL; - duplr->protocol = apr_pstrdup(p, lr->protocol); - hostname = apr_pstrdup(p, lr->bind_addr->hostname); - port = lr->bind_addr->port; - apr_sockaddr_info_get(&sa, hostname, APR_UNSPEC, port, 0, p); - duplr->bind_addr = sa; - duplr->next = NULL; - stat = apr_socket_create(&duplr->sd, duplr->bind_addr->family, - SOCK_STREAM, 0, p); - if (stat != APR_SUCCESS) { - ap_log_perror(APLOG_MARK, APLOG_CRIT, 0, p, APLOGNO(02640) - "ap_duplicate_listeners: for address %pI, " - "cannot duplicate a new socket!", - duplr->bind_addr); - return stat; +#ifdef HAVE_SYSTEMD + if (use_systemd) { + int thesock; + apr_os_sock_get(&thesock, lr->sd); + if ((stat = alloc_systemd_listener(s->process, thesock, + lr->protocol, &duplr)) != APR_SUCCESS) { + return stat; + } + } + else +#endif + { + duplr = apr_palloc(p, sizeof(ap_listen_rec)); + duplr->slave = NULL; + duplr->protocol = apr_pstrdup(p, lr->protocol); + hostname = apr_pstrdup(p, lr->bind_addr->hostname); + port = lr->bind_addr->port; + apr_sockaddr_info_get(&sa, hostname, APR_UNSPEC, port, 0, p); + duplr->bind_addr = sa; + duplr->next = NULL; + if ((stat = apr_socket_create(&duplr->sd, duplr->bind_addr->family, + SOCK_STREAM, 0, p)) != APR_SUCCESS) { + ap_log_perror(APLOG_MARK, APLOG_CRIT, 0, p, APLOGNO(02640) + "ap_duplicate_socket: for address %pI, " + "cannot duplicate a new socket!", + duplr->bind_addr); + return stat; + } + make_sock(p, duplr, 1); } - make_sock(p, duplr); #if AP_NONBLOCK_WHEN_MULTI_LISTEN use_nonblock = (ap_listeners && ap_listeners->next); stat = apr_socket_opt_set(duplr->sd, APR_SO_NONBLOCK, use_nonblock); @@ -851,6 +990,9 @@ AP_DECLARE_NONSTD(const char *) ap_set_listener(cmd_parms *cmd, void *dummy, apr_port_t port; apr_status_t rv; const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); +#ifdef HAVE_SYSTEMD + APR_OPTIONAL_FN_TYPE(ap_systemd_listen_fds) *systemd_listen_fds; +#endif if (err != NULL) { return err; @@ -859,6 +1001,16 @@ AP_DECLARE_NONSTD(const char *) ap_set_listener(cmd_parms *cmd, void *dummy, if (argc < 1 || argc > 2) { return "Listen requires 1 or 2 arguments."; } +#ifdef HAVE_SYSTEMD + if (use_systemd == -1) { + systemd_listen_fds = APR_RETRIEVE_OPTIONAL_FN(ap_systemd_listen_fds); + if (systemd_listen_fds != NULL) { + use_systemd = systemd_listen_fds(0) > 0; + } else { + use_systemd = 0; + } + } +#endif rv = apr_parse_addr_port(&host, &scope_id, &port, argv[0], cmd->pool); if (rv != APR_SUCCESS) { @@ -894,6 +1046,12 @@ AP_DECLARE_NONSTD(const char *) ap_set_listener(cmd_parms *cmd, void *dummy, ap_str_tolower(proto); } +#ifdef HAVE_SYSTEMD + if (use_systemd) { + return set_systemd_listener(cmd->server->process, port, proto); + } +#endif + return alloc_listener(cmd->server->process, host, port, proto, scope_id, NULL, cmd->temp_pool); }