版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
基于PassThru的NDIS中間層驅(qū)動(dòng)程序擴(kuò)展概要:開(kāi)發(fā)一個(gè)NDIS驅(qū)動(dòng)是一項(xiàng)相對(duì)復(fù)雜的工作,這一方面是由于核心驅(qū)動(dòng)本身有更多的限制和要求,有更多的“游戲規(guī)則”要求開(kāi)發(fā)者理解和掌握,NDIS的復(fù)雜性把難度更是提高了,本文以PassThru為例,加上自己的理解,講述了NDIS驅(qū)動(dòng)的處理過(guò)程和在PassThru的基礎(chǔ)上進(jìn)行擴(kuò)展的基本方法,本文并不是一個(gè)入門(mén)讀物,所以沒(méi)有提及任何核心驅(qū)動(dòng)開(kāi)發(fā)的相關(guān)知識(shí),本文主要講述的是NDIS中間層對(duì)數(shù)據(jù)包處理的流程。在閱讀過(guò)程中,關(guān)于相關(guān)API的用法,或其它信息,請(qǐng)參看DDK文檔。
一
NDIS驅(qū)動(dòng)程序分類.
NDIS(NetworkDriverInterfaceSpecification)是Windows網(wǎng)絡(luò)驅(qū)動(dòng)程序接口標(biāo)準(zhǔn),NDIS驅(qū)動(dòng)程序分為三類:
1.NDISMiniportNICDriver:底層的微端口NIC驅(qū)動(dòng),這就是網(wǎng)絡(luò)設(shè)備的物理的驅(qū)動(dòng)程序了。
2.NDISProtocolDriver:高層的協(xié)議驅(qū)動(dòng),用來(lái)實(shí)現(xiàn)某個(gè)具體的協(xié)議棧,如TCP/IP協(xié)議棧,
并向上導(dǎo)出TDI接口。
3.NDISIntermediateDriver:中間層驅(qū)動(dòng),位于MiniportDriver和ProtocolDriver之間。
二
NDIS驅(qū)動(dòng)結(jié)構(gòu)簡(jiǎn)介.
其中,最上層是一個(gè)NDISProtocolDriver,它向上提供一個(gè)TransportDriverInterface(TDI),向下通過(guò)NDIS接口與下面的NDIS中間層的上邊界交互,NDIS中間層的下邊界通過(guò)NDIS接口與下層的NDISMiniportDriver交互。最后,由NDISMiniportDriver利用NDIS接口與物理網(wǎng)絡(luò)設(shè)備NetCard交互。NetCard是由不同的網(wǎng)卡設(shè)備產(chǎn)商提供的,而NDIS接口庫(kù)是由Microsoft開(kāi)發(fā)好的,為什么NDISMiniportDriver不是直接與物理網(wǎng)卡交互,而是通過(guò)NDIS接口與下物理網(wǎng)卡交互呢?(我想很多人都會(huì)和我當(dāng)初一樣,有這個(gè)疑問(wèn))。
事實(shí)上,這是由于Windows系統(tǒng)為了提高可移植性,而設(shè)計(jì)出一個(gè)硬件抽象層(HAL),硬件抽象層在內(nèi)部處理不同的硬件之間的差異,并且暴露出一個(gè)統(tǒng)一的接口給核心驅(qū)動(dòng)開(kāi)發(fā)者。例如:在Intel構(gòu)架的系統(tǒng)中,內(nèi)存和外部設(shè)備的端口采用分別編址,如果要從某個(gè)外部設(shè)備的端口上讀寫(xiě)數(shù)據(jù)的話,可能要通過(guò)專用指令I(lǐng)N/OUT讀寫(xiě),而在Alpha構(gòu)架的系統(tǒng)上,采用的是統(tǒng)一編址的方式,所以對(duì)外部設(shè)備的IO端口進(jìn)行讀寫(xiě)的話還是通過(guò)訪問(wèn)內(nèi)存的指令,HAL提供一組服務(wù)支持函數(shù),如果要訪問(wèn)外部設(shè)備上的端口數(shù)據(jù)可以使用READ_PORT_UCHAR/WRITE_PORT_UCHAR等等,核心驅(qū)動(dòng)開(kāi)發(fā)者不用去考慮不同硬件構(gòu)架的之間的差異。在NDISMiniportDriver中,NetCard驅(qū)動(dòng)的程序,正是這樣通過(guò)NDIS接口提供的一組類似功能的函數(shù),與物理的網(wǎng)絡(luò)設(shè)備進(jìn)行交互。其中,最上層是一個(gè)NDISProtocolDriver,它向上提供一個(gè)TransportDriverInterface(TDI),向下通過(guò)NDIS接口與下面的NDIS中間層的上邊界交互,NDIS中間層的下邊界通過(guò)NDIS接口與下層的NDISMiniportDriver交互。最后,由NDISMiniportDriver利用NDIS接口與物理網(wǎng)絡(luò)設(shè)備NetCard交互。三NDIIS驅(qū)動(dòng)動(dòng)程序的的數(shù)據(jù)處處理流程程
3.11三種種NDIIS驅(qū)動(dòng)動(dòng)程序的的關(guān)系。
通通常一個(gè)個(gè)NDIISPProttocoolDDrivver的上邊邊沿導(dǎo)出出TDII接口,并并在其下下邊沿向向NDIIS注冊(cè)冊(cè)一組PProttocoolxxxx操作作例程;;一個(gè)NNDISSMiinipporttDrriveer則在在其下邊邊沿通過(guò)過(guò)NDIIS接口口操作物物理網(wǎng)絡(luò)絡(luò)設(shè)備,并并在其上上邊沿向向NDIIS注冊(cè)冊(cè)一組MMiniiporrtxxxx操作作例程。當(dāng)當(dāng)一個(gè)中中間層介介入的時(shí)時(shí)候,必必需遵守守這個(gè)規(guī)規(guī)則,因因此,中中間層驅(qū)驅(qū)動(dòng)對(duì)上上層來(lái)說(shuō)說(shuō),扮演演一個(gè)MMiniiporrtDDrivver的的角色,它它在上邊邊沿向NNDISS注冊(cè)一一組Miinipporttxxxx函數(shù);;對(duì)于下下層MiinipporttDrriveer來(lái)說(shuō)說(shuō),中間間層驅(qū)動(dòng)動(dòng)扮演一一個(gè)PrrotoocollDrriveer的角角色,因因此它在在下邊沿沿向NDDIS注注冊(cè)一組組Prootoccolxxxx函函數(shù)。MMiniiporrtDDrivver通通過(guò)調(diào)用用NdiisMRRegiisteerMiinipportt向NDDIS注注冊(cè)一組組MinnipoortXXxx函函數(shù)。其其中原型型如下::
NDDIS__STAATUSSNddisMMReggistterMMiniiporrt(
INNNDDIS__HANNDLEE
NNdissWraappeerHaandlle,
IINPPNDIIS_MMINIIPORRT_CCHARRACTTERIISTIICS
MiinipporttChaaraccterristticss,
INNUIINT
ChharaacteerissticcsLeengtth
);;
其中中,NddisWWrappperrHanndlss是之前前通過(guò)調(diào)調(diào)用NddisMMIniitiaalizzeWrrappper取取得的句句柄MiinipporttChaaraccterristticss包含一一組MiinipporttXxxx函數(shù)指指針。
ProotoccolDriiverr通過(guò)過(guò)調(diào)用NdiisReegissterrProotoccol向向NDIIS注冊(cè)冊(cè)一組PProttocoolXxxx函數(shù)數(shù)。其中中原型如如下:
VOIIDNNdissReggistterPProttocool(
OUUTPPNDIIS_SSTATTUS
Sttatuus,
OUUTPPNDIIS_HHANDDLE
NddisPProttocoolHaandlle,
INNPNNDISS_PRROTOOCOLL_CHHARAACTEERISSTICCS
ProotoccolCCharractteriistiics,,
IINUUINTT
CCharractteriistiicsLLenggth
);;
其中中,PrrotoocollChaaraccterristticss包含一一組PrrotoocollXxxx函數(shù)。由由于NDDISInttermmediiateeDrriveer的雙雙重性,它它需要調(diào)調(diào)用NNdissIMRRegiisteerLaayerredMMiniiporrt向向NDIIS注冊(cè)冊(cè),并向向上層導(dǎo)導(dǎo)出一組組MinnipoortXXxx函函數(shù),之之后,調(diào)調(diào)用NddisRRegiisteerPrrotoocoll向NIIDS注注冊(cè),并并向下層層導(dǎo)出一一組PProttocoolXxxx函數(shù)數(shù)。當(dāng)一一個(gè)NDDIS中中間層介介入后,如如圖二所所示。
33.2NDIIS數(shù)據(jù)據(jù)發(fā)送流流程:
當(dāng)上層層協(xié)議驅(qū)驅(qū)動(dòng)要發(fā)發(fā)數(shù)據(jù)時(shí)時(shí),調(diào)用用NdiisSeend//NdiisSeendPPackketss請(qǐng)求NNDISS發(fā)送數(shù)數(shù)據(jù)包,NNDISS將會(huì)調(diào)調(diào)用緊接接其下的的中間層層驅(qū)動(dòng)的的MinnipoortSSendd/MiinipporttSenndPaackeets,中中間層驅(qū)驅(qū)動(dòng)MiinipporttSennd/MMiniiporrtSeendPPackketss有機(jī)機(jī)會(huì)在這這里對(duì)包包進(jìn)行必必要的操操作,然然后,中中間層驅(qū)驅(qū)動(dòng)再次次調(diào)用NNdissSennd/NNdissSenndPaackeets請(qǐng)請(qǐng)NDIIS發(fā)送送數(shù)據(jù)包包,NDDIS將將調(diào)用其其下層的的MinnipoortDriiverr的MiinipporttSennd/MMiniiporrtSeendPPackketss,底層層MinnipoortSSendd/MMiniiporrtSeendPPackketss通過(guò)NNDISS接口控控制物理理網(wǎng)絡(luò)設(shè)設(shè)備,將將數(shù)據(jù)發(fā)發(fā)送出去去。在上上層請(qǐng)求求發(fā)送數(shù)數(shù)據(jù)包時(shí)時(shí),上層層分配了了相關(guān)的的資源((如內(nèi)存存),希希望在下下層完成成發(fā)送動(dòng)動(dòng)作后,能能夠及時(shí)時(shí)的收回回相關(guān)的的資源,所所以,當(dāng)當(dāng)上層調(diào)調(diào)用NddisSSendd/NddisSSenddPaccketts返回回NDDIS__STAATUSS_PEENDIING以以外的任任何值時(shí)時(shí),上層層就可以以釋放資資源了,如如果得到到返回的的結(jié)果是是NDIIS_SSTATTUS__PENNDINNG話,說(shuō)說(shuō)明下層層還沒(méi)有有完成發(fā)發(fā)送請(qǐng)求求,以后后,等下下層最終終完成發(fā)發(fā)送請(qǐng)求求時(shí),下下層調(diào)用用NdiisMSSenddCommpleete請(qǐng)請(qǐng)求NDDIS通通知上層層可以釋釋放資源源了,于于是NDDIS調(diào)用上上層注冊(cè)冊(cè)的PrrotoocollSenndCoomplletee函數(shù),上上層在這這它的PProttocoolSeendCCompplette中釋釋放了資資源后,再再次調(diào)用用NddisMMSenndCoomplletee請(qǐng)求NNDISS通知更更上層。
3.3NDIS數(shù)據(jù)接收流程:
當(dāng)?shù)讓泳W(wǎng)絡(luò)設(shè)備有數(shù)據(jù)到來(lái)的時(shí)候,將觸發(fā)中斷,相應(yīng)的中斷處理程序接管中斷后,將可能調(diào)用MiniportDriver所注冊(cè)的中斷處理例程(ISR),MiniportDriver通常在這里把網(wǎng)卡上的數(shù)據(jù)考貝到MiniportDriver緩沖區(qū)隊(duì)列中去,出于效率的考慮,MiniportDriver這時(shí)可能不會(huì)立即通知上層處理新的數(shù)據(jù),因?yàn)楹芸赡?,馬上還有隨后的新的數(shù)據(jù)到來(lái),當(dāng)接收到的包的數(shù)量達(dá)到一定程度的時(shí)候,MiniportDriver會(huì)調(diào)用NdisMIndicateReceivePacket指示新的NDIS新數(shù)據(jù)的到來(lái),這時(shí)候,NdisMIndicateReceivePacket的調(diào)用將導(dǎo)致NDIS調(diào)用位于Miniport上層的中間層向NDIS注冊(cè)的下邊沿ProtocolReceivePacket函數(shù)。中間層驅(qū)動(dòng)程序的ProtocolReceivePacket可以對(duì)收到的數(shù)據(jù)包進(jìn)行相應(yīng)的處理,之后,可以選擇再次調(diào)用NdisMIndicateReceivePacket請(qǐng)求NDIS通知更上層數(shù)據(jù)包的到來(lái),這時(shí),NDIS調(diào)用更上層注冊(cè)的ProtocolReceive函數(shù),上層的ProtocolReceive對(duì)數(shù)據(jù)包進(jìn)行必要的處理后,繼續(xù)調(diào)用NdisMIndicateReceivePacket請(qǐng)求NDIS,通知更上層,最終數(shù)據(jù)包傳到協(xié)議驅(qū)動(dòng)中,由相關(guān)的協(xié)議棧進(jìn)行處理。
有時(shí)候,在這種級(jí)連的上傳過(guò)程中,并不是那么的順利,例如,由于某種原因,如:網(wǎng)絡(luò)設(shè)備的驅(qū)動(dòng)程序的可用緩沖區(qū)數(shù)量減少到某個(gè)指定的數(shù)量時(shí),網(wǎng)絡(luò)設(shè)備的驅(qū)動(dòng)程序調(diào)用NdisMxxxIndicateReceivePacket請(qǐng)求NDIS通知上層數(shù)據(jù)的到來(lái),這時(shí)NDIS將調(diào)用上層注冊(cè)的ProtocolReceive,上層在ProtocolReceive中進(jìn)行必要的處理后,進(jìn)一步調(diào)用NdisMxxxIndicateReceivePacket使得NDIS調(diào)用上層的協(xié)議驅(qū)動(dòng)注冊(cè)的ProtocolReceive。在一些不太理想的情況下,一次中斷,從網(wǎng)絡(luò)設(shè)備中接收到的數(shù)據(jù)對(duì)某個(gè)協(xié)議來(lái)說(shuō)并不是一個(gè)完整的協(xié)議數(shù)據(jù)包。(一般情況下,其余的數(shù)據(jù)bit已經(jīng)在鏈路途中了,并隨后立即就會(huì)到達(dá)網(wǎng)絡(luò)設(shè)備,這有可能就發(fā)生在一個(gè)CPU在處理網(wǎng)絡(luò)設(shè)備中斷的同時(shí),網(wǎng)絡(luò)設(shè)備的板載存儲(chǔ)器上就已經(jīng)收到了其余的數(shù)據(jù)了,甚至DMA控制器可能已經(jīng)把這些數(shù)據(jù)傳到了系統(tǒng)的主存儲(chǔ)器上了),這時(shí),上層的ProtocolReceive都無(wú)法進(jìn)行正常的處理(一般對(duì)某個(gè)包進(jìn)行處理,都要以相關(guān)的協(xié)議為依據(jù),進(jìn)行分析)。這時(shí),在上傳到某一層時(shí),可以調(diào)用NdisTransferData請(qǐng)求NDIS把隨后的信息傳上來(lái),這時(shí),NDIS又將在向上傳遞的途中回過(guò)頭來(lái)向下調(diào)用下面的MiniportTransferData,下層重復(fù)調(diào)用NdisTransferData把這個(gè)請(qǐng)求傳送到底程的MiniportDriver。如果在上層調(diào)用NdisTransferData時(shí)不是返回NDIS_STATUS_PENDING,則上層可以繼續(xù)它的處理,而如果返回NDIS_STATUS_PENDING,底程在最終完成請(qǐng)求時(shí),調(diào)用NdisMTransferDataComplete請(qǐng)求NDIS通知上層傳送完成,這將導(dǎo)致上層注冊(cè)的ProtocolTransferDataComplete被調(diào)用,上層調(diào)用NdisMTransferDataComplete請(qǐng)求NDIS通知更上層。由于硬件技術(shù)的發(fā)展,網(wǎng)絡(luò)設(shè)備板載存儲(chǔ)的增加,系統(tǒng)主存儲(chǔ)器的增加,以及網(wǎng)絡(luò)傳輸能力的改善,NDIS那么迂回的通過(guò)MdisMxxxIndicateReceivePacket,ProtocolReceive,MiniportTransferData這一條坎坷的路徑進(jìn)行數(shù)據(jù)處理的情況似乎越來(lái)越少見(jiàn)了。
接收過(guò)程是由下層傳遞上去的,同樣,底層的Miniport分配了一些資源,如用于存儲(chǔ)這個(gè)數(shù)據(jù)包內(nèi)容的內(nèi)存,我們希望這些資源最終能極時(shí)的被歸還,以供以后使用。一個(gè)包在從下到上的傳遞過(guò)程時(shí),如果某一層的ProtocolReceive/ProtocolReceivePacket有興趣對(duì)這個(gè)包進(jìn)行處理的話,則需要檢查這個(gè)包的OOB信息段是不是攜帶NDIS_STATUS_RESOURCES,如果是的話,說(shuō)明其下層資源緊缺,希望上層在處理的時(shí)候,自己考貝一份副本,以供自己使用,因?yàn)橄聦酉M约耗軌虮M快收回這個(gè)包的資源,在這里,上層以后可以用自己的那份拷貝指示上層數(shù)據(jù)包的到來(lái),這樣的話,以后,中間層希望上層處理完后,能夠收回所有權(quán)。另一方面,底層的Miniport并不是每一次都會(huì)在OOB信息段中設(shè)置NDIS_STATUS_RESOURCES標(biāo)志的,這在很多情況下是不必要的。當(dāng)上層協(xié)議驅(qū)動(dòng)完成處理時(shí),可以調(diào)用NdisReturnPackets通知NDIS,相應(yīng)包已經(jīng)處理完成,可以安全的釋放相關(guān)資源了,于是NDIS將調(diào)用其下層注冊(cè)的MiniportReturnPackets,下層在這里釋放與這個(gè)包相關(guān)的資源,并繼續(xù)調(diào)用NdisReturnPackets,請(qǐng)求NDIS把這個(gè)通知傳給更下層。
這樣一來(lái),發(fā)數(shù)據(jù)由上層發(fā)起請(qǐng)求往下傳,而接收數(shù)據(jù)從下層往上傳,有沒(méi)有可能一次接收的過(guò)層是由上面發(fā)起往下傳的呢?這是沒(méi)有必要的,為什么?我的應(yīng)用程序不就主動(dòng)調(diào)用WSARecv或WSARecvFrom等函數(shù)主動(dòng)向下傳遞的一次收數(shù)據(jù)的請(qǐng)求的嗎?事實(shí)上是這樣的,你的接收請(qǐng)求經(jīng)過(guò)SPI,TDI,到了最終的協(xié)議驅(qū)動(dòng)時(shí),如果協(xié)議驅(qū)動(dòng)中,指定的套接字上(最重要的是端口和目的IP了)有相應(yīng)的數(shù)據(jù)的能滿足你的這一次的讀請(qǐng)求的話,就完成你的請(qǐng)求,如果不能的話,則阻塞了。當(dāng)下層有數(shù)據(jù)來(lái)的時(shí)候,數(shù)據(jù)傳遞到協(xié)議驅(qū)動(dòng)時(shí),協(xié)議驅(qū)動(dòng)會(huì)檢查包頭的信息并查看當(dāng)前不是有應(yīng)用程序打開(kāi)過(guò)相應(yīng)的端口,以及和對(duì)應(yīng)的目標(biāo)建立過(guò)連接,如果有的話,就把數(shù)據(jù)存到協(xié)議棧中的緩沖區(qū)中去,如果對(duì)應(yīng)套接字上有阻塞的接收請(qǐng)求的話,就判斷是不是能完成它的請(qǐng)求了,如果能了,就完成他,如果不能,繼續(xù)等以后下層傳上來(lái)再重復(fù)這個(gè)過(guò)程。否則就拋棄了,另外,如果,一個(gè)應(yīng)用程序建立一個(gè)套接字,并與一臺(tái)機(jī)器建立連接,對(duì)方發(fā)送了數(shù)據(jù),協(xié)議棧會(huì)把數(shù)據(jù)保存起來(lái),也許連接超時(shí)后,協(xié)議棧的緩沖區(qū)中還有應(yīng)用程序沒(méi)有接收的數(shù)據(jù)的話,也被拋棄了。所以,協(xié)議驅(qū)動(dòng)從來(lái)都沒(méi)有必要主動(dòng)往下傳遞一個(gè)接收數(shù)據(jù)的請(qǐng)求。這一點(diǎn),對(duì)于有一點(diǎn)網(wǎng)絡(luò)程序調(diào)試經(jīng)驗(yàn)的人來(lái)說(shuō),似乎可以直接找到一個(gè)的證據(jù),在調(diào)試器的調(diào)用WSARecv前下一個(gè)斷點(diǎn),用Sniffer抓包,可能數(shù)據(jù)已經(jīng)到來(lái)了,然后,再回到調(diào)試器中執(zhí)行WSARecv,可以看到收到的就是先前Sniffer下來(lái)的數(shù)據(jù)了。
(注:用一個(gè)工作在NDIS協(xié)議層或是NDIS中間層的Sniffer來(lái)觀查。)3.4NNDISS的數(shù)數(shù)據(jù)包結(jié)結(jié)構(gòu)。
發(fā)送NNDISSPrrotoocollDrriveer分配配相關(guān)的的包資源源,請(qǐng)求求NDIIS向下下傳遞發(fā)發(fā)送動(dòng)作作,接收收時(shí),NNDISSMiinipporttDrriveer分配配相關(guān)的的包資源源請(qǐng)求NNDISS向上傳傳遞接收收動(dòng)作,中中間層要要對(duì)包進(jìn)進(jìn)行處理理,首先先通過(guò)包包描述符符查詢出出這個(gè)包包中的所所有Buuffeer描述述符,然然后,從從每一個(gè)個(gè)Buffferr描述符符中取得得相應(yīng)的的數(shù)據(jù)。一一個(gè)包描描述符中中包含了了一個(gè)或或多個(gè)BBufffer描描述符,每每一個(gè)BBufffer描描述符中中包含了了這個(gè)BBufffer中中數(shù)據(jù)的的緩沖區(qū)區(qū)首地址址及其大大小等信信息,另另外,一一個(gè)包描描述符中中還包括括了一些些保留給給開(kāi)發(fā)者者自己使使用的RReseerveed字段段,其于于的一些些字段,并并沒(méi)有被被公開(kāi)。另另外NNDISS提供了了一些宏宏和一些些函數(shù)對(duì)對(duì)這相應(yīng)應(yīng)的描述述符進(jìn)行行操作。為為什么要要把這個(gè)個(gè)結(jié)構(gòu)弄弄得這么么復(fù)雜呢呢?這是是由于面面對(duì)分層層的協(xié)議議處理的的時(shí)候,避避免過(guò)多多的數(shù)據(jù)據(jù)考貝,比比如對(duì)于于TCPP/IPP協(xié)議來(lái)來(lái)說(shuō),上上層傳遞遞下來(lái)的的數(shù)據(jù),在在經(jīng)過(guò)TTCP,IIP層時(shí)時(shí),把TTCP,IIP協(xié)議議頭部那那個(gè)Buuffeer分別別加入這這個(gè)Paackeet來(lái)就就可以了了,如果果,要它它們?cè)谝灰粋€(gè)Buuffeer中,則則需要在在經(jīng)過(guò)TTCP層層時(shí),TTCP層層建立一一個(gè)新的的Buffferr,把頭頭部放到到這個(gè)BBufffer中中來(lái),并并把數(shù)據(jù)據(jù)考貝到到這個(gè)BBufffer中中來(lái);到到了IPP層還要要繼續(xù)這這一動(dòng)作作
四基基于PaassTThruu框架的的中間層層驅(qū)動(dòng)程程序的擴(kuò)擴(kuò)展實(shí)現(xiàn)現(xiàn)
Miicroosofft在DDDK中中附帶PPasssThrru提供供了一個(gè)個(gè)的中間間層驅(qū)動(dòng)動(dòng)框架,使使得開(kāi)發(fā)發(fā)者能夠夠相對(duì)容容易的在在這個(gè)基基礎(chǔ)實(shí)現(xiàn)現(xiàn)自己的的NDIIS中間間層驅(qū)動(dòng)動(dòng)擴(kuò)展。我我們將在在PasssThhru的的基礎(chǔ)上上實(shí)現(xiàn)一一個(gè)基本本的數(shù)據(jù)據(jù)包操作作的擴(kuò)展展。對(duì)于于發(fā)送出出去的數(shù)數(shù)據(jù)包處處理,只只要在PPasssThrru中的的MiinipporttSennd和MMiniiporrtSeendPPackketss中加入入必要的的操作代代碼,而而對(duì)于接接收的數(shù)數(shù)據(jù)包時(shí)時(shí),則需需要在ProotoccolRReceeivee和PrrotoocollRecceviiePaackeets中中加入必必要的操操作代碼碼,在這這里,我我將以wwinddowss20003DDKK的PaassTThruu為例,進(jìn)進(jìn)行擴(kuò)展展。
4..1發(fā)發(fā)送處理理
VOIDMPSSenddPaccketts(
INNNDDIS__HANNDLEEMiinipporttAdaapteerCoonteext,,
INNPPPNDIIS_PPACKKETPacckettArrray,,
INNUIINTNummberrOfPPackketss
){
///省略略代碼若若干,請(qǐng)請(qǐng)參看PPasssThrru的源源代碼。
//分配一個(gè)新的包描述符。
NdisAllocatePacket(&Status,&MyPacket,pAdapt->SendPacketPoolHandle);
if(Status==NDIS_STATUS_SUCCESS)
{
PSEND_RSVDSendRsvd;
SendRsvd=(PSEND_RSVD)(MyPacket->ProtocolReserved);
//把原來(lái)的包描述符保存在新分配的包描述符中的Reserved字段中,原因在后面描述。
SendRsvd->OriginalPkt=Packet;
}
//調(diào)用BuildMyPacket對(duì)包進(jìn)行自己的處理(更改包的內(nèi)容,或其它動(dòng)作)。
if(BuildMyPacket(pAdapt,Packet,MyPacket)==FALSE)
{
//如果處理失敗,則把原始的包信息Copy到MyPacket。
//這是為了在處理失敗的情況下,也讓原始的信息能發(fā)出去。
NDIS_PACKET_FIRST_NDIS_BUFFER(MyPacket)=NDIS_PACKET_FIRST_NDIS_BUFFER(Packet);
NDIS_PACKET_LAST_NDIS_BUFFER(MyPacket)=NDIS_PACKET_LAST_NDIS_BUFFER(Packet);
}
//
//請(qǐng)求NDIS向下層傳遞發(fā)送動(dòng)作。
NdisSend(&Status,pAdapt->BindingHandle,MyPacket);
//如果NdisSend返回非NDIS_STATUS_PENDING則釋放自己的資源。
if(Status!=NDIS_STATUS_PENDING)
{
DestroyMyPacket(MyPacket);
NdisFreePacket(MyPacket);
}
//
//如果NdisSend返回非NDIS_STATUS_PENDING,說(shuō)明下層已成功發(fā)送完成
//調(diào)用NdisMSendComplete請(qǐng)求NDIS通知上層釋放資源,這將導(dǎo)致上層注冊(cè)的
//ProtocolSendComplete被調(diào)用,上層在ProtocolSendComplete中釋放資源后
//將繼續(xù)調(diào)用NdisMSendComplete請(qǐng)求NDIS把這個(gè)通知往上傳遞。
if(Status!=NDIS_STATUS_PENDING)
{
NdisMSendComplete(ADAPT_MINIPORT_HANDLE(pAdapt),Packet,Status);
}
//如果返回了NDIS_STATUS_PENDING,則在該層的資源還不能釋放,在底層
//完成發(fā)送時(shí),底層將調(diào)用NdisMSendComplete,請(qǐng)求NDIS向上傳遞這個(gè)通知。
//該層在自己的ProtocolSendComplete釋放相應(yīng)的資源。
}
VOIDPtSendComplete(
INNDIS_HANDLEProtocolBindingContext,
INPNDIS_PACKETPacket,
INNDIS_STATUSStatus
){
//
//上面發(fā)送的時(shí)候,我們分配了一個(gè)新的包描述符,并把上層的包描述符保存在
//ProtocolReserved中,現(xiàn)在,把這個(gè)上層的包描述符還原出來(lái)。
PSEND_RSVDSendRsvd;
SendRsvd=(PSEND_RSVD)(Packet->ProtocolReserved);
Pkt=SendRsvd->OriginalPkt;
//
//釋放自己的資源
DestroyMyPacket(Packet);
NdisDprFreePacket(Packet);
//用上層的包描述符請(qǐng)求NDIS通知上層釋放資源
NdisMSendComplete(pAdapt->MiniportHandle,Pkt,Status);}
BOOLEANBuildMyPacket(
INPADAPTpAdapt,
INPNDIS_PACKEToriginal_packet,
OUTPNDIS_PACKETMyPacket
){
PSEND_RSVDSendRsvd;
NDIS_STATUSStatus;
NDIS_PHYSICAL_ADDRESSphyaddr={-1};
PVOIDpcontent=NULL;
ULONGtotal_length=0,current_length=0;
PNDIS_BUFFERMyBuffer;
//分配新的內(nèi)存
Status=NdisAllocateMemory((PVOID)&pcontent,2014,0,phyaddr);
if(NDIS_STATUS_SUCCESS!=Status)
returnFALSE;
NdisZeroMemory(pcontent,2014);
//把包中的數(shù)據(jù)Copy到自己的Buffer中來(lái)。
NdisQueryPacket(packet,NULL,NULL,&ndis_buffer,&total_length);
while(NULL!=ndis_buffer)
{
NdisQueryBufferSafe(ndis_buffer,&address,¤t_length,NormalPagePriority);
NdisMoveMemory(pcontent,address,current_length);
(PUCHAR)pcontent+=current_length;
NdisGetNextBuffer(ndis_buffer,&ndis_buffer);
}
//分配新的一個(gè)Buffer描述符
NdisAllocateBuffer(&Status,&MyBuffer,pAdapt->SendPacketPoolHandle,
pcontent,total_length);
if(NDIS_STATUS_SUCCESS!=Status)
{
NdisFreeMemory(pcontent,2014,0);
returnFALSE;
}
//在這里對(duì)包的內(nèi)容進(jìn)行你自己的處理,如果修改了
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024年膜分離制氮設(shè)備投資申請(qǐng)報(bào)告
- 2023年高品質(zhì)研磨碳酸鈣漿料投資申請(qǐng)報(bào)告
- 2024年混凝土攪拌機(jī)項(xiàng)目資金申請(qǐng)報(bào)告代可行性研究報(bào)告
- 第七章 環(huán)境規(guī)劃與管理的政策、法規(guī)、制度、標(biāo)準(zhǔn)和管理體系課件
- 大病救治自查報(bào)告
- 生物安全自查報(bào)告
- 2024年商鋪轉(zhuǎn)租協(xié)議范本
- 單位資金周轉(zhuǎn)借款協(xié)議范本2024
- 2024年度綜合經(jīng)濟(jì)服務(wù)協(xié)議模板
- 2024年個(gè)人借款協(xié)議范本協(xié)議
- 期中考試卷(試題)-2024-2025學(xué)年蘇教版二年級(jí)數(shù)學(xué)上冊(cè)
- 2024年全國(guó)企業(yè)員工全面質(zhì)量管理知識(shí)競(jìng)賽題庫(kù)(含答案)(共132題)
- 《國(guó)有企業(yè)采購(gòu)操作規(guī)范》【2023修訂版】
- 一年級(jí)上冊(cè)語(yǔ)文期中考試試卷分析
- 中藥知識(shí)文庫(kù):冬葵子
- [新版]高速公路交安工程監(jiān)理實(shí)施細(xì)則
- 品質(zhì)周報(bào)模板
- 壓力管道焊接工藝、工藝卡、規(guī)程及工藝評(píng)定
- 2021年河南省實(shí)施殯葬管理?xiàng)l例
- 對(duì)上好少先隊(duì)活動(dòng)課的五點(diǎn)建議
- 慢性病自我管理新ppt課件.ppt
評(píng)論
0/150
提交評(píng)論