@@ -4365,4 +4365,66 @@ START_TEST(test_regression_udp_checksum_zero_substituted_with_ffff)
43654365END_TEST
43664366
43674367
4368+ /* RFC 9293 s3.10.7.2: segment acceptability applies to all synchronized
4369+ * states including LAST_ACK. The current LAST_ACK handler processes ACKs
4370+ * without checking tcp_segment_acceptable, so an out-of-window ACK could
4371+ * close the connection. */
4372+ START_TEST (test_regression_last_ack_rejects_out_of_window_segment )
4373+ {
4374+ struct wolfIP s ;
4375+ struct tsocket * ts ;
4376+ struct wolfIP_tcp_seg seg ;
4377+
4378+ wolfIP_init (& s );
4379+ mock_link_init (& s );
4380+ wolfIP_ipconfig_set (& s , 0x0A000001U , 0xFFFFFF00U , 0 );
4381+
4382+ ts = & s .tcpsockets [0 ];
4383+ memset (ts , 0 , sizeof (* ts ));
4384+ ts -> proto = WI_IPPROTO_TCP ;
4385+ ts -> S = & s ;
4386+ ts -> if_idx = TEST_PRIMARY_IF ;
4387+ ts -> sock .tcp .state = TCP_LAST_ACK ;
4388+ ts -> sock .tcp .ack = 100 ;
4389+ ts -> sock .tcp .seq = 1000 ;
4390+ ts -> sock .tcp .snd_una = 1000 ;
4391+ ts -> sock .tcp .last = 999 ; /* FIN was at seq 999 */
4392+ ts -> sock .tcp .cwnd = TCP_MSS ;
4393+ ts -> sock .tcp .peer_rwnd = TCP_MSS ;
4394+ ts -> src_port = 1234 ;
4395+ ts -> dst_port = 4321 ;
4396+ ts -> local_ip = 0x0A000001U ;
4397+ ts -> remote_ip = 0x0A000002U ;
4398+ queue_init (& ts -> sock .tcp .rxbuf , ts -> rxmem , RXBUF_SIZE , ts -> sock .tcp .ack );
4399+ fifo_init (& ts -> sock .tcp .txbuf , ts -> txmem , TXBUF_SIZE );
4400+
4401+ /* Send an ACK with an out-of-window sequence number.
4402+ * rcv_nxt = 100, window = RXBUF_SIZE (20480), so seq = 99999
4403+ * is far outside the window. */
4404+ memset (& seg , 0 , sizeof (seg ));
4405+ seg .ip .ver_ihl = 0x45 ;
4406+ seg .ip .ttl = 64 ;
4407+ seg .ip .proto = WI_IPPROTO_TCP ;
4408+ seg .ip .len = ee16 (IP_HEADER_LEN + TCP_HEADER_LEN );
4409+ seg .ip .src = ee32 (ts -> remote_ip );
4410+ seg .ip .dst = ee32 (ts -> local_ip );
4411+ seg .dst_port = ee16 (ts -> src_port );
4412+ seg .src_port = ee16 (ts -> dst_port );
4413+ seg .hlen = TCP_HEADER_LEN << 2 ;
4414+ seg .flags = TCP_FLAG_ACK ;
4415+ seg .seq = ee32 (99999 );
4416+ seg .ack = ee32 (1001 ); /* ACKs the FIN */
4417+ seg .win = ee16 (65535 );
4418+ fix_tcp_checksums (& seg );
4419+
4420+ tcp_input (& s , TEST_PRIMARY_IF , & seg ,
4421+ (uint32_t )(ETH_HEADER_LEN + IP_HEADER_LEN + TCP_HEADER_LEN ));
4422+
4423+ /* The out-of-window segment must be rejected; connection must
4424+ * remain in LAST_ACK, not transition to CLOSED. */
4425+ ck_assert_int_eq (ts -> sock .tcp .state , TCP_LAST_ACK );
4426+ }
4427+ END_TEST
4428+
4429+
43684430/* ----------------------------------------------------------------------- */
0 commit comments