⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 packet32.c

📁 Windows XP下的抓包程序实现
💻 C
📖 第 1 页 / 共 5 页
字号:
		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 + -