當前位置:
首頁 > 最新 > 適配器的打開與關閉(下)

適配器的打開與關閉(下)

先介紹和適配器相關結構體:

_ADAPTER用來描述一個已打開的適配器實例

具體定義如下:

typedef struct_ADAPTER

{

//指向一個NPF驅動程序實例的句柄

HANDLE hFile;

//保存當前打開網路適配器的名稱

CHAR SymbolicLink[MAX_LINK_NAME_LENGTH];

//每個數據包重複發送的次數

int NumWrites;

//與適配器讀調用關聯的通知事件

HANDLE ReadEvent;

//讀超時時間

UINT ReadTimeOut;

CHAR Name[ADAPTER_NAME_LENGTH];

PWAN_ADAPTER pWanAdapter;

//適配器標識

UINT Flags;

}ADAPTER,*LPADAPTER;

_PACKET從驅動程序處得到的一組數據包

具體定義如下:

typedef struct_PACKET

{

//儲存數據包的緩衝區

PVOID Buffer;

//緩衝區的長度

UINT Length;

//緩衝區中的有效位元組數

DWORD ulBytesReceived;

}PACKET,*LPPACKET;

_PACKET_OID_DATA包含一個OID請求

具體定義如下:

struct_PACKET_OID_DATA

{

//OID碼,獲得一個有效編碼的完整列表

ULONG Oid;

//Data成員的長度

ULONG Length;

//變長成員,包含傳遞到適配器或從適配器接收的信息

UCHAR Data[1];

};

typedef struct_PACKET_OID_DATA PACKET_OID_DATA, *PPACKET_OID_DATA;

由上節已知適配器的打開主要依靠pcap_open函數實現,而在pcap_open函數中,調用pcap_create函數創建pcap_t結構體,而pcap_create函數中又是通過調用pcap_create_common來實現創建pcap_t結構體的,同時調用pcap_active_win32實現對網路適配器實例的激活,pcap_active_win32函數又通過調用Packet.dll的PacketOpenAdapter函數打開適配器,並通過調用PacketSetHwFilter設置捕獲器的過濾模式,最後調用PacketAllocatePacket和PacketSetBuff對數據包結構體進行分配空間及初始化操作.

PacketOpenAdapter函數先獲得g_AdaptersInfoMutex互斥信號,然後更新鏈表並查找適配器,接著通過調用更為底層的PacketOpenAdapterNPF函數試圖打開正常的NPF適配器,並釋放互斥信號。

而PacketOpenAdapterNPF函數同通過連到服務控制管理器(SCM),檢查NPF驅動程序是否存在,若不存在,調用PacketInstallDriver函數安裝驅動程序,接下來分配並初始化_ADAPTER對象,根據設備的原始名稱創建NPF設備名稱,並試圖通過調用CreateFile函數打開該適配器,若成功,則調用PacketSetReadEvt函數通過IOCTL系統調用將讀事件信號分配捕獲並傳遞到內核,調用PacketSetMaxLookaheadsize函數為驅動程序NPF_tap函數設置前視緩衝區,調用PacketGetNetType函數獲取適配器鏈路層信息。

內核中有一個最重要的結構體:_OPEN_INSTANCE描述NPF驅動程序運行實例狀態,幾乎被所有驅動程序函數使用,由於代碼太長,這裡就不展示它的具體定義。

內核驅動程序NPF,因此相關函數基本都以NPF開頭或結尾,Packet.dll中的PacketOpenAdapterNPF調用CreateFileA函數,調用NPF_Open函數打開驅動的一個新實例,而NPF_Open函數又調用NdisOpenAdapter函數打開網路設備,在NdisOpenAdapter函數操作完成時NPF_OpenAdapterCmplete函數被調用結束一個適配器的打開操作。

上層的設置緩衝區大小和讀寫請求的操作都是由底層的NdisRequest實現的,用來執行OID(對象標識符)請求或設置,在完成一個OID請求操作時,NPF_RequestComplete函數被調用來結束一個OID請求。通常僅網路驅動程序執行OID操作,但NPF會通過調用NPF_IoControl執行IOCTL調用,當DeviceIoControl系統函數被調用時,該函數響應IRP_MJ_DEVICE_CONTROL而被調用,常見的IOCTL命令碼如下:

BIOCSMINTOCOPY

設置內核緩衝區中最小數據量大小

BIOCISETLOBBEH

用來設置環回的行為,處理接收自己發送包的方式;

BOPCSETBUFFERSIZE

用來設置內核緩衝區的大小

BIOCSETEVENTHANDLE

將用戶所分配的事件句柄傳遞給內核空間

接下來介紹關閉適配器的實現,通過pcap_close函數釋放pcap_t結構體及其相關所獲得的資源,在該函數中調用pcap_cleanup_win32函數關閉適配欸,釋放儲存數據包的內存,最後調用pcap_cleanup_live_common函數清除過濾器

而pcap_cleanup_win32函數調用PacketCloseAdapter關閉並釋放一個ADAPTER結構體資源,在調用CloseHandle時,NPF_Cleanup函數被調用來停止捕獲/監視/轉儲過程並釋放資源,通過調用NPF_CloseOpenInstance函數釋放與Open實例相關的資源,通過調用NPF_CloseBinding函數解除調用NdisOpenAdapter庫函數所建立的綁定和分配的資源,在NPF_CloseBinding中調用NdisCloseAdapter時,NPF_CloseAdapterComplete函數被調用來結束適配器的關閉,通過調用NPF_ReleaseOpenInstanceResources函數釋放在NPF_Open函數中所分配的部分資源。

通過這一階段的學習,發現難點在於熟練語法的基礎上理解其中的機制運行,並熟悉內核空間與用戶空間的介面操作流程。

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 全球大搜羅 的精彩文章:

TAG:全球大搜羅 |