1*d8b80295SApple OSS Distributions /*
2*d8b80295SApple OSS Distributions * Copyright (c) 2019-2023 Apple Inc. All rights reserved.
3*d8b80295SApple OSS Distributions *
4*d8b80295SApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5*d8b80295SApple OSS Distributions *
6*d8b80295SApple OSS Distributions * This file contains Original Code and/or Modifications of Original Code
7*d8b80295SApple OSS Distributions * as defined in and that are subject to the Apple Public Source License
8*d8b80295SApple OSS Distributions * Version 2.0 (the 'License'). You may not use this file except in
9*d8b80295SApple OSS Distributions * compliance with the License. The rights granted to you under the License
10*d8b80295SApple OSS Distributions * may not be used to create, or enable the creation or redistribution of,
11*d8b80295SApple OSS Distributions * unlawful or unlicensed copies of an Apple operating system, or to
12*d8b80295SApple OSS Distributions * circumvent, violate, or enable the circumvention or violation of, any
13*d8b80295SApple OSS Distributions * terms of an Apple operating system software license agreement.
14*d8b80295SApple OSS Distributions *
15*d8b80295SApple OSS Distributions * Please obtain a copy of the License at
16*d8b80295SApple OSS Distributions * http://www.opensource.apple.com/apsl/ and read it before using this file.
17*d8b80295SApple OSS Distributions *
18*d8b80295SApple OSS Distributions * The Original Code and all software distributed under the License are
19*d8b80295SApple OSS Distributions * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20*d8b80295SApple OSS Distributions * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21*d8b80295SApple OSS Distributions * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22*d8b80295SApple OSS Distributions * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23*d8b80295SApple OSS Distributions * Please see the License for the specific language governing rights and
24*d8b80295SApple OSS Distributions * limitations under the License.
25*d8b80295SApple OSS Distributions *
26*d8b80295SApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27*d8b80295SApple OSS Distributions */
28*d8b80295SApple OSS Distributions
29*d8b80295SApple OSS Distributions #include "net_test_lib.h"
30*d8b80295SApple OSS Distributions #include "inet_transfer.h"
31*d8b80295SApple OSS Distributions #include "bpflib.h"
32*d8b80295SApple OSS Distributions #include "in_cksum.h"
33*d8b80295SApple OSS Distributions
34*d8b80295SApple OSS Distributions bool S_debug;
35*d8b80295SApple OSS Distributions
36*d8b80295SApple OSS Distributions int
inet_dgram_socket(void)37*d8b80295SApple OSS Distributions inet_dgram_socket(void)
38*d8b80295SApple OSS Distributions {
39*d8b80295SApple OSS Distributions int s;
40*d8b80295SApple OSS Distributions
41*d8b80295SApple OSS Distributions s = socket(AF_INET, SOCK_DGRAM, 0);
42*d8b80295SApple OSS Distributions T_QUIET;
43*d8b80295SApple OSS Distributions T_ASSERT_POSIX_SUCCESS(s, "socket(AF_INET, SOCK_DGRAM, 0)");
44*d8b80295SApple OSS Distributions return s;
45*d8b80295SApple OSS Distributions }
46*d8b80295SApple OSS Distributions
47*d8b80295SApple OSS Distributions int
inet6_dgram_socket(void)48*d8b80295SApple OSS Distributions inet6_dgram_socket(void)
49*d8b80295SApple OSS Distributions {
50*d8b80295SApple OSS Distributions int s;
51*d8b80295SApple OSS Distributions
52*d8b80295SApple OSS Distributions s = socket(AF_INET6, SOCK_DGRAM, 0);
53*d8b80295SApple OSS Distributions T_QUIET;
54*d8b80295SApple OSS Distributions T_ASSERT_POSIX_SUCCESS(s, "socket(AF_INET6, SOCK_DGRAM, 0)");
55*d8b80295SApple OSS Distributions return s;
56*d8b80295SApple OSS Distributions }
57*d8b80295SApple OSS Distributions
58*d8b80295SApple OSS Distributions int
routing_socket(void)59*d8b80295SApple OSS Distributions routing_socket(void)
60*d8b80295SApple OSS Distributions {
61*d8b80295SApple OSS Distributions int s;
62*d8b80295SApple OSS Distributions
63*d8b80295SApple OSS Distributions s = socket(PF_ROUTE, SOCK_RAW, PF_ROUTE);
64*d8b80295SApple OSS Distributions T_QUIET;
65*d8b80295SApple OSS Distributions T_ASSERT_POSIX_SUCCESS(s, "socket(PF_ROUTE, SOCK_RAW, PF_ROUTE)");
66*d8b80295SApple OSS Distributions return s;
67*d8b80295SApple OSS Distributions }
68*d8b80295SApple OSS Distributions
69*d8b80295SApple 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)70*d8b80295SApple OSS Distributions ethernet_udp4_frame_populate(void * buf, size_t buf_len,
71*d8b80295SApple OSS Distributions const ether_addr_t * src,
72*d8b80295SApple OSS Distributions struct in_addr src_ip,
73*d8b80295SApple OSS Distributions uint16_t src_port,
74*d8b80295SApple OSS Distributions const ether_addr_t * dst,
75*d8b80295SApple OSS Distributions struct in_addr dst_ip,
76*d8b80295SApple OSS Distributions uint16_t dst_port,
77*d8b80295SApple OSS Distributions const void * data, u_int data_len)
78*d8b80295SApple OSS Distributions {
79*d8b80295SApple OSS Distributions ether_header_t * eh_p;
80*d8b80295SApple OSS Distributions u_int frame_length;
81*d8b80295SApple OSS Distributions static int ip_id;
82*d8b80295SApple OSS Distributions ip_udp_header_t * ip_udp;
83*d8b80295SApple OSS Distributions char * payload;
84*d8b80295SApple OSS Distributions udp_pseudo_hdr_t * udp_pseudo;
85*d8b80295SApple OSS Distributions
86*d8b80295SApple OSS Distributions frame_length = (u_int)(sizeof(*eh_p) + sizeof(*ip_udp)) + data_len;
87*d8b80295SApple OSS Distributions if (buf_len < frame_length) {
88*d8b80295SApple OSS Distributions return 0;
89*d8b80295SApple OSS Distributions }
90*d8b80295SApple OSS Distributions
91*d8b80295SApple OSS Distributions /* determine frame offsets */
92*d8b80295SApple OSS Distributions eh_p = (ether_header_t *)buf;
93*d8b80295SApple OSS Distributions ip_udp = (ip_udp_header_t *)(void *)(eh_p + 1);
94*d8b80295SApple OSS Distributions udp_pseudo = (udp_pseudo_hdr_t *)(void *)
95*d8b80295SApple OSS Distributions (((char *)&ip_udp->udp) - sizeof(*udp_pseudo));
96*d8b80295SApple OSS Distributions payload = (char *)(eh_p + 1) + sizeof(*ip_udp);
97*d8b80295SApple OSS Distributions
98*d8b80295SApple OSS Distributions /* ethernet_header */
99*d8b80295SApple OSS Distributions bcopy(src, eh_p->ether_shost, ETHER_ADDR_LEN);
100*d8b80295SApple OSS Distributions bcopy(dst, eh_p->ether_dhost, ETHER_ADDR_LEN);
101*d8b80295SApple OSS Distributions eh_p->ether_type = htons(ETHERTYPE_IP);
102*d8b80295SApple OSS Distributions
103*d8b80295SApple OSS Distributions /* copy the data */
104*d8b80295SApple OSS Distributions bcopy(data, payload, data_len);
105*d8b80295SApple OSS Distributions
106*d8b80295SApple OSS Distributions /* fill in UDP pseudo header (gets overwritten by IP header below) */
107*d8b80295SApple OSS Distributions bcopy(&src_ip, &udp_pseudo->src_ip, sizeof(src_ip));
108*d8b80295SApple OSS Distributions bcopy(&dst_ip, &udp_pseudo->dst_ip, sizeof(dst_ip));
109*d8b80295SApple OSS Distributions udp_pseudo->zero = 0;
110*d8b80295SApple OSS Distributions udp_pseudo->proto = IPPROTO_UDP;
111*d8b80295SApple OSS Distributions udp_pseudo->length = htons(sizeof(ip_udp->udp) + data_len);
112*d8b80295SApple OSS Distributions
113*d8b80295SApple OSS Distributions /* fill in UDP header */
114*d8b80295SApple OSS Distributions ip_udp->udp.uh_sport = htons(src_port);
115*d8b80295SApple OSS Distributions ip_udp->udp.uh_dport = htons(dst_port);
116*d8b80295SApple OSS Distributions ip_udp->udp.uh_ulen = htons(sizeof(ip_udp->udp) + data_len);
117*d8b80295SApple OSS Distributions ip_udp->udp.uh_sum = 0;
118*d8b80295SApple OSS Distributions ip_udp->udp.uh_sum = in_cksum(udp_pseudo, (int)(sizeof(*udp_pseudo)
119*d8b80295SApple OSS Distributions + sizeof(ip_udp->udp) + data_len));
120*d8b80295SApple OSS Distributions
121*d8b80295SApple OSS Distributions /* fill in IP header */
122*d8b80295SApple OSS Distributions bzero(ip_udp, sizeof(ip_udp->ip));
123*d8b80295SApple OSS Distributions ip_udp->ip.ip_v = IPVERSION;
124*d8b80295SApple OSS Distributions ip_udp->ip.ip_hl = sizeof(struct ip) >> 2;
125*d8b80295SApple OSS Distributions ip_udp->ip.ip_ttl = MAXTTL;
126*d8b80295SApple OSS Distributions ip_udp->ip.ip_p = IPPROTO_UDP;
127*d8b80295SApple OSS Distributions bcopy(&src_ip, &ip_udp->ip.ip_src, sizeof(src_ip));
128*d8b80295SApple OSS Distributions bcopy(&dst_ip, &ip_udp->ip.ip_dst, sizeof(dst_ip));
129*d8b80295SApple OSS Distributions ip_udp->ip.ip_len = htons(sizeof(*ip_udp) + data_len);
130*d8b80295SApple OSS Distributions ip_udp->ip.ip_id = htons(ip_id++);
131*d8b80295SApple OSS Distributions
132*d8b80295SApple OSS Distributions /* compute the IP checksum */
133*d8b80295SApple OSS Distributions ip_udp->ip.ip_sum = 0; /* needs to be zero for checksum */
134*d8b80295SApple OSS Distributions ip_udp->ip.ip_sum = in_cksum(&ip_udp->ip, sizeof(ip_udp->ip));
135*d8b80295SApple OSS Distributions
136*d8b80295SApple OSS Distributions return frame_length;
137*d8b80295SApple OSS Distributions }
138*d8b80295SApple OSS Distributions
139*d8b80295SApple 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)140*d8b80295SApple OSS Distributions ethernet_udp6_frame_populate(void * buf, size_t buf_len,
141*d8b80295SApple OSS Distributions const ether_addr_t * src,
142*d8b80295SApple OSS Distributions struct in6_addr *src_ip,
143*d8b80295SApple OSS Distributions uint16_t src_port,
144*d8b80295SApple OSS Distributions const ether_addr_t * dst,
145*d8b80295SApple OSS Distributions struct in6_addr * dst_ip,
146*d8b80295SApple OSS Distributions uint16_t dst_port,
147*d8b80295SApple OSS Distributions const void * data, u_int data_len)
148*d8b80295SApple OSS Distributions {
149*d8b80295SApple OSS Distributions ether_header_t * eh_p;
150*d8b80295SApple OSS Distributions u_int frame_length;
151*d8b80295SApple OSS Distributions ip6_udp_header_t * ip6_udp;
152*d8b80295SApple OSS Distributions char * payload;
153*d8b80295SApple OSS Distributions udp6_pseudo_hdr_t * udp6_pseudo;
154*d8b80295SApple OSS Distributions
155*d8b80295SApple OSS Distributions frame_length = (u_int)(sizeof(*eh_p) + sizeof(*ip6_udp)) + data_len;
156*d8b80295SApple OSS Distributions if (buf_len < frame_length) {
157*d8b80295SApple OSS Distributions return 0;
158*d8b80295SApple OSS Distributions }
159*d8b80295SApple OSS Distributions
160*d8b80295SApple OSS Distributions /* determine frame offsets */
161*d8b80295SApple OSS Distributions eh_p = (ether_header_t *)buf;
162*d8b80295SApple OSS Distributions ip6_udp = (ip6_udp_header_t *)(void *)(eh_p + 1);
163*d8b80295SApple OSS Distributions udp6_pseudo = (udp6_pseudo_hdr_t *)(void *)
164*d8b80295SApple OSS Distributions (((char *)&ip6_udp->udp) - sizeof(*udp6_pseudo));
165*d8b80295SApple OSS Distributions payload = (char *)(eh_p + 1) + sizeof(*ip6_udp);
166*d8b80295SApple OSS Distributions
167*d8b80295SApple OSS Distributions /* ethernet_header */
168*d8b80295SApple OSS Distributions bcopy(src, eh_p->ether_shost, ETHER_ADDR_LEN);
169*d8b80295SApple OSS Distributions bcopy(dst, eh_p->ether_dhost, ETHER_ADDR_LEN);
170*d8b80295SApple OSS Distributions eh_p->ether_type = htons(ETHERTYPE_IPV6);
171*d8b80295SApple OSS Distributions
172*d8b80295SApple OSS Distributions /* copy the data */
173*d8b80295SApple OSS Distributions bcopy(data, payload, data_len);
174*d8b80295SApple OSS Distributions
175*d8b80295SApple OSS Distributions /* fill in UDP pseudo header (gets overwritten by IP header below) */
176*d8b80295SApple OSS Distributions bcopy(src_ip, &udp6_pseudo->src_ip, sizeof(*src_ip));
177*d8b80295SApple OSS Distributions bcopy(dst_ip, &udp6_pseudo->dst_ip, sizeof(*dst_ip));
178*d8b80295SApple OSS Distributions udp6_pseudo->zero = 0;
179*d8b80295SApple OSS Distributions udp6_pseudo->proto = IPPROTO_UDP;
180*d8b80295SApple OSS Distributions udp6_pseudo->length = htons(sizeof(ip6_udp->udp) + data_len);
181*d8b80295SApple OSS Distributions
182*d8b80295SApple OSS Distributions /* fill in UDP header */
183*d8b80295SApple OSS Distributions ip6_udp->udp.uh_sport = htons(src_port);
184*d8b80295SApple OSS Distributions ip6_udp->udp.uh_dport = htons(dst_port);
185*d8b80295SApple OSS Distributions ip6_udp->udp.uh_ulen = htons(sizeof(ip6_udp->udp) + data_len);
186*d8b80295SApple OSS Distributions ip6_udp->udp.uh_sum = 0;
187*d8b80295SApple OSS Distributions ip6_udp->udp.uh_sum = in_cksum(udp6_pseudo, (int)(sizeof(*udp6_pseudo)
188*d8b80295SApple OSS Distributions + sizeof(ip6_udp->udp) + data_len));
189*d8b80295SApple OSS Distributions
190*d8b80295SApple OSS Distributions /* fill in IP header */
191*d8b80295SApple OSS Distributions bzero(&ip6_udp->ip6, sizeof(ip6_udp->ip6));
192*d8b80295SApple OSS Distributions ip6_udp->ip6.ip6_vfc = IPV6_VERSION;
193*d8b80295SApple OSS Distributions ip6_udp->ip6.ip6_nxt = IPPROTO_UDP;
194*d8b80295SApple OSS Distributions bcopy(src_ip, &ip6_udp->ip6.ip6_src, sizeof(*src_ip));
195*d8b80295SApple OSS Distributions bcopy(dst_ip, &ip6_udp->ip6.ip6_dst, sizeof(*dst_ip));
196*d8b80295SApple OSS Distributions ip6_udp->ip6.ip6_plen = htons(sizeof(struct udphdr) + data_len);
197*d8b80295SApple OSS Distributions /* ip6_udp->ip6.ip6_flow = ? */
198*d8b80295SApple OSS Distributions return frame_length;
199*d8b80295SApple OSS Distributions }
200*d8b80295SApple OSS Distributions
201*d8b80295SApple OSS Distributions /**
202*d8b80295SApple OSS Distributions ** interface management
203*d8b80295SApple OSS Distributions **/
204*d8b80295SApple OSS Distributions
205*d8b80295SApple OSS Distributions void
ifnet_get_lladdr(int s,const char * ifname,ether_addr_t * eaddr)206*d8b80295SApple OSS Distributions ifnet_get_lladdr(int s, const char * ifname, ether_addr_t * eaddr)
207*d8b80295SApple OSS Distributions {
208*d8b80295SApple OSS Distributions int err;
209*d8b80295SApple OSS Distributions struct ifreq ifr;
210*d8b80295SApple OSS Distributions
211*d8b80295SApple OSS Distributions bzero(&ifr, sizeof(ifr));
212*d8b80295SApple OSS Distributions strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
213*d8b80295SApple OSS Distributions ifr.ifr_addr.sa_family = AF_LINK;
214*d8b80295SApple OSS Distributions ifr.ifr_addr.sa_len = ETHER_ADDR_LEN;
215*d8b80295SApple OSS Distributions err = ioctl(s, SIOCGIFLLADDR, &ifr);
216*d8b80295SApple OSS Distributions T_QUIET;
217*d8b80295SApple OSS Distributions T_ASSERT_POSIX_SUCCESS(err, "SIOCGIFLLADDR %s", ifname);
218*d8b80295SApple OSS Distributions bcopy(ifr.ifr_addr.sa_data, eaddr->octet, ETHER_ADDR_LEN);
219*d8b80295SApple OSS Distributions return;
220*d8b80295SApple OSS Distributions }
221*d8b80295SApple OSS Distributions
222*d8b80295SApple OSS Distributions
223*d8b80295SApple OSS Distributions int
ifnet_attach_ip(int s,char * name)224*d8b80295SApple OSS Distributions ifnet_attach_ip(int s, char * name)
225*d8b80295SApple OSS Distributions {
226*d8b80295SApple OSS Distributions int err;
227*d8b80295SApple OSS Distributions struct ifreq ifr;
228*d8b80295SApple OSS Distributions
229*d8b80295SApple OSS Distributions bzero(&ifr, sizeof(ifr));
230*d8b80295SApple OSS Distributions strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
231*d8b80295SApple OSS Distributions err = ioctl(s, SIOCPROTOATTACH, &ifr);
232*d8b80295SApple OSS Distributions T_QUIET;
233*d8b80295SApple OSS Distributions T_ASSERT_POSIX_SUCCESS(err, "SIOCPROTOATTACH %s", ifr.ifr_name);
234*d8b80295SApple OSS Distributions return err;
235*d8b80295SApple OSS Distributions }
236*d8b80295SApple OSS Distributions
237*d8b80295SApple OSS Distributions int
ifnet_destroy(int s,const char * ifname,bool fail_on_error)238*d8b80295SApple OSS Distributions ifnet_destroy(int s, const char * ifname, bool fail_on_error)
239*d8b80295SApple OSS Distributions {
240*d8b80295SApple OSS Distributions int err;
241*d8b80295SApple OSS Distributions struct ifreq ifr;
242*d8b80295SApple OSS Distributions
243*d8b80295SApple OSS Distributions bzero(&ifr, sizeof(ifr));
244*d8b80295SApple OSS Distributions strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
245*d8b80295SApple OSS Distributions err = ioctl(s, SIOCIFDESTROY, &ifr);
246*d8b80295SApple OSS Distributions if (fail_on_error) {
247*d8b80295SApple OSS Distributions T_QUIET;
248*d8b80295SApple OSS Distributions T_ASSERT_POSIX_SUCCESS(err, "SIOCSIFDESTROY %s", ifr.ifr_name);
249*d8b80295SApple OSS Distributions }
250*d8b80295SApple OSS Distributions if (err < 0) {
251*d8b80295SApple OSS Distributions T_LOG("SIOCSIFDESTROY %s", ifr.ifr_name);
252*d8b80295SApple OSS Distributions }
253*d8b80295SApple OSS Distributions return err;
254*d8b80295SApple OSS Distributions }
255*d8b80295SApple OSS Distributions
256*d8b80295SApple OSS Distributions int
ifnet_set_flags(int s,const char * ifname,uint16_t flags_set,uint16_t flags_clear)257*d8b80295SApple OSS Distributions ifnet_set_flags(int s, const char * ifname,
258*d8b80295SApple OSS Distributions uint16_t flags_set, uint16_t flags_clear)
259*d8b80295SApple OSS Distributions {
260*d8b80295SApple OSS Distributions uint16_t flags_after;
261*d8b80295SApple OSS Distributions uint16_t flags_before;
262*d8b80295SApple OSS Distributions struct ifreq ifr;
263*d8b80295SApple OSS Distributions int ret;
264*d8b80295SApple OSS Distributions
265*d8b80295SApple OSS Distributions bzero(&ifr, sizeof(ifr));
266*d8b80295SApple OSS Distributions strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
267*d8b80295SApple OSS Distributions ret = ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr);
268*d8b80295SApple OSS Distributions if (ret != 0) {
269*d8b80295SApple OSS Distributions T_LOG("SIOCGIFFLAGS %s", ifr.ifr_name);
270*d8b80295SApple OSS Distributions return ret;
271*d8b80295SApple OSS Distributions }
272*d8b80295SApple OSS Distributions flags_before = (uint16_t)ifr.ifr_flags;
273*d8b80295SApple OSS Distributions ifr.ifr_flags |= flags_set;
274*d8b80295SApple OSS Distributions ifr.ifr_flags &= ~(flags_clear);
275*d8b80295SApple OSS Distributions flags_after = (uint16_t)ifr.ifr_flags;
276*d8b80295SApple OSS Distributions if (flags_before == flags_after) {
277*d8b80295SApple OSS Distributions /* nothing to do */
278*d8b80295SApple OSS Distributions ret = 0;
279*d8b80295SApple OSS Distributions } else {
280*d8b80295SApple OSS Distributions /* issue the ioctl */
281*d8b80295SApple OSS Distributions T_QUIET;
282*d8b80295SApple OSS Distributions T_ASSERT_POSIX_SUCCESS(ioctl(s, SIOCSIFFLAGS, &ifr),
283*d8b80295SApple OSS Distributions "SIOCSIFFLAGS %s 0x%x",
284*d8b80295SApple OSS Distributions ifr.ifr_name, (uint16_t)ifr.ifr_flags);
285*d8b80295SApple OSS Distributions if (S_debug) {
286*d8b80295SApple OSS Distributions T_LOG("setflags(%s set 0x%x clear 0x%x) 0x%x => 0x%x",
287*d8b80295SApple OSS Distributions ifr.ifr_name, flags_set, flags_clear,
288*d8b80295SApple OSS Distributions flags_before, flags_after);
289*d8b80295SApple OSS Distributions }
290*d8b80295SApple OSS Distributions }
291*d8b80295SApple OSS Distributions return ret;
292*d8b80295SApple OSS Distributions }
293*d8b80295SApple OSS Distributions
294*d8b80295SApple OSS Distributions #define FETH_NAME "feth"
295*d8b80295SApple OSS Distributions
296*d8b80295SApple OSS Distributions /* On some platforms with DEBUG kernel, we need to wait a while */
297*d8b80295SApple OSS Distributions #define SIFCREATE_RETRY 600
298*d8b80295SApple OSS Distributions
299*d8b80295SApple OSS Distributions static int
ifnet_create_common(int s,const char * ifname,char * ifname_out,size_t ifname_out_len)300*d8b80295SApple OSS Distributions ifnet_create_common(int s, const char * ifname, char *ifname_out, size_t ifname_out_len)
301*d8b80295SApple OSS Distributions {
302*d8b80295SApple OSS Distributions int error = 0;
303*d8b80295SApple OSS Distributions struct ifreq ifr;
304*d8b80295SApple OSS Distributions
305*d8b80295SApple OSS Distributions bzero(&ifr, sizeof(ifr));
306*d8b80295SApple OSS Distributions strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
307*d8b80295SApple OSS Distributions
308*d8b80295SApple OSS Distributions for (int i = 0; i < SIFCREATE_RETRY; i++) {
309*d8b80295SApple OSS Distributions if (ioctl(s, SIOCIFCREATE, &ifr) < 0) {
310*d8b80295SApple OSS Distributions error = errno;
311*d8b80295SApple OSS Distributions T_LOG("SIOCSIFCREATE %s: %s", ifname,
312*d8b80295SApple OSS Distributions strerror(error));
313*d8b80295SApple OSS Distributions if (error == EBUSY) {
314*d8b80295SApple OSS Distributions /* interface is tearing down, try again */
315*d8b80295SApple OSS Distributions usleep(10000);
316*d8b80295SApple OSS Distributions } else if (error == EEXIST) {
317*d8b80295SApple OSS Distributions /* interface exists, try destroying it */
318*d8b80295SApple OSS Distributions (void)ifnet_destroy(s, ifname, false);
319*d8b80295SApple OSS Distributions } else {
320*d8b80295SApple OSS Distributions /* unexpected failure */
321*d8b80295SApple OSS Distributions break;
322*d8b80295SApple OSS Distributions }
323*d8b80295SApple OSS Distributions } else {
324*d8b80295SApple OSS Distributions if (ifname_out != NULL) {
325*d8b80295SApple OSS Distributions strlcpy(ifname_out, ifr.ifr_name, ifname_out_len);
326*d8b80295SApple OSS Distributions }
327*d8b80295SApple OSS Distributions error = 0;
328*d8b80295SApple OSS Distributions break;
329*d8b80295SApple OSS Distributions }
330*d8b80295SApple OSS Distributions }
331*d8b80295SApple OSS Distributions if (error == 0) {
332*d8b80295SApple OSS Distributions error = ifnet_set_flags(s, ifname, IFF_UP, 0);
333*d8b80295SApple OSS Distributions }
334*d8b80295SApple OSS Distributions return error;
335*d8b80295SApple OSS Distributions }
336*d8b80295SApple OSS Distributions
337*d8b80295SApple OSS Distributions int
ifnet_create(int s,const char * ifname)338*d8b80295SApple OSS Distributions ifnet_create(int s, const char * ifname)
339*d8b80295SApple OSS Distributions {
340*d8b80295SApple OSS Distributions return ifnet_create_common(s, ifname, NULL, 0);
341*d8b80295SApple OSS Distributions }
342*d8b80295SApple OSS Distributions
343*d8b80295SApple OSS Distributions int
ifnet_create_2(int s,char * ifname,size_t len)344*d8b80295SApple OSS Distributions ifnet_create_2(int s, char * ifname, size_t len)
345*d8b80295SApple OSS Distributions {
346*d8b80295SApple OSS Distributions return ifnet_create_common(s, ifname, ifname, len);
347*d8b80295SApple OSS Distributions }
348*d8b80295SApple OSS Distributions
349*d8b80295SApple OSS Distributions int
siocdrvspec(int s,const char * ifname,u_long op,void * arg,size_t argsize,bool set)350*d8b80295SApple OSS Distributions siocdrvspec(int s, const char * ifname,
351*d8b80295SApple OSS Distributions u_long op, void *arg, size_t argsize, bool set)
352*d8b80295SApple OSS Distributions {
353*d8b80295SApple OSS Distributions struct ifdrv ifd;
354*d8b80295SApple OSS Distributions
355*d8b80295SApple OSS Distributions memset(&ifd, 0, sizeof(ifd));
356*d8b80295SApple OSS Distributions strlcpy(ifd.ifd_name, ifname, sizeof(ifd.ifd_name));
357*d8b80295SApple OSS Distributions ifd.ifd_cmd = op;
358*d8b80295SApple OSS Distributions ifd.ifd_len = argsize;
359*d8b80295SApple OSS Distributions ifd.ifd_data = arg;
360*d8b80295SApple OSS Distributions return ioctl(s, set ? SIOCSDRVSPEC : SIOCGDRVSPEC, &ifd);
361*d8b80295SApple OSS Distributions }
362*d8b80295SApple OSS Distributions
363*d8b80295SApple OSS Distributions int
fake_set_peer(int s,const char * feth,const char * feth_peer)364*d8b80295SApple OSS Distributions fake_set_peer(int s, const char * feth, const char * feth_peer)
365*d8b80295SApple OSS Distributions {
366*d8b80295SApple OSS Distributions struct if_fake_request iffr;
367*d8b80295SApple OSS Distributions int ret;
368*d8b80295SApple OSS Distributions
369*d8b80295SApple OSS Distributions bzero((char *)&iffr, sizeof(iffr));
370*d8b80295SApple OSS Distributions if (feth_peer != NULL) {
371*d8b80295SApple OSS Distributions strlcpy(iffr.iffr_peer_name, feth_peer,
372*d8b80295SApple OSS Distributions sizeof(iffr.iffr_peer_name));
373*d8b80295SApple OSS Distributions }
374*d8b80295SApple OSS Distributions ret = siocdrvspec(s, feth, IF_FAKE_S_CMD_SET_PEER,
375*d8b80295SApple OSS Distributions &iffr, sizeof(iffr), true);
376*d8b80295SApple OSS Distributions T_QUIET;
377*d8b80295SApple OSS Distributions T_ASSERT_POSIX_SUCCESS(ret,
378*d8b80295SApple OSS Distributions "SIOCDRVSPEC(%s, IF_FAKE_S_CMD_SET_PEER, %s)",
379*d8b80295SApple OSS Distributions feth, (feth_peer != NULL) ? feth_peer : "<none>");
380*d8b80295SApple OSS Distributions return ret;
381*d8b80295SApple OSS Distributions }
382*d8b80295SApple OSS Distributions
383*d8b80295SApple OSS Distributions u_int
make_dhcp_payload(dhcp_min_payload_t payload,ether_addr_t * eaddr)384*d8b80295SApple OSS Distributions make_dhcp_payload(dhcp_min_payload_t payload, ether_addr_t *eaddr)
385*d8b80295SApple OSS Distributions {
386*d8b80295SApple OSS Distributions struct bootp * dhcp;
387*d8b80295SApple OSS Distributions u_int payload_length;
388*d8b80295SApple OSS Distributions
389*d8b80295SApple OSS Distributions /* create a minimal BOOTP packet */
390*d8b80295SApple OSS Distributions payload_length = sizeof(*payload);
391*d8b80295SApple OSS Distributions dhcp = (struct bootp *)payload;
392*d8b80295SApple OSS Distributions bzero(dhcp, payload_length);
393*d8b80295SApple OSS Distributions dhcp->bp_op = BOOTREQUEST;
394*d8b80295SApple OSS Distributions dhcp->bp_htype = ARPHRD_ETHER;
395*d8b80295SApple OSS Distributions dhcp->bp_hlen = sizeof(*eaddr);
396*d8b80295SApple OSS Distributions bcopy(eaddr->octet, dhcp->bp_chaddr, sizeof(eaddr->octet));
397*d8b80295SApple OSS Distributions return payload_length;
398*d8b80295SApple OSS Distributions }
399