]> granicus.if.org Git - apache/blobdiff - server/listen.c
event: child_main() never returns, so remove some dead code after
[apache] / server / listen.c
index f2d78f576254f16556248d41d48e205f126bcf00..10029801ae44b30ae97cdf8308e3815ec2166726 100644 (file)
 #include "http_core.h"
 #include "ap_listen.h"
 #include "http_log.h"
-#include "mpm.h"
 #include "mpm_common.h"
 
+APLOG_USE_MODULE(core);
+
 AP_DECLARE_DATA ap_listen_rec *ap_listeners = NULL;
 
 static ap_listen_rec *old_listeners;
@@ -169,11 +170,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;
 }
@@ -223,13 +220,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, 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
     }
 }
@@ -241,7 +236,8 @@ static apr_status_t close_listeners_on_exec(void *v)
 }
 
 static const char *alloc_listener(process_rec *process, char *addr,
-                                  apr_port_t port, const char* proto)
+                                  apr_port_t port, const char* proto,
+                                  void *dummy)
 {
     ap_listen_rec **walk, *last;
     apr_status_t status;
@@ -276,6 +272,9 @@ static const char *alloc_listener(process_rec *process, char *addr,
     }
 
     if (found_listener) {
+        if (ap_listeners->slave != dummy) {
+            return "Cannot define a slave on the same IP:port as a Listener";
+        }
         return NULL;
     }
 
@@ -333,6 +332,7 @@ static const char *alloc_listener(process_rec *process, char *addr,
             last->next = new;
             last = new;
         }
+        new->slave = dummy;
     }
 
     return NULL;
@@ -376,14 +376,22 @@ 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
@@ -401,31 +409,36 @@ 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;
-                lr = previous; /* maintain current value of previous after
-                                * post-loop expression is evaluated
-                                */
-                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) {
                 ++num_open;
-                lr->active = 1;
             }
             else {
 #if APR_HAVE_IPV6
@@ -574,6 +587,22 @@ AP_DECLARE_NONSTD(void) ap_close_listeners(void)
         lr->active = 0;
     }
 }
+AP_DECLARE_NONSTD(int) ap_close_selected_listeners(ap_slave_t *slave)
+{
+    ap_listen_rec *lr;
+    int n = 0;
+
+    for (lr = ap_listeners; lr; lr = lr->next) {
+        if (lr->slave != slave) {
+            apr_socket_close(lr->sd);
+            lr->active = 0;
+        }
+        else {
+            ++n;
+        }
+    }
+    return n;
+}
 
 AP_DECLARE(void) ap_listen_pre_config(void)
 {
@@ -582,7 +611,10 @@ AP_DECLARE(void) ap_listen_pre_config(void)
     ap_listenbacklog = DEFAULT_LISTENBACKLOG;
 }
 
-
+/* Hack: populate an extra field
+ * When this gets called from a Listen directive, dummy is null.
+ * So we can use non-null dummy to pass a data pointer without conflict
+ */
 AP_DECLARE_NONSTD(const char *) ap_set_listener(cmd_parms *cmd, void *dummy,
                                                 int argc, char *const argv[])
 {
@@ -618,14 +650,18 @@ 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]);
         ap_str_tolower(proto);
     }
 
-    return alloc_listener(cmd->server->process, host, port, proto);
+    return alloc_listener(cmd->server->process, host, port, proto, dummy);
 }
 
 AP_DECLARE_NONSTD(const char *) ap_set_listenbacklog(cmd_parms *cmd,