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