Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/test/unit/unit.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ Suite *wolf_suite(void)
#endif
tcase_add_test(tc_utils, test_wolfip_send_port_unreachable_ignores_missing_link_sender);
tcase_add_test(tc_utils, test_wolfip_send_port_unreachable_non_ethernet_skips_eth_filter);
tcase_add_test(tc_utils, test_wolfip_send_port_unreachable_sets_df);
tcase_add_test(tc_utils, test_tcp_adv_win_clamps_and_applies_window_scale);
tcase_add_test(tc_utils, test_tcp_segment_acceptable_zero_window_and_overlap_cases);
tcase_add_test(tc_utils, test_tcp_segment_acceptable_counts_syn_in_segment_length);
Expand Down Expand Up @@ -156,6 +157,7 @@ Suite *wolf_suite(void)
tcase_add_test(tc_utils, test_sock_bind_invalid_fd);
tcase_add_test(tc_utils, test_sock_bind_tcp_state_not_closed);
tcase_add_test(tc_utils, test_sock_bind_tcp_filter_blocks);
tcase_add_test(tc_utils, test_sock_bind_tcp_port_collision_rejected);
tcase_add_test(tc_utils, test_sock_bind_udp_src_port_nonzero);
tcase_add_test(tc_utils, test_sock_bind_udp_filter_blocks);
tcase_add_test(tc_utils, test_sock_bind_icmp_success);
Expand Down Expand Up @@ -220,6 +222,7 @@ Suite *wolf_suite(void)
tcase_add_test(tc_utils, test_syn_rcvd_rst_bad_seq_dropped);
tcase_add_test(tc_utils, test_ip_recv_drops_broadcast_source);
tcase_add_test(tc_utils, test_ip_recv_drops_multicast_source);
tcase_add_test(tc_utils, test_ip_recv_drops_zero_source);
tcase_add_test(tc_utils, test_arp_recv_rejects_broadcast_sender);
tcase_add_test(tc_utils, test_arp_recv_rejects_multicast_sender);
tcase_add_test(tc_utils, test_dhcp_ack_rejects_mismatched_server_id);
Expand Down Expand Up @@ -607,6 +610,7 @@ Suite *wolf_suite(void)
tcase_add_test(tc_utils, test_tcp_recv_ooo_capacity_limit);
tcase_add_test(tc_utils, test_tcp_recv_overlapping_ooo_segments_coalesce_on_consume);
tcase_add_test(tc_utils, test_tcp_input_syn_with_sack_option_enables_sack);
tcase_add_test(tc_utils, test_tcp_input_ignores_reserved_bits_in_hlen);
tcase_add_test(tc_utils, test_tcp_input_syn_with_sack_option_respects_local_sack_offer);
tcase_add_test(tc_utils, test_tcp_input_iplen_too_big);
tcase_add_test(tc_utils, test_tcp_checksum_valid_passes);
Expand Down Expand Up @@ -653,6 +657,7 @@ Suite *wolf_suite(void)
tcase_add_test(tc_proto, test_send_ttl_exceeded_eth_filter_drop);
tcase_add_test(tc_proto, test_send_ttl_exceeded_no_send);
tcase_add_test(tc_proto, test_send_ttl_exceeded_non_ethernet_skips_eth_filter);
tcase_add_test(tc_proto, test_send_ttl_exceeded_sets_df);
#if WOLFIP_ENABLE_FORWARDING
tcase_add_test(tc_proto, test_wolfip_forward_ttl_exceeded_short_len_does_not_send);
#endif
Expand Down Expand Up @@ -770,6 +775,7 @@ Suite *wolf_suite(void)
tcase_add_test(tc_proto, test_icmp_socket_send_recv);
tcase_add_test(tc_proto, test_icmp_input_echo_reply_queues);
tcase_add_test(tc_proto, test_icmp_input_echo_request_reply_sent);
tcase_add_test(tc_proto, test_icmp_input_echo_reply_sets_df);
tcase_add_test(tc_proto, test_icmp_input_echo_request_bad_checksum_dropped);
tcase_add_test(tc_proto, test_icmp_input_echo_request_odd_len_reply_checksum);
tcase_add_test(tc_proto, test_icmp_input_echo_request_dhcp_running_no_reply);
Expand All @@ -782,6 +788,7 @@ Suite *wolf_suite(void)
tcase_add_test(tc_proto, test_icmp_input_filter_drop_receiving);
tcase_add_test(tc_proto, test_icmp_input_dest_unreach_port_unreachable_keeps_established_tcp_socket);
tcase_add_test(tc_proto, test_icmp_input_dest_unreach_frag_needed_reduces_tcp_peer_mss);
tcase_add_test(tc_proto, test_icmp_input_dest_unreach_frag_needed_below_floor_preserves_peer_mss);
tcase_add_test(tc_proto, test_icmp_input_dest_unreach_port_unreachable_closes_syn_sent_tcp_socket);
tcase_add_test(tc_proto, test_icmp_input_dest_unreach_port_unreachable_quoted_ip_options_keep_established_tcp_socket);
tcase_add_test(tc_proto, test_udp_sendto_and_recvfrom);
Expand Down
86 changes: 86 additions & 0 deletions src/test/unit/unit_tests_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -1014,6 +1014,33 @@ START_TEST(test_sock_bind_tcp_filter_blocks)
}
END_TEST

