#include "http_core.h"
#include "ap_listen.h"
#include "http_log.h"
-#include "mpm.h"
#include "mpm_common.h"
+APLOG_USE_MODULE(core);
+
AP_DECLARE_DATA ap_listen_rec *ap_listeners = NULL;
static ap_listen_rec *old_listeners;
server->sd = s;
server->active = 1;
-#ifdef MPM_ACCEPT_FUNC
- server->accept_func = MPM_ACCEPT_FUNC;
-#else
server->accept_func = NULL;
-#endif
return APR_SUCCESS;
}
accf);
}
#else
-#ifdef APR_TCP_DEFER_ACCEPT
rv = apr_socket_opt_set(s, APR_TCP_DEFER_ACCEPT, 30);
if (rv != APR_SUCCESS && !APR_STATUS_IS_ENOTIMPL(rv)) {
ap_log_perror(APLOG_MARK, APLOG_WARNING, rv, p,
"Failed to enable APR_TCP_DEFER_ACCEPT");
}
-#endif
#endif
}
}
}
static const char *alloc_listener(process_rec *process, char *addr,
- apr_port_t port, const char* proto)
+ apr_port_t port, const char* proto,
+ void *dummy)
{
ap_listen_rec **walk, *last;
apr_status_t status;
}
if (found_listener) {
+ if (ap_listeners->slave != dummy) {
+ return "Cannot define a slave on the same IP:port as a Listener";
+ }
return NULL;
}
last->next = new;
last = new;
}
+ new->slave = dummy;
}
return NULL;
}
else {
#if APR_HAVE_IPV6
+ ap_listen_rec *cur;
int v6only_setting;
+ int skip = 0;
/* If we have the unspecified IPv4 address (0.0.0.0) and
* the unspecified IPv6 address (::) is next, we need to
* swap the order of these in the list. We always try to
* bind to IPv6 first, then IPv4, since an IPv6 socket
* might be able to receive IPv4 packets if V6ONLY is not
- * enabled, but never the other way around. */
+ * enabled, but never the other way around.
+ * Note: In some configurations, the unspecified IPv6 address
+ * could be even later in the list. This logic only corrects
+ * the situation where it is next in the list, such as when
+ * apr_sockaddr_info_get() returns an IPv4 and an IPv6 address,
+ * in that order.
+ */
if (lr->next != NULL
&& IS_INADDR_ANY(lr->bind_addr)
&& lr->bind_addr->port == lr->next->bind_addr->port
lr = next;
}
- /* If we are trying to bind to 0.0.0.0 and the previous listener
+ /* If we are trying to bind to 0.0.0.0 and a previous listener
* was :: on the same port and in turn that socket does not have
* the IPV6_V6ONLY flag set; we must skip the current attempt to
* listen (which would generate an error). IPv4 will be handled
* on the established IPv6 socket.
*/
- if (previous != NULL
- && IS_INADDR_ANY(lr->bind_addr)
- && lr->bind_addr->port == previous->bind_addr->port
- && IS_IN6ADDR_ANY(previous->bind_addr)
- && apr_socket_opt_get(previous->sd, APR_IPV6_V6ONLY,
- &v6only_setting) == APR_SUCCESS
- && v6only_setting == 0) {
-
- /* Remove the current listener from the list */
- previous->next = lr->next;
- lr = previous; /* maintain current value of previous after
- * post-loop expression is evaluated
- */
- continue;
+ if (IS_INADDR_ANY(lr->bind_addr)) {
+ for (cur = ap_listeners; cur != lr; cur = cur->next) {
+ if (lr->bind_addr->port == cur->bind_addr->port
+ && IS_IN6ADDR_ANY(cur->bind_addr)
+ && apr_socket_opt_get(cur->sd, APR_IPV6_V6ONLY,
+ &v6only_setting) == APR_SUCCESS
+ && v6only_setting == 0) {
+
+ /* Remove the current listener from the list */
+ previous->next = lr->next;
+ lr = previous; /* maintain current value of previous after
+ * post-loop expression is evaluated
+ */
+ skip = 1;
+ break;
+ }
+ }
+ if (skip) {
+ continue;
+ }
}
#endif
if (make_sock(pool, lr) == APR_SUCCESS) {
++num_open;
- lr->active = 1;
}
else {
#if APR_HAVE_IPV6
lr->active = 0;
}
}
+AP_DECLARE_NONSTD(int) ap_close_selected_listeners(ap_slave_t *slave)
+{
+ ap_listen_rec *lr;
+ int n = 0;
+
+ for (lr = ap_listeners; lr; lr = lr->next) {
+ if (lr->slave != slave) {
+ apr_socket_close(lr->sd);
+ lr->active = 0;
+ }
+ else {
+ ++n;
+ }
+ }
+ return n;
+}
AP_DECLARE(void) ap_listen_pre_config(void)
{
ap_listenbacklog = DEFAULT_LISTENBACKLOG;
}
-
+/* Hack: populate an extra field
+ * When this gets called from a Listen directive, dummy is null.
+ * So we can use non-null dummy to pass a data pointer without conflict
+ */
AP_DECLARE_NONSTD(const char *) ap_set_listener(cmd_parms *cmd, void *dummy,
int argc, char *const argv[])
{
}
if (argc != 2) {
- proto = "http";
+ if (port == 443) {
+ proto = "https";
+ } else {
+ proto = "http";
+ }
}
else {
proto = apr_pstrdup(cmd->pool, argv[1]);
ap_str_tolower(proto);
}
- return alloc_listener(cmd->server->process, host, port, proto);
+ return alloc_listener(cmd->server->process, host, port, proto, dummy);
}
AP_DECLARE_NONSTD(const char *) ap_set_listenbacklog(cmd_parms *cmd,