xref: /xnu-11215.61.5/tests/skywalk/skt_mpprotons.c (revision 4f1223e81cd707a65cc109d0b8ad6653699da3c4)
1 /*
2  * Copyright (c) 2019-2024 Apple Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5  *
6  * This file contains Original Code and/or Modifications of Original Code
7  * as defined in and that are subject to the Apple Public Source License
8  * Version 2.0 (the 'License'). You may not use this file except in
9  * compliance with the License. The rights granted to you under the License
10  * may not be used to create, or enable the creation or redistribution of,
11  * unlawful or unlicensed copies of an Apple operating system, or to
12  * circumvent, violate, or enable the circumvention or violation of, any
13  * terms of an Apple operating system software license agreement.
14  *
15  * Please obtain a copy of the License at
16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17  *
18  * The Original Code and all software distributed under the License are
19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23  * Please see the License for the specific language governing rights and
24  * limitations under the License.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 
29 #include <err.h>
30 #include <assert.h>
31 #include <errno.h>
32 #include <semaphore.h>
33 #include <stdio.h>
34 #include <spawn.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <sysexits.h>
38 #include <sys/socket.h>
39 #include <uuid/uuid.h>
40 #include <unistd.h>
41 #include <arpa/inet.h>
42 #include <darwintest.h>
43 #include "skywalk_test_driver.h"
44 #include "skywalk_test_utils.h"
45 #include "skywalk_test_common.h"
46 
47 static const char * ifname;
48 static struct in_addr our_ip, dst_ip, zero_ip, nowhere_ip;
49 static struct in_addr our_mask;
50 static struct sktc_nexus_handles handles;
51 
52 #define SEM_1ST_FLOW_CREATED "/skt_mpprotons_1FC"
53 #define SEM_2ND_FLOW_FAILED "/skt_mpprotons_2FF"
54 
55 static void
skt_flow_req_should_succeed(sa_family_t af,void * src,void * dst,uint8_t protocol,uint16_t sport,uint16_t dport)56 skt_flow_req_should_succeed(sa_family_t af, void *src, void *dst,
57     uint8_t protocol, uint16_t sport, uint16_t dport)
58 {
59 	struct sktu_flow *flow;
60 
61 	flow = sktu_create_nexus_flow(&handles, af, src, dst, protocol, sport, dport);
62 	assert(flow);
63 }
64 
65 static void
skt_flow_req_should_fail(sa_family_t af,void * src,void * dst,uint8_t protocol,uint16_t sport,uint16_t dport)66 skt_flow_req_should_fail(sa_family_t af, void *src, void *dst,
67     uint8_t protocol, uint16_t sport, uint16_t dport)
68 {
69 	struct sktu_flow *flow;
70 
71 	flow = sktu_create_nexus_flow(&handles, af, src, dst, protocol, sport, dport);
72 	assert(!flow);
73 }
74 
75 static int
skt_protons_main(int argc,char * argv[])76 skt_protons_main(int argc, char *argv[])
77 {
78 	ifname = FETH0_NAME;
79 	our_mask = sktc_make_in_addr(IN_CLASSC_NET);
80 	our_ip = sktc_feth0_in_addr();
81 	dst_ip = sktc_feth1_in_addr();
82 	zero_ip = (struct in_addr){.s_addr = htonl(INADDR_ANY)};
83 	nowhere_ip = sktc_nowhere_in_addr();
84 
85 	bzero(&handles, sizeof(handles));
86 	strlcpy(handles.netif_ifname, ifname, sizeof(handles.netif_ifname));
87 	handles.netif_addr = our_ip;
88 	handles.netif_mask = our_mask;
89 	sktc_create_flowswitch_no_address(&handles, -1, -1, -1, -1, 0);
90 
91 	skt_flow_req_should_fail(AF_INET, &our_ip, &dst_ip, IPPROTO_TCP, 0, 0);
92 	skt_flow_req_should_fail(AF_INET, &our_ip, &dst_ip, IPPROTO_UDP, 0, 0);
93 	skt_flow_req_should_fail(AF_INET, &our_ip, &dst_ip, IPPROTO_TTP, 1, 0);
94 	skt_flow_req_should_fail(AF_INET, &our_ip, &dst_ip, IPPROTO_TTP, 0, 1);
95 	skt_flow_req_should_fail(AF_INET, &our_ip, &dst_ip, IPPROTO_TTP, 1, 1);
96 	skt_flow_req_should_fail(AF_INET, &our_ip, &dst_ip, IPPROTO_RAW, 0, 0);
97 
98 	skt_flow_req_should_succeed(AF_INET, &our_ip, &dst_ip, IPPROTO_TTP, 0, 0);
99 	skt_flow_req_should_succeed(AF_INET, &our_ip, &nowhere_ip, IPPROTO_TTP, 0, 0);
100 	skt_flow_req_should_fail(AF_INET, &our_ip, &dst_ip, IPPROTO_TTP, 0, 0);
101 
102 	sktc_cleanup_flowswitch(&handles);
103 
104 	return 0;
105 }
106 
107 static void
skt_protons_net_init(void)108 skt_protons_net_init(void)
109 {
110 	sktc_ifnet_feth_pair_create(FETH_FLAGS_TXSTART);
111 }
112 
113 static void
skt_protons_net_fini(void)114 skt_protons_net_fini(void)
115 {
116 	sktc_ifnet_feth_pair_destroy();
117 
118 	// cleanup any leftovers
119 	sem_unlink(SEM_1ST_FLOW_CREATED);
120 	sem_unlink(SEM_2ND_FLOW_FAILED);
121 }
122 
123 struct skywalk_test skt_protons = {
124 	.skt_testname = "protons",
125 	.skt_testdesc = "test skywalk protocol namespace",
126 	.skt_required_features = SK_FEATURE_SKYWALK | SK_FEATURE_NEXUS_FLOWSWITCH | SK_FEATURE_NETNS,
127 	.skt_main = skt_protons_main,
128 	.skt_argv = { NULL },
129 	.skt_init = skt_protons_net_init,
130 	.skt_fini = skt_protons_net_fini,
131 };
132 
133 /****************************************************************/
134 
135 static int
skt_mpprotons_main(int argc,char * argv[])136 skt_mpprotons_main(int argc, char *argv[])
137 {
138 	char buf[1] = { 0 };
139 	const char * ifname;
140 	struct in_addr our_ip, peer_ip;
141 	struct in_addr our_mask;
142 	ssize_t ret;
143 
144 	assert(!strcmp(argv[3], "--child"));
145 	int child = atoi(argv[4]);
146 	T_LOG("in child %d\n", child);
147 
148 	if (child == 0) {
149 		ifname = FETH0_NAME;
150 		our_ip = sktc_feth0_in_addr();
151 		peer_ip = sktc_feth1_in_addr();
152 	} else {
153 		child = 1;
154 		ifname = FETH1_NAME;
155 		our_ip = sktc_feth1_in_addr();
156 		peer_ip = sktc_feth0_in_addr();
157 	}
158 	our_mask = sktc_make_in_addr(IN_CLASSC_NET);
159 
160 	bzero(&handles, sizeof(handles));
161 	strlcpy(handles.netif_ifname, ifname, sizeof(handles.netif_ifname));
162 	handles.netif_addr = our_ip;
163 	handles.netif_mask = our_mask;
164 	sktc_create_flowswitch_no_address(&handles, -1, -1, -1, -1, 0);
165 
166 	sem_t *sem_flow_created = sem_open(SEM_1ST_FLOW_CREATED, O_CREAT, 0660, 0);
167 	sem_t *sem_dup_flow_failed = sem_open(SEM_2ND_FLOW_FAILED, O_CREAT, 0660, 0);
168 	if (sem_flow_created == SEM_FAILED || sem_dup_flow_failed == SEM_FAILED) {
169 		err(EX_OSERR, "sem open failed");
170 	}
171 
172 	if ((ret = write(MPTEST_SEQ_FILENO, buf, sizeof(buf))) == -1) {
173 		SKT_LOG("write fail: %s\n", strerror(errno));
174 		return 1;
175 	}
176 	assert(ret == 1);
177 
178 	/* Wait for go signal */
179 	if ((ret = read(MPTEST_SEQ_FILENO, buf, sizeof(buf))) == -1) {
180 		SKT_LOG("read fail: %s\n", strerror(errno));
181 		return 1;
182 	}
183 	assert(ret == 1);
184 
185 	if (child == 0) {
186 		skt_flow_req_should_succeed(AF_INET, &our_ip, &dst_ip, IPPROTO_IPEIP, 0, 0);
187 		sem_post(sem_flow_created);
188 		sem_wait(sem_dup_flow_failed);
189 		sem_post(sem_dup_flow_failed);
190 	}
191 
192 	if (child == 1) {
193 		sem_wait(sem_flow_created);
194 		skt_flow_req_should_fail(AF_INET, &our_ip, &dst_ip, IPPROTO_IPEIP, 0, 0);
195 		sem_post(sem_flow_created);
196 		sem_post(sem_dup_flow_failed);
197 	}
198 
199 	sem_close(sem_flow_created);
200 	sem_close(sem_dup_flow_failed);
201 
202 	return 0;
203 }
204 
205 struct skywalk_mptest skt_mpprotons = {
206 	.skt_testname = "mpprotons",
207 	.skt_testdesc = "test skywalk protocol namespace with two process doing conflicting reservation",
208 	.skt_required_features = SK_FEATURE_SKYWALK | SK_FEATURE_NEXUS_NETIF | SK_FEATURE_NEXUS_FLOWSWITCH,
209 	.skt_nchildren = 2,
210 	.skt_main = skt_mpprotons_main,
211 	.skt_init = skt_protons_net_init,
212 	.skt_fini = skt_protons_net_fini,
213 };
214