httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Jim Carlson <jcarl...@jnous.com>
Subject [PATCH] IPV6 enabled check on Solaris
Date Sat, 12 Apr 2003 10:11:07 GMT
Howdy,
   I noticed that I was getting a lot of "[warn] (128)Network is unreachable: 
connect to listener" messages in my log file, and traced them back to 
prefork.c's attempts to kill off idle processes with ap_mpm_pod_killpg().  The 
problem is that Apache believes my Solaris box has IPv6 enabled, and 
consequently is trying to contact it's children by opening sockets to "::". 
While HAVE_IPV6 is true on my system, IPv6 is not enabled.  Apache tries to 
detect this in listen.c, find_default_family(), by creating and binding a socket 
to "::", and checking for errors.  However, it appears that on Solaris 8 (my 
box, anyway), socket() and bind() will succeed for a PF_INET6 address, but 
connect (even to localhost) will fail.  Consequently, I augmented the check in 
listen.c to call socket(), bind(), AND listen(), and then to call connect() with 
a second socket.  This "works" on my machine, in that it correctly fails and 
falls back to a default familty APR_INET (aforementioned log file warnings are 
now gone).  Someone with IPv6 enabled will need to ensure that my code doesn't 
give false negatives.

Thanks,

Jim

p.s.  An "ack" by anyone on this would be appreciated.  I've submitted several 
patches in recent weeks, none of which are of great moment, but at least one of 
which (the last one) I believe is a no-brainer for correctness.  I'm a little 
new to OSS contribution, but eager to help -- confirmation that I'm on the right 
track would be useful to me.  Thanks!


--- listen.c.orig       2002-12-02 15:53:37.000000000 -0800
+++ listen.c    2003-04-12 02:55:20.949997000 -0700
@@ -240,20 +240,31 @@
  #if APR_HAVE_IPV6
      /* We know the platform supports IPv6, but this particular
       * system may not have IPv6 enabled.  See if we can get an
-     * AF_INET6 socket and bind to an ephemeral port.  (On most
-     * systems, getting an AF_INET6 socket is a sufficient test.
-     * On certain levels of OpenUNIX, getting the socket is
-     * successful but bind always returns ENETUNREACH.)
+     * AF_INET6 socket, bind and listen to an ephemeral port,
+     * and then connect to that port.  (On most systems, getting
+     * an AF_INET6 socket is a sufficient test.  On certain levels
+     * of OpenUNIX, getting the socket is successful but bind always
+     * returns ENETUNREACH.  On Solaris 8, a bind/listen will be
+     * successful, but a connect will fail.)
       */
+
      if (default_family == APR_UNSPEC) {
-        apr_status_t sock_rv;
-        apr_socket_t *tmp_sock;
+        apr_status_t sock_rv, sock2_rv;
+        apr_socket_t *tmp_sock, *tmp_sock2;
          apr_sockaddr_t *sa;

          if ((sock_rv = apr_socket_create(&tmp_sock, APR_INET6, SOCK_STREAM, p))
-            == APR_SUCCESS &&
+                == APR_SUCCESS &&
              apr_sockaddr_info_get(&sa, NULL, APR_INET6, 0, 0, p) == APR_SUCCESS &&
-            apr_bind(tmp_sock, sa) == APR_SUCCESS) {
+            apr_bind(tmp_sock, sa) == APR_SUCCESS &&
+            apr_socket_listen(tmp_sock, 1) == APR_SUCCESS &&
+            apr_socket_addr_get(&sa, APR_LOCAL, tmp_sock) == APR_SUCCESS &&
+            apr_sockaddr_info_get(&sa, "localhost", APR_INET6, sa->port, 0, p)
+                == APR_SUCCESS &&
+            (sock2_rv = apr_socket_create(&tmp_sock2, APR_INET6, SOCK_STREAM, p))
+                == APR_SUCCESS &&
+            apr_socket_connect(tmp_sock2, sa) == APR_SUCCESS) {
+
              default_family = APR_INET6;
          }
          else {
@@ -262,6 +273,9 @@
          if (sock_rv == APR_SUCCESS) {
              apr_socket_close(tmp_sock);
          }
+        if (sock2_rv == APR_SUCCESS) {
+            apr_socket_close(tmp_sock2);
+        }
      }
  #endif
  }


Mime
View raw message