diff --git a/russh/src/client/encrypted.rs b/russh/src/client/encrypted.rs index a0919a4f..e0391ab3 100644 --- a/russh/src/client/encrypted.rs +++ b/russh/src/client/encrypted.rs @@ -559,6 +559,20 @@ impl Session { } Ok((client, self)) } + Some(&msg::REQUEST_SUCCESS) => { + let mut r = buf.reader(1); + let port_num = r.read_u32().map_err(crate::Error::from)?; + self.sender + .send(Reply::GlobalRequestSuccess(port_num)) + .map_err(|_| crate::Error::SendError)?; + Ok((client, self)) + } + Some(&msg::REQUEST_FAILURE) => { + self.sender + .send(Reply::GlobalRequestFailure) + .map_err(|_| crate::Error::SendError)?; + Ok((client, self)) + } Some(&msg::CHANNEL_SUCCESS) => { let mut r = buf.reader(1); let channel_num = ChannelId(r.read_u32().map_err(crate::Error::from)?); diff --git a/russh/src/client/mod.rs b/russh/src/client/mod.rs index a9984fc5..2609b749 100644 --- a/russh/src/client/mod.rs +++ b/russh/src/client/mod.rs @@ -141,6 +141,9 @@ impl Drop for Session { enum Reply { AuthSuccess, AuthFailure, + // TODO GlobalRequestSuccess its data depends on the type of request send. for now only support an u32 because thats what's needed for tcp-ip-forward. + GlobalRequestSuccess(u32), + GlobalRequestFailure, ChannelOpenFailure, SignRequest { key: key::PublicKey, @@ -424,19 +427,29 @@ impl Handle { &mut self, address: A, port: u32, - ) -> Result { + ) -> Result { self.sender .send(Msg::TcpIpForward { - want_reply: true, + want_reply: port == 0, address: address.into(), port, }) .await .map_err(|_| crate::Error::SendError)?; if port == 0 { - self.wait_recv_reply().await?; + loop { + match self.receiver.recv().await { + Some(Reply::GlobalRequestSuccess(port)) => return Ok(port), + Some(Reply::GlobalRequestFailure) => { + return Err(crate::Error::GlobalRequestFailure) + } + None => return Err(crate::Error::GlobalRequestFailure), + _ => {} + } + } + } else { + Ok(port) } - Ok(true) } pub async fn cancel_tcpip_forward>( diff --git a/russh/src/lib.rs b/russh/src/lib.rs index 323c5bee..1e077dd6 100644 --- a/russh/src/lib.rs +++ b/russh/src/lib.rs @@ -266,6 +266,9 @@ pub enum Error { #[error("Failed to decrypt a packet")] DecryptionError, + #[error("Global request failed")] + GlobalRequestFailure, + #[error(transparent)] Keys(#[from] russh_keys::Error),