xref: /xnu-10002.61.3/tests/ipsec.m (revision 0f4c859e951fba394238ab619495c4e1d54d0f34)
1*0f4c859eSApple OSS Distributions#import <darwintest.h>
2*0f4c859eSApple OSS Distributions#import <darwintest_utils.h>
3*0f4c859eSApple OSS Distributions#import <dispatch/dispatch.h>
4*0f4c859eSApple OSS Distributions#import <net/pfkeyv2.h>
5*0f4c859eSApple OSS Distributions#import <netinet6/ipsec.h>
6*0f4c859eSApple OSS Distributions#import <arpa/inet.h>
7*0f4c859eSApple OSS Distributions#import <NetworkExtension/NetworkExtensionPrivate.h>
8*0f4c859eSApple OSS Distributions#import <System/net/bpf.h>
9*0f4c859eSApple OSS Distributions#import <System/netinet/ip.h>
10*0f4c859eSApple OSS Distributions#import <System/netinet/ip6.h>
11*0f4c859eSApple OSS Distributions
12*0f4c859eSApple OSS Distributions#import <sys/mbuf.h>
13*0f4c859eSApple OSS Distributions
14*0f4c859eSApple OSS Distributions
15*0f4c859eSApple OSS DistributionsT_GLOBAL_META(
16*0f4c859eSApple OSS Distributions	T_META_NAMESPACE("xnu.ipsec"),
17*0f4c859eSApple OSS Distributions	T_META_ASROOT(true),
18*0f4c859eSApple OSS Distributions	T_META_CHECK_LEAKS(false));
19*0f4c859eSApple OSS Distributions
20*0f4c859eSApple OSS Distributionstypedef enum {
21*0f4c859eSApple OSS Distributions	TEST_INVALID = 0,
22*0f4c859eSApple OSS Distributions	TEST_IPSEC_IPv4_ENCAPSULATE_PANIC = 1,
23*0f4c859eSApple OSS Distributions	TEST_IPSEC_IPv6_ENCAPSULATE_PANIC = 2,
24*0f4c859eSApple OSS Distributions} test_identifier;
25*0f4c859eSApple OSS Distributions
26*0f4c859eSApple OSS Distributions#define TEST_SRC_ADDRESS_IPv4                           "10.0.0.2"
27*0f4c859eSApple OSS Distributions#define TEST_DST_ADDRESS_IPv4                           "10.0.0.3"
28*0f4c859eSApple OSS Distributions#define TEST_IPSEC_IPv4_INTERFACE_ADDRESS               "192.168.10.10"
29*0f4c859eSApple OSS Distributions#define TEST_IPSEC_IPv6_INTERFACE_ADDRESS               "fdd3:0f89:9afd:9b9c::1234"
30*0f4c859eSApple OSS Distributions#define TEST_DELEGATE_IPSEC_INTERFACE_ADDRESS           "192.168.20.10"
31*0f4c859eSApple OSS Distributions#define TEST_IPSEC_IPv4_INTERFACE_MASK                  "255.255.255.255"
32*0f4c859eSApple OSS Distributions#define TEST_IPSEC_IPv6_INTERFACE_MASK                  "ffff:ffff:ffff:ffff::"
33*0f4c859eSApple OSS Distributions
34*0f4c859eSApple OSS Distributionsstatic test_identifier test_id = TEST_INVALID;
35*0f4c859eSApple OSS Distributionsstatic dispatch_source_t pfkey_source = NULL;
36*0f4c859eSApple OSS Distributionsstatic NEVirtualInterfaceRef ipsecInterface = NULL;
37*0f4c859eSApple OSS Distributionsstatic NEVirtualInterfaceRef delegateIPsecInterface = NULL;
38*0f4c859eSApple OSS Distributionsstatic int bpf_fd = -1;
39*0f4c859eSApple OSS Distributions
40*0f4c859eSApple OSS Distributionsstatic void bpf_write(int fd);
41*0f4c859eSApple OSS Distributionsstatic void pfkey_cleanup(void);
42*0f4c859eSApple OSS Distributionsstatic void pfkey_process_message_test_encapsulate_panic(uint8_t **mhp, int pfkey_socket);
43*0f4c859eSApple OSS Distributions
44*0f4c859eSApple OSS Distributionsstatic void(*const process_pfkey_message_tests[])(uint8_t * *mhp, int pfkey_socket) =
45*0f4c859eSApple OSS Distributions{
46*0f4c859eSApple OSS Distributions	NULL,
47*0f4c859eSApple OSS Distributions	pfkey_process_message_test_encapsulate_panic,    // TEST_IPSEC_IPv4_ENCAPSULATE_PANIC
48*0f4c859eSApple OSS Distributions	pfkey_process_message_test_encapsulate_panic,    // TEST_IPSEC_IPv6_ENCAPSULATE_PANIC
49*0f4c859eSApple OSS Distributions};
50*0f4c859eSApple OSS Distributions
51*0f4c859eSApple OSS Distributionsstatic void
52*0f4c859eSApple OSS Distributionssend_pkey_add_sa(int pfkey_socket, uint32_t spi, const char *src, const char *dst, int family)
53*0f4c859eSApple OSS Distributions{
54*0f4c859eSApple OSS Distributions	uint8_t payload[MCLBYTES] __attribute__ ((aligned(32)));
55*0f4c859eSApple OSS Distributions	bzero(payload, sizeof(payload));
56*0f4c859eSApple OSS Distributions	uint16_t tlen = 0;
57*0f4c859eSApple OSS Distributions
58*0f4c859eSApple OSS Distributions	struct sadb_msg *msg_payload = (struct sadb_msg *)payload;
59*0f4c859eSApple OSS Distributions	msg_payload->sadb_msg_version = PF_KEY_V2;
60*0f4c859eSApple OSS Distributions	msg_payload->sadb_msg_type = SADB_ADD;
61*0f4c859eSApple OSS Distributions	msg_payload->sadb_msg_errno = 0;
62*0f4c859eSApple OSS Distributions	msg_payload->sadb_msg_satype = SADB_SATYPE_ESP;
63*0f4c859eSApple OSS Distributions	msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen);
64*0f4c859eSApple OSS Distributions	msg_payload->sadb_msg_reserved = 0;
65*0f4c859eSApple OSS Distributions	msg_payload->sadb_msg_seq = 0;
66*0f4c859eSApple OSS Distributions	msg_payload->sadb_msg_pid = (u_int32_t)getpid();
67*0f4c859eSApple OSS Distributions	tlen += sizeof(*msg_payload);
68*0f4c859eSApple OSS Distributions
69*0f4c859eSApple OSS Distributions	struct sadb_sa_2 *sa2_payload = (struct sadb_sa_2 *)(void *)(payload + tlen);
70*0f4c859eSApple OSS Distributions	sa2_payload->sa.sadb_sa_len = PFKEY_UNIT64(sizeof(*sa2_payload));
71*0f4c859eSApple OSS Distributions	sa2_payload->sa.sadb_sa_exttype = SADB_EXT_SA;
72*0f4c859eSApple OSS Distributions	sa2_payload->sa.sadb_sa_spi = htonl(spi);
73*0f4c859eSApple OSS Distributions	sa2_payload->sa.sadb_sa_replay = 4;
74*0f4c859eSApple OSS Distributions	sa2_payload->sa.sadb_sa_state = SADB_SASTATE_LARVAL;
75*0f4c859eSApple OSS Distributions	sa2_payload->sa.sadb_sa_auth = SADB_X_AALG_SHA2_256;
76*0f4c859eSApple OSS Distributions	sa2_payload->sa.sadb_sa_encrypt = SADB_X_EALG_AESCBC;
77*0f4c859eSApple OSS Distributions	sa2_payload->sa.sadb_sa_flags |= (SADB_X_EXT_NATT | SADB_X_EXT_NATT_KEEPALIVE);
78*0f4c859eSApple OSS Distributions	sa2_payload->sadb_sa_natt_src_port = htons(4500);
79*0f4c859eSApple OSS Distributions	sa2_payload->sadb_sa_natt_port = 4500;
80*0f4c859eSApple OSS Distributions	sa2_payload->sadb_sa_natt_interval = 20;
81*0f4c859eSApple OSS Distributions	sa2_payload->sadb_sa_natt_offload_interval = 0;
82*0f4c859eSApple OSS Distributions	tlen += sizeof(*sa2_payload);
83*0f4c859eSApple OSS Distributions
84*0f4c859eSApple OSS Distributions	struct sadb_x_sa2 *sa2_x_payload = (struct sadb_x_sa2 *)(void *)(payload + tlen);
85*0f4c859eSApple OSS Distributions	sa2_x_payload->sadb_x_sa2_len = PFKEY_UNIT64(sizeof(*sa2_x_payload));
86*0f4c859eSApple OSS Distributions	sa2_x_payload->sadb_x_sa2_exttype = SADB_X_EXT_SA2;
87*0f4c859eSApple OSS Distributions	sa2_x_payload->sadb_x_sa2_mode = IPSEC_MODE_TUNNEL;
88*0f4c859eSApple OSS Distributions	sa2_x_payload->sadb_x_sa2_reqid = 0;
89*0f4c859eSApple OSS Distributions	tlen += sizeof(*sa2_x_payload);
90*0f4c859eSApple OSS Distributions
91*0f4c859eSApple OSS Distributions	uint8_t prefixlen = (family == AF_INET) ? (sizeof(struct in_addr) << 3) : (sizeof(struct in6_addr) << 3);
92*0f4c859eSApple OSS Distributions
93*0f4c859eSApple OSS Distributions	struct sadb_address *src_address_payload = (struct sadb_address *)(void *)(payload + tlen);
94*0f4c859eSApple OSS Distributions	src_address_payload->sadb_address_exttype = SADB_EXT_ADDRESS_SRC & 0xffff;
95*0f4c859eSApple OSS Distributions	src_address_payload->sadb_address_proto = IPSEC_ULPROTO_ANY & 0xff;
96*0f4c859eSApple OSS Distributions	src_address_payload->sadb_address_prefixlen = prefixlen;
97*0f4c859eSApple OSS Distributions	src_address_payload->sadb_address_reserved = 0;
98*0f4c859eSApple OSS Distributions	tlen += sizeof(*src_address_payload);
99*0f4c859eSApple OSS Distributions
100*0f4c859eSApple OSS Distributions	if (family == AF_INET) {
101*0f4c859eSApple OSS Distributions		struct sockaddr_in *src4 = (struct sockaddr_in *)(void *)(payload + tlen);
102*0f4c859eSApple OSS Distributions		T_QUIET; T_ASSERT_EQ_INT(inet_pton(AF_INET, src, &src4->sin_addr), 1, "src address fail");
103*0f4c859eSApple OSS Distributions		src4->sin_family = AF_INET;
104*0f4c859eSApple OSS Distributions		src4->sin_len = sizeof(*src4);
105*0f4c859eSApple OSS Distributions		uint16_t len = sizeof(*src_address_payload) + PFKEY_ALIGN8(src4->sin_len);
106*0f4c859eSApple OSS Distributions		src_address_payload->sadb_address_len = PFKEY_UNIT64(len);
107*0f4c859eSApple OSS Distributions		tlen += PFKEY_ALIGN8(src4->sin_len);
108*0f4c859eSApple OSS Distributions	} else {
109*0f4c859eSApple OSS Distributions		struct sockaddr_in6 *src6 = (struct sockaddr_in6 *)(void *)(payload + tlen);
110*0f4c859eSApple OSS Distributions		T_QUIET; T_ASSERT_EQ_INT(inet_pton(AF_INET6, src, &src6->sin6_addr), 1, "src address fail");
111*0f4c859eSApple OSS Distributions		src6->sin6_family = AF_INET6;
112*0f4c859eSApple OSS Distributions		src6->sin6_len = sizeof(*src6);
113*0f4c859eSApple OSS Distributions		uint16_t len = sizeof(*src_address_payload) + PFKEY_ALIGN8(src6->sin6_len);
114*0f4c859eSApple OSS Distributions		src_address_payload->sadb_address_len = PFKEY_UNIT64(len);
115*0f4c859eSApple OSS Distributions		tlen += PFKEY_ALIGN8(src6->sin6_len);
116*0f4c859eSApple OSS Distributions	}
117*0f4c859eSApple OSS Distributions
118*0f4c859eSApple OSS Distributions	struct sadb_address *dst_address_payload = (struct sadb_address *)(void *)(payload + tlen);
119*0f4c859eSApple OSS Distributions	dst_address_payload->sadb_address_exttype = SADB_EXT_ADDRESS_DST & 0xffff;
120*0f4c859eSApple OSS Distributions	dst_address_payload->sadb_address_proto = IPSEC_ULPROTO_ANY & 0xff;
121*0f4c859eSApple OSS Distributions	dst_address_payload->sadb_address_prefixlen = prefixlen;
122*0f4c859eSApple OSS Distributions	dst_address_payload->sadb_address_reserved = 0;
123*0f4c859eSApple OSS Distributions	tlen += sizeof(*dst_address_payload);
124*0f4c859eSApple OSS Distributions
125*0f4c859eSApple OSS Distributions	if (family == AF_INET) {
126*0f4c859eSApple OSS Distributions		struct sockaddr_in *dst4 = (struct sockaddr_in *)(void *)(payload + tlen);
127*0f4c859eSApple OSS Distributions		T_QUIET; T_ASSERT_EQ_INT(inet_pton(AF_INET, dst, &dst4->sin_addr), 1, "dst address fail");
128*0f4c859eSApple OSS Distributions		dst4->sin_family = AF_INET;
129*0f4c859eSApple OSS Distributions		dst4->sin_len = sizeof(*dst4);
130*0f4c859eSApple OSS Distributions		uint16_t len = sizeof(*dst_address_payload) + PFKEY_ALIGN8(dst4->sin_len);
131*0f4c859eSApple OSS Distributions		dst_address_payload->sadb_address_len = PFKEY_UNIT64(len);
132*0f4c859eSApple OSS Distributions		tlen += PFKEY_ALIGN8(dst4->sin_len);
133*0f4c859eSApple OSS Distributions	} else {
134*0f4c859eSApple OSS Distributions		struct sockaddr_in6 *dst6 = (struct sockaddr_in6 *)(void *)(payload + tlen);
135*0f4c859eSApple OSS Distributions		T_QUIET; T_ASSERT_EQ_INT(inet_pton(AF_INET6, dst, &dst6->sin6_addr), 1, "dst address fail");
136*0f4c859eSApple OSS Distributions		dst6->sin6_family = AF_INET6;
137*0f4c859eSApple OSS Distributions		dst6->sin6_len = sizeof(*dst6);
138*0f4c859eSApple OSS Distributions		uint16_t len = sizeof(*dst_address_payload) + PFKEY_ALIGN8(dst6->sin6_len);
139*0f4c859eSApple OSS Distributions		dst_address_payload->sadb_address_len = PFKEY_UNIT64(len);
140*0f4c859eSApple OSS Distributions		tlen += PFKEY_ALIGN8(dst6->sin6_len);
141*0f4c859eSApple OSS Distributions	}
142*0f4c859eSApple OSS Distributions
143*0f4c859eSApple OSS Distributions	CFStringRef ipsecIfName = NEVirtualInterfaceCopyName(ipsecInterface);
144*0f4c859eSApple OSS Distributions	T_QUIET; T_ASSERT_NOTNULL(ipsecIfName, "failed to get ipsec interface name");
145*0f4c859eSApple OSS Distributions	char ifname[IFNAMSIZ];
146*0f4c859eSApple OSS Distributions	CFStringGetCString(ipsecIfName, ifname, IFNAMSIZ, kCFStringEncodingUTF8);
147*0f4c859eSApple OSS Distributions
148*0f4c859eSApple OSS Distributions	CFStringRef delegateIPsecIfName = NEVirtualInterfaceCopyName(delegateIPsecInterface);
149*0f4c859eSApple OSS Distributions	T_QUIET; T_ASSERT_NOTNULL(delegateIPsecIfName, "failed to get delegate ipsec interface name");
150*0f4c859eSApple OSS Distributions	char delegateIfname[IFNAMSIZ];
151*0f4c859eSApple OSS Distributions	CFStringGetCString(delegateIPsecIfName, delegateIfname, IFNAMSIZ, kCFStringEncodingUTF8);
152*0f4c859eSApple OSS Distributions
153*0f4c859eSApple OSS Distributions	struct sadb_x_ipsecif *ipsec_if_payload = (struct sadb_x_ipsecif *)(void *)(payload + tlen);
154*0f4c859eSApple OSS Distributions	ipsec_if_payload->sadb_x_ipsecif_len = PFKEY_UNIT64(sizeof(*ipsec_if_payload));
155*0f4c859eSApple OSS Distributions	ipsec_if_payload->sadb_x_ipsecif_exttype = SADB_X_EXT_IPSECIF;
156*0f4c859eSApple OSS Distributions	strncpy(ipsec_if_payload->sadb_x_ipsecif_ipsec_if, ifname, strlen(ifname));
157*0f4c859eSApple OSS Distributions	strncpy(ipsec_if_payload->sadb_x_ipsecif_outgoing_if, delegateIfname, strlen(delegateIfname));
158*0f4c859eSApple OSS Distributions	tlen += sizeof(*ipsec_if_payload);
159*0f4c859eSApple OSS Distributions
160*0f4c859eSApple OSS Distributions	struct sadb_key *encrypt_key_payload = (struct sadb_key *)(void *)(payload + tlen);
161*0f4c859eSApple OSS Distributions	uint16_t len = sizeof(*encrypt_key_payload) + PFKEY_ALIGN8(32);
162*0f4c859eSApple OSS Distributions	encrypt_key_payload->sadb_key_len = PFKEY_UNIT64(len);
163*0f4c859eSApple OSS Distributions	encrypt_key_payload->sadb_key_exttype = SADB_EXT_KEY_ENCRYPT;
164*0f4c859eSApple OSS Distributions	encrypt_key_payload->sadb_key_bits = (uint16_t)(32 << 3);
165*0f4c859eSApple OSS Distributions	encrypt_key_payload->sadb_key_reserved = 0;
166*0f4c859eSApple OSS Distributions	tlen += sizeof(*encrypt_key_payload);
167*0f4c859eSApple OSS Distributions	arc4random_buf(payload + tlen, 32);
168*0f4c859eSApple OSS Distributions	tlen += PFKEY_ALIGN8(32);
169*0f4c859eSApple OSS Distributions
170*0f4c859eSApple OSS Distributions	struct sadb_key *auth_key_payload = (struct sadb_key *)(void *)(payload + tlen);
171*0f4c859eSApple OSS Distributions	len = sizeof(*auth_key_payload) + PFKEY_ALIGN8(32);
172*0f4c859eSApple OSS Distributions	auth_key_payload->sadb_key_len = PFKEY_UNIT64(len);
173*0f4c859eSApple OSS Distributions	auth_key_payload->sadb_key_exttype = SADB_EXT_KEY_AUTH;
174*0f4c859eSApple OSS Distributions	auth_key_payload->sadb_key_bits = (uint16_t)(32 << 3);
175*0f4c859eSApple OSS Distributions	auth_key_payload->sadb_key_reserved = 0;
176*0f4c859eSApple OSS Distributions	tlen += sizeof(*auth_key_payload);
177*0f4c859eSApple OSS Distributions	arc4random_buf(payload + tlen, 32);
178*0f4c859eSApple OSS Distributions	tlen += PFKEY_ALIGN8(32);
179*0f4c859eSApple OSS Distributions
180*0f4c859eSApple OSS Distributions	struct sadb_lifetime *hard_lifetime_payload = (struct sadb_lifetime *)(void *)(payload + tlen);
181*0f4c859eSApple OSS Distributions	hard_lifetime_payload->sadb_lifetime_len = PFKEY_UNIT64(sizeof(*hard_lifetime_payload));
182*0f4c859eSApple OSS Distributions	hard_lifetime_payload->sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD;
183*0f4c859eSApple OSS Distributions	tlen += sizeof(*hard_lifetime_payload);
184*0f4c859eSApple OSS Distributions
185*0f4c859eSApple OSS Distributions	struct sadb_lifetime *soft_lifetime_payload = (struct sadb_lifetime *)(void *)(payload + tlen);
186*0f4c859eSApple OSS Distributions	soft_lifetime_payload->sadb_lifetime_len = PFKEY_UNIT64(sizeof(*soft_lifetime_payload));
187*0f4c859eSApple OSS Distributions	soft_lifetime_payload->sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT;
188*0f4c859eSApple OSS Distributions	tlen += sizeof(*soft_lifetime_payload);
189*0f4c859eSApple OSS Distributions
190*0f4c859eSApple OSS Distributions	// Update the total length
191*0f4c859eSApple OSS Distributions	msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen);
192*0f4c859eSApple OSS Distributions	T_QUIET; T_ASSERT_POSIX_SUCCESS(send(pfkey_socket, payload, (size_t)PFKEY_UNUNIT64(msg_payload->sadb_msg_len), 0), "pfkey send update sa");
193*0f4c859eSApple OSS Distributions}
194*0f4c859eSApple OSS Distributions
195*0f4c859eSApple OSS Distributionsstatic void
196*0f4c859eSApple OSS Distributionssend_pfkey_flush_sa(int pfkey_socket)
197*0f4c859eSApple OSS Distributions{
198*0f4c859eSApple OSS Distributions	uint8_t payload[MCLBYTES] __attribute__ ((aligned(32)));
199*0f4c859eSApple OSS Distributions	bzero(payload, sizeof(payload));
200*0f4c859eSApple OSS Distributions	uint16_t tlen = 0;
201*0f4c859eSApple OSS Distributions
202*0f4c859eSApple OSS Distributions	struct sadb_msg *msg_payload = (struct sadb_msg *)payload;
203*0f4c859eSApple OSS Distributions	msg_payload->sadb_msg_version = PF_KEY_V2;
204*0f4c859eSApple OSS Distributions	msg_payload->sadb_msg_type = SADB_FLUSH;
205*0f4c859eSApple OSS Distributions	msg_payload->sadb_msg_errno = 0;
206*0f4c859eSApple OSS Distributions	msg_payload->sadb_msg_satype = SADB_SATYPE_UNSPEC;
207*0f4c859eSApple OSS Distributions	msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen);
208*0f4c859eSApple OSS Distributions	msg_payload->sadb_msg_reserved = 0;
209*0f4c859eSApple OSS Distributions	msg_payload->sadb_msg_seq = 0;
210*0f4c859eSApple OSS Distributions	msg_payload->sadb_msg_pid = (u_int32_t)getpid();
211*0f4c859eSApple OSS Distributions	tlen += sizeof(*msg_payload);
212*0f4c859eSApple OSS Distributions
213*0f4c859eSApple OSS Distributions	// Update the total length
214*0f4c859eSApple OSS Distributions	msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen);
215*0f4c859eSApple OSS Distributions	T_QUIET; T_ASSERT_POSIX_SUCCESS(send(pfkey_socket, payload, (size_t)PFKEY_UNUNIT64(msg_payload->sadb_msg_len), 0), "pfkey flush sa");
216*0f4c859eSApple OSS Distributions}
217*0f4c859eSApple OSS Distributions
218*0f4c859eSApple OSS Distributionsstatic void
219*0f4c859eSApple OSS Distributionspfkey_cleanup(void)
220*0f4c859eSApple OSS Distributions{
221*0f4c859eSApple OSS Distributions	if (pfkey_source != NULL) {
222*0f4c859eSApple OSS Distributions		int pfkey_socket = (int)dispatch_source_get_handle(pfkey_source);
223*0f4c859eSApple OSS Distributions		if (pfkey_socket > 0) {
224*0f4c859eSApple OSS Distributions			send_pfkey_flush_sa(pfkey_socket);
225*0f4c859eSApple OSS Distributions		}
226*0f4c859eSApple OSS Distributions		dispatch_source_cancel(pfkey_source);
227*0f4c859eSApple OSS Distributions		pfkey_source = NULL;
228*0f4c859eSApple OSS Distributions	}
229*0f4c859eSApple OSS Distributions}
230*0f4c859eSApple OSS Distributions
231*0f4c859eSApple OSS Distributionsstatic void
232*0f4c859eSApple OSS Distributionspfkey_align(struct sadb_msg *msg, uint8_t **mhp)
233*0f4c859eSApple OSS Distributions{
234*0f4c859eSApple OSS Distributions	struct sadb_ext *ext;
235*0f4c859eSApple OSS Distributions	int i;
236*0f4c859eSApple OSS Distributions	uint8_t *p;
237*0f4c859eSApple OSS Distributions	uint8_t *ep;     /* XXX should be passed from upper layer */
238*0f4c859eSApple OSS Distributions
239*0f4c859eSApple OSS Distributions	/* validity check */
240*0f4c859eSApple OSS Distributions	T_QUIET; T_ASSERT_NOTNULL(msg, "pfkey align msg");
241*0f4c859eSApple OSS Distributions	T_QUIET; T_ASSERT_NOTNULL(mhp, "pfkey align mhp");
242*0f4c859eSApple OSS Distributions
243*0f4c859eSApple OSS Distributions	/* initialize */
244*0f4c859eSApple OSS Distributions	for (i = 0; i < SADB_EXT_MAX + 1; i++) {
245*0f4c859eSApple OSS Distributions		mhp[i] = NULL;
246*0f4c859eSApple OSS Distributions	}
247*0f4c859eSApple OSS Distributions
248*0f4c859eSApple OSS Distributions	mhp[0] = (void *)msg;
249*0f4c859eSApple OSS Distributions
250*0f4c859eSApple OSS Distributions	/* initialize */
251*0f4c859eSApple OSS Distributions	p = (void *) msg;
252*0f4c859eSApple OSS Distributions	ep = p + PFKEY_UNUNIT64(msg->sadb_msg_len);
253*0f4c859eSApple OSS Distributions
254*0f4c859eSApple OSS Distributions	/* skip base header */
255*0f4c859eSApple OSS Distributions	p += sizeof(struct sadb_msg);
256*0f4c859eSApple OSS Distributions
257*0f4c859eSApple OSS Distributions	while (p < ep) {
258*0f4c859eSApple OSS Distributions		ext = (void *)p;
259*0f4c859eSApple OSS Distributions		T_QUIET; T_ASSERT_GE_PTR((void *)ep, (void *)(p + sizeof(*ext)), "pfkey extension header beyond end of buffer");
260*0f4c859eSApple OSS Distributions		T_QUIET; T_ASSERT_GE_ULONG((unsigned long)PFKEY_EXTLEN(ext), sizeof(*ext), "pfkey extension shorter than extension header");
261*0f4c859eSApple OSS Distributions		T_QUIET; T_ASSERT_GE_PTR((void *)ep, (void *)(p + PFKEY_EXTLEN(ext)), "pfkey extension length beyond end of buffer");
262*0f4c859eSApple OSS Distributions
263*0f4c859eSApple OSS Distributions		T_QUIET; T_EXPECT_NULL(mhp[ext->sadb_ext_type], "duplicate extension type %u payload", ext->sadb_ext_type);
264*0f4c859eSApple OSS Distributions
265*0f4c859eSApple OSS Distributions		/* set pointer */
266*0f4c859eSApple OSS Distributions		switch (ext->sadb_ext_type) {
267*0f4c859eSApple OSS Distributions		case SADB_EXT_SA:
268*0f4c859eSApple OSS Distributions		case SADB_EXT_LIFETIME_CURRENT:
269*0f4c859eSApple OSS Distributions		case SADB_EXT_LIFETIME_HARD:
270*0f4c859eSApple OSS Distributions		case SADB_EXT_LIFETIME_SOFT:
271*0f4c859eSApple OSS Distributions		case SADB_EXT_ADDRESS_SRC:
272*0f4c859eSApple OSS Distributions		case SADB_EXT_ADDRESS_DST:
273*0f4c859eSApple OSS Distributions		case SADB_EXT_ADDRESS_PROXY:
274*0f4c859eSApple OSS Distributions		case SADB_EXT_KEY_AUTH:
275*0f4c859eSApple OSS Distributions		/* XXX should to be check weak keys. */
276*0f4c859eSApple OSS Distributions		case SADB_EXT_KEY_ENCRYPT:
277*0f4c859eSApple OSS Distributions		/* XXX should to be check weak keys. */
278*0f4c859eSApple OSS Distributions		case SADB_EXT_IDENTITY_SRC:
279*0f4c859eSApple OSS Distributions		case SADB_EXT_IDENTITY_DST:
280*0f4c859eSApple OSS Distributions		case SADB_EXT_SENSITIVITY:
281*0f4c859eSApple OSS Distributions		case SADB_EXT_PROPOSAL:
282*0f4c859eSApple OSS Distributions		case SADB_EXT_SUPPORTED_AUTH:
283*0f4c859eSApple OSS Distributions		case SADB_EXT_SUPPORTED_ENCRYPT:
284*0f4c859eSApple OSS Distributions		case SADB_EXT_SPIRANGE:
285*0f4c859eSApple OSS Distributions		case SADB_X_EXT_POLICY:
286*0f4c859eSApple OSS Distributions		case SADB_X_EXT_SA2:
287*0f4c859eSApple OSS Distributions		case SADB_EXT_SESSION_ID:
288*0f4c859eSApple OSS Distributions		case SADB_EXT_SASTAT:
289*0f4c859eSApple OSS Distributions#ifdef SADB_X_EXT_NAT_T_TYPE
290*0f4c859eSApple OSS Distributions		case SADB_X_EXT_NAT_T_TYPE:
291*0f4c859eSApple OSS Distributions		case SADB_X_EXT_NAT_T_SPORT:
292*0f4c859eSApple OSS Distributions		case SADB_X_EXT_NAT_T_DPORT:
293*0f4c859eSApple OSS Distributions		case SADB_X_EXT_NAT_T_OA:
294*0f4c859eSApple OSS Distributions#endif
295*0f4c859eSApple OSS Distributions#ifdef SADB_X_EXT_TAG
296*0f4c859eSApple OSS Distributions		case SADB_X_EXT_TAG:
297*0f4c859eSApple OSS Distributions#endif
298*0f4c859eSApple OSS Distributions#ifdef SADB_X_EXT_PACKET
299*0f4c859eSApple OSS Distributions		case SADB_X_EXT_PACKET:
300*0f4c859eSApple OSS Distributions#endif
301*0f4c859eSApple OSS Distributions		case SADB_X_EXT_IPSECIF:
302*0f4c859eSApple OSS Distributions		case SADB_X_EXT_ADDR_RANGE_SRC_START:
303*0f4c859eSApple OSS Distributions		case SADB_X_EXT_ADDR_RANGE_SRC_END:
304*0f4c859eSApple OSS Distributions		case SADB_X_EXT_ADDR_RANGE_DST_START:
305*0f4c859eSApple OSS Distributions		case SADB_X_EXT_ADDR_RANGE_DST_END:
306*0f4c859eSApple OSS Distributions#ifdef SADB_MIGRATE
307*0f4c859eSApple OSS Distributions		case SADB_EXT_MIGRATE_ADDRESS_SRC:
308*0f4c859eSApple OSS Distributions		case SADB_EXT_MIGRATE_ADDRESS_DST:
309*0f4c859eSApple OSS Distributions		case SADB_X_EXT_MIGRATE_IPSECIF:
310*0f4c859eSApple OSS Distributions#endif
311*0f4c859eSApple OSS Distributions			mhp[ext->sadb_ext_type] = (void *)ext;
312*0f4c859eSApple OSS Distributions			break;
313*0f4c859eSApple OSS Distributions		default:
314*0f4c859eSApple OSS Distributions			T_FAIL("bad extension type %u", ext->sadb_ext_type);
315*0f4c859eSApple OSS Distributions			T_END;
316*0f4c859eSApple OSS Distributions		}
317*0f4c859eSApple OSS Distributions
318*0f4c859eSApple OSS Distributions		p += PFKEY_EXTLEN(ext);
319*0f4c859eSApple OSS Distributions	}
320*0f4c859eSApple OSS Distributions
321*0f4c859eSApple OSS Distributions	T_QUIET; T_EXPECT_EQ_PTR((void *)ep, (void *)p, "invalid pfkey message length");
322*0f4c859eSApple OSS Distributions	return;
323*0f4c859eSApple OSS Distributions}
324*0f4c859eSApple OSS Distributions
325*0f4c859eSApple OSS Distributionsstatic void
326*0f4c859eSApple OSS Distributionspfkey_process_message_test_encapsulate_panic(uint8_t **mhp, __unused int pfkey_socket)
327*0f4c859eSApple OSS Distributions{
328*0f4c859eSApple OSS Distributions	struct sadb_msg *message = (struct sadb_msg *)(void *)mhp[0];
329*0f4c859eSApple OSS Distributions	static uint32_t spi = 0;
330*0f4c859eSApple OSS Distributions	static uint8_t added_sa_counter = 0;
331*0f4c859eSApple OSS Distributions
332*0f4c859eSApple OSS Distributions	if (message->sadb_msg_pid != (uint32_t)getpid()) {
333*0f4c859eSApple OSS Distributions		return;
334*0f4c859eSApple OSS Distributions	}
335*0f4c859eSApple OSS Distributions
336*0f4c859eSApple OSS Distributions	if (message->sadb_msg_errno != 0) {
337*0f4c859eSApple OSS Distributions		T_FAIL("SADB add SA received error %d", message->sadb_msg_errno);
338*0f4c859eSApple OSS Distributions		T_END;
339*0f4c859eSApple OSS Distributions	}
340*0f4c859eSApple OSS Distributions
341*0f4c859eSApple OSS Distributions	switch (message->sadb_msg_type) {
342*0f4c859eSApple OSS Distributions	case SADB_ADD:
343*0f4c859eSApple OSS Distributions	{
344*0f4c859eSApple OSS Distributions		struct sadb_sa *sa_message = (struct sadb_sa *)(void *)mhp[SADB_EXT_SA];
345*0f4c859eSApple OSS Distributions		T_QUIET; T_ASSERT_NOTNULL(sa_message, "add sa message is NULL");
346*0f4c859eSApple OSS Distributions		spi = ntohl(sa_message->sadb_sa_spi);
347*0f4c859eSApple OSS Distributions		T_LOG("added sa 0x%x", spi);
348*0f4c859eSApple OSS Distributions		added_sa_counter++;
349*0f4c859eSApple OSS Distributions		if (added_sa_counter == 2) {
350*0f4c859eSApple OSS Distributions			bpf_write(bpf_fd);
351*0f4c859eSApple OSS Distributions		}
352*0f4c859eSApple OSS Distributions		break;
353*0f4c859eSApple OSS Distributions	}
354*0f4c859eSApple OSS Distributions	case SADB_FLUSH:
355*0f4c859eSApple OSS Distributions	case SADB_X_SPDFLUSH:
356*0f4c859eSApple OSS Distributions		break;
357*0f4c859eSApple OSS Distributions	default:
358*0f4c859eSApple OSS Distributions		T_FAIL("bad SADB message type %u", message->sadb_msg_type);
359*0f4c859eSApple OSS Distributions		T_END;
360*0f4c859eSApple OSS Distributions	}
361*0f4c859eSApple OSS Distributions	return;
362*0f4c859eSApple OSS Distributions}
363*0f4c859eSApple OSS Distributions
364*0f4c859eSApple OSS Distributionsstatic void
365*0f4c859eSApple OSS Distributionsrecv_pfkey_message(int pfkey_socket)
366*0f4c859eSApple OSS Distributions{
367*0f4c859eSApple OSS Distributions	uint8_t buffer[8192] __attribute__((aligned(4)));
368*0f4c859eSApple OSS Distributions	struct iovec iovecs[1] = {
369*0f4c859eSApple OSS Distributions		{ buffer, sizeof(buffer) },
370*0f4c859eSApple OSS Distributions	};
371*0f4c859eSApple OSS Distributions	struct msghdr msg = {
372*0f4c859eSApple OSS Distributions		NULL,
373*0f4c859eSApple OSS Distributions		0,
374*0f4c859eSApple OSS Distributions		iovecs,
375*0f4c859eSApple OSS Distributions		sizeof(iovecs) / sizeof(iovecs[0]),
376*0f4c859eSApple OSS Distributions		NULL,
377*0f4c859eSApple OSS Distributions		0,
378*0f4c859eSApple OSS Distributions		0,
379*0f4c859eSApple OSS Distributions	};
380*0f4c859eSApple OSS Distributions
381*0f4c859eSApple OSS Distributions	do {
382*0f4c859eSApple OSS Distributions		ssize_t result = -1;
383*0f4c859eSApple OSS Distributions		memset(buffer, 0, sizeof(buffer));
384*0f4c859eSApple OSS Distributions		T_QUIET; T_ASSERT_POSIX_SUCCESS(result = recvmsg(pfkey_socket, &msg, 0), NULL);
385*0f4c859eSApple OSS Distributions
386*0f4c859eSApple OSS Distributions		if (result > 0) {
387*0f4c859eSApple OSS Distributions			T_QUIET; T_ASSERT_GE_ULONG((size_t)result, sizeof(struct sadb_msg), "Invalid PFKey message size: %zu", result);
388*0f4c859eSApple OSS Distributions			struct sadb_msg *hdr = (struct sadb_msg *)buffer;
389*0f4c859eSApple OSS Distributions			uint8_t *mhp[SADB_EXT_MAX + 1];
390*0f4c859eSApple OSS Distributions			pfkey_align(hdr, mhp);
391*0f4c859eSApple OSS Distributions			(*process_pfkey_message_tests[test_id])(mhp, pfkey_socket);
392*0f4c859eSApple OSS Distributions		} else if (result == 0) {
393*0f4c859eSApple OSS Distributions			T_LOG("PFKey socket received EOF");
394*0f4c859eSApple OSS Distributions			break;
395*0f4c859eSApple OSS Distributions		}
396*0f4c859eSApple OSS Distributions	} while (1);
397*0f4c859eSApple OSS Distributions}
398*0f4c859eSApple OSS Distributions
399*0f4c859eSApple OSS Distributionsstatic int
400*0f4c859eSApple OSS Distributionspfkey_setup_socket(void)
401*0f4c859eSApple OSS Distributions{
402*0f4c859eSApple OSS Distributions	int pfkey_socket = -1;
403*0f4c859eSApple OSS Distributions
404*0f4c859eSApple OSS Distributions	T_QUIET; T_ASSERT_POSIX_SUCCESS(pfkey_socket = socket(PF_KEY, SOCK_RAW, PF_KEY_V2), NULL);
405*0f4c859eSApple OSS Distributions
406*0f4c859eSApple OSS Distributions	struct mbstat mbstat;
407*0f4c859eSApple OSS Distributions	size_t len_mbstat = sizeof(struct mbstat);
408*0f4c859eSApple OSS Distributions
409*0f4c859eSApple OSS Distributions	T_QUIET; T_ASSERT_POSIX_SUCCESS(sysctlbyname("kern.ipc.mbstat", &mbstat, &len_mbstat, NULL, 0), "kern.ipc.mbstat");
410*0f4c859eSApple OSS Distributions
411*0f4c859eSApple OSS Distributions	int bufsiz = 0;
412*0f4c859eSApple OSS Distributions	const unsigned long newbufk = 1536;
413*0f4c859eSApple OSS Distributions	unsigned long oldmax;
414*0f4c859eSApple OSS Distributions	size_t  oldmaxsize = sizeof(oldmax);
415*0f4c859eSApple OSS Distributions	unsigned long newmax = newbufk * (1024 + mbstat.m_msize / 2);
416*0f4c859eSApple OSS Distributions
417*0f4c859eSApple OSS Distributions	if (sysctlbyname("kern.ipc.maxsockbuf", &oldmax, &oldmaxsize, &newmax, sizeof(newmax)) != 0) {
418*0f4c859eSApple OSS Distributions		bufsiz = 233016;        /* Max allowed by default */
419*0f4c859eSApple OSS Distributions	} else {
420*0f4c859eSApple OSS Distributions		bufsiz = newbufk * 1024;
421*0f4c859eSApple OSS Distributions	}
422*0f4c859eSApple OSS Distributions
423*0f4c859eSApple OSS Distributions	T_QUIET; T_ASSERT_POSIX_SUCCESS(setsockopt(pfkey_socket, SOL_SOCKET, SO_SNDBUF, &bufsiz, sizeof(bufsiz)), "pfkey set snd socket buf failed %d", bufsiz);
424*0f4c859eSApple OSS Distributions	T_QUIET; T_ASSERT_POSIX_SUCCESS(setsockopt(pfkey_socket, SOL_SOCKET, SO_RCVBUF, &bufsiz, sizeof(bufsiz)), "pfkey set recv socket buf failed %d", bufsiz);
425*0f4c859eSApple OSS Distributions
426*0f4c859eSApple OSS Distributions	pfkey_source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, (uintptr_t)pfkey_socket, 0, dispatch_get_main_queue());
427*0f4c859eSApple OSS Distributions	T_QUIET; T_ASSERT_NOTNULL(pfkey_source, "dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, ...)");
428*0f4c859eSApple OSS Distributions	dispatch_source_set_event_handler(pfkey_source, ^{
429*0f4c859eSApple OSS Distributions		recv_pfkey_message(pfkey_socket);
430*0f4c859eSApple OSS Distributions	});
431*0f4c859eSApple OSS Distributions	dispatch_source_set_cancel_handler(pfkey_source, ^{
432*0f4c859eSApple OSS Distributions		close(pfkey_socket);
433*0f4c859eSApple OSS Distributions	});
434*0f4c859eSApple OSS Distributions	dispatch_resume(pfkey_source);
435*0f4c859eSApple OSS Distributions	return pfkey_socket;
436*0f4c859eSApple OSS Distributions}
437*0f4c859eSApple OSS Distributions
438*0f4c859eSApple OSS Distributionsstatic int
439*0f4c859eSApple OSS Distributionsbpf_new(void)
440*0f4c859eSApple OSS Distributions{
441*0f4c859eSApple OSS Distributions	char bpfdev[256];
442*0f4c859eSApple OSS Distributions	int i;
443*0f4c859eSApple OSS Distributions	int fd = -1;
444*0f4c859eSApple OSS Distributions
445*0f4c859eSApple OSS Distributions	for (i = 0; true; i++) {
446*0f4c859eSApple OSS Distributions		snprintf(bpfdev, sizeof(bpfdev), "/dev/bpf%d", i);
447*0f4c859eSApple OSS Distributions		fd = open(bpfdev, O_RDWR, 0);
448*0f4c859eSApple OSS Distributions		if (fd >= 0) {
449*0f4c859eSApple OSS Distributions			break;
450*0f4c859eSApple OSS Distributions		}
451*0f4c859eSApple OSS Distributions		if (errno != EBUSY) {
452*0f4c859eSApple OSS Distributions			break;
453*0f4c859eSApple OSS Distributions		}
454*0f4c859eSApple OSS Distributions	}
455*0f4c859eSApple OSS Distributions	return fd;
456*0f4c859eSApple OSS Distributions}
457*0f4c859eSApple OSS Distributions
458*0f4c859eSApple OSS Distributionsstatic int
459*0f4c859eSApple OSS Distributionsbpf_setif(int fd, const char *en_name)
460*0f4c859eSApple OSS Distributions{
461*0f4c859eSApple OSS Distributions	struct ifreq ifr;
462*0f4c859eSApple OSS Distributions
463*0f4c859eSApple OSS Distributions	strlcpy(ifr.ifr_name, en_name, sizeof(ifr.ifr_name));
464*0f4c859eSApple OSS Distributions	return ioctl(fd, BIOCSETIF, &ifr);
465*0f4c859eSApple OSS Distributions}
466*0f4c859eSApple OSS Distributions
467*0f4c859eSApple OSS Distributionsstatic int
468*0f4c859eSApple OSS Distributionsbpf_sethdr_complete(int fd)
469*0f4c859eSApple OSS Distributions{
470*0f4c859eSApple OSS Distributions	u_int8_t hdr_complete = 1;
471*0f4c859eSApple OSS Distributions	return ioctl(fd, BIOCSHDRCMPLT, &hdr_complete);
472*0f4c859eSApple OSS Distributions}
473*0f4c859eSApple OSS Distributions
474*0f4c859eSApple OSS Distributionsstatic void
475*0f4c859eSApple OSS Distributionsbpf_write(int fd)
476*0f4c859eSApple OSS Distributions{
477*0f4c859eSApple OSS Distributions	if (test_id == TEST_IPSEC_IPv4_ENCAPSULATE_PANIC) {
478*0f4c859eSApple OSS Distributions		char buffer[500];
479*0f4c859eSApple OSS Distributions		struct ip *ipheader = (void *)buffer;
480*0f4c859eSApple OSS Distributions		ipheader->ip_v = IPVERSION;
481*0f4c859eSApple OSS Distributions		ipheader->ip_hl = (sizeof(struct ip) - 4) >> 2;
482*0f4c859eSApple OSS Distributions		ipheader->ip_ttl = MAXTTL;
483*0f4c859eSApple OSS Distributions		ipheader->ip_p = IPPROTO_UDP;
484*0f4c859eSApple OSS Distributions		T_QUIET; T_ASSERT_POSIX_SUCCESS(write(fd, buffer, 500), "bpf write call failed");
485*0f4c859eSApple OSS Distributions		T_PASS("wrote bad ip header successfully");
486*0f4c859eSApple OSS Distributions		T_END;
487*0f4c859eSApple OSS Distributions	} else if (test_id == TEST_IPSEC_IPv6_ENCAPSULATE_PANIC) {
488*0f4c859eSApple OSS Distributions		struct ip6_hdr ip6 = {0};
489*0f4c859eSApple OSS Distributions		ip6.ip6_vfc |= IPV6_VERSION;
490*0f4c859eSApple OSS Distributions		T_QUIET; T_ASSERT_POSIX_SUCCESS(write(fd, &ip6, sizeof(ip6) - 4), "bpf write call failed");
491*0f4c859eSApple OSS Distributions		T_PASS("wrote bad ipv6 header successfully");
492*0f4c859eSApple OSS Distributions		T_END;
493*0f4c859eSApple OSS Distributions	}
494*0f4c859eSApple OSS Distributions}
495*0f4c859eSApple OSS Distributions
496*0f4c859eSApple OSS Distributionsstatic void
497*0f4c859eSApple OSS Distributionsbpf_socket_setup(void)
498*0f4c859eSApple OSS Distributions{
499*0f4c859eSApple OSS Distributions	int status = -1;
500*0f4c859eSApple OSS Distributions
501*0f4c859eSApple OSS Distributions	bpf_fd = bpf_new();
502*0f4c859eSApple OSS Distributions	T_QUIET; T_ASSERT_NE(bpf_fd, -1, "failed to create bpf file descriptor");
503*0f4c859eSApple OSS Distributions
504*0f4c859eSApple OSS Distributions	CFStringRef ipsecIfName = NEVirtualInterfaceCopyName(ipsecInterface);
505*0f4c859eSApple OSS Distributions	T_QUIET; T_ASSERT_NOTNULL(ipsecIfName, "failed to get ipsec interface name");
506*0f4c859eSApple OSS Distributions
507*0f4c859eSApple OSS Distributions	char ifname[IFNAMSIZ];
508*0f4c859eSApple OSS Distributions	CFStringGetCString(ipsecIfName, ifname, IFNAMSIZ, kCFStringEncodingUTF8);
509*0f4c859eSApple OSS Distributions
510*0f4c859eSApple OSS Distributions	status = bpf_setif(bpf_fd, ifname);
511*0f4c859eSApple OSS Distributions	T_QUIET; T_ASSERT_NE(status, -1, "failed to set bpf interface");
512*0f4c859eSApple OSS Distributions
513*0f4c859eSApple OSS Distributions	status = bpf_sethdr_complete(bpf_fd);
514*0f4c859eSApple OSS Distributions	T_QUIET; T_ASSERT_NE(status, -1, "failed to set bpf header complete");
515*0f4c859eSApple OSS Distributions}
516*0f4c859eSApple OSS Distributions
517*0f4c859eSApple OSS Distributionsstatic NEVirtualInterfaceRef
518*0f4c859eSApple OSS Distributionsipsec_interface_setup(CFStringRef interfaceAddress, CFStringRef interfaceMask)
519*0f4c859eSApple OSS Distributions{
520*0f4c859eSApple OSS Distributions	Boolean status = FALSE;
521*0f4c859eSApple OSS Distributions
522*0f4c859eSApple OSS Distributions	NEVirtualInterfaceRef interface = NEVirtualInterfaceCreate(NULL, kNEVirtualInterfaceValTypeIPSec, dispatch_get_main_queue(), NULL);
523*0f4c859eSApple OSS Distributions	T_QUIET; T_ASSERT_NOTNULL(interface, "ipsec interface creation failed");
524*0f4c859eSApple OSS Distributions	status = NEVirtualInterfaceSetMTU(interface, 1400);
525*0f4c859eSApple OSS Distributions	if (status == FALSE) {
526*0f4c859eSApple OSS Distributions		T_FAIL("Failed to set MTU on ipsec interface");
527*0f4c859eSApple OSS Distributions		T_END;
528*0f4c859eSApple OSS Distributions	}
529*0f4c859eSApple OSS Distributions
530*0f4c859eSApple OSS Distributions	status = NEVirtualInterfaceAddAddress(interface, interfaceAddress, interfaceMask);
531*0f4c859eSApple OSS Distributions	if (status == FALSE) {
532*0f4c859eSApple OSS Distributions		T_FAIL("Failed to set address on ipsec interface");
533*0f4c859eSApple OSS Distributions		T_END;
534*0f4c859eSApple OSS Distributions	}
535*0f4c859eSApple OSS Distributions
536*0f4c859eSApple OSS Distributions	CFStringRef ipsecIfName = NEVirtualInterfaceCopyName(interface);
537*0f4c859eSApple OSS Distributions	T_QUIET; T_ASSERT_NOTNULL(ipsecIfName, "failed to get ipsec interface name");
538*0f4c859eSApple OSS Distributions
539*0f4c859eSApple OSS Distributions	char ifname[IFNAMSIZ];
540*0f4c859eSApple OSS Distributions	CFStringGetCString(ipsecIfName, ifname, IFNAMSIZ, kCFStringEncodingUTF8);
541*0f4c859eSApple OSS Distributions
542*0f4c859eSApple OSS Distributions	T_LOG("%s interface setup", ifname);
543*0f4c859eSApple OSS Distributions	return interface;
544*0f4c859eSApple OSS Distributions}
545*0f4c859eSApple OSS Distributions
546*0f4c859eSApple OSS Distributionsstatic void
547*0f4c859eSApple OSS Distributionsipsec_interface_set_delegate(NEVirtualInterfaceRef interface, CFStringRef delegateInterfaceName)
548*0f4c859eSApple OSS Distributions{
549*0f4c859eSApple OSS Distributions	Boolean status = NEVirtualInterfaceSetDelegateInterface(interface, delegateInterfaceName);
550*0f4c859eSApple OSS Distributions	if (status == FALSE) {
551*0f4c859eSApple OSS Distributions		T_FAIL("Failed to set delegate on ipsec interface");
552*0f4c859eSApple OSS Distributions		T_END;
553*0f4c859eSApple OSS Distributions	}
554*0f4c859eSApple OSS Distributions
555*0f4c859eSApple OSS Distributions	return;
556*0f4c859eSApple OSS Distributions}
557*0f4c859eSApple OSS Distributions
558*0f4c859eSApple OSS Distributionsstatic void
559*0f4c859eSApple OSS Distributionsipsec_cleanup(void)
560*0f4c859eSApple OSS Distributions{
561*0f4c859eSApple OSS Distributions	pfkey_cleanup();
562*0f4c859eSApple OSS Distributions
563*0f4c859eSApple OSS Distributions	if (ipsecInterface != NULL) {
564*0f4c859eSApple OSS Distributions		NEVirtualInterfaceInvalidate(ipsecInterface);
565*0f4c859eSApple OSS Distributions		ipsecInterface = NULL;
566*0f4c859eSApple OSS Distributions	}
567*0f4c859eSApple OSS Distributions
568*0f4c859eSApple OSS Distributions	if (delegateIPsecInterface != NULL) {
569*0f4c859eSApple OSS Distributions		NEVirtualInterfaceInvalidate(delegateIPsecInterface);
570*0f4c859eSApple OSS Distributions		delegateIPsecInterface = NULL;
571*0f4c859eSApple OSS Distributions	}
572*0f4c859eSApple OSS Distributions
573*0f4c859eSApple OSS Distributions	if (bpf_fd != -1) {
574*0f4c859eSApple OSS Distributions		close(bpf_fd);
575*0f4c859eSApple OSS Distributions		bpf_fd = -1;
576*0f4c859eSApple OSS Distributions	}
577*0f4c859eSApple OSS Distributions}
578*0f4c859eSApple OSS Distributions
579*0f4c859eSApple OSS DistributionsT_DECL(ipsec_ipv4_encapsulate_panic_63139357, "ipsec: outer ip header length less than 20")
580*0f4c859eSApple OSS Distributions{
581*0f4c859eSApple OSS Distributions	test_id = TEST_IPSEC_IPv4_ENCAPSULATE_PANIC;
582*0f4c859eSApple OSS Distributions
583*0f4c859eSApple OSS Distributions	T_ATEND(ipsec_cleanup);
584*0f4c859eSApple OSS Distributions
585*0f4c859eSApple OSS Distributions	ipsecInterface = ipsec_interface_setup(CFSTR(TEST_IPSEC_IPv4_INTERFACE_ADDRESS), CFSTR(TEST_IPSEC_IPv4_INTERFACE_MASK));
586*0f4c859eSApple OSS Distributions	delegateIPsecInterface = ipsec_interface_setup(CFSTR(TEST_DELEGATE_IPSEC_INTERFACE_ADDRESS), CFSTR(TEST_IPSEC_IPv4_INTERFACE_MASK));
587*0f4c859eSApple OSS Distributions
588*0f4c859eSApple OSS Distributions	CFStringRef delegateIPsecIfName = NEVirtualInterfaceCopyName(delegateIPsecInterface);
589*0f4c859eSApple OSS Distributions	T_QUIET; T_ASSERT_NOTNULL(delegateIPsecIfName, "failed to get ipsec interface name");
590*0f4c859eSApple OSS Distributions	ipsec_interface_set_delegate(ipsecInterface, delegateIPsecIfName);
591*0f4c859eSApple OSS Distributions
592*0f4c859eSApple OSS Distributions	bpf_socket_setup();
593*0f4c859eSApple OSS Distributions
594*0f4c859eSApple OSS Distributions	int pfkey_socket = pfkey_setup_socket();
595*0f4c859eSApple OSS Distributions	send_pfkey_flush_sa(pfkey_socket);
596*0f4c859eSApple OSS Distributions
597*0f4c859eSApple OSS Distributions	send_pkey_add_sa(pfkey_socket, 0x12345678, TEST_SRC_ADDRESS_IPv4, TEST_DST_ADDRESS_IPv4, AF_INET);
598*0f4c859eSApple OSS Distributions	send_pkey_add_sa(pfkey_socket, 0x23456789, TEST_SRC_ADDRESS_IPv4, TEST_DST_ADDRESS_IPv4, AF_INET);
599*0f4c859eSApple OSS Distributions
600*0f4c859eSApple OSS Distributions	dispatch_main();
601*0f4c859eSApple OSS Distributions}
602*0f4c859eSApple OSS Distributions
603*0f4c859eSApple OSS DistributionsT_DECL(ipsec_ipv6_encapsulate_panic_63139357, "ipsec: payload less than IPv6 header")
604*0f4c859eSApple OSS Distributions{
605*0f4c859eSApple OSS Distributions	test_id = TEST_IPSEC_IPv6_ENCAPSULATE_PANIC;
606*0f4c859eSApple OSS Distributions
607*0f4c859eSApple OSS Distributions	T_ATEND(ipsec_cleanup);
608*0f4c859eSApple OSS Distributions
609*0f4c859eSApple OSS Distributions	ipsecInterface = ipsec_interface_setup(CFSTR(TEST_IPSEC_IPv6_INTERFACE_ADDRESS), CFSTR(TEST_IPSEC_IPv6_INTERFACE_MASK));
610*0f4c859eSApple OSS Distributions	delegateIPsecInterface = ipsec_interface_setup(CFSTR(TEST_DELEGATE_IPSEC_INTERFACE_ADDRESS), CFSTR(TEST_IPSEC_IPv4_INTERFACE_MASK));
611*0f4c859eSApple OSS Distributions
612*0f4c859eSApple OSS Distributions	CFStringRef delegateIPsecIfName = NEVirtualInterfaceCopyName(delegateIPsecInterface);
613*0f4c859eSApple OSS Distributions	T_QUIET; T_ASSERT_NOTNULL(delegateIPsecIfName, "failed to get ipsec interface name");
614*0f4c859eSApple OSS Distributions	ipsec_interface_set_delegate(ipsecInterface, delegateIPsecIfName);
615*0f4c859eSApple OSS Distributions
616*0f4c859eSApple OSS Distributions	bpf_socket_setup();
617*0f4c859eSApple OSS Distributions
618*0f4c859eSApple OSS Distributions	int pfkey_socket = pfkey_setup_socket();
619*0f4c859eSApple OSS Distributions	send_pfkey_flush_sa(pfkey_socket);
620*0f4c859eSApple OSS Distributions
621*0f4c859eSApple OSS Distributions	send_pkey_add_sa(pfkey_socket, 0x12345678, TEST_SRC_ADDRESS_IPv4, TEST_DST_ADDRESS_IPv4, AF_INET);
622*0f4c859eSApple OSS Distributions	send_pkey_add_sa(pfkey_socket, 0x23456789, TEST_SRC_ADDRESS_IPv4, TEST_DST_ADDRESS_IPv4, AF_INET);
623*0f4c859eSApple OSS Distributions
624*0f4c859eSApple OSS Distributions	dispatch_main();
625*0f4c859eSApple OSS Distributions}
626