Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
8 changes: 8 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,8 @@ 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_recv_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 +658,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 +776,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 +789,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