]> granicus.if.org Git - apache/blobdiff - server/listen.c
Catch up to apr_dbm projects
[apache] / server / listen.c
index fc584742aa45e67b445b8b40ee9c05760123a2ee..8361fb3c35d132f5443886c0bb3746f31b77d0e6 100644 (file)
@@ -1,9 +1,9 @@
-/* Copyright 1999-2005 The Apache Software Foundation or its licensors, as
- * applicable.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
  *
  *     http://www.apache.org/licenses/LICENSE-2.0
  *
 #define APR_WANT_STRFUNC
 #include "apr_want.h"
 
-#define CORE_PRIVATE
 #include "ap_config.h"
 #include "httpd.h"
 #include "http_config.h"
 #include "http_core.h"
 #include "ap_listen.h"
 #include "http_log.h"
-#include "mpm.h"
 #include "mpm_common.h"
 
 AP_DECLARE_DATA ap_listen_rec *ap_listeners = NULL;
@@ -121,7 +119,6 @@ static apr_status_t make_sock(apr_pool_t *p, ap_listen_rec *server)
                           "make_sock: failed to set ReceiveBufferSize for "
                           "address %pI, using default",
                           server->bind_addr);
-            strerror(errno);
             /* not a fatal error */
         }
     }
@@ -161,7 +158,7 @@ static apr_status_t make_sock(apr_pool_t *p, ap_listen_rec *server)
     stat = apr_socket_opt_set(s, APR_SO_REUSEADDR, one);
     if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) {
         ap_log_perror(APLOG_MARK, APLOG_CRIT, stat, p,
-                    "make_sock: for address %pI, apr_socket_opt_set: (SO_REUSEADDR)", 
+                    "make_sock: for address %pI, apr_socket_opt_set: (SO_REUSEADDR)",
                      server->bind_addr);
         apr_socket_close(s);
         return stat;
@@ -171,11 +168,7 @@ static apr_status_t make_sock(apr_pool_t *p, ap_listen_rec *server)
     server->sd = s;
     server->active = 1;
 
-#ifdef MPM_ACCEPT_FUNC
-    server->accept_func = MPM_ACCEPT_FUNC;
-#else
     server->accept_func = NULL;
-#endif
 
     return APR_SUCCESS;
 }
@@ -198,7 +191,7 @@ static const char* find_accf_name(server_rec *s, const char *proto)
     return accf;
 }
 
