xref: /xnu-12377.81.4/tests/tcp_cache_test.c (revision 043036a2b3718f7f0be807e2870f8f47d3fa0796)
1*043036a2SApple OSS Distributions /*
2*043036a2SApple OSS Distributions  * Copyright (c) 2025 Apple Computer, Inc. All rights reserved.
3*043036a2SApple OSS Distributions  *
4*043036a2SApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5*043036a2SApple OSS Distributions  *
6*043036a2SApple OSS Distributions  * This file contains Original Code and/or Modifications of Original Code
7*043036a2SApple OSS Distributions  * as defined in and that are subject to the Apple Public Source License
8*043036a2SApple OSS Distributions  * Version 2.0 (the 'License'). You may not use this file except in
9*043036a2SApple OSS Distributions  * compliance with the License. The rights granted to you under the License
10*043036a2SApple OSS Distributions  * may not be used to create, or enable the creation or redistribution of,
11*043036a2SApple OSS Distributions  * unlawful or unlicensed copies of an Apple operating system, or to
12*043036a2SApple OSS Distributions  * circumvent, violate, or enable the circumvention or violation of, any
13*043036a2SApple OSS Distributions  * terms of an Apple operating system software license agreement.
14*043036a2SApple OSS Distributions  *
15*043036a2SApple OSS Distributions  * Please obtain a copy of the License at
16*043036a2SApple OSS Distributions  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17*043036a2SApple OSS Distributions  *
18*043036a2SApple OSS Distributions  * The Original Code and all software distributed under the License are
19*043036a2SApple OSS Distributions  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20*043036a2SApple OSS Distributions  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21*043036a2SApple OSS Distributions  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22*043036a2SApple OSS Distributions  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23*043036a2SApple OSS Distributions  * Please see the License for the specific language governing rights and
24*043036a2SApple OSS Distributions  * limitations under the License.
25*043036a2SApple OSS Distributions  *
26*043036a2SApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27*043036a2SApple OSS Distributions  */
28*043036a2SApple OSS Distributions 
29*043036a2SApple OSS Distributions #include <darwintest.h>
30*043036a2SApple OSS Distributions #include <sys/sysctl.h>
31*043036a2SApple OSS Distributions #include <netinet/tcp_cache.h>
32*043036a2SApple OSS Distributions #include <arpa/inet.h>
33*043036a2SApple OSS Distributions #include <stdlib.h>
34*043036a2SApple OSS Distributions 
35*043036a2SApple OSS Distributions T_DECL(tcp_cache_list_sysctl, "Test retrieving TCP cache list via sysctl")
36*043036a2SApple OSS Distributions {
37*043036a2SApple OSS Distributions 	size_t size = 0;
38*043036a2SApple OSS Distributions 	int ret;
39*043036a2SApple OSS Distributions 
40*043036a2SApple OSS Distributions 	// First call to get the required buffer size
41*043036a2SApple OSS Distributions 	ret = sysctlbyname("net.inet.tcp.cache_list", NULL, &size, NULL, 0);
42*043036a2SApple OSS Distributions 	if (ret == -1) {
43*043036a2SApple OSS Distributions 		T_SKIP("sysctlbyname(\"net.inet.tcp.cache_list\") error: %d", errno);
44*043036a2SApple OSS Distributions 	}
45*043036a2SApple OSS Distributions 
46*043036a2SApple OSS Distributions 	T_LOG("TCP cache list size: %zu bytes", size);
47*043036a2SApple OSS Distributions 
48*043036a2SApple OSS Distributions 	if (size == 0) {
49*043036a2SApple OSS Distributions 		T_PASS("No TCP cache entries found");
50*043036a2SApple OSS Distributions 	}
51*043036a2SApple OSS Distributions 
52*043036a2SApple OSS Distributions 	// Allocate buffer and retrieve the data
53*043036a2SApple OSS Distributions 	void *buffer = malloc(size);
54*043036a2SApple OSS Distributions 	T_QUIET; T_ASSERT_NOTNULL(buffer, "malloc buffer");
55*043036a2SApple OSS Distributions 
56*043036a2SApple OSS Distributions 	ret = sysctlbyname("net.inet.tcp.cache_list", buffer, &size, NULL, 0);
57*043036a2SApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(ret, "sysctlbyname to get data");
58*043036a2SApple OSS Distributions 
59*043036a2SApple OSS Distributions 	// Calculate number of entries
60*043036a2SApple OSS Distributions 	size_t num_entries = size / sizeof(struct tcp_cache_data);
61*043036a2SApple OSS Distributions 	T_LOG("Found %zu TCP cache entries", num_entries);
62*043036a2SApple OSS Distributions 
63*043036a2SApple OSS Distributions 	struct tcp_cache_data *entries = (struct tcp_cache_data *)buffer;
64*043036a2SApple OSS Distributions 
65*043036a2SApple OSS Distributions 	// Log all fields of each entry
66*043036a2SApple OSS Distributions 	for (size_t i = 0; i < num_entries; i++) {
67*043036a2SApple OSS Distributions 		struct tcp_cache_data *entry = &entries[i];
68*043036a2SApple OSS Distributions 
69*043036a2SApple OSS Distributions 		T_LOG("Entry %zu:", i);
70*043036a2SApple OSS Distributions 		T_LOG("  tc_last_access: %u", entry->tc_last_access);
71*043036a2SApple OSS Distributions 		T_LOG("  tc_key.tck_family: %d", entry->tc_key.tck_family);
72*043036a2SApple OSS Distributions 
73*043036a2SApple OSS Distributions 		// Log source key info
74*043036a2SApple OSS Distributions 		T_LOG("  tc_key.tck_src.thk_family: %d", entry->tc_key.tck_src.thk_family);
75*043036a2SApple OSS Distributions 		if (entry->tc_key.tck_src.thk_family == AF_INET) {
76*043036a2SApple OSS Distributions 			T_LOG("  tc_key.tck_src IP: %s", inet_ntoa(entry->tc_key.tck_src.thk_ip.addr));
77*043036a2SApple OSS Distributions 		} else if (entry->tc_key.tck_src.thk_family == AF_INET6) {
78*043036a2SApple OSS Distributions 			char addr_str[INET6_ADDRSTRLEN];
79*043036a2SApple OSS Distributions 			inet_ntop(AF_INET6, &entry->tc_key.tck_src.thk_ip.addr6, addr_str, sizeof(addr_str));
80*043036a2SApple OSS Distributions 			T_LOG("  tc_key.tck_src IPv6: %s", addr_str);
81*043036a2SApple OSS Distributions 		}
82*043036a2SApple OSS Distributions 
83*043036a2SApple OSS Distributions 		// Log destination address
84*043036a2SApple OSS Distributions 		if (entry->tc_key.tck_family == AF_INET) {
85*043036a2SApple OSS Distributions 			T_LOG("  tc_key.tck_dst IP: %s", inet_ntoa(entry->tc_key.tck_dst.addr));
86*043036a2SApple OSS Distributions 		} else if (entry->tc_key.tck_family == AF_INET6) {
87*043036a2SApple OSS Distributions 			char addr_str[INET6_ADDRSTRLEN];
88*043036a2SApple OSS Distributions 			inet_ntop(AF_INET6, &entry->tc_key.tck_dst.addr6, addr_str, sizeof(addr_str));
89*043036a2SApple OSS Distributions 			T_LOG("  tc_key.tck_dst IPv6: %s", addr_str);
90*043036a2SApple OSS Distributions 		}
91*043036a2SApple OSS Distributions 
92*043036a2SApple OSS Distributions 		// Log TFO cookie info
93*043036a2SApple OSS Distributions 		T_LOG("  tc_tfo_cookie_len: %u", entry->tc_tfo_cookie_len);
94*043036a2SApple OSS Distributions 		if (entry->tc_tfo_cookie_len > 0) {
95*043036a2SApple OSS Distributions 			char cookie_hex[TFO_COOKIE_LEN_MAX * 2 + 1] = {0};
96*043036a2SApple OSS Distributions 			for (int j = 0; j < entry->tc_tfo_cookie_len && j < TFO_COOKIE_LEN_MAX; j++) {
97*043036a2SApple OSS Distributions 				snprintf(cookie_hex + j * 2, 3, "%02x", entry->tc_tfo_cookie[j]);
98*043036a2SApple OSS Distributions 			}
99*043036a2SApple OSS Distributions 			T_LOG("  tc_tfo_cookie: %s", cookie_hex);
100*043036a2SApple OSS Distributions 		}
101*043036a2SApple OSS Distributions 
102*043036a2SApple OSS Distributions 		// Log MPTCP info
103*043036a2SApple OSS Distributions 		T_LOG("  tc_mptcp_version_confirmed: %u", entry->tc_mptcp_version_confirmed);
104*043036a2SApple OSS Distributions 		T_LOG("  tc_mptcp_version: %u", entry->tc_mptcp_version);
105*043036a2SApple OSS Distributions 		T_LOG("  tc_mptcp_next_version_try: %u", entry->tc_mptcp_next_version_try);
106*043036a2SApple OSS Distributions 		T_LOG(""); // Empty line between entries
107*043036a2SApple OSS Distributions 	}
108*043036a2SApple OSS Distributions 
109*043036a2SApple OSS Distributions 	free(buffer);
110*043036a2SApple OSS Distributions 
111*043036a2SApple OSS Distributions 	T_PASS("%s", __func__);
112*043036a2SApple OSS Distributions }
113*043036a2SApple OSS Distributions 
114*043036a2SApple OSS Distributions T_DECL(tcp_heuristics_list_sysctl, "Test retrieving TCP heuristics list via sysctl")
115*043036a2SApple OSS Distributions {
116*043036a2SApple OSS Distributions 	size_t size = 0;
117*043036a2SApple OSS Distributions 	int ret;
118*043036a2SApple OSS Distributions 
119*043036a2SApple OSS Distributions 	// First call to get the required buffer size
120*043036a2SApple OSS Distributions 	ret = sysctlbyname("net.inet.tcp.heuristics_list", NULL, &size, NULL, 0);
121*043036a2SApple OSS Distributions 	if (ret == -1) {
122*043036a2SApple OSS Distributions 		T_SKIP("sysctlbyname(\"net.inet.tcp.cache_list\") error: %d", errno);
123*043036a2SApple OSS Distributions 	}
124*043036a2SApple OSS Distributions 
125*043036a2SApple OSS Distributions 	T_LOG("TCP heuristics list size: %zu bytes", size);
126*043036a2SApple OSS Distributions 
127*043036a2SApple OSS Distributions 	if (size == 0) {
128*043036a2SApple OSS Distributions 		T_PASS("No TCP heuristics entries found");
129*043036a2SApple OSS Distributions 	}
130*043036a2SApple OSS Distributions 
131*043036a2SApple OSS Distributions 	// Allocate buffer and retrieve the data
132*043036a2SApple OSS Distributions 	void *buffer = malloc(size);
133*043036a2SApple OSS Distributions 	T_QUIET; T_ASSERT_NOTNULL(buffer, "malloc buffer");
134*043036a2SApple OSS Distributions 
135*043036a2SApple OSS Distributions 	ret = sysctlbyname("net.inet.tcp.heuristics_list", buffer, &size, NULL, 0);
136*043036a2SApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(ret, "sysctlbyname to get data");
137*043036a2SApple OSS Distributions 
138*043036a2SApple OSS Distributions 	// Calculate number of entries
139*043036a2SApple OSS Distributions 	size_t num_entries = size / sizeof(struct tcp_heuristics_data);
140*043036a2SApple OSS Distributions 	T_LOG("Found %zu TCP heuristics entries", num_entries);
141*043036a2SApple OSS Distributions 
142*043036a2SApple OSS Distributions 	struct tcp_heuristics_data *entries = (struct tcp_heuristics_data *)buffer;
143*043036a2SApple OSS Distributions 
144*043036a2SApple OSS Distributions 	// Log all fields of each entry
145*043036a2SApple OSS Distributions 	for (size_t i = 0; i < num_entries; i++) {
146*043036a2SApple OSS Distributions 		struct tcp_heuristics_data *entry = &entries[i];
147*043036a2SApple OSS Distributions 
148*043036a2SApple OSS Distributions 		T_LOG("Heuristics Entry %zu:", i);
149*043036a2SApple OSS Distributions 		T_LOG("  th_last_access: %u", entry->th_last_access);
150*043036a2SApple OSS Distributions 		T_LOG("  th_key.thk_family: %d", entry->th_key.thk_family);
151*043036a2SApple OSS Distributions 
152*043036a2SApple OSS Distributions 		// Log source key info
153*043036a2SApple OSS Distributions 		if (entry->th_key.thk_family == AF_INET) {
154*043036a2SApple OSS Distributions 			T_LOG("  th_key.thk_ip IP: %s", inet_ntoa(entry->th_key.thk_ip.addr));
155*043036a2SApple OSS Distributions 		} else if (entry->th_key.thk_family == AF_INET6) {
156*043036a2SApple OSS Distributions 			char addr_str[INET6_ADDRSTRLEN];
157*043036a2SApple OSS Distributions 			inet_ntop(AF_INET6, &entry->th_key.thk_ip.addr6, addr_str, sizeof(addr_str));
158*043036a2SApple OSS Distributions 			T_LOG("  th_key.thk_ip IPv6: %s", addr_str);
159*043036a2SApple OSS Distributions 		}
160*043036a2SApple OSS Distributions 
161*043036a2SApple OSS Distributions 		// Log TFO heuristics
162*043036a2SApple OSS Distributions 		T_LOG("  th_tfo_data_loss: %u", entry->th_tfo_data_loss);
163*043036a2SApple OSS Distributions 		T_LOG("  th_tfo_req_loss: %u", entry->th_tfo_req_loss);
164*043036a2SApple OSS Distributions 		T_LOG("  th_tfo_data_rst: %u", entry->th_tfo_data_rst);
165*043036a2SApple OSS Distributions 
166*043036a2SApple OSS Distributions 
167*043036a2SApple OSS Distributions 		T_LOG("  th_tfo_req_rst: %u", entry->th_tfo_req_rst);
168*043036a2SApple OSS Distributions 
169*043036a2SApple OSS Distributions 		// Log MPTCP heuristics
170*043036a2SApple OSS Distributions 		T_LOG("  th_mptcp_loss: %u", entry->th_mptcp_loss);
171*043036a2SApple OSS Distributions 		T_LOG("  th_mptcp_success: %u", entry->th_mptcp_success);
172*043036a2SApple OSS Distributions 
173*043036a2SApple OSS Distributions 		// Log ECN heuristics
174*043036a2SApple OSS Distributions 		T_LOG("  th_ecn_droprst: %u", entry->th_ecn_droprst);
175*043036a2SApple OSS Distributions 		T_LOG("  th_ecn_synrst: %u", entry->th_ecn_synrst);
176*043036a2SApple OSS Distributions 
177*043036a2SApple OSS Distributions 		// Log timing information
178*043036a2SApple OSS Distributions 		T_LOG("  th_tfo_enabled_time: %u", entry->th_tfo_enabled_time);
179*043036a2SApple OSS Distributions 		T_LOG("  th_tfo_backoff_until: %u", entry->th_tfo_backoff_until);
180*043036a2SApple OSS Distributions 		T_LOG("  th_tfo_backoff: %u", entry->th_tfo_backoff);
181*043036a2SApple OSS Distributions 		T_LOG("  th_mptcp_backoff: %u", entry->th_mptcp_backoff);
182*043036a2SApple OSS Distributions 		T_LOG("  th_ecn_backoff: %u", entry->th_ecn_backoff);
183*043036a2SApple OSS Distributions 
184*043036a2SApple OSS Distributions 		// Log flags
185*043036a2SApple OSS Distributions 		T_LOG("  th_tfo_in_backoff: %u", entry->th_tfo_in_backoff);
186*043036a2SApple OSS Distributions 		T_LOG("  th_mptcp_in_backoff: %u", entry->th_mptcp_in_backoff);
187*043036a2SApple OSS Distributions 		T_LOG("  th_mptcp_heuristic_disabled: %u", entry->th_mptcp_heuristic_disabled);
188*043036a2SApple OSS Distributions 		T_LOG(""); // Empty line between entries
189*043036a2SApple OSS Distributions 	}
190*043036a2SApple OSS Distributions 
191*043036a2SApple OSS Distributions 	free(buffer);
192*043036a2SApple OSS Distributions 
193*043036a2SApple OSS Distributions 	T_PASS("%s", __func__);
194*043036a2SApple OSS Distributions }
195