xref: /dragonfly/contrib/libpcap/pcap-airpcap.c (revision e75ef36f1332e115895388cede9dfd24ca1a806c)
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                     /*
978                      * We assume this means that we don't have the AirPcap
979                      * software installed, which probably means we don't
980                      * have an AirPcap device.
981                      *
982                      * Don't treat that as an error.
983                      */
984                     *is_ours = 0;
985                     return (NULL);
986           }
987 
988           /*
989            * Is this an AirPcap device?
990            */
991           ret = device_is_airpcap(device, ebuf);
992           if (ret == 0) {
993                     /* No. */
994                     *is_ours = 0;
995                     return (NULL);
996           }
997 
998           /*
999            * Yes.
1000            */
1001           *is_ours = 1;
1002           p = PCAP_CREATE_COMMON(ebuf, struct pcap_airpcap);
1003           if (p == NULL)
1004                     return (NULL);
1005 
1006           p->activate_op = airpcap_activate;
1007           p->can_set_rfmon_op = airpcap_can_set_rfmon;
1008           return (p);
1009 }
1010 
1011 /*
1012  * Add all AirPcap devices.
1013  */
1014 int
airpcap_findalldevs(pcap_if_list_t * devlistp,char * errbuf)1015 airpcap_findalldevs(pcap_if_list_t *devlistp, char *errbuf)
1016 {
1017           AirpcapDeviceDescription *airpcap_devices, *airpcap_device;
1018           char airpcap_errbuf[AIRPCAP_ERRBUF_SIZE];
1019 
1020           /*
1021            * This can be called before we've tried loading the library,
1022            * so do so if we haven't already tried to do so.
1023            */
1024           if (load_airpcap_functions() != AIRPCAP_API_LOADED) {
1025                     /*
1026                      * XXX - unless the error is "no such DLL", report this
1027                      * as an error rather than as "no AirPcap devices"?
1028                      */
1029                     return (0);
1030           }
1031 
1032           if (!p_AirpcapGetDeviceList(&airpcap_devices, airpcap_errbuf)) {
1033                     snprintf(errbuf, PCAP_ERRBUF_SIZE,
1034                         "AirpcapGetDeviceList() failed: %s", airpcap_errbuf);
1035                     return (-1);
1036           }
1037 
1038           for (airpcap_device = airpcap_devices; airpcap_device != NULL;
1039               airpcap_device = airpcap_device->next) {
1040                     if (add_dev(devlistp, airpcap_device->Name, 0,
1041                         airpcap_device->Description, errbuf) == NULL) {
1042                               /*
1043                                * Failure.
1044                                */
1045                               p_AirpcapFreeDeviceList(airpcap_devices);
1046                               return (-1);
1047                     }
1048           }
1049           p_AirpcapFreeDeviceList(airpcap_devices);
1050           return (0);
1051 }
1052