1 /* ====================================================================
2 * The Apache Software License, Version 1.1
4 * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
19 * 3. The end-user documentation included with the redistribution,
20 * if any, must include the following acknowledgment:
21 * "This product includes software developed by the
22 * Apache Software Foundation (http://www.apache.org/)."
23 * Alternately, this acknowledgment may appear in the software itself,
24 * if and wherever such third-party acknowledgments normally appear.
26 * 4. The names "Apache" and "Apache Software Foundation" must
27 * not be used to endorse or promote products derived from this
28 * software without prior written permission. For written
29 * permission, please contact apache@apache.org.
31 * 5. Products derived from this software may not be called "Apache",
32 * nor may "Apache" appear in their name, without prior written
33 * permission of the Apache Software Foundation.
35 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
36 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
37 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
38 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
39 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
42 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
43 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
44 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
45 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47 * ====================================================================
49 * This software consists of voluntary contributions made by many
50 * individuals on behalf of the Apache Software Foundation. For more
51 * information on the Apache Software Foundation, please see
52 * <http://www.apache.org/>.
54 * Portions of this software are based upon public domain software
55 * originally written at the National Center for Supercomputing Applications,
56 * University of Illinois, Urbana-Champaign.
59 #include "apr_network_io.h"
60 #include "apr_strings.h"
63 #define APR_WANT_STRFUNC
67 #include "ap_config.h"
69 #include "http_config.h"
70 #include "ap_listen.h"
73 #include "mpm_common.h"
75 ap_listen_rec *ap_listeners;
77 static int default_family = APR_UNSPEC;
79 static int default_family = APR_INET;
81 static ap_listen_rec *old_listeners;
82 static int ap_listenbacklog;
83 static int send_buffer_size;
85 /* TODO: make_sock is just begging and screaming for APR abstraction */
86 static apr_status_t make_sock(apr_pool_t *p, ap_listen_rec *server)
88 apr_socket_t *s = server->sd;
92 stat = apr_setsocketopt(s, APR_SO_REUSEADDR, one);
93 if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) {
94 ap_log_perror(APLOG_MARK, APLOG_CRIT, stat, p,
95 "make_sock: for address %pI, setsockopt: (SO_REUSEADDR)",
101 stat = apr_setsocketopt(s, APR_SO_KEEPALIVE, one);
102 if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) {
103 ap_log_perror(APLOG_MARK, APLOG_CRIT, stat, p,
104 "make_sock: for address %pI, setsockopt: (SO_KEEPALIVE)",
111 * To send data over high bandwidth-delay connections at full
112 * speed we must force the TCP window to open wide enough to keep the
113 * pipe full. The default window size on many systems
114 * is only 4kB. Cross-country WAN connections of 100ms
115 * at 1Mb/s are not impossible for well connected sites.
116 * If we assume 100ms cross-country latency,
117 * a 4kB buffer limits throughput to 40kB/s.
119 * To avoid this problem I've added the SendBufferSize directive
120 * to allow the web master to configure send buffer size.
122 * The trade-off of larger buffers is that more kernel memory
123 * is consumed. YMMV, know your customers and your network!
125 * -John Heidemann <johnh@isi.edu> 25-Oct-96
127 * If no size is specified, use the kernel default.
129 if (send_buffer_size) {
130 stat = apr_setsocketopt(s, APR_SO_SNDBUF, send_buffer_size);
131 if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) {
132 ap_log_perror(APLOG_MARK, APLOG_WARNING, stat, p,
133 "make_sock: failed to set SendBufferSize for "
134 "address %pI, using default",
136 /* not a fatal error */
140 #if APR_TCP_NODELAY_INHERITED
141 ap_sock_disable_nagle(s);
144 if ((stat = apr_bind(s, server->bind_addr)) != APR_SUCCESS) {
145 ap_log_perror(APLOG_MARK, APLOG_CRIT, stat, p,
146 "make_sock: could not bind to address %pI",
152 if ((stat = apr_listen(s, ap_listenbacklog)) != APR_SUCCESS) {
153 ap_log_perror(APLOG_MARK, APLOG_ERR, stat, p,
154 "make_sock: unable to listen for connections on address %pI",
160 #if APR_HAS_SO_ACCEPTFILTER
161 #ifndef ACCEPT_FILTER_NAME
162 #define ACCEPT_FILTER_NAME "dataready"
164 apr_socket_accept_filter(s, ACCEPT_FILTER_NAME, "");
169 #ifdef MPM_ACCEPT_FUNC
170 server->accept_func = MPM_ACCEPT_FUNC;
172 server->accept_func = NULL;
177 static apr_status_t close_listeners_on_exec(void *v)
181 for (lr = ap_listeners; lr; lr = lr->next) {
182 apr_socket_close(lr->sd);
189 static void find_default_family(apr_pool_t *p)
192 /* We know the platform supports IPv6, but this particular
193 * system may not have IPv6 enabled. See if we can get an
196 if (default_family == APR_UNSPEC) {
197 apr_socket_t *tmp_sock;
199 if (apr_socket_create(&tmp_sock, APR_INET6, SOCK_STREAM,
201 apr_socket_close(tmp_sock);
202 default_family = APR_INET6;
205 default_family = APR_INET;
212 static void alloc_listener(process_rec *process, char *addr, apr_port_t port)
214 ap_listen_rec **walk;
221 if (!addr) { /* don't bind to specific interface */
222 find_default_family(process->pool);
223 switch(default_family) {
233 ap_assert(1 != 1); /* should not occur */
237 /* see if we've got an old listener for this address:port */
238 for (walk = &old_listeners; *walk; walk = &(*walk)->next) {
239 sa = (*walk)->bind_addr;
240 /* Some listeners are not real so they will not have a bind_addr. */
242 apr_sockaddr_port_get(&oldport, sa);
243 apr_sockaddr_ip_get(&oldaddr, sa);
244 if (!strcmp(oldaddr, addr) && port == oldport) {
245 /* re-use existing record */
248 new->next = ap_listeners;
255 /* this has to survive restarts */
256 new = apr_palloc(process->pool, sizeof(ap_listen_rec));
258 if ((status = apr_sockaddr_info_get(&new->bind_addr, addr, APR_UNSPEC,
259 port, 0, process->pool)) != APR_SUCCESS) {
260 ap_log_perror(APLOG_MARK, APLOG_CRIT, status, process->pool,
261 "alloc_listener: failed to set up sockaddr for %s", addr);
264 if ((status = apr_socket_create(&new->sd, new->bind_addr->sa.sin.sin_family,
265 SOCK_STREAM, process->pool)) != APR_SUCCESS) {
266 ap_log_perror(APLOG_MARK, APLOG_CRIT, status, process->pool,
267 "alloc_listener: failed to get a socket for %s", addr);
270 new->next = ap_listeners;
274 #if !defined(SPMT_OS2_MPM)
277 int ap_listen_open(process_rec *process, apr_port_t port)
279 apr_pool_t *pconf = process->pconf;
284 /* Don't allocate a default listener. If we need to listen to a
285 * port, then the user needs to have a Listen directive in their
289 for (lr = ap_listeners; lr; lr = lr->next) {
294 if (make_sock(pconf, lr) == APR_SUCCESS) {
305 /* close the old listeners */
306 for (lr = old_listeners; lr; lr = next) {
307 apr_socket_close(lr->sd);
312 old_listeners = NULL;
314 apr_pool_cleanup_register(pconf, NULL, apr_pool_cleanup_null,
315 close_listeners_on_exec);
317 return num_open ? 0 : -1;
320 int ap_setup_listeners(server_rec *s)
323 int num_listeners = 0;
324 if (ap_listen_open(s->process, s->port)) {
327 for (lr = ap_listeners; lr; lr = lr->next) {
330 return num_listeners;
333 void ap_listen_pre_config(void)
335 old_listeners = ap_listeners;
337 ap_listenbacklog = DEFAULT_LISTENBACKLOG;
341 const char *ap_set_listener(cmd_parms *cmd, void *dummy, const char *ips)
343 char *host, *scope_id;
347 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
352 rv = apr_parse_addr_port(&host, &scope_id, &port, ips, cmd->pool);
353 if (rv != APR_SUCCESS) {
354 return "Invalid address or port";
356 if (host && !strcmp(host, "*")) {
360 /* XXX scope id support is useful with link-local IPv6 addresses */
361 return "Scope id is not supported";
364 return "Port must be specified";
367 alloc_listener(cmd->server->process, host, port);
372 const char *ap_set_listenbacklog(cmd_parms *cmd, void *dummy, const char *arg)
376 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
383 return "ListenBacklog must be > 0";
385 ap_listenbacklog = b;
389 const char *ap_set_send_buffer_size(cmd_parms *cmd, void *dummy,
393 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
398 if (s < 512 && s != 0) {
399 return "SendBufferSize must be >= 512 bytes, or 0 for system default.";
401 send_buffer_size = s;