-static void ap_apply_accept_filter(apr_pool_t *p, ap_listen_rec *lis, 
+static void ap_apply_accept_filter(apr_pool_t *p, ap_listen_rec *lis,
                                            server_rec *server)
 {
     apr_socket_t *s = lis->sd;
@@ -217,7 +210,7 @@ static void ap_apply_accept_filter(apr_pool_t *p, ap_listen_rec *lis,
 
     if (accf) {
 #if APR_HAS_SO_ACCEPTFILTER
-        rv = apr_socket_accept_filter(s, apr_pstrdup(p, accf), 
+        rv = apr_socket_accept_filter(s, apr_pstrdup(p, accf),
                                       apr_pstrdup(p,""));
         if (rv != APR_SUCCESS && !APR_STATUS_IS_ENOTIMPL(rv)) {
             ap_log_perror(APLOG_MARK, APLOG_WARNING, rv, p,
@@ -225,13 +218,11 @@ static void ap_apply_accept_filter(apr_pool_t *p, ap_listen_rec *lis,
                           accf);
         }
 #else
-#ifdef APR_TCP_DEFER_ACCEPT
-        rv = apr_socket_opt_set(s, APR_TCP_DEFER_ACCEPT, 1);   
+        rv = apr_socket_opt_set(s, APR_TCP_DEFER_ACCEPT, 30);
         if (rv != APR_SUCCESS && !APR_STATUS_IS_ENOTIMPL(rv)) {
             ap_log_perror(APLOG_MARK, APLOG_WARNING, rv, p,
                               "Failed to enable APR_TCP_DEFER_ACCEPT");
         }
-#endif
 #endif
     }
 }
@@ -242,7 +233,7 @@ static apr_status_t close_listeners_on_exec(void *v)
     return APR_SUCCESS;
 }
 
-static const char *alloc_listener(process_rec *process, char *addr, 
+static const char *alloc_listener(process_rec *process, char *addr,
                                   apr_port_t port, const char* proto)
 {
     ap_listen_rec **walk, *last;
@@ -362,6 +353,9 @@ static int open_listeners(apr_pool_t *pool)
     int num_open;
     const char *userdata_key = "ap_open_listeners";
     void *data;
+#if AP_NONBLOCK_WHEN_MULTI_LISTEN
+    int use_nonblock;
+#endif
 
     /* Don't allocate a default listener.  If we need to listen to a
      * port, then the user needs to have a Listen directive in their
@@ -375,20 +369,28 @@ static int open_listeners(apr_pool_t *pool)
         }
         else {
 #if APR_HAVE_IPV6
+            ap_listen_rec *cur;
             int v6only_setting;
+            int skip = 0;
 
             /* If we have the unspecified IPv4 address (0.0.0.0) and
              * the unspecified IPv6 address (::) is next, we need to
              * swap the order of these in the list. We always try to
              * bind to IPv6 first, then IPv4, since an IPv6 socket
              * might be able to receive IPv4 packets if V6ONLY is not
-             * enabled, but never the other way around. */
+             * enabled, but never the other way around.
+             * Note: In some configurations, the unspecified IPv6 address
+             * could be even later in the list.  This logic only corrects
+             * the situation where it is next in the list, such as when
+             * apr_sockaddr_info_get() returns an IPv4 and an IPv6 address,
+             * in that order.
+             */
             if (lr->next != NULL
                 && IS_INADDR_ANY(lr->bind_addr)
                 && lr->bind_addr->port == lr->next->bind_addr->port
                 && IS_IN6ADDR_ANY(lr->next->bind_addr)) {
                 /* Exchange lr and lr->next */
-                ap_listen_rec *next = lr->next;
+                next = lr->next;
                 lr->next = next->next;
                 next->next = lr;
                 if (previous) {
@@ -400,23 +402,32 @@ static int open_listeners(apr_pool_t *pool)
                 lr = next;
             }
 
-            /* If we are trying to bind to 0.0.0.0 and the previous listener
+            /* If we are trying to bind to 0.0.0.0 and a previous listener
              * was :: on the same port and in turn that socket does not have
              * the IPV6_V6ONLY flag set; we must skip the current attempt to
              * listen (which would generate an error). IPv4 will be handled
              * on the established IPv6 socket.
              */
-            if (previous != NULL
-                && IS_INADDR_ANY(lr->bind_addr)
-                && lr->bind_addr->port == previous->bind_addr->port
-                && IS_IN6ADDR_ANY(previous->bind_addr)
-                && apr_socket_opt_get(previous->sd, APR_IPV6_V6ONLY,
-                                      &v6only_setting) == APR_SUCCESS
-                && v6only_setting == 0) {
-
-                /* Remove the current listener from the list */
-                previous->next = lr->next;
-                continue;
+            if (IS_INADDR_ANY(lr->bind_addr)) {
+                for (cur = ap_listeners; cur != lr; cur = cur->next) {
+                    if (lr->bind_addr->port == cur->bind_addr->port
+                        && IS_IN6ADDR_ANY(cur->bind_addr)
+                        && apr_socket_opt_get(cur->sd, APR_IPV6_V6ONLY,
+                                              &v6only_setting) == APR_SUCCESS
+                        && v6only_setting == 0) {
+
+                        /* Remove the current listener from the list */
+                        previous->next = lr->next;
+                        lr = previous; /* maintain current value of previous after
+                                        * post-loop expression is evaluated
+                                        */
+                        skip = 1;
+                        break;
+                    }
+                }
+                if (skip) {
+                    continue;
+                }
             }
 #endif
             if (make_sock(pool, lr) == APR_SUCCESS) {
@@ -474,16 +485,15 @@ static int open_listeners(apr_pool_t *pool)
      * is already forgotten about by the time we call accept, we won't
      * be hung until another connection arrives on that port
      */
-    if (ap_listeners && ap_listeners->next) {
-        for (lr = ap_listeners; lr; lr = lr->next) {
-            apr_status_t status;
-
-            status = apr_socket_opt_set(lr->sd, APR_SO_NONBLOCK, 1);
-            if (status != APR_SUCCESS) {
-                ap_log_perror(APLOG_MARK, APLOG_STARTUP|APLOG_ERR, status, pool,
-                              "unable to make listening socket non-blocking");
-                return -1;
-            }
+    use_nonblock = (ap_listeners && ap_listeners->next);
+    for (lr = ap_listeners; lr; lr = lr->next) {
+        apr_status_t status;
+
+        status = apr_socket_opt_set(lr->sd, APR_SO_NONBLOCK, use_nonblock);
+        if (status != APR_SUCCESS) {
+            ap_log_perror(APLOG_MARK, APLOG_STARTUP|APLOG_ERR, status, pool,
+                          "unable to control socket non-blocking status");
+            return -1;
         }
     }
 #endif /* AP_NONBLOCK_WHEN_MULTI_LISTEN */
@@ -516,8 +526,8 @@ AP_DECLARE(int) ap_setup_listeners(server_rec *s)
         proto = ap_get_server_protocol(ls);
         if (!proto) {
             found = 0;
-            /* No protocol was set for this vhost, 
-             * use the default for this listener. 
+            /* No protocol was set for this vhost,
+             * use the default for this listener.
              */
             for (addr = ls->addrs; addr && !found; addr = addr->next) {
                 for (lr = ap_listeners; lr; lr = lr->next) {
@@ -562,7 +572,7 @@ AP_DECLARE(int) ap_setup_listeners(server_rec *s)
     return num_listeners;
 }
 
-AP_DECLARE_NONSTD(void) ap_close_listeners(void) 
+AP_DECLARE_NONSTD(void) ap_close_listeners(void)
 {
     ap_listen_rec *lr;
 
@@ -615,7 +625,11 @@ AP_DECLARE_NONSTD(const char *) ap_set_listener(cmd_parms *cmd, void *dummy,
     }
 
     if (argc != 2) {
-        proto = "http";
+        if (port == 443) {
+            proto = "https";
+        } else {
+            proto = "http";
+        }
     }
     else {
         proto = apr_pstrdup(cmd->pool, argv[1]);