diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-07-01 17:06:36 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-07-01 17:06:36 +0000 |
commit | e5260a81260d593ababfa53fcd8b82c42f30fa8b (patch) | |
tree | 4397979cf8d951f4f6dc5f3360c67677ac65a9fc /server/listen.c | |
parent | Releasing progress-linux version 2.4.59-2~progress7.99u1. (diff) | |
download | apache2-e5260a81260d593ababfa53fcd8b82c42f30fa8b.tar.xz apache2-e5260a81260d593ababfa53fcd8b82c42f30fa8b.zip |
Merging upstream version 2.4.60.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'server/listen.c')
-rw-r--r-- | server/listen.c | 69 |
1 files changed, 54 insertions, 15 deletions
diff --git a/server/listen.c b/server/listen.c index 5242c2a..9577d60 100644 --- a/server/listen.c +++ b/server/listen.c @@ -19,6 +19,7 @@ #define APR_WANT_STRFUNC #include "apr_want.h" +#include "apr_version.h" #include "ap_config.h" #include "httpd.h" @@ -277,8 +278,32 @@ static apr_status_t close_listeners_on_exec(void *v) return APR_SUCCESS; } +/* 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, + const char *hostname, apr_port_t port, + const char *scope_id, apr_pool_t *p) +{ + const char *old_scope = NULL; + +#if APR_VERSION_AT_LEAST(1,7,0) + /* To be clever here we could correctly match numeric and + * non-numeric zone ids. Ignore failure, old_scope will be left + * as NULL. */ + (void) apr_sockaddr_zone_get(sa, &old_scope, NULL, p); +#endif + + return port == sa->port + && ((!hostname && !sa->hostname) + || (hostname && sa->hostname && !strcmp(sa->hostname, hostname))) + && ((!scope_id && !old_scope) + || (scope_id && old_scope && !strcmp(scope_id, old_scope))); +} + +/* ### This logic doesn't cope with DNS changes across a restart. */ static int find_listeners(ap_listen_rec **from, ap_listen_rec **to, - const char *addr, apr_port_t port) + const char *addr, apr_port_t port, + const char *scope_id, apr_pool_t *temp_pool) { int found = 0; @@ -288,15 +313,10 @@ static int find_listeners(ap_listen_rec **from, ap_listen_rec **to, /* Some listeners are not real so they will not have a bind_addr. */ if (sa) { ap_listen_rec *new; - apr_port_t oldport; - oldport = sa->port; - /* If both ports are equivalent, then if their names are equivalent, - * then we will re-use the existing record. - */ - if (port == oldport && - ((!addr && !sa->hostname) || - ((addr && sa->hostname) && !strcmp(sa->hostname, addr)))) { + /* Re-use the existing record if it matches completely + * against an existing listener. */ + if (match_address(sa, addr, port, scope_id, temp_pool)) { found = 1; if (!to) { break; @@ -317,19 +337,21 @@ static int find_listeners(ap_listen_rec **from, ap_listen_rec **to, static const char *alloc_listener(process_rec *process, const char *addr, apr_port_t port, const char* proto, - void *slave) + const char *scope_id, void *slave, + apr_pool_t *temp_pool) { ap_listen_rec *last; apr_status_t status; apr_sockaddr_t *sa; /* see if we've got a listener for this address:port, which is an error */ - if (find_listeners(&ap_listeners, NULL, addr, port)) { + if (find_listeners(&ap_listeners, NULL, addr, port, scope_id, temp_pool)) { return "Cannot define multiple Listeners on the same IP:port"; } /* see if we've got an old listener for this address:port */ - if (find_listeners(&old_listeners, &ap_listeners, addr, port)) { + if (find_listeners(&old_listeners, &ap_listeners, addr, port, + scope_id, temp_pool)) { if (ap_listeners->slave != slave) { return "Cannot define a slave on the same IP:port as a Listener"; } @@ -383,6 +405,18 @@ static const char *alloc_listener(process_rec *process, const char *addr, return "Listen setup failed"; } +#if APR_VERSION_AT_LEAST(1,7,0) + if (scope_id) { + status = apr_sockaddr_zone_set(new->bind_addr, scope_id); + if (status) { + ap_log_perror(APLOG_MARK, APLOG_CRIT, status, process->pool, APLOGNO(10102) + "alloc_listener: failed to set scope for %pI to %s", + new->bind_addr, scope_id); + return "Listen step failed"; + } + } +#endif + /* We need to preserve the order returned by getaddrinfo() */ if (last == NULL) { ap_listeners = last = new; @@ -835,10 +869,14 @@ AP_DECLARE_NONSTD(const char *) ap_set_listener(cmd_parms *cmd, void *dummy, host = NULL; } +#if !APR_VERSION_AT_LEAST(1,7,0) if (scope_id) { - /* XXX scope id support is useful with link-local IPv6 addresses */ - return "Scope id is not supported"; + return apr_pstrcat(cmd->pool, + "Scope ID in address '", argv[0], + "' not supported with APR " APR_VERSION_STRING, + NULL); } +#endif if (!port) { return "Port must be specified"; @@ -856,7 +894,8 @@ AP_DECLARE_NONSTD(const char *) ap_set_listener(cmd_parms *cmd, void *dummy, ap_str_tolower(proto); } - return alloc_listener(cmd->server->process, host, port, proto, NULL); + return alloc_listener(cmd->server->process, host, port, proto, + scope_id, NULL, cmd->temp_pool); } AP_DECLARE_NONSTD(const char *) ap_set_listenbacklog(cmd_parms *cmd, |