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