裡介紹如何從建立資料到最後傳送資料的乙個過程。
首先要做準你要傳送的資料,注意你的資料大小至少要不少於64byte。我們這裡設定資料報的大小為80byte.裡面的內容包含乙個14byte的ethernet header,其他空位用無用資料填充。下面是具體流程:
一、建立緩衝區----用於儲存自定義的資料
pwritebuf = (puchar)ndisallocatememorywithtagpriority(pfilter->filterhandle,buffersize,filter_alloc_tag, lowpoolpriority);
其中buffersize等於80(比這個大也可以!根據需要。)
二、封裝自定義資料
因為ethernet header是乙個struct結構,定義如下:
typedef struct _testprov_eth_header
testprov_eth_header;
所以我們要把這些成員變數都賦值。首先申明乙個testprov_eth_header的乙個指標變數,然後指向pwritebuf所指的那塊記憶體:
pethheader = (ptestprov_eth_header)pwritebuf;
然後開始給testprov_eth_header中的每個成員函式賦值,其中ethtype= 0x8e88.
三、建立mdl
由於我們最終要把自定義的資料封裝成nbl,然後傳送出去。如果了解nbl結構,知道nbl由乙個或者多個nb構成,每個nb又由乙個或者多個mdl構成。所以這裡我們先分配乙個mdl,用來儲存自定義的資料。
pmdl = ndisallocatemdl(pfilter->filterhandle,
pethframenew,
buffersize);
pethframenew = (puchar)ndisallocatememorywithtagpriority(pfilter->filterhandle,buffersize,filter_alloc_tag, lowpoolpriority);
四、拷貝資料到mdl,並且釋放pwritebuf
如果你的mdl建立成功之後,mdl中是沒有內容的,需要把之前自定義在pwritebuf中的資料拷貝到mdl中:
ndismovememory(pethframenew,pethheader, buffersize);
之後釋放pwritebuf(勿忘)
ndisfreememory(pwritebuf,buffersize,0);
五、建立nbl
在建立nbl之前,有一件很重要的工作,那就是要分配好netbufferlistspool.因為之後所有從filter建立的nbl都要建立在這個pool之上。從方便和多次利用考慮,我們把pool分配工作在filterattach中完成:
ndiszeromemory(&poolparameters, sizeof(net_buffer_list_pool_parameters));
poolparameters.header.type = ndis_object_type_default;
poolparameters.header.revision = net_buffer_list_pool_parameters_revision_1;
poolparameters.header.size = sizeof(poolparameters);
poolparameters.protocolid = ndis_protocol_id_default ;
poolparameters.contextsize = sizeof(filter_send_netbuflist_rsvd);
poolparameters.fallocatenetbuffer = true;
poolparameters.pooltag = filter_alloc_tag;
pfilter->sendnetbufferlistpool = ndisallocatenetbufferlistpool(
ndisfilterhandle,
&poolparameters);
需要注意的是,ndis為每個filter module instance 各自分配乙個pool. 還有sizeof(filter_send_netbuffer_rsvd)的值必須為8的整數倍(0亦可)
這裡我們採用函式ndisallocatenetbufferandnetbufferlist()來建立nbl,因為它不需要事先建立nb就可以直接跳過這一步建立nbl,有興趣可以參考ndisallocatenetbufferlist().需要的引數為之前建立的pool,以及預分配的mdl等。
pnetbufferlist = ndisallocatenetbufferandnetbufferlist(
pfilter->sendnetbufferlistpool,
sizeof(filter_send_netbuflist_rsvd),
0, // back fill size
pmdl,
0, // data offset
buffersize);
注意:如果沒有成功建立nbl,需要釋放mdl.免得記憶體洩露。
六、傳送nbl
傳送之前需要制定nbl的sourcehandle,為了後面處理需要,以辨別是自己定義的資料。其次制定傳送的dispatch_level.
pnetbufferlist->sourcehandle = pfilter->filterhandle;
//ndis_mdl_linkage(pmdl) = null;
sendflags = ndis_send_flags_dispatch_level;
ndisfsendnetbufferlists(
pfilter->filterhandle,
pnetbufferlist,
ndis_default_port_number,
sendflags);
七、處理ndisfsengnetbufferlistcomplete
這裡需要注意:如果不是你自己傳送的資料,需要通知protocol層,該資料已經提交給底層了。如果是自己的建立和傳送的,需要額外處理,銷毀證據,因為上層protocol沒有讓filter傳送該資料,如果也通知傳送完畢就會出事,最顯而易見的就是blue screen. 所以你要做的:
1. 判斷是否是自己傳送的資料:
if(netbufferlists->sourcehandle == pfilter->filterhandle){}
2. 如果是,銷毀自定義資料
pmdl = net_buffer_first_mdl(net_buffer_list_first_nb(netbufferlists));
filter_assert(pmdl != null);
ndisquerymdl(
pmdl,
(pvoid *)&pcopydata,
&bufferlength,
normalpagepriority);
filter_assert(pcopydata != null);
filter_deref_send_nbl(netbufferlists, dispatchlevel);
ndisfreemdl(pmdl);
pcopydata = null;
3. 如果不是,呼叫ndisfsendnetbufferlistscomplete()通知上層驅動
ndisfsendnetbufferlistscomplete(pfilter->filterhandle, netbufferlists, sendcompleteflags);
到這裡,該資料報傳送完畢!
八、解除安裝釋放pool
這裡是題外話:你在filterattach分配的pool,你需要在filterdetach時釋放:
if(pfilter->sendnetbufferlistpool !=null)
不要擔心,各自的filter module instance都會各自釋放自己的pool.
九、整理暫時結束
一路風塵 整理
7 2自定義開發Filter
custom filters iauthorizationfilter iactionfilter iresultfilter iexceptionfilter actionfilterattribute類 actionfilterattribute public virtual void onac...
Shiro實現自定義filter
當使用者訪問匹配規則的url時觸發的過濾器,通常我們都繼承如下幾個類並重寫方法完成自定義過濾器 概述 這個類是遊客訪問即無需登入訪問的資源時進入的過濾器 概述 該方法如果返回true則可以訪問,返回false則不能訪問 引數request 關於這個請求的請求物件 引數response 關於這個請求的...
django 自定義tag和filter
首先,在polls目錄下建立templatetags目錄,結構如下 polls init py models.py templatetags init py 包含了 init py的才會被django認作是資料夾 polls extras.py views.py 在模板中使用標籤時要 現在可以在po...