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 #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
airpcap_inject(pcap_t * p,const void * buf,int size)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
airpcap_cleanup(pcap_t * p)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
airpcap_breakloop(pcap_t * p)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
airpcap_activate(pcap_t * p)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
airpcap_can_set_rfmon(pcap_t * p)936 airpcap_can_set_rfmon(pcap_t *p)
937 {
938 return (1);
939 }
940
941 int
device_is_airpcap(const char * device,char * ebuf)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 *
airpcap_create(const char * device,char * ebuf,int * is_ours)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 snprintf(ebuf, PCAP_ERRBUF_SIZE, "Couldn't load AirPcap DLL\n");
978 return (NULL);
979 }
980
981 /*
982 * Is this an AirPcap device?
983 */
984 ret = device_is_airpcap(device, ebuf);
985 if (ret == 0) {
986 /* No. */
987 *is_ours = 0;
988 return (NULL);
989 }
990
991 /*
992 * Yes.
993 */
994 *is_ours = 1;
995 p = PCAP_CREATE_COMMON(ebuf, struct pcap_airpcap);
996 if (p == NULL)
997 return (NULL);
998
999 p->activate_op = airpcap_activate;
1000 p->can_set_rfmon_op = airpcap_can_set_rfmon;
1001 return (p);
1002 }
1003
1004 /*
1005 * Add all AirPcap devices.
1006 */
1007 int
airpcap_findalldevs(pcap_if_list_t * devlistp,char * errbuf)1008 airpcap_findalldevs(pcap_if_list_t *devlistp, char *errbuf)
1009 {
1010 AirpcapDeviceDescription *airpcap_devices, *airpcap_device;
1011 char airpcap_errbuf[AIRPCAP_ERRBUF_SIZE];
1012
1013 /*
1014 * This can be called before we've tried loading the library,
1015 * so do so if we haven't already tried to do so.
1016 */
1017 if (load_airpcap_functions() != AIRPCAP_API_LOADED) {
1018 /*
1019 * XXX - unless the error is "no such DLL", report this
1020 * as an error rather than as "no AirPcap devices"?
1021 */
1022 return (0);
1023 }
1024
1025 if (!p_AirpcapGetDeviceList(&airpcap_devices, airpcap_errbuf)) {
1026 snprintf(errbuf, PCAP_ERRBUF_SIZE,
1027 "AirpcapGetDeviceList() failed: %s", airpcap_errbuf);
1028 return (-1);
1029 }
1030
1031 for (airpcap_device = airpcap_devices; airpcap_device != NULL;
1032 airpcap_device = airpcap_device->next) {
1033 if (add_dev(devlistp, airpcap_device->Name, 0,
1034 airpcap_device->Description, errbuf) == NULL) {
1035 /*
1036 * Failure.
1037 */
1038 p_AirpcapFreeDeviceList(airpcap_devices);
1039 return (-1);
1040 }
1041 }
1042 p_AirpcapFreeDeviceList(airpcap_devices);
1043 return (0);
1044 }
1045