apr-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "William A. Rowe, Jr." <wr...@rowe-clan.net>
Subject Re: svn commit: r602176 - /apr/apr/trunk/network_io/unix/sockaddr.c
Date Mon, 10 Dec 2007 20:39:19 GMT
Colm MacCarthaigh wrote:
> On Mon, Dec 10, 2007 at 12:57:18PM -0600, William A. Rowe, Jr. wrote:
>> Now apr has provided a tuple of ip address, family and port that
>> cannot be reconstituted by APR.  So, for example, where we have
>> to create a connection to the very same host/family on a different
>> port, it becomes impossible.
> 
> O.k., so the scenario is ;
> 
> 	1. Host application listens on :: , accepts incoming socket
> 	   from ::ffff:127.0.0.1
> 
> 	2. Host application resolves the IP into a text format.
> 	   (calls getnameinfo or whatever)
> 
> 	3. Host application takes that text format and turns 
> 	   it back into a sockaddr. (calls getaddrinfo or whatever)
> 
> 	4. Connects to that IP.
> 
> Why would it ever do steps 2 and 3?
> 
> Maybe we should support using INET6 sockets for outbound IPv4
> connections more - and the patch would enable that for connections
> involving lookups - but the use-case scanario is mighty strange, it has
> to go through a text lookup.
> 
>> They know the family and IP from an existing connection, and that
>> existing connection is internally inconsistent.
> 
> How? we don't modify the sockaddr.

See this file;

http://svn.apache.org/repos/asf/httpd/mod_ftp/trunk/modules/ftp/ftp_commands.c

Jump into the ftp_cmd_eprt function...

     /* XXX: Anything special to handle IPv6 ip_addr string where c->remote_ip
      * is IPv4 mapped?
      */
     if (((c->local_addr->family == APR_INET) && (family == APR_INET))
#if APR_HAVE_IPV6
             || ((c->local_addr->family == APR_INET6) && (family == APR_INET6))
#endif
        ) {
         apr_sockaddr_info_get(&sa, c->local_ip, family,
                               local_port, 0, c->pool);
         if (!sa) {
             ap_log_rerror(APLOG_MARK, APLOG_WARNING, rv, r,
                           "Couldn't resolve explicit local socket address"
                           " (apr or socket stack bug?)  Retrying");
             apr_sockaddr_info_get(&sa, NULL, family,
                                   local_port, 0, c->pool);
         }
     }
     else {
         /* If the family differs, it's difficult to map the EPRT origin IP */
         apr_sockaddr_info_get(&sa, NULL, family,
                               local_port, 0, c->pool);
     }

     if (!sa) {
         ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
                       "Couldn't resolve local socket address"
                       " (apr or socket stack bug?)  Giving up");
         return FTP_REPLY_CANNOT_OPEN_DATACONN;
     }

     apr_socket_opt_set(s, APR_SO_REUSEADDR, 1);
     rv = apr_socket_bind(s, sa);

To decipher; FTP by design should originate the connection to the client's
specified adapter from the *same adapter/address* to which the client had
connected.

In httpd, we know this from the c->local_addr.

Here, we take the c->local_ip and c->family, but we now need to give this
a different outgoing port assignment.  We reconstruct a sockaddr_t that
consists of the IP, Family, and our new idea for a origin port.

This code in apr-1.2 falls through to the (!sa) case because 127.0.0.1
and family APR_INET6 returns NULL for the sa.  then (as Joe hinted) we
can always retry with UNSPEC.  But that means we do route through a
different interface, potentially.

This code with apr-1.x succeeds to bind to 127.0.0.1 as an IPV6 mapped
IPV6 address, so the interface is preserved.

Now; are you suggesting that it would be more efficient and effective
if we cloned the local_addr structure, modified the port and directly
used the clone to apr_socket_bind rather than going through these extra
apr_sockaddr_info_get gymnastics?

If so, what is the proper method to clone an sa in the apr schema?

Bill




Mime
View raw message