1/*
2 * Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy)
3 * Copyright (c) 2005 - 2010 CACE Technologies, Davis (California)
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the Politecnico di Torino, CACE Technologies
16 * nor the names of its contributors may be used to endorse or promote
17 * products derived from this software without specific prior written
18 * permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33
34#ifdef HAVE_CONFIG_H
35#include <config.h>
36#endif
37
38#include "pcap-int.h"
39
40#include <airpcap.h>
41
42#include "pcap-airpcap.h"
43
44/* Default size of the buffer we allocate in userland. */
45#define	AIRPCAP_DEFAULT_USER_BUFFER_SIZE 256000
46
47/* Default size of the buffer for the AirPcap adapter. */
48#define	AIRPCAP_DEFAULT_KERNEL_BUFFER_SIZE 1000000
49
50//
51// We load the AirPcap DLL dynamically, so that the code will
52// work whether you have it installed or not, and there don't
53// have to be two different versions of the library, one linked
54// to the AirPcap library and one not linked to it.
55//
56static pcap_code_handle_t airpcap_lib;
57
58typedef PCHAR (*AirpcapGetLastErrorHandler)(PAirpcapHandle);
59typedef BOOL (*AirpcapGetDeviceListHandler)(PAirpcapDeviceDescription *, PCHAR);
60typedef VOID (*AirpcapFreeDeviceListHandler)(PAirpcapDeviceDescription);
61typedef PAirpcapHandle (*AirpcapOpenHandler)(PCHAR, PCHAR);
62typedef VOID (*AirpcapCloseHandler)(PAirpcapHandle);
63typedef BOOL (*AirpcapSetDeviceMacFlagsHandler)(PAirpcapHandle, UINT);
64typedef BOOL (*AirpcapSetLinkTypeHandler)(PAirpcapHandle, AirpcapLinkType);
65typedef BOOL (*AirpcapGetLinkTypeHandler)(PAirpcapHandle, PAirpcapLinkType);
66typedef BOOL (*AirpcapSetKernelBufferHandler)(PAirpcapHandle, UINT);
67typedef BOOL (*AirpcapSetFilterHandler)(PAirpcapHandle, PVOID, UINT);
68typedef BOOL (*AirpcapSetMinToCopyHandler)(PAirpcapHandle, UINT);
69typedef BOOL (*AirpcapGetReadEventHandler)(PAirpcapHandle, HANDLE *);
70typedef BOOL (*AirpcapReadHandler)(PAirpcapHandle, PBYTE, UINT, PUINT);
71typedef BOOL (*AirpcapWriteHandler)(PAirpcapHandle, PCHAR, ULONG);
72typedef BOOL (*AirpcapGetStatsHandler)(PAirpcapHandle, PAirpcapStats);
73
74static AirpcapGetLastErrorHandler p_AirpcapGetLastError;
75static AirpcapGetDeviceListHandler p_AirpcapGetDeviceList;
76static AirpcapFreeDeviceListHandler p_AirpcapFreeDeviceList;
77static AirpcapOpenHandler p_AirpcapOpen;
78static AirpcapCloseHandler p_AirpcapClose;
79static AirpcapSetDeviceMacFlagsHandler p_AirpcapSetDeviceMacFlags;
80static AirpcapSetLinkTypeHandler p_AirpcapSetLinkType;
81static AirpcapGetLinkTypeHandler p_AirpcapGetLinkType;
82static AirpcapSetKernelBufferHandler p_AirpcapSetKernelBuffer;
83static AirpcapSetFilterHandler p_AirpcapSetFilter;
84static AirpcapSetMinToCopyHandler p_AirpcapSetMinToCopy;
85static AirpcapGetReadEventHandler p_AirpcapGetReadEvent;
86static AirpcapReadHandler p_AirpcapRead;
87static AirpcapWriteHandler p_AirpcapWrite;
88static AirpcapGetStatsHandler p_AirpcapGetStats;
89
90typedef enum LONG
91{
92	AIRPCAP_API_UNLOADED = 0,
93	AIRPCAP_API_LOADED,
94	AIRPCAP_API_CANNOT_LOAD,
95	AIRPCAP_API_LOADING
96} AIRPCAP_API_LOAD_STATUS;
97
98static AIRPCAP_API_LOAD_STATUS	airpcap_load_status;
99
100/*
101 * NOTE: this function should be called by the pcap functions that can
102 *       theoretically deal with the AirPcap library for the first time,
103 *       namely listing the adapters and creating a pcap_t for an adapter.
104 *       All the other ones (activate, close, read, write, set parameters)
105 *       work on a pcap_t for an AirPcap device, meaning we've already
106 *       created the pcap_t and thus have loaded the functions, so we do
107 *       not need to call this function.
108 */
109static AIRPCAP_API_LOAD_STATUS
110load_airpcap_functions(void)
111{
112	AIRPCAP_API_LOAD_STATUS current_status;
113
114	/*
115	 * We don't use a mutex because there's no place that
116	 * we can guarantee we'll be called before any threads
117	 * other than the main thread exists.  (For example,
118	 * this might be a static library, so we can't arrange
119	 * to be called by DllMain(), and there's no guarantee
120	 * that the application called pcap_init() - which is
121	 * supposed to be called only from one thread - so
122	 * we can't arrange to be called from it.)
123	 *
124	 * If nobody's tried to load it yet, mark it as
125	 * loading; in any case, return the status before
126	 * we modified it.
127	 */
128	current_status = InterlockedCompareExchange((LONG *)&airpcap_load_status,
129	    AIRPCAP_API_LOADING, AIRPCAP_API_UNLOADED);
130
131	/*
132	 * If the status was AIRPCAP_API_UNLOADED, we've set it
133	 * to AIRPCAP_API_LOADING, because we're going to be
134	 * the ones to load the library but current_status is
135	 * AIRPCAP_API_UNLOADED.
136	 *
137	 * if it was AIRPCAP_API_LOADING, meaning somebody else
138	 * was trying to load it, spin until they finish and
139	 * set the status to a value reflecting whether they
140	 * succeeded.
141	 */
142	while (current_status == AIRPCAP_API_LOADING) {
143		current_status = InterlockedCompareExchange((LONG*)&airpcap_load_status,
144		    AIRPCAP_API_LOADING, AIRPCAP_API_LOADING);
145		Sleep(10);
146	}
147
148	/*
149	 * At this point, current_status is either:
150	 *
151	 *	AIRPCAP_API_LOADED, in which case another thread
152	 *	loaded the library, so we're done;
153	 *
154	 *	AIRPCAP_API_CANNOT_LOAD, in which another thread
155	 *	tried and failed to load the library, so we're
156	 *	done - we won't try it ourselves;
157	 *
158	 *	AIRPCAP_API_LOADING, in which case *we're* the
159	 *	ones loading it, and should now try to do so.
160	 */
161	if (current_status == AIRPCAP_API_LOADED)
162		return AIRPCAP_API_LOADED;
163
164	if (current_status == AIRPCAP_API_CANNOT_LOAD)
165		return AIRPCAP_API_CANNOT_LOAD;
166
167	/*
168	 * Start out assuming we can't load it.
169	 */
170	current_status = AIRPCAP_API_CANNOT_LOAD;
171
172	airpcap_lib = pcap_load_code("airpcap.dll");
173	if (airpcap_lib != NULL) {
174		/*
175		 * OK, we've loaded the library; now try to find the
176		 * functions we need in it.
177		 */
178		p_AirpcapGetLastError = (AirpcapGetLastErrorHandler) pcap_find_function(airpcap_lib, "AirpcapGetLastError");
179		p_AirpcapGetDeviceList = (AirpcapGetDeviceListHandler) pcap_find_function(airpcap_lib, "AirpcapGetDeviceList");
180		p_AirpcapFreeDeviceList = (AirpcapFreeDeviceListHandler) pcap_find_function(airpcap_lib, "AirpcapFreeDeviceList");
181		p_AirpcapOpen = (AirpcapOpenHandler) pcap_find_function(airpcap_lib, "AirpcapOpen");
182		p_AirpcapClose = (AirpcapCloseHandler) pcap_find_function(airpcap_lib, "AirpcapClose");
183		p_AirpcapSetDeviceMacFlags = (AirpcapSetDeviceMacFlagsHandler) pcap_find_function(airpcap_lib, "AirpcapSetDeviceMacFlags");
184		p_AirpcapSetLinkType = (AirpcapSetLinkTypeHandler) pcap_find_function(airpcap_lib, "AirpcapSetLinkType");
185		p_AirpcapGetLinkType = (AirpcapGetLinkTypeHandler) pcap_find_function(airpcap_lib, "AirpcapGetLinkType");
186		p_AirpcapSetKernelBuffer = (AirpcapSetKernelBufferHandler) pcap_find_function(airpcap_lib, "AirpcapSetKernelBuffer");
187		p_AirpcapSetFilter = (AirpcapSetFilterHandler) pcap_find_function(airpcap_lib, "AirpcapSetFilter");
188		p_AirpcapSetMinToCopy = (AirpcapSetMinToCopyHandler) pcap_find_function(airpcap_lib, "AirpcapSetMinToCopy");
189		p_AirpcapGetReadEvent = (AirpcapGetReadEventHandler) pcap_find_function(airpcap_lib, "AirpcapGetReadEvent");
190		p_AirpcapRead = (AirpcapReadHandler) pcap_find_function(airpcap_lib, "AirpcapRead");
191		p_AirpcapWrite = (AirpcapWriteHandler) pcap_find_function(airpcap_lib, "AirpcapWrite");
192		p_AirpcapGetStats = (AirpcapGetStatsHandler) pcap_find_function(airpcap_lib, "AirpcapGetStats");
193
194		//
195		// Make sure that we found everything
196		//
197		if (p_AirpcapGetLastError != NULL &&
198		    p_AirpcapGetDeviceList != NULL &&
199		    p_AirpcapFreeDeviceList != NULL &&
200		    p_AirpcapOpen != NULL &&
201		    p_AirpcapClose != NULL &&
202		    p_AirpcapSetDeviceMacFlags != NULL &&
203		    p_AirpcapSetLinkType != NULL &&
204		    p_AirpcapGetLinkType != NULL &&
205		    p_AirpcapSetKernelBuffer != NULL &&
206		    p_AirpcapSetFilter != NULL &&
207		    p_AirpcapSetMinToCopy != NULL &&
208		    p_AirpcapGetReadEvent != NULL &&
209		    p_AirpcapRead != NULL &&
210		    p_AirpcapWrite != NULL &&
211		    p_AirpcapGetStats != NULL) {
212			/*
213			 * We have all we need.
214			 */
215			current_status = AIRPCAP_API_LOADED;
216		}
217	}
218
219	if (current_status != AIRPCAP_API_LOADED) {
220		/*
221		 * We failed; if we found the DLL, close the
222		 * handle for it.
223		 */
224		if (airpcap_lib != NULL) {
225			FreeLibrary(airpcap_lib);
226			airpcap_lib = NULL;
227		}
228	}
229
230	/*
231	 * Now set the status appropriately - and atomically.
232	 */
233	InterlockedExchange((LONG *)&airpcap_load_status, current_status);
234
235	return current_status;
236}
237
238/*
239 * Private data for capturing on AirPcap devices.
240 */
241struct pcap_airpcap {
242	PAirpcapHandle adapter;
243	int filtering_in_kernel;
244	int nonblock;
245	int read_timeout;
246	HANDLE read_event;
247	struct pcap_stat stat;
248};
249
250static int
251airpcap_setfilter(pcap_t *p, struct bpf_program *fp)
252{
253	struct pcap_airpcap *pa = p->priv;
254
255	if (!p_AirpcapSetFilter(pa->adapter, fp->bf_insns,
256	    fp->bf_len * sizeof(struct bpf_insn))) {
257		/*
258		 * Kernel filter not installed.
259		 *
260		 * XXX - we don't know whether this failed because:
261		 *
262		 *  the kernel rejected the filter program as invalid,
263		 *  in which case we should fall back on userland
264		 *  filtering;
265		 *
266		 *  the kernel rejected the filter program as too big,
267		 *  in which case we should again fall back on
268		 *  userland filtering;
269		 *
270		 *  there was some other problem, in which case we
271		 *  should probably report an error;
272		 *
273		 * So we just fall back on userland filtering in
274		 * all cases.
275		 */
276
277		/*
278		 * install_bpf_program() validates the program.
279		 *
280		 * XXX - what if we already have a filter in the kernel?
281		 */
282		if (install_bpf_program(p, fp) < 0)
283			return (-1);
284		pa->filtering_in_kernel = 0;	/* filtering in userland */
285		return (0);
286	}
287
288	/*
289	 * It worked.
290	 */
291	pa->filtering_in_kernel = 1;	/* filtering in the kernel */
292
293	/*
294	 * Discard any previously-received packets, as they might have
295	 * passed whatever filter was formerly in effect, but might
296	 * not pass this filter (BIOCSETF discards packets buffered
297	 * in the kernel, so you can lose packets in any case).
298	 */
299	p->cc = 0;
300	return (0);
301}
302
303static int
304airpcap_set_datalink(pcap_t *p, int dlt)
305{
306	struct pcap_airpcap *pa = p->priv;
307	AirpcapLinkType type;
308
309	switch (dlt) {
310
311	case DLT_IEEE802_11_RADIO:
312		type = AIRPCAP_LT_802_11_PLUS_RADIO;
313		break;
314
315	case DLT_PPI:
316		type = AIRPCAP_LT_802_11_PLUS_PPI;
317		break;
318
319	case DLT_IEEE802_11:
320		type = AIRPCAP_LT_802_11;
321		break;
322
323	default:
324		/* This can't happen; just return. */
325		return (0);
326	}
327	if (!p_AirpcapSetLinkType(pa->adapter, type)) {
328		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
329		    "AirpcapSetLinkType() failed: %s",
330		    p_AirpcapGetLastError(pa->adapter));
331		return (-1);
332	}
333	p->linktype = dlt;
334	return (0);
335}
336
337static int
338airpcap_getnonblock(pcap_t *p)
339{
340	struct pcap_airpcap *pa = p->priv;
341
342	return (pa->nonblock);
343}
344
345static int
346airpcap_setnonblock(pcap_t *p, int nonblock)
347{
348	struct pcap_airpcap *pa = p->priv;
349	int newtimeout;
350
351	if (nonblock) {
352		/*
353		 * Set the packet buffer timeout to -1 for non-blocking
354		 * mode.
355		 */
356		newtimeout = -1;
357	} else {
358		/*
359		 * Restore the timeout set when the device was opened.
360		 * (Note that this may be -1, in which case we're not
361		 * really leaving non-blocking mode.  However, although
362		 * the timeout argument to pcap_set_timeout() and
363		 * pcap_open_live() is an int, you're not supposed to
364		 * supply a negative value, so that "shouldn't happen".)
365		 */
366		newtimeout = p->opt.timeout;
367	}
368	pa->read_timeout = newtimeout;
369	pa->nonblock = (newtimeout == -1);
370	return (0);
371}
372
373static int
374airpcap_stats(pcap_t *p, struct pcap_stat *ps)
375{
376	struct pcap_airpcap *pa = p->priv;
377	AirpcapStats tas;
378
379	/*
380	 * Try to get statistics.
381	 */
382	if (!p_AirpcapGetStats(pa->adapter, &tas)) {
383		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
384		    "AirpcapGetStats() failed: %s",
385		    p_AirpcapGetLastError(pa->adapter));
386		return (-1);
387	}
388
389	ps->ps_drop = tas.Drops;
390	ps->ps_recv = tas.Recvs;
391	ps->ps_ifdrop = tas.IfDrops;
392
393	return (0);
394}
395
396/*
397 * Win32-only routine for getting statistics.
398 *
399 * This way is definitely safer than passing the pcap_stat * from the userland.
400 * In fact, there could happen than the user allocates a variable which is not
401 * big enough for the new structure, and the library will write in a zone
402 * which is not allocated to this variable.
403 *
404 * In this way, we're pretty sure we are writing on memory allocated to this
405 * variable.
406 *
407 * XXX - but this is the wrong way to handle statistics.  Instead, we should
408 * have an API that returns data in a form like the Options section of a
409 * pcapng Interface Statistics Block:
410 *
411 *    https://xml2rfc.tools.ietf.org/cgi-bin/xml2rfc.cgi?url=https://raw.githubusercontent.com/pcapng/pcapng/master/draft-tuexen-opsawg-pcapng.xml&modeAsFormat=html/ascii&type=ascii#rfc.section.4.6
412 *
413 * which would let us add new statistics straightforwardly and indicate which
414 * statistics we are and are *not* providing, rather than having to provide
415 * possibly-bogus values for statistics we can't provide.
416 */
417static struct pcap_stat *
418airpcap_stats_ex(pcap_t *p, int *pcap_stat_size)
419{
420	struct pcap_airpcap *pa = p->priv;
421	AirpcapStats tas;
422
423	*pcap_stat_size = sizeof (p->stat);
424
425	/*
426	 * Try to get statistics.
427	 */
428	if (!p_AirpcapGetStats(pa->adapter, &tas)) {
429		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
430		    "AirpcapGetStats() failed: %s",
431		    p_AirpcapGetLastError(pa->adapter));
432		return (NULL);
433	}
434
435	p->stat.ps_recv = tas.Recvs;
436	p->stat.ps_drop = tas.Drops;
437	p->stat.ps_ifdrop = tas.IfDrops;
438	/*
439	 * Just in case this is ever compiled for a target other than
440	 * Windows, which is extremely unlikely at best.
441	 */
442#ifdef _WIN32
443	p->stat.ps_capt = tas.Capt;
444#endif
445	return (&p->stat);
446}
447
448/* Set the dimension of the kernel-level capture buffer */
449static int
450airpcap_setbuff(pcap_t *p, int dim)
451{
452	struct pcap_airpcap *pa = p->priv;
453
454	if (!p_AirpcapSetKernelBuffer(pa->adapter, dim)) {
455		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
456		    "AirpcapSetKernelBuffer() failed: %s",
457		    p_AirpcapGetLastError(pa->adapter));
458		return (-1);
459	}
460	return (0);
461}
462
463/* Set the driver working mode */
464static int
465airpcap_setmode(pcap_t *p, int mode)
466{
467	 if (mode != MODE_CAPT) {
468		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
469		    "Only MODE_CAPT is supported on an AirPcap adapter");
470		return (-1);
471	 }
472	 return (0);
473}
474
475/*set the minimum amount of data that will release a read call*/
476static int
477airpcap_setmintocopy(pcap_t *p, int size)
478{
479	struct pcap_airpcap *pa = p->priv;
480
481	if (!p_AirpcapSetMinToCopy(pa->adapter, size)) {
482		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
483		    "AirpcapSetMinToCopy() failed: %s",
484		    p_AirpcapGetLastError(pa->adapter));
485		return (-1);
486	}
487	return (0);
488}
489
490static HANDLE
491airpcap_getevent(pcap_t *p)
492{
493	struct pcap_airpcap *pa = p->priv;
494
495	return (pa->read_event);
496}
497
498static int
499airpcap_oid_get_request(pcap_t *p, bpf_u_int32 oid _U_, void *data _U_,
500    size_t *lenp _U_)
501{
502	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
503	    "Getting OID values is not supported on an AirPcap adapter");
504	return (PCAP_ERROR);
505}
506
507static int
508airpcap_oid_set_request(pcap_t *p, bpf_u_int32 oid _U_, const void *data _U_,
509    size_t *lenp _U_)
510{
511	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
512	    "Setting OID values is not supported on an AirPcap adapter");
513	return (PCAP_ERROR);
514}
515
516static u_int
517airpcap_sendqueue_transmit(pcap_t *p, pcap_send_queue *queue _U_, int sync _U_)
518{
519	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
520	    "Cannot queue packets for transmission on an AirPcap adapter");
521	return (0);
522}
523
524static int
525airpcap_setuserbuffer(pcap_t *p, int size)
526{
527	unsigned char *new_buff;
528
529	if (size <= 0) {
530		/* Bogus parameter */
531		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
532		    "Error: invalid size %d",size);
533		return (-1);
534	}
535
536	/* Allocate the buffer */
537	new_buff = (unsigned char *)malloc(sizeof(char)*size);
538
539	if (!new_buff) {
540		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
541		    "Error: not enough memory");
542		return (-1);
543	}
544
545	free(p->buffer);
546
547	p->buffer = new_buff;
548	p->bufsize = size;
549
550	return (0);
551}
552
553static int
554airpcap_live_dump(pcap_t *p, char *filename _U_, int maxsize _U_,
555    int maxpacks _U_)
556{
557	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
558	    "AirPcap adapters don't support live dump");
559	return (-1);
560}
561
562static int
563airpcap_live_dump_ended(pcap_t *p, int sync _U_)
564{
565	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
566	    "AirPcap adapters don't support live dump");
567	return (-1);
568}
569
570static PAirpcapHandle
571airpcap_get_airpcap_handle(pcap_t *p)
572{
573	struct pcap_airpcap *pa = p->priv;
574
575	return (pa->adapter);
576}
577
578static int
579airpcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
580{
581	struct pcap_airpcap *pa = p->priv;
582	int cc;
583	int n;
584	register u_char *bp, *ep;
585	UINT bytes_read;
586	u_char *datap;
587
588	cc = p->cc;
589	if (cc == 0) {
590		/*
591		 * Has "pcap_breakloop()" been called?
592		 */
593		if (p->break_loop) {
594			/*
595			 * Yes - clear the flag that indicates that it
596			 * has, and return PCAP_ERROR_BREAK to indicate
597			 * that we were told to break out of the loop.
598			 */
599			p->break_loop = 0;
600			return (PCAP_ERROR_BREAK);
601		}
602
603		//
604		// If we're not in non-blocking mode, wait for data to
605		// arrive.
606		//
607		if (pa->read_timeout != -1) {
608			WaitForSingleObject(pa->read_event,
609			    (pa->read_timeout ==0 )? INFINITE: pa->read_timeout);
610		}
611
612		//
613		// Read the data.
614		// p_AirpcapRead doesn't block.
615		//
616		if (!p_AirpcapRead(pa->adapter, (PBYTE)p->buffer,
617		    p->bufsize, &bytes_read)) {
618			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
619			    "AirpcapRead() failed: %s",
620			    p_AirpcapGetLastError(pa->adapter));
621			return (-1);
622		}
623		cc = bytes_read;
624		bp = (u_char *)p->buffer;
625	} else
626		bp = p->bp;
627
628	/*
629	 * Loop through each packet.
630	 *
631	 * This assumes that a single buffer of packets will have
632	 * <= INT_MAX packets, so the packet count doesn't overflow.
633	 */
634#define bhp ((AirpcapBpfHeader *)bp)
635	n = 0;
636	ep = bp + cc;
637	for (;;) {
638		register u_int caplen, hdrlen;
639
640		/*
641		 * Has "pcap_breakloop()" been called?
642		 * If so, return immediately - if we haven't read any
643		 * packets, clear the flag and return PCAP_ERROR_BREAK
644		 * to indicate that we were told to break out of the loop,
645		 * otherwise leave the flag set, so that the *next* call
646		 * will break out of the loop without having read any
647		 * packets, and return the number of packets we've
648		 * processed so far.
649		 */
650		if (p->break_loop) {
651			if (n == 0) {
652				p->break_loop = 0;
653				return (PCAP_ERROR_BREAK);
654			} else {
655				p->bp = bp;
656				p->cc = (int) (ep - bp);
657				return (n);
658			}
659		}
660		if (bp >= ep)
661			break;
662
663		caplen = bhp->Caplen;
664		hdrlen = bhp->Hdrlen;
665		datap = bp + hdrlen;
666		/*
667		 * Short-circuit evaluation: if using BPF filter
668		 * in the AirPcap adapter, no need to do it now -
669		 * we already know the packet passed the filter.
670		 */
671		if (pa->filtering_in_kernel ||
672		    p->fcode.bf_insns == NULL ||
673		    pcap_filter(p->fcode.bf_insns, datap, bhp->Originallen, caplen)) {
674			struct pcap_pkthdr pkthdr;
675
676			pkthdr.ts.tv_sec = bhp->TsSec;
677			pkthdr.ts.tv_usec = bhp->TsUsec;
678			pkthdr.caplen = caplen;
679			pkthdr.len = bhp->Originallen;
680			(*callback)(user, &pkthdr, datap);
681			bp += AIRPCAP_WORDALIGN(caplen + hdrlen);
682			if (++n >= cnt && !PACKET_COUNT_IS_UNLIMITED(cnt)) {
683				p->bp = bp;
684				p->cc = (int)(ep - bp);
685				return (n);
686			}
687		} else {
688			/*
689			 * Skip this packet.
690			 */
691			bp += AIRPCAP_WORDALIGN(caplen + hdrlen);
692		}
693	}
694#undef bhp
695	p->cc = 0;
696	return (n);
697}
698
699static int
700airpcap_inject(pcap_t *p, const void *buf, int size)
701{
702	struct pcap_airpcap *pa = p->priv;
703
704	/*
705	 * XXX - the second argument to AirpcapWrite() *should* have
706	 * been declared as a const pointer - a write function that
707	 * stomps on what it writes is *extremely* rude - but such
708	 * is life.  We assume it is, in fact, not going to write on
709	 * our buffer.
710	 */
711	if (!p_AirpcapWrite(pa->adapter, (void *)buf, size)) {
712		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
713		    "AirpcapWrite() failed: %s",
714		    p_AirpcapGetLastError(pa->adapter));
715		return (-1);
716	}
717
718	/*
719	 * We assume it all got sent if "AirpcapWrite()" succeeded.
720	 * "pcap_inject()" is expected to return the number of bytes
721	 * sent.
722	 */
723	return (size);
724}
725
726static void
727airpcap_cleanup(pcap_t *p)
728{
729	struct pcap_airpcap *pa = p->priv;
730
731	if (pa->adapter != NULL) {
732		p_AirpcapClose(pa->adapter);
733		pa->adapter = NULL;
734	}
735	pcap_cleanup_live_common(p);
736}
737
738static void
739airpcap_breakloop(pcap_t *p)
740{
741	HANDLE read_event;
742
743	pcap_breakloop_common(p);
744	struct pcap_airpcap *pa = p->priv;
745
746	/* XXX - what if either of these fail? */
747	/*
748	 * XXX - will SetEvent() force a wakeup and, if so, will
749	 * the AirPcap read code handle that sanely?
750	 */
751	if (!p_AirpcapGetReadEvent(pa->adapter, &read_event))
752		return;
753	SetEvent(read_event);
754}
755
756static int
757airpcap_activate(pcap_t *p)
758{
759	struct pcap_airpcap *pa = p->priv;
760	char *device = p->opt.device;
761	char airpcap_errbuf[AIRPCAP_ERRBUF_SIZE];
762	BOOL status;
763	AirpcapLinkType link_type;
764
765	pa->adapter = p_AirpcapOpen(device, airpcap_errbuf);
766	if (pa->adapter == NULL) {
767		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s", airpcap_errbuf);
768		return (PCAP_ERROR);
769	}
770
771	/*
772	 * Set monitor mode appropriately.
773	 * Always turn off the "ACK frames sent to the card" mode.
774	 */
775	if (p->opt.rfmon) {
776		status = p_AirpcapSetDeviceMacFlags(pa->adapter,
777		    AIRPCAP_MF_MONITOR_MODE_ON);
778	} else
779		status = p_AirpcapSetDeviceMacFlags(pa->adapter,
780		    AIRPCAP_MF_ACK_FRAMES_ON);
781	if (!status) {
782		p_AirpcapClose(pa->adapter);
783		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
784		    "AirpcapSetDeviceMacFlags() failed: %s",
785		    p_AirpcapGetLastError(pa->adapter));
786		return (PCAP_ERROR);
787	}
788
789	/*
790	 * Turn a negative snapshot value (invalid), a snapshot value of
791	 * 0 (unspecified), or a value bigger than the normal maximum
792	 * value, into the maximum allowed value.
793	 *
794	 * If some application really *needs* a bigger snapshot
795	 * length, we should just increase MAXIMUM_SNAPLEN.
796	 */
797	if (p->snapshot <= 0 || p->snapshot > MAXIMUM_SNAPLEN)
798		p->snapshot = MAXIMUM_SNAPLEN;
799
800	/*
801	 * If the buffer size wasn't explicitly set, default to
802	 * AIRPCAP_DEFAULT_KERNEL_BUFFER_SIZE.
803	 */
804	if (p->opt.buffer_size == 0)
805		p->opt.buffer_size = AIRPCAP_DEFAULT_KERNEL_BUFFER_SIZE;
806
807	if (!p_AirpcapSetKernelBuffer(pa->adapter, p->opt.buffer_size)) {
808		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
809		    "AirpcapSetKernelBuffer() failed: %s",
810		    p_AirpcapGetLastError(pa->adapter));
811		goto bad;
812	}
813
814	if(!p_AirpcapGetReadEvent(pa->adapter, &pa->read_event)) {
815		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
816		    "AirpcapGetReadEvent() failed: %s",
817		    p_AirpcapGetLastError(pa->adapter));
818		goto bad;
819	}
820
821	/* Set the buffer size */
822	p->bufsize = AIRPCAP_DEFAULT_USER_BUFFER_SIZE;
823	p->buffer = malloc(p->bufsize);
824	if (p->buffer == NULL) {
825		pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
826		    errno, "malloc");
827		goto bad;
828	}
829
830	if (p->opt.immediate) {
831		/* Tell the driver to copy the buffer as soon as data arrives. */
832		if (!p_AirpcapSetMinToCopy(pa->adapter, 0)) {
833			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
834			    "AirpcapSetMinToCopy() failed: %s",
835			    p_AirpcapGetLastError(pa->adapter));
836			goto bad;
837		}
838	} else {
839		/*
840		 * Tell the driver to copy the buffer only if it contains
841		 * at least 16K.
842		 */
843		if (!p_AirpcapSetMinToCopy(pa->adapter, 16000)) {
844			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
845			    "AirpcapSetMinToCopy() failed: %s",
846			    p_AirpcapGetLastError(pa->adapter));
847			goto bad;
848		}
849	}
850
851	/*
852	 * Find out what the default link-layer header type is,
853	 * and set p->datalink to that.
854	 *
855	 * We don't force it to another value because there
856	 * might be some programs using WinPcap/Npcap that,
857	 * when capturing on AirPcap devices, assume the
858	 * default value set with the AirPcap configuration
859	 * program is what you get.
860	 *
861	 * The out-of-the-box default appears to be radiotap.
862	 */
863	if (!p_AirpcapGetLinkType(pa->adapter, &link_type)) {
864		/* That failed. */
865		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
866		    "AirpcapGetLinkType() failed: %s",
867		    p_AirpcapGetLastError(pa->adapter));
868		goto bad;
869	}
870	switch (link_type) {
871
872	case AIRPCAP_LT_802_11_PLUS_RADIO:
873		p->linktype = DLT_IEEE802_11_RADIO;
874		break;
875
876	case AIRPCAP_LT_802_11_PLUS_PPI:
877		p->linktype = DLT_PPI;
878		break;
879
880	case AIRPCAP_LT_802_11:
881		p->linktype = DLT_IEEE802_11;
882		break;
883
884	case AIRPCAP_LT_UNKNOWN:
885	default:
886		/* OK, what? */
887		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
888		    "AirpcapGetLinkType() returned unknown link type %u",
889		    link_type);
890		goto bad;
891	}
892
893	/*
894	 * Now provide a list of all the supported types; we
895	 * assume they all work.  We put radiotap at the top,
896	 * followed by PPI, followed by "no radio metadata".
897	 */
898	p->dlt_list = (u_int *) malloc(sizeof(u_int) * 3);
899	if (p->dlt_list == NULL)
900		goto bad;
901	p->dlt_list[0] = DLT_IEEE802_11_RADIO;
902	p->dlt_list[1] = DLT_PPI;
903	p->dlt_list[2] = DLT_IEEE802_11;
904	p->dlt_count = 3;
905
906	p->read_op = airpcap_read;
907	p->inject_op = airpcap_inject;
908	p->setfilter_op = airpcap_setfilter;
909	p->setdirection_op = NULL;	/* Not implemented. */
910	p->set_datalink_op = airpcap_set_datalink;
911	p->getnonblock_op = airpcap_getnonblock;
912	p->setnonblock_op = airpcap_setnonblock;
913	p->breakloop_op = airpcap_breakloop;
914	p->stats_op = airpcap_stats;
915	p->stats_ex_op = airpcap_stats_ex;
916	p->setbuff_op = airpcap_setbuff;
917	p->setmode_op = airpcap_setmode;
918	p->setmintocopy_op = airpcap_setmintocopy;
919	p->getevent_op = airpcap_getevent;
920	p->oid_get_request_op = airpcap_oid_get_request;
921	p->oid_set_request_op = airpcap_oid_set_request;
922	p->sendqueue_transmit_op = airpcap_sendqueue_transmit;
923	p->setuserbuffer_op = airpcap_setuserbuffer;
924	p->live_dump_op = airpcap_live_dump;
925	p->live_dump_ended_op = airpcap_live_dump_ended;
926	p->get_airpcap_handle_op = airpcap_get_airpcap_handle;
927	p->cleanup_op = airpcap_cleanup;
928
929	return (0);
930 bad:
931	airpcap_cleanup(p);
932	return (PCAP_ERROR);
933}
934
935/*
936 * Monitor mode is supported.
937 */
938static int
939airpcap_can_set_rfmon(pcap_t *p)
940{
941	return (1);
942}
943
944int
945device_is_airpcap(const char *device, char *ebuf)
946{
947	static const char airpcap_prefix[] = "\\\\.\\airpcap";
948
949	/*
950	 * We don't determine this by calling AirpcapGetDeviceList()
951	 * and looking at the list, as that appears to be a costly
952	 * operation.
953	 *
954	 * Instead, we just check whether it begins with "\\.\airpcap".
955	 */
956	if (strncmp(device, airpcap_prefix, sizeof airpcap_prefix - 1) == 0) {
957		/*
958		 * Yes, it's an AirPcap device.
959		 */
960		return (1);
961	}
962
963	/*
964	 * No, it's not an AirPcap device.
965	 */
966	return (0);
967}
968
969pcap_t *
970airpcap_create(const char *device, char *ebuf, int *is_ours)
971{
972	int ret;
973	pcap_t *p;
974
975	/*
976	 * This can be called before we've tried loading the library,
977	 * so do so if we haven't already tried to do so.
978	 */
979	if (load_airpcap_functions() != AIRPCAP_API_LOADED) {
980		/*
981		 * We assume this means that we don't have the AirPcap
982		 * software installed, which probably means we don't
983		 * have an AirPcap device.
984		 *
985		 * Don't treat that as an error.
986		 */
987		*is_ours = 0;
988		return (NULL);
989	}
990
991	/*
992	 * Is this an AirPcap device?
993	 */
994	ret = device_is_airpcap(device, ebuf);
995	if (ret == 0) {
996		/* No. */
997		*is_ours = 0;
998		return (NULL);
999	}
1000
1001	/*
1002	 * Yes.
1003	 */
1004	*is_ours = 1;
1005	p = PCAP_CREATE_COMMON(ebuf, struct pcap_airpcap);
1006	if (p == NULL)
1007		return (NULL);
1008
1009	p->activate_op = airpcap_activate;
1010	p->can_set_rfmon_op = airpcap_can_set_rfmon;
1011	return (p);
1012}
1013
1014/*
1015 * Add all AirPcap devices.
1016 */
1017int
1018airpcap_findalldevs(pcap_if_list_t *devlistp, char *errbuf)
1019{
1020	AirpcapDeviceDescription *airpcap_devices, *airpcap_device;
1021	char airpcap_errbuf[AIRPCAP_ERRBUF_SIZE];
1022
1023	/*
1024	 * This can be called before we've tried loading the library,
1025	 * so do so if we haven't already tried to do so.
1026	 */
1027	if (load_airpcap_functions() != AIRPCAP_API_LOADED) {
1028		/*
1029		 * XXX - unless the error is "no such DLL", report this
1030		 * as an error rather than as "no AirPcap devices"?
1031		 */
1032		return (0);
1033	}
1034
1035	if (!p_AirpcapGetDeviceList(&airpcap_devices, airpcap_errbuf)) {
1036		snprintf(errbuf, PCAP_ERRBUF_SIZE,
1037		    "AirpcapGetDeviceList() failed: %s", airpcap_errbuf);
1038		return (-1);
1039	}
1040
1041	for (airpcap_device = airpcap_devices; airpcap_device != NULL;
1042	    airpcap_device = airpcap_device->next) {
1043		if (add_dev(devlistp, airpcap_device->Name, 0,
1044		    airpcap_device->Description, errbuf) == NULL) {
1045			/*
1046			 * Failure.
1047			 */
1048			p_AirpcapFreeDeviceList(airpcap_devices);
1049			return (-1);
1050		}
1051	}
1052	p_AirpcapFreeDeviceList(airpcap_devices);
1053	return (0);
1054}
1055