Skip to content

Commit 0fb740d

Browse files
committed
fix regressions
1 parent 1de7e22 commit 0fb740d

File tree

4 files changed

+130
-4
lines changed

4 files changed

+130
-4
lines changed

src/test/unit/unit.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -749,6 +749,7 @@ Suite *wolf_suite(void)
749749
tcase_add_test(tc_proto, test_regression_syn_on_established_not_silently_processed);
750750
tcase_add_test(tc_proto, test_regression_syn_on_last_ack_not_silently_processed);
751751
tcase_add_test(tc_proto, test_regression_full_txbuf_still_sends_pure_ack);
752+
tcase_add_test(tc_proto, test_regression_loopback_immediate_pure_ack_uses_loopback_ll);
752753
tcase_add_test(tc_proto, test_regression_fast_recovery_cwnd_ssthresh_rfc5681);
753754
tcase_add_test(tc_proto, test_regression_paws_rejects_stale_timestamp);
754755
tcase_add_test(tc_proto, test_regression_paws_accepts_wrapped_newer_timestamp);
@@ -759,6 +760,7 @@ Suite *wolf_suite(void)
759760
tcase_add_test(tc_proto, test_regression_last_ack_rejects_out_of_window_segment);
760761
tcase_add_test(tc_proto, test_regression_dns_id_never_zero);
761762
tcase_add_test(tc_proto, test_tcp_input_listen_synack_sends_rst_and_stays_listen);
763+
tcase_add_test(tc_proto, test_tcp_input_listen_accept_final_ack_does_not_send_rst);
762764

763765
tcase_add_test(tc_utils, test_transport_checksum);
764766
tcase_add_test(tc_utils, test_iphdr_set_checksum);

src/test/unit/unit_tests_proto.c

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4754,6 +4754,52 @@ START_TEST(test_regression_full_txbuf_still_sends_pure_ack)
47544754
}
47554755
END_TEST
47564756

4757+
START_TEST(test_regression_loopback_immediate_pure_ack_uses_loopback_ll)
4758+
{
4759+
struct wolfIP s;
4760+
struct tsocket *ts;
4761+
struct wolfIP_ll_dev *loop;
4762+
struct wolfIP_tcp_seg seg;
4763+
4764+
wolfIP_init(&s);
4765+
loop = wolfIP_getdev_ex(&s, TEST_LOOPBACK_IF);
4766+
ck_assert_ptr_nonnull(loop);
4767+
loop->send = mock_send;
4768+
last_frame_sent_size = 0;
4769+
memset(last_frame_sent, 0, sizeof(last_frame_sent));
4770+
4771+
ts = &s.tcpsockets[0];
4772+
memset(ts, 0, sizeof(*ts));
4773+
ts->proto = WI_IPPROTO_TCP;
4774+
ts->S = &s;
4775+
ts->if_idx = TEST_LOOPBACK_IF;
4776+
ts->sock.tcp.state = TCP_ESTABLISHED;
4777+
ts->sock.tcp.ack = 100;
4778+
ts->sock.tcp.seq = 1000;
4779+
ts->sock.tcp.snd_una = 900;
4780+
ts->sock.tcp.cwnd = TXBUF_SIZE;
4781+
ts->sock.tcp.peer_rwnd = TXBUF_SIZE;
4782+
ts->src_port = 1234;
4783+
ts->dst_port = 4321;
4784+
ts->local_ip = 0x7F000001U;
4785+
ts->remote_ip = 0x7F000001U;
4786+
memset(&seg, 0, sizeof(seg));
4787+
seg.src_port = ee16(ts->src_port);
4788+
seg.dst_port = ee16(ts->dst_port);
4789+
seg.seq = ee32(ts->sock.tcp.seq);
4790+
seg.ack = ee32(ts->sock.tcp.ack);
4791+
seg.hlen = TCP_HEADER_LEN << 2;
4792+
seg.flags = TCP_FLAG_ACK;
4793+
4794+
ck_assert_int_eq(tcp_send_empty_immediate(ts, &seg,
4795+
(uint32_t)sizeof(seg)), 0);
4796+
ck_assert_uint_eq(ts->sock.tcp.last_ack, ts->sock.tcp.ack);
4797+
ck_assert_uint_eq(last_frame_sent_size, (uint32_t)sizeof(seg));
4798+
ck_assert_mem_eq(seg.ip.eth.dst, loop->mac, 6);
4799+
ck_assert_mem_eq(seg.ip.eth.src, loop->mac, 6);
4800+
}
4801+
END_TEST
4802+
47574803

