@@ -9,7 +9,7 @@ use crate::{
99 } ,
1010 stream:: tcb:: { PacketType , Tcb , TcpState } ,
1111} ;
12- use etherparse:: { IpNumber , Ipv4Header , Ipv6FlowLabel , TcpHeader } ;
12+ use etherparse:: { IpNumber , Ipv4Header , Ipv6FlowLabel , TcpHeader , TcpOptionElement } ;
1313use std:: {
1414 future:: Future ,
1515 io:: ErrorKind :: { BrokenPipe , ConnectionRefused , InvalidInput , UnexpectedEof } ,
@@ -43,6 +43,15 @@ pub struct TcpConfig {
4343 pub timeout : Duration ,
4444 /// Timeout for the TIME_WAIT state. Default is 2 seconds.
4545 pub two_msl : Duration ,
46+ /// TCP options
47+ pub options : Option < Vec < TcpOptions > > ,
48+ }
49+
50+ #[ non_exhaustive]
51+ #[ derive( Debug , Clone ) ]
52+ pub enum TcpOptions {
53+ /// Maximum segment size (MSS) for TCP connections. Default is 1460 bytes.
54+ MaximumSegmentSize ( u16 ) ,
4655}
4756
4857impl Default for TcpConfig {
@@ -53,6 +62,7 @@ impl Default for TcpConfig {
5362 close_wait_timeout : CLOSE_WAIT_TIMEOUT ,
5463 timeout : TIMEOUT ,
5564 two_msl : TWO_MSL ,
65+ options : Default :: default ( ) ,
5666 }
5767 }
5868}
@@ -134,7 +144,7 @@ impl IpStackTcpStream {
134144 let tuple = NetworkTuple :: new ( src_addr, dst_addr, true ) ;
135145 if !tcp. syn {
136146 if !tcp. rst
137- && let Err ( err) = write_packet_to_device ( & up_packet_sender, tuple, & tcb, ACK | RST , None , None )
147+ && let Err ( err) = write_packet_to_device ( & up_packet_sender, tuple, & tcb, None , ACK | RST , None , None )
138148 {
139149 log:: warn!( "Error sending RST/ACK packet: {err}" ) ;
140150 }
@@ -222,7 +232,7 @@ impl AsyncRead for IpStackTcpStream {
222232 let l_info = format ! ( "local {{ seq: {seq}, ack: {ack} }}" ) ;
223233 log:: warn!( "{network_tuple} {state:?}: [poll_read] {l_info}, session timeout reached, closing forcefully..." ) ;
224234 let sender = & self . up_packet_sender ;
225- write_packet_to_device ( sender, network_tuple, & tcb, ACK | RST , None , None ) ?;
235+ write_packet_to_device ( sender, network_tuple, & tcb, None , ACK | RST , None , None ) ?;
226236 tcb. change_state ( TcpState :: Closed ) ;
227237 let state = tcb. get_state ( ) ;
228238 log:: warn!( "{network_tuple} {state:?}: [poll_read] {l_info}, session notified to close" ) ;
@@ -281,7 +291,7 @@ impl AsyncWrite for IpStackTcpStream {
281291
282292 let mut tcb = self . tcb . lock ( ) . unwrap ( ) ;
283293 let sender = & self . up_packet_sender ;
284- let payload_len = write_packet_to_device ( sender, nt, & tcb, ACK | PSH , None , Some ( buf. to_vec ( ) ) ) ?;
294+ let payload_len = write_packet_to_device ( sender, nt, & tcb, None , ACK | PSH , None , Some ( buf. to_vec ( ) ) ) ?;
285295 tcb. add_inflight_packet ( buf[ ..payload_len] . to_vec ( ) ) ?;
286296
287297 let ( state, seq, ack) = ( tcb. get_state ( ) , tcb. get_seq ( ) , tcb. get_ack ( ) ) ;
@@ -335,7 +345,7 @@ fn send_fin_n_change_state_to_fin_wait1(hint: &str, nt: NetworkTuple, sender: &P
335345 }
336346
337347 log:: debug!( "{nt} {state:?}: {hint} actively send a farewell packet to the other side..." ) ;
338- write_packet_to_device ( sender, nt, tcb, ACK | FIN , None , None ) ?;
348+ write_packet_to_device ( sender, nt, tcb, None , ACK | FIN , None , None ) ?;
339349 tcb. increase_seq ( ) ;
340350 tcb. change_state ( TcpState :: FinWait1 ) ;
341351 let state = tcb. get_state ( ) ;
@@ -437,7 +447,15 @@ async fn tcp_main_logic_loop(
437447 let ( seq, ack) = ( tcb. get_seq ( ) . 0 , tcb. get_ack ( ) . 0 ) ;
438448 let l_info = format ! ( "local {{ seq: {seq}, ack: {ack} }}" ) ;
439449 log:: trace!( "{network_tuple} {state:?}: {l_info} session begins" ) ;
440- write_packet_to_device ( & up_packet_sender, network_tuple, & tcb, ACK | SYN , None , None ) ?;
450+ write_packet_to_device (
451+ & up_packet_sender,
452+ network_tuple,
453+ & tcb,
454+ config. options . as_ref ( ) ,
455+ ACK | SYN ,
456+ None ,
457+ None ,
458+ ) ?;
441459 tcb. increase_seq ( ) ;
442460 tcb. change_state ( TcpState :: SynReceived ) ;
443461 let state = tcb. get_state ( ) ;
@@ -483,7 +501,7 @@ async fn tcp_main_logic_loop(
483501 return ;
484502 }
485503 log:: debug!( "{nt} {state:?}: {hint} timer expired, resending ACK|FIN (retry {idx}/{last_ack_max_retries})" ) ;
486- _ = write_packet_to_device ( & pkt_sdr, nt, & tcb, ACK | FIN , None , None ) ;
504+ _ = write_packet_to_device ( & pkt_sdr, nt, & tcb, None , ACK | FIN , None , None ) ;
487505 }
488506 }
489507 {
@@ -512,7 +530,7 @@ async fn tcp_main_logic_loop(
512530 return Ok ( ( ) ) ;
513531 }
514532 log:: warn!( "{nt} {state:?}: Upstream timeout, forcing FIN" ) ;
515- write_packet_to_device ( & up_packet_sender, nt, & tcb, ACK | FIN , None , None ) ?;
533+ write_packet_to_device ( & up_packet_sender, nt, & tcb, None , ACK | FIN , None , None ) ?;
516534 tcb. increase_seq ( ) ;
517535 tcb. change_state ( TcpState :: LastAck ) ;
518536 let new_state = tcb. get_state ( ) ;
@@ -581,7 +599,15 @@ async fn tcp_main_logic_loop(
581599 for packet in tcb. collect_timed_out_inflight_packets ( ) {
582600 let ( seq, count) = ( packet. seq , packet. retransmit_count ) ;
583601 log:: debug!( "{network_tuple} inflight packet retransmission timeout: {seq:?}, retransmit_count: {count}" , ) ;
584- write_packet_to_device ( & up_packet_sender, network_tuple, & tcb, ACK | PSH , Some ( seq) , Some ( packet. payload ) ) ?;
602+ write_packet_to_device (
603+ & up_packet_sender,
604+ network_tuple,
605+ & tcb,
606+ None ,
607+ ACK | PSH ,
608+ Some ( seq) ,
609+ Some ( packet. payload ) ,
610+ ) ?;
585611 }
586612
587613 let pkt_type = tcb. check_pkt_type ( tcp_header, & payload) ;
@@ -611,7 +637,7 @@ async fn tcp_main_logic_loop(
611637 write_notify. lock ( ) . unwrap ( ) . take ( ) . map ( |w| w. wake_by_ref ( ) ) . unwrap_or ( ( ) ) ;
612638 }
613639 PacketType :: KeepAlive => {
614- write_packet_to_device ( & up_packet_sender, network_tuple, & tcb, ACK , None , None ) ?;
640+ write_packet_to_device ( & up_packet_sender, network_tuple, & tcb, None , ACK , None , None ) ?;
615641 }
616642 PacketType :: RetransmissionRequest => {
617643 if let Some ( packet) = tcb. find_inflight_packet ( incoming_ack) {
@@ -620,7 +646,7 @@ async fn tcp_main_logic_loop(
620646 "{network_tuple} {state:?}: {l_info}, {pkt_type:?}, retransmission request, seq = {s}, len = {}" ,
621647 p. len( )
622648 ) ;
623- write_packet_to_device ( & up_packet_sender, network_tuple, & tcb, ACK | PSH , Some ( s) , Some ( p) ) ?;
649+ write_packet_to_device ( & up_packet_sender, network_tuple, & tcb, None , ACK | PSH , Some ( s) , Some ( p) ) ?;
624650 }
625651 }
626652 PacketType :: NewPacket => {
@@ -637,7 +663,7 @@ async fn tcp_main_logic_loop(
637663 } else if flags == ( ACK | FIN ) {
638664 // The other side is closing the connection, we need to send an ACK and change state to CloseWait
639665 tcb. increase_ack ( ) ;
640- write_packet_to_device ( & up_packet_sender, network_tuple, & tcb, ACK , None , None ) ?;
666+ write_packet_to_device ( & up_packet_sender, network_tuple, & tcb, None , ACK , None , None ) ?;
641667 tcb. change_state ( TcpState :: CloseWait ) ;
642668
643669 let s = tcb. get_state ( ) ;
@@ -647,7 +673,7 @@ async fn tcp_main_logic_loop(
647673 log:: trace!( "{network_tuple} {s:?}: {l_info}, {pkt_type:?}, closed by the other side, no upstream data" ) ;
648674
649675 // Here we don't wait, just send FIN to the other side and change state to LastAck directly,
650- write_packet_to_device ( & up_packet_sender, network_tuple, & tcb, ACK | FIN , None , None ) ?;
676+ write_packet_to_device ( & up_packet_sender, network_tuple, & tcb, None , ACK | FIN , None , None ) ?;
651677 tcb. increase_seq ( ) ;
652678 tcb. change_state ( TcpState :: LastAck ) ;
653679
@@ -696,7 +722,7 @@ async fn tcp_main_logic_loop(
696722 }
697723 TcpState :: CloseWait => {
698724 if flags & ACK == ACK && tcb. get_inflight_packets_total_len ( ) == 0 {
699- write_packet_to_device ( & up_packet_sender, network_tuple, & tcb, ACK | FIN , None , None ) ?;
725+ write_packet_to_device ( & up_packet_sender, network_tuple, & tcb, None , ACK | FIN , None , None ) ?;
700726 tcb. increase_seq ( ) ;
701727 tcb. change_state ( TcpState :: LastAck ) ;
702728 let new_state = tcb. get_state ( ) ;
@@ -734,7 +760,7 @@ async fn tcp_main_logic_loop(
734760 if flags & ( ACK | FIN ) == ( ACK | FIN ) && len == 0 {
735761 // If the received packet is an ACK with FIN, we need to send an ACK and change state to TimeWait directly, not to FinWait2
736762 tcb. increase_ack ( ) ;
737- write_packet_to_device ( & up_packet_sender, network_tuple, & tcb, ACK , None , None ) ?;
763+ write_packet_to_device ( & up_packet_sender, network_tuple, & tcb, None , ACK , None , None ) ?;
738764 tcb. change_state ( TcpState :: TimeWait ) ;
739765
740766 tokio:: spawn ( task_wait_to_close ( tcb_clone. clone ( ) , exit_notifier, network_tuple, config. two_msl ) ) ;
@@ -758,7 +784,7 @@ async fn tcp_main_logic_loop(
758784 TcpState :: FinWait2 => {
759785 if flags & ( ACK | FIN ) == ( ACK | FIN ) && len == 0 {
760786 tcb. increase_ack ( ) ;
761- write_packet_to_device ( & up_packet_sender, network_tuple, & tcb, ACK , None , None ) ?;
787+ write_packet_to_device ( & up_packet_sender, network_tuple, & tcb, None , ACK , None , None ) ?;
762788 tcb. change_state ( TcpState :: TimeWait ) ;
763789 tokio:: spawn ( task_wait_to_close ( tcb_clone. clone ( ) , exit_notifier, network_tuple, config. two_msl ) ) ;
764790 let new_state = tcb. get_state ( ) ;
@@ -771,7 +797,7 @@ async fn tcp_main_logic_loop(
771797 }
772798 } else if flags & ACK == ACK && len > 0 {
773799 if pkt_type == PacketType :: KeepAlive {
774- write_packet_to_device ( & up_packet_sender, network_tuple, & tcb, ACK , None , None ) ?;
800+ write_packet_to_device ( & up_packet_sender, network_tuple, & tcb, None , ACK , None , None ) ?;
775801 } else {
776802 // if the other side is still sending data, we need to deal with it like PacketStatus::NewPacket
777803 tcb. add_unordered_packet ( incoming_seq, payload) ;
@@ -791,7 +817,7 @@ async fn tcp_main_logic_loop(
791817 }
792818 TcpState :: TimeWait => {
793819 if flags & ( ACK | FIN ) == ( ACK | FIN ) {
794- write_packet_to_device ( & up_packet_sender, network_tuple, & tcb, ACK , None , None ) ?;
820+ write_packet_to_device ( & up_packet_sender, network_tuple, & tcb, None , ACK , None , None ) ?;
795821 // wait to timeout, can't call `tcb.change_state(TcpState::Closed);` to change state here
796822 // now we need to wait for the timeout to reach...
797823 }
@@ -824,7 +850,7 @@ fn extract_data_n_write_upstream(
824850 log:: trace!( "{network_tuple} {state:?}: {l_info} {hint} receiving data, len = {}" , data. len( ) ) ;
825851 data_tx. send ( data) . map_err ( |e| std:: io:: Error :: new ( BrokenPipe , e) ) ?;
826852 read_notify. lock ( ) . unwrap ( ) . take ( ) . map ( |w| w. wake_by_ref ( ) ) . unwrap_or ( ( ) ) ;
827- write_packet_to_device ( up_packet_sender, network_tuple, tcb, ACK , None , None ) ?;
853+ write_packet_to_device ( up_packet_sender, network_tuple, tcb, None , ACK , None , None ) ?;
828854 }
829855 Ok ( ( ) )
830856}
@@ -835,6 +861,7 @@ pub(crate) fn write_packet_to_device(
835861 up_packet_sender : & PacketSender ,
836862 tuple : NetworkTuple ,
837863 tcb : & Tcb ,
864+ options : Option < & Vec < TcpOptions > > ,
838865 flags : u8 ,
839866 seq : Option < SeqNum > ,
840867 payload : Option < Vec < u8 > > ,
@@ -844,7 +871,18 @@ pub(crate) fn write_packet_to_device(
844871 let ( ack, window_size) = ( tcb. get_ack ( ) . 0 , tcb. get_recv_window ( ) . max ( tcb. get_mtu ( ) ) ) ;
845872 let ( src, dst) = ( tuple. dst , tuple. src ) ; // Note: The address is reversed here
846873 let calc = |ip_header_len : usize , tcp_header_len : usize | tcb. calculate_payload_max_len ( ip_header_len, tcp_header_len) ;
847- let packet = create_raw_packet ( src, dst, calc, flags, TTL , seq, ack, window_size, payload. unwrap_or_default ( ) ) ?;
874+ let packet = create_raw_packet (
875+ src,
876+ dst,
877+ calc,
878+ flags,
879+ TTL ,
880+ seq,
881+ ack,
882+ window_size,
883+ payload. unwrap_or_default ( ) ,
884+ options,
885+ ) ?;
848886 let len = packet. payload . as_ref ( ) . map ( |p| p. len ( ) ) . unwrap_or ( 0 ) ;
849887 up_packet_sender. send ( packet) . map_err ( |e| Error :: new ( UnexpectedEof , e) ) ?;
850888 Ok ( len)
@@ -861,6 +899,7 @@ pub(crate) fn create_raw_packet(
861899 ack : u32 ,
862900 win : u16 ,
863901 mut payload : Vec < u8 > ,
902+ options : Option < & Vec < TcpOptions > > ,
864903) -> std:: io:: Result < NetworkPacket > {
865904 let mut tcp_header = etherparse:: TcpHeader :: new ( src_addr. port ( ) , dst_addr. port ( ) , seq, win) ;
866905 tcp_header. acknowledgment_number = ack;
@@ -870,6 +909,17 @@ pub(crate) fn create_raw_packet(
870909 tcp_header. fin = flags & FIN != 0 ;
871910 tcp_header. psh = flags & PSH != 0 ;
872911
912+ if let Some ( opts) = options {
913+ let mut tcp_options = Vec :: new ( ) ;
914+ for opt in opts {
915+ match opt {
916+ TcpOptions :: MaximumSegmentSize ( mss) => tcp_options. push ( TcpOptionElement :: MaximumSegmentSize ( * mss) ) ,
917+ }
918+ }
919+ tcp_header
920+ . set_options ( & tcp_options)
921+ . map_err ( |e| std:: io:: Error :: new ( InvalidInput , e) ) ?;
922+ }
873923 let ip_header = match ( src_addr. ip ( ) , dst_addr. ip ( ) ) {
874924 ( std:: net:: IpAddr :: V4 ( src) , std:: net:: IpAddr :: V4 ( dst) ) => {
875925 let mut ip_h =
0 commit comments