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