diff --git a/src/stream/tcp.rs b/src/stream/tcp.rs index 4ece70d..6bf154a 100644 --- a/src/stream/tcp.rs +++ b/src/stream/tcp.rs @@ -9,7 +9,7 @@ use crate::{ }, stream::tcb::{PacketType, Tcb, TcpState}, }; -use etherparse::{IpNumber, Ipv4Header, Ipv6FlowLabel, TcpHeader, TcpOptionElement}; +use etherparse::{IpNumber, Ipv4Header, Ipv6FlowLabel, TcpHeader}; use std::{ future::Future, io::ErrorKind::{BrokenPipe, ConnectionRefused, InvalidInput, UnexpectedEof}, @@ -28,6 +28,7 @@ const CLOSE_WAIT_TIMEOUT: Duration = Duration::from_secs(5); const LAST_ACK_MAX_RETRIES: usize = 3; const LAST_ACK_TIMEOUT: Duration = Duration::from_millis(500); const TIMEOUT: Duration = Duration::from_secs(60); +const TCP_HEADER_LEN: u16 = 20; #[non_exhaustive] #[derive(Debug, Clone)] @@ -451,7 +452,16 @@ async fn tcp_main_logic_loop( &up_packet_sender, network_tuple, &tcb, - config.options.as_ref(), + config.options.as_ref().map(|o| { + ( + o, + if network_tuple.src.is_ipv4() && network_tuple.dst.is_ipv4() { + tcb.get_mtu() - 20 - TCP_HEADER_LEN + } else { + tcb.get_mtu() - 40 - TCP_HEADER_LEN + }, + ) + }), ACK | SYN, None, None, @@ -861,7 +871,7 @@ pub(crate) fn write_packet_to_device( up_packet_sender: &PacketSender, tuple: NetworkTuple, tcb: &Tcb, - options: Option<&Vec>, + options: Option<(&Vec, u16)>, flags: u8, seq: Option, payload: Option>, @@ -899,7 +909,7 @@ pub(crate) fn create_raw_packet( ack: u32, win: u16, mut payload: Vec, - options: Option<&Vec>, + options: Option<(&Vec, u16)>, ) -> std::io::Result { let mut tcp_header = etherparse::TcpHeader::new(src_addr.port(), dst_addr.port(), seq, win); tcp_header.acknowledgment_number = ack; @@ -909,17 +919,19 @@ pub(crate) fn create_raw_packet( tcp_header.fin = flags & FIN != 0; tcp_header.psh = flags & PSH != 0; - if let Some(opts) = options { + if let Some((opts, mut mss)) = options { let mut tcp_options = Vec::new(); for opt in opts { match opt { - TcpOptions::MaximumSegmentSize(mss) => tcp_options.push(TcpOptionElement::MaximumSegmentSize(*mss)), + TcpOptions::MaximumSegmentSize(fixed_mss) => mss = *fixed_mss, } } + tcp_options.push(etherparse::TcpOptionElement::MaximumSegmentSize(mss)); tcp_header .set_options(&tcp_options) .map_err(|e| std::io::Error::new(InvalidInput, e))?; } + let ip_header = match (src_addr.ip(), dst_addr.ip()) { (std::net::IpAddr::V4(src), std::net::IpAddr::V4(dst)) => { let mut ip_h =