Skip to content

Commit 5edaf4f

Browse files
committed
Verified/fixed regressions indicated by copilot
1 parent 7578fbc commit 5edaf4f

4 files changed

Lines changed: 198 additions & 22 deletions

File tree

src/test/unit/unit.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,7 @@ Suite *wolf_suite(void)
342342
tcase_add_test(tc_utils, test_udp_try_recv_remote_ip_matches_local_ip);
343343
tcase_add_test(tc_utils, test_udp_try_recv_unmatched_port_sends_icmp_unreachable);
344344
tcase_add_test(tc_utils, test_udp_try_recv_unmatched_nonlocal_dst_does_not_send_icmp);
345-
tcase_add_test(tc_utils, test_udp_try_recv_full_fifo_drop_does_not_set_readable_or_suppress_icmp);
345+
tcase_add_test(tc_utils, test_udp_try_recv_full_fifo_drop_does_not_set_readable_or_send_icmp);
346346
tcase_add_test(tc_utils, test_dns_callback_bad_flags);
347347
tcase_add_test(tc_utils, test_dns_callback_truncated_response_aborts_query);
348348
tcase_add_test(tc_utils, test_dns_callback_bad_name);
@@ -426,9 +426,11 @@ Suite *wolf_suite(void)
426426
tcase_add_test(tc_utils, test_tcp_rto_cb_syn_sent_requeues_syn_and_arms_timer);
427427
tcase_add_test(tc_utils, test_tcp_input_synack_cancels_control_rto);
428428
tcase_add_test(tc_utils, test_tcp_rto_cb_last_ack_requeues_finack_and_arms_timer);
429+
tcase_add_test(tc_utils, test_tcp_rto_cb_last_ack_full_txbuf_keeps_retry_budget);
429430
tcase_add_test(tc_utils, test_tcp_ctrl_state_needs_rto_fin_wait_1_waits_for_payload_drain);
430431
tcase_add_test(tc_utils, test_tcp_rto_cb_fin_wait_1_with_data_uses_data_recovery);
431432
tcase_add_test(tc_utils, test_tcp_rto_cb_fin_wait_1_no_data_requeues_finack);
433+
tcase_add_test(tc_utils, test_tcp_rto_cb_fin_wait_1_no_data_full_txbuf_keeps_retry_budget);
432434
tcase_add_test(tc_utils, test_tcp_ack_fin_wait_1_ack_of_fin_moves_to_fin_wait_2_and_arms_timeout);
433435
tcase_add_test(tc_utils, test_tcp_ack_closing_ack_of_fin_moves_to_time_wait_and_stops_timer);
434436
tcase_add_test(tc_utils, test_tcp_rto_cb_control_retry_cap_closes_socket);
@@ -440,6 +442,8 @@ Suite *wolf_suite(void)
440442
tcase_add_test(tc_utils, test_sock_close_udp_icmp);
441443
tcase_add_test(tc_utils, test_sock_close_invalid_fds);
442444
tcase_add_test(tc_utils, test_sock_close_tcp_fin_wait_1);
445+
tcase_add_test(tc_utils, test_sock_close_tcp_established_full_txbuf_preserves_state);
446+
tcase_add_test(tc_utils, test_sock_close_tcp_close_wait_full_txbuf_preserves_state);
443447
tcase_add_test(tc_utils, test_sock_close_tcp_other_state_closes);
444448
tcase_add_test(tc_utils, test_sock_close_tcp_cancels_rto_timer);
445449
tcase_add_test(tc_utils, test_sock_close_tcp_closed_returns_minus_one);
@@ -470,6 +474,7 @@ Suite *wolf_suite(void)
470474
tcase_add_test(tc_utils, test_tcp_input_filter_drop);
471475
tcase_add_test(tc_utils, test_tcp_input_port_mismatch_skips_socket);
472476
tcase_add_test(tc_utils, test_tcp_input_remote_ip_mismatch_skips_socket);
477+
tcase_add_test(tc_utils, test_tcp_input_local_ip_mismatch_preserves_if_idx);
473478
tcase_add_test(tc_utils, test_tcp_input_unmatched_ack_sends_rst);
474479
tcase_add_test(tc_utils, test_tcp_input_unmatched_ack_nonlocal_dst_does_not_send_rst);
475480
tcase_add_test(tc_utils, test_tcp_input_unmatched_syn_sends_rst_ack);

