Issue1391

classification
Title: socket.getaddrinfo() breaks ftplib FTP client
Type: behaviour Severity: major
Components: Library Versions: Deferred
Milestone:
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: amak Nosy List: amak, pjdm
Priority: Keywords:

Created on 2009-07-02.03:39:16 by pjdm, last changed 2009-07-03.15:48:32 by amak.

Messages
msg4869 (view) Author: Peter Mayne (pjdm) Date: 2009-07-02.03:39:15
Consider the following call taken not quite verbatim from
ftplib.makeport(). (The difference is that socket.AF_INET) is actually
self.af, which can be either socket.AF_INET or socket.AF_INET6.) Assume
“import socket”.
 
socket.getaddrinfo(None, 0, socket.AF_INET, socket.SOCK_STREAM, 0,
socket.AI_PASSIVE)
 
CPython 2.5 returns
 
[(2, 1, 0, '', ('0.0.0.0', 0))]
 
Jython 2.5 returns
 
[(2, 2, 0, 'localhost', ('127.0.0.1', 0))]
 
The second element in the tuple is socktype: the difference reflects the
different values of socket.SOCK_STREAM in the two implementations, and
is of no concern. However, the canonname and particularly the sockaddr
(fourth and fifth elements) in Jython are a problem.
 
When an FTP client (using set_pasv(False)) binds a socket to sockaddr to
accept the incoming data connection from the FTP server, CPython binds
to sockaddr (‘0.0.0.0’, 0), which allows the FTP server to connect, and
the FTP session continues.
 
However, Jython binds to sockaddr (‘127.0.0.1’, 0). Since the socket is
bound to localhost, external connection attempts from the FTP server
fail: the FTP client hangs waiting for a connection to 127.0.0.1, and
the FTP server fails because it can’t connect to the address/port that
it was told to connect to.
msg4877 (view) Author: Alan Kennedy (amak) Date: 2009-07-03.12:33:12
OK, this problem is caused by the fact that we're not correctly handling
the AI_PASSIVE flag. According to the man page for getaddrinfo

"""
.... the network address in each socket structure  is  initialized  
according to   the   AI_PASSIVE  flag,  which  is  set  in
hints.ai_flags.  The network address in each socket structure  will  be
left  unspecified  if  AI_PASSIVE  flag is set.  This is used by server
applications, which intend to accept client connections on any  network
address.   The  network  address  will be set to the loopback interface
address if the AI_PASSIVE flag is not set.   This  is  used  by  client
applications,  which  intend to connect to a server running on the same
network host.
"""

Which means that when the AI_PASSIVE flag is set, we should be returning
an address that can be used in a bind call, as cpython does.

I'll be checking in a fix for this fairly soon.
msg4880 (view) Author: Alan Kennedy (amak) Date: 2009-07-03.15:48:32
Fixed checked in at r6506.

Support has now been added for the AI_PASSIVE flag, and the AI_CANONNAME
flag.

The OP may wish to download the latest module from SVN

https://jython.svn.sourceforge.net/svnroot/jython/trunk/jython/Lib/socket.py

Many thanks for taking the time to report this.
History
Date User Action Args
2009-07-03 15:48:32amaksetstatus: open -> closed
resolution: fixed
messages: + msg4880
2009-07-03 12:33:13amaksetmessages: + msg4877
2009-07-02 08:34:25amaksetassignee: amak
nosy: + amak
2009-07-02 03:39:16pjdmcreate