1*f6217f89SApple OSS Distributions /*
2*f6217f89SApple OSS Distributions * Copyright (c) 2000-2018 Apple Inc. All rights reserved.
3*f6217f89SApple OSS Distributions *
4*f6217f89SApple OSS Distributions * @APPLE_LICENSE_HEADER_START@
5*f6217f89SApple OSS Distributions *
6*f6217f89SApple OSS Distributions * This file contains Original Code and/or Modifications of Original Code
7*f6217f89SApple OSS Distributions * as defined in and that are subject to the Apple Public Source License
8*f6217f89SApple OSS Distributions * Version 2.0 (the 'License'). You may not use this file except in
9*f6217f89SApple OSS Distributions * compliance with the License. Please obtain a copy of the License at
10*f6217f89SApple OSS Distributions * http://www.opensource.apple.com/apsl/ and read it before using this
11*f6217f89SApple OSS Distributions * file.
12*f6217f89SApple OSS Distributions *
13*f6217f89SApple OSS Distributions * The Original Code and all software distributed under the License are
14*f6217f89SApple OSS Distributions * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15*f6217f89SApple OSS Distributions * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16*f6217f89SApple OSS Distributions * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17*f6217f89SApple OSS Distributions * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18*f6217f89SApple OSS Distributions * Please see the License for the specific language governing rights and
19*f6217f89SApple OSS Distributions * limitations under the License.
20*f6217f89SApple OSS Distributions *
21*f6217f89SApple OSS Distributions * @APPLE_LICENSE_HEADER_END@
22*f6217f89SApple OSS Distributions */
23*f6217f89SApple OSS Distributions
24*f6217f89SApple OSS Distributions #include <stdlib.h>
25*f6217f89SApple OSS Distributions #include <unistd.h>
26*f6217f89SApple OSS Distributions #include <stdio.h>
27*f6217f89SApple OSS Distributions #include <sys/types.h>
28*f6217f89SApple OSS Distributions #include <sys/time.h>
29*f6217f89SApple OSS Distributions #include <sys/ioctl.h>
30*f6217f89SApple OSS Distributions #include <sys/stat.h>
31*f6217f89SApple OSS Distributions #include <fcntl.h>
32*f6217f89SApple OSS Distributions #include <net/bpf.h>
33*f6217f89SApple OSS Distributions #include <string.h>
34*f6217f89SApple OSS Distributions #include <sys/socket.h>
35*f6217f89SApple OSS Distributions #include <errno.h>
36*f6217f89SApple OSS Distributions #include <net/if.h>
37*f6217f89SApple OSS Distributions #include <stdbool.h>
38*f6217f89SApple OSS Distributions #define PRIVATE_EXTERN __private_extern__
39*f6217f89SApple OSS Distributions
40*f6217f89SApple OSS Distributions #include "bpflib.h"
41*f6217f89SApple OSS Distributions
42*f6217f89SApple OSS Distributions #ifdef TESTING
43*f6217f89SApple OSS Distributions #include "util.h"
44*f6217f89SApple OSS Distributions #endif /* TESTING */
45*f6217f89SApple OSS Distributions
46*f6217f89SApple OSS Distributions PRIVATE_EXTERN int
bpf_set_timeout(int fd,struct timeval * tv_p)47*f6217f89SApple OSS Distributions bpf_set_timeout(int fd, struct timeval * tv_p)
48*f6217f89SApple OSS Distributions {
49*f6217f89SApple OSS Distributions return ioctl(fd, BIOCSRTIMEOUT, tv_p);
50*f6217f89SApple OSS Distributions }
51*f6217f89SApple OSS Distributions
52*f6217f89SApple OSS Distributions PRIVATE_EXTERN int
bpf_get_blen(int fd,int * blen)53*f6217f89SApple OSS Distributions bpf_get_blen(int fd, int * blen)
54*f6217f89SApple OSS Distributions {
55*f6217f89SApple OSS Distributions return ioctl(fd, BIOCGBLEN, blen);
56*f6217f89SApple OSS Distributions }
57*f6217f89SApple OSS Distributions
58*f6217f89SApple OSS Distributions PRIVATE_EXTERN int
bpf_set_blen(int fd,int blen)59*f6217f89SApple OSS Distributions bpf_set_blen(int fd, int blen)
60*f6217f89SApple OSS Distributions {
61*f6217f89SApple OSS Distributions return ioctl(fd, BIOCSBLEN, &blen);
62*f6217f89SApple OSS Distributions }
63*f6217f89SApple OSS Distributions
64*f6217f89SApple OSS Distributions PRIVATE_EXTERN int
bpf_set_header_complete(int fd,u_int header_complete)65*f6217f89SApple OSS Distributions bpf_set_header_complete(int fd, u_int header_complete)
66*f6217f89SApple OSS Distributions {
67*f6217f89SApple OSS Distributions return ioctl(fd, BIOCSHDRCMPLT, &header_complete);
68*f6217f89SApple OSS Distributions }
69*f6217f89SApple OSS Distributions
70*f6217f89SApple OSS Distributions PRIVATE_EXTERN int
bpf_set_see_sent(int fd,u_int see_sent)71*f6217f89SApple OSS Distributions bpf_set_see_sent(int fd, u_int see_sent)
72*f6217f89SApple OSS Distributions {
73*f6217f89SApple OSS Distributions return ioctl(fd, BIOCSSEESENT, &see_sent);
74*f6217f89SApple OSS Distributions }
75*f6217f89SApple OSS Distributions
76*f6217f89SApple OSS Distributions PRIVATE_EXTERN int
bpf_dispose(int bpf_fd)77*f6217f89SApple OSS Distributions bpf_dispose(int bpf_fd)
78*f6217f89SApple OSS Distributions {
79*f6217f89SApple OSS Distributions if (bpf_fd >= 0) {
80*f6217f89SApple OSS Distributions return close(bpf_fd);
81*f6217f89SApple OSS Distributions }
82*f6217f89SApple OSS Distributions return 0;
83*f6217f89SApple OSS Distributions }
84*f6217f89SApple OSS Distributions
85*f6217f89SApple OSS Distributions PRIVATE_EXTERN int
bpf_set_traffic_class(int fd,int tc)86*f6217f89SApple OSS Distributions bpf_set_traffic_class(int fd, int tc)
87*f6217f89SApple OSS Distributions {
88*f6217f89SApple OSS Distributions return ioctl(fd, BIOCSETTC, &tc);
89*f6217f89SApple OSS Distributions }
90*f6217f89SApple OSS Distributions
91*f6217f89SApple OSS Distributions #ifdef BIOCSDIRECTION
92*f6217f89SApple OSS Distributions PRIVATE_EXTERN int
bpf_set_direction(int fd,u_int direction)93*f6217f89SApple OSS Distributions bpf_set_direction(int fd, u_int direction)
94*f6217f89SApple OSS Distributions {
95*f6217f89SApple OSS Distributions return ioctl(fd, BIOCSDIRECTION, &direction);
96*f6217f89SApple OSS Distributions }
97*f6217f89SApple OSS Distributions
98*f6217f89SApple OSS Distributions PRIVATE_EXTERN int
bpf_get_direction(int fd,u_int * direction)99*f6217f89SApple OSS Distributions bpf_get_direction(int fd, u_int *direction)
100*f6217f89SApple OSS Distributions {
101*f6217f89SApple OSS Distributions return ioctl(fd, BIOCGDIRECTION, direction);
102*f6217f89SApple OSS Distributions }
103*f6217f89SApple OSS Distributions
104*f6217f89SApple OSS Distributions #endif /* BIOCSDIRECTION */
105*f6217f89SApple OSS Distributions
106*f6217f89SApple OSS Distributions PRIVATE_EXTERN int
bpf_new(void)107*f6217f89SApple OSS Distributions bpf_new(void)
108*f6217f89SApple OSS Distributions {
109*f6217f89SApple OSS Distributions char bpfdev[256];
110*f6217f89SApple OSS Distributions int i;
111*f6217f89SApple OSS Distributions int fd = -1;
112*f6217f89SApple OSS Distributions
113*f6217f89SApple OSS Distributions for (i = 0; true; i++) {
114*f6217f89SApple OSS Distributions snprintf(bpfdev, sizeof(bpfdev), "/dev/bpf%d", i);
115*f6217f89SApple OSS Distributions fd = open(bpfdev, O_RDWR, 0);
116*f6217f89SApple OSS Distributions if (fd >= 0) {
117*f6217f89SApple OSS Distributions break;
118*f6217f89SApple OSS Distributions }
119*f6217f89SApple OSS Distributions if (errno != EBUSY) {
120*f6217f89SApple OSS Distributions break;
121*f6217f89SApple OSS Distributions }
122*f6217f89SApple OSS Distributions }
123*f6217f89SApple OSS Distributions return fd;
124*f6217f89SApple OSS Distributions }
125*f6217f89SApple OSS Distributions
126*f6217f89SApple OSS Distributions PRIVATE_EXTERN int
bpf_setif(int fd,const char * en_name)127*f6217f89SApple OSS Distributions bpf_setif(int fd, const char * en_name)
128*f6217f89SApple OSS Distributions {
129*f6217f89SApple OSS Distributions struct ifreq ifr;
130*f6217f89SApple OSS Distributions
131*f6217f89SApple OSS Distributions strlcpy(ifr.ifr_name, en_name, sizeof(ifr.ifr_name));
132*f6217f89SApple OSS Distributions return ioctl(fd, BIOCSETIF, &ifr);
133*f6217f89SApple OSS Distributions }
134*f6217f89SApple OSS Distributions
135*f6217f89SApple OSS Distributions PRIVATE_EXTERN int
bpf_set_immediate(int fd,u_int value)136*f6217f89SApple OSS Distributions bpf_set_immediate(int fd, u_int value)
137*f6217f89SApple OSS Distributions {
138*f6217f89SApple OSS Distributions return ioctl(fd, BIOCIMMEDIATE, &value);
139*f6217f89SApple OSS Distributions }
140*f6217f89SApple OSS Distributions
141*f6217f89SApple OSS Distributions PRIVATE_EXTERN int
bpf_filter_receive_none(int fd)142*f6217f89SApple OSS Distributions bpf_filter_receive_none(int fd)
143*f6217f89SApple OSS Distributions {
144*f6217f89SApple OSS Distributions struct bpf_insn insns[] = {
145*f6217f89SApple OSS Distributions BPF_STMT(BPF_RET + BPF_K, 0),
146*f6217f89SApple OSS Distributions };
147*f6217f89SApple OSS Distributions struct bpf_program prog;
148*f6217f89SApple OSS Distributions
149*f6217f89SApple OSS Distributions prog.bf_len = sizeof(insns) / sizeof(struct bpf_insn);
150*f6217f89SApple OSS Distributions prog.bf_insns = insns;
151*f6217f89SApple OSS Distributions return ioctl(fd, BIOCSETF, &prog);
152*f6217f89SApple OSS Distributions }
153*f6217f89SApple OSS Distributions
154*f6217f89SApple OSS Distributions PRIVATE_EXTERN int
bpf_arp_filter(int fd,int type_offset,int type,u_int pkt_size)155*f6217f89SApple OSS Distributions bpf_arp_filter(int fd, int type_offset, int type, u_int pkt_size)
156*f6217f89SApple OSS Distributions {
157*f6217f89SApple OSS Distributions struct bpf_insn insns[] = {
158*f6217f89SApple OSS Distributions BPF_STMT(BPF_LD + BPF_H + BPF_ABS, type_offset),
159*f6217f89SApple OSS Distributions BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, type, 0, 1),
160*f6217f89SApple OSS Distributions BPF_STMT(BPF_RET + BPF_K, pkt_size),
161*f6217f89SApple OSS Distributions BPF_STMT(BPF_RET + BPF_K, 0),
162*f6217f89SApple OSS Distributions };
163*f6217f89SApple OSS Distributions struct bpf_program prog;
164*f6217f89SApple OSS Distributions
165*f6217f89SApple OSS Distributions prog.bf_len = sizeof(insns) / sizeof(struct bpf_insn);
166*f6217f89SApple OSS Distributions prog.bf_insns = insns;
167*f6217f89SApple OSS Distributions return ioctl(fd, BIOCSETF, &prog);
168*f6217f89SApple OSS Distributions }
169*f6217f89SApple OSS Distributions
170*f6217f89SApple OSS Distributions PRIVATE_EXTERN int
bpf_set_write_size_max(int fd,u_int value)171*f6217f89SApple OSS Distributions bpf_set_write_size_max(int fd, u_int value)
172*f6217f89SApple OSS Distributions {
173*f6217f89SApple OSS Distributions #ifdef BIOCSWRITEMAX
174*f6217f89SApple OSS Distributions return ioctl(fd, BIOCSWRITEMAX, &value);
175*f6217f89SApple OSS Distributions #else
176*f6217f89SApple OSS Distributions #pragma unused(fd, value)
177*f6217f89SApple OSS Distributions return ENOTSUP;
178*f6217f89SApple OSS Distributions #endif
179*f6217f89SApple OSS Distributions }
180*f6217f89SApple OSS Distributions
181*f6217f89SApple OSS Distributions PRIVATE_EXTERN int
bpf_get_write_size_max(int fd,u_int * value)182*f6217f89SApple OSS Distributions bpf_get_write_size_max(int fd, u_int *value)
183*f6217f89SApple OSS Distributions {
184*f6217f89SApple OSS Distributions #ifdef BIOCGWRITEMAX
185*f6217f89SApple OSS Distributions return ioctl(fd, BIOCGWRITEMAX, value);
186*f6217f89SApple OSS Distributions #else
187*f6217f89SApple OSS Distributions #pragma unused(fd, value)
188*f6217f89SApple OSS Distributions return ENOTSUP;
189*f6217f89SApple OSS Distributions #endif
190*f6217f89SApple OSS Distributions }
191*f6217f89SApple OSS Distributions
192*f6217f89SApple OSS Distributions PRIVATE_EXTERN int
bpf_set_batch_write(int fd,u_int value)193*f6217f89SApple OSS Distributions bpf_set_batch_write(int fd, u_int value)
194*f6217f89SApple OSS Distributions {
195*f6217f89SApple OSS Distributions #ifdef BIOCSBATCHWRITE
196*f6217f89SApple OSS Distributions return ioctl(fd, BIOCSBATCHWRITE, &value);
197*f6217f89SApple OSS Distributions #else
198*f6217f89SApple OSS Distributions #pragma unused(fd, value)
199*f6217f89SApple OSS Distributions return ENOTSUP;
200*f6217f89SApple OSS Distributions #endif
201*f6217f89SApple OSS Distributions }
202*f6217f89SApple OSS Distributions
203*f6217f89SApple OSS Distributions PRIVATE_EXTERN int
bpf_get_batch_write(int fd,u_int * value)204*f6217f89SApple OSS Distributions bpf_get_batch_write(int fd, u_int *value)
205*f6217f89SApple OSS Distributions {
206*f6217f89SApple OSS Distributions #ifdef BIOCGBATCHWRITE
207*f6217f89SApple OSS Distributions return ioctl(fd, BIOCGBATCHWRITE, value);
208*f6217f89SApple OSS Distributions #else
209*f6217f89SApple OSS Distributions #pragma unused(fd, value)
210*f6217f89SApple OSS Distributions return ENOTSUP;
211*f6217f89SApple OSS Distributions #endif
212*f6217f89SApple OSS Distributions }
213*f6217f89SApple OSS Distributions
214*f6217f89SApple OSS Distributions #ifdef TESTING
215*f6217f89SApple OSS Distributions #include <net/if_arp.h>
216*f6217f89SApple OSS Distributions #include <net/ethernet.h>
217*f6217f89SApple OSS Distributions #include <netinet/if_ether.h>
218*f6217f89SApple OSS Distributions
219*f6217f89SApple OSS Distributions void
bpf_read_continuously(int fd,u_int blen)220*f6217f89SApple OSS Distributions bpf_read_continuously(int fd, u_int blen)
221*f6217f89SApple OSS Distributions {
222*f6217f89SApple OSS Distributions int n;
223*f6217f89SApple OSS Distributions char * rxbuf = malloc(blen);
224*f6217f89SApple OSS Distributions
225*f6217f89SApple OSS Distributions printf("rx buf len is %d\n", blen);
226*f6217f89SApple OSS Distributions while (1) {
227*f6217f89SApple OSS Distributions n = read(fd, rxbuf, blen);
228*f6217f89SApple OSS Distributions if (n < 0) {
229*f6217f89SApple OSS Distributions perror("bpf_read_continuously");
230*f6217f89SApple OSS Distributions return;
231*f6217f89SApple OSS Distributions }
232*f6217f89SApple OSS Distributions if (n == 0) {
233*f6217f89SApple OSS Distributions continue;
234*f6217f89SApple OSS Distributions }
235*f6217f89SApple OSS Distributions print_data(rxbuf, n);
236*f6217f89SApple OSS Distributions }
237*f6217f89SApple OSS Distributions }
238*f6217f89SApple OSS Distributions
239*f6217f89SApple OSS Distributions int
main(int argc,char * argv[])240*f6217f89SApple OSS Distributions main(int argc, char * argv[])
241*f6217f89SApple OSS Distributions {
242*f6217f89SApple OSS Distributions int fd = bpf_new();
243*f6217f89SApple OSS Distributions char * en_name = "en0";
244*f6217f89SApple OSS Distributions u_int bpf_blen = 0;
245*f6217f89SApple OSS Distributions
246*f6217f89SApple OSS Distributions if (fd < 0) {
247*f6217f89SApple OSS Distributions perror("no bpf devices");
248*f6217f89SApple OSS Distributions exit(1);
249*f6217f89SApple OSS Distributions }
250*f6217f89SApple OSS Distributions bpf_set_traffic_class(SO_TC_CTL);
251*f6217f89SApple OSS Distributions
252*f6217f89SApple OSS Distributions if (argc > 1) {
253*f6217f89SApple OSS Distributions en_name = argv[1];
254*f6217f89SApple OSS Distributions }
255*f6217f89SApple OSS Distributions (void)bpf_set_immediate(fd, 1);
256*f6217f89SApple OSS Distributions if (bpf_arp_filter(fd, 12, ETHERTYPE_ARP,
257*f6217f89SApple OSS Distributions sizeof(struct ether_arp) + sizeof(struct ether_header))
258*f6217f89SApple OSS Distributions < 0) {
259*f6217f89SApple OSS Distributions perror("bpf_arp_filter");
260*f6217f89SApple OSS Distributions }
261*f6217f89SApple OSS Distributions if (bpf_setif(fd, en_name) < 0) {
262*f6217f89SApple OSS Distributions perror("bpf_attach");
263*f6217f89SApple OSS Distributions exit(1);
264*f6217f89SApple OSS Distributions }
265*f6217f89SApple OSS Distributions
266*f6217f89SApple OSS Distributions if (bpf_get_blen(fd, &bpf_blen) < 0) {
267*f6217f89SApple OSS Distributions perror("bpf_get_blen");
268*f6217f89SApple OSS Distributions exit(1);
269*f6217f89SApple OSS Distributions }
270*f6217f89SApple OSS Distributions bpf_read_continuously(fd, bpf_blen);
271*f6217f89SApple OSS Distributions exit(0);
272*f6217f89SApple OSS Distributions return 0;
273*f6217f89SApple OSS Distributions }
274*f6217f89SApple OSS Distributions #endif /* TESTING */
275