mattnenterprise / rust-ftp

FTP client for Rust
Apache License 2.0
182 stars 57 forks source link

Support IPv6 with PASV #88

Closed kulp closed 2 years ago

kulp commented 4 years ago

If an FTP connection is made via IPv6, then the IP address returned by the server in response to PASV will be all zeros, which will result in a connection error right afterward.

Users can work around this by forcing IPv4 (if they can recognize the problem), or we could fall back to using the connections peer address (whether IPv4 or IPv6). The current pull request implements the latter solution.

Before the current pull request, this code breaks (throws an FtpError::ConnectionError) if ftp.gnu.org resolves to an IPv6 address :

let addr = ("ftp.gnu.org", 21);
let mut ftp = FtpStream::connect(addr).unwrap();
ftp.login("anonymous", "").unwrap();
let fname = "/gnu/lightning/lightning-2.1.3.tar.gz";
ftp.list(Some(fname)).unwrap();

The error looks like this, where build.rs:22 refers to the line with ftp.list.

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: ConnectionError(Os { code: 61, kind: ConnectionRefused, message: "Connection refused" })', build.rs:22:1

This is a workaround (see https://github.com/Petelliott/lightning-sys/pull/33) until the current PR is merged :

// Force IPv4 for now, because the `ftp` crate does not switch to PASV mode
// correctly when connecting over IPv6.
let addr = ("ftp.gnu.org", 21)
    .to_socket_addrs()
    .unwrap()
    .find(|a| match a { std::net::SocketAddr::V4(_) => true, _ => false })
    .unwrap();

let mut ftp = FtpStream::connect(addr).unwrap();
ftp.login("anonymous", "").unwrap();
let fname = "/gnu/lightning/lightning-2.1.3.tar.gz";
ftp.list(Some(fname)).unwrap();
kulp commented 2 years ago

It does not look like this PR is likely to get attention. I am closing it.