1*d8b80295SApple OSS Distributions /*
2*d8b80295SApple OSS Distributions * Copyright (c) 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 <darwintest.h>
30*d8b80295SApple OSS Distributions
31*d8b80295SApple OSS Distributions #include <sys/ioctl.h>
32*d8b80295SApple OSS Distributions #include <sys/sysctl.h>
33*d8b80295SApple OSS Distributions #include <sys/uio.h>
34*d8b80295SApple OSS Distributions
35*d8b80295SApple OSS Distributions #include <net/if.h>
36*d8b80295SApple OSS Distributions #include <net/if_arp.h>
37*d8b80295SApple OSS Distributions #include <net/if_fake_var.h>
38*d8b80295SApple OSS Distributions #include <net/bpf.h>
39*d8b80295SApple OSS Distributions #include <net/ethernet.h>
40*d8b80295SApple OSS Distributions
41*d8b80295SApple OSS Distributions #include <netinet/ip.h>
42*d8b80295SApple OSS Distributions
43*d8b80295SApple OSS Distributions #include <stdlib.h>
44*d8b80295SApple OSS Distributions #include <string.h>
45*d8b80295SApple OSS Distributions #include <strings.h>
46*d8b80295SApple OSS Distributions
47*d8b80295SApple OSS Distributions #include "net_test_lib.h"
48*d8b80295SApple OSS Distributions #include "bpflib.h"
49*d8b80295SApple OSS Distributions #include "in_cksum.h"
50*d8b80295SApple OSS Distributions
51*d8b80295SApple OSS Distributions T_GLOBAL_META(
52*d8b80295SApple OSS Distributions T_META_NAMESPACE("xnu.net"),
53*d8b80295SApple OSS Distributions T_META_ASROOT(true),
54*d8b80295SApple OSS Distributions T_META_RADAR_COMPONENT_NAME("xnu"),
55*d8b80295SApple OSS Distributions T_META_RADAR_COMPONENT_VERSION("networking"),
56*d8b80295SApple OSS Distributions T_META_CHECK_LEAKS(false));
57*d8b80295SApple OSS Distributions
58*d8b80295SApple OSS Distributions #define MAXBUF 32
59*d8b80295SApple OSS Distributions static void
HexDump(void * data,size_t len)60*d8b80295SApple OSS Distributions HexDump(void *data, size_t len)
61*d8b80295SApple OSS Distributions {
62*d8b80295SApple OSS Distributions size_t i, j, k;
63*d8b80295SApple OSS Distributions unsigned char *ptr = (unsigned char *)data;
64*d8b80295SApple OSS Distributions unsigned char buf[3 * MAXBUF + 1];
65*d8b80295SApple OSS Distributions
66*d8b80295SApple OSS Distributions for (i = 0; i < len; i += MAXBUF) {
67*d8b80295SApple OSS Distributions for (j = i, k = 0; j < i + MAXBUF && j < len; j++) {
68*d8b80295SApple OSS Distributions unsigned char msnbl = ptr[j] >> 4;
69*d8b80295SApple OSS Distributions unsigned char lsnbl = ptr[j] & 0x0f;
70*d8b80295SApple OSS Distributions
71*d8b80295SApple OSS Distributions buf[k++] = msnbl < 10 ? msnbl + '0' : msnbl + 'a' - 10;
72*d8b80295SApple OSS Distributions buf[k++] = lsnbl < 10 ? lsnbl + '0' : lsnbl + 'a' - 10;
73*d8b80295SApple OSS Distributions if ((j % 2) == 1) {
74*d8b80295SApple OSS Distributions buf[k++] = ' ';
75*d8b80295SApple OSS Distributions }
76*d8b80295SApple OSS Distributions if ((j % MAXBUF) == MAXBUF - 1) {
77*d8b80295SApple OSS Distributions buf[k++] = ' ';
78*d8b80295SApple OSS Distributions }
79*d8b80295SApple OSS Distributions }
80*d8b80295SApple OSS Distributions buf[k] = 0;
81*d8b80295SApple OSS Distributions T_LOG("%5zd: %s\n", i, buf);
82*d8b80295SApple OSS Distributions }
83*d8b80295SApple OSS Distributions }
84*d8b80295SApple OSS Distributions
85*d8b80295SApple OSS Distributions static int udp_fd = -1;
86*d8b80295SApple OSS Distributions static char ifname1[IF_NAMESIZE];
87*d8b80295SApple OSS Distributions static char ifname2[IF_NAMESIZE];
88*d8b80295SApple OSS Distributions static int default_fake_max_mtu = 0;
89*d8b80295SApple OSS Distributions
90*d8b80295SApple OSS Distributions static void
cleanup(void)91*d8b80295SApple OSS Distributions cleanup(void)
92*d8b80295SApple OSS Distributions {
93*d8b80295SApple OSS Distributions if (udp_fd != -1) {
94*d8b80295SApple OSS Distributions (void)ifnet_destroy(udp_fd, ifname1, false);
95*d8b80295SApple OSS Distributions T_LOG("ifnet_destroy %s", ifname1);
96*d8b80295SApple OSS Distributions
97*d8b80295SApple OSS Distributions (void)ifnet_destroy(udp_fd, ifname2, false);
98*d8b80295SApple OSS Distributions T_LOG("ifnet_destroy %s", ifname2);
99*d8b80295SApple OSS Distributions }
100*d8b80295SApple OSS Distributions
101*d8b80295SApple OSS Distributions if (default_fake_max_mtu != 0) {
102*d8b80295SApple OSS Distributions T_LOG("sysctl net.link.fake.max_mtu=%d", default_fake_max_mtu);
103*d8b80295SApple OSS Distributions (void) sysctlbyname("net.link.fake.max_mtu", NULL, NULL, &default_fake_max_mtu, sizeof(int));
104*d8b80295SApple OSS Distributions }
105*d8b80295SApple OSS Distributions
106*d8b80295SApple OSS Distributions if (udp_fd != -1) {
107*d8b80295SApple OSS Distributions (void) close(udp_fd);
108*d8b80295SApple OSS Distributions }
109*d8b80295SApple OSS Distributions }
110*d8b80295SApple OSS Distributions
111*d8b80295SApple OSS Distributions static void
init(int mtu)112*d8b80295SApple OSS Distributions init(int mtu)
113*d8b80295SApple OSS Distributions {
114*d8b80295SApple OSS Distributions T_ATEND(cleanup);
115*d8b80295SApple OSS Distributions
116*d8b80295SApple OSS Distributions udp_fd = inet_dgram_socket();
117*d8b80295SApple OSS Distributions
118*d8b80295SApple OSS Distributions if (mtu > 0) {
119*d8b80295SApple OSS Distributions size_t oldlen = sizeof(int);
120*d8b80295SApple OSS Distributions T_ASSERT_POSIX_SUCCESS(sysctlbyname("net.link.fake.max_mtu", &default_fake_max_mtu, &oldlen, &mtu, sizeof(int)),
121*d8b80295SApple OSS Distributions "sysctl net.link.fake.max_mtu %d -> %d", default_fake_max_mtu, mtu);
122*d8b80295SApple OSS Distributions }
123*d8b80295SApple OSS Distributions }
124*d8b80295SApple OSS Distributions
125*d8b80295SApple OSS Distributions static int
set_if_mtu(const char * ifname,int mtu)126*d8b80295SApple OSS Distributions set_if_mtu(const char *ifname, int mtu)
127*d8b80295SApple OSS Distributions {
128*d8b80295SApple OSS Distributions int error = 0;
129*d8b80295SApple OSS Distributions struct ifreq ifr = {};
130*d8b80295SApple OSS Distributions
131*d8b80295SApple OSS Distributions strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
132*d8b80295SApple OSS Distributions ifr.ifr_mtu = mtu;
133*d8b80295SApple OSS Distributions
134*d8b80295SApple OSS Distributions T_ASSERT_POSIX_SUCCESS(ioctl(udp_fd, SIOCSIFMTU, (caddr_t)&ifr), NULL);
135*d8b80295SApple OSS Distributions
136*d8b80295SApple OSS Distributions return error;
137*d8b80295SApple OSS Distributions }
138*d8b80295SApple OSS Distributions
139*d8b80295SApple OSS Distributions static int
setup_feth_pair(int mtu)140*d8b80295SApple OSS Distributions setup_feth_pair(int mtu)
141*d8b80295SApple OSS Distributions {
142*d8b80295SApple OSS Distributions int error = 0;
143*d8b80295SApple OSS Distributions
144*d8b80295SApple OSS Distributions strlcpy(ifname1, FETH_NAME, sizeof(ifname1));
145*d8b80295SApple OSS Distributions error = ifnet_create_2(udp_fd, ifname1, sizeof(ifname1));
146*d8b80295SApple OSS Distributions if (error != 0) {
147*d8b80295SApple OSS Distributions goto done;
148*d8b80295SApple OSS Distributions }
149*d8b80295SApple OSS Distributions T_LOG("created %s", ifname1);
150*d8b80295SApple OSS Distributions
151*d8b80295SApple OSS Distributions strlcpy(ifname2, FETH_NAME, sizeof(ifname2));
152*d8b80295SApple OSS Distributions error = ifnet_create_2(udp_fd, ifname2, sizeof(ifname2));
153*d8b80295SApple OSS Distributions if (error != 0) {
154*d8b80295SApple OSS Distributions goto done;
155*d8b80295SApple OSS Distributions }
156*d8b80295SApple OSS Distributions T_LOG("created %s", ifname2);
157*d8b80295SApple OSS Distributions
158*d8b80295SApple OSS Distributions ifnet_attach_ip(udp_fd, ifname1);
159*d8b80295SApple OSS Distributions
160*d8b80295SApple OSS Distributions if ((error = fake_set_peer(udp_fd, ifname1, ifname2)) != 0) {
161*d8b80295SApple OSS Distributions goto done;
162*d8b80295SApple OSS Distributions }
163*d8b80295SApple OSS Distributions if (mtu != 0) {
164*d8b80295SApple OSS Distributions set_if_mtu(ifname1, mtu);
165*d8b80295SApple OSS Distributions set_if_mtu(ifname2, mtu);
166*d8b80295SApple OSS Distributions }
167*d8b80295SApple OSS Distributions done:
168*d8b80295SApple OSS Distributions return error;
169*d8b80295SApple OSS Distributions }
170*d8b80295SApple OSS Distributions
171*d8b80295SApple OSS Distributions static int
create_bpf_on_interface(const char * ifname,int * out_fd,int * out_bdlen,u_int write_size_max)172*d8b80295SApple OSS Distributions create_bpf_on_interface(const char *ifname, int *out_fd, int *out_bdlen, u_int write_size_max)
173*d8b80295SApple OSS Distributions {
174*d8b80295SApple OSS Distributions int bpf_fd = -1;
175*d8b80295SApple OSS Distributions int error = 0;
176*d8b80295SApple OSS Distributions int bdlen = 0;
177*d8b80295SApple OSS Distributions u_int value;
178*d8b80295SApple OSS Distributions
179*d8b80295SApple OSS Distributions bpf_fd = bpf_new();
180*d8b80295SApple OSS Distributions if (bpf_fd < 0) {
181*d8b80295SApple OSS Distributions error = errno;
182*d8b80295SApple OSS Distributions T_LOG("bpf_new");
183*d8b80295SApple OSS Distributions goto done;
184*d8b80295SApple OSS Distributions }
185*d8b80295SApple OSS Distributions T_ASSERT_POSIX_SUCCESS(bpf_set_blen(bpf_fd, 128 * 1024), NULL);
186*d8b80295SApple OSS Distributions
187*d8b80295SApple OSS Distributions T_ASSERT_POSIX_SUCCESS(bpf_get_blen(bpf_fd, &bdlen), NULL);
188*d8b80295SApple OSS Distributions
189*d8b80295SApple OSS Distributions T_ASSERT_POSIX_SUCCESS(bpf_set_immediate(bpf_fd, 1), NULL);
190*d8b80295SApple OSS Distributions
191*d8b80295SApple OSS Distributions T_ASSERT_POSIX_SUCCESS(bpf_setif(bpf_fd, ifname), "bpf set if %s",
192*d8b80295SApple OSS Distributions ifname1);
193*d8b80295SApple OSS Distributions
194*d8b80295SApple OSS Distributions T_ASSERT_POSIX_SUCCESS(bpf_set_see_sent(bpf_fd, 1), NULL);
195*d8b80295SApple OSS Distributions
196*d8b80295SApple OSS Distributions T_ASSERT_POSIX_SUCCESS(bpf_set_header_complete(bpf_fd, 1), NULL);
197*d8b80295SApple OSS Distributions
198*d8b80295SApple OSS Distributions #ifdef BIOCSWRITEMAX
199*d8b80295SApple OSS Distributions T_ASSERT_POSIX_SUCCESS(bpf_set_write_size_max(bpf_fd, write_size_max), NULL);
200*d8b80295SApple OSS Distributions
201*d8b80295SApple OSS Distributions T_ASSERT_POSIX_SUCCESS(bpf_get_write_size_max(bpf_fd, &value), NULL);
202*d8b80295SApple OSS Distributions
203*d8b80295SApple OSS Distributions T_LOG("write_size_max %u %s value %u", write_size_max, write_size_max != value ? "!=" : "==", value);
204*d8b80295SApple OSS Distributions #else
205*d8b80295SApple OSS Distributions if (write_size_max > 0) {
206*d8b80295SApple OSS Distributions T_SKIP("BIOCSWRITEMAX not supported");
207*d8b80295SApple OSS Distributions }
208*d8b80295SApple OSS Distributions #endif
209*d8b80295SApple OSS Distributions
210*d8b80295SApple OSS Distributions #ifdef BIOCSBATCHWRITE
211*d8b80295SApple OSS Distributions T_ASSERT_POSIX_SUCCESS(bpf_set_batch_write(bpf_fd, 1), NULL);
212*d8b80295SApple OSS Distributions
213*d8b80295SApple OSS Distributions T_ASSERT_POSIX_SUCCESS(bpf_get_batch_write(bpf_fd, &value), NULL);
214*d8b80295SApple OSS Distributions
215*d8b80295SApple OSS Distributions T_LOG("batch_write %u %s 1", value, value != 1 ? "!=" : "==");
216*d8b80295SApple OSS Distributions #else
217*d8b80295SApple OSS Distributions T_SKIP("BIOCSBATCHWRITE not supported");
218*d8b80295SApple OSS Distributions #endif
219*d8b80295SApple OSS Distributions
220*d8b80295SApple OSS Distributions struct timeval five_seconds = { .tv_sec = 5, .tv_usec = 0 };
221*d8b80295SApple OSS Distributions T_ASSERT_POSIX_SUCCESS(bpf_set_timeout(bpf_fd, &five_seconds), NULL);
222*d8b80295SApple OSS Distributions
223*d8b80295SApple OSS Distributions done:
224*d8b80295SApple OSS Distributions *out_bdlen = bdlen;
225*d8b80295SApple OSS Distributions *out_fd = bpf_fd;
226*d8b80295SApple OSS Distributions return error;
227*d8b80295SApple OSS Distributions }
228*d8b80295SApple OSS Distributions
229*d8b80295SApple OSS Distributions static void
make_bootp_packet(struct iovec * iov,u_int ip_len,int id)230*d8b80295SApple OSS Distributions make_bootp_packet(struct iovec *iov, u_int ip_len, int id)
231*d8b80295SApple OSS Distributions {
232*d8b80295SApple OSS Distributions u_int payload_len;
233*d8b80295SApple OSS Distributions
234*d8b80295SApple OSS Distributions if (ip_len == 0) {
235*d8b80295SApple OSS Distributions payload_len = (u_int)sizeof(dhcp_min_payload);
236*d8b80295SApple OSS Distributions } else {
237*d8b80295SApple OSS Distributions T_ASSERT_GE((size_t)ip_len, sizeof(struct ip) + sizeof(struct udphdr) + sizeof(dhcp_min_payload),
238*d8b80295SApple OSS Distributions "ip_len");
239*d8b80295SApple OSS Distributions payload_len = ip_len - (sizeof(struct ip) + sizeof(struct udphdr));
240*d8b80295SApple OSS Distributions }
241*d8b80295SApple OSS Distributions
242*d8b80295SApple OSS Distributions struct ether_addr src_eaddr = {};
243*d8b80295SApple OSS Distributions ifnet_get_lladdr(udp_fd, ifname1, &src_eaddr);
244*d8b80295SApple OSS Distributions
245*d8b80295SApple OSS Distributions struct in_addr src_ip = { .s_addr = INADDR_ANY };
246*d8b80295SApple OSS Distributions uint16_t src_port = 68;
247*d8b80295SApple OSS Distributions
248*d8b80295SApple OSS Distributions struct ether_addr dst_eaddr = {};
249*d8b80295SApple OSS Distributions memset(dst_eaddr.octet, 255, ETHER_ADDR_LEN);
250*d8b80295SApple OSS Distributions
251*d8b80295SApple OSS Distributions struct in_addr dst_ip = { .s_addr = INADDR_BROADCAST };
252*d8b80295SApple OSS Distributions
253*d8b80295SApple OSS Distributions uint16_t dst_port = 67;
254*d8b80295SApple OSS Distributions
255*d8b80295SApple OSS Distributions void *payload = calloc(1, payload_len);
256*d8b80295SApple OSS Distributions
257*d8b80295SApple OSS Distributions make_dhcp_payload((dhcp_min_payload_t)payload, &src_eaddr);
258*d8b80295SApple OSS Distributions
259*d8b80295SApple OSS Distributions struct bootp *dhcp = (struct bootp *)payload;
260*d8b80295SApple OSS Distributions dhcp->bp_xid = (uint32_t)id;
261*d8b80295SApple OSS Distributions
262*d8b80295SApple OSS Distributions u_int pkt_size = ETHER_HDR_LEN + IP_MAXPACKET;
263*d8b80295SApple OSS Distributions unsigned char *pkt = calloc(1, pkt_size);
264*d8b80295SApple OSS Distributions
265*d8b80295SApple OSS Distributions u_int frame_length = ethernet_udp4_frame_populate((void *)pkt,
266*d8b80295SApple OSS Distributions pkt_size,
267*d8b80295SApple OSS Distributions &src_eaddr,
268*d8b80295SApple OSS Distributions src_ip,
269*d8b80295SApple OSS Distributions src_port,
270*d8b80295SApple OSS Distributions &dst_eaddr,
271*d8b80295SApple OSS Distributions dst_ip,
272*d8b80295SApple OSS Distributions dst_port,
273*d8b80295SApple OSS Distributions payload,
274*d8b80295SApple OSS Distributions payload_len);
275*d8b80295SApple OSS Distributions
276*d8b80295SApple OSS Distributions T_ASSERT_EQ(sizeof(struct bpf_hdr), BPF_WORDALIGN(sizeof(struct bpf_hdr)), "bpfhdr.bh_hdrlen == BPF_WORDALIGN(sizeof(struct bpf_hdr))");
277*d8b80295SApple OSS Distributions
278*d8b80295SApple OSS Distributions struct bpf_hdr bpfhdr = {};
279*d8b80295SApple OSS Distributions bpfhdr.bh_caplen = frame_length;
280*d8b80295SApple OSS Distributions bpfhdr.bh_datalen = frame_length;
281*d8b80295SApple OSS Distributions bpfhdr.bh_hdrlen = sizeof(struct bpf_hdr);
282*d8b80295SApple OSS Distributions
283*d8b80295SApple OSS Distributions iov->iov_len = BPF_WORDALIGN(bpfhdr.bh_hdrlen + frame_length);
284*d8b80295SApple OSS Distributions iov->iov_base = calloc(1, iov->iov_len);
285*d8b80295SApple OSS Distributions
286*d8b80295SApple OSS Distributions T_LOG("iov_len %lu bh_hdrlen %u frame_length %u ip_len %u payload_len %u",
287*d8b80295SApple OSS Distributions iov->iov_len, bpfhdr.bh_hdrlen, frame_length, ip_len, payload_len);
288*d8b80295SApple OSS Distributions
289*d8b80295SApple OSS Distributions bcopy(&bpfhdr, iov->iov_base, bpfhdr.bh_hdrlen);
290*d8b80295SApple OSS Distributions bcopy(pkt, (char *)iov->iov_base + bpfhdr.bh_hdrlen, frame_length);
291*d8b80295SApple OSS Distributions
292*d8b80295SApple OSS Distributions free(pkt);
293*d8b80295SApple OSS Distributions free(payload);
294*d8b80295SApple OSS Distributions }
295*d8b80295SApple OSS Distributions
296*d8b80295SApple OSS Distributions static void
do_bpf_write_batch(int count,const char * ifname,u_int ip_len,bool expect_success,u_int write_size_max)297*d8b80295SApple OSS Distributions do_bpf_write_batch(int count, const char *ifname, u_int ip_len, bool expect_success, u_int write_size_max)
298*d8b80295SApple OSS Distributions {
299*d8b80295SApple OSS Distributions int bpf_fd = -1;
300*d8b80295SApple OSS Distributions int bdlen = 0;
301*d8b80295SApple OSS Distributions struct iovec *iovs = NULL;
302*d8b80295SApple OSS Distributions int i;
303*d8b80295SApple OSS Distributions
304*d8b80295SApple OSS Distributions T_ASSERT_POSIX_ZERO(create_bpf_on_interface(ifname, &bpf_fd, &bdlen, write_size_max), NULL);
305*d8b80295SApple OSS Distributions T_LOG("bpf bdlen %d", bdlen);
306*d8b80295SApple OSS Distributions
307*d8b80295SApple OSS Distributions /*
308*d8b80295SApple OSS Distributions * Allocate an iovec for each packet that contains the BPF header + the data
309*d8b80295SApple OSS Distributions */
310*d8b80295SApple OSS Distributions iovs = calloc((size_t)count, sizeof(struct iovec));
311*d8b80295SApple OSS Distributions
312*d8b80295SApple OSS Distributions ssize_t total_len = 0;
313*d8b80295SApple OSS Distributions for (i = 0; i < count; i++) {
314*d8b80295SApple OSS Distributions make_bootp_packet(&iovs[i], ip_len, i + 1);
315*d8b80295SApple OSS Distributions total_len += iovs[i].iov_len;
316*d8b80295SApple OSS Distributions
317*d8b80295SApple OSS Distributions struct bpf_hdr *h0 = (struct bpf_hdr *)iovs[i].iov_base;;
318*d8b80295SApple OSS Distributions
319*d8b80295SApple OSS Distributions T_LOG("tv_sec %u tv_usec %u caplen %u datalen %u hdrlen %u",
320*d8b80295SApple OSS Distributions h0->bh_tstamp.tv_sec, h0->bh_tstamp.tv_usec,
321*d8b80295SApple OSS Distributions h0->bh_caplen, h0->bh_datalen, h0->bh_hdrlen);
322*d8b80295SApple OSS Distributions
323*d8b80295SApple OSS Distributions HexDump(iovs[i].iov_base, MIN((size_t)iovs[i].iov_len, 512));
324*d8b80295SApple OSS Distributions
325*d8b80295SApple OSS Distributions T_ASSERT_EQ((int)(iovs[i].iov_len % BPF_ALIGNMENT), 0, "iovs[i].iov_len %% BPF_ALIGNMENT == 0");
326*d8b80295SApple OSS Distributions }
327*d8b80295SApple OSS Distributions T_LOG("total_len %ld", total_len);
328*d8b80295SApple OSS Distributions
329*d8b80295SApple OSS Distributions ssize_t nwritten;
330*d8b80295SApple OSS Distributions nwritten = writev(bpf_fd, iovs, count);
331*d8b80295SApple OSS Distributions
332*d8b80295SApple OSS Distributions T_LOG("bpf write returned %ld", nwritten);
333*d8b80295SApple OSS Distributions
334*d8b80295SApple OSS Distributions if (expect_success) {
335*d8b80295SApple OSS Distributions T_ASSERT_POSIX_SUCCESS(nwritten, "write bpf");
336*d8b80295SApple OSS Distributions } else {
337*d8b80295SApple OSS Distributions T_ASSERT_POSIX_FAILURE(nwritten, EMSGSIZE, "write bpf");
338*d8b80295SApple OSS Distributions goto done;
339*d8b80295SApple OSS Distributions }
340*d8b80295SApple OSS Distributions
341*d8b80295SApple OSS Distributions T_LOG("bpf written %ld bytes over %lu", nwritten, total_len);
342*d8b80295SApple OSS Distributions
343*d8b80295SApple OSS Distributions T_ASSERT_GE((size_t)nwritten, iovs[0].iov_len, "nwritten %lu >= iovs[0].iov_len %lu", nwritten, iovs[0].iov_len);
344*d8b80295SApple OSS Distributions
345*d8b80295SApple OSS Distributions /*
346*d8b80295SApple OSS Distributions * Give 100 ms for the packets to be captured
347*d8b80295SApple OSS Distributions */
348*d8b80295SApple OSS Distributions usleep(100000);
349*d8b80295SApple OSS Distributions
350*d8b80295SApple OSS Distributions /*
351*d8b80295SApple OSS Distributions * Read the batch and verify the content matches what we just sent.
352*d8b80295SApple OSS Distributions */
353*d8b80295SApple OSS Distributions unsigned char *buffer = calloc(1, (size_t)bdlen);
354*d8b80295SApple OSS Distributions T_ASSERT_NOTNULL(buffer, "malloc()");
355*d8b80295SApple OSS Distributions
356*d8b80295SApple OSS Distributions ssize_t nread = read(bpf_fd, buffer, (size_t)bdlen);
357*d8b80295SApple OSS Distributions
358*d8b80295SApple OSS Distributions T_ASSERT_POSIX_SUCCESS(nread, "read bpf");
359*d8b80295SApple OSS Distributions
360*d8b80295SApple OSS Distributions T_LOG("bpf read %ld bytes", nread);
361*d8b80295SApple OSS Distributions
362*d8b80295SApple OSS Distributions /*
363*d8b80295SApple OSS Distributions * We need at least the BPF header
364*d8b80295SApple OSS Distributions */
365*d8b80295SApple OSS Distributions T_ASSERT_GT((size_t)nread, sizeof(sizeof(struct bpf_hdr)), NULL);
366*d8b80295SApple OSS Distributions
367*d8b80295SApple OSS Distributions unsigned char *bp = buffer;
368*d8b80295SApple OSS Distributions unsigned char *ep = buffer + nread;
369*d8b80295SApple OSS Distributions
370*d8b80295SApple OSS Distributions for (i = 0; i < count && bp < ep; i++) {
371*d8b80295SApple OSS Distributions struct bpf_hdr *hp = (struct bpf_hdr *)(void *)bp;
372*d8b80295SApple OSS Distributions
373*d8b80295SApple OSS Distributions T_LOG("tv_sec %u tv_usec %u caplen %u datalen %u hdrlen %u",
374*d8b80295SApple OSS Distributions hp->bh_tstamp.tv_sec, hp->bh_tstamp.tv_usec,
375*d8b80295SApple OSS Distributions hp->bh_caplen, hp->bh_datalen, hp->bh_hdrlen);
376*d8b80295SApple OSS Distributions
377*d8b80295SApple OSS Distributions HexDump(bp, MIN((size_t)BPF_WORDALIGN(hp->bh_hdrlen + hp->bh_caplen), 512));
378*d8b80295SApple OSS Distributions
379*d8b80295SApple OSS Distributions /*
380*d8b80295SApple OSS Distributions * Note: The following will fail if there is parasitic traffic and that should not happen over feth
381*d8b80295SApple OSS Distributions */
382*d8b80295SApple OSS Distributions unsigned char *p0 = iovs[i].iov_base;
383*d8b80295SApple OSS Distributions struct bpf_hdr *h0 = (struct bpf_hdr *)iovs[i].iov_base;;
384*d8b80295SApple OSS Distributions
385*d8b80295SApple OSS Distributions T_ASSERT_EQ(h0->bh_caplen, hp->bh_caplen, "h0->bh_caplen %d == hp->bh_caplen %d", h0->bh_caplen, hp->bh_caplen);
386*d8b80295SApple OSS Distributions T_ASSERT_EQ(h0->bh_datalen, hp->bh_datalen, "h0->bh_datalen %d == hp->bh_datalen %d", h0->bh_datalen, hp->bh_datalen);
387*d8b80295SApple OSS Distributions
388*d8b80295SApple OSS Distributions T_ASSERT_EQ_INT(bcmp(h0->bh_hdrlen + p0, hp->bh_hdrlen + bp, hp->bh_caplen), 0, "bpf read same bytes as written iov %d", i);
389*d8b80295SApple OSS Distributions
390*d8b80295SApple OSS Distributions bp += BPF_WORDALIGN(hp->bh_hdrlen + hp->bh_caplen);
391*d8b80295SApple OSS Distributions }
392*d8b80295SApple OSS Distributions
393*d8b80295SApple OSS Distributions if (buffer != NULL) {
394*d8b80295SApple OSS Distributions free(buffer);
395*d8b80295SApple OSS Distributions }
396*d8b80295SApple OSS Distributions done:
397*d8b80295SApple OSS Distributions if (bpf_fd != -1) {
398*d8b80295SApple OSS Distributions close(bpf_fd);
399*d8b80295SApple OSS Distributions }
400*d8b80295SApple OSS Distributions }
401*d8b80295SApple OSS Distributions
402*d8b80295SApple OSS Distributions static void
test_bpf_write_batch(int count,u_int data_len,int mtu,bool expect_success,u_int write_size_max)403*d8b80295SApple OSS Distributions test_bpf_write_batch(int count, u_int data_len, int mtu, bool expect_success, u_int write_size_max)
404*d8b80295SApple OSS Distributions {
405*d8b80295SApple OSS Distributions init(mtu);
406*d8b80295SApple OSS Distributions
407*d8b80295SApple OSS Distributions T_ASSERT_POSIX_ZERO(setup_feth_pair(mtu), NULL);
408*d8b80295SApple OSS Distributions
409*d8b80295SApple OSS Distributions do_bpf_write_batch(count, ifname1, data_len, expect_success, write_size_max);
410*d8b80295SApple OSS Distributions }
411*d8b80295SApple OSS Distributions
412*d8b80295SApple OSS Distributions T_DECL(bpf_write_batch_dhcp, "BPF write DHCP feth MTU 1500")
413*d8b80295SApple OSS Distributions {
414*d8b80295SApple OSS Distributions test_bpf_write_batch(1, 0, 1500, true, 0);
415*d8b80295SApple OSS Distributions }
416*d8b80295SApple OSS Distributions
417*d8b80295SApple OSS Distributions T_DECL(bpf_write_batch_dhcp_x2, "BPF write DHCP feth MTU 1500 x 2")
418*d8b80295SApple OSS Distributions {
419*d8b80295SApple OSS Distributions test_bpf_write_batch(2, 0, 1500, true, 0);
420*d8b80295SApple OSS Distributions }
421*d8b80295SApple OSS Distributions
422*d8b80295SApple OSS Distributions T_DECL(bpf_write_batch_dhcp_x3, "BPF write DHCP feth MTU 1500 x 3")
423*d8b80295SApple OSS Distributions {
424*d8b80295SApple OSS Distributions test_bpf_write_batch(3, 0, 1500, true, 0);
425*d8b80295SApple OSS Distributions }
426*d8b80295SApple OSS Distributions
427*d8b80295SApple OSS Distributions T_DECL(bpf_write_batch_1020, "BPF write 1020 feth MTU 1500 x 2")
428*d8b80295SApple OSS Distributions {
429*d8b80295SApple OSS Distributions test_bpf_write_batch(2, 1020, 1500, true, 0);
430*d8b80295SApple OSS Distributions }
431*d8b80295SApple OSS Distributions
432*d8b80295SApple OSS Distributions T_DECL(bpf_write_batch_1021, "BPF write 1021 feth MTU 1500 x 2")
433*d8b80295SApple OSS Distributions {
434*d8b80295SApple OSS Distributions test_bpf_write_batch(2, 1021, 1500, true, 0);
435*d8b80295SApple OSS Distributions }
436*d8b80295SApple OSS Distributions
437*d8b80295SApple OSS Distributions T_DECL(bpf_write_batch_1022, "BPF write 1022 feth MTU 1500 x 2")
438*d8b80295SApple OSS Distributions {
439*d8b80295SApple OSS Distributions test_bpf_write_batch(2, 1022, 1500, true, 0);
440*d8b80295SApple OSS Distributions }
441*d8b80295SApple OSS Distributions
442*d8b80295SApple OSS Distributions T_DECL(bpf_write_batch_1023, "BPF write 1023 feth MTU 1500 x2 ")
443*d8b80295SApple OSS Distributions {
444*d8b80295SApple OSS Distributions test_bpf_write_batch(2, 1023, 1500, true, 0);
445*d8b80295SApple OSS Distributions }
446