You are viewing a plain text version of this content. The canonical link for it is here.
Posted to mod_ftp-commits@incubator.apache.org by wr...@apache.org on 2007/02/07 06:54:46 UTC

svn commit: r504452 - /incubator/mod_ftp/trunk/modules/ftp/ftp_commands.c

Author: wrowe
Date: Tue Feb  6 22:54:46 2007
New Revision: 504452

URL: http://svn.apache.org/viewvc?view=rev&rev=504452
Log:
Move the socket creation AFTER the socket address resolution, so that
we can leverage the created socket's family.  Allows us to create an
IPv6 socket when appropriate in response to PASV (an unusual situation.)

Finally, offer an alternative if the socket is not an IPv4 or faux-IPv4
socket, and respond to PASV with 127,555,555,555,p,p - an invalid port
as suggested at http://cr.yp.to/ftp/retr.html - to allow some value to
be returned other than the currently bogus (::1,p,p).

We have two other alternatives that would be somewhat legitimate in this
impossible case, (,,,,p,p) or (0.0.0.0,p,p), but the later has a defined
meaning and the prior might choke more clients than the suggested exception.

This is only triggered for a PASV command over an IPv6 socket, so it's a
very obscure edge case in the first place.

Modified:
    incubator/mod_ftp/trunk/modules/ftp/ftp_commands.c

Modified: incubator/mod_ftp/trunk/modules/ftp/ftp_commands.c
URL: http://svn.apache.org/viewvc/incubator/mod_ftp/trunk/modules/ftp/ftp_commands.c?view=diff&rev=504452&r1=504451&r2=504452
==============================================================================
--- incubator/mod_ftp/trunk/modules/ftp/ftp_commands.c (original)
+++ incubator/mod_ftp/trunk/modules/ftp/ftp_commands.c Tue Feb  6 22:54:46 2007
@@ -1387,33 +1387,6 @@
         fc->passive_created = -1;
     }
 
-#if APR_MAJOR_VERSION < 1
-    rv = apr_socket_create_ex(&s, APR_INET, SOCK_STREAM, APR_PROTO_TCP, c->pool);
-#else
-    rv = apr_socket_create(&s, APR_INET, SOCK_STREAM, APR_PROTO_TCP, c->pool);
-#endif
-    if (rv != APR_SUCCESS) {
-        ap_log_error(APLOG_MARK, APLOG_ERR, rv, c->base_server,
-                     "Couldn't create passive socket");
-        return FTP_REPLY_CANNOT_OPEN_DATACONN;
-    }
-
-    rv = apr_socket_opt_set(s, APR_SO_LINGER,
-                            APR_MAX_SECS_TO_LINGER);
-    if (rv != APR_SUCCESS) {
-        ap_log_error(APLOG_MARK, APLOG_ERR, rv, c->base_server,
-                     "Couldn't set APR_SO_LINGER socket option");
-        apr_socket_close(s);
-        return FTP_REPLY_CANNOT_OPEN_DATACONN;
-    }
-    rv = apr_socket_opt_set(s, APR_SO_REUSEADDR, 1);
-    if (rv != APR_SUCCESS && rv != APR_ENOTIMPL) {
-        ap_log_error(APLOG_MARK, APLOG_ERR, rv, c->base_server,
-                     "Couldn't set APR_SO_REUSEADDR socket option");
-        apr_socket_close(s);
-        return FTP_REPLY_CANNOT_OPEN_DATACONN;
-    }
-
     if (fsc->pasv_bindaddr) {
         apr_sockaddr_info_get(&sa, fsc->pasv_bindaddr, APR_INET,
                               0, 0, c->pool);
@@ -1442,7 +1415,37 @@
          */
         apr_sockaddr_info_get(&sa, NULL, APR_INET,
                               0, 0, c->pool);
-        /* XXX: Perhaps we should simply fail? */
+        /* XXX: Perhaps we should simply fail?  Or copy c->local_addr? */
+    }
+
+#if APR_MAJOR_VERSION < 1
+    rv = apr_socket_create_ex(&s, sa->family, SOCK_STREAM,
+                              APR_PROTO_TCP, c->pool);
+#else
+    rv = apr_socket_create(&s, sa->family, SOCK_STREAM,
+                           APR_PROTO_TCP, c->pool);
+#endif
+    if (rv != APR_SUCCESS) {
+        ap_log_error(APLOG_MARK, APLOG_ERR, rv, c->base_server,
+                     "Couldn't create passive socket");
+        return FTP_REPLY_CANNOT_OPEN_DATACONN;
+    }
+
+    rv = apr_socket_opt_set(s, APR_SO_LINGER,
+                            APR_MAX_SECS_TO_LINGER);
+    if (rv != APR_SUCCESS) {
+        ap_log_error(APLOG_MARK, APLOG_ERR, rv, c->base_server,
+                     "Couldn't set APR_SO_LINGER socket option");
+        apr_socket_close(s);
+        return FTP_REPLY_CANNOT_OPEN_DATACONN;
+    }
+
+    rv = apr_socket_opt_set(s, APR_SO_REUSEADDR, 1);
+    if (rv != APR_SUCCESS && rv != APR_ENOTIMPL) {
+        ap_log_error(APLOG_MARK, APLOG_ERR, rv, c->base_server,
+                     "Couldn't set APR_SO_REUSEADDR socket option");
+        apr_socket_close(s);
+        return FTP_REPLY_CANNOT_OPEN_DATACONN;
     }
 
     found_port = 0;
@@ -1515,8 +1518,21 @@
     else if (fsc->pasv_bindaddr) {
         a = apr_pstrdup(c->pool, fsc->pasv_bindaddr);
     }
-    else {
+    else if ((c->local_addr->family == AF_INET)
+#if APR_HAVE_IPV6
+          || (c->local_addr->family == AF_INET6
+          && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)c->local_addr->ipaddr_ptr))
+#endif
+             ) {
         a = apr_pstrdup(c->pool, c->local_ip);
+    }
+    else {
+        /* a bogus answer, which will not be translated below,
+         * wherein clients can choose to connect back to the
+         * original, same address.  Suggested as an early solution
+         * at http://cr.yp.to/ftp/retr.html
+         */
+        a = "127,555,555,555";
     }
 
     /* Translate x.x.x.x to x,x,x,x */