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