@@ -2742,6 +2742,33 @@ START_TEST(test_sock_connect_icmp_primary_ip_fallback)
27422742}
27432743END_TEST
27442744
2745+ START_TEST(test_sock_connect_icmp_bound_local_ip_match)
2746+ {
2747+ struct wolfIP s;
2748+ const ip4 primary_ip = 0xC0A80009U;
2749+ const ip4 secondary_ip = 0xC0A80109U;
2750+ const ip4 remote_secondary = 0xC0A801A1U;
2751+ int icmp_sd;
2752+ struct tsocket *ts;
2753+ struct wolfIP_sockaddr_in sin;
2754+
2755+ setup_stack_with_two_ifaces(&s, primary_ip, secondary_ip);
2756+
2757+ icmp_sd = wolfIP_sock_socket(&s, AF_INET, IPSTACK_SOCK_DGRAM, WI_IPPROTO_ICMP);
2758+ ck_assert_int_gt(icmp_sd, 0);
2759+ ts = &s.icmpsockets[SOCKET_UNMARK(icmp_sd)];
2760+ ts->bound_local_ip = primary_ip;
2761+
2762+ memset(&sin, 0, sizeof(sin));
2763+ sin.sin_family = AF_INET;
2764+ sin.sin_addr.s_addr = ee32(remote_secondary);
2765+
2766+ ck_assert_int_eq(wolfIP_sock_connect(&s, icmp_sd, (struct wolfIP_sockaddr *)&sin, sizeof(sin)), 0);
2767+ ck_assert_uint_eq(ts->local_ip, primary_ip);
2768+ ck_assert_uint_eq(ts->if_idx, TEST_PRIMARY_IF);
2769+ }
2770+ END_TEST
2771+
27452772START_TEST(test_sock_connect_tcp_established_returns_zero)
27462773{
27472774 struct wolfIP s;
@@ -7820,6 +7847,82 @@ START_TEST(test_dns_callback_wrong_id_ignored)
78207847}
78217848END_TEST
78227849
7850+ START_TEST(test_dns_callback_abort_clears_query_state)
7851+ {
7852+ struct wolfIP s;
7853+ uint8_t bad_response[64];
7854+ uint8_t good_response[128];
7855+ int pos;
7856+ struct dns_header *hdr = (struct dns_header *)bad_response;
7857+ struct dns_header *good_hdr = (struct dns_header *)good_response;
7858+ struct dns_question *q;
7859+ struct dns_rr *rr;
7860+ const uint8_t ip_bytes[4] = {0x0A, 0x00, 0x00, 0x42};
7861+
7862+ wolfIP_init(&s);
7863+ mock_link_init(&s);
7864+ s.dns_server = 0x0A000001U;
7865+ s.dns_query_type = DNS_QUERY_TYPE_A;
7866+ s.dns_id = 0x1234;
7867+ s.dns_lookup_cb = test_dns_lookup_cb;
7868+ dns_lookup_calls = 0;
7869+ dns_lookup_ip = 0;
7870+ s.dns_udp_sd = wolfIP_sock_socket(&s, AF_INET, IPSTACK_SOCK_DGRAM, WI_IPPROTO_UDP);
7871+ ck_assert_int_gt(s.dns_udp_sd, 0);
7872+
7873+ memset(bad_response, 0, sizeof(bad_response));
7874+ hdr->id = ee16(s.dns_id);
7875+ hdr->flags = ee16(0x8100);
7876+ hdr->qdcount = ee16(1);
7877+ hdr->ancount = ee16(0);
7878+ pos = sizeof(struct dns_header);
7879+ bad_response[pos++] = 60;
7880+ memset(&bad_response[pos], 'a', 5);
7881+ pos += 5;
7882+
7883+ enqueue_udp_rx(&s.udpsockets[SOCKET_UNMARK(s.dns_udp_sd)], bad_response, (uint16_t)pos, DNS_PORT);
7884+ dns_callback(s.dns_udp_sd, CB_EVENT_READABLE, &s);
7885+ ck_assert_uint_eq(s.dns_id, 0);
7886+
7887+ memset(good_response, 0, sizeof(good_response));
7888+ good_hdr->id = 0;
7889+ good_hdr->flags = ee16(0x8100);
7890+ good_hdr->qdcount = ee16(1);
7891+ good_hdr->ancount = ee16(1);
7892+ pos = sizeof(struct dns_header);
7893+ good_response[pos++] = 7; memcpy(&good_response[pos], "example", 7); pos += 7;
7894+ good_response[pos++] = 3; memcpy(&good_response[pos], "com", 3); pos += 3;
7895+ good_response[pos++] = 0;
7896+ q = (struct dns_question *)(good_response + pos);
7897+ q->qtype = ee16(DNS_A);
7898+ q->qclass = ee16(1);
7899+ pos += sizeof(struct dns_question);
7900+ good_response[pos++] = 0xC0;
7901+ good_response[pos++] = (uint8_t)sizeof(struct dns_header);
7902+ rr = (struct dns_rr *)(good_response + pos);
7903+ rr->type = ee16(DNS_A);
7904+ rr->class = ee16(1);
7905+ rr->ttl = ee32(60);
7906+ rr->rdlength = ee16(4);
7907+ pos += sizeof(struct dns_rr);
7908+ memcpy(&good_response[pos], ip_bytes, sizeof(ip_bytes));
7909+ pos += sizeof(ip_bytes);
7910+
7911+ enqueue_udp_rx(&s.udpsockets[SOCKET_UNMARK(s.dns_udp_sd)], good_response, (uint16_t)pos, DNS_PORT);
7912+ dns_callback(s.dns_udp_sd, CB_EVENT_READABLE, &s);
7913+ ck_assert_int_eq(dns_lookup_calls, 0);
7914+ ck_assert_uint_eq(dns_lookup_ip, 0U);
7915+ ck_assert_int_eq(s.dns_query_type, DNS_QUERY_TYPE_NONE);
7916+ ck_assert_ptr_eq(s.dns_lookup_cb, NULL);
7917+ }
7918+ END_TEST
7919+
7920+ START_TEST(test_dns_abort_query_null_noop)
7921+ {
7922+ dns_abort_query(NULL);
7923+ }
7924+ END_TEST
7925+
78237926START_TEST(test_tcp_input_ttl_zero_sends_icmp)
78247927{
78257928 struct wolfIP s;
@@ -14366,6 +14469,48 @@ START_TEST(test_tcp_ack_coarse_rtt_sets_writable)
1436614469}
1436714470END_TEST
1436814471
14472+ START_TEST(test_tcp_ack_coarse_rtt_across_low32_wrap)
14473+ {
14474+ struct wolfIP s;
14475+ struct tsocket *ts;
14476+ struct tcp_seg_buf segbuf;
14477+ struct wolfIP_tcp_seg *seg;
14478+ struct wolfIP_tcp_seg ackseg;
14479+ struct pkt_desc *desc;
14480+
14481+ wolfIP_init(&s);
14482+ ts = &s.tcpsockets[0];
14483+ memset(ts, 0, sizeof(*ts));
14484+ ts->proto = WI_IPPROTO_TCP;
14485+ ts->S = &s;
14486+ ts->sock.tcp.state = TCP_ESTABLISHED;
14487+ ts->sock.tcp.cwnd = TCP_MSS;
14488+ ts->sock.tcp.ssthresh = TCP_MSS * 4;
14489+ fifo_init(&ts->sock.tcp.txbuf, ts->txmem, TXBUF_SIZE);
14490+ s.last_tick = (1ULL << 32) + 100U;
14491+
14492+ memset(&segbuf, 0, sizeof(segbuf));
14493+ seg = &segbuf.seg;
14494+ seg->ip.len = ee16(IP_HEADER_LEN + TCP_HEADER_LEN + 1);
14495+ seg->hlen = TCP_HEADER_LEN << 2;
14496+ seg->seq = ee32(100);
14497+ ck_assert_int_eq(fifo_push(&ts->sock.tcp.txbuf, &segbuf, sizeof(segbuf)), 0);
14498+ desc = fifo_peek(&ts->sock.tcp.txbuf);
14499+ ck_assert_ptr_nonnull(desc);
14500+ desc->flags |= PKT_FLAG_SENT;
14501+ desc->time_sent = 0xFFFFFFF0U;
14502+
14503+ memset(&ackseg, 0, sizeof(ackseg));
14504+ ackseg.ack = ee32(101);
14505+ ackseg.hlen = TCP_HEADER_LEN << 2;
14506+ ackseg.flags = TCP_FLAG_ACK;
14507+
14508+ tcp_ack(ts, &ackseg);
14509+ ck_assert_uint_eq(ts->sock.tcp.rtt, 116U);
14510+ ck_assert_uint_eq(ts->events & CB_EVENT_WRITABLE, CB_EVENT_WRITABLE);
14511+ }
14512+ END_TEST
14513+
1436914514START_TEST(test_tcp_ack_duplicate_clears_sent_large_seg_len)
1437014515{
1437114516 struct wolfIP s;
@@ -18120,6 +18265,38 @@ START_TEST(test_icmp_socket_send_recv)
1812018265}
1812118266END_TEST
1812218267
18268+ START_TEST(test_icmp_sendto_respects_bound_local_ip_interface)
18269+ {
18270+ struct wolfIP s;
18271+ const ip4 primary_ip = 0xC0A80009U;
18272+ const ip4 secondary_ip = 0xC0A80109U;
18273+ const ip4 remote_secondary = 0xC0A801A1U;
18274+ int sd;
18275+ struct tsocket *ts;
18276+ struct wolfIP_sockaddr_in sin;
18277+ uint8_t payload[ICMP_HEADER_LEN] = {0};
18278+
18279+ setup_stack_with_two_ifaces(&s, primary_ip, secondary_ip);
18280+
18281+ sd = wolfIP_sock_socket(&s, AF_INET, IPSTACK_SOCK_DGRAM, WI_IPPROTO_ICMP);
18282+ ck_assert_int_gt(sd, 0);
18283+ ts = &s.icmpsockets[SOCKET_UNMARK(sd)];
18284+ fifo_init(&ts->sock.udp.txbuf, ts->txmem, TXBUF_SIZE);
18285+ ts->bound_local_ip = primary_ip;
18286+
18287+ memset(&sin, 0, sizeof(sin));
18288+ sin.sin_family = AF_INET;
18289+ sin.sin_addr.s_addr = ee32(remote_secondary);
18290+
18291+ payload[0] = ICMP_ECHO_REQUEST;
18292+
18293+ ck_assert_int_eq(wolfIP_sock_sendto(&s, sd, payload, sizeof(payload), 0,
18294+ (struct wolfIP_sockaddr *)&sin, sizeof(sin)), (int)sizeof(payload));
18295+ ck_assert_uint_eq(ts->local_ip, primary_ip);
18296+ ck_assert_uint_eq(ts->if_idx, TEST_PRIMARY_IF);
18297+ }
18298+ END_TEST
18299+
1812318300START_TEST(test_regression_snd_una_initialized_on_syn_rcvd)
1812418301{
1812518302 struct wolfIP s;
@@ -18615,6 +18792,7 @@ Suite *wolf_suite(void)
1861518792 tcase_add_test(tc_utils, test_sock_connect_udp_bound_local_ip_no_match);
1861618793 tcase_add_test(tc_utils, test_sock_connect_udp_bound_local_ip_match);
1861718794 tcase_add_test(tc_utils, test_sock_connect_icmp_sets_local_ip_from_conf);
18795+ tcase_add_test(tc_utils, test_sock_connect_icmp_bound_local_ip_match);
1861818796 tcase_add_test(tc_utils, test_sock_connect_icmp_wrong_family);
1861918797 tcase_add_test(tc_utils, test_sock_connect_icmp_local_ip_pre_set);
1862018798 tcase_add_test(tc_utils, test_sock_connect_icmp_conf_null);
@@ -18748,6 +18926,8 @@ Suite *wolf_suite(void)
1874818926 tcase_add_test(tc_utils, test_dns_callback_bad_name);
1874918927 tcase_add_test(tc_utils, test_dns_callback_short_header_ignored);
1875018928 tcase_add_test(tc_utils, test_dns_callback_wrong_id_ignored);
18929+ tcase_add_test(tc_utils, test_dns_callback_abort_clears_query_state);
18930+ tcase_add_test(tc_utils, test_dns_abort_query_null_noop);
1875118931 tcase_add_test(tc_utils, test_tcp_input_ttl_zero_sends_icmp);
1875218932 tcase_add_test(tc_utils, test_dns_callback_bad_rr_rdlen);
1875318933 tcase_add_test(tc_utils, test_dhcp_parse_offer_no_match);
@@ -18865,6 +19045,7 @@ Suite *wolf_suite(void)
1886519045 tcase_add_test(tc_utils, test_tcp_ack_last_seq_not_last_ack_state);
1886619046 tcase_add_test(tc_utils, test_tcp_ack_no_progress_when_ack_far_ahead);
1886719047 tcase_add_test(tc_utils, test_tcp_ack_coarse_rtt_sets_writable);
19048+ tcase_add_test(tc_utils, test_tcp_ack_coarse_rtt_across_low32_wrap);
1886819049 tcase_add_test(tc_utils, test_tcp_ack_duplicate_clears_sent_large_seg_len);
1886919050 tcase_add_test(tc_utils, test_tcp_ack_duplicate_discards_zero_len_segment_far_ack);
1887019051 tcase_add_test(tc_utils, test_tcp_ack_duplicate_ssthresh_min);
@@ -18890,6 +19071,7 @@ Suite *wolf_suite(void)
1889019071 tcase_add_test(tc_utils, test_tcp_send_syn_advertises_sack_permitted);
1889119072 tcase_add_test(tc_utils, test_tcp_build_ack_options_does_not_write_past_returned_len);
1889219073 tcase_add_test(tc_utils, test_tcp_build_ack_options_omits_ts_when_not_negotiated);
19074+ tcase_add_test(tc_utils, test_icmp_sendto_respects_bound_local_ip_interface);
1889319075 tcase_add_test(tc_utils, test_tcp_sort_sack_blocks_swaps_out_of_order);
1889419076 tcase_add_test(tc_utils, test_tcp_sort_sack_blocks_wrap_order);
1889519077 tcase_add_test(tc_utils, test_tcp_merge_sack_blocks_adjacent_and_disjoint);
0 commit comments