xref: /aosp_15_r20/external/libpcap/pcap-netmap.c (revision 8b26181f966a6af5cf6981a6f474313de533bb28)
1*8b26181fSAndroid Build Coastguard Worker /*
2*8b26181fSAndroid Build Coastguard Worker  * Copyright (C) 2014 Luigi Rizzo. All rights reserved.
3*8b26181fSAndroid Build Coastguard Worker  *
4*8b26181fSAndroid Build Coastguard Worker  * Redistribution and use in source and binary forms, with or without
5*8b26181fSAndroid Build Coastguard Worker  * modification, are permitted provided that the following conditions
6*8b26181fSAndroid Build Coastguard Worker  * are met:
7*8b26181fSAndroid Build Coastguard Worker  *
8*8b26181fSAndroid Build Coastguard Worker  *   1. Redistributions of source code must retain the above copyright
9*8b26181fSAndroid Build Coastguard Worker  *      notice, this list of conditions and the following disclaimer.
10*8b26181fSAndroid Build Coastguard Worker  *   2. Redistributions in binary form must reproduce the above copyright
11*8b26181fSAndroid Build Coastguard Worker  *      notice, this list of conditions and the following disclaimer in the
12*8b26181fSAndroid Build Coastguard Worker  *      documentation and/or other materials provided with the distribution.
13*8b26181fSAndroid Build Coastguard Worker  *
14*8b26181fSAndroid Build Coastguard Worker  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''AND
15*8b26181fSAndroid Build Coastguard Worker  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16*8b26181fSAndroid Build Coastguard Worker  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17*8b26181fSAndroid Build Coastguard Worker  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18*8b26181fSAndroid Build Coastguard Worker  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19*8b26181fSAndroid Build Coastguard Worker  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20*8b26181fSAndroid Build Coastguard Worker  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21*8b26181fSAndroid Build Coastguard Worker  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22*8b26181fSAndroid Build Coastguard Worker  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23*8b26181fSAndroid Build Coastguard Worker  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24*8b26181fSAndroid Build Coastguard Worker  * SUCH DAMAGE.
25*8b26181fSAndroid Build Coastguard Worker  */
26*8b26181fSAndroid Build Coastguard Worker 
27*8b26181fSAndroid Build Coastguard Worker #ifdef HAVE_CONFIG_H
28*8b26181fSAndroid Build Coastguard Worker #include <config.h>
29*8b26181fSAndroid Build Coastguard Worker #endif
30*8b26181fSAndroid Build Coastguard Worker 
31*8b26181fSAndroid Build Coastguard Worker #include <poll.h>
32*8b26181fSAndroid Build Coastguard Worker #include <errno.h>
33*8b26181fSAndroid Build Coastguard Worker #include <netdb.h>
34*8b26181fSAndroid Build Coastguard Worker #include <stdio.h>
35*8b26181fSAndroid Build Coastguard Worker #include <stdlib.h>
36*8b26181fSAndroid Build Coastguard Worker #include <string.h>
37*8b26181fSAndroid Build Coastguard Worker #include <unistd.h>
38*8b26181fSAndroid Build Coastguard Worker 
39*8b26181fSAndroid Build Coastguard Worker #define NETMAP_WITH_LIBS
40*8b26181fSAndroid Build Coastguard Worker #include <net/netmap_user.h>
41*8b26181fSAndroid Build Coastguard Worker 
42*8b26181fSAndroid Build Coastguard Worker #include "pcap-int.h"
43*8b26181fSAndroid Build Coastguard Worker #include "pcap-netmap.h"
44*8b26181fSAndroid Build Coastguard Worker 
45*8b26181fSAndroid Build Coastguard Worker #ifndef __FreeBSD__
46*8b26181fSAndroid Build Coastguard Worker   /*
47*8b26181fSAndroid Build Coastguard Worker    * On FreeBSD we use IFF_PPROMISC which is in ifr_flagshigh.
48*8b26181fSAndroid Build Coastguard Worker    * Remap to IFF_PROMISC on other platforms.
49*8b26181fSAndroid Build Coastguard Worker    *
50*8b26181fSAndroid Build Coastguard Worker    * XXX - DragonFly BSD?
51*8b26181fSAndroid Build Coastguard Worker    */
52*8b26181fSAndroid Build Coastguard Worker   #define IFF_PPROMISC	IFF_PROMISC
53*8b26181fSAndroid Build Coastguard Worker #endif /* __FreeBSD__ */
54*8b26181fSAndroid Build Coastguard Worker 
55*8b26181fSAndroid Build Coastguard Worker struct pcap_netmap {
56*8b26181fSAndroid Build Coastguard Worker 	struct nm_desc *d;	/* pointer returned by nm_open() */
57*8b26181fSAndroid Build Coastguard Worker 	pcap_handler cb;	/* callback and argument */
58*8b26181fSAndroid Build Coastguard Worker 	u_char *cb_arg;
59*8b26181fSAndroid Build Coastguard Worker 	int must_clear_promisc;	/* flag */
60*8b26181fSAndroid Build Coastguard Worker 	uint64_t rx_pkts;	/* # of pkts received before the filter */
61*8b26181fSAndroid Build Coastguard Worker };
62*8b26181fSAndroid Build Coastguard Worker 
63*8b26181fSAndroid Build Coastguard Worker 
64*8b26181fSAndroid Build Coastguard Worker static int
pcap_netmap_stats(pcap_t * p,struct pcap_stat * ps)65*8b26181fSAndroid Build Coastguard Worker pcap_netmap_stats(pcap_t *p, struct pcap_stat *ps)
66*8b26181fSAndroid Build Coastguard Worker {
67*8b26181fSAndroid Build Coastguard Worker 	struct pcap_netmap *pn = p->priv;
68*8b26181fSAndroid Build Coastguard Worker 
69*8b26181fSAndroid Build Coastguard Worker 	ps->ps_recv = (u_int)pn->rx_pkts;
70*8b26181fSAndroid Build Coastguard Worker 	ps->ps_drop = 0;
71*8b26181fSAndroid Build Coastguard Worker 	ps->ps_ifdrop = 0;
72*8b26181fSAndroid Build Coastguard Worker 	return 0;
73*8b26181fSAndroid Build Coastguard Worker }
74*8b26181fSAndroid Build Coastguard Worker 
75*8b26181fSAndroid Build Coastguard Worker 
76*8b26181fSAndroid Build Coastguard Worker static void
pcap_netmap_filter(u_char * arg,struct pcap_pkthdr * h,const u_char * buf)77*8b26181fSAndroid Build Coastguard Worker pcap_netmap_filter(u_char *arg, struct pcap_pkthdr *h, const u_char *buf)
78*8b26181fSAndroid Build Coastguard Worker {
79*8b26181fSAndroid Build Coastguard Worker 	pcap_t *p = (pcap_t *)arg;
80*8b26181fSAndroid Build Coastguard Worker 	struct pcap_netmap *pn = p->priv;
81*8b26181fSAndroid Build Coastguard Worker 	const struct bpf_insn *pc = p->fcode.bf_insns;
82*8b26181fSAndroid Build Coastguard Worker 
83*8b26181fSAndroid Build Coastguard Worker 	++pn->rx_pkts;
84*8b26181fSAndroid Build Coastguard Worker 	if (pc == NULL || pcap_filter(pc, buf, h->len, h->caplen))
85*8b26181fSAndroid Build Coastguard Worker 		pn->cb(pn->cb_arg, h, buf);
86*8b26181fSAndroid Build Coastguard Worker }
87*8b26181fSAndroid Build Coastguard Worker 
88*8b26181fSAndroid Build Coastguard Worker 
89*8b26181fSAndroid Build Coastguard Worker static int
pcap_netmap_dispatch(pcap_t * p,int cnt,pcap_handler cb,u_char * user)90*8b26181fSAndroid Build Coastguard Worker pcap_netmap_dispatch(pcap_t *p, int cnt, pcap_handler cb, u_char *user)
91*8b26181fSAndroid Build Coastguard Worker {
92*8b26181fSAndroid Build Coastguard Worker 	int ret;
93*8b26181fSAndroid Build Coastguard Worker 	struct pcap_netmap *pn = p->priv;
94*8b26181fSAndroid Build Coastguard Worker 	struct nm_desc *d = pn->d;
95*8b26181fSAndroid Build Coastguard Worker 	struct pollfd pfd = { .fd = p->fd, .events = POLLIN, .revents = 0 };
96*8b26181fSAndroid Build Coastguard Worker 
97*8b26181fSAndroid Build Coastguard Worker 	pn->cb = cb;
98*8b26181fSAndroid Build Coastguard Worker 	pn->cb_arg = user;
99*8b26181fSAndroid Build Coastguard Worker 
100*8b26181fSAndroid Build Coastguard Worker 	for (;;) {
101*8b26181fSAndroid Build Coastguard Worker 		if (p->break_loop) {
102*8b26181fSAndroid Build Coastguard Worker 			p->break_loop = 0;
103*8b26181fSAndroid Build Coastguard Worker 			return PCAP_ERROR_BREAK;
104*8b26181fSAndroid Build Coastguard Worker 		}
105*8b26181fSAndroid Build Coastguard Worker 		/* nm_dispatch won't run forever */
106*8b26181fSAndroid Build Coastguard Worker 
107*8b26181fSAndroid Build Coastguard Worker 		ret = nm_dispatch((void *)d, cnt, (void *)pcap_netmap_filter, (void *)p);
108*8b26181fSAndroid Build Coastguard Worker 		if (ret != 0)
109*8b26181fSAndroid Build Coastguard Worker 			break;
110*8b26181fSAndroid Build Coastguard Worker 		errno = 0;
111*8b26181fSAndroid Build Coastguard Worker 		ret = poll(&pfd, 1, p->opt.timeout);
112*8b26181fSAndroid Build Coastguard Worker 	}
113*8b26181fSAndroid Build Coastguard Worker 	return ret;
114*8b26181fSAndroid Build Coastguard Worker }
115*8b26181fSAndroid Build Coastguard Worker 
116*8b26181fSAndroid Build Coastguard Worker 
117*8b26181fSAndroid Build Coastguard Worker /* XXX need to check the NIOCTXSYNC/poll */
118*8b26181fSAndroid Build Coastguard Worker static int
pcap_netmap_inject(pcap_t * p,const void * buf,int size)119*8b26181fSAndroid Build Coastguard Worker pcap_netmap_inject(pcap_t *p, const void *buf, int size)
120*8b26181fSAndroid Build Coastguard Worker {
121*8b26181fSAndroid Build Coastguard Worker 	struct pcap_netmap *pn = p->priv;
122*8b26181fSAndroid Build Coastguard Worker 	struct nm_desc *d = pn->d;
123*8b26181fSAndroid Build Coastguard Worker 
124*8b26181fSAndroid Build Coastguard Worker 	return nm_inject(d, buf, size);
125*8b26181fSAndroid Build Coastguard Worker }
126*8b26181fSAndroid Build Coastguard Worker 
127*8b26181fSAndroid Build Coastguard Worker 
128*8b26181fSAndroid Build Coastguard Worker static int
pcap_netmap_ioctl(pcap_t * p,u_long what,uint32_t * if_flags)129*8b26181fSAndroid Build Coastguard Worker pcap_netmap_ioctl(pcap_t *p, u_long what, uint32_t *if_flags)
130*8b26181fSAndroid Build Coastguard Worker {
131*8b26181fSAndroid Build Coastguard Worker 	struct pcap_netmap *pn = p->priv;
132*8b26181fSAndroid Build Coastguard Worker 	struct nm_desc *d = pn->d;
133*8b26181fSAndroid Build Coastguard Worker 	struct ifreq ifr;
134*8b26181fSAndroid Build Coastguard Worker 	int error, fd = d->fd;
135*8b26181fSAndroid Build Coastguard Worker 
136*8b26181fSAndroid Build Coastguard Worker #ifdef linux
137*8b26181fSAndroid Build Coastguard Worker 	fd = socket(AF_INET, SOCK_DGRAM, 0);
138*8b26181fSAndroid Build Coastguard Worker 	if (fd < 0) {
139*8b26181fSAndroid Build Coastguard Worker 		fprintf(stderr, "Error: cannot get device control socket.\n");
140*8b26181fSAndroid Build Coastguard Worker 		return -1;
141*8b26181fSAndroid Build Coastguard Worker 	}
142*8b26181fSAndroid Build Coastguard Worker #endif /* linux */
143*8b26181fSAndroid Build Coastguard Worker 	bzero(&ifr, sizeof(ifr));
144*8b26181fSAndroid Build Coastguard Worker 	strncpy(ifr.ifr_name, d->req.nr_name, sizeof(ifr.ifr_name));
145*8b26181fSAndroid Build Coastguard Worker 	switch (what) {
146*8b26181fSAndroid Build Coastguard Worker 	case SIOCSIFFLAGS:
147*8b26181fSAndroid Build Coastguard Worker 		/*
148*8b26181fSAndroid Build Coastguard Worker 		 * The flags we pass in are 32-bit and unsigned.
149*8b26181fSAndroid Build Coastguard Worker 		 *
150*8b26181fSAndroid Build Coastguard Worker 		 * On most if not all UN*Xes, ifr_flags is 16-bit and
151*8b26181fSAndroid Build Coastguard Worker 		 * signed, and the result of assigning a longer
152*8b26181fSAndroid Build Coastguard Worker 		 * unsigned value to a shorter signed value is
153*8b26181fSAndroid Build Coastguard Worker 		 * implementation-defined (even if, in practice, it'll
154*8b26181fSAndroid Build Coastguard Worker 		 * do what's intended on all platforms we support
155*8b26181fSAndroid Build Coastguard Worker 		 * result of assigning a 32-bit unsigned value).
156*8b26181fSAndroid Build Coastguard Worker 		 * So we mask out the upper 16 bits.
157*8b26181fSAndroid Build Coastguard Worker 		 */
158*8b26181fSAndroid Build Coastguard Worker 		ifr.ifr_flags = *if_flags & 0xffff;
159*8b26181fSAndroid Build Coastguard Worker #ifdef __FreeBSD__
160*8b26181fSAndroid Build Coastguard Worker 		/*
161*8b26181fSAndroid Build Coastguard Worker 		 * In FreeBSD, we need to set the high-order flags,
162*8b26181fSAndroid Build Coastguard Worker 		 * as we're using IFF_PPROMISC, which is in those bits.
163*8b26181fSAndroid Build Coastguard Worker 		 *
164*8b26181fSAndroid Build Coastguard Worker 		 * XXX - DragonFly BSD?
165*8b26181fSAndroid Build Coastguard Worker 		 */
166*8b26181fSAndroid Build Coastguard Worker 		ifr.ifr_flagshigh = *if_flags >> 16;
167*8b26181fSAndroid Build Coastguard Worker #endif /* __FreeBSD__ */
168*8b26181fSAndroid Build Coastguard Worker 		break;
169*8b26181fSAndroid Build Coastguard Worker 	}
170*8b26181fSAndroid Build Coastguard Worker 	error = ioctl(fd, what, &ifr);
171*8b26181fSAndroid Build Coastguard Worker 	if (!error) {
172*8b26181fSAndroid Build Coastguard Worker 		switch (what) {
173*8b26181fSAndroid Build Coastguard Worker 		case SIOCGIFFLAGS:
174*8b26181fSAndroid Build Coastguard Worker 			/*
175*8b26181fSAndroid Build Coastguard Worker 			 * The flags we return are 32-bit.
176*8b26181fSAndroid Build Coastguard Worker 			 *
177*8b26181fSAndroid Build Coastguard Worker 			 * On most if not all UN*Xes, ifr_flags is
178*8b26181fSAndroid Build Coastguard Worker 			 * 16-bit and signed, and will get sign-
179*8b26181fSAndroid Build Coastguard Worker 			 * extended, so that the upper 16 bits of
180*8b26181fSAndroid Build Coastguard Worker 			 * those flags will be forced on.  So we
181*8b26181fSAndroid Build Coastguard Worker 			 * mask out the upper 16 bits of the
182*8b26181fSAndroid Build Coastguard Worker 			 * sign-extended value.
183*8b26181fSAndroid Build Coastguard Worker 			 */
184*8b26181fSAndroid Build Coastguard Worker 			*if_flags = ifr.ifr_flags & 0xffff;
185*8b26181fSAndroid Build Coastguard Worker #ifdef __FreeBSD__
186*8b26181fSAndroid Build Coastguard Worker 			/*
187*8b26181fSAndroid Build Coastguard Worker 			 * In FreeBSD, we need to return the
188*8b26181fSAndroid Build Coastguard Worker 			 * high-order flags, as we're using
189*8b26181fSAndroid Build Coastguard Worker 			 * IFF_PPROMISC, which is in those bits.
190*8b26181fSAndroid Build Coastguard Worker 			 *
191*8b26181fSAndroid Build Coastguard Worker 			 * XXX - DragonFly BSD?
192*8b26181fSAndroid Build Coastguard Worker 			 */
193*8b26181fSAndroid Build Coastguard Worker 			*if_flags |= (ifr.ifr_flagshigh << 16);
194*8b26181fSAndroid Build Coastguard Worker #endif /* __FreeBSD__ */
195*8b26181fSAndroid Build Coastguard Worker 		}
196*8b26181fSAndroid Build Coastguard Worker 	}
197*8b26181fSAndroid Build Coastguard Worker #ifdef linux
198*8b26181fSAndroid Build Coastguard Worker 	close(fd);
199*8b26181fSAndroid Build Coastguard Worker #endif /* linux */
200*8b26181fSAndroid Build Coastguard Worker 	return error ? -1 : 0;
201*8b26181fSAndroid Build Coastguard Worker }
202*8b26181fSAndroid Build Coastguard Worker 
203*8b26181fSAndroid Build Coastguard Worker 
204*8b26181fSAndroid Build Coastguard Worker static void
pcap_netmap_close(pcap_t * p)205*8b26181fSAndroid Build Coastguard Worker pcap_netmap_close(pcap_t *p)
206*8b26181fSAndroid Build Coastguard Worker {
207*8b26181fSAndroid Build Coastguard Worker 	struct pcap_netmap *pn = p->priv;
208*8b26181fSAndroid Build Coastguard Worker 	struct nm_desc *d = pn->d;
209*8b26181fSAndroid Build Coastguard Worker 	uint32_t if_flags = 0;
210*8b26181fSAndroid Build Coastguard Worker 
211*8b26181fSAndroid Build Coastguard Worker 	if (pn->must_clear_promisc) {
212*8b26181fSAndroid Build Coastguard Worker 		pcap_netmap_ioctl(p, SIOCGIFFLAGS, &if_flags); /* fetch flags */
213*8b26181fSAndroid Build Coastguard Worker 		if (if_flags & IFF_PPROMISC) {
214*8b26181fSAndroid Build Coastguard Worker 			if_flags &= ~IFF_PPROMISC;
215*8b26181fSAndroid Build Coastguard Worker 			pcap_netmap_ioctl(p, SIOCSIFFLAGS, &if_flags);
216*8b26181fSAndroid Build Coastguard Worker 		}
217*8b26181fSAndroid Build Coastguard Worker 	}
218*8b26181fSAndroid Build Coastguard Worker 	nm_close(d);
219*8b26181fSAndroid Build Coastguard Worker 	pcap_cleanup_live_common(p);
220*8b26181fSAndroid Build Coastguard Worker }
221*8b26181fSAndroid Build Coastguard Worker 
222*8b26181fSAndroid Build Coastguard Worker 
223*8b26181fSAndroid Build Coastguard Worker static int
pcap_netmap_activate(pcap_t * p)224*8b26181fSAndroid Build Coastguard Worker pcap_netmap_activate(pcap_t *p)
225*8b26181fSAndroid Build Coastguard Worker {
226*8b26181fSAndroid Build Coastguard Worker 	struct pcap_netmap *pn = p->priv;
227*8b26181fSAndroid Build Coastguard Worker 	struct nm_desc *d;
228*8b26181fSAndroid Build Coastguard Worker 	uint32_t if_flags = 0;
229*8b26181fSAndroid Build Coastguard Worker 
230*8b26181fSAndroid Build Coastguard Worker 	d = nm_open(p->opt.device, NULL, 0, NULL);
231*8b26181fSAndroid Build Coastguard Worker 	if (d == NULL) {
232*8b26181fSAndroid Build Coastguard Worker 		pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
233*8b26181fSAndroid Build Coastguard Worker 		    errno, "netmap open: cannot access %s",
234*8b26181fSAndroid Build Coastguard Worker 		    p->opt.device);
235*8b26181fSAndroid Build Coastguard Worker 		pcap_cleanup_live_common(p);
236*8b26181fSAndroid Build Coastguard Worker 		return (PCAP_ERROR);
237*8b26181fSAndroid Build Coastguard Worker 	}
238*8b26181fSAndroid Build Coastguard Worker #if 0
239*8b26181fSAndroid Build Coastguard Worker 	fprintf(stderr, "%s device %s priv %p fd %d ports %d..%d\n",
240*8b26181fSAndroid Build Coastguard Worker 	    __FUNCTION__, p->opt.device, d, d->fd,
241*8b26181fSAndroid Build Coastguard Worker 	    d->first_rx_ring, d->last_rx_ring);
242*8b26181fSAndroid Build Coastguard Worker #endif
243*8b26181fSAndroid Build Coastguard Worker 	pn->d = d;
244*8b26181fSAndroid Build Coastguard Worker 	p->fd = d->fd;
245*8b26181fSAndroid Build Coastguard Worker 
246*8b26181fSAndroid Build Coastguard Worker 	/*
247*8b26181fSAndroid Build Coastguard Worker 	 * Turn a negative snapshot value (invalid), a snapshot value of
248*8b26181fSAndroid Build Coastguard Worker 	 * 0 (unspecified), or a value bigger than the normal maximum
249*8b26181fSAndroid Build Coastguard Worker 	 * value, into the maximum allowed value.
250*8b26181fSAndroid Build Coastguard Worker 	 *
251*8b26181fSAndroid Build Coastguard Worker 	 * If some application really *needs* a bigger snapshot
252*8b26181fSAndroid Build Coastguard Worker 	 * length, we should just increase MAXIMUM_SNAPLEN.
253*8b26181fSAndroid Build Coastguard Worker 	 */
254*8b26181fSAndroid Build Coastguard Worker 	if (p->snapshot <= 0 || p->snapshot > MAXIMUM_SNAPLEN)
255*8b26181fSAndroid Build Coastguard Worker 		p->snapshot = MAXIMUM_SNAPLEN;
256*8b26181fSAndroid Build Coastguard Worker 
257*8b26181fSAndroid Build Coastguard Worker 	if (p->opt.promisc && !(d->req.nr_ringid & NETMAP_SW_RING)) {
258*8b26181fSAndroid Build Coastguard Worker 		pcap_netmap_ioctl(p, SIOCGIFFLAGS, &if_flags); /* fetch flags */
259*8b26181fSAndroid Build Coastguard Worker 		if (!(if_flags & IFF_PPROMISC)) {
260*8b26181fSAndroid Build Coastguard Worker 			pn->must_clear_promisc = 1;
261*8b26181fSAndroid Build Coastguard Worker 			if_flags |= IFF_PPROMISC;
262*8b26181fSAndroid Build Coastguard Worker 			pcap_netmap_ioctl(p, SIOCSIFFLAGS, &if_flags);
263*8b26181fSAndroid Build Coastguard Worker 		}
264*8b26181fSAndroid Build Coastguard Worker 	}
265*8b26181fSAndroid Build Coastguard Worker 	p->linktype = DLT_EN10MB;
266*8b26181fSAndroid Build Coastguard Worker 	p->selectable_fd = p->fd;
267*8b26181fSAndroid Build Coastguard Worker 	p->read_op = pcap_netmap_dispatch;
268*8b26181fSAndroid Build Coastguard Worker 	p->inject_op = pcap_netmap_inject;
269*8b26181fSAndroid Build Coastguard Worker 	p->setfilter_op = install_bpf_program;
270*8b26181fSAndroid Build Coastguard Worker 	p->setdirection_op = NULL;
271*8b26181fSAndroid Build Coastguard Worker 	p->set_datalink_op = NULL;
272*8b26181fSAndroid Build Coastguard Worker 	p->getnonblock_op = pcap_getnonblock_fd;
273*8b26181fSAndroid Build Coastguard Worker 	p->setnonblock_op = pcap_setnonblock_fd;
274*8b26181fSAndroid Build Coastguard Worker 	p->stats_op = pcap_netmap_stats;
275*8b26181fSAndroid Build Coastguard Worker 	p->cleanup_op = pcap_netmap_close;
276*8b26181fSAndroid Build Coastguard Worker 
277*8b26181fSAndroid Build Coastguard Worker 	return (0);
278*8b26181fSAndroid Build Coastguard Worker }
279*8b26181fSAndroid Build Coastguard Worker 
280*8b26181fSAndroid Build Coastguard Worker 
281*8b26181fSAndroid Build Coastguard Worker pcap_t *
pcap_netmap_create(const char * device,char * ebuf,int * is_ours)282*8b26181fSAndroid Build Coastguard Worker pcap_netmap_create(const char *device, char *ebuf, int *is_ours)
283*8b26181fSAndroid Build Coastguard Worker {
284*8b26181fSAndroid Build Coastguard Worker 	pcap_t *p;
285*8b26181fSAndroid Build Coastguard Worker 
286*8b26181fSAndroid Build Coastguard Worker 	*is_ours = (!strncmp(device, "netmap:", 7) || !strncmp(device, "vale", 4));
287*8b26181fSAndroid Build Coastguard Worker 	if (! *is_ours)
288*8b26181fSAndroid Build Coastguard Worker 		return NULL;
289*8b26181fSAndroid Build Coastguard Worker 	p = PCAP_CREATE_COMMON(ebuf, struct pcap_netmap);
290*8b26181fSAndroid Build Coastguard Worker 	if (p == NULL)
291*8b26181fSAndroid Build Coastguard Worker 		return (NULL);
292*8b26181fSAndroid Build Coastguard Worker 	p->activate_op = pcap_netmap_activate;
293*8b26181fSAndroid Build Coastguard Worker 	return (p);
294*8b26181fSAndroid Build Coastguard Worker }
295*8b26181fSAndroid Build Coastguard Worker 
296*8b26181fSAndroid Build Coastguard Worker /*
297*8b26181fSAndroid Build Coastguard Worker  * The "device name" for netmap devices isn't a name for a device, it's
298*8b26181fSAndroid Build Coastguard Worker  * an expression that indicates how the device should be set up, so
299*8b26181fSAndroid Build Coastguard Worker  * there's no way to enumerate them.
300*8b26181fSAndroid Build Coastguard Worker  */
301*8b26181fSAndroid Build Coastguard Worker int
pcap_netmap_findalldevs(pcap_if_list_t * devlistp _U_,char * err_str _U_)302*8b26181fSAndroid Build Coastguard Worker pcap_netmap_findalldevs(pcap_if_list_t *devlistp _U_, char *err_str _U_)
303*8b26181fSAndroid Build Coastguard Worker {
304*8b26181fSAndroid Build Coastguard Worker 	return 0;
305*8b26181fSAndroid Build Coastguard Worker }
306