add winpcap 4.0.2 from url http://www.winpcap.org/
[natblaster.git] / winpcap / packetNtx / Dll / Packet32.c
blob866c3fee03055b87919d3ec353cafbbc4eead78e
1 /*
2 * Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy)
3 * Copyright (c) 2005 - 2006 CACE Technologies, Davis (California)
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
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.
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.
34 #define UNICODE 1
36 #pragma warning (disable : 4127) //conditional expression is constant. Used for do{}while(FALSE) loops.
38 #if (MSC_VER < 1300)
39 #pragma warning (disable : 4710) // inline function not expanded. used for strsafe functions
40 #endif
43 #include <packet32.h>
44 #include <StrSafe.h>
46 #include "Packet32-Int.h"
48 #ifdef HAVE_WANPACKET_API
49 #include "wanpacket/wanpacket.h"
50 #endif //HAVE_WANPACKET_API
52 #include "debug.h"
54 #ifdef _WINNT4
55 #if (defined(HAVE_NPFIM_API) || defined(HAVE_WANPACKET_API) || defined (HAVE_AIRPCAP_API) || defined(HAVE_IPHELPER_API))
56 #error Do not enable _WINNT4 with any other API
57 #endif
58 #endif //_WINNT4
60 #ifdef _WINNT4
61 #pragma message ("Compiling Packet.dll for WINNT4 only")
62 #endif
64 #ifdef HAVE_AIRPCAP_API
65 #pragma message ("Compiling Packet.dll with support for AirPcap")
66 #endif
68 #ifdef HAVE_NPFIM_API
69 #pragma message ("Compiling Packet.dll with support for NpfIm driver")
70 #endif
72 #ifdef HAVE_DAG_API
73 #pragma message ("Compiling Packet.dll with support for DAG cards")
74 #endif
76 #ifdef HAVE_WANPACKET_API
77 #pragma message ("Compiling Packet.dll with support for WanPacket (aka Dialup thru NetMon)")
78 #endif
80 #ifdef HAVE_IPHELPER_API
81 #pragma message ("Compiling Packet.dll with support from IP helper API for API addresses")
82 #endif
84 #ifndef UNUSED
85 #define UNUSED(_x) (_x)
86 #endif
89 #ifdef _DEBUG_TO_FILE
90 LONG PacketDumpRegistryKey(PCHAR KeyName, PCHAR FileName);
91 CHAR g_LogFileName[1024] = "winpcap_debug.txt";
92 #endif //_DEBUG_TO_FILE
94 #include <windows.h>
95 #include <windowsx.h>
96 #include <Iphlpapi.h>
97 #include <IPIfCons.h>
99 #include <ntddndis.h>
101 #include <WpcapNames.h>
104 // Current packet.dll Version. It can be retrieved directly or through the PacketGetVersion() function.
106 char PacketLibraryVersion[64];
109 // Current NPF.sys Version. It can be retrieved directly or through the PacketGetVersion() function.
111 char PacketDriverVersion[64];
114 // WinPcap global registry key
116 //WCHAR g_WinPcapKeyBuffer[MAX_WINPCAP_KEY_CHARS];
117 //HKEY g_WinpcapKey = NULL;
120 // Global adapters list related variables
122 extern PADAPTER_INFO g_AdaptersInfoList;
123 extern HANDLE g_AdaptersInfoMutex;
125 #ifdef HAVE_IPHELPER_API
126 typedef VOID (*GAAHandler)(
127 ULONG,
128 DWORD,
129 PVOID,
130 PIP_ADAPTER_ADDRESSES,
131 PULONG);
132 GAAHandler g_GetAdaptersAddressesPointer = NULL;
133 #endif // HAVE_IPHELPER_API
136 // Dynamic dependencies variables and declarations
138 volatile LONG g_DynamicLibrariesLoaded = 0;
139 HANDLE g_DynamicLibrariesMutex;
141 #ifdef HAVE_AIRPCAP_API
142 // We load dinamically the dag library in order link it only when it's present on the system
143 AirpcapGetLastErrorHandler g_PAirpcapGetLastError;
144 AirpcapGetDeviceListHandler g_PAirpcapGetDeviceList;
145 AirpcapFreeDeviceListHandler g_PAirpcapFreeDeviceList;
146 AirpcapOpenHandler g_PAirpcapOpen;
147 AirpcapCloseHandler g_PAirpcapClose;
148 AirpcapGetLinkTypeHandler g_PAirpcapGetLinkType;
149 AirpcapSetKernelBufferHandler g_PAirpcapSetKernelBuffer;
150 AirpcapSetFilterHandler g_PAirpcapSetFilter;
151 AirpcapGetMacAddressHandler g_PAirpcapGetMacAddress;
152 AirpcapSetMinToCopyHandler g_PAirpcapSetMinToCopy;
153 AirpcapGetReadEventHandler g_PAirpcapGetReadEvent;
154 AirpcapReadHandler g_PAirpcapRead;
155 AirpcapGetStatsHandler g_PAirpcapGetStats;
156 AirpcapWriteHandler g_PAirpcapWrite;
157 #endif // HAVE_AIRPCAP_API
159 #ifdef HAVE_DAG_API
160 // We load dinamically the dag library in order link it only when it's present on the system
161 dagc_open_handler g_p_dagc_open = NULL;
162 dagc_close_handler g_p_dagc_close = NULL;
163 dagc_getlinktype_handler g_p_dagc_getlinktype = NULL;
164 dagc_getlinkspeed_handler g_p_dagc_getlinkspeed = NULL;
165 dagc_getfcslen_handler g_p_dagc_getfcslen = NULL;
166 dagc_receive_handler g_p_dagc_receive = NULL;
167 dagc_wait_handler g_p_dagc_wait = NULL;
168 dagc_stats_handler g_p_dagc_stats = NULL;
169 dagc_setsnaplen_handler g_p_dagc_setsnaplen = NULL;
170 dagc_finddevs_handler g_p_dagc_finddevs = NULL;
171 dagc_freedevs_handler g_p_dagc_freedevs = NULL;
172 #endif // HAVE_DAG_API
174 BOOLEAN PacketAddAdapterDag(PCHAR name, PCHAR description, BOOLEAN IsAFile);
177 // Additions for WinPcap OEM
179 #ifdef WPCAP_OEM_UNLOAD_H
180 typedef BOOL (*WoemLeaveDllHandler)(void);
181 WoemLeaveDllHandler g_WoemLeaveDllH = NULL;
183 __declspec (dllexport) VOID PacketRegWoemLeaveHandler(PVOID Handler)
185 g_WoemLeaveDllH = Handler;
187 #endif // WPCAP_OEM_UNLOAD_H
189 //---------------------------------------------------------------------------
191 /*!
192 \brief The main dll function.
195 BOOL APIENTRY DllMain(HANDLE DllHandle,DWORD Reason,LPVOID lpReserved)
197 BOOLEAN Status=TRUE;
198 PADAPTER_INFO NewAdInfo;
199 TCHAR DllFileName[MAX_PATH];
201 UNUSED(lpReserved);
203 switch(Reason)
205 case DLL_PROCESS_ATTACH:
207 TRACE_PRINT_DLLMAIN("************Packet32: DllMain************");
209 #if 0
210 #ifdef WPCAP_OEM
211 #ifdef HAVE_WANPACKET_API
212 LoadNdisNpp(Reason);
213 #endif // HAVE_WANPACKET_API
214 #endif // WPCAP_OEM
215 #endif
217 #ifdef _DEBUG_TO_FILE
218 PacketDumpRegistryKey("HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\" NPF_DRIVER_NAME,"npf.reg");
220 // dump a bunch of registry keys useful for debug to file
221 PacketDumpRegistryKey("HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}",
222 "adapters.reg");
223 PacketDumpRegistryKey("HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\Tcpip",
224 "tcpip.reg");
225 PacketDumpRegistryKey("HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services",
226 "services.reg");
228 #endif
230 // Create the mutex that will protect the adapter information list
231 g_AdaptersInfoMutex = CreateMutex(NULL, FALSE, NULL);
233 // Create the mutex that will protect the PacketLoadLibrariesDynamically() function
234 g_DynamicLibrariesMutex = CreateMutex(NULL, FALSE, NULL);
237 // Retrieve packet.dll version information from the file
239 // XXX We want to replace this with a constant. We leave it out for the moment
240 if(GetModuleFileName(DllHandle, DllFileName, sizeof(DllFileName) / sizeof(DllFileName[0])) > 0)
242 PacketGetFileVersion(DllFileName, PacketLibraryVersion, sizeof(PacketLibraryVersion));
245 // Retrieve NPF.sys version information from the file
247 // XXX We want to replace this with a constant. We leave it out for the moment
248 // TODO fixme. Those hardcoded strings are terrible...
249 PacketGetFileVersion(TEXT("drivers\\") TEXT(NPF_DRIVER_NAME) TEXT(".sys"), PacketDriverVersion, sizeof(PacketDriverVersion));
251 break;
253 case DLL_PROCESS_DETACH:
255 CloseHandle(g_AdaptersInfoMutex);
257 g_AdaptersInfoList;
259 while(g_AdaptersInfoList != NULL)
262 NewAdInfo = g_AdaptersInfoList->Next;
263 if (g_AdaptersInfoList->NetworkAddresses != NULL)
264 GlobalFreePtr(g_AdaptersInfoList->NetworkAddresses);
265 GlobalFreePtr(g_AdaptersInfoList);
267 g_AdaptersInfoList = NewAdInfo;
270 #ifdef WPCAP_OEM_UNLOAD_H
271 if(g_WoemLeaveDllH)
273 g_WoemLeaveDllH();
275 #endif // WPCAP_OEM_UNLOAD_H
277 break;
279 default:
280 break;
283 return Status;
287 /*!
288 \brief This function is used to dynamically load some of the libraries winpcap depends on,
289 and that are not guaranteed to be in the system
290 \param cp A string containing the address.
291 \return the converted 32-bit numeric address.
293 Doesn't check to make sure the address is valid.
295 VOID PacketLoadLibrariesDynamically()
297 #ifdef HAVE_IPHELPER_API
298 HMODULE IPHMod;
299 #endif // HAVE_IPHELPER_API
301 #ifdef HAVE_AIRPCAP_API
302 HMODULE AirpcapLib;
303 #endif // HAVE_DAG_API
305 #ifdef HAVE_DAG_API
306 HMODULE DagcLib;
307 #endif // HAVE_DAG_API
309 TRACE_ENTER("PacketLoadLibrariesDynamically");
312 // Acquire the global mutex, so we wait until other threads are done
314 WaitForSingleObject(g_DynamicLibrariesMutex, INFINITE);
317 // Only the first thread should do the initialization
319 g_DynamicLibrariesLoaded++;
321 if(g_DynamicLibrariesLoaded != 1)
323 ReleaseMutex(g_DynamicLibrariesMutex);
324 TRACE_EXIT("PacketLoadLibrariesDynamically");
325 return;
329 // Locate GetAdaptersAddresses dinamically since it is not present in Win2k
332 #ifdef HAVE_IPHELPER_API
333 IPHMod = GetModuleHandle(TEXT("Iphlpapi"));
334 if (IPHMod != NULL)
336 g_GetAdaptersAddressesPointer = (GAAHandler) GetProcAddress(IPHMod ,"GetAdaptersAddresses");
338 #endif // HAVE_IPHELPER_API
340 #ifdef HAVE_AIRPCAP_API
341 /* We dinamically load the airpcap library in order link it only when it's present on the system */
342 if((AirpcapLib = LoadLibrary(TEXT("airpcap.dll"))) == NULL)
344 // Report the error but go on
345 TRACE_PRINT("AirPcap library not found on this system");
347 else
350 // Find the exports
352 g_PAirpcapGetLastError = (AirpcapGetLastErrorHandler) GetProcAddress(AirpcapLib, "AirpcapGetLastError");
353 g_PAirpcapGetDeviceList = (AirpcapGetDeviceListHandler) GetProcAddress(AirpcapLib, "AirpcapGetDeviceList");
354 g_PAirpcapFreeDeviceList = (AirpcapFreeDeviceListHandler) GetProcAddress(AirpcapLib, "AirpcapFreeDeviceList");
355 g_PAirpcapOpen = (AirpcapOpenHandler) GetProcAddress(AirpcapLib, "AirpcapOpen");
356 g_PAirpcapClose = (AirpcapCloseHandler) GetProcAddress(AirpcapLib, "AirpcapClose");
357 g_PAirpcapGetLinkType = (AirpcapGetLinkTypeHandler) GetProcAddress(AirpcapLib, "AirpcapGetLinkType");
358 g_PAirpcapSetKernelBuffer = (AirpcapSetKernelBufferHandler) GetProcAddress(AirpcapLib, "AirpcapSetKernelBuffer");
359 g_PAirpcapSetFilter = (AirpcapSetFilterHandler) GetProcAddress(AirpcapLib, "AirpcapSetFilter");
360 g_PAirpcapGetMacAddress = (AirpcapGetMacAddressHandler) GetProcAddress(AirpcapLib, "AirpcapGetMacAddress");
361 g_PAirpcapSetMinToCopy = (AirpcapSetMinToCopyHandler) GetProcAddress(AirpcapLib, "AirpcapSetMinToCopy");
362 g_PAirpcapGetReadEvent = (AirpcapGetReadEventHandler) GetProcAddress(AirpcapLib, "AirpcapGetReadEvent");
363 g_PAirpcapRead = (AirpcapReadHandler) GetProcAddress(AirpcapLib, "AirpcapRead");
364 g_PAirpcapGetStats = (AirpcapGetStatsHandler) GetProcAddress(AirpcapLib, "AirpcapGetStats");
365 g_PAirpcapWrite = (AirpcapWriteHandler) GetProcAddress(AirpcapLib, "AirpcapWrite");
368 // Make sure that we found everything
370 if(g_PAirpcapGetLastError == NULL ||
371 g_PAirpcapGetDeviceList == NULL ||
372 g_PAirpcapFreeDeviceList == NULL ||
373 g_PAirpcapClose == NULL ||
374 g_PAirpcapGetLinkType == NULL ||
375 g_PAirpcapSetKernelBuffer == NULL ||
376 g_PAirpcapSetFilter == NULL ||
377 g_PAirpcapGetMacAddress == NULL ||
378 g_PAirpcapSetMinToCopy == NULL ||
379 g_PAirpcapGetReadEvent == NULL ||
380 g_PAirpcapRead == NULL ||
381 g_PAirpcapGetStats == NULL)
383 // No, something missing. A NULL g_PAirpcapOpen will disable airpcap adapters check
384 g_PAirpcapOpen = NULL;
387 #endif // HAVE_DAG_API
389 #ifdef HAVE_DAG_API
390 /* We dinamically load the dag library in order link it only when it's present on the system */
391 if((DagcLib = LoadLibrary(TEXT("dagc.dll"))) == NULL)
393 // Report the error but go on
394 TRACE_PRINT("dag capture library not found on this system");
396 else
398 g_p_dagc_open = (dagc_open_handler) GetProcAddress(DagcLib, "dagc_open");
399 g_p_dagc_close = (dagc_close_handler) GetProcAddress(DagcLib, "dagc_close");
400 g_p_dagc_setsnaplen = (dagc_setsnaplen_handler) GetProcAddress(DagcLib, "dagc_setsnaplen");
401 g_p_dagc_getlinktype = (dagc_getlinktype_handler) GetProcAddress(DagcLib, "dagc_getlinktype");
402 g_p_dagc_getlinkspeed = (dagc_getlinkspeed_handler) GetProcAddress(DagcLib, "dagc_getlinkspeed");
403 g_p_dagc_getfcslen = (dagc_getfcslen_handler) GetProcAddress(DagcLib, "dagc_getfcslen");
404 g_p_dagc_receive = (dagc_receive_handler) GetProcAddress(DagcLib, "dagc_receive");
405 g_p_dagc_wait = (dagc_wait_handler) GetProcAddress(DagcLib, "dagc_wait");
406 g_p_dagc_stats = (dagc_stats_handler) GetProcAddress(DagcLib, "dagc_stats");
407 g_p_dagc_finddevs = (dagc_finddevs_handler) GetProcAddress(DagcLib, "dagc_finddevs");
408 g_p_dagc_freedevs = (dagc_freedevs_handler) GetProcAddress(DagcLib, "dagc_freedevs");
410 #endif /* HAVE_DAG_API */
412 #ifdef HAVE_NPFIM_API
413 if (LoadNpfImDll() == FALSE)
415 TRACE_PRINT("Failed loading NpfIm extension");
417 #endif //HAVE_NPFIM_API
421 // Done. Release the mutex and return
423 ReleaseMutex(g_DynamicLibrariesMutex);
425 TRACE_EXIT("PacketLoadLibrariesDynamically");
426 return;
430 BOOLEAN QueryWinPcapRegistryStringA(CHAR *SubKeyName,
431 CHAR *Value,
432 UINT *pValueLen,
433 CHAR *DefaultVal)
435 #ifdef WPCAP_OEM
436 DWORD Type;
437 LONG QveRes;
438 HKEY hWinPcapKey;
440 if (QveRes = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
441 WINPCAP_INSTANCE_KEY,
443 KEY_ALL_ACCESS,
444 &hWinPcapKey) != ERROR_SUCCESS)
446 *pValueLen = 0;
448 SetLastError(QveRes);
450 return FALSE;
454 // Query the requested value
456 QveRes = RegQueryValueExA(hWinPcapKey,
457 SubKeyName,
458 NULL,
459 &Type,
460 Value,
461 pValueLen);
463 RegCloseKey(hWinPcapKey);
465 if (QveRes == ERROR_SUCCESS)
467 //let's check that the key is text
468 if (Type != REG_SZ)
470 *pValueLen = 0;
472 SetLastError(ERROR_INVALID_DATA);
473 return FALSE;
475 else
477 //success!
478 return TRUE;
481 else
482 if (QveRes == ERROR_MORE_DATA)
485 //the needed bytes are already set by RegQueryValueExA
488 SetLastError(QveRes);
489 return FALSE;
491 else
494 //print the error
496 ODSEx("QueryWinpcapRegistryKey, RegQueryValueEx failed, code %d",QveRes);
498 //JUST CONTINUE WITH THE DEFAULT VALUE
502 #endif // WPCAP_OEM
504 if ((*pValueLen) < strlen(DefaultVal) + 1)
506 memcpy(Value, DefaultVal, *pValueLen - 1);
507 Value[*pValueLen - 1] = '\0';
508 *pValueLen = strlen(DefaultVal) + 1;
509 SetLastError(ERROR_MORE_DATA);
510 return FALSE;
512 else
514 strcpy(Value, DefaultVal);
515 *pValueLen = strlen(DefaultVal) + 1;
516 return TRUE;
521 BOOLEAN QueryWinPcapRegistryStringW(WCHAR *SubKeyName,
522 WCHAR *Value,
523 UINT *pValueLen,
524 WCHAR *DefaultVal)
526 #ifdef WPCAP_OEM
527 DWORD Type;
528 LONG QveRes;
529 HKEY hWinPcapKey;
530 DWORD InternalLenBytes;
532 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
533 WINPCAP_INSTANCE_KEY_WIDECHAR,
535 KEY_ALL_ACCESS,
536 &hWinPcapKey) != ERROR_SUCCESS)
538 *pValueLen = 0;
539 return FALSE;
542 InternalLenBytes = *pValueLen * 2;
545 // Query the requested value
547 QveRes = RegQueryValueExW(hWinPcapKey,
548 SubKeyName,
549 NULL,
550 &Type,
551 (LPBYTE)Value,
552 &InternalLenBytes);
554 RegCloseKey(hWinPcapKey);
556 if (QveRes == ERROR_SUCCESS)
558 //let's check that the key is text
559 if (Type != REG_SZ)
561 *pValueLen = 0;
562 SetLastError(ERROR_INVALID_DATA);
563 return FALSE;
565 else
567 //success!
568 *pValueLen = wcslen(Value) + 1;
570 return TRUE;
573 else
574 if (QveRes == ERROR_MORE_DATA)
577 //the needed bytes are not set by RegQueryValueExW
580 //the +1 is needed to round the needed buffer size (in WCHARs) to a number of WCHARs that will fit
581 //the number of needed bytes. In any case if it's a W string, the number of needed bytes should always be even!
583 *pValueLen = (InternalLenBytes + 1) / 2;
585 SetLastError(ERROR_MORE_DATA);
586 return FALSE;
588 else
591 //print the error
593 ODSEx("QueryWinpcapRegistryKey, RegQueryValueEx failed, code %d\n",QveRes);
595 //JUST CONTINUE WITH THE DEFAULT VALUE
599 #endif // WPCAP_OEM
601 if (*pValueLen < wcslen(DefaultVal) + 1)
603 memcpy(Value, DefaultVal, (*pValueLen - 1) * 2);
604 Value[*pValueLen - 1] = '\0';
605 *pValueLen = wcslen(DefaultVal) + 1;
606 SetLastError(ERROR_MORE_DATA);
607 return FALSE;
609 else
611 wcscpy(Value, DefaultVal);
612 *pValueLen = wcslen(DefaultVal) + 1;
613 return TRUE;
620 /*!
621 \brief Convert a Unicode dotted-quad to a 32-bit IP address.
622 \param cp A string containing the address.
623 \return the converted 32-bit numeric address.
625 Doesn't check to make sure the address is valid.
627 ULONG inet_addrU(const WCHAR *cp)
629 ULONG val, part;
630 WCHAR c;
631 int i;
633 val = 0;
634 for (i = 0; i < 4; i++) {
635 part = 0;
636 while ((c = *cp++) != '\0' && c != '.') {
637 if (c < '0' || c > '9')
638 return (ULONG)-1;
639 part = part*10 + (c - '0');
641 if (part > 255)
642 return (ULONG)-1;
643 val = val | (part << i*8);
644 if (i == 3) {
645 if (c != '\0')
646 return (ULONG)-1; // extra gunk at end of string
647 } else {
648 if (c == '\0')
649 return (ULONG)-1; // string ends early
652 return val;
655 /*!
656 \brief Converts an ASCII string to UNICODE. Uses the MultiByteToWideChar() system function.
657 \param string The string to convert.
658 \return The converted string.
660 static PWCHAR SChar2WChar(PCHAR string)
662 PWCHAR TmpStr;
663 TmpStr = (WCHAR*) GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT, (DWORD)(strlen(string)+2)*sizeof(WCHAR));
665 MultiByteToWideChar(CP_ACP, 0, string, -1, TmpStr, (DWORD)(strlen(string)+2));
667 return TmpStr;
670 /*!
671 \brief Converts an UNICODE string to ASCII. Uses the WideCharToMultiByte() system function.
672 \param string The string to convert.
673 \return The converted string.
675 static PCHAR WChar2SChar(PWCHAR string)
677 PCHAR TmpStr;
678 TmpStr = (CHAR*) GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT, (DWORD)(wcslen(string)+2));
680 // Conver to ASCII
681 WideCharToMultiByte(
682 CP_ACP,
684 string,
686 TmpStr,
687 (DWORD)(wcslen(string)+2), // size of buffer
688 NULL,
689 NULL);
691 return TmpStr;
694 /*!
695 \brief Sets the maximum possible lookahead buffer for the driver's Packet_tap() function.
696 \param AdapterObject Handle to the service control manager.
697 \return If the function succeeds, the return value is nonzero.
699 The lookahead buffer is the portion of packet that Packet_tap() can access from the NIC driver's memory
700 without performing a copy. This function tries to increase the size of that buffer.
702 NOTE: this function is used for NPF adapters, only.
705 BOOLEAN PacketSetMaxLookaheadsize (LPADAPTER AdapterObject)
707 BOOLEAN Status;
708 ULONG IoCtlBufferLength=(sizeof(PACKET_OID_DATA)+sizeof(ULONG)-1);
709 PPACKET_OID_DATA OidData;
711 TRACE_ENTER("PacketSetMaxLookaheadsize");
713 OidData = GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT,IoCtlBufferLength);
714 if (OidData == NULL) {
715 TRACE_PRINT("PacketSetMaxLookaheadsize failed");
716 Status = FALSE;
718 else
720 //set the size of the lookahead buffer to the maximum available by the the NIC driver
721 OidData->Oid=OID_GEN_MAXIMUM_LOOKAHEAD;
722 OidData->Length=sizeof(ULONG);
723 Status=PacketRequest(AdapterObject,FALSE,OidData);
724 OidData->Oid=OID_GEN_CURRENT_LOOKAHEAD;
725 Status=PacketRequest(AdapterObject,TRUE,OidData);
726 GlobalFreePtr(OidData);
729 TRACE_EXIT("PacketSetMaxLookaheadsize");
730 return Status;
733 /*!
734 \brief Allocates the read event associated with the capture instance, passes it down to the kernel driver
735 and stores it in an _ADAPTER structure.
736 \param AdapterObject Handle to the adapter.
737 \return If the function succeeds, the return value is nonzero.
739 This function is used by PacketOpenAdapter() to allocate the read event and pass it to the driver by means of an ioctl
740 call and set it in the _ADAPTER structure pointed by AdapterObject.
742 NOTE: this function is used for NPF adapters, only.
744 BOOLEAN PacketSetReadEvt(LPADAPTER AdapterObject)
746 DWORD BytesReturned;
747 HANDLE hEvent;
749 TRACE_ENTER("PacketSetReadEvt");
751 if (AdapterObject->ReadEvent != NULL)
753 SetLastError(ERROR_INVALID_FUNCTION);
754 return FALSE;
757 hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
759 if (hEvent == NULL)
761 //SetLastError done by CreateEvent
762 TRACE_EXIT("PacketSetReadEvt");
763 return FALSE;
766 if(DeviceIoControl(AdapterObject->hFile,
767 pBIOCSETEVENTHANDLE,
768 &hEvent,
769 sizeof(hEvent),
770 NULL,
772 &BytesReturned,
773 NULL)==FALSE)
775 DWORD dwLastError = GetLastError();
777 CloseHandle(hEvent);
779 SetLastError(dwLastError);
781 TRACE_EXIT("PacketSetReadEvt");
782 return FALSE;
785 AdapterObject->ReadEvent = hEvent;
786 AdapterObject->ReadTimeOut=0;
788 TRACE_EXIT("PacketSetReadEvt");
789 return TRUE;
792 /*!
793 \brief Installs the NPF device driver.
794 \return If the function succeeds, the return value is nonzero.
796 This function installs the driver's service in the system using the CreateService function.
799 BOOLEAN PacketInstallDriver()
801 BOOLEAN result = FALSE;
802 ULONG err = 0;
803 SC_HANDLE svcHandle;
804 SC_HANDLE scmHandle;
806 // Old registry based WinPcap names
808 // CHAR driverName[MAX_WINPCAP_KEY_CHARS];
809 // CHAR driverDesc[MAX_WINPCAP_KEY_CHARS];
810 // CHAR driverLocation[MAX_WINPCAP_KEY_CHARS;
811 // UINT len;
813 CHAR driverName[MAX_WINPCAP_KEY_CHARS] = NPF_DRIVER_NAME;
814 CHAR driverDesc[MAX_WINPCAP_KEY_CHARS] = NPF_SERVICE_DESC;
815 CHAR driverLocation[MAX_WINPCAP_KEY_CHARS] = NPF_DRIVER_COMPLETE_PATH;
817 TRACE_ENTER("PacketInstallDriver");
820 // Old registry based WinPcap names
822 // len = sizeof(driverName)/sizeof(driverName[0]);
823 // if (QueryWinPcapRegistryStringA(NPF_DRIVER_NAME_REG_KEY, driverName, &len, NPF_DRIVER_NAME) == FALSE && len == 0)
824 // return FALSE;
826 // len = sizeof(driverDesc)/sizeof(driverDesc[0]);
827 // if (QueryWinPcapRegistryStringA(NPF_SERVICE_DESC_REG_KEY, driverDesc, &len, NPF_SERVICE_DESC) == FALSE && len == 0)
828 // return FALSE;
830 // len = sizeof(driverLocation)/sizeof(driverLocation[0]);
831 // if (QueryWinPcapRegistryStringA(NPF_DRIVER_COMPLETE_PATH_REG_KEY, driverLocation, &len, NPF_DRIVER_COMPLETE_PATH) == FALSE && len == 0)
832 // return FALSE;
834 scmHandle = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
836 if(scmHandle == NULL)
837 return FALSE;
839 svcHandle = CreateServiceA(scmHandle,
840 driverName,
841 driverDesc,
842 SERVICE_ALL_ACCESS,
843 SERVICE_KERNEL_DRIVER,
844 SERVICE_DEMAND_START,
845 SERVICE_ERROR_NORMAL,
846 driverLocation,
847 NULL, NULL, NULL, NULL, NULL);
848 if (svcHandle == NULL)
850 err = GetLastError();
851 if (err == ERROR_SERVICE_EXISTS)
853 TRACE_PRINT("Service npf.sys already exists");
854 //npf.sys already existed
855 err = 0;
856 result = TRUE;
859 else
861 TRACE_PRINT("Created service for npf.sys");
862 //Created service for npf.sys
863 result = TRUE;
866 if (svcHandle != NULL)
867 CloseServiceHandle(svcHandle);
869 if(result == FALSE)
871 TRACE_PRINT1("PacketInstallDriver failed, Error=%u",err);
874 CloseServiceHandle(scmHandle);
875 SetLastError(err);
876 TRACE_EXIT("PacketInstallDriver");
877 return result;
881 /*!
882 \brief Dumps a registry key to disk in text format. Uses regedit.
883 \param KeyName Name of the ket to dump. All its subkeys will be saved recursively.
884 \param FileName Name of the file that will contain the dump.
885 \return If the function succeeds, the return value is nonzero.
887 For debugging purposes, we use this function to obtain some registry keys from the user's machine.
890 #ifdef _DEBUG_TO_FILE
892 LONG PacketDumpRegistryKey(PCHAR KeyName, PCHAR FileName)
894 CHAR Command[256];
896 TRACE_ENTER("PacketDumpRegistryKey");
897 StringCchPrintfA(Command, sizeof(Command), "regedit /e %s %s", FileName, KeyName);
899 /// Let regedit do the dirty work for us
900 system(Command);
902 TRACE_EXIT("PacketDumpRegistryKey");
903 return TRUE;
905 #endif
907 /*!
908 \brief Returns the version of a dll or exe file
909 \param FileName Name of the file whose version has to be retrieved.
910 \param VersionBuff Buffer that will contain the string with the file version.
911 \param VersionBuffLen Length of the buffer poited by VersionBuff.
912 \return If the function succeeds, the return value is TRUE.
914 \note uses the GetFileVersionInfoSize() and GetFileVersionInfo() WIN32 API functions
916 BOOL PacketGetFileVersion(LPTSTR FileName, PCHAR VersionBuff, UINT VersionBuffLen)
918 DWORD dwVerInfoSize; // Size of version information block
919 DWORD dwVerHnd=0; // An 'ignored' parameter, always '0'
920 LPSTR lpstrVffInfo;
921 UINT cbTranslate, dwBytes;
922 TCHAR SubBlock[64];
923 PVOID lpBuffer;
924 PCHAR TmpStr;
926 // Structure used to store enumerated languages and code pages.
927 struct LANGANDCODEPAGE {
928 WORD wLanguage;
929 WORD wCodePage;
930 } *lpTranslate;
932 TRACE_ENTER("PacketGetFileVersion");
934 // Now lets dive in and pull out the version information:
935 dwVerInfoSize = GetFileVersionInfoSize(FileName, &dwVerHnd);
936 if (dwVerInfoSize)
938 lpstrVffInfo = GlobalAllocPtr(GMEM_MOVEABLE, dwVerInfoSize);
939 if (lpstrVffInfo == NULL)
941 TRACE_PRINT("PacketGetFileVersion: failed to allocate memory");
942 TRACE_EXIT("PacketGetFileVersion");
943 return FALSE;
946 if(!GetFileVersionInfo(FileName, dwVerHnd, dwVerInfoSize, lpstrVffInfo))
948 TRACE_PRINT("PacketGetFileVersion: failed to call GetFileVersionInfo");
949 GlobalFreePtr(lpstrVffInfo);
950 TRACE_EXIT("PacketGetFileVersion");
951 return FALSE;
954 // Read the list of languages and code pages.
955 if(!VerQueryValue(lpstrVffInfo, TEXT("\\VarFileInfo\\Translation"), (LPVOID*)&lpTranslate, &cbTranslate))
957 TRACE_PRINT("PacketGetFileVersion: failed to call VerQueryValue");
958 GlobalFreePtr(lpstrVffInfo);
959 TRACE_EXIT("PacketGetFileVersion");
960 return FALSE;
963 // Create the file version string for the first (i.e. the only one) language.
964 StringCchPrintf(SubBlock,
965 sizeof(SubBlock)/sizeof(SubBlock[0]),
966 TEXT("\\StringFileInfo\\%04x%04x\\FileVersion"),
967 (*lpTranslate).wLanguage,
968 (*lpTranslate).wCodePage);
970 // Retrieve the file version string for the language.
971 if(!VerQueryValue(lpstrVffInfo, SubBlock, &lpBuffer, &dwBytes))
973 TRACE_PRINT("PacketGetFileVersion: failed to call VerQueryValue");
974 GlobalFreePtr(lpstrVffInfo);
975 TRACE_EXIT("PacketGetFileVersion");
976 return FALSE;
979 // Convert to ASCII
980 TmpStr = WChar2SChar(lpBuffer);
982 if(strlen(TmpStr) >= VersionBuffLen)
984 TRACE_PRINT("PacketGetFileVersion: Input buffer too small");
985 GlobalFreePtr(lpstrVffInfo);
986 GlobalFreePtr(TmpStr);
987 TRACE_EXIT("PacketGetFileVersion");
988 return FALSE;
991 StringCchCopyA(VersionBuff, VersionBuffLen, TmpStr);
993 GlobalFreePtr(lpstrVffInfo);
994 GlobalFreePtr(TmpStr);
997 else
999 TRACE_PRINT1("PacketGetFileVersion: failed to call GetFileVersionInfoSize, LastError = %8.8x", GetLastError());
1000 TRACE_EXIT("PacketGetFileVersion");
1001 return FALSE;
1005 TRACE_EXIT("PacketGetFileVersion");
1006 return TRUE;
1009 /*!
1010 \brief Opens an adapter using the NPF device driver.
1011 \param AdapterName A string containing the name of the device to open.
1012 \return If the function succeeds, the return value is the pointer to a properly initialized ADAPTER object,
1013 otherwise the return value is NULL.
1015 \note internal function used by PacketOpenAdapter() and AddAdapter()
1017 LPADAPTER PacketOpenAdapterNPF(PCHAR AdapterNameA)
1019 LPADAPTER lpAdapter;
1020 BOOL Result;
1021 DWORD error;
1022 SC_HANDLE svcHandle = NULL;
1023 SC_HANDLE scmHandle = NULL;
1024 LONG KeyRes;
1025 HKEY PathKey;
1026 SERVICE_STATUS SStat;
1027 BOOL QuerySStat;
1028 CHAR SymbolicLinkA[MAX_PATH];
1030 // Old registry based WinPcap names
1032 // CHAR NpfDriverName[MAX_WINPCAP_KEY_CHARS];
1033 // UINT RegQueryLen;
1035 CHAR NpfDriverName[MAX_WINPCAP_KEY_CHARS] = NPF_DRIVER_NAME;
1036 CHAR NpfServiceLocation[MAX_WINPCAP_KEY_CHARS];
1038 // Create the NPF device name from the original device name
1039 TRACE_ENTER("PacketOpenAdapterNPF");
1041 TRACE_PRINT1("Trying to open adapter %s", AdapterNameA);
1043 scmHandle = OpenSCManager(NULL, NULL, GENERIC_READ);
1045 if(scmHandle == NULL)
1047 error = GetLastError();
1048 TRACE_PRINT1("OpenSCManager failed! LastError=%8.8x", error);
1050 else
1053 // Old registry based WinPcap names
1055 // RegQueryLen = sizeof(NpfDriverName)/sizeof(NpfDriverName[0]);
1056 // if (QueryWinPcapRegistryStringA(NPF_DRIVER_NAME_REG_KEY, NpfDriverName, &RegQueryLen, NPF_DRIVER_NAME) == FALSE && RegQueryLen == 0)
1057 // {
1058 // //just use an empty string string for the service name
1059 // NpfDriverName[0] = '\0';
1060 // }
1063 // Create the name of the registry key containing the service.
1065 StringCchPrintfA(NpfServiceLocation, sizeof(NpfServiceLocation), "SYSTEM\\CurrentControlSet\\Services\\%s", NpfDriverName);
1067 // check if the NPF registry key is already present
1068 // this means that the driver is already installed and that we don't need to call PacketInstallDriver
1069 KeyRes=RegOpenKeyExA(HKEY_LOCAL_MACHINE,
1070 NpfServiceLocation,
1072 KEY_READ,
1073 &PathKey);
1075 if(KeyRes != ERROR_SUCCESS)
1077 TRACE_PRINT("NPF registry key not present, trying to install the driver.");
1078 Result = PacketInstallDriver();
1080 else
1082 TRACE_PRINT("NPF registry key present, driver is installed.");
1083 Result = TRUE;
1084 RegCloseKey(PathKey);
1087 if (Result)
1089 TRACE_PRINT("Trying to see if the NPF service is running...");
1090 svcHandle = OpenServiceA(scmHandle, NpfDriverName, SERVICE_START | SERVICE_QUERY_STATUS );
1092 if (svcHandle != NULL)
1094 QuerySStat = QueryServiceStatus(svcHandle, &SStat);
1096 #ifdef _DBG
1097 switch (SStat.dwCurrentState)
1099 case SERVICE_CONTINUE_PENDING:
1100 TRACE_PRINT("The status of the driver is: SERVICE_CONTINUE_PENDING");
1101 break;
1102 case SERVICE_PAUSE_PENDING:
1103 TRACE_PRINT("The status of the driver is: SERVICE_PAUSE_PENDING");
1104 break;
1105 case SERVICE_PAUSED:
1106 TRACE_PRINT("The status of the driver is: SERVICE_PAUSED");
1107 break;
1108 case SERVICE_RUNNING:
1109 TRACE_PRINT("The status of the driver is: SERVICE_RUNNING");
1110 break;
1111 case SERVICE_START_PENDING:
1112 TRACE_PRINT("The status of the driver is: SERVICE_START_PENDING");
1113 break;
1114 case SERVICE_STOP_PENDING:
1115 TRACE_PRINT("The status of the driver is: SERVICE_STOP_PENDING");
1116 break;
1117 case SERVICE_STOPPED:
1118 TRACE_PRINT("The status of the driver is: SERVICE_STOPPED");
1119 break;
1121 default:
1122 TRACE_PRINT("The status of the driver is: unknown");
1123 break;
1125 #endif
1127 if(!QuerySStat || SStat.dwCurrentState != SERVICE_RUNNING)
1129 TRACE_PRINT("Driver NPF not running. Calling startservice");
1130 if (StartService(svcHandle, 0, NULL)==0)
1132 error = GetLastError();
1133 if(error!=ERROR_SERVICE_ALREADY_RUNNING && error!=ERROR_ALREADY_EXISTS)
1135 SetLastError(error);
1136 if (scmHandle != NULL)
1137 CloseServiceHandle(scmHandle);
1138 error = GetLastError();
1139 TRACE_PRINT1("PacketOpenAdapterNPF: StartService failed, LastError=%8.8x",error);
1140 TRACE_EXIT("PacketOpenAdapterNPF");
1141 SetLastError(error);
1142 return NULL;
1147 CloseServiceHandle( svcHandle );
1148 svcHandle = NULL;
1151 else
1153 error = GetLastError();
1154 TRACE_PRINT1("OpenService failed! Error=%8.8x", error);
1155 SetLastError(error);
1158 else
1160 if(KeyRes != ERROR_SUCCESS)
1161 Result = PacketInstallDriver();
1162 else
1163 Result = TRUE;
1165 if (Result) {
1167 svcHandle = OpenServiceA(scmHandle,
1168 NpfDriverName,
1169 SERVICE_START);
1170 if (svcHandle != NULL)
1173 QuerySStat = QueryServiceStatus(svcHandle, &SStat);
1175 #ifdef _DBG
1176 switch (SStat.dwCurrentState)
1178 case SERVICE_CONTINUE_PENDING:
1179 TRACE_PRINT("The status of the driver is: SERVICE_CONTINUE_PENDING");
1180 break;
1181 case SERVICE_PAUSE_PENDING:
1182 TRACE_PRINT("The status of the driver is: SERVICE_PAUSE_PENDING");
1183 break;
1184 case SERVICE_PAUSED:
1185 TRACE_PRINT("The status of the driver is: SERVICE_PAUSED");
1186 break;
1187 case SERVICE_RUNNING:
1188 TRACE_PRINT("The status of the driver is: SERVICE_RUNNING");
1189 break;
1190 case SERVICE_START_PENDING:
1191 TRACE_PRINT("The status of the driver is: SERVICE_START_PENDING");
1192 break;
1193 case SERVICE_STOP_PENDING:
1194 TRACE_PRINT("The status of the driver is: SERVICE_STOP_PENDING");
1195 break;
1196 case SERVICE_STOPPED:
1197 TRACE_PRINT("The status of the driver is: SERVICE_STOPPED");
1198 break;
1200 default:
1201 TRACE_PRINT("The status of the driver is: unknown");
1202 break;
1204 #endif
1206 if(!QuerySStat || SStat.dwCurrentState != SERVICE_RUNNING){
1208 TRACE_PRINT("Calling startservice");
1210 if (StartService(svcHandle, 0, NULL)==0){
1211 error = GetLastError();
1212 if(error!=ERROR_SERVICE_ALREADY_RUNNING && error!=ERROR_ALREADY_EXISTS)
1214 if (scmHandle != NULL) CloseServiceHandle(scmHandle);
1215 TRACE_PRINT1("PacketOpenAdapterNPF: StartService failed, LastError=%8.8x",error);
1216 TRACE_EXIT("PacketOpenAdapterNPF");
1217 SetLastError(error);
1218 return NULL;
1223 CloseServiceHandle( svcHandle );
1224 svcHandle = NULL;
1227 else{
1228 error = GetLastError();
1229 TRACE_PRINT1("OpenService failed! LastError=%8.8x", error);
1230 SetLastError(error);
1236 if (scmHandle != NULL) CloseServiceHandle(scmHandle);
1238 lpAdapter=(LPADAPTER)GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(ADAPTER));
1239 if (lpAdapter==NULL)
1241 TRACE_PRINT("PacketOpenAdapterNPF: GlobalAlloc Failed to allocate the ADAPTER structure");
1242 error=GetLastError();
1243 //set the error to the one on which we failed
1244 TRACE_EXIT("PacketOpenAdapterNPF");
1245 SetLastError(error);
1246 return NULL;
1249 lpAdapter->NumWrites=1;
1251 #define DEVICE_PREFIX "\\Device\\"
1253 if (LOWORD(GetVersion()) == 4)
1255 if (strlen(AdapterNameA) > strlen(DEVICE_PREFIX))
1257 StringCchPrintfA(SymbolicLinkA, MAX_PATH, "\\\\.\\%s", AdapterNameA + strlen(DEVICE_PREFIX));
1259 else
1261 ZeroMemory(SymbolicLinkA, sizeof(SymbolicLinkA));
1264 else
1266 if (strlen(AdapterNameA) > strlen(DEVICE_PREFIX))
1268 StringCchPrintfA(SymbolicLinkA, MAX_PATH, "\\\\.\\Global\\%s", AdapterNameA + strlen(DEVICE_PREFIX));
1270 else
1272 ZeroMemory(SymbolicLinkA, sizeof(SymbolicLinkA));
1277 // NOTE GV 20061114 This is a sort of breaking change. In the past we were putting what
1278 // we could fit inside this variable. Now we simply put NOTHING. It's just useless
1280 ZeroMemory(lpAdapter->SymbolicLink, sizeof(lpAdapter->SymbolicLink));
1282 //try if it is possible to open the adapter immediately
1283 lpAdapter->hFile=CreateFileA(SymbolicLinkA,GENERIC_WRITE | GENERIC_READ,
1284 0,NULL,OPEN_EXISTING,0,0);
1286 if (lpAdapter->hFile != INVALID_HANDLE_VALUE)
1289 if(PacketSetReadEvt(lpAdapter)==FALSE){
1290 error=GetLastError();
1291 TRACE_PRINT("PacketOpenAdapterNPF: Unable to open the read event");
1292 CloseHandle(lpAdapter->hFile);
1293 GlobalFreePtr(lpAdapter);
1294 //set the error to the one on which we failed
1296 TRACE_PRINT1("PacketOpenAdapterNPF: PacketSetReadEvt failed, LastError=%8.8x",error);
1297 TRACE_EXIT("PacketOpenAdapterNPF");
1300 SetLastError(error);
1301 return NULL;
1304 PacketSetMaxLookaheadsize(lpAdapter);
1307 // Indicate that this is a device managed by NPF.sys
1309 lpAdapter->Flags = INFO_FLAG_NDIS_ADAPTER;
1312 StringCchCopyA(lpAdapter->Name, ADAPTER_NAME_LENGTH, AdapterNameA);
1314 TRACE_PRINT("Successfully opened adapter");
1315 TRACE_EXIT("PacketOpenAdapterNPF");
1316 return lpAdapter;
1319 error=GetLastError();
1320 GlobalFreePtr(lpAdapter);
1321 //set the error to the one on which we failed
1322 TRACE_PRINT1("PacketOpenAdapterNPF: CreateFile failed, LastError= %8.8x",error);
1323 TRACE_EXIT("PacketOpenAdapterNPF");
1324 SetLastError(error);
1325 return NULL;
1328 #ifdef HAVE_WANPACKET_API
1329 static LPADAPTER PacketOpenAdapterWanPacket(PCHAR AdapterName)
1331 LPADAPTER lpAdapter = NULL;
1332 DWORD dwLastError = ERROR_SUCCESS;
1334 TRACE_ENTER("PacketOpenAdapterWanPacket");
1336 TRACE_PRINT("Opening a NDISWAN adapter...");
1341 // This is a wan adapter. Open it using the netmon API
1343 lpAdapter = (LPADAPTER) GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT,
1344 sizeof(ADAPTER));
1346 if (lpAdapter == NULL)
1348 TRACE_PRINT("GlobalAlloc failed allocating memory for the ADAPTER structure. Failing (BAD_UNIT).");
1349 dwLastError = ERROR_NOT_ENOUGH_MEMORY;
1350 break;
1353 lpAdapter->Flags = INFO_FLAG_NDISWAN_ADAPTER;
1355 TRACE_PRINT("Trying to open the Wan Adapter through WanPacket.dll...");
1357 // Open the adapter
1358 lpAdapter->pWanAdapter = WanPacketOpenAdapter();
1360 if (lpAdapter->pWanAdapter == NULL)
1362 TRACE_PRINT("WanPacketOpenAdapter failed. Failing. (BAD_UNIT)");
1363 dwLastError = ERROR_BAD_UNIT;
1364 break;
1367 StringCchCopyA(lpAdapter->Name, ADAPTER_NAME_LENGTH, AdapterName);
1369 lpAdapter->ReadEvent = WanPacketGetReadEvent(lpAdapter->pWanAdapter);
1371 TRACE_PRINT("Successfully opened the Wan Adapter.");
1373 }while(FALSE);
1375 if (dwLastError == ERROR_SUCCESS)
1377 TRACE_EXIT("PacketOpenAdapterWanPacket");
1378 return lpAdapter;
1380 else
1382 if (lpAdapter != NULL) GlobalFree(lpAdapter);
1384 TRACE_EXIT("PacketOpenAdapterWanPacket");
1385 SetLastError(dwLastError);
1386 return NULL;
1389 #endif //HAVE_WANPACKET_API
1391 /*!
1392 \brief Opens an adapter using the aircap dll.
1393 \param AdapterName A string containing the name of the device to open.
1394 \return If the function succeeds, the return value is the pointer to a properly initialized ADAPTER object,
1395 otherwise the return value is NULL.
1397 \note internal function used by PacketOpenAdapter()
1399 #ifdef HAVE_AIRPCAP_API
1400 static LPADAPTER PacketOpenAdapterAirpcap(PCHAR AdapterName)
1402 CHAR Ebuf[AIRPCAP_ERRBUF_SIZE];
1403 LPADAPTER lpAdapter;
1406 // Make sure that the airpcap API has been linked
1408 if(!g_PAirpcapOpen)
1410 return NULL;
1413 lpAdapter = (LPADAPTER) GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT,
1414 sizeof(ADAPTER));
1415 if (lpAdapter == NULL)
1417 return NULL;
1421 // Indicate that this is a aircap card
1423 lpAdapter->Flags = INFO_FLAG_AIRPCAP_CARD;
1426 // Open the adapter
1428 lpAdapter->AirpcapAd = g_PAirpcapOpen(AdapterName, Ebuf);
1430 if(lpAdapter->AirpcapAd == NULL)
1432 GlobalFreePtr(lpAdapter);
1433 return NULL;
1436 StringCchCopyA(lpAdapter->Name, ADAPTER_NAME_LENGTH, AdapterName);
1438 return lpAdapter;
1440 #endif // HAVE_AIRPCAP_API
1443 #ifdef HAVE_NPFIM_API
1444 static LPADAPTER PacketOpenAdapterNpfIm(PCHAR AdapterName)
1446 LPADAPTER lpAdapter;
1448 lpAdapter = (LPADAPTER) GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT,
1449 sizeof(ADAPTER));
1450 if (lpAdapter == NULL)
1452 return NULL;
1456 // Indicate that this is a aircap card
1458 lpAdapter->Flags = INFO_FLAG_NPFIM_DEVICE;
1461 // Open the adapter
1464 if (g_NpfImHandlers.NpfImOpenDevice(AdapterName, (NPF_IM_DEV_HANDLE*)&lpAdapter->NpfImHandle) == FALSE)
1466 GlobalFreePtr(lpAdapter);
1467 return NULL;
1470 StringCchCopyA(lpAdapter->Name, ADAPTER_NAME_LENGTH, AdapterName);
1472 return lpAdapter;
1474 #endif // HAVE_NpfIm_API
1477 /*!
1478 \brief Opens an adapter using the DAG capture API.
1479 \param AdapterName A string containing the name of the device to open.
1480 \return If the function succeeds, the return value is the pointer to a properly initialized ADAPTER object,
1481 otherwise the return value is NULL.
1483 \note internal function used by PacketOpenAdapter()
1485 #ifdef HAVE_DAG_API
1486 static LPADAPTER PacketOpenAdapterDAG(PCHAR AdapterName, BOOLEAN IsAFile)
1488 CHAR DagEbuf[DAGC_ERRBUF_SIZE];
1489 LPADAPTER lpAdapter;
1490 LONG status;
1491 HKEY dagkey;
1492 DWORD lptype;
1493 DWORD fpc;
1494 DWORD lpcbdata = sizeof(fpc);
1495 WCHAR keyname[512];
1496 PWCHAR tsn;
1498 TRACE_ENTER("PacketOpenAdapterDAG");
1501 lpAdapter = (LPADAPTER) GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT,
1502 sizeof(ADAPTER));
1503 if (lpAdapter == NULL)
1505 TRACE_PRINT("GlobalAlloc failed allocating memory for the ADAPTER structure");
1506 TRACE_EXIT("PacketOpenAdapterDAG");
1507 return NULL;
1510 if(IsAFile)
1512 // We must add an entry to the adapter description list, otherwise many function will not
1513 // be able to work
1514 if(!PacketAddAdapterDag(AdapterName, "DAG file", IsAFile))
1516 TRACE_PRINT("Failed adding the Dag file to the list of adapters");
1517 TRACE_EXIT("PacketOpenAdapterDAG");
1518 GlobalFreePtr(lpAdapter);
1519 return NULL;
1522 // Flag that this is a DAG file
1523 lpAdapter->Flags = INFO_FLAG_DAG_FILE;
1525 else
1527 // Flag that this is a DAG card
1528 lpAdapter->Flags = INFO_FLAG_DAG_CARD;
1532 // See if the user is asking for fast capture with this device
1535 lpAdapter->DagFastProcess = FALSE;
1537 tsn = (strstr(strlwr((char*)AdapterName), "dag") != NULL)?
1538 SChar2WChar(strstr(strlwr((char*)AdapterName), "dag")):
1539 L"";
1541 StringCchPrintfW(keyname, sizeof(keyname)/sizeof(keyname[0]), L"%s\\CardParams\\%ws",
1542 L"SYSTEM\\CurrentControlSet\\Services\\DAG",
1543 tsn);
1545 GlobalFreePtr(tsn);
1549 status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyname, 0 , KEY_READ, &dagkey);
1550 if(status != ERROR_SUCCESS)
1551 break;
1553 status = RegQueryValueEx(dagkey,
1554 L"FastCap",
1555 NULL,
1556 &lptype,
1557 (LPBYTE)&fpc,
1558 &lpcbdata);
1560 if(status == ERROR_SUCCESS)
1561 lpAdapter->DagFastProcess = fpc;
1563 RegCloseKey(dagkey);
1565 while(FALSE);
1568 TRACE_PRINT("Trying to open the DAG device...");
1570 // Open the card
1572 lpAdapter->pDagCard = g_p_dagc_open(AdapterName,
1574 DagEbuf);
1576 if(lpAdapter->pDagCard == NULL)
1578 TRACE_PRINT("Failed opening the DAG device");
1579 TRACE_EXIT("PacketOpenAdapterDAG");
1580 GlobalFreePtr(lpAdapter);
1581 return NULL;
1584 lpAdapter->DagFcsLen = g_p_dagc_getfcslen(lpAdapter->pDagCard);
1586 StringCchCopyA(lpAdapter->Name, ADAPTER_NAME_LENGTH, AdapterName);
1588 // XXX we could create the read event here
1589 TRACE_PRINT("Successfully opened the DAG device");
1590 TRACE_EXIT("PacketOpenAdapterDAG");
1592 return lpAdapter;
1594 #endif // HAVE_DAG_API
1597 //---------------------------------------------------------------------------
1598 // PUBLIC API
1599 //---------------------------------------------------------------------------
1601 /** @ingroup packetapi
1602 * @{
1605 /** @defgroup packet32 Packet.dll exported functions and variables
1606 * @{
1609 /*!
1610 \brief Return a string with the dll version.
1611 \return A char pointer to the version of the library.
1613 PCHAR PacketGetVersion()
1615 TRACE_ENTER("PacketGetVersion");
1616 TRACE_EXIT("PacketGetVersion");
1617 return PacketLibraryVersion;
1620 /*!
1621 \brief Return a string with the version of the NPF.sys device driver.
1622 \return A char pointer to the version of the driver.
1624 PCHAR PacketGetDriverVersion()
1626 TRACE_ENTER("PacketGetDriverVersion");
1627 TRACE_EXIT("PacketGetDriverVersion");
1628 return PacketDriverVersion;
1631 /*!
1632 \brief Stops and unloads the WinPcap device driver.
1633 \return If the function succeeds, the return value is nonzero, otherwise it is zero.
1635 This function can be used to unload the driver from memory when the application no more needs it.
1636 Note that the driver is physically stopped and unloaded only when all the files on its devices
1637 are closed, i.e. when all the applications that use WinPcap close all their adapters.
1639 BOOL PacketStopDriver()
1641 SC_HANDLE scmHandle;
1642 SC_HANDLE schService;
1643 BOOL ret;
1644 SERVICE_STATUS serviceStatus;
1645 CHAR NpfDriverName[MAX_WINPCAP_KEY_CHARS] = NPF_DRIVER_NAME;
1648 // Old registry based WinPcap names
1650 // CHAR NpfDriverName[MAX_WINPCAP_KEY_CHARS];
1651 // UINT RegQueryLen;
1653 TRACE_ENTER("PacketStopDriver");
1655 ret = FALSE;
1658 // Old registry based WinPcap names
1660 // // Create the NPF device name from the original device name
1661 // RegQueryLen = sizeof(NpfDriverName)/sizeof(NpfDriverName[0]);
1663 // if (QueryWinPcapRegistryStringA(NPF_DRIVER_NAME_REG_KEY, NpfDriverName, &RegQueryLen, NPF_DRIVER_NAME) == FALSE && RegQueryLen == 0)
1664 // return FALSE;
1666 scmHandle = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
1668 if(scmHandle != NULL){
1670 TRACE_PRINT("Opened the SCM");
1672 schService = OpenServiceA (scmHandle,
1673 NpfDriverName,
1674 SERVICE_ALL_ACCESS
1677 if (schService != NULL)
1679 TRACE_PRINT("Opened the NPF service in the SCM");
1681 ret = ControlService (schService,
1682 SERVICE_CONTROL_STOP,
1683 &serviceStatus
1685 if (!ret)
1687 TRACE_PRINT("Failed to stop the NPF service");
1689 else
1691 TRACE_PRINT("NPF service stopped");
1694 CloseServiceHandle (schService);
1696 CloseServiceHandle(scmHandle);
1701 TRACE_EXIT("PacketStopDriver");
1702 return ret;
1705 /*!
1706 \brief Opens an adapter.
1707 \param AdapterName A string containing the name of the device to open.
1708 Use the PacketGetAdapterNames() function to retrieve the list of available devices.
1709 \return If the function succeeds, the return value is the pointer to a properly initialized ADAPTER object,
1710 otherwise the return value is NULL.
1712 LPADAPTER PacketOpenAdapter(PCHAR AdapterNameWA)
1714 LPADAPTER lpAdapter = NULL;
1715 PCHAR AdapterNameA = NULL;
1716 BOOL bFreeAdapterNameA;
1717 #ifndef _WINNT4
1718 PADAPTER_INFO TAdInfo;
1719 #endif //_WINNT4
1721 DWORD dwLastError = ERROR_SUCCESS;
1723 TRACE_ENTER("PacketOpenAdapter");
1725 TRACE_PRINT_OS_INFO();
1727 TRACE_PRINT2("Packet DLL version %s, Driver version %s", PacketLibraryVersion, PacketDriverVersion);
1730 // Check the presence on some libraries we rely on, and load them if we found them
1732 PacketLoadLibrariesDynamically();
1735 // Ugly heuristic to detect if the adapter is ASCII
1737 if(AdapterNameWA[1]!=0)
1740 // ASCII
1742 bFreeAdapterNameA = FALSE;
1743 AdapterNameA = AdapterNameWA;
1745 else
1748 // Unicode
1750 size_t bufferSize = wcslen((PWCHAR)AdapterNameWA) + 1;
1752 AdapterNameA = GlobalAllocPtr(GPTR, bufferSize);
1754 if (AdapterNameA == NULL)
1756 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1757 return NULL;
1760 StringCchPrintfA(AdapterNameA, bufferSize, "%ws", (PWCHAR)AdapterNameWA);
1761 bFreeAdapterNameA = TRUE;
1764 #ifndef _WINNT4
1765 WaitForSingleObject(g_AdaptersInfoMutex, INFINITE);
1766 #endif // not WINNT4
1771 #ifndef _WINNT4
1773 // Windows NT4 does not have support for the various nifty
1774 // adapters supported from 2000 on (airpcap, ndiswan, npfim...)
1775 // so we just skip all the magic of the global adapter list,
1776 // and try to open the adapter with PacketOpenAdapterNPF at
1777 // the end of this big function!
1781 // If we are here it's because we need to update the list
1785 TRACE_PRINT("Looking for the adapter in our list 1st time...");
1787 // Find the PADAPTER_INFO structure associated with this adapter
1788 TAdInfo = PacketFindAdInfo(AdapterNameA);
1789 if(TAdInfo == NULL)
1791 TRACE_PRINT("Adapter not found in our list. Try to refresh the list.");
1793 PacketUpdateAdInfo(AdapterNameA);
1794 TAdInfo = PacketFindAdInfo(AdapterNameA);
1796 TRACE_PRINT("Looking for the adapter in our list 2nd time...");
1799 if(TAdInfo == NULL)
1801 #ifdef HAVE_DAG_API
1802 TRACE_PRINT("Adapter not found in our list. Try to open it as a DAG/ERF file...");
1804 //can be an ERF file?
1805 lpAdapter = PacketOpenAdapterDAG(AdapterNameA, TRUE);
1806 #endif // HAVE_DAG_API
1808 if (lpAdapter == NULL)
1810 TRACE_PRINT("Failed to open it as a DAG/ERF file, failing with ERROR_BAD_UNIT");
1811 dwLastError = ERROR_BAD_UNIT; //this is the best we can do....
1813 else
1815 TRACE_PRINT("Opened the adapter as a DAG/ERF file.");
1818 break;
1821 TRACE_PRINT("Adapter found in our list. Check adapter type and see if it's actually supported.");
1823 #ifdef HAVE_WANPACKET_API
1824 if(TAdInfo->Flags == INFO_FLAG_NDISWAN_ADAPTER)
1826 lpAdapter = PacketOpenAdapterWanPacket(AdapterNameA);
1828 if (lpAdapter == NULL)
1830 dwLastError = GetLastError();
1833 break;
1835 #endif //HAVE_WANPACKET_API
1837 #ifdef HAVE_AIRPCAP_API
1838 if(TAdInfo->Flags == INFO_FLAG_AIRPCAP_CARD)
1841 // This is an airpcap card. Open it using the airpcap api
1843 lpAdapter = PacketOpenAdapterAirpcap(AdapterNameA);
1845 if(lpAdapter == NULL)
1847 dwLastError = ERROR_BAD_UNIT;
1848 break;
1852 // Airpcap provides a read event
1854 if(!g_PAirpcapGetReadEvent(lpAdapter->AirpcapAd, &lpAdapter->ReadEvent))
1856 PacketCloseAdapter(lpAdapter);
1857 dwLastError = ERROR_BAD_UNIT;
1859 else
1861 dwLastError = ERROR_SUCCESS;
1864 break;
1866 #endif // HAVE_AIRPCAP_API
1868 #ifdef HAVE_NPFIM_API
1869 if(TAdInfo->Flags == INFO_FLAG_NPFIM_DEVICE)
1872 // This is an airpcap card. Open it using the airpcap api
1874 lpAdapter = PacketOpenAdapterNpfIm(AdapterNameA);
1876 if(lpAdapter == NULL)
1878 dwLastError = ERROR_BAD_UNIT;
1879 break;
1883 // NpfIm provides a read event
1885 if(!g_NpfImHandlers.NpfImGetCaptureReadEvent((NPF_IM_DEV_HANDLE)lpAdapter->NpfImHandle, &lpAdapter->ReadEvent))
1887 dwLastError = GetLastError();
1888 PacketCloseAdapter(lpAdapter);
1890 else
1892 dwLastError = ERROR_SUCCESS;
1895 break;
1897 #endif // HAVE_NPFIM_API
1899 #ifdef HAVE_DAG_API
1900 if(TAdInfo->Flags == INFO_FLAG_DAG_CARD)
1902 TRACE_PRINT("Opening a DAG adapter...");
1904 // This is a Dag card. Open it using the dagc API
1906 lpAdapter = PacketOpenAdapterDAG(AdapterNameA, FALSE);
1907 if (lpAdapter == NULL)
1909 TRACE_PRINT("Failed opening the DAG adapter with PacketOpenAdapterDAG. Failing. (BAD_UNIT)");
1910 dwLastError = ERROR_BAD_UNIT;
1912 else
1914 dwLastError = ERROR_SUCCESS;
1917 break;
1919 #endif // HAVE_DAG_API
1921 if(TAdInfo->Flags == INFO_FLAG_DONT_EXPORT)
1924 // The adapter is flagged as not exported, probably because it's broken
1925 // or incompatible with WinPcap. We end here with an error.
1927 TRACE_PRINT1("Trying to open the adapter %s which is flagged as not exported. Failing (BAD_UNIT)", AdapterNameA);
1928 dwLastError = ERROR_BAD_UNIT;
1930 break;
1933 if (TAdInfo->Flags != INFO_FLAG_NDIS_ADAPTER)
1935 TRACE_PRINT1("Trying to open the adapter with an unknown flag type %u", TAdInfo->Flags);
1936 dwLastError = ERROR_BAD_UNIT;
1938 break;
1941 #endif // not _WINNT4
1944 // This is the only code executed on NT4
1946 // Windows NT4 does not have support for the various nifty
1947 // adapters supported from 2000 on (airpcap, ndiswan, npfim...)
1948 // so we just skip all the magic of the global adapter list,
1949 // and try to open the adapter with PacketOpenAdapterNPF at
1950 // the end of this big function!
1952 TRACE_PRINT("Normal NPF adapter, trying to open it...");
1953 lpAdapter = PacketOpenAdapterNPF(AdapterNameA);
1954 if (lpAdapter == NULL)
1956 dwLastError = GetLastError();
1959 }while(FALSE);
1961 #ifndef _WINNT4
1962 ReleaseMutex(g_AdaptersInfoMutex);
1963 #endif
1965 if (bFreeAdapterNameA) GlobalFree(AdapterNameA);
1968 if (dwLastError != ERROR_SUCCESS)
1970 TRACE_EXIT("PacketOpenAdapter");
1971 SetLastError(dwLastError);
1973 return NULL;
1975 else
1977 TRACE_EXIT("PacketOpenAdapter");
1979 return lpAdapter;
1984 /*!
1985 \brief Closes an adapter.
1986 \param lpAdapter the pointer to the adapter to close.
1988 PacketCloseAdapter closes the given adapter and frees the associated ADAPTER structure
1990 VOID PacketCloseAdapter(LPADAPTER lpAdapter)
1992 TRACE_ENTER("PacketCloseAdapter");
1993 if(!lpAdapter)
1995 TRACE_PRINT("PacketCloseAdapter: attempt to close a NULL adapter");
1996 TRACE_EXIT("PacketCloseAdapter");
1997 return;
2000 #ifdef HAVE_WANPACKET_API
2001 if (lpAdapter->Flags == INFO_FLAG_NDISWAN_ADAPTER)
2003 TRACE_PRINT("Closing a WAN adapter through WanPacket...");
2004 WanPacketCloseAdapter(lpAdapter->pWanAdapter);
2005 GlobalFreePtr(lpAdapter);
2006 return;
2008 #endif
2010 #ifdef HAVE_AIRPCAP_API
2011 if(lpAdapter->Flags == INFO_FLAG_AIRPCAP_CARD)
2013 g_PAirpcapClose(lpAdapter->AirpcapAd);
2014 GlobalFreePtr(lpAdapter);
2015 return;
2017 #endif // HAVE_AIRPCAP_API
2019 #ifdef HAVE_NPFIM_API
2020 if(lpAdapter->Flags == INFO_FLAG_NPFIM_DEVICE)
2022 g_NpfImHandlers.NpfImCloseDevice(lpAdapter->NpfImHandle);
2023 GlobalFreePtr(lpAdapter);
2024 return;
2026 #endif
2028 #ifdef HAVE_DAG_API
2029 if(lpAdapter->Flags & INFO_FLAG_DAG_FILE || lpAdapter->Flags & INFO_FLAG_DAG_CARD)
2031 TRACE_PRINT("Closing a DAG file...");
2032 if(lpAdapter->Flags & INFO_FLAG_DAG_FILE & ~INFO_FLAG_DAG_CARD)
2034 // This is a file. We must remove the entry in the adapter description list
2035 PacketUpdateAdInfo(lpAdapter->Name);
2037 g_p_dagc_close(lpAdapter->pDagCard);
2038 GlobalFreePtr(lpAdapter);
2039 return;
2041 #endif // HAVE_DAG_API
2043 if (lpAdapter->Flags != INFO_FLAG_NDIS_ADAPTER)
2045 TRACE_PRINT1("Trying to close an unknown adapter type (%u)", lpAdapter->Flags);
2047 else
2049 SetEvent(lpAdapter->ReadEvent);
2050 CloseHandle(lpAdapter->ReadEvent);
2051 CloseHandle(lpAdapter->hFile);
2052 GlobalFreePtr(lpAdapter);
2053 TRACE_EXIT("PacketCloseAdapter");
2058 /*!
2059 \brief Allocates a _PACKET structure.
2060 \return On succeess, the return value is the pointer to a _PACKET structure otherwise the
2061 return value is NULL.
2063 The structure returned will be passed to the PacketReceivePacket() function to receive the
2064 packets from the driver.
2066 \warning The Buffer field of the _PACKET structure is not set by this function.
2067 The buffer \b must be allocated by the application, and associated to the PACKET structure
2068 with a call to PacketInitPacket.
2070 LPPACKET PacketAllocatePacket(void)
2072 LPPACKET lpPacket;
2074 TRACE_ENTER("PacketAllocatePacket");
2076 lpPacket=(LPPACKET)GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT,sizeof(PACKET));
2077 if (lpPacket==NULL)
2079 TRACE_PRINT("PacketAllocatePacket: GlobalAlloc Failed");
2082 TRACE_EXIT("PacketAllocatePacket");
2084 return lpPacket;
2087 /*!
2088 \brief Frees a _PACKET structure.
2089 \param lpPacket The structure to free.
2091 \warning the user-allocated buffer associated with the _PACKET structure is not deallocated
2092 by this function and \b must be explicitly deallocated by the programmer.
2095 VOID PacketFreePacket(LPPACKET lpPacket)
2098 TRACE_ENTER("PacketFreePacket");
2099 GlobalFreePtr(lpPacket);
2100 TRACE_EXIT("PacketFreePacket");
2103 /*!
2104 \brief Initializes a _PACKET structure.
2105 \param lpPacket The structure to initialize.
2106 \param Buffer A pointer to a user-allocated buffer that will contain the captured data.
2107 \param Length the length of the buffer. This is the maximum buffer size that will be
2108 transferred from the driver to the application using a single read.
2110 \note the size of the buffer associated with the PACKET structure is a parameter that can sensibly
2111 influence the performance of the capture process, since this buffer will contain the packets received
2112 from the the driver. The driver is able to return several packets using a single read call
2113 (see the PacketReceivePacket() function for details), and the number of packets transferable to the
2114 application in a call is limited only by the size of the buffer associated with the PACKET structure
2115 passed to PacketReceivePacket(). Therefore setting a big buffer with PacketInitPacket can noticeably
2116 decrease the number of system calls, reducing the impcat of the capture process on the processor.
2119 VOID PacketInitPacket(LPPACKET lpPacket,PVOID Buffer,UINT Length)
2122 TRACE_ENTER("PacketInitPacket");
2124 lpPacket->Buffer = Buffer;
2125 lpPacket->Length = Length;
2126 lpPacket->ulBytesReceived = 0;
2127 lpPacket->bIoComplete = FALSE;
2129 TRACE_EXIT("PacketInitPacket");
2132 /*!
2133 \brief Read data (packets or statistics) from the NPF driver.
2134 \param AdapterObject Pointer to an _ADAPTER structure identifying the network adapter from which
2135 the data is received.
2136 \param lpPacket Pointer to a PACKET structure that will contain the data.
2137 \param Sync This parameter is deprecated and will be ignored. It is present for compatibility with
2138 older applications.
2139 \return If the function succeeds, the return value is nonzero.
2141 The data received with this function can be a group of packets or a static on the network traffic,
2142 depending on the working mode of the driver. The working mode can be set with the PacketSetMode()
2143 function. Give a look at that function if you are interested in the format used to return statistics
2144 values, here only the normal capture mode will be described.
2146 The number of packets received with this function is variable. It depends on the number of packets
2147 currently stored in the driver’s buffer, on the size of these packets and on the size of the buffer
2148 associated to the lpPacket parameter. The following figure shows the format used by the driver to pass
2149 packets to the application.
2151 \image html encoding.gif "method used to encode the packets"
2153 Packets are stored in the buffer associated with the lpPacket _PACKET structure. The Length field of
2154 that structure is updated with the amount of data copied in the buffer. Each packet has a header
2155 consisting in a bpf_hdr structure that defines its length and contains its timestamp. A padding field
2156 is used to word-align the data in the buffer (to speed up the access to the packets). The bh_datalen
2157 and bh_hdrlen fields of the bpf_hdr structures should be used to extract the packets from the buffer.
2159 Examples can be seen either in the TestApp sample application (see the \ref packetsamps page) provided
2160 in the developer's pack, or in the pcap_read() function of wpcap.
2162 BOOLEAN PacketReceivePacket(LPADAPTER AdapterObject,LPPACKET lpPacket,BOOLEAN Sync)
2164 BOOLEAN res;
2166 UNUSED(Sync);
2168 TRACE_ENTER("PacketReceivePacket");
2169 #ifdef HAVE_WANPACKET_API
2171 if (AdapterObject->Flags == INFO_FLAG_NDISWAN_ADAPTER)
2173 lpPacket->ulBytesReceived = WanPacketReceivePacket(AdapterObject->pWanAdapter, lpPacket->Buffer, lpPacket->Length);
2175 TRACE_EXIT("PacketReceivePacket");
2176 return TRUE;
2178 #endif //HAVE_WANPACKET_API
2180 #ifdef HAVE_AIRPCAP_API
2181 if(AdapterObject->Flags == INFO_FLAG_AIRPCAP_CARD)
2184 // Wait for data, only if the user requested us to do that
2186 if((int)AdapterObject->ReadTimeOut != -1)
2188 WaitForSingleObject(AdapterObject->ReadEvent, (AdapterObject->ReadTimeOut==0)? INFINITE: AdapterObject->ReadTimeOut);
2192 // Read the data.
2193 // g_PAirpcapRead always returns immediately.
2195 res = (BOOLEAN)g_PAirpcapRead(AdapterObject->AirpcapAd,
2196 lpPacket->Buffer,
2197 lpPacket->Length,
2198 &lpPacket->ulBytesReceived);
2200 TRACE_EXIT("PacketReceivePacket");
2202 return res;
2204 #endif // HAVE_AIRPCAP_API
2206 #ifdef HAVE_NPFIM_API
2207 if(AdapterObject->Flags == INFO_FLAG_NPFIM_DEVICE)
2210 // Read the data.
2211 // NpfImReceivePacket performs its own wait internally.
2214 res = (BOOLEAN)g_NpfImHandlers.NpfImReceivePackets(AdapterObject->NpfImHandle,
2215 lpPacket->Buffer,
2216 lpPacket->Length,
2217 &lpPacket->ulBytesReceived);
2219 TRACE_EXIT("PacketReceivePacket");
2221 return res;
2223 #endif // HAVE_NPFIM_API
2225 #ifdef HAVE_DAG_API
2226 if((AdapterObject->Flags & INFO_FLAG_DAG_CARD) || (AdapterObject->Flags & INFO_FLAG_DAG_FILE))
2228 g_p_dagc_wait(AdapterObject->pDagCard, &AdapterObject->DagReadTimeout);
2230 res = (BOOLEAN)(g_p_dagc_receive(AdapterObject->pDagCard, (u_char**)&AdapterObject->DagBuffer, (u_int*)&lpPacket->ulBytesReceived) == 0);
2232 TRACE_EXIT("PacketReceivePacket");
2233 return res;
2235 #endif // HAVE_DAG_API
2237 if (AdapterObject->Flags == INFO_FLAG_NDIS_ADAPTER)
2239 if((int)AdapterObject->ReadTimeOut != -1)
2240 WaitForSingleObject(AdapterObject->ReadEvent, (AdapterObject->ReadTimeOut==0)?INFINITE:AdapterObject->ReadTimeOut);
2242 res = (BOOLEAN)ReadFile(AdapterObject->hFile, lpPacket->Buffer, lpPacket->Length, &lpPacket->ulBytesReceived,NULL);
2244 else
2246 TRACE_PRINT1("Request to read on an unknown device type (%u)", AdapterObject->Flags);
2247 res = FALSE;
2250 TRACE_EXIT("PacketReceivePacket");
2251 return res;
2254 /*!
2255 \brief Sends one (or more) copies of a packet to the network.
2256 \param AdapterObject Pointer to an _ADAPTER structure identifying the network adapter that will
2257 send the packets.
2258 \param lpPacket Pointer to a PACKET structure with the packet to send.
2259 \param Sync This parameter is deprecated and will be ignored. It is present for compatibility with
2260 older applications.
2261 \return If the function succeeds, the return value is nonzero.
2263 This function is used to send a raw packet to the network. 'Raw packet' means that the programmer
2264 will have to include the protocol headers, since the packet is sent to the network 'as is'.
2265 The CRC needs not to be calculated and put at the end of the packet, because it will be transparently
2266 added by the network interface.
2268 The behavior of this function is influenced by the PacketSetNumWrites() function. With PacketSetNumWrites(),
2269 it is possible to change the number of times a single write must be repeated. The default is 1,
2270 i.e. every call to PacketSendPacket() will correspond to one packet sent to the network. If this number is
2271 greater than 1, for example 1000, every raw packet written by the application will be sent 1000 times on
2272 the network. This feature mitigates the overhead of the context switches and therefore can be used to generate
2273 high speed traffic. It is particularly useful for tools that test networks, routers, and servers and need
2274 to obtain high network loads.
2275 The optimized sending process is still limited to one packet at a time: for the moment it cannot be used
2276 to send a buffer with multiple packets.
2278 \note The ability to write multiple packets is currently present only in the Windows NTx version of the
2279 packet driver. In Windows 95/98/ME it is emulated at user level in packet.dll. This means that an application
2280 that uses the multiple write method will run in Windows 9x as well, but its performance will be very low
2281 compared to the one of WindowsNTx.
2283 BOOLEAN PacketSendPacket(LPADAPTER AdapterObject,LPPACKET lpPacket,BOOLEAN Sync)
2285 DWORD BytesTransfered;
2286 BOOLEAN Result;
2287 TRACE_ENTER("PacketSendPacket");
2289 UNUSED(Sync);
2291 #ifdef HAVE_AIRPCAP_API
2292 if(AdapterObject->Flags == INFO_FLAG_AIRPCAP_CARD)
2294 if(g_PAirpcapWrite)
2296 Result = (BOOLEAN)g_PAirpcapWrite(AdapterObject->AirpcapAd, lpPacket->Buffer, lpPacket->Length);
2297 TRACE_EXIT("PacketSetMinToCopy");
2299 return Result;
2301 else
2303 TRACE_EXIT("PacketSetMinToCopy");
2304 TRACE_PRINT("Transmission not supported with this version of AirPcap");
2306 return FALSE;
2309 #endif // HAVE_AIRPCAP_API
2311 #ifdef HAVE_WANPACKET_API
2312 if(AdapterObject->Flags == INFO_FLAG_NDISWAN_ADAPTER)
2314 TRACE_PRINT("PacketSendPacket: packet sending not allowed on wan adapters");
2316 TRACE_EXIT("PacketSendPacket");
2317 return FALSE;
2319 #endif // HAVE_WANPACKET_API
2321 #ifdef HAVE_NPFIM_API
2322 if(AdapterObject->Flags == INFO_FLAG_NPFIM_DEVICE)
2324 TRACE_PRINT("PacketSendPacket: packet sending not allowed on NPFIM adapters");
2326 TRACE_EXIT("PacketSendPacket");
2327 return FALSE;
2329 #endif //HAVE_NPFIM_API
2331 if (AdapterObject->Flags == INFO_FLAG_NDIS_ADAPTER)
2333 Result = (BOOLEAN)WriteFile(AdapterObject->hFile,lpPacket->Buffer,lpPacket->Length,&BytesTransfered,NULL);
2335 else
2337 TRACE_PRINT1("Request to write on an unknown device type (%u)", AdapterObject->Flags);
2338 Result = FALSE;
2341 TRACE_EXIT("PacketSendPacket");
2342 return Result;
2345 /*!
2346 \brief Sends a buffer of packets to the network.
2347 \param AdapterObject Pointer to an _ADAPTER structure identifying the network adapter that will
2348 send the packets.
2349 \param PacketBuff Pointer to buffer with the packets to send.
2350 \param Size Size of the buffer pointed by the PacketBuff argument.
2351 \param Sync if TRUE, the packets are sent respecting the timestamps. If FALSE, the packets are sent as
2352 fast as possible
2353 \return The amount of bytes actually sent. If the return value is smaller than the Size parameter, an
2354 error occurred during the send. The error can be caused by a driver/adapter problem or by an
2355 inconsistent/bogus packet buffer.
2357 This function is used to send a buffer of raw packets to the network. The buffer can contain an arbitrary
2358 number of raw packets, each of which preceded by a dump_bpf_hdr structure. The dump_bpf_hdr is the same used
2359 by WinPcap and libpcap to store the packets in a file, therefore sending a capture file is straightforward.
2360 'Raw packets' means that the sending application will have to include the protocol headers, since every packet
2361 is sent to the network 'as is'. The CRC of the packets needs not to be calculated, because it will be
2362 transparently added by the network interface.
2364 \note Using this function if more efficient than issuing a series of PacketSendPacket(), because the packets are
2365 buffered in the kernel driver, so the number of context switches is reduced.
2367 \note When Sync is set to TRUE, the packets are synchronized in the kerenl with a high precision timestamp.
2368 This requires a remarkable amount of CPU, but allows to send the packets with a precision of some microseconds
2369 (depending on the precision of the performance counter of the machine). Such a precision cannot be reached
2370 sending the packets separately with PacketSendPacket().
2372 INT PacketSendPackets(LPADAPTER AdapterObject, PVOID PacketBuff, ULONG Size, BOOLEAN Sync)
2374 BOOLEAN Res;
2375 DWORD BytesTransfered, TotBytesTransfered=0;
2376 struct timeval BufStartTime;
2377 LARGE_INTEGER StartTicks, CurTicks, TargetTicks, TimeFreq;
2380 TRACE_ENTER("PacketSendPackets");
2382 #ifdef HAVE_WANPACKET_API
2383 if(AdapterObject->Flags == INFO_FLAG_NDISWAN_ADAPTER)
2385 TRACE_PRINT("PacketSendPackets: packet sending not allowed on wan adapters");
2386 TRACE_EXIT("PacketSendPackets");
2387 return 0;
2389 #endif // HAVE_WANPACKET_API
2391 #ifdef HAVE_NPFIM_API
2392 if(AdapterObject->Flags == INFO_FLAG_NPFIM_DEVICE)
2394 TRACE_PRINT("PacketSendPackets: packet sending not allowed on npfim adapters");
2395 TRACE_EXIT("PacketSendPackets");
2396 return 0;
2398 #endif // HAVE_NPFIM_API
2400 #ifdef HAVE_AIRPCAP_API
2401 if(AdapterObject->Flags == INFO_FLAG_AIRPCAP_CARD)
2403 TRACE_PRINT("PacketSendPackets: packet sending not allowed on airpcap adapters");
2404 TRACE_EXIT("PacketSendPackets");
2405 return 0;
2407 #endif // HAVE_AIRPCAP_API
2409 if (AdapterObject->Flags == INFO_FLAG_NDIS_ADAPTER)
2411 // Obtain starting timestamp of the buffer
2412 BufStartTime.tv_sec = ((struct timeval*)(PacketBuff))->tv_sec;
2413 BufStartTime.tv_usec = ((struct timeval*)(PacketBuff))->tv_usec;
2415 // Retrieve the reference time counters
2416 QueryPerformanceCounter(&StartTicks);
2417 QueryPerformanceFrequency(&TimeFreq);
2419 CurTicks.QuadPart = StartTicks.QuadPart;
2422 // Send the data to the driver
2423 //TODO Res is NEVER checked, this is REALLY bad.
2424 Res = (BOOLEAN)DeviceIoControl(AdapterObject->hFile,
2425 (Sync)?pBIOCSENDPACKETSSYNC:pBIOCSENDPACKETSNOSYNC,
2426 (PCHAR)PacketBuff + TotBytesTransfered,
2427 Size - TotBytesTransfered,
2428 NULL,
2430 &BytesTransfered,
2431 NULL);
2433 TotBytesTransfered += BytesTransfered;
2435 // Exit from the loop on termination or error
2436 if(TotBytesTransfered >= Size || Res != TRUE)
2437 break;
2439 // calculate the time interval to wait before sending the next packet
2440 TargetTicks.QuadPart = StartTicks.QuadPart +
2441 (LONGLONG)
2442 ((((struct timeval*)((PCHAR)PacketBuff + TotBytesTransfered))->tv_sec - BufStartTime.tv_sec) * 1000000 +
2443 (((struct timeval*)((PCHAR)PacketBuff + TotBytesTransfered))->tv_usec - BufStartTime.tv_usec)) *
2444 (TimeFreq.QuadPart) / 1000000;
2446 // Wait until the time interval has elapsed
2447 while( CurTicks.QuadPart <= TargetTicks.QuadPart )
2448 QueryPerformanceCounter(&CurTicks);
2451 while(TRUE);
2453 else
2455 TRACE_PRINT1("Request to write on an unknown device type (%u)", AdapterObject->Flags);
2456 TotBytesTransfered = 0;
2459 TRACE_EXIT("PacketSendPackets");
2461 return TotBytesTransfered;
2464 /*!
2465 \brief Defines the minimum amount of data that will be received in a read.
2466 \param AdapterObject Pointer to an _ADAPTER structure
2467 \param nbytes the minimum amount of data in the kernel buffer that will cause the driver to
2468 release a read on this adapter.
2469 \return If the function succeeds, the return value is nonzero.
2471 In presence of a large value for nbytes, the kernel waits for the arrival of several packets before
2472 copying the data to the user. This guarantees a low number of system calls, i.e. lower processor usage,
2473 i.e. better performance, which is a good setting for applications like sniffers. Vice versa, a small value
2474 means that the kernel will copy the packets as soon as the application is ready to receive them. This is
2475 suggested for real time applications (like, for example, a bridge) that need the better responsiveness from
2476 the kernel.
2478 \b note: this function has effect only in Windows NTx. The driver for Windows 9x doesn't offer
2479 this possibility, therefore PacketSetMinToCopy is implemented under these systems only for compatibility.
2482 BOOLEAN PacketSetMinToCopy(LPADAPTER AdapterObject,int nbytes)
2484 DWORD BytesReturned;
2485 BOOLEAN Result;
2486 TRACE_ENTER("PacketSetMinToCopy");
2488 #ifdef HAVE_WANPACKET_API
2489 if (AdapterObject->Flags == INFO_FLAG_NDISWAN_ADAPTER)
2491 Result = WanPacketSetMinToCopy(AdapterObject->pWanAdapter, nbytes);
2492 TRACE_EXIT("PacketSetMinToCopy");
2494 return Result;
2496 #endif //HAVE_WANPACKET_API
2498 #ifdef HAVE_NPFIM_API
2499 if(AdapterObject->Flags == INFO_FLAG_NPFIM_DEVICE)
2501 Result = (BOOLEAN)g_NpfImHandlers.NpfImSetMinToCopy(AdapterObject->NpfImHandle, nbytes);
2502 TRACE_EXIT("PacketSetMinToCopy");
2504 return Result;
2506 #endif // HAVE_NPFIM_API
2508 #ifdef HAVE_AIRPCAP_API
2509 if(AdapterObject->Flags == INFO_FLAG_AIRPCAP_CARD)
2511 Result = (BOOLEAN)g_PAirpcapSetMinToCopy(AdapterObject->AirpcapAd, nbytes);
2512 TRACE_EXIT("PacketSetMinToCopy");
2514 return Result;
2516 #endif // HAVE_AIRPCAP_API
2518 #ifdef HAVE_DAG_API
2519 if(AdapterObject->Flags & INFO_FLAG_DAG_CARD)
2521 TRACE_EXIT("PacketSetMinToCopy");
2522 // No mintocopy with DAGs
2523 return TRUE;
2525 #endif // HAVE_DAG_API
2527 if (AdapterObject->Flags == INFO_FLAG_NDIS_ADAPTER)
2529 Result = (BOOLEAN)DeviceIoControl(AdapterObject->hFile,pBIOCSMINTOCOPY,&nbytes,4,NULL,0,&BytesReturned,NULL);
2531 else
2533 TRACE_PRINT1("Request to set mintocopy on an unknown device type (%u)", AdapterObject->Flags);
2534 Result = FALSE;
2537 TRACE_EXIT("PacketSetMinToCopy");
2539 return Result;
2543 \brief Sets the working mode of an adapter.
2544 \param AdapterObject Pointer to an _ADAPTER structure.
2545 \param mode The new working mode of the adapter.
2546 \return If the function succeeds, the return value is nonzero.
2548 The device driver of WinPcap has 4 working modes:
2549 - Capture mode (mode = PACKET_MODE_CAPT): normal capture mode. The packets transiting on the wire are copied
2550 to the application when PacketReceivePacket() is called. This is the default working mode of an adapter.
2551 - Statistical mode (mode = PACKET_MODE_STAT): programmable statistical mode. PacketReceivePacket() returns, at
2552 precise intervals, statics values on the network traffic. The interval between the statistic samples is
2553 by default 1 second but it can be set to any other value (with a 1 ms precision) with the
2554 PacketSetReadTimeout() function. The data returned by PacketReceivePacket() when the adapter is in statistical
2555 mode is shown in the following figure:<p>
2556 \image html stats.gif "data structure returned by statistical mode"
2557 Two 64-bit counters are provided: the number of packets and the amount of bytes that satisfy a filter
2558 previously set with PacketSetBPF(). If no filter has been set, all the packets are counted. The counters are
2559 encapsulated in a bpf_hdr structure, so that they will be parsed correctly by wpcap. Statistical mode has a
2560 very low impact on system performance compared to capture mode.
2561 - Dump mode (mode = PACKET_MODE_DUMP): the packets are dumped to disk by the driver, in libpcap format. This
2562 method is much faster than saving the packets after having captured them. No data is returned
2563 by PacketReceivePacket(). If the application sets a filter with PacketSetBPF(), only the packets that satisfy
2564 this filter are dumped to disk.
2565 - Statitical Dump mode (mode = PACKET_MODE_STAT_DUMP): the packets are dumped to disk by the driver, in libpcap
2566 format, like in dump mode. PacketReceivePacket() returns, at precise intervals, statics values on the
2567 network traffic and on the amount of data saved to file, in a way similar to statistical mode.
2568 The data returned by PacketReceivePacket() when the adapter is in statistical dump mode is shown in
2569 the following figure:<p>
2570 \image html dump.gif "data structure returned by statistical dump mode"
2571 Three 64-bit counters are provided: the number of packets accepted, the amount of bytes accepted and the
2572 effective amount of data (including headers) dumped to file. If no filter has been set, all the packets are
2573 dumped to disk. The counters are encapsulated in a bpf_hdr structure, so that they will be parsed correctly
2574 by wpcap.
2575 Look at the NetMeter example in the
2576 WinPcap developer's pack to see how to use statistics mode.
2578 BOOLEAN PacketSetMode(LPADAPTER AdapterObject,int mode)
2580 DWORD BytesReturned;
2581 BOOLEAN Result;
2583 TRACE_ENTER("PacketSetMode");
2585 #ifdef HAVE_WANPACKET_API
2586 if (AdapterObject->Flags == INFO_FLAG_NDISWAN_ADAPTER)
2588 Result = WanPacketSetMode(AdapterObject->pWanAdapter, mode);
2589 TRACE_EXIT("PacketSetMode");
2591 return Result;
2593 #endif // HAVE_WANPACKET_API
2595 #ifdef HAVE_AIRPCAP_API
2596 if (AdapterObject->Flags == INFO_FLAG_AIRPCAP_CARD)
2598 if (mode == PACKET_MODE_CAPT)
2600 Result = TRUE;
2602 else
2604 Result = FALSE;
2607 TRACE_EXIT("PacketSetMode");
2609 return Result;
2611 #endif //HAVE_AIRPCAP_API
2613 #ifdef HAVE_NPFIM_API
2614 if (AdapterObject->Flags == INFO_FLAG_NPFIM_DEVICE)
2616 if (mode == PACKET_MODE_CAPT)
2618 Result = TRUE;
2620 else
2622 Result = FALSE;
2625 TRACE_EXIT("PacketSetMode");
2627 return Result;
2629 #endif //HAVE_NPFIM_API
2631 if (AdapterObject->Flags == INFO_FLAG_NDIS_ADAPTER)
2633 Result = (BOOLEAN)DeviceIoControl(AdapterObject->hFile,pBIOCSMODE,&mode,4,NULL,0,&BytesReturned,NULL);
2635 else
2637 TRACE_PRINT1("Request to set mode on an unknown device type (%u)", AdapterObject->Flags);
2638 Result = FALSE;
2641 TRACE_EXIT("PacketSetMode");
2643 return Result;
2648 \brief Sets the name of the file that will receive the packet when the adapter is in dump mode.
2649 \param AdapterObject Pointer to an _ADAPTER structure.
2650 \param name the file name, in ASCII or UNICODE.
2651 \param len the length of the buffer containing the name, in bytes.
2652 \return If the function succeeds, the return value is nonzero.
2654 This function defines the file name that the driver will open to store the packets on disk when
2655 it works in dump mode. The adapter must be in dump mode, i.e. PacketSetMode() should have been
2656 called previously with mode = PACKET_MODE_DUMP. otherwise this function will fail.
2657 If PacketSetDumpName was already invoked on the adapter pointed by AdapterObject, the driver
2658 closes the old file and opens the new one.
2661 BOOLEAN PacketSetDumpName(LPADAPTER AdapterObject, void *name, int len)
2663 DWORD BytesReturned;
2664 WCHAR *FileName;
2665 BOOLEAN res;
2666 WCHAR NameWithPath[1024];
2667 int TStrLen;
2668 WCHAR *NamePos;
2670 TRACE_ENTER("PacketSetDumpName");
2672 if (AdapterObject->Flags != INFO_FLAG_NDIS_ADAPTER)
2674 TRACE_PRINT("PacketSetDumpName: not allowed on non-NPF adapters");
2675 TRACE_EXIT("PacketSetDumpName");
2676 return FALSE;
2679 if(((PUCHAR)name)[1]!=0 && len>1){ //ASCII
2680 FileName=SChar2WChar(name);
2681 len*=2;
2683 else { //Unicode
2684 FileName=name;
2687 TStrLen=GetFullPathName(FileName,1024,NameWithPath,&NamePos);
2689 len=TStrLen*2+2; //add the terminating null character
2691 // Try to catch malformed strings
2692 if(len>2048){
2693 if(((PUCHAR)name)[1]!=0 && len>1) free(FileName);
2695 TRACE_EXIT("PacketSetDumpName");
2697 return FALSE;
2700 res = (BOOLEAN)DeviceIoControl(AdapterObject->hFile,pBIOCSETDUMPFILENAME,NameWithPath,len,NULL,0,&BytesReturned,NULL);
2701 free(FileName);
2703 TRACE_EXIT("PacketSetDumpName");
2704 return res;
2708 \brief Set the dump mode limits.
2709 \param AdapterObject Pointer to an _ADAPTER structure.
2710 \param maxfilesize The maximum dimension of the dump file, in bytes. 0 means no limit.
2711 \param maxnpacks The maximum number of packets contained in the dump file. 0 means no limit.
2712 \return If the function succeeds, the return value is nonzero.
2714 This function sets the limits after which the NPF driver stops to save the packets to file when an adapter
2715 is in dump mode. This allows to limit the dump file to a precise number of bytes or packets, avoiding that
2716 very long dumps fill the disk space. If both maxfilesize and maxnpacks are set, the dump is stopped when
2717 the first of the two is reached.
2719 \note When a limit is reached, the dump is stopped, but the file remains opened. In order to flush
2720 correctly the data and access the file consistently, you need to close the adapter with PacketCloseAdapter().
2722 BOOLEAN PacketSetDumpLimits(LPADAPTER AdapterObject, UINT maxfilesize, UINT maxnpacks)
2724 DWORD BytesReturned;
2725 UINT valbuff[2];
2726 BOOLEAN Result;
2728 TRACE_ENTER("PacketSetDumpLimits");
2730 if (AdapterObject->Flags != INFO_FLAG_NDIS_ADAPTER)
2732 TRACE_PRINT("PacketSetDumpLimits: not allowed on non-NPF adapters");
2733 TRACE_EXIT("PacketSetDumpLimits");
2734 return FALSE;
2737 valbuff[0] = maxfilesize;
2738 valbuff[1] = maxnpacks;
2740 Result = (BOOLEAN)DeviceIoControl(AdapterObject->hFile,
2741 pBIOCSETDUMPLIMITS,
2742 valbuff,
2743 sizeof valbuff,
2744 NULL,
2746 &BytesReturned,
2747 NULL);
2749 TRACE_EXIT("PacketSetDumpLimits");
2751 return Result;
2756 \brief Returns the status of the kernel dump process, i.e. tells if one of the limits defined with PacketSetDumpLimits() was reached.
2757 \param AdapterObject Pointer to an _ADAPTER structure.
2758 \param sync if TRUE, the function blocks until the dump is finished, otherwise it returns immediately.
2759 \return TRUE if the dump is ended, FALSE otherwise.
2761 PacketIsDumpEnded() informs the user about the limits that were set with a previous call to
2762 PacketSetDumpLimits().
2764 \warning If no calls to PacketSetDumpLimits() were performed or if the dump process has no limits
2765 (i.e. if the arguments of the last call to PacketSetDumpLimits() were both 0), setting sync to TRUE will
2766 block the application on this call forever.
2768 BOOLEAN PacketIsDumpEnded(LPADAPTER AdapterObject, BOOLEAN sync)
2770 DWORD BytesReturned;
2771 int IsDumpEnded;
2772 BOOLEAN res;
2774 TRACE_ENTER("PacketIsDumpEnded");
2776 if(AdapterObject->Flags != INFO_FLAG_NDIS_ADAPTER)
2778 TRACE_PRINT("PacketIsDumpEnded: not allowed on non-NPF adapters");
2780 TRACE_EXIT("PacketIsDumpEnded");
2782 return FALSE;
2785 if(sync)
2786 WaitForSingleObject(AdapterObject->ReadEvent, INFINITE);
2788 res = (BOOLEAN)DeviceIoControl(AdapterObject->hFile,
2789 pBIOCISDUMPENDED,
2790 NULL,
2792 &IsDumpEnded,
2794 &BytesReturned,
2795 NULL);
2797 TRACE_EXIT("PacketIsDumpEnded");
2799 if(res == FALSE) return TRUE; // If the IOCTL returns an error we consider the dump finished
2801 return (BOOLEAN)IsDumpEnded;
2805 \brief Returns the notification event associated with the read calls on an adapter.
2806 \param AdapterObject Pointer to an _ADAPTER structure.
2807 \return The handle of the event that the driver signals when some data is available in the kernel buffer.
2809 The event returned by this function is signaled by the driver if:
2810 - The adapter pointed by AdapterObject is in capture mode and an amount of data greater or equal
2811 than the one set with the PacketSetMinToCopy() function is received from the network.
2812 - the adapter pointed by AdapterObject is in capture mode, no data has been received from the network
2813 but the the timeout set with the PacketSetReadTimeout() function has elapsed.
2814 - the adapter pointed by AdapterObject is in statics mode and the the timeout set with the
2815 PacketSetReadTimeout() function has elapsed. This means that a new statistic sample is available.
2817 In every case, a call to PacketReceivePacket() will return immediately.
2818 The event can be passed to standard Win32 functions (like WaitForSingleObject or WaitForMultipleObjects)
2819 to wait until the driver's buffer contains some data. It is particularly useful in GUI applications that
2820 need to wait concurrently on several events.
2823 HANDLE PacketGetReadEvent(LPADAPTER AdapterObject)
2825 TRACE_ENTER("PacketGetReadEvent");
2826 TRACE_EXIT("PacketGetReadEvent");
2827 return AdapterObject->ReadEvent;
2831 \brief Sets the number of times a single packet written with PacketSendPacket() will be repeated on the network.
2832 \param AdapterObject Pointer to an _ADAPTER structure.
2833 \param nwrites Number of copies of a packet that will be physically sent by the interface.
2834 \return If the function succeeds, the return value is nonzero.
2836 See PacketSendPacket() for details.
2838 BOOLEAN PacketSetNumWrites(LPADAPTER AdapterObject,int nwrites)
2840 DWORD BytesReturned;
2841 BOOLEAN Result;
2843 TRACE_ENTER("PacketSetNumWrites");
2845 if(AdapterObject->Flags != INFO_FLAG_NDIS_ADAPTER)
2847 TRACE_PRINT("PacketSetNumWrites: not allowed on non-NPF adapters");
2848 TRACE_EXIT("PacketSetNumWrites");
2849 return FALSE;
2852 Result = (BOOLEAN)DeviceIoControl(AdapterObject->hFile,pBIOCSWRITEREP,&nwrites,4,NULL,0,&BytesReturned,NULL);
2854 TRACE_EXIT("PacketSetNumWrites");
2856 return Result;
2860 \brief Sets the timeout after which a read on an adapter returns.
2861 \param AdapterObject Pointer to an _ADAPTER structure.
2862 \param timeout indicates the timeout, in milliseconds, after which a call to PacketReceivePacket() on
2863 the adapter pointed by AdapterObject will be released, also if no packets have been captured by the driver.
2864 Setting timeout to 0 means no timeout, i.e. PacketReceivePacket() never returns if no packet arrives.
2865 A timeout of -1 causes PacketReceivePacket() to always return immediately.
2866 \return If the function succeeds, the return value is nonzero.
2868 \note This function works also if the adapter is working in statistics mode, and can be used to set the
2869 time interval between two statistic reports.
2871 BOOLEAN PacketSetReadTimeout(LPADAPTER AdapterObject,int timeout)
2873 BOOLEAN Result;
2875 TRACE_ENTER("PacketSetReadTimeout");
2877 AdapterObject->ReadTimeOut = timeout;
2879 #ifdef HAVE_WANPACKET_API
2880 if (AdapterObject->Flags == INFO_FLAG_NDISWAN_ADAPTER)
2882 Result = WanPacketSetReadTimeout(AdapterObject->pWanAdapter,timeout);
2884 TRACE_EXIT("PacketSetReadTimeout");
2886 return Result;
2888 #endif // HAVE_WANPACKET_API
2890 #ifdef HAVE_NPFIM_API
2891 if (AdapterObject->Flags == INFO_FLAG_NPFIM_DEVICE)
2894 // convert the timestamps to Windows like format (0 = immediate, -1(INFINITE) = infinite)
2896 if (timeout == -1) timeout = 0;
2897 else if (timeout == 0) timeout = INFINITE;
2899 Result = (BOOLEAN)g_NpfImHandlers.NpfImSetReadTimeout(AdapterObject->NpfImHandle, timeout);
2900 TRACE_EXIT("PacketSetReadTimeout");
2901 return Result;
2903 #endif // HAVE_NPFIM_API
2905 #ifdef HAVE_AIRPCAP_API
2907 // Timeout with AirPcap is handled at user level
2909 if(AdapterObject->Flags == INFO_FLAG_AIRPCAP_CARD)
2911 TRACE_EXIT("PacketSetReadTimeout");
2912 return TRUE;
2914 #endif // HAVE_AIRPCAP_API
2916 #ifdef HAVE_DAG_API
2917 // Under DAG, we simply store the timeout value and then
2918 if(AdapterObject->Flags & INFO_FLAG_DAG_CARD)
2920 if(timeout == -1)
2922 // tell DAG card to return immediately
2923 AdapterObject->DagReadTimeout.tv_sec = 0;
2924 AdapterObject->DagReadTimeout.tv_usec = 0;
2926 else
2928 if(timeout == 0)
2930 // tell the DAG card to wait forvever
2931 AdapterObject->DagReadTimeout.tv_sec = -1;
2932 AdapterObject->DagReadTimeout.tv_usec = -1;
2934 else
2936 // Set the timeout for the DAG card
2937 AdapterObject->DagReadTimeout.tv_sec = timeout / 1000;
2938 AdapterObject->DagReadTimeout.tv_usec = (timeout * 1000) % 1000000;
2942 TRACE_EXIT("PacketSetReadTimeout");
2943 return TRUE;
2945 #endif // HAVE_DAG_API
2947 if(AdapterObject->Flags == INFO_FLAG_NDIS_ADAPTER)
2949 Result = TRUE;
2951 else
2954 // if we are here, it's an unsupported ADAPTER type!
2956 TRACE_PRINT1("Request to set read timeout on an unknown device type (%u)", AdapterObject->Flags);
2957 Result = FALSE;
2960 TRACE_EXIT("PacketSetReadTimeout");
2961 return Result;
2966 \brief Sets the size of the kernel-level buffer associated with a capture.
2967 \param AdapterObject Pointer to an _ADAPTER structure.
2968 \param dim New size of the buffer, in \b kilobytes.
2969 \return The function returns TRUE if successfully completed, FALSE if there is not enough memory to
2970 allocate the new buffer.
2972 When a new dimension is set, the data in the old buffer is discarded and the packets stored in it are
2973 lost.
2975 Note: the dimension of the kernel buffer affects heavily the performances of the capture process.
2976 An adequate buffer in the driver is able to keep the packets while the application is busy, compensating
2977 the delays of the application and avoiding the loss of packets during bursts or high network activity.
2978 The buffer size is set to 0 when an instance of the driver is opened: the programmer should remember to
2979 set it to a proper value. As an example, wpcap sets the buffer size to 1MB at the beginning of a capture.
2981 BOOLEAN PacketSetBuff(LPADAPTER AdapterObject,int dim)
2983 DWORD BytesReturned;
2984 BOOLEAN Result;
2986 TRACE_ENTER("PacketSetBuff");
2988 #ifdef HAVE_WANPACKET_API
2989 if (AdapterObject->Flags == INFO_FLAG_NDISWAN_ADAPTER)
2991 Result = WanPacketSetBufferSize(AdapterObject->pWanAdapter, dim);
2993 TRACE_EXIT("PacketSetBuff");
2994 return Result;
2996 #endif
2998 #ifdef HAVE_AIRPCAP_API
2999 if(AdapterObject->Flags == INFO_FLAG_AIRPCAP_CARD)
3001 Result = (BOOLEAN)g_PAirpcapSetKernelBuffer(AdapterObject->AirpcapAd, dim);
3003 TRACE_EXIT("PacketSetBuff");
3004 return Result;
3006 #endif // HAVE_AIRPCAP_API
3008 #ifdef HAVE_NPFIM_API
3009 if(AdapterObject->Flags == INFO_FLAG_NPFIM_DEVICE)
3011 Result = (BOOLEAN)g_NpfImHandlers.NpfImSetCaptureBufferSize(AdapterObject->NpfImHandle, dim);
3013 TRACE_EXIT("PacketSetBuff");
3014 return Result;
3016 #endif // HAVE_NPFIM_API
3018 #ifdef HAVE_DAG_API
3019 if(AdapterObject->Flags == INFO_FLAG_DAG_CARD)
3021 // We can't change DAG buffers
3022 TRACE_EXIT("PacketSetBuff");
3023 return TRUE;
3025 #endif // HAVE_DAG_API
3027 if (AdapterObject->Flags == INFO_FLAG_NDIS_ADAPTER)
3029 Result = (BOOLEAN)DeviceIoControl(AdapterObject->hFile,pBIOCSETBUFFERSIZE,&dim,sizeof(dim),NULL,0,&BytesReturned,NULL);
3031 else
3033 TRACE_PRINT1("Request to set buf size on an unknown device type (%u)", AdapterObject->Flags);
3034 Result = FALSE;
3037 TRACE_EXIT("PacketSetBuff");
3039 return Result;
3043 \brief Sets a kernel-level packet filter.
3044 \param AdapterObject Pointer to an _ADAPTER structure.
3045 \param fp Pointer to a filtering program that will be associated with this capture or monitoring
3046 instance and that will be executed on every incoming packet.
3047 \return This function returns TRUE if the filter is set successfully, FALSE if an error occurs
3048 or if the filter program is not accepted after a safeness check by the driver. The driver performs
3049 the check in order to avoid system crashes due to buggy or malicious filters, and it rejects non
3050 conformat filters.
3052 This function associates a new BPF filter to the adapter AdapterObject. The filter, pointed by fp, is a
3053 set of bpf_insn instructions.
3055 A filter can be automatically created by using the pcap_compile() function of wpcap. This function
3056 converts a human readable text expression with the tcpdump/libpcap syntax (see the manual of WinDump at
3057 http://www.winpcap.org/windump for details) into a BPF program. If your program doesn't link wpcap, but
3058 you need to know the code of a particular filter, you can run WinDump with the -d or -dd or -ddd
3059 flags to obtain the pseudocode.
3062 BOOLEAN PacketSetBpf(LPADAPTER AdapterObject, struct bpf_program *fp)
3064 DWORD BytesReturned;
3065 BOOLEAN Result;
3067 TRACE_ENTER("PacketSetBpf");
3069 #ifdef HAVE_WANPACKET_API
3070 if (AdapterObject->Flags == INFO_FLAG_NDISWAN_ADAPTER)
3072 Result = WanPacketSetBpfFilter(AdapterObject->pWanAdapter, (PUCHAR)fp->bf_insns, fp->bf_len * sizeof(struct bpf_insn));
3073 TRACE_EXIT("PacketSetBpf");
3074 return Result;
3076 #endif
3078 #ifdef HAVE_AIRPCAP_API
3079 if(AdapterObject->Flags == INFO_FLAG_AIRPCAP_CARD)
3081 Result = (BOOLEAN)g_PAirpcapSetFilter(AdapterObject->AirpcapAd,
3082 (char*)fp->bf_insns,
3083 fp->bf_len * sizeof(struct bpf_insn));
3085 TRACE_EXIT("PacketSetBpf");
3086 return Result;
3088 #endif // HAVE_AIRPCAP_API
3090 #ifdef HAVE_NPFIM_API
3091 if(AdapterObject->Flags == INFO_FLAG_NPFIM_DEVICE)
3093 Result = (BOOLEAN)g_NpfImHandlers.NpfImSetBpfFilter(AdapterObject->NpfImHandle,
3094 fp->bf_insns,
3095 fp->bf_len * sizeof(struct bpf_insn));
3097 TRACE_EXIT("PacketSetBpf");
3098 return TRUE;
3100 #endif // HAVE_NPFIM_API
3102 #ifdef HAVE_DAG_API
3103 if(AdapterObject->Flags & INFO_FLAG_DAG_CARD)
3105 // Delegate the filtering to higher layers since it's too expensive here
3106 TRACE_EXIT("PacketSetBpf");
3107 return TRUE;
3109 #endif // HAVE_DAG_API
3111 if (AdapterObject->Flags == INFO_FLAG_NDIS_ADAPTER)
3113 Result = (BOOLEAN)DeviceIoControl(AdapterObject->hFile,pBIOCSETF,(char*)fp->bf_insns,fp->bf_len*sizeof(struct bpf_insn),NULL,0,&BytesReturned,NULL);
3115 else
3117 TRACE_PRINT1("Request to set BPF filter on an unknown device type (%u)", AdapterObject->Flags);
3118 Result = FALSE;
3121 TRACE_EXIT("PacketSetBpf");
3123 return Result;
3127 \brief Sets the behavior of the NPF driver with packets sent by itself: capture or drop.
3128 \param AdapterObject Pointer to an _ADAPTER structure.
3129 \param LoopbackBehavior Can be one of the following:
3130 - \ref NPF_ENABLE_LOOPBACK
3131 - \ref NPF_DISABLE_LOOPBACK
3132 \return If the function succeeds, the return value is nonzero.
3134 \note: when opened, adapters have loopback capture \b enabled.
3136 BOOLEAN PacketSetLoopbackBehavior(LPADAPTER AdapterObject, UINT LoopbackBehavior)
3138 DWORD BytesReturned;
3139 BOOLEAN result;
3141 TRACE_ENTER("PacketSetLoopbackBehavior");
3143 if (AdapterObject->Flags != INFO_FLAG_NDIS_ADAPTER)
3145 TRACE_PRINT("PacketSetLoopbackBehavior: not allowed on non-NPF adapters");
3147 TRACE_EXIT("PacketSetLoopbackBehavior");
3149 return FALSE;
3153 result = (BOOLEAN)DeviceIoControl(AdapterObject->hFile,
3154 pBIOCISETLOBBEH,
3155 &LoopbackBehavior,
3156 sizeof(UINT),
3157 NULL,
3159 &BytesReturned,
3160 NULL);
3162 TRACE_EXIT("PacketSetLoopbackBehavior");
3164 return result;
3168 \brief Sets the snap len on the adapters that allow it.
3169 \param AdapterObject Pointer to an _ADAPTER structure.
3170 \param snaplen Desired snap len for this capture.
3171 \return If the function succeeds, the return value is nonzero and specifies the actual snaplen that
3172 the card is using. If the function fails or if the card does't allow to set sna length, the return
3173 value is 0.
3175 The snap len is the amount of packet that is actually captured by the interface and received by the
3176 application. Some interfaces allow to capture only a portion of any packet for performance reasons.
3178 \note: the return value can be different from the snaplen parameter, for example some boards round the
3179 snaplen to 4 bytes.
3181 INT PacketSetSnapLen(LPADAPTER AdapterObject, int snaplen)
3183 INT Result;
3185 TRACE_ENTER("PacketSetSnapLen");
3187 UNUSED(snaplen);
3188 UNUSED(AdapterObject);
3190 #ifdef HAVE_DAG_API
3191 if(AdapterObject->Flags & INFO_FLAG_DAG_CARD)
3192 Result = g_p_dagc_setsnaplen(AdapterObject->pDagCard, snaplen);
3193 else
3194 #endif // HAVE_DAG_API
3195 Result = 0;
3197 TRACE_EXIT("PacketSetSnapLen");
3199 return Result;
3204 \brief Returns a couple of statistic values about the current capture session.
3205 \param AdapterObject Pointer to an _ADAPTER structure.
3206 \param s Pointer to a user provided bpf_stat structure that will be filled by the function.
3207 \return If the function succeeds, the return value is nonzero.
3209 With this function, the programmer can know the value of two internal variables of the driver:
3211 - the number of packets that have been received by the adapter AdapterObject, starting at the
3212 time in which it was opened with PacketOpenAdapter.
3213 - the number of packets that have been dropped by the driver. A packet is dropped when the kernel
3214 buffer associated with the adapter is full.
3216 BOOLEAN PacketGetStats(LPADAPTER AdapterObject,struct bpf_stat *s)
3218 BOOLEAN Res;
3219 DWORD BytesReturned;
3220 struct bpf_stat tmpstat; // We use a support structure to avoid kernel-level inconsistencies with old or malicious applications
3222 TRACE_ENTER("PacketGetStats");
3224 #ifdef HAVE_AIRPCAP_API
3225 if(AdapterObject->Flags == INFO_FLAG_AIRPCAP_CARD)
3227 AirpcapStats tas;
3229 Res = (BOOLEAN)g_PAirpcapGetStats(AdapterObject->AirpcapAd, &tas);
3231 if (Res)
3234 // Do NOT write this value. This function is probably called with a small structure, old style, containing only the first three fields recv, drop, ifdrop
3236 // s->bs_capt = tas.Capt;
3237 s->bs_drop = tas.Drops;
3238 s->bs_recv = tas.Recvs;
3239 s->ps_ifdrop = tas.IfDrops;
3242 TRACE_EXIT("PacketGetStats");
3243 return Res;
3245 #endif // HAVE_AIRPCAP_API
3247 #ifdef HAVE_NPFIM_API
3248 if(AdapterObject->Flags == INFO_FLAG_NPFIM_DEVICE)
3250 ULONGLONG stats[7];
3251 DWORD neededBytes;
3253 Res = (BOOLEAN)g_NpfImHandlers.NpfImGetCaptureStatistics(AdapterObject->NpfImHandle, stats, sizeof(stats), &neededBytes);
3255 if (Res)
3257 // if (stats[NPFIM_CAPTURE_STATS_RECEIVED] < 0xFFFFFFFF)
3258 // s->bs_capt = (UINT)stats[NPFIM_CAPTURE_STATS_RECEIVED];
3259 // else
3260 // s->bs_capt = 0xFFFFFFFF;
3262 if (stats[NPFIM_CAPTURE_STATS_DROPPED_FILTER] < 0xFFFFFFFF)
3263 s->bs_drop = (UINT)stats[NPFIM_CAPTURE_STATS_DROPPED_FILTER];
3264 else
3265 s->bs_drop = 0xFFFFFFFF;
3267 if (stats[NPFIM_CAPTURE_STATS_ACCEPTED] < 0xFFFFFFFF)
3268 s->bs_recv = (UINT)stats[NPFIM_CAPTURE_STATS_ACCEPTED];
3269 else
3270 s->bs_recv = 0xFFFFFFFF;
3272 s->ps_ifdrop = 0;
3275 TRACE_EXIT("PacketGetStats");
3276 return Res;
3278 #endif // HAVE_AIRPCAP_API
3281 #ifdef HAVE_DAG_API
3282 if(AdapterObject->Flags & INFO_FLAG_DAG_CARD)
3284 dagc_stats_t DagStats;
3286 // Note: DAG cards are currently very limited from the statistics reporting point of view,
3287 // so most of the values returned by dagc_stats() are zero at the moment
3288 if(g_p_dagc_stats(AdapterObject->pDagCard, &DagStats) == 0)
3290 // XXX: Only copy the dropped packets for now, since the received counter is not supported by
3291 // DAGS at the moment
3293 s->bs_recv = (ULONG)DagStats.received;
3294 s->bs_drop = (ULONG)DagStats.dropped;
3295 TRACE_EXIT("PacketGetStats");
3296 return TRUE;
3298 else
3300 TRACE_EXIT("PacketGetStats");
3301 return FALSE;
3305 #endif // HAVE_DAG_API
3307 #ifdef HAVE_WANPACKET_API
3308 if ( AdapterObject->Flags == INFO_FLAG_NDISWAN_ADAPTER)
3310 Res = WanPacketGetStats(AdapterObject->pWanAdapter, (PVOID)&tmpstat);
3312 // Copy only the first two values retrieved from the driver
3313 s->bs_recv = tmpstat.bs_recv;
3314 s->bs_drop = tmpstat.bs_drop;
3316 TRACE_EXIT("PacketGetStats");
3318 return Res;
3321 #endif // HAVE_WANPACKET_API
3323 if (AdapterObject->Flags == INFO_FLAG_NDIS_ADAPTER)
3325 Res = (BOOLEAN)DeviceIoControl(AdapterObject->hFile,
3326 pBIOCGSTATS,
3327 NULL,
3329 &tmpstat,
3330 sizeof(struct bpf_stat),
3331 &BytesReturned,
3332 NULL);
3335 if (Res)
3337 // Copy only the first two values retrieved from the driver
3338 s->bs_recv = tmpstat.bs_recv;
3339 s->bs_drop = tmpstat.bs_drop;
3343 else
3345 TRACE_PRINT1("Request to obtain statistics on an unknown device type (%u)", AdapterObject->Flags);
3346 Res = FALSE;
3348 TRACE_EXIT("PacketGetStats");
3349 return Res;
3354 \brief Returns statistic values about the current capture session. Enhanced version of PacketGetStats().
3355 \param AdapterObject Pointer to an _ADAPTER structure.
3356 \param s Pointer to a user provided bpf_stat structure that will be filled by the function.
3357 \return If the function succeeds, the return value is nonzero.
3359 With this function, the programmer can retireve the sname values provided by PacketGetStats(), plus:
3361 - the number of drops by interface (not yet supported, always 0).
3362 - the number of packets that reached the application, i.e that were accepted by the kernel filter and
3363 that fitted in the kernel buffer.
3365 BOOLEAN PacketGetStatsEx(LPADAPTER AdapterObject,struct bpf_stat *s)
3367 BOOLEAN Res;
3368 DWORD BytesReturned;
3369 struct bpf_stat tmpstat; // We use a support structure to avoid kernel-level inconsistencies with old or malicious applications
3371 TRACE_ENTER("PacketGetStatsEx");
3373 #ifdef HAVE_DAG_API
3374 if(AdapterObject->Flags == INFO_FLAG_DAG_CARD)
3376 dagc_stats_t DagStats;
3378 // Note: DAG cards are currently very limited from the statistics reporting point of view,
3379 // so most of the values returned by dagc_stats() are zero at the moment
3380 g_p_dagc_stats(AdapterObject->pDagCard, &DagStats);
3381 s->bs_recv = (ULONG)DagStats.received;
3382 s->bs_drop = (ULONG)DagStats.dropped;
3383 s->ps_ifdrop = 0;
3384 s->bs_capt = (ULONG)DagStats.captured;
3386 TRACE_EXIT("PacketGetStatsEx");
3387 return TRUE;
3390 #endif // HAVE_DAG_API
3392 #ifdef HAVE_WANPACKET_API
3393 if(AdapterObject->Flags == INFO_FLAG_NDISWAN_ADAPTER)
3395 Res = WanPacketGetStats(AdapterObject->pWanAdapter, (PVOID)&tmpstat);
3396 TRACE_EXIT("PacketGetStatsEx");
3397 return Res;
3399 #endif // HAVE_WANPACKET_API
3401 #ifdef HAVE_AIRPCAP_API
3402 if(AdapterObject->Flags == INFO_FLAG_AIRPCAP_CARD)
3404 AirpcapStats tas;
3406 Res = (BOOLEAN)g_PAirpcapGetStats(AdapterObject->AirpcapAd, &tas);
3408 if (Res)
3410 s->bs_capt = tas.Capt;
3411 s->bs_drop = tas.Drops;
3412 s->bs_recv = tas.Recvs;
3413 s->ps_ifdrop = tas.IfDrops;
3416 TRACE_EXIT("PacketGetStatsEx");
3417 return Res;
3419 #endif // HAVE_AIRPCAP_API
3421 if (AdapterObject->Flags == INFO_FLAG_NDIS_ADAPTER)
3423 Res = (BOOLEAN)DeviceIoControl(AdapterObject->hFile,
3424 pBIOCGSTATS,
3425 NULL,
3427 &tmpstat,
3428 sizeof(struct bpf_stat),
3429 &BytesReturned,
3430 NULL);
3433 if (Res)
3435 s->bs_recv = tmpstat.bs_recv;
3436 s->bs_drop = tmpstat.bs_drop;
3437 s->ps_ifdrop = tmpstat.ps_ifdrop;
3438 s->bs_capt = tmpstat.bs_capt;
3441 else
3443 TRACE_PRINT1("Request to obtain statistics on an unknown device type (%u)", AdapterObject->Flags);
3444 Res = FALSE;
3446 TRACE_EXIT("PacketGetStatsEx");
3447 return Res;
3452 \brief Performs a query/set operation on an internal variable of the network card driver.
3453 \param AdapterObject Pointer to an _ADAPTER structure.
3454 \param Set Determines if the operation is a set (Set=TRUE) or a query (Set=FALSE).
3455 \param OidData A pointer to a _PACKET_OID_DATA structure that contains or receives the data.
3456 \return If the function succeeds, the return value is nonzero.
3458 \note not all the network adapters implement all the query/set functions. There is a set of mandatory
3459 OID functions that is granted to be present on all the adapters, and a set of facultative functions, not
3460 provided by all the cards (see the Microsoft DDKs to see which functions are mandatory). If you use a
3461 facultative function, be careful to enclose it in an if statement to check the result.
3463 BOOLEAN PacketRequest(LPADAPTER AdapterObject,BOOLEAN Set,PPACKET_OID_DATA OidData)
3465 DWORD BytesReturned;
3466 BOOLEAN Result;
3468 TRACE_ENTER("PacketRequest");
3470 #ifdef HAVE_NPFIM_API
3471 if(AdapterObject->Flags == INFO_FLAG_NPFIM_DEVICE)
3473 if (Set)
3475 TRACE_PRINT("PacketRequest SET not supported on NPFIM devices");
3476 TRACE_EXIT("PacketRequest");
3477 return FALSE;
3480 Result = (BOOLEAN)g_NpfImHandlers.NpfImIssueQueryOid(AdapterObject->NpfImHandle,
3481 OidData->Oid,
3482 OidData->Data,
3483 &OidData->Length);
3485 TRACE_EXIT("PacketRequest");
3486 return Result;
3488 #endif
3490 if(AdapterObject->Flags != INFO_FLAG_NDIS_ADAPTER)
3492 TRACE_PRINT("PacketRequest not supported on non-NPF/NPFIM adapters.");
3493 TRACE_EXIT("PacketRequest");
3494 return FALSE;
3497 Result=(BOOLEAN)DeviceIoControl(AdapterObject->hFile,(DWORD) Set ? (DWORD)pBIOCSETOID : (DWORD)pBIOCQUERYOID,
3498 OidData,sizeof(PACKET_OID_DATA)-1+OidData->Length,OidData,
3499 sizeof(PACKET_OID_DATA)-1+OidData->Length,&BytesReturned,NULL);
3501 // output some debug info
3502 TRACE_PRINT4("PacketRequest, OID=%.08x Length=%.05d Set=%.04d Res=%.04d",
3503 OidData->Oid,
3504 OidData->Length,
3505 Set,
3506 Result);
3508 TRACE_EXIT("PacketRequest");
3509 return Result;
3513 \brief Sets a hardware filter on the incoming packets.
3514 \param AdapterObject Pointer to an _ADAPTER structure.
3515 \param Filter The identifier of the filter.
3516 \return If the function succeeds, the return value is nonzero.
3518 The filter defined with this filter is evaluated by the network card, at a level that is under the NPF
3519 device driver. Here is a list of the most useful hardware filters (A complete list can be found in ntddndis.h):
3521 - NDIS_PACKET_TYPE_PROMISCUOUS: sets promiscuous mode. Every incoming packet is accepted by the adapter.
3522 - NDIS_PACKET_TYPE_DIRECTED: only packets directed to the workstation's adapter are accepted.
3523 - NDIS_PACKET_TYPE_BROADCAST: only broadcast packets are accepted.
3524 - NDIS_PACKET_TYPE_MULTICAST: only multicast packets belonging to groups of which this adapter is a member are accepted.
3525 - NDIS_PACKET_TYPE_ALL_MULTICAST: every multicast packet is accepted.
3526 - NDIS_PACKET_TYPE_ALL_LOCAL: all local packets, i.e. NDIS_PACKET_TYPE_DIRECTED + NDIS_PACKET_TYPE_BROADCAST + NDIS_PACKET_TYPE_MULTICAST
3528 BOOLEAN PacketSetHwFilter(LPADAPTER AdapterObject,ULONG Filter)
3530 BOOLEAN Status;
3531 ULONG IoCtlBufferLength=(sizeof(PACKET_OID_DATA)+sizeof(ULONG)-1);
3532 PPACKET_OID_DATA OidData;
3534 TRACE_ENTER("PacketSetHwFilter");
3536 #ifdef HAVE_AIRPCAP_API
3537 if(AdapterObject->Flags == INFO_FLAG_AIRPCAP_CARD)
3539 // Airpcap for the moment is always in promiscuous mode, and ignores any other filters
3540 return TRUE;
3542 #endif // HAVE_AIRPCAP_API
3544 #ifdef HAVE_NPFIM_API
3545 if(AdapterObject->Flags == INFO_FLAG_NPFIM_DEVICE)
3547 return TRUE;
3549 #endif // HAVE_NPFIM_API
3551 #ifdef HAVE_WANPACKET_API
3552 if(AdapterObject->Flags == INFO_FLAG_NDISWAN_ADAPTER)
3554 TRACE_EXIT("PacketSetHwFilter");
3555 return TRUE;
3557 #endif // HAVE_WANPACKET_API
3559 if (AdapterObject->Flags == INFO_FLAG_NDIS_ADAPTER)
3561 OidData=GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT,IoCtlBufferLength);
3562 if (OidData == NULL) {
3563 TRACE_PRINT("PacketSetHwFilter: GlobalAlloc Failed");
3564 TRACE_EXIT("PacketSetHwFilter");
3565 return FALSE;
3567 OidData->Oid=OID_GEN_CURRENT_PACKET_FILTER;
3568 OidData->Length=sizeof(ULONG);
3569 *((PULONG)OidData->Data)=Filter;
3570 Status=PacketRequest(AdapterObject,TRUE,OidData);
3571 GlobalFreePtr(OidData);
3573 else
3575 TRACE_PRINT1("Setting HW filter not supported on this adapter type (%u)", AdapterObject->Flags);
3576 Status = FALSE;
3579 TRACE_EXIT("PacketSetHwFilter");
3580 return Status;
3584 \brief Retrieve the list of available network adapters and their description.
3585 \param pStr User allocated string that will be filled with the names of the adapters.
3586 \param BufferSize Length of the buffer pointed by pStr. If the function fails, this variable contains the
3587 number of bytes that are needed to contain the adapter list.
3588 \return If the function succeeds, the return value is nonzero. If the return value is zero, BufferSize contains
3589 the number of bytes that are needed to contain the adapter list.
3591 Usually, this is the first function that should be used to communicate with the driver.
3592 It returns the names of the adapters installed on the system <B>and supported by WinPcap</B>.
3593 After the names of the adapters, pStr contains a string that describes each of them.
3595 After a call to PacketGetAdapterNames pStr contains, in succession:
3596 - a variable number of ASCII strings, each with the names of an adapter, separated by a "\0"
3597 - a double "\0"
3598 - a number of ASCII strings, each with the description of an adapter, separated by a "\0". The number
3599 of descriptions is the same of the one of names. The fisrt description corresponds to the first name, and
3600 so on.
3601 - a double "\0".
3604 BOOLEAN PacketGetAdapterNames(PTSTR pStr,PULONG BufferSize)
3606 PADAPTER_INFO TAdInfo;
3607 ULONG SizeNeeded = 0;
3608 ULONG SizeNames = 0;
3609 ULONG SizeDesc;
3610 ULONG OffDescriptions;
3612 TRACE_ENTER("PacketGetAdapterNames");
3614 TRACE_PRINT_OS_INFO();
3616 TRACE_PRINT2("Packet DLL version %s, Driver version %s", PacketLibraryVersion, PacketDriverVersion);
3618 TRACE_PRINT1("PacketGetAdapterNames: BufferSize=%u", *BufferSize);
3622 // Check the presence on some libraries we rely on, and load them if we found them
3624 PacketLoadLibrariesDynamically();
3627 // Create the adapter information list
3629 TRACE_PRINT("Populating the adapter list...");
3631 PacketPopulateAdaptersInfoList();
3633 WaitForSingleObject(g_AdaptersInfoMutex, INFINITE);
3635 if(!g_AdaptersInfoList)
3637 ReleaseMutex(g_AdaptersInfoMutex);
3638 *BufferSize = 0;
3640 TRACE_PRINT("No adapters found in the system. Failing.");
3642 SetLastError(ERROR_INSUFFICIENT_BUFFER);
3644 TRACE_EXIT("PacketGetAdapterNames");
3645 return FALSE; // No adapters to return
3649 // First scan of the list to calculate the offsets and check the sizes
3651 for(TAdInfo = g_AdaptersInfoList; TAdInfo != NULL; TAdInfo = TAdInfo->Next)
3653 if(TAdInfo->Flags != INFO_FLAG_DONT_EXPORT)
3655 // Update the size variables
3656 SizeNeeded += (ULONG)strlen(TAdInfo->Name) + (ULONG)strlen(TAdInfo->Description) + 2;
3657 SizeNames += (ULONG)strlen(TAdInfo->Name) + 1;
3661 // Check that we don't overflow the buffer.
3662 // Note: 2 is the number of additional separators needed inside the list
3663 if(SizeNeeded + 2 > *BufferSize || pStr == NULL)
3665 ReleaseMutex(g_AdaptersInfoMutex);
3667 TRACE_PRINT1("PacketGetAdapterNames: input buffer too small, we need %u bytes", *BufferSize);
3669 *BufferSize = SizeNeeded + 2; // Report the required size
3671 TRACE_EXIT("PacketGetAdapterNames");
3672 SetLastError(ERROR_INSUFFICIENT_BUFFER);
3673 return FALSE;
3676 OffDescriptions = SizeNames + 1;
3679 // Second scan of the list to copy the information
3681 for(TAdInfo = g_AdaptersInfoList, SizeNames = 0, SizeDesc = 0; TAdInfo != NULL; TAdInfo = TAdInfo->Next)
3683 if(TAdInfo->Flags != INFO_FLAG_DONT_EXPORT)
3685 // Copy the data
3686 StringCchCopyA(
3687 ((PCHAR)pStr) + SizeNames,
3688 *BufferSize - SizeNames,
3689 TAdInfo->Name);
3690 StringCchCopyA(
3691 ((PCHAR)pStr) + OffDescriptions + SizeDesc,
3692 *BufferSize - OffDescriptions - SizeDesc,
3693 TAdInfo->Description);
3695 // Update the size variables
3696 SizeNames += (ULONG)strlen(TAdInfo->Name) + 1;
3697 SizeDesc += (ULONG)strlen(TAdInfo->Description) + 1;
3701 // Separate the two lists
3702 ((PCHAR)pStr)[SizeNames] = 0;
3704 // End the list with a further \0
3705 ((PCHAR)pStr)[SizeNeeded + 1] = 0;
3708 ReleaseMutex(g_AdaptersInfoMutex);
3709 TRACE_EXIT("PacketGetAdapterNames");
3710 return TRUE;
3714 \brief Returns comprehensive information the addresses of an adapter.
3715 \param AdapterName String that contains the name of the adapter.
3716 \param buffer A user allocated array of npf_if_addr that will be filled by the function.
3717 \param NEntries Size of the array (in npf_if_addr).
3718 \return If the function succeeds, the return value is nonzero.
3720 This function grabs from the registry information like the IP addresses, the netmasks
3721 and the broadcast addresses of an interface. The buffer passed by the user is filled with
3722 npf_if_addr structures, each of which contains the data for a single address. If the buffer
3723 is full, the reaming addresses are dropeed, therefore set its dimension to sizeof(npf_if_addr)
3724 if you want only the first address.
3726 BOOLEAN PacketGetNetInfoEx(PCHAR AdapterName, npf_if_addr* buffer, PLONG NEntries)
3728 PADAPTER_INFO TAdInfo;
3729 PCHAR Tname;
3730 BOOLEAN Res, FreeBuff;
3732 TRACE_ENTER("PacketGetNetInfoEx");
3734 // Provide conversion for backward compatibility
3735 if(AdapterName[1] != 0)
3736 { //ASCII
3737 Tname = AdapterName;
3738 FreeBuff = FALSE;
3740 else
3742 Tname = WChar2SChar((PWCHAR)AdapterName);
3743 FreeBuff = TRUE;
3747 // Update the information about this adapter
3749 if(!PacketUpdateAdInfo(Tname))
3751 TRACE_PRINT("PacketGetNetInfoEx. Failed updating the adapter list. Failing.");
3752 if(FreeBuff)
3753 GlobalFreePtr(Tname);
3755 TRACE_EXIT("PacketGetNetInfoEx");
3757 return FALSE;
3760 WaitForSingleObject(g_AdaptersInfoMutex, INFINITE);
3761 // Find the PADAPTER_INFO structure associated with this adapter
3762 TAdInfo = PacketFindAdInfo(Tname);
3764 if(TAdInfo != NULL)
3766 TRACE_PRINT("Adapter found.");
3767 *NEntries = (TAdInfo->NNetworkAddresses < *NEntries)? TAdInfo->NNetworkAddresses: *NEntries;
3768 //TODO what if nentries = 0?
3769 if (*NEntries > 0)
3770 memcpy(buffer, TAdInfo->NetworkAddresses, *NEntries * sizeof(npf_if_addr));
3771 Res = TRUE;
3773 else
3775 TRACE_PRINT("PacketGetNetInfoEx: Adapter not found");
3776 Res = FALSE;
3779 ReleaseMutex(g_AdaptersInfoMutex);
3781 if(FreeBuff)GlobalFreePtr(Tname);
3783 TRACE_EXIT("PacketGetNetInfoEx");
3784 return Res;
3787 /*!
3788 \brief Returns information about the MAC type of an adapter.
3789 \param AdapterObject The adapter on which information is needed.
3790 \param type Pointer to a NetType structure that will be filled by the function.
3791 \return If the function succeeds, the return value is nonzero, otherwise the return value is zero.
3793 This function return the link layer and the speed (in bps) of an opened adapter.
3794 The LinkType field of the type parameter can have one of the following values:
3796 - NdisMedium802_3: Ethernet (802.3)
3797 - NdisMediumWan: WAN
3798 - NdisMedium802_5: Token Ring (802.5)
3799 - NdisMediumFddi: FDDI
3800 - NdisMediumAtm: ATM
3801 - NdisMediumArcnet878_2: ARCNET (878.2)
3803 BOOLEAN PacketGetNetType(LPADAPTER AdapterObject, NetType *type)
3805 PADAPTER_INFO TAdInfo;
3806 BOOLEAN ret;
3807 TRACE_ENTER("PacketGetNetType");
3809 WaitForSingleObject(g_AdaptersInfoMutex, INFINITE);
3810 // Find the PADAPTER_INFO structure associated with this adapter
3811 TAdInfo = PacketFindAdInfo(AdapterObject->Name);
3813 if(TAdInfo != NULL)
3815 TRACE_PRINT("Adapter found");
3816 // Copy the data
3817 memcpy(type, &(TAdInfo->LinkLayer), sizeof(struct NetType));
3818 ret = TRUE;
3820 else
3822 TRACE_PRINT("PacketGetNetType: Adapter not found");
3823 ret = FALSE;
3826 ReleaseMutex(g_AdaptersInfoMutex);
3828 TRACE_EXIT("PacketGetNetType");
3829 return ret;
3833 \brief Returns the AirPcap handler associated with an adapter. This handler can be used to change
3834 the wireless-related settings of the CACE Technologies AirPcap wireless capture adapters.
3835 \param AdapterObject the open adapter whose AirPcap handler is needed.
3836 \return a pointer to an open AirPcap handle, used internally by the adapter pointed by AdapterObject.
3837 NULL if the libpcap adapter doesn't have wireless support through AirPcap.
3839 PacketGetAirPcapHandle() allows to obtain the airpcap handle of an open adapter. This handle can be used with
3840 the AirPcap API functions to perform wireless-releated operations, e.g. changing the channel or enabling
3841 WEP decryption. For more details about the AirPcap wireless capture adapters, see
3842 http://www.cacetech.com/products/airpcap.htm.
3844 PAirpcapHandle PacketGetAirPcapHandle(LPADAPTER AdapterObject)
3846 PAirpcapHandle handle = NULL;
3847 TRACE_ENTER("PacketGetAirPcapHandle");
3849 #ifdef HAVE_AIRPCAP_API
3850 if (AdapterObject->Flags == INFO_FLAG_AIRPCAP_CARD)
3852 handle = AdapterObject->AirpcapAd;
3854 #else
3855 UNUSED(AdapterObject);
3856 #endif // HAVE_AIRPCAP_API
3858 TRACE_EXIT("PacketGetAirPcapHandle");
3859 return handle;
3862 /* @} */