]> granicus.if.org Git - apache/blob - server/listen.c
Properly export ap_listen_* functions.
[apache] / server / listen.c
1 /* Copyright 1999-2004 The Apache Software Foundation
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15
16 #include "apr_network_io.h"
17 #include "apr_strings.h"
18
19 #define APR_WANT_STRFUNC
20 #include "apr_want.h"
21
22 #define CORE_PRIVATE
23 #include "ap_config.h"
24 #include "httpd.h"
25 #include "http_config.h"
26 #include "ap_listen.h"
27 #include "http_log.h"
28 #include "mpm.h"
29 #include "mpm_common.h"
30
31 AP_DECLARE_DATA ap_listen_rec *ap_listeners = NULL;
32
33 static ap_listen_rec *old_listeners;
34 static int ap_listenbacklog;
35 static int send_buffer_size;
36
37 /* TODO: make_sock is just begging and screaming for APR abstraction */
38 static apr_status_t make_sock(apr_pool_t *p, ap_listen_rec *server)
39 {
40     apr_socket_t *s = server->sd;
41     int one = 1;
42 #if APR_HAVE_IPV6
43 #ifdef AP_ENABLE_V4_MAPPED
44     int v6only_setting = 0;
45 #else
46     int v6only_setting = 1;
47 #endif
48 #endif
49     apr_status_t stat;
50
51 #ifndef WIN32
52     stat = apr_socket_opt_set(s, APR_SO_REUSEADDR, one);
53     if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) {
54         ap_log_perror(APLOG_MARK, APLOG_CRIT, stat, p,
55                       "make_sock: for address %pI, apr_socket_opt_set: (SO_REUSEADDR)",
56                       server->bind_addr);
57         apr_socket_close(s);
58         return stat;
59     }
60 #endif
61
62     stat = apr_socket_opt_set(s, APR_SO_KEEPALIVE, one);
63     if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) {
64         ap_log_perror(APLOG_MARK, APLOG_CRIT, stat, p,
65                       "make_sock: for address %pI, apr_socket_opt_set: (SO_KEEPALIVE)",
66                       server->bind_addr);
67         apr_socket_close(s);
68         return stat;
69     }
70
71 #if APR_HAVE_IPV6
72     if (server->bind_addr->family == APR_INET6) {
73         stat = apr_socket_opt_set(s, APR_IPV6_V6ONLY, v6only_setting);
74         if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) {
75             ap_log_perror(APLOG_MARK, APLOG_CRIT, stat, p,
76                           "make_sock: for address %pI, apr_socket_opt_set: "
77                           "(IPV6_V6ONLY)",
78                           server->bind_addr);
79             apr_socket_close(s);
80             return stat;
81         }
82     }
83 #endif
84
85     /*
86      * To send data over high bandwidth-delay connections at full
87      * speed we must force the TCP window to open wide enough to keep the
88      * pipe full.  The default window size on many systems
89      * is only 4kB.  Cross-country WAN connections of 100ms
90      * at 1Mb/s are not impossible for well connected sites.
91      * If we assume 100ms cross-country latency,
92      * a 4kB buffer limits throughput to 40kB/s.
93      *
94      * To avoid this problem I've added the SendBufferSize directive
95      * to allow the web master to configure send buffer size.
96      *
97      * The trade-off of larger buffers is that more kernel memory
98      * is consumed.  YMMV, know your customers and your network!
99      *
100      * -John Heidemann <johnh@isi.edu> 25-Oct-96
101      *
102      * If no size is specified, use the kernel default.
103      */
104     if (send_buffer_size) {
105         stat = apr_socket_opt_set(s, APR_SO_SNDBUF,  send_buffer_size);
106         if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) {
107             ap_log_perror(APLOG_MARK, APLOG_WARNING, stat, p,
108                           "make_sock: failed to set SendBufferSize for "
109                           "address %pI, using default",
110                           server->bind_addr);
111             /* not a fatal error */
112         }
113     }
114
115 #if APR_TCP_NODELAY_INHERITED
116     ap_sock_disable_nagle(s);
117 #endif
118
119     if ((stat = apr_socket_bind(s, server->bind_addr)) != APR_SUCCESS) {
120         ap_log_perror(APLOG_MARK, APLOG_STARTUP|APLOG_CRIT, stat, p,
121                       "make_sock: could not bind to address %pI",
122                       server->bind_addr);
123         apr_socket_close(s);
124         return stat;
125     }
126
127     if ((stat = apr_socket_listen(s, ap_listenbacklog)) != APR_SUCCESS) {
128         ap_log_perror(APLOG_MARK, APLOG_STARTUP|APLOG_ERR, stat, p,
129                       "make_sock: unable to listen for connections "
130                       "on address %pI",
131                       server->bind_addr);
132         apr_socket_close(s);
133         return stat;
134     }
135
136 #ifdef WIN32
137     /* I seriously doubt that this would work on Unix; I have doubts that
138      * it entirely solves the problem on Win32.  However, since setting
139      * reuseaddr on the listener -prior- to binding the socket has allowed
140      * us to attach to the same port as an already running instance of
141      * Apache, or even another web server, we cannot identify that this
142      * port was exclusively granted to this instance of Apache.
143      *
144      * So set reuseaddr, but do not attempt to do so until we have the
145      * parent listeners successfully bound.
146      */
147     stat = apr_socket_opt_set(s, APR_SO_REUSEADDR, one);
148     if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) {
149         ap_log_perror(APLOG_MARK, APLOG_CRIT, stat, p,
150                     "make_sock: for address %pI, apr_socket_opt_set: (SO_REUSEADDR)", 
151                      server->bind_addr);
152         apr_socket_close(s);
153         return stat;
154     }
155 #endif
156
157 #if APR_HAS_SO_ACCEPTFILTER
158 #ifndef ACCEPT_FILTER_NAME
159 #define ACCEPT_FILTER_NAME "httpready"
160 #ifdef __FreeBSD_version
161 #if __FreeBSD_version < 411000 /* httpready broken before 4.1.1 */
162 #undef ACCEPT_FILTER_NAME
163 #define ACCEPT_FILTER_NAME "dataready"
164 #endif
165 #endif
166 #endif
167     apr_socket_accept_filter(s, ACCEPT_FILTER_NAME, "");
168 #endif
169
170     server->sd = s;
171     server->active = 1;
172
173 #ifdef MPM_ACCEPT_FUNC
174     server->accept_func = MPM_ACCEPT_FUNC;
175 #else
176     server->accept_func = NULL;
177 #endif
178
179     return APR_SUCCESS;
180 }
181
182 static apr_status_t close_listeners_on_exec(void *v)
183 {
184     ap_listen_rec *lr;
185
186     for (lr = ap_listeners; lr; lr = lr->next) {
187         apr_socket_close(lr->sd);
188         lr->active = 0;
189     }
190
191     return APR_SUCCESS;
192 }
193
194
195 static const char *alloc_listener(process_rec *process, char *addr, apr_port_t port)
196 {
197     ap_listen_rec **walk, *last;
198     apr_status_t status;
199     apr_sockaddr_t *sa;
200     int found_listener = 0;
201
202     /* see if we've got an old listener for this address:port */
203     for (walk = &old_listeners; *walk;) {
204         sa = (*walk)->bind_addr;
205         /* Some listeners are not real so they will not have a bind_addr. */
206         if (sa) {
207             ap_listen_rec *new;
208             apr_port_t oldport;
209
210             oldport = sa->port;
211             /* If both ports are equivalent, then if their names are equivalent,
212              * then we will re-use the existing record.
213              */
214             if (port == oldport &&
215                 ((!addr && !sa->hostname) ||
216                  ((addr && sa->hostname) && !strcmp(sa->hostname, addr)))) {
217                 new = *walk;
218                 *walk = new->next;
219                 new->next = ap_listeners;
220                 ap_listeners = new;
221                 found_listener = 1;
222                 continue;
223             }
224         }
225
226         walk = &(*walk)->next;
227     }
228
229     if (found_listener) {
230         return NULL;
231     }
232
233     if ((status = apr_sockaddr_info_get(&sa, addr, APR_UNSPEC, port, 0,
234                                         process->pool))
235         != APR_SUCCESS) {
236         ap_log_perror(APLOG_MARK, APLOG_CRIT, status, process->pool,
237                       "alloc_listener: failed to set up sockaddr for %s",
238                       addr);
239         return "Listen setup failed";
240     }
241
242     /* Initialize to our last configured ap_listener. */
243     last = ap_listeners;
244     while (last && last->next) {
245         last = last->next;
246     }
247
248     while (sa) {
249         ap_listen_rec *new;
250
251         /* this has to survive restarts */
252         new = apr_palloc(process->pool, sizeof(ap_listen_rec));
253         new->active = 0;
254         new->next = 0;
255         new->bind_addr = sa;
256
257         /* Go to the next sockaddr. */
258         sa = sa->next;
259
260         status = apr_socket_create(&new->sd, new->bind_addr->family,
261                                     SOCK_STREAM, 0, process->pool);
262
263 #if APR_HAVE_IPV6
264         /* What could happen is that we got an IPv6 address, but this system
265          * doesn't actually support IPv6.  Try the next address.
266          */
267         if (status != APR_SUCCESS && !addr &&
268             new->bind_addr->family == APR_INET6) {
269             continue;
270         }
271 #endif
272         if (status != APR_SUCCESS) {
273             ap_log_perror(APLOG_MARK, APLOG_CRIT, status, process->pool,
274                           "alloc_listener: failed to get a socket for %s",
275                           addr);
276             return "Listen setup failed";
277         }
278
279         /* We need to preserve the order returned by getaddrinfo() */
280         if (last == NULL) {
281             ap_listeners = last = new;
282         } else {
283             last->next = new;
284             last = new;
285         }
286     }
287
288     return NULL;
289 }
290
291 AP_DECLARE(int) ap_listen_open(apr_pool_t *pool, apr_port_t port)
292 {
293     ap_listen_rec *lr;
294     ap_listen_rec *next;
295     ap_listen_rec *previous;
296     int num_open;
297     const char *userdata_key = "ap_listen_open";
298     void *data;
299
300     /* Don't allocate a default listener.  If we need to listen to a
301      * port, then the user needs to have a Listen directive in their
302      * config file.
303      */
304     num_open = 0;
305     previous = NULL;
306     for (lr = ap_listeners; lr; previous = lr, lr = lr->next) {
307         if (lr->active) {
308             ++num_open;
309         }
310         else {
311 #if APR_HAVE_IPV6
312             int v6only_setting;
313             /* If we are trying to bind to 0.0.0.0 and the previous listener
314              * was :: on the same port and in turn that socket does not have
315              * the IPV6_V6ONLY flag set; we must skip the current attempt to
316              * listen (which would generate an error). IPv4 will be handled
317              * on the established IPv6 socket.
318              */
319             if (previous != NULL &&
320                 lr->bind_addr->family == APR_INET &&
321                 lr->bind_addr->sa.sin.sin_addr.s_addr == INADDR_ANY &&
322                 lr->bind_addr->port == previous->bind_addr->port &&
323                 previous->bind_addr->family == APR_INET6 &&
324                 IN6_IS_ADDR_UNSPECIFIED(
325                     &previous->bind_addr->sa.sin6.sin6_addr) &&
326                 apr_socket_opt_get(previous->sd, APR_IPV6_V6ONLY,
327                                    &v6only_setting) == APR_SUCCESS &&
328                 v6only_setting == 0) {
329
330                 /* Remove the current listener from the list */
331                 previous->next = lr->next;
332                 continue;
333             }
334 #endif
335             if (make_sock(pool, lr) == APR_SUCCESS) {
336                 ++num_open;
337                 lr->active = 1;
338             }
339             else {
340 #if APR_HAVE_IPV6
341                 /* If we tried to bind to ::, and the next listener is
342                  * on 0.0.0.0 with the same port, don't give a fatal
343                  * error. The user will still get a warning from make_sock
344                  * though.
345                  */
346                 if (lr->next != NULL && lr->bind_addr->family == APR_INET6 &&
347                     IN6_IS_ADDR_UNSPECIFIED(
348                         &lr->bind_addr->sa.sin6.sin6_addr) &&
349                     lr->bind_addr->port == lr->next->bind_addr->port &&
350                     lr->next->bind_addr->family == APR_INET && 
351                     lr->next->bind_addr->sa.sin.sin_addr.s_addr == INADDR_ANY) {
352
353                     /* Remove the current listener from the list */
354                     if (previous) {
355                         previous->next = lr->next;
356                     }
357                     else {
358                         ap_listeners = lr->next;
359                     }
360
361                     /* Although we've removed ourselves from the list,
362                      * we need to make sure that the next iteration won't
363                      * consider "previous" a working IPv6 '::' socket.
364                      * Changing the family is enough to make sure the
365                      * conditions before make_sock() fail.
366                      */
367                     lr->bind_addr->family = AF_INET;
368
369                     continue;
370                 }
371 #endif
372                 /* fatal error */
373                 return -1;
374             }
375         }
376     }
377
378     /* close the old listeners */
379     for (lr = old_listeners; lr; lr = next) {
380         apr_socket_close(lr->sd);
381         lr->active = 0;
382         next = lr->next;
383     }
384     old_listeners = NULL;
385
386 #if AP_NONBLOCK_WHEN_MULTI_LISTEN
387     /* if multiple listening sockets, make them non-blocking so that
388      * if select()/poll() reports readability for a reset connection that
389      * is already forgotten about by the time we call accept, we won't
390      * be hung until another connection arrives on that port
391      */
392     if (ap_listeners && ap_listeners->next) {
393         for (lr = ap_listeners; lr; lr = lr->next) {
394             apr_status_t status;
395
396             status = apr_socket_opt_set(lr->sd, APR_SO_NONBLOCK, 1);
397             if (status != APR_SUCCESS) {
398                 ap_log_perror(APLOG_MARK, APLOG_STARTUP|APLOG_ERR, status, pool,
399                               "ap_listen_open: unable to make socket non-blocking");
400                 return -1;
401             }
402         }
403     }
404 #endif /* AP_NONBLOCK_WHEN_MULTI_LISTEN */
405
406     /* we come through here on both passes of the open logs phase
407      * only register the cleanup once... otherwise we try to close
408      * listening sockets twice when cleaning up prior to exec
409      */
410     apr_pool_userdata_get(&data, userdata_key, pool);
411     if (!data) {
412         apr_pool_userdata_set((const void *)1, userdata_key,
413                               apr_pool_cleanup_null, pool);
414         apr_pool_cleanup_register(pool, NULL, apr_pool_cleanup_null,
415                                   close_listeners_on_exec);
416     }
417
418     return num_open ? 0 : -1;
419 }
420
421 AP_DECLARE(int) ap_setup_listeners(server_rec *s)
422 {
423     ap_listen_rec *lr;
424     int num_listeners = 0;
425
426     if (ap_listen_open(s->process->pool, s->port)) {
427        return 0;
428     }
429
430     for (lr = ap_listeners; lr; lr = lr->next) {
431         num_listeners++;
432     }
433
434     return num_listeners;
435 }
436
437 AP_DECLARE(void) ap_listen_pre_config(void)
438 {
439     old_listeners = ap_listeners;
440     ap_listeners = NULL;
441     ap_listenbacklog = DEFAULT_LISTENBACKLOG;
442 }
443
444
445 AP_DECLARE(const char *) ap_set_listener(cmd_parms *cmd, void *dummy, const char *ips)
446 {
447     char *host, *scope_id;
448     apr_port_t port;
449     apr_status_t rv;
450     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
451
452     if (err != NULL) {
453         return err;
454     }
455
456     rv = apr_parse_addr_port(&host, &scope_id, &port, ips, cmd->pool);
457     if (rv != APR_SUCCESS) {
458         return "Invalid address or port";
459     }
460
461     if (host && !strcmp(host, "*")) {
462         host = NULL;
463     }
464
465     if (scope_id) {
466         /* XXX scope id support is useful with link-local IPv6 addresses */
467         return "Scope id is not supported";
468     }
469
470     if (!port) {
471         return "Port must be specified";
472     }
473
474     return alloc_listener(cmd->server->process, host, port);
475 }
476
477 AP_DECLARE(const char *) ap_set_listenbacklog(cmd_parms *cmd, void *dummy, const char *arg)
478 {
479     int b;
480     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
481
482     if (err != NULL) {
483         return err;
484     }
485
486     b = atoi(arg);
487     if (b < 1) {
488         return "ListenBacklog must be > 0";
489     }
490
491     ap_listenbacklog = b;
492     return NULL;
493 }
494
495 AP_DECLARE(const char *) ap_set_send_buffer_size(cmd_parms *cmd, void *dummy,
496                                     const char *arg)
497 {
498     int s = atoi(arg);
499     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
500
501     if (err != NULL) {
502         return err;
503     }
504
505     if (s < 512 && s != 0) {
506         return "SendBufferSize must be >= 512 bytes, or 0 for system default.";
507     }
508
509     send_buffer_size = s;
510     return NULL;
511 }