-/* Copyright 1999-2005 The Apache Software Foundation or its licensors, as
- * applicable.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
#define APR_WANT_STRFUNC
#include "apr_want.h"
-#define CORE_PRIVATE
#include "ap_config.h"
#include "httpd.h"
#include "http_config.h"
#include "http_core.h"
#include "ap_listen.h"
#include "http_log.h"
-#include "mpm.h"
#include "mpm_common.h"
AP_DECLARE_DATA ap_listen_rec *ap_listeners = NULL;
"make_sock: failed to set ReceiveBufferSize for "
"address %pI, using default",
server->bind_addr);
- strerror(errno);
/* not a fatal error */
}
}
stat = apr_socket_opt_set(s, APR_SO_REUSEADDR, one);
if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) {
ap_log_perror(APLOG_MARK, APLOG_CRIT, stat, p,
- "make_sock: for address %pI, apr_socket_opt_set: (SO_REUSEADDR)",
+ "make_sock: for address %pI, apr_socket_opt_set: (SO_REUSEADDR)",
server->bind_addr);
apr_socket_close(s);
return stat;
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;
}
return accf;
}
-static void ap_apply_accept_filter(apr_pool_t *p, ap_listen_rec *lis,
+static void ap_apply_accept_filter(apr_pool_t *p, ap_listen_rec *lis,
server_rec *server)
{
apr_socket_t *s = lis->sd;
if (accf) {
#if APR_HAS_SO_ACCEPTFILTER
- rv = apr_socket_accept_filter(s, apr_pstrdup(p, accf),
+ rv = apr_socket_accept_filter(s, apr_pstrdup(p, accf),
apr_pstrdup(p,""));
if (rv != APR_SUCCESS && !APR_STATUS_IS_ENOTIMPL(rv)) {
ap_log_perror(APLOG_MARK, APLOG_WARNING, rv, p,
accf);
}
#else
-#ifdef APR_TCP_DEFER_ACCEPT
- rv = apr_socket_opt_set(s, APR_TCP_DEFER_ACCEPT, 1);
+ 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
}
}
return APR_SUCCESS;
}
-static const char *alloc_listener(process_rec *process, char *addr,
+static const char *alloc_listener(process_rec *process, char *addr,
apr_port_t port, const char* proto)
{
ap_listen_rec **walk, *last;
int num_open;
const char *userdata_key = "ap_open_listeners";
void *data;
+#if AP_NONBLOCK_WHEN_MULTI_LISTEN
+ int use_nonblock;
+#endif
/* Don't allocate a default listener. If we need to listen to a
* port, then the user needs to have a Listen directive in their
}
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
&& IS_IN6ADDR_ANY(lr->next->bind_addr)) {
/* Exchange lr and lr->next */
- ap_listen_rec *next = lr->next;
+ next = lr->next;
lr->next = next->next;
next->next = lr;
if (previous) {
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;
- 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) {
* is already forgotten about by the time we call accept, we won't
* be hung until another connection arrives on that port
*/
- if (ap_listeners && ap_listeners->next) {
- for (lr = ap_listeners; lr; lr = lr->next) {
- apr_status_t status;
-
- status = apr_socket_opt_set(lr->sd, APR_SO_NONBLOCK, 1);
- if (status != APR_SUCCESS) {
- ap_log_perror(APLOG_MARK, APLOG_STARTUP|APLOG_ERR, status, pool,
- "unable to make listening socket non-blocking");
- return -1;
- }
+ use_nonblock = (ap_listeners && ap_listeners->next);
+ for (lr = ap_listeners; lr; lr = lr->next) {
+ apr_status_t status;
+
+ status = apr_socket_opt_set(lr->sd, APR_SO_NONBLOCK, use_nonblock);
+ if (status != APR_SUCCESS) {
+ ap_log_perror(APLOG_MARK, APLOG_STARTUP|APLOG_ERR, status, pool,
+ "unable to control socket non-blocking status");
+ return -1;
}
}
#endif /* AP_NONBLOCK_WHEN_MULTI_LISTEN */
proto = ap_get_server_protocol(ls);
if (!proto) {
found = 0;
- /* No protocol was set for this vhost,
- * use the default for this listener.
+ /* No protocol was set for this vhost,
+ * use the default for this listener.
*/
for (addr = ls->addrs; addr && !found; addr = addr->next) {
for (lr = ap_listeners; lr; lr = lr->next) {
return num_listeners;
}
-AP_DECLARE_NONSTD(void) ap_close_listeners(void)
+AP_DECLARE_NONSTD(void) ap_close_listeners(void)
{
ap_listen_rec *lr;
}
if (argc != 2) {
- proto = "http";
+ if (port == 443) {
+ proto = "https";
+ } else {
+ proto = "http";
+ }
}
else {
proto = apr_pstrdup(cmd->pool, argv[1]);