]> granicus.if.org Git - apache/blob - server/listen.c
Update mergeinfo only: r1735891 was merged to 2.4.x in r1787728.
[apache] / server / listen.c
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
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include "apr_network_io.h"
18 #include "apr_strings.h"
19
20 #define APR_WANT_STRFUNC
21 #include "apr_want.h"
22
23 #include "ap_config.h"
24 #include "httpd.h"
25 #include "http_main.h"
26 #include "http_config.h"
27 #include "http_core.h"
28 #include "ap_listen.h"
29 #include "http_log.h"
30 #include "mpm_common.h"
31
32 #include <stdlib.h>
33 #if APR_HAVE_UNISTD_H
34 #include <unistd.h>
35 #endif
36
37 /* we know core's module_index is 0 */
38 #undef APLOG_MODULE_INDEX
39 #define APLOG_MODULE_INDEX AP_CORE_MODULE_INDEX
40
41 AP_DECLARE_DATA ap_listen_rec *ap_listeners = NULL;
42
43 /* Let ap_num_listen_buckets be global so that it can
44  * be printed by ap_log_mpm_common(), but keep the listeners
45  * buckets static since it is used only here to close them
46  * all (including duplicated) with ap_close_listeners().
47  */
48 AP_DECLARE_DATA int ap_num_listen_buckets;
49 static ap_listen_rec **ap_listen_buckets;
50
51 /* Determine once, at runtime, whether or not SO_REUSEPORT
52  * is usable on this platform, and hence whether or not
53  * listeners can be duplicated (if configured).
54  */
55 AP_DECLARE_DATA int ap_have_so_reuseport = -1;
56
57 static ap_listen_rec *old_listeners;
58 static int ap_listenbacklog;
59 static int ap_listencbratio;
60 static int send_buffer_size;
61 static int receive_buffer_size;
62
63 /* TODO: make_sock is just begging and screaming for APR abstraction */
64 static apr_status_t make_sock(apr_pool_t *p, ap_listen_rec *server)
65 {
66     apr_socket_t *s = server->sd;
67     int one = 1;
68 #if APR_HAVE_IPV6
69 #ifdef AP_ENABLE_V4_MAPPED
70     int v6only_setting = 0;
71 #else
72     int v6only_setting = 1;
73 #endif
74 #endif
75     apr_status_t stat;
76
77 #ifndef WIN32
78     stat = apr_socket_opt_set(s, APR_SO_REUSEADDR, one);
79     if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) {
80         ap_log_perror(APLOG_MARK, APLOG_CRIT, stat, p, APLOGNO(00067)
81                       "make_sock: for address %pI, apr_socket_opt_set: (SO_REUSEADDR)",
82                       server->bind_addr);
83         apr_socket_close(s);
84         return stat;
85     }
86 #endif
87
88     stat = apr_socket_opt_set(s, APR_SO_KEEPALIVE, one);
89     if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) {
90         ap_log_perror(APLOG_MARK, APLOG_CRIT, stat, p, APLOGNO(00068)
91                       "make_sock: for address %pI, apr_socket_opt_set: (SO_KEEPALIVE)",
92                       server->bind_addr);
93         apr_socket_close(s);
94         return stat;
95     }
96
97 #if APR_HAVE_IPV6
98     if (server->bind_addr->family == APR_INET6) {
99         stat = apr_socket_opt_set(s, APR_IPV6_V6ONLY, v6only_setting);
100         if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) {
101             ap_log_perror(APLOG_MARK, APLOG_CRIT, stat, p, APLOGNO(00069)
102                           "make_sock: for address %pI, apr_socket_opt_set: "
103                           "(IPV6_V6ONLY)",
104                           server->bind_addr);
105             apr_socket_close(s);
106             return stat;
107         }
108     }
109 #endif
110
111     /*
112      * To send data over high bandwidth-delay connections at full
113      * speed we must force the TCP window to open wide enough to keep the
114      * pipe full.  The default window size on many systems
115      * is only 4kB.  Cross-country WAN connections of 100ms
116      * at 1Mb/s are not impossible for well connected sites.
117      * If we assume 100ms cross-country latency,
118      * a 4kB buffer limits throughput to 40kB/s.
119      *
120      * To avoid this problem I've added the SendBufferSize directive
121      * to allow the web master to configure send buffer size.
122      *
123      * The trade-off of larger buffers is that more kernel memory
124      * is consumed.  YMMV, know your customers and your network!
125      *
126      * -John Heidemann <johnh@isi.edu> 25-Oct-96
127      *
128      * If no size is specified, use the kernel default.
129      */
130     if (send_buffer_size) {
131         stat = apr_socket_opt_set(s, APR_SO_SNDBUF,  send_buffer_size);
132         if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) {
133             ap_log_perror(APLOG_MARK, APLOG_WARNING, stat, p, APLOGNO(00070)
134                           "make_sock: failed to set SendBufferSize for "
135                           "address %pI, using default",
136                           server->bind_addr);
137             /* not a fatal error */
138         }
139     }
140     if (receive_buffer_size) {
141         stat = apr_socket_opt_set(s, APR_SO_RCVBUF, receive_buffer_size);
142         if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) {
143             ap_log_perror(APLOG_MARK, APLOG_WARNING, stat, p, APLOGNO(00071)
144                           "make_sock: failed to set ReceiveBufferSize for "
145                           "address %pI, using default",
146                           server->bind_addr);
147             /* not a fatal error */
148         }
149     }
150
151 #if APR_TCP_NODELAY_INHERITED
152     ap_sock_disable_nagle(s);
153 #endif
154
155 #if defined(SO_REUSEPORT)
156     if (ap_have_so_reuseport && ap_listencbratio > 0) {
157         int thesock;
158         apr_os_sock_get(&thesock, s);
159         if (setsockopt(thesock, SOL_SOCKET, SO_REUSEPORT,
160                        (void *)&one, sizeof(int)) < 0) {
161             stat = apr_get_netos_error();
162             ap_log_perror(APLOG_MARK, APLOG_CRIT, stat, p, APLOGNO(02638)
163                           "make_sock: for address %pI, apr_socket_opt_set: "
164                           "(SO_REUSEPORT)",
165                           server->bind_addr);
166             apr_socket_close(s);
167             return stat;
168         }
169     }
170 #endif
171
172     if ((stat = apr_socket_bind(s, server->bind_addr)) != APR_SUCCESS) {
173         ap_log_perror(APLOG_MARK, APLOG_STARTUP|APLOG_CRIT, stat, p, APLOGNO(00072)
174                       "make_sock: could not bind to address %pI",
175                       server->bind_addr);
176         apr_socket_close(s);
177         return stat;
178     }
179
180     if ((stat = apr_socket_listen(s, ap_listenbacklog)) != APR_SUCCESS) {
181         ap_log_perror(APLOG_MARK, APLOG_STARTUP|APLOG_ERR, stat, p, APLOGNO(00073)
182                       "make_sock: unable to listen for connections "
183                       "on address %pI",
184                       server->bind_addr);
185         apr_socket_close(s);
186         return stat;
187     }
188
189 #ifdef WIN32
190     /* I seriously doubt that this would work on Unix; I have doubts that
191      * it entirely solves the problem on Win32.  However, since setting
192      * reuseaddr on the listener -prior- to binding the socket has allowed
193      * us to attach to the same port as an already running instance of
194      * Apache, or even another web server, we cannot identify that this
195      * port was exclusively granted to this instance of Apache.
196      *
197      * So set reuseaddr, but do not attempt to do so until we have the
198      * parent listeners successfully bound.
199      */
200     stat = apr_socket_opt_set(s, APR_SO_REUSEADDR, one);
201     if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) {
202         ap_log_perror(APLOG_MARK, APLOG_CRIT, stat, p, APLOGNO(00074)
203                     "make_sock: for address %pI, apr_socket_opt_set: (SO_REUSEADDR)",
204                      server->bind_addr);
205         apr_socket_close(s);
206         return stat;
207     }
208 #endif
209
210     server->sd = s;
211     server->active = 1;
212
213     server->accept_func = NULL;
214
215     return APR_SUCCESS;
216 }
217
218 static const char* find_accf_name(server_rec *s, const char *proto)
219 {
220     const char* accf;
221     core_server_config *conf = ap_get_core_module_config(s->module_config);
222     if (!proto) {
223         return NULL;
224     }
225
226     accf = apr_table_get(conf->accf_map, proto);
227
228     if (accf && !strcmp("none", accf)) {
229         return NULL;
230     }
231
232     return accf;
233 }
234
235 static void ap_apply_accept_filter(apr_pool_t *p, ap_listen_rec *lis,
236                                            server_rec *server)
237 {
238     apr_socket_t *s = lis->sd;
239     const char *accf;
240     apr_status_t rv;
241     const char *proto;
242
243     proto = lis->protocol;
244
245     if (!proto) {
246         proto = ap_get_server_protocol(server);
247     }
248
249
250     accf = find_accf_name(server, proto);
251
252     if (accf) {
253 #if APR_HAS_SO_ACCEPTFILTER
254         /* In APR 1.x, the 2nd and 3rd parameters are char * instead of 
255          * const char *, so make a copy of those args here.
256          */
257         rv = apr_socket_accept_filter(s, apr_pstrdup(p, accf),
258                                       apr_pstrdup(p, ""));
259         if (rv != APR_SUCCESS && !APR_STATUS_IS_ENOTIMPL(rv)) {
260             ap_log_perror(APLOG_MARK, APLOG_WARNING, rv, p, APLOGNO(00075)
261                           "Failed to enable the '%s' Accept Filter",
262                           accf);
263         }
264 #else
265         rv = apr_socket_opt_set(s, APR_TCP_DEFER_ACCEPT, 30);
266         if (rv != APR_SUCCESS && !APR_STATUS_IS_ENOTIMPL(rv)) {
267             ap_log_perror(APLOG_MARK, APLOG_WARNING, rv, p, APLOGNO(00076)
268                               "Failed to enable APR_TCP_DEFER_ACCEPT");
269         }
270 #endif
271     }
272 }
273
274 static apr_status_t close_listeners_on_exec(void *v)
275 {
276     ap_close_listeners();
277     return APR_SUCCESS;
278 }
279
280 static int find_listeners(ap_listen_rec **from, ap_listen_rec **to,
281                           const char *addr, apr_port_t port)
282 {
283     int found = 0;
284
285     while (*from) {
286         apr_sockaddr_t *sa = (*from)->bind_addr;
287
288         /* Some listeners are not real so they will not have a bind_addr. */
289         if (sa) {
290             ap_listen_rec *new;
291             apr_port_t oldport;
292
293             oldport = sa->port;
294             /* If both ports are equivalent, then if their names are equivalent,
295              * then we will re-use the existing record.
296              */
297             if (port == oldport &&
298                 ((!addr && !sa->hostname) ||
299                  ((addr && sa->hostname) && !strcmp(sa->hostname, addr)))) {
300                 found = 1;
301                 if (!to) {
302                     break;
303                 }
304                 new = *from;
305                 *from = new->next;
306                 new->next = *to;
307                 *to = new;
308                 continue;
309             }
310         }
311
312         from = &(*from)->next;
313     }
314
315     return found;
316 }
317
318 static const char *alloc_listener(process_rec *process, const char *addr,
319                                   apr_port_t port, const char* proto,
320                                   void *slave)
321 {
322     ap_listen_rec *last;
323     apr_status_t status;
324     apr_sockaddr_t *sa;
325
326     /* see if we've got a listener for this address:port, which is an error */
327     if (find_listeners(&ap_listeners, NULL, addr, port)) {
328         return "Cannot define multiple Listeners on the same IP:port";
329     }
330
331     /* see if we've got an old listener for this address:port */
332     if (find_listeners(&old_listeners, &ap_listeners, addr, port)) {
333         if (ap_listeners->slave != slave) {
334             return "Cannot define a slave on the same IP:port as a Listener";
335         }
336         return NULL;
337     }
338
339     if ((status = apr_sockaddr_info_get(&sa, addr, APR_UNSPEC, port, 0,
340                                         process->pool))
341         != APR_SUCCESS) {
342         ap_log_perror(APLOG_MARK, APLOG_CRIT, status, process->pool, APLOGNO(00077)
343                       "alloc_listener: failed to set up sockaddr for %s",
344                       addr);
345         return "Listen setup failed";
346     }
347
348     /* Initialize to our last configured ap_listener. */
349     last = ap_listeners;
350     while (last && last->next) {
351         last = last->next;
352     }
353
354     while (sa) {
355         ap_listen_rec *new;
356
357         /* this has to survive restarts */
358         new = apr_palloc(process->pool, sizeof(ap_listen_rec));
359         new->active = 0;
360         new->next = 0;
361         new->bind_addr = sa;
362         new->protocol = apr_pstrdup(process->pool, proto);
363
364         /* Go to the next sockaddr. */
365         sa = sa->next;
366
367         status = apr_socket_create(&new->sd, new->bind_addr->family,
368                                     SOCK_STREAM, 0, process->pool);
369
370 #if APR_HAVE_IPV6
371         /* What could happen is that we got an IPv6 address, but this system
372          * doesn't actually support IPv6.  Try the next address.
373          */
374         if (status != APR_SUCCESS && !addr &&
375             new->bind_addr->family == APR_INET6) {
376             continue;
377         }
378 #endif
379         if (status != APR_SUCCESS) {
380             ap_log_perror(APLOG_MARK, APLOG_CRIT, status, process->pool, APLOGNO(00078)
381                           "alloc_listener: failed to get a socket for %s",
382                           addr);
383             return "Listen setup failed";
384         }
385
386         /* We need to preserve the order returned by getaddrinfo() */
387         if (last == NULL) {
388             ap_listeners = last = new;
389         } else {
390             last->next = new;
391             last = new;
392         }
393         new->slave = slave;
394     }
395
396     return NULL;
397 }
398 /* Evaluates to true if the (apr_sockaddr_t *) addr argument is the
399  * IPv4 match-any-address, 0.0.0.0. */
400 #define IS_INADDR_ANY(addr) ((addr)->family == APR_INET \
401                              && (addr)->sa.sin.sin_addr.s_addr == INADDR_ANY)
402
403 /* Evaluates to true if the (apr_sockaddr_t *) addr argument is the
404  * IPv6 match-any-address, [::]. */
405 #define IS_IN6ADDR_ANY(addr) ((addr)->family == APR_INET6 \
406                               && IN6_IS_ADDR_UNSPECIFIED(&(addr)->sa.sin6.sin6_addr))
407
408 /**
409  * Create, open, listen, and bind all sockets.
410  * @param process The process record for the currently running server
411  * @return The number of open sockets
412  */
413 static int open_listeners(apr_pool_t *pool)
414 {
415     ap_listen_rec *lr;
416     ap_listen_rec *next;
417     ap_listen_rec *previous;
418     int num_open;
419     const char *userdata_key = "ap_open_listeners";
420     void *data;
421 #if AP_NONBLOCK_WHEN_MULTI_LISTEN
422     int use_nonblock;
423 #endif
424
425     /* Don't allocate a default listener.  If we need to listen to a
426      * port, then the user needs to have a Listen directive in their
427      * config file.
428      */
429     num_open = 0;
430     previous = NULL;
431     for (lr = ap_listeners; lr; previous = lr, lr = lr->next) {
432         if (lr->active) {
433             ++num_open;
434         }
435         else {
436 #if APR_HAVE_IPV6
437             ap_listen_rec *cur;
438             int v6only_setting;
439             int skip = 0;
440
441             /* If we have the unspecified IPv4 address (0.0.0.0) and
442              * the unspecified IPv6 address (::) is next, we need to
443              * swap the order of these in the list. We always try to
444              * bind to IPv6 first, then IPv4, since an IPv6 socket
445              * might be able to receive IPv4 packets if V6ONLY is not
446              * enabled, but never the other way around.
447              * Note: In some configurations, the unspecified IPv6 address
448              * could be even later in the list.  This logic only corrects
449              * the situation where it is next in the list, such as when
450              * apr_sockaddr_info_get() returns an IPv4 and an IPv6 address,
451              * in that order.
452              */
453             if (lr->next != NULL
454                 && IS_INADDR_ANY(lr->bind_addr)
455                 && lr->bind_addr->port == lr->next->bind_addr->port
456                 && IS_IN6ADDR_ANY(lr->next->bind_addr)) {
457                 /* Exchange lr and lr->next */
458                 next = lr->next;
459                 lr->next = next->next;
460                 next->next = lr;
461                 if (previous) {
462                     previous->next = next;
463                 }
464                 else {
465                     ap_listeners = next;
466                 }
467                 lr = next;
468             }
469
470             /* If we are trying to bind to 0.0.0.0 and a previous listener
471              * was :: on the same port and in turn that socket does not have
472              * the IPV6_V6ONLY flag set; we must skip the current attempt to
473              * listen (which would generate an error). IPv4 will be handled
474              * on the established IPv6 socket.
475              */
476             if (IS_INADDR_ANY(lr->bind_addr) && previous) {
477                 for (cur = ap_listeners; cur != lr; cur = cur->next) {
478                     if (lr->bind_addr->port == cur->bind_addr->port
479                         && IS_IN6ADDR_ANY(cur->bind_addr)
480                         && apr_socket_opt_get(cur->sd, APR_IPV6_V6ONLY,
481                                               &v6only_setting) == APR_SUCCESS
482                         && v6only_setting == 0) {
483
484                         /* Remove the current listener from the list */
485                         previous->next = lr->next;
486                         lr = previous; /* maintain current value of previous after
487                                         * post-loop expression is evaluated
488                                         */
489                         skip = 1;
490                         break;
491                     }
492                 }
493                 if (skip) {
494                     continue;
495                 }
496             }
497 #endif
498             if (make_sock(pool, lr) == APR_SUCCESS) {
499                 ++num_open;
500             }
501             else {
502 #if APR_HAVE_IPV6
503                 /* If we tried to bind to ::, and the next listener is
504                  * on 0.0.0.0 with the same port, don't give a fatal
505                  * error. The user will still get a warning from make_sock
506                  * though.
507                  */
508                 if (lr->next != NULL
509                     && IS_IN6ADDR_ANY(lr->bind_addr)
510                     && lr->bind_addr->port == lr->next->bind_addr->port
511                     && IS_INADDR_ANY(lr->next->bind_addr)) {
512
513                     /* Remove the current listener from the list */
514                     if (previous) {
515                         previous->next = lr->next;
516                     }
517                     else {
518                         ap_listeners = lr->next;
519                     }
520
521                     /* Although we've removed ourselves from the list,
522                      * we need to make sure that the next iteration won't
523                      * consider "previous" a working IPv6 '::' socket.
524                      * Changing the family is enough to make sure the
525                      * conditions before make_sock() fail.
526                      */
527                     lr->bind_addr->family = AF_INET;
528
529                     continue;
530                 }
531 #endif
532                 /* fatal error */
533                 return -1;
534             }
535         }
536     }
537
538     /* close the old listeners */
539     ap_close_listeners_ex(old_listeners);
540     old_listeners = NULL;
541
542 #if AP_NONBLOCK_WHEN_MULTI_LISTEN
543     /* if multiple listening sockets, make them non-blocking so that
544      * if select()/poll() reports readability for a reset connection that
545      * is already forgotten about by the time we call accept, we won't
546      * be hung until another connection arrives on that port
547      */
548     use_nonblock = (ap_listeners && ap_listeners->next);
549     for (lr = ap_listeners; lr; lr = lr->next) {
550         apr_status_t status;
551
552         status = apr_socket_opt_set(lr->sd, APR_SO_NONBLOCK, use_nonblock);
553         if (status != APR_SUCCESS) {
554             ap_log_perror(APLOG_MARK, APLOG_STARTUP|APLOG_ERR, status, pool, APLOGNO(00079)
555                           "unable to control socket non-blocking status");
556             return -1;
557         }
558     }
559 #endif /* AP_NONBLOCK_WHEN_MULTI_LISTEN */
560
561     /* we come through here on both passes of the open logs phase
562      * only register the cleanup once... otherwise we try to close
563      * listening sockets twice when cleaning up prior to exec
564      */
565     apr_pool_userdata_get(&data, userdata_key, pool);
566     if (!data) {
567         apr_pool_userdata_set((const void *)1, userdata_key,
568                               apr_pool_cleanup_null, pool);
569         apr_pool_cleanup_register(pool, NULL, apr_pool_cleanup_null,
570                                   close_listeners_on_exec);
571     }
572
573     return num_open ? 0 : -1;
574 }
575
576 AP_DECLARE(int) ap_setup_listeners(server_rec *s)
577 {
578     server_rec *ls;
579     server_addr_rec *addr;
580     ap_listen_rec *lr;
581     int num_listeners = 0;
582     const char* proto;
583     int found;
584
585     for (ls = s; ls; ls = ls->next) {
586         proto = ap_get_server_protocol(ls);
587         if (!proto) {
588             found = 0;
589             /* No protocol was set for this vhost,
590              * use the default for this listener.
591              */
592             for (addr = ls->addrs; addr && !found; addr = addr->next) {
593                 for (lr = ap_listeners; lr; lr = lr->next) {
594                     if (apr_sockaddr_equal(lr->bind_addr, addr->host_addr) &&
595                         lr->bind_addr->port == addr->host_port) {
596                         ap_set_server_protocol(ls, lr->protocol);
597                         found = 1;
598                         break;
599                     }
600                 }
601             }
602
603             if (!found) {
604                 /* TODO: set protocol defaults per-Port, eg 25=smtp */
605                 ap_set_server_protocol(ls, "http");
606             }
607         }
608     }
609
610     if (open_listeners(s->process->pool)) {
611         return 0;
612     }
613
614     for (lr = ap_listeners; lr; lr = lr->next) {
615         num_listeners++;
616         found = 0;
617         for (ls = s; ls && !found; ls = ls->next) {
618             for (addr = ls->addrs; addr && !found; addr = addr->next) {
619                 if (apr_sockaddr_equal(lr->bind_addr, addr->host_addr) &&
620                     lr->bind_addr->port == addr->host_port) {
621                     found = 1;
622                     ap_apply_accept_filter(s->process->pool, lr, ls);
623                 }
624             }
625         }
626
627         if (!found) {
628             ap_apply_accept_filter(s->process->pool, lr, s);
629         }
630     }
631
632     return num_listeners;
633 }
634
635 AP_DECLARE(apr_status_t) ap_duplicate_listeners(apr_pool_t *p, server_rec *s,
636                                                 ap_listen_rec ***buckets,
637                                                 int *num_buckets)
638 {
639     static int warn_once;
640     int i;
641     apr_status_t stat;
642     int use_nonblock = 0;
643     ap_listen_rec *lr;
644
645     if (*num_buckets < 1) {
646         *num_buckets = 1;
647         if (ap_listencbratio > 0) {
648 #ifdef _SC_NPROCESSORS_ONLN
649             if (ap_have_so_reuseport) {
650                 int num_online_cores = sysconf(_SC_NPROCESSORS_ONLN),
651                     val = num_online_cores / ap_listencbratio;
652                 if (val > 1) {
653                     *num_buckets = val;
654                 }
655                 ap_log_perror(APLOG_MARK, APLOG_INFO, 0, p, APLOGNO(02819)
656                               "Using %i listeners bucket(s) based on %i "
657                               "online CPU cores and a ratio of %i",
658                               *num_buckets, num_online_cores,
659                               ap_listencbratio);
660             }
661             else
662 #endif
663             if (!warn_once) {
664                 ap_log_perror(APLOG_MARK, APLOG_WARNING, 0, p, APLOGNO(02820)
665                               "ListenCoresBucketsRatio ignored without "
666                               "SO_REUSEPORT and _SC_NPROCESSORS_ONLN "
667                               "support: using a single listeners bucket");
668                 warn_once = 1;
669             }
670         }
671     }
672
673     *buckets = apr_pcalloc(p, *num_buckets * sizeof(ap_listen_rec *));
674     (*buckets)[0] = ap_listeners;
675
676     for (i = 1; i < *num_buckets; i++) {
677         ap_listen_rec *last = NULL;
678         lr = ap_listeners;
679         while (lr) {
680             ap_listen_rec *duplr;
681             char *hostname;
682             apr_port_t port;
683             apr_sockaddr_t *sa;
684             duplr = apr_palloc(p, sizeof(ap_listen_rec));
685             duplr->slave = NULL;
686             duplr->protocol = apr_pstrdup(p, lr->protocol);
687             hostname = apr_pstrdup(p, lr->bind_addr->hostname);
688             port = lr->bind_addr->port;
689             apr_sockaddr_info_get(&sa, hostname, APR_UNSPEC, port, 0, p);
690             duplr->bind_addr = sa;
691             duplr->next = NULL;
692             stat = apr_socket_create(&duplr->sd, duplr->bind_addr->family,
693                                      SOCK_STREAM, 0, p);
694             if (stat != APR_SUCCESS) {
695                 ap_log_perror(APLOG_MARK, APLOG_CRIT, 0, p, APLOGNO(02640)
696                             "ap_duplicate_listeners: for address %pI, "
697                             "cannot duplicate a new socket!",
698                             duplr->bind_addr);
699                 return stat;
700             }
701             make_sock(p, duplr);
702 #if AP_NONBLOCK_WHEN_MULTI_LISTEN
703             use_nonblock = (ap_listeners && ap_listeners->next);
704             stat = apr_socket_opt_set(duplr->sd, APR_SO_NONBLOCK, use_nonblock);
705             if (stat != APR_SUCCESS) {
706                 ap_log_perror(APLOG_MARK, APLOG_CRIT, stat, p, APLOGNO(02641)
707                               "unable to control socket non-blocking status");
708                 return stat;
709             }
710 #endif
711             ap_apply_accept_filter(p, duplr, s);
712
713             if (last == NULL) {
714                 (*buckets)[i] = last = duplr;
715             }
716             else {
717                 last->next = duplr;
718                 last = duplr;
719             }
720             lr = lr->next;
721         }
722     }
723
724     ap_listen_buckets = *buckets;
725     ap_num_listen_buckets = *num_buckets;
726     return APR_SUCCESS;
727 }
728
729 AP_DECLARE_NONSTD(void) ap_close_listeners(void)
730 {
731     int i;
732
733     ap_close_listeners_ex(ap_listeners);
734
735     /* Start from index 1 since either ap_duplicate_listeners()
736      * was called and ap_listen_buckets[0] == ap_listeners, or
737      * it wasn't and ap_num_listen_buckets == 0.
738      */
739     for (i = 1; i < ap_num_listen_buckets; i++) {
740         ap_close_listeners_ex(ap_listen_buckets[i]);
741     }
742 }
743
744 AP_DECLARE_NONSTD(void) ap_close_listeners_ex(ap_listen_rec *listeners)
745 {
746     ap_listen_rec *lr;
747     for (lr = listeners; lr; lr = lr->next) {
748         apr_socket_close(lr->sd);
749         lr->active = 0;
750     }
751 }
752
753 AP_DECLARE_NONSTD(int) ap_close_selected_listeners(ap_slave_t *slave)
754 {
755     ap_listen_rec *lr;
756     int n = 0;
757
758     for (lr = ap_listeners; lr; lr = lr->next) {
759         if (lr->slave != slave) {
760             apr_socket_close(lr->sd);
761             lr->active = 0;
762         }
763         else {
764             ++n;
765         }
766     }
767     return n;
768 }
769
770 AP_DECLARE(void) ap_listen_pre_config(void)
771 {
772     old_listeners = ap_listeners;
773     ap_listeners = NULL;
774     ap_listen_buckets = NULL;
775     ap_num_listen_buckets = 0;
776     ap_listenbacklog = DEFAULT_LISTENBACKLOG;
777     ap_listencbratio = 0;
778
779     /* Check once whether or not SO_REUSEPORT is supported. */
780     if (ap_have_so_reuseport < 0) {
781         /* This is limited to Linux with defined SO_REUSEPORT (ie. 3.9+) for
782          * now since the implementation evenly distributes connections across
783          * all the listening threads/processes.
784          *
785          * *BSDs have SO_REUSEPORT too but with a different semantic: the first
786          * wildcard address bound socket or the last non-wildcard address bound
787          * socket will receive connections (no evenness garantee); the rest of
788          * the sockets bound to the same port will not.
789          * This can't (always) work for httpd.
790          *
791          * TODO: latests DragonFlyBSD's SO_REUSEPORT (seems to?) have the same
792          * semantic as Linux, so we may need HAVE_SO_REUSEPORT available from
793          * configure.in some day.
794          */
795 #if defined(SO_REUSEPORT) && defined(__linux__)
796         apr_socket_t *sock;
797         if (apr_socket_create(&sock, APR_UNSPEC, SOCK_STREAM, 0,
798                               ap_pglobal) == APR_SUCCESS) {
799             int thesock, on = 1;
800             apr_os_sock_get(&thesock, sock);
801             ap_have_so_reuseport = (setsockopt(thesock, SOL_SOCKET,
802                                                SO_REUSEPORT, (void *)&on,
803                                                sizeof(int)) == 0);
804             apr_socket_close(sock);
805         }
806         else
807 #endif
808         ap_have_so_reuseport = 0;
809
810     }
811 }
812
813 AP_DECLARE_NONSTD(const char *) ap_set_listener(cmd_parms *cmd, void *dummy,
814                                                 int argc, char *const argv[])
815 {
816     char *host, *scope_id, *proto;
817     apr_port_t port;
818     apr_status_t rv;
819     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
820
821     if (err != NULL) {
822         return err;
823     }
824
825     if (argc < 1 || argc > 2) {
826         return "Listen requires 1 or 2 arguments.";
827     }
828
829     rv = apr_parse_addr_port(&host, &scope_id, &port, argv[0], cmd->pool);
830     if (rv != APR_SUCCESS) {
831         return "Invalid address or port";
832     }
833
834     if (host && !strcmp(host, "*")) {
835         host = NULL;
836     }
837
838     if (scope_id) {
839         /* XXX scope id support is useful with link-local IPv6 addresses */
840         return "Scope id is not supported";
841     }
842
843     if (!port) {
844         return "Port must be specified";
845     }
846
847     if (argc != 2) {
848         if (port == 443) {
849             proto = "https";
850         } else {
851             proto = "http";
852         }
853     }
854     else {
855         proto = apr_pstrdup(cmd->pool, argv[1]);
856         ap_str_tolower(proto);
857     }
858
859     return alloc_listener(cmd->server->process, host, port, proto, NULL);
860 }
861
862 AP_DECLARE_NONSTD(const char *) ap_set_listenbacklog(cmd_parms *cmd,
863                                                      void *dummy,
864                                                      const char *arg)
865 {
866     int b;
867     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
868
869     if (err != NULL) {
870         return err;
871     }
872
873     b = atoi(arg);
874     if (b < 1) {
875         return "ListenBacklog must be > 0";
876     }
877
878     ap_listenbacklog = b;
879     return NULL;
880 }
881
882 AP_DECLARE_NONSTD(const char *) ap_set_listencbratio(cmd_parms *cmd,
883                                                      void *dummy,
884                                                      const char *arg)
885 {
886     int b;
887     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
888
889     if (err != NULL) {
890         return err;
891     }
892
893     b = atoi(arg);
894     if (b < 1) {
895         return "ListenCoresBucketsRatio must be > 0";
896     }
897
898     ap_listencbratio = b;
899     return NULL;
900 }
901
902 AP_DECLARE_NONSTD(const char *) ap_set_send_buffer_size(cmd_parms *cmd,
903                                                         void *dummy,
904                                                         const char *arg)
905 {
906     int s = atoi(arg);
907     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
908
909     if (err != NULL) {
910         return err;
911     }
912
913     if (s < 512 && s != 0) {
914         return "SendBufferSize must be >= 512 bytes, or 0 for system default.";
915     }
916
917     send_buffer_size = s;
918     return NULL;
919 }
920
921 AP_DECLARE_NONSTD(const char *) ap_set_receive_buffer_size(cmd_parms *cmd,
922                                                            void *dummy,
923                                                            const char *arg)
924 {
925     int s = atoi(arg);
926     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
927
928     if (err != NULL) {
929         return err;
930     }
931
932     if (s < 512 && s != 0) {
933         return "ReceiveBufferSize must be >= 512 bytes, or 0 for system default.";
934     }
935
936     receive_buffer_size = s;
937     return NULL;
938 }