START_TEST(test_sock_bind_tcp_port_collision_rejected)
{
struct wolfIP s;
int tcp_sd1, tcp_sd2;
struct wolfIP_sockaddr_in sin;

wolfIP_init(&s);
mock_link_init(&s);
wolfIP_ipconfig_set(&s, 0x0A000001U, 0xFFFFFF00U, 0);

tcp_sd1 = wolfIP_sock_socket(&s, AF_INET, IPSTACK_SOCK_STREAM, WI_IPPROTO_TCP);
ck_assert_int_gt(tcp_sd1, 0);
tcp_sd2 = wolfIP_sock_socket(&s, AF_INET, IPSTACK_SOCK_STREAM, WI_IPPROTO_TCP);
ck_assert_int_gt(tcp_sd2, 0);

memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = ee16(1234);
sin.sin_addr.s_addr = ee32(0x0A000001U);

ck_assert_int_eq(wolfIP_sock_bind(&s, tcp_sd1,
(struct wolfIP_sockaddr *)&sin, sizeof(sin)), 0);
ck_assert_int_eq(wolfIP_sock_bind(&s, tcp_sd2,
(struct wolfIP_sockaddr *)&sin, sizeof(sin)), -1);
}
END_TEST

START_TEST(test_sock_bind_udp_src_port_nonzero)
{
struct wolfIP s;
Expand Down Expand Up @@ -3974,6 +4001,65 @@ START_TEST(test_ip_recv_drops_multicast_source)
}
END_TEST

START_TEST(test_ip_recv_drops_zero_source)
{
struct wolfIP s;
int listen_sd;
struct tsocket *listener;
struct wolfIP_sockaddr_in sin;
struct wolfIP_tcp_seg seg;
struct wolfIP_ll_dev *ll;
union transport_pseudo_header ph;
static const uint8_t src_mac[6] = {0x10, 0x20, 0x30, 0x40, 0x50, 0x60};

wolfIP_init(&s);
mock_link_init(&s);
wolfIP_ipconfig_set(&s, 0x0A000001U, 0xFFFFFF00U, 0);

listen_sd = wolfIP_sock_socket(&s, AF_INET, IPSTACK_SOCK_STREAM, WI_IPPROTO_TCP);
ck_assert_int_gt(listen_sd, 0);
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = ee16(1234);
sin.sin_addr.s_addr = ee32(0x0A000001U);
ck_assert_int_eq(wolfIP_sock_bind(&s, listen_sd, (struct wolfIP_sockaddr *)&sin, sizeof(sin)), 0);
ck_assert_int_eq(wolfIP_sock_listen(&s, listen_sd, 1), 0);

listener = &s.tcpsockets[SOCKET_UNMARK(listen_sd)];

ll = wolfIP_getdev_ex(&s, TEST_PRIMARY_IF);
memset(&seg, 0, sizeof(seg));
memcpy(seg.ip.eth.dst, ll->mac, 6);
memcpy(seg.ip.eth.src, src_mac, 6);
seg.ip.eth.type = ee16(ETH_TYPE_IP);
seg.ip.ver_ihl = 0x45;
seg.ip.ttl = 64;
seg.ip.proto = WI_IPPROTO_TCP;
seg.ip.len = ee16(IP_HEADER_LEN + TCP_HEADER_LEN);
seg.ip.src = ee32(IPADDR_ANY);
seg.ip.dst = ee32(0x0A000001U);
seg.ip.csum = 0;
iphdr_set_checksum(&seg.ip);
seg.src_port = ee16(40000);
seg.dst_port = ee16(1234);
seg.seq = ee32(1);
seg.hlen = TCP_HEADER_LEN << 2;
seg.flags = TCP_FLAG_SYN;
seg.win = ee16(65535);
memset(&ph, 0, sizeof(ph));
ph.ph.src = seg.ip.src;
ph.ph.dst = seg.ip.dst;
ph.ph.proto = WI_IPPROTO_TCP;
ph.ph.len = ee16(TCP_HEADER_LEN);
seg.csum = ee16(transport_checksum(&ph, &seg.src_port));

ip_recv(&s, TEST_PRIMARY_IF, (struct wolfIP_ip_packet *)&seg,
sizeof(struct wolfIP_eth_frame) + IP_HEADER_LEN + TCP_HEADER_LEN);

ck_assert_int_eq(listener->sock.tcp.state, TCP_LISTEN);
}
END_TEST

