"Fossies" - the Fresh Open Source Software Archive

Member "libpcap-1.10.1/./pcap-airpcap.c" (7 Jun 2021, 29317 Bytes) of package /linux/misc/libpcap-1.10.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "pcap-airpcap.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.10.0_vs_1.10.1.

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