src/test/unit/unit_tests_dns_dhcp.c

Lines changed: 127 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3241,6 +3241,38 @@ START_TEST(test_tcp_rto_cb_last_ack_requeues_finack_and_arms_timer)
32413241
}
32423242
END_TEST
32433243

3244+
START_TEST(test_tcp_rto_cb_last_ack_full_txbuf_keeps_retry_budget)
3245+
{
3246+
struct wolfIP s;
3247+
struct tsocket *ts;
3248+
3249+
wolfIP_init(&s);
3250+
ts = &s.tcpsockets[0];
3251+
memset(ts, 0, sizeof(*ts));
3252+
ts->proto = WI_IPPROTO_TCP;
3253+
ts->S = &s;
3254+
ts->sock.tcp.state = TCP_LAST_ACK;
3255+
ts->sock.tcp.rto = 100;
3256+
ts->sock.tcp.ctrl_rto_retries = 2;
3257+
ts->src_port = 12345;
3258+
ts->dst_port = 5001;
3259+
ts->local_ip = 0x0A000001U;
3260+
ts->remote_ip = 0x0A000002U;
3261+
fifo_init(&ts->sock.tcp.txbuf, ts->txmem, TXBUF_SIZE);
3262+
ts->sock.tcp.txbuf.head = 0;
3263+
ts->sock.tcp.txbuf.tail = 0;
3264+
ts->sock.tcp.txbuf.h_wrap = ts->sock.tcp.txbuf.size;
3265+
3266+
s.last_tick = 1000;
3267+
tcp_rto_cb(ts);
3268+
3269+
ck_assert_uint_eq(ts->sock.tcp.ctrl_rto_retries, 2);
3270+
ck_assert_uint_eq(ts->sock.tcp.ctrl_rto_active, 1);
3271+
ck_assert_int_ne(ts->sock.tcp.tmr_rto, NO_TIMER);
3272+
ck_assert_uint_eq(find_timer_expiry(&s, ts->sock.tcp.tmr_rto), 1400U);
3273+
}
3274+
END_TEST
3275+
32443276
START_TEST(test_tcp_ctrl_state_needs_rto_fin_wait_1_waits_for_payload_drain)
32453277
{
32463278
struct wolfIP s;
@@ -3333,6 +3365,39 @@ START_TEST(test_tcp_rto_cb_fin_wait_1_no_data_requeues_finack)
33333365
}
33343366
END_TEST
33353367

3368+
START_TEST(test_tcp_rto_cb_fin_wait_1_no_data_full_txbuf_keeps_retry_budget)
3369+
{
3370+
struct wolfIP s;
3371+
struct tsocket *ts;
3372+
3373+
wolfIP_init(&s);
3374+
ts = &s.tcpsockets[0];
3375+
memset(ts, 0, sizeof(*ts));
3376+
ts->proto = WI_IPPROTO_TCP;
3377+
ts->S = &s;
3378+
ts->sock.tcp.state = TCP_FIN_WAIT_1;
3379+
ts->sock.tcp.rto = 100;
3380+
ts->sock.tcp.ctrl_rto_retries = 2;
3381+
ts->src_port = 12345;
3382+
ts->dst_port = 5001;
3383+
ts->local_ip = 0x0A000001U;
3384+
ts->remote_ip = 0x0A000002U;
3385+
ts->sock.tcp.bytes_in_flight = 0;
3386+
fifo_init(&ts->sock.tcp.txbuf, ts->txmem, TXBUF_SIZE);
3387+
ts->sock.tcp.txbuf.head = 0;
3388+
ts->sock.tcp.txbuf.tail = 0;
3389+
ts->sock.tcp.txbuf.h_wrap = ts->sock.tcp.txbuf.size;
3390+
3391+
s.last_tick = 1000;
3392+
tcp_rto_cb(ts);
3393+
3394+
ck_assert_uint_eq(ts->sock.tcp.ctrl_rto_retries, 2);
3395+
ck_assert_uint_eq(ts->sock.tcp.ctrl_rto_active, 1);
3396+
ck_assert_int_ne(ts->sock.tcp.tmr_rto, NO_TIMER);
3397+
ck_assert_uint_eq(find_timer_expiry(&s, ts->sock.tcp.tmr_rto), 1400U);
3398+
}
3399+
END_TEST
3400+
33363401
START_TEST(test_tcp_ack_fin_wait_1_ack_of_fin_moves_to_fin_wait_2_and_arms_timeout)
33373402
{
33383403
struct wolfIP s;
@@ -3990,6 +4055,66 @@ START_TEST(test_sock_close_tcp_fin_wait_1)
39904055
}
39914056
END_TEST
39924057

