監聽以太網(四) Packet32函數SDK

Packet32包中的函數說明:

No.3. PacketSetHwFilter (設置過濾器)

設置一個hardware filter。比如,Filter參數傳遞NDIS_PACKET_TYPE_PROMISCUOUS,就可以設置網卡爲混雜模式。

BOOLEAN PacketSetHwFilter(
LPADAPTER AdapterObject,
ULONG Filter
);

Parameters:
AdapterObject:
    [in] 指向一個_ADAPTER結構的指針。
Filter:
     [in] 過濾器的id。
Return Values:
如果執行成功,返回一個非零值。

Usage:
C/C++ Usage Sample
lpAdapter = PacketOpenAdapter(AdapterList[Open-1]);
PacketSetHwFilter(lpAdapter,NDIS_PACKET_TYPE_PROMISCUOUS);

Remarks:
過濾器定義在ntddndis.h中。下面是一些最常用的: NDIS_PACKET_TYPE_PROMISCUOUS:設置混雜模式。網卡接收每一個Packet;
NDIS_PACKET_TYPE_DIRECTED;
NDIS_PACKET_TYPE_BROADCAST:只接收broadcast packets;
NDIS_PACKET_TYPE_MULTICAST:只接收multicast packets,而且本機網卡是接收組的一個成員;
NDIS_PACKET_TYPE_ALL_MULTICAST:所有multicast packets都接收;
NDIS_PACKET_TYPE_ALL_LOCAL:所有local packets。

這個函數的實現是非常簡單的:首先填充PACKET_OID_DATA結構的Oid成員爲OID_GEN_CURRENT_PACKET_FILTER,填充Data成員爲既定的Filter,調用PacketRequest向網卡發送OID請求即可。
No.4. PacketSetBuff (設置緩衝區的大小)

設置捕獲的內核級緩衝區的大小。

BOOLEAN PacketSetBuff(
LPADAPTER AdapterObject,
int dim
);

Parameters:
AdapterObject: [in] 指向一個_ADAPTER結構的指針。
dim: [in] 緩衝區的大小(單位:字節)。
Return Values: 如果執行成功,返回一個TRUE。如果沒有足夠的內存分配,返回FALSE。

Usage:
C/C++ Usage Sample
lpAdapter = PacketOpenAdapter(AdapterList[Open-1]);
PacketSetBuff(lpAdapter,512000)?; // 設置driver有512KB字節的緩衝區

Remarks:
  一旦設定了一個新緩衝區大小,在原來的那塊緩衝區中的數據就會被丟棄,包括存在裏面的Packets。注意:內核緩衝區的大小會嚴重影響到捕獲進程的性能。一個適當的緩衝區可以在應用忙時保有數據,從而補償應用的響應延遲,並在網絡活動頻繁時做到不丟失Packets。當driver的一個實例被打開時,這個緩衝區的大小被重設爲0:開發者應該記得把它設爲一個合適的值,比如設爲1MB。

  本函數調用了DeviceIoControl,給AdapterObject參數的hFile成員指向的NPF driver設備發送pBIOCSETBUFFERSIZE控制碼。pBIOCSETBUFFERSIZE是在Packet32.h中定義的: //< IOCTL code: set kernel buffer size:
#define pBIOCSETBUFFERSIZE 9592

No.5. PacketSetReadTimeout (設置讀操作的超時時間)
設置一次讀操作返回的超時時間。

BOOLEAN PacketSetReadTimeout(
LPADAPTER AdapterObject,
int timeout
);

Parameters:
AdapterObject: [in] 指向一個_ADAPTER結構的指針。
timeout: [in] 超時時間(單位:毫秒)。
Return Values: 如果執行成功,返回非零值。

Usage:
C/C++ Usage Sample
lpAdapter = PacketOpenAdapter(AdapterList[Open-1]);
PacketSetReadTimeout(lpAdapter,1000)?; // 設置讀操作超時時間1秒

Remarks:
  在AdapterObject指向的網卡上調用PacketReceivePacket(),到了設定的超時時間,這次調用就會釋放,即使沒有Packet被捕獲到。設置超時時間爲0,說明沒有超時。這樣,如果沒有Packet到來的話,PacketReceivePacket()方法永不會返回。設置超時時間爲-1,PacketReceivePacket()會立即返回。

這個函數也工作在網卡的統計模式下。所以可以用來設置兩次統計報告之間的時間間隔。
這個函數也是通過DeviceIoControl發送控制碼來實現的。
No.6. PacketAllocatePacket

爲_PACKET結構分配內存。

LPPACKET PacketAllocatePacket(void);

Parameters: 無
Return Values: 如果執行成功,返回指向_PACKET結構的指針。否則,返回NULL。

Usage:
C/C++ Usage Sample
LPPACKET lpPacket;
lpPacket = PacketAllocatePacket()?;

