xref: /freebsd/contrib/libpcap/pcap-airpcap.c (revision 6f9cba8f)
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
load_airpcap_functions(void)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
airpcap_setfilter(pcap_t * p,struct bpf_program * fp)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
airpcap_set_datalink(pcap_t * p,int dlt)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
airpcap_getnonblock(pcap_t * p)338 airpcap_getnonblock(pcap_t *p)
339 {
340 	struct pcap_airpcap *pa = p->priv;
341 
342 	return (pa->nonblock);
343 }
344 
345 static int
airpcap_setnonblock(pcap_t * p,int nonblock)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
airpcap_stats(pcap_t * p,struct pcap_stat * ps)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 *
airpcap_stats_ex(pcap_t * p,int * pcap_stat_size)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
airpcap_setbuff(pcap_t * p,int dim)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
airpcap_setmode(pcap_t * p,int mode)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
airpcap_setmintocopy(pcap_t * p,int size)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
airpcap_getevent(pcap_t * p)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
airpcap_oid_get_request(pcap_t * p,bpf_u_int32 oid _U_,void * data _U_,size_t * lenp _U_)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
airpcap_oid_set_request(pcap_t * p,bpf_u_int32 oid _U_,const void * data _U_,size_t * lenp _U_)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
airpcap_sendqueue_transmit(pcap_t * p,pcap_send_queue * queue _U_,int sync _U_)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
airpcap_setuserbuffer(pcap_t * p,int size)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
airpcap_live_dump(pcap_t * p,char * filename _U_,int maxsize _U_,int maxpacks _U_)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
airpcap_live_dump_ended(pcap_t * p,int sync _U_)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
airpcap_get_airpcap_handle(pcap_t * p)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
airpcap_read(pcap_t * p,int cnt,pcap_handler callback,u_char * user)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 	 * This assumes that a single buffer of packets will have
632 	 * <= INT_MAX packets, so the packet count doesn't overflow.
633 	 */
634 #define bhp ((AirpcapBpfHeader *)bp)
635 	n = 0;
636 	ep = bp + cc;
637 	for (;;) {
638 		register u_int caplen, hdrlen;
639 
640 		/*
641 		 * Has "pcap_breakloop()" been called?
642 		 * If so, return immediately - if we haven't read any
643 		 * packets, clear the flag and return PCAP_ERROR_BREAK
644 		 * to indicate that we were told to break out of the loop,
645 		 * otherwise leave the flag set, so that the *next* call
646 		 * will break out of the loop without having read any
647 		 * packets, and return the number of packets we've
648 		 * processed so far.
649 		 */
650 		if (p->break_loop) {
651 			if (n == 0) {
652 				p->break_loop = 0;
653 				return (PCAP_ERROR_BREAK);
654 			} else {
655 				p->bp = bp;
656 				p->cc = (int) (ep - bp);
657 				return (n);
658 			}
659 		}
660 		if (bp >= ep)
661 			break;
662 
663 		caplen = bhp->Caplen;
664 		hdrlen = bhp->Hdrlen;
665 		datap = bp + hdrlen;
666 		/*
667 		 * Short-circuit evaluation: if using BPF filter
668 		 * in the AirPcap adapter, no need to do it now -
669 		 * we already know the packet passed the filter.
670 		 */
671 		if (pa->filtering_in_kernel ||
672 		    p->fcode.bf_insns == NULL ||
673 		    pcap_filter(p->fcode.bf_insns, datap, bhp->Originallen, caplen)) {
674 			struct pcap_pkthdr pkthdr;
675 
676 			pkthdr.ts.tv_sec = bhp->TsSec;
677 			pkthdr.ts.tv_usec = bhp->TsUsec;
678 			pkthdr.caplen = caplen;
679 			pkthdr.len = bhp->Originallen;
680 			(*callback)(user, &pkthdr, datap);
681 			bp += AIRPCAP_WORDALIGN(caplen + hdrlen);
682 			if (++n >= cnt && !PACKET_COUNT_IS_UNLIMITED(cnt)) {
683 				p->bp = bp;
684 				p->cc = (int)(ep - bp);
685 				return (n);
686 			}
687 		} else {
688 			/*
689 			 * Skip this packet.
690 			 */
691 			bp += AIRPCAP_WORDALIGN(caplen + hdrlen);
692 		}
693 	}
694 #undef bhp
695 	p->cc = 0;
696 	return (n);
697 }
698 
699 static int
airpcap_inject(pcap_t * p,const void * buf,int size)700 airpcap_inject(pcap_t *p, const void *buf, int size)
701 {
702 	struct pcap_airpcap *pa = p->priv;
703 
704 	/*
705 	 * XXX - the second argument to AirpcapWrite() *should* have
706 	 * been declared as a const pointer - a write function that
707 	 * stomps on what it writes is *extremely* rude - but such
708 	 * is life.  We assume it is, in fact, not going to write on
709 	 * our buffer.
710 	 */
711 	if (!p_AirpcapWrite(pa->adapter, (void *)buf, size)) {
712 		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
713 		    "AirpcapWrite() failed: %s",
714 		    p_AirpcapGetLastError(pa->adapter));
715 		return (-1);
716 	}
717 
718 	/*
719 	 * We assume it all got sent if "AirpcapWrite()" succeeded.
720 	 * "pcap_inject()" is expected to return the number of bytes
721 	 * sent.
722 	 */
723 	return (size);
724 }
725 
726 static void
airpcap_cleanup(pcap_t * p)727 airpcap_cleanup(pcap_t *p)
728 {
729 	struct pcap_airpcap *pa = p->priv;
730 
731 	if (pa->adapter != NULL) {
732 		p_AirpcapClose(pa->adapter);
733 		pa->adapter = NULL;
734 	}
735 	pcap_cleanup_live_common(p);
736 }
737 
738 static void
airpcap_breakloop(pcap_t * p)739 airpcap_breakloop(pcap_t *p)
740 {
741 	HANDLE read_event;
742 
743 	pcap_breakloop_common(p);
744 	struct pcap_airpcap *pa = p->priv;
745 
746 	/* XXX - what if either of these fail? */
747 	/*
748 	 * XXX - will SetEvent() force a wakeup and, if so, will
749 	 * the AirPcap read code handle that sanely?
750 	 */
751 	if (!p_AirpcapGetReadEvent(pa->adapter, &read_event))
752 		return;
753 	SetEvent(read_event);
754 }
755 
756 static int
airpcap_activate(pcap_t * p)757 airpcap_activate(pcap_t *p)
758 {
759 	struct pcap_airpcap *pa = p->priv;
760 	char *device = p->opt.device;
761 	char airpcap_errbuf[AIRPCAP_ERRBUF_SIZE];
762 	BOOL status;
763 	AirpcapLinkType link_type;
764 
765 	pa->adapter = p_AirpcapOpen(device, airpcap_errbuf);
766 	if (pa->adapter == NULL) {
767 		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s", airpcap_errbuf);
768 		return (PCAP_ERROR);
769 	}
770 
771 	/*
772 	 * Set monitor mode appropriately.
773 	 * Always turn off the "ACK frames sent to the card" mode.
774 	 */
775 	if (p->opt.rfmon) {
776 		status = p_AirpcapSetDeviceMacFlags(pa->adapter,
777 		    AIRPCAP_MF_MONITOR_MODE_ON);
778 	} else
779 		status = p_AirpcapSetDeviceMacFlags(pa->adapter,
780 		    AIRPCAP_MF_ACK_FRAMES_ON);
781 	if (!status) {
782 		p_AirpcapClose(pa->adapter);
783 		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
784 		    "AirpcapSetDeviceMacFlags() failed: %s",
785 		    p_AirpcapGetLastError(pa->adapter));
786 		return (PCAP_ERROR);
787 	}
788 
789 	/*
790 	 * Turn a negative snapshot value (invalid), a snapshot value of
791 	 * 0 (unspecified), or a value bigger than the normal maximum
792 	 * value, into the maximum allowed value.
793 	 *
794 	 * If some application really *needs* a bigger snapshot
795 	 * length, we should just increase MAXIMUM_SNAPLEN.
796 	 */
797 	if (p->snapshot <= 0 || p->snapshot > MAXIMUM_SNAPLEN)
798 		p->snapshot = MAXIMUM_SNAPLEN;
799 
800 	/*
801 	 * If the buffer size wasn't explicitly set, default to
802 	 * AIRPCAP_DEFAULT_KERNEL_BUFFER_SIZE.
803 	 */
804 	if (p->opt.buffer_size == 0)
805 		p->opt.buffer_size = AIRPCAP_DEFAULT_KERNEL_BUFFER_SIZE;
806 
807 	if (!p_AirpcapSetKernelBuffer(pa->adapter, p->opt.buffer_size)) {
808 		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
809 		    "AirpcapSetKernelBuffer() failed: %s",
810 		    p_AirpcapGetLastError(pa->adapter));
811 		goto bad;
812 	}
813 
814 	if(!p_AirpcapGetReadEvent(pa->adapter, &pa->read_event)) {
815 		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
816 		    "AirpcapGetReadEvent() failed: %s",
817 		    p_AirpcapGetLastError(pa->adapter));
818 		goto bad;
819 	}
820 
821 	/* Set the buffer size */
822 	p->bufsize = AIRPCAP_DEFAULT_USER_BUFFER_SIZE;
823 	p->buffer = malloc(p->bufsize);
824 	if (p->buffer == NULL) {
825 		pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
826 		    errno, "malloc");
827 		goto bad;
828 	}
829 
830 	if (p->opt.immediate) {
831 		/* Tell the driver to copy the buffer as soon as data arrives. */
832 		if (!p_AirpcapSetMinToCopy(pa->adapter, 0)) {
833 			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
834 			    "AirpcapSetMinToCopy() failed: %s",
835 			    p_AirpcapGetLastError(pa->adapter));
836 			goto bad;
837 		}
838 	} else {
839 		/*
840 		 * Tell the driver to copy the buffer only if it contains
841 		 * at least 16K.
842 		 */
843 		if (!p_AirpcapSetMinToCopy(pa->adapter, 16000)) {
844 			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
845 			    "AirpcapSetMinToCopy() failed: %s",
846 			    p_AirpcapGetLastError(pa->adapter));
847 			goto bad;
848 		}
849 	}
850 
851 	/*
852 	 * Find out what the default link-layer header type is,
853 	 * and set p->datalink to that.
854 	 *
855 	 * We don't force it to another value because there
856 	 * might be some programs using WinPcap/Npcap that,
857 	 * when capturing on AirPcap devices, assume the
858 	 * default value set with the AirPcap configuration
859 	 * program is what you get.
860 	 *
861 	 * The out-of-the-box default appears to be radiotap.
862 	 */
863 	if (!p_AirpcapGetLinkType(pa->adapter, &link_type)) {
864 		/* That failed. */
865 		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
866 		    "AirpcapGetLinkType() failed: %s",
867 		    p_AirpcapGetLastError(pa->adapter));
868 		goto bad;
869 	}
870 	switch (link_type) {
871 
872 	case AIRPCAP_LT_802_11_PLUS_RADIO:
873 		p->linktype = DLT_IEEE802_11_RADIO;
874 		break;
875 
876 	case AIRPCAP_LT_802_11_PLUS_PPI:
877 		p->linktype = DLT_PPI;
878 		break;
879 
880 	case AIRPCAP_LT_802_11:
881 		p->linktype = DLT_IEEE802_11;
882 		break;
883 
884 	case AIRPCAP_LT_UNKNOWN:
885 	default:
886 		/* OK, what? */
887 		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
888 		    "AirpcapGetLinkType() returned unknown link type %u",
889 		    link_type);
890 		goto bad;
891 	}
892 
893 	/*
894 	 * Now provide a list of all the supported types; we
895 	 * assume they all work.  We put radiotap at the top,
896 	 * followed by PPI, followed by "no radio metadata".
897 	 */
898 	p->dlt_list = (u_int *) malloc(sizeof(u_int) * 3);
899 	if (p->dlt_list == NULL)
900 		goto bad;
901 	p->dlt_list[0] = DLT_IEEE802_11_RADIO;
902 	p->dlt_list[1] = DLT_PPI;
903 	p->dlt_list[2] = DLT_IEEE802_11;
904 	p->dlt_count = 3;
905 
906 	p->read_op = airpcap_read;
907 	p->inject_op = airpcap_inject;
908 	p->setfilter_op = airpcap_setfilter;
909 	p->setdirection_op = NULL;	/* Not implemented. */
910 	p->set_datalink_op = airpcap_set_datalink;
911 	p->getnonblock_op = airpcap_getnonblock;
912 	p->setnonblock_op = airpcap_setnonblock;
913 	p->breakloop_op = airpcap_breakloop;
914 	p->stats_op = airpcap_stats;
915 	p->stats_ex_op = airpcap_stats_ex;
916 	p->setbuff_op = airpcap_setbuff;
917 	p->setmode_op = airpcap_setmode;
918 	p->setmintocopy_op = airpcap_setmintocopy;
919 	p->getevent_op = airpcap_getevent;
920 	p->oid_get_request_op = airpcap_oid_get_request;
921 	p->oid_set_request_op = airpcap_oid_set_request;
922 	p->sendqueue_transmit_op = airpcap_sendqueue_transmit;
923 	p->setuserbuffer_op = airpcap_setuserbuffer;
924 	p->live_dump_op = airpcap_live_dump;
925 	p->live_dump_ended_op = airpcap_live_dump_ended;
926 	p->get_airpcap_handle_op = airpcap_get_airpcap_handle;
927 	p->cleanup_op = airpcap_cleanup;
928 
929 	return (0);
930  bad:
931 	airpcap_cleanup(p);
932 	return (PCAP_ERROR);
933 }
934 
935 /*
936  * Monitor mode is supported.
937  */
938 static int
airpcap_can_set_rfmon(pcap_t * p)939 airpcap_can_set_rfmon(pcap_t *p)
940 {
941 	return (1);
942 }
943 
944 int
device_is_airpcap(const char * device,char * ebuf)945 device_is_airpcap(const char *device, char *ebuf)
946 {
947 	static const char airpcap_prefix[] = "\\\\.\\airpcap";
948 
949 	/*
950 	 * We don't determine this by calling AirpcapGetDeviceList()
951 	 * and looking at the list, as that appears to be a costly
952 	 * operation.
953 	 *
954 	 * Instead, we just check whether it begins with "\\.\airpcap".
955 	 */
956 	if (strncmp(device, airpcap_prefix, sizeof airpcap_prefix - 1) == 0) {
957 		/*
958 		 * Yes, it's an AirPcap device.
959 		 */
960 		return (1);
961 	}
962 
963 	/*
964 	 * No, it's not an AirPcap device.
965 	 */
966 	return (0);
967 }
968 
969 pcap_t *
airpcap_create(const char * device,char * ebuf,int * is_ours)970 airpcap_create(const char *device, char *ebuf, int *is_ours)
971 {
972 	int ret;
973 	pcap_t *p;
974 
975 	/*
976 	 * This can be called before we've tried loading the library,
977 	 * so do so if we haven't already tried to do so.
978 	 */
979 	if (load_airpcap_functions() != AIRPCAP_API_LOADED) {
980 		/*
981 		 * We assume this means that we don't have the AirPcap
982 		 * software installed, which probably means we don't
983 		 * have an AirPcap device.
984 		 *
985 		 * Don't treat that as an error.
986 		 */
987 		*is_ours = 0;
988 		return (NULL);
989 	}
990 
991 	/*
992 	 * Is this an AirPcap device?
993 	 */
994 	ret = device_is_airpcap(device, ebuf);
995 	if (ret == 0) {
996 		/* No. */
997 		*is_ours = 0;
998 		return (NULL);
999 	}
1000 
1001 	/*
1002 	 * Yes.
1003 	 */
1004 	*is_ours = 1;
1005 	p = PCAP_CREATE_COMMON(ebuf, struct pcap_airpcap);
1006 	if (p == NULL)
1007 		return (NULL);
1008 
1009 	p->activate_op = airpcap_activate;
1010 	p->can_set_rfmon_op = airpcap_can_set_rfmon;
1011 	return (p);
1012 }
1013 
1014 /*
1015  * Add all AirPcap devices.
1016  */
1017 int
airpcap_findalldevs(pcap_if_list_t * devlistp,char * errbuf)1018 airpcap_findalldevs(pcap_if_list_t *devlistp, char *errbuf)
1019 {
1020 	AirpcapDeviceDescription *airpcap_devices, *airpcap_device;
1021 	char airpcap_errbuf[AIRPCAP_ERRBUF_SIZE];
1022 
1023 	/*
1024 	 * This can be called before we've tried loading the library,
1025 	 * so do so if we haven't already tried to do so.
1026 	 */
1027 	if (load_airpcap_functions() != AIRPCAP_API_LOADED) {
1028 		/*
1029 		 * XXX - unless the error is "no such DLL", report this
1030 		 * as an error rather than as "no AirPcap devices"?
1031 		 */
1032 		return (0);
1033 	}
1034 
1035 	if (!p_AirpcapGetDeviceList(&airpcap_devices, airpcap_errbuf)) {
1036 		snprintf(errbuf, PCAP_ERRBUF_SIZE,
1037 		    "AirpcapGetDeviceList() failed: %s", airpcap_errbuf);
1038 		return (-1);
1039 	}
1040 
1041 	for (airpcap_device = airpcap_devices; airpcap_device != NULL;
1042 	    airpcap_device = airpcap_device->next) {
1043 		if (add_dev(devlistp, airpcap_device->Name, 0,
1044 		    airpcap_device->Description, errbuf) == NULL) {
1045 			/*
1046 			 * Failure.
1047 			 */
1048 			p_AirpcapFreeDeviceList(airpcap_devices);
1049 			return (-1);
1050 		}
1051 	}
1052 	p_AirpcapFreeDeviceList(airpcap_devices);
1053 	return (0);
1054 }
1055