4058+
START_TEST(test_sock_close_tcp_established_full_txbuf_preserves_state)
4059+
{
4060+
struct wolfIP s;
4061+
struct tsocket *ts;
4062+
int sd;
4063+
4064+
wolfIP_init(&s);
4065+
mock_link_init(&s);
4066+
4067+
sd = wolfIP_sock_socket(&s, AF_INET, IPSTACK_SOCK_STREAM, WI_IPPROTO_TCP);
4068+
ck_assert_int_gt(sd, 0);
4069+
ts = &s.tcpsockets[SOCKET_UNMARK(sd)];
4070+
ts->sock.tcp.state = TCP_ESTABLISHED;
4071+
ts->src_port = 12345;
4072+
ts->dst_port = 5001;
4073+
ts->local_ip = 0x0A000001U;
4074+
ts->remote_ip = 0x0A000002U;
4075+
fifo_init(&ts->sock.tcp.txbuf, ts->txmem, TXBUF_SIZE);
4076+
ts->sock.tcp.txbuf.head = 0;
4077+
ts->sock.tcp.txbuf.tail = 0;
4078+
ts->sock.tcp.txbuf.h_wrap = ts->sock.tcp.txbuf.size;
4079+
4080+
ck_assert_int_eq(wolfIP_sock_close(&s, sd), -WOLFIP_EAGAIN);
4081+
ck_assert_int_eq(ts->sock.tcp.state, TCP_ESTABLISHED);
4082+
ck_assert_uint_eq(ts->sock.tcp.ctrl_rto_active, 0);
4083+
ck_assert_uint_eq(ts->sock.tcp.ctrl_rto_retries, 0);
4084+
ck_assert_uint_eq(ts->sock.tcp.tmr_rto, NO_TIMER);
4085+
}
4086+
END_TEST
4087+
4088+
START_TEST(test_sock_close_tcp_close_wait_full_txbuf_preserves_state)
4089+
{
4090+
struct wolfIP s;
4091+
struct tsocket *ts;
4092+
int sd;
4093+
4094+
wolfIP_init(&s);
4095+
mock_link_init(&s);
4096+
4097+
sd = wolfIP_sock_socket(&s, AF_INET, IPSTACK_SOCK_STREAM, WI_IPPROTO_TCP);
4098+
ck_assert_int_gt(sd, 0);
4099+
ts = &s.tcpsockets[SOCKET_UNMARK(sd)];
4100+
ts->sock.tcp.state = TCP_CLOSE_WAIT;
4101+
ts->src_port = 12345;
4102+
ts->dst_port = 5001;
4103+
ts->local_ip = 0x0A000001U;
4104+
ts->remote_ip = 0x0A000002U;
4105+
fifo_init(&ts->sock.tcp.txbuf, ts->txmem, TXBUF_SIZE);
4106+
ts->sock.tcp.txbuf.head = 0;
4107+
ts->sock.tcp.txbuf.tail = 0;
4108+
ts->sock.tcp.txbuf.h_wrap = ts->sock.tcp.txbuf.size;
4109+
4110+
ck_assert_int_eq(wolfIP_sock_close(&s, sd), -WOLFIP_EAGAIN);
4111+
ck_assert_int_eq(ts->sock.tcp.state, TCP_CLOSE_WAIT);
4112+
ck_assert_uint_eq(ts->sock.tcp.ctrl_rto_active, 0);
4113+
ck_assert_uint_eq(ts->sock.tcp.ctrl_rto_retries, 0);
4114+
ck_assert_uint_eq(ts->sock.tcp.tmr_rto, NO_TIMER);
4115+
}
4116+
END_TEST
4117+
39934118
START_TEST(test_sock_close_tcp_fin_wait_1_repeated_close_keeps_fin_wait_2_path)
39944119
{
39954120
struct wolfIP s;
@@ -4751,13 +4876,12 @@ START_TEST(test_udp_try_recv_unmatched_nonlocal_dst_does_not_send_icmp)
47514876
}
47524877
END_TEST
47534878

