2 * Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy)
3 * Copyright (c) 2005 - 2010 CACE Technologies, Davis (California)
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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
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.
40 #include "pcap-airpcap.h"
42 /* Default size of the buffer we allocate in userland. */
43 #define AIRPCAP_DEFAULT_USER_BUFFER_SIZE 256000
45 /* Default size of the buffer for the AirPcap adapter. */
46 #define AIRPCAP_DEFAULT_KERNEL_BUFFER_SIZE 1000000
49 // We load the AirPcap DLL dynamically, so that the code will
50 // work whether you have it installed or not, and there don't
51 // have to be two different versions of the library, one linked
52 // to the AirPcap library and one not linked to it.
54 static pcap_code_handle_t airpcap_lib
;
56 typedef PCHAR (*AirpcapGetLastErrorHandler
)(PAirpcapHandle
);
57 typedef BOOL (*AirpcapGetDeviceListHandler
)(PAirpcapDeviceDescription
*, PCHAR
);
58 typedef VOID (*AirpcapFreeDeviceListHandler
)(PAirpcapDeviceDescription
);
59 typedef PAirpcapHandle (*AirpcapOpenHandler
)(PCHAR
, PCHAR
);
60 typedef VOID (*AirpcapCloseHandler
)(PAirpcapHandle
);
61 typedef BOOL (*AirpcapSetDeviceMacFlagsHandler
)(PAirpcapHandle
, UINT
);
62 typedef BOOL (*AirpcapSetLinkTypeHandler
)(PAirpcapHandle
, AirpcapLinkType
);
63 typedef BOOL (*AirpcapGetLinkTypeHandler
)(PAirpcapHandle
, PAirpcapLinkType
);
64 typedef BOOL (*AirpcapSetKernelBufferHandler
)(PAirpcapHandle
, UINT
);
65 typedef BOOL (*AirpcapSetFilterHandler
)(PAirpcapHandle
, PVOID
, UINT
);
66 typedef BOOL (*AirpcapSetMinToCopyHandler
)(PAirpcapHandle
, UINT
);
67 typedef BOOL (*AirpcapGetReadEventHandler
)(PAirpcapHandle
, HANDLE
*);
68 typedef BOOL (*AirpcapReadHandler
)(PAirpcapHandle
, PBYTE
, UINT
, PUINT
);
69 typedef BOOL (*AirpcapWriteHandler
)(PAirpcapHandle
, PCHAR
, ULONG
);
70 typedef BOOL (*AirpcapGetStatsHandler
)(PAirpcapHandle
, PAirpcapStats
);
72 static AirpcapGetLastErrorHandler p_AirpcapGetLastError
;
73 static AirpcapGetDeviceListHandler p_AirpcapGetDeviceList
;
74 static AirpcapFreeDeviceListHandler p_AirpcapFreeDeviceList
;
75 static AirpcapOpenHandler p_AirpcapOpen
;
76 static AirpcapCloseHandler p_AirpcapClose
;
77 static AirpcapSetDeviceMacFlagsHandler p_AirpcapSetDeviceMacFlags
;
78 static AirpcapSetLinkTypeHandler p_AirpcapSetLinkType
;
79 static AirpcapGetLinkTypeHandler p_AirpcapGetLinkType
;
80 static AirpcapSetKernelBufferHandler p_AirpcapSetKernelBuffer
;
81 static AirpcapSetFilterHandler p_AirpcapSetFilter
;
82 static AirpcapSetMinToCopyHandler p_AirpcapSetMinToCopy
;
83 static AirpcapGetReadEventHandler p_AirpcapGetReadEvent
;
84 static AirpcapReadHandler p_AirpcapRead
;
85 static AirpcapWriteHandler p_AirpcapWrite
;
86 static AirpcapGetStatsHandler p_AirpcapGetStats
;
90 AIRPCAP_API_UNLOADED
= 0,
92 AIRPCAP_API_CANNOT_LOAD
,
94 } AIRPCAP_API_LOAD_STATUS
;
96 static AIRPCAP_API_LOAD_STATUS airpcap_load_status
;
99 * NOTE: this function should be called by the pcap functions that can
100 * theoretically deal with the AirPcap library for the first time,
101 * namely listing the adapters and creating a pcap_t for an adapter.
102 * All the other ones (activate, close, read, write, set parameters)
103 * work on a pcap_t for an AirPcap device, meaning we've already
104 * created the pcap_t and thus have loaded the functions, so we do
105 * not need to call this function.
107 static AIRPCAP_API_LOAD_STATUS
108 load_airpcap_functions(void)
110 AIRPCAP_API_LOAD_STATUS current_status
;
113 * We don't use a mutex because there's no place that
114 * we can guarantee we'll be called before any threads
115 * other than the main thread exists. (For example,
116 * this might be a static library, so we can't arrange
117 * to be called by DllMain(), and there's no guarantee
118 * that the application called pcap_init() - which is
119 * supposed to be called only from one thread - so
120 * we can't arrange to be called from it.)
122 * If nobody's tried to load it yet, mark it as
123 * loading; in any case, return the status before
126 current_status
= InterlockedCompareExchange((LONG
*)&airpcap_load_status
,
127 AIRPCAP_API_LOADING
, AIRPCAP_API_UNLOADED
);
130 * If the status was AIRPCAP_API_UNLOADED, we've set it
131 * to AIRPCAP_API_LOADING, because we're going to be
132 * the ones to load the library but current_status is
133 * AIRPCAP_API_UNLOADED.
135 * if it was AIRPCAP_API_LOADING, meaning somebody else
136 * was trying to load it, spin until they finish and
137 * set the status to a value reflecting whether they
140 while (current_status
== AIRPCAP_API_LOADING
) {
141 current_status
= InterlockedCompareExchange((LONG
*)&airpcap_load_status
,
142 AIRPCAP_API_LOADING
, AIRPCAP_API_LOADING
);
147 * At this point, current_status is either:
149 * AIRPCAP_API_LOADED, in which case another thread
150 * loaded the library, so we're done;
152 * AIRPCAP_API_CANNOT_LOAD, in which another thread
153 * tried and failed to load the library, so we're
154 * done - we won't try it ourselves;
156 * AIRPCAP_API_LOADING, in which case *we're* the
157 * ones loading it, and should now try to do so.
159 if (current_status
== AIRPCAP_API_LOADED
)
160 return AIRPCAP_API_LOADED
;
162 if (current_status
== AIRPCAP_API_CANNOT_LOAD
)
163 return AIRPCAP_API_CANNOT_LOAD
;
166 * Start out assuming we can't load it.
168 current_status
= AIRPCAP_API_CANNOT_LOAD
;
170 airpcap_lib
= pcapint_load_code("airpcap.dll");
171 if (airpcap_lib
!= NULL
) {
173 * OK, we've loaded the library; now try to find the
174 * functions we need in it.
176 p_AirpcapGetLastError
= (AirpcapGetLastErrorHandler
) pcapint_find_function(airpcap_lib
, "AirpcapGetLastError");
177 p_AirpcapGetDeviceList
= (AirpcapGetDeviceListHandler
) pcapint_find_function(airpcap_lib
, "AirpcapGetDeviceList");
178 p_AirpcapFreeDeviceList
= (AirpcapFreeDeviceListHandler
) pcapint_find_function(airpcap_lib
, "AirpcapFreeDeviceList");
179 p_AirpcapOpen
= (AirpcapOpenHandler
) pcapint_find_function(airpcap_lib
, "AirpcapOpen");
180 p_AirpcapClose
= (AirpcapCloseHandler
) pcapint_find_function(airpcap_lib
, "AirpcapClose");
181 p_AirpcapSetDeviceMacFlags
= (AirpcapSetDeviceMacFlagsHandler
) pcapint_find_function(airpcap_lib
, "AirpcapSetDeviceMacFlags");
182 p_AirpcapSetLinkType
= (AirpcapSetLinkTypeHandler
) pcapint_find_function(airpcap_lib
, "AirpcapSetLinkType");
183 p_AirpcapGetLinkType
= (AirpcapGetLinkTypeHandler
) pcapint_find_function(airpcap_lib
, "AirpcapGetLinkType");
184 p_AirpcapSetKernelBuffer
= (AirpcapSetKernelBufferHandler
) pcapint_find_function(airpcap_lib
, "AirpcapSetKernelBuffer");
185 p_AirpcapSetFilter
= (AirpcapSetFilterHandler
) pcapint_find_function(airpcap_lib
, "AirpcapSetFilter");
186 p_AirpcapSetMinToCopy
= (AirpcapSetMinToCopyHandler
) pcapint_find_function(airpcap_lib
, "AirpcapSetMinToCopy");
187 p_AirpcapGetReadEvent
= (AirpcapGetReadEventHandler
) pcapint_find_function(airpcap_lib
, "AirpcapGetReadEvent");
188 p_AirpcapRead
= (AirpcapReadHandler
) pcapint_find_function(airpcap_lib
, "AirpcapRead");
189 p_AirpcapWrite
= (AirpcapWriteHandler
) pcapint_find_function(airpcap_lib
, "AirpcapWrite");
190 p_AirpcapGetStats
= (AirpcapGetStatsHandler
) pcapint_find_function(airpcap_lib
, "AirpcapGetStats");
193 // Make sure that we found everything
195 if (p_AirpcapGetLastError
!= NULL
&&
196 p_AirpcapGetDeviceList
!= NULL
&&
197 p_AirpcapFreeDeviceList
!= NULL
&&
198 p_AirpcapOpen
!= NULL
&&
199 p_AirpcapClose
!= NULL
&&
200 p_AirpcapSetDeviceMacFlags
!= NULL
&&
201 p_AirpcapSetLinkType
!= NULL
&&
202 p_AirpcapGetLinkType
!= NULL
&&
203 p_AirpcapSetKernelBuffer
!= NULL
&&
204 p_AirpcapSetFilter
!= NULL
&&
205 p_AirpcapSetMinToCopy
!= NULL
&&
206 p_AirpcapGetReadEvent
!= NULL
&&
207 p_AirpcapRead
!= NULL
&&
208 p_AirpcapWrite
!= NULL
&&
209 p_AirpcapGetStats
!= NULL
) {
211 * We have all we need.
213 current_status
= AIRPCAP_API_LOADED
;
217 if (current_status
!= AIRPCAP_API_LOADED
) {
219 * We failed; if we found the DLL, close the
222 if (airpcap_lib
!= NULL
) {
223 FreeLibrary(airpcap_lib
);
229 * Now set the status appropriately - and atomically.
231 InterlockedExchange((LONG
*)&airpcap_load_status
, current_status
);
233 return current_status
;
237 * Private data for capturing on AirPcap devices.
239 struct pcap_airpcap
{
240 PAirpcapHandle adapter
;
241 int filtering_in_kernel
;
245 struct pcap_stat stat
;
249 airpcap_setfilter(pcap_t
*p
, struct bpf_program
*fp
)
251 struct pcap_airpcap
*pa
= p
->priv
;
253 if (!p_AirpcapSetFilter(pa
->adapter
, fp
->bf_insns
,
254 fp
->bf_len
* sizeof(struct bpf_insn
))) {
256 * Kernel filter not installed.
258 * XXX - we don't know whether this failed because:
260 * the kernel rejected the filter program as invalid,
261 * in which case we should fall back on userland
264 * the kernel rejected the filter program as too big,
265 * in which case we should again fall back on
266 * userland filtering;
268 * there was some other problem, in which case we
269 * should probably report an error;
271 * So we just fall back on userland filtering in
276 * pcapint_install_bpf_program() validates the program.
278 * XXX - what if we already have a filter in the kernel?
280 if (pcapint_install_bpf_program(p
, fp
) < 0)
282 pa
->filtering_in_kernel
= 0; /* filtering in userland */
289 pa
->filtering_in_kernel
= 1; /* filtering in the kernel */
292 * Discard any previously-received packets, as they might have
293 * passed whatever filter was formerly in effect, but might
294 * not pass this filter (BIOCSETF discards packets buffered
295 * in the kernel, so you can lose packets in any case).
302 airpcap_set_datalink(pcap_t
*p
, int dlt
)
304 struct pcap_airpcap
*pa
= p
->priv
;
305 AirpcapLinkType type
;
309 case DLT_IEEE802_11_RADIO
:
310 type
= AIRPCAP_LT_802_11_PLUS_RADIO
;
314 type
= AIRPCAP_LT_802_11_PLUS_PPI
;
318 type
= AIRPCAP_LT_802_11
;
322 /* This can't happen; just return. */
325 if (!p_AirpcapSetLinkType(pa
->adapter
, type
)) {
326 snprintf(p
->errbuf
, PCAP_ERRBUF_SIZE
,
327 "AirpcapSetLinkType() failed: %s",
328 p_AirpcapGetLastError(pa
->adapter
));
336 airpcap_getnonblock(pcap_t
*p
)
338 struct pcap_airpcap
*pa
= p
->priv
;
340 return (pa
->nonblock
);
344 airpcap_setnonblock(pcap_t
*p
, int nonblock
)
346 struct pcap_airpcap
*pa
= p
->priv
;
351 * Set the packet buffer timeout to -1 for non-blocking
357 * Restore the timeout set when the device was opened.
358 * (Note that this may be -1, in which case we're not
359 * really leaving non-blocking mode. However, although
360 * the timeout argument to pcap_set_timeout() and
361 * pcap_open_live() is an int, you're not supposed to
362 * supply a negative value, so that "shouldn't happen".)
364 newtimeout
= p
->opt
.timeout
;
366 pa
->read_timeout
= newtimeout
;
367 pa
->nonblock
= (newtimeout
== -1);
372 airpcap_stats(pcap_t
*p
, struct pcap_stat
*ps
)
374 struct pcap_airpcap
*pa
= p
->priv
;
378 * Try to get statistics.
380 if (!p_AirpcapGetStats(pa
->adapter
, &tas
)) {
381 snprintf(p
->errbuf
, PCAP_ERRBUF_SIZE
,
382 "AirpcapGetStats() failed: %s",
383 p_AirpcapGetLastError(pa
->adapter
));
387 ps
->ps_drop
= tas
.Drops
;
388 ps
->ps_recv
= tas
.Recvs
;
389 ps
->ps_ifdrop
= tas
.IfDrops
;
395 * Win32-only routine for getting statistics.
397 * This way is definitely safer than passing the pcap_stat * from the userland.
398 * In fact, there could happen than the user allocates a variable which is not
399 * big enough for the new structure, and the library will write in a zone
400 * which is not allocated to this variable.
402 * In this way, we're pretty sure we are writing on memory allocated to this
405 * XXX - but this is the wrong way to handle statistics. Instead, we should
406 * have an API that returns data in a form like the Options section of a
407 * pcapng Interface Statistics Block:
409 * 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
411 * which would let us add new statistics straightforwardly and indicate which
412 * statistics we are and are *not* providing, rather than having to provide
413 * possibly-bogus values for statistics we can't provide.
415 static struct pcap_stat
*
416 airpcap_stats_ex(pcap_t
*p
, int *pcap_stat_size
)
418 struct pcap_airpcap
*pa
= p
->priv
;
421 *pcap_stat_size
= sizeof (p
->stat
);
424 * Try to get statistics.
426 if (!p_AirpcapGetStats(pa
->adapter
, &tas
)) {
427 snprintf(p
->errbuf
, PCAP_ERRBUF_SIZE
,
428 "AirpcapGetStats() failed: %s",
429 p_AirpcapGetLastError(pa
->adapter
));
433 p
->stat
.ps_recv
= tas
.Recvs
;
434 p
->stat
.ps_drop
= tas
.Drops
;
435 p
->stat
.ps_ifdrop
= tas
.IfDrops
;
437 * Just in case this is ever compiled for a target other than
438 * Windows, which is extremely unlikely at best.
441 p
->stat
.ps_capt
= tas
.Capt
;
446 /* Set the dimension of the kernel-level capture buffer */
448 airpcap_setbuff(pcap_t
*p
, int dim
)
450 struct pcap_airpcap
*pa
= p
->priv
;
452 if (!p_AirpcapSetKernelBuffer(pa
->adapter
, dim
)) {
453 snprintf(p
->errbuf
, PCAP_ERRBUF_SIZE
,
454 "AirpcapSetKernelBuffer() failed: %s",
455 p_AirpcapGetLastError(pa
->adapter
));
461 /* Set the driver working mode */
463 airpcap_setmode(pcap_t
*p
, int mode
)
465 if (mode
!= MODE_CAPT
) {
466 snprintf(p
->errbuf
, PCAP_ERRBUF_SIZE
,
467 "Only MODE_CAPT is supported on an AirPcap adapter");
473 /*set the minimum amount of data that will release a read call*/
475 airpcap_setmintocopy(pcap_t
*p
, int size
)
477 struct pcap_airpcap
*pa
= p
->priv
;
479 if (!p_AirpcapSetMinToCopy(pa
->adapter
, size
)) {
480 snprintf(p
->errbuf
, PCAP_ERRBUF_SIZE
,
481 "AirpcapSetMinToCopy() failed: %s",
482 p_AirpcapGetLastError(pa
->adapter
));
489 airpcap_getevent(pcap_t
*p
)
491 struct pcap_airpcap
*pa
= p
->priv
;
493 return (pa
->read_event
);
497 airpcap_oid_get_request(pcap_t
*p
, bpf_u_int32 oid _U_
, void *data _U_
,
500 snprintf(p
->errbuf
, PCAP_ERRBUF_SIZE
,
501 "Getting OID values is not supported on an AirPcap adapter");
506 airpcap_oid_set_request(pcap_t
*p
, bpf_u_int32 oid _U_
, const void *data _U_
,
509 snprintf(p
->errbuf
, PCAP_ERRBUF_SIZE
,
510 "Setting OID values is not supported on an AirPcap adapter");
515 airpcap_sendqueue_transmit(pcap_t
*p
, pcap_send_queue
*queue _U_
, int sync _U_
)
517 snprintf(p
->errbuf
, PCAP_ERRBUF_SIZE
,
518 "Cannot queue packets for transmission on an AirPcap adapter");
523 airpcap_setuserbuffer(pcap_t
*p
, int size
)
525 unsigned char *new_buff
;
528 /* Bogus parameter */
529 snprintf(p
->errbuf
, PCAP_ERRBUF_SIZE
,
530 "Error: invalid size %d",size
);
534 /* Allocate the buffer */
535 new_buff
= (unsigned char *)malloc(sizeof(char)*size
);
538 snprintf(p
->errbuf
, PCAP_ERRBUF_SIZE
,
539 "Error: not enough memory");
545 p
->buffer
= new_buff
;
552 airpcap_live_dump(pcap_t
*p
, char *filename _U_
, int maxsize _U_
,
555 snprintf(p
->errbuf
, PCAP_ERRBUF_SIZE
,
556 "AirPcap adapters don't support live dump");
561 airpcap_live_dump_ended(pcap_t
*p
, int sync _U_
)
563 snprintf(p
->errbuf
, PCAP_ERRBUF_SIZE
,
564 "AirPcap adapters don't support live dump");
568 static PAirpcapHandle
569 airpcap_get_airpcap_handle(pcap_t
*p
)
571 struct pcap_airpcap
*pa
= p
->priv
;
573 return (pa
->adapter
);
577 airpcap_read(pcap_t
*p
, int cnt
, pcap_handler callback
, u_char
*user
)
579 struct pcap_airpcap
*pa
= p
->priv
;
582 register u_char
*bp
, *ep
;
589 * Has "pcap_breakloop()" been called?
593 * Yes - clear the flag that indicates that it
594 * has, and return PCAP_ERROR_BREAK to indicate
595 * that we were told to break out of the loop.
598 return (PCAP_ERROR_BREAK
);
602 // If we're not in non-blocking mode, wait for data to
605 if (pa
->read_timeout
!= -1) {
606 WaitForSingleObject(pa
->read_event
,
607 (pa
->read_timeout
==0 )? INFINITE
: pa
->read_timeout
);
612 // p_AirpcapRead doesn't block.
614 if (!p_AirpcapRead(pa
->adapter
, (PBYTE
)p
->buffer
,
615 p
->bufsize
, &bytes_read
)) {
616 snprintf(p
->errbuf
, PCAP_ERRBUF_SIZE
,
617 "AirpcapRead() failed: %s",
618 p_AirpcapGetLastError(pa
->adapter
));
623 * At this point, read_ret is guaranteed to be
624 * >= 0 and < p->bufsize; p->bufsize is a u_int,
625 * so its value is guaranteed to fit in cc, which
634 * Loop through each packet.
636 * This assumes that a single buffer of packets will have
637 * <= INT_MAX packets, so the packet count doesn't overflow.
639 #define bhp ((AirpcapBpfHeader *)bp)
643 register u_int caplen
, hdrlen
;
647 * Has "pcap_breakloop()" been called?
648 * If so, return immediately - if we haven't read any
649 * packets, clear the flag and return PCAP_ERROR_BREAK
650 * to indicate that we were told to break out of the loop,
651 * otherwise leave the flag set, so that the *next* call
652 * will break out of the loop without having read any
653 * packets, and return the number of packets we've
659 return (PCAP_ERROR_BREAK
);
662 p
->cc
= (u_int
) (ep
- bp
);
669 caplen
= bhp
->Caplen
;
670 hdrlen
= bhp
->Hdrlen
;
674 * Compute the number of bytes for this packet in
677 * That's the sum of the header length and the packet
678 * data length plus, if this is not the last packet,
679 * the padding required to align the next packet on
680 * the appropriate boundary.
682 * That means that it should be the minimum of the
683 * number of bytes left in the buffer and the
684 * rounded-up sum of the header and packet data lengths.
686 packet_bytes
= min((u_int
)(ep
- bp
), AIRPCAP_WORDALIGN(caplen
+ hdrlen
));
689 * Short-circuit evaluation: if using BPF filter
690 * in the AirPcap adapter, no need to do it now -
691 * we already know the packet passed the filter.
693 if (pa
->filtering_in_kernel
||
694 p
->fcode
.bf_insns
== NULL
||
695 pcapint_filter(p
->fcode
.bf_insns
, datap
, bhp
->Originallen
, caplen
)) {
696 struct pcap_pkthdr pkthdr
;
698 pkthdr
.ts
.tv_sec
= bhp
->TsSec
;
699 pkthdr
.ts
.tv_usec
= bhp
->TsUsec
;
700 pkthdr
.caplen
= caplen
;
701 pkthdr
.len
= bhp
->Originallen
;
702 (*callback
)(user
, &pkthdr
, datap
);
704 if (++n
>= cnt
&& !PACKET_COUNT_IS_UNLIMITED(cnt
)) {
706 p
->cc
= (u_int
)(ep
- bp
);
722 airpcap_inject(pcap_t
*p
, const void *buf
, int size
)
724 struct pcap_airpcap
*pa
= p
->priv
;
727 * XXX - the second argument to AirpcapWrite() *should* have
728 * been declared as a const pointer - a write function that
729 * stomps on what it writes is *extremely* rude - but such
730 * is life. We assume it is, in fact, not going to write on
733 if (!p_AirpcapWrite(pa
->adapter
, (void *)buf
, size
)) {
734 snprintf(p
->errbuf
, PCAP_ERRBUF_SIZE
,
735 "AirpcapWrite() failed: %s",
736 p_AirpcapGetLastError(pa
->adapter
));
741 * We assume it all got sent if "AirpcapWrite()" succeeded.
742 * "pcap_inject()" is expected to return the number of bytes
749 airpcap_cleanup(pcap_t
*p
)
751 struct pcap_airpcap
*pa
= p
->priv
;
753 if (pa
->adapter
!= NULL
) {
754 p_AirpcapClose(pa
->adapter
);
757 pcapint_cleanup_live_common(p
);
761 airpcap_breakloop(pcap_t
*p
)
765 pcapint_breakloop_common(p
);
766 struct pcap_airpcap
*pa
= p
->priv
;
768 /* XXX - what if either of these fail? */
770 * XXX - will SetEvent() force a wakeup and, if so, will
771 * the AirPcap read code handle that sanely?
773 if (!p_AirpcapGetReadEvent(pa
->adapter
, &read_event
))
775 SetEvent(read_event
);
779 airpcap_activate(pcap_t
*p
)
781 struct pcap_airpcap
*pa
= p
->priv
;
782 char *device
= p
->opt
.device
;
783 char airpcap_errbuf
[AIRPCAP_ERRBUF_SIZE
];
785 AirpcapLinkType link_type
;
787 pa
->adapter
= p_AirpcapOpen(device
, airpcap_errbuf
);
788 if (pa
->adapter
== NULL
) {
789 snprintf(p
->errbuf
, PCAP_ERRBUF_SIZE
, "%s", airpcap_errbuf
);
794 * Set monitor mode appropriately.
795 * Always turn off the "ACK frames sent to the card" mode.
798 status
= p_AirpcapSetDeviceMacFlags(pa
->adapter
,
799 AIRPCAP_MF_MONITOR_MODE_ON
);
801 status
= p_AirpcapSetDeviceMacFlags(pa
->adapter
,
802 AIRPCAP_MF_ACK_FRAMES_ON
);
804 p_AirpcapClose(pa
->adapter
);
805 snprintf(p
->errbuf
, PCAP_ERRBUF_SIZE
,
806 "AirpcapSetDeviceMacFlags() failed: %s",
807 p_AirpcapGetLastError(pa
->adapter
));
812 * Turn a negative snapshot value (invalid), a snapshot value of
813 * 0 (unspecified), or a value bigger than the normal maximum
814 * value, into the maximum allowed value.
816 * If some application really *needs* a bigger snapshot
817 * length, we should just increase MAXIMUM_SNAPLEN.
819 if (p
->snapshot
<= 0 || p
->snapshot
> MAXIMUM_SNAPLEN
)
820 p
->snapshot
= MAXIMUM_SNAPLEN
;
823 * If the buffer size wasn't explicitly set, default to
824 * AIRPCAP_DEFAULT_KERNEL_BUFFER_SIZE.
826 if (p
->opt
.buffer_size
== 0)
827 p
->opt
.buffer_size
= AIRPCAP_DEFAULT_KERNEL_BUFFER_SIZE
;
829 if (!p_AirpcapSetKernelBuffer(pa
->adapter
, p
->opt
.buffer_size
)) {
830 snprintf(p
->errbuf
, PCAP_ERRBUF_SIZE
,
831 "AirpcapSetKernelBuffer() failed: %s",
832 p_AirpcapGetLastError(pa
->adapter
));
836 if(!p_AirpcapGetReadEvent(pa
->adapter
, &pa
->read_event
)) {
837 snprintf(p
->errbuf
, PCAP_ERRBUF_SIZE
,
838 "AirpcapGetReadEvent() failed: %s",
839 p_AirpcapGetLastError(pa
->adapter
));
843 /* Set the buffer size */
844 p
->bufsize
= AIRPCAP_DEFAULT_USER_BUFFER_SIZE
;
845 p
->buffer
= malloc(p
->bufsize
);
846 if (p
->buffer
== NULL
) {
847 pcapint_fmt_errmsg_for_errno(p
->errbuf
, PCAP_ERRBUF_SIZE
,
852 if (p
->opt
.immediate
) {
853 /* Tell the driver to copy the buffer as soon as data arrives. */
854 if (!p_AirpcapSetMinToCopy(pa
->adapter
, 0)) {
855 snprintf(p
->errbuf
, PCAP_ERRBUF_SIZE
,
856 "AirpcapSetMinToCopy() failed: %s",
857 p_AirpcapGetLastError(pa
->adapter
));
862 * Tell the driver to copy the buffer only if it contains
865 if (!p_AirpcapSetMinToCopy(pa
->adapter
, 16000)) {
866 snprintf(p
->errbuf
, PCAP_ERRBUF_SIZE
,
867 "AirpcapSetMinToCopy() failed: %s",
868 p_AirpcapGetLastError(pa
->adapter
));
874 * Find out what the default link-layer header type is,
875 * and set p->datalink to that.
877 * We don't force it to another value because there
878 * might be some programs using WinPcap/Npcap that,
879 * when capturing on AirPcap devices, assume the
880 * default value set with the AirPcap configuration
881 * program is what you get.
883 * The out-of-the-box default appears to be radiotap.
885 if (!p_AirpcapGetLinkType(pa
->adapter
, &link_type
)) {
887 snprintf(p
->errbuf
, PCAP_ERRBUF_SIZE
,
888 "AirpcapGetLinkType() failed: %s",
889 p_AirpcapGetLastError(pa
->adapter
));
894 case AIRPCAP_LT_802_11_PLUS_RADIO
:
895 p
->linktype
= DLT_IEEE802_11_RADIO
;
898 case AIRPCAP_LT_802_11_PLUS_PPI
:
899 p
->linktype
= DLT_PPI
;
902 case AIRPCAP_LT_802_11
:
903 p
->linktype
= DLT_IEEE802_11
;
906 case AIRPCAP_LT_UNKNOWN
:
909 snprintf(p
->errbuf
, PCAP_ERRBUF_SIZE
,
910 "AirpcapGetLinkType() returned unknown link type %u",
916 * Now provide a list of all the supported types; we
917 * assume they all work. We put radiotap at the top,
918 * followed by PPI, followed by "no radio metadata".
920 p
->dlt_list
= (u_int
*) malloc(sizeof(u_int
) * 3);
921 if (p
->dlt_list
== NULL
) {
922 pcapint_fmt_errmsg_for_errno(p
->errbuf
, PCAP_ERRBUF_SIZE
,
926 p
->dlt_list
[0] = DLT_IEEE802_11_RADIO
;
927 p
->dlt_list
[1] = DLT_PPI
;
928 p
->dlt_list
[2] = DLT_IEEE802_11
;
931 p
->read_op
= airpcap_read
;
932 p
->inject_op
= airpcap_inject
;
933 p
->setfilter_op
= airpcap_setfilter
;
934 p
->setdirection_op
= NULL
; /* Not implemented. */
935 p
->set_datalink_op
= airpcap_set_datalink
;
936 p
->getnonblock_op
= airpcap_getnonblock
;
937 p
->setnonblock_op
= airpcap_setnonblock
;
938 p
->breakloop_op
= airpcap_breakloop
;
939 p
->stats_op
= airpcap_stats
;
940 p
->stats_ex_op
= airpcap_stats_ex
;
941 p
->setbuff_op
= airpcap_setbuff
;
942 p
->setmode_op
= airpcap_setmode
;
943 p
->setmintocopy_op
= airpcap_setmintocopy
;
944 p
->getevent_op
= airpcap_getevent
;
945 p
->oid_get_request_op
= airpcap_oid_get_request
;
946 p
->oid_set_request_op
= airpcap_oid_set_request
;
947 p
->sendqueue_transmit_op
= airpcap_sendqueue_transmit
;
948 p
->setuserbuffer_op
= airpcap_setuserbuffer
;
949 p
->live_dump_op
= airpcap_live_dump
;
950 p
->live_dump_ended_op
= airpcap_live_dump_ended
;
951 p
->get_airpcap_handle_op
= airpcap_get_airpcap_handle
;
952 p
->cleanup_op
= airpcap_cleanup
;
961 * Monitor mode is supported.
964 airpcap_can_set_rfmon(pcap_t
*p
)
970 device_is_airpcap(const char *device
, char *ebuf
)
972 static const char airpcap_prefix
[] = "\\\\.\\airpcap";
975 * We don't determine this by calling AirpcapGetDeviceList()
976 * and looking at the list, as that appears to be a costly
979 * Instead, we just check whether it begins with "\\.\airpcap".
981 if (strncmp(device
, airpcap_prefix
, sizeof airpcap_prefix
- 1) == 0) {
983 * Yes, it's an AirPcap device.
989 * No, it's not an AirPcap device.
995 airpcap_create(const char *device
, char *ebuf
, int *is_ours
)
1001 * This can be called before we've tried loading the library,
1002 * so do so if we haven't already tried to do so.
1004 if (load_airpcap_functions() != AIRPCAP_API_LOADED
) {
1006 * We assume this means that we don't have the AirPcap
1007 * software installed, which probably means we don't
1008 * have an AirPcap device.
1010 * Don't treat that as an error.
1017 * Is this an AirPcap device?
1019 ret
= device_is_airpcap(device
, ebuf
);
1030 p
= PCAP_CREATE_COMMON(ebuf
, struct pcap_airpcap
);
1034 p
->activate_op
= airpcap_activate
;
1035 p
->can_set_rfmon_op
= airpcap_can_set_rfmon
;
1040 * Add all AirPcap devices.
1043 airpcap_findalldevs(pcap_if_list_t
*devlistp
, char *errbuf
)
1045 AirpcapDeviceDescription
*airpcap_devices
, *airpcap_device
;
1046 char airpcap_errbuf
[AIRPCAP_ERRBUF_SIZE
];
1049 * This can be called before we've tried loading the library,
1050 * so do so if we haven't already tried to do so.
1052 if (load_airpcap_functions() != AIRPCAP_API_LOADED
) {
1054 * XXX - unless the error is "no such DLL", report this
1055 * as an error rather than as "no AirPcap devices"?
1060 if (!p_AirpcapGetDeviceList(&airpcap_devices
, airpcap_errbuf
)) {
1061 snprintf(errbuf
, PCAP_ERRBUF_SIZE
,
1062 "AirpcapGetDeviceList() failed: %s", airpcap_errbuf
);
1066 for (airpcap_device
= airpcap_devices
; airpcap_device
!= NULL
;
1067 airpcap_device
= airpcap_device
->next
) {
1068 if (pcapint_add_dev(devlistp
, airpcap_device
->Name
, 0,
1069 airpcap_device
->Description
, errbuf
) == NULL
) {
1073 p_AirpcapFreeDeviceList(airpcap_devices
);
1077 p_AirpcapFreeDeviceList(airpcap_devices
);