/* Regression: arp_recv must not cache entries with broadcast, multicast,
* zero, or own-IP sender addresses. Without validation, an ARP request
* with a spoofed sender IP poisons the neighbor cache. */
Expand Down
91 changes: 91 additions & 0 deletions src/test/unit/unit_tests_dns_dhcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1758,6 +1758,37 @@ START_TEST(test_icmp_input_echo_request_reply_sent)
}
END_TEST

START_TEST(test_icmp_input_echo_reply_sets_df)
{
struct wolfIP s;
struct wolfIP_icmp_packet icmp;
struct wolfIP_icmp_packet *reply;
uint32_t frame_len;

wolfIP_init(&s);
mock_link_init(&s);
s.dhcp_state = DHCP_OFF;
wolfIP_filter_set_callback(NULL, NULL);
last_frame_sent_size = 0;

memset(&icmp, 0, sizeof(icmp));
icmp.ip.src = ee32(0x0A000002U);
icmp.ip.dst = ee32(0x0A000001U);
icmp.ip.ttl = 1;
icmp.ip.len = ee16(IP_HEADER_LEN + ICMP_HEADER_LEN);
icmp.ip.flags_fo = 0;
icmp.type = ICMP_ECHO_REQUEST;
icmp.csum = ee16(icmp_checksum(&icmp, ICMP_HEADER_LEN));
frame_len = (uint32_t)(ETH_HEADER_LEN + IP_HEADER_LEN + ICMP_HEADER_LEN);

icmp_input(&s, TEST_PRIMARY_IF, (struct wolfIP_ip_packet *)&icmp, frame_len);
ck_assert_uint_gt(last_frame_sent_size, 0);
reply = (struct wolfIP_icmp_packet *)last_frame_sent;
ck_assert_uint_eq(reply->type, ICMP_ECHO_REPLY);
ck_assert_uint_eq(ee16(reply->ip.flags_fo) & 0x4000U, 0x4000U);
}
END_TEST

START_TEST(test_icmp_input_echo_request_bad_checksum_dropped)
{
struct wolfIP s;
Expand Down Expand Up @@ -2169,6 +2200,66 @@ START_TEST(test_icmp_input_dest_unreach_frag_needed_reduces_tcp_peer_mss)
}
END_TEST

START_TEST(test_icmp_input_dest_unreach_frag_needed_below_floor_preserves_peer_mss)
{
struct wolfIP s;
struct tsocket *ts;
struct wolfIP_icmp_dest_unreachable_packet icmp;
struct wolfIP_tcp_wire_prefix *orig;
uint32_t frame_len;
uint16_t next_hop_mtu;
static const uint16_t below_floor[] = { 0U, 41U, 67U, 68U, 575U };
size_t i;

wolfIP_init(&s);
mock_link_init(&s);
wolfIP_ipconfig_set(&s, 0x0A000001U, 0xFFFFFF00U, 0);

ts = &s.tcpsockets[0];
memset(ts, 0, sizeof(*ts));
ts->proto = WI_IPPROTO_TCP;
ts->S = &s;
ts->sock.tcp.state = TCP_ESTABLISHED;
ts->local_ip = 0x0A000001U;
ts->remote_ip = 0x0A000002U;
ts->src_port = 1234;
ts->dst_port = 4321;

frame_len = (uint32_t)(ETH_HEADER_LEN + IP_HEADER_LEN + ICMP_DEST_UNREACH_SIZE);

for (i = 0; i < sizeof(below_floor) / sizeof(below_floor[0]); i++) {
ts->sock.tcp.peer_mss = 1460U;

memset(&icmp, 0, sizeof(icmp));
icmp.ip.src = ee32(0x0A0000FEU);
icmp.ip.dst = ee32(ts->local_ip);
icmp.ip.ttl = 64;
icmp.ip.proto = WI_IPPROTO_ICMP;
icmp.ip.len = ee16(IP_HEADER_LEN + ICMP_DEST_UNREACH_SIZE);
icmp.type = ICMP_DEST_UNREACH;
icmp.code = ICMP_FRAG_NEEDED;
next_hop_mtu = ee16(below_floor[i]);
memcpy(&icmp.unused[2], &next_hop_mtu, sizeof(next_hop_mtu));

orig = (struct wolfIP_tcp_wire_prefix *)icmp.orig_packet;
orig->ip.ver_ihl = 0x45;
orig->ip.proto = WI_IPPROTO_TCP;
orig->ip.src = ee32(ts->local_ip);
orig->ip.dst = ee32(ts->remote_ip);
orig->ip.len = ee16(IP_HEADER_LEN + 8U);
orig->src_port = ee16(ts->src_port);
orig->dst_port = ee16(ts->dst_port);

icmp.csum = ee16(icmp_checksum((struct wolfIP_icmp_packet *)&icmp,
ICMP_DEST_UNREACH_SIZE));

icmp_input(&s, TEST_PRIMARY_IF, (struct wolfIP_ip_packet *)&icmp, frame_len);

ck_assert_uint_eq(ts->sock.tcp.peer_mss, 1460U);
}
}
END_TEST

