2 * Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy)
3 * Copyright (c) 2005 - 2006 CACE Technologies, Davis (California)
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the Politecnico di Torino, CACE Technologies
16 * nor the names of its contributors may be used to endorse or promote
17 * products derived from this software without specific prior written
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 #pragma warning (disable : 4127) //conditional expression is constant. Used for do{}while(FALSE) loops.
39 #pragma warning (disable : 4710) // inline function not expanded. used for strsafe functions
46 #include "Packet32-Int.h"
48 #ifdef HAVE_WANPACKET_API
49 #include "wanpacket/wanpacket.h"
50 #endif //HAVE_WANPACKET_API
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
61 #pragma message ("Compiling Packet.dll for WINNT4 only")
64 #ifdef HAVE_AIRPCAP_API
65 #pragma message ("Compiling Packet.dll with support for AirPcap")
69 #pragma message ("Compiling Packet.dll with support for NpfIm driver")
73 #pragma message ("Compiling Packet.dll with support for DAG cards")
76 #ifdef HAVE_WANPACKET_API
77 #pragma message ("Compiling Packet.dll with support for WanPacket (aka Dialup thru NetMon)")
80 #ifdef HAVE_IPHELPER_API
81 #pragma message ("Compiling Packet.dll with support from IP helper API for API addresses")
85 #define UNUSED(_x) (_x)
90 LONG
PacketDumpRegistryKey(PCHAR KeyName
, PCHAR FileName
);
91 CHAR g_LogFileName
[1024] = "winpcap_debug.txt";
92 #endif //_DEBUG_TO_FILE
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
)(
130 PIP_ADAPTER_ADDRESSES
,
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
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 //---------------------------------------------------------------------------
192 \brief The main dll function.
195 BOOL APIENTRY
DllMain(HANDLE DllHandle
,DWORD Reason
,LPVOID lpReserved
)
198 PADAPTER_INFO NewAdInfo
;
199 TCHAR DllFileName
[MAX_PATH
];
205 case DLL_PROCESS_ATTACH
:
207 TRACE_PRINT_DLLMAIN("************Packet32: DllMain************");
211 #ifdef HAVE_WANPACKET_API
213 #endif // HAVE_WANPACKET_API
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}",
223 PacketDumpRegistryKey("HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\Tcpip",
225 PacketDumpRegistryKey("HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services",
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
));
253 case DLL_PROCESS_DETACH
:
255 CloseHandle(g_AdaptersInfoMutex
);
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
275 #endif // WPCAP_OEM_UNLOAD_H
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
299 #endif // HAVE_IPHELPER_API
301 #ifdef HAVE_AIRPCAP_API
303 #endif // HAVE_DAG_API
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");
329 // Locate GetAdaptersAddresses dinamically since it is not present in Win2k
332 #ifdef HAVE_IPHELPER_API
333 IPHMod
= GetModuleHandle(TEXT("Iphlpapi"));
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");
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
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");
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");
430 BOOLEAN QueryWinPcapRegistryStringA(CHAR *SubKeyName,
440 if (QveRes = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
441 WINPCAP_INSTANCE_KEY,
444 &hWinPcapKey) != ERROR_SUCCESS)
448 SetLastError(QveRes);
454 // Query the requested value
456 QveRes = RegQueryValueExA(hWinPcapKey,
463 RegCloseKey(hWinPcapKey);
465 if (QveRes == ERROR_SUCCESS)
467 //let's check that the key is text
472 SetLastError(ERROR_INVALID_DATA);
482 if (QveRes == ERROR_MORE_DATA)
485 //the needed bytes are already set by RegQueryValueExA
488 SetLastError(QveRes);
496 ODSEx("QueryWinpcapRegistryKey, RegQueryValueEx failed, code %d",QveRes);
498 //JUST CONTINUE WITH THE DEFAULT VALUE
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);
514 strcpy(Value, DefaultVal);
515 *pValueLen = strlen(DefaultVal) + 1;
521 BOOLEAN QueryWinPcapRegistryStringW(WCHAR *SubKeyName,
530 DWORD InternalLenBytes;
532 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
533 WINPCAP_INSTANCE_KEY_WIDECHAR,
536 &hWinPcapKey) != ERROR_SUCCESS)
542 InternalLenBytes = *pValueLen * 2;
545 // Query the requested value
547 QveRes = RegQueryValueExW(hWinPcapKey,
554 RegCloseKey(hWinPcapKey);
556 if (QveRes == ERROR_SUCCESS)
558 //let's check that the key is text
562 SetLastError(ERROR_INVALID_DATA);
568 *pValueLen = wcslen(Value) + 1;
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);
593 ODSEx("QueryWinpcapRegistryKey, RegQueryValueEx failed, code %d\n",QveRes);
595 //JUST CONTINUE WITH THE DEFAULT VALUE
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);
611 wcscpy(Value, DefaultVal);
612 *pValueLen = wcslen(DefaultVal) + 1;
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
)
634 for (i
= 0; i
< 4; i
++) {
636 while ((c
= *cp
++) != '\0' && c
!= '.') {
637 if (c
< '0' || c
> '9')
639 part
= part
*10 + (c
- '0');
643 val
= val
| (part
<< i
*8);
646 return (ULONG
)-1; // extra gunk at end of string
649 return (ULONG
)-1; // string ends early
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
)
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));
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
)
678 TmpStr
= (CHAR
*) GlobalAllocPtr(GMEM_MOVEABLE
| GMEM_ZEROINIT
, (DWORD
)(wcslen(string
)+2));
687 (DWORD
)(wcslen(string
)+2), // size of buffer
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
)
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");
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");
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
)
749 TRACE_ENTER("PacketSetReadEvt");
751 if (AdapterObject
->ReadEvent
!= NULL
)
753 SetLastError(ERROR_INVALID_FUNCTION
);
757 hEvent
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
761 //SetLastError done by CreateEvent
762 TRACE_EXIT("PacketSetReadEvt");
766 if(DeviceIoControl(AdapterObject
->hFile
,
775 DWORD dwLastError
= GetLastError();
779 SetLastError(dwLastError
);
781 TRACE_EXIT("PacketSetReadEvt");
785 AdapterObject
->ReadEvent
= hEvent
;
786 AdapterObject
->ReadTimeOut
=0;
788 TRACE_EXIT("PacketSetReadEvt");
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
;
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;
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)
826 // len = sizeof(driverDesc)/sizeof(driverDesc[0]);
827 // if (QueryWinPcapRegistryStringA(NPF_SERVICE_DESC_REG_KEY, driverDesc, &len, NPF_SERVICE_DESC) == FALSE && len == 0)
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)
834 scmHandle
= OpenSCManager(NULL
, NULL
, SC_MANAGER_ALL_ACCESS
);
836 if(scmHandle
== NULL
)
839 svcHandle
= CreateServiceA(scmHandle
,
843 SERVICE_KERNEL_DRIVER
,
844 SERVICE_DEMAND_START
,
845 SERVICE_ERROR_NORMAL
,
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
861 TRACE_PRINT("Created service for npf.sys");
862 //Created service for npf.sys
866 if (svcHandle
!= NULL
)
867 CloseServiceHandle(svcHandle
);
871 TRACE_PRINT1("PacketInstallDriver failed, Error=%u",err
);
874 CloseServiceHandle(scmHandle
);
876 TRACE_EXIT("PacketInstallDriver");
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
)
896 TRACE_ENTER("PacketDumpRegistryKey");
897 StringCchPrintfA(Command
, sizeof(Command
), "regedit /e %s %s", FileName
, KeyName
);
899 /// Let regedit do the dirty work for us
902 TRACE_EXIT("PacketDumpRegistryKey");
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'
921 UINT cbTranslate
, dwBytes
;
926 // Structure used to store enumerated languages and code pages.
927 struct LANGANDCODEPAGE
{
932 TRACE_ENTER("PacketGetFileVersion");
934 // Now lets dive in and pull out the version information:
935 dwVerInfoSize
= GetFileVersionInfoSize(FileName
, &dwVerHnd
);
938 lpstrVffInfo
= GlobalAllocPtr(GMEM_MOVEABLE
, dwVerInfoSize
);
939 if (lpstrVffInfo
== NULL
)
941 TRACE_PRINT("PacketGetFileVersion: failed to allocate memory");
942 TRACE_EXIT("PacketGetFileVersion");
946 if(!GetFileVersionInfo(FileName
, dwVerHnd
, dwVerInfoSize
, lpstrVffInfo
))
948 TRACE_PRINT("PacketGetFileVersion: failed to call GetFileVersionInfo");
949 GlobalFreePtr(lpstrVffInfo
);
950 TRACE_EXIT("PacketGetFileVersion");
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");
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");
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");
991 StringCchCopyA(VersionBuff
, VersionBuffLen
, TmpStr
);
993 GlobalFreePtr(lpstrVffInfo
);
994 GlobalFreePtr(TmpStr
);
999 TRACE_PRINT1("PacketGetFileVersion: failed to call GetFileVersionInfoSize, LastError = %8.8x", GetLastError());
1000 TRACE_EXIT("PacketGetFileVersion");
1005 TRACE_EXIT("PacketGetFileVersion");
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
;
1022 SC_HANDLE svcHandle
= NULL
;
1023 SC_HANDLE scmHandle
= NULL
;
1026 SERVICE_STATUS SStat
;
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
);
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)
1058 // //just use an empty string string for the service name
1059 // NpfDriverName[0] = '\0';
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
,
1075 if(KeyRes
!= ERROR_SUCCESS
)
1077 TRACE_PRINT("NPF registry key not present, trying to install the driver.");
1078 Result
= PacketInstallDriver();
1082 TRACE_PRINT("NPF registry key present, driver is installed.");
1084 RegCloseKey(PathKey
);
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
);
1097 switch (SStat
.dwCurrentState
)
1099 case SERVICE_CONTINUE_PENDING
:
1100 TRACE_PRINT("The status of the driver is: SERVICE_CONTINUE_PENDING");
1102 case SERVICE_PAUSE_PENDING
:
1103 TRACE_PRINT("The status of the driver is: SERVICE_PAUSE_PENDING");
1105 case SERVICE_PAUSED
:
1106 TRACE_PRINT("The status of the driver is: SERVICE_PAUSED");
1108 case SERVICE_RUNNING
:
1109 TRACE_PRINT("The status of the driver is: SERVICE_RUNNING");
1111 case SERVICE_START_PENDING
:
1112 TRACE_PRINT("The status of the driver is: SERVICE_START_PENDING");
1114 case SERVICE_STOP_PENDING
:
1115 TRACE_PRINT("The status of the driver is: SERVICE_STOP_PENDING");
1117 case SERVICE_STOPPED
:
1118 TRACE_PRINT("The status of the driver is: SERVICE_STOPPED");
1122 TRACE_PRINT("The status of the driver is: unknown");
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
);
1147 CloseServiceHandle( svcHandle
);
1153 error
= GetLastError();
1154 TRACE_PRINT1("OpenService failed! Error=%8.8x", error
);
1155 SetLastError(error
);
1160 if(KeyRes
!= ERROR_SUCCESS
)
1161 Result
= PacketInstallDriver();
1167 svcHandle
= OpenServiceA(scmHandle
,
1170 if (svcHandle
!= NULL
)
1173 QuerySStat
= QueryServiceStatus(svcHandle
, &SStat
);
1176 switch (SStat
.dwCurrentState
)
1178 case SERVICE_CONTINUE_PENDING
:
1179 TRACE_PRINT("The status of the driver is: SERVICE_CONTINUE_PENDING");
1181 case SERVICE_PAUSE_PENDING
:
1182 TRACE_PRINT("The status of the driver is: SERVICE_PAUSE_PENDING");
1184 case SERVICE_PAUSED
:
1185 TRACE_PRINT("The status of the driver is: SERVICE_PAUSED");
1187 case SERVICE_RUNNING
:
1188 TRACE_PRINT("The status of the driver is: SERVICE_RUNNING");
1190 case SERVICE_START_PENDING
:
1191 TRACE_PRINT("The status of the driver is: SERVICE_START_PENDING");
1193 case SERVICE_STOP_PENDING
:
1194 TRACE_PRINT("The status of the driver is: SERVICE_STOP_PENDING");
1196 case SERVICE_STOPPED
:
1197 TRACE_PRINT("The status of the driver is: SERVICE_STOPPED");
1201 TRACE_PRINT("The status of the driver is: unknown");
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
);
1223 CloseServiceHandle( svcHandle
);
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
);
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
));
1261 ZeroMemory(SymbolicLinkA
, sizeof(SymbolicLinkA
));
1266 if (strlen(AdapterNameA
) > strlen(DEVICE_PREFIX
))
1268 StringCchPrintfA(SymbolicLinkA
, MAX_PATH
, "\\\\.\\Global\\%s", AdapterNameA
+ strlen(DEVICE_PREFIX
));
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
);
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");
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
);
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
,
1346 if (lpAdapter
== NULL
)
1348 TRACE_PRINT("GlobalAlloc failed allocating memory for the ADAPTER structure. Failing (BAD_UNIT).");
1349 dwLastError
= ERROR_NOT_ENOUGH_MEMORY
;
1353 lpAdapter
->Flags
= INFO_FLAG_NDISWAN_ADAPTER
;
1355 TRACE_PRINT("Trying to open the Wan Adapter through WanPacket.dll...");
1358 lpAdapter
->pWanAdapter
= WanPacketOpenAdapter();
1360 if (lpAdapter
->pWanAdapter
== NULL
)
1362 TRACE_PRINT("WanPacketOpenAdapter failed. Failing. (BAD_UNIT)");
1363 dwLastError
= ERROR_BAD_UNIT
;
1367 StringCchCopyA(lpAdapter
->Name
, ADAPTER_NAME_LENGTH
, AdapterName
);
1369 lpAdapter
->ReadEvent
= WanPacketGetReadEvent(lpAdapter
->pWanAdapter
);
1371 TRACE_PRINT("Successfully opened the Wan Adapter.");
1375 if (dwLastError
== ERROR_SUCCESS
)
1377 TRACE_EXIT("PacketOpenAdapterWanPacket");
1382 if (lpAdapter
!= NULL
) GlobalFree(lpAdapter
);
1384 TRACE_EXIT("PacketOpenAdapterWanPacket");
1385 SetLastError(dwLastError
);
1389 #endif //HAVE_WANPACKET_API
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
1413 lpAdapter
= (LPADAPTER
) GlobalAllocPtr(GMEM_MOVEABLE
| GMEM_ZEROINIT
,
1415 if (lpAdapter
== NULL
)
1421 // Indicate that this is a aircap card
1423 lpAdapter
->Flags
= INFO_FLAG_AIRPCAP_CARD
;
1428 lpAdapter
->AirpcapAd
= g_PAirpcapOpen(AdapterName
, Ebuf
);
1430 if(lpAdapter
->AirpcapAd
== NULL
)
1432 GlobalFreePtr(lpAdapter
);
1436 StringCchCopyA(lpAdapter
->Name
, ADAPTER_NAME_LENGTH
, AdapterName
);
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
,
1450 if (lpAdapter
== NULL
)
1456 // Indicate that this is a aircap card
1458 lpAdapter
->Flags
= INFO_FLAG_NPFIM_DEVICE
;
1464 if (g_NpfImHandlers
.NpfImOpenDevice(AdapterName
, (NPF_IM_DEV_HANDLE
*)&lpAdapter
->NpfImHandle
) == FALSE
)
1466 GlobalFreePtr(lpAdapter
);
1470 StringCchCopyA(lpAdapter
->Name
, ADAPTER_NAME_LENGTH
, AdapterName
);
1474 #endif // HAVE_NpfIm_API
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()
1486 static LPADAPTER
PacketOpenAdapterDAG(PCHAR AdapterName
, BOOLEAN IsAFile
)
1488 CHAR DagEbuf
[DAGC_ERRBUF_SIZE
];
1489 LPADAPTER lpAdapter
;
1494 DWORD lpcbdata
= sizeof(fpc
);
1498 TRACE_ENTER("PacketOpenAdapterDAG");
1501 lpAdapter
= (LPADAPTER
) GlobalAllocPtr(GMEM_MOVEABLE
| GMEM_ZEROINIT
,
1503 if (lpAdapter
== NULL
)
1505 TRACE_PRINT("GlobalAlloc failed allocating memory for the ADAPTER structure");
1506 TRACE_EXIT("PacketOpenAdapterDAG");
1512 // We must add an entry to the adapter description list, otherwise many function will not
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
);
1522 // Flag that this is a DAG file
1523 lpAdapter
->Flags
= INFO_FLAG_DAG_FILE
;
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")):
1541 StringCchPrintfW(keyname
, sizeof(keyname
)/sizeof(keyname
[0]), L
"%s\\CardParams\\%ws",
1542 L
"SYSTEM\\CurrentControlSet\\Services\\DAG",
1549 status
= RegOpenKeyEx(HKEY_LOCAL_MACHINE
, keyname
, 0 , KEY_READ
, &dagkey
);
1550 if(status
!= ERROR_SUCCESS
)
1553 status
= RegQueryValueEx(dagkey
,
1560 if(status
== ERROR_SUCCESS
)
1561 lpAdapter
->DagFastProcess
= fpc
;
1563 RegCloseKey(dagkey
);
1568 TRACE_PRINT("Trying to open the DAG device...");
1572 lpAdapter
->pDagCard
= g_p_dagc_open(AdapterName
,
1576 if(lpAdapter
->pDagCard
== NULL
)
1578 TRACE_PRINT("Failed opening the DAG device");
1579 TRACE_EXIT("PacketOpenAdapterDAG");
1580 GlobalFreePtr(lpAdapter
);
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");
1594 #endif // HAVE_DAG_API
1597 //---------------------------------------------------------------------------
1599 //---------------------------------------------------------------------------
1601 /** @ingroup packetapi
1605 /** @defgroup packet32 Packet.dll exported functions and variables
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
;
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
;
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
;
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");
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)
1666 scmHandle
= OpenSCManager(NULL
, NULL
, SC_MANAGER_ALL_ACCESS
);
1668 if(scmHandle
!= NULL
){
1670 TRACE_PRINT("Opened the SCM");
1672 schService
= OpenServiceA (scmHandle
,
1677 if (schService
!= NULL
)
1679 TRACE_PRINT("Opened the NPF service in the SCM");
1681 ret
= ControlService (schService
,
1682 SERVICE_CONTROL_STOP
,
1687 TRACE_PRINT("Failed to stop the NPF service");
1691 TRACE_PRINT("NPF service stopped");
1694 CloseServiceHandle (schService
);
1696 CloseServiceHandle(scmHandle
);
1701 TRACE_EXIT("PacketStopDriver");
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
;
1718 PADAPTER_INFO TAdInfo
;
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)
1742 bFreeAdapterNameA
= FALSE
;
1743 AdapterNameA
= AdapterNameWA
;
1750 size_t bufferSize
= wcslen((PWCHAR
)AdapterNameWA
) + 1;
1752 AdapterNameA
= GlobalAllocPtr(GPTR
, bufferSize
);
1754 if (AdapterNameA
== NULL
)
1756 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1760 StringCchPrintfA(AdapterNameA
, bufferSize
, "%ws", (PWCHAR
)AdapterNameWA
);
1761 bFreeAdapterNameA
= TRUE
;
1765 WaitForSingleObject(g_AdaptersInfoMutex
, INFINITE
);
1766 #endif // not 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
);
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...");
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....
1815 TRACE_PRINT("Opened the adapter as a DAG/ERF file.");
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();
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
;
1852 // Airpcap provides a read event
1854 if(!g_PAirpcapGetReadEvent(lpAdapter
->AirpcapAd
, &lpAdapter
->ReadEvent
))
1856 PacketCloseAdapter(lpAdapter
);
1857 dwLastError
= ERROR_BAD_UNIT
;
1861 dwLastError
= ERROR_SUCCESS
;
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
;
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
);
1892 dwLastError
= ERROR_SUCCESS
;
1897 #endif // HAVE_NPFIM_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
;
1914 dwLastError
= ERROR_SUCCESS
;
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
;
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
;
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();
1962 ReleaseMutex(g_AdaptersInfoMutex
);
1965 if (bFreeAdapterNameA
) GlobalFree(AdapterNameA
);
1968 if (dwLastError
!= ERROR_SUCCESS
)
1970 TRACE_EXIT("PacketOpenAdapter");
1971 SetLastError(dwLastError
);
1977 TRACE_EXIT("PacketOpenAdapter");
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");
1995 TRACE_PRINT("PacketCloseAdapter: attempt to close a NULL adapter");
1996 TRACE_EXIT("PacketCloseAdapter");
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
);
2010 #ifdef HAVE_AIRPCAP_API
2011 if(lpAdapter
->Flags
== INFO_FLAG_AIRPCAP_CARD
)
2013 g_PAirpcapClose(lpAdapter
->AirpcapAd
);
2014 GlobalFreePtr(lpAdapter
);
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
);
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
);
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
);
2049 SetEvent(lpAdapter
->ReadEvent
);
2050 CloseHandle(lpAdapter
->ReadEvent
);
2051 CloseHandle(lpAdapter
->hFile
);
2052 GlobalFreePtr(lpAdapter
);
2053 TRACE_EXIT("PacketCloseAdapter");
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)
2074 TRACE_ENTER("PacketAllocatePacket");
2076 lpPacket
=(LPPACKET
)GlobalAllocPtr(GMEM_MOVEABLE
| GMEM_ZEROINIT
,sizeof(PACKET
));
2079 TRACE_PRINT("PacketAllocatePacket: GlobalAlloc Failed");
2082 TRACE_EXIT("PacketAllocatePacket");
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");
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");
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
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
)
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");
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
);
2193 // g_PAirpcapRead always returns immediately.
2195 res
= (BOOLEAN
)g_PAirpcapRead(AdapterObject
->AirpcapAd
,
2198 &lpPacket
->ulBytesReceived
);
2200 TRACE_EXIT("PacketReceivePacket");
2204 #endif // HAVE_AIRPCAP_API
2206 #ifdef HAVE_NPFIM_API
2207 if(AdapterObject
->Flags
== INFO_FLAG_NPFIM_DEVICE
)
2211 // NpfImReceivePacket performs its own wait internally.
2214 res
= (BOOLEAN
)g_NpfImHandlers
.NpfImReceivePackets(AdapterObject
->NpfImHandle
,
2217 &lpPacket
->ulBytesReceived
);
2219 TRACE_EXIT("PacketReceivePacket");
2223 #endif // HAVE_NPFIM_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");
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
);
2246 TRACE_PRINT1("Request to read on an unknown device type (%u)", AdapterObject
->Flags
);
2250 TRACE_EXIT("PacketReceivePacket");
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
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
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
;
2287 TRACE_ENTER("PacketSendPacket");
2291 #ifdef HAVE_AIRPCAP_API
2292 if(AdapterObject
->Flags
== INFO_FLAG_AIRPCAP_CARD
)
2296 Result
= (BOOLEAN
)g_PAirpcapWrite(AdapterObject
->AirpcapAd
, lpPacket
->Buffer
, lpPacket
->Length
);
2297 TRACE_EXIT("PacketSetMinToCopy");
2303 TRACE_EXIT("PacketSetMinToCopy");
2304 TRACE_PRINT("Transmission not supported with this version of AirPcap");
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");
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");
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
);
2337 TRACE_PRINT1("Request to write on an unknown device type (%u)", AdapterObject
->Flags
);
2341 TRACE_EXIT("PacketSendPacket");
2346 \brief Sends a buffer of packets to the network.
2347 \param AdapterObject Pointer to an _ADAPTER structure identifying the network adapter that will
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
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
)
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");
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");
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");
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
,
2433 TotBytesTransfered
+= BytesTransfered
;
2435 // Exit from the loop on termination or error
2436 if(TotBytesTransfered
>= Size
|| Res
!= TRUE
)
2439 // calculate the time interval to wait before sending the next packet
2440 TargetTicks
.QuadPart
= StartTicks
.QuadPart
+
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
);
2455 TRACE_PRINT1("Request to write on an unknown device type (%u)", AdapterObject
->Flags
);
2456 TotBytesTransfered
= 0;
2459 TRACE_EXIT("PacketSendPackets");
2461 return TotBytesTransfered
;
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
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
;
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");
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");
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");
2516 #endif // HAVE_AIRPCAP_API
2519 if(AdapterObject
->Flags
& INFO_FLAG_DAG_CARD
)
2521 TRACE_EXIT("PacketSetMinToCopy");
2522 // No mintocopy with DAGs
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
);
2533 TRACE_PRINT1("Request to set mintocopy on an unknown device type (%u)", AdapterObject
->Flags
);
2537 TRACE_EXIT("PacketSetMinToCopy");
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
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
;
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");
2593 #endif // HAVE_WANPACKET_API
2595 #ifdef HAVE_AIRPCAP_API
2596 if (AdapterObject
->Flags
== INFO_FLAG_AIRPCAP_CARD
)
2598 if (mode
== PACKET_MODE_CAPT
)
2607 TRACE_EXIT("PacketSetMode");
2611 #endif //HAVE_AIRPCAP_API
2613 #ifdef HAVE_NPFIM_API
2614 if (AdapterObject
->Flags
== INFO_FLAG_NPFIM_DEVICE
)
2616 if (mode
== PACKET_MODE_CAPT
)
2625 TRACE_EXIT("PacketSetMode");
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
);
2637 TRACE_PRINT1("Request to set mode on an unknown device type (%u)", AdapterObject
->Flags
);
2641 TRACE_EXIT("PacketSetMode");
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
;
2666 WCHAR NameWithPath
[1024];
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");
2679 if(((PUCHAR
)name
)[1]!=0 && len
>1){ //ASCII
2680 FileName
=SChar2WChar(name
);
2687 TStrLen
=GetFullPathName(FileName
,1024,NameWithPath
,&NamePos
);
2689 len
=TStrLen
*2+2; //add the terminating null character
2691 // Try to catch malformed strings
2693 if(((PUCHAR
)name
)[1]!=0 && len
>1) free(FileName
);
2695 TRACE_EXIT("PacketSetDumpName");
2700 res
= (BOOLEAN
)DeviceIoControl(AdapterObject
->hFile
,pBIOCSETDUMPFILENAME
,NameWithPath
,len
,NULL
,0,&BytesReturned
,NULL
);
2703 TRACE_EXIT("PacketSetDumpName");
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
;
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");
2737 valbuff
[0] = maxfilesize
;
2738 valbuff
[1] = maxnpacks
;
2740 Result
= (BOOLEAN
)DeviceIoControl(AdapterObject
->hFile
,
2749 TRACE_EXIT("PacketSetDumpLimits");
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
;
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");
2786 WaitForSingleObject(AdapterObject
->ReadEvent
, INFINITE
);
2788 res
= (BOOLEAN
)DeviceIoControl(AdapterObject
->hFile
,
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
;
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");
2852 Result
= (BOOLEAN
)DeviceIoControl(AdapterObject
->hFile
,pBIOCSWRITEREP
,&nwrites
,4,NULL
,0,&BytesReturned
,NULL
);
2854 TRACE_EXIT("PacketSetNumWrites");
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
)
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");
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");
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");
2914 #endif // HAVE_AIRPCAP_API
2917 // Under DAG, we simply store the timeout value and then
2918 if(AdapterObject
->Flags
& INFO_FLAG_DAG_CARD
)
2922 // tell DAG card to return immediately
2923 AdapterObject
->DagReadTimeout
.tv_sec
= 0;
2924 AdapterObject
->DagReadTimeout
.tv_usec
= 0;
2930 // tell the DAG card to wait forvever
2931 AdapterObject
->DagReadTimeout
.tv_sec
= -1;
2932 AdapterObject
->DagReadTimeout
.tv_usec
= -1;
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");
2945 #endif // HAVE_DAG_API
2947 if(AdapterObject
->Flags
== INFO_FLAG_NDIS_ADAPTER
)
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
);
2960 TRACE_EXIT("PacketSetReadTimeout");
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
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
;
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");
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");
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");
3016 #endif // HAVE_NPFIM_API
3019 if(AdapterObject
->Flags
== INFO_FLAG_DAG_CARD
)
3021 // We can't change DAG buffers
3022 TRACE_EXIT("PacketSetBuff");
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
);
3033 TRACE_PRINT1("Request to set buf size on an unknown device type (%u)", AdapterObject
->Flags
);
3037 TRACE_EXIT("PacketSetBuff");
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
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
;
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");
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");
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
,
3095 fp
->bf_len
* sizeof(struct bpf_insn
));
3097 TRACE_EXIT("PacketSetBpf");
3100 #endif // HAVE_NPFIM_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");
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
);
3117 TRACE_PRINT1("Request to set BPF filter on an unknown device type (%u)", AdapterObject
->Flags
);
3121 TRACE_EXIT("PacketSetBpf");
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
;
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");
3153 result
= (BOOLEAN
)DeviceIoControl(AdapterObject
->hFile
,
3162 TRACE_EXIT("PacketSetLoopbackBehavior");
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
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
3181 INT
PacketSetSnapLen(LPADAPTER AdapterObject
, int snaplen
)
3185 TRACE_ENTER("PacketSetSnapLen");
3188 UNUSED(AdapterObject
);
3191 if(AdapterObject
->Flags
& INFO_FLAG_DAG_CARD
)
3192 Result
= g_p_dagc_setsnaplen(AdapterObject
->pDagCard
, snaplen
);
3194 #endif // HAVE_DAG_API
3197 TRACE_EXIT("PacketSetSnapLen");
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
)
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
)
3229 Res
= (BOOLEAN
)g_PAirpcapGetStats(AdapterObject
->AirpcapAd
, &tas
);
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");
3245 #endif // HAVE_AIRPCAP_API
3247 #ifdef HAVE_NPFIM_API
3248 if(AdapterObject
->Flags
== INFO_FLAG_NPFIM_DEVICE
)
3253 Res
= (BOOLEAN
)g_NpfImHandlers
.NpfImGetCaptureStatistics(AdapterObject
->NpfImHandle
, stats
, sizeof(stats
), &neededBytes
);
3257 // if (stats[NPFIM_CAPTURE_STATS_RECEIVED] < 0xFFFFFFFF)
3258 // s->bs_capt = (UINT)stats[NPFIM_CAPTURE_STATS_RECEIVED];
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
];
3265 s
->bs_drop
= 0xFFFFFFFF;
3267 if (stats
[NPFIM_CAPTURE_STATS_ACCEPTED
] < 0xFFFFFFFF)
3268 s
->bs_recv
= (UINT
)stats
[NPFIM_CAPTURE_STATS_ACCEPTED
];
3270 s
->bs_recv
= 0xFFFFFFFF;
3275 TRACE_EXIT("PacketGetStats");
3278 #endif // HAVE_AIRPCAP_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");
3300 TRACE_EXIT("PacketGetStats");
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");
3321 #endif // HAVE_WANPACKET_API
3323 if (AdapterObject
->Flags
== INFO_FLAG_NDIS_ADAPTER
)
3325 Res
= (BOOLEAN
)DeviceIoControl(AdapterObject
->hFile
,
3330 sizeof(struct bpf_stat
),
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
;
3345 TRACE_PRINT1("Request to obtain statistics on an unknown device type (%u)", AdapterObject
->Flags
);
3348 TRACE_EXIT("PacketGetStats");
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
)
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");
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
;
3384 s
->bs_capt
= (ULONG
)DagStats
.captured
;
3386 TRACE_EXIT("PacketGetStatsEx");
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");
3399 #endif // HAVE_WANPACKET_API
3401 #ifdef HAVE_AIRPCAP_API
3402 if(AdapterObject
->Flags
== INFO_FLAG_AIRPCAP_CARD
)
3406 Res
= (BOOLEAN
)g_PAirpcapGetStats(AdapterObject
->AirpcapAd
, &tas
);
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");
3419 #endif // HAVE_AIRPCAP_API
3421 if (AdapterObject
->Flags
== INFO_FLAG_NDIS_ADAPTER
)
3423 Res
= (BOOLEAN
)DeviceIoControl(AdapterObject
->hFile
,
3428 sizeof(struct bpf_stat
),
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
;
3443 TRACE_PRINT1("Request to obtain statistics on an unknown device type (%u)", AdapterObject
->Flags
);
3446 TRACE_EXIT("PacketGetStatsEx");
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
;
3468 TRACE_ENTER("PacketRequest");
3470 #ifdef HAVE_NPFIM_API
3471 if(AdapterObject
->Flags
== INFO_FLAG_NPFIM_DEVICE
)
3475 TRACE_PRINT("PacketRequest SET not supported on NPFIM devices");
3476 TRACE_EXIT("PacketRequest");
3480 Result
= (BOOLEAN
)g_NpfImHandlers
.NpfImIssueQueryOid(AdapterObject
->NpfImHandle
,
3485 TRACE_EXIT("PacketRequest");
3490 if(AdapterObject
->Flags
!= INFO_FLAG_NDIS_ADAPTER
)
3492 TRACE_PRINT("PacketRequest not supported on non-NPF/NPFIM adapters.");
3493 TRACE_EXIT("PacketRequest");
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",
3508 TRACE_EXIT("PacketRequest");
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
)
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
3542 #endif // HAVE_AIRPCAP_API
3544 #ifdef HAVE_NPFIM_API
3545 if(AdapterObject
->Flags
== INFO_FLAG_NPFIM_DEVICE
)
3549 #endif // HAVE_NPFIM_API
3551 #ifdef HAVE_WANPACKET_API
3552 if(AdapterObject
->Flags
== INFO_FLAG_NDISWAN_ADAPTER
)
3554 TRACE_EXIT("PacketSetHwFilter");
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");
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
);
3575 TRACE_PRINT1("Setting HW filter not supported on this adapter type (%u)", AdapterObject
->Flags
);
3579 TRACE_EXIT("PacketSetHwFilter");
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"
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
3604 BOOLEAN
PacketGetAdapterNames(PTSTR pStr
,PULONG BufferSize
)
3606 PADAPTER_INFO TAdInfo
;
3607 ULONG SizeNeeded
= 0;
3608 ULONG SizeNames
= 0;
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
);
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
);
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
)
3687 ((PCHAR
)pStr
) + SizeNames
,
3688 *BufferSize
- SizeNames
,
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");
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
;
3730 BOOLEAN Res
, FreeBuff
;
3732 TRACE_ENTER("PacketGetNetInfoEx");
3734 // Provide conversion for backward compatibility
3735 if(AdapterName
[1] != 0)
3737 Tname
= AdapterName
;
3742 Tname
= WChar2SChar((PWCHAR
)AdapterName
);
3747 // Update the information about this adapter
3749 if(!PacketUpdateAdInfo(Tname
))
3751 TRACE_PRINT("PacketGetNetInfoEx. Failed updating the adapter list. Failing.");
3753 GlobalFreePtr(Tname
);
3755 TRACE_EXIT("PacketGetNetInfoEx");
3760 WaitForSingleObject(g_AdaptersInfoMutex
, INFINITE
);
3761 // Find the PADAPTER_INFO structure associated with this adapter
3762 TAdInfo
= PacketFindAdInfo(Tname
);
3766 TRACE_PRINT("Adapter found.");
3767 *NEntries
= (TAdInfo
->NNetworkAddresses
< *NEntries
)? TAdInfo
->NNetworkAddresses
: *NEntries
;
3768 //TODO what if nentries = 0?
3770 memcpy(buffer
, TAdInfo
->NetworkAddresses
, *NEntries
* sizeof(npf_if_addr
));
3775 TRACE_PRINT("PacketGetNetInfoEx: Adapter not found");
3779 ReleaseMutex(g_AdaptersInfoMutex
);
3781 if(FreeBuff
)GlobalFreePtr(Tname
);
3783 TRACE_EXIT("PacketGetNetInfoEx");
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
;
3807 TRACE_ENTER("PacketGetNetType");
3809 WaitForSingleObject(g_AdaptersInfoMutex
, INFINITE
);
3810 // Find the PADAPTER_INFO structure associated with this adapter
3811 TAdInfo
= PacketFindAdInfo(AdapterObject
->Name
);
3815 TRACE_PRINT("Adapter found");
3817 memcpy(type
, &(TAdInfo
->LinkLayer
), sizeof(struct NetType
));
3822 TRACE_PRINT("PacketGetNetType: Adapter not found");
3826 ReleaseMutex(g_AdaptersInfoMutex
);
3828 TRACE_EXIT("PacketGetNetType");
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
;
3855 UNUSED(AdapterObject
);
3856 #endif // HAVE_AIRPCAP_API
3858 TRACE_EXIT("PacketGetAirPcapHandle");