2 * Copyright (c) 1999, 2000
3 * Politecnico di Torino. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that: (1) source code distributions
7 * retain the above copyright notice and this paragraph in its entirety, (2)
8 * distributions including binary code include the above copyright notice and
9 * this paragraph in its entirety in the documentation or other materials
10 * provided with the distribution, and (3) all advertising materials mentioning
11 * features or use of this software display the following acknowledgement:
12 * ``This product includes software developed by the Politecnico
13 * di Torino, and its contributors.'' Neither the name of
14 * the University nor the names of its contributors may be used to endorse
15 * or promote products derived from this software without specific prior
17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
25 #include <net/ntddndis.h>
31 /****** KERNEL Macro APIs ******************************************************/
33 #define GetInstanceModule(hInst) (HMODULE)(hInst)
34 #define GlobalPtrHandle(lp) ((HGLOBAL)GlobalHandle(lp))
35 #define GlobalLockPtr(lp) ((BOOL)GlobalLock(GlobalPtrHandle(lp)))
36 #define GlobalUnlockPtr(lp) GlobalUnlock(GlobalPtrHandle(lp))
37 #define GlobalAllocPtr(flags, cb) (GlobalLock(GlobalAlloc((flags), (cb))))
38 #define GlobalReAllocPtr(lp, cbNew, flags) (GlobalUnlockPtr(lp), GlobalLock(GlobalReAlloc(GlobalPtrHandle(lp) , (cbNew), (flags))))
39 #define GlobalFreePtr(lp) (GlobalUnlockPtr(lp), (BOOL)(ULONG_PTR)GlobalFree(GlobalPtrHandle(lp)))
42 #define GMEM_MOVEABLE 0
46 /// Title of error windows
47 TCHAR szWindowTitle[] = TEXT("PACKET.DLL");
50 #define ODS(_x) OutputDebugString(TEXT(_x))
51 //#define ODSEx(_x, _y)
57 \brief Macro to print a debug string. The behavior differs depending on the debug level
61 f = fopen("winpcap_debug.txt", "a"); \
62 fprintf(f, "%s", _x); \
66 \brief Macro to print debug data with the printf convention. The behavior differs depending on
69 #define ODSEx(_x, _y) { \
71 f = fopen("winpcap_debug.txt", "a"); \
76 LONG PacketDumpRegistryKey(PCHAR KeyName, PCHAR FileName);
84 SC_HANDLE scmHandle = NULL;
85 SC_HANDLE srvHandle = NULL;
86 LPCTSTR NPFServiceName = TEXT("NPF");
87 LPCTSTR NPFServiceDesc = TEXT("Netgroup Packet Filter");
88 LPCTSTR NPFDriverName = TEXT("\\npf.sys");
89 LPCTSTR NPFRegistryLocation = TEXT("SYSTEM\\ControlSet001\\Services\\NPF");
92 //---------------------------------------------------------------------------
95 \brief The main dll function.
98 BOOL APIENTRY DllMain (HANDLE DllHandle,DWORD Reason,LPVOID lpReserved)
104 case DLL_PROCESS_ATTACH:
106 ODS("\n************Packet32: DllMain************\n");
108 #ifdef _DEBUG_TO_FILE
109 // dump a bunch of registry keys useful for debug to file
110 PacketDumpRegistryKey("HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}",
112 PacketDumpRegistryKey("HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Services\\Tcpip",
114 PacketDumpRegistryKey("HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Services\\NPF",
116 PacketDumpRegistryKey("HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Services",
121 case DLL_PROCESS_DETACH:
132 \brief Converts an ASCII string to UNICODE. Uses the MultiByteToWideChar() system function.
133 \param string The string to convert.
134 \return The converted string.
137 WCHAR* SChar2WChar(char* string)
140 TmpStr=(WCHAR*) malloc ((strlen(string)+2)*sizeof(WCHAR));
142 MultiByteToWideChar(CP_ACP, 0, string, -1, TmpStr, (strlen(string)+2));
148 \brief Sets the maximum possible lookahead buffer for the driver's Packet_tap() function.
149 \param AdapterObject Handle to the service control manager.
150 \return If the function succeeds, the return value is nonzero.
152 The lookahead buffer is the portion of packet that Packet_tap() can access from the NIC driver's memory
153 without performing a copy. This function tries to increase the size of that buffer.
156 BOOLEAN PacketSetMaxLookaheadsize (LPADAPTER AdapterObject)
159 ULONG IoCtlBufferLength=(sizeof(PACKET_OID_DATA)+sizeof(ULONG)-1);
160 PPACKET_OID_DATA OidData;
162 OidData=GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT,IoCtlBufferLength);
163 if (OidData == NULL) {
164 ODS("PacketSetMaxLookaheadsize failed\n");
168 //set the size of the lookahead buffer to the maximum available by the the NIC driver
169 OidData->Oid=OID_GEN_MAXIMUM_LOOKAHEAD;
170 OidData->Length=sizeof(ULONG);
171 Status=PacketRequest(AdapterObject,FALSE,OidData);
172 OidData->Oid=OID_GEN_CURRENT_LOOKAHEAD;
173 Status=PacketRequest(AdapterObject,TRUE,OidData);
174 GlobalFreePtr(OidData);
179 \brief Retrieves the event associated in the driver with a capture instance and stores it in an
181 \param AdapterObject Handle to the service control manager.
182 \return If the function succeeds, the return value is nonzero.
184 This function is used by PacketOpenAdapter() to retrieve the read event from the driver by means of an ioctl
185 call and set it in the _ADAPTER structure pointed by AdapterObject.
188 BOOLEAN PacketSetReadEvt(LPADAPTER AdapterObject)
193 // this tells the terminal service to retrieve the event from the global namespace
194 wcsncpy(EventName,L"Global\\",sizeof(L"Global\\"));
196 // retrieve the name of the shared event from the driver
197 if(DeviceIoControl(AdapterObject->hFile,pBIOCEVNAME,NULL,0,EventName+7,13*sizeof(TCHAR),&BytesReturned,NULL)==FALSE) return FALSE;
199 EventName[20]=0; // terminate the string
201 // open the shared event
202 AdapterObject->ReadEvent=CreateEventW(NULL,
207 // in NT4 "Global\" is not automatically ignored: try to use simply the event name
208 if(GetLastError()!=ERROR_ALREADY_EXISTS){
209 if(AdapterObject->ReadEvent != NULL)
210 CloseHandle(AdapterObject->ReadEvent);
212 // open the shared event
213 AdapterObject->ReadEvent=CreateEventW(NULL,
219 if(AdapterObject->ReadEvent==NULL || GetLastError()!=ERROR_ALREADY_EXISTS){
220 ODS("PacketSetReadEvt: error retrieving the event from the kernel\n");
224 AdapterObject->ReadTimeOut=0;
231 \brief Installs the NPF device driver.
232 \param ascmHandle Handle to the service control manager.
233 \param ascmHandle A pointer to a handle that will receive the pointer to the driver's service.
234 \param driverPath The full path of the .sys file to load.
235 \return If the function succeeds, the return value is nonzero.
237 This function installs the driver's service in the system using the CreateService function.
240 BOOL PacketInstallDriver(SC_HANDLE ascmHandle, SC_HANDLE* srvHandle, TCHAR* driverPath)
245 ODS("installdriver\n");
247 if (GetFileAttributes(driverPath) != 0xffffffff) {
248 *srvHandle = CreateService(ascmHandle,
252 SERVICE_KERNEL_DRIVER,
253 SERVICE_DEMAND_START,
254 SERVICE_ERROR_NORMAL,
256 NULL, NULL, NULL, NULL, NULL);
257 if (*srvHandle == NULL) {
258 if (GetLastError() == ERROR_SERVICE_EXISTS) {
259 //npf.sys already existed
263 //Created service for npf.sys
267 if (result == TRUE) {
268 if (*srvHandle != NULL) {
269 CloseServiceHandle(*srvHandle);
273 if (result == FALSE){
274 err = GetLastError();
276 ODSEx("PacketInstallDriver failed, Error=%d\n",err);
284 \brief Convert a Unicode dotted-quad to a 32-bit IP address.
285 \param cp A string containing the address.
286 \return the converted 32-bit numeric address.
288 Doesn't check to make sure the address is valid.
292 ULONG inet_addrU(const WCHAR *cp)
299 for (i = 0; i < 4; i++) {
301 while ((c = *cp++) != '\0' && c != '.') {
302 if (c < '0' || c > '9')
304 part = part*10 + (c - '0');
308 val = val | (part << i*8);
311 return -1; // extra gunk at end of string
314 return -1; // string ends early
321 \brief Dumps a registry key to disk in text format. Uses regedit.
322 \param KeyName Name of the ket to dump. All its subkeys will be saved recursively.
323 \param FileName Name of the file that will contain the dump.
324 \return If the function succeeds, the return value is nonzero.
326 For debugging purposes, we use this function to obtain some registry keys from the user's machine.
329 #ifdef _DEBUG_TO_FILE
331 LONG PacketDumpRegistryKey(PCHAR KeyName, PCHAR FileName)
335 strcpy(Command, "regedit /e ");
336 strcat(Command, FileName);
337 strcat(Command, " ");
338 strcat(Command, KeyName);
340 /// Let regedit do the dirt work for us
347 //---------------------------------------------------------------------------
349 //---------------------------------------------------------------------------
351 /** @ingroup packetapi
355 /** @defgroup packet32 Packet.dll exported functions and variables
359 /// Current packet.dll Version. It can be retrieved directly or through the PacketGetVersion() function.
360 char PacketLibraryVersion[] = "2.3";
363 \brief Returns a string with the dll version.
364 \return A char pointer to the version of the library.
366 PCHAR PacketGetVersion(){
367 return PacketLibraryVersion;
371 \brief Returns information about the MAC type of an adapter.
372 \param AdapterObject The adapter on which information is needed.
373 \param type Pointer to a NetType structure that will be filled by the function.
374 \return If the function succeeds, the return value is nonzero, otherwise the return value is zero.
376 This function return the link layer technology and the speed (in bps) of an opened adapter.
377 The LinkType field of the type parameter can have one of the following values:
379 - NdisMedium802_3: Ethernet (802.3)
381 - NdisMedium802_5: Token Ring (802.5)
382 - NdisMediumFddi: FDDI
384 - NdisMediumArcnet878_2: ARCNET (878.2)
386 BOOLEAN PacketGetNetType (LPADAPTER AdapterObject,NetType *type)
389 ULONG IoCtlBufferLength=(sizeof(PACKET_OID_DATA)+sizeof(ULONG)-1);
390 PPACKET_OID_DATA OidData;
392 OidData=GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT,IoCtlBufferLength);
393 if (OidData == NULL) {
394 ODS("PacketGetNetType failed\n");
397 //get the link-layer type
398 OidData->Oid = OID_GEN_MEDIA_IN_USE;
399 OidData->Length = sizeof (ULONG);
400 Status = PacketRequest(AdapterObject,FALSE,OidData);
401 type->LinkType=*((UINT*)OidData->Data);
403 //get the link-layer speed
404 OidData->Oid = OID_GEN_LINK_SPEED;
405 OidData->Length = sizeof (ULONG);
406 Status = PacketRequest(AdapterObject,FALSE,OidData);
407 type->LinkSpeed=*((UINT*)OidData->Data)*100;
408 GlobalFreePtr (OidData);
410 ODSEx("Media:%d ",type->LinkType);
411 ODSEx("Speed=%d\n",type->LinkSpeed);
417 \brief Stops and unloads the WinPcap device driver.
418 \return If the function succeeds, the return value is nonzero, otherwise it is zero.
420 This function can be used to unload the driver from memory when the application no more needs it.
421 Note that the driver is physically stopped and unloaded only when all the files on its devices
422 are closed, i.e. when all the applications that use WinPcap close all their adapters.
424 BOOL PacketStopDriver()
427 SC_HANDLE schService;
429 SERVICE_STATUS serviceStatus;
431 scmHandle = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
433 if(scmHandle != NULL){
435 schService = OpenService (scmHandle,
440 if (schService != NULL)
443 ret = ControlService (schService,
444 SERVICE_CONTROL_STOP,
451 CloseServiceHandle (schService);
453 CloseServiceHandle(scmHandle);
464 \brief Opens an adapter.
465 \param AdapterName A string containing the name of the device to open.
466 Use the PacketGetAdapterNames() function to retrieve the list of available devices.
467 \return If the function succeeds, the return value is the pointer to a properly initialized ADAPTER object,
468 otherwise the return value is NULL.
470 This function tries to load and start the packet driver at the first invocation. In this way,
471 the management of the driver is transparent to the application, that simply needs to open an adapter to start
474 \note the Windows 95 version of the NPF driver works with the ASCII string format, while the Windows NT
475 version works with UNICODE. Therefore, AdapterName \b should be an ASCII string in Windows 95, and a UNICODE
476 string in Windows NT. This difference is not a problem if the string pointed by AdapterName was obtained
477 through the PacketGetAdapterNames function, because it returns the names of the adapters in the proper format.
478 Problems can arise in Windows NT when the string is obtained from ANSI C functions like scanf, because they
479 use the ASCII format. Since this could be a relevant problem during the porting of command-line applications
480 from UNIX, we included in the Windows NT version of PacketOpenAdapter the ability to detect ASCII strings and
481 convert them to UNICODE before sending them to the device driver. Therefore PacketOpenAdapter in Windows NT
482 accepts both the ASCII and the UNICODE format. If a ASCII string is received, it is converted to UNICODE
483 by PACKET.DLL before being passed to the driver.
485 LPADAPTER PacketOpenAdapter(LPTSTR AdapterName)
492 SC_HANDLE svcHandle = NULL;
493 TCHAR driverPath[512];
497 SERVICE_STATUS SStat;
499 WCHAR SymbolicLink[128];
501 ODSEx("PacketOpenAdapter: trying to open the adapter=%S\n",AdapterName);
503 scmHandle = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
504 if(scmHandle == NULL){
505 error = GetLastError();
506 ODSEx("OpenSCManager failed! Error=%d\n", error);
509 GetCurrentDirectory(512, driverPath);
510 wsprintf(driverPath + wcslen(driverPath), NPFDriverName);
512 // check if the NPF registry key is already present
513 // this means that the driver is already installed and that we don't need to call PacketInstallDriver
514 KeyRes=RegOpenKeyEx(HKEY_LOCAL_MACHINE,
520 if(KeyRes != ERROR_SUCCESS){
521 Result = PacketInstallDriver(scmHandle,&svcHandle,driverPath);
524 RegCloseKey(PathKey);
529 srvHandle = OpenService(scmHandle, NPFServiceName, SERVICE_START | SERVICE_QUERY_STATUS );
530 if (srvHandle != NULL){
532 QuerySStat = QueryServiceStatus(srvHandle, &SStat);
533 ODSEx("The status of the driver is:%d\n",SStat.dwCurrentState);
535 if (!QuerySStat || SStat.dwCurrentState != SERVICE_RUNNING){
536 ODS("Calling startservice\n");
537 if (StartService(srvHandle, 0, NULL)==0){
538 error = GetLastError();
539 if (error!=ERROR_SERVICE_ALREADY_RUNNING && error!=ERROR_ALREADY_EXISTS){
541 if (scmHandle != NULL) CloseServiceHandle(scmHandle);
542 error = GetLastError();
543 ODSEx("PacketOpenAdapter: StartService failed, Error=%d\n",error);
549 error = GetLastError();
550 ODSEx("OpenService failed! Error=%d", error);
553 if (GetSystemDirectory(WinPath, sizeof(WinPath)/sizeof(TCHAR)) == 0) {
556 wsprintf(driverPath, TEXT("%s\\drivers%s"), WinPath, NPFDriverName);
558 if (KeyRes != ERROR_SUCCESS) {
559 Result = PacketInstallDriver(scmHandle,&svcHandle,driverPath);
564 srvHandle = OpenService(scmHandle,NPFServiceName,SERVICE_START);
565 if (srvHandle != NULL) {
566 QuerySStat = QueryServiceStatus(srvHandle, &SStat);
567 ODSEx("The status of the driver is:%d\n",SStat.dwCurrentState);
568 if (!QuerySStat || SStat.dwCurrentState != SERVICE_RUNNING) {
569 ODS("Calling startservice\n");
570 if (StartService(srvHandle, 0, NULL) == 0) {
571 error = GetLastError();
572 if (error != ERROR_SERVICE_ALREADY_RUNNING && error!=ERROR_ALREADY_EXISTS) {
574 if (scmHandle != NULL) CloseServiceHandle(scmHandle);
575 ODSEx("PacketOpenAdapter: StartService failed, Error=%d\n",error);
581 error = GetLastError();
582 ODSEx("OpenService failed! Error=%d", error);
587 if (scmHandle != NULL) CloseServiceHandle(scmHandle);
589 AdapterNameA = (char*)AdapterName;
590 if (AdapterNameA[1] != 0) { // ASCII
591 AdapterNameU = SChar2WChar(AdapterNameA);
592 AdapterName = AdapterNameU;
597 lpAdapter = (LPADAPTER)GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT,sizeof(ADAPTER));
598 if (lpAdapter == NULL) {
599 ODS("PacketOpenAdapter: GlobalAlloc Failed\n");
600 error = GetLastError();
601 if (AdapterNameU != NULL) free(AdapterNameU);
602 //set the error to the one on which we failed
604 ODS("PacketOpenAdapter: Failed to allocate the adapter structure\n");
607 lpAdapter->NumWrites = 1;
609 wsprintf(SymbolicLink,TEXT("\\\\.\\%s%s"), DOSNAMEPREFIX, &AdapterName[8]);
611 // Copy only the bytes that fit in the adapter structure.
612 // Note that lpAdapter->SymbolicLink is present for backward compatibility but will
613 // never be used by the apps
614 memcpy(lpAdapter->SymbolicLink, (PCHAR)SymbolicLink, MAX_LINK_NAME_LENGTH);
616 //try if it is possible to open the adapter immediately
617 lpAdapter->hFile = CreateFile(SymbolicLink,GENERIC_WRITE | GENERIC_READ,0,NULL,OPEN_EXISTING,0,0);
619 if (lpAdapter->hFile != INVALID_HANDLE_VALUE) {
620 ODSEx("PacketOpenAdapter: CreateFile(%S) successfull\n", SymbolicLink);
621 if (PacketSetReadEvt(lpAdapter) == FALSE) {
622 error = GetLastError();
623 ODS("PacketOpenAdapter: Unable to open the read event\n");
624 if (AdapterNameU != NULL)
626 GlobalFreePtr(lpAdapter);
627 //set the error to the one on which we failed
629 ODSEx("PacketOpenAdapter: PacketSetReadEvt failed, Error=%d\n",error);
633 PacketSetMaxLookaheadsize(lpAdapter);
634 if (AdapterNameU != NULL)
638 //this is probably the first request on the packet driver.
639 //We must create the dos device and set the access rights on it
641 Result = DefineDosDevice(DDD_RAW_TARGET_PATH,
646 ODSEx("PacketOpenAdapter: calling CreateFile(%S)\n", SymbolicLink);
648 lpAdapter->hFile = CreateFile(
650 GENERIC_WRITE | GENERIC_READ,0,NULL,OPEN_EXISTING,0,0);
651 if (lpAdapter->hFile != INVALID_HANDLE_VALUE) {
652 if (PacketSetReadEvt(lpAdapter) == FALSE) {
653 error = GetLastError();
654 ODS("PacketOpenAdapter: Unable to open the read event\n");
655 if (AdapterNameU != NULL)
657 GlobalFreePtr(lpAdapter);
658 //set the error to the one on which we failed
660 ODSEx("PacketOpenAdapter: PacketSetReadEvt failed, Error=1,%d\n",error);
663 PacketSetMaxLookaheadsize(lpAdapter);
664 if (AdapterNameU != NULL)
668 ODS("PacketOpenAdapter: CreateFile failed\n");
671 ODSEx("PacketOpenAdapter: DefineDosDevice(%S) failed\n", &SymbolicLink[4]);
674 error = GetLastError();
675 if (AdapterNameU != NULL)
677 GlobalFreePtr(lpAdapter);
678 //set the error to the one on which we failed
680 ODSEx("PacketOpenAdapter: CreateFile failed, Error=2,%d\n",error);
686 \brief Closes an adapter.
687 \param lpAdapter the pointer to the adapter to close.
689 PacketCloseAdapter closes the given adapter and frees the associated ADAPTER structure
691 VOID PacketCloseAdapter(LPADAPTER lpAdapter)
693 CloseHandle(lpAdapter->hFile);
694 SetEvent(lpAdapter->ReadEvent);
695 CloseHandle(lpAdapter->ReadEvent);
696 GlobalFreePtr(lpAdapter);
700 \brief Allocates a _PACKET structure.
701 \return On succeess, the return value is the pointer to a _PACKET structure otherwise the
702 return value is NULL.
704 The structure returned will be passed to the PacketReceivePacket() function to receive the
705 packets from the driver.
707 \warning The Buffer field of the _PACKET structure is not set by this function.
708 The buffer \b must be allocated by the application, and associated to the PACKET structure
709 with a call to PacketInitPacket.
711 LPPACKET PacketAllocatePacket(void)
715 lpPacket = (LPPACKET)GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT,sizeof(PACKET));
716 if (lpPacket == NULL) {
717 ODS("PacketAllocatePacket: GlobalAlloc Failed\n");
724 \brief Frees a _PACKET structure.
725 \param lpPacket The structure to free.
727 \warning the user-allocated buffer associated with the _PACKET structure is not deallocated
728 by this function and \b must be explicitly deallocated by the programmer.
731 VOID PacketFreePacket(LPPACKET lpPacket)
733 GlobalFreePtr(lpPacket);
737 \brief Initializes a _PACKET structure.
738 \param lpPacket The structure to initialize.
739 \param Buffer A pointer to a user-allocated buffer that will contain the captured data.
740 \param Length the length of the buffer. This is the maximum buffer size that will be
741 transferred from the driver to the application using a single read.
743 \note the size of the buffer associated with the PACKET structure is a parameter that can sensibly
744 influence the performance of the capture process, since this buffer will contain the packets received
745 from the the driver. The driver is able to return several packets using a single read call
746 (see the PacketReceivePacket() function for details), and the number of packets transferable to the
747 application in a call is limited only by the size of the buffer associated with the PACKET structure
748 passed to PacketReceivePacket(). Therefore setting a big buffer with PacketInitPacket can noticeably
749 decrease the number of system calls, reducing the impcat of the capture process on the processor.
752 VOID PacketInitPacket(LPPACKET lpPacket,PVOID Buffer,UINT Length)
754 lpPacket->Buffer = Buffer;
755 lpPacket->Length = Length;
756 lpPacket->ulBytesReceived = 0;
757 lpPacket->bIoComplete = FALSE;
761 \brief Read data (packets or statistics) from the NPF driver.
762 \param AdapterObject Pointer to an _ADAPTER structure identifying the network adapter from which
763 the data is received.
764 \param lpPacket Pointer to a PACKET structure that will contain the data.
765 \param Sync This parameter is deprecated and will be ignored. It is present for compatibility with
767 \return If the function succeeds, the return value is nonzero.
769 The data received with this function can be a group of packets or a static on the network traffic,
770 depending on the working mode of the driver. The working mode can be set with the PacketSetMode()
771 function. Give a look at that function if you are interested in the format used to return statistics
772 values, here only the normal capture mode will be described.
774 The number of packets received with this function is variable. It depends on the number of packets
775 currently stored in the driver
\92s buffer, on the size of these packets and on the size of the buffer
776 associated to the lpPacket parameter. The following figure shows the format used by the driver to pass
777 packets to the application.
779 \image html encoding.gif "method used to encode the packets"
781 Packets are stored in the buffer associated with the lpPacket _PACKET structure. The Length field of
782 that structure is updated with the amount of data copied in the buffer. Each packet has a header
783 consisting in a bpf_hdr structure that defines its length and contains its timestamp. A padding field
784 is used to word-align the data in the buffer (to speed up the access to the packets). The bh_datalen
785 and bh_hdrlen fields of the bpf_hdr structures should be used to extract the packets from the buffer.
787 Examples can be seen either in the TestApp sample application (see the \ref packetsamps page) provided
788 in the developer's pack, or in the pcap_read() function of wpcap.
790 BOOLEAN PacketReceivePacket(LPADAPTER AdapterObject,LPPACKET lpPacket,BOOLEAN Sync)
793 if ((int)AdapterObject->ReadTimeOut != -1)
794 WaitForSingleObject(AdapterObject->ReadEvent, (AdapterObject->ReadTimeOut==0)?INFINITE:AdapterObject->ReadTimeOut);
795 res = ReadFile(AdapterObject->hFile, lpPacket->Buffer, lpPacket->Length, &lpPacket->ulBytesReceived,NULL);
800 \brief Sends one (or more) copies of a packet to the network.
801 \param AdapterObject Pointer to an _ADAPTER structure identifying the network adapter that will
803 \param lpPacket Pointer to a PACKET structure with the packet to send.
804 \param Sync This parameter is deprecated and will be ignored. It is present for compatibility with
806 \return If the function succeeds, the return value is nonzero.
808 This function is used to send a raw packet to the network. 'Raw packet' means that the programmer
809 will have to include the protocol headers, since the packet is sent to the network 'as is'.
810 The CRC needs not to be calculated and put at the end of the packet, because it will be transparently
811 added by the network interface.
813 The behavior of this function is influenced by the PacketSetNumWrites() function. With PacketSetNumWrites(),
814 it is possible to change the number of times a single write must be repeated. The default is 1,
815 i.e. every call to PacketSendPacket() will correspond to one packet sent to the network. If this number is
816 greater than 1, for example 1000, every raw packet written by the application will be sent 1000 times on
817 the network. This feature mitigates the overhead of the context switches and therefore can be used to generate
818 high speed traffic. It is particularly useful for tools that test networks, routers, and servers and need
819 to obtain high network loads.
820 The optimized sending process is still limited to one packet at a time: for the moment it cannot be used
821 to send a buffer with multiple packets.
823 \note The ability to write multiple packets is currently present only in the Windows NTx version of the
824 packet driver. In Windows 95/98/ME it is emulated at user level in packet.dll. This means that an application
825 that uses the multiple write method will run in Windows 9x as well, but its performance will be very low
826 compared to the one of WindowsNTx.
828 BOOLEAN PacketSendPacket(LPADAPTER AdapterObject,LPPACKET lpPacket,BOOLEAN Sync)
830 DWORD BytesTransfered;
831 return WriteFile(AdapterObject->hFile,lpPacket->Buffer,lpPacket->Length,&BytesTransfered,NULL);
836 \brief Sends a buffer of packets to the network.
837 \param AdapterObject Pointer to an _ADAPTER structure identifying the network adapter that will
839 \param PacketBuff Pointer to buffer with the packets to send.
840 \param Size Size of the buffer pointed by the PacketBuff argument.
841 \param Sync if TRUE, the packets are sent respecting the timestamps. If FALSE, the packets are sent as
843 \return The amount of bytes actually sent. If the return value is smaller than the Size parameter, an
844 error occurred during the send. The error can be caused by a driver/adapter problem or by an
845 inconsistent/bogus packet buffer.
847 This function is used to send a buffer of raw packets to the network. The buffer can contain an arbitrary
848 number of raw packets, each of which preceded by a dump_bpf_hdr structure. The dump_bpf_hdr is the same used
849 by WinPcap and libpcap to store the packets in a file, therefore sending a capture file is straightforward.
850 'Raw packets' means that the sending application will have to include the protocol headers, since every packet
851 is sent to the network 'as is'. The CRC of the packets needs not to be calculated, because it will be
852 transparently added by the network interface.
854 \note Using this function if more efficient than issuing a series of PacketSendPacket(), because the packets are
855 buffered in the kernel driver, so the number of context switches is reduced.
857 \note When Sync is set to TRUE, the packets are synchronized in the kerenl with a high precision timestamp.
858 This requires a remarkable amount of CPU, but allows to send the packets with a precision of some microseconds
859 (depending on the precision of the performance counter of the machine). Such a precision cannot be reached
860 sending the packets separately with PacketSendPacket().
862 INT PacketSendPackets(LPADAPTER AdapterObject, PVOID PacketBuff, ULONG Size, BOOLEAN Sync)
865 DWORD BytesTransfered, TotBytesTransfered=0;
866 struct timeval BufStartTime;
867 LARGE_INTEGER StartTicks, CurTicks, TargetTicks, TimeFreq;
870 ODS("PacketSendPackets");
872 // Obtain starting timestamp of the buffer
873 BufStartTime.tv_sec = ((struct timeval*)(PacketBuff))->tv_sec;
874 BufStartTime.tv_usec = ((struct timeval*)(PacketBuff))->tv_usec;
876 // Retrieve the reference time counters
877 QueryPerformanceCounter(&StartTicks);
878 QueryPerformanceFrequency(&TimeFreq);
880 CurTicks.QuadPart = StartTicks.QuadPart;
883 // Send the data to the driver
884 Res = DeviceIoControl(AdapterObject->hFile,
885 (Sync)?pBIOCSENDPACKETSSYNC:pBIOCSENDPACKETSNOSYNC,
886 (PCHAR)PacketBuff + TotBytesTransfered,
887 Size - TotBytesTransfered,
893 TotBytesTransfered += BytesTransfered;
895 // calculate the time interval to wait before sending the next packet
896 TargetTicks.QuadPart = StartTicks.QuadPart +
898 ((((struct timeval*)((PCHAR)PacketBuff + TotBytesTransfered))->tv_sec - BufStartTime.tv_sec) * 1000000 +
899 (((struct timeval*)((PCHAR)PacketBuff + TotBytesTransfered))->tv_usec - BufStartTime.tv_usec)) *
900 (TimeFreq.QuadPart) / 1000000;
902 // Exit from the loop on termination or error
903 if(TotBytesTransfered >= Size || Res != TRUE)
906 // Wait until the time interval has elapsed
907 while( CurTicks.QuadPart <= TargetTicks.QuadPart )
908 QueryPerformanceCounter(&CurTicks);
913 return TotBytesTransfered;
917 \brief Defines the minimum amount of data that will be received in a read.
918 \param AdapterObject Pointer to an _ADAPTER structure
919 \param nbytes the minimum amount of data in the kernel buffer that will cause the driver to
920 release a read on this adapter.
921 \return If the function succeeds, the return value is nonzero.
923 In presence of a large value for nbytes, the kernel waits for the arrival of several packets before
924 copying the data to the user. This guarantees a low number of system calls, i.e. lower processor usage,
925 i.e. better performance, which is a good setting for applications like sniffers. Vice versa, a small value
926 means that the kernel will copy the packets as soon as the application is ready to receive them. This is
927 suggested for real time applications (like, for example, a bridge) that need the better responsiveness from
930 \b note: this function has effect only in Windows NTx. The driver for Windows 9x doesn't offer
931 this possibility, therefore PacketSetMinToCopy is implemented under these systems only for compatibility.
934 BOOLEAN PacketSetMinToCopy(LPADAPTER AdapterObject,int nbytes)
937 return DeviceIoControl(AdapterObject->hFile,pBIOCSMINTOCOPY,&nbytes,4,NULL,0,&BytesReturned,NULL);
941 \brief Sets the working mode of an adapter.
942 \param AdapterObject Pointer to an _ADAPTER structure.
943 \param mode The new working mode of the adapter.
944 \return If the function succeeds, the return value is nonzero.
946 The device driver of WinPcap has 4 working modes:
947 - Capture mode (mode = PACKET_MODE_CAPT): normal capture mode. The packets transiting on the wire are copied
948 to the application when PacketReceivePacket() is called. This is the default working mode of an adapter.
949 - Statistical mode (mode = PACKET_MODE_STAT): programmable statistical mode. PacketReceivePacket() returns, at
950 precise intervals, statics values on the network traffic. The interval between the statistic samples is
951 by default 1 second but it can be set to any other value (with a 1 ms precision) with the
952 PacketSetReadTimeout() function. The data returned by PacketReceivePacket() when the adapter is in statistical
953 mode is shown in the following figure:<p>
954 \image html stats.gif "data structure returned by statistical mode"
955 Two 64-bit counters are provided: the number of packets and the amount of bytes that satisfy a filter
956 previously set with PacketSetBPF(). If no filter has been set, all the packets are counted. The counters are
957 encapsulated in a bpf_hdr structure, so that they will be parsed correctly by wpcap. Statistical mode has a
958 very low impact on system performance compared to capture mode.
959 - Dump mode (mode = PACKET_MODE_DUMP): the packets are dumped to disk by the driver, in libpcap format. This
960 method is much faster than saving the packets after having captured them. No data is returned
961 by PacketReceivePacket(). If the application sets a filter with PacketSetBPF(), only the packets that satisfy
962 this filter are dumped to disk.
963 - Statitical Dump mode (mode = PACKET_MODE_STAT_DUMP): the packets are dumped to disk by the driver, in libpcap
964 format, like in dump mode. PacketReceivePacket() returns, at precise intervals, statics values on the
965 network traffic and on the amount of data saved to file, in a way similar to statistical mode.
966 The data returned by PacketReceivePacket() when the adapter is in statistical dump mode is shown in
967 the following figure:<p>
968 \image html dump.gif "data structure returned by statistical dump mode"
969 Three 64-bit counters are provided: the number of packets accepted, the amount of bytes accepted and the
970 effective amount of data (including headers) dumped to file. If no filter has been set, all the packets are
971 dumped to disk. The counters are encapsulated in a bpf_hdr structure, so that they will be parsed correctly
973 Look at the NetMeter example in the
974 WinPcap developer's pack to see how to use statistics mode.
976 BOOLEAN PacketSetMode(LPADAPTER AdapterObject,int mode)
979 return DeviceIoControl(AdapterObject->hFile,pBIOCSMODE,&mode,4,NULL,0,&BytesReturned,NULL);
983 \brief Sets the name of the file that will receive the packet when the adapter is in dump mode.
984 \param AdapterObject Pointer to an _ADAPTER structure.
985 \param name the file name, in ASCII or UNICODE.
986 \param len the length of the buffer containing the name, in bytes.
987 \return If the function succeeds, the return value is nonzero.
989 This function defines the file name that the driver will open to store the packets on disk when
990 it works in dump mode. The adapter must be in dump mode, i.e. PacketSetMode() should have been
991 called previously with mode = PACKET_MODE_DUMP. otherwise this function will fail.
992 If PacketSetDumpName was already invoked on the adapter pointed by AdapterObject, the driver
993 closes the old file and opens the new one.
996 BOOLEAN PacketSetDumpName(LPADAPTER AdapterObject, void *name, int len)
1001 WCHAR NameWithPath[1024];
1005 if(((PUCHAR)name)[1]!=0 && len>1){ //ASCII
1006 FileName=SChar2WChar(name);
1013 TStrLen=GetFullPathName(FileName,1024,NameWithPath,&NamePos);
1015 len=TStrLen*2+2; //add the terminating null character
1017 // Try to catch malformed strings
1019 if(((PUCHAR)name)[1]!=0 && len>1) free(FileName);
1023 res = DeviceIoControl(AdapterObject->hFile,pBIOCSETDUMPFILENAME,NameWithPath,len,NULL,0,&BytesReturned,NULL);
1029 \brief Set the dump mode limits.
1030 \param AdapterObject Pointer to an _ADAPTER structure.
1031 \param maxfilesize The maximum dimension of the dump file, in bytes. 0 means no limit.
1032 \param maxnpacks The maximum number of packets contained in the dump file. 0 means no limit.
1033 \return If the function succeeds, the return value is nonzero.
1035 This function sets the limits after which the NPF driver stops to save the packets to file when an adapter
1036 is in dump mode. This allows to limit the dump file to a precise number of bytes or packets, avoiding that
1037 very long dumps fill the disk space. If both maxfilesize and maxnpacks are set, the dump is stopped when
1038 the first of the two is reached.
1040 \note When a limit is reached, the dump is stopped, but the file remains opened. In order to flush
1041 correctly the data and access the file consistently, you need to close the adapter with PacketCloseAdapter().
1043 BOOLEAN PacketSetDumpLimits(LPADAPTER AdapterObject, UINT maxfilesize, UINT maxnpacks)
1045 DWORD BytesReturned;
1048 valbuff[0] = maxfilesize;
1049 valbuff[1] = maxnpacks;
1051 return DeviceIoControl(AdapterObject->hFile,
1062 \brief Returns the status of the kernel dump process, i.e. tells if one of the limits defined with PacketSetDumpLimits() was reached.
1063 \param AdapterObject Pointer to an _ADAPTER structure.
1064 \param sync if TRUE, the function blocks until the dump is finished, otherwise it returns immediately.
1065 \return TRUE if the dump is ended, FALSE otherwise.
1067 PacketIsDumpEnded() informs the user about the limits that were set with a previous call to
1068 PacketSetDumpLimits().
1070 \warning If no calls to PacketSetDumpLimits() were performed or if the dump process has no limits
1071 (i.e. if the arguments of the last call to PacketSetDumpLimits() were both 0), setting sync to TRUE will
1072 block the application on this call forever.
1074 BOOLEAN PacketIsDumpEnded(LPADAPTER AdapterObject, BOOLEAN sync)
1076 DWORD BytesReturned;
1081 WaitForSingleObject(AdapterObject->ReadEvent, INFINITE);
1083 res = DeviceIoControl(AdapterObject->hFile,
1092 if(res == FALSE) return TRUE; // If the IOCTL returns an error we consider the dump finished
1094 return (BOOLEAN)IsDumpEnded;
1098 \brief Returns the notification event associated with the read calls on an adapter.
1099 \param AdapterObject Pointer to an _ADAPTER structure.
1100 \return The handle of the event that the driver signals when some data is available in the kernel buffer.
1102 The event returned by this function is signaled by the driver if:
1103 - The adapter pointed by AdapterObject is in capture mode and an amount of data greater or equal
1104 than the one set with the PacketSetMinToCopy() function is received from the network.
1105 - the adapter pointed by AdapterObject is in capture mode, no data has been received from the network
1106 but the the timeout set with the PacketSetReadTimeout() function has elapsed.
1107 - the adapter pointed by AdapterObject is in statics mode and the the timeout set with the
1108 PacketSetReadTimeout() function has elapsed. This means that a new statistic sample is available.
1110 In every case, a call to PacketReceivePacket() will return immediately.
1111 The event can be passed to standard Win32 functions (like WaitForSingleObject or WaitForMultipleObjects)
1112 to wait until the driver's buffer contains some data. It is particularly useful in GUI applications that
1113 need to wait concurrently on several events.
1116 HANDLE PacketGetReadEvent(LPADAPTER AdapterObject)
1118 return AdapterObject->ReadEvent;
1122 \brief Sets the number of times a single packet written with PacketSendPacket() will be repeated on the network.
1123 \param AdapterObject Pointer to an _ADAPTER structure.
1124 \param nwrites Number of copies of a packet that will be physically sent by the interface.
1125 \return If the function succeeds, the return value is nonzero.
1127 See PacketSendPacket() for details.
1129 BOOLEAN PacketSetNumWrites(LPADAPTER AdapterObject,int nwrites)
1131 DWORD BytesReturned;
1132 return DeviceIoControl(AdapterObject->hFile,pBIOCSWRITEREP,&nwrites,4,NULL,0,&BytesReturned,NULL);
1136 \brief Sets the timeout after which a read on an adapter returns.
1137 \param AdapterObject Pointer to an _ADAPTER structure.
1138 \param timeout indicates the timeout, in milliseconds, after which a call to PacketReceivePacket() on
1139 the adapter pointed by AdapterObject will be released, also if no packets have been captured by the driver.
1140 Setting timeout to 0 means no timeout, i.e. PacketReceivePacket() never returns if no packet arrives.
1141 A timeout of -1 causes PacketReceivePacket() to always return immediately.
1142 \return If the function succeeds, the return value is nonzero.
1144 \note This function works also if the adapter is working in statistics mode, and can be used to set the
1145 time interval between two statistic reports.
1147 BOOLEAN PacketSetReadTimeout(LPADAPTER AdapterObject,int timeout)
1149 DWORD BytesReturned;
1150 int DriverTimeOut=-1;
1152 AdapterObject->ReadTimeOut=timeout;
1154 return DeviceIoControl(AdapterObject->hFile,pBIOCSRTIMEOUT,&DriverTimeOut,4,NULL,0,&BytesReturned,NULL);
1158 \brief Sets the size of the kernel-level buffer associated with a capture.
1159 \param AdapterObject Pointer to an _ADAPTER structure.
1160 \param dim New size of the buffer, in \b kilobytes.
1161 \return The function returns TRUE if successfully completed, FALSE if there is not enough memory to
1162 allocate the new buffer.
1164 When a new dimension is set, the data in the old buffer is discarded and the packets stored in it are
1167 Note: the dimension of the kernel buffer affects heavily the performances of the capture process.
1168 An adequate buffer in the driver is able to keep the packets while the application is busy, compensating
1169 the delays of the application and avoiding the loss of packets during bursts or high network activity.
1170 The buffer size is set to 0 when an instance of the driver is opened: the programmer should remember to
1171 set it to a proper value. As an example, wpcap sets the buffer size to 1MB at the beginning of a capture.
1173 BOOLEAN PacketSetBuff(LPADAPTER AdapterObject,int dim)
1175 DWORD BytesReturned;
1176 return DeviceIoControl(AdapterObject->hFile,pBIOCSETBUFFERSIZE,&dim,4,NULL,0,&BytesReturned,NULL);
1180 \brief Sets a kernel-level packet filter.
1181 \param AdapterObject Pointer to an _ADAPTER structure.
1182 \param fp Pointer to a filtering program that will be associated with this capture or monitoring
1183 instance and that will be executed on every incoming packet.
1184 \return This function returns TRUE if the filter is set successfully, FALSE if an error occurs
1185 or if the filter program is not accepted after a safeness check by the driver. The driver performs
1186 the check in order to avoid system crashes due to buggy or malicious filters, and it rejects non
1189 This function associates a new BPF filter to the adapter AdapterObject. The filter, pointed by fp, is a
1190 set of bpf_insn instructions.
1192 A filter can be automatically created by using the pcap_compile() function of wpcap. This function
1193 converts a human readable text expression with the syntax of WinDump (see the manual of WinDump at
1194 http://netgroup.polito.it/windump for details) into a BPF program. If your program doesn't link wpcap, but
1195 you need to know the code of a particular filter, you can launch WinDump with the -d or -dd or -ddd
1196 flags to obtain the pseudocode.
1199 BOOLEAN PacketSetBpf(LPADAPTER AdapterObject,struct bpf_program *fp)
1201 DWORD BytesReturned;
1202 return DeviceIoControl(AdapterObject->hFile,pBIOCSETF,(char*)fp->bf_insns,fp->bf_len*sizeof(struct bpf_insn),NULL,0,&BytesReturned,NULL);
1206 \brief Returns a couple of statistic values about the current capture session.
1207 \param AdapterObject Pointer to an _ADAPTER structure.
1208 \param s Pointer to a user provided bpf_stat structure that will be filled by the function.
1209 \return If the function succeeds, the return value is nonzero.
1211 With this function, the programmer can know the value of two internal variables of the driver:
1213 - the number of packets that have been received by the adapter AdapterObject, starting at the
1214 time in which it was opened with PacketOpenAdapter.
1215 - the number of packets that have been dropped by the driver. A packet is dropped when the kernel
1216 buffer associated with the adapter is full.
1218 BOOLEAN PacketGetStats(LPADAPTER AdapterObject,struct bpf_stat *s)
1221 DWORD BytesReturned;
1222 struct bpf_stat tmpstat; // We use a support structure to avoid kernel-level inconsistencies with old or malicious applications
1224 Res = DeviceIoControl(AdapterObject->hFile,
1229 sizeof(struct bpf_stat),
1233 // Copy only the first two values retrieved from the driver
1234 s->bs_recv = tmpstat.bs_recv;
1235 s->bs_drop = tmpstat.bs_drop;
1241 \brief Returns statistic values about the current capture session. Enhanced version of PacketGetStats().
1242 \param AdapterObject Pointer to an _ADAPTER structure.
1243 \param s Pointer to a user provided bpf_stat structure that will be filled by the function.
1244 \return If the function succeeds, the return value is nonzero.
1246 With this function, the programmer can retireve the sname values provided by PacketGetStats(), plus:
1248 - the number of drops by interface (not yet supported, always 0).
1249 - the number of packets that reached the application, i.e that were accepted by the kernel filter and
1250 that fitted in the kernel buffer.
1252 BOOLEAN PacketGetStatsEx(LPADAPTER AdapterObject,struct bpf_stat *s)
1255 DWORD BytesReturned;
1256 struct bpf_stat tmpstat; // We use a support structure to avoid kernel-level inconsistencies with old or malicious applications
1258 Res = DeviceIoControl(AdapterObject->hFile,
1263 sizeof(struct bpf_stat),
1267 s->bs_recv = tmpstat.bs_recv;
1268 s->bs_drop = tmpstat.bs_drop;
1269 s->ps_ifdrop = tmpstat.ps_ifdrop;
1270 s->bs_capt = tmpstat.bs_capt;
1276 \brief Performs a query/set operation on an internal variable of the network card driver.
1277 \param AdapterObject Pointer to an _ADAPTER structure.
1278 \param Set Determines if the operation is a set (Set=TRUE) or a query (Set=FALSE).
1279 \param OidData A pointer to a _PACKET_OID_DATA structure that contains or receives the data.
1280 \return If the function succeeds, the return value is nonzero.
1282 \note not all the network adapters implement all the query/set functions. There is a set of mandatory
1283 OID functions that is granted to be present on all the adapters, and a set of facultative functions, not
1284 provided by all the cards (see the Microsoft DDKs to see which functions are mandatory). If you use a
1285 facultative function, be careful to enclose it in an if statement to check the result.
1287 BOOLEAN PacketRequest(LPADAPTER AdapterObject,BOOLEAN Set,PPACKET_OID_DATA OidData)
1289 DWORD BytesReturned;
1292 Result=DeviceIoControl(AdapterObject->hFile,(DWORD) Set ? pBIOCSETOID : pBIOCQUERYOID,
1293 OidData,sizeof(PACKET_OID_DATA)-1+OidData->Length,OidData,
1294 sizeof(PACKET_OID_DATA)-1+OidData->Length,&BytesReturned,NULL);
1296 // output some debug info
1297 ODSEx("PacketRequest, OID=%d ", OidData->Oid);
1298 ODSEx("Length=%d ", OidData->Length);
1299 ODSEx("Set=%d ", Set);
1300 ODSEx("Res=%d\n", Result);
1306 \brief Sets a hardware filter on the incoming packets.
1307 \param AdapterObject Pointer to an _ADAPTER structure.
1308 \param Filter The identifier of the filter.
1309 \return If the function succeeds, the return value is nonzero.
1311 The filter defined with this filter is evaluated by the network card, at a level that is under the NPF
1312 device driver. Here is a list of the most useful hardware filters (A complete list can be found in ntddndis.h):
1314 - NDIS_PACKET_TYPE_PROMISCUOUS: sets promiscuous mode. Every incoming packet is accepted by the adapter.
1315 - NDIS_PACKET_TYPE_DIRECTED: only packets directed to the workstation's adapter are accepted.
1316 - NDIS_PACKET_TYPE_BROADCAST: only broadcast packets are accepted.
1317 - NDIS_PACKET_TYPE_MULTICAST: only multicast packets belonging to groups of which this adapter is a member are accepted.
1318 - NDIS_PACKET_TYPE_ALL_MULTICAST: every multicast packet is accepted.
1319 - NDIS_PACKET_TYPE_ALL_LOCAL: all local packets, i.e. NDIS_PACKET_TYPE_DIRECTED + NDIS_PACKET_TYPE_BROADCAST + NDIS_PACKET_TYPE_MULTICAST
1321 BOOLEAN PacketSetHwFilter(LPADAPTER AdapterObject,ULONG Filter)
1324 ULONG IoCtlBufferLength=(sizeof(PACKET_OID_DATA)+sizeof(ULONG)-1);
1325 PPACKET_OID_DATA OidData;
1327 OidData=GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT,IoCtlBufferLength);
1328 if (OidData == NULL) {
1329 ODS("PacketSetHwFilter: GlobalAlloc Failed\n");
1332 OidData->Oid=OID_GEN_CURRENT_PACKET_FILTER;
1333 OidData->Length=sizeof(ULONG);
1334 *((PULONG)OidData->Data)=Filter;
1335 Status=PacketRequest(AdapterObject,TRUE,OidData);
1336 GlobalFreePtr(OidData);
1341 \brief Retrieve the list of available network adapters and their description.
1342 \param pStr User allocated string that will be filled with the names of the adapters.
1343 \param BufferSize Length of the buffer pointed by pStr.
1344 \return If the function succeeds, the return value is nonzero.
1346 Usually, this is the first function that should be used to communicate with the driver.
1347 It returns the names of the adapters installed on the system <B>and supported by WinPcap</B>.
1348 After the names of the adapters, pStr contains a string that describes each of them.
1351 the result of this function is obtained querying the registry, therefore the format
1352 of the result in Windows NTx is different from the one in Windows 9x. Windows 9x uses the ASCII
1353 encoding method to store a string, while Windows NTx uses UNICODE. After a call to PacketGetAdapterNames
1354 in Windows 95x, pStr contains, in succession:
1355 - a variable number of ASCII strings, each with the names of an adapter, separated by a "\0"
1357 - a number of ASCII strings, each with the description of an adapter, separated by a "\0". The number
1358 of descriptions is the same of the one of names. The fisrt description corresponds to the first name, and
1362 In Windows NTx, pStr contains: the names of the adapters, in UNICODE format, separated by a single UNICODE "\0" (i.e. 2 ASCII "\0"), a double UNICODE "\0", followed by the descriptions of the adapters, in ASCII format, separated by a single ASCII "\0" . The string is terminated by a double ASCII "\0".
1363 - a variable number of UNICODE strings, each with the names of an adapter, separated by a UNICODE "\0"
1364 - a double UNICODE "\0"
1365 - a number of ASCII strings, each with the description of an adapter, separated by an ASCII "\0".
1366 - a double ASCII "\0".
1369 BOOLEAN PacketGetAdapterNames(PTSTR pStr, PULONG BufferSize)
1371 HKEY LinkageKey, AdapKey;
1372 DWORD RegKeySize = 0;
1380 PPACKET_OID_DATA OidData;
1381 int i = 0, k, rewind;
1383 TCHAR AdapName[256];
1385 ODSEx("PacketGetAdapterNames: BufferSize=%d\n",*BufferSize);
1387 OidData = GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT, 512);
1388 if (OidData == NULL) {
1389 ODS("PacketGetAdapterNames: GlobalAlloc Failed\n");
1393 Status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
1394 TEXT("SYSTEM\\ControlSet001\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}"),
1395 0, KEY_READ, &AdapKey);
1397 // Get the size to allocate for the original device names
1398 while ((Result = RegEnumKey(AdapKey, i, AdapName, sizeof(AdapName)/2)) == ERROR_SUCCESS) {
1399 Status = RegOpenKeyEx(AdapKey, AdapName,0, KEY_READ, &LinkageKey);
1400 Status = RegOpenKeyExW(LinkageKey, L"Linkage",0, KEY_READ, &LinkageKey);
1401 Status = RegQueryValueExW(LinkageKey, L"Export", NULL, NULL, NULL, &dim);
1403 if (Status!=ERROR_SUCCESS) continue;
1407 // Allocate the memory for the original device names
1408 ODSEx("Need %d bytes for the names\n", RegKeySize+2);
1409 BpStr = GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT, RegKeySize+2);
1410 if (BpStr == NULL || RegKeySize > *BufferSize) {
1411 ODS("PacketGetAdapterNames: GlobalAlloc Failed\n");
1412 GlobalFreePtr(OidData);
1418 ODS("PacketGetAdapterNames: Cycling through the adapters:\n");
1420 // Copy the names to the buffer
1421 while ((Result = RegEnumKey(AdapKey, i, AdapName, sizeof(AdapName)/2)) == ERROR_SUCCESS) {
1422 WCHAR UpperBindStr[64];
1427 Status = RegOpenKeyEx(AdapKey,AdapName,0,KEY_READ,&LinkageKey);
1428 Status = RegOpenKeyExW(LinkageKey,L"Linkage",0,KEY_READ,&LinkageKey);
1430 dim=sizeof(UpperBindStr);
1431 Status=RegQueryValueExW(LinkageKey,L"UpperBind",NULL,NULL,(PUCHAR)UpperBindStr,&dim);
1433 ODSEx("UpperBind=%S ", UpperBindStr);
1435 if( Status!=ERROR_SUCCESS || _wcsicmp(UpperBindStr,L"NdisWan")==0 ){
1436 ODS("Name = SKIPPED\n");
1441 Status=RegQueryValueExW(LinkageKey,L"Export",NULL,NULL,(LPBYTE)BpStr+k,&dim);
1442 if(Status!=ERROR_SUCCESS){
1443 ODS("Name = SKIPPED (error reading the key)\n");
1447 ODSEx("Name = %S\n", (LPBYTE)BpStr+k);
1452 CloseHandle(AdapKey);
1454 #ifdef _DEBUG_TO_FILE
1455 //dump BpStr for debug purposes
1456 ODS("Dumping BpStr:");
1459 f = fopen("winpcap_debug.txt", "a");
1461 if(!(i%32))fprintf(f, "\n ");
1462 fprintf(f, "%c " , *((LPBYTE)BpStr+i));
1472 DescBuf=GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT, 4096);
1473 if (DescBuf == NULL) {
1474 GlobalFreePtr (BpStr);
1475 GlobalFreePtr(OidData);
1480 for(i=0,k=0;BpStr[i]!=0 || BpStr[i+1]!=0;){
1482 if(k+wcslen(BpStr+i)+30 > *BufferSize){
1483 // Input buffer too small
1484 GlobalFreePtr(OidData);
1485 GlobalFreePtr (BpStr);
1486 GlobalFreePtr (DescBuf);
1487 ODS("PacketGetAdapterNames: Input buffer too small!\n");
1491 // Create the device name
1493 memcpy(pStr+k,BpStr+i,16);
1494 memcpy(pStr+k+8,TEXT("NPF_"),8);
1497 while(BpStr[i-1]!=0){
1498 pStr[k++]=BpStr[i++];
1502 adapter=PacketOpenAdapter(pStr+rewind);
1508 // Retrieve the description
1509 OidData->Oid = OID_GEN_VENDOR_DESCRIPTION;
1510 OidData->Length = 256;
1511 ZeroMemory(OidData->Data,256);
1512 Status = PacketRequest(adapter,FALSE,OidData);
1513 if(Status==0 || ((char*)OidData->Data)[0]==0){
1518 ODSEx("Adapter Description=%s\n\n",OidData->Data);
1520 // Copy the description
1521 TTpStr=(char*)(OidData->Data);
1527 // Close the adapter
1528 PacketCloseAdapter(adapter);
1536 if ((ULONG)(DpStr - DescBuf + k) < *BufferSize) {
1537 memcpy(pStr + k, DescBuf, DpStr - DescBuf);
1539 GlobalFreePtr(OidData);
1540 GlobalFreePtr(BpStr);
1541 GlobalFreePtr(DescBuf);
1542 ODS("\nPacketGetAdapterNames: ended with failure\n");
1546 GlobalFreePtr(OidData);
1547 GlobalFreePtr(BpStr);
1548 GlobalFreePtr(DescBuf);
1549 ODS("\nPacketGetAdapterNames: ended correctly\n");
1555 ODS("Adapters not found under SYSTEM\\ControlSet001\\Control\\Class. Using the TCP/IP bindings.\n");
1557 GlobalFreePtr(BpStr);
1558 Status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
1559 TEXT("SYSTEM\\ControlSet001\\Services\\Tcpip\\Linkage"),
1560 0, KEY_READ, &LinkageKey);
1561 if (Status == ERROR_SUCCESS) {
1562 // Retrieve the length of the key
1563 Status = RegQueryValueEx(LinkageKey, TEXT("bind"), NULL, &RegType, NULL, &RegKeySize);
1564 // Allocate the buffer
1565 BpStr = GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT, RegKeySize + 2);
1566 if (BpStr == NULL || RegKeySize > *BufferSize) {
1567 GlobalFreePtr(OidData);
1570 Status = RegQueryValueEx(LinkageKey, TEXT("bind"), NULL, &RegType, (LPBYTE)BpStr, &RegKeySize);
1571 RegCloseKey(LinkageKey);
1573 //ODS("SYSTEM\\ControlSet001\\Control\\Class - RegKey not found.\n");
1574 ODS("SYSTEM\\ControlSet001\\Services\\Tcpip\\Linkage - RegKey not found.\n");
1576 if (Status == ERROR_SUCCESS) {
1577 DescBuf = GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT, 4096);
1578 if (DescBuf == NULL) {
1579 GlobalFreePtr(BpStr);
1580 GlobalFreePtr(OidData);
1584 for (i = 0, k = 0; BpStr[i] != 0 || BpStr[i+1] != 0; ) {
1585 if (k + wcslen(BpStr + i) + 30 > *BufferSize) {
1586 // Input buffer too small
1587 GlobalFreePtr(OidData);
1588 GlobalFreePtr(BpStr);
1589 GlobalFreePtr(DescBuf);
1593 ODS("\tCreating a device name - started.\n");
1595 // Create the device name
1597 memcpy(pStr + k,BpStr + i,16);
1598 memcpy(pStr + k + 8, TEXT("NPF_"), 8);
1601 while (BpStr[i - 1] != 0) {
1602 pStr[k++] = BpStr[i++];
1605 adapter = PacketOpenAdapter(pStr+rewind);
1606 if (adapter == NULL) {
1610 // Retrieve the description
1611 OidData->Oid = OID_GEN_VENDOR_DESCRIPTION;
1612 OidData->Length = 256;
1613 Status = PacketRequest(adapter, FALSE, OidData);
1614 if (Status == 0 || ((char*)OidData->Data)[0] == 0) {
1616 ODS("\tCreating a device name - Retrieve the description.\n");
1620 // Copy the description
1621 TTpStr = (char*)(OidData->Data);
1622 while (*TTpStr != 0){
1623 *DpStr++ = *TTpStr++;
1625 *DpStr++ = *TTpStr++;
1626 // Close the adapter
1627 PacketCloseAdapter(adapter);
1629 ODS("\tCreating a device name - completed.\n");
1636 if ((ULONG)(DpStr - DescBuf + k) < *BufferSize) {
1637 memcpy(pStr + k, DescBuf, DpStr-DescBuf);
1639 GlobalFreePtr(OidData);
1640 GlobalFreePtr(BpStr);
1641 GlobalFreePtr(DescBuf);
1645 GlobalFreePtr(OidData);
1646 GlobalFreePtr(BpStr);
1647 GlobalFreePtr(DescBuf);
1648 ODS("PacketGetAdapterNames() returning TRUE\n");
1651 MessageBox(NULL,TEXT("Can not find TCP/IP bindings.\nIn order to run the packet capture driver you must install TCP/IP."),szWindowTitle,MB_OK);
1652 ODS("Cannot find the TCP/IP bindings\n");
1659 \brief Returns comprehensive information the addresses of an adapter.
1660 \param AdapterName String that contain _ADAPTER structure.
1661 \param buffer A user allocated array of npf_if_addr that will be filled by the function.
1662 \param NEntries Size of the array (in npf_if_addr).
1663 \return If the function succeeds, the return value is nonzero.
1665 This function grabs from the registry information like the IP addresses, the netmasks
1666 and the broadcast addresses of an interface. The buffer passed by the user is filled with
1667 npf_if_addr structures, each of which contains the data for a single address. If the buffer
1668 is full, the reaming addresses are dropeed, therefore set its dimension to sizeof(npf_if_addr)
1669 if you want only the first address.
1672 BOOLEAN PacketGetNetInfoEx(LPTSTR AdapterName, npf_if_addr* buffer, PLONG NEntries)
1675 WCHAR *AdapterNameU;
1683 WCHAR String[1024+1];
1687 struct sockaddr_in *TmpAddr, *TmpBroad;
1688 LONG naddrs,nmasks,StringPos;
1689 DWORD ZeroBroadcast;
1691 AdapterNameA = (char*)AdapterName;
1692 if(AdapterNameA[1] != 0) { //ASCII
1693 AdapterNameU = SChar2WChar(AdapterNameA);
1694 AdapterName = AdapterNameU;
1696 AdapterNameU = NULL;
1698 ifname = wcsrchr(AdapterName, '\\');
1700 ifname = AdapterName;
1703 if (wcsncmp(ifname, L"NPF_", 4) == 0)
1706 if( RegOpenKeyEx(HKEY_LOCAL_MACHINE,
1707 TEXT("SYSTEM\\ControlSet001\\Services\\Tcpip\\Parameters\\Interfaces"),
1708 0, KEY_READ, &UnderTcpKey) == ERROR_SUCCESS)
1710 status = RegOpenKeyExW(UnderTcpKey,ifname,0,KEY_READ,&TcpIpKey);
1711 if (status != ERROR_SUCCESS) {
1712 RegCloseKey(UnderTcpKey);
1719 // Query the registry key with the interface's adresses
1720 status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
1721 TEXT("SYSTEM\\ControlSet001\\Services"),
1722 0,KEY_READ,&SystemKey);
1723 if (status != ERROR_SUCCESS)
1725 status = RegOpenKeyExW(SystemKey,ifname,0,KEY_READ,&InterfaceKey);
1726 if (status != ERROR_SUCCESS) {
1727 RegCloseKey(SystemKey);
1730 RegCloseKey(SystemKey);
1731 status = RegOpenKeyEx(InterfaceKey,TEXT("Parameters"),0,KEY_READ,&ParametersKey);
1732 if (status != ERROR_SUCCESS) {
1733 RegCloseKey(InterfaceKey);
1736 RegCloseKey(InterfaceKey);
1737 status = RegOpenKeyEx(ParametersKey,TEXT("TcpIp"),0,KEY_READ,&TcpIpKey);
1738 if (status != ERROR_SUCCESS) {
1739 RegCloseKey(ParametersKey);
1742 RegCloseKey(ParametersKey);
1743 BufLen = sizeof String;
1747 /* Try to detect if the interface has a zero broadcast addr */
1748 status=RegQueryValueEx(TcpIpKey,TEXT("UseZeroBroadcast"),NULL,&RegType,(LPBYTE)&ZeroBroadcast,&BufLen);
1749 if (status != ERROR_SUCCESS)
1753 /* See if DHCP is used by this system */
1754 status=RegQueryValueEx(TcpIpKey,TEXT("EnableDHCP"),NULL,&RegType,(LPBYTE)&DHCPEnabled,&BufLen);
1755 if (status != ERROR_SUCCESS)
1759 /* Retrieve the adrresses */
1762 BufLen = sizeof String;
1763 // Open the key with the addresses
1764 status = RegQueryValueEx(TcpIpKey,TEXT("DhcpIPAddress"),NULL,&RegType,(LPBYTE)String,&BufLen);
1765 if (status != ERROR_SUCCESS) {
1766 RegCloseKey(TcpIpKey);
1770 // scan the key to obtain the addresses
1772 for(naddrs = 0;naddrs <* NEntries;naddrs++){
1773 TmpAddr = (struct sockaddr_in *) &(buffer[naddrs].IPAddress);
1775 if((TmpAddr->sin_addr.S_un.S_addr = inet_addrU(String + StringPos))!= -1){
1776 TmpAddr->sin_family = AF_INET;
1778 TmpBroad = (struct sockaddr_in *) &(buffer[naddrs].Broadcast);
1779 TmpBroad->sin_family = AF_INET;
1780 if(ZeroBroadcast==0)
1781 TmpBroad->sin_addr.S_un.S_addr = 0xffffffff; // 255.255.255.255
1783 TmpBroad->sin_addr.S_un.S_addr = 0; // 0.0.0.0
1785 while(*(String + StringPos) != 0)StringPos++;
1788 if(*(String + StringPos) == 0 || (StringPos * sizeof (WCHAR)) >= BufLen)
1794 BufLen = sizeof String;
1795 // Open the key with the netmasks
1796 status = RegQueryValueEx(TcpIpKey,TEXT("DhcpSubnetMask"),NULL,&RegType,(LPBYTE)String,&BufLen);
1797 if (status != ERROR_SUCCESS) {
1798 RegCloseKey(TcpIpKey);
1802 // scan the key to obtain the masks
1804 for(nmasks = 0;nmasks < *NEntries;nmasks++){
1805 TmpAddr = (struct sockaddr_in *) &(buffer[nmasks].SubnetMask);
1807 if((TmpAddr->sin_addr.S_un.S_addr = inet_addrU(String + StringPos))!= -1){
1808 TmpAddr->sin_family = AF_INET;
1810 while(*(String + StringPos) != 0)StringPos++;
1813 if(*(String + StringPos) == 0 || (StringPos * sizeof (WCHAR)) >= BufLen)
1819 // The number of masks MUST be equal to the number of adresses
1820 if(nmasks != naddrs){
1821 RegCloseKey(TcpIpKey);
1828 BufLen = sizeof String;
1829 // Open the key with the addresses
1830 status = RegQueryValueEx(TcpIpKey,TEXT("IPAddress"),NULL,&RegType,(LPBYTE)String,&BufLen);
1831 if (status != ERROR_SUCCESS) {
1832 RegCloseKey(TcpIpKey);
1836 // scan the key to obtain the addresses
1838 for(naddrs = 0;naddrs < *NEntries;naddrs++){
1839 TmpAddr = (struct sockaddr_in *) &(buffer[naddrs].IPAddress);
1841 if((TmpAddr->sin_addr.S_un.S_addr = inet_addrU(String + StringPos))!= -1){
1842 TmpAddr->sin_family = AF_INET;
1844 TmpBroad = (struct sockaddr_in *) &(buffer[naddrs].Broadcast);
1845 TmpBroad->sin_family = AF_INET;
1846 if(ZeroBroadcast==0)
1847 TmpBroad->sin_addr.S_un.S_addr = 0xffffffff; // 255.255.255.255
1849 TmpBroad->sin_addr.S_un.S_addr = 0; // 0.0.0.0
1851 while(*(String + StringPos) != 0)StringPos++;
1854 if(*(String + StringPos) == 0 || (StringPos * sizeof (WCHAR)) >= BufLen)
1860 BufLen = sizeof String;
1861 // Open the key with the netmasks
1862 status = RegQueryValueEx(TcpIpKey,TEXT("SubnetMask"),NULL,&RegType,(LPBYTE)String,&BufLen);
1863 if (status != ERROR_SUCCESS) {
1864 RegCloseKey(TcpIpKey);
1868 // scan the key to obtain the masks
1870 for(nmasks = 0;nmasks <* NEntries;nmasks++){
1871 TmpAddr = (struct sockaddr_in *) &(buffer[nmasks].SubnetMask);
1873 if((TmpAddr->sin_addr.S_un.S_addr = inet_addrU(String + StringPos))!= -1){
1874 TmpAddr->sin_family = AF_INET;
1876 while(*(String + StringPos) != 0)StringPos++;
1879 if(*(String + StringPos) == 0 || (StringPos * sizeof (WCHAR)) >= BufLen)
1885 // The number of masks MUST be equal to the number of adresses
1886 if(nmasks != naddrs){
1887 RegCloseKey(TcpIpKey);
1893 *NEntries = naddrs + 1;
1895 RegCloseKey(TcpIpKey);
1897 if (status != ERROR_SUCCESS) {
1902 if (AdapterNameU != NULL)
1907 if (AdapterNameU != NULL)
1913 \brief Returns the IP address and the netmask of an adapter.
1914 \param AdapterName String that contain _ADAPTER structure.
1915 \param netp Pointer to a variable that will receive the IP address of the adapter.
1916 \param maskp Pointer to a variable that will receive the netmask of the adapter.
1917 \return If the function succeeds, the return value is nonzero.
1919 \note this function is obsolete and is maintained for backward compatibility. Use PacketGetNetInfoEx() instead.
1922 BOOLEAN PacketGetNetInfo(LPTSTR AdapterName, PULONG netp, PULONG maskp)
1925 WCHAR *AdapterNameU;
1932 WCHAR String[1024+1];
1938 AdapterNameA = (char*)AdapterName;
1939 if(AdapterNameA[1] != 0) { //ASCII
1940 AdapterNameU = SChar2WChar(AdapterNameA);
1941 AdapterName = AdapterNameU;
1943 AdapterNameU = NULL;
1945 ifname = wcsrchr(AdapterName, '\\');
1947 ifname = AdapterName;
1950 if (wcsncmp(ifname, L"NPF_", 4) == 0)
1952 status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
1953 TEXT("SYSTEM\\ControlSet001\\Services"),
1954 0,KEY_READ,&SystemKey);
1955 if (status != ERROR_SUCCESS)
1957 status = RegOpenKeyExW(SystemKey,ifname,0,KEY_READ,&InterfaceKey);
1958 if (status != ERROR_SUCCESS) {
1959 RegCloseKey(SystemKey);
1962 RegCloseKey(SystemKey);
1963 status = RegOpenKeyEx(InterfaceKey,TEXT("Parameters"),0,KEY_READ,&ParametersKey);
1964 if (status != ERROR_SUCCESS) {
1965 RegCloseKey(InterfaceKey);
1968 RegCloseKey(InterfaceKey);
1969 status = RegOpenKeyEx(ParametersKey,TEXT("TcpIp"),0,KEY_READ,&TcpIpKey);
1970 if (status != ERROR_SUCCESS) {
1971 RegCloseKey(ParametersKey);
1974 RegCloseKey(ParametersKey);
1977 /* See if DHCP is used by this system */
1978 status=RegQueryValueEx(TcpIpKey,TEXT("EnableDHCP"),NULL,&RegType,(LPBYTE)&DHCPEnabled,&BufLen);
1979 if (status != ERROR_SUCCESS)
1983 /* Retrieve the netmask */
1986 BufLen = sizeof String;
1987 status = RegQueryValueEx(TcpIpKey,TEXT("DhcpIPAddress"),NULL,&RegType,(LPBYTE)String,&BufLen);
1988 if (status != ERROR_SUCCESS) {
1989 RegCloseKey(TcpIpKey);
1993 TAddr = inet_addrU(String);
1994 // swap bytes for backward compatibility
1996 *((char*)netp+i) = *((char*)&TAddr+3-i);
1999 BufLen = sizeof String;
2000 status=RegQueryValueEx(TcpIpKey,TEXT("DHCPSubnetMask"),NULL,&RegType,
2001 (LPBYTE)String,&BufLen);
2003 TAddr = inet_addrU(String);
2004 // swap bytes for backward compatibility
2006 *((char*)maskp+i) = *((char*)&TAddr+3-i);
2013 BufLen = sizeof String;
2014 status = RegQueryValueEx(TcpIpKey,TEXT("IPAddress"),NULL,&RegType,(LPBYTE)String,&BufLen);
2015 if (status != ERROR_SUCCESS) {
2016 RegCloseKey(TcpIpKey);
2020 TAddr = inet_addrU(String);
2021 // swap bytes for backward compatibility
2023 *((char*)netp+i) = *((char*)&TAddr+3-i);
2026 BufLen = sizeof String;
2027 status=RegQueryValueEx(TcpIpKey,TEXT("SubnetMask"),NULL,&RegType,
2028 (LPBYTE)String,&BufLen);
2030 TAddr = inet_addrU(String);
2031 // swap bytes for backward compatibility
2033 *((char*)maskp+i) = *((char*)&TAddr+3-i);
2039 if (status != ERROR_SUCCESS) {
2040 RegCloseKey(TcpIpKey);
2045 if (AdapterNameU != NULL)
2050 if (AdapterNameU != NULL)