📄 packet32.c
字号:
if(TAdInfo->Flags == INFO_FLAG_NPFIM_DEVICE)
{
//
// This is an airpcap card. Open it using the airpcap api
//
lpAdapter = PacketOpenAdapterNpfIm(AdapterNameA);
if(lpAdapter == NULL)
{
dwLastError = ERROR_BAD_UNIT;
break;
}
//
// NpfIm provides a read event
//
if(!g_NpfImHandlers.NpfImGetCaptureReadEvent((NPF_IM_DEV_HANDLE)lpAdapter->NpfImHandle, &lpAdapter->ReadEvent))
{
dwLastError = GetLastError();
PacketCloseAdapter(lpAdapter);
}
else
{
dwLastError = ERROR_SUCCESS;
}
break;
}
#endif // HAVE_NPFIM_API
#ifdef HAVE_DAG_API
if(TAdInfo->Flags == INFO_FLAG_DAG_CARD)
{
TRACE_PRINT("Opening a DAG adapter...");
//
// This is a Dag card. Open it using the dagc API
//
lpAdapter = PacketOpenAdapterDAG(AdapterNameA, FALSE);
if (lpAdapter == NULL)
{
TRACE_PRINT("Failed opening the DAG adapter with PacketOpenAdapterDAG. Failing. (BAD_UNIT)");
dwLastError = ERROR_BAD_UNIT;
}
else
{
dwLastError = ERROR_SUCCESS;
}
break;
}
#endif // HAVE_DAG_API
if(TAdInfo->Flags == INFO_FLAG_DONT_EXPORT)
{
//
// The adapter is flagged as not exported, probably because it's broken
// or incompatible with WinPcap. We end here with an error.
//
TRACE_PRINT1("Trying to open the adapter %s which is flagged as not exported. Failing (BAD_UNIT)", AdapterNameA);
dwLastError = ERROR_BAD_UNIT;
break;
}
if (TAdInfo->Flags != INFO_FLAG_NDIS_ADAPTER)
{
TRACE_PRINT1("Trying to open the adapter with an unknown flag type %u", TAdInfo->Flags);
dwLastError = ERROR_BAD_UNIT;
break;
}
#endif // not _WINNT4
//
// This is the only code executed on NT4
//
// Windows NT4 does not have support for the various nifty
// adapters supported from 2000 on (airpcap, ndiswan, npfim...)
// so we just skip all the magic of the global adapter list,
// and try to open the adapter with PacketOpenAdapterNPF at
// the end of this big function!
//
TRACE_PRINT("Normal NPF adapter, trying to open it...");
lpAdapter = PacketOpenAdapterNPF(AdapterNameA);
if (lpAdapter == NULL)
{
dwLastError = GetLastError();
}
}while(FALSE);
#ifndef _WINNT4
ReleaseMutex(g_AdaptersInfoMutex);
#endif
if (bFreeAdapterNameA) GlobalFree(AdapterNameA);
if (dwLastError != ERROR_SUCCESS)
{
TRACE_EXIT("PacketOpenAdapter");
SetLastError(dwLastError);
return NULL;
}
else
{
TRACE_EXIT("PacketOpenAdapter");
return lpAdapter;
}
}
/*!
\brief Closes an adapter.
\param lpAdapter the pointer to the adapter to close.
PacketCloseAdapter closes the given adapter and frees the associated ADAPTER structure
*/
VOID PacketCloseAdapter(LPADAPTER lpAdapter)
{
TRACE_ENTER("PacketCloseAdapter");
if(!lpAdapter)
{
TRACE_PRINT("PacketCloseAdapter: attempt to close a NULL adapter");
TRACE_EXIT("PacketCloseAdapter");
return;
}
#ifdef HAVE_WANPACKET_API
if (lpAdapter->Flags == INFO_FLAG_NDISWAN_ADAPTER)
{
TRACE_PRINT("Closing a WAN adapter through WanPacket...");
WanPacketCloseAdapter(lpAdapter->pWanAdapter);
GlobalFreePtr(lpAdapter);
return;
}
#endif
#ifdef HAVE_AIRPCAP_API
if(lpAdapter->Flags == INFO_FLAG_AIRPCAP_CARD)
{
g_PAirpcapClose(lpAdapter->AirpcapAd);
GlobalFreePtr(lpAdapter);
return;
}
#endif // HAVE_AIRPCAP_API
#ifdef HAVE_NPFIM_API
if(lpAdapter->Flags == INFO_FLAG_NPFIM_DEVICE)
{
g_NpfImHandlers.NpfImCloseDevice(lpAdapter->NpfImHandle);
GlobalFreePtr(lpAdapter);
return;
}
#endif
#ifdef HAVE_DAG_API
if(lpAdapter->Flags & INFO_FLAG_DAG_FILE || lpAdapter->Flags & INFO_FLAG_DAG_CARD)
{
TRACE_PRINT("Closing a DAG file...");
if(lpAdapter->Flags & INFO_FLAG_DAG_FILE & ~INFO_FLAG_DAG_CARD)
{
// This is a file. We must remove the entry in the adapter description list
PacketUpdateAdInfo(lpAdapter->Name);
}
g_p_dagc_close(lpAdapter->pDagCard);
GlobalFreePtr(lpAdapter);
return;
}
#endif // HAVE_DAG_API
if (lpAdapter->Flags != INFO_FLAG_NDIS_ADAPTER)
{
TRACE_PRINT1("Trying to close an unknown adapter type (%u)", lpAdapter->Flags);
}
else
{
SetEvent(lpAdapter->ReadEvent);
CloseHandle(lpAdapter->ReadEvent);
CloseHandle(lpAdapter->hFile);
GlobalFreePtr(lpAdapter);
TRACE_EXIT("PacketCloseAdapter");
}
}
/*!
\brief Allocates a _PACKET structure.
\return On succeess, the return value is the pointer to a _PACKET structure otherwise the
return value is NULL.
The structure returned will be passed to the PacketReceivePacket() function to receive the
packets from the driver.
\warning The Buffer field of the _PACKET structure is not set by this function.
The buffer \b must be allocated by the application, and associated to the PACKET structure
with a call to PacketInitPacket.
*/
LPPACKET PacketAllocatePacket(void)
{
LPPACKET lpPacket;
TRACE_ENTER("PacketAllocatePacket");
lpPacket=(LPPACKET)GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT,sizeof(PACKET));
if (lpPacket==NULL)
{
TRACE_PRINT("PacketAllocatePacket: GlobalAlloc Failed");
}
TRACE_EXIT("PacketAllocatePacket");
return lpPacket;
}
/*!
\brief Frees a _PACKET structure.
\param lpPacket The structure to free.
\warning the user-allocated buffer associated with the _PACKET structure is not deallocated
by this function and \b must be explicitly deallocated by the programmer.
*/
VOID PacketFreePacket(LPPACKET lpPacket)
{
TRACE_ENTER("PacketFreePacket");
GlobalFreePtr(lpPacket);
TRACE_EXIT("PacketFreePacket");
}
/*!
\brief Initializes a _PACKET structure.
\param lpPacket The structure to initialize.
\param Buffer A pointer to a user-allocated buffer that will contain the captured data.
\param Length the length of the buffer. This is the maximum buffer size that will be
transferred from the driver to the application using a single read.
\note the size of the buffer associated with the PACKET structure is a parameter that can sensibly
influence the performance of the capture process, since this buffer will contain the packets received
from the the driver. The driver is able to return several packets using a single read call
(see the PacketReceivePacket() function for details), and the number of packets transferable to the
application in a call is limited only by the size of the buffer associated with the PACKET structure
passed to PacketReceivePacket(). Therefore setting a big buffer with PacketInitPacket can noticeably
decrease the number of system calls, reducing the impcat of the capture process on the processor.
*/
VOID PacketInitPacket(LPPACKET lpPacket,PVOID Buffer,UINT Length)
{
TRACE_ENTER("PacketInitPacket");
lpPacket->Buffer = Buffer;
lpPacket->Length = Length;
lpPacket->ulBytesReceived = 0;
lpPacket->bIoComplete = FALSE;
TRACE_EXIT("PacketInitPacket");
}
/*!
\brief Read data (packets or statistics) from the NPF driver.
\param AdapterObject Pointer to an _ADAPTER structure identifying the network adapter from which
the data is received.
\param lpPacket Pointer to a PACKET structure that will contain the data.
\param Sync This parameter is deprecated and will be ignored. It is present for compatibility with
older applications.
\return If the function succeeds, the return value is nonzero.
The data received with this function can be a group of packets or a static on the network traffic,
depending on the working mode of the driver. The working mode can be set with the PacketSetMode()
function. Give a look at that function if you are interested in the format used to return statistics
values, here only the normal capture mode will be described.
The number of packets received with this function is variable. It depends on the number of packets
currently stored in the driver抯 buffer, on the size of these packets and on the size of the buffer
associated to the lpPacket parameter. The following figure shows the format used by the driver to pass
packets to the application.
\image html encoding.gif "method used to encode the packets"
Packets are stored in the buffer associated with the lpPacket _PACKET structure. The Length field of
that structure is updated with the amount of data copied in the buffer. Each packet has a header
consisting in a bpf_hdr structure that defines its length and contains its timestamp. A padding field
is used to word-align the data in the buffer (to speed up the access to the packets). The bh_datalen
and bh_hdrlen fields of the bpf_hdr structures should be used to extract the packets from the buffer.
Examples can be seen either in the TestApp sample application (see the \ref packetsamps page) provided
in the developer's pack, or in the pcap_read() function of wpcap.
*/
BOOLEAN PacketReceivePacket(LPADAPTER AdapterObject,LPPACKET lpPacket,BOOLEAN Sync)
{
BOOLEAN res;
UNUSED(Sync);
TRACE_ENTER("PacketReceivePacket");
#ifdef HAVE_WANPACKET_API
if (AdapterObject->Flags == INFO_FLAG_NDISWAN_ADAPTER)
{
lpPacket->ulBytesReceived = WanPacketReceivePacket(AdapterObject->pWanAdapter, lpPacket->Buffer, lpPacket->Length);
TRACE_EXIT("PacketReceivePacket");
return TRUE;
}
#endif //HAVE_WANPACKET_API
#ifdef HAVE_AIRPCAP_API
if(AdapterObject->Flags == INFO_FLAG_AIRPCAP_CARD)
{
//
// Wait for data, only if the user requested us to do that
//
if((int)AdapterObject->ReadTimeOut != -1)
{
WaitForSingleObject(AdapterObject->ReadEvent, (AdapterObject->ReadTimeOut==0)? INFINITE: AdapterObject->ReadTimeOut);
}
//
// Read the data.
// g_PAirpcapRead always returns immediately.
//
res = (BOOLEAN)g_PAirpcapRead(AdapterObject->AirpcapAd,
lpPacket->Buffer,
lpPacket->Length,
&lpPacket->ulBytesReceived);
TRACE_EXIT("PacketReceivePacket");
return res;
}
#endif // HAVE_AIRPCAP_API
#ifdef HAVE_NPFIM_API
if(AdapterObject->Flags == INFO_FLAG_NPFIM_DEVICE)
{
//
// Read the data.
// NpfImReceivePacket performs its own wait internally.
//
res = (BOOLEAN)g_NpfImHandlers.NpfImReceivePackets(AdapterObject->NpfImHandle,
lpPacket->Buffer,
lpPacket->Length,
&lpPacket->ulBytesReceived);
TRACE_EXIT("PacketReceivePacket");
return res;
}
#endif // HAVE_NPFIM_API
#ifdef HAVE_DAG_API
if((AdapterObject->Flags & INFO_FLAG_DAG_CARD) || (AdapterObject->Flags & INFO_FLAG_DAG_FILE))
{
g_p_dagc_wait(AdapterObject->pDagCard, &AdapterObject->DagReadTimeout);
res = (BOOLEAN)(g_p_dagc_receive(AdapterObject->pDagCard, (u_char**)&AdapterObject->DagBuffer, (u_int*)&lpPacket->ulBytesReceived) == 0);
TRACE_EXIT("PacketReceivePacket");
return res;
}
#endif // HAVE_DAG_API
if (AdapterObject->Flags == INFO_FLAG_NDIS_ADAPTER)
{
if((int)AdapterObject->ReadTimeOut != -1)
WaitForSingleObject(AdapterObject->ReadEvent, (AdapterObject->ReadTimeOut==0)?INFINITE:AdapterObject->ReadTimeOut);
res = (BOOLEAN)ReadFile(AdapterObject->hFile, lpPacket->Buffer, lpPacket->Length, &lpPacket->ulBytesReceived,NULL);
}
else
{
TRACE_PRINT1("Request to read on an unknown device type (%u)", AdapterObject->Flags);
res = FALSE;
}
TRACE_EXIT("PacketReceivePacket");
return res;
}
/*!
\brief Sends one (or more) copies of a packet to the network.
\param AdapterObject Pointer to an _ADAPTER structure identifying the network adapter that will
send the packets.
\param lpPacket Pointer to a PACKET structure with the packet to send.
\param Sync This parameter is deprecated and will be ignored. It is present for compatibility with
older applications.
\return If the function succeeds, the return value is nonzero.
This function is used to send a raw packet to the network. 'Raw packet' means that the programmer
will have to include the protocol headers, since the packet is sent to the network 'as is'.
The CRC needs not to be calculated and put at the end of the packet, because it will be transparently
added by the network interface.
The behavior of this function is influenced by the PacketSetNumWrites() function. With PacketSetNumWrites(),
it is possible to change the number of times a single write must be repeated. The default is 1,
i.e. every call to PacketSendPacket() will correspond to one packet sent to the network. If this number is
greater than 1, for example 1000, every raw packet written by the application will be sent 1000 times on
the network. This feature mitigates the overhead of the context switches and therefore can be used to generate
high speed traffic. It is particularly useful for tools that test networks, routers, and servers and need
to obtain high network loads.
The optimized sending process is still limited to one packet at a time: for the moment it cannot be used
to send a buffer with multiple packets.
\note The ability to write multiple packets is currently present only in the Windows NTx version of the
packet driver. In Windows 95/98/ME it is emulated at user level in packet.dll. This means that an application
that uses the multiple write method will run in Windows 9x as well, but its performance will be very low
compared to the one of WindowsNTx.
*/
BOOLEAN PacketSendPacket(LPADAPTER AdapterObject,LPPACKET lpPacket,BOOLEAN Sync)
{
DWORD BytesTransfered;
BOOLEAN Result;
TRACE_ENTER("PacketSendPacket");
UNUSED(Sync);
#ifdef HAVE_AIRPCAP_API
if(AdapterObject->Flags == INFO_FLAG_AIRPCAP_CARD)
{
if(g_PAirpcapWrite)
{
Result = (BOOLEAN)g_PAirpcapWrite(AdapterObject->AirpcapAd, lpPacket->Buffer, lpPacket->Length);
TRACE_EXIT("PacketSetMinToCopy");
return Result;
}
else
{
TRACE_EXIT("PacketSetMinToCopy");
TRACE_PRINT("Transmission not supported with this version of AirPcap");
return FALSE;
}
}
#endif // HAVE_AIRPCAP_API
#ifdef HAVE_WANPACKET_API
if(AdapterObject->Flags == INFO_FLAG_NDISWAN_ADAPTER)
{
TRACE_PRINT("PacketSendPacket: packet sending not allowed on wan adapters");
TRACE_EXIT("PacketSendPacket");
return FALSE;
}
#endif // HAVE_WANPACKET_API
#ifdef HAVE_NPFIM_API
if(AdapterObject->Flags == INFO_FLAG_NPFIM_DEVICE)
{
TRACE_PRINT("PacketSendPacket: packet sending not allowed on NPFIM adapters");
TRACE_EXIT("PacketSendPacket");
return FALSE;
}
#endif //HAVE_NPFIM_API
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -