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