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