xref: /xnu-12377.81.4/tests/net_tuntests.c (revision 043036a2b3718f7f0be807e2870f8f47d3fa0796)
1*043036a2SApple OSS Distributions /* -*- compile-command: "xcrun --sdk iphoneos.internal make net_tuntests" -*- */
2*043036a2SApple OSS Distributions 
3*043036a2SApple OSS Distributions #include <inttypes.h>
4*043036a2SApple OSS Distributions #include <stdbool.h>
5*043036a2SApple OSS Distributions #include <stdio.h>
6*043036a2SApple OSS Distributions #include <stdlib.h>
7*043036a2SApple OSS Distributions #include <time.h>
8*043036a2SApple OSS Distributions #include <string.h>
9*043036a2SApple OSS Distributions #include <unistd.h>
10*043036a2SApple OSS Distributions #include <poll.h>
11*043036a2SApple OSS Distributions #include <sys/types.h>
12*043036a2SApple OSS Distributions #include <sys/event.h>
13*043036a2SApple OSS Distributions #include <sys/time.h>
14*043036a2SApple OSS Distributions #include <uuid/uuid.h>
15*043036a2SApple OSS Distributions #include <arpa/inet.h>
16*043036a2SApple OSS Distributions #include <sys/sysctl.h>
17*043036a2SApple OSS Distributions #include <sys/kern_control.h>
18*043036a2SApple OSS Distributions #include <sys/ioctl.h>
19*043036a2SApple OSS Distributions #include <sys/socket.h>
20*043036a2SApple OSS Distributions #include <sys/kern_control.h>
21*043036a2SApple OSS Distributions #include <sys/sys_domain.h>
22*043036a2SApple OSS Distributions 
23*043036a2SApple OSS Distributions #include <net/if.h>
24*043036a2SApple OSS Distributions #include <net/if_ipsec.h>
25*043036a2SApple OSS Distributions #include <net/if_utun.h>
26*043036a2SApple OSS Distributions #include <netinet/in.h>
27*043036a2SApple OSS Distributions #include <netinet/in_var.h>
28*043036a2SApple OSS Distributions #include <net/pfkeyv2.h>
29*043036a2SApple OSS Distributions #include <netinet6/ipsec.h>
30*043036a2SApple OSS Distributions 
31*043036a2SApple OSS Distributions #include <darwintest.h>
32*043036a2SApple OSS Distributions #include <darwintest_utils.h>
33*043036a2SApple OSS Distributions 
34*043036a2SApple OSS Distributions #include <skywalk/os_skywalk_private.h> // for SK_FEATURE_*
35*043036a2SApple OSS Distributions 
36*043036a2SApple OSS Distributions T_GLOBAL_META(T_META_NAMESPACE("xnu.net.tun"));
37*043036a2SApple OSS Distributions 
38*043036a2SApple OSS Distributions /* Disable all these test until <rdar://problem/49124468> is fixed */
39*043036a2SApple OSS Distributions T_GLOBAL_META(T_META_ENABLED(false));
40*043036a2SApple OSS Distributions 
41*043036a2SApple OSS Distributions #if 0
42*043036a2SApple OSS Distributions #undef T_QUIET
43*043036a2SApple OSS Distributions #define T_QUIET
44*043036a2SApple OSS Distributions #endif
45*043036a2SApple OSS Distributions 
46*043036a2SApple OSS Distributions #if 0
47*043036a2SApple OSS Distributions static void
48*043036a2SApple OSS Distributions log_hexdump(const void *inp, size_t len)
49*043036a2SApple OSS Distributions {
50*043036a2SApple OSS Distributions 	unsigned i, off = 0;
51*043036a2SApple OSS Distributions 	char buf[9 + 16 * 3 + 1];
52*043036a2SApple OSS Distributions 	for (i = 0; i < len; i++) {
53*043036a2SApple OSS Distributions 		if (i % 16 == 0) {
54*043036a2SApple OSS Distributions 			off = (unsigned)snprintf(buf, sizeof(buf), "%08x:", i);
55*043036a2SApple OSS Distributions 		}
56*043036a2SApple OSS Distributions 		off += (unsigned)snprintf(buf + off, sizeof(buf) - off, " %02x", (((const uint8_t *)inp)[i]) & 0xff);
57*043036a2SApple OSS Distributions 		if (i % 16 == 15) {
58*043036a2SApple OSS Distributions 			T_LOG("%s", buf);
59*043036a2SApple OSS Distributions 		}
60*043036a2SApple OSS Distributions 	}
61*043036a2SApple OSS Distributions 	if (len % 16) {
62*043036a2SApple OSS Distributions 		T_LOG("%s", buf);
63*043036a2SApple OSS Distributions 	}
64*043036a2SApple OSS Distributions }
65*043036a2SApple OSS Distributions #else
66*043036a2SApple OSS Distributions static void
log_hexdump(const void * inp,size_t len)67*043036a2SApple OSS Distributions log_hexdump(const void *inp, size_t len)
68*043036a2SApple OSS Distributions {
69*043036a2SApple OSS Distributions #pragma unused(inp, len)
70*043036a2SApple OSS Distributions }
71*043036a2SApple OSS Distributions #endif
72*043036a2SApple OSS Distributions 
73*043036a2SApple OSS Distributions static bool
is_netagent_enabled(void)74*043036a2SApple OSS Distributions is_netagent_enabled(void)
75*043036a2SApple OSS Distributions {
76*043036a2SApple OSS Distributions 	int enabled = 0;
77*043036a2SApple OSS Distributions 	size_t len = sizeof(enabled);
78*043036a2SApple OSS Distributions 	T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(sysctlbyname("net.link.generic.system.enable_netagent", &enabled, &len, NULL, 0), NULL);
79*043036a2SApple OSS Distributions 	T_QUIET; T_ASSERT_EQ(len, sizeof(enabled), NULL);
80*043036a2SApple OSS Distributions 	return enabled == 1;
81*043036a2SApple OSS Distributions }
82*043036a2SApple OSS Distributions 
83*043036a2SApple OSS Distributions static bool g_is_ipsec_test;
84*043036a2SApple OSS Distributions static bool g_is_utun_test;
85*043036a2SApple OSS Distributions static int g_OPT_ENABLE_NETIF = -1;
86*043036a2SApple OSS Distributions static int g_OPT_ENABLE_FLOWSWITCH = -1;
87*043036a2SApple OSS Distributions static int g_OPT_ENABLE_CHANNEL = -1;
88*043036a2SApple OSS Distributions static int g_OPT_GET_CHANNEL_UUID = -1;
89*043036a2SApple OSS Distributions static int g_OPT_IFNAME = -1;
90*043036a2SApple OSS Distributions static char *g_CONTROL_NAME = NULL;
91*043036a2SApple OSS Distributions 
92*043036a2SApple OSS Distributions static int create_tunsock(int enable_netif, int enable_flowswitch, int channel_count, uuid_t uuid[]);
93*043036a2SApple OSS Distributions 
94*043036a2SApple OSS Distributions static void
setup_ipsec_test(void)95*043036a2SApple OSS Distributions setup_ipsec_test(void)
96*043036a2SApple OSS Distributions {
97*043036a2SApple OSS Distributions 	T_LOG("Configuring for ipsec tests");
98*043036a2SApple OSS Distributions 	g_OPT_ENABLE_NETIF = IPSEC_OPT_ENABLE_NETIF;
99*043036a2SApple OSS Distributions 	g_OPT_ENABLE_FLOWSWITCH = IPSEC_OPT_ENABLE_FLOWSWITCH;
100*043036a2SApple OSS Distributions 	g_OPT_ENABLE_CHANNEL = IPSEC_OPT_ENABLE_CHANNEL;
101*043036a2SApple OSS Distributions 	g_OPT_GET_CHANNEL_UUID = IPSEC_OPT_GET_CHANNEL_UUID;
102*043036a2SApple OSS Distributions 	g_OPT_IFNAME = IPSEC_OPT_IFNAME;
103*043036a2SApple OSS Distributions 	g_CONTROL_NAME = IPSEC_CONTROL_NAME;
104*043036a2SApple OSS Distributions 	g_is_ipsec_test = true;
105*043036a2SApple OSS Distributions }
106*043036a2SApple OSS Distributions 
107*043036a2SApple OSS Distributions static void
setup_utun_test(void)108*043036a2SApple OSS Distributions setup_utun_test(void)
109*043036a2SApple OSS Distributions {
110*043036a2SApple OSS Distributions 	T_LOG("Configuring for utun tests");
111*043036a2SApple OSS Distributions 	g_OPT_ENABLE_NETIF = UTUN_OPT_ENABLE_NETIF;
112*043036a2SApple OSS Distributions 	g_OPT_ENABLE_FLOWSWITCH = UTUN_OPT_ENABLE_FLOWSWITCH;
113*043036a2SApple OSS Distributions 	g_OPT_ENABLE_CHANNEL = UTUN_OPT_ENABLE_CHANNEL;
114*043036a2SApple OSS Distributions 	g_OPT_GET_CHANNEL_UUID = UTUN_OPT_GET_CHANNEL_UUID;
115*043036a2SApple OSS Distributions 	g_OPT_IFNAME = UTUN_OPT_IFNAME;
116*043036a2SApple OSS Distributions 	g_CONTROL_NAME = UTUN_CONTROL_NAME;
117*043036a2SApple OSS Distributions 	g_is_utun_test = true;
118*043036a2SApple OSS Distributions }
119*043036a2SApple OSS Distributions 
120*043036a2SApple OSS Distributions static bool
setblocking(int s,bool blocking)121*043036a2SApple OSS Distributions setblocking(int s, bool blocking)
122*043036a2SApple OSS Distributions {
123*043036a2SApple OSS Distributions 	int flags;
124*043036a2SApple OSS Distributions 	bool ret;
125*043036a2SApple OSS Distributions 
126*043036a2SApple OSS Distributions 	T_QUIET; T_EXPECT_POSIX_SUCCESS(flags = fcntl(s, F_GETFL, 0), NULL);
127*043036a2SApple OSS Distributions 
128*043036a2SApple OSS Distributions 	ret = !(flags & O_NONBLOCK);
129*043036a2SApple OSS Distributions 
130*043036a2SApple OSS Distributions 	if (blocking) {
131*043036a2SApple OSS Distributions 		flags &= ~O_NONBLOCK;
132*043036a2SApple OSS Distributions 	} else {
133*043036a2SApple OSS Distributions 		flags |= O_NONBLOCK;
134*043036a2SApple OSS Distributions 	}
135*043036a2SApple OSS Distributions 
136*043036a2SApple OSS Distributions #if 0
137*043036a2SApple OSS Distributions 	T_LOG("Setting fd %d from %s to %s\n",
138*043036a2SApple OSS Distributions 	    s, ret ? "blocking" : "nonblocking",
139*043036a2SApple OSS Distributions 	    blocking ? "blocking" : "nonblocking");
140*043036a2SApple OSS Distributions #endif
141*043036a2SApple OSS Distributions 
142*043036a2SApple OSS Distributions 	T_QUIET; T_EXPECT_POSIX_SUCCESS(flags = fcntl(s, F_SETFL, flags), NULL);
143*043036a2SApple OSS Distributions 
144*043036a2SApple OSS Distributions 	return ret;
145*043036a2SApple OSS Distributions }
146*043036a2SApple OSS Distributions 
147*043036a2SApple OSS Distributions 
148*043036a2SApple OSS Distributions static void
check_enables(int tunsock,int enable_netif,int enable_flowswitch,int channel_count,uuid_t uuid[])149*043036a2SApple OSS Distributions check_enables(int tunsock, int enable_netif, int enable_flowswitch, int channel_count, uuid_t uuid[])
150*043036a2SApple OSS Distributions {
151*043036a2SApple OSS Distributions 	int scratch;
152*043036a2SApple OSS Distributions 	socklen_t scratchlen, uuidlen;
153*043036a2SApple OSS Distributions 	uuid_t scratchuuid[channel_count];
154*043036a2SApple OSS Distributions 	if (!uuid) {
155*043036a2SApple OSS Distributions 		uuid = scratchuuid;
156*043036a2SApple OSS Distributions 	}
157*043036a2SApple OSS Distributions 
158*043036a2SApple OSS Distributions 	//T_LOG("checking tunsock %d", tunsock);
159*043036a2SApple OSS Distributions 
160*043036a2SApple OSS Distributions 	if (g_is_ipsec_test && channel_count && !enable_netif) {
161*043036a2SApple OSS Distributions 		/* Unfortunately, the connect incorrectly unwinds the bind if it get an error.
162*043036a2SApple OSS Distributions 		 * until that is fixed, expect EINVAL here
163*043036a2SApple OSS Distributions 		 */
164*043036a2SApple OSS Distributions 		scratchlen = sizeof(scratch);
165*043036a2SApple OSS Distributions 		T_QUIET; T_EXPECT_POSIX_FAILURE(getsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_ENABLE_NETIF,
166*043036a2SApple OSS Distributions 		    &scratch, &scratchlen), EINVAL, NULL);
167*043036a2SApple OSS Distributions 		T_QUIET; T_EXPECT_POSIX_FAILURE(getsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_ENABLE_FLOWSWITCH,
168*043036a2SApple OSS Distributions 		    &scratch, &scratchlen), EINVAL, NULL);
169*043036a2SApple OSS Distributions 		T_QUIET; T_EXPECT_POSIX_FAILURE(getsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_ENABLE_CHANNEL,
170*043036a2SApple OSS Distributions 		    &scratch, &scratchlen), EINVAL, NULL);
171*043036a2SApple OSS Distributions 		for (int i = 0; i < channel_count; i++) {
172*043036a2SApple OSS Distributions 			uuid_clear(uuid[i]);
173*043036a2SApple OSS Distributions 		}
174*043036a2SApple OSS Distributions 		uuidlen = sizeof(uuid_t) * (unsigned int)channel_count;
175*043036a2SApple OSS Distributions 		T_QUIET; T_EXPECT_POSIX_FAILURE(getsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_GET_CHANNEL_UUID,
176*043036a2SApple OSS Distributions 		    uuid, &uuidlen), EINVAL, NULL);
177*043036a2SApple OSS Distributions 		for (int i = 0; i < channel_count; i++) {
178*043036a2SApple OSS Distributions 			T_QUIET; T_EXPECT_TRUE(uuid_is_null(uuid[i]), NULL);
179*043036a2SApple OSS Distributions 		}
180*043036a2SApple OSS Distributions 		return;
181*043036a2SApple OSS Distributions 	}
182*043036a2SApple OSS Distributions 
183*043036a2SApple OSS Distributions 
184*043036a2SApple OSS Distributions 	scratchlen = sizeof(scratch);
185*043036a2SApple OSS Distributions 	T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(getsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_ENABLE_NETIF,
186*043036a2SApple OSS Distributions 	    &scratch, &scratchlen), NULL);
187*043036a2SApple OSS Distributions 	T_QUIET; T_EXPECT_EQ_ULONG((unsigned long)scratchlen, sizeof(scratch), NULL);
188*043036a2SApple OSS Distributions 	T_QUIET; T_EXPECT_EQ(scratch, enable_netif, NULL);
189*043036a2SApple OSS Distributions 
190*043036a2SApple OSS Distributions 	scratchlen = sizeof(scratch);
191*043036a2SApple OSS Distributions 	T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(getsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_ENABLE_FLOWSWITCH,
192*043036a2SApple OSS Distributions 	    &scratch, &scratchlen), NULL);
193*043036a2SApple OSS Distributions 	T_QUIET; T_EXPECT_EQ_ULONG((unsigned long)scratchlen, sizeof(scratch), NULL);
194*043036a2SApple OSS Distributions 	if (is_netagent_enabled()) {
195*043036a2SApple OSS Distributions 		if (enable_netif) {
196*043036a2SApple OSS Distributions 			T_QUIET; T_EXPECT_EQ(scratch, enable_flowswitch, NULL);
197*043036a2SApple OSS Distributions 		} else {
198*043036a2SApple OSS Distributions 			T_QUIET; T_EXPECT_EQ(scratch, 0, NULL);
199*043036a2SApple OSS Distributions 		}
200*043036a2SApple OSS Distributions 	} else {
201*043036a2SApple OSS Distributions 		T_QUIET; T_EXPECT_EQ(scratch, 0, NULL);
202*043036a2SApple OSS Distributions 	}
203*043036a2SApple OSS Distributions 
204*043036a2SApple OSS Distributions 	scratchlen = sizeof(scratch);
205*043036a2SApple OSS Distributions 	T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(getsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_ENABLE_CHANNEL,
206*043036a2SApple OSS Distributions 	    &scratch, &scratchlen), NULL);
207*043036a2SApple OSS Distributions 	T_QUIET; T_EXPECT_EQ_ULONG((unsigned long)scratchlen, sizeof(scratch), NULL);
208*043036a2SApple OSS Distributions 	if (g_is_ipsec_test && !enable_netif) {
209*043036a2SApple OSS Distributions 		T_QUIET; T_EXPECT_EQ(scratch, 0, NULL);
210*043036a2SApple OSS Distributions 	} else {
211*043036a2SApple OSS Distributions 		T_QUIET; T_EXPECT_EQ(scratch, (int)channel_count, NULL);
212*043036a2SApple OSS Distributions 	}
213*043036a2SApple OSS Distributions 
214*043036a2SApple OSS Distributions 	if (scratch) {
215*043036a2SApple OSS Distributions 		for (int i = 0; i < channel_count; i++) {
216*043036a2SApple OSS Distributions 			uuid_clear(uuid[i]);
217*043036a2SApple OSS Distributions 		}
218*043036a2SApple OSS Distributions 		uuidlen = sizeof(uuid_t) * (unsigned int)channel_count;
219*043036a2SApple OSS Distributions 		T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(getsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_GET_CHANNEL_UUID,
220*043036a2SApple OSS Distributions 		    uuid, &uuidlen), NULL);
221*043036a2SApple OSS Distributions 		T_QUIET; T_EXPECT_EQ_ULONG((unsigned long)uuidlen, sizeof(uuid_t) * (unsigned long)channel_count, NULL);
222*043036a2SApple OSS Distributions 		for (int i = 0; i < channel_count; i++) {
223*043036a2SApple OSS Distributions 			T_QUIET; T_EXPECT_FALSE(uuid_is_null(uuid[i]), NULL);
224*043036a2SApple OSS Distributions 		}
225*043036a2SApple OSS Distributions 	} else {
226*043036a2SApple OSS Distributions 		for (int i = 0; i < channel_count; i++) {
227*043036a2SApple OSS Distributions 			uuid_clear(uuid[i]);
228*043036a2SApple OSS Distributions 		}
229*043036a2SApple OSS Distributions 		uuidlen = sizeof(uuid_t) * (unsigned int)channel_count;
230*043036a2SApple OSS Distributions 		T_QUIET; T_EXPECT_POSIX_FAILURE(getsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_GET_CHANNEL_UUID,
231*043036a2SApple OSS Distributions 		    uuid, &uuidlen), ENXIO, NULL);
232*043036a2SApple OSS Distributions 		T_QUIET; T_EXPECT_EQ_ULONG((unsigned long)uuidlen, sizeof(uuid_t) * (unsigned long)channel_count, NULL);
233*043036a2SApple OSS Distributions 		for (int i = 0; i < channel_count; i++) {
234*043036a2SApple OSS Distributions 			T_QUIET; T_EXPECT_TRUE(uuid_is_null(uuid[i]), NULL);
235*043036a2SApple OSS Distributions 		}
236*043036a2SApple OSS Distributions 	}
237*043036a2SApple OSS Distributions }
238*043036a2SApple OSS Distributions 
239*043036a2SApple OSS Distributions static void
tunsock_get_ifname(int s,char ifname[IFXNAMSIZ])240*043036a2SApple OSS Distributions tunsock_get_ifname(int s, char ifname[IFXNAMSIZ])
241*043036a2SApple OSS Distributions {
242*043036a2SApple OSS Distributions 	socklen_t optlen = IFXNAMSIZ;
243*043036a2SApple OSS Distributions 	T_QUIET; T_WITH_ERRNO; T_ASSERT_POSIX_ZERO(getsockopt(s, SYSPROTO_CONTROL, g_OPT_IFNAME, ifname, &optlen), NULL);
244*043036a2SApple OSS Distributions 	T_QUIET; T_ASSERT_TRUE(optlen > 0, NULL);
245*043036a2SApple OSS Distributions 	T_QUIET; T_ASSERT_TRUE(ifname[optlen - 1] == '\0', NULL);
246*043036a2SApple OSS Distributions 	T_QUIET; T_ASSERT_TRUE(strlen(ifname) + 1 == optlen, "got ifname \"%s\" len %zd expected %u", ifname, strlen(ifname), optlen);
247*043036a2SApple OSS Distributions }
248*043036a2SApple OSS Distributions 
249*043036a2SApple OSS Distributions static short
ifnet_get_flags(int s,const char ifname[IFNAMSIZ])250*043036a2SApple OSS Distributions ifnet_get_flags(int s, const char ifname[IFNAMSIZ])
251*043036a2SApple OSS Distributions {
252*043036a2SApple OSS Distributions 	struct ifreq    ifr;
253*043036a2SApple OSS Distributions 	memset(&ifr, 0, sizeof(ifr));
254*043036a2SApple OSS Distributions 	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
255*043036a2SApple OSS Distributions 	T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr), NULL);
256*043036a2SApple OSS Distributions 	return ifr.ifr_flags;
257*043036a2SApple OSS Distributions }
258*043036a2SApple OSS Distributions 
259*043036a2SApple OSS Distributions static void
ifnet_add_addr4(const char ifname[IFNAMSIZ],struct in_addr * addr,struct in_addr * mask,struct in_addr * broadaddr)260*043036a2SApple OSS Distributions ifnet_add_addr4(const char ifname[IFNAMSIZ], struct in_addr *addr, struct in_addr *mask, struct in_addr *broadaddr)
261*043036a2SApple OSS Distributions {
262*043036a2SApple OSS Distributions 	struct sockaddr_in *sin;
263*043036a2SApple OSS Distributions 	struct in_aliasreq ifra;
264*043036a2SApple OSS Distributions 	int s;
265*043036a2SApple OSS Distributions 
266*043036a2SApple OSS Distributions 	T_QUIET; T_EXPECT_POSIX_SUCCESS(s = socket(AF_INET, SOCK_DGRAM, 0), NULL);
267*043036a2SApple OSS Distributions 
268*043036a2SApple OSS Distributions 	memset(&ifra, 0, sizeof(ifra));
269*043036a2SApple OSS Distributions 	strlcpy(ifra.ifra_name, ifname, sizeof(ifra.ifra_name));
270*043036a2SApple OSS Distributions 
271*043036a2SApple OSS Distributions 	if (addr != NULL) {
272*043036a2SApple OSS Distributions 		sin = &ifra.ifra_addr;
273*043036a2SApple OSS Distributions 		sin->sin_len = sizeof(*sin);
274*043036a2SApple OSS Distributions 		sin->sin_family = AF_INET;
275*043036a2SApple OSS Distributions 		sin->sin_addr = *addr;
276*043036a2SApple OSS Distributions 	}
277*043036a2SApple OSS Distributions 
278*043036a2SApple OSS Distributions 	if (mask != NULL) {
279*043036a2SApple OSS Distributions 		sin = &ifra.ifra_mask;
280*043036a2SApple OSS Distributions 		sin->sin_len = sizeof(*sin);
281*043036a2SApple OSS Distributions 		sin->sin_family = AF_INET;
282*043036a2SApple OSS Distributions 		sin->sin_addr = *mask;
283*043036a2SApple OSS Distributions 	}
284*043036a2SApple OSS Distributions 
285*043036a2SApple OSS Distributions 	if (broadaddr != NULL || (addr != NULL &&
286*043036a2SApple OSS Distributions 	    (ifnet_get_flags(s, ifname) & IFF_POINTOPOINT) != 0)) {
287*043036a2SApple OSS Distributions 		sin = &ifra.ifra_broadaddr;
288*043036a2SApple OSS Distributions 		sin->sin_len = sizeof(*sin);
289*043036a2SApple OSS Distributions 		sin->sin_family = AF_INET;
290*043036a2SApple OSS Distributions 		sin->sin_addr = (broadaddr != NULL) ? *broadaddr : *addr;
291*043036a2SApple OSS Distributions 	}
292*043036a2SApple OSS Distributions 
293*043036a2SApple OSS Distributions 	T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(ioctl(s, SIOCAIFADDR, &ifra), NULL);
294*043036a2SApple OSS Distributions 
295*043036a2SApple OSS Distributions 	T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(close(s), NULL);
296*043036a2SApple OSS Distributions }
297*043036a2SApple OSS Distributions 
298*043036a2SApple OSS Distributions static int g_pfkeyso = -1;
299*043036a2SApple OSS Distributions static struct in_addr g_addr1, g_addr2;
300*043036a2SApple OSS Distributions 
301*043036a2SApple OSS Distributions static void
create_sa(const char ifname[IFXNAMSIZ],uint8_t type,uint32_t spi,struct in_addr * src,struct in_addr * dst)302*043036a2SApple OSS Distributions create_sa(const char ifname[IFXNAMSIZ], uint8_t type, uint32_t spi, struct in_addr *src, struct in_addr *dst)
303*043036a2SApple OSS Distributions {
304*043036a2SApple OSS Distributions 	if (g_pfkeyso == -1) {
305*043036a2SApple OSS Distributions 		T_QUIET; T_EXPECT_POSIX_SUCCESS(g_pfkeyso = socket(PF_KEY, SOCK_RAW, PF_KEY_V2), NULL);
306*043036a2SApple OSS Distributions 	}
307*043036a2SApple OSS Distributions 
308*043036a2SApple OSS Distributions 	/*
309*043036a2SApple OSS Distributions 	 *       <base, SA, (lifetime(HS),) address(SD), (address(P),)
310*043036a2SApple OSS Distributions 	 *       key(AE), (identity(SD),) (sensitivity)>
311*043036a2SApple OSS Distributions 	 */
312*043036a2SApple OSS Distributions 
313*043036a2SApple OSS Distributions 	struct {
314*043036a2SApple OSS Distributions 		struct sadb_msg msg __attribute((aligned(sizeof(uint64_t))));
315*043036a2SApple OSS Distributions 		struct sadb_key key  __attribute((aligned(sizeof(uint64_t))));
316*043036a2SApple OSS Distributions 		struct sadb_sa sa  __attribute((aligned(sizeof(uint64_t))));
317*043036a2SApple OSS Distributions 		struct sadb_x_sa2 sa2  __attribute((aligned(sizeof(uint64_t))));
318*043036a2SApple OSS Distributions 		struct sadb_x_ipsecif ipsecif __attribute((aligned(sizeof(uint64_t))));
319*043036a2SApple OSS Distributions 		struct {
320*043036a2SApple OSS Distributions 			struct sadb_address addr __attribute((aligned(sizeof(uint64_t))));
321*043036a2SApple OSS Distributions 			struct sockaddr_in saddr __attribute((aligned(sizeof(uint64_t))));
322*043036a2SApple OSS Distributions 		} src;
323*043036a2SApple OSS Distributions 		struct {
324*043036a2SApple OSS Distributions 			struct sadb_address addr __attribute((aligned(sizeof(uint64_t))));
325*043036a2SApple OSS Distributions 			struct sockaddr_in saddr __attribute((aligned(sizeof(uint64_t))));
326*043036a2SApple OSS Distributions 		} dst;
327*043036a2SApple OSS Distributions 	} addcmd;
328*043036a2SApple OSS Distributions 
329*043036a2SApple OSS Distributions 	memset(&addcmd, 0, sizeof(addcmd));
330*043036a2SApple OSS Distributions 
331*043036a2SApple OSS Distributions 	addcmd.msg.sadb_msg_version = PF_KEY_V2;
332*043036a2SApple OSS Distributions 	addcmd.msg.sadb_msg_type = type;
333*043036a2SApple OSS Distributions 	addcmd.msg.sadb_msg_errno = 0;
334*043036a2SApple OSS Distributions 	addcmd.msg.sadb_msg_satype = SADB_SATYPE_ESP;
335*043036a2SApple OSS Distributions 	addcmd.msg.sadb_msg_len = PFKEY_UNIT64(sizeof(addcmd));
336*043036a2SApple OSS Distributions 	addcmd.msg.sadb_msg_reserved = 0;
337*043036a2SApple OSS Distributions 	addcmd.msg.sadb_msg_seq = 0;
338*043036a2SApple OSS Distributions 	addcmd.msg.sadb_msg_pid = (unsigned)getpid();
339*043036a2SApple OSS Distributions 
340*043036a2SApple OSS Distributions 	addcmd.key.sadb_key_len = PFKEY_UNIT64(sizeof(addcmd.key));
341*043036a2SApple OSS Distributions 	addcmd.key.sadb_key_exttype = SADB_EXT_KEY_ENCRYPT;
342*043036a2SApple OSS Distributions 	addcmd.key.sadb_key_bits = 0;
343*043036a2SApple OSS Distributions 	addcmd.key.sadb_key_reserved = 0;
344*043036a2SApple OSS Distributions 
345*043036a2SApple OSS Distributions 	addcmd.sa.sadb_sa_len = PFKEY_UNIT64(sizeof(addcmd.sa));
346*043036a2SApple OSS Distributions 	addcmd.sa.sadb_sa_exttype = SADB_EXT_SA;
347*043036a2SApple OSS Distributions 	addcmd.sa.sadb_sa_spi = htonl(spi);
348*043036a2SApple OSS Distributions 	addcmd.sa.sadb_sa_replay = 0;
349*043036a2SApple OSS Distributions 	addcmd.sa.sadb_sa_state = 0;
350*043036a2SApple OSS Distributions 	addcmd.sa.sadb_sa_auth = SADB_AALG_NONE;
351*043036a2SApple OSS Distributions 	addcmd.sa.sadb_sa_encrypt = SADB_EALG_NULL;
352*043036a2SApple OSS Distributions 	addcmd.sa.sadb_sa_flags = SADB_X_EXT_CYCSEQ;
353*043036a2SApple OSS Distributions 
354*043036a2SApple OSS Distributions 	addcmd.sa2.sadb_x_sa2_len = PFKEY_UNIT64(sizeof(addcmd.sa2));
355*043036a2SApple OSS Distributions 	addcmd.sa2.sadb_x_sa2_exttype = SADB_X_EXT_SA2;
356*043036a2SApple OSS Distributions 	addcmd.sa2.sadb_x_sa2_mode = IPSEC_MODE_ANY;
357*043036a2SApple OSS Distributions 	addcmd.sa2.sadb_x_sa2_alwaysexpire = 1;
358*043036a2SApple OSS Distributions 	addcmd.sa2.sadb_x_sa2_flags = SADB_X_EXT_SA2_DELETE_ON_DETACH;
359*043036a2SApple OSS Distributions 	addcmd.sa2.sadb_x_sa2_sequence = 0;
360*043036a2SApple OSS Distributions 	addcmd.sa2.sadb_x_sa2_reqid = 0;
361*043036a2SApple OSS Distributions 
362*043036a2SApple OSS Distributions 	addcmd.ipsecif.sadb_x_ipsecif_len = PFKEY_UNIT64(sizeof(addcmd.ipsecif));
363*043036a2SApple OSS Distributions 	addcmd.ipsecif.sadb_x_ipsecif_exttype = SADB_X_EXT_IPSECIF;
364*043036a2SApple OSS Distributions 	memset(addcmd.ipsecif.sadb_x_ipsecif_internal_if, 0, sizeof(addcmd.ipsecif.sadb_x_ipsecif_internal_if));
365*043036a2SApple OSS Distributions 	memset(addcmd.ipsecif.sadb_x_ipsecif_outgoing_if, 0, sizeof(addcmd.ipsecif.sadb_x_ipsecif_outgoing_if));
366*043036a2SApple OSS Distributions 	strlcpy(addcmd.ipsecif.sadb_x_ipsecif_ipsec_if, ifname, sizeof(addcmd.ipsecif.sadb_x_ipsecif_ipsec_if));
367*043036a2SApple OSS Distributions 	addcmd.ipsecif.sadb_x_ipsecif_init_disabled = 0;
368*043036a2SApple OSS Distributions 	addcmd.ipsecif.reserved = 0;
369*043036a2SApple OSS Distributions 
370*043036a2SApple OSS Distributions 	addcmd.src.addr.sadb_address_len = PFKEY_UNIT64(sizeof(addcmd.src));
371*043036a2SApple OSS Distributions 	addcmd.src.addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
372*043036a2SApple OSS Distributions 	addcmd.src.addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
373*043036a2SApple OSS Distributions 	addcmd.src.addr.sadb_address_prefixlen = sizeof(struct in_addr) << 3; //XXX Why?
374*043036a2SApple OSS Distributions 	addcmd.src.addr.sadb_address_reserved = 0;
375*043036a2SApple OSS Distributions 	addcmd.src.saddr.sin_len = sizeof(addcmd.src.saddr);
376*043036a2SApple OSS Distributions 	addcmd.src.saddr.sin_family = AF_INET;
377*043036a2SApple OSS Distributions 	addcmd.src.saddr.sin_port = htons(0);
378*043036a2SApple OSS Distributions 	addcmd.src.saddr.sin_addr = *src;
379*043036a2SApple OSS Distributions 
380*043036a2SApple OSS Distributions 	addcmd.dst.addr.sadb_address_len = PFKEY_UNIT64(sizeof(addcmd.dst));
381*043036a2SApple OSS Distributions 	addcmd.dst.addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
382*043036a2SApple OSS Distributions 	addcmd.dst.addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
383*043036a2SApple OSS Distributions 	addcmd.dst.addr.sadb_address_prefixlen = sizeof(struct in_addr) << 3; //XXX Why?
384*043036a2SApple OSS Distributions 	addcmd.dst.addr.sadb_address_reserved = 0;
385*043036a2SApple OSS Distributions 	addcmd.dst.saddr.sin_len = sizeof(addcmd.dst.saddr);
386*043036a2SApple OSS Distributions 	addcmd.dst.saddr.sin_family = AF_INET;
387*043036a2SApple OSS Distributions 	addcmd.dst.saddr.sin_port = htons(0);
388*043036a2SApple OSS Distributions 	addcmd.dst.saddr.sin_addr = *dst;
389*043036a2SApple OSS Distributions 
390*043036a2SApple OSS Distributions 	log_hexdump(&addcmd, sizeof(addcmd));
391*043036a2SApple OSS Distributions 
392*043036a2SApple OSS Distributions 	ssize_t slen;
393*043036a2SApple OSS Distributions 	T_QUIET; T_EXPECT_POSIX_SUCCESS(slen = send(g_pfkeyso, &addcmd, sizeof(addcmd), 0), NULL);
394*043036a2SApple OSS Distributions 	T_QUIET; T_EXPECT_EQ(slen, (ssize_t)sizeof(addcmd), NULL);
395*043036a2SApple OSS Distributions }
396*043036a2SApple OSS Distributions 
397*043036a2SApple OSS Distributions /* This version of the test expects channels to be enabled before connect
398*043036a2SApple OSS Distributions  */
399*043036a2SApple OSS Distributions static int
create_tunsock(int enable_netif,int enable_flowswitch,int channel_count,uuid_t uuid[])400*043036a2SApple OSS Distributions create_tunsock(int enable_netif, int enable_flowswitch, int channel_count, uuid_t uuid[])
401*043036a2SApple OSS Distributions {
402*043036a2SApple OSS Distributions 	int tunsock;
403*043036a2SApple OSS Distributions 	struct ctl_info kernctl_info;
404*043036a2SApple OSS Distributions 	struct sockaddr_ctl kernctl_addr;
405*043036a2SApple OSS Distributions 	uuid_t scratchuuid[channel_count];
406*043036a2SApple OSS Distributions 	if (!uuid) {
407*043036a2SApple OSS Distributions 		uuid = scratchuuid;
408*043036a2SApple OSS Distributions 	}
409*043036a2SApple OSS Distributions 	socklen_t uuidlen;
410*043036a2SApple OSS Distributions 
411*043036a2SApple OSS Distributions startover:
412*043036a2SApple OSS Distributions 
413*043036a2SApple OSS Distributions 	T_QUIET; T_EXPECT_POSIX_SUCCESS(tunsock = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL), NULL);
414*043036a2SApple OSS Distributions 
415*043036a2SApple OSS Distributions 	memset(&kernctl_info, 0, sizeof(kernctl_info));
416*043036a2SApple OSS Distributions 	strlcpy(kernctl_info.ctl_name, g_CONTROL_NAME, sizeof(kernctl_info.ctl_name));
417*043036a2SApple OSS Distributions 	T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(ioctl(tunsock, CTLIOCGINFO, &kernctl_info), NULL);
418*043036a2SApple OSS Distributions 
419*043036a2SApple OSS Distributions 	memset(&kernctl_addr, 0, sizeof(kernctl_addr));
420*043036a2SApple OSS Distributions 	kernctl_addr.sc_len = sizeof(kernctl_addr);
421*043036a2SApple OSS Distributions 	kernctl_addr.sc_family = AF_SYSTEM;
422*043036a2SApple OSS Distributions 	kernctl_addr.ss_sysaddr = AF_SYS_CONTROL;
423*043036a2SApple OSS Distributions 	kernctl_addr.sc_id = kernctl_info.ctl_id;
424*043036a2SApple OSS Distributions 	kernctl_addr.sc_unit = 0;
425*043036a2SApple OSS Distributions 
426*043036a2SApple OSS Distributions 	T_LOG("%s: enable_netif = %d, enable_flowswitch = %d, channel_count = %d",
427*043036a2SApple OSS Distributions 	    __func__, enable_netif, enable_flowswitch, channel_count);
428*043036a2SApple OSS Distributions 
429*043036a2SApple OSS Distributions 	T_QUIET; T_EXPECT_POSIX_FAILURE(setsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_ENABLE_NETIF,
430*043036a2SApple OSS Distributions 	    &enable_netif, sizeof(enable_netif)), EINVAL, NULL);
431*043036a2SApple OSS Distributions 	T_QUIET; T_EXPECT_POSIX_FAILURE(setsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_ENABLE_FLOWSWITCH,
432*043036a2SApple OSS Distributions 	    &enable_flowswitch, sizeof(enable_flowswitch)), EINVAL, NULL);
433*043036a2SApple OSS Distributions 	T_QUIET; T_EXPECT_POSIX_FAILURE(setsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_ENABLE_CHANNEL,
434*043036a2SApple OSS Distributions 	    &channel_count, sizeof(channel_count)), EINVAL, NULL);
435*043036a2SApple OSS Distributions 	for (int i = 0; i < channel_count; i++) {
436*043036a2SApple OSS Distributions 		uuid_clear(uuid[i]);
437*043036a2SApple OSS Distributions 	}
438*043036a2SApple OSS Distributions 	uuidlen = sizeof(uuid_t) * (unsigned int)channel_count;
439*043036a2SApple OSS Distributions 	T_QUIET; T_EXPECT_POSIX_FAILURE(getsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_GET_CHANNEL_UUID,
440*043036a2SApple OSS Distributions 	    uuid, &uuidlen), EINVAL, NULL);
441*043036a2SApple OSS Distributions 	T_QUIET; T_EXPECT_EQ_ULONG((unsigned long)uuidlen, sizeof(uuid_t) * (unsigned long)channel_count, NULL);
442*043036a2SApple OSS Distributions 	for (int i = 0; i < channel_count; i++) {
443*043036a2SApple OSS Distributions 		T_QUIET; T_EXPECT_TRUE(uuid_is_null(uuid[i]), NULL);
444*043036a2SApple OSS Distributions 	}
445*043036a2SApple OSS Distributions 
446*043036a2SApple OSS Distributions 	T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(bind(tunsock, (struct sockaddr *)&kernctl_addr, sizeof(kernctl_addr)), NULL);
447*043036a2SApple OSS Distributions 
448*043036a2SApple OSS Distributions 	T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(setsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_ENABLE_NETIF,
449*043036a2SApple OSS Distributions 	    &enable_netif, sizeof(enable_netif)), NULL);
450*043036a2SApple OSS Distributions 	T_QUIET; T_EXPECT_POSIX_FAILURE(setsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_ENABLE_FLOWSWITCH,
451*043036a2SApple OSS Distributions 	    &enable_flowswitch, sizeof(enable_flowswitch)), EINVAL, NULL);
452*043036a2SApple OSS Distributions 	T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(setsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_ENABLE_CHANNEL,
453*043036a2SApple OSS Distributions 	    &channel_count, sizeof(channel_count)), NULL);
454*043036a2SApple OSS Distributions 
455*043036a2SApple OSS Distributions 	for (int i = 0; i < channel_count; i++) {
456*043036a2SApple OSS Distributions 		uuid_clear(uuid[i]);
457*043036a2SApple OSS Distributions 	}
458*043036a2SApple OSS Distributions 	uuidlen = sizeof(uuid_t) * (unsigned int)channel_count;
459*043036a2SApple OSS Distributions 	T_QUIET; T_EXPECT_POSIX_FAILURE(getsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_GET_CHANNEL_UUID,
460*043036a2SApple OSS Distributions 	    uuid, &uuidlen), ENXIO, NULL);
461*043036a2SApple OSS Distributions 	T_QUIET; T_EXPECT_EQ_ULONG((unsigned long)uuidlen, sizeof(uuid_t) * (unsigned long)channel_count, NULL);
462*043036a2SApple OSS Distributions 	for (int i = 0; i < channel_count; i++) {
463*043036a2SApple OSS Distributions 		T_QUIET; T_EXPECT_TRUE(uuid_is_null(uuid[i]), NULL);
464*043036a2SApple OSS Distributions 	}
465*043036a2SApple OSS Distributions 
466*043036a2SApple OSS Distributions 	int error = connect(tunsock, (struct sockaddr *)&kernctl_addr, sizeof(kernctl_addr));
467*043036a2SApple OSS Distributions 	if (error == -1 && errno == EBUSY) {
468*043036a2SApple OSS Distributions 		/* XXX remove this retry nonsense when this is fixed:
469*043036a2SApple OSS Distributions 		 * <rdar://problem/37340313> creating an interface without specifying specific interface name should not return EBUSY
470*043036a2SApple OSS Distributions 		 */
471*043036a2SApple OSS Distributions 		close(tunsock);
472*043036a2SApple OSS Distributions 		T_LOG("connect got EBUSY, sleeping 1 second before retry");
473*043036a2SApple OSS Distributions 		sleep(1);
474*043036a2SApple OSS Distributions 		goto startover;
475*043036a2SApple OSS Distributions 	}
476*043036a2SApple OSS Distributions 	if (g_is_ipsec_test && channel_count && !enable_netif) {
477*043036a2SApple OSS Distributions 		/* ipsec doesn't support channels without a netif */
478*043036a2SApple OSS Distributions 		T_QUIET; T_EXPECT_POSIX_FAILURE(error, ENOTSUP, "connect() == -1 && errno == ENOTSUP");
479*043036a2SApple OSS Distributions 	} else {
480*043036a2SApple OSS Distributions 		T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(error, "connect() == 0");
481*043036a2SApple OSS Distributions 	}
482*043036a2SApple OSS Distributions 
483*043036a2SApple OSS Distributions 	T_QUIET; T_EXPECT_POSIX_FAILURE(setsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_ENABLE_NETIF,
484*043036a2SApple OSS Distributions 	    &enable_netif, sizeof(enable_netif)), EINVAL, NULL);
485*043036a2SApple OSS Distributions 
486*043036a2SApple OSS Distributions 	if (g_is_ipsec_test && channel_count && !enable_netif) {
487*043036a2SApple OSS Distributions 		/* Connect failed above, so we get EINVAL */
488*043036a2SApple OSS Distributions 		T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_FAILURE(setsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_ENABLE_FLOWSWITCH,
489*043036a2SApple OSS Distributions 		    &enable_flowswitch, sizeof(enable_flowswitch)), EINVAL, NULL);
490*043036a2SApple OSS Distributions 	} else {
491*043036a2SApple OSS Distributions 		if (is_netagent_enabled()) {
492*043036a2SApple OSS Distributions 			if (enable_netif) {
493*043036a2SApple OSS Distributions 				T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(setsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_ENABLE_FLOWSWITCH,
494*043036a2SApple OSS Distributions 				    &enable_flowswitch, sizeof(enable_flowswitch)), NULL);
495*043036a2SApple OSS Distributions 			} else {
496*043036a2SApple OSS Distributions 				T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_FAILURE(setsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_ENABLE_FLOWSWITCH,
497*043036a2SApple OSS Distributions 				    &enable_flowswitch, sizeof(enable_flowswitch)), ENOENT, NULL);
498*043036a2SApple OSS Distributions 			}
499*043036a2SApple OSS Distributions 		} else {
500*043036a2SApple OSS Distributions 			T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_FAILURE(setsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_ENABLE_FLOWSWITCH,
501*043036a2SApple OSS Distributions 			    &enable_flowswitch, sizeof(enable_flowswitch)), ENOTSUP, NULL);
502*043036a2SApple OSS Distributions 		}
503*043036a2SApple OSS Distributions 	}
504*043036a2SApple OSS Distributions 
505*043036a2SApple OSS Distributions 	T_QUIET; T_EXPECT_POSIX_FAILURE(setsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_ENABLE_CHANNEL,
506*043036a2SApple OSS Distributions 	    &channel_count, sizeof(channel_count)), EINVAL, NULL);
507*043036a2SApple OSS Distributions 
508*043036a2SApple OSS Distributions 	for (int i = 0; i < channel_count; i++) {
509*043036a2SApple OSS Distributions 		uuid_clear(uuid[i]);
510*043036a2SApple OSS Distributions 	}
511*043036a2SApple OSS Distributions 	uuidlen = sizeof(uuid_t) * (unsigned int)channel_count;
512*043036a2SApple OSS Distributions 	if (!channel_count || (g_is_ipsec_test && channel_count && !enable_netif)) {
513*043036a2SApple OSS Distributions 		/* ipsec doesn't support channels without a netif */
514*043036a2SApple OSS Distributions 		if (g_is_ipsec_test && channel_count && !enable_netif) {
515*043036a2SApple OSS Distributions 			/* Unfortunately, the connect incorrectly unwinds the bind if it get an error.
516*043036a2SApple OSS Distributions 			 * until that is fixed, expect EINVAL here
517*043036a2SApple OSS Distributions 			 */
518*043036a2SApple OSS Distributions 			T_QUIET; T_EXPECT_POSIX_FAILURE(getsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_GET_CHANNEL_UUID,
519*043036a2SApple OSS Distributions 			    uuid, &uuidlen), EINVAL, NULL);
520*043036a2SApple OSS Distributions 		} else {
521*043036a2SApple OSS Distributions 			T_QUIET; T_EXPECT_POSIX_FAILURE(getsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_GET_CHANNEL_UUID,
522*043036a2SApple OSS Distributions 			    uuid, &uuidlen), ENXIO, NULL);
523*043036a2SApple OSS Distributions 		}
524*043036a2SApple OSS Distributions 		T_QUIET; T_EXPECT_EQ_ULONG((unsigned long)uuidlen, sizeof(uuid_t) * (unsigned long)channel_count, NULL);
525*043036a2SApple OSS Distributions 		for (int i = 0; i < channel_count; i++) {
526*043036a2SApple OSS Distributions 			T_QUIET; T_EXPECT_TRUE(uuid_is_null(uuid[i]), NULL);
527*043036a2SApple OSS Distributions 		}
528*043036a2SApple OSS Distributions 	} else {
529*043036a2SApple OSS Distributions 		uuidlen = sizeof(uuid_t) * (unsigned int)channel_count;
530*043036a2SApple OSS Distributions 		T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(getsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_GET_CHANNEL_UUID,
531*043036a2SApple OSS Distributions 		    uuid, &uuidlen), NULL);
532*043036a2SApple OSS Distributions 		T_QUIET; T_EXPECT_EQ_ULONG((unsigned long)uuidlen, sizeof(uuid_t) * (unsigned long)channel_count, NULL);
533*043036a2SApple OSS Distributions 		for (int i = 0; i < channel_count; i++) {
534*043036a2SApple OSS Distributions 			T_QUIET; T_EXPECT_FALSE(uuid_is_null(uuid[i]), NULL);
535*043036a2SApple OSS Distributions 		}
536*043036a2SApple OSS Distributions 	}
537*043036a2SApple OSS Distributions 
538*043036a2SApple OSS Distributions 	check_enables(tunsock, enable_netif, enable_flowswitch, channel_count, uuid);
539*043036a2SApple OSS Distributions 
540*043036a2SApple OSS Distributions 	//T_LOG("Returning tunsock %d", tunsock);
541*043036a2SApple OSS Distributions 
542*043036a2SApple OSS Distributions 	return tunsock;
543*043036a2SApple OSS Distributions }
544*043036a2SApple OSS Distributions 
545*043036a2SApple OSS Distributions #if 0
546*043036a2SApple OSS Distributions static void
547*043036a2SApple OSS Distributions ipsec_stats(void)
548*043036a2SApple OSS Distributions {
549*043036a2SApple OSS Distributions 	struct ifmibdata ifmd;
550*043036a2SApple OSS Distributions 
551*043036a2SApple OSS Distributions 	len = sizeof(struct ifmibdata);
552*043036a2SApple OSS Distributions 	name[3] = IFMIB_IFDATA;
553*043036a2SApple OSS Distributions 	name[4] = interesting_row;
554*043036a2SApple OSS Distributions 	name[5] = IpFDATA_GENERAL;
555*043036a2SApple OSS Distributions 	if (sysctl(name, 6, &ifmd, &len, (void *)0, 0) == -1) {
556*043036a2SApple OSS Distributions 		err(1, "sysctl IFDATA_GENERAL %d", interesting_row);
557*043036a2SApple OSS Distributions 	}
558*043036a2SApple OSS Distributions }
559*043036a2SApple OSS Distributions #endif
560*043036a2SApple OSS Distributions 
561*043036a2SApple OSS Distributions static void
permute_enables(void)562*043036a2SApple OSS Distributions permute_enables(void)
563*043036a2SApple OSS Distributions {
564*043036a2SApple OSS Distributions 	int tunsock;
565*043036a2SApple OSS Distributions 	T_EXPECT_GE(tunsock = create_tunsock(false, false, false, NULL), 0, NULL);
566*043036a2SApple OSS Distributions 	T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(close(tunsock), NULL);
567*043036a2SApple OSS Distributions 	T_EXPECT_GE(tunsock = create_tunsock(false, false, true, NULL), 0, NULL);
568*043036a2SApple OSS Distributions 	T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(close(tunsock), NULL);
569*043036a2SApple OSS Distributions 	T_EXPECT_GE(tunsock = create_tunsock(false, true, false, NULL), 0, NULL);
570*043036a2SApple OSS Distributions 	T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(close(tunsock), NULL);
571*043036a2SApple OSS Distributions 	T_EXPECT_GE(tunsock = create_tunsock(false, true, true, NULL), 0, NULL);
572*043036a2SApple OSS Distributions 	T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(close(tunsock), NULL);
573*043036a2SApple OSS Distributions 	T_EXPECT_GE(tunsock = create_tunsock(true, false, false, NULL), 0, NULL);
574*043036a2SApple OSS Distributions 	T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(close(tunsock), NULL);
575*043036a2SApple OSS Distributions 	T_EXPECT_GE(tunsock = create_tunsock(true, false, true, NULL), 0, NULL);
576*043036a2SApple OSS Distributions 	T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(close(tunsock), NULL);
577*043036a2SApple OSS Distributions 	T_EXPECT_GE(tunsock = create_tunsock(true, true, false, NULL), 0, NULL);
578*043036a2SApple OSS Distributions 	T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(close(tunsock), NULL);
579*043036a2SApple OSS Distributions 	T_EXPECT_GE(tunsock = create_tunsock(true, true, true, NULL), 0, NULL);
580*043036a2SApple OSS Distributions 	T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(close(tunsock), NULL);
581*043036a2SApple OSS Distributions }
582*043036a2SApple OSS Distributions 
583*043036a2SApple OSS Distributions T_DECL(ipsec_enables, "This test checks combinations of netif/channel/flowswitch on ipsec", T_META_TAG_VM_PREFERRED)
584*043036a2SApple OSS Distributions {
585*043036a2SApple OSS Distributions 	setup_ipsec_test();
586*043036a2SApple OSS Distributions 	permute_enables();
587*043036a2SApple OSS Distributions }
588*043036a2SApple OSS Distributions 
589*043036a2SApple OSS Distributions T_DECL(utun_enables, "This test checks combinations of netif/channel/flowswitch on utun", T_META_TAG_VM_PREFERRED)
590*043036a2SApple OSS Distributions {
591*043036a2SApple OSS Distributions 	setup_utun_test();
592*043036a2SApple OSS Distributions 	permute_enables();
593*043036a2SApple OSS Distributions }
594*043036a2SApple OSS Distributions 
595*043036a2SApple OSS Distributions static int g_tunsock = -1;
596*043036a2SApple OSS Distributions 
597*043036a2SApple OSS Distributions static void
cleanup_tunsock(void)598*043036a2SApple OSS Distributions cleanup_tunsock(void)
599*043036a2SApple OSS Distributions {
600*043036a2SApple OSS Distributions 	T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(close(g_tunsock), NULL);
601*043036a2SApple OSS Distributions 	T_QUIET; T_EXPECT_POSIX_FAILURE(close(g_tunsock), EBADF, NULL);
602*043036a2SApple OSS Distributions 	if (g_is_ipsec_test) {
603*043036a2SApple OSS Distributions 		T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(close(g_pfkeyso), NULL);
604*043036a2SApple OSS Distributions 		T_QUIET; T_EXPECT_POSIX_FAILURE(close(g_pfkeyso), EBADF, NULL);
605*043036a2SApple OSS Distributions 	}
606*043036a2SApple OSS Distributions }
607*043036a2SApple OSS Distributions 
608*043036a2SApple OSS Distributions static void
setup_tunsock(int channel_count,uuid_t uuids[])609*043036a2SApple OSS Distributions setup_tunsock(int channel_count, uuid_t uuids[])
610*043036a2SApple OSS Distributions {
611*043036a2SApple OSS Distributions 	T_ASSERT_GE(g_tunsock = create_tunsock(true, false, channel_count, uuids), 0, NULL);
612*043036a2SApple OSS Distributions 	T_ATEND(cleanup_tunsock);
613*043036a2SApple OSS Distributions 
614*043036a2SApple OSS Distributions 	char ifname[IFXNAMSIZ];
615*043036a2SApple OSS Distributions 	tunsock_get_ifname(g_tunsock, ifname);
616*043036a2SApple OSS Distributions 
617*043036a2SApple OSS Distributions 	T_LOG("Created interface %s", ifname);
618*043036a2SApple OSS Distributions 
619*043036a2SApple OSS Distributions 	uint32_t ifaddr = (10 << 24) | ((unsigned)getpid() & 0xffff) << 8 | 160;
620*043036a2SApple OSS Distributions 	struct in_addr mask;
621*043036a2SApple OSS Distributions 	g_addr1.s_addr = htonl(ifaddr);
622*043036a2SApple OSS Distributions 	g_addr2.s_addr = htonl(ifaddr + 1);
623*043036a2SApple OSS Distributions 	mask.s_addr = htonl(0xffffffff);
624*043036a2SApple OSS Distributions 
625*043036a2SApple OSS Distributions 	ifnet_add_addr4(ifname, &g_addr1, &mask, &g_addr2);
626*043036a2SApple OSS Distributions 
627*043036a2SApple OSS Distributions 	if (g_is_ipsec_test) {
628*043036a2SApple OSS Distributions 		create_sa(ifname, SADB_ADD, 12345, &g_addr1, &g_addr2);
629*043036a2SApple OSS Distributions 		create_sa(ifname, SADB_ADD, 12346, &g_addr2, &g_addr1);
630*043036a2SApple OSS Distributions 	}
631*043036a2SApple OSS Distributions }
632*043036a2SApple OSS Distributions 
633*043036a2SApple OSS Distributions T_DECL(setup_ipsec, "This test sets up an ipsec interface", T_META_TAG_VM_PREFERRED)
634*043036a2SApple OSS Distributions {
635*043036a2SApple OSS Distributions 	setup_ipsec_test();
636*043036a2SApple OSS Distributions 	setup_tunsock(1, NULL);
637*043036a2SApple OSS Distributions }
638*043036a2SApple OSS Distributions 
639*043036a2SApple OSS Distributions T_DECL(setup_utun, "This test sets up a utun interface", T_META_TAG_VM_PREFERRED)
640*043036a2SApple OSS Distributions {
641*043036a2SApple OSS Distributions 	setup_utun_test();
642*043036a2SApple OSS Distributions 	setup_tunsock(1, NULL);
643*043036a2SApple OSS Distributions }
644*043036a2SApple OSS Distributions 
645*043036a2SApple OSS Distributions static const int SOCKET_TRAFFIC_CLASSES[] = {
646*043036a2SApple OSS Distributions 	SO_TC_BK_SYS, // BK
647*043036a2SApple OSS Distributions 	SO_TC_BK,  // BK
648*043036a2SApple OSS Distributions 	SO_TC_BE,  // BE
649*043036a2SApple OSS Distributions 	SO_TC_RD,  // BE
650*043036a2SApple OSS Distributions 	SO_TC_OAM, // BE
651*043036a2SApple OSS Distributions 	SO_TC_AV,  // VI
652*043036a2SApple OSS Distributions 	SO_TC_RV,  // VI
653*043036a2SApple OSS Distributions 	SO_TC_VI,  // VI
654*043036a2SApple OSS Distributions 	SO_TC_VO,  // VO
655*043036a2SApple OSS Distributions 	SO_TC_CTL, // VO
656*043036a2SApple OSS Distributions };
657*043036a2SApple OSS Distributions 
658*043036a2SApple OSS Distributions // this should match ipsec_find_tx_ring_by_svc in ipsec driver
659*043036a2SApple OSS Distributions static const int SOCKET_TC_TO_RING[] = {
660*043036a2SApple OSS Distributions 	3,
661*043036a2SApple OSS Distributions 	3,
662*043036a2SApple OSS Distributions 	2,
663*043036a2SApple OSS Distributions 	2,
664*043036a2SApple OSS Distributions 	2,
665*043036a2SApple OSS Distributions 	1,
666*043036a2SApple OSS Distributions 	1,
667*043036a2SApple OSS Distributions 	1,
668*043036a2SApple OSS Distributions 	0,
669*043036a2SApple OSS Distributions 	0,
670*043036a2SApple OSS Distributions };
671*043036a2SApple OSS Distributions 
672*043036a2SApple OSS Distributions /* How many sockets map to this ring */
673*043036a2SApple OSS Distributions static const int RING_TO_TC_COUNT[] = {
674*043036a2SApple OSS Distributions 	2, 3, 3, 2,
675*043036a2SApple OSS Distributions };
676*043036a2SApple OSS Distributions 
677*043036a2SApple OSS Distributions static void
setup_channels_and_rings(int kq,int channel_count,channel_t channels[],channel_ring_t rxrings[],channel_ring_t txrings[],uuid_t uuids[],int cfds[])678*043036a2SApple OSS Distributions setup_channels_and_rings(int kq, int channel_count, channel_t channels[], channel_ring_t rxrings[], channel_ring_t txrings[], uuid_t uuids[], int cfds[])
679*043036a2SApple OSS Distributions {
680*043036a2SApple OSS Distributions 	setup_tunsock(channel_count, uuids);
681*043036a2SApple OSS Distributions 
682*043036a2SApple OSS Distributions #if 0
683*043036a2SApple OSS Distributions 	// give time to enable a tcpdump if desired
684*043036a2SApple OSS Distributions 	T_LOG("Sleeping 10");
685*043036a2SApple OSS Distributions 	sleep(10);
686*043036a2SApple OSS Distributions 	T_LOG("Done");
687*043036a2SApple OSS Distributions #endif
688*043036a2SApple OSS Distributions 
689*043036a2SApple OSS Distributions 	for (int ri = 0; ri < channel_count; ri++) {
690*043036a2SApple OSS Distributions 		if (rxrings) {
691*043036a2SApple OSS Distributions 			T_QUIET; T_WITH_ERRNO; T_ASSERT_NOTNULL(channels[ri] = os_channel_create(uuids[ri], 0), NULL);
692*043036a2SApple OSS Distributions 			T_QUIET; T_WITH_ERRNO; T_ASSERT_NOTNULL(rxrings[ri] = os_channel_rx_ring(channels[ri],
693*043036a2SApple OSS Distributions 			    os_channel_ring_id(channels[ri], CHANNEL_FIRST_RX_RING)), NULL);
694*043036a2SApple OSS Distributions 		}
695*043036a2SApple OSS Distributions 		if (txrings) {
696*043036a2SApple OSS Distributions 			T_QUIET; T_WITH_ERRNO; T_ASSERT_NOTNULL(channels[ri] = os_channel_create(uuids[ri], 0), NULL);
697*043036a2SApple OSS Distributions 			T_QUIET; T_WITH_ERRNO; T_ASSERT_NOTNULL(rxrings[ri] = os_channel_rx_ring(channels[ri],
698*043036a2SApple OSS Distributions 			    os_channel_ring_id(channels[ri], CHANNEL_FIRST_TX_RING)), NULL);
699*043036a2SApple OSS Distributions 		}
700*043036a2SApple OSS Distributions 
701*043036a2SApple OSS Distributions 		struct kevent kev;
702*043036a2SApple OSS Distributions 		T_QUIET; T_EXPECT_POSIX_SUCCESS(cfds[ri] = os_channel_get_fd(channels[ri]), NULL);
703*043036a2SApple OSS Distributions 		EV_SET(&kev, cfds[ri], EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, (void *)(uintptr_t)ri);
704*043036a2SApple OSS Distributions 		T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(kevent(kq, &kev, 1, NULL, 0, NULL), NULL);
705*043036a2SApple OSS Distributions 	}
706*043036a2SApple OSS Distributions }
707*043036a2SApple OSS Distributions 
708*043036a2SApple OSS Distributions static void
cleanup_channels_and_rings(int channel_count,channel_t channels[],channel_ring_t rxrings[],channel_ring_t txrings[],uuid_t uuids[])709*043036a2SApple OSS Distributions cleanup_channels_and_rings(int channel_count, channel_t channels[], channel_ring_t rxrings[], channel_ring_t txrings[], uuid_t uuids[])
710*043036a2SApple OSS Distributions {
711*043036a2SApple OSS Distributions 	for (int ri = 0; ri < channel_count; ri++) {
712*043036a2SApple OSS Distributions 		if (rxrings) {
713*043036a2SApple OSS Distributions 			rxrings[ri] = NULL;
714*043036a2SApple OSS Distributions 		}
715*043036a2SApple OSS Distributions 		if (txrings) {
716*043036a2SApple OSS Distributions 			rxrings[ri] = NULL;
717*043036a2SApple OSS Distributions 		}
718*043036a2SApple OSS Distributions 		os_channel_destroy(channels[ri]);
719*043036a2SApple OSS Distributions 		channels[ri] = NULL;
720*043036a2SApple OSS Distributions 		uuid_clear(uuids[ri]);
721*043036a2SApple OSS Distributions 	}
722*043036a2SApple OSS Distributions }
723*043036a2SApple OSS Distributions 
724*043036a2SApple OSS Distributions static void
setup_sockets(int sockets[SO_TC_MAX],int type)725*043036a2SApple OSS Distributions setup_sockets(int sockets[SO_TC_MAX], int type)
726*043036a2SApple OSS Distributions {
727*043036a2SApple OSS Distributions 	for (int si = 0; si < SO_TC_MAX; si++) {
728*043036a2SApple OSS Distributions 		T_QUIET; T_EXPECT_POSIX_SUCCESS(sockets[si] = socket(PF_INET, type, 0), NULL);
729*043036a2SApple OSS Distributions 
730*043036a2SApple OSS Distributions 		T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(setsockopt(sockets[si], SOL_SOCKET,
731*043036a2SApple OSS Distributions 		    SO_TRAFFIC_CLASS, &SOCKET_TRAFFIC_CLASSES[si], sizeof(SOCKET_TRAFFIC_CLASSES[si])), NULL);
732*043036a2SApple OSS Distributions 
733*043036a2SApple OSS Distributions 		// XXX setsockopt(IP_BOUND_IF) here?
734*043036a2SApple OSS Distributions 
735*043036a2SApple OSS Distributions 		struct sockaddr_in sin;
736*043036a2SApple OSS Distributions 		memset(&sin, 0, sizeof(sin));
737*043036a2SApple OSS Distributions 		sin.sin_len = sizeof(sin);
738*043036a2SApple OSS Distributions 		sin.sin_family = AF_INET;
739*043036a2SApple OSS Distributions 		sin.sin_addr = g_addr1;
740*043036a2SApple OSS Distributions 
741*043036a2SApple OSS Distributions 		T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(bind(sockets[si], (struct sockaddr *)&sin, sizeof(sin)), NULL);
742*043036a2SApple OSS Distributions 
743*043036a2SApple OSS Distributions 		char sbuf[INET6_ADDRSTRLEN];
744*043036a2SApple OSS Distributions 		inet_ntop(sin.sin_family, &sin.sin_addr.s_addr, sbuf, sizeof(sbuf));
745*043036a2SApple OSS Distributions #if 0
746*043036a2SApple OSS Distributions 		T_LOG("%s socket %d bound to %s port %d",
747*043036a2SApple OSS Distributions 		    type == SOCK_DGRAM ? "udp" : type == SOCK_STREAM ? "tcp" : "???",
748*043036a2SApple OSS Distributions 		    sockets[si], sbuf, ntohs(sin.sin_port));
749*043036a2SApple OSS Distributions #endif
750*043036a2SApple OSS Distributions 		setblocking(sockets[si], false);
751*043036a2SApple OSS Distributions 	}
752*043036a2SApple OSS Distributions }
753*043036a2SApple OSS Distributions 
754*043036a2SApple OSS Distributions static void
cleanup_sockets(int sockets[SO_TC_MAX])755*043036a2SApple OSS Distributions cleanup_sockets(int sockets[SO_TC_MAX])
756*043036a2SApple OSS Distributions {
757*043036a2SApple OSS Distributions 	for (int si = 0; si < SO_TC_MAX; si++) {
758*043036a2SApple OSS Distributions 		T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(close(sockets[si]), NULL);
759*043036a2SApple OSS Distributions 		sockets[si] = -1;
760*043036a2SApple OSS Distributions 	}
761*043036a2SApple OSS Distributions }
762*043036a2SApple OSS Distributions 
763*043036a2SApple OSS Distributions static void
drain_ring(channel_ring_t rxring)764*043036a2SApple OSS Distributions drain_ring(channel_ring_t rxring)
765*043036a2SApple OSS Distributions {
766*043036a2SApple OSS Distributions 	uint32_t i, sc = os_channel_available_slot_count(rxring);
767*043036a2SApple OSS Distributions 	channel_slot_t rxprev = NULL;
768*043036a2SApple OSS Distributions 	for (i = 0; i < sc; i++) {
769*043036a2SApple OSS Distributions 		slot_prop_t rxprop;
770*043036a2SApple OSS Distributions 		channel_slot_t rxslot;
771*043036a2SApple OSS Distributions 
772*043036a2SApple OSS Distributions 		memset(&rxprop, 0, sizeof(rxprop));
773*043036a2SApple OSS Distributions 		T_QUIET; T_WITH_ERRNO; T_EXPECT_NOTNULL(rxslot = os_channel_get_next_slot(rxring, rxprev, &rxprop), NULL);
774*043036a2SApple OSS Distributions 		T_QUIET; T_ASSERT_NE_UINT(0, rxprop.sp_len, NULL);
775*043036a2SApple OSS Distributions 		T_QUIET; T_ASSERT_NOTNULL((void *)rxprop.sp_buf_ptr, NULL);
776*043036a2SApple OSS Distributions 
777*043036a2SApple OSS Distributions 		log_hexdump((void *)rxprop.sp_buf_ptr, rxprop.sp_len);
778*043036a2SApple OSS Distributions 
779*043036a2SApple OSS Distributions 		rxprev = rxslot;
780*043036a2SApple OSS Distributions 	}
781*043036a2SApple OSS Distributions 	if (sc) {
782*043036a2SApple OSS Distributions 		T_QUIET; T_EXPECT_POSIX_ZERO(os_channel_advance_slot(rxring, rxprev), NULL);
783*043036a2SApple OSS Distributions 	}
784*043036a2SApple OSS Distributions }
785*043036a2SApple OSS Distributions 
786*043036a2SApple OSS Distributions static void
send_one_packet(int s,int type)787*043036a2SApple OSS Distributions send_one_packet(int s, int type)
788*043036a2SApple OSS Distributions {
789*043036a2SApple OSS Distributions 	struct sockaddr_in sin;
790*043036a2SApple OSS Distributions 	memset(&sin, 0, sizeof(sin));
791*043036a2SApple OSS Distributions 	sin.sin_len = sizeof(sin);
792*043036a2SApple OSS Distributions 	sin.sin_family = AF_INET;
793*043036a2SApple OSS Distributions 	sin.sin_addr = g_addr2;
794*043036a2SApple OSS Distributions 	sin.sin_port = ntohs(12345);
795*043036a2SApple OSS Distributions 
796*043036a2SApple OSS Distributions 	if (type == SOCK_STREAM) {
797*043036a2SApple OSS Distributions 		T_QUIET; T_EXPECT_POSIX_FAILURE(connect(s, (struct sockaddr *)&sin, sizeof(sin)), EINPROGRESS, NULL);
798*043036a2SApple OSS Distributions 	}
799*043036a2SApple OSS Distributions 	if (type == SOCK_DGRAM) {
800*043036a2SApple OSS Distributions 		T_QUIET; T_WITH_ERRNO; T_EXPECT_EQ_LONG((long)sizeof(s), sendto(s, &s, sizeof(s), 0,
801*043036a2SApple OSS Distributions 		    (struct sockaddr *)&sin, sizeof(sin)), NULL);
802*043036a2SApple OSS Distributions 	}
803*043036a2SApple OSS Distributions }
804*043036a2SApple OSS Distributions 
805*043036a2SApple OSS Distributions static void
expect_empty_rings(int channel_count,channel_ring_t rings[])806*043036a2SApple OSS Distributions expect_empty_rings(int channel_count, channel_ring_t rings[])
807*043036a2SApple OSS Distributions {
808*043036a2SApple OSS Distributions 	/* Check all the rings and make sure there are no packets */
809*043036a2SApple OSS Distributions 	for (int ri = 0; ri < channel_count; ri++) {
810*043036a2SApple OSS Distributions 		T_QUIET; T_EXPECT_EQ_UINT(0U, os_channel_available_slot_count(rings[ri]), NULL);
811*043036a2SApple OSS Distributions 	}
812*043036a2SApple OSS Distributions }
813*043036a2SApple OSS Distributions 
814*043036a2SApple OSS Distributions static void
xfer_1_packet_singly(int channel_count,int type)815*043036a2SApple OSS Distributions xfer_1_packet_singly(int channel_count, int type)
816*043036a2SApple OSS Distributions {
817*043036a2SApple OSS Distributions 	uuid_t uuids[channel_count];
818*043036a2SApple OSS Distributions 	channel_t channels[channel_count];
819*043036a2SApple OSS Distributions 	int sockets[SO_TC_MAX];
820*043036a2SApple OSS Distributions 	channel_ring_t rxrings[channel_count];
821*043036a2SApple OSS Distributions 	int cfds[channel_count];
822*043036a2SApple OSS Distributions 	int kq;
823*043036a2SApple OSS Distributions 
824*043036a2SApple OSS Distributions 	T_QUIET; T_EXPECT_POSIX_SUCCESS(kq = kqueue(), NULL);
825*043036a2SApple OSS Distributions 
826*043036a2SApple OSS Distributions 	setup_channels_and_rings(kq, channel_count, channels, rxrings, NULL, uuids, cfds);
827*043036a2SApple OSS Distributions 
828*043036a2SApple OSS Distributions 	setup_sockets(sockets, type);
829*043036a2SApple OSS Distributions 
830*043036a2SApple OSS Distributions 	for (int si = 0; si < SO_TC_MAX; si++) {
831*043036a2SApple OSS Distributions 		expect_empty_rings(channel_count, rxrings);
832*043036a2SApple OSS Distributions 
833*043036a2SApple OSS Distributions 		send_one_packet(sockets[si], type);
834*043036a2SApple OSS Distributions 
835*043036a2SApple OSS Distributions 		int expected_ring = channel_count == 1 ? 0 : SOCKET_TC_TO_RING[si];
836*043036a2SApple OSS Distributions 
837*043036a2SApple OSS Distributions 		/* Wait for the packet delivery and check that it's only one packet and on the correct ring */
838*043036a2SApple OSS Distributions 		struct kevent kev[channel_count + 1];
839*043036a2SApple OSS Distributions 		int nev;
840*043036a2SApple OSS Distributions 		memset(kev, 0, sizeof(kev));
841*043036a2SApple OSS Distributions 		struct timespec to = { 0, 100 * NSEC_PER_MSEC }; // 100 ms
842*043036a2SApple OSS Distributions 		T_QUIET; T_EXPECT_POSIX_SUCCESS(nev = kevent(kq, NULL, 0, kev, channel_count + 1, &to), NULL);
843*043036a2SApple OSS Distributions 		T_QUIET; T_EXPECT_EQ_INT(nev, 1, NULL);
844*043036a2SApple OSS Distributions 		T_QUIET; T_EXPECT_EQ_PTR((void *)kev[0].ident, (void *)(uintptr_t)cfds[expected_ring], NULL);
845*043036a2SApple OSS Distributions 		T_QUIET; T_EXPECT_EQ_PTR(kev[0].udata, (void *)(uintptr_t)expected_ring, NULL);
846*043036a2SApple OSS Distributions 		T_QUIET; T_EXPECT_EQ_SHORT(kev[0].filter, (short)EVFILT_READ, NULL);
847*043036a2SApple OSS Distributions 		T_QUIET; T_EXPECT_FALSE(kev[0].flags & EV_ERROR, NULL);
848*043036a2SApple OSS Distributions 
849*043036a2SApple OSS Distributions 		/* Make sure it comes out the expected interface */
850*043036a2SApple OSS Distributions 		for (int ri = 0; ri < channel_count; ri++) {
851*043036a2SApple OSS Distributions 			errno = 0;
852*043036a2SApple OSS Distributions 
853*043036a2SApple OSS Distributions 			uint32_t sc = os_channel_available_slot_count(rxrings[ri]);
854*043036a2SApple OSS Distributions 
855*043036a2SApple OSS Distributions 			/* Check that the packet appears only on the expected ring and
856*043036a2SApple OSS Distributions 			 * is the only packet on the expected ring.
857*043036a2SApple OSS Distributions 			 */
858*043036a2SApple OSS Distributions 			T_QUIET; T_EXPECT_EQ_UINT(ri == expected_ring, sc, NULL);
859*043036a2SApple OSS Distributions 
860*043036a2SApple OSS Distributions 			if ((ri == expected_ring) == sc) {
861*043036a2SApple OSS Distributions 				T_PASS("tc index %d ring %d expected ring %d slot count %u", si, ri, expected_ring, sc);
862*043036a2SApple OSS Distributions 			} else {
863*043036a2SApple OSS Distributions 				T_FAIL("tc index %d ring %d expected ring %d slot count %u", si, ri, expected_ring, sc);
864*043036a2SApple OSS Distributions 			}
865*043036a2SApple OSS Distributions 
866*043036a2SApple OSS Distributions 			drain_ring(rxrings[ri]);
867*043036a2SApple OSS Distributions 		}
868*043036a2SApple OSS Distributions 	}
869*043036a2SApple OSS Distributions 
870*043036a2SApple OSS Distributions 	cleanup_sockets(sockets);
871*043036a2SApple OSS Distributions 
872*043036a2SApple OSS Distributions 	cleanup_channels_and_rings(channel_count, channels, rxrings, NULL, uuids);
873*043036a2SApple OSS Distributions 
874*043036a2SApple OSS Distributions 	T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(close(kq), NULL);
875*043036a2SApple OSS Distributions }
876*043036a2SApple OSS Distributions 
877*043036a2SApple OSS Distributions T_DECL(ipsec35889979u1s, "transfers 1 packet at a time of each sevice class over udp to a single ring", T_META_TAG_VM_PREFERRED)
878*043036a2SApple OSS Distributions {
879*043036a2SApple OSS Distributions 	setup_ipsec_test();
880*043036a2SApple OSS Distributions 	xfer_1_packet_singly(1, SOCK_DGRAM);
881*043036a2SApple OSS Distributions }
882*043036a2SApple OSS Distributions 
883*043036a2SApple OSS Distributions T_DECL(ipsec35889979u4s, "transfers 1 packet at a time of each sevice class over udp to 4 rings", T_META_TAG_VM_PREFERRED)
884*043036a2SApple OSS Distributions {
885*043036a2SApple OSS Distributions 	setup_ipsec_test();
886*043036a2SApple OSS Distributions 	xfer_1_packet_singly(4, SOCK_DGRAM);
887*043036a2SApple OSS Distributions }
888*043036a2SApple OSS Distributions 
889*043036a2SApple OSS Distributions T_DECL(ipsec35889979t1s, "transfers 1 packet at a time of each sevice class over tcp to a single ring", T_META_TAG_VM_PREFERRED)
890*043036a2SApple OSS Distributions {
891*043036a2SApple OSS Distributions 	setup_ipsec_test();
892*043036a2SApple OSS Distributions 	xfer_1_packet_singly(1, SOCK_STREAM);
893*043036a2SApple OSS Distributions }
894*043036a2SApple OSS Distributions 
895*043036a2SApple OSS Distributions 
896*043036a2SApple OSS Distributions T_DECL(ipsec35889979t4s, "transfers 1 packet at a time of each sevice class over tcp to 4 rings",
897*043036a2SApple OSS Distributions     /* This test will fail because tcp syn packets get elevated
898*043036a2SApple OSS Distributions      * due to ack prioritization
899*043036a2SApple OSS Distributions      */
900*043036a2SApple OSS Distributions     T_META_ENABLED(false), T_META_TAG_VM_PREFERRED)
901*043036a2SApple OSS Distributions {
902*043036a2SApple OSS Distributions 	setup_ipsec_test();
903*043036a2SApple OSS Distributions 	xfer_1_packet_singly(4, SOCK_STREAM);
904*043036a2SApple OSS Distributions }
905*043036a2SApple OSS Distributions 
906*043036a2SApple OSS Distributions static void
xfer_1_packet_together(int channel_count,int type)907*043036a2SApple OSS Distributions xfer_1_packet_together(int channel_count, int type)
908*043036a2SApple OSS Distributions {
909*043036a2SApple OSS Distributions 	uuid_t uuids[channel_count];
910*043036a2SApple OSS Distributions 	channel_t channels[channel_count];
911*043036a2SApple OSS Distributions 	int sockets[SO_TC_MAX];
912*043036a2SApple OSS Distributions 	channel_ring_t rxrings[channel_count];
913*043036a2SApple OSS Distributions 	int cfds[channel_count];
914*043036a2SApple OSS Distributions 	int kq;
915*043036a2SApple OSS Distributions 
916*043036a2SApple OSS Distributions 	T_QUIET; T_EXPECT_POSIX_SUCCESS(kq = kqueue(), NULL);
917*043036a2SApple OSS Distributions 
918*043036a2SApple OSS Distributions 	setup_channels_and_rings(kq, channel_count, channels, rxrings, NULL, uuids, cfds);
919*043036a2SApple OSS Distributions 
920*043036a2SApple OSS Distributions 	setup_sockets(sockets, type);
921*043036a2SApple OSS Distributions 
922*043036a2SApple OSS Distributions 	for (int si = 0; si < SO_TC_MAX; si++) {
923*043036a2SApple OSS Distributions 		expect_empty_rings(channel_count, rxrings);
924*043036a2SApple OSS Distributions 
925*043036a2SApple OSS Distributions 		send_one_packet(sockets[si], type);
926*043036a2SApple OSS Distributions 	}
927*043036a2SApple OSS Distributions 
928*043036a2SApple OSS Distributions 	/* Sleep to make sure all packets get delivered */
929*043036a2SApple OSS Distributions 	struct timespec to = { 0, 100 * NSEC_PER_MSEC }; // 100 ms
930*043036a2SApple OSS Distributions 	nanosleep(&to, NULL);
931*043036a2SApple OSS Distributions 
932*043036a2SApple OSS Distributions 	/* Wait for the packet delivery and check that all rings event */
933*043036a2SApple OSS Distributions 	struct kevent kev[channel_count + 1];
934*043036a2SApple OSS Distributions 	int nev;
935*043036a2SApple OSS Distributions 	memset(kev, 0, sizeof(kev));
936*043036a2SApple OSS Distributions 	T_QUIET; T_EXPECT_POSIX_SUCCESS(nev = kevent(kq, NULL, 0, kev, channel_count + 1, &to), NULL);
937*043036a2SApple OSS Distributions 	T_QUIET; T_EXPECT_EQ_INT(nev, channel_count, NULL);
938*043036a2SApple OSS Distributions 
939*043036a2SApple OSS Distributions 	uint32_t found[channel_count];
940*043036a2SApple OSS Distributions 	memset(found, 0, sizeof(found));
941*043036a2SApple OSS Distributions 	for (int e = 0; e < nev; e++) {
942*043036a2SApple OSS Distributions 		T_LOG("kevent %lu filter 0x%4x flags 0x%04x fflags 0x%08x data %"PRIdPTR" udata %p",
943*043036a2SApple OSS Distributions 		    kev[e].ident, kev[e].filter, kev[e].flags, kev[e].fflags, kev[e].data, kev[e].udata);
944*043036a2SApple OSS Distributions 
945*043036a2SApple OSS Distributions 		T_QUIET; T_ASSERT_GE_PTR(kev[e].udata, (void *)0, NULL);
946*043036a2SApple OSS Distributions 		T_QUIET; T_ASSERT_LT_PTR(kev[e].udata, (void *)(intptr_t)channel_count, NULL);
947*043036a2SApple OSS Distributions 		int ri = (int)kev[e].udata;
948*043036a2SApple OSS Distributions 		T_QUIET; T_EXPECT_EQ_UINT(found[ri], 0U, NULL);
949*043036a2SApple OSS Distributions 
950*043036a2SApple OSS Distributions 		T_QUIET; T_EXPECT_EQ_ULONG(kev[e].ident, (uintptr_t)cfds[ri], NULL);
951*043036a2SApple OSS Distributions 		T_QUIET; T_EXPECT_EQ_SHORT(kev[e].filter, (short)EVFILT_READ, NULL);
952*043036a2SApple OSS Distributions 		T_QUIET; T_EXPECT_FALSE(kev[e].flags & EV_ERROR, NULL);
953*043036a2SApple OSS Distributions 
954*043036a2SApple OSS Distributions 		if (channel_count == 1) {
955*043036a2SApple OSS Distributions 			T_QUIET; T_EXPECT_EQ_LONG(kev[e].data, (long)SO_TC_MAX, NULL);
956*043036a2SApple OSS Distributions 		} else {
957*043036a2SApple OSS Distributions 			T_QUIET; T_EXPECT_EQ_LONG(kev[e].data, (long)RING_TO_TC_COUNT[ri], NULL);
958*043036a2SApple OSS Distributions 		}
959*043036a2SApple OSS Distributions 
960*043036a2SApple OSS Distributions 		found[ri] += (uint32_t)kev[e].data;
961*043036a2SApple OSS Distributions 	}
962*043036a2SApple OSS Distributions 	/* Check that something came out of all rings */
963*043036a2SApple OSS Distributions 	for (int ri = 0; ri < channel_count; ri++) {
964*043036a2SApple OSS Distributions 		T_QUIET; T_EXPECT_NE_UINT(found[ri], 0U, NULL);
965*043036a2SApple OSS Distributions 	}
966*043036a2SApple OSS Distributions 
967*043036a2SApple OSS Distributions 	/* Make sure it comes out the expected interface */
968*043036a2SApple OSS Distributions 	for (int ri = 0; ri < channel_count; ri++) {
969*043036a2SApple OSS Distributions 		uint32_t sc = os_channel_available_slot_count(rxrings[ri]);
970*043036a2SApple OSS Distributions 		if (channel_count == 1) {
971*043036a2SApple OSS Distributions 			if (sc == SO_TC_MAX) {
972*043036a2SApple OSS Distributions 				T_PASS("ring %d got %"PRIu32" slots expecting %"PRIu32"", ri, sc, SO_TC_MAX);
973*043036a2SApple OSS Distributions 			} else {
974*043036a2SApple OSS Distributions 				T_FAIL("ring %d got %"PRIu32" slots expecting %"PRIu32"", ri, sc, SO_TC_MAX);
975*043036a2SApple OSS Distributions 			}
976*043036a2SApple OSS Distributions 		} else {
977*043036a2SApple OSS Distributions 			if (sc == (uint32_t)RING_TO_TC_COUNT[ri]) {
978*043036a2SApple OSS Distributions 				T_PASS("ring %d got %"PRIu32" slots expecting %"PRIu32"", ri, sc, (uint32_t)RING_TO_TC_COUNT[ri]);
979*043036a2SApple OSS Distributions 			} else {
980*043036a2SApple OSS Distributions 				T_FAIL("ring %d got %"PRIu32" slots expecting %"PRIu32"", ri, sc, (uint32_t)RING_TO_TC_COUNT[ri]);
981*043036a2SApple OSS Distributions 			}
982*043036a2SApple OSS Distributions 		}
983*043036a2SApple OSS Distributions 
984*043036a2SApple OSS Distributions 		drain_ring(rxrings[ri]);
985*043036a2SApple OSS Distributions 	}
986*043036a2SApple OSS Distributions 
987*043036a2SApple OSS Distributions 	cleanup_sockets(sockets);
988*043036a2SApple OSS Distributions 
989*043036a2SApple OSS Distributions 	cleanup_channels_and_rings(channel_count, channels, rxrings, NULL, uuids);
990*043036a2SApple OSS Distributions 
991*043036a2SApple OSS Distributions 	T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(close(kq), NULL);
992*043036a2SApple OSS Distributions }
993*043036a2SApple OSS Distributions 
994*043036a2SApple OSS Distributions T_DECL(ipsec35889979u1m, "transfers 1 packet together of each sevice class over udp to a single ring", T_META_TAG_VM_PREFERRED)
995*043036a2SApple OSS Distributions {
996*043036a2SApple OSS Distributions 	setup_ipsec_test();
997*043036a2SApple OSS Distributions 	xfer_1_packet_together(1, SOCK_DGRAM);
998*043036a2SApple OSS Distributions }
999*043036a2SApple OSS Distributions 
1000*043036a2SApple OSS Distributions T_DECL(ipsec35889979u4m, "transfers 1 packet together of each sevice class over udp to 4 rings", T_META_TAG_VM_PREFERRED)
1001*043036a2SApple OSS Distributions {
1002*043036a2SApple OSS Distributions 	setup_ipsec_test();
1003*043036a2SApple OSS Distributions 	xfer_1_packet_together(4, SOCK_DGRAM);
1004*043036a2SApple OSS Distributions }
1005*043036a2SApple OSS Distributions 
1006*043036a2SApple OSS Distributions T_DECL(ipsec35889979t1m, "transfers 1 packet together of each sevice class over tcp to a single ring", T_META_TAG_VM_PREFERRED)
1007*043036a2SApple OSS Distributions {
1008*043036a2SApple OSS Distributions 	setup_ipsec_test();
1009*043036a2SApple OSS Distributions 	xfer_1_packet_together(1, SOCK_STREAM);
1010*043036a2SApple OSS Distributions }
1011*043036a2SApple OSS Distributions 
1012*043036a2SApple OSS Distributions T_DECL(ipsec35889979t4m, "transfers 1 packet together of each sevice class over tcp to 4 rings",
1013*043036a2SApple OSS Distributions     /* This test will fail because tcp syn packets get elevated
1014*043036a2SApple OSS Distributions      * due to ack prioritization
1015*043036a2SApple OSS Distributions      */
1016*043036a2SApple OSS Distributions     T_META_ENABLED(false), T_META_TAG_VM_PREFERRED)
1017*043036a2SApple OSS Distributions {
1018*043036a2SApple OSS Distributions 	setup_ipsec_test();
1019*043036a2SApple OSS Distributions 	xfer_1_packet_together(4, SOCK_STREAM);
1020*043036a2SApple OSS Distributions }
1021