Skip to content

Commit f4010bf

Browse files
authored
fix: active mode uses EPRT for IPv6 connections (#145)
* fix: active mode uses EPRT for IPv6, fix unwrap panics The PORT command only supports IPv4. When connected via IPv6, the client now uses EPRT instead. Also replaces unwrap() on local_addr() with proper error handling.
1 parent 1e9ebfa commit f4010bf

3 files changed

Lines changed: 59 additions & 21 deletions

File tree

crates/suppaftp/src/async_ftp/async_std_ftp/mod.rs

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -985,17 +985,30 @@ where
985985
trace!("Local address is {}", addr);
986986

987987
let ip = match self.reader.get_mut() {
988-
DataStream::Tcp(stream) => stream.local_addr().unwrap().ip(),
989-
DataStream::Ssl(stream) => stream.get_ref().local_addr().unwrap().ip(),
988+
DataStream::Tcp(stream) => stream.local_addr().map_err(FtpError::ConnectionError)?.ip(),
989+
DataStream::Ssl(stream) => stream
990+
.get_ref()
991+
.local_addr()
992+
.map_err(FtpError::ConnectionError)?
993+
.ip(),
990994
};
991995

992-
let msb = addr.port() / 256;
993-
let lsb = addr.port() % 256;
994-
let ip_port = format!("{},{},{}", ip.to_string().replace('.', ","), msb, lsb);
995996
debug!("Active mode, listening on {}:{}", ip, addr.port());
996997

997-
debug!("Running PORT command");
998-
self.perform(Command::Port(ip_port)).await?;
998+
match ip {
999+
std::net::IpAddr::V4(_) => {
1000+
let msb = addr.port() / 256;
1001+
let lsb = addr.port() % 256;
1002+
let ip_port = format!("{},{},{}", ip.to_string().replace('.', ","), msb, lsb);
1003+
debug!("Running PORT command");
1004+
self.perform(Command::Port(ip_port)).await?;
1005+
}
1006+
std::net::IpAddr::V6(_) => {
1007+
debug!("Running EPRT command");
1008+
self.perform(Command::Eprt(SocketAddr::new(ip, addr.port())))
1009+
.await?;
1010+
}
1011+
}
9991012
self.read_response(Status::CommandOk).await?;
10001013

10011014
Ok(conn)

crates/suppaftp/src/async_ftp/tokio_ftp/mod.rs

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -982,17 +982,30 @@ where
982982
trace!("Local address is {}", addr);
983983

984984
let ip = match self.reader.get_mut() {
985-
DataStream::Tcp(stream) => stream.local_addr().unwrap().ip(),
986-
DataStream::Ssl(stream) => stream.get_ref().local_addr().unwrap().ip(),
985+
DataStream::Tcp(stream) => stream.local_addr().map_err(FtpError::ConnectionError)?.ip(),
986+
DataStream::Ssl(stream) => stream
987+
.get_ref()
988+
.local_addr()
989+
.map_err(FtpError::ConnectionError)?
990+
.ip(),
987991
};
988992

989-
let msb = addr.port() / 256;
990-
let lsb = addr.port() % 256;
991-
let ip_port = format!("{},{},{}", ip.to_string().replace('.', ","), msb, lsb);
992993
debug!("Active mode, listening on {}:{}", ip, addr.port());
993994

994-
debug!("Running PORT command");
995-
self.perform(Command::Port(ip_port)).await?;
995+
match ip {
996+
std::net::IpAddr::V4(_) => {
997+
let msb = addr.port() / 256;
998+
let lsb = addr.port() % 256;
999+
let ip_port = format!("{},{},{}", ip.to_string().replace('.', ","), msb, lsb);
1000+
debug!("Running PORT command");
1001+
self.perform(Command::Port(ip_port)).await?;
1002+
}
1003+
std::net::IpAddr::V6(_) => {
1004+
debug!("Running EPRT command");
1005+
self.perform(Command::Eprt(SocketAddr::new(ip, addr.port())))
1006+
.await?;
1007+
}
1008+
}
9961009
self.read_response(Status::CommandOk).await?;
9971010

9981011
Ok(conn)

crates/suppaftp/src/sync_ftp/mod.rs

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -999,17 +999,29 @@ where
999999
trace!("Local address is {}", addr);
10001000

10011001
let ip = match self.reader.get_mut() {
1002-
DataStream::Tcp(stream) => stream.local_addr().unwrap().ip(),
1003-
DataStream::Ssl(stream) => stream.get_ref().local_addr().unwrap().ip(),
1002+
DataStream::Tcp(stream) => stream.local_addr().map_err(FtpError::ConnectionError)?.ip(),
1003+
DataStream::Ssl(stream) => stream
1004+
.get_ref()
1005+
.local_addr()
1006+
.map_err(FtpError::ConnectionError)?
1007+
.ip(),
10041008
};
10051009

1006-
let msb = addr.port() / 256;
1007-
let lsb = addr.port() % 256;
1008-
let ip_port = format!("{},{},{}", ip.to_string().replace('.', ","), msb, lsb);
10091010
debug!("Active mode, listening on {}:{}", ip, addr.port());
10101011

1011-
debug!("Running PORT command");
1012-
self.perform(Command::Port(ip_port))?;
1012+
match ip {
1013+
std::net::IpAddr::V4(_) => {
1014+
let msb = addr.port() / 256;
1015+
let lsb = addr.port() % 256;
1016+
let ip_port = format!("{},{},{}", ip.to_string().replace('.', ","), msb, lsb);
1017+
debug!("Running PORT command");
1018+
self.perform(Command::Port(ip_port))?;
1019+
}
1020+
std::net::IpAddr::V6(_) => {
1021+
debug!("Running EPRT command");
1022+
self.perform(Command::Eprt(SocketAddr::new(ip, addr.port())))?;
1023+
}
1024+
}
10131025
self.read_response(Status::CommandOk)?;
10141026

10151027
Ok(conn)

0 commit comments

Comments
 (0)