4754-
START_TEST(test_udp_try_recv_full_fifo_drop_does_not_set_readable_or_suppress_icmp)
4879+
START_TEST(test_udp_try_recv_full_fifo_drop_does_not_set_readable_or_send_icmp)
47554880
{
47564881
struct wolfIP s;
47574882
struct tsocket *ts;
47584883
uint8_t udp_buf[sizeof(struct wolfIP_udp_datagram) + 4];
47594884
struct wolfIP_udp_datagram *udp = (struct wolfIP_udp_datagram *)udp_buf;
4760-
struct wolfIP_icmp_dest_unreachable_packet *icmp;
47614885
uint32_t local_ip = 0x0A000001U;
47624886
uint32_t remote_ip = 0x0A000002U;
47634887
uint8_t src_mac[6] = {0x20, 0x21, 0x22, 0x23, 0x24, 0x25};
@@ -4811,12 +4935,7 @@ START_TEST(test_udp_try_recv_full_fifo_drop_does_not_set_readable_or_suppress_ic
48114935
ck_assert_uint_eq(ts->sock.udp.rxbuf.head, head_before);
48124936
ck_assert_uint_eq(ts->sock.udp.rxbuf.tail, tail_before);
48134937
ck_assert_uint_eq(ts->sock.udp.rxbuf.h_wrap, h_wrap_before);
4814-
ck_assert_uint_eq(last_frame_sent_size,
4815-
sizeof(struct wolfIP_icmp_dest_unreachable_packet));
4816-
4817-
icmp = (struct wolfIP_icmp_dest_unreachable_packet *)last_frame_sent;
4818-
ck_assert_uint_eq(icmp->type, 3U);
4819-
ck_assert_uint_eq(icmp->code, 3U);
4938+
ck_assert_uint_eq(last_frame_sent_size, 0U);
48204939
}
48214940
END_TEST
48224941

src/test/unit/unit_tests_tcp_flow.c

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3676,6 +3676,7 @@ START_TEST(test_tcp_input_remote_ip_mismatch_skips_socket)
36763676
ts->dst_port = 4321;
36773677
ts->local_ip = 0x0A000001U;
36783678
ts->remote_ip = 0x0A000002U;
3679+
ts->if_idx = TEST_SECOND_IF;
36793680
ts->sock.tcp.peer_rwnd = 100;
36803681

36813682
memset(&seg, 0, sizeof(seg));
@@ -3695,6 +3696,50 @@ START_TEST(test_tcp_input_remote_ip_mismatch_skips_socket)
36953696
tcp_input(&s, TEST_PRIMARY_IF, &seg, (uint32_t)(ETH_HEADER_LEN + IP_HEADER_LEN + TCP_HEADER_LEN));
36963697
ck_assert_int_eq(ts->sock.tcp.state, TCP_ESTABLISHED);
36973698
ck_assert_uint_eq(ts->sock.tcp.peer_rwnd, 100);
3699+
ck_assert_uint_eq(ts->if_idx, TEST_SECOND_IF);
3700+
}
3701+
END_TEST
3702+
3703+
START_TEST(test_tcp_input_local_ip_mismatch_preserves_if_idx)
3704+
{
3705+
struct wolfIP s;
3706+
struct wolfIP_tcp_seg seg;
3707+
struct tsocket *ts;
3708+
3709+
wolfIP_init(&s);
3710+
mock_link_init(&s);
3711+
wolfIP_ipconfig_set(&s, 0x0A000001U, 0xFFFFFF00U, 0);
3712+
3713+
ts = &s.tcpsockets[0];
3714+
memset(ts, 0, sizeof(*ts));
3715+
ts->proto = WI_IPPROTO_TCP;
3716+
ts->S = &s;
3717+
ts->sock.tcp.state = TCP_ESTABLISHED;
3718+
ts->src_port = 1234;
3719+
ts->dst_port = 4321;
3720+
ts->local_ip = 0x0A000001U;
3721+
ts->remote_ip = 0x0A000002U;
3722+
ts->if_idx = TEST_SECOND_IF;
3723+
ts->sock.tcp.peer_rwnd = 100;
3724+
3725+
memset(&seg, 0, sizeof(seg));
3726+
seg.ip.ver_ihl = 0x45;
3727+
seg.ip.ttl = 64;
3728+
seg.ip.proto = WI_IPPROTO_TCP;
3729+
seg.ip.len = ee16(IP_HEADER_LEN + TCP_HEADER_LEN);
3730+
seg.ip.src = ee32(ts->remote_ip);
3731+
seg.ip.dst = ee32(0x0A000003U);
3732+
seg.dst_port = ee16(ts->src_port);
3733+
seg.src_port = ee16(ts->dst_port);
3734+
seg.hlen = TCP_HEADER_LEN << 2;
3735+
seg.flags = TCP_FLAG_ACK;
3736+
seg.win = ee16(777);
3737+
fix_tcp_checksums(&seg);
3738+
3739+
tcp_input(&s, TEST_PRIMARY_IF, &seg, (uint32_t)(ETH_HEADER_LEN + IP_HEADER_LEN + TCP_HEADER_LEN));
3740+
ck_assert_int_eq(ts->sock.tcp.state, TCP_ESTABLISHED);
3741+
ck_assert_uint_eq(ts->sock.tcp.peer_rwnd, 100);
3742+
ck_assert_uint_eq(ts->if_idx, TEST_SECOND_IF);
36983743
}
36993744
END_TEST
37003745