47584804
/* RFC 5681 §3.2: fast recovery deviates in multiple ways.
47594805
* (a) ssthresh uses cwnd/2 instead of max(FlightSize/2, 2*SMSS)

src/test/unit/unit_tests_tcp_flow.c

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3875,6 +3875,55 @@ START_TEST(test_tcp_input_listen_synack_sends_rst_and_stays_listen)
38753875
}
38763876
END_TEST
38773877

3878+
START_TEST(test_tcp_input_listen_accept_final_ack_does_not_send_rst)
3879+
{
3880+
struct wolfIP s;
3881+
int listen_sd;
3882+
int client_sd;
3883+
struct tsocket *listen_ts;
3884+
struct tsocket *client_ts;
3885+
struct wolfIP_sockaddr_in sin;
3886+
3887+
wolfIP_init(&s);
3888+
mock_link_init(&s);
3889+
wolfIP_ipconfig_set(&s, 0x0A000001U, 0xFFFFFF00U, 0);
3890+
3891+
listen_sd = wolfIP_sock_socket(&s, AF_INET, IPSTACK_SOCK_STREAM, WI_IPPROTO_TCP);
3892+
ck_assert_int_gt(listen_sd, 0);
3893+
memset(&sin, 0, sizeof(sin));
3894+
sin.sin_family = AF_INET;
3895+
sin.sin_port = ee16(1234);
3896+
sin.sin_addr.s_addr = ee32(0x0A000001U);
3897+
ck_assert_int_eq(wolfIP_sock_bind(&s, listen_sd,
3898+
(struct wolfIP_sockaddr *)&sin, sizeof(sin)), 0);
3899+
ck_assert_int_eq(wolfIP_sock_listen(&s, listen_sd, 1), 0);
3900+
3901+
inject_tcp_segment(&s, TEST_PRIMARY_IF, 0x0A000002U, 0x0A000001U,
3902+
4321, 1234, 77, 0, TCP_FLAG_SYN);
3903+
3904+
listen_ts = &s.tcpsockets[SOCKET_UNMARK(listen_sd)];
3905+
ck_assert_int_eq(listen_ts->sock.tcp.state, TCP_SYN_RCVD);
3906+
3907+
client_sd = wolfIP_sock_accept(&s, listen_sd, NULL, NULL);
3908+
ck_assert_int_gt(client_sd, 0);
3909+
3910+
client_ts = &s.tcpsockets[SOCKET_UNMARK(client_sd)];
3911+
ck_assert_int_eq(listen_ts->sock.tcp.state, TCP_LISTEN);
3912+
ck_assert_int_eq(client_ts->sock.tcp.state, TCP_SYN_RCVD);
3913+
3914+
last_frame_sent_size = 0;
3915+
memset(last_frame_sent, 0, sizeof(last_frame_sent));
3916+
3917+
inject_tcp_segment(&s, TEST_PRIMARY_IF, 0x0A000002U, 0x0A000001U,
3918+
4321, 1234, client_ts->sock.tcp.ack,
3919+
tcp_seq_inc(client_ts->sock.tcp.snd_una, 1), TCP_FLAG_ACK);
3920+
3921+
ck_assert_uint_eq(last_frame_sent_size, 0U);
3922+
ck_assert_int_eq(listen_ts->sock.tcp.state, TCP_LISTEN);
3923+
ck_assert_int_eq(client_ts->sock.tcp.state, TCP_ESTABLISHED);
3924+
}
3925+
END_TEST
3926+
38783927
START_TEST(test_tcp_input_syn_bound_ip_mismatch)
38793928
{
38803929
struct wolfIP s;

src/wolfip.c

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2499,10 +2499,12 @@ static int tcp_send_empty_immediate(struct tsocket *t, struct wolfIP_tcp_seg *tc
24992499
ll = wolfIP_ll_at(t->S, tx_if);
25002500
if (!ll)
25012501
return -1;
2502-
if (wolfIP_is_loopback_if(tx_if))
2503-
return -1;
25042502
#ifdef ETHERNET
2505-
if (!wolfIP_ll_is_non_ethernet(t->S, tx_if)) {
2503+
if (wolfIP_is_loopback_if(tx_if)) {
2504+
if (t->local_ip == IPADDR_ANY || t->remote_ip == IPADDR_ANY)
2505+
return -1;
2506+
memcpy(t->nexthop_mac, ll->mac, 6);
2507+
} else if (!wolfIP_ll_is_non_ethernet(t->S, tx_if)) {
25062508
struct ipconf *conf = wolfIP_ipconf_at(t->S, tx_if);
25072509
ip4 nexthop;
25082510

@@ -3770,6 +3772,32 @@ static void tcp_ack(struct tsocket *t, const struct wolfIP_tcp_seg *tcp)
37703772

37713773
}
37723774

3775+
static int tcp_listen_ack_matches_pending_child(struct wolfIP *S,
3776+
const struct tsocket *listener, const struct wolfIP_tcp_seg *tcp)
3777+
{
3778+
int i;
3779+
uint16_t local_port = ee16(tcp->dst_port);
3780+
uint16_t remote_port = ee16(tcp->src_port);
3781+
ip4 local_ip = ee32(tcp->ip.dst);
3782+
ip4 remote_ip = ee32(tcp->ip.src);
3783+
3784+
for (i = 0; i < MAX_TCPSOCKETS; i++) {
3785+
const struct tsocket *t = &S->tcpsockets[i];
3786+
3787+
if (t == listener || t->proto == 0 || t->S == NULL)
3788+
continue;
3789+
if (t->sock.tcp.state != TCP_SYN_RCVD)
3790+
continue;
3791+
if (t->src_port != local_port || t->dst_port != remote_port)
3792+
continue;
3793+
if (t->local_ip != local_ip || t->remote_ip != remote_ip)
3794+
continue;
3795+
return 1;
3796+
}
3797+
3798+
return 0;
3799+
}
3800+
37733801
/* Preselect socket, parse options, manage handshakes, pass to application */
37743802
static void tcp_input(struct wolfIP *S, unsigned int if_idx,
37753803
struct wolfIP_tcp_seg *tcp, uint32_t frame_len)
@@ -3849,7 +3877,8 @@ static void tcp_input(struct wolfIP *S, unsigned int if_idx,
38493877
if (tcp->flags & TCP_FLAG_RST)
38503878
continue;
38513879
if (tcp->flags & TCP_FLAG_ACK) {
3852-
tcp_send_reset_reply(S, if_idx, tcp);
3880+
if (!tcp_listen_ack_matches_pending_child(S, t, tcp))
3881+
tcp_send_reset_reply(S, if_idx, tcp);
38533882
continue;
38543883
}
38553884
}

0 commit comments

Comments
 (0)