1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include "apr_network_io.h"
18 #include "apr_strings.h"
20 #define APR_WANT_STRFUNC
23 #include "ap_config.h"
25 #include "http_config.h"
26 #include "http_core.h"
27 #include "ap_listen.h"
30 #include "mpm_common.h"
32 AP_DECLARE_DATA ap_listen_rec *ap_listeners = NULL;
34 static ap_listen_rec *old_listeners;
35 static int ap_listenbacklog;
36 static int send_buffer_size;
37 static int receive_buffer_size;
39 /* TODO: make_sock is just begging and screaming for APR abstraction */
40 static apr_status_t make_sock(apr_pool_t *p, ap_listen_rec *server)
42 apr_socket_t *s = server->sd;
45 #ifdef AP_ENABLE_V4_MAPPED
46 int v6only_setting = 0;
48 int v6only_setting = 1;
54 stat = apr_socket_opt_set(s, APR_SO_REUSEADDR, one);
55 if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) {
56 ap_log_perror(APLOG_MARK, APLOG_CRIT, stat, p,
57 "make_sock: for address %pI, apr_socket_opt_set: (SO_REUSEADDR)",
64 stat = apr_socket_opt_set(s, APR_SO_KEEPALIVE, one);
65 if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) {
66 ap_log_perror(APLOG_MARK, APLOG_CRIT, stat, p,
67 "make_sock: for address %pI, apr_socket_opt_set: (SO_KEEPALIVE)",
74 if (server->bind_addr->family == APR_INET6) {
75 stat = apr_socket_opt_set(s, APR_IPV6_V6ONLY, v6only_setting);
76 if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) {
77 ap_log_perror(APLOG_MARK, APLOG_CRIT, stat, p,
78 "make_sock: for address %pI, apr_socket_opt_set: "
88 * To send data over high bandwidth-delay connections at full
89 * speed we must force the TCP window to open wide enough to keep the
90 * pipe full. The default window size on many systems
91 * is only 4kB. Cross-country WAN connections of 100ms
92 * at 1Mb/s are not impossible for well connected sites.
93 * If we assume 100ms cross-country latency,
94 * a 4kB buffer limits throughput to 40kB/s.
96 * To avoid this problem I've added the SendBufferSize directive
97 * to allow the web master to configure send buffer size.
99 * The trade-off of larger buffers is that more kernel memory
100 * is consumed. YMMV, know your customers and your network!
102 * -John Heidemann <johnh@isi.edu> 25-Oct-96
104 * If no size is specified, use the kernel default.
106 if (send_buffer_size) {
107 stat = apr_socket_opt_set(s, APR_SO_SNDBUF, send_buffer_size);
108 if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) {
109 ap_log_perror(APLOG_MARK, APLOG_WARNING, stat, p,
110 "make_sock: failed to set SendBufferSize for "
111 "address %pI, using default",
113 /* not a fatal error */
116 if (receive_buffer_size) {
117 stat = apr_socket_opt_set(s, APR_SO_RCVBUF, receive_buffer_size);
118 if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) {
119 ap_log_perror(APLOG_MARK, APLOG_WARNING, stat, p,
120 "make_sock: failed to set ReceiveBufferSize for "
121 "address %pI, using default",
123 /* not a fatal error */
127 #if APR_TCP_NODELAY_INHERITED
128 ap_sock_disable_nagle(s);
131 if ((stat = apr_socket_bind(s, server->bind_addr)) != APR_SUCCESS) {
132 ap_log_perror(APLOG_MARK, APLOG_STARTUP|APLOG_CRIT, stat, p,
133 "make_sock: could not bind to address %pI",
139 if ((stat = apr_socket_listen(s, ap_listenbacklog)) != APR_SUCCESS) {
140 ap_log_perror(APLOG_MARK, APLOG_STARTUP|APLOG_ERR, stat, p,
141 "make_sock: unable to listen for connections "
149 /* I seriously doubt that this would work on Unix; I have doubts that
150 * it entirely solves the problem on Win32. However, since setting
151 * reuseaddr on the listener -prior- to binding the socket has allowed
152 * us to attach to the same port as an already running instance of
153 * Apache, or even another web server, we cannot identify that this
154 * port was exclusively granted to this instance of Apache.
156 * So set reuseaddr, but do not attempt to do so until we have the
157 * parent listeners successfully bound.
159 stat = apr_socket_opt_set(s, APR_SO_REUSEADDR, one);
160 if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) {
161 ap_log_perror(APLOG_MARK, APLOG_CRIT, stat, p,
162 "make_sock: for address %pI, apr_socket_opt_set: (SO_REUSEADDR)",
172 #ifdef MPM_ACCEPT_FUNC
173 server->accept_func = MPM_ACCEPT_FUNC;
175 server->accept_func = NULL;
181 static const char* find_accf_name(server_rec *s, const char *proto)
184 core_server_config *conf = ap_get_module_config(s->module_config,
190 accf = apr_table_get(conf->accf_map, proto);
192 if (accf && !strcmp("none", accf)) {
199 static void ap_apply_accept_filter(apr_pool_t *p, ap_listen_rec *lis,
202 apr_socket_t *s = lis->sd;
207 proto = lis->protocol;
210 proto = ap_get_server_protocol(server);
214 accf = find_accf_name(server, proto);
217 #if APR_HAS_SO_ACCEPTFILTER
218 rv = apr_socket_accept_filter(s, apr_pstrdup(p, accf),
220 if (rv != APR_SUCCESS && !APR_STATUS_IS_ENOTIMPL(rv)) {
221 ap_log_perror(APLOG_MARK, APLOG_WARNING, rv, p,
222 "Failed to enable the '%s' Accept Filter",
226 #ifdef APR_TCP_DEFER_ACCEPT
227 rv = apr_socket_opt_set(s, APR_TCP_DEFER_ACCEPT, 30);
228 if (rv != APR_SUCCESS && !APR_STATUS_IS_ENOTIMPL(rv)) {
229 ap_log_perror(APLOG_MARK, APLOG_WARNING, rv, p,
230 "Failed to enable APR_TCP_DEFER_ACCEPT");
237 static apr_status_t close_listeners_on_exec(void *v)
239 ap_close_listeners();
243 static const char *alloc_listener(process_rec *process, char *addr,
244 apr_port_t port, const char* proto)
246 ap_listen_rec **walk, *last;
249 int found_listener = 0;
251 /* see if we've got an old listener for this address:port */
252 for (walk = &old_listeners; *walk;) {
253 sa = (*walk)->bind_addr;
254 /* Some listeners are not real so they will not have a bind_addr. */
260 /* If both ports are equivalent, then if their names are equivalent,
261 * then we will re-use the existing record.
263 if (port == oldport &&
264 ((!addr && !sa->hostname) ||
265 ((addr && sa->hostname) && !strcmp(sa->hostname, addr)))) {
268 new->next = ap_listeners;
275 walk = &(*walk)->next;
278 if (found_listener) {
282 if ((status = apr_sockaddr_info_get(&sa, addr, APR_UNSPEC, port, 0,
285 ap_log_perror(APLOG_MARK, APLOG_CRIT, status, process->pool,
286 "alloc_listener: failed to set up sockaddr for %s",
288 return "Listen setup failed";
291 /* Initialize to our last configured ap_listener. */
293 while (last && last->next) {
300 /* this has to survive restarts */
301 new = apr_palloc(process->pool, sizeof(ap_listen_rec));
305 new->protocol = apr_pstrdup(process->pool, proto);
307 /* Go to the next sockaddr. */
310 status = apr_socket_create(&new->sd, new->bind_addr->family,
311 SOCK_STREAM, 0, process->pool);
314 /* What could happen is that we got an IPv6 address, but this system
315 * doesn't actually support IPv6. Try the next address.
317 if (status != APR_SUCCESS && !addr &&
318 new->bind_addr->family == APR_INET6) {
322 if (status != APR_SUCCESS) {
323 ap_log_perror(APLOG_MARK, APLOG_CRIT, status, process->pool,
324 "alloc_listener: failed to get a socket for %s",
326 return "Listen setup failed";
329 /* We need to preserve the order returned by getaddrinfo() */
331 ap_listeners = last = new;
340 /* Evaluates to true if the (apr_sockaddr_t *) addr argument is the
341 * IPv4 match-any-address, 0.0.0.0. */
342 #define IS_INADDR_ANY(addr) ((addr)->family == APR_INET \
343 && (addr)->sa.sin.sin_addr.s_addr == INADDR_ANY)
345 /* Evaluates to true if the (apr_sockaddr_t *) addr argument is the
346 * IPv6 match-any-address, [::]. */
347 #define IS_IN6ADDR_ANY(addr) ((addr)->family == APR_INET6 \
348 && IN6_IS_ADDR_UNSPECIFIED(&(addr)->sa.sin6.sin6_addr))
351 * Create, open, listen, and bind all sockets.
352 * @param process The process record for the currently running server
353 * @return The number of open sockets
355 static int open_listeners(apr_pool_t *pool)
359 ap_listen_rec *previous;
361 const char *userdata_key = "ap_open_listeners";
363 #if AP_NONBLOCK_WHEN_MULTI_LISTEN
367 /* Don't allocate a default listener. If we need to listen to a
368 * port, then the user needs to have a Listen directive in their
373 for (lr = ap_listeners; lr; previous = lr, lr = lr->next) {
383 /* If we have the unspecified IPv4 address (0.0.0.0) and
384 * the unspecified IPv6 address (::) is next, we need to
385 * swap the order of these in the list. We always try to
386 * bind to IPv6 first, then IPv4, since an IPv6 socket
387 * might be able to receive IPv4 packets if V6ONLY is not
388 * enabled, but never the other way around.
389 * Note: In some configurations, the unspecified IPv6 address
390 * could be even later in the list. This logic only corrects
391 * the situation where it is next in the list, such as when
392 * apr_sockaddr_info_get() returns an IPv4 and an IPv6 address,
396 && IS_INADDR_ANY(lr->bind_addr)
397 && lr->bind_addr->port == lr->next->bind_addr->port
398 && IS_IN6ADDR_ANY(lr->next->bind_addr)) {
399 /* Exchange lr and lr->next */
401 lr->next = next->next;
404 previous->next = next;
412 /* If we are trying to bind to 0.0.0.0 and a previous listener
413 * was :: on the same port and in turn that socket does not have
414 * the IPV6_V6ONLY flag set; we must skip the current attempt to
415 * listen (which would generate an error). IPv4 will be handled
416 * on the established IPv6 socket.
418 if (IS_INADDR_ANY(lr->bind_addr)) {
419 for (cur = ap_listeners; cur != lr; cur = cur->next) {
420 if (lr->bind_addr->port == cur->bind_addr->port
421 && IS_IN6ADDR_ANY(cur->bind_addr)
422 && apr_socket_opt_get(cur->sd, APR_IPV6_V6ONLY,
423 &v6only_setting) == APR_SUCCESS
424 && v6only_setting == 0) {
426 /* Remove the current listener from the list */
427 previous->next = lr->next;
428 lr = previous; /* maintain current value of previous after
429 * post-loop expression is evaluated
440 if (make_sock(pool, lr) == APR_SUCCESS) {
446 /* If we tried to bind to ::, and the next listener is
447 * on 0.0.0.0 with the same port, don't give a fatal
448 * error. The user will still get a warning from make_sock
452 && IS_IN6ADDR_ANY(lr->bind_addr)
453 && lr->bind_addr->port == lr->next->bind_addr->port
454 && IS_INADDR_ANY(lr->next->bind_addr)) {
456 /* Remove the current listener from the list */
458 previous->next = lr->next;
461 ap_listeners = lr->next;
464 /* Although we've removed ourselves from the list,
465 * we need to make sure that the next iteration won't
466 * consider "previous" a working IPv6 '::' socket.
467 * Changing the family is enough to make sure the
468 * conditions before make_sock() fail.
470 lr->bind_addr->family = AF_INET;
481 /* close the old listeners */
482 for (lr = old_listeners; lr; lr = next) {
483 apr_socket_close(lr->sd);
487 old_listeners = NULL;
489 #if AP_NONBLOCK_WHEN_MULTI_LISTEN
490 /* if multiple listening sockets, make them non-blocking so that
491 * if select()/poll() reports readability for a reset connection that
492 * is already forgotten about by the time we call accept, we won't
493 * be hung until another connection arrives on that port
495 use_nonblock = (ap_listeners && ap_listeners->next);
496 for (lr = ap_listeners; lr; lr = lr->next) {
499 status = apr_socket_opt_set(lr->sd, APR_SO_NONBLOCK, use_nonblock);
500 if (status != APR_SUCCESS) {
501 ap_log_perror(APLOG_MARK, APLOG_STARTUP|APLOG_ERR, status, pool,
502 "unable to control socket non-blocking status");
506 #endif /* AP_NONBLOCK_WHEN_MULTI_LISTEN */
508 /* we come through here on both passes of the open logs phase
509 * only register the cleanup once... otherwise we try to close
510 * listening sockets twice when cleaning up prior to exec
512 apr_pool_userdata_get(&data, userdata_key, pool);
514 apr_pool_userdata_set((const void *)1, userdata_key,
515 apr_pool_cleanup_null, pool);
516 apr_pool_cleanup_register(pool, NULL, apr_pool_cleanup_null,
517 close_listeners_on_exec);
520 return num_open ? 0 : -1;
523 AP_DECLARE(int) ap_setup_listeners(server_rec *s)
526 server_addr_rec *addr;
528 int num_listeners = 0;
532 for (ls = s; ls; ls = ls->next) {
533 proto = ap_get_server_protocol(ls);
536 /* No protocol was set for this vhost,
537 * use the default for this listener.
539 for (addr = ls->addrs; addr && !found; addr = addr->next) {
540 for (lr = ap_listeners; lr; lr = lr->next) {
541 if (apr_sockaddr_equal(lr->bind_addr, addr->host_addr) &&
542 lr->bind_addr->port == addr->host_port) {
543 ap_set_server_protocol(ls, lr->protocol);
551 /* TODO: set protocol defaults per-Port, eg 25=smtp */
552 ap_set_server_protocol(ls, "http");
557 if (open_listeners(s->process->pool)) {
561 for (lr = ap_listeners; lr; lr = lr->next) {
564 for (ls = s; ls && !found; ls = ls->next) {
565 for (addr = ls->addrs; addr && !found; addr = addr->next) {
566 if (apr_sockaddr_equal(lr->bind_addr, addr->host_addr) &&
567 lr->bind_addr->port == addr->host_port) {
569 ap_apply_accept_filter(s->process->pool, lr, ls);
575 ap_apply_accept_filter(s->process->pool, lr, s);
579 return num_listeners;
582 AP_DECLARE_NONSTD(void) ap_close_listeners(void)
586 for (lr = ap_listeners; lr; lr = lr->next) {
587 apr_socket_close(lr->sd);
592 AP_DECLARE(void) ap_listen_pre_config(void)
594 old_listeners = ap_listeners;
596 ap_listenbacklog = DEFAULT_LISTENBACKLOG;
600 AP_DECLARE_NONSTD(const char *) ap_set_listener(cmd_parms *cmd, void *dummy,
601 int argc, char *const argv[])
603 char *host, *scope_id, *proto;
606 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
612 if (argc < 1 || argc > 2) {
613 return "Listen requires 1 or 2 arguments.";
616 rv = apr_parse_addr_port(&host, &scope_id, &port, argv[0], cmd->pool);
617 if (rv != APR_SUCCESS) {
618 return "Invalid address or port";
621 if (host && !strcmp(host, "*")) {
626 /* XXX scope id support is useful with link-local IPv6 addresses */
627 return "Scope id is not supported";
631 return "Port must be specified";
642 proto = apr_pstrdup(cmd->pool, argv[1]);
643 ap_str_tolower(proto);
646 return alloc_listener(cmd->server->process, host, port, proto);
649 AP_DECLARE_NONSTD(const char *) ap_set_listenbacklog(cmd_parms *cmd,
654 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
662 return "ListenBacklog must be > 0";
665 ap_listenbacklog = b;
669 AP_DECLARE_NONSTD(const char *) ap_set_send_buffer_size(cmd_parms *cmd,
674 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
680 if (s < 512 && s != 0) {
681 return "SendBufferSize must be >= 512 bytes, or 0 for system default.";
684 send_buffer_size = s;
688 AP_DECLARE_NONSTD(const char *) ap_set_receive_buffer_size(cmd_parms *cmd,
693 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
699 if (s < 512 && s != 0) {
700 return "ReceiveBufferSize must be >= 512 bytes, or 0 for system default.";
703 receive_buffer_size = s;