libpcap  1.10.1
About: libpcap is a packet filter library used by tools like tcpdump.
  Fossies Dox: libpcap-1.10.1.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

pcap-airpcap.c
Go to the documentation of this file.
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 
89 
90 typedef enum LONG
91 {
97 
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  */
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,
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,
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)
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;
244  int nonblock;
246  HANDLE read_event;
247  struct pcap_stat stat;
248 };
249 
250 static int
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
305 {
306  struct pcap_airpcap *pa = p->priv;
307  AirpcapLinkType type;
308 
309  switch (dlt) {
310 
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)) {
329  "AirpcapSetLinkType() failed: %s",
331  return (-1);
332  }
333  p->linktype = dlt;
334  return (0);
335 }
336 
337 static int
339 {
340  struct pcap_airpcap *pa = p->priv;
341 
342  return (pa->nonblock);
343 }
344 
345 static int
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
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)) {
384  "AirpcapGetStats() failed: %s",
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)) {
430  "AirpcapGetStats() failed: %s",
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
451 {
452  struct pcap_airpcap *pa = p->priv;
453 
454  if (!p_AirpcapSetKernelBuffer(pa->adapter, dim)) {
456  "AirpcapSetKernelBuffer() failed: %s",
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) {
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
478 {
479  struct pcap_airpcap *pa = p->priv;
480 
481  if (!p_AirpcapSetMinToCopy(pa->adapter, size)) {
483  "AirpcapSetMinToCopy() failed: %s",
485  return (-1);
486  }
487  return (0);
488 }
489 
490 static HANDLE
492 {
493  struct pcap_airpcap *pa = p->priv;
494 
495  return (pa->read_event);
496 }
497 
498 static int
500  size_t *lenp _U_)
501 {
503  "Getting OID values is not supported on an AirPcap adapter");
504  return (PCAP_ERROR);
505 }
506 
507 static int
509  size_t *lenp _U_)
510 {
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 {
520  "Cannot queue packets for transmission on an AirPcap adapter");
521  return (0);
522 }
523 
524 static int
526 {
527  unsigned char *new_buff;
528 
529  if (size <= 0) {
530  /* Bogus parameter */
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) {
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 {
558  "AirPcap adapters don't support live dump");
559  return (-1);
560 }
561 
562 static int
564 {
566  "AirPcap adapters don't support live dump");
567  return (-1);
568 }
569 
570 static PAirpcapHandle
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)) {
619  "AirpcapRead() failed: %s",
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)) {
710  "AirpcapWrite() failed: %s",
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
725 {
726  struct pcap_airpcap *pa = p->priv;
727 
728  if (pa->adapter != NULL) {
729  p_AirpcapClose(pa->adapter);
730  pa->adapter = NULL;
731  }
733 }
734 
735 static void
737 {
738  HANDLE read_event;
739 
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  */
749  return;
750  SetEvent(read_event);
751 }
752 
753 static int
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);
781  "AirpcapSetDeviceMacFlags() failed: %s",
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)
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)
803 
806  "AirpcapSetKernelBuffer() failed: %s",
808  goto bad;
809  }
810 
811  if(!p_AirpcapGetReadEvent(pa->adapter, &pa->read_event)) {
813  "AirpcapGetReadEvent() failed: %s",
815  goto bad;
816  }
817 
818  /* Set the buffer size */
820  p->buffer = malloc(p->bufsize);
821  if (p->buffer == NULL) {
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)) {
831  "AirpcapSetMinToCopy() failed: %s",
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)) {
842  "AirpcapSetMinToCopy() failed: %s",
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. */
863  "AirpcapGetLinkType() failed: %s",
865  goto bad;
866  }
867  switch (link_type) {
868 
869  case AIRPCAP_LT_802_11_PLUS_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:
879  break;
880 
881  case AIRPCAP_LT_UNKNOWN:
882  default:
883  /* OK, what? */
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;
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;
906  p->setdirection_op = NULL; /* Not implemented. */
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;
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
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  */
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 
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  */
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 }
u_int bpf_u_int32
Definition: bpf.h:98
u_int pcap_filter(const struct bpf_insn *pc, const u_char *p, u_int wirelen, u_int buflen)
Definition: bpf_filter.c:391
#define DLT_IEEE802_11_RADIO
Definition: dlt.h:396
#define DLT_PPI
Definition: dlt.h:722
#define DLT_IEEE802_11
Definition: dlt.h:200
void pcap_fmt_errmsg_for_errno(char *errbuf, size_t errbuflen, int errnum, const char *fmt,...)
Definition: fmtutils.c:269
int install_bpf_program(pcap_t *p, struct bpf_program *fp)
Definition: optimize.c:2939
int snprintf(char *, size_t, const char *,...)
void sync(void)
static pcap_code_handle_t airpcap_lib
Definition: pcap-airpcap.c:56
static AirpcapGetLastErrorHandler p_AirpcapGetLastError
Definition: pcap-airpcap.c:74
static int airpcap_activate(pcap_t *p)
Definition: pcap-airpcap.c:754
static AIRPCAP_API_LOAD_STATUS load_airpcap_functions(void)
Definition: pcap-airpcap.c:110
enum LONG AIRPCAP_API_LOAD_STATUS
static int airpcap_oid_get_request(pcap_t *p, bpf_u_int32 oid, void *data, size_t *lenp)
Definition: pcap-airpcap.c:499
#define bhp
static int airpcap_live_dump_ended(pcap_t *p, int sync)
Definition: pcap-airpcap.c:563
static int airpcap_live_dump(pcap_t *p, char *filename, int maxsize, int maxpacks)
Definition: pcap-airpcap.c:554
static AirpcapSetMinToCopyHandler p_AirpcapSetMinToCopy
Definition: pcap-airpcap.c:84
BOOL(* AirpcapSetFilterHandler)(PAirpcapHandle, PVOID, UINT)
Definition: pcap-airpcap.c:67
static AirpcapSetFilterHandler p_AirpcapSetFilter
Definition: pcap-airpcap.c:83
PCHAR(* AirpcapGetLastErrorHandler)(PAirpcapHandle)
Definition: pcap-airpcap.c:58
static int airpcap_stats(pcap_t *p, struct pcap_stat *ps)
Definition: pcap-airpcap.c:374
static int airpcap_can_set_rfmon(pcap_t *p)
Definition: pcap-airpcap.c:936
BOOL(* AirpcapSetMinToCopyHandler)(PAirpcapHandle, UINT)
Definition: pcap-airpcap.c:68
VOID(* AirpcapCloseHandler)(PAirpcapHandle)
Definition: pcap-airpcap.c:62
static AirpcapCloseHandler p_AirpcapClose
Definition: pcap-airpcap.c:78
BOOL(* AirpcapSetKernelBufferHandler)(PAirpcapHandle, UINT)
Definition: pcap-airpcap.c:66
PAirpcapHandle(* AirpcapOpenHandler)(PCHAR, PCHAR)
Definition: pcap-airpcap.c:61
static AirpcapGetReadEventHandler p_AirpcapGetReadEvent
Definition: pcap-airpcap.c:85
static AirpcapGetLinkTypeHandler p_AirpcapGetLinkType
Definition: pcap-airpcap.c:81
static AirpcapSetLinkTypeHandler p_AirpcapSetLinkType
Definition: pcap-airpcap.c:80
static PAirpcapHandle airpcap_get_airpcap_handle(pcap_t *p)
Definition: pcap-airpcap.c:571
static int airpcap_inject(pcap_t *p, const void *buf, int size)
Definition: pcap-airpcap.c:697
static AIRPCAP_API_LOAD_STATUS airpcap_load_status
Definition: pcap-airpcap.c:98
static int airpcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
Definition: pcap-airpcap.c:579
static struct pcap_stat * airpcap_stats_ex(pcap_t *p, int *pcap_stat_size)
Definition: pcap-airpcap.c:418
BOOL(* AirpcapSetLinkTypeHandler)(PAirpcapHandle, AirpcapLinkType)
Definition: pcap-airpcap.c:64
static int airpcap_setfilter(pcap_t *p, struct bpf_program *fp)
Definition: pcap-airpcap.c:251
static void airpcap_cleanup(pcap_t *p)
Definition: pcap-airpcap.c:724
static AirpcapGetStatsHandler p_AirpcapGetStats
Definition: pcap-airpcap.c:88
static int airpcap_set_datalink(pcap_t *p, int dlt)
Definition: pcap-airpcap.c:304
static int airpcap_oid_set_request(pcap_t *p, bpf_u_int32 oid, const void *data, size_t *lenp)
Definition: pcap-airpcap.c:508
static AirpcapWriteHandler p_AirpcapWrite
Definition: pcap-airpcap.c:87
static int airpcap_setnonblock(pcap_t *p, int nonblock)
Definition: pcap-airpcap.c:346
static AirpcapSetDeviceMacFlagsHandler p_AirpcapSetDeviceMacFlags
Definition: pcap-airpcap.c:79
VOID(* AirpcapFreeDeviceListHandler)(PAirpcapDeviceDescription)
Definition: pcap-airpcap.c:60
static HANDLE airpcap_getevent(pcap_t *p)
Definition: pcap-airpcap.c:491
BOOL(* AirpcapGetReadEventHandler)(PAirpcapHandle, HANDLE *)
Definition: pcap-airpcap.c:69
#define AIRPCAP_DEFAULT_USER_BUFFER_SIZE
Definition: pcap-airpcap.c:45
static int airpcap_setuserbuffer(pcap_t *p, int size)
Definition: pcap-airpcap.c:525
static int airpcap_setmode(pcap_t *p, int mode)
Definition: pcap-airpcap.c:465
static AirpcapSetKernelBufferHandler p_AirpcapSetKernelBuffer
Definition: pcap-airpcap.c:82
int airpcap_findalldevs(pcap_if_list_t *devlistp, char *errbuf)
static int airpcap_getnonblock(pcap_t *p)
Definition: pcap-airpcap.c:338
BOOL(* AirpcapWriteHandler)(PAirpcapHandle, PCHAR, ULONG)
Definition: pcap-airpcap.c:71
static void airpcap_breakloop(pcap_t *p)
Definition: pcap-airpcap.c:736
BOOL(* AirpcapSetDeviceMacFlagsHandler)(PAirpcapHandle, UINT)
Definition: pcap-airpcap.c:63
static AirpcapReadHandler p_AirpcapRead
Definition: pcap-airpcap.c:86
static int airpcap_setbuff(pcap_t *p, int dim)
Definition: pcap-airpcap.c:450
static AirpcapFreeDeviceListHandler p_AirpcapFreeDeviceList
Definition: pcap-airpcap.c:76
static AirpcapOpenHandler p_AirpcapOpen
Definition: pcap-airpcap.c:77
static AirpcapGetDeviceListHandler p_AirpcapGetDeviceList
Definition: pcap-airpcap.c:75
#define AIRPCAP_DEFAULT_KERNEL_BUFFER_SIZE
Definition: pcap-airpcap.c:48
LONG
Definition: pcap-airpcap.c:91
@ AIRPCAP_API_LOADING
Definition: pcap-airpcap.c:95
@ AIRPCAP_API_UNLOADED
Definition: pcap-airpcap.c:92
@ AIRPCAP_API_LOADED
Definition: pcap-airpcap.c:93
@ AIRPCAP_API_CANNOT_LOAD
Definition: pcap-airpcap.c:94
BOOL(* AirpcapReadHandler)(PAirpcapHandle, PBYTE, UINT, PUINT)
Definition: pcap-airpcap.c:70
BOOL(* AirpcapGetDeviceListHandler)(PAirpcapDeviceDescription *, PCHAR)
Definition: pcap-airpcap.c:59
BOOL(* AirpcapGetLinkTypeHandler)(PAirpcapHandle, PAirpcapLinkType)
Definition: pcap-airpcap.c:65
static u_int airpcap_sendqueue_transmit(pcap_t *p, pcap_send_queue *queue, int sync)
Definition: pcap-airpcap.c:517
BOOL(* AirpcapGetStatsHandler)(PAirpcapHandle, PAirpcapStats)
Definition: pcap-airpcap.c:72
static int airpcap_setmintocopy(pcap_t *p, int size)
Definition: pcap-airpcap.c:477
pcap_t * airpcap_create(const char *device, char *ebuf, int *is_ours)
Definition: pcap-airpcap.c:967
int device_is_airpcap(const char *device, char *ebuf)
Definition: pcap-airpcap.c:942
int BOOL
Definition: pcap-dos.h:15
unsigned int UINT
Definition: pcap-dos.h:52
#define _U_
Definition: pcap-dos.h:93
int errno
#define MAXIMUM_SNAPLEN
Definition: pcap-int.h:131
void pcap_breakloop_common(pcap_t *)
Definition: pcap.c:3980
#define PACKET_COUNT_IS_UNLIMITED(count)
Definition: pcap-int.h:444
pcap_if_t * add_dev(pcap_if_list_t *, const char *, bpf_u_int32, const char *, char *)
Definition: pcap.c:1308
void pcap_cleanup_live_common(pcap_t *)
Definition: pcap.c:3987
#define PCAP_CREATE_COMMON(ebuf, type)
Definition: pcap-int.h:474
void(* pcap_handler)(u_char *, const struct pcap_pkthdr *, const u_char *)
Definition: pcap.h:330
#define PCAP_ERROR_BREAK
Definition: pcap.h:340
#define PCAP_ERRBUF_SIZE
Definition: pcap.h:152
#define PCAP_ERROR
Definition: pcap.h:339
Definition: bpf.h:245
struct bpf_insn * bf_insns
Definition: bpf.h:119
u_int bf_len
Definition: bpf.h:118
PAirpcapHandle adapter
Definition: pcap-airpcap.c:242
int filtering_in_kernel
Definition: pcap-airpcap.c:243
HANDLE read_event
Definition: pcap-airpcap.c:246
struct pcap_stat stat
Definition: pcap-airpcap.c:247
int timeout
Definition: pcap-int.h:147
char * device
Definition: pcap-int.h:146
int rfmon
Definition: pcap-int.h:150
int immediate
Definition: pcap-int.h:151
u_int buffer_size
Definition: pcap-int.h:148
bpf_u_int32 caplen
Definition: pcap.h:247
struct timeval ts
Definition: pcap.h:246
bpf_u_int32 len
Definition: pcap.h:248
u_int ps_drop
Definition: pcap.h:256
u_int ps_recv
Definition: pcap.h:255
u_int ps_ifdrop
Definition: pcap.h:257
Definition: pcap-int.h:200
stats_op_t stats_op
Definition: pcap-int.h:320
activate_op_t activate_op
Definition: pcap-int.h:311
setnonblock_op_t setnonblock_op
Definition: pcap-int.h:319
setfilter_op_t setfilter_op
Definition: pcap-int.h:315
sig_atomic_t break_loop
Definition: pcap-int.h:225
int dlt_count
Definition: pcap-int.h:299
u_int bufsize
Definition: pcap-int.h:220
void * priv
Definition: pcap-int.h:227
getnonblock_op_t getnonblock_op
Definition: pcap-int.h:318
u_int * dlt_list
Definition: pcap-int.h:300
read_op_t read_op
Definition: pcap-int.h:204
void * buffer
Definition: pcap-int.h:221
u_char * bp
Definition: pcap-int.h:222
int snapshot
Definition: pcap-int.h:247
cleanup_op_t cleanup_op
Definition: pcap-int.h:346
setdirection_op_t setdirection_op
Definition: pcap-int.h:316
inject_op_t inject_op
Definition: pcap-int.h:313
int cc
Definition: pcap-int.h:223
struct bpf_program fcode
Definition: pcap-int.h:293
breakloop_op_t breakloop_op
Definition: pcap-int.h:321
set_datalink_op_t set_datalink_op
Definition: pcap-int.h:317
char errbuf[256+1]
Definition: pcap-int.h:295
int linktype
Definition: pcap-int.h:248
can_set_rfmon_op_t can_set_rfmon_op
Definition: pcap-int.h:312
struct pcap_opt opt
Definition: pcap-int.h:254