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