xref: /xnu-11417.101.15/tests/net_test_lib.c (revision e3723e1f17661b24996789d8afc084c0c3303b26)
1*e3723e1fSApple OSS Distributions /*
2*e3723e1fSApple OSS Distributions  * Copyright (c) 2019-2024 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 #include "net_test_lib.h"
30*e3723e1fSApple OSS Distributions #include "inet_transfer.h"
31*e3723e1fSApple OSS Distributions #include "bpflib.h"
32*e3723e1fSApple OSS Distributions #include "in_cksum.h"
33*e3723e1fSApple OSS Distributions #include <net/if_fake_var.h>
34*e3723e1fSApple OSS Distributions #include <net/if_vlan_var.h>
35*e3723e1fSApple OSS Distributions #include <net/if_bridgevar.h>
36*e3723e1fSApple OSS Distributions 
37*e3723e1fSApple OSS Distributions #define RTM_BUFLEN (sizeof(struct rt_msghdr) + 6 * SOCK_MAXADDRLEN)
38*e3723e1fSApple OSS Distributions 
39*e3723e1fSApple OSS Distributions #define ROUNDUP(a) \
40*e3723e1fSApple OSS Distributions ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
41*e3723e1fSApple OSS Distributions 
42*e3723e1fSApple OSS Distributions bool G_debug;
43*e3723e1fSApple OSS Distributions 
44*e3723e1fSApple OSS Distributions struct in_addr inet_class_c_subnet_mask = {
45*e3723e1fSApple OSS Distributions 	.s_addr = htonl(IN_CLASSC_NET)
46*e3723e1fSApple OSS Distributions };
47*e3723e1fSApple OSS Distributions 
48*e3723e1fSApple OSS Distributions ether_addr_t ether_broadcast = {
49*e3723e1fSApple OSS Distributions 	{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }
50*e3723e1fSApple OSS Distributions };
51*e3723e1fSApple OSS Distributions 
52*e3723e1fSApple OSS Distributions /*
53*e3723e1fSApple OSS Distributions  * local utility functions
54*e3723e1fSApple OSS Distributions  */
55*e3723e1fSApple OSS Distributions static void
siocll_start(int s,const char * ifname)56*e3723e1fSApple OSS Distributions siocll_start(int s, const char * ifname)
57*e3723e1fSApple OSS Distributions {
58*e3723e1fSApple OSS Distributions 	struct in6_aliasreq     ifra_in6;
59*e3723e1fSApple OSS Distributions 	int                     result;
60*e3723e1fSApple OSS Distributions 
61*e3723e1fSApple OSS Distributions 	bzero(&ifra_in6, sizeof(ifra_in6));
62*e3723e1fSApple OSS Distributions 	strncpy(ifra_in6.ifra_name, ifname, sizeof(ifra_in6.ifra_name));
63*e3723e1fSApple OSS Distributions 	result = ioctl(s, SIOCLL_START, &ifra_in6);
64*e3723e1fSApple OSS Distributions 	T_QUIET;
65*e3723e1fSApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(result, "SIOCLL_START %s", ifname);
66*e3723e1fSApple OSS Distributions 	return;
67*e3723e1fSApple OSS Distributions }
68*e3723e1fSApple OSS Distributions 
69*e3723e1fSApple OSS Distributions static void
nd_flags_set(int s,const char * if_name,uint32_t set_flags,uint32_t clear_flags)70*e3723e1fSApple OSS Distributions nd_flags_set(int s, const char * if_name,
71*e3723e1fSApple OSS Distributions     uint32_t set_flags, uint32_t clear_flags)
72*e3723e1fSApple OSS Distributions {
73*e3723e1fSApple OSS Distributions 	uint32_t                new_flags;
74*e3723e1fSApple OSS Distributions 	struct in6_ndireq       nd;
75*e3723e1fSApple OSS Distributions 	int                     result;
76*e3723e1fSApple OSS Distributions 
77*e3723e1fSApple OSS Distributions 	bzero(&nd, sizeof(nd));
78*e3723e1fSApple OSS Distributions 	strncpy(nd.ifname, if_name, sizeof(nd.ifname));
79*e3723e1fSApple OSS Distributions 	result = ioctl(s, SIOCGIFINFO_IN6, &nd);
80*e3723e1fSApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(result, "SIOCGIFINFO_IN6(%s)", if_name);
81*e3723e1fSApple OSS Distributions 	new_flags = nd.ndi.flags;
82*e3723e1fSApple OSS Distributions 	if (set_flags) {
83*e3723e1fSApple OSS Distributions 		new_flags |= set_flags;
84*e3723e1fSApple OSS Distributions 	}
85*e3723e1fSApple OSS Distributions 	if (clear_flags) {
86*e3723e1fSApple OSS Distributions 		new_flags &= ~clear_flags;
87*e3723e1fSApple OSS Distributions 	}
88*e3723e1fSApple OSS Distributions 	if (new_flags != nd.ndi.flags) {
89*e3723e1fSApple OSS Distributions 		nd.ndi.flags = new_flags;
90*e3723e1fSApple OSS Distributions 		result = ioctl(s, SIOCSIFINFO_FLAGS, (caddr_t)&nd);
91*e3723e1fSApple OSS Distributions 		T_ASSERT_POSIX_SUCCESS(result,
92*e3723e1fSApple OSS Distributions 		    "SIOCSIFINFO_FLAGS(%s) 0x%x",
93*e3723e1fSApple OSS Distributions 		    if_name, nd.ndi.flags);
94*e3723e1fSApple OSS Distributions 	}
95*e3723e1fSApple OSS Distributions 	return;
96*e3723e1fSApple OSS Distributions }
97*e3723e1fSApple OSS Distributions 
98*e3723e1fSApple OSS Distributions 
99*e3723e1fSApple OSS Distributions static void
siocprotoattach_in6(int s,const char * name)100*e3723e1fSApple OSS Distributions siocprotoattach_in6(int s, const char * name)
101*e3723e1fSApple OSS Distributions {
102*e3723e1fSApple OSS Distributions 	struct in6_aliasreq ifra;
103*e3723e1fSApple OSS Distributions 	int                 result;
104*e3723e1fSApple OSS Distributions 
105*e3723e1fSApple OSS Distributions 	bzero(&ifra, sizeof(ifra));
106*e3723e1fSApple OSS Distributions 	strncpy(ifra.ifra_name, name, sizeof(ifra.ifra_name));
107*e3723e1fSApple OSS Distributions 	result = ioctl(s, SIOCPROTOATTACH_IN6, &ifra);
108*e3723e1fSApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(result, "SIOCPROTOATTACH_IN6(%s)", name);
109*e3723e1fSApple OSS Distributions 	return;
110*e3723e1fSApple OSS Distributions }
111*e3723e1fSApple OSS Distributions 
112*e3723e1fSApple OSS Distributions static void
siocaifaddr(int s,char * ifname,struct in_addr addr,struct in_addr mask)113*e3723e1fSApple OSS Distributions siocaifaddr(int s, char *ifname, struct in_addr addr, struct in_addr mask)
114*e3723e1fSApple OSS Distributions {
115*e3723e1fSApple OSS Distributions 	struct ifaliasreq       ifra;
116*e3723e1fSApple OSS Distributions 	char                    ntopbuf_ip[INET_ADDRSTRLEN];
117*e3723e1fSApple OSS Distributions 	char                    ntopbuf_mask[INET_ADDRSTRLEN];
118*e3723e1fSApple OSS Distributions 	int                     ret;
119*e3723e1fSApple OSS Distributions 	struct sockaddr_in *    sin;
120*e3723e1fSApple OSS Distributions 
121*e3723e1fSApple OSS Distributions 	bzero(&ifra, sizeof(ifra));
122*e3723e1fSApple OSS Distributions 	strncpy(ifra.ifra_name, ifname, sizeof(ifra.ifra_name));
123*e3723e1fSApple OSS Distributions 
124*e3723e1fSApple OSS Distributions 	sin = (struct sockaddr_in *)(void *)&ifra.ifra_addr;
125*e3723e1fSApple OSS Distributions 	sin->sin_len = sizeof(*sin);
126*e3723e1fSApple OSS Distributions 	sin->sin_family = AF_INET;
127*e3723e1fSApple OSS Distributions 	sin->sin_addr = addr;
128*e3723e1fSApple OSS Distributions 
129*e3723e1fSApple OSS Distributions 	sin = (struct sockaddr_in *)(void *)&ifra.ifra_mask;
130*e3723e1fSApple OSS Distributions 	sin->sin_len = sizeof(*sin);
131*e3723e1fSApple OSS Distributions 	sin->sin_family = AF_INET;
132*e3723e1fSApple OSS Distributions 	sin->sin_addr = mask;
133*e3723e1fSApple OSS Distributions 
134*e3723e1fSApple OSS Distributions 	ret = ioctl(s, SIOCAIFADDR, &ifra);
135*e3723e1fSApple OSS Distributions 	inet_ntop(AF_INET, &addr, ntopbuf_ip, sizeof(ntopbuf_ip));
136*e3723e1fSApple OSS Distributions 	inet_ntop(AF_INET, &sin->sin_addr, ntopbuf_mask, sizeof(ntopbuf_mask));
137*e3723e1fSApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(ret, "SIOCAIFADDR %s %s %s",
138*e3723e1fSApple OSS Distributions 	    ifname, ntopbuf_ip, ntopbuf_mask);
139*e3723e1fSApple OSS Distributions 	return;
140*e3723e1fSApple OSS Distributions }
141*e3723e1fSApple OSS Distributions 
142*e3723e1fSApple OSS Distributions 
143*e3723e1fSApple OSS Distributions /*
144*e3723e1fSApple OSS Distributions  * utility functions
145*e3723e1fSApple OSS Distributions  */
146*e3723e1fSApple OSS Distributions 
147*e3723e1fSApple OSS Distributions #define NO_SOCKET       (-1)
148*e3723e1fSApple OSS Distributions 
149*e3723e1fSApple OSS Distributions static int
_dgram_socket_get(int * sock_p,int af)150*e3723e1fSApple OSS Distributions _dgram_socket_get(int * sock_p, int af)
151*e3723e1fSApple OSS Distributions {
152*e3723e1fSApple OSS Distributions 	int     sock = *sock_p;
153*e3723e1fSApple OSS Distributions 
154*e3723e1fSApple OSS Distributions 	if (sock != NO_SOCKET) {
155*e3723e1fSApple OSS Distributions 		goto done;
156*e3723e1fSApple OSS Distributions 	}
157*e3723e1fSApple OSS Distributions 	sock = *sock_p = socket(af, SOCK_DGRAM, 0);
158*e3723e1fSApple OSS Distributions 	T_QUIET;
159*e3723e1fSApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(sock,
160*e3723e1fSApple OSS Distributions 	    "socket(SOCK_DGRAM, %s, 0)",
161*e3723e1fSApple OSS Distributions 	    af == AF_INET ? "AF_INET" : "AF_INET6");
162*e3723e1fSApple OSS Distributions done:
163*e3723e1fSApple OSS Distributions 	return sock;
164*e3723e1fSApple OSS Distributions }
165*e3723e1fSApple OSS Distributions 
166*e3723e1fSApple OSS Distributions static void
_socket_close(int * sock_p)167*e3723e1fSApple OSS Distributions _socket_close(int * sock_p)
168*e3723e1fSApple OSS Distributions {
169*e3723e1fSApple OSS Distributions 	int sock = *sock_p;
170*e3723e1fSApple OSS Distributions 
171*e3723e1fSApple OSS Distributions 	if (sock != NO_SOCKET) {
172*e3723e1fSApple OSS Distributions 		close(sock);
173*e3723e1fSApple OSS Distributions 		*sock_p = NO_SOCKET;
174*e3723e1fSApple OSS Distributions 	}
175*e3723e1fSApple OSS Distributions }
176*e3723e1fSApple OSS Distributions 
177*e3723e1fSApple OSS Distributions static int inet_dgram_socket = NO_SOCKET;
178*e3723e1fSApple OSS Distributions 
179*e3723e1fSApple OSS Distributions int
inet_dgram_socket_get(void)180*e3723e1fSApple OSS Distributions inet_dgram_socket_get(void)
181*e3723e1fSApple OSS Distributions {
182*e3723e1fSApple OSS Distributions 	return _dgram_socket_get(&inet_dgram_socket, AF_INET);
183*e3723e1fSApple OSS Distributions }
184*e3723e1fSApple OSS Distributions 
185*e3723e1fSApple OSS Distributions void
inet_dgram_socket_close(void)186*e3723e1fSApple OSS Distributions inet_dgram_socket_close(void)
187*e3723e1fSApple OSS Distributions {
188*e3723e1fSApple OSS Distributions 	_socket_close(&inet_dgram_socket);
189*e3723e1fSApple OSS Distributions }
190*e3723e1fSApple OSS Distributions 
191*e3723e1fSApple OSS Distributions 
192*e3723e1fSApple OSS Distributions static int inet6_dgram_socket = NO_SOCKET;
193*e3723e1fSApple OSS Distributions 
194*e3723e1fSApple OSS Distributions int
inet6_dgram_socket_get(void)195*e3723e1fSApple OSS Distributions inet6_dgram_socket_get(void)
196*e3723e1fSApple OSS Distributions {
197*e3723e1fSApple OSS Distributions 	return _dgram_socket_get(&inet6_dgram_socket, AF_INET6);
198*e3723e1fSApple OSS Distributions }
199*e3723e1fSApple OSS Distributions 
200*e3723e1fSApple OSS Distributions void
inet6_dgram_socket_close(void)201*e3723e1fSApple OSS Distributions inet6_dgram_socket_close(void)
202*e3723e1fSApple OSS Distributions {
203*e3723e1fSApple OSS Distributions 	_socket_close(&inet6_dgram_socket);
204*e3723e1fSApple OSS Distributions }
205*e3723e1fSApple OSS Distributions 
206*e3723e1fSApple OSS Distributions u_int
ethernet_udp4_frame_populate(void * buf,size_t buf_len,const ether_addr_t * src,struct in_addr src_ip,uint16_t src_port,const ether_addr_t * dst,struct in_addr dst_ip,uint16_t dst_port,const void * data,u_int data_len)207*e3723e1fSApple OSS Distributions ethernet_udp4_frame_populate(void * buf, size_t buf_len,
208*e3723e1fSApple OSS Distributions     const ether_addr_t * src,
209*e3723e1fSApple OSS Distributions     struct in_addr src_ip,
210*e3723e1fSApple OSS Distributions     uint16_t src_port,
211*e3723e1fSApple OSS Distributions     const ether_addr_t * dst,
212*e3723e1fSApple OSS Distributions     struct in_addr dst_ip,
213*e3723e1fSApple OSS Distributions     uint16_t dst_port,
214*e3723e1fSApple OSS Distributions     const void * data, u_int data_len)
215*e3723e1fSApple OSS Distributions {
216*e3723e1fSApple OSS Distributions 	ether_header_t *        eh_p;
217*e3723e1fSApple OSS Distributions 	u_int                   frame_length;
218*e3723e1fSApple OSS Distributions 	static int              ip_id;
219*e3723e1fSApple OSS Distributions 	ip_udp_header_t *       ip_udp;
220*e3723e1fSApple OSS Distributions 	char *                  payload;
221*e3723e1fSApple OSS Distributions 	udp_pseudo_hdr_t *      udp_pseudo;
222*e3723e1fSApple OSS Distributions 
223*e3723e1fSApple OSS Distributions 	frame_length = (u_int)(sizeof(*eh_p) + sizeof(*ip_udp)) + data_len;
224*e3723e1fSApple OSS Distributions 	if (buf_len < frame_length) {
225*e3723e1fSApple OSS Distributions 		return 0;
226*e3723e1fSApple OSS Distributions 	}
227*e3723e1fSApple OSS Distributions 
228*e3723e1fSApple OSS Distributions 	/* determine frame offsets */
229*e3723e1fSApple OSS Distributions 	eh_p = (ether_header_t *)buf;
230*e3723e1fSApple OSS Distributions 	ip_udp = (ip_udp_header_t *)(void *)(eh_p + 1);
231*e3723e1fSApple OSS Distributions 	udp_pseudo = (udp_pseudo_hdr_t *)(void *)
232*e3723e1fSApple OSS Distributions 	    (((char *)&ip_udp->udp) - sizeof(*udp_pseudo));
233*e3723e1fSApple OSS Distributions 	payload = (char *)(eh_p + 1) + sizeof(*ip_udp);
234*e3723e1fSApple OSS Distributions 
235*e3723e1fSApple OSS Distributions 	/* ethernet_header */
236*e3723e1fSApple OSS Distributions 	bcopy(src, eh_p->ether_shost, ETHER_ADDR_LEN);
237*e3723e1fSApple OSS Distributions 	bcopy(dst, eh_p->ether_dhost, ETHER_ADDR_LEN);
238*e3723e1fSApple OSS Distributions 	eh_p->ether_type = htons(ETHERTYPE_IP);
239*e3723e1fSApple OSS Distributions 
240*e3723e1fSApple OSS Distributions 	/* copy the data */
241*e3723e1fSApple OSS Distributions 	bcopy(data, payload, data_len);
242*e3723e1fSApple OSS Distributions 
243*e3723e1fSApple OSS Distributions 	/* fill in UDP pseudo header (gets overwritten by IP header below) */
244*e3723e1fSApple OSS Distributions 	bcopy(&src_ip, &udp_pseudo->src_ip, sizeof(src_ip));
245*e3723e1fSApple OSS Distributions 	bcopy(&dst_ip, &udp_pseudo->dst_ip, sizeof(dst_ip));
246*e3723e1fSApple OSS Distributions 	udp_pseudo->zero = 0;
247*e3723e1fSApple OSS Distributions 	udp_pseudo->proto = IPPROTO_UDP;
248*e3723e1fSApple OSS Distributions 	udp_pseudo->length = htons(sizeof(ip_udp->udp) + data_len);
249*e3723e1fSApple OSS Distributions 
250*e3723e1fSApple OSS Distributions 	/* fill in UDP header */
251*e3723e1fSApple OSS Distributions 	ip_udp->udp.uh_sport = htons(src_port);
252*e3723e1fSApple OSS Distributions 	ip_udp->udp.uh_dport = htons(dst_port);
253*e3723e1fSApple OSS Distributions 	ip_udp->udp.uh_ulen = htons(sizeof(ip_udp->udp) + data_len);
254*e3723e1fSApple OSS Distributions 	ip_udp->udp.uh_sum = 0;
255*e3723e1fSApple OSS Distributions 	ip_udp->udp.uh_sum = in_cksum(udp_pseudo, (int)(sizeof(*udp_pseudo)
256*e3723e1fSApple OSS Distributions 	    + sizeof(ip_udp->udp) + data_len));
257*e3723e1fSApple OSS Distributions 
258*e3723e1fSApple OSS Distributions 	/* fill in IP header */
259*e3723e1fSApple OSS Distributions 	bzero(ip_udp, sizeof(ip_udp->ip));
260*e3723e1fSApple OSS Distributions 	ip_udp->ip.ip_v = IPVERSION;
261*e3723e1fSApple OSS Distributions 	ip_udp->ip.ip_hl = sizeof(struct ip) >> 2;
262*e3723e1fSApple OSS Distributions 	ip_udp->ip.ip_ttl = MAXTTL;
263*e3723e1fSApple OSS Distributions 	ip_udp->ip.ip_p = IPPROTO_UDP;
264*e3723e1fSApple OSS Distributions 	bcopy(&src_ip, &ip_udp->ip.ip_src, sizeof(src_ip));
265*e3723e1fSApple OSS Distributions 	bcopy(&dst_ip, &ip_udp->ip.ip_dst, sizeof(dst_ip));
266*e3723e1fSApple OSS Distributions 	ip_udp->ip.ip_len = htons(sizeof(*ip_udp) + data_len);
267*e3723e1fSApple OSS Distributions 	ip_udp->ip.ip_id = htons(ip_id++);
268*e3723e1fSApple OSS Distributions 
269*e3723e1fSApple OSS Distributions 	/* compute the IP checksum */
270*e3723e1fSApple OSS Distributions 	ip_udp->ip.ip_sum = 0; /* needs to be zero for checksum */
271*e3723e1fSApple OSS Distributions 	ip_udp->ip.ip_sum = in_cksum(&ip_udp->ip, sizeof(ip_udp->ip));
272*e3723e1fSApple OSS Distributions 
273*e3723e1fSApple OSS Distributions 	return frame_length;
274*e3723e1fSApple OSS Distributions }
275*e3723e1fSApple OSS Distributions 
276*e3723e1fSApple OSS Distributions u_int
ethernet_udp6_frame_populate(void * buf,size_t buf_len,const ether_addr_t * src,struct in6_addr * src_ip,uint16_t src_port,const ether_addr_t * dst,struct in6_addr * dst_ip,uint16_t dst_port,const void * data,u_int data_len)277*e3723e1fSApple OSS Distributions ethernet_udp6_frame_populate(void * buf, size_t buf_len,
278*e3723e1fSApple OSS Distributions     const ether_addr_t * src,
279*e3723e1fSApple OSS Distributions     struct in6_addr *src_ip,
280*e3723e1fSApple OSS Distributions     uint16_t src_port,
281*e3723e1fSApple OSS Distributions     const ether_addr_t * dst,
282*e3723e1fSApple OSS Distributions     struct in6_addr * dst_ip,
283*e3723e1fSApple OSS Distributions     uint16_t dst_port,
284*e3723e1fSApple OSS Distributions     const void * data, u_int data_len)
285*e3723e1fSApple OSS Distributions {
286*e3723e1fSApple OSS Distributions 	ether_header_t *        eh_p;
287*e3723e1fSApple OSS Distributions 	u_int                   frame_length;
288*e3723e1fSApple OSS Distributions 	ip6_udp_header_t *      ip6_udp;
289*e3723e1fSApple OSS Distributions 	char *                  payload;
290*e3723e1fSApple OSS Distributions 	udp6_pseudo_hdr_t *     udp6_pseudo;
291*e3723e1fSApple OSS Distributions 
292*e3723e1fSApple OSS Distributions 	frame_length = (u_int)(sizeof(*eh_p) + sizeof(*ip6_udp)) + data_len;
293*e3723e1fSApple OSS Distributions 	if (buf_len < frame_length) {
294*e3723e1fSApple OSS Distributions 		return 0;
295*e3723e1fSApple OSS Distributions 	}
296*e3723e1fSApple OSS Distributions 
297*e3723e1fSApple OSS Distributions 	/* determine frame offsets */
298*e3723e1fSApple OSS Distributions 	eh_p = (ether_header_t *)buf;
299*e3723e1fSApple OSS Distributions 	ip6_udp = (ip6_udp_header_t *)(void *)(eh_p + 1);
300*e3723e1fSApple OSS Distributions 	udp6_pseudo = (udp6_pseudo_hdr_t *)(void *)
301*e3723e1fSApple OSS Distributions 	    (((char *)&ip6_udp->udp) - sizeof(*udp6_pseudo));
302*e3723e1fSApple OSS Distributions 	payload = (char *)(eh_p + 1) + sizeof(*ip6_udp);
303*e3723e1fSApple OSS Distributions 
304*e3723e1fSApple OSS Distributions 	/* ethernet_header */
305*e3723e1fSApple OSS Distributions 	bcopy(src, eh_p->ether_shost, ETHER_ADDR_LEN);
306*e3723e1fSApple OSS Distributions 	bcopy(dst, eh_p->ether_dhost, ETHER_ADDR_LEN);
307*e3723e1fSApple OSS Distributions 	eh_p->ether_type = htons(ETHERTYPE_IPV6);
308*e3723e1fSApple OSS Distributions 
309*e3723e1fSApple OSS Distributions 	/* copy the data */
310*e3723e1fSApple OSS Distributions 	bcopy(data, payload, data_len);
311*e3723e1fSApple OSS Distributions 
312*e3723e1fSApple OSS Distributions 	/* fill in UDP pseudo header (gets overwritten by IP header below) */
313*e3723e1fSApple OSS Distributions 	bcopy(src_ip, &udp6_pseudo->src_ip, sizeof(*src_ip));
314*e3723e1fSApple OSS Distributions 	bcopy(dst_ip, &udp6_pseudo->dst_ip, sizeof(*dst_ip));
315*e3723e1fSApple OSS Distributions 	udp6_pseudo->zero = 0;
316*e3723e1fSApple OSS Distributions 	udp6_pseudo->proto = IPPROTO_UDP;
317*e3723e1fSApple OSS Distributions 	udp6_pseudo->length = htons(sizeof(ip6_udp->udp) + data_len);
318*e3723e1fSApple OSS Distributions 
319*e3723e1fSApple OSS Distributions 	/* fill in UDP header */
320*e3723e1fSApple OSS Distributions 	ip6_udp->udp.uh_sport = htons(src_port);
321*e3723e1fSApple OSS Distributions 	ip6_udp->udp.uh_dport = htons(dst_port);
322*e3723e1fSApple OSS Distributions 	ip6_udp->udp.uh_ulen = htons(sizeof(ip6_udp->udp) + data_len);
323*e3723e1fSApple OSS Distributions 	ip6_udp->udp.uh_sum = 0;
324*e3723e1fSApple OSS Distributions 	ip6_udp->udp.uh_sum = in_cksum(udp6_pseudo, (int)(sizeof(*udp6_pseudo)
325*e3723e1fSApple OSS Distributions 	    + sizeof(ip6_udp->udp) + data_len));
326*e3723e1fSApple OSS Distributions 
327*e3723e1fSApple OSS Distributions 	/* fill in IP header */
328*e3723e1fSApple OSS Distributions 	bzero(&ip6_udp->ip6, sizeof(ip6_udp->ip6));
329*e3723e1fSApple OSS Distributions 	ip6_udp->ip6.ip6_vfc = IPV6_VERSION;
330*e3723e1fSApple OSS Distributions 	ip6_udp->ip6.ip6_nxt = IPPROTO_UDP;
331*e3723e1fSApple OSS Distributions 	bcopy(src_ip, &ip6_udp->ip6.ip6_src, sizeof(*src_ip));
332*e3723e1fSApple OSS Distributions 	bcopy(dst_ip, &ip6_udp->ip6.ip6_dst, sizeof(*dst_ip));
333*e3723e1fSApple OSS Distributions 	ip6_udp->ip6.ip6_plen = htons(sizeof(struct udphdr) + data_len);
334*e3723e1fSApple OSS Distributions 	/* ip6_udp->ip6.ip6_flow = ? */
335*e3723e1fSApple OSS Distributions 	return frame_length;
336*e3723e1fSApple OSS Distributions }
337*e3723e1fSApple OSS Distributions 
338*e3723e1fSApple OSS Distributions /**
339*e3723e1fSApple OSS Distributions ** interface management
340*e3723e1fSApple OSS Distributions **/
341*e3723e1fSApple OSS Distributions 
342*e3723e1fSApple OSS Distributions void
ifnet_get_lladdr(const char * ifname,ether_addr_t * eaddr)343*e3723e1fSApple OSS Distributions ifnet_get_lladdr(const char * ifname, ether_addr_t * eaddr)
344*e3723e1fSApple OSS Distributions {
345*e3723e1fSApple OSS Distributions 	int err;
346*e3723e1fSApple OSS Distributions 	struct ifreq ifr;
347*e3723e1fSApple OSS Distributions 	int s = inet_dgram_socket_get();
348*e3723e1fSApple OSS Distributions 
349*e3723e1fSApple OSS Distributions 	bzero(&ifr, sizeof(ifr));
350*e3723e1fSApple OSS Distributions 	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
351*e3723e1fSApple OSS Distributions 	ifr.ifr_addr.sa_family = AF_LINK;
352*e3723e1fSApple OSS Distributions 	ifr.ifr_addr.sa_len = ETHER_ADDR_LEN;
353*e3723e1fSApple OSS Distributions 	err = ioctl(s, SIOCGIFLLADDR, &ifr);
354*e3723e1fSApple OSS Distributions 	T_QUIET;
355*e3723e1fSApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(err, "SIOCGIFLLADDR %s", ifname);
356*e3723e1fSApple OSS Distributions 	bcopy(ifr.ifr_addr.sa_data, eaddr->octet, ETHER_ADDR_LEN);
357*e3723e1fSApple OSS Distributions 	return;
358*e3723e1fSApple OSS Distributions }
359*e3723e1fSApple OSS Distributions 
360*e3723e1fSApple OSS Distributions int
ifnet_set_lladdr(const char * ifname,ether_addr_t * eaddr)361*e3723e1fSApple OSS Distributions ifnet_set_lladdr(const char * ifname, ether_addr_t * eaddr)
362*e3723e1fSApple OSS Distributions {
363*e3723e1fSApple OSS Distributions 	int err;
364*e3723e1fSApple OSS Distributions 	int this_errno = 0;
365*e3723e1fSApple OSS Distributions 	struct ifreq ifr;
366*e3723e1fSApple OSS Distributions 	int s = inet_dgram_socket_get();
367*e3723e1fSApple OSS Distributions 
368*e3723e1fSApple OSS Distributions 	bzero(&ifr, sizeof(ifr));
369*e3723e1fSApple OSS Distributions 	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
370*e3723e1fSApple OSS Distributions 	ifr.ifr_addr.sa_family = AF_LINK;
371*e3723e1fSApple OSS Distributions 	ifr.ifr_addr.sa_len = ETHER_ADDR_LEN;
372*e3723e1fSApple OSS Distributions 	bcopy(eaddr->octet, ifr.ifr_addr.sa_data, ETHER_ADDR_LEN);
373*e3723e1fSApple OSS Distributions 	err = ioctl(s, SIOCSIFLLADDR, &ifr);
374*e3723e1fSApple OSS Distributions 	if (err != 0) {
375*e3723e1fSApple OSS Distributions 		this_errno = errno;
376*e3723e1fSApple OSS Distributions 		T_LOG("SIOCSIFLLADDR %s %s (%d)", ifname,
377*e3723e1fSApple OSS Distributions 		    strerror(this_errno), this_errno);
378*e3723e1fSApple OSS Distributions 	} else {
379*e3723e1fSApple OSS Distributions 		T_LOG("SIOCSIFLLADDR %s success", ifname);
380*e3723e1fSApple OSS Distributions 	}
381*e3723e1fSApple OSS Distributions 	return err;
382*e3723e1fSApple OSS Distributions }
383*e3723e1fSApple OSS Distributions 
384*e3723e1fSApple OSS Distributions 
385*e3723e1fSApple OSS Distributions void
ifnet_attach_ip(char * name)386*e3723e1fSApple OSS Distributions ifnet_attach_ip(char * name)
387*e3723e1fSApple OSS Distributions {
388*e3723e1fSApple OSS Distributions 	int             err;
389*e3723e1fSApple OSS Distributions 	struct ifreq    ifr;
390*e3723e1fSApple OSS Distributions 	int             s = inet_dgram_socket_get();
391*e3723e1fSApple OSS Distributions 
392*e3723e1fSApple OSS Distributions 	bzero(&ifr, sizeof(ifr));
393*e3723e1fSApple OSS Distributions 	strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
394*e3723e1fSApple OSS Distributions 	err = ioctl(s, SIOCPROTOATTACH, &ifr);
395*e3723e1fSApple OSS Distributions 	T_QUIET;
396*e3723e1fSApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(err, "SIOCPROTOATTACH %s", ifr.ifr_name);
397*e3723e1fSApple OSS Distributions 	return;
398*e3723e1fSApple OSS Distributions }
399*e3723e1fSApple OSS Distributions 
400*e3723e1fSApple OSS Distributions void
ifnet_start_ipv6(const char * ifname)401*e3723e1fSApple OSS Distributions ifnet_start_ipv6(const char * ifname)
402*e3723e1fSApple OSS Distributions {
403*e3723e1fSApple OSS Distributions 	int             s6 = inet6_dgram_socket_get();
404*e3723e1fSApple OSS Distributions 
405*e3723e1fSApple OSS Distributions 	/* attach IPv6 */
406*e3723e1fSApple OSS Distributions 	siocprotoattach_in6(s6, ifname);
407*e3723e1fSApple OSS Distributions 
408*e3723e1fSApple OSS Distributions 	/* disable DAD to avoid 1 second delay (rdar://problem/73270401) */
409*e3723e1fSApple OSS Distributions 	nd_flags_set(s6, ifname, 0, ND6_IFF_DAD);
410*e3723e1fSApple OSS Distributions 
411*e3723e1fSApple OSS Distributions 	/* start IPv6LL */
412*e3723e1fSApple OSS Distributions 	siocll_start(s6, ifname);
413*e3723e1fSApple OSS Distributions 
414*e3723e1fSApple OSS Distributions 	return;
415*e3723e1fSApple OSS Distributions }
416*e3723e1fSApple OSS Distributions 
417*e3723e1fSApple OSS Distributions int
ifnet_destroy(const char * ifname,bool fail_on_error)418*e3723e1fSApple OSS Distributions ifnet_destroy(const char * ifname, bool fail_on_error)
419*e3723e1fSApple OSS Distributions {
420*e3723e1fSApple OSS Distributions 	int             err;
421*e3723e1fSApple OSS Distributions 	struct ifreq    ifr;
422*e3723e1fSApple OSS Distributions 	int             s = inet_dgram_socket_get();
423*e3723e1fSApple OSS Distributions 
424*e3723e1fSApple OSS Distributions 	bzero(&ifr, sizeof(ifr));
425*e3723e1fSApple OSS Distributions 	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
426*e3723e1fSApple OSS Distributions 	err = ioctl(s, SIOCIFDESTROY, &ifr);
427*e3723e1fSApple OSS Distributions 	if (fail_on_error) {
428*e3723e1fSApple OSS Distributions 		T_QUIET;
429*e3723e1fSApple OSS Distributions 		T_ASSERT_POSIX_SUCCESS(err, "SIOCSIFDESTROY %s", ifr.ifr_name);
430*e3723e1fSApple OSS Distributions 	}
431*e3723e1fSApple OSS Distributions 	if (err < 0) {
432*e3723e1fSApple OSS Distributions 		T_LOG("SIOCSIFDESTROY %s", ifr.ifr_name);
433*e3723e1fSApple OSS Distributions 	}
434*e3723e1fSApple OSS Distributions 	return err;
435*e3723e1fSApple OSS Distributions }
436*e3723e1fSApple OSS Distributions 
437*e3723e1fSApple OSS Distributions int
ifnet_set_flags(const char * ifname,uint16_t flags_set,uint16_t flags_clear)438*e3723e1fSApple OSS Distributions ifnet_set_flags(const char * ifname, uint16_t flags_set, uint16_t flags_clear)
439*e3723e1fSApple OSS Distributions {
440*e3723e1fSApple OSS Distributions 	uint16_t        flags_after;
441*e3723e1fSApple OSS Distributions 	uint16_t        flags_before;
442*e3723e1fSApple OSS Distributions 	struct ifreq    ifr;
443*e3723e1fSApple OSS Distributions 	int             ret;
444*e3723e1fSApple OSS Distributions 	int             s = inet_dgram_socket_get();
445*e3723e1fSApple OSS Distributions 
446*e3723e1fSApple OSS Distributions 	bzero(&ifr, sizeof(ifr));
447*e3723e1fSApple OSS Distributions 	strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
448*e3723e1fSApple OSS Distributions 	ret = ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr);
449*e3723e1fSApple OSS Distributions 	if (ret != 0) {
450*e3723e1fSApple OSS Distributions 		T_LOG("SIOCGIFFLAGS %s", ifr.ifr_name);
451*e3723e1fSApple OSS Distributions 		return ret;
452*e3723e1fSApple OSS Distributions 	}
453*e3723e1fSApple OSS Distributions 	flags_before = (uint16_t)ifr.ifr_flags;
454*e3723e1fSApple OSS Distributions 	ifr.ifr_flags |= flags_set;
455*e3723e1fSApple OSS Distributions 	ifr.ifr_flags &= ~(flags_clear);
456*e3723e1fSApple OSS Distributions 	flags_after = (uint16_t)ifr.ifr_flags;
457*e3723e1fSApple OSS Distributions 	if (flags_before == flags_after) {
458*e3723e1fSApple OSS Distributions 		/* nothing to do */
459*e3723e1fSApple OSS Distributions 		ret = 0;
460*e3723e1fSApple OSS Distributions 	} else {
461*e3723e1fSApple OSS Distributions 		/* issue the ioctl */
462*e3723e1fSApple OSS Distributions 		T_QUIET;
463*e3723e1fSApple OSS Distributions 		T_ASSERT_POSIX_SUCCESS(ioctl(s, SIOCSIFFLAGS, &ifr),
464*e3723e1fSApple OSS Distributions 		    "SIOCSIFFLAGS %s 0x%x",
465*e3723e1fSApple OSS Distributions 		    ifr.ifr_name, (uint16_t)ifr.ifr_flags);
466*e3723e1fSApple OSS Distributions 		if (G_debug) {
467*e3723e1fSApple OSS Distributions 			T_LOG("setflags(%s set 0x%x clear 0x%x) 0x%x => 0x%x",
468*e3723e1fSApple OSS Distributions 			    ifr.ifr_name, flags_set, flags_clear,
469*e3723e1fSApple OSS Distributions 			    flags_before, flags_after);
470*e3723e1fSApple OSS Distributions 		}
471*e3723e1fSApple OSS Distributions 	}
472*e3723e1fSApple OSS Distributions 	return ret;
473*e3723e1fSApple OSS Distributions }
474*e3723e1fSApple OSS Distributions 
475*e3723e1fSApple OSS Distributions /* On some platforms with DEBUG kernel, we need to wait a while */
476*e3723e1fSApple OSS Distributions #define SIFCREATE_RETRY 600
477*e3723e1fSApple OSS Distributions 
478*e3723e1fSApple OSS Distributions static int
ifnet_create_common(const char * ifname,char * ifname_out,size_t ifname_out_len)479*e3723e1fSApple OSS Distributions ifnet_create_common(const char * ifname, char *ifname_out, size_t ifname_out_len)
480*e3723e1fSApple OSS Distributions {
481*e3723e1fSApple OSS Distributions 	int             error = 0;
482*e3723e1fSApple OSS Distributions 	struct ifreq    ifr;
483*e3723e1fSApple OSS Distributions 	int             s = inet_dgram_socket_get();
484*e3723e1fSApple OSS Distributions 
485*e3723e1fSApple OSS Distributions 	bzero(&ifr, sizeof(ifr));
486*e3723e1fSApple OSS Distributions 	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
487*e3723e1fSApple OSS Distributions 
488*e3723e1fSApple OSS Distributions 	for (int i = 0; i < SIFCREATE_RETRY; i++) {
489*e3723e1fSApple OSS Distributions 		if (ioctl(s, SIOCIFCREATE, &ifr) < 0) {
490*e3723e1fSApple OSS Distributions 			error = errno;
491*e3723e1fSApple OSS Distributions 			T_LOG("SIOCSIFCREATE %s: %s", ifname,
492*e3723e1fSApple OSS Distributions 			    strerror(error));
493*e3723e1fSApple OSS Distributions 			if (error == EBUSY) {
494*e3723e1fSApple OSS Distributions 				/* interface is tearing down, try again */
495*e3723e1fSApple OSS Distributions 				usleep(10000);
496*e3723e1fSApple OSS Distributions 			} else if (error == EEXIST) {
497*e3723e1fSApple OSS Distributions 				/* interface exists, try destroying it */
498*e3723e1fSApple OSS Distributions 				(void)ifnet_destroy(ifname, false);
499*e3723e1fSApple OSS Distributions 			} else {
500*e3723e1fSApple OSS Distributions 				/* unexpected failure */
501*e3723e1fSApple OSS Distributions 				break;
502*e3723e1fSApple OSS Distributions 			}
503*e3723e1fSApple OSS Distributions 		} else {
504*e3723e1fSApple OSS Distributions 			if (ifname_out != NULL) {
505*e3723e1fSApple OSS Distributions 				strlcpy(ifname_out, ifr.ifr_name, ifname_out_len);
506*e3723e1fSApple OSS Distributions 			}
507*e3723e1fSApple OSS Distributions 			error = 0;
508*e3723e1fSApple OSS Distributions 			break;
509*e3723e1fSApple OSS Distributions 		}
510*e3723e1fSApple OSS Distributions 	}
511*e3723e1fSApple OSS Distributions 	if (error == 0) {
512*e3723e1fSApple OSS Distributions 		error = ifnet_set_flags(ifname, IFF_UP, 0);
513*e3723e1fSApple OSS Distributions 	}
514*e3723e1fSApple OSS Distributions 	return error;
515*e3723e1fSApple OSS Distributions }
516*e3723e1fSApple OSS Distributions 
517*e3723e1fSApple OSS Distributions int
ifnet_create(const char * ifname)518*e3723e1fSApple OSS Distributions ifnet_create(const char * ifname)
519*e3723e1fSApple OSS Distributions {
520*e3723e1fSApple OSS Distributions 	return ifnet_create_common(ifname, NULL, 0);
521*e3723e1fSApple OSS Distributions }
522*e3723e1fSApple OSS Distributions 
523*e3723e1fSApple OSS Distributions int
ifnet_create_2(char * ifname,size_t len)524*e3723e1fSApple OSS Distributions ifnet_create_2(char * ifname, size_t len)
525*e3723e1fSApple OSS Distributions {
526*e3723e1fSApple OSS Distributions 	return ifnet_create_common(ifname, ifname, len);
527*e3723e1fSApple OSS Distributions }
528*e3723e1fSApple OSS Distributions 
529*e3723e1fSApple OSS Distributions void
ifnet_add_ip_address(char * ifname,struct in_addr addr,struct in_addr mask)530*e3723e1fSApple OSS Distributions ifnet_add_ip_address(char *ifname, struct in_addr addr, struct in_addr mask)
531*e3723e1fSApple OSS Distributions {
532*e3723e1fSApple OSS Distributions 	int             s = inet_dgram_socket_get();
533*e3723e1fSApple OSS Distributions 
534*e3723e1fSApple OSS Distributions 	siocaifaddr(s, ifname, addr, mask);
535*e3723e1fSApple OSS Distributions }
536*e3723e1fSApple OSS Distributions 
537*e3723e1fSApple OSS Distributions int
ifnet_set_mtu(const char * ifname,int mtu)538*e3723e1fSApple OSS Distributions ifnet_set_mtu(const char *ifname, int mtu)
539*e3723e1fSApple OSS Distributions {
540*e3723e1fSApple OSS Distributions 	int error = 0;
541*e3723e1fSApple OSS Distributions 	struct ifreq ifr = { 0 };
542*e3723e1fSApple OSS Distributions 	int s = inet_dgram_socket_get();
543*e3723e1fSApple OSS Distributions 
544*e3723e1fSApple OSS Distributions 	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
545*e3723e1fSApple OSS Distributions 	ifr.ifr_mtu = mtu;
546*e3723e1fSApple OSS Distributions 
547*e3723e1fSApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(ioctl(s, SIOCSIFMTU, (caddr_t)&ifr), "set MTU");
548*e3723e1fSApple OSS Distributions 
549*e3723e1fSApple OSS Distributions 	return error;
550*e3723e1fSApple OSS Distributions }
551*e3723e1fSApple OSS Distributions 
552*e3723e1fSApple OSS Distributions int
siocdrvspec(const char * ifname,u_long op,void * arg,size_t argsize,bool set)553*e3723e1fSApple OSS Distributions siocdrvspec(const char * ifname, u_long op, void *arg, size_t argsize, bool set)
554*e3723e1fSApple OSS Distributions {
555*e3723e1fSApple OSS Distributions 	struct ifdrv    ifd;
556*e3723e1fSApple OSS Distributions 	int             s = inet_dgram_socket_get();
557*e3723e1fSApple OSS Distributions 
558*e3723e1fSApple OSS Distributions 	memset(&ifd, 0, sizeof(ifd));
559*e3723e1fSApple OSS Distributions 	strlcpy(ifd.ifd_name, ifname, sizeof(ifd.ifd_name));
560*e3723e1fSApple OSS Distributions 	ifd.ifd_cmd = op;
561*e3723e1fSApple OSS Distributions 	ifd.ifd_len = argsize;
562*e3723e1fSApple OSS Distributions 	ifd.ifd_data = arg;
563*e3723e1fSApple OSS Distributions 	return ioctl(s, set ? SIOCSDRVSPEC : SIOCGDRVSPEC, &ifd);
564*e3723e1fSApple OSS Distributions }
565*e3723e1fSApple OSS Distributions 
566*e3723e1fSApple OSS Distributions void
fake_set_peer(const char * feth,const char * feth_peer)567*e3723e1fSApple OSS Distributions fake_set_peer(const char * feth, const char * feth_peer)
568*e3723e1fSApple OSS Distributions {
569*e3723e1fSApple OSS Distributions 	struct if_fake_request  iffr;
570*e3723e1fSApple OSS Distributions 	int                     ret;
571*e3723e1fSApple OSS Distributions 
572*e3723e1fSApple OSS Distributions 	bzero((char *)&iffr, sizeof(iffr));
573*e3723e1fSApple OSS Distributions 	if (feth_peer != NULL) {
574*e3723e1fSApple OSS Distributions 		strlcpy(iffr.iffr_peer_name, feth_peer,
575*e3723e1fSApple OSS Distributions 		    sizeof(iffr.iffr_peer_name));
576*e3723e1fSApple OSS Distributions 	}
577*e3723e1fSApple OSS Distributions 	ret = siocdrvspec(feth, IF_FAKE_S_CMD_SET_PEER,
578*e3723e1fSApple OSS Distributions 	    &iffr, sizeof(iffr), true);
579*e3723e1fSApple OSS Distributions 	T_QUIET;
580*e3723e1fSApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(ret,
581*e3723e1fSApple OSS Distributions 	    "SIOCDRVSPEC(%s, IF_FAKE_S_CMD_SET_PEER, %s)",
582*e3723e1fSApple OSS Distributions 	    feth, (feth_peer != NULL) ? feth_peer : "<none>");
583*e3723e1fSApple OSS Distributions 	T_LOG("%s peer %s\n", feth, feth_peer);
584*e3723e1fSApple OSS Distributions 	return;
585*e3723e1fSApple OSS Distributions }
586*e3723e1fSApple OSS Distributions 
587*e3723e1fSApple OSS Distributions void
siocsifvlan(const char * vlan,const char * phys,uint16_t tag)588*e3723e1fSApple OSS Distributions siocsifvlan(const char * vlan, const char * phys, uint16_t tag)
589*e3723e1fSApple OSS Distributions {
590*e3723e1fSApple OSS Distributions 	int             result;
591*e3723e1fSApple OSS Distributions 	struct ifreq    ifr;
592*e3723e1fSApple OSS Distributions 	int             s = inet_dgram_socket_get();
593*e3723e1fSApple OSS Distributions 	struct vlanreq  vlr;
594*e3723e1fSApple OSS Distributions 
595*e3723e1fSApple OSS Distributions 	bzero(&ifr, sizeof(ifr));
596*e3723e1fSApple OSS Distributions 	strlcpy(ifr.ifr_name, vlan, sizeof(ifr.ifr_name));
597*e3723e1fSApple OSS Distributions 	ifr.ifr_data = (caddr_t)&vlr;
598*e3723e1fSApple OSS Distributions 	strlcpy(vlr.vlr_parent, phys, sizeof(vlr.vlr_parent));
599*e3723e1fSApple OSS Distributions 	vlr.vlr_tag = tag;
600*e3723e1fSApple OSS Distributions 	result = ioctl(s, SIOCSIFVLAN, &ifr);
601*e3723e1fSApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(result, "SIOCSIFVLAN(%s) %s %d",
602*e3723e1fSApple OSS Distributions 	    vlan, phys, tag);
603*e3723e1fSApple OSS Distributions }
604*e3723e1fSApple OSS Distributions 
605*e3723e1fSApple OSS Distributions u_int
make_dhcp_payload(dhcp_min_payload_t payload,ether_addr_t * eaddr)606*e3723e1fSApple OSS Distributions make_dhcp_payload(dhcp_min_payload_t payload, ether_addr_t *eaddr)
607*e3723e1fSApple OSS Distributions {
608*e3723e1fSApple OSS Distributions 	struct bootp *  dhcp;
609*e3723e1fSApple OSS Distributions 	u_int           payload_length;
610*e3723e1fSApple OSS Distributions 
611*e3723e1fSApple OSS Distributions 	/* create a minimal BOOTP packet */
612*e3723e1fSApple OSS Distributions 	payload_length = sizeof(*payload);
613*e3723e1fSApple OSS Distributions 	dhcp = (struct bootp *)payload;
614*e3723e1fSApple OSS Distributions 	bzero(dhcp, payload_length);
615*e3723e1fSApple OSS Distributions 	dhcp->bp_op = BOOTREQUEST;
616*e3723e1fSApple OSS Distributions 	dhcp->bp_htype = ARPHRD_ETHER;
617*e3723e1fSApple OSS Distributions 	dhcp->bp_hlen = sizeof(*eaddr);
618*e3723e1fSApple OSS Distributions 	bcopy(eaddr->octet, dhcp->bp_chaddr, sizeof(eaddr->octet));
619*e3723e1fSApple OSS Distributions 	return payload_length;
620*e3723e1fSApple OSS Distributions }
621*e3723e1fSApple OSS Distributions 
622*e3723e1fSApple OSS Distributions 
623*e3723e1fSApple OSS Distributions 
624*e3723e1fSApple OSS Distributions /*
625*e3723e1fSApple OSS Distributions  * routing table
626*e3723e1fSApple OSS Distributions  */
627*e3723e1fSApple OSS Distributions 
628*e3723e1fSApple OSS Distributions /*
629*e3723e1fSApple OSS Distributions  * Stolen/modified from IPMonitor/ip_plugin.c
630*e3723e1fSApple OSS Distributions  */
631*e3723e1fSApple OSS Distributions /*
632*e3723e1fSApple OSS Distributions  * Define: ROUTE_MSG_ADDRS_SPACE
633*e3723e1fSApple OSS Distributions  * Purpose:
634*e3723e1fSApple OSS Distributions  *   Since sizeof(sockaddr_dl) > sizeof(sockaddr_in), we need space for
635*e3723e1fSApple OSS Distributions  *   3 sockaddr_in's and 2 sockaddr_dl's, but pad it just in case
636*e3723e1fSApple OSS Distributions  *   someone changes the code and doesn't think to modify this.
637*e3723e1fSApple OSS Distributions  */
638*e3723e1fSApple OSS Distributions #define ROUTE_MSG_ADDRS_SPACE   (3 * sizeof(struct sockaddr_in) \
639*e3723e1fSApple OSS Distributions 	                         + 2 * sizeof(struct sockaddr_dl) \
640*e3723e1fSApple OSS Distributions 	                         + 128)
641*e3723e1fSApple OSS Distributions typedef struct {
642*e3723e1fSApple OSS Distributions 	struct rt_msghdr    hdr;
643*e3723e1fSApple OSS Distributions 	char                addrs[ROUTE_MSG_ADDRS_SPACE];
644*e3723e1fSApple OSS Distributions } route_msg;
645*e3723e1fSApple OSS Distributions 
646*e3723e1fSApple OSS Distributions typedef unsigned short  IFIndex;
647*e3723e1fSApple OSS Distributions 
648*e3723e1fSApple OSS Distributions typedef enum {
649*e3723e1fSApple OSS Distributions 	kRouteFlagsIsScoped         = 0x0001,
650*e3723e1fSApple OSS Distributions 	kRouteFlagsHasGateway       = 0x0002,
651*e3723e1fSApple OSS Distributions 	kRouteFlagsIsHost           = 0x0004,
652*e3723e1fSApple OSS Distributions } RouteFlags;
653*e3723e1fSApple OSS Distributions 
654*e3723e1fSApple OSS Distributions typedef struct {
655*e3723e1fSApple OSS Distributions 	IFIndex         ifindex;
656*e3723e1fSApple OSS Distributions 	RouteFlags      flags;
657*e3723e1fSApple OSS Distributions 	struct in_addr  dest;
658*e3723e1fSApple OSS Distributions 	struct in_addr  mask;
659*e3723e1fSApple OSS Distributions 	struct in_addr  gateway;
660*e3723e1fSApple OSS Distributions 	struct in_addr  ifa;
661*e3723e1fSApple OSS Distributions } IPv4Route, * IPv4RouteRef;
662*e3723e1fSApple OSS Distributions 
663*e3723e1fSApple OSS Distributions /*
664*e3723e1fSApple OSS Distributions  * Function: IPv4RouteApply
665*e3723e1fSApple OSS Distributions  * Purpose:
666*e3723e1fSApple OSS Distributions  *   Add or remove the specified route to/from the kernel routing table.
667*e3723e1fSApple OSS Distributions  */
668*e3723e1fSApple OSS Distributions static int
IPv4RouteApply(IPv4RouteRef route,uint8_t cmd,int s)669*e3723e1fSApple OSS Distributions IPv4RouteApply(IPv4RouteRef route, uint8_t cmd, int s)
670*e3723e1fSApple OSS Distributions {
671*e3723e1fSApple OSS Distributions 	size_t          len;
672*e3723e1fSApple OSS Distributions 	int             ret = 0;
673*e3723e1fSApple OSS Distributions 	route_msg       rtmsg;
674*e3723e1fSApple OSS Distributions 	union {
675*e3723e1fSApple OSS Distributions 		struct sockaddr_in *    in_p;
676*e3723e1fSApple OSS Distributions 		struct sockaddr_dl *    dl_p;
677*e3723e1fSApple OSS Distributions 		char *                  ptr;
678*e3723e1fSApple OSS Distributions 	} rtaddr;
679*e3723e1fSApple OSS Distributions 	static int      rtm_seq;
680*e3723e1fSApple OSS Distributions 	static bool     rtm_seq_inited;
681*e3723e1fSApple OSS Distributions 
682*e3723e1fSApple OSS Distributions 	if (!rtm_seq_inited) {
683*e3723e1fSApple OSS Distributions 		rtm_seq_inited = true;
684*e3723e1fSApple OSS Distributions 		rtm_seq = (int)arc4random();
685*e3723e1fSApple OSS Distributions 	}
686*e3723e1fSApple OSS Distributions 	if (route->ifindex == 0) {
687*e3723e1fSApple OSS Distributions 		T_LOG("no interface specified, ignoring %s",
688*e3723e1fSApple OSS Distributions 		    inet_ntoa(route->dest));
689*e3723e1fSApple OSS Distributions 		return ENXIO;
690*e3723e1fSApple OSS Distributions 	}
691*e3723e1fSApple OSS Distributions 	if (s < 0) {
692*e3723e1fSApple OSS Distributions 		T_LOG("invalid routing socket");
693*e3723e1fSApple OSS Distributions 		return EBADF;
694*e3723e1fSApple OSS Distributions 	}
695*e3723e1fSApple OSS Distributions 	memset(&rtmsg, 0, sizeof(rtmsg));
696*e3723e1fSApple OSS Distributions 	rtmsg.hdr.rtm_type = cmd;
697*e3723e1fSApple OSS Distributions 	rtmsg.hdr.rtm_version = RTM_VERSION;
698*e3723e1fSApple OSS Distributions 	rtmsg.hdr.rtm_seq = rtm_seq++;
699*e3723e1fSApple OSS Distributions 	rtmsg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_IFP;
700*e3723e1fSApple OSS Distributions 	if (route->ifa.s_addr != 0) {
701*e3723e1fSApple OSS Distributions 		rtmsg.hdr.rtm_addrs |= RTA_IFA;
702*e3723e1fSApple OSS Distributions 	}
703*e3723e1fSApple OSS Distributions 	rtmsg.hdr.rtm_flags = RTF_UP | RTF_STATIC;
704*e3723e1fSApple OSS Distributions 	if ((route->flags & kRouteFlagsIsHost) != 0) {
705*e3723e1fSApple OSS Distributions 		rtmsg.hdr.rtm_flags |= RTF_HOST;
706*e3723e1fSApple OSS Distributions 	} else {
707*e3723e1fSApple OSS Distributions 		rtmsg.hdr.rtm_addrs |= RTA_NETMASK;
708*e3723e1fSApple OSS Distributions 		if ((route->flags & kRouteFlagsHasGateway) == 0) {
709*e3723e1fSApple OSS Distributions 			rtmsg.hdr.rtm_flags |= RTF_CLONING;
710*e3723e1fSApple OSS Distributions 		}
711*e3723e1fSApple OSS Distributions 	}
712*e3723e1fSApple OSS Distributions 	if ((route->flags & kRouteFlagsHasGateway) != 0) {
713*e3723e1fSApple OSS Distributions 		rtmsg.hdr.rtm_flags |= RTF_GATEWAY;
714*e3723e1fSApple OSS Distributions 	}
715*e3723e1fSApple OSS Distributions 	if ((route->flags & kRouteFlagsIsScoped) != 0) {
716*e3723e1fSApple OSS Distributions 		rtmsg.hdr.rtm_index = route->ifindex;
717*e3723e1fSApple OSS Distributions 		rtmsg.hdr.rtm_flags |= RTF_IFSCOPE;
718*e3723e1fSApple OSS Distributions 	}
719*e3723e1fSApple OSS Distributions 
720*e3723e1fSApple OSS Distributions 	rtaddr.ptr = rtmsg.addrs;
721*e3723e1fSApple OSS Distributions 
722*e3723e1fSApple OSS Distributions 	/* dest */
723*e3723e1fSApple OSS Distributions 	rtaddr.in_p->sin_len = sizeof(*rtaddr.in_p);
724*e3723e1fSApple OSS Distributions 	rtaddr.in_p->sin_family = AF_INET;
725*e3723e1fSApple OSS Distributions 	rtaddr.in_p->sin_addr = route->dest;
726*e3723e1fSApple OSS Distributions 	rtaddr.ptr += sizeof(*rtaddr.in_p);
727*e3723e1fSApple OSS Distributions 
728*e3723e1fSApple OSS Distributions 	/* gateway */
729*e3723e1fSApple OSS Distributions 	if ((rtmsg.hdr.rtm_flags & RTF_GATEWAY) != 0) {
730*e3723e1fSApple OSS Distributions 		/* gateway is an IP address */
731*e3723e1fSApple OSS Distributions 		rtaddr.in_p->sin_len = sizeof(*rtaddr.in_p);
732*e3723e1fSApple OSS Distributions 		rtaddr.in_p->sin_family = AF_INET;
733*e3723e1fSApple OSS Distributions 		rtaddr.in_p->sin_addr = route->gateway;
734*e3723e1fSApple OSS Distributions 		rtaddr.ptr += sizeof(*rtaddr.in_p);
735*e3723e1fSApple OSS Distributions 	} else {
736*e3723e1fSApple OSS Distributions 		/* gateway is the interface itself */
737*e3723e1fSApple OSS Distributions 		rtaddr.dl_p->sdl_len = sizeof(*rtaddr.dl_p);
738*e3723e1fSApple OSS Distributions 		rtaddr.dl_p->sdl_family = AF_LINK;
739*e3723e1fSApple OSS Distributions 		rtaddr.dl_p->sdl_index = route->ifindex;
740*e3723e1fSApple OSS Distributions 		rtaddr.ptr += sizeof(*rtaddr.dl_p);
741*e3723e1fSApple OSS Distributions 	}
742*e3723e1fSApple OSS Distributions 
743*e3723e1fSApple OSS Distributions 	/* mask */
744*e3723e1fSApple OSS Distributions 	if ((rtmsg.hdr.rtm_addrs & RTA_NETMASK) != 0) {
745*e3723e1fSApple OSS Distributions 		rtaddr.in_p->sin_len = sizeof(*rtaddr.in_p);
746*e3723e1fSApple OSS Distributions 		rtaddr.in_p->sin_family = AF_INET;
747*e3723e1fSApple OSS Distributions 		rtaddr.in_p->sin_addr = route->mask;
748*e3723e1fSApple OSS Distributions 		rtaddr.ptr += sizeof(*rtaddr.in_p);
749*e3723e1fSApple OSS Distributions 	}
750*e3723e1fSApple OSS Distributions 
751*e3723e1fSApple OSS Distributions 	/* interface */
752*e3723e1fSApple OSS Distributions 	if ((rtmsg.hdr.rtm_addrs & RTA_IFP) != 0) {
753*e3723e1fSApple OSS Distributions 		rtaddr.dl_p->sdl_len = sizeof(*rtaddr.dl_p);
754*e3723e1fSApple OSS Distributions 		rtaddr.dl_p->sdl_family = AF_LINK;
755*e3723e1fSApple OSS Distributions 		rtaddr.dl_p->sdl_index = route->ifindex;
756*e3723e1fSApple OSS Distributions 		rtaddr.ptr += sizeof(*rtaddr.dl_p);
757*e3723e1fSApple OSS Distributions 	}
758*e3723e1fSApple OSS Distributions 	/* interface address */
759*e3723e1fSApple OSS Distributions 	if ((rtmsg.hdr.rtm_addrs & RTA_IFA) != 0) {
760*e3723e1fSApple OSS Distributions 		rtaddr.in_p->sin_len = sizeof(*rtaddr.in_p);
761*e3723e1fSApple OSS Distributions 		rtaddr.in_p->sin_family = AF_INET;
762*e3723e1fSApple OSS Distributions 		rtaddr.in_p->sin_addr = route->ifa;
763*e3723e1fSApple OSS Distributions 		rtaddr.ptr += sizeof(*rtaddr.in_p);
764*e3723e1fSApple OSS Distributions 	}
765*e3723e1fSApple OSS Distributions 
766*e3723e1fSApple OSS Distributions 	/* apply the route */
767*e3723e1fSApple OSS Distributions 	len = (sizeof(rtmsg.hdr)
768*e3723e1fSApple OSS Distributions 	    + (unsigned long)(rtaddr.ptr - (char *)rtmsg.addrs));
769*e3723e1fSApple OSS Distributions 	rtmsg.hdr.rtm_msglen = (u_short)len;
770*e3723e1fSApple OSS Distributions 	if (write(s, &rtmsg, len) == -1) {
771*e3723e1fSApple OSS Distributions 		ret = errno;
772*e3723e1fSApple OSS Distributions 		T_LOG("write routing socket failed, (%d) %s",
773*e3723e1fSApple OSS Distributions 		    errno, strerror(errno));
774*e3723e1fSApple OSS Distributions 	}
775*e3723e1fSApple OSS Distributions 	return ret;
776*e3723e1fSApple OSS Distributions }
777*e3723e1fSApple OSS Distributions 
778*e3723e1fSApple OSS Distributions static int routing_socket = -1;
779*e3723e1fSApple OSS Distributions 
780*e3723e1fSApple OSS Distributions static int
routing_socket_get(void)781*e3723e1fSApple OSS Distributions routing_socket_get(void)
782*e3723e1fSApple OSS Distributions {
783*e3723e1fSApple OSS Distributions 	if (routing_socket != NO_SOCKET) {
784*e3723e1fSApple OSS Distributions 		goto done;
785*e3723e1fSApple OSS Distributions 	}
786*e3723e1fSApple OSS Distributions 	routing_socket = socket(PF_ROUTE, SOCK_RAW, PF_ROUTE);
787*e3723e1fSApple OSS Distributions 	T_QUIET;
788*e3723e1fSApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(routing_socket,
789*e3723e1fSApple OSS Distributions 	    "socket(PF_ROUTE, SOCK_RAW, PF_ROUTE)");
790*e3723e1fSApple OSS Distributions done:
791*e3723e1fSApple OSS Distributions 	return routing_socket;
792*e3723e1fSApple OSS Distributions }
793*e3723e1fSApple OSS Distributions 
794*e3723e1fSApple OSS Distributions void
route_add_inet_scoped_subnet(char * ifname,u_short if_index,struct in_addr ifa,struct in_addr mask)795*e3723e1fSApple OSS Distributions route_add_inet_scoped_subnet(char * ifname, u_short if_index,
796*e3723e1fSApple OSS Distributions     struct in_addr ifa, struct in_addr mask)
797*e3723e1fSApple OSS Distributions {
798*e3723e1fSApple OSS Distributions 	int             error;
799*e3723e1fSApple OSS Distributions 	IPv4Route       route;
800*e3723e1fSApple OSS Distributions 	int             rs = routing_socket_get();
801*e3723e1fSApple OSS Distributions 
802*e3723e1fSApple OSS Distributions 	bzero(&route, sizeof(route));
803*e3723e1fSApple OSS Distributions 	route.flags |= kRouteFlagsIsScoped;
804*e3723e1fSApple OSS Distributions 	route.ifa = ifa;
805*e3723e1fSApple OSS Distributions 	route.ifindex = if_index;
806*e3723e1fSApple OSS Distributions 	route.mask = mask;
807*e3723e1fSApple OSS Distributions 	route.dest.s_addr = route.ifa.s_addr & route.mask.s_addr;
808*e3723e1fSApple OSS Distributions 	T_QUIET;
809*e3723e1fSApple OSS Distributions 	T_ASSERT_NE((int)route.ifindex, 0, "if_nametoindex(%s)", ifname);
810*e3723e1fSApple OSS Distributions 	error = IPv4RouteApply(&route, RTM_ADD, rs);
811*e3723e1fSApple OSS Distributions 	T_ASSERT_EQ(error, 0, "add scoped subnet route %s %s/24", ifname,
812*e3723e1fSApple OSS Distributions 	    inet_ntoa(route.dest));
813*e3723e1fSApple OSS Distributions 	return;
814*e3723e1fSApple OSS Distributions }
815*e3723e1fSApple OSS Distributions 
816*e3723e1fSApple OSS Distributions /**
817*e3723e1fSApple OSS Distributions ** network_interface
818*e3723e1fSApple OSS Distributions **/
819*e3723e1fSApple OSS Distributions 
820*e3723e1fSApple OSS Distributions void
network_interface_create(network_interface_t if_p,const if_name_t name)821*e3723e1fSApple OSS Distributions network_interface_create(network_interface_t if_p, const if_name_t name)
822*e3723e1fSApple OSS Distributions {
823*e3723e1fSApple OSS Distributions 	int             error;
824*e3723e1fSApple OSS Distributions 	size_t          len = sizeof(if_p->if_name);
825*e3723e1fSApple OSS Distributions 
826*e3723e1fSApple OSS Distributions 	strlcpy(if_p->if_name, name, len);
827*e3723e1fSApple OSS Distributions 	error = ifnet_create_2(if_p->if_name, len);
828*e3723e1fSApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(error, "ifnet_create_2 %s", if_p->if_name);
829*e3723e1fSApple OSS Distributions 
830*e3723e1fSApple OSS Distributions 	if_p->if_index = (u_short)if_nametoindex(if_p->if_name);
831*e3723e1fSApple OSS Distributions 	T_QUIET;
832*e3723e1fSApple OSS Distributions 	T_ASSERT_TRUE(if_p->if_index != 0, NULL);
833*e3723e1fSApple OSS Distributions 	T_LOG("%s: created %s index %d\n",
834*e3723e1fSApple OSS Distributions 	    __func__, if_p->if_name, if_p->if_index);
835*e3723e1fSApple OSS Distributions }
836*e3723e1fSApple OSS Distributions 
837*e3723e1fSApple OSS Distributions void
network_interface_destroy(network_interface_t if_p)838*e3723e1fSApple OSS Distributions network_interface_destroy(network_interface_t if_p)
839*e3723e1fSApple OSS Distributions {
840*e3723e1fSApple OSS Distributions 	if (if_p->if_index != 0) {
841*e3723e1fSApple OSS Distributions 		ifnet_destroy(if_p->if_name, false);
842*e3723e1fSApple OSS Distributions 		T_LOG("%s: destroyed %s\n", __func__, if_p->if_name);
843*e3723e1fSApple OSS Distributions 	}
844*e3723e1fSApple OSS Distributions }
845*e3723e1fSApple OSS Distributions 
846*e3723e1fSApple OSS Distributions static inline size_t
network_interface_pair_list_size(size_t count)847*e3723e1fSApple OSS Distributions network_interface_pair_list_size(size_t count)
848*e3723e1fSApple OSS Distributions {
849*e3723e1fSApple OSS Distributions 	return offsetof(network_interface_pair_list, list[count]);
850*e3723e1fSApple OSS Distributions }
851*e3723e1fSApple OSS Distributions 
852*e3723e1fSApple OSS Distributions network_interface_pair_list_t
network_interface_pair_list_alloc(u_int n)853*e3723e1fSApple OSS Distributions network_interface_pair_list_alloc(u_int n)
854*e3723e1fSApple OSS Distributions {
855*e3723e1fSApple OSS Distributions 	network_interface_pair_list_t   list;
856*e3723e1fSApple OSS Distributions 
857*e3723e1fSApple OSS Distributions 	list = (network_interface_pair_list_t)
858*e3723e1fSApple OSS Distributions 	    calloc(1, network_interface_pair_list_size(n));
859*e3723e1fSApple OSS Distributions 	list->count = n;
860*e3723e1fSApple OSS Distributions 	return list;
861*e3723e1fSApple OSS Distributions }
862*e3723e1fSApple OSS Distributions 
863*e3723e1fSApple OSS Distributions void
network_interface_pair_list_destroy(network_interface_pair_list_t list)864*e3723e1fSApple OSS Distributions network_interface_pair_list_destroy(network_interface_pair_list_t list)
865*e3723e1fSApple OSS Distributions {
866*e3723e1fSApple OSS Distributions 	network_interface_pair_t        scan;
867*e3723e1fSApple OSS Distributions 
868*e3723e1fSApple OSS Distributions 	if (list == NULL) {
869*e3723e1fSApple OSS Distributions 		return;
870*e3723e1fSApple OSS Distributions 	}
871*e3723e1fSApple OSS Distributions 	scan = list->list;
872*e3723e1fSApple OSS Distributions 	for (size_t i = 0; i < list->count; i++, scan++) {
873*e3723e1fSApple OSS Distributions 		network_interface_destroy(&scan->one);
874*e3723e1fSApple OSS Distributions 		network_interface_destroy(&scan->two);
875*e3723e1fSApple OSS Distributions 	}
876*e3723e1fSApple OSS Distributions }
877*e3723e1fSApple OSS Distributions 
878*e3723e1fSApple OSS Distributions bool
has_ipv4_default_route(void)879*e3723e1fSApple OSS Distributions has_ipv4_default_route(void)
880*e3723e1fSApple OSS Distributions {
881*e3723e1fSApple OSS Distributions 	bool result = false;
882*e3723e1fSApple OSS Distributions 	struct rt_msghdr *rtm = NULL;
883*e3723e1fSApple OSS Distributions 	struct sockaddr_in sin = { 0 };
884*e3723e1fSApple OSS Distributions 
885*e3723e1fSApple OSS Distributions 	sin.sin_len = sizeof(struct sockaddr_in);
886*e3723e1fSApple OSS Distributions 	sin.sin_family = AF_INET;
887*e3723e1fSApple OSS Distributions 	sin.sin_addr.s_addr = INADDR_ANY;
888*e3723e1fSApple OSS Distributions 
889*e3723e1fSApple OSS Distributions 	T_QUIET; T_ASSERT_NOTNULL(rtm = (struct rt_msghdr *)calloc(1, RTM_BUFLEN), NULL);
890*e3723e1fSApple OSS Distributions 
891*e3723e1fSApple OSS Distributions 	rtm->rtm_msglen = sizeof(struct rt_msghdr) + sizeof(struct sockaddr_in);
892*e3723e1fSApple OSS Distributions 	rtm->rtm_version = RTM_VERSION;
893*e3723e1fSApple OSS Distributions 	rtm->rtm_type = RTM_GET;
894*e3723e1fSApple OSS Distributions 	rtm->rtm_flags = RTF_UP | RTF_STATIC | RTF_GATEWAY | RTF_HOST;
895*e3723e1fSApple OSS Distributions 	rtm->rtm_addrs = RTA_DST;
896*e3723e1fSApple OSS Distributions 	rtm->rtm_pid = getpid();
897*e3723e1fSApple OSS Distributions 	rtm->rtm_seq = 1;
898*e3723e1fSApple OSS Distributions 
899*e3723e1fSApple OSS Distributions 	uint8_t *cp = (unsigned char *)(rtm + 1);
900*e3723e1fSApple OSS Distributions 
901*e3723e1fSApple OSS Distributions 	bcopy(&sin, cp, sin.sin_len);
902*e3723e1fSApple OSS Distributions 	cp += ROUNDUP(sin.sin_len);
903*e3723e1fSApple OSS Distributions 
904*e3723e1fSApple OSS Distributions 	u_short len = (u_short)(cp - (uint8_t *)rtm);
905*e3723e1fSApple OSS Distributions 
906*e3723e1fSApple OSS Distributions 	rtm->rtm_msglen = len;
907*e3723e1fSApple OSS Distributions 
908*e3723e1fSApple OSS Distributions 	int fd;
909*e3723e1fSApple OSS Distributions 	T_QUIET; T_ASSERT_POSIX_SUCCESS(fd = socket(PF_ROUTE, SOCK_RAW, 0), NULL);
910*e3723e1fSApple OSS Distributions 
911*e3723e1fSApple OSS Distributions 	ssize_t sent = send(fd, rtm, len, 0);
912*e3723e1fSApple OSS Distributions 	if (sent == len) {
913*e3723e1fSApple OSS Distributions 		result = true;
914*e3723e1fSApple OSS Distributions 	} else {
915*e3723e1fSApple OSS Distributions 		result = false;
916*e3723e1fSApple OSS Distributions 	}
917*e3723e1fSApple OSS Distributions 
918*e3723e1fSApple OSS Distributions 	(void) close(fd);
919*e3723e1fSApple OSS Distributions 	free(rtm);
920*e3723e1fSApple OSS Distributions 
921*e3723e1fSApple OSS Distributions 	return result;
922*e3723e1fSApple OSS Distributions }
923*e3723e1fSApple OSS Distributions 
924*e3723e1fSApple OSS Distributions bool
has_ipv6_default_route(void)925*e3723e1fSApple OSS Distributions has_ipv6_default_route(void)
926*e3723e1fSApple OSS Distributions {
927*e3723e1fSApple OSS Distributions 	bool result = false;
928*e3723e1fSApple OSS Distributions 	struct rt_msghdr *rtm = NULL;
929*e3723e1fSApple OSS Distributions 	struct sockaddr_in6 sin6 = { 0 };
930*e3723e1fSApple OSS Distributions 
931*e3723e1fSApple OSS Distributions 	sin6.sin6_len = sizeof(struct sockaddr_in6);
932*e3723e1fSApple OSS Distributions 	sin6.sin6_family = AF_INET6;
933*e3723e1fSApple OSS Distributions 
934*e3723e1fSApple OSS Distributions 	T_QUIET; T_ASSERT_NOTNULL(rtm = (struct rt_msghdr *)calloc(1, RTM_BUFLEN), NULL);
935*e3723e1fSApple OSS Distributions 
936*e3723e1fSApple OSS Distributions 	rtm->rtm_msglen = sizeof(struct rt_msghdr) + sizeof(struct sockaddr_in6);
937*e3723e1fSApple OSS Distributions 	rtm->rtm_version = RTM_VERSION;
938*e3723e1fSApple OSS Distributions 	rtm->rtm_type = RTM_GET;
939*e3723e1fSApple OSS Distributions 	rtm->rtm_flags = RTF_UP | RTF_STATIC | RTF_GATEWAY | RTF_HOST;
940*e3723e1fSApple OSS Distributions 	rtm->rtm_addrs = RTA_DST;
941*e3723e1fSApple OSS Distributions 	rtm->rtm_pid = getpid();
942*e3723e1fSApple OSS Distributions 	rtm->rtm_seq = 1;
943*e3723e1fSApple OSS Distributions 
944*e3723e1fSApple OSS Distributions 	uint8_t *cp = (unsigned char *)(rtm + 1);
945*e3723e1fSApple OSS Distributions 
946*e3723e1fSApple OSS Distributions 	bcopy(&sin6, cp, sin6.sin6_len);
947*e3723e1fSApple OSS Distributions 	cp += ROUNDUP(sin6.sin6_len);
948*e3723e1fSApple OSS Distributions 
949*e3723e1fSApple OSS Distributions 	u_short len = (u_short)(cp - (uint8_t *)rtm);
950*e3723e1fSApple OSS Distributions 
951*e3723e1fSApple OSS Distributions 	rtm->rtm_msglen = len;
952*e3723e1fSApple OSS Distributions 
953*e3723e1fSApple OSS Distributions 	int fd;
954*e3723e1fSApple OSS Distributions 	T_QUIET; T_ASSERT_POSIX_SUCCESS(fd = socket(PF_ROUTE, SOCK_RAW, 0), NULL);
955*e3723e1fSApple OSS Distributions 
956*e3723e1fSApple OSS Distributions 	ssize_t sent = send(fd, rtm, len, 0);
957*e3723e1fSApple OSS Distributions 	if (sent == len) {
958*e3723e1fSApple OSS Distributions 		result = true;
959*e3723e1fSApple OSS Distributions 	} else {
960*e3723e1fSApple OSS Distributions 		result = false;
961*e3723e1fSApple OSS Distributions 	}
962*e3723e1fSApple OSS Distributions 
963*e3723e1fSApple OSS Distributions 	(void) close(fd);
964*e3723e1fSApple OSS Distributions 	free(rtm);
965*e3723e1fSApple OSS Distributions 
966*e3723e1fSApple OSS Distributions 	return result;
967*e3723e1fSApple OSS Distributions }
968*e3723e1fSApple OSS Distributions 
969*e3723e1fSApple OSS Distributions /*
970*e3723e1fSApple OSS Distributions  * Bridge management
971*e3723e1fSApple OSS Distributions  */
972*e3723e1fSApple OSS Distributions int
bridge_add_member(const char * bridge,const char * member)973*e3723e1fSApple OSS Distributions bridge_add_member(const char * bridge, const char * member)
974*e3723e1fSApple OSS Distributions {
975*e3723e1fSApple OSS Distributions 	struct ifbreq           req;
976*e3723e1fSApple OSS Distributions 	int                     ret;
977*e3723e1fSApple OSS Distributions 
978*e3723e1fSApple OSS Distributions 	memset(&req, 0, sizeof(req));
979*e3723e1fSApple OSS Distributions 	strlcpy(req.ifbr_ifsname, member, sizeof(req.ifbr_ifsname));
980*e3723e1fSApple OSS Distributions 	ret = siocdrvspec(bridge, BRDGADD, &req, sizeof(req), true);
981*e3723e1fSApple OSS Distributions 	T_QUIET;
982*e3723e1fSApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(ret, "%s %s %s", __func__, bridge, member);
983*e3723e1fSApple OSS Distributions 	return ret;
984*e3723e1fSApple OSS Distributions }
985