src/wolfip.c

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1910,10 +1910,11 @@ static void udp_try_recv(struct wolfIP *s, unsigned int if_idx,
19101910
expected_len = ee16(udp->len) + IP_HEADER_LEN + ETH_HEADER_LEN;
19111911
if ((int)frame_len < (int)expected_len)
19121912
return;
1913-
/* Insert into socket buffer */
1913+
/* A bound socket matched this datagram. If the RX FIFO is full,
1914+
* drop silently instead of misreporting the port as closed. */
1915+
matched = 1;
19141916
if (fifo_push(&t->sock.udp.rxbuf, udp, frame_len) == 0) {
19151917
t->events |= CB_EVENT_READABLE;
1916-
matched = 1;
19171918
}
19181919
}
19191920
}
@@ -2537,7 +2538,7 @@ static int tcp_send_empty_immediate(struct tsocket *t, struct wolfIP_tcp_seg *tc
25372538
return 0;
25382539
}
25392540

2540-
static void tcp_send_empty(struct tsocket *t, uint8_t flags)
2541+
static int tcp_send_empty(struct tsocket *t, uint8_t flags)
25412542
{
25422543
struct wolfIP_tcp_seg *tcp;
25432544
uint8_t opt_len;
@@ -2557,17 +2558,18 @@ static void tcp_send_empty(struct tsocket *t, uint8_t flags)
25572558
tcp->urg = 0;
25582559
frame_len = sizeof(struct wolfIP_tcp_seg) + opt_len;
25592560
if (fifo_push(&t->sock.tcp.txbuf, tcp, frame_len) == 0)
2560-
return;
2561+
return 0;
25612562

25622563
/* Pure ACKs have no retransmission path, so do not drop them when the
25632564
* shared data/control TX FIFO is saturated by already queued payload. */
25642565
if (flags == TCP_FLAG_ACK)
2565-
(void)tcp_send_empty_immediate(t, tcp, frame_len);
2566+
return tcp_send_empty_immediate(t, tcp, frame_len);
2567+
return -1;
25662568
}
25672569

25682570
static void tcp_send_ack(struct tsocket *t)
25692571
{
2570-
return tcp_send_empty(t, TCP_FLAG_ACK);
2572+
(void)tcp_send_empty(t, TCP_FLAG_ACK);
25712573
}
25722574

