From 5aae15aabad727ce47f9c9010e490ce73bfd46c6 Mon Sep 17 00:00:00 2001 From: whitequark Date: Fri, 22 Sep 2017 10:14:26 +0000 Subject: [PATCH] Fix an issue where TCP packets would have zero IP payload length. --- src/socket/tcp.rs | 7 ++++--- src/wire/ip.rs | 11 +++++++++++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/socket/tcp.rs b/src/socket/tcp.rs index fbfa554..00f89e8 100644 --- a/src/socket/tcp.rs +++ b/src/socket/tcp.rs @@ -756,11 +756,10 @@ impl<'a> TcpSocket<'a> { (ip_reply_repr, reply_repr) } - pub(crate) fn ack_reply(&self, ip_repr: &IpRepr, repr: &TcpRepr) -> - (IpRepr, TcpRepr<'static>) { + fn ack_reply(&self, ip_repr: &IpRepr, repr: &TcpRepr) -> (IpRepr, TcpRepr<'static>) { let (ip_reply_repr, mut reply_repr) = Self::reply(ip_repr, repr); - // From RFC793: + // From RFC 793: // [...] an empty acknowledgment segment containing the current send-sequence number // and an acknowledgment indicating the next sequence number expected // to be received. @@ -1338,6 +1337,7 @@ impl<'a> TcpSocket<'a> { repr.max_seg_size = Some(max_segment_size as u16); } + ip_repr.set_payload_len(repr.buffer_len()); emit((ip_repr, repr))?; // We've sent something, whether useful data or a keep-alive packet, so rewind @@ -1481,6 +1481,7 @@ mod test { assert_eq!(ip_repr.protocol(), IpProtocol::Tcp); assert_eq!(ip_repr.src_addr(), LOCAL_IP); assert_eq!(ip_repr.dst_addr(), REMOTE_IP); + assert_eq!(ip_repr.payload_len(), tcp_repr.buffer_len()); trace!("recv: {}", tcp_repr); Ok(f(Ok(tcp_repr))) diff --git a/src/wire/ip.rs b/src/wire/ip.rs index b8a2cde..eb59356 100644 --- a/src/wire/ip.rs +++ b/src/wire/ip.rs @@ -237,6 +237,17 @@ impl IpRepr { } } + /// Set the payload length. + pub fn set_payload_len(&mut self, length: usize) { + match self { + &mut IpRepr::Unspecified { ref mut payload_len, .. } => + *payload_len = length, + &mut IpRepr::Ipv4(Ipv4Repr { ref mut payload_len, .. }) => + *payload_len = length, + &mut IpRepr::__Nonexhaustive => unreachable!() + } + } + /// Convert an unspecified representation into a concrete one, or return /// `Err(Error::Unaddressable)` if not possible. ///