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.
26 //#include <windowsx.h>
32 /****** KERNEL Macro APIs ******************************************************/
34 #define GetInstanceModule(hInst) (HMODULE)(hInst)
35 #define GlobalPtrHandle(lp) ((HGLOBAL)GlobalHandle(lp))
36 #define GlobalLockPtr(lp) ((BOOL)GlobalLock(GlobalPtrHandle(lp)))
37 #define GlobalUnlockPtr(lp) GlobalUnlock(GlobalPtrHandle(lp))
38 #define GlobalAllocPtr(flags, cb) (GlobalLock(GlobalAlloc((flags), (cb))))
39 #define GlobalReAllocPtr(lp, cbNew, flags) (GlobalUnlockPtr(lp), GlobalLock(GlobalReAlloc(GlobalPtrHandle(lp) , (cbNew), (flags))))
40 #define GlobalFreePtr(lp) (GlobalUnlockPtr(lp), (BOOL)(ULONG_PTR)GlobalFree(GlobalPtrHandle(lp)))
43 #define GMEM_MOVEABLE 0
47 /// Title of error windows
48 TCHAR szWindowTitle[] = TEXT("PACKET.DLL");
51 #define ODS(_x) OutputDebugString(TEXT(_x))
52 //#define ODSEx(_x, _y)
58 \brief Macro to print a debug string. The behavior differs depending on the debug level
62 f = fopen("winpcap_debug.txt", "a"); \
63 fprintf(f, "%s", _x); \
67 \brief Macro to print debug data with the printf convention. The behavior differs depending on
70 #define ODSEx(_x, _y) { \
72 f = fopen("winpcap_debug.txt", "a"); \
77 LONG PacketDumpRegistryKey(PCHAR KeyName, PCHAR FileName);
85 SC_HANDLE scmHandle = NULL;
86 SC_HANDLE srvHandle = NULL;
87 LPCTSTR NPFServiceName = TEXT("NPF");
88 LPCTSTR NPFServiceDesc = TEXT("Netgroup Packet Filter");
89 LPCTSTR NPFDriverName = TEXT("\\npf.sys");
90 LPCTSTR NPFRegistryLocation = TEXT("SYSTEM\\ControlSet001\\Services\\NPF");
93 //---------------------------------------------------------------------------
96 \brief The main dll function.
99 BOOL APIENTRY DllMain (HANDLE DllHandle,DWORD Reason,LPVOID lpReserved)
105 case DLL_PROCESS_ATTACH:
107 ODS("\n************Packet32: DllMain************\n");
109 #ifdef _DEBUG_TO_FILE
110 // dump a bunch of registry keys useful for debug to file
111 PacketDumpRegistryKey("HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}",
113 PacketDumpRegistryKey("HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Services\\Tcpip",
115 PacketDumpRegistryKey("HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Services\\NPF",
117 PacketDumpRegistryKey("HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Services",
122 case DLL_PROCESS_DETACH:
133 \brief Converts an ASCII string to UNICODE. Uses the MultiByteToWideChar() system function.
134 \param string The string to convert.
135 \return The converted string.
138 WCHAR* SChar2WChar(char* string)
141 TmpStr=(WCHAR*) malloc ((strlen(string)+2)*sizeof(WCHAR));
143 MultiByteToWideChar(CP_ACP, 0, string, -1, TmpStr, (strlen(string)+2));
149 \brief Sets the maximum possible lookahead buffer for the driver's Packet_tap() function.
150 \param AdapterObject Handle to the service control manager.
151 \return If the function succeeds, the return value is nonzero.
153 The lookahead buffer is the portion of packet that Packet_tap() can access from the NIC driver's memory
154 without performing a copy. This function tries to increase the size of that buffer.
157 BOOLEAN PacketSetMaxLookaheadsize (LPADAPTER AdapterObject)
160 ULONG IoCtlBufferLength=(sizeof(PACKET_OID_DATA)+sizeof(ULONG)-1);
161 PPACKET_OID_DATA OidData;
163 OidData=GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT,IoCtlBufferLength);
164 if (OidData == NULL) {
165 ODS("PacketSetMaxLookaheadsize failed\n");
169 //set the size of the lookahead buffer to the maximum available by the the NIC driver
170 OidData->Oid=OID_GEN_MAXIMUM_LOOKAHEAD;
171 OidData->Length=sizeof(ULONG);
172 Status=PacketRequest(AdapterObject,FALSE,OidData);
173 OidData->Oid=OID_GEN_CURRENT_LOOKAHEAD;
174 Status=PacketRequest(AdapterObject,TRUE,OidData);
175 GlobalFreePtr(OidData);
180 \brief Retrieves the event associated in the driver with a capture instance and stores it in an
182 \param AdapterObject Handle to the service control manager.
183 \return If the function succeeds, the return value is nonzero.
185 This function is used by PacketOpenAdapter() to retrieve the read event from the driver by means of an ioctl
186 call and set it in the _ADAPTER structure pointed by AdapterObject.
189 BOOLEAN PacketSetReadEvt(LPADAPTER AdapterObject)
194 // this tells the terminal service to retrieve the event from the global namespace
195 wcsncpy(EventName,L"Global\\",sizeof(L"Global\\"));
197 // retrieve the name of the shared event from the driver
198 if(DeviceIoControl(AdapterObject->hFile,pBIOCEVNAME,NULL,0,EventName+7,13*sizeof(TCHAR),&BytesReturned,NULL)==FALSE) return FALSE;
200 EventName[20]=0; // terminate the string
202 // open the shared event
203 AdapterObject->ReadEvent=CreateEventW(NULL,
208 // in NT4 "Global\" is not automatically ignored: try to use simply the event name
209 if(GetLastError()!=ERROR_ALREADY_EXISTS){
210 if(AdapterObject->ReadEvent != NULL)
211 CloseHandle(AdapterObject->ReadEvent);
213 // open the shared event
214 AdapterObject->ReadEvent=CreateEventW(NULL,
220 if(AdapterObject->ReadEvent==NULL || GetLastError()!=ERROR_ALREADY_EXISTS){
221 ODS("PacketSetReadEvt: error retrieving the event from the kernel\n");
225 AdapterObject->ReadTimeOut=0;
232 \brief Installs the NPF device driver.
233 \param ascmHandle Handle to the service control manager.
234 \param ascmHandle A pointer to a handle that will receive the pointer to the driver's service.
235 \param driverPath The full path of the .sys file to load.
236 \return If the function succeeds, the return value is nonzero.
238 This function installs the driver's service in the system using the CreateService function.
241 BOOL PacketInstallDriver(SC_HANDLE ascmHandle, SC_HANDLE* srvHandle, TCHAR* driverPath)
246 ODS("installdriver\n");
248 if (GetFileAttributes(driverPath) != 0xffffffff) {
249 *srvHandle = CreateService(ascmHandle,
253 SERVICE_KERNEL_DRIVER,
254 SERVICE_DEMAND_START,
255 SERVICE_ERROR_NORMAL,
257 NULL, NULL, NULL, NULL, NULL);
258 if (*srvHandle == NULL) {
259 if (GetLastError() == ERROR_SERVICE_EXISTS) {
260 //npf.sys already existed
264 //Created service for npf.sys
268 if (result == TRUE) {
269 if (*srvHandle != NULL) {
270 CloseServiceHandle(*srvHandle);
274 if (result == FALSE){
275 err = GetLastError();
277 ODSEx("PacketInstallDriver failed, Error=%d\n",err);
285 \brief Convert a Unicode dotted-quad to a 32-bit IP address.
286 \param cp A string containing the address.
287 \return the converted 32-bit numeric address.
289 Doesn't check to make sure the address is valid.
293 ULONG inet_addrU(const WCHAR *cp)
300 for (i = 0; i < 4; i++) {
302 while ((c = *cp++) != '\0' && c != '.') {
303 if (c < '0' || c > '9')
305 part = part*10 + (c - '0');
309 val = val | (part << i*8);
312 return -1; // extra gunk at end of string
315 return -1; // string ends early
322 \brief Dumps a registry key to disk in text format. Uses regedit.
323 \param KeyName Name of the ket to dump. All its subkeys will be saved recursively.
324 \param FileName Name of the file that will contain the dump.
325 \return If the function succeeds, the return value is nonzero.
327 For debugging purposes, we use this function to obtain some registry keys from the user's machine.
330 #ifdef _DEBUG_TO_FILE
332 LONG PacketDumpRegistryKey(PCHAR KeyName, PCHAR FileName)
336 strcpy(Command, "regedit /e ");
337 strcat(Command, FileName);
338 strcat(Command, " ");
339 strcat(Command, KeyName);
341 /// Let regedit do the dirt work for us
348 //---------------------------------------------------------------------------
350 //---------------------------------------------------------------------------
352 /** @ingroup packetapi
356 /** @defgroup packet32 Packet.dll exported functions and variables
360 /// Current packet.dll Version. It can be retrieved directly or through the PacketGetVersion() function.
361 char PacketLibraryVersion[] = "2.3";
364 \brief Returns a string with the dll version.
365 \return A char pointer to the version of the library.
367 PCHAR PacketGetVersion(){
368 return PacketLibraryVersion;
372 \brief Returns information about the MAC type of an adapter.
373 \param AdapterObject The adapter on which information is needed.
374 \param type Pointer to a NetType structure that will be filled by the function.
375 \return If the function succeeds, the return value is nonzero, otherwise the return value is zero.
377 This function return the link layer technology and the speed (in bps) of an opened adapter.
378 The LinkType field of the type parameter can have one of the following values:
380 - NdisMedium802_3: Ethernet (802.3)
382 - NdisMedium802_5: Token Ring (802.5)
383 - NdisMediumFddi: FDDI
385 - NdisMediumArcnet878_2: ARCNET (878.2)
387 BOOLEAN PacketGetNetType (LPADAPTER AdapterObject,NetType *type)
390 ULONG IoCtlBufferLength=(sizeof(PACKET_OID_DATA)+sizeof(ULONG)-1);
391 PPACKET_OID_DATA OidData;
393 OidData=GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT,IoCtlBufferLength);
394 if (OidData == NULL) {
395 ODS("PacketGetNetType failed\n");
398 //get the link-layer type
399 OidData->Oid = OID_GEN_MEDIA_IN_USE;
400 OidData->Length = sizeof (ULONG);
401 Status = PacketRequest(AdapterObject,FALSE,OidData);
402 type->LinkType=*((UINT*)OidData->Data);
404 //get the link-layer speed
405 OidData->Oid = OID_GEN_LINK_SPEED;
406 OidData->Length = sizeof (ULONG);
407 Status = PacketRequest(AdapterObject,FALSE,OidData);
408 type->LinkSpeed=*((UINT*)OidData->Data)*100;
409 GlobalFreePtr (OidData);
411 ODSEx("Media:%d ",type->LinkType);
412 ODSEx("Speed=%d\n",type->LinkSpeed);
418 \brief Stops and unloads the WinPcap device driver.
419 \return If the function succeeds, the return value is nonzero, otherwise it is zero.
421 This function can be used to unload the driver from memory when the application no more needs it.
422 Note that the driver is physically stopped and unloaded only when all the files on its devices
423 are closed, i.e. when all the applications that use WinPcap close all their adapters.
425 BOOL PacketStopDriver()
428 SC_HANDLE schService;
430 SERVICE_STATUS serviceStatus;
432 scmHandle = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
434 if(scmHandle != NULL){
436 schService = OpenService (scmHandle,
441 if (schService != NULL)
444 ret = ControlService (schService,
445 SERVICE_CONTROL_STOP,
452 CloseServiceHandle (schService);
454 CloseServiceHandle(scmHandle);
465 \brief Opens an adapter.
466 \param AdapterName A string containing the name of the device to open.
467 Use the PacketGetAdapterNames() function to retrieve the list of available devices.
468 \return If the function succeeds, the return value is the pointer to a properly initialized ADAPTER object,
469 otherwise the return value is NULL.
471 This function tries to load and start the packet driver at the first invocation. In this way,
472 the management of the driver is transparent to the application, that simply needs to open an adapter to start
475 \note the Windows 95 version of the NPF driver works with the ASCII string format, while the Windows NT
476 version works with UNICODE. Therefore, AdapterName \b should be an ASCII string in Windows 95, and a UNICODE
477 string in Windows NT. This difference is not a problem if the string pointed by AdapterName was obtained
478 through the PacketGetAdapterNames function, because it returns the names of the adapters in the proper format.
479 Problems can arise in Windows NT when the string is obtained from ANSI C functions like scanf, because they
480 use the ASCII format. Since this could be a relevant problem during the porting of command-line applications
481 from UNIX, we included in the Windows NT version of PacketOpenAdapter the ability to detect ASCII strings and
482 convert them to UNICODE before sending them to the device driver. Therefore PacketOpenAdapter in Windows NT
483 accepts both the ASCII and the UNICODE format. If a ASCII string is received, it is converted to UNICODE
484 by PACKET.DLL before being passed to the driver.
486 LPADAPTER PacketOpenAdapter(LPTSTR AdapterName)
493 SC_HANDLE svcHandle = NULL;
494 TCHAR driverPath[512];
498 SERVICE_STATUS SStat;
500 WCHAR SymbolicLink[128];
502 ODSEx("PacketOpenAdapter: trying to open the adapter=%S\n",AdapterName);
504 scmHandle = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
505 if(scmHandle == NULL){
506 error = GetLastError();
507 ODSEx("OpenSCManager failed! Error=%d\n", error);
510 GetCurrentDirectory(512, driverPath);
511 wsprintf(driverPath + wcslen(driverPath), NPFDriverName);
513 // check if the NPF registry key is already present
514 // this means that the driver is already installed and that we don't need to call PacketInstallDriver
515 KeyRes=RegOpenKeyEx(HKEY_LOCAL_MACHINE,
521 if(KeyRes != ERROR_SUCCESS){
522 Result = PacketInstallDriver(scmHandle,&svcHandle,driverPath);
525 RegCloseKey(PathKey);
530 srvHandle = OpenService(scmHandle, NPFServiceName, SERVICE_START | SERVICE_QUERY_STATUS );
531 if (srvHandle != NULL){
533 QuerySStat = QueryServiceStatus(srvHandle, &SStat);
534 ODSEx("The status of the driver is:%d\n",SStat.dwCurrentState);
536 if (!QuerySStat || SStat.dwCurrentState != SERVICE_RUNNING){
537 ODS("Calling startservice\n");
538 if (StartService(srvHandle, 0, NULL)==0){
539 error = GetLastError();
540 if (error!=ERROR_SERVICE_ALREADY_RUNNING && error!=ERROR_ALREADY_EXISTS){
542 if (scmHandle != NULL) CloseServiceHandle(scmHandle);
543 error = GetLastError();
544 ODSEx("PacketOpenAdapter: StartService failed, Error=%d\n",error);
550 error = GetLastError();
551 ODSEx("OpenService failed! Error=%d", error);
554 if (GetSystemDirectory(WinPath, sizeof(WinPath)/sizeof(TCHAR)) == 0) {
557 wsprintf(driverPath, TEXT("%s\\drivers%s"), WinPath, NPFDriverName);
559 if (KeyRes != ERROR_SUCCESS) {
560 Result = PacketInstallDriver(scmHandle,&svcHandle,driverPath);
565 srvHandle = OpenService(scmHandle,NPFServiceName,SERVICE_START);
566 if (srvHandle != NULL) {
567 QuerySStat = QueryServiceStatus(srvHandle, &SStat);
568 ODSEx("The status of the driver is:%d\n",SStat.dwCurrentState);
569 if (!QuerySStat || SStat.dwCurrentState != SERVICE_RUNNING) {
570 ODS("Calling startservice\n");
571 if (StartService(srvHandle, 0, NULL) == 0) {
572 error = GetLastError();
573 if (error != ERROR_SERVICE_ALREADY_RUNNING && error!=ERROR_ALREADY_EXISTS) {
575 if (scmHandle != NULL) CloseServiceHandle(scmHandle);
576 ODSEx("PacketOpenAdapter: StartService failed, Error=%d\n",error);
582 error = GetLastError();
583 ODSEx("OpenService failed! Error=%d", error);
588 if (scmHandle != NULL) CloseServiceHandle(scmHandle);
590 AdapterNameA = (char*)AdapterName;
591 if (AdapterNameA[1] != 0) { // ASCII
592 AdapterNameU = SChar2WChar(AdapterNameA);
593 AdapterName = AdapterNameU;
598 lpAdapter = (LPADAPTER)GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT,sizeof(ADAPTER));
599 if (lpAdapter == NULL) {
600 ODS("PacketOpenAdapter: GlobalAlloc Failed\n");
601 error = GetLastError();
602 if (AdapterNameU != NULL) free(AdapterNameU);
603 //set the error to the one on which we failed
605 ODS("PacketOpenAdapter: Failed to allocate the adapter structure\n");
608 lpAdapter->NumWrites = 1;
610 wsprintf(SymbolicLink,TEXT("\\\\.\\%s%s"), DOSNAMEPREFIX, &AdapterName[8]);
612 // Copy only the bytes that fit in the adapter structure.
613 // Note that lpAdapter->SymbolicLink is present for backward compatibility but will
614 // never be used by the apps
615 memcpy(lpAdapter->SymbolicLink, (PCHAR)SymbolicLink, MAX_LINK_NAME_LENGTH);
617 //try if it is possible to open the adapter immediately
618 lpAdapter->hFile = CreateFile(SymbolicLink,GENERIC_WRITE | GENERIC_READ,0,NULL,OPEN_EXISTING,0,0);
620 if (lpAdapter->hFile != INVALID_HANDLE_VALUE) {
621 ODSEx("PacketOpenAdapter: CreateFile(%S) successfull\n", SymbolicLink);
622 if (PacketSetReadEvt(lpAdapter) == FALSE) {
623 error = GetLastError();
624 ODS("PacketOpenAdapter: Unable to open the read event\n");
625 if (AdapterNameU != NULL)
627 GlobalFreePtr(lpAdapter);
628 //set the error to the one on which we failed
630 ODSEx("PacketOpenAdapter: PacketSetReadEvt failed, Error=%d\n",error);
634 PacketSetMaxLookaheadsize(lpAdapter);
635 if (AdapterNameU != NULL)
639 //this is probably the first request on the packet driver.
640 //We must create the dos device and set the access rights on it
642 Result = DefineDosDevice(DDD_RAW_TARGET_PATH,
647 ODSEx("PacketOpenAdapter: calling CreateFile(%S)\n", SymbolicLink);
649 lpAdapter->hFile = CreateFile(
651 GENERIC_WRITE | GENERIC_READ,0,NULL,OPEN_EXISTING,0,0);
652 if (lpAdapter->hFile != INVALID_HANDLE_VALUE) {
653 if (PacketSetReadEvt(lpAdapter) == FALSE) {
654 error = GetLastError();
655 ODS("PacketOpenAdapter: Unable to open the read event\n");
656 if (AdapterNameU != NULL)
658 GlobalFreePtr(lpAdapter);
659 //set the error to the one on which we failed
661 ODSEx("PacketOpenAdapter: PacketSetReadEvt failed, Error=1,%d\n",error);
664 PacketSetMaxLookaheadsize(lpAdapter);
665 if (AdapterNameU != NULL)
669 ODS("PacketOpenAdapter: CreateFile failed\n");
672 ODSEx("PacketOpenAdapter: DefineDosDevice(%S) failed\n", &SymbolicLink[4]);
675 error = GetLastError();
676 if (AdapterNameU != NULL)
678 GlobalFreePtr(lpAdapter);
679 //set the error to the one on which we failed
681 ODSEx("PacketOpenAdapter: CreateFile failed, Error=2,%d\n",error);
687 \brief Closes an adapter.
688 \param lpAdapter the pointer to the adapter to close.
690 PacketCloseAdapter closes the given adapter and frees the associated ADAPTER structure
692 VOID PacketCloseAdapter(LPADAPTER lpAdapter)
694 CloseHandle(lpAdapter->hFile);
695 SetEvent(lpAdapter->ReadEvent);
696 CloseHandle(lpAdapter->ReadEvent);
697 GlobalFreePtr(lpAdapter);
701 \brief Allocates a _PACKET structure.
702 \return On succeess, the return value is the pointer to a _PACKET structure otherwise the
703 return value is NULL.
705 The structure returned will be passed to the PacketReceivePacket() function to receive the
706 packets from the driver.
708 \warning The Buffer field of the _PACKET structure is not set by this function.
709 The buffer \b must be allocated by the application, and associated to the PACKET structure
710 with a call to PacketInitPacket.
712 LPPACKET PacketAllocatePacket(void)
716 lpPacket = (LPPACKET)GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT,sizeof(PACKET));
717 if (lpPacket == NULL) {
718 ODS("PacketAllocatePacket: GlobalAlloc Failed\n");
725 \brief Frees a _PACKET structure.
726 \param lpPacket The structure to free.
728 \warning the user-allocated buffer associated with the _PACKET structure is not deallocated
729 by this function and \b must be explicitly deallocated by the programmer.
732 VOID PacketFreePacket(LPPACKET lpPacket)
734 GlobalFreePtr(lpPacket);
738 \brief Initializes a _PACKET structure.
739 \param lpPacket The structure to initialize.
740 \param Buffer A pointer to a user-allocated buffer that will contain the captured data.
741 \param Length the length of the buffer. This is the maximum buffer size that will be
742 transferred from the driver to the application using a single read.
744 \note the size of the buffer associated with the PACKET structure is a parameter that can sensibly
745 influence the performance of the capture process, since this buffer will contain the packets received
746 from the the driver. The driver is able to return several packets using a single read call
747 (see the PacketReceivePacket() function for details), and the number of packets transferable to the
748 application in a call is limited only by the size of the buffer associated with the PACKET structure
749 passed to PacketReceivePacket(). Therefore setting a big buffer with PacketInitPacket can noticeably
750 decrease the number of system calls, reducing the impcat of the capture process on the processor.
753 VOID PacketInitPacket(LPPACKET lpPacket,PVOID Buffer,UINT Length)
755 lpPacket->Buffer = Buffer;
756 lpPacket->Length = Length;
757 lpPacket->ulBytesReceived = 0;
758 lpPacket->bIoComplete = FALSE;
762 \brief Read data (packets or statistics) from the NPF driver.
763 \param AdapterObject Pointer to an _ADAPTER structure identifying the network adapter from which
764 the data is received.
765 \param lpPacket Pointer to a PACKET structure that will contain the data.
766 \param Sync This parameter is deprecated and will be ignored. It is present for compatibility with
768 \return If the function succeeds, the return value is nonzero.
770 The data received with this function can be a group of packets or a static on the network traffic,
771 depending on the working mode of the driver. The working mode can be set with the PacketSetMode()
772 function. Give a look at that function if you are interested in the format used to return statistics
773 values, here only the normal capture mode will be described.
775 The number of packets received with this function is variable. It depends on the number of packets
776 currently stored in the driver
\92s buffer, on the size of these packets and on the size of the buffer
777 associated to the lpPacket parameter. The following figure shows the format used by the driver to pass
778 packets to the application.
780 \image html encoding.gif "method used to encode the packets"
782 Packets are stored in the buffer associated with the lpPacket _PACKET structure. The Length field of
783 that structure is updated with the amount of data copied in the buffer. Each packet has a header
784 consisting in a bpf_hdr structure that defines its length and contains its timestamp. A padding field
785 is used to word-align the data in the buffer (to speed up the access to the packets). The bh_datalen
786 and bh_hdrlen fields of the bpf_hdr structures should be used to extract the packets from the buffer.
788 Examples can be seen either in the TestApp sample application (see the \ref packetsamps page) provided
789 in the developer's pack, or in the pcap_read() function of wpcap.
791 BOOLEAN PacketReceivePacket(LPADAPTER AdapterObject,LPPACKET lpPacket,BOOLEAN Sync)
794 if ((int)AdapterObject->ReadTimeOut != -1)
795 WaitForSingleObject(AdapterObject->ReadEvent, (AdapterObject->ReadTimeOut==0)?INFINITE:AdapterObject->ReadTimeOut);
796 res = ReadFile(AdapterObject->hFile, lpPacket->Buffer, lpPacket->Length, &lpPacket->ulBytesReceived,NULL);
801 \brief Sends one (or more) copies of a packet to the network.
802 \param AdapterObject Pointer to an _ADAPTER structure identifying the network adapter that will
804 \param lpPacket Pointer to a PACKET structure with the packet to send.
805 \param Sync This parameter is deprecated and will be ignored. It is present for compatibility with
807 \return If the function succeeds, the return value is nonzero.
809 This function is used to send a raw packet to the network. 'Raw packet' means that the programmer
810 will have to include the protocol headers, since the packet is sent to the network 'as is'.
811 The CRC needs not to be calculated and put at the end of the packet, because it will be transparently
812 added by the network interface.
814 The behavior of this function is influenced by the PacketSetNumWrites() function. With PacketSetNumWrites(),
815 it is possible to change the number of times a single write must be repeated. The default is 1,
816 i.e. every call to PacketSendPacket() will correspond to one packet sent to the network. If this number is
817 greater than 1, for example 1000, every raw packet written by the application will be sent 1000 times on
818 the network. This feature mitigates the overhead of the context switches and therefore can be used to generate
819 high speed traffic. It is particularly useful for tools that test networks, routers, and servers and need
820 to obtain high network loads.
821 The optimized sending process is still limited to one packet at a time: for the moment it cannot be used
822 to send a buffer with multiple packets.
824 \note The ability to write multiple packets is currently present only in the Windows NTx version of the
825 packet driver. In Windows 95/98/ME it is emulated at user level in packet.dll. This means that an application
826 that uses the multiple write method will run in Windows 9x as well, but its performance will be very low
827 compared to the one of WindowsNTx.
829 BOOLEAN PacketSendPacket(LPADAPTER AdapterObject,LPPACKET lpPacket,BOOLEAN Sync)
831 DWORD BytesTransfered;
832 return WriteFile(AdapterObject->hFile,lpPacket->Buffer,lpPacket->Length,&BytesTransfered,NULL);
837 \brief Sends a buffer of packets to the network.
838 \param AdapterObject Pointer to an _ADAPTER structure identifying the network adapter that will
840 \param PacketBuff Pointer to buffer with the packets to send.
841 \param Size Size of the buffer pointed by the PacketBuff argument.
842 \param Sync if TRUE, the packets are sent respecting the timestamps. If FALSE, the packets are sent as
844 \return The amount of bytes actually sent. If the return value is smaller than the Size parameter, an
845 error occurred during the send. The error can be caused by a driver/adapter problem or by an
846 inconsistent/bogus packet buffer.
848 This function is used to send a buffer of raw packets to the network. The buffer can contain an arbitrary
849 number of raw packets, each of which preceded by a dump_bpf_hdr structure. The dump_bpf_hdr is the same used
850 by WinPcap and libpcap to store the packets in a file, therefore sending a capture file is straightforward.
851 'Raw packets' means that the sending application will have to include the protocol headers, since every packet
852 is sent to the network 'as is'. The CRC of the packets needs not to be calculated, because it will be
853 transparently added by the network interface.
855 \note Using this function if more efficient than issuing a series of PacketSendPacket(), because the packets are
856 buffered in the kernel driver, so the number of context switches is reduced.
858 \note When Sync is set to TRUE, the packets are synchronized in the kerenl with a high precision timestamp.
859 This requires a remarkable amount of CPU, but allows to send the packets with a precision of some microseconds
860 (depending on the precision of the performance counter of the machine). Such a precision cannot be reached
861 sending the packets separately with PacketSendPacket().
863 INT PacketSendPackets(LPADAPTER AdapterObject, PVOID PacketBuff, ULONG Size, BOOLEAN Sync)
866 DWORD BytesTransfered, TotBytesTransfered=0;
867 struct timeval BufStartTime;
868 LARGE_INTEGER StartTicks, CurTicks, TargetTicks, TimeFreq;
871 ODS("PacketSendPackets");
873 // Obtain starting timestamp of the buffer
874 BufStartTime.tv_sec = ((struct timeval*)(PacketBuff))->tv_sec;
875 BufStartTime.tv_usec = ((struct timeval*)(PacketBuff))->tv_usec;
877 // Retrieve the reference time counters
878 QueryPerformanceCounter(&StartTicks);
879 QueryPerformanceFrequency(&TimeFreq);
881 CurTicks.QuadPart = StartTicks.QuadPart;
884 // Send the data to the driver
885 Res = DeviceIoControl(AdapterObject->hFile,
886 (Sync)?pBIOCSENDPACKETSSYNC:pBIOCSENDPACKETSNOSYNC,
887 (PCHAR)PacketBuff + TotBytesTransfered,
888 Size - TotBytesTransfered,
894 TotBytesTransfered += BytesTransfered;
896 // calculate the time interval to wait before sending the next packet
897 TargetTicks.QuadPart = StartTicks.QuadPart +
899 ((((struct timeval*)((PCHAR)PacketBuff + TotBytesTransfered))->tv_sec - BufStartTime.tv_sec) * 1000000 +
900 (((struct timeval*)((PCHAR)PacketBuff + TotBytesTransfered))->tv_usec - BufStartTime.tv_usec)) *
901 (TimeFreq.QuadPart) / 1000000;
903 // Exit from the loop on termination or error
904 if(TotBytesTransfered >= Size || Res != TRUE)
907 // Wait until the time interval has elapsed
908 while( CurTicks.QuadPart <= TargetTicks.QuadPart )
909 QueryPerformanceCounter(&CurTicks);
914 return TotBytesTransfered;
918 \brief Defines the minimum amount of data that will be received in a read.
919 \param AdapterObject Pointer to an _ADAPTER structure
920 \param nbytes the minimum amount of data in the kernel buffer that will cause the driver to
921 release a read on this adapter.
922 \return If the function succeeds, the return value is nonzero.
924 In presence of a large value for nbytes, the kernel waits for the arrival of several packets before
925 copying the data to the user. This guarantees a low number of system calls, i.e. lower processor usage,
926 i.e. better performance, which is a good setting for applications like sniffers. Vice versa, a small value
927 means that the kernel will copy the packets as soon as the application is ready to receive them. This is
928 suggested for real time applications (like, for example, a bridge) that need the better responsiveness from
931 \b note: this function has effect only in Windows NTx. The driver for Windows 9x doesn't offer
932 this possibility, therefore PacketSetMinToCopy is implemented under these systems only for compatibility.
935 BOOLEAN PacketSetMinToCopy(LPADAPTER AdapterObject,int nbytes)
938 return DeviceIoControl(AdapterObject->hFile,pBIOCSMINTOCOPY,&nbytes,4,NULL,0,&BytesReturned,NULL);
942 \brief Sets the working mode of an adapter.
943 \param AdapterObject Pointer to an _ADAPTER structure.
944 \param mode The new working mode of the adapter.
945 \return If the function succeeds, the return value is nonzero.
947 The device driver of WinPcap has 4 working modes:
948 - Capture mode (mode = PACKET_MODE_CAPT): normal capture mode. The packets transiting on the wire are copied
949 to the application when PacketReceivePacket() is called. This is the default working mode of an adapter.
950 - Statistical mode (mode = PACKET_MODE_STAT): programmable statistical mode. PacketReceivePacket() returns, at
951 precise intervals, statics values on the network traffic. The interval between the statistic samples is
952 by default 1 second but it can be set to any other value (with a 1 ms precision) with the
953 PacketSetReadTimeout() function. The data returned by PacketReceivePacket() when the adapter is in statistical
954 mode is shown in the following figure:<p>
955 \image html stats.gif "data structure returned by statistical mode"
956 Two 64-bit counters are provided: the number of packets and the amount of bytes that satisfy a filter
957 previously set with PacketSetBPF(). If no filter has been set, all the packets are counted. The counters are
958 encapsulated in a bpf_hdr structure, so that they will be parsed correctly by wpcap. Statistical mode has a
959 very low impact on system performance compared to capture mode.
960 - Dump mode (mode = PACKET_MODE_DUMP): the packets are dumped to disk by the driver, in libpcap format. This
961 method is much faster than saving the packets after having captured them. No data is returned
962 by PacketReceivePacket(). If the application sets a filter with PacketSetBPF(), only the packets that satisfy
963 this filter are dumped to disk.
964 - Statitical Dump mode (mode = PACKET_MODE_STAT_DUMP): the packets are dumped to disk by the driver, in libpcap
965 format, like in dump mode. PacketReceivePacket() returns, at precise intervals, statics values on the
966 network traffic and on the amount of data saved to file, in a way similar to statistical mode.
967 The data returned by PacketReceivePacket() when the adapter is in statistical dump mode is shown in
968 the following figure:<p>
969 \image html dump.gif "data structure returned by statistical dump mode"
970 Three 64-bit counters are provided: the number of packets accepted, the amount of bytes accepted and the
971 effective amount of data (including headers) dumped to file. If no filter has been set, all the packets are
972 dumped to disk. The counters are encapsulated in a bpf_hdr structure, so that they will be parsed correctly
974 Look at the NetMeter example in the
975 WinPcap developer's pack to see how to use statistics mode.
977 BOOLEAN PacketSetMode(LPADAPTER AdapterObject,int mode)
980 return DeviceIoControl(AdapterObject->hFile,pBIOCSMODE,&mode,4,NULL,0,&BytesReturned,NULL);
984 \brief Sets the name of the file that will receive the packet when the adapter is in dump mode.
985 \param AdapterObject Pointer to an _ADAPTER structure.
986 \param name the file name, in ASCII or UNICODE.
987 \param len the length of the buffer containing the name, in bytes.
988 \return If the function succeeds, the return value is nonzero.
990 This function defines the file name that the driver will open to store the packets on disk when
991 it works in dump mode. The adapter must be in dump mode, i.e. PacketSetMode() should have been
992 called previously with mode = PACKET_MODE_DUMP. otherwise this function will fail.
993 If PacketSetDumpName was already invoked on the adapter pointed by AdapterObject, the driver
994 closes the old file and opens the new one.
997 BOOLEAN PacketSetDumpName(LPADAPTER AdapterObject, void *name, int len)
1002 WCHAR NameWithPath[1024];
1006 if(((PUCHAR)name)[1]!=0 && len>1){ //ASCII
1007 FileName=SChar2WChar(name);
1014 TStrLen=GetFullPathName(FileName,1024,NameWithPath,&NamePos);
1016 len=TStrLen*2+2; //add the terminating null character
1018 // Try to catch malformed strings
1020 if(((PUCHAR)name)[1]!=0 && len>1) free(FileName);
1024 res = DeviceIoControl(AdapterObject->hFile,pBIOCSETDUMPFILENAME,NameWithPath,len,NULL,0,&BytesReturned,NULL);
1030 \brief Set the dump mode limits.
1031 \param AdapterObject Pointer to an _ADAPTER structure.
1032 \param maxfilesize The maximum dimension of the dump file, in bytes. 0 means no limit.
1033 \param maxnpacks The maximum number of packets contained in the dump file. 0 means no limit.
1034 \return If the function succeeds, the return value is nonzero.
1036 This function sets the limits after which the NPF driver stops to save the packets to file when an adapter
1037 is in dump mode. This allows to limit the dump file to a precise number of bytes or packets, avoiding that
1038 very long dumps fill the disk space. If both maxfilesize and maxnpacks are set, the dump is stopped when
1039 the first of the two is reached.
1041 \note When a limit is reached, the dump is stopped, but the file remains opened. In order to flush
1042 correctly the data and access the file consistently, you need to close the adapter with PacketCloseAdapter().
1044 BOOLEAN PacketSetDumpLimits(LPADAPTER AdapterObject, UINT maxfilesize, UINT maxnpacks)
1046 DWORD BytesReturned;
1049 valbuff[0] = maxfilesize;
1050 valbuff[1] = maxnpacks;
1052 return DeviceIoControl(AdapterObject->hFile,
1063 \brief Returns the status of the kernel dump process, i.e. tells if one of the limits defined with PacketSetDumpLimits() was reached.
1064 \param AdapterObject Pointer to an _ADAPTER structure.
1065 \param sync if TRUE, the function blocks until the dump is finished, otherwise it returns immediately.
1066 \return TRUE if the dump is ended, FALSE otherwise.
1068 PacketIsDumpEnded() informs the user about the limits that were set with a previous call to
1069 PacketSetDumpLimits().
1071 \warning If no calls to PacketSetDumpLimits() were performed or if the dump process has no limits
1072 (i.e. if the arguments of the last call to PacketSetDumpLimits() were both 0), setting sync to TRUE will
1073 block the application on this call forever.
1075 BOOLEAN PacketIsDumpEnded(LPADAPTER AdapterObject, BOOLEAN sync)
1077 DWORD BytesReturned;
1082 WaitForSingleObject(AdapterObject->ReadEvent, INFINITE);
1084 res = DeviceIoControl(AdapterObject->hFile,
1093 if(res == FALSE) return TRUE; // If the IOCTL returns an error we consider the dump finished
1095 return (BOOLEAN)IsDumpEnded;
1099 \brief Returns the notification event associated with the read calls on an adapter.
1100 \param AdapterObject Pointer to an _ADAPTER structure.
1101 \return The handle of the event that the driver signals when some data is available in the kernel buffer.
1103 The event returned by this function is signaled by the driver if:
1104 - The adapter pointed by AdapterObject is in capture mode and an amount of data greater or equal
1105 than the one set with the PacketSetMinToCopy() function is received from the network.
1106 - the adapter pointed by AdapterObject is in capture mode, no data has been received from the network
1107 but the the timeout set with the PacketSetReadTimeout() function has elapsed.
1108 - the adapter pointed by AdapterObject is in statics mode and the the timeout set with the
1109 PacketSetReadTimeout() function has elapsed. This means that a new statistic sample is available.
1111 In every case, a call to PacketReceivePacket() will return immediately.
1112 The event can be passed to standard Win32 functions (like WaitForSingleObject or WaitForMultipleObjects)
1113 to wait until the driver's buffer contains some data. It is particularly useful in GUI applications that
1114 need to wait concurrently on several events.
1117 HANDLE PacketGetReadEvent(LPADAPTER AdapterObject)
1119 return AdapterObject->ReadEvent;
1123 \brief Sets the number of times a single packet written with PacketSendPacket() will be repeated on the network.
1124 \param AdapterObject Pointer to an _ADAPTER structure.
1125 \param nwrites Number of copies of a packet that will be physically sent by the interface.
1126 \return If the function succeeds, the return value is nonzero.
1128 See PacketSendPacket() for details.
1130 BOOLEAN PacketSetNumWrites(LPADAPTER AdapterObject,int nwrites)
1132 DWORD BytesReturned;
1133 return DeviceIoControl(AdapterObject->hFile,pBIOCSWRITEREP,&nwrites,4,NULL,0,&BytesReturned,NULL);
1137 \brief Sets the timeout after which a read on an adapter returns.
1138 \param AdapterObject Pointer to an _ADAPTER structure.
1139 \param timeout indicates the timeout, in milliseconds, after which a call to PacketReceivePacket() on
1140 the adapter pointed by AdapterObject will be released, also if no packets have been captured by the driver.
1141 Setting timeout to 0 means no timeout, i.e. PacketReceivePacket() never returns if no packet arrives.
1142 A timeout of -1 causes PacketReceivePacket() to always return immediately.
1143 \return If the function succeeds, the return value is nonzero.
1145 \note This function works also if the adapter is working in statistics mode, and can be used to set the
1146 time interval between two statistic reports.
1148 BOOLEAN PacketSetReadTimeout(LPADAPTER AdapterObject,int timeout)
1150 DWORD BytesReturned;
1151 int DriverTimeOut=-1;
1153 AdapterObject->ReadTimeOut=timeout;
1155 return DeviceIoControl(AdapterObject->hFile,pBIOCSRTIMEOUT,&DriverTimeOut,4,NULL,0,&BytesReturned,NULL);
1159 \brief Sets the size of the kernel-level buffer associated with a capture.
1160 \param AdapterObject Pointer to an _ADAPTER structure.
1161 \param dim New size of the buffer, in \b kilobytes.
1162 \return The function returns TRUE if successfully completed, FALSE if there is not enough memory to
1163 allocate the new buffer.
1165 When a new dimension is set, the data in the old buffer is discarded and the packets stored in it are
1168 Note: the dimension of the kernel buffer affects heavily the performances of the capture process.
1169 An adequate buffer in the driver is able to keep the packets while the application is busy, compensating
1170 the delays of the application and avoiding the loss of packets during bursts or high network activity.
1171 The buffer size is set to 0 when an instance of the driver is opened: the programmer should remember to
1172 set it to a proper value. As an example, wpcap sets the buffer size to 1MB at the beginning of a capture.
1174 BOOLEAN PacketSetBuff(LPADAPTER AdapterObject,int dim)
1176 DWORD BytesReturned;
1177 return DeviceIoControl(AdapterObject->hFile,pBIOCSETBUFFERSIZE,&dim,4,NULL,0,&BytesReturned,NULL);
1181 \brief Sets a kernel-level packet filter.
1182 \param AdapterObject Pointer to an _ADAPTER structure.
1183 \param fp Pointer to a filtering program that will be associated with this capture or monitoring
1184 instance and that will be executed on every incoming packet.
1185 \return This function returns TRUE if the filter is set successfully, FALSE if an error occurs
1186 or if the filter program is not accepted after a safeness check by the driver. The driver performs
1187 the check in order to avoid system crashes due to buggy or malicious filters, and it rejects non
1190 This function associates a new BPF filter to the adapter AdapterObject. The filter, pointed by fp, is a
1191 set of bpf_insn instructions.
1193 A filter can be automatically created by using the pcap_compile() function of wpcap. This function
1194 converts a human readable text expression with the syntax of WinDump (see the manual of WinDump at
1195 http://netgroup.polito.it/windump for details) into a BPF program. If your program doesn't link wpcap, but
1196 you need to know the code of a particular filter, you can launch WinDump with the -d or -dd or -ddd
1197 flags to obtain the pseudocode.
1200 BOOLEAN PacketSetBpf(LPADAPTER AdapterObject,struct bpf_program *fp)
1202 DWORD BytesReturned;
1203 return DeviceIoControl(AdapterObject->hFile,pBIOCSETF,(char*)fp->bf_insns,fp->bf_len*sizeof(struct bpf_insn),NULL,0,&BytesReturned,NULL);
1207 \brief Returns a couple of statistic values about the current capture session.
1208 \param AdapterObject Pointer to an _ADAPTER structure.
1209 \param s Pointer to a user provided bpf_stat structure that will be filled by the function.
1210 \return If the function succeeds, the return value is nonzero.
1212 With this function, the programmer can know the value of two internal variables of the driver:
1214 - the number of packets that have been received by the adapter AdapterObject, starting at the
1215 time in which it was opened with PacketOpenAdapter.
1216 - the number of packets that have been dropped by the driver. A packet is dropped when the kernel
1217 buffer associated with the adapter is full.
1219 BOOLEAN PacketGetStats(LPADAPTER AdapterObject,struct bpf_stat *s)
1222 DWORD BytesReturned;
1223 struct bpf_stat tmpstat; // We use a support structure to avoid kernel-level inconsistencies with old or malicious applications
1225 Res = DeviceIoControl(AdapterObject->hFile,
1230 sizeof(struct bpf_stat),
1234 // Copy only the first two values retrieved from the driver
1235 s->bs_recv = tmpstat.bs_recv;
1236 s->bs_drop = tmpstat.bs_drop;
1242 \brief Returns statistic values about the current capture session. Enhanced version of PacketGetStats().
1243 \param AdapterObject Pointer to an _ADAPTER structure.
1244 \param s Pointer to a user provided bpf_stat structure that will be filled by the function.
1245 \return If the function succeeds, the return value is nonzero.
1247 With this function, the programmer can retireve the sname values provided by PacketGetStats(), plus:
1249 - the number of drops by interface (not yet supported, always 0).
1250 - the number of packets that reached the application, i.e that were accepted by the kernel filter and
1251 that fitted in the kernel buffer.
1253 BOOLEAN PacketGetStatsEx(LPADAPTER AdapterObject,struct bpf_stat *s)
1256 DWORD BytesReturned;
1257 struct bpf_stat tmpstat; // We use a support structure to avoid kernel-level inconsistencies with old or malicious applications
1259 Res = DeviceIoControl(AdapterObject->hFile,
1264 sizeof(struct bpf_stat),
1268 s->bs_recv = tmpstat.bs_recv;
1269 s->bs_drop = tmpstat.bs_drop;
1270 s->ps_ifdrop = tmpstat.ps_ifdrop;
1271 s->bs_capt = tmpstat.bs_capt;
1277 \brief Performs a query/set operation on an internal variable of the network card driver.
1278 \param AdapterObject Pointer to an _ADAPTER structure.
1279 \param Set Determines if the operation is a set (Set=TRUE) or a query (Set=FALSE).
1280 \param OidData A pointer to a _PACKET_OID_DATA structure that contains or receives the data.
1281 \return If the function succeeds, the return value is nonzero.
1283 \note not all the network adapters implement all the query/set functions. There is a set of mandatory
1284 OID functions that is granted to be present on all the adapters, and a set of facultative functions, not
1285 provided by all the cards (see the Microsoft DDKs to see which functions are mandatory). If you use a
1286 facultative function, be careful to enclose it in an if statement to check the result.
1288 BOOLEAN PacketRequest(LPADAPTER AdapterObject,BOOLEAN Set,PPACKET_OID_DATA OidData)
1290 DWORD BytesReturned;
1293 Result=DeviceIoControl(AdapterObject->hFile,(DWORD) Set ? pBIOCSETOID : pBIOCQUERYOID,
1294 OidData,sizeof(PACKET_OID_DATA)-1+OidData->Length,OidData,
1295 sizeof(PACKET_OID_DATA)-1+OidData->Length,&BytesReturned,NULL);
1297 // output some debug info
1298 ODSEx("PacketRequest, OID=%d ", OidData->Oid);
1299 ODSEx("Length=%d ", OidData->Length);
1300 ODSEx("Set=%d ", Set);
1301 ODSEx("Res=%d\n", Result);
1307 \brief Sets a hardware filter on the incoming packets.
1308 \param AdapterObject Pointer to an _ADAPTER structure.
1309 \param Filter The identifier of the filter.
1310 \return If the function succeeds, the return value is nonzero.
1312 The filter defined with this filter is evaluated by the network card, at a level that is under the NPF
1313 device driver. Here is a list of the most useful hardware filters (A complete list can be found in ntddndis.h):
1315 - NDIS_PACKET_TYPE_PROMISCUOUS: sets promiscuous mode. Every incoming packet is accepted by the adapter.
1316 - NDIS_PACKET_TYPE_DIRECTED: only packets directed to the workstation's adapter are accepted.
1317 - NDIS_PACKET_TYPE_BROADCAST: only broadcast packets are accepted.
1318 - NDIS_PACKET_TYPE_MULTICAST: only multicast packets belonging to groups of which this adapter is a member are accepted.
1319 - NDIS_PACKET_TYPE_ALL_MULTICAST: every multicast packet is accepted.
1320 - NDIS_PACKET_TYPE_ALL_LOCAL: all local packets, i.e. NDIS_PACKET_TYPE_DIRECTED + NDIS_PACKET_TYPE_BROADCAST + NDIS_PACKET_TYPE_MULTICAST
1322 BOOLEAN PacketSetHwFilter(LPADAPTER AdapterObject,ULONG Filter)
1325 ULONG IoCtlBufferLength=(sizeof(PACKET_OID_DATA)+sizeof(ULONG)-1);
1326 PPACKET_OID_DATA OidData;
1328 OidData=GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT,IoCtlBufferLength);
1329 if (OidData == NULL) {
1330 ODS("PacketSetHwFilter: GlobalAlloc Failed\n");
1333 OidData->Oid=OID_GEN_CURRENT_PACKET_FILTER;
1334 OidData->Length=sizeof(ULONG);
1335 *((PULONG)OidData->Data)=Filter;
1336 Status=PacketRequest(AdapterObject,TRUE,OidData);
1337 GlobalFreePtr(OidData);
1342 \brief Retrieve the list of available network adapters and their description.
1343 \param pStr User allocated string that will be filled with the names of the adapters.
1344 \param BufferSize Length of the buffer pointed by pStr.
1345 \return If the function succeeds, the return value is nonzero.
1347 Usually, this is the first function that should be used to communicate with the driver.
1348 It returns the names of the adapters installed on the system <B>and supported by WinPcap</B>.
1349 After the names of the adapters, pStr contains a string that describes each of them.
1352 the result of this function is obtained querying the registry, therefore the format
1353 of the result in Windows NTx is different from the one in Windows 9x. Windows 9x uses the ASCII
1354 encoding method to store a string, while Windows NTx uses UNICODE. After a call to PacketGetAdapterNames
1355 in Windows 95x, pStr contains, in succession:
1356 - a variable number of ASCII strings, each with the names of an adapter, separated by a "\0"
1358 - a number of ASCII strings, each with the description of an adapter, separated by a "\0". The number
1359 of descriptions is the same of the one of names. The fisrt description corresponds to the first name, and
1363 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".
1364 - a variable number of UNICODE strings, each with the names of an adapter, separated by a UNICODE "\0"
1365 - a double UNICODE "\0"
1366 - a number of ASCII strings, each with the description of an adapter, separated by an ASCII "\0".
1367 - a double ASCII "\0".
1370 BOOLEAN PacketGetAdapterNames(PTSTR pStr, PULONG BufferSize)
1372 HKEY LinkageKey, AdapKey;
1373 DWORD RegKeySize = 0;
1381 PPACKET_OID_DATA OidData;
1382 int i = 0, k, rewind;
1384 TCHAR AdapName[256];
1386 ODSEx("PacketGetAdapterNames: BufferSize=%d\n",*BufferSize);
1388 OidData = GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT, 512);
1389 if (OidData == NULL) {
1390 ODS("PacketGetAdapterNames: GlobalAlloc Failed\n");
1394 Status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
1395 TEXT("SYSTEM\\ControlSet001\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}"),
1396 0, KEY_READ, &AdapKey);
1398 // Get the size to allocate for the original device names
1399 while ((Result = RegEnumKey(AdapKey, i, AdapName, sizeof(AdapName)/2)) == ERROR_SUCCESS) {
1400 Status = RegOpenKeyEx(AdapKey, AdapName,0, KEY_READ, &LinkageKey);
1401 Status = RegOpenKeyExW(LinkageKey, L"Linkage",0, KEY_READ, &LinkageKey);
1402 Status = RegQueryValueExW(LinkageKey, L"Export", NULL, NULL, NULL, &dim);
1404 if (Status!=ERROR_SUCCESS) continue;
1408 // Allocate the memory for the original device names
1409 ODSEx("Need %d bytes for the names\n", RegKeySize+2);
1410 BpStr = GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT, RegKeySize+2);
1411 if (BpStr == NULL || RegKeySize > *BufferSize) {
1412 ODS("PacketGetAdapterNames: GlobalAlloc Failed\n");
1413 GlobalFreePtr(OidData);
1419 ODS("PacketGetAdapterNames: Cycling through the adapters:\n");
1421 // Copy the names to the buffer
1422 while ((Result = RegEnumKey(AdapKey, i, AdapName, sizeof(AdapName)/2)) == ERROR_SUCCESS) {
1423 WCHAR UpperBindStr[64];
1428 Status = RegOpenKeyEx(AdapKey,AdapName,0,KEY_READ,&LinkageKey);
1429 Status = RegOpenKeyExW(LinkageKey,L"Linkage",0,KEY_READ,&LinkageKey);
1431 dim=sizeof(UpperBindStr);
1432 Status=RegQueryValueExW(LinkageKey,L"UpperBind",NULL,NULL,(PUCHAR)UpperBindStr,&dim);
1434 ODSEx("UpperBind=%S ", UpperBindStr);
1436 if( Status!=ERROR_SUCCESS || _wcsicmp(UpperBindStr,L"NdisWan")==0 ){
1437 ODS("Name = SKIPPED\n");
1442 Status=RegQueryValueExW(LinkageKey,L"Export",NULL,NULL,(LPBYTE)BpStr+k,&dim);
1443 if(Status!=ERROR_SUCCESS){
1444 ODS("Name = SKIPPED (error reading the key)\n");
1448 ODSEx("Name = %S\n", (LPBYTE)BpStr+k);
1453 CloseHandle(AdapKey);
1455 #ifdef _DEBUG_TO_FILE
1456 //dump BpStr for debug purposes
1457 ODS("Dumping BpStr:");
1460 f = fopen("winpcap_debug.txt", "a");
1462 if(!(i%32))fprintf(f, "\n ");
1463 fprintf(f, "%c " , *((LPBYTE)BpStr+i));
1473 DescBuf=GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT, 4096);
1474 if (DescBuf == NULL) {
1475 GlobalFreePtr (BpStr);
1476 GlobalFreePtr(OidData);
1481 for(i=0,k=0;BpStr[i]!=0 || BpStr[i+1]!=0;){
1483 if(k+wcslen(BpStr+i)+30 > *BufferSize){
1484 // Input buffer too small
1485 GlobalFreePtr(OidData);
1486 GlobalFreePtr (BpStr);
1487 GlobalFreePtr (DescBuf);
1488 ODS("PacketGetAdapterNames: Input buffer too small!\n");
1492 // Create the device name
1494 memcpy(pStr+k,BpStr+i,16);
1495 memcpy(pStr+k+8,TEXT("NPF_"),8);
1498 while(BpStr[i-1]!=0){
1499 pStr[k++]=BpStr[i++];
1503 adapter=PacketOpenAdapter(pStr+rewind);
1509 // Retrieve the description
1510 OidData->Oid = OID_GEN_VENDOR_DESCRIPTION;
1511 OidData->Length = 256;
1512 ZeroMemory(OidData->Data,256);
1513 Status = PacketRequest(adapter,FALSE,OidData);
1514 if(Status==0 || ((char*)OidData->Data)[0]==0){
1519 ODSEx("Adapter Description=%s\n\n",OidData->Data);
1521 // Copy the description
1522 TTpStr=(char*)(OidData->Data);
1528 // Close the adapter
1529 PacketCloseAdapter(adapter);
1537 if ((ULONG)(DpStr - DescBuf + k) < *BufferSize) {
1538 memcpy(pStr + k, DescBuf, DpStr - DescBuf);
1540 GlobalFreePtr(OidData);
1541 GlobalFreePtr(BpStr);
1542 GlobalFreePtr(DescBuf);
1543 ODS("\nPacketGetAdapterNames: ended with failure\n");
1547 GlobalFreePtr(OidData);
1548 GlobalFreePtr(BpStr);
1549 GlobalFreePtr(DescBuf);
1550 ODS("\nPacketGetAdapterNames: ended correctly\n");
1556 ODS("Adapters not found under SYSTEM\\ControlSet001\\Control\\Class. Using the TCP/IP bindings.\n");
1558 GlobalFreePtr(BpStr);
1559 Status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
1560 TEXT("SYSTEM\\ControlSet001\\Services\\Tcpip\\Linkage"),
1561 0, KEY_READ, &LinkageKey);
1562 if (Status == ERROR_SUCCESS) {
1563 // Retrieve the length of the key
1564 Status = RegQueryValueEx(LinkageKey, TEXT("bind"), NULL, &RegType, NULL, &RegKeySize);
1565 // Allocate the buffer
1566 BpStr = GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT, RegKeySize + 2);
1567 if (BpStr == NULL || RegKeySize > *BufferSize) {
1568 GlobalFreePtr(OidData);
1571 Status = RegQueryValueEx(LinkageKey, TEXT("bind"), NULL, &RegType, (LPBYTE)BpStr, &RegKeySize);
1572 RegCloseKey(LinkageKey);
1574 //ODS("SYSTEM\\ControlSet001\\Control\\Class - RegKey not found.\n");
1575 ODS("SYSTEM\\ControlSet001\\Services\\Tcpip\\Linkage - RegKey not found.\n");
1577 if (Status == ERROR_SUCCESS) {
1578 DescBuf = GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT, 4096);
1579 if (DescBuf == NULL) {
1580 GlobalFreePtr(BpStr);
1581 GlobalFreePtr(OidData);
1585 for (i = 0, k = 0; BpStr[i] != 0 || BpStr[i+1] != 0; ) {
1586 if (k + wcslen(BpStr + i) + 30 > *BufferSize) {
1587 // Input buffer too small
1588 GlobalFreePtr(OidData);
1589 GlobalFreePtr(BpStr);
1590 GlobalFreePtr(DescBuf);
1594 ODS("\tCreating a device name - started.\n");
1596 // Create the device name
1598 memcpy(pStr + k,BpStr + i,16);
1599 memcpy(pStr + k + 8, TEXT("NPF_"), 8);
1602 while (BpStr[i - 1] != 0) {
1603 pStr[k++] = BpStr[i++];
1606 adapter = PacketOpenAdapter(pStr+rewind);
1607 if (adapter == NULL) {
1611 // Retrieve the description
1612 OidData->Oid = OID_GEN_VENDOR_DESCRIPTION;
1613 OidData->Length = 256;
1614 Status = PacketRequest(adapter, FALSE, OidData);
1615 if (Status == 0 || ((char*)OidData->Data)[0] == 0) {
1617 ODS("\tCreating a device name - Retrieve the description.\n");
1621 // Copy the description
1622 TTpStr = (char*)(OidData->Data);
1623 while (*TTpStr != 0){
1624 *DpStr++ = *TTpStr++;
1626 *DpStr++ = *TTpStr++;
1627 // Close the adapter
1628 PacketCloseAdapter(adapter);
1630 ODS("\tCreating a device name - completed.\n");
1637 if ((ULONG)(DpStr - DescBuf + k) < *BufferSize) {
1638 memcpy(pStr + k, DescBuf, DpStr-DescBuf);
1640 GlobalFreePtr(OidData);
1641 GlobalFreePtr(BpStr);
1642 GlobalFreePtr(DescBuf);
1646 GlobalFreePtr(OidData);
1647 GlobalFreePtr(BpStr);
1648 GlobalFreePtr(DescBuf);
1649 ODS("PacketGetAdapterNames() returning TRUE\n");
1652 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);
1653 ODS("Cannot find the TCP/IP bindings\n");
1660 \brief Returns comprehensive information the addresses of an adapter.
1661 \param AdapterName String that contain _ADAPTER structure.
1662 \param buffer A user allocated array of npf_if_addr that will be filled by the function.
1663 \param NEntries Size of the array (in npf_if_addr).
1664 \return If the function succeeds, the return value is nonzero.
1666 This function grabs from the registry information like the IP addresses, the netmasks
1667 and the broadcast addresses of an interface. The buffer passed by the user is filled with
1668 npf_if_addr structures, each of which contains the data for a single address. If the buffer
1669 is full, the reaming addresses are dropeed, therefore set its dimension to sizeof(npf_if_addr)
1670 if you want only the first address.
1673 BOOLEAN PacketGetNetInfoEx(LPTSTR AdapterName, npf_if_addr* buffer, PLONG NEntries)
1676 WCHAR *AdapterNameU;
1684 WCHAR String[1024+1];
1688 struct sockaddr_in *TmpAddr, *TmpBroad;
1689 LONG naddrs,nmasks,StringPos;
1690 DWORD ZeroBroadcast;
1692 AdapterNameA = (char*)AdapterName;
1693 if(AdapterNameA[1] != 0) { //ASCII
1694 AdapterNameU = SChar2WChar(AdapterNameA);
1695 AdapterName = AdapterNameU;
1697 AdapterNameU = NULL;
1699 ifname = wcsrchr(AdapterName, '\\');
1701 ifname = AdapterName;
1704 if (wcsncmp(ifname, L"NPF_", 4) == 0)
1707 if( RegOpenKeyEx(HKEY_LOCAL_MACHINE,
1708 TEXT("SYSTEM\\ControlSet001\\Services\\Tcpip\\Parameters\\Interfaces"),
1709 0, KEY_READ, &UnderTcpKey) == ERROR_SUCCESS)
1711 status = RegOpenKeyExW(UnderTcpKey,ifname,0,KEY_READ,&TcpIpKey);
1712 if (status != ERROR_SUCCESS) {
1713 RegCloseKey(UnderTcpKey);
1720 // Query the registry key with the interface's adresses
1721 status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
1722 TEXT("SYSTEM\\ControlSet001\\Services"),
1723 0,KEY_READ,&SystemKey);
1724 if (status != ERROR_SUCCESS)
1726 status = RegOpenKeyExW(SystemKey,ifname,0,KEY_READ,&InterfaceKey);
1727 if (status != ERROR_SUCCESS) {
1728 RegCloseKey(SystemKey);
1731 RegCloseKey(SystemKey);
1732 status = RegOpenKeyEx(InterfaceKey,TEXT("Parameters"),0,KEY_READ,&ParametersKey);
1733 if (status != ERROR_SUCCESS) {
1734 RegCloseKey(InterfaceKey);
1737 RegCloseKey(InterfaceKey);
1738 status = RegOpenKeyEx(ParametersKey,TEXT("TcpIp"),0,KEY_READ,&TcpIpKey);
1739 if (status != ERROR_SUCCESS) {
1740 RegCloseKey(ParametersKey);
1743 RegCloseKey(ParametersKey);
1744 BufLen = sizeof String;
1748 /* Try to detect if the interface has a zero broadcast addr */
1749 status=RegQueryValueEx(TcpIpKey,TEXT("UseZeroBroadcast"),NULL,&RegType,(LPBYTE)&ZeroBroadcast,&BufLen);
1750 if (status != ERROR_SUCCESS)
1754 /* See if DHCP is used by this system */
1755 status=RegQueryValueEx(TcpIpKey,TEXT("EnableDHCP"),NULL,&RegType,(LPBYTE)&DHCPEnabled,&BufLen);
1756 if (status != ERROR_SUCCESS)
1760 /* Retrieve the adrresses */
1763 BufLen = sizeof String;
1764 // Open the key with the addresses
1765 status = RegQueryValueEx(TcpIpKey,TEXT("DhcpIPAddress"),NULL,&RegType,(LPBYTE)String,&BufLen);
1766 if (status != ERROR_SUCCESS) {
1767 RegCloseKey(TcpIpKey);
1771 // scan the key to obtain the addresses
1773 for(naddrs = 0;naddrs <* NEntries;naddrs++){
1774 TmpAddr = (struct sockaddr_in *) &(buffer[naddrs].IPAddress);
1776 if((TmpAddr->sin_addr.S_un.S_addr = inet_addrU(String + StringPos))!= -1){
1777 TmpAddr->sin_family = AF_INET;
1779 TmpBroad = (struct sockaddr_in *) &(buffer[naddrs].Broadcast);
1780 TmpBroad->sin_family = AF_INET;
1781 if(ZeroBroadcast==0)
1782 TmpBroad->sin_addr.S_un.S_addr = 0xffffffff; // 255.255.255.255
1784 TmpBroad->sin_addr.S_un.S_addr = 0; // 0.0.0.0
1786 while(*(String + StringPos) != 0)StringPos++;
1789 if(*(String + StringPos) == 0 || (StringPos * sizeof (WCHAR)) >= BufLen)
1795 BufLen = sizeof String;
1796 // Open the key with the netmasks
1797 status = RegQueryValueEx(TcpIpKey,TEXT("DhcpSubnetMask"),NULL,&RegType,(LPBYTE)String,&BufLen);
1798 if (status != ERROR_SUCCESS) {
1799 RegCloseKey(TcpIpKey);
1803 // scan the key to obtain the masks
1805 for(nmasks = 0;nmasks < *NEntries;nmasks++){
1806 TmpAddr = (struct sockaddr_in *) &(buffer[nmasks].SubnetMask);
1808 if((TmpAddr->sin_addr.S_un.S_addr = inet_addrU(String + StringPos))!= -1){
1809 TmpAddr->sin_family = AF_INET;
1811 while(*(String + StringPos) != 0)StringPos++;
1814 if(*(String + StringPos) == 0 || (StringPos * sizeof (WCHAR)) >= BufLen)
1820 // The number of masks MUST be equal to the number of adresses
1821 if(nmasks != naddrs){
1822 RegCloseKey(TcpIpKey);
1829 BufLen = sizeof String;
1830 // Open the key with the addresses
1831 status = RegQueryValueEx(TcpIpKey,TEXT("IPAddress"),NULL,&RegType,(LPBYTE)String,&BufLen);
1832 if (status != ERROR_SUCCESS) {
1833 RegCloseKey(TcpIpKey);
1837 // scan the key to obtain the addresses
1839 for(naddrs = 0;naddrs < *NEntries;naddrs++){
1840 TmpAddr = (struct sockaddr_in *) &(buffer[naddrs].IPAddress);
1842 if((TmpAddr->sin_addr.S_un.S_addr = inet_addrU(String + StringPos))!= -1){
1843 TmpAddr->sin_family = AF_INET;
1845 TmpBroad = (struct sockaddr_in *) &(buffer[naddrs].Broadcast);
1846 TmpBroad->sin_family = AF_INET;
1847 if(ZeroBroadcast==0)
1848 TmpBroad->sin_addr.S_un.S_addr = 0xffffffff; // 255.255.255.255
1850 TmpBroad->sin_addr.S_un.S_addr = 0; // 0.0.0.0
1852 while(*(String + StringPos) != 0)StringPos++;
1855 if(*(String + StringPos) == 0 || (StringPos * sizeof (WCHAR)) >= BufLen)
1861 BufLen = sizeof String;
1862 // Open the key with the netmasks
1863 status = RegQueryValueEx(TcpIpKey,TEXT("SubnetMask"),NULL,&RegType,(LPBYTE)String,&BufLen);
1864 if (status != ERROR_SUCCESS) {
1865 RegCloseKey(TcpIpKey);
1869 // scan the key to obtain the masks
1871 for(nmasks = 0;nmasks <* NEntries;nmasks++){
1872 TmpAddr = (struct sockaddr_in *) &(buffer[nmasks].SubnetMask);
1874 if((TmpAddr->sin_addr.S_un.S_addr = inet_addrU(String + StringPos))!= -1){
1875 TmpAddr->sin_family = AF_INET;
1877 while(*(String + StringPos) != 0)StringPos++;
1880 if(*(String + StringPos) == 0 || (StringPos * sizeof (WCHAR)) >= BufLen)
1886 // The number of masks MUST be equal to the number of adresses
1887 if(nmasks != naddrs){
1888 RegCloseKey(TcpIpKey);
1894 *NEntries = naddrs + 1;
1896 RegCloseKey(TcpIpKey);
1898 if (status != ERROR_SUCCESS) {
1903 if (AdapterNameU != NULL)
1908 if (AdapterNameU != NULL)
1914 \brief Returns the IP address and the netmask of an adapter.
1915 \param AdapterName String that contain _ADAPTER structure.
1916 \param netp Pointer to a variable that will receive the IP address of the adapter.
1917 \param maskp Pointer to a variable that will receive the netmask of the adapter.
1918 \return If the function succeeds, the return value is nonzero.
1920 \note this function is obsolete and is maintained for backward compatibility. Use PacketGetNetInfoEx() instead.
1923 BOOLEAN PacketGetNetInfo(LPTSTR AdapterName, PULONG netp, PULONG maskp)
1926 WCHAR *AdapterNameU;
1933 WCHAR String[1024+1];
1939 AdapterNameA = (char*)AdapterName;
1940 if(AdapterNameA[1] != 0) { //ASCII
1941 AdapterNameU = SChar2WChar(AdapterNameA);
1942 AdapterName = AdapterNameU;
1944 AdapterNameU = NULL;
1946 ifname = wcsrchr(AdapterName, '\\');
1948 ifname = AdapterName;
1951 if (wcsncmp(ifname, L"NPF_", 4) == 0)
1953 status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
1954 TEXT("SYSTEM\\ControlSet001\\Services"),
1955 0,KEY_READ,&SystemKey);
1956 if (status != ERROR_SUCCESS)
1958 status = RegOpenKeyExW(SystemKey,ifname,0,KEY_READ,&InterfaceKey);
1959 if (status != ERROR_SUCCESS) {
1960 RegCloseKey(SystemKey);
1963 RegCloseKey(SystemKey);
1964 status = RegOpenKeyEx(InterfaceKey,TEXT("Parameters"),0,KEY_READ,&ParametersKey);
1965 if (status != ERROR_SUCCESS) {
1966 RegCloseKey(InterfaceKey);
1969 RegCloseKey(InterfaceKey);
1970 status = RegOpenKeyEx(ParametersKey,TEXT("TcpIp"),0,KEY_READ,&TcpIpKey);
1971 if (status != ERROR_SUCCESS) {
1972 RegCloseKey(ParametersKey);
1975 RegCloseKey(ParametersKey);
1978 /* See if DHCP is used by this system */
1979 status=RegQueryValueEx(TcpIpKey,TEXT("EnableDHCP"),NULL,&RegType,(LPBYTE)&DHCPEnabled,&BufLen);
1980 if (status != ERROR_SUCCESS)
1984 /* Retrieve the netmask */
1987 BufLen = sizeof String;
1988 status = RegQueryValueEx(TcpIpKey,TEXT("DhcpIPAddress"),NULL,&RegType,(LPBYTE)String,&BufLen);
1989 if (status != ERROR_SUCCESS) {
1990 RegCloseKey(TcpIpKey);
1994 TAddr = inet_addrU(String);
1995 // swap bytes for backward compatibility
1997 *((char*)netp+i) = *((char*)&TAddr+3-i);
2000 BufLen = sizeof String;
2001 status=RegQueryValueEx(TcpIpKey,TEXT("DHCPSubnetMask"),NULL,&RegType,
2002 (LPBYTE)String,&BufLen);
2004 TAddr = inet_addrU(String);
2005 // swap bytes for backward compatibility
2007 *((char*)maskp+i) = *((char*)&TAddr+3-i);
2014 BufLen = sizeof String;
2015 status = RegQueryValueEx(TcpIpKey,TEXT("IPAddress"),NULL,&RegType,(LPBYTE)String,&BufLen);
2016 if (status != ERROR_SUCCESS) {
2017 RegCloseKey(TcpIpKey);
2021 TAddr = inet_addrU(String);
2022 // swap bytes for backward compatibility
2024 *((char*)netp+i) = *((char*)&TAddr+3-i);
2027 BufLen = sizeof String;
2028 status=RegQueryValueEx(TcpIpKey,TEXT("SubnetMask"),NULL,&RegType,
2029 (LPBYTE)String,&BufLen);
2031 TAddr = inet_addrU(String);
2032 // swap bytes for backward compatibility
2034 *((char*)maskp+i) = *((char*)&TAddr+3-i);
2040 if (status != ERROR_SUCCESS) {
2041 RegCloseKey(TcpIpKey);
2046 if (AdapterNameU != NULL)
2051 if (AdapterNameU != NULL)