]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/libpcap/pcap-airpcap.c
zfs: merge openzfs/zfs@043c6ee3b
[FreeBSD/FreeBSD.git] / contrib / libpcap / pcap-airpcap.c
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          * 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
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
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
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
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
939 airpcap_can_set_rfmon(pcap_t *p)
940 {
941         return (1);
942 }
943
944 int
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 *
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
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 }