listen.c revision 7184de27ec1d62a83c41cdeac0953ca9fd661e8c
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova/* Licensed to the Apache Software Foundation (ASF) under one or more
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova * contributor license agreements. See the NOTICE file distributed with
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova * this work for additional information regarding copyright ownership.
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova * The ASF licenses this file to You under the Apache License, Version 2.0
98890889ffb2e8f6f722b00e265a211f13b5a861Corneliu-Claudiu Prodescu * (the "License"); you may not use this file except in compliance with
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova * the License. You may obtain a copy of the License at
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova * http://www.apache.org/licenses/LICENSE-2.0
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova * Unless required by applicable law or agreed to in writing, software
e8dd447a2aa5fbac10668749dfe4142c05ec3d7dKristina Sojakova * distributed under the License is distributed on an "AS IS" BASIS,
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova * See the License for the specific language governing permissions and
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova * limitations under the License.
5e35940c3516ccea02caa0450d2b075de0106fa5Kristina Sojakova/* we know core's module_index is 0 */
118add2c5ac398465f6f66adb165852dffe1264dKristina Sojakova#define APLOG_MODULE_INDEX AP_CORE_MODULE_INDEX
5e35940c3516ccea02caa0450d2b075de0106fa5Kristina SojakovaAP_DECLARE_DATA ap_listen_rec *ap_listeners = NULL;
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova/* TODO: make_sock is just begging and screaming for APR abstraction */
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakovastatic apr_status_t make_sock(apr_pool_t *p, ap_listen_rec *server)
5e35940c3516ccea02caa0450d2b075de0106fa5Kristina Sojakova stat = apr_socket_opt_set(s, APR_SO_REUSEADDR, one);
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) {
5e35940c3516ccea02caa0450d2b075de0106fa5Kristina Sojakova ap_log_perror(APLOG_MARK, APLOG_CRIT, stat, p,
5e35940c3516ccea02caa0450d2b075de0106fa5Kristina Sojakova "make_sock: for address %pI, apr_socket_opt_set: (SO_REUSEADDR)",
e8dd447a2aa5fbac10668749dfe4142c05ec3d7dKristina Sojakova stat = apr_socket_opt_set(s, APR_SO_KEEPALIVE, one);
e8dd447a2aa5fbac10668749dfe4142c05ec3d7dKristina Sojakova if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) {
e8dd447a2aa5fbac10668749dfe4142c05ec3d7dKristina Sojakova ap_log_perror(APLOG_MARK, APLOG_CRIT, stat, p,
e8dd447a2aa5fbac10668749dfe4142c05ec3d7dKristina Sojakova "make_sock: for address %pI, apr_socket_opt_set: (SO_KEEPALIVE)",
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova if (server->bind_addr->family == APR_INET6) {
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova stat = apr_socket_opt_set(s, APR_IPV6_V6ONLY, v6only_setting);
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) {
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova ap_log_perror(APLOG_MARK, APLOG_CRIT, stat, p,
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova "make_sock: for address %pI, apr_socket_opt_set: "
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova "(IPV6_V6ONLY)",
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova * To send data over high bandwidth-delay connections at full
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova * speed we must force the TCP window to open wide enough to keep the
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova * pipe full. The default window size on many systems
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova * is only 4kB. Cross-country WAN connections of 100ms
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova * at 1Mb/s are not impossible for well connected sites.
e8dd447a2aa5fbac10668749dfe4142c05ec3d7dKristina Sojakova * If we assume 100ms cross-country latency,
e8dd447a2aa5fbac10668749dfe4142c05ec3d7dKristina Sojakova * a 4kB buffer limits throughput to 40kB/s.
e8dd447a2aa5fbac10668749dfe4142c05ec3d7dKristina Sojakova * To avoid this problem I've added the SendBufferSize directive
e8dd447a2aa5fbac10668749dfe4142c05ec3d7dKristina Sojakova * to allow the web master to configure send buffer size.
e8dd447a2aa5fbac10668749dfe4142c05ec3d7dKristina Sojakova * The trade-off of larger buffers is that more kernel memory
e8dd447a2aa5fbac10668749dfe4142c05ec3d7dKristina Sojakova * is consumed. YMMV, know your customers and your network!
e8dd447a2aa5fbac10668749dfe4142c05ec3d7dKristina Sojakova * -John Heidemann <johnh@isi.edu> 25-Oct-96
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova * If no size is specified, use the kernel default.
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova stat = apr_socket_opt_set(s, APR_SO_SNDBUF, send_buffer_size);
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) {
168d206b4e5fd436c98239a1b6629c651f54c8eeKristina Sojakova ap_log_perror(APLOG_MARK, APLOG_WARNING, stat, p,
168d206b4e5fd436c98239a1b6629c651f54c8eeKristina Sojakova "make_sock: failed to set SendBufferSize for "
168d206b4e5fd436c98239a1b6629c651f54c8eeKristina Sojakova "address %pI, using default",
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova /* not a fatal error */
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova stat = apr_socket_opt_set(s, APR_SO_RCVBUF, receive_buffer_size);
e8dd447a2aa5fbac10668749dfe4142c05ec3d7dKristina Sojakova if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) {
5e35940c3516ccea02caa0450d2b075de0106fa5Kristina Sojakova ap_log_perror(APLOG_MARK, APLOG_WARNING, stat, p,
5e35940c3516ccea02caa0450d2b075de0106fa5Kristina Sojakova "make_sock: failed to set ReceiveBufferSize for "
5e35940c3516ccea02caa0450d2b075de0106fa5Kristina Sojakova "address %pI, using default",
5e35940c3516ccea02caa0450d2b075de0106fa5Kristina Sojakova /* not a fatal error */
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova if ((stat = apr_socket_bind(s, server->bind_addr)) != APR_SUCCESS) {
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova ap_log_perror(APLOG_MARK, APLOG_STARTUP|APLOG_CRIT, stat, p,
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova "make_sock: could not bind to address %pI",
5e35940c3516ccea02caa0450d2b075de0106fa5Kristina Sojakova if ((stat = apr_socket_listen(s, ap_listenbacklog)) != APR_SUCCESS) {
5e35940c3516ccea02caa0450d2b075de0106fa5Kristina Sojakova ap_log_perror(APLOG_MARK, APLOG_STARTUP|APLOG_ERR, stat, p,
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova "make_sock: unable to listen for connections "
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova "on address %pI",
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova /* I seriously doubt that this would work on Unix; I have doubts that
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova * it entirely solves the problem on Win32. However, since setting
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova * reuseaddr on the listener -prior- to binding the socket has allowed
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova * us to attach to the same port as an already running instance of
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova * Apache, or even another web server, we cannot identify that this
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova * port was exclusively granted to this instance of Apache.
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova * So set reuseaddr, but do not attempt to do so until we have the
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova * parent listeners successfully bound.
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova stat = apr_socket_opt_set(s, APR_SO_REUSEADDR, one);
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) {
ccaa75089b23c0f043cdbd4001cba4e076ca4fd3Kristina Sojakova ap_log_perror(APLOG_MARK, APLOG_CRIT, stat, p,
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova "make_sock: for address %pI, apr_socket_opt_set: (SO_REUSEADDR)",
168d206b4e5fd436c98239a1b6629c651f54c8eeKristina Sojakovastatic const char* find_accf_name(server_rec *s, const char *proto)
168d206b4e5fd436c98239a1b6629c651f54c8eeKristina Sojakova core_server_config *conf = ap_get_core_module_config(s->module_config);
d71bb9deea089887b4fd829c5b766e7e4de9f204Kristina Sojakova accf = apr_table_get(conf->accf_map, proto);
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakovastatic void ap_apply_accept_filter(apr_pool_t *p, ap_listen_rec *lis,
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova rv = apr_socket_accept_filter(s, apr_pstrdup(p, accf),
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova if (rv != APR_SUCCESS && !APR_STATUS_IS_ENOTIMPL(rv)) {
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova ap_log_perror(APLOG_MARK, APLOG_WARNING, rv, p,
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova "Failed to enable the '%s' Accept Filter",
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova rv = apr_socket_opt_set(s, APR_TCP_DEFER_ACCEPT, 30);
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova if (rv != APR_SUCCESS && !APR_STATUS_IS_ENOTIMPL(rv)) {
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova ap_log_perror(APLOG_MARK, APLOG_WARNING, rv, p,
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakova "Failed to enable APR_TCP_DEFER_ACCEPT");
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakovastatic apr_status_t close_listeners_on_exec(void *v)
abd5fc85dc7e19b1614890182436940e922963a4Kristina Sojakovastatic const char *alloc_listener(process_rec *process, char *addr,
void *dummy)
int found_listener = 0;
if (sa) {
if (found_listener) {
return NULL;
!= APR_SUCCESS) {
addr);
while (sa) {
#if APR_HAVE_IPV6
addr);
return NULL;
int num_open;
void *data;
int use_nonblock;
num_open = 0;
++num_open;
#if APR_HAVE_IPV6
int v6only_setting;
int skip = 0;
if (previous) {
&& v6only_setting == 0) {
if (skip) {
++num_open;
#if APR_HAVE_IPV6
if (previous) {
if (!data) {
int num_listeners = 0;
const char* proto;
int found;
if (!proto) {
found = 0;
if (!found) {
found = 0;
if (!found) {
return num_listeners;
return err;
if (scope_id) {
if (!port) {
void *dummy,
const char *arg)
return err;
ap_listenbacklog = b;
return NULL;
void *dummy,
const char *arg)
return err;
send_buffer_size = s;
return NULL;
void *dummy,
const char *arg)
return err;
receive_buffer_size = s;
return NULL;