START_TEST(test_icmp_input_dest_unreach_port_unreachable_closes_syn_sent_tcp_socket)
{
struct wolfIP s;
Expand Down
24 changes: 24 additions & 0 deletions src/test/unit/unit_tests_proto.c
Original file line number Diff line number Diff line change
Expand Up @@ -3329,6 +3329,30 @@ START_TEST(test_wolfip_send_port_unreachable_non_ethernet_skips_eth_filter)
}
END_TEST

START_TEST(test_wolfip_send_port_unreachable_sets_df)
{
struct wolfIP s;
uint8_t orig_buf[ETH_HEADER_LEN + TTL_EXCEEDED_ORIG_PACKET_SIZE_DEFAULT];
struct wolfIP_ip_packet *orig = (struct wolfIP_ip_packet *)orig_buf;
struct wolfIP_icmp_dest_unreachable_packet *reply;

wolfIP_init(&s);
mock_link_init(&s);
wolfIP_ipconfig_set(&s, 0x0A000001U, 0xFFFFFF00U, 0);
last_frame_sent_size = 0;

memset(orig_buf, 0, sizeof(orig_buf));
orig->ver_ihl = 0x45;
orig->src = ee32(0x0A000002U);
orig->dst = ee32(0x0A000001U);

wolfIP_send_port_unreachable(&s, TEST_PRIMARY_IF, orig);
ck_assert_uint_gt(last_frame_sent_size, 0U);
reply = (struct wolfIP_icmp_dest_unreachable_packet *)last_frame_sent;
ck_assert_uint_eq(ee16(reply->ip.flags_fo) & 0x4000U, 0x4000U);
}
END_TEST

START_TEST(test_tcp_adv_win_clamps_and_applies_window_scale)
{
struct tsocket ts;
Expand Down
26 changes: 26 additions & 0 deletions src/test/unit/unit_tests_tcp_ack.c
Original file line number Diff line number Diff line change
Expand Up @@ -2457,6 +2457,32 @@ START_TEST(test_send_ttl_exceeded_non_ethernet_skips_eth_filter)
}
END_TEST

START_TEST(test_send_ttl_exceeded_sets_df)
{
struct wolfIP s;
uint8_t ip_buf[ETH_HEADER_LEN + TTL_EXCEEDED_ORIG_PACKET_SIZE_DEFAULT];
struct wolfIP_ip_packet *ip = (struct wolfIP_ip_packet *)ip_buf;
struct wolfIP_icmp_ttl_exceeded_packet *reply;

wolfIP_init(&s);
mock_link_init(&s);
wolfIP_ipconfig_set(&s, 0x0A000001U, 0xFFFFFF00U, 0);
wolfIP_filter_set_callback(NULL, NULL);
last_frame_sent_size = 0;

memset(ip_buf, 0, sizeof(ip_buf));
memcpy(ip->eth.src, "\x01\x02\x03\x04\x05\x06", 6);
ip->ver_ihl = 0x45;
ip->src = ee32(0x0A000002U);
ip->dst = ee32(0x0A000001U);

wolfIP_send_ttl_exceeded(&s, TEST_PRIMARY_IF, ip);
ck_assert_uint_gt(last_frame_sent_size, 0U);
reply = (struct wolfIP_icmp_ttl_exceeded_packet *)last_frame_sent;
ck_assert_uint_eq(ee16(reply->ip.flags_fo) & 0x4000U, 0x4000U);
}
END_TEST

#if WOLFIP_ENABLE_FORWARDING
START_TEST(test_wolfip_forward_ttl_exceeded_short_len_does_not_send)
{
Expand Down
Loading
Loading