Remarks:
  這個函數並不負責爲_PACKET結構的Buffer成員分配空間。這塊緩衝區必須由應用程序分配,而且必須調用PacketInitPacket來將這緩衝區和_PACKET結構關聯到一起。
No.7. PacketInitPacket

初始化一個_PACKET結構,即將packet結構中的buffer設置爲傳遞的buffer指針。

VOID PacketInitPacket(
LPPACKET lpPacket,
PVOID Buffer,
UINT Length
);

Parameters:
lpPacket [in] 指向一個_PACKET結構的指針。
Buffer [in] 一個指向一塊用戶分配的緩衝區的指針。捕獲的數據將放置於此。
Length [in] 緩衝區的大小。這是一個讀操作從driver傳遞到應用的最大數據量。
Return Values: 無。

Usage:
C/C++ Usage Sample
char buffer[256000];
LPPACKET lpPacket;
PacketInitPacket(lpPacket,(char*)buffer,256000);;

Remarks:
  Driver能夠用一個讀操作返回幾個Packets,那麼一次調用傳遞給應用程序的packet的數量,就只取決於傳遞給PacketReceivePacket()的_PACKET結構的buffer的大小了。因此用PacketInitPacket()初始化一塊大緩衝區,能夠顯著地減少系統調用,減少捕獲進程在處理器上的影響。
No.8. PacketReceivePacket (讀取數據)

從NPF driver上讀取數據(Packets或者統計信息)。

BOOLEAN PacketReceivePacket(
LPADAPTER AdapterObject,
LPPACKET lpPacket,
BOOLEAN Sync
);

Parameters:
AdapterObject: [in] 指向一個_ADAPTER結構的指針。
lpPacket: [in , out] 放數據的_PACKET結構緩衝區。
Sync: [in] 一個可以忽略的參數,保留它是爲了向後兼容。
Return Values: 如果執行成功,返回一個非零值。

Usage:
C/C++ Usage Sample
LPADAPTER lpAdapter = 0;
LPPACKET lpPacket;
lpAdapter = PacketOpenAdapter(AdapterList[Open-1]);
lpPacket = PacketAllocatePacket();
PacketInitPacket(lpPacket,(char*)buffer,256000);
PacketReceivePacket(lpAdapter,lpPacket,TRUE);

Remarks:
  這個函數所接收的數據可以是一組Packets,也可以是網絡流量的一個統計數據,依賴於網卡的工作模式。
接收到的Packet的數量是可變的。它依賴於幾個因素:當前存儲在driver緩衝區中的Packet的數目,這些Packet的大小,分配給lpPacket參數的緩衝區的大小。
   Packet存儲在lpPacket結構的buffer緩衝區內,lpPacket->Length指示着複製到緩衝區的數據的大小。

它的實現也很簡單:先看看AdapterObject->ReadTimeOut是否是-1:
如果不是-1,則調用WaitForSingleObject等候AdapterObject->ReadEvent讀事件觸發,超時時間爲AdapterObject->ReadTimeOut的數值。
如果AdapterObject->ReadTimeOut爲0,則永不超時。
如果是-1,就表明讀完立即返回。
之後,調用ReadFile讀取數據。
No.9. PacketGetStats (得到本次捕獲的統計數據)

得到當前捕獲進程的統計信息。

BOOLEAN PacketGetStats(
LPADAPTER AdapterObject,
struct bpf_stat *s
);

Parameters:
AdapterObject: [in] 指向一個_ADAPTER結構的指針。
s: [in, out] bpf_stat結構,通過它,我們可以知道接收到的包數,丟失的包數等。
Return Values: 如果執行成功,返回非零值。

Usage:
C/C++ Usage Sample
struct bpf_stat stat;
PacketGetStats(lpAdapter,&stat)?;

Remarks:
通過這個函數,我們可以知道:
從開始捕獲起,這個driver從網卡上接收的Packet的數量(包括driver丟失的Packet);
從開始捕獲起,這個driver丟失的Packet的數量,一般地,包丟失,是因爲driver的緩衝區滿了,這時driver將扔掉這個包。
  具體實現也是調用DeviceIoControl函數向設備發送pBIOCGSTATS控制碼,得到一個bpf_stat結構,然後只把這個結構的bs_recv和bs_drop成員返回。

No.10. PacketCloseAdapter

關閉網卡。

VOID PacketCloseAdapter(LPADAPTER lpAdapter);

Parameters:
lpAdapter: [in] 指向一個_ADAPTER結構的指針。
Remarks:依次做下面的動作:
關閉lpAdapter->hFile,打開的NPF driver的實例句柄;
觸發lpAdapter->ReadEvent,並關閉這個句柄;
解鎖並釋放lpAdapter。 

 
發佈了4 篇原創文章 · 獲贊 1 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章