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