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
24
#include "ap_config.h"
26
#include "http_config.h"
27
#include "http_core.h"
28
#include "ap_listen.h"
31
#include "mpm_common.h"
33
AP_DECLARE_DATA ap_listen_rec *ap_listeners = NULL;
35
static ap_listen_rec *old_listeners;
36
static int ap_listenbacklog;
37
static int send_buffer_size;
38
static int receive_buffer_size;
40
/* TODO: make_sock is just begging and screaming for APR abstraction */
41
static apr_status_t make_sock(apr_pool_t *p, ap_listen_rec *server)
43
apr_socket_t *s = server->sd;
46
#ifdef AP_ENABLE_V4_MAPPED
47
int v6only_setting = 0;
49
int v6only_setting = 1;
55
stat = apr_socket_opt_set(s, APR_SO_REUSEADDR, one);
56
if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) {
57
ap_log_perror(APLOG_MARK, APLOG_CRIT, stat, p,
58
"make_sock: for address %pI, apr_socket_opt_set: (SO_REUSEADDR)",
65
stat = apr_socket_opt_set(s, APR_SO_KEEPALIVE, one);
66
if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) {
67
ap_log_perror(APLOG_MARK, APLOG_CRIT, stat, p,
68
"make_sock: for address %pI, apr_socket_opt_set: (SO_KEEPALIVE)",
75
if (server->bind_addr->family == APR_INET6) {
76
stat = apr_socket_opt_set(s, APR_IPV6_V6ONLY, v6only_setting);
77
if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) {
78
ap_log_perror(APLOG_MARK, APLOG_CRIT, stat, p,
79
"make_sock: for address %pI, apr_socket_opt_set: "
89
* To send data over high bandwidth-delay connections at full
90
* speed we must force the TCP window to open wide enough to keep the
91
* pipe full. The default window size on many systems
92
* is only 4kB. Cross-country WAN connections of 100ms
93
* at 1Mb/s are not impossible for well connected sites.
94
* If we assume 100ms cross-country latency,
95
* a 4kB buffer limits throughput to 40kB/s.
97
* To avoid this problem I've added the SendBufferSize directive
98
* to allow the web master to configure send buffer size.
100
* The trade-off of larger buffers is that more kernel memory
101
* is consumed. YMMV, know your customers and your network!
103
* -John Heidemann <johnh@isi.edu> 25-Oct-96
105
* If no size is specified, use the kernel default.
107
if (send_buffer_size) {
108
stat = apr_socket_opt_set(s, APR_SO_SNDBUF, send_buffer_size);
109
if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) {
110
ap_log_perror(APLOG_MARK, APLOG_WARNING, stat, p,
111
"make_sock: failed to set SendBufferSize for "
112
"address %pI, using default",
114
/* not a fatal error */
117
if (receive_buffer_size) {
118
stat = apr_socket_opt_set(s, APR_SO_RCVBUF, receive_buffer_size);
119
if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) {
120
ap_log_perror(APLOG_MARK, APLOG_WARNING, stat, p,
121
"make_sock: failed to set ReceiveBufferSize for "
122
"address %pI, using default",
124
/* not a fatal error */
128
#if APR_TCP_NODELAY_INHERITED
129
ap_sock_disable_nagle(s);
132
if ((stat = apr_socket_bind(s, server->bind_addr)) != APR_SUCCESS) {
133
ap_log_perror(APLOG_MARK, APLOG_STARTUP|APLOG_CRIT, stat, p,
134
"make_sock: could not bind to address %pI",
140
if ((stat = apr_socket_listen(s, ap_listenbacklog)) != APR_SUCCESS) {
141
ap_log_perror(APLOG_MARK, APLOG_STARTUP|APLOG_ERR, stat, p,
142
"make_sock: unable to listen for connections "
150
/* I seriously doubt that this would work on Unix; I have doubts that
151
* it entirely solves the problem on Win32. However, since setting
152
* reuseaddr on the listener -prior- to binding the socket has allowed
153
* us to attach to the same port as an already running instance of
154
* Apache, or even another web server, we cannot identify that this
155
* port was exclusively granted to this instance of Apache.
157
* So set reuseaddr, but do not attempt to do so until we have the
158
* parent listeners successfully bound.
160
stat = apr_socket_opt_set(s, APR_SO_REUSEADDR, one);
161
if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) {
162
ap_log_perror(APLOG_MARK, APLOG_CRIT, stat, p,
163
"make_sock: for address %pI, apr_socket_opt_set: (SO_REUSEADDR)",
173
#ifdef MPM_ACCEPT_FUNC
174
server->accept_func = MPM_ACCEPT_FUNC;
176
server->accept_func = NULL;
182
static const char* find_accf_name(server_rec *s, const char *proto)
185
core_server_config *conf = ap_get_module_config(s->module_config,
191
accf = apr_table_get(conf->accf_map, proto);
193
if (accf && !strcmp("none", accf)) {
200
static void ap_apply_accept_filter(apr_pool_t *p, ap_listen_rec *lis,
203
apr_socket_t *s = lis->sd;
208
proto = lis->protocol;
211
proto = ap_get_server_protocol(server);
215
accf = find_accf_name(server, proto);
218
#if APR_HAS_SO_ACCEPTFILTER
219
rv = apr_socket_accept_filter(s, apr_pstrdup(p, accf),
221
if (rv != APR_SUCCESS && !APR_STATUS_IS_ENOTIMPL(rv)) {
222
ap_log_perror(APLOG_MARK, APLOG_WARNING, rv, p,
223
"Failed to enable the '%s' Accept Filter",
227
#ifdef APR_TCP_DEFER_ACCEPT
228
rv = apr_socket_opt_set(s, APR_TCP_DEFER_ACCEPT, 1);
229
if (rv != APR_SUCCESS && !APR_STATUS_IS_ENOTIMPL(rv)) {
230
ap_log_perror(APLOG_MARK, APLOG_WARNING, rv, p,
231
"Failed to enable APR_TCP_DEFER_ACCEPT");
238
static apr_status_t close_listeners_on_exec(void *v)
240
ap_close_listeners();
244
static const char *alloc_listener(process_rec *process, char *addr,
245
apr_port_t port, const char* proto)
247
ap_listen_rec **walk, *last;
250
int found_listener = 0;
252
/* see if we've got an old listener for this address:port */
253
for (walk = &old_listeners; *walk;) {
254
sa = (*walk)->bind_addr;
255
/* Some listeners are not real so they will not have a bind_addr. */
261
/* If both ports are equivalent, then if their names are equivalent,
262
* then we will re-use the existing record.
264
if (port == oldport &&
265
((!addr && !sa->hostname) ||
266
((addr && sa->hostname) && !strcmp(sa->hostname, addr)))) {
269
new->next = ap_listeners;
276
walk = &(*walk)->next;
279
if (found_listener) {
283
if ((status = apr_sockaddr_info_get(&sa, addr, APR_UNSPEC, port, 0,
286
ap_log_perror(APLOG_MARK, APLOG_CRIT, status, process->pool,
287
"alloc_listener: failed to set up sockaddr for %s",
289
return "Listen setup failed";
292
/* Initialize to our last configured ap_listener. */
294
while (last && last->next) {
301
/* this has to survive restarts */
302
new = apr_palloc(process->pool, sizeof(ap_listen_rec));
306
new->protocol = apr_pstrdup(process->pool, proto);
308
/* Go to the next sockaddr. */
311
status = apr_socket_create(&new->sd, new->bind_addr->family,
312
SOCK_STREAM, 0, process->pool);
315
/* What could happen is that we got an IPv6 address, but this system
316
* doesn't actually support IPv6. Try the next address.
318
if (status != APR_SUCCESS && !addr &&
319
new->bind_addr->family == APR_INET6) {
323
if (status != APR_SUCCESS) {
324
ap_log_perror(APLOG_MARK, APLOG_CRIT, status, process->pool,
325
"alloc_listener: failed to get a socket for %s",
327
return "Listen setup failed";
330
/* We need to preserve the order returned by getaddrinfo() */
332
ap_listeners = last = new;
341
/* Evaluates to true if the (apr_sockaddr_t *) addr argument is the
342
* IPv4 match-any-address, 0.0.0.0. */
343
#define IS_INADDR_ANY(addr) ((addr)->family == APR_INET \
344
&& (addr)->sa.sin.sin_addr.s_addr == INADDR_ANY)
346
/* Evaluates to true if the (apr_sockaddr_t *) addr argument is the
347
* IPv6 match-any-address, [::]. */
348
#define IS_IN6ADDR_ANY(addr) ((addr)->family == APR_INET6 \
349
&& IN6_IS_ADDR_UNSPECIFIED(&(addr)->sa.sin6.sin6_addr))
352
* Create, open, listen, and bind all sockets.
353
* @param process The process record for the currently running server
354
* @return The number of open sockets
356
static int open_listeners(apr_pool_t *pool)
360
ap_listen_rec *previous;
362
const char *userdata_key = "ap_open_listeners";
365
/* Don't allocate a default listener. If we need to listen to a
366
* port, then the user needs to have a Listen directive in their
371
for (lr = ap_listeners; lr; previous = lr, lr = lr->next) {
379
/* If we have the unspecified IPv4 address (0.0.0.0) and
380
* the unspecified IPv6 address (::) is next, we need to
381
* swap the order of these in the list. We always try to
382
* bind to IPv6 first, then IPv4, since an IPv6 socket
383
* might be able to receive IPv4 packets if V6ONLY is not
384
* enabled, but never the other way around. */
386
&& IS_INADDR_ANY(lr->bind_addr)
387
&& lr->bind_addr->port == lr->next->bind_addr->port
388
&& IS_IN6ADDR_ANY(lr->next->bind_addr)) {
389
/* Exchange lr and lr->next */
391
lr->next = next->next;
394
previous->next = next;
402
/* If we are trying to bind to 0.0.0.0 and the previous listener
403
* was :: on the same port and in turn that socket does not have
404
* the IPV6_V6ONLY flag set; we must skip the current attempt to
405
* listen (which would generate an error). IPv4 will be handled
406
* on the established IPv6 socket.
409
&& IS_INADDR_ANY(lr->bind_addr)
410
&& lr->bind_addr->port == previous->bind_addr->port
411
&& IS_IN6ADDR_ANY(previous->bind_addr)
412
&& apr_socket_opt_get(previous->sd, APR_IPV6_V6ONLY,
413
&v6only_setting) == APR_SUCCESS
414
&& v6only_setting == 0) {
416
/* Remove the current listener from the list */
417
previous->next = lr->next;
421
if (make_sock(pool, lr) == APR_SUCCESS) {
427
/* If we tried to bind to ::, and the next listener is
428
* on 0.0.0.0 with the same port, don't give a fatal
429
* error. The user will still get a warning from make_sock
433
&& IS_IN6ADDR_ANY(lr->bind_addr)
434
&& lr->bind_addr->port == lr->next->bind_addr->port
435
&& IS_INADDR_ANY(lr->next->bind_addr)) {
437
/* Remove the current listener from the list */
439
previous->next = lr->next;
442
ap_listeners = lr->next;
445
/* Although we've removed ourselves from the list,
446
* we need to make sure that the next iteration won't
447
* consider "previous" a working IPv6 '::' socket.
448
* Changing the family is enough to make sure the
449
* conditions before make_sock() fail.
451
lr->bind_addr->family = AF_INET;
462
/* close the old listeners */
463
for (lr = old_listeners; lr; lr = next) {
464
apr_socket_close(lr->sd);
468
old_listeners = NULL;
470
#if AP_NONBLOCK_WHEN_MULTI_LISTEN
471
/* if multiple listening sockets, make them non-blocking so that
472
* if select()/poll() reports readability for a reset connection that
473
* is already forgotten about by the time we call accept, we won't
474
* be hung until another connection arrives on that port
476
if (ap_listeners && ap_listeners->next) {
477
for (lr = ap_listeners; lr; lr = lr->next) {
480
status = apr_socket_opt_set(lr->sd, APR_SO_NONBLOCK, 1);
481
if (status != APR_SUCCESS) {
482
ap_log_perror(APLOG_MARK, APLOG_STARTUP|APLOG_ERR, status, pool,
483
"unable to make listening socket non-blocking");
488
#endif /* AP_NONBLOCK_WHEN_MULTI_LISTEN */
490
/* we come through here on both passes of the open logs phase
491
* only register the cleanup once... otherwise we try to close
492
* listening sockets twice when cleaning up prior to exec
494
apr_pool_userdata_get(&data, userdata_key, pool);
496
apr_pool_userdata_set((const void *)1, userdata_key,
497
apr_pool_cleanup_null, pool);
498
apr_pool_cleanup_register(pool, NULL, apr_pool_cleanup_null,
499
close_listeners_on_exec);
502
return num_open ? 0 : -1;
505
AP_DECLARE(int) ap_setup_listeners(server_rec *s)
508
server_addr_rec *addr;
510
int num_listeners = 0;
514
for (ls = s; ls; ls = ls->next) {
515
proto = ap_get_server_protocol(ls);
518
/* No protocol was set for this vhost,
519
* use the default for this listener.
521
for (addr = ls->addrs; addr && !found; addr = addr->next) {
522
for (lr = ap_listeners; lr; lr = lr->next) {
523
if (apr_sockaddr_equal(lr->bind_addr, addr->host_addr) &&
524
lr->bind_addr->port == addr->host_port) {
525
ap_set_server_protocol(ls, lr->protocol);
533
/* TODO: set protocol defaults per-Port, eg 25=smtp */
534
ap_set_server_protocol(ls, "http");
539
if (open_listeners(s->process->pool)) {
543
for (lr = ap_listeners; lr; lr = lr->next) {
546
for (ls = s; ls && !found; ls = ls->next) {
547
for (addr = ls->addrs; addr && !found; addr = addr->next) {
548
if (apr_sockaddr_equal(lr->bind_addr, addr->host_addr) &&
549
lr->bind_addr->port == addr->host_port) {
551
ap_apply_accept_filter(s->process->pool, lr, ls);
557
ap_apply_accept_filter(s->process->pool, lr, s);
561
return num_listeners;
564
AP_DECLARE_NONSTD(void) ap_close_listeners(void)
568
for (lr = ap_listeners; lr; lr = lr->next) {
569
apr_socket_close(lr->sd);
574
AP_DECLARE(void) ap_listen_pre_config(void)
576
old_listeners = ap_listeners;
578
ap_listenbacklog = DEFAULT_LISTENBACKLOG;
582
AP_DECLARE_NONSTD(const char *) ap_set_listener(cmd_parms *cmd, void *dummy,
583
int argc, char *const argv[])
585
char *host, *scope_id, *proto;
588
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
594
if (argc < 1 || argc > 2) {
595
return "Listen requires 1 or 2 arguments.";
598
rv = apr_parse_addr_port(&host, &scope_id, &port, argv[0], cmd->pool);
599
if (rv != APR_SUCCESS) {
600
return "Invalid address or port";
603
if (host && !strcmp(host, "*")) {
608
/* XXX scope id support is useful with link-local IPv6 addresses */
609
return "Scope id is not supported";
613
return "Port must be specified";
620
proto = apr_pstrdup(cmd->pool, argv[1]);
621
ap_str_tolower(proto);
624
return alloc_listener(cmd->server->process, host, port, proto);
627
AP_DECLARE_NONSTD(const char *) ap_set_listenbacklog(cmd_parms *cmd,
632
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
640
return "ListenBacklog must be > 0";
643
ap_listenbacklog = b;
647
AP_DECLARE_NONSTD(const char *) ap_set_send_buffer_size(cmd_parms *cmd,
652
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
658
if (s < 512 && s != 0) {
659
return "SendBufferSize must be >= 512 bytes, or 0 for system default.";
662
send_buffer_size = s;
666
AP_DECLARE_NONSTD(const char *) ap_set_receive_buffer_size(cmd_parms *cmd,
671
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
677
if (s < 512 && s != 0) {
678
return "ReceiveBufferSize must be >= 512 bytes, or 0 for system default.";
681
receive_buffer_size = s;