]>
Commit | Line | Data |
---|---|---|
a39ff7e2 A |
1 | |
2 | #include <inttypes.h> | |
3 | #include <stdbool.h> | |
4 | #include <stdio.h> | |
5 | #include <stdlib.h> | |
6 | #include <time.h> | |
7 | #include <string.h> | |
8 | #include <unistd.h> | |
9 | #include <poll.h> | |
10 | #include <sys/event.h> | |
11 | #include <uuid/uuid.h> | |
12 | #include <arpa/inet.h> | |
13 | #include <sys/types.h> | |
14 | #include <sys/sysctl.h> | |
15 | #include <sys/kern_control.h> | |
16 | #include <sys/ioctl.h> | |
17 | #include <sys/socket.h> | |
18 | #include <sys/kern_control.h> | |
19 | #include <sys/sys_domain.h> | |
20 | ||
21 | #include <net/if.h> | |
22 | #include <net/if_ipsec.h> | |
23 | #include <net/if_utun.h> | |
24 | #include <netinet/in.h> | |
25 | #include <netinet/in_var.h> | |
26 | #include <net/pfkeyv2.h> | |
27 | #include <netinet6/ipsec.h> | |
28 | ||
29 | #include <darwintest.h> | |
30 | #include <darwintest_utils.h> | |
31 | ||
32 | #include <skywalk/os_skywalk_private.h> // for SK_FEATURE_* | |
33 | ||
34 | T_GLOBAL_META(T_META_NAMESPACE("xnu.net.tun")); | |
35 | ||
36 | #if 0 | |
37 | static void | |
38 | log_hexdump(const void *inp, size_t len) | |
39 | { | |
40 | unsigned i, off = 0; | |
41 | char buf[9+16*3+1]; | |
42 | for (i = 0; i < len; i++) { | |
43 | if (i % 16 == 0) | |
44 | off = (unsigned)snprintf(buf, sizeof(buf), "%08x:", i); | |
45 | off += (unsigned)snprintf(buf+off, sizeof(buf)-off, " %02x", (((const uint8_t *)inp)[i]) & 0xff); | |
46 | if (i % 16 == 15) | |
47 | T_LOG("%s", buf); | |
48 | } | |
49 | if (len % 16) | |
50 | T_LOG("%s", buf); | |
51 | } | |
52 | #endif | |
53 | ||
54 | static uint64_t | |
55 | get_skywalk_features(void) | |
56 | { | |
57 | uint64_t features = 0; | |
58 | size_t len = sizeof(features); | |
59 | T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(sysctlbyname("kern.skywalk.features", &features, &len, NULL, 0), NULL); | |
60 | T_QUIET; T_ASSERT_EQ(len, sizeof(features), NULL); | |
61 | T_QUIET; T_ASSERT_TRUE(features & SK_FEATURE_SKYWALK, NULL); | |
62 | return features; | |
63 | } | |
64 | ||
65 | static bool g_is_ipsec_test; | |
66 | static bool g_is_utun_test; | |
67 | static int g_OPT_ENABLE_NETIF = -1; | |
68 | static int g_OPT_ENABLE_FLOWSWITCH = -1; | |
69 | static int g_OPT_ENABLE_CHANNEL = -1; | |
70 | static int g_OPT_GET_CHANNEL_UUID = -1; | |
71 | static int g_OPT_IFNAME = -1; | |
72 | static char *g_CONTROL_NAME = NULL; | |
73 | ||
74 | static void | |
75 | setup_ipsec_test(void) | |
76 | { | |
77 | T_LOG("Configuring for ipsec tests"); | |
78 | g_OPT_ENABLE_NETIF = IPSEC_OPT_ENABLE_NETIF; | |
79 | g_OPT_ENABLE_FLOWSWITCH = IPSEC_OPT_ENABLE_FLOWSWITCH; | |
80 | g_OPT_ENABLE_CHANNEL = IPSEC_OPT_ENABLE_CHANNEL; | |
81 | g_OPT_GET_CHANNEL_UUID = IPSEC_OPT_GET_CHANNEL_UUID; | |
82 | g_OPT_IFNAME = IPSEC_OPT_IFNAME; | |
83 | g_CONTROL_NAME = IPSEC_CONTROL_NAME; | |
84 | g_is_ipsec_test = true; | |
85 | } | |
86 | ||
87 | static void | |
88 | setup_utun_test(void) | |
89 | { | |
90 | T_LOG("Configuring for utun tests"); | |
91 | g_OPT_ENABLE_NETIF = UTUN_OPT_ENABLE_NETIF; | |
92 | g_OPT_ENABLE_FLOWSWITCH = UTUN_OPT_ENABLE_FLOWSWITCH; | |
93 | g_OPT_ENABLE_CHANNEL = UTUN_OPT_ENABLE_CHANNEL; | |
94 | g_OPT_GET_CHANNEL_UUID = UTUN_OPT_GET_CHANNEL_UUID; | |
95 | g_OPT_IFNAME = UTUN_OPT_IFNAME; | |
96 | g_CONTROL_NAME = UTUN_CONTROL_NAME; | |
97 | g_is_utun_test = true; | |
98 | } | |
99 | ||
100 | static void | |
101 | check_enables(int tunsock, int enable_netif, int enable_flowswitch, int enable_channel, uuid_t uuid) | |
102 | { | |
103 | int scratch; | |
104 | socklen_t scratchlen, uuidlen; | |
105 | uuid_t scratchuuid; | |
106 | if (!uuid) { | |
107 | uuid = scratchuuid; | |
108 | } | |
109 | ||
110 | //T_LOG("checking tunsock %d", tunsock); | |
111 | ||
112 | scratchlen = sizeof(scratch); | |
113 | T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(getsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_ENABLE_NETIF, | |
114 | &scratch, &scratchlen), NULL); | |
115 | T_QUIET; T_EXPECT_EQ_ULONG((unsigned long )scratchlen, sizeof(scratch), NULL); | |
116 | T_QUIET; T_EXPECT_EQ(scratch, enable_netif, NULL); | |
117 | ||
118 | scratchlen = sizeof(scratch); | |
119 | T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(getsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_ENABLE_FLOWSWITCH, | |
120 | &scratch, &scratchlen), NULL); | |
121 | T_QUIET; T_EXPECT_EQ_ULONG((unsigned long )scratchlen, sizeof(scratch), NULL); | |
122 | if (get_skywalk_features() & SK_FEATURE_NETNS) { | |
123 | if (enable_netif) { | |
124 | T_QUIET; T_EXPECT_EQ(scratch, enable_flowswitch, NULL); | |
125 | } else { | |
126 | T_QUIET; T_EXPECT_EQ(scratch, 0, NULL); | |
127 | } | |
128 | } else { | |
129 | T_QUIET; T_EXPECT_EQ(scratch, 0, NULL); | |
130 | } | |
131 | ||
132 | scratchlen = sizeof(scratch); | |
133 | T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(getsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_ENABLE_CHANNEL, | |
134 | &scratch, &scratchlen), NULL); | |
135 | T_QUIET; T_EXPECT_EQ_ULONG((unsigned long )scratchlen, sizeof(scratch), NULL); | |
136 | if (g_is_ipsec_test && !enable_netif) { | |
137 | T_QUIET; T_EXPECT_EQ(scratch, 0, NULL); | |
138 | } else { | |
139 | T_QUIET; T_EXPECT_EQ(scratch, enable_channel, NULL); | |
140 | } | |
141 | ||
142 | if (scratch) { | |
143 | uuid_clear(uuid); | |
144 | uuidlen = sizeof(uuid_t); | |
145 | T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(getsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_GET_CHANNEL_UUID, | |
146 | uuid, &uuidlen), NULL); | |
147 | T_QUIET; T_EXPECT_EQ_ULONG((unsigned long )uuidlen, sizeof(uuid_t), NULL); | |
148 | T_QUIET; T_EXPECT_FALSE(uuid_is_null(uuid), NULL); | |
149 | } else { | |
150 | uuid_clear(uuid); | |
151 | uuidlen = sizeof(uuid_t); | |
152 | T_QUIET; T_EXPECT_POSIX_FAILURE(getsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_GET_CHANNEL_UUID, | |
153 | uuid, &uuidlen), ENXIO, NULL); | |
154 | T_QUIET; T_EXPECT_EQ_ULONG((unsigned long )uuidlen, sizeof(uuid_t), NULL); | |
155 | T_QUIET; T_EXPECT_TRUE(uuid_is_null(uuid), NULL); | |
156 | } | |
157 | } | |
158 | ||
159 | static void | |
160 | tunsock_get_ifname(int s, char ifname[IFXNAMSIZ]) | |
161 | { | |
162 | socklen_t optlen = IFXNAMSIZ; | |
163 | T_QUIET; T_WITH_ERRNO; T_ASSERT_POSIX_ZERO(getsockopt(s, SYSPROTO_CONTROL, g_OPT_IFNAME, ifname, &optlen), NULL); | |
164 | T_QUIET; T_ASSERT_TRUE(optlen > 0, NULL); | |
165 | T_QUIET; T_ASSERT_TRUE(ifname[optlen-1] == '\0', NULL); | |
166 | T_QUIET; T_ASSERT_TRUE(strlen(ifname)+1 == optlen, "got ifname \"%s\" len %zd expected %u", ifname, strlen(ifname), optlen); | |
167 | } | |
168 | ||
169 | static short | |
170 | ifnet_get_flags(int s, const char ifname[IFNAMSIZ]) | |
171 | { | |
172 | struct ifreq ifr; | |
173 | memset(&ifr, 0, sizeof(ifr)); | |
174 | strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); | |
175 | T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr), NULL); | |
176 | return ifr.ifr_flags; | |
177 | } | |
178 | ||
179 | static void | |
180 | ifnet_add_addr4(const char ifname[IFNAMSIZ], struct in_addr *addr, struct in_addr *mask, struct in_addr *broadaddr) | |
181 | { | |
182 | struct sockaddr_in *sin; | |
183 | struct in_aliasreq ifra; | |
184 | int s; | |
185 | ||
186 | T_QUIET; T_EXPECT_POSIX_SUCCESS(s = socket(AF_INET, SOCK_DGRAM, 0), NULL); | |
187 | ||
188 | memset(&ifra, 0, sizeof(ifra)); | |
189 | strlcpy(ifra.ifra_name, ifname, sizeof(ifra.ifra_name)); | |
190 | ||
191 | if (addr != NULL) { | |
192 | sin = &ifra.ifra_addr; | |
193 | sin->sin_len = sizeof(*sin); | |
194 | sin->sin_family = AF_INET; | |
195 | sin->sin_addr = *addr; | |
196 | } | |
197 | ||
198 | if (mask != NULL) { | |
199 | sin = &ifra.ifra_mask; | |
200 | sin->sin_len = sizeof(*sin); | |
201 | sin->sin_family = AF_INET; | |
202 | sin->sin_addr = *mask; | |
203 | } | |
204 | ||
205 | if (broadaddr != NULL || (addr != NULL && | |
206 | (ifnet_get_flags(s, ifname) & IFF_POINTOPOINT) != 0)) { | |
207 | sin = &ifra.ifra_broadaddr; | |
208 | sin->sin_len = sizeof(*sin); | |
209 | sin->sin_family = AF_INET; | |
210 | sin->sin_addr = (broadaddr != NULL) ? *broadaddr : *addr; | |
211 | } | |
212 | ||
213 | T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(ioctl(s, SIOCAIFADDR, &ifra), NULL); | |
214 | ||
215 | T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(close(s), NULL); | |
216 | } | |
217 | ||
218 | static int g_pfkeyso = -1; | |
219 | static struct in_addr g_addr1, g_addr2; | |
220 | ||
221 | static void | |
222 | create_sa(const char ifname[IFXNAMSIZ], uint8_t type, uint32_t spi, struct in_addr *src, struct in_addr *dst) | |
223 | { | |
224 | if (g_pfkeyso == -1) { | |
225 | T_QUIET; T_EXPECT_POSIX_SUCCESS(g_pfkeyso = socket(PF_KEY, SOCK_RAW, PF_KEY_V2), NULL); | |
226 | } | |
227 | ||
228 | /* | |
229 | <base, SA, (lifetime(HS),) address(SD), (address(P),) | |
230 | key(AE), (identity(SD),) (sensitivity)> | |
231 | */ | |
232 | ||
233 | struct { | |
234 | struct sadb_msg msg __attribute((aligned(sizeof (uint64_t)))); | |
235 | struct sadb_key key __attribute((aligned(sizeof (uint64_t)))); | |
236 | struct sadb_sa sa __attribute((aligned(sizeof (uint64_t)))); | |
237 | struct sadb_x_sa2 sa2 __attribute((aligned(sizeof (uint64_t)))); | |
238 | struct sadb_x_ipsecif ipsecif __attribute((aligned(sizeof (uint64_t)))); | |
239 | struct { | |
240 | struct sadb_address addr __attribute((aligned(sizeof (uint64_t)))); | |
241 | struct sockaddr_in saddr __attribute((aligned(sizeof (uint64_t)))); | |
242 | } src; | |
243 | struct { | |
244 | struct sadb_address addr __attribute((aligned(sizeof (uint64_t)))); | |
245 | struct sockaddr_in saddr __attribute((aligned(sizeof (uint64_t)))); | |
246 | } dst; | |
247 | } addcmd; | |
248 | ||
249 | memset(&addcmd, 0, sizeof(addcmd)); | |
250 | ||
251 | addcmd.msg.sadb_msg_version = PF_KEY_V2; | |
252 | addcmd.msg.sadb_msg_type = type; | |
253 | addcmd.msg.sadb_msg_errno = 0; | |
254 | addcmd.msg.sadb_msg_satype = SADB_SATYPE_ESP; | |
255 | addcmd.msg.sadb_msg_len = PFKEY_UNIT64(sizeof(addcmd)); | |
256 | addcmd.msg.sadb_msg_reserved = 0; | |
257 | addcmd.msg.sadb_msg_seq = 0; | |
258 | addcmd.msg.sadb_msg_pid = (unsigned)getpid(); | |
259 | ||
260 | addcmd.key.sadb_key_len = PFKEY_UNIT64(sizeof(addcmd.key)); | |
261 | addcmd.key.sadb_key_exttype = SADB_EXT_KEY_ENCRYPT; | |
262 | addcmd.key.sadb_key_bits = 0; | |
263 | addcmd.key.sadb_key_reserved = 0; | |
264 | ||
265 | addcmd.sa.sadb_sa_len = PFKEY_UNIT64(sizeof(addcmd.sa)); | |
266 | addcmd.sa.sadb_sa_exttype = SADB_EXT_SA; | |
267 | addcmd.sa.sadb_sa_spi = htonl(spi); | |
268 | addcmd.sa.sadb_sa_replay = 0; | |
269 | addcmd.sa.sadb_sa_state = 0; | |
270 | addcmd.sa.sadb_sa_auth = SADB_AALG_NONE; | |
271 | addcmd.sa.sadb_sa_encrypt = SADB_EALG_NULL; | |
272 | addcmd.sa.sadb_sa_flags = SADB_X_EXT_CYCSEQ; | |
273 | ||
274 | addcmd.sa2.sadb_x_sa2_len = PFKEY_UNIT64(sizeof(addcmd.sa2)); | |
275 | addcmd.sa2.sadb_x_sa2_exttype = SADB_X_EXT_SA2; | |
276 | addcmd.sa2.sadb_x_sa2_mode = IPSEC_MODE_ANY; | |
277 | addcmd.sa2.sadb_x_sa2_alwaysexpire = 1; | |
278 | addcmd.sa2.sadb_x_sa2_flags = SADB_X_EXT_SA2_DELETE_ON_DETACH; | |
279 | addcmd.sa2.sadb_x_sa2_sequence = 0; | |
280 | addcmd.sa2.sadb_x_sa2_reqid = 0; | |
281 | ||
282 | addcmd.ipsecif.sadb_x_ipsecif_len = PFKEY_UNIT64(sizeof(addcmd.ipsecif)); | |
283 | addcmd.ipsecif.sadb_x_ipsecif_exttype = SADB_X_EXT_IPSECIF; | |
284 | memset(addcmd.ipsecif.sadb_x_ipsecif_internal_if, 0, sizeof(addcmd.ipsecif.sadb_x_ipsecif_internal_if)); | |
285 | memset(addcmd.ipsecif.sadb_x_ipsecif_outgoing_if, 0, sizeof(addcmd.ipsecif.sadb_x_ipsecif_outgoing_if)); | |
286 | strlcpy(addcmd.ipsecif.sadb_x_ipsecif_ipsec_if, ifname, sizeof(addcmd.ipsecif.sadb_x_ipsecif_ipsec_if)); | |
287 | addcmd.ipsecif.sadb_x_ipsecif_init_disabled = 0; | |
288 | addcmd.ipsecif.reserved = 0; | |
289 | ||
290 | addcmd.src.addr.sadb_address_len = PFKEY_UNIT64(sizeof(addcmd.src)); | |
291 | addcmd.src.addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC; | |
292 | addcmd.src.addr.sadb_address_proto = IPSEC_ULPROTO_ANY; | |
293 | addcmd.src.addr.sadb_address_prefixlen = sizeof(struct in_addr) << 3; //XXX Why? | |
294 | addcmd.src.addr.sadb_address_reserved = 0; | |
295 | addcmd.src.saddr.sin_len = sizeof(addcmd.src.saddr); | |
296 | addcmd.src.saddr.sin_family = AF_INET; | |
297 | addcmd.src.saddr.sin_port = htons(0); | |
298 | addcmd.src.saddr.sin_addr = *src; | |
299 | ||
300 | addcmd.dst.addr.sadb_address_len = PFKEY_UNIT64(sizeof(addcmd.dst)); | |
301 | addcmd.dst.addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST; | |
302 | addcmd.dst.addr.sadb_address_proto = IPSEC_ULPROTO_ANY; | |
303 | addcmd.dst.addr.sadb_address_prefixlen = sizeof(struct in_addr) << 3; //XXX Why? | |
304 | addcmd.dst.addr.sadb_address_reserved = 0; | |
305 | addcmd.dst.saddr.sin_len = sizeof(addcmd.dst.saddr); | |
306 | addcmd.dst.saddr.sin_family = AF_INET; | |
307 | addcmd.dst.saddr.sin_port = htons(0); | |
308 | addcmd.dst.saddr.sin_addr = *dst; | |
309 | ||
310 | //log_hexdump(&addcmd, sizeof(addcmd)); | |
311 | ||
312 | ssize_t slen; | |
313 | T_QUIET; T_EXPECT_POSIX_SUCCESS(slen = send(g_pfkeyso, &addcmd, sizeof(addcmd), 0), NULL); | |
314 | T_QUIET; T_EXPECT_EQ(slen, (ssize_t)sizeof(addcmd), NULL); | |
315 | } | |
316 | ||
317 | /* Unfortunately, connect can return EBUSY due to: | |
318 | * <rdar://problem/33832735> Always return EBUSY if interface with the same name is in delayed detach even if the unique ID is different. | |
319 | * | |
320 | * We should fix that so we don't return EBUSY when we aren't | |
321 | * requesting a specific interface name, but until then workaround it | |
322 | * in the test. | |
323 | */ | |
324 | ||
325 | static int | |
326 | try_connect(int socket, const struct sockaddr *address, socklen_t address_len) | |
327 | { | |
328 | int ret; | |
329 | while (1) { | |
330 | ret = connect(socket, address, address_len); | |
331 | if (ret != -1 || errno != EBUSY) | |
332 | return ret; | |
333 | sleep(1); | |
334 | } | |
335 | } | |
336 | ||
337 | static int | |
338 | create_tunsock(int enable_netif, int enable_flowswitch, int enable_channel) | |
339 | { | |
340 | int tunsock; | |
341 | struct ctl_info kernctl_info; | |
342 | struct sockaddr_ctl kernctl_addr; | |
343 | uuid_t uuid; | |
344 | socklen_t uuidlen; | |
345 | ||
346 | T_QUIET; T_EXPECT_POSIX_SUCCESS(tunsock = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL), NULL); | |
347 | ||
348 | memset(&kernctl_info, 0, sizeof(kernctl_info)); | |
349 | strlcpy(kernctl_info.ctl_name, g_CONTROL_NAME, sizeof(kernctl_info.ctl_name)); | |
350 | T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(ioctl(tunsock, CTLIOCGINFO, &kernctl_info), NULL); | |
351 | ||
352 | memset(&kernctl_addr, 0, sizeof(kernctl_addr)); | |
353 | kernctl_addr.sc_len = sizeof(kernctl_addr); | |
354 | kernctl_addr.sc_family = AF_SYSTEM; | |
355 | kernctl_addr.ss_sysaddr = AF_SYS_CONTROL; | |
356 | kernctl_addr.sc_id = kernctl_info.ctl_id; | |
357 | kernctl_addr.sc_unit = 0; | |
358 | ||
359 | //T_LOG("enable_netif = %d, enable_flowswitch = %d, enable_channel = %d", | |
360 | //enable_netif, enable_channel, enable_flowswitch); | |
361 | ||
362 | T_QUIET; T_EXPECT_POSIX_FAILURE(setsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_ENABLE_NETIF, | |
363 | &enable_netif, sizeof(enable_netif)), EINVAL, NULL); | |
364 | T_QUIET; T_EXPECT_POSIX_FAILURE(setsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_ENABLE_FLOWSWITCH, | |
365 | &enable_flowswitch, sizeof(enable_flowswitch)), EINVAL, NULL); | |
366 | T_QUIET; T_EXPECT_POSIX_FAILURE(setsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_ENABLE_CHANNEL, | |
367 | &enable_channel, sizeof(enable_channel)), EINVAL, NULL); | |
368 | uuid_clear(uuid); | |
369 | uuidlen = sizeof(uuid_t); | |
370 | T_QUIET; T_EXPECT_POSIX_FAILURE(getsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_GET_CHANNEL_UUID, | |
371 | uuid, &uuidlen), EINVAL, NULL); | |
372 | T_QUIET; T_EXPECT_EQ_ULONG((unsigned long )uuidlen, sizeof(uuid_t), NULL); | |
373 | T_QUIET; T_EXPECT_TRUE(uuid_is_null(uuid), NULL); | |
374 | ||
375 | T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(bind(tunsock, (struct sockaddr *)&kernctl_addr, sizeof(kernctl_addr)), NULL); | |
376 | ||
377 | T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(setsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_ENABLE_NETIF, | |
378 | &enable_netif, sizeof(enable_netif)), NULL); | |
379 | T_QUIET; T_EXPECT_POSIX_FAILURE(setsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_ENABLE_FLOWSWITCH, | |
380 | &enable_flowswitch, sizeof(enable_flowswitch)), EINVAL, NULL); | |
381 | T_QUIET; T_EXPECT_POSIX_FAILURE(setsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_ENABLE_CHANNEL, | |
382 | &enable_channel, sizeof(enable_channel)), EINVAL, NULL); | |
383 | uuid_clear(uuid); | |
384 | uuidlen = sizeof(uuid_t); | |
385 | T_QUIET; T_EXPECT_POSIX_FAILURE(getsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_GET_CHANNEL_UUID, | |
386 | uuid, &uuidlen), ENXIO, NULL); | |
387 | T_QUIET; T_EXPECT_EQ_ULONG((unsigned long )uuidlen, sizeof(uuid_t), NULL); | |
388 | T_QUIET; T_EXPECT_TRUE(uuid_is_null(uuid), NULL); | |
389 | ||
390 | T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(try_connect(tunsock, (struct sockaddr *)&kernctl_addr, sizeof(kernctl_addr)), NULL); | |
391 | ||
392 | T_QUIET; T_EXPECT_POSIX_FAILURE(setsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_ENABLE_NETIF, | |
393 | &enable_netif, sizeof(enable_netif)), EINVAL, NULL); | |
394 | ||
395 | if (get_skywalk_features() & SK_FEATURE_NETNS) { | |
396 | if (enable_netif) { | |
397 | T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(setsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_ENABLE_FLOWSWITCH, | |
398 | &enable_flowswitch, sizeof(enable_flowswitch)), NULL); | |
399 | } else { | |
400 | T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_FAILURE(setsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_ENABLE_FLOWSWITCH, | |
401 | &enable_flowswitch, sizeof(enable_flowswitch)), ENOENT, NULL); | |
402 | } | |
403 | } else { | |
404 | T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_FAILURE(setsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_ENABLE_FLOWSWITCH, | |
405 | &enable_flowswitch, sizeof(enable_flowswitch)), ENOTSUP, NULL); | |
406 | } | |
407 | ||
408 | if (enable_channel) { | |
409 | if (g_is_ipsec_test && !enable_netif) { | |
410 | /* ipsec doesn't support channels without a netif */ | |
411 | T_QUIET; T_EXPECT_POSIX_FAILURE(setsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_ENABLE_CHANNEL, | |
412 | &enable_channel, sizeof(enable_channel)), EOPNOTSUPP, NULL); | |
413 | uuid_clear(uuid); | |
414 | uuidlen = sizeof(uuid_t); | |
415 | T_QUIET; T_EXPECT_POSIX_FAILURE(getsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_GET_CHANNEL_UUID, | |
416 | uuid, &uuidlen), ENXIO, NULL); | |
417 | T_QUIET; T_EXPECT_EQ_ULONG((unsigned long )uuidlen, sizeof(uuid_t), NULL); | |
418 | T_QUIET; T_EXPECT_TRUE(uuid_is_null(uuid), NULL); | |
419 | } else { | |
420 | T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(setsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_ENABLE_CHANNEL, | |
421 | &enable_channel, sizeof(enable_channel)), NULL); | |
422 | uuid_clear(uuid); | |
423 | uuidlen = sizeof(uuid_t); | |
424 | T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(getsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_GET_CHANNEL_UUID, | |
425 | uuid, &uuidlen), NULL); | |
426 | T_QUIET; T_EXPECT_EQ_ULONG((unsigned long )uuidlen, sizeof(uuid_t), NULL); | |
427 | T_QUIET; T_EXPECT_FALSE(uuid_is_null(uuid), NULL); | |
428 | } | |
429 | } else { | |
430 | T_QUIET; T_EXPECT_POSIX_FAILURE(setsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_ENABLE_CHANNEL, | |
431 | &enable_channel, sizeof(enable_channel)), ENXIO, NULL); | |
432 | uuid_clear(uuid); | |
433 | uuidlen = sizeof(uuid_t); | |
434 | T_QUIET; T_EXPECT_POSIX_FAILURE(getsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_GET_CHANNEL_UUID, | |
435 | uuid, &uuidlen), ENXIO, NULL); | |
436 | T_QUIET; T_EXPECT_EQ_ULONG((unsigned long )uuidlen, sizeof(uuid_t), NULL); | |
437 | T_QUIET; T_EXPECT_TRUE(uuid_is_null(uuid), NULL); | |
438 | } | |
439 | ||
440 | check_enables(tunsock, enable_netif, enable_flowswitch, enable_channel, uuid); | |
441 | ||
442 | //T_LOG("Returning tunsock %d", tunsock); | |
443 | ||
444 | return tunsock; | |
445 | } | |
446 | ||
447 | #if 0 | |
448 | static void | |
449 | ipsec_stats(void) | |
450 | { | |
451 | struct ifmibdata ifmd; | |
452 | ||
453 | len = sizeof(struct ifmibdata); | |
454 | name[3] = IFMIB_IFDATA; | |
455 | name[4] = interesting_row; | |
456 | name[5] = IpFDATA_GENERAL; | |
457 | if (sysctl(name, 6, &ifmd, &len, (void *)0, 0) == -1) | |
458 | err(1, "sysctl IFDATA_GENERAL %d", interesting_row); | |
459 | } | |
460 | #endif | |
461 | ||
462 | static void | |
463 | permute_enables(void) | |
464 | { | |
465 | int tunsock; | |
466 | T_EXPECT_GE(tunsock = create_tunsock(false, false, false), 0, NULL); | |
467 | T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(close(tunsock), NULL); | |
468 | T_EXPECT_GE(tunsock = create_tunsock(false, false, true), 0, NULL); | |
469 | T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(close(tunsock), NULL); | |
470 | T_EXPECT_GE(tunsock = create_tunsock(false, true, false), 0, NULL); | |
471 | T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(close(tunsock), NULL); | |
472 | T_EXPECT_GE(tunsock = create_tunsock(false, true, true), 0, NULL); | |
473 | T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(close(tunsock), NULL); | |
474 | T_EXPECT_GE(tunsock = create_tunsock(true, false, false), 0, NULL); | |
475 | T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(close(tunsock), NULL); | |
476 | T_EXPECT_GE(tunsock = create_tunsock(true, false, true), 0, NULL); | |
477 | T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(close(tunsock), NULL); | |
478 | T_EXPECT_GE(tunsock = create_tunsock(true, true, false), 0, NULL); | |
479 | T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(close(tunsock), NULL); | |
480 | T_EXPECT_GE(tunsock = create_tunsock(true, true, true), 0, NULL); | |
481 | T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(close(tunsock), NULL); | |
482 | } | |
483 | ||
484 | T_DECL(ipsec_enables, "This test checks combinations of netif/channel/flowswitch on ipsec") | |
485 | { | |
486 | setup_ipsec_test(); | |
487 | permute_enables(); | |
488 | } | |
489 | ||
490 | T_DECL(utun_enables, "This test checks combinations of netif/channel/flowswitch on utun") | |
491 | { | |
492 | setup_utun_test(); | |
493 | permute_enables(); | |
494 | } | |
495 | ||
496 | static int g_tunsock = -1; | |
497 | ||
498 | static void | |
499 | cleanup_tunsock(void) | |
500 | { | |
501 | T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(close(g_tunsock), NULL); | |
502 | T_QUIET; T_EXPECT_POSIX_FAILURE(close(g_tunsock), EBADF, NULL); | |
503 | if (g_is_ipsec_test) { | |
504 | T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(close(g_pfkeyso), NULL); | |
505 | T_QUIET; T_EXPECT_POSIX_FAILURE(close(g_pfkeyso), EBADF, NULL); | |
506 | } | |
507 | } | |
508 | ||
509 | static void | |
510 | setup_tunsock(void) | |
511 | { | |
512 | T_ASSERT_GE(g_tunsock = create_tunsock(true, false, true), 0, NULL); | |
513 | T_ATEND(cleanup_tunsock); | |
514 | ||
515 | char ifname[IFXNAMSIZ]; | |
516 | tunsock_get_ifname(g_tunsock, ifname); | |
517 | ||
518 | T_LOG("Created interface %s", ifname); | |
519 | ||
520 | uint32_t ifaddr = (10 << 24) | ((unsigned)getpid()&0xffff) << 8 | 160; | |
521 | struct in_addr mask; | |
522 | g_addr1.s_addr = htonl(ifaddr); | |
523 | g_addr2.s_addr = htonl(ifaddr+1); | |
524 | mask.s_addr = htonl(0xffffffff); | |
525 | ||
526 | ifnet_add_addr4(ifname, &g_addr1, &mask, &g_addr2); | |
527 | ||
528 | if (g_is_ipsec_test) { | |
529 | create_sa(ifname, SADB_ADD, 12345, &g_addr1, &g_addr2); | |
530 | create_sa(ifname, SADB_ADD, 12346, &g_addr2, &g_addr1); | |
531 | } | |
532 | } | |
533 | ||
534 | T_DECL(setup_ipsec, "This test sets up an ipsec interface") | |
535 | { | |
536 | setup_ipsec_test(); | |
537 | setup_tunsock(); | |
538 | } | |
539 | ||
540 | T_DECL(setup_utun, "This test sets up a utun interface") | |
541 | { | |
542 | setup_utun_test(); | |
543 | setup_tunsock(); | |
544 | } |