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