25732575
static void tcp_send_reset_reply(struct wolfIP *s, unsigned int if_idx,
@@ -2644,10 +2646,12 @@ static void tcp_send_reset_reply(struct wolfIP *s, unsigned int if_idx,
26442646
wolfIP_ll_send_frame(s, if_idx, &out.ip, sizeof(out));
26452647
}
26462648

2647-
static void tcp_send_finack(struct tsocket *t)
2649+
static int tcp_send_finack(struct tsocket *t)
26482650
{
2649-
tcp_send_empty(t, TCP_FLAG_FIN | TCP_FLAG_ACK);
2651+
if (tcp_send_empty(t, TCP_FLAG_FIN | TCP_FLAG_ACK) < 0)
2652+
return -1;
26502653
t->sock.tcp.last = t->sock.tcp.seq;
2654+
return 0;
26512655
}
26522656

26532657
static int tcp_send_syn(struct tsocket *t, uint8_t flags)
@@ -3809,7 +3813,6 @@ static void tcp_input(struct wolfIP *S, unsigned int if_idx,
38093813
if (t->proto == 0 || t->S == NULL)
38103814
continue;
38113815
if (t->src_port == ee16(tcp->dst_port)) {
3812-
t->if_idx = (uint8_t)if_idx;
38133816
/* TCP segment sanity checks */
38143817
iplen = ee16(tcp->ip.len);
38153818
if (iplen > frame_len - ETH_HEADER_LEN) {
@@ -3830,6 +3833,7 @@ static void tcp_input(struct wolfIP *S, unsigned int if_idx,
38303833
continue;
38313834
}
38323835
}
3836+
t->if_idx = (uint8_t)if_idx;
38333837
matched = 1;
38343838
/* Validate minimum TCP header length (data offset). */
38353839
if ((tcp->hlen >> 2) < TCP_HEADER_LEN) {
@@ -4179,8 +4183,9 @@ static void tcp_rto_cb(void *arg)
41794183
} else if (ts->sock.tcp.state == TCP_SYN_RCVD) {
41804184
queued = (tcp_send_syn(ts, TCP_FLAG_SYN | TCP_FLAG_ACK) == 0);
41814185
} else if (ts->sock.tcp.state == TCP_FIN_WAIT_1 || ts->sock.tcp.state == TCP_LAST_ACK) {
4182-
ts->sock.tcp.ctrl_rto_retries++;
4183-
tcp_send_finack(ts);
4186+
queued = (tcp_send_finack(ts) == 0);
4187+
if (queued)
4188+
ts->sock.tcp.ctrl_rto_retries++;
41844189
tcp_ctrl_rto_start(ts, ts->S->last_tick);
41854190
return;
41864191
}
@@ -5079,9 +5084,10 @@ int wolfIP_sock_close(struct wolfIP *s, int sockfd)
50795084
return -WOLFIP_EINVAL;
50805085
ts = &s->tcpsockets[SOCKET_UNMARK(sockfd)];
50815086
if (ts->sock.tcp.state == TCP_ESTABLISHED) {
5087+
if (tcp_send_finack(ts) < 0)
5088+
return -WOLFIP_EAGAIN;
50825089
ts->sock.tcp.state = TCP_FIN_WAIT_1;
50835090
ts->sock.tcp.ctrl_rto_retries = 0;
5084-
tcp_send_finack(ts);
50855091
tcp_ctrl_rto_start(ts, s->last_tick);
50865092
return -WOLFIP_EAGAIN;
50875093
} else if (ts->sock.tcp.state == TCP_LISTEN) {
@@ -5092,9 +5098,10 @@ int wolfIP_sock_close(struct wolfIP *s, int sockfd)
50925098
close_socket(ts);
50935099
return 0;
50945100
} else if (ts->sock.tcp.state == TCP_CLOSE_WAIT) {
5101+
if (tcp_send_finack(ts) < 0)
5102+
return -WOLFIP_EAGAIN;
50955103
ts->sock.tcp.state = TCP_LAST_ACK;
50965104
ts->sock.tcp.ctrl_rto_retries = 0;
5097-
tcp_send_finack(ts);
50985105
tcp_ctrl_rto_start(ts, s->last_tick);
50995106
return -WOLFIP_EAGAIN;
51005107
} else if (ts->sock.tcp.state == TCP_CLOSING) {

0 commit comments

Comments
 (0)