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