xref: /xnu-11417.121.6/tests/sioc-if-addr-bounds.c (revision a1e26a70f38d1d7daa7b49b258e2f8538ad81650)
1*a1e26a70SApple OSS Distributions /*
2*a1e26a70SApple OSS Distributions  * Copyright (c) 2020-2022 Apple Inc. All rights reserved.
3*a1e26a70SApple OSS Distributions  *
4*a1e26a70SApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5*a1e26a70SApple OSS Distributions  *
6*a1e26a70SApple OSS Distributions  * This file contains Original Code and/or Modifications of Original Code
7*a1e26a70SApple OSS Distributions  * as defined in and that are subject to the Apple Public Source License
8*a1e26a70SApple OSS Distributions  * Version 2.0 (the 'License'). You may not use this file except in
9*a1e26a70SApple OSS Distributions  * compliance with the License. The rights granted to you under the License
10*a1e26a70SApple OSS Distributions  * may not be used to create, or enable the creation or redistribution of,
11*a1e26a70SApple OSS Distributions  * unlawful or unlicensed copies of an Apple operating system, or to
12*a1e26a70SApple OSS Distributions  * circumvent, violate, or enable the circumvention or violation of, any
13*a1e26a70SApple OSS Distributions  * terms of an Apple operating system software license agreement.
14*a1e26a70SApple OSS Distributions  *
15*a1e26a70SApple OSS Distributions  * Please obtain a copy of the License at
16*a1e26a70SApple OSS Distributions  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17*a1e26a70SApple OSS Distributions  *
18*a1e26a70SApple OSS Distributions  * The Original Code and all software distributed under the License are
19*a1e26a70SApple OSS Distributions  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20*a1e26a70SApple OSS Distributions  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21*a1e26a70SApple OSS Distributions  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22*a1e26a70SApple OSS Distributions  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23*a1e26a70SApple OSS Distributions  * Please see the License for the specific language governing rights and
24*a1e26a70SApple OSS Distributions  * limitations under the License.
25*a1e26a70SApple OSS Distributions  *
26*a1e26a70SApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27*a1e26a70SApple OSS Distributions  */
28*a1e26a70SApple OSS Distributions 
29*a1e26a70SApple OSS Distributions /* -*- compile-command: "xcrun --sdk iphoneos.internal make sioc-if-addr-bounds" -*- */
30*a1e26a70SApple OSS Distributions 
31*a1e26a70SApple OSS Distributions #include <sys/ioctl.h>
32*a1e26a70SApple OSS Distributions #include <sys/socket.h>
33*a1e26a70SApple OSS Distributions #include <sys/sockio.h>
34*a1e26a70SApple OSS Distributions 
35*a1e26a70SApple OSS Distributions #include <net/if.h>
36*a1e26a70SApple OSS Distributions #include <net/if_dl.h>
37*a1e26a70SApple OSS Distributions 
38*a1e26a70SApple OSS Distributions #include <netinet/in.h>
39*a1e26a70SApple OSS Distributions #include <netinet/in_var.h>
40*a1e26a70SApple OSS Distributions 
41*a1e26a70SApple OSS Distributions #include <string.h>
42*a1e26a70SApple OSS Distributions #include <unistd.h>
43*a1e26a70SApple OSS Distributions 
44*a1e26a70SApple OSS Distributions #include <arpa/inet.h>
45*a1e26a70SApple OSS Distributions 
46*a1e26a70SApple OSS Distributions #include <darwintest.h>
47*a1e26a70SApple OSS Distributions #include <darwintest_utils.h>
48*a1e26a70SApple OSS Distributions 
49*a1e26a70SApple OSS Distributions #include <uuid/uuid.h>
50*a1e26a70SApple OSS Distributions 
51*a1e26a70SApple OSS Distributions #include <ifaddrs.h>
52*a1e26a70SApple OSS Distributions 
53*a1e26a70SApple OSS Distributions #include <arpa/inet.h>
54*a1e26a70SApple OSS Distributions 
55*a1e26a70SApple OSS Distributions #include "ioc_str.h"
56*a1e26a70SApple OSS Distributions 
57*a1e26a70SApple OSS Distributions T_GLOBAL_META(T_META_NAMESPACE("xnu.net"));
58*a1e26a70SApple OSS Distributions 
59*a1e26a70SApple OSS Distributions #ifndef STRINGIFY
60*a1e26a70SApple OSS Distributions #define __STR(x)        #x              /* just a helper macro */
61*a1e26a70SApple OSS Distributions #define STRINGIFY(x)    __STR(x)
62*a1e26a70SApple OSS Distributions #endif /* STRINGIFY */
63*a1e26a70SApple OSS Distributions 
64*a1e26a70SApple OSS Distributions #define IF_NAME       "bridge"
65*a1e26a70SApple OSS Distributions 
66*a1e26a70SApple OSS Distributions /* On some platforms with DEBUG kernel, we need to wait a while */
67*a1e26a70SApple OSS Distributions #define SIFCREATE_RETRY 600
68*a1e26a70SApple OSS Distributions 
69*a1e26a70SApple OSS Distributions #define PATTERN_SIZE 8
70*a1e26a70SApple OSS Distributions 
71*a1e26a70SApple OSS Distributions static int
ifnet_destroy(int s,const char * ifname,bool fail_on_error)72*a1e26a70SApple OSS Distributions ifnet_destroy(int s, const char * ifname, bool fail_on_error)
73*a1e26a70SApple OSS Distributions {
74*a1e26a70SApple OSS Distributions 	int             err;
75*a1e26a70SApple OSS Distributions 	struct ifreq    ifr;
76*a1e26a70SApple OSS Distributions 
77*a1e26a70SApple OSS Distributions 	bzero(&ifr, sizeof(ifr));
78*a1e26a70SApple OSS Distributions 	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
79*a1e26a70SApple OSS Distributions 	err = ioctl(s, SIOCIFDESTROY, &ifr);
80*a1e26a70SApple OSS Distributions 	if (fail_on_error) {
81*a1e26a70SApple OSS Distributions 		T_QUIET;
82*a1e26a70SApple OSS Distributions 		T_ASSERT_POSIX_SUCCESS(err, "SIOCSIFDESTROY %s", ifr.ifr_name);
83*a1e26a70SApple OSS Distributions 	}
84*a1e26a70SApple OSS Distributions 	if (err < 0) {
85*a1e26a70SApple OSS Distributions 		T_LOG("SIOCSIFDESTROY %s", ifr.ifr_name);
86*a1e26a70SApple OSS Distributions 	}
87*a1e26a70SApple OSS Distributions 	return err;
88*a1e26a70SApple OSS Distributions }
89*a1e26a70SApple OSS Distributions 
90*a1e26a70SApple OSS Distributions static int
ifnet_set_flags(int s,const char * ifname,uint16_t flags_set,uint16_t flags_clear)91*a1e26a70SApple OSS Distributions ifnet_set_flags(int s, const char * ifname,
92*a1e26a70SApple OSS Distributions     uint16_t flags_set, uint16_t flags_clear)
93*a1e26a70SApple OSS Distributions {
94*a1e26a70SApple OSS Distributions 	uint16_t        flags_after;
95*a1e26a70SApple OSS Distributions 	uint16_t        flags_before;
96*a1e26a70SApple OSS Distributions 	struct ifreq    ifr;
97*a1e26a70SApple OSS Distributions 	int             ret;
98*a1e26a70SApple OSS Distributions 
99*a1e26a70SApple OSS Distributions 	bzero(&ifr, sizeof(ifr));
100*a1e26a70SApple OSS Distributions 	strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
101*a1e26a70SApple OSS Distributions 	ret = ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr);
102*a1e26a70SApple OSS Distributions 	if (ret != 0) {
103*a1e26a70SApple OSS Distributions 		T_LOG("SIOCGIFFLAGS %s", ifr.ifr_name);
104*a1e26a70SApple OSS Distributions 		return ret;
105*a1e26a70SApple OSS Distributions 	}
106*a1e26a70SApple OSS Distributions 	flags_before = (uint16_t)ifr.ifr_flags;
107*a1e26a70SApple OSS Distributions 	ifr.ifr_flags |= flags_set;
108*a1e26a70SApple OSS Distributions 	ifr.ifr_flags &= ~(flags_clear);
109*a1e26a70SApple OSS Distributions 	flags_after = (uint16_t)ifr.ifr_flags;
110*a1e26a70SApple OSS Distributions 	if (flags_before == flags_after) {
111*a1e26a70SApple OSS Distributions 		/* nothing to do */
112*a1e26a70SApple OSS Distributions 		ret = 0;
113*a1e26a70SApple OSS Distributions 	} else {
114*a1e26a70SApple OSS Distributions 		/* issue the ioctl */
115*a1e26a70SApple OSS Distributions 		T_QUIET;
116*a1e26a70SApple OSS Distributions 		T_ASSERT_POSIX_SUCCESS(ioctl(s, SIOCSIFFLAGS, &ifr),
117*a1e26a70SApple OSS Distributions 		    "SIOCSIFFLAGS %s 0x%x",
118*a1e26a70SApple OSS Distributions 		    ifr.ifr_name, (uint16_t)ifr.ifr_flags);
119*a1e26a70SApple OSS Distributions 	}
120*a1e26a70SApple OSS Distributions 	return ret;
121*a1e26a70SApple OSS Distributions }
122*a1e26a70SApple OSS Distributions 
123*a1e26a70SApple OSS Distributions static int
ifnet_create(int s,char * ifname,size_t ifname_size)124*a1e26a70SApple OSS Distributions ifnet_create(int s, char * ifname, size_t ifname_size)
125*a1e26a70SApple OSS Distributions {
126*a1e26a70SApple OSS Distributions 	int error = 0;
127*a1e26a70SApple OSS Distributions 	struct ifreq ifr;
128*a1e26a70SApple OSS Distributions 
129*a1e26a70SApple OSS Distributions 	bzero(&ifr, sizeof(ifr));
130*a1e26a70SApple OSS Distributions 	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
131*a1e26a70SApple OSS Distributions 
132*a1e26a70SApple OSS Distributions 	for (int i = 0; i < SIFCREATE_RETRY; i++) {
133*a1e26a70SApple OSS Distributions 		if (ioctl(s, SIOCIFCREATE, &ifr) < 0) {
134*a1e26a70SApple OSS Distributions 			error = errno;
135*a1e26a70SApple OSS Distributions 			T_LOG("SIOCSIFCREATE %s: %s", ifname,
136*a1e26a70SApple OSS Distributions 			    strerror(error));
137*a1e26a70SApple OSS Distributions 			if (error == EBUSY) {
138*a1e26a70SApple OSS Distributions 				/* interface is tearing down, try again */
139*a1e26a70SApple OSS Distributions 				usleep(10000);
140*a1e26a70SApple OSS Distributions 			} else if (error == EEXIST) {
141*a1e26a70SApple OSS Distributions 				/* interface exists, try destroying it */
142*a1e26a70SApple OSS Distributions 				(void)ifnet_destroy(s, ifname, false);
143*a1e26a70SApple OSS Distributions 			} else {
144*a1e26a70SApple OSS Distributions 				/* unexpected failure */
145*a1e26a70SApple OSS Distributions 				break;
146*a1e26a70SApple OSS Distributions 			}
147*a1e26a70SApple OSS Distributions 		} else {
148*a1e26a70SApple OSS Distributions 			error = 0;
149*a1e26a70SApple OSS Distributions 			break;
150*a1e26a70SApple OSS Distributions 		}
151*a1e26a70SApple OSS Distributions 	}
152*a1e26a70SApple OSS Distributions 	if (error == 0) {
153*a1e26a70SApple OSS Distributions 		/* Copy back the interface name with unit number */
154*a1e26a70SApple OSS Distributions 		strlcpy(ifname, ifr.ifr_name, ifname_size);
155*a1e26a70SApple OSS Distributions 		error = ifnet_set_flags(s, ifname, IFF_UP, 0);
156*a1e26a70SApple OSS Distributions 	}
157*a1e26a70SApple OSS Distributions 	return error;
158*a1e26a70SApple OSS Distributions }
159*a1e26a70SApple OSS Distributions 
160*a1e26a70SApple OSS Distributions #define MAXBUF 32
161*a1e26a70SApple OSS Distributions 
162*a1e26a70SApple OSS Distributions static void
HexDump(void * data,size_t len)163*a1e26a70SApple OSS Distributions HexDump(void *data, size_t len)
164*a1e26a70SApple OSS Distributions {
165*a1e26a70SApple OSS Distributions 	size_t i, j, k;
166*a1e26a70SApple OSS Distributions 	unsigned char *ptr = (unsigned char *)data;
167*a1e26a70SApple OSS Distributions 	unsigned char buf[3 * MAXBUF + 1];
168*a1e26a70SApple OSS Distributions 
169*a1e26a70SApple OSS Distributions 	for (i = 0; i < len; i += MAXBUF) {
170*a1e26a70SApple OSS Distributions 		for (j = i, k = 0; j < i + MAXBUF && j < len; j++) {
171*a1e26a70SApple OSS Distributions 			unsigned char msnbl = ptr[j] >> 4;
172*a1e26a70SApple OSS Distributions 			unsigned char lsnbl = ptr[j] & 0x0f;
173*a1e26a70SApple OSS Distributions 
174*a1e26a70SApple OSS Distributions 			buf[k++] = msnbl < 10 ? msnbl + '0' : msnbl + 'a' - 10;
175*a1e26a70SApple OSS Distributions 			buf[k++] = lsnbl < 10 ? lsnbl + '0' : lsnbl + 'a' - 10;
176*a1e26a70SApple OSS Distributions 			if ((j % 2) == 1) {
177*a1e26a70SApple OSS Distributions 				buf[k++] = ' ';
178*a1e26a70SApple OSS Distributions 			}
179*a1e26a70SApple OSS Distributions 			if ((j % MAXBUF) == MAXBUF - 1) {
180*a1e26a70SApple OSS Distributions 				buf[k++] = ' ';
181*a1e26a70SApple OSS Distributions 			}
182*a1e26a70SApple OSS Distributions 		}
183*a1e26a70SApple OSS Distributions 		buf[k] = 0;
184*a1e26a70SApple OSS Distributions 		T_LOG("%5zd: %s\n", i, buf);
185*a1e26a70SApple OSS Distributions 	}
186*a1e26a70SApple OSS Distributions }
187*a1e26a70SApple OSS Distributions 
188*a1e26a70SApple OSS Distributions static size_t
snprint_dottedhex(char * str,size_t strsize,const void * data,const size_t datasize)189*a1e26a70SApple OSS Distributions snprint_dottedhex(char *str, size_t strsize, const void *data, const size_t datasize)
190*a1e26a70SApple OSS Distributions {
191*a1e26a70SApple OSS Distributions 	size_t is = 0, ip = 0;
192*a1e26a70SApple OSS Distributions 	const unsigned char *ptr = (const unsigned char *)data;
193*a1e26a70SApple OSS Distributions 
194*a1e26a70SApple OSS Distributions 	for (is = 0, ip = 0; is + 3 < strsize - 1 && ip < datasize; ip++) {
195*a1e26a70SApple OSS Distributions 		unsigned char msnbl = ptr[ip] >> 4;
196*a1e26a70SApple OSS Distributions 		unsigned char lsnbl = ptr[ip] & 0x0f;
197*a1e26a70SApple OSS Distributions 
198*a1e26a70SApple OSS Distributions 		if (ip > 0) {
199*a1e26a70SApple OSS Distributions 			str[is++] = '.';
200*a1e26a70SApple OSS Distributions 		}
201*a1e26a70SApple OSS Distributions 		str[is++] = (char)(msnbl + (msnbl < 10 ? '0' : 'a' - 10));
202*a1e26a70SApple OSS Distributions 		str[is++] = (char)(lsnbl + (lsnbl < 10 ? '0' : 'a' - 10));
203*a1e26a70SApple OSS Distributions 	}
204*a1e26a70SApple OSS Distributions 	str[is] = 0;
205*a1e26a70SApple OSS Distributions 	return is;
206*a1e26a70SApple OSS Distributions }
207*a1e26a70SApple OSS Distributions 
208*a1e26a70SApple OSS Distributions static void
print_sockaddr_dl(const char * pre,const struct sockaddr * sa,const char * post)209*a1e26a70SApple OSS Distributions print_sockaddr_dl(const char *pre, const struct sockaddr *sa, const char *post)
210*a1e26a70SApple OSS Distributions {
211*a1e26a70SApple OSS Distributions 	char nbuffer[256];
212*a1e26a70SApple OSS Distributions 	char abuffer[256];
213*a1e26a70SApple OSS Distributions 	char sbuffer[256];
214*a1e26a70SApple OSS Distributions 	struct sockaddr_dl sdl = { 0 };
215*a1e26a70SApple OSS Distributions 
216*a1e26a70SApple OSS Distributions 	if (sa == NULL) {
217*a1e26a70SApple OSS Distributions 		return;
218*a1e26a70SApple OSS Distributions 	}
219*a1e26a70SApple OSS Distributions 	memcpy(&sdl, sa, MIN(sizeof(sdl), sa->sa_len));
220*a1e26a70SApple OSS Distributions 	strlcpy(nbuffer, sdl.sdl_data, sdl.sdl_nlen);
221*a1e26a70SApple OSS Distributions 	snprint_dottedhex(abuffer, sizeof(abuffer), sdl.sdl_data + sdl.sdl_nlen, sdl.sdl_alen);
222*a1e26a70SApple OSS Distributions 	snprint_dottedhex(sbuffer, sizeof(sbuffer), sdl.sdl_data + sdl.sdl_nlen + sdl.sdl_alen, sdl.sdl_slen);
223*a1e26a70SApple OSS Distributions 
224*a1e26a70SApple OSS Distributions 	T_LOG("%ssdl_len %u sdl_family %u sdl_index %u sdl_type %u sdl_nlen %u (%s) sdl_alen %u (%s) sdl_slen %u (%s)%s",
225*a1e26a70SApple OSS Distributions 	    pre != NULL ? pre : "",
226*a1e26a70SApple OSS Distributions 	    sdl.sdl_len, sdl.sdl_family, sdl.sdl_index, sdl.sdl_type,
227*a1e26a70SApple OSS Distributions 	    sdl.sdl_nlen, nbuffer, sdl.sdl_alen, abuffer, sdl.sdl_slen, sbuffer,
228*a1e26a70SApple OSS Distributions 	    post != NULL ? post : "");
229*a1e26a70SApple OSS Distributions }
230*a1e26a70SApple OSS Distributions 
231*a1e26a70SApple OSS Distributions static void
print_sockaddr_in(const char * pre,const struct sockaddr * sa,const char * post)232*a1e26a70SApple OSS Distributions print_sockaddr_in(const char *pre, const struct sockaddr *sa, const char *post)
233*a1e26a70SApple OSS Distributions {
234*a1e26a70SApple OSS Distributions 	char abuffer[256];
235*a1e26a70SApple OSS Distributions 	char zbuffer[256];
236*a1e26a70SApple OSS Distributions 	struct sockaddr_in sin = { 0 };
237*a1e26a70SApple OSS Distributions 
238*a1e26a70SApple OSS Distributions 	if (sa == NULL) {
239*a1e26a70SApple OSS Distributions 		return;
240*a1e26a70SApple OSS Distributions 	}
241*a1e26a70SApple OSS Distributions 
242*a1e26a70SApple OSS Distributions 	memcpy(&sin, sa, MIN(sizeof(sin), sa->sa_len));
243*a1e26a70SApple OSS Distributions 	inet_ntop(AF_INET, &sin.sin_addr, abuffer, sizeof(abuffer));
244*a1e26a70SApple OSS Distributions 	snprint_dottedhex(zbuffer, sizeof(zbuffer), sin.sin_zero, sizeof(sin.sin_zero));
245*a1e26a70SApple OSS Distributions 
246*a1e26a70SApple OSS Distributions 	T_LOG("%ssin_len %u sin_family %u sin_port %u sin_addr %s sin_zero %s%s",
247*a1e26a70SApple OSS Distributions 	    pre != NULL ? pre : "",
248*a1e26a70SApple OSS Distributions 	    sin.sin_len, sin.sin_family, htons(sin.sin_port), abuffer, zbuffer,
249*a1e26a70SApple OSS Distributions 	    post != NULL ? post : "");
250*a1e26a70SApple OSS Distributions }
251*a1e26a70SApple OSS Distributions 
252*a1e26a70SApple OSS Distributions static void
print_sockaddr_in6(const char * pre,const struct sockaddr * sa,const char * post)253*a1e26a70SApple OSS Distributions print_sockaddr_in6(const char *pre, const struct sockaddr *sa, const char *post)
254*a1e26a70SApple OSS Distributions {
255*a1e26a70SApple OSS Distributions 	char abuffer[256];
256*a1e26a70SApple OSS Distributions 	struct sockaddr_in6 sin6 = { 0 };
257*a1e26a70SApple OSS Distributions 
258*a1e26a70SApple OSS Distributions 	if (sa == NULL) {
259*a1e26a70SApple OSS Distributions 		return;
260*a1e26a70SApple OSS Distributions 	}
261*a1e26a70SApple OSS Distributions 
262*a1e26a70SApple OSS Distributions 	memcpy(&sin6, sa, MIN(sizeof(sin6), sa->sa_len));
263*a1e26a70SApple OSS Distributions 	inet_ntop(AF_INET6, &sin6.sin6_addr, abuffer, sizeof(abuffer));
264*a1e26a70SApple OSS Distributions 
265*a1e26a70SApple OSS Distributions 	T_LOG("%ssin6_len %u sin6_family %u sin6_port %u sin6_flowinfo %u sin6_addr %s sin6_scope_id %u%s",
266*a1e26a70SApple OSS Distributions 	    pre != NULL ? pre : "",
267*a1e26a70SApple OSS Distributions 	    sin6.sin6_len, sin6.sin6_family, htons(sin6.sin6_port), sin6.sin6_flowinfo, abuffer, sin6.sin6_scope_id,
268*a1e26a70SApple OSS Distributions 	    post != NULL ? post : "");
269*a1e26a70SApple OSS Distributions }
270*a1e26a70SApple OSS Distributions 
271*a1e26a70SApple OSS Distributions static void
print_sockaddr(const char * pre,const struct sockaddr * sa,const char * post)272*a1e26a70SApple OSS Distributions print_sockaddr(const char *pre, const struct sockaddr *sa, const char *post)
273*a1e26a70SApple OSS Distributions {
274*a1e26a70SApple OSS Distributions 	char buffer[256];
275*a1e26a70SApple OSS Distributions 
276*a1e26a70SApple OSS Distributions 	if (sa == NULL) {
277*a1e26a70SApple OSS Distributions 		return;
278*a1e26a70SApple OSS Distributions 	}
279*a1e26a70SApple OSS Distributions 
280*a1e26a70SApple OSS Distributions 	snprint_dottedhex(buffer, sizeof(buffer), sa->sa_data, sa->sa_len - 2);
281*a1e26a70SApple OSS Distributions 
282*a1e26a70SApple OSS Distributions 	T_LOG("%ssa_len %u sa_family %u sa_data %s%s",
283*a1e26a70SApple OSS Distributions 	    pre != NULL ? pre : "",
284*a1e26a70SApple OSS Distributions 	    sa->sa_len, sa->sa_family, buffer,
285*a1e26a70SApple OSS Distributions 	    post != NULL ? post : "");
286*a1e26a70SApple OSS Distributions }
287*a1e26a70SApple OSS Distributions 
288*a1e26a70SApple OSS Distributions 
289*a1e26a70SApple OSS Distributions #define ROUNDUP(a, size) (((a) & ((size) - 1)) ? (1 + ((a)|(size - 1))) : (a))
290*a1e26a70SApple OSS Distributions 
291*a1e26a70SApple OSS Distributions #define NEXT_SA(p) (struct sockaddr *) \
292*a1e26a70SApple OSS Distributions     ((caddr_t)p + (p->sa_len ? ROUNDUP(p->sa_len, sizeof(u_int32_t)) : \
293*a1e26a70SApple OSS Distributions      sizeof(u_long)))
294*a1e26a70SApple OSS Distributions 
295*a1e26a70SApple OSS Distributions static size_t
get_rti_info(int addrs,struct sockaddr * sa,struct sockaddr ** rti_info)296*a1e26a70SApple OSS Distributions get_rti_info(int addrs, struct sockaddr *sa, struct sockaddr **rti_info)
297*a1e26a70SApple OSS Distributions {
298*a1e26a70SApple OSS Distributions 	int i;
299*a1e26a70SApple OSS Distributions 	size_t len = 0;
300*a1e26a70SApple OSS Distributions 
301*a1e26a70SApple OSS Distributions 	for (i = 0; i < RTAX_MAX; i++) {
302*a1e26a70SApple OSS Distributions 		if (addrs & (1 << i)) {
303*a1e26a70SApple OSS Distributions 			rti_info[i] = sa;
304*a1e26a70SApple OSS Distributions 			if (sa->sa_len < sizeof(struct sockaddr)) {
305*a1e26a70SApple OSS Distributions 				len += sizeof(struct sockaddr);
306*a1e26a70SApple OSS Distributions 			} else {
307*a1e26a70SApple OSS Distributions 				len += sa->sa_len;
308*a1e26a70SApple OSS Distributions 			}
309*a1e26a70SApple OSS Distributions 			sa = NEXT_SA(sa);
310*a1e26a70SApple OSS Distributions 		} else {
311*a1e26a70SApple OSS Distributions 			rti_info[i] = NULL;
312*a1e26a70SApple OSS Distributions 		}
313*a1e26a70SApple OSS Distributions 	}
314*a1e26a70SApple OSS Distributions 	return len;
315*a1e26a70SApple OSS Distributions }
316*a1e26a70SApple OSS Distributions 
317*a1e26a70SApple OSS Distributions static void
print_address(const char * pre,const struct sockaddr * sa,const char * post,u_char asFamily)318*a1e26a70SApple OSS Distributions print_address(const char *pre, const struct sockaddr *sa, const char *post, u_char asFamily)
319*a1e26a70SApple OSS Distributions {
320*a1e26a70SApple OSS Distributions 	if (sa == NULL) {
321*a1e26a70SApple OSS Distributions 		T_LOG("%s(NULL)%s",
322*a1e26a70SApple OSS Distributions 		    pre != NULL ? pre : "",
323*a1e26a70SApple OSS Distributions 		    post != NULL ? post : "");
324*a1e26a70SApple OSS Distributions 		return;
325*a1e26a70SApple OSS Distributions 	}
326*a1e26a70SApple OSS Distributions 	if (sa->sa_len == 0) {
327*a1e26a70SApple OSS Distributions 		T_LOG("%ssa_len 0%s",
328*a1e26a70SApple OSS Distributions 		    pre != NULL ? pre : "",
329*a1e26a70SApple OSS Distributions 		    post != NULL ? post : "");
330*a1e26a70SApple OSS Distributions 		return;
331*a1e26a70SApple OSS Distributions 	}
332*a1e26a70SApple OSS Distributions 	if (sa->sa_len == 1) {
333*a1e26a70SApple OSS Distributions 		T_LOG("%ssa_len 1%s",
334*a1e26a70SApple OSS Distributions 		    pre != NULL ? pre : "",
335*a1e26a70SApple OSS Distributions 		    post != NULL ? post : "");
336*a1e26a70SApple OSS Distributions 		return;
337*a1e26a70SApple OSS Distributions 	}
338*a1e26a70SApple OSS Distributions 
339*a1e26a70SApple OSS Distributions 	// If not forced
340*a1e26a70SApple OSS Distributions 	if (asFamily == AF_UNSPEC) {
341*a1e26a70SApple OSS Distributions 		asFamily = sa->sa_family;
342*a1e26a70SApple OSS Distributions 	}
343*a1e26a70SApple OSS Distributions 	switch (asFamily) {
344*a1e26a70SApple OSS Distributions 	case AF_INET: {
345*a1e26a70SApple OSS Distributions 		print_sockaddr_in(pre, sa, post);
346*a1e26a70SApple OSS Distributions 		break;
347*a1e26a70SApple OSS Distributions 	}
348*a1e26a70SApple OSS Distributions 	case AF_INET6: {
349*a1e26a70SApple OSS Distributions 		print_sockaddr_in6(pre, sa, post);
350*a1e26a70SApple OSS Distributions 		break;
351*a1e26a70SApple OSS Distributions 	}
352*a1e26a70SApple OSS Distributions 	case AF_LINK: {
353*a1e26a70SApple OSS Distributions 		print_sockaddr_dl(pre, sa, post);
354*a1e26a70SApple OSS Distributions 		break;
355*a1e26a70SApple OSS Distributions 	}
356*a1e26a70SApple OSS Distributions 	default:
357*a1e26a70SApple OSS Distributions 		print_sockaddr(pre, sa, post);
358*a1e26a70SApple OSS Distributions 		break;
359*a1e26a70SApple OSS Distributions 	}
360*a1e26a70SApple OSS Distributions }
361*a1e26a70SApple OSS Distributions 
362*a1e26a70SApple OSS Distributions static void
print_rti_info(struct sockaddr * rti_info[])363*a1e26a70SApple OSS Distributions print_rti_info(struct sockaddr *rti_info[])
364*a1e26a70SApple OSS Distributions {
365*a1e26a70SApple OSS Distributions 	struct sockaddr *sa;
366*a1e26a70SApple OSS Distributions 	u_char asFamily = 0;
367*a1e26a70SApple OSS Distributions 
368*a1e26a70SApple OSS Distributions 	if ((sa = rti_info[RTAX_IFA])) {
369*a1e26a70SApple OSS Distributions 		asFamily = sa->sa_family;
370*a1e26a70SApple OSS Distributions 		print_address(" RTAX_IFA         ", sa, "\n", 0);
371*a1e26a70SApple OSS Distributions 	}
372*a1e26a70SApple OSS Distributions 	if ((sa = rti_info[RTAX_DST])) {
373*a1e26a70SApple OSS Distributions 		asFamily = sa->sa_family;
374*a1e26a70SApple OSS Distributions 		print_address(" RTAX_DST         ", sa, "\n", 0);
375*a1e26a70SApple OSS Distributions 	}
376*a1e26a70SApple OSS Distributions 	if ((sa = rti_info[RTAX_BRD])) {
377*a1e26a70SApple OSS Distributions 		print_address(" RTAX_BRD         ", sa, "\n", asFamily);
378*a1e26a70SApple OSS Distributions 	}
379*a1e26a70SApple OSS Distributions 
380*a1e26a70SApple OSS Distributions 	if ((sa = rti_info[RTAX_NETMASK])) {
381*a1e26a70SApple OSS Distributions 		print_address(" RTAX_NETMASK     ", sa, "\n", asFamily);
382*a1e26a70SApple OSS Distributions 	}
383*a1e26a70SApple OSS Distributions 
384*a1e26a70SApple OSS Distributions 	if ((sa = rti_info[RTAX_GATEWAY])) {
385*a1e26a70SApple OSS Distributions 		print_address(" RTAX_GATEWAY     ", sa, "\n", 0);
386*a1e26a70SApple OSS Distributions 	}
387*a1e26a70SApple OSS Distributions 
388*a1e26a70SApple OSS Distributions 	if ((sa = rti_info[RTAX_GENMASK])) {
389*a1e26a70SApple OSS Distributions 		print_address(" RTAX_GENMASK     ", sa, "\n", asFamily);
390*a1e26a70SApple OSS Distributions 	}
391*a1e26a70SApple OSS Distributions 
392*a1e26a70SApple OSS Distributions 	if ((sa = rti_info[RTAX_AUTHOR])) {
393*a1e26a70SApple OSS Distributions 		print_address(" RTAX_AUTHOR      ", sa, "\n", asFamily);
394*a1e26a70SApple OSS Distributions 	}
395*a1e26a70SApple OSS Distributions 
396*a1e26a70SApple OSS Distributions 	if ((sa = rti_info[RTAX_IFP])) {
397*a1e26a70SApple OSS Distributions 		print_address(" RTAX_IFP         ", sa, "\n", 0);
398*a1e26a70SApple OSS Distributions 	}
399*a1e26a70SApple OSS Distributions }
400*a1e26a70SApple OSS Distributions 
401*a1e26a70SApple OSS Distributions static void
print_rt_iflist2(const char * label)402*a1e26a70SApple OSS Distributions print_rt_iflist2(const char *label)
403*a1e26a70SApple OSS Distributions {
404*a1e26a70SApple OSS Distributions 	size_t len;
405*a1e26a70SApple OSS Distributions 	int mib[6] = { CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST2, 0 };
406*a1e26a70SApple OSS Distributions 	unsigned char *buf = NULL;
407*a1e26a70SApple OSS Distributions 	unsigned char *lim, *next;
408*a1e26a70SApple OSS Distributions 	struct if_msghdr *ifmsg;
409*a1e26a70SApple OSS Distributions 
410*a1e26a70SApple OSS Distributions 	T_LOG("interface address list for %s", label);
411*a1e26a70SApple OSS Distributions 
412*a1e26a70SApple OSS Distributions 	T_QUIET; T_EXPECT_POSIX_SUCCESS(sysctl(mib, 6, NULL, &len, NULL, 0), "sysctl NET_RT_IFLIST2");
413*a1e26a70SApple OSS Distributions 
414*a1e26a70SApple OSS Distributions 	T_QUIET; T_ASSERT_NOTNULL(buf = calloc(1, len), "rt_if_list_buf calloc(1, %zd)", len);
415*a1e26a70SApple OSS Distributions 
416*a1e26a70SApple OSS Distributions 	T_QUIET; T_EXPECT_POSIX_SUCCESS(sysctl(mib, 6, buf, &len, NULL, 0), "sysctl NET_RT_IFLIST2");
417*a1e26a70SApple OSS Distributions 
418*a1e26a70SApple OSS Distributions 	lim = buf + len;
419*a1e26a70SApple OSS Distributions 	for (next = buf; next < lim; next += ifmsg->ifm_msglen) {
420*a1e26a70SApple OSS Distributions 		ifmsg = (struct if_msghdr *)(void *)next;
421*a1e26a70SApple OSS Distributions 		char ifname[IF_NAMESIZE + 1];
422*a1e26a70SApple OSS Distributions 
423*a1e26a70SApple OSS Distributions 		if (ifmsg->ifm_type == RTM_IFINFO2) {
424*a1e26a70SApple OSS Distributions 			struct if_msghdr2 *ifm = (struct if_msghdr2 *)ifmsg;
425*a1e26a70SApple OSS Distributions 			struct sockaddr *sa = (struct sockaddr *)(ifm + 1);
426*a1e26a70SApple OSS Distributions 
427*a1e26a70SApple OSS Distributions 			(void)if_indextoname(ifm->ifm_index, ifname);
428*a1e26a70SApple OSS Distributions 			T_LOG("interface: %s", ifname);
429*a1e26a70SApple OSS Distributions 			print_address(" PRIMARY          ", sa, "", 0);
430*a1e26a70SApple OSS Distributions 		} else if (ifmsg->ifm_type == RTM_NEWADDR) {
431*a1e26a70SApple OSS Distributions 			struct sockaddr *rti_info[RTAX_MAX];
432*a1e26a70SApple OSS Distributions 			struct ifa_msghdr *ifam = (struct ifa_msghdr *)ifmsg;
433*a1e26a70SApple OSS Distributions 
434*a1e26a70SApple OSS Distributions 			(void) get_rti_info(ifam->ifam_addrs, (struct sockaddr *)(ifam + 1), rti_info);
435*a1e26a70SApple OSS Distributions 
436*a1e26a70SApple OSS Distributions 			print_rti_info(rti_info);
437*a1e26a70SApple OSS Distributions 		}
438*a1e26a70SApple OSS Distributions 	}
439*a1e26a70SApple OSS Distributions 	free(buf);
440*a1e26a70SApple OSS Distributions }
441*a1e26a70SApple OSS Distributions 
442*a1e26a70SApple OSS Distributions static int
check_rt_if_list_for_pattern(const char * label,unsigned char pattern,size_t pattern_size)443*a1e26a70SApple OSS Distributions check_rt_if_list_for_pattern(const char *label, unsigned char pattern, size_t pattern_size)
444*a1e26a70SApple OSS Distributions {
445*a1e26a70SApple OSS Distributions 	size_t i;
446*a1e26a70SApple OSS Distributions 	size_t len;
447*a1e26a70SApple OSS Distributions 	int mib[6] = { CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, 0 };
448*a1e26a70SApple OSS Distributions 	unsigned char *rt_if_list_buf = NULL;
449*a1e26a70SApple OSS Distributions 	int count = 0;
450*a1e26a70SApple OSS Distributions 	unsigned char *pattern_buf = NULL;
451*a1e26a70SApple OSS Distributions 
452*a1e26a70SApple OSS Distributions 	T_QUIET; T_ASSERT_NOTNULL(pattern_buf = calloc(1, pattern_size), "pattern_buf calloc(1, %zd)", pattern_size);
453*a1e26a70SApple OSS Distributions 	memset(pattern_buf, pattern, pattern_size);
454*a1e26a70SApple OSS Distributions 
455*a1e26a70SApple OSS Distributions 	T_QUIET; T_EXPECT_POSIX_SUCCESS(sysctl(mib, 6, NULL, &len, NULL, 0), "sysctl NET_RT_IFLIST");
456*a1e26a70SApple OSS Distributions 
457*a1e26a70SApple OSS Distributions 	T_QUIET; T_ASSERT_NOTNULL(rt_if_list_buf = calloc(1, len), "rt_if_list_buf calloc(1, %zd)", len);
458*a1e26a70SApple OSS Distributions 
459*a1e26a70SApple OSS Distributions 	T_QUIET; T_EXPECT_POSIX_SUCCESS(sysctl(mib, 6, rt_if_list_buf, &len, NULL, 0), "sysctl NET_RT_IFLIST");
460*a1e26a70SApple OSS Distributions 
461*a1e26a70SApple OSS Distributions 	if (label != NULL) {
462*a1e26a70SApple OSS Distributions 		T_LOG("%s sysctl NET_RT_IFLIST buffer length %zd\n", label, len);
463*a1e26a70SApple OSS Distributions 	}
464*a1e26a70SApple OSS Distributions 
465*a1e26a70SApple OSS Distributions 	count = 0;
466*a1e26a70SApple OSS Distributions 	for (i = 0; i < len - pattern_size; i++) {
467*a1e26a70SApple OSS Distributions 		if (memcmp(rt_if_list_buf + i, pattern_buf, pattern_size) == 0) {
468*a1e26a70SApple OSS Distributions 			count++;
469*a1e26a70SApple OSS Distributions 			i += pattern_size - 1;
470*a1e26a70SApple OSS Distributions 		}
471*a1e26a70SApple OSS Distributions 	}
472*a1e26a70SApple OSS Distributions 
473*a1e26a70SApple OSS Distributions 	if (label != NULL) {
474*a1e26a70SApple OSS Distributions 		if (label != NULL && count > 0) {
475*a1e26a70SApple OSS Distributions 			T_LOG("%s found pattern at %zd count %d times\n", label, i, count);
476*a1e26a70SApple OSS Distributions 			HexDump(rt_if_list_buf, len);
477*a1e26a70SApple OSS Distributions 		}
478*a1e26a70SApple OSS Distributions 	}
479*a1e26a70SApple OSS Distributions 
480*a1e26a70SApple OSS Distributions 	free(rt_if_list_buf);
481*a1e26a70SApple OSS Distributions 	free(pattern_buf);
482*a1e26a70SApple OSS Distributions 
483*a1e26a70SApple OSS Distributions 	return count;
484*a1e26a70SApple OSS Distributions }
485*a1e26a70SApple OSS Distributions 
486*a1e26a70SApple OSS Distributions static bool
find_unused_pattern_in_rt_if_list(unsigned char * pattern,size_t pattern_size)487*a1e26a70SApple OSS Distributions find_unused_pattern_in_rt_if_list(unsigned char *pattern, size_t pattern_size)
488*a1e26a70SApple OSS Distributions {
489*a1e26a70SApple OSS Distributions 	bool found_pattern = false;
490*a1e26a70SApple OSS Distributions 	unsigned char i;
491*a1e26a70SApple OSS Distributions 	unsigned char *pattern_buf = NULL;
492*a1e26a70SApple OSS Distributions 
493*a1e26a70SApple OSS Distributions 	T_QUIET; T_ASSERT_NOTNULL(pattern_buf = calloc(1, pattern_size), "pattern_buf calloc(1, %zd)", pattern_size);
494*a1e26a70SApple OSS Distributions 
495*a1e26a70SApple OSS Distributions 	/* Try 10 times to find an unused pattern */
496*a1e26a70SApple OSS Distributions 	for (i = 1; i < 255; i++) {
497*a1e26a70SApple OSS Distributions 		if (check_rt_if_list_for_pattern(NULL, i, pattern_size) == 0) {
498*a1e26a70SApple OSS Distributions 			found_pattern = true;
499*a1e26a70SApple OSS Distributions 			*pattern = i;
500*a1e26a70SApple OSS Distributions 			memset(pattern_buf, i, pattern_size);
501*a1e26a70SApple OSS Distributions 			T_LOG("PATTERN: ");
502*a1e26a70SApple OSS Distributions 			HexDump(pattern_buf, pattern_size);
503*a1e26a70SApple OSS Distributions 			break;
504*a1e26a70SApple OSS Distributions 		}
505*a1e26a70SApple OSS Distributions 	}
506*a1e26a70SApple OSS Distributions 	free(pattern_buf);
507*a1e26a70SApple OSS Distributions 
508*a1e26a70SApple OSS Distributions 	return found_pattern;
509*a1e26a70SApple OSS Distributions }
510*a1e26a70SApple OSS Distributions 
511*a1e26a70SApple OSS Distributions static const char *
ioc_str(unsigned long cmd)512*a1e26a70SApple OSS Distributions ioc_str(unsigned long cmd)
513*a1e26a70SApple OSS Distributions {
514*a1e26a70SApple OSS Distributions 	switch (cmd) {
515*a1e26a70SApple OSS Distributions #define X(a) case a: return #a;
516*a1e26a70SApple OSS Distributions 		SIOC_LIST
517*a1e26a70SApple OSS Distributions #undef X
518*a1e26a70SApple OSS Distributions 	default:
519*a1e26a70SApple OSS Distributions 		break;
520*a1e26a70SApple OSS Distributions 	}
521*a1e26a70SApple OSS Distributions 	return "";
522*a1e26a70SApple OSS Distributions }
523*a1e26a70SApple OSS Distributions 
524*a1e26a70SApple OSS Distributions struct ioc_ifreq {
525*a1e26a70SApple OSS Distributions 	unsigned long ioc_cmd;
526*a1e26a70SApple OSS Distributions 	uint8_t salen;
527*a1e26a70SApple OSS Distributions 	uint8_t safamily;
528*a1e26a70SApple OSS Distributions 	const char *sastr;
529*a1e26a70SApple OSS Distributions 	int error; // 0 means no error, -1, end of list, otherwise expected errno
530*a1e26a70SApple OSS Distributions };
531*a1e26a70SApple OSS Distributions 
532*a1e26a70SApple OSS Distributions static struct ioc_ifreq ioc_list[] = {
533*a1e26a70SApple OSS Distributions 	{ SIOCSIFADDR, sizeof(struct sockaddr_in), AF_INET6, "10.2.3.1", EINVAL },
534*a1e26a70SApple OSS Distributions 	{ SIOCDIFADDR, sizeof(struct sockaddr_in), AF_INET6, "10.2.3.1", EADDRNOTAVAIL },
535*a1e26a70SApple OSS Distributions 	{ SIOCDIFADDR, sizeof(struct sockaddr_in6), AF_INET, "10.2.3.1", EADDRNOTAVAIL },
536*a1e26a70SApple OSS Distributions 	{ SIOCDIFADDR, sizeof(struct sockaddr_in), AF_INET, "10.2.3.1", EADDRNOTAVAIL },
537*a1e26a70SApple OSS Distributions 
538*a1e26a70SApple OSS Distributions 	{ SIOCSIFADDR, 0xf0, AF_INET6, "10.2.3.1", EINVAL },
539*a1e26a70SApple OSS Distributions 	{ SIOCDIFADDR, 0xf0, AF_INET6, "10.2.3.1", EADDRNOTAVAIL },
540*a1e26a70SApple OSS Distributions 	{ SIOCDIFADDR, 0xf0, AF_INET, "10.2.3.1", EADDRNOTAVAIL },
541*a1e26a70SApple OSS Distributions 	{ SIOCDIFADDR, 0xf0, AF_INET, "10.2.3.1", EADDRNOTAVAIL },
542*a1e26a70SApple OSS Distributions 
543*a1e26a70SApple OSS Distributions 	{ SIOCSIFADDR, 0, AF_INET6, "10.2.3.1", EINVAL },
544*a1e26a70SApple OSS Distributions 	{ SIOCDIFADDR, 0, AF_INET6, "10.2.3.1", EADDRNOTAVAIL },
545*a1e26a70SApple OSS Distributions 	{ SIOCDIFADDR, 0, AF_INET, "10.2.3.1", EADDRNOTAVAIL },
546*a1e26a70SApple OSS Distributions 	{ SIOCDIFADDR, 0, AF_INET, "10.2.3.1", EADDRNOTAVAIL },
547*a1e26a70SApple OSS Distributions 
548*a1e26a70SApple OSS Distributions 	{ SIOCSIFADDR, sizeof(struct sockaddr_in6), AF_INET, "10.2.3.2", 0 },
549*a1e26a70SApple OSS Distributions 	{ SIOCDIFADDR, sizeof(struct sockaddr_in), AF_INET6, "10.2.3.2", 0 },
550*a1e26a70SApple OSS Distributions 
551*a1e26a70SApple OSS Distributions 	{ SIOCSIFADDR, sizeof(struct sockaddr_in), AF_INET, "10.2.3.3", 0 },
552*a1e26a70SApple OSS Distributions 	{ SIOCDIFADDR, sizeof(struct sockaddr_in6), AF_INET, "10.2.3.3", 0 },
553*a1e26a70SApple OSS Distributions 
554*a1e26a70SApple OSS Distributions 	{ SIOCSIFADDR, sizeof(struct sockaddr_in6), AF_INET6, "10.2.3.4", EINVAL },
555*a1e26a70SApple OSS Distributions 	{ SIOCDIFADDR, sizeof(struct sockaddr_in6), AF_INET, "10.2.3.4", EADDRNOTAVAIL },
556*a1e26a70SApple OSS Distributions 
557*a1e26a70SApple OSS Distributions 	{ SIOCSIFADDR, sizeof(struct sockaddr_in), AF_INET, "10.2.3.5", 0 },
558*a1e26a70SApple OSS Distributions 	{ SIOCDIFADDR, sizeof(struct sockaddr_in), AF_INET, "0.0.0.0", EADDRNOTAVAIL },
559*a1e26a70SApple OSS Distributions 	{ SIOCDIFADDR, sizeof(struct sockaddr_in), AF_INET, "10.2.3.5", 0 },
560*a1e26a70SApple OSS Distributions 
561*a1e26a70SApple OSS Distributions 	{ SIOCSIFADDR, sizeof(struct sockaddr_in), AF_INET, "10.2.3.6", 0 },
562*a1e26a70SApple OSS Distributions 
563*a1e26a70SApple OSS Distributions 	{ SIOCSIFNETMASK, sizeof(struct sockaddr_in), 0, "ff.00.00.00", 0 },
564*a1e26a70SApple OSS Distributions 	{ SIOCSIFNETMASK, sizeof(struct sockaddr_in), AF_INET, "ff.00.00.00", 0 },
565*a1e26a70SApple OSS Distributions 	{ SIOCSIFNETMASK, sizeof(struct sockaddr_in), AF_INET6, "ff.f.00.00", 0 },
566*a1e26a70SApple OSS Distributions 
567*a1e26a70SApple OSS Distributions 	{ SIOCSIFNETMASK, sizeof(struct sockaddr_in6), 0, "ff.ff.00.00", 0 },
568*a1e26a70SApple OSS Distributions 	{ SIOCSIFNETMASK, sizeof(struct sockaddr_in6), AF_INET, "ff.ff.00.00", 0 },
569*a1e26a70SApple OSS Distributions 	{ SIOCSIFNETMASK, sizeof(struct sockaddr_in6), AF_INET6, "ff.ff.f0.00", 0 },
570*a1e26a70SApple OSS Distributions 
571*a1e26a70SApple OSS Distributions 	{ SIOCSIFNETMASK, 0, 0, "ff.ff.00.00", 0 },
572*a1e26a70SApple OSS Distributions 	{ SIOCSIFNETMASK, 0, AF_INET, "ff.ff.00.00", 0 },
573*a1e26a70SApple OSS Distributions 	{ SIOCSIFNETMASK, 0, AF_INET6, "ff.ff.f0.00", 0 },
574*a1e26a70SApple OSS Distributions 
575*a1e26a70SApple OSS Distributions 	{ SIOCSIFNETMASK, 0xf0, 0, "ff.ff.00.00", 0 },
576*a1e26a70SApple OSS Distributions 	{ SIOCSIFNETMASK, 0xf0, AF_INET, "ff.ff.00.00", 0 },
577*a1e26a70SApple OSS Distributions 	{ SIOCSIFNETMASK, 0xf0, AF_INET6, "ff.ff.f0.00", 0 },
578*a1e26a70SApple OSS Distributions 
579*a1e26a70SApple OSS Distributions 	{ SIOCSIFBRDADDR, sizeof(struct sockaddr_in), 0, "10.255.255.255", 0 },
580*a1e26a70SApple OSS Distributions 	{ SIOCSIFBRDADDR, sizeof(struct sockaddr_in), AF_INET, "10.255.255.255", 0 },
581*a1e26a70SApple OSS Distributions 	{ SIOCSIFBRDADDR, sizeof(struct sockaddr_in), AF_INET6, "10.255.255.255", 0 },
582*a1e26a70SApple OSS Distributions 	{ SIOCSIFBRDADDR, sizeof(struct sockaddr_in6), AF_INET, "10.255.255.255", 0 },
583*a1e26a70SApple OSS Distributions 
584*a1e26a70SApple OSS Distributions 	{ SIOCSIFBRDADDR, 0xf0, 0, "10.255.255.255", 0 },
585*a1e26a70SApple OSS Distributions 	{ SIOCSIFBRDADDR, 0xf0, AF_INET, "10.255.255.255", 0 },
586*a1e26a70SApple OSS Distributions 	{ SIOCSIFBRDADDR, 0xf0, AF_INET6, "10.255.255.255", 0 },
587*a1e26a70SApple OSS Distributions 	{ SIOCSIFBRDADDR, 0xf0, AF_INET, "10.255.255.255", 0 },
588*a1e26a70SApple OSS Distributions 
589*a1e26a70SApple OSS Distributions 	{ SIOCSIFBRDADDR, 0, 0, "10.255.255.255", 0 },
590*a1e26a70SApple OSS Distributions 	{ SIOCSIFBRDADDR, 0, AF_INET, "10.255.255.255", 0 },
591*a1e26a70SApple OSS Distributions 	{ SIOCSIFBRDADDR, 0, AF_INET6, "10.255.255.255", 0 },
592*a1e26a70SApple OSS Distributions 	{ SIOCSIFBRDADDR, 0, AF_INET, "10.255.255.255", 0 },
593*a1e26a70SApple OSS Distributions 
594*a1e26a70SApple OSS Distributions 	{ 0, 0, 0, "", -1 },
595*a1e26a70SApple OSS Distributions };
596*a1e26a70SApple OSS Distributions 
597*a1e26a70SApple OSS Distributions static void
test_sioc_ifr_bounds(struct ioc_ifreq * ioc_ifreq,int s,const char * ifname)598*a1e26a70SApple OSS Distributions test_sioc_ifr_bounds(struct ioc_ifreq *ioc_ifreq, int s, const char *ifname)
599*a1e26a70SApple OSS Distributions {
600*a1e26a70SApple OSS Distributions 	struct ifreq ifr = { 0 };
601*a1e26a70SApple OSS Distributions 	unsigned char pattern;
602*a1e26a70SApple OSS Distributions 	struct sockaddr_in *sin;
603*a1e26a70SApple OSS Distributions 
604*a1e26a70SApple OSS Distributions 	T_LOG("");
605*a1e26a70SApple OSS Distributions 	T_LOG("TEST CASE: %s ioctl(%s, sa_len %u, sa_family %u, %s) -> %d", __func__,
606*a1e26a70SApple OSS Distributions 	    ioc_str(ioc_ifreq->ioc_cmd), ioc_ifreq->salen, ioc_ifreq->safamily, ioc_ifreq->sastr, ioc_ifreq->error);
607*a1e26a70SApple OSS Distributions 
608*a1e26a70SApple OSS Distributions 
609*a1e26a70SApple OSS Distributions 	if (find_unused_pattern_in_rt_if_list(&pattern, PATTERN_SIZE) == false) {
610*a1e26a70SApple OSS Distributions 		T_SKIP("Could not find unused pattern");
611*a1e26a70SApple OSS Distributions 	}
612*a1e26a70SApple OSS Distributions 
613*a1e26a70SApple OSS Distributions 	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
614*a1e26a70SApple OSS Distributions 	memset(&ifr.ifr_addr.sa_data, pattern, sizeof(ifr.ifr_dstaddr.sa_data));
615*a1e26a70SApple OSS Distributions 
616*a1e26a70SApple OSS Distributions 	sin = (struct sockaddr_in *)(void *)&ifr.ifr_addr;
617*a1e26a70SApple OSS Distributions 	sin->sin_len = ioc_ifreq->salen;
618*a1e26a70SApple OSS Distributions 	sin->sin_family = ioc_ifreq->safamily;
619*a1e26a70SApple OSS Distributions 	sin->sin_addr.s_addr = inet_addr(ioc_ifreq->sastr);
620*a1e26a70SApple OSS Distributions 
621*a1e26a70SApple OSS Distributions 	int retval;
622*a1e26a70SApple OSS Distributions 	if (ioc_ifreq->error == 0) {
623*a1e26a70SApple OSS Distributions 		T_EXPECT_POSIX_SUCCESS(retval = ioctl(s, ioc_ifreq->ioc_cmd, &ifr),
624*a1e26a70SApple OSS Distributions 		    "%s, %s: retval %d", ioc_str(ioc_ifreq->ioc_cmd), ioc_ifreq->sastr, retval);
625*a1e26a70SApple OSS Distributions 	} else {
626*a1e26a70SApple OSS Distributions 		T_EXPECT_POSIX_FAILURE(retval = ioctl(s, ioc_ifreq->ioc_cmd, &ifr), ioc_ifreq->error,
627*a1e26a70SApple OSS Distributions 		    "%s, %s: retval %d errno %s", ioc_str(ioc_ifreq->ioc_cmd), ioc_ifreq->sastr, retval, strerror(errno));
628*a1e26a70SApple OSS Distributions 	}
629*a1e26a70SApple OSS Distributions 
630*a1e26a70SApple OSS Distributions 	T_EXPECT_EQ(check_rt_if_list_for_pattern("test_sioc_ifr_bounds", pattern, PATTERN_SIZE), 0, "pattern should not be found");
631*a1e26a70SApple OSS Distributions 
632*a1e26a70SApple OSS Distributions 
633*a1e26a70SApple OSS Distributions 	fflush(stdout);
634*a1e26a70SApple OSS Distributions 	fflush(stderr);
635*a1e26a70SApple OSS Distributions }
636*a1e26a70SApple OSS Distributions 
637*a1e26a70SApple OSS Distributions T_DECL(sioc_ifr_bounds, "test bound checks on struct ifreq addresses passed to interface ioctls",
638*a1e26a70SApple OSS Distributions     T_META_ASROOT(true), T_META_TAG_VM_PREFERRED)
639*a1e26a70SApple OSS Distributions {
640*a1e26a70SApple OSS Distributions 	int s = -1;
641*a1e26a70SApple OSS Distributions 	char ifname[IFNAMSIZ];
642*a1e26a70SApple OSS Distributions 
643*a1e26a70SApple OSS Distributions 	T_LOG("%s", __func__);
644*a1e26a70SApple OSS Distributions 
645*a1e26a70SApple OSS Distributions 	T_QUIET; T_EXPECT_POSIX_SUCCESS(s = socket(AF_INET, SOCK_DGRAM, 0), "socket");
646*a1e26a70SApple OSS Distributions 
647*a1e26a70SApple OSS Distributions 	strlcpy(ifname, IF_NAME, sizeof(ifname));
648*a1e26a70SApple OSS Distributions 
649*a1e26a70SApple OSS Distributions 	int error = 0;
650*a1e26a70SApple OSS Distributions 	if ((error = ifnet_create(s, ifname, sizeof(ifname))) != 0) {
651*a1e26a70SApple OSS Distributions 		if (error == EINVAL) {
652*a1e26a70SApple OSS Distributions 			T_SKIP("The system does not support the %s cloning interface", IF_NAME);
653*a1e26a70SApple OSS Distributions 		}
654*a1e26a70SApple OSS Distributions 		T_SKIP("This test failed creating a %s cloning interface", IF_NAME);
655*a1e26a70SApple OSS Distributions 	}
656*a1e26a70SApple OSS Distributions 	T_LOG("created clone interface '%s'", ifname);
657*a1e26a70SApple OSS Distributions 
658*a1e26a70SApple OSS Distributions 	struct ioc_ifreq *ioc_ifreq;
659*a1e26a70SApple OSS Distributions 	for (ioc_ifreq = ioc_list; ioc_ifreq->error != -1; ioc_ifreq++) {
660*a1e26a70SApple OSS Distributions 		test_sioc_ifr_bounds(ioc_ifreq, s, ifname);
661*a1e26a70SApple OSS Distributions 	}
662*a1e26a70SApple OSS Distributions 	print_rt_iflist2(__func__);
663*a1e26a70SApple OSS Distributions 	(void)ifnet_destroy(s, ifname, true);
664*a1e26a70SApple OSS Distributions 
665*a1e26a70SApple OSS Distributions 	close(s);
666*a1e26a70SApple OSS Distributions }
667*a1e26a70SApple OSS Distributions 
668*a1e26a70SApple OSS Distributions struct ioc_ifra {
669*a1e26a70SApple OSS Distributions 	const char *description;
670*a1e26a70SApple OSS Distributions 
671*a1e26a70SApple OSS Distributions 	uint8_t addr_len;
672*a1e26a70SApple OSS Distributions 	uint8_t addr_fam;
673*a1e26a70SApple OSS Distributions 	const char *addr_str;
674*a1e26a70SApple OSS Distributions 
675*a1e26a70SApple OSS Distributions 	uint8_t broad_len;
676*a1e26a70SApple OSS Distributions 	uint8_t broad_fam;
677*a1e26a70SApple OSS Distributions 	const char *broad_str;
678*a1e26a70SApple OSS Distributions 
679*a1e26a70SApple OSS Distributions 	uint8_t mask_len;
680*a1e26a70SApple OSS Distributions 	uint8_t mask_fam;
681*a1e26a70SApple OSS Distributions 	const char *mask_str;
682*a1e26a70SApple OSS Distributions 
683*a1e26a70SApple OSS Distributions 	int error; // 0 means no error, -1, end of list, otherwise expected errno
684*a1e26a70SApple OSS Distributions };
685*a1e26a70SApple OSS Distributions 
686*a1e26a70SApple OSS Distributions static struct ioc_ifra ioc_ifra_list[] = {
687*a1e26a70SApple OSS Distributions 	{
688*a1e26a70SApple OSS Distributions 		.description = "fully formed",
689*a1e26a70SApple OSS Distributions 		.addr_len = sizeof(struct sockaddr_in), .addr_fam = AF_INET, .addr_str = "10.1.1.1",
690*a1e26a70SApple OSS Distributions 		.broad_len = sizeof(struct sockaddr_in), .broad_fam = AF_INET, .broad_str = "1.1.1.255",
691*a1e26a70SApple OSS Distributions 		.mask_len = sizeof(struct sockaddr_in), .mask_fam = AF_INET, .mask_str = "255.255.0.0",
692*a1e26a70SApple OSS Distributions 		.error = 0
693*a1e26a70SApple OSS Distributions 	},
694*a1e26a70SApple OSS Distributions 	{
695*a1e26a70SApple OSS Distributions 		.description = "addr_len 0",
696*a1e26a70SApple OSS Distributions 		.addr_len = 0, .addr_fam = AF_INET, .addr_str = "10.2.2.0",
697*a1e26a70SApple OSS Distributions 		.broad_len = sizeof(struct sockaddr_in), .broad_fam = AF_INET, .broad_str = "10.2.2.255",
698*a1e26a70SApple OSS Distributions 		.mask_len = sizeof(struct sockaddr_in), .mask_fam = AF_INET, .mask_str = "255.0.0.0",
699*a1e26a70SApple OSS Distributions 		.error = 0
700*a1e26a70SApple OSS Distributions 	},
701*a1e26a70SApple OSS Distributions 	{
702*a1e26a70SApple OSS Distributions 		.description = "addr_len 1",
703*a1e26a70SApple OSS Distributions 		.addr_len = 1, .addr_fam = AF_INET, .addr_str = "10.2.2.1",
704*a1e26a70SApple OSS Distributions 		.broad_len = sizeof(struct sockaddr_in), .broad_fam = AF_INET, .broad_str = "10.2.2.255",
705*a1e26a70SApple OSS Distributions 		.mask_len = sizeof(struct sockaddr_in), .mask_fam = AF_INET, .mask_str = "255.0.0.0",
706*a1e26a70SApple OSS Distributions 		.error = 0
707*a1e26a70SApple OSS Distributions 	},
708*a1e26a70SApple OSS Distributions 	{
709*a1e26a70SApple OSS Distributions 		.description = "addr_len 250",
710*a1e26a70SApple OSS Distributions 		.addr_len = 250, .addr_fam = AF_INET, .addr_str = "10.2.2.250",
711*a1e26a70SApple OSS Distributions 		.broad_len = sizeof(struct sockaddr_in), .broad_fam = AF_INET, .broad_str = "10.2.2.255",
712*a1e26a70SApple OSS Distributions 		.mask_len = sizeof(struct sockaddr_in), .mask_fam = AF_INET, .mask_str = "255.0.0.0",
713*a1e26a70SApple OSS Distributions 		.error = 0
714*a1e26a70SApple OSS Distributions 	},
715*a1e26a70SApple OSS Distributions 	{
716*a1e26a70SApple OSS Distributions 		.description = "addr_family AF_INET6",
717*a1e26a70SApple OSS Distributions 		.addr_len = sizeof(struct sockaddr_in), .addr_fam = AF_INET6, .addr_str = "10.3.3.3",
718*a1e26a70SApple OSS Distributions 		.broad_len = sizeof(struct sockaddr_in), .broad_fam = AF_INET, .broad_str = "10.3.255.255",
719*a1e26a70SApple OSS Distributions 		.mask_len = sizeof(struct sockaddr_in), .mask_fam = AF_INET, .mask_str = "255.255.255.0",
720*a1e26a70SApple OSS Distributions 		.error = EINVAL
721*a1e26a70SApple OSS Distributions 	},
722*a1e26a70SApple OSS Distributions 	{
723*a1e26a70SApple OSS Distributions 		.description = "broadcast_len 0xf0",
724*a1e26a70SApple OSS Distributions 		.addr_len = sizeof(struct sockaddr_in), .addr_fam = AF_INET, .addr_str = "10.4.4.4",
725*a1e26a70SApple OSS Distributions 		.broad_len = 0xf0, .broad_fam = AF_INET, .broad_str = "10.4.4.255",
726*a1e26a70SApple OSS Distributions 		.mask_len = sizeof(struct sockaddr_in), .mask_fam = AF_INET, .mask_str = "255.255.255.0",
727*a1e26a70SApple OSS Distributions 		.error = 0
728*a1e26a70SApple OSS Distributions 	},
729*a1e26a70SApple OSS Distributions 	{
730*a1e26a70SApple OSS Distributions 		.description = "broadcast_family AF_INET6",
731*a1e26a70SApple OSS Distributions 		.addr_len = sizeof(struct sockaddr_in), .addr_fam = AF_INET, .addr_str = "10.5.5.5",
732*a1e26a70SApple OSS Distributions 		.broad_len = sizeof(struct sockaddr_in), .broad_fam = AF_INET6, .broad_str = "10.5.5.255",
733*a1e26a70SApple OSS Distributions 		.mask_len = sizeof(struct sockaddr_in), .mask_fam = AF_INET, .mask_str = "255.255.0.0",
734*a1e26a70SApple OSS Distributions 		.error = 0
735*a1e26a70SApple OSS Distributions 	},
736*a1e26a70SApple OSS Distributions 	{
737*a1e26a70SApple OSS Distributions 		.description = "mask_len 0xf0",
738*a1e26a70SApple OSS Distributions 		.addr_len = sizeof(struct sockaddr_in), .addr_fam = AF_INET, .addr_str = "10.6.6.6",
739*a1e26a70SApple OSS Distributions 		.broad_len = sizeof(struct sockaddr_in), .broad_fam = AF_INET, .broad_str = "1.6.6.255",
740*a1e26a70SApple OSS Distributions 		.mask_len = 0xf0, .mask_fam = AF_INET, .mask_str = "255.255.0.0",
741*a1e26a70SApple OSS Distributions 		.error = 0
742*a1e26a70SApple OSS Distributions 	},
743*a1e26a70SApple OSS Distributions 	{
744*a1e26a70SApple OSS Distributions 		.description = "mask_family AF_INET6",
745*a1e26a70SApple OSS Distributions 		.addr_len = sizeof(struct sockaddr_in), .addr_fam = AF_INET, .addr_str = "10.7.7.7",
746*a1e26a70SApple OSS Distributions 		.broad_len = sizeof(struct sockaddr_in), .broad_fam = AF_INET, .broad_str = "10.7.7.255",
747*a1e26a70SApple OSS Distributions 		.mask_len = sizeof(struct sockaddr_in), .mask_fam = AF_INET6, .mask_str = "255.255.0.0",
748*a1e26a70SApple OSS Distributions 		.error = 0
749*a1e26a70SApple OSS Distributions 	},
750*a1e26a70SApple OSS Distributions 	{
751*a1e26a70SApple OSS Distributions 		.description = "ifra address only",
752*a1e26a70SApple OSS Distributions 		.addr_len = sizeof(struct sockaddr_in), .addr_fam = AF_INET, .addr_str = "10.8.8.8",
753*a1e26a70SApple OSS Distributions 		.broad_len = 0, .broad_str = NULL,
754*a1e26a70SApple OSS Distributions 		.mask_len = 0, .mask_str = NULL,
755*a1e26a70SApple OSS Distributions 		.error = 0
756*a1e26a70SApple OSS Distributions 	},
757*a1e26a70SApple OSS Distributions 	{
758*a1e26a70SApple OSS Distributions 		.description = "ifra mask len 1",
759*a1e26a70SApple OSS Distributions 		.addr_len = sizeof(struct sockaddr_in), .addr_fam = AF_INET, .addr_str = "10.9.9.1",
760*a1e26a70SApple OSS Distributions 		.broad_len = 0, .broad_str = NULL,
761*a1e26a70SApple OSS Distributions 		.mask_len = 1, .mask_fam = AF_INET, .mask_str = "255.255.255.0",
762*a1e26a70SApple OSS Distributions 		.error = 0
763*a1e26a70SApple OSS Distributions 	},
764*a1e26a70SApple OSS Distributions 	{
765*a1e26a70SApple OSS Distributions 		.description = "ifra mask len 3",
766*a1e26a70SApple OSS Distributions 		.addr_len = sizeof(struct sockaddr_in), .addr_fam = AF_INET, .addr_str = "10.9.9.3",
767*a1e26a70SApple OSS Distributions 		.broad_len = 0, .broad_str = NULL,
768*a1e26a70SApple OSS Distributions 		.mask_len = 1, .mask_fam = AF_INET, .mask_str = "255.255.255.0",
769*a1e26a70SApple OSS Distributions 		.error = 0
770*a1e26a70SApple OSS Distributions 	},
771*a1e26a70SApple OSS Distributions 	{
772*a1e26a70SApple OSS Distributions 		.description = "ifra mask len 5",
773*a1e26a70SApple OSS Distributions 		.addr_len = sizeof(struct sockaddr_in), .addr_fam = AF_INET, .addr_str = "10.9.9.5",
774*a1e26a70SApple OSS Distributions 		.broad_len = 0, .broad_str = NULL,
775*a1e26a70SApple OSS Distributions 		.mask_len = 1, .mask_fam = AF_INET, .mask_str = "255.255.255.0",
776*a1e26a70SApple OSS Distributions 		.error = 0
777*a1e26a70SApple OSS Distributions 	},
778*a1e26a70SApple OSS Distributions 	{
779*a1e26a70SApple OSS Distributions 		.description = "ifra mask len 7",
780*a1e26a70SApple OSS Distributions 		.addr_len = sizeof(struct sockaddr_in), .addr_fam = AF_INET, .addr_str = "10.9.9.7",
781*a1e26a70SApple OSS Distributions 		.broad_len = 0, .broad_str = NULL,
782*a1e26a70SApple OSS Distributions 		.mask_len = 1, .mask_fam = AF_INET, .mask_str = "255.255.255.0",
783*a1e26a70SApple OSS Distributions 		.error = 0
784*a1e26a70SApple OSS Distributions 	},
785*a1e26a70SApple OSS Distributions 	{
786*a1e26a70SApple OSS Distributions 		.description = "ifra mask len 9",
787*a1e26a70SApple OSS Distributions 		.addr_len = sizeof(struct sockaddr_in), .addr_fam = AF_INET, .addr_str = "10.9.9.9",
788*a1e26a70SApple OSS Distributions 		.broad_len = 0, .broad_str = NULL,
789*a1e26a70SApple OSS Distributions 		.mask_len = 1, .mask_fam = AF_INET, .mask_str = "255.255.255.0",
790*a1e26a70SApple OSS Distributions 		.error = 0
791*a1e26a70SApple OSS Distributions 	},
792*a1e26a70SApple OSS Distributions 	{
793*a1e26a70SApple OSS Distributions 		.description = "ifra mask len 11",
794*a1e26a70SApple OSS Distributions 		.addr_len = sizeof(struct sockaddr_in), .addr_fam = AF_INET, .addr_str = "10.9.9.11",
795*a1e26a70SApple OSS Distributions 		.broad_len = 0, .broad_str = NULL,
796*a1e26a70SApple OSS Distributions 		.mask_len = 1, .mask_fam = AF_INET, .mask_str = "255.255.255.0",
797*a1e26a70SApple OSS Distributions 		.error = 0
798*a1e26a70SApple OSS Distributions 	},
799*a1e26a70SApple OSS Distributions 	{
800*a1e26a70SApple OSS Distributions 		.description = "ifra mask len 13",
801*a1e26a70SApple OSS Distributions 		.addr_len = sizeof(struct sockaddr_in), .addr_fam = AF_INET, .addr_str = "10.9.9.13",
802*a1e26a70SApple OSS Distributions 		.broad_len = 0, .broad_str = NULL,
803*a1e26a70SApple OSS Distributions 		.mask_len = 1, .mask_fam = AF_INET, .mask_str = "255.255.255.0",
804*a1e26a70SApple OSS Distributions 		.error = 0
805*a1e26a70SApple OSS Distributions 	},
806*a1e26a70SApple OSS Distributions 	{
807*a1e26a70SApple OSS Distributions 		.description = NULL,
808*a1e26a70SApple OSS Distributions 		.error = -1
809*a1e26a70SApple OSS Distributions 	}
810*a1e26a70SApple OSS Distributions };
811*a1e26a70SApple OSS Distributions 
812*a1e26a70SApple OSS Distributions T_DECL(sioc_ifra_addr_bounds, "test bound checks on socket address passed to interface ioctls",
813*a1e26a70SApple OSS Distributions     T_META_ASROOT(true), T_META_TAG_VM_PREFERRED)
814*a1e26a70SApple OSS Distributions {
815*a1e26a70SApple OSS Distributions 	int s = -1;
816*a1e26a70SApple OSS Distributions 
817*a1e26a70SApple OSS Distributions 	T_QUIET; T_EXPECT_POSIX_SUCCESS(s = socket(AF_INET, SOCK_DGRAM, 0), "socket");
818*a1e26a70SApple OSS Distributions 
819*a1e26a70SApple OSS Distributions 	char ifname[IFNAMSIZ];
820*a1e26a70SApple OSS Distributions 	strlcpy(ifname, IF_NAME, sizeof(ifname));
821*a1e26a70SApple OSS Distributions 	int error = 0;
822*a1e26a70SApple OSS Distributions 	if ((error = ifnet_create(s, ifname, sizeof(ifname))) != 0) {
823*a1e26a70SApple OSS Distributions 		if (error == EINVAL) {
824*a1e26a70SApple OSS Distributions 			T_SKIP("The system does not support the %s cloning interface", IF_NAME);
825*a1e26a70SApple OSS Distributions 		}
826*a1e26a70SApple OSS Distributions 		T_SKIP("This test failed creating a %s cloning interface", IF_NAME);
827*a1e26a70SApple OSS Distributions 	}
828*a1e26a70SApple OSS Distributions 	T_LOG("created clone interface '%s'", ifname);
829*a1e26a70SApple OSS Distributions 
830*a1e26a70SApple OSS Distributions 	struct ioc_ifra *ioc_ifra;
831*a1e26a70SApple OSS Distributions 
832*a1e26a70SApple OSS Distributions 	for (ioc_ifra = ioc_ifra_list; ioc_ifra->error != -1; ioc_ifra++) {
833*a1e26a70SApple OSS Distributions 		struct in_aliasreq ifra = { 0 };
834*a1e26a70SApple OSS Distributions 		unsigned char pattern;
835*a1e26a70SApple OSS Distributions 		int retval;
836*a1e26a70SApple OSS Distributions 
837*a1e26a70SApple OSS Distributions 		T_LOG("");
838*a1e26a70SApple OSS Distributions 		T_LOG("TEST CASE: %s, ioctl(SIOCAIFADDR, %s)", ioc_ifra->description, ioc_ifra->addr_str != NULL ? ioc_ifra->addr_str : "");
839*a1e26a70SApple OSS Distributions 
840*a1e26a70SApple OSS Distributions 		if (find_unused_pattern_in_rt_if_list(&pattern, PATTERN_SIZE) == false) {
841*a1e26a70SApple OSS Distributions 			T_SKIP("Could not find unused pattern in rt_if_list");
842*a1e26a70SApple OSS Distributions 			return;
843*a1e26a70SApple OSS Distributions 		}
844*a1e26a70SApple OSS Distributions 
845*a1e26a70SApple OSS Distributions 		memset(&ifra, pattern, sizeof(ifra));
846*a1e26a70SApple OSS Distributions 
847*a1e26a70SApple OSS Distributions 		strlcpy(ifra.ifra_name, ifname, sizeof(ifra.ifra_name));
848*a1e26a70SApple OSS Distributions 
849*a1e26a70SApple OSS Distributions 		ifra.ifra_addr.sin_len = ioc_ifra->addr_len;
850*a1e26a70SApple OSS Distributions 		ifra.ifra_addr.sin_family = ioc_ifra->addr_fam;
851*a1e26a70SApple OSS Distributions 		if (ioc_ifra->addr_str != NULL) {
852*a1e26a70SApple OSS Distributions 			ifra.ifra_addr.sin_addr.s_addr = inet_addr(ioc_ifra->addr_str);
853*a1e26a70SApple OSS Distributions 		}
854*a1e26a70SApple OSS Distributions 
855*a1e26a70SApple OSS Distributions 		ifra.ifra_broadaddr.sin_len = ioc_ifra->broad_len;
856*a1e26a70SApple OSS Distributions 		ifra.ifra_broadaddr.sin_family = ioc_ifra->broad_fam;
857*a1e26a70SApple OSS Distributions 		if (ioc_ifra->broad_str != NULL) {
858*a1e26a70SApple OSS Distributions 			ifra.ifra_broadaddr.sin_addr.s_addr = inet_addr(ioc_ifra->broad_str);
859*a1e26a70SApple OSS Distributions 		}
860*a1e26a70SApple OSS Distributions 
861*a1e26a70SApple OSS Distributions 		ifra.ifra_mask.sin_len = ioc_ifra->mask_len;
862*a1e26a70SApple OSS Distributions 		ifra.ifra_mask.sin_family = ioc_ifra->mask_fam;
863*a1e26a70SApple OSS Distributions 		if (ioc_ifra->mask_str != NULL) {
864*a1e26a70SApple OSS Distributions 			ifra.ifra_mask.sin_addr.s_addr = inet_addr(ioc_ifra->mask_str);
865*a1e26a70SApple OSS Distributions 		}
866*a1e26a70SApple OSS Distributions 
867*a1e26a70SApple OSS Distributions 		if (ioc_ifra->error == 0) {
868*a1e26a70SApple OSS Distributions 			T_EXPECT_POSIX_SUCCESS(retval = ioctl(s, SIOCAIFADDR, &ifra), "SIOCAIFADDR retval %d", retval);
869*a1e26a70SApple OSS Distributions 		} else {
870*a1e26a70SApple OSS Distributions 			T_EXPECT_POSIX_FAILURE(retval = ioctl(s, SIOCAIFADDR, &ifra), EINVAL, "SIOCAIFADDR retval %d, %s", retval, strerror(errno));
871*a1e26a70SApple OSS Distributions 		}
872*a1e26a70SApple OSS Distributions 
873*a1e26a70SApple OSS Distributions 		T_EXPECT_EQ(check_rt_if_list_for_pattern("after ioctl SIOCAIFADDR", pattern, PATTERN_SIZE), 0, "pattern should not be found");
874*a1e26a70SApple OSS Distributions 	}
875*a1e26a70SApple OSS Distributions 
876*a1e26a70SApple OSS Distributions 	print_rt_iflist2(__func__);
877*a1e26a70SApple OSS Distributions 
878*a1e26a70SApple OSS Distributions 	(void)ifnet_destroy(s, ifname, true);
879*a1e26a70SApple OSS Distributions 
880*a1e26a70SApple OSS Distributions 	close(s);
881*a1e26a70SApple OSS Distributions }
882*a1e26a70SApple OSS Distributions 
883*a1e26a70SApple OSS Distributions T_DECL(sioc_ifr_dstaddr_leak, "test bound checks on socket address passed to interface ioctls",
884*a1e26a70SApple OSS Distributions     T_META_ASROOT(true), T_META_TAG_VM_PREFERRED)
885*a1e26a70SApple OSS Distributions {
886*a1e26a70SApple OSS Distributions 	int s = -1;
887*a1e26a70SApple OSS Distributions 	struct ifreq ifr = { 0 };
888*a1e26a70SApple OSS Distributions 	unsigned char pattern;
889*a1e26a70SApple OSS Distributions 	struct ifaddrs *ifap = NULL, *ifa;
890*a1e26a70SApple OSS Distributions 	bool found_gif0 = false;
891*a1e26a70SApple OSS Distributions 
892*a1e26a70SApple OSS Distributions 	T_QUIET; T_EXPECT_POSIX_SUCCESS(getifaddrs(&ifap), "getifaddrs");
893*a1e26a70SApple OSS Distributions 	for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
894*a1e26a70SApple OSS Distributions 		if (strcmp(ifa->ifa_name, "gif0") == 0) {
895*a1e26a70SApple OSS Distributions 			found_gif0 = true;
896*a1e26a70SApple OSS Distributions 			break;
897*a1e26a70SApple OSS Distributions 		}
898*a1e26a70SApple OSS Distributions 	}
899*a1e26a70SApple OSS Distributions 	freeifaddrs(ifap);
900*a1e26a70SApple OSS Distributions 	ifap = NULL;
901*a1e26a70SApple OSS Distributions 	if (found_gif0 == false) {
902*a1e26a70SApple OSS Distributions 		T_SKIP("gif0 does not exists");
903*a1e26a70SApple OSS Distributions 	}
904*a1e26a70SApple OSS Distributions 
905*a1e26a70SApple OSS Distributions 	if (find_unused_pattern_in_rt_if_list(&pattern, PATTERN_SIZE) == false) {
906*a1e26a70SApple OSS Distributions 		T_SKIP("Could not find unused pattern");
907*a1e26a70SApple OSS Distributions 		return;
908*a1e26a70SApple OSS Distributions 	}
909*a1e26a70SApple OSS Distributions 
910*a1e26a70SApple OSS Distributions 	T_QUIET; T_EXPECT_POSIX_SUCCESS(s = socket(AF_INET, SOCK_DGRAM, 0), "socket");
911*a1e26a70SApple OSS Distributions 
912*a1e26a70SApple OSS Distributions 	strlcpy(ifr.ifr_name, "gif0", sizeof(ifr.ifr_name));
913*a1e26a70SApple OSS Distributions 	ifr.ifr_dstaddr.sa_family = AF_INET6;
914*a1e26a70SApple OSS Distributions 	ifr.ifr_dstaddr.sa_len = 0xf0;
915*a1e26a70SApple OSS Distributions 	memset(&ifr.ifr_dstaddr.sa_data, pattern, PATTERN_SIZE);
916*a1e26a70SApple OSS Distributions 
917*a1e26a70SApple OSS Distributions 	T_EXPECT_POSIX_SUCCESS(ioctl(s, SIOCSIFDSTADDR, &ifr), "ioctl(SIOCSIFDSTADDR)");
918*a1e26a70SApple OSS Distributions 
919*a1e26a70SApple OSS Distributions 	print_rt_iflist2(__func__);
920*a1e26a70SApple OSS Distributions 
921*a1e26a70SApple OSS Distributions 	close(s);
922*a1e26a70SApple OSS Distributions 
923*a1e26a70SApple OSS Distributions 	T_EXPECT_EQ(check_rt_if_list_for_pattern("AFTER", pattern, PATTERN_SIZE), 0, "pattern should not be found");
924*a1e26a70SApple OSS Distributions }
925*a1e26a70SApple OSS Distributions 
926*a1e26a70SApple OSS Distributions static struct ioc_ifreq ioc_list_config[] = {
927*a1e26a70SApple OSS Distributions 	{ SIOCSIFADDR, sizeof(struct sockaddr_in), AF_INET, "0.0.0.0", EINVAL },
928*a1e26a70SApple OSS Distributions 	{ SIOCSIFADDR, sizeof(struct sockaddr_in), AF_INET, "255.255.255.255", EINVAL },
929*a1e26a70SApple OSS Distributions 	{ SIOCSIFADDR, sizeof(struct sockaddr_in), AF_INET, "238.207.49.91", EINVAL },
930*a1e26a70SApple OSS Distributions 
931*a1e26a70SApple OSS Distributions 	{ SIOCAIFADDR_IN6, sizeof(struct sockaddr_in6), AF_INET6, "::", EINVAL },
932*a1e26a70SApple OSS Distributions 	{ SIOCAIFADDR_IN6, sizeof(struct sockaddr_in6), AF_INET6, "ff33:40:fd25:549c:675b::1", EINVAL },
933*a1e26a70SApple OSS Distributions 	{ SIOCAIFADDR_IN6, sizeof(struct sockaddr_in6), AF_INET6, "::ffff:0a0a:0a0a", EINVAL },
934*a1e26a70SApple OSS Distributions 	{ SIOCAIFADDR_IN6, sizeof(struct sockaddr_in6), AF_INET6, "::0a0a:0a0a", EINVAL },
935*a1e26a70SApple OSS Distributions 
936*a1e26a70SApple OSS Distributions 	{ 0, 0, 0, "", -1 },
937*a1e26a70SApple OSS Distributions };
938*a1e26a70SApple OSS Distributions 
939*a1e26a70SApple OSS Distributions static void
test_sioc_ifr_addr_config_v4(struct ioc_ifreq * ioc_ifreq,int s,const char * ifname)940*a1e26a70SApple OSS Distributions test_sioc_ifr_addr_config_v4(struct ioc_ifreq *ioc_ifreq, int s, const char *ifname)
941*a1e26a70SApple OSS Distributions {
942*a1e26a70SApple OSS Distributions 	struct ifreq ifr = { 0 };
943*a1e26a70SApple OSS Distributions 	struct sockaddr_in *sin;
944*a1e26a70SApple OSS Distributions 
945*a1e26a70SApple OSS Distributions 	T_LOG("");
946*a1e26a70SApple OSS Distributions 	T_LOG("TEST CASE: %s ioctl(%s, sa_len %u, sa_family %u, %s) -> %d", __func__,
947*a1e26a70SApple OSS Distributions 	    ioc_str(ioc_ifreq->ioc_cmd), ioc_ifreq->salen, ioc_ifreq->safamily, ioc_ifreq->sastr, ioc_ifreq->error);
948*a1e26a70SApple OSS Distributions 
949*a1e26a70SApple OSS Distributions 
950*a1e26a70SApple OSS Distributions 	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
951*a1e26a70SApple OSS Distributions 
952*a1e26a70SApple OSS Distributions 	sin = (struct sockaddr_in *)(void *)&ifr.ifr_addr;
953*a1e26a70SApple OSS Distributions 	sin->sin_len = ioc_ifreq->salen;
954*a1e26a70SApple OSS Distributions 	sin->sin_family = ioc_ifreq->safamily;
955*a1e26a70SApple OSS Distributions 	sin->sin_addr.s_addr = inet_addr(ioc_ifreq->sastr);
956*a1e26a70SApple OSS Distributions 
957*a1e26a70SApple OSS Distributions 	int retval;
958*a1e26a70SApple OSS Distributions 	if (ioc_ifreq->error == 0) {
959*a1e26a70SApple OSS Distributions 		T_EXPECT_POSIX_SUCCESS(retval = ioctl(s, ioc_ifreq->ioc_cmd, &ifr),
960*a1e26a70SApple OSS Distributions 		    "%s, %s: retval %d", ioc_str(ioc_ifreq->ioc_cmd), ioc_ifreq->sastr, retval);
961*a1e26a70SApple OSS Distributions 	} else {
962*a1e26a70SApple OSS Distributions 		T_EXPECT_POSIX_FAILURE(retval = ioctl(s, ioc_ifreq->ioc_cmd, &ifr), ioc_ifreq->error,
963*a1e26a70SApple OSS Distributions 		    "%s, %s: retval %d errno %s", ioc_str(ioc_ifreq->ioc_cmd), ioc_ifreq->sastr, retval, strerror(errno));
964*a1e26a70SApple OSS Distributions 	}
965*a1e26a70SApple OSS Distributions 
966*a1e26a70SApple OSS Distributions 	fflush(stdout);
967*a1e26a70SApple OSS Distributions 	fflush(stderr);
968*a1e26a70SApple OSS Distributions }
969*a1e26a70SApple OSS Distributions 
970*a1e26a70SApple OSS Distributions static void
test_sioc_ifr_addr_config_v6(struct ioc_ifreq * ioc_ifreq,int s,const char * ifname)971*a1e26a70SApple OSS Distributions test_sioc_ifr_addr_config_v6(struct ioc_ifreq *ioc_ifreq, int s, const char *ifname)
972*a1e26a70SApple OSS Distributions {
973*a1e26a70SApple OSS Distributions 	struct in6_aliasreq     ifra = {{ 0 }, { 0 }, { 0 }, { 0 }, 0, { 0, 0, ND6_INFINITE_LIFETIME, ND6_INFINITE_LIFETIME }};
974*a1e26a70SApple OSS Distributions 	struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)(void *)&ifra.ifra_addr;
975*a1e26a70SApple OSS Distributions 	struct sockaddr_in6 *mask6 = (struct sockaddr_in6 *)(void *)&ifra.ifra_prefixmask;
976*a1e26a70SApple OSS Distributions 	T_LOG("");
977*a1e26a70SApple OSS Distributions 	T_LOG("TEST CASE: %s ioctl(%s, sa_len %u, sa_family %u, %s) -> %d", __func__,
978*a1e26a70SApple OSS Distributions 	    ioc_str(ioc_ifreq->ioc_cmd), ioc_ifreq->salen, ioc_ifreq->safamily, ioc_ifreq->sastr, ioc_ifreq->error);
979*a1e26a70SApple OSS Distributions 
980*a1e26a70SApple OSS Distributions 	strlcpy(ifra.ifra_name, ifname, sizeof(ifra.ifra_name));
981*a1e26a70SApple OSS Distributions 
982*a1e26a70SApple OSS Distributions 	sin6->sin6_len = ioc_ifreq->salen;
983*a1e26a70SApple OSS Distributions 	sin6->sin6_family = ioc_ifreq->safamily;
984*a1e26a70SApple OSS Distributions 	T_ASSERT_EQ(inet_pton(AF_INET6, ioc_ifreq->sastr, &sin6->sin6_addr), 1, NULL);
985*a1e26a70SApple OSS Distributions 	sin6->sin6_scope_id = if_nametoindex(ifname);
986*a1e26a70SApple OSS Distributions 
987*a1e26a70SApple OSS Distributions 	mask6->sin6_len = ioc_ifreq->salen;
988*a1e26a70SApple OSS Distributions 	mask6->sin6_family = ioc_ifreq->safamily;
989*a1e26a70SApple OSS Distributions 	T_ASSERT_EQ(inet_pton(AF_INET6, "ffff:ffff:ffff:ffff::", &mask6->sin6_addr), 1, NULL);
990*a1e26a70SApple OSS Distributions 
991*a1e26a70SApple OSS Distributions 	ifra.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
992*a1e26a70SApple OSS Distributions 	ifra.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
993*a1e26a70SApple OSS Distributions 
994*a1e26a70SApple OSS Distributions 	int retval;
995*a1e26a70SApple OSS Distributions 	if (ioc_ifreq->error == 0) {
996*a1e26a70SApple OSS Distributions 		T_EXPECT_POSIX_SUCCESS(retval = ioctl(s, ioc_ifreq->ioc_cmd, &ifra),
997*a1e26a70SApple OSS Distributions 		    "%s, %s: retval %d", ioc_str(ioc_ifreq->ioc_cmd), ioc_ifreq->sastr, retval);
998*a1e26a70SApple OSS Distributions 	} else {
999*a1e26a70SApple OSS Distributions 		T_EXPECT_POSIX_FAILURE(retval = ioctl(s, ioc_ifreq->ioc_cmd, &ifra), ioc_ifreq->error,
1000*a1e26a70SApple OSS Distributions 		    "%s, %s: retval %d errno %s", ioc_str(ioc_ifreq->ioc_cmd), ioc_ifreq->sastr, retval, strerror(errno));
1001*a1e26a70SApple OSS Distributions 	}
1002*a1e26a70SApple OSS Distributions 
1003*a1e26a70SApple OSS Distributions 	fflush(stdout);
1004*a1e26a70SApple OSS Distributions 	fflush(stderr);
1005*a1e26a70SApple OSS Distributions }
1006*a1e26a70SApple OSS Distributions 
1007*a1e26a70SApple OSS Distributions 
1008*a1e26a70SApple OSS Distributions T_DECL(sioc_ifr_addr_config, "test failure cases for interface address configuration ioctls",
1009*a1e26a70SApple OSS Distributions     T_META_ASROOT(true), T_META_TAG_VM_PREFERRED)
1010*a1e26a70SApple OSS Distributions {
1011*a1e26a70SApple OSS Distributions 	int s = -1;
1012*a1e26a70SApple OSS Distributions 	int s6 = -1;
1013*a1e26a70SApple OSS Distributions 	char ifname[IFNAMSIZ];
1014*a1e26a70SApple OSS Distributions 
1015*a1e26a70SApple OSS Distributions 	T_LOG("%s", __func__);
1016*a1e26a70SApple OSS Distributions 
1017*a1e26a70SApple OSS Distributions 	T_QUIET; T_EXPECT_POSIX_SUCCESS(s = socket(AF_INET, SOCK_DGRAM, 0), "socket");
1018*a1e26a70SApple OSS Distributions 	T_QUIET; T_EXPECT_POSIX_SUCCESS(s6 = socket(AF_INET6, SOCK_DGRAM, 0), "socket");
1019*a1e26a70SApple OSS Distributions 
1020*a1e26a70SApple OSS Distributions 	strlcpy(ifname, IF_NAME, sizeof(ifname));
1021*a1e26a70SApple OSS Distributions 
1022*a1e26a70SApple OSS Distributions 	int error = 0;
1023*a1e26a70SApple OSS Distributions 	if ((error = ifnet_create(s, ifname, sizeof(ifname))) != 0) {
1024*a1e26a70SApple OSS Distributions 		if (error == EINVAL) {
1025*a1e26a70SApple OSS Distributions 			T_SKIP("The system does not support the %s cloning interface", IF_NAME);
1026*a1e26a70SApple OSS Distributions 		}
1027*a1e26a70SApple OSS Distributions 		T_SKIP("This test failed creating a %s cloning interface", IF_NAME);
1028*a1e26a70SApple OSS Distributions 	}
1029*a1e26a70SApple OSS Distributions 	T_LOG("created clone interface '%s'", ifname);
1030*a1e26a70SApple OSS Distributions 
1031*a1e26a70SApple OSS Distributions 	struct ioc_ifreq *ioc_ifreq;
1032*a1e26a70SApple OSS Distributions 	for (ioc_ifreq = ioc_list_config; ioc_ifreq->error != -1; ioc_ifreq++) {
1033*a1e26a70SApple OSS Distributions 		if (ioc_ifreq->safamily == AF_INET) {
1034*a1e26a70SApple OSS Distributions 			test_sioc_ifr_addr_config_v4(ioc_ifreq, s, ifname);
1035*a1e26a70SApple OSS Distributions 		} else if (ioc_ifreq->safamily == AF_INET6) {
1036*a1e26a70SApple OSS Distributions 			test_sioc_ifr_addr_config_v6(ioc_ifreq, s6, ifname);
1037*a1e26a70SApple OSS Distributions 		}
1038*a1e26a70SApple OSS Distributions 	}
1039*a1e26a70SApple OSS Distributions 	print_rt_iflist2(__func__);
1040*a1e26a70SApple OSS Distributions 	(void)ifnet_destroy(s, ifname, true);
1041*a1e26a70SApple OSS Distributions 
1042*a1e26a70SApple OSS Distributions 	close(s);
1043*a1e26a70SApple OSS Distributions 	close(s6);
1044*a1e26a70SApple OSS Distributions }
1045*a1e26a70SApple OSS Distributions 
1046*a1e26a70SApple OSS Distributions /**
1047*a1e26a70SApple OSS Distributions ** Test SIOCPROTOATTACH, SIOCPROTOATTACH_IN6
1048*a1e26a70SApple OSS Distributions **/
1049*a1e26a70SApple OSS Distributions static int S_socket = -1;
1050*a1e26a70SApple OSS Distributions 
1051*a1e26a70SApple OSS Distributions static int
get_inet_dgram_socket(void)1052*a1e26a70SApple OSS Distributions get_inet_dgram_socket(void)
1053*a1e26a70SApple OSS Distributions {
1054*a1e26a70SApple OSS Distributions 	if (S_socket >= 0) {
1055*a1e26a70SApple OSS Distributions 		return S_socket;
1056*a1e26a70SApple OSS Distributions 	}
1057*a1e26a70SApple OSS Distributions 	S_socket = socket(AF_INET, SOCK_DGRAM, 0);
1058*a1e26a70SApple OSS Distributions 	T_QUIET;
1059*a1e26a70SApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(S_socket, "socket(AF_INET, SOCK_DGRAM, 0)");
1060*a1e26a70SApple OSS Distributions 	return S_socket;
1061*a1e26a70SApple OSS Distributions }
1062*a1e26a70SApple OSS Distributions 
1063*a1e26a70SApple OSS Distributions static void
close_inet_dgram_socket(void)1064*a1e26a70SApple OSS Distributions close_inet_dgram_socket(void)
1065*a1e26a70SApple OSS Distributions {
1066*a1e26a70SApple OSS Distributions 	if (S_socket >= 0) {
1067*a1e26a70SApple OSS Distributions 		close(S_socket);
1068*a1e26a70SApple OSS Distributions 		S_socket = -1;
1069*a1e26a70SApple OSS Distributions 	}
1070*a1e26a70SApple OSS Distributions }
1071*a1e26a70SApple OSS Distributions 
1072*a1e26a70SApple OSS Distributions static int S_socket_6 = -1;
1073*a1e26a70SApple OSS Distributions 
1074*a1e26a70SApple OSS Distributions static int
get_inet6_dgram_socket(void)1075*a1e26a70SApple OSS Distributions get_inet6_dgram_socket(void)
1076*a1e26a70SApple OSS Distributions {
1077*a1e26a70SApple OSS Distributions 	if (S_socket_6 >= 0) {
1078*a1e26a70SApple OSS Distributions 		return S_socket_6;
1079*a1e26a70SApple OSS Distributions 	}
1080*a1e26a70SApple OSS Distributions 	S_socket_6 = socket(AF_INET6, SOCK_DGRAM, 0);
1081*a1e26a70SApple OSS Distributions 	T_QUIET;
1082*a1e26a70SApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(S_socket_6, "socket(AF_INET6, SOCK_DGRAM, 0)");
1083*a1e26a70SApple OSS Distributions 	return S_socket_6;
1084*a1e26a70SApple OSS Distributions }
1085*a1e26a70SApple OSS Distributions 
1086*a1e26a70SApple OSS Distributions static void
close_inet6_dgram_socket(void)1087*a1e26a70SApple OSS Distributions close_inet6_dgram_socket(void)
1088*a1e26a70SApple OSS Distributions {
1089*a1e26a70SApple OSS Distributions 	if (S_socket_6 >= 0) {
1090*a1e26a70SApple OSS Distributions 		close(S_socket_6);
1091*a1e26a70SApple OSS Distributions 		S_socket_6 = -1;
1092*a1e26a70SApple OSS Distributions 	}
1093*a1e26a70SApple OSS Distributions }
1094*a1e26a70SApple OSS Distributions 
1095*a1e26a70SApple OSS Distributions static char ifname[IFNAMSIZ];
1096*a1e26a70SApple OSS Distributions 
1097*a1e26a70SApple OSS Distributions static void
test_proto_attach_cleanup(void)1098*a1e26a70SApple OSS Distributions test_proto_attach_cleanup(void)
1099*a1e26a70SApple OSS Distributions {
1100*a1e26a70SApple OSS Distributions 	if (ifname[0] != '\0') {
1101*a1e26a70SApple OSS Distributions 		int     s;
1102*a1e26a70SApple OSS Distributions 
1103*a1e26a70SApple OSS Distributions 		s = get_inet_dgram_socket();
1104*a1e26a70SApple OSS Distributions 		(void)ifnet_destroy(s, ifname, false);
1105*a1e26a70SApple OSS Distributions 		T_LOG("Destroyed '%s'", ifname);
1106*a1e26a70SApple OSS Distributions 		ifname[0] = '\0';
1107*a1e26a70SApple OSS Distributions 	}
1108*a1e26a70SApple OSS Distributions }
1109*a1e26a70SApple OSS Distributions 
1110*a1e26a70SApple OSS Distributions static void
test_proto_attach_atend(void)1111*a1e26a70SApple OSS Distributions test_proto_attach_atend(void)
1112*a1e26a70SApple OSS Distributions {
1113*a1e26a70SApple OSS Distributions 	test_proto_attach_cleanup();
1114*a1e26a70SApple OSS Distributions 	close_inet_dgram_socket();
1115*a1e26a70SApple OSS Distributions 	close_inet6_dgram_socket();
1116*a1e26a70SApple OSS Distributions }
1117*a1e26a70SApple OSS Distributions 
1118*a1e26a70SApple OSS Distributions static void
test_proto_attach(void)1119*a1e26a70SApple OSS Distributions test_proto_attach(void)
1120*a1e26a70SApple OSS Distributions {
1121*a1e26a70SApple OSS Distributions 	int             error;
1122*a1e26a70SApple OSS Distributions 	struct ifreq    ifr;
1123*a1e26a70SApple OSS Distributions 	int             s;
1124*a1e26a70SApple OSS Distributions 	int             s6;
1125*a1e26a70SApple OSS Distributions 
1126*a1e26a70SApple OSS Distributions 	T_ATEND(test_proto_attach_atend);
1127*a1e26a70SApple OSS Distributions 	s = get_inet_dgram_socket();
1128*a1e26a70SApple OSS Distributions 	strlcpy(ifname, "feth", sizeof(ifname));
1129*a1e26a70SApple OSS Distributions 	error = ifnet_create(s, ifname, sizeof(ifname));
1130*a1e26a70SApple OSS Distributions 	if (error != 0) {
1131*a1e26a70SApple OSS Distributions 		if (error == EINVAL) {
1132*a1e26a70SApple OSS Distributions 			T_SKIP("%s cloning interface not supported", ifname);
1133*a1e26a70SApple OSS Distributions 		}
1134*a1e26a70SApple OSS Distributions 		T_SKIP("%s cloning interface failed", ifname);
1135*a1e26a70SApple OSS Distributions 	}
1136*a1e26a70SApple OSS Distributions 	T_LOG("Created '%s'", ifname);
1137*a1e26a70SApple OSS Distributions 
1138*a1e26a70SApple OSS Distributions 	/* first proto attach should succeed */
1139*a1e26a70SApple OSS Distributions 	bzero(&ifr, sizeof(ifr));
1140*a1e26a70SApple OSS Distributions 	strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1141*a1e26a70SApple OSS Distributions 	error = ioctl(s, SIOCPROTOATTACH, &ifr);
1142*a1e26a70SApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(error, "SIOCPROTOATTACH %s succeeded",
1143*a1e26a70SApple OSS Distributions 	    ifr.ifr_name);
1144*a1e26a70SApple OSS Distributions 
1145*a1e26a70SApple OSS Distributions 	/* second proto attach should fail with EEXIST */
1146*a1e26a70SApple OSS Distributions 	error = ioctl(s, SIOCPROTOATTACH, &ifr);
1147*a1e26a70SApple OSS Distributions 	T_ASSERT_POSIX_FAILURE(error, EEXIST,
1148*a1e26a70SApple OSS Distributions 	    "SIOCPROTOATTACH %s failed as expected",
1149*a1e26a70SApple OSS Distributions 	    ifr.ifr_name);
1150*a1e26a70SApple OSS Distributions 
1151*a1e26a70SApple OSS Distributions 	/* first proto attach should succeed */
1152*a1e26a70SApple OSS Distributions 	s6 = get_inet6_dgram_socket();
1153*a1e26a70SApple OSS Distributions 	bzero(&ifr, sizeof(ifr));
1154*a1e26a70SApple OSS Distributions 	strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1155*a1e26a70SApple OSS Distributions 	error = ioctl(s6, SIOCPROTOATTACH_IN6, &ifr);
1156*a1e26a70SApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(error,
1157*a1e26a70SApple OSS Distributions 	    "SIOCPROTOATTACH_IN6 %s succeeded",
1158*a1e26a70SApple OSS Distributions 	    ifr.ifr_name);
1159*a1e26a70SApple OSS Distributions 
1160*a1e26a70SApple OSS Distributions 	/* second proto attach should fail with EEXIST */
1161*a1e26a70SApple OSS Distributions 	error = ioctl(s6, SIOCPROTOATTACH_IN6, &ifr);
1162*a1e26a70SApple OSS Distributions 	T_ASSERT_POSIX_FAILURE(error, EEXIST,
1163*a1e26a70SApple OSS Distributions 	    "SIOCPROTOATTACH_IN6 %s failed as expected",
1164*a1e26a70SApple OSS Distributions 	    ifr.ifr_name);
1165*a1e26a70SApple OSS Distributions 	test_proto_attach_cleanup();
1166*a1e26a70SApple OSS Distributions }
1167*a1e26a70SApple OSS Distributions 
1168*a1e26a70SApple OSS Distributions T_DECL(sioc_proto_attach, "test protocol attachment",
1169*a1e26a70SApple OSS Distributions     T_META_ASROOT(true), T_META_TAG_VM_PREFERRED)
1170*a1e26a70SApple OSS Distributions {
1171*a1e26a70SApple OSS Distributions 	test_proto_attach();
1172*a1e26a70SApple OSS Distributions }
1173*a1e26a70SApple OSS Distributions 
1174*a1e26a70SApple OSS Distributions /*
1175*a1e26a70SApple OSS Distributions  * The following is only meant to be run from the command line
1176*a1e26a70SApple OSS Distributions  * when one adds a new socket interface ioctl
1177*a1e26a70SApple OSS Distributions  */
1178*a1e26a70SApple OSS Distributions T_DECL(sioc_print_all, "print all socket interface ioctls", T_META_ENABLED(false), T_META_TAG_VM_PREFERRED)
1179*a1e26a70SApple OSS Distributions {
1180*a1e26a70SApple OSS Distributions #define X(a) T_LOG("%-32s 0x%08lx GROUP %3lu BASECMD %3ld LEN %4lu\n", \
1181*a1e26a70SApple OSS Distributions     #a, a, (a & 0x00000ff00) >> 8, a & 0x000000ff, IOCPARM_LEN(a));
1182*a1e26a70SApple OSS Distributions 	SIOC_LIST
1183*a1e26a70SApple OSS Distributions #undef X
1184*a1e26a70SApple OSS Distributions }
1185