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