@@ -2092,6 +2092,7 @@ START_TEST(test_sock_bind_icmp_success)
20922092
20932093 ck_assert_int_eq(wolfIP_sock_bind(&s, icmp_sd, (struct wolfIP_sockaddr *)&sin, sizeof(sin)), 0);
20942094 ck_assert_uint_eq(ts->src_port, 7U);
2095+ ck_assert_uint_eq(ts->bound_local_ip, 0x0A000001U);
20952096}
20962097END_TEST
20972098
@@ -2255,7 +2256,7 @@ START_TEST(test_dns_query_and_callback_a)
22552256
22562257 dns_callback(s.dns_udp_sd, CB_EVENT_READABLE, &s);
22572258 ck_assert_int_eq(dns_lookup_calls, 1);
2258- ck_assert_uint_eq(dns_lookup_ip, ee32( 0x0A000042U) );
2259+ ck_assert_uint_eq(dns_lookup_ip, 0x0A000042U);
22592260 ck_assert_int_eq(s.dns_id, 0);
22602261 ck_assert_int_eq(s.dns_query_type, DNS_QUERY_TYPE_NONE);
22612262}
@@ -2741,6 +2742,33 @@ START_TEST(test_sock_connect_icmp_primary_ip_fallback)
27412742}
27422743END_TEST
27432744
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+
27442772START_TEST(test_sock_connect_tcp_established_returns_zero)
27452773{
27462774 struct wolfIP s;
@@ -7765,6 +7793,136 @@ START_TEST(test_dns_callback_short_header_ignored)
77657793}
77667794END_TEST
77677795
7796+ START_TEST(test_dns_callback_wrong_id_ignored)
7797+ {
7798+ struct wolfIP s;
7799+ uint8_t response[128];
7800+ int pos;
7801+ struct dns_header *hdr = (struct dns_header *)response;
7802+ struct dns_question *q;
7803+ struct dns_rr *rr;
7804+ const uint8_t ip_bytes[4] = {0x0A, 0x00, 0x00, 0x42};
7805+
7806+ wolfIP_init(&s);
7807+ mock_link_init(&s);
7808+ s.dns_server = 0x0A000001U;
7809+ s.dns_query_type = DNS_QUERY_TYPE_A;
7810+ s.dns_id = 0x1234;
7811+ s.dns_lookup_cb = test_dns_lookup_cb;
7812+ dns_lookup_calls = 0;
7813+ dns_lookup_ip = 0;
7814+ s.dns_udp_sd = wolfIP_sock_socket(&s, AF_INET, IPSTACK_SOCK_DGRAM, WI_IPPROTO_UDP);
7815+ ck_assert_int_gt(s.dns_udp_sd, 0);
7816+
7817+ memset(response, 0, sizeof(response));
7818+ hdr->id = ee16(0x4321);
7819+ hdr->flags = ee16(0x8100);
7820+ hdr->qdcount = ee16(1);
7821+ hdr->ancount = ee16(1);
7822+ pos = sizeof(struct dns_header);
7823+ response[pos++] = 7; memcpy(&response[pos], "example", 7); pos += 7;
7824+ response[pos++] = 3; memcpy(&response[pos], "com", 3); pos += 3;
7825+ response[pos++] = 0;
7826+ q = (struct dns_question *)(response + pos);
7827+ q->qtype = ee16(DNS_A);
7828+ q->qclass = ee16(1);
7829+ pos += sizeof(struct dns_question);
7830+ response[pos++] = 0xC0;
7831+ response[pos++] = (uint8_t)sizeof(struct dns_header);
7832+ rr = (struct dns_rr *)(response + pos);
7833+ rr->type = ee16(DNS_A);
7834+ rr->class = ee16(1);
7835+ rr->ttl = ee32(60);
7836+ rr->rdlength = ee16(4);
7837+ pos += sizeof(struct dns_rr);
7838+ memcpy(&response[pos], ip_bytes, sizeof(ip_bytes));
7839+ pos += sizeof(ip_bytes);
7840+
7841+ enqueue_udp_rx(&s.udpsockets[SOCKET_UNMARK(s.dns_udp_sd)], response, (uint16_t)pos, DNS_PORT);
7842+ dns_callback(s.dns_udp_sd, CB_EVENT_READABLE, &s);
7843+ ck_assert_int_eq(dns_lookup_calls, 0);
7844+ ck_assert_uint_eq(dns_lookup_ip, 0U);
7845+ ck_assert_uint_eq(s.dns_id, 0x1234);
7846+ ck_assert_int_eq(s.dns_query_type, DNS_QUERY_TYPE_A);
7847+ }
7848+ END_TEST
7849+
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+
77687926START_TEST(test_tcp_input_ttl_zero_sends_icmp)
77697927{
77707928 struct wolfIP s;
@@ -14311,6 +14469,48 @@ START_TEST(test_tcp_ack_coarse_rtt_sets_writable)
1431114469}
1431214470END_TEST
1431314471
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+
1431414514START_TEST(test_tcp_ack_duplicate_clears_sent_large_seg_len)
1431514515{
1431614516 struct wolfIP s;
@@ -15292,6 +15492,68 @@ START_TEST(test_tcp_input_established_ack_only_returns)
1529215492}
1529315493END_TEST
1529415494
15495+ START_TEST(test_tcp_input_close_wait_processes_ack)
15496+ {
15497+ struct wolfIP s;
15498+ struct tsocket *ts;
15499+ struct tcp_seg_buf segbuf;
15500+ struct wolfIP_tcp_seg *queued;
15501+ struct wolfIP_tcp_seg ackseg;
15502+ struct pkt_desc *desc;
15503+
15504+ wolfIP_init(&s);
15505+ mock_link_init(&s);
15506+ wolfIP_ipconfig_set(&s, 0x0A000001U, 0xFFFFFF00U, 0);
15507+
15508+ ts = &s.tcpsockets[0];
15509+ memset(ts, 0, sizeof(*ts));
15510+ ts->proto = WI_IPPROTO_TCP;
15511+ ts->S = &s;
15512+ ts->sock.tcp.state = TCP_CLOSE_WAIT;
15513+ ts->src_port = 1234;
15514+ ts->dst_port = 4321;
15515+ ts->local_ip = 0x0A000001U;
15516+ ts->remote_ip = 0x0A000002U;
15517+ ts->sock.tcp.snd_una = 100;
15518+ ts->sock.tcp.seq = 101;
15519+ ts->sock.tcp.bytes_in_flight = 1;
15520+ fifo_init(&ts->sock.tcp.txbuf, ts->txmem, TXBUF_SIZE);
15521+
15522+ memset(&segbuf, 0, sizeof(segbuf));
15523+ queued = &segbuf.seg;
15524+ queued->ip.len = ee16(IP_HEADER_LEN + TCP_HEADER_LEN + 1);
15525+ queued->hlen = TCP_HEADER_LEN << 2;
15526+ queued->seq = ee32(100);
15527+ ck_assert_int_eq(fifo_push(&ts->sock.tcp.txbuf, &segbuf, sizeof(segbuf)), 0);
15528+ desc = fifo_peek(&ts->sock.tcp.txbuf);
15529+ ck_assert_ptr_nonnull(desc);
15530+ desc->flags |= PKT_FLAG_SENT;
15531+
15532+ memset(&ackseg, 0, sizeof(ackseg));
15533+ ackseg.ip.ver_ihl = 0x45;
15534+ ackseg.ip.ttl = 64;
15535+ ackseg.ip.proto = WI_IPPROTO_TCP;
15536+ ackseg.ip.len = ee16(IP_HEADER_LEN + TCP_HEADER_LEN);
15537+ ackseg.ip.src = ee32(ts->remote_ip);
15538+ ackseg.ip.dst = ee32(ts->local_ip);
15539+ ackseg.src_port = ee16(ts->dst_port);
15540+ ackseg.dst_port = ee16(ts->src_port);
15541+ ackseg.hlen = TCP_HEADER_LEN << 2;
15542+ ackseg.flags = TCP_FLAG_ACK;
15543+ ackseg.ack = ee32(101);
15544+ ackseg.win = ee16(32);
15545+ fix_tcp_checksums(&ackseg);
15546+
15547+ tcp_input(&s, TEST_PRIMARY_IF, &ackseg,
15548+ (uint32_t)(ETH_HEADER_LEN + IP_HEADER_LEN + TCP_HEADER_LEN));
15549+
15550+ ck_assert_int_eq(ts->sock.tcp.state, TCP_CLOSE_WAIT);
15551+ ck_assert_uint_eq(ts->sock.tcp.snd_una, 101U);
15552+ ck_assert_uint_eq(ts->sock.tcp.bytes_in_flight, 0U);
15553+ ck_assert_ptr_eq(fifo_peek(&ts->sock.tcp.txbuf), NULL);
15554+ }
15555+ END_TEST
15556+
1529515557START_TEST(test_tcp_sock_close_state_transitions)
1529615558{
1529715559 struct wolfIP s;
@@ -18003,6 +18265,38 @@ START_TEST(test_icmp_socket_send_recv)
1800318265}
1800418266END_TEST
1800518267
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+
1800618300START_TEST(test_regression_snd_una_initialized_on_syn_rcvd)
1800718301{
1800818302 struct wolfIP s;
@@ -18498,6 +18792,7 @@ Suite *wolf_suite(void)
1849818792 tcase_add_test(tc_utils, test_sock_connect_udp_bound_local_ip_no_match);
1849918793 tcase_add_test(tc_utils, test_sock_connect_udp_bound_local_ip_match);
1850018794 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);
1850118796 tcase_add_test(tc_utils, test_sock_connect_icmp_wrong_family);
1850218797 tcase_add_test(tc_utils, test_sock_connect_icmp_local_ip_pre_set);
1850318798 tcase_add_test(tc_utils, test_sock_connect_icmp_conf_null);
@@ -18630,6 +18925,9 @@ Suite *wolf_suite(void)
1863018925 tcase_add_test(tc_utils, test_dns_callback_bad_flags);
1863118926 tcase_add_test(tc_utils, test_dns_callback_bad_name);
1863218927 tcase_add_test(tc_utils, test_dns_callback_short_header_ignored);
18928+ 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);
1863318931 tcase_add_test(tc_utils, test_tcp_input_ttl_zero_sends_icmp);
1863418932 tcase_add_test(tc_utils, test_dns_callback_bad_rr_rdlen);
1863518933 tcase_add_test(tc_utils, test_dhcp_parse_offer_no_match);
@@ -18716,6 +19014,7 @@ Suite *wolf_suite(void)
1871619014 tcase_add_test(tc_utils, test_tcp_input_port_mismatch_skips_socket);
1871719015 tcase_add_test(tc_utils, test_tcp_input_syn_bound_ip_mismatch);
1871819016 tcase_add_test(tc_utils, test_tcp_input_syn_rcvd_ack_wrong_flags);
19017+ tcase_add_test(tc_utils, test_tcp_input_close_wait_processes_ack);
1871919018 tcase_add_test(tc_utils, test_tcp_input_established_ack_only_returns);
1872019019 tcase_add_test(tc_utils, test_tcp_input_syn_dst_not_local);
1872119020 tcase_add_test(tc_utils, test_tcp_input_syn_dst_outside_subnet);
@@ -18746,6 +19045,7 @@ Suite *wolf_suite(void)
1874619045 tcase_add_test(tc_utils, test_tcp_ack_last_seq_not_last_ack_state);
1874719046 tcase_add_test(tc_utils, test_tcp_ack_no_progress_when_ack_far_ahead);
1874819047 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);
1874919049 tcase_add_test(tc_utils, test_tcp_ack_duplicate_clears_sent_large_seg_len);
1875019050 tcase_add_test(tc_utils, test_tcp_ack_duplicate_discards_zero_len_segment_far_ack);
1875119051 tcase_add_test(tc_utils, test_tcp_ack_duplicate_ssthresh_min);
@@ -18771,6 +19071,7 @@ Suite *wolf_suite(void)
1877119071 tcase_add_test(tc_utils, test_tcp_send_syn_advertises_sack_permitted);
1877219072 tcase_add_test(tc_utils, test_tcp_build_ack_options_does_not_write_past_returned_len);
1877319073 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);
1877419075 tcase_add_test(tc_utils, test_tcp_sort_sack_blocks_swaps_out_of_order);
1877519076 tcase_add_test(tc_utils, test_tcp_sort_sack_blocks_wrap_order);
1877619077 tcase_add_test(tc_utils, test_tcp_merge_sack_blocks_adjacent_and_disjoint);
0 commit comments