網(wǎng)絡(luò)知識tcpip協(xié)議詳解卷二實現(xiàn)31_第1頁
網(wǎng)絡(luò)知識tcpip協(xié)議詳解卷二實現(xiàn)31_第2頁
網(wǎng)絡(luò)知識tcpip協(xié)議詳解卷二實現(xiàn)31_第3頁
網(wǎng)絡(luò)知識tcpip協(xié)議詳解卷二實現(xiàn)31_第4頁
網(wǎng)絡(luò)知識tcpip協(xié)議詳解卷二實現(xiàn)31_第5頁
已閱讀5頁,還剩13頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、 下載第31章BPF:BSD 分組過濾程序31.1引言 BSD分組過濾程序( BPF)是一種軟件設(shè)備,用于過濾網(wǎng)絡(luò)接口的數(shù)據(jù)流,即給網(wǎng)絡(luò)接口加上“開關(guān)”。應(yīng)用進程打開/dev/bpf0、/dev/bpf1等等后,可以讀取BPF設(shè)備。每個應(yīng)用進程一次只能打開一個BPF設(shè)備。 因為每個BPF設(shè)備需要8192字節(jié)的緩存,系統(tǒng)管理員一般限制 BPF設(shè)備的數(shù)目。如果open返回EBUSY,說明該設(shè)備已被使用,應(yīng)用進程應(yīng)該試著打開下一 BPF設(shè)備, 直到open成功為止。 通過若干ioctl命令,可以配置BPF設(shè)備,把它與某個網(wǎng)絡(luò)接口相關(guān)連,并安裝過濾程序,從而能夠選擇性地接收輸入的分組。 BPF設(shè)備打開

2、后,應(yīng)用進程通過讀寫設(shè)備來接收分組,或?qū)⒎纸M放入網(wǎng)絡(luò)接口隊列中。 我們將一直使用“分組”,盡管“幀”可能更準確一些,因為 BPF工作在數(shù)據(jù)鏈路層,在發(fā)送和接收的數(shù)據(jù)幀中包含了鏈路層的首部。 BPF設(shè)備工作的前提是網(wǎng)絡(luò)接口必須能夠支持 BPF。第3章中提到以太網(wǎng)、 SLIP和環(huán)回接口的驅(qū)動程序都調(diào)用了 bpfattach,用于配置讀取 BPF設(shè)備的接口。本節(jié)中,我們將介紹BPF設(shè)備驅(qū)動程序是如何組織的,以及數(shù)據(jù)分組在驅(qū)動程序和網(wǎng)絡(luò)接口之間是如何傳遞的。 BPF一般情況下用作診斷工具,查看某個本地網(wǎng)絡(luò)上的流量,卷 1附錄A 介紹的tcpdump 程序是此類工具中最好的一個。通常情況下,用戶感興趣的

3、是一組指定主機間交互的分組, 或者某個特定協(xié)議,甚至某個特定 TCP連接上的數(shù)據(jù)流。BPF設(shè)備經(jīng)過適當(dāng)配置,能夠根據(jù)過濾程序的定義丟棄或接受輸入的分組。過濾程序的定義類似于偽機器指令, BPF的細節(jié)超出了本書的討論范圍,感興趣的讀者請參閱 bpf(4)和McCanne and Jacobson 1993。 31.2代碼介紹 下面將要介紹的有關(guān)BPF設(shè)備驅(qū)動程序的代碼,包括兩個頭文件和一個 C文件,在圖31-1中給出。 圖31-1 本章討論的文件 31.2.1 全局變量 本章用到的全局變量在圖31-2中給出。 文 件 描 述 net/bpf.h net/bpfdesc.hBPF常量BPF結(jié)構(gòu) n

4、et/bpf.cBPF設(shè)備支持 822TCP/IP詳解 卷2:實現(xiàn) 下載圖31-2 本章用到的全局變量 31.2.2 統(tǒng)計量 圖31-3列出了bpf_d結(jié)構(gòu)中為每個活動的BPF設(shè)備維護的兩個統(tǒng)計量。 圖31-3 本章討論的統(tǒng)計值 本章的其余內(nèi)容分為4個部分: BPF 接口結(jié)構(gòu); BPF 設(shè)備描述符; BPF 輸入處理;和 BPF輸出處理。 31.3bpf_if結(jié)構(gòu) BPF維護一個鏈表,包括所有支持BPF的網(wǎng)絡(luò)接口。每個接口都由一個bpf_if結(jié)構(gòu)描述, 全局指針bpf_iflist指向表中的第一個結(jié)構(gòu)。圖31-4給出了BPF接口結(jié)構(gòu)。 圖31-4 bpf_if 結(jié)構(gòu)6 7 - 79bif_ne

5、xt指向鏈表中的下一個BPF接口結(jié)構(gòu)。bif_dlist指向另一個鏈表,包括 所有已打開并配置過的BPF設(shè)備。 7 0 如果某個網(wǎng)絡(luò)接口已配置了BPF設(shè)備,即被加上了開關(guān),則bif_driverp將指向ifnet 結(jié)構(gòu)中的bpf_if指針。如果網(wǎng)絡(luò)接口還未加上開關(guān), *bif_driverp為空。為某個網(wǎng)絡(luò)接口配置BPF設(shè)備時,*bif_driverp將指向bif_if結(jié)構(gòu),從而告訴接口可以開始向BPF傳遞分組。 7 1 接口類型保存在bif_dlt中。圖31-5中列出了前面提到的幾個接口所分別對應(yīng)的常量值。 bpf_d成員變量 描 述 bd_rcount bd_dcount從網(wǎng)絡(luò)接口接收的分

6、組的數(shù)目 由于緩存空間不足而丟棄的分組的數(shù)目 變 量 數(shù) 據(jù) 類 型 描 述 bpf_iflist bpf_dtab bpf_bufsizestruct bpf_if * struct bpf_d int支持BPF的接口組成的鏈表 BPF描述符數(shù)組 BPF緩存大小默認值 第31章 BPF:BSD分組過濾程序823 下載圖 31-5 bif_dlt 值 7 2 - 74BPF接受的所有分組都有一個附加的BPF首部。bif_hdrlen等于首部大小。最后, bif_ifp指向?qū)?yīng)接口的ifnet結(jié)構(gòu)。 圖31-6給出了每個輸入分組中附加的bpf_hdr結(jié)構(gòu)。 圖31-6 bpf_hdr 結(jié)構(gòu)1 2

7、 2 - 1 2 8 bh_ tstamp記錄了分組捉的時間。 bh_ caplen等于BPF保存的字節(jié)數(shù),bh_datalen等于原始分組中的字節(jié)數(shù)。 bh_headlen等于bpf_hdr的大小加上所需填充字節(jié)的長度。它用于解釋從BPF設(shè)備中讀取的分組,應(yīng)該等同于接收接口的 bif_hdrlen。 圖31-7給出了bpf_if結(jié)構(gòu)是如何與前述 3個接口(le_softc loif)的ifnet結(jié)構(gòu)建立連接的。 0、sl_softc0和圖31-7bpf_if 和ifnet 結(jié)構(gòu)注意,bif_driverp指向網(wǎng)絡(luò)接口的if_bpf和sc_bpf指針,而不是接口結(jié)構(gòu)。 SLIP設(shè)備使用sc_b

8、pf,而不是if_bpf。這可能是因為SLIP BPF 代碼完成時, bif_dlt描述 DLT _ EN 1 0 MB D L T _ S L I PDL T_ NUL L10 Mb以太網(wǎng)接口SLIP接口 環(huán)回接口 824TCP/IP詳解 卷2:實現(xiàn) 下載if_bpf成員變量還未加入到ifnet結(jié)構(gòu)中。Net/2中的ifnet結(jié)構(gòu)不包括if_bpf成員。 按照各接口驅(qū)動程序調(diào)用 bpfattach時給出的信息,對 3個接口初始化鏈路類型和首部長度成員變量。 第3章介紹了bpfattach被以太網(wǎng)、SLIP和環(huán)回接口的驅(qū)動程序調(diào)用。每個設(shè)備驅(qū)動程序初始化調(diào)用bpfattach時,將構(gòu)建BPF接

9、口結(jié)構(gòu)鏈表。圖31-8給出了該函數(shù)。 圖31-8 bpfattach 函數(shù)1 0 5 3 - 1 0 6 3 每個支持BPF的設(shè)備驅(qū)動程序都將調(diào)用 bpfattach。第一個參數(shù)是保存在bif_driverp的指針(圖31-4給出),第二個參數(shù)指向接口的ifnet結(jié)構(gòu),第三個參數(shù)確認數(shù)據(jù)鏈路層類型,第四個參數(shù)傳遞分組中的數(shù)據(jù)鏈路首部大小,為接口分配一個新的 bpf_if結(jié)構(gòu)。 1. 初始化bpf_if結(jié)構(gòu) 第31章 BPF:BSD分組過濾程序825 下載1 0 6 4 - 1 0 7 0bpf_ if結(jié)構(gòu)根據(jù)函數(shù)的參數(shù)進行初始化,并插入到B P F接口鏈表,bpf_iflist,的表頭。 2.

10、 計算BPF首部大小 1 0 7 1 - 1 0 7 7設(shè)定bif_hdrlen大小,強迫網(wǎng)絡(luò)層首部 (如IP首部)從一個長字的邊界開始。這樣可以提高性能,避免為 BPF加入不必要的對齊限制。圖 31-9列出了在前述3個接口上,各自捕捉到的BPF分組的總體結(jié)構(gòu)。 18字節(jié) 填充18字節(jié) 2字節(jié) 16字節(jié) 填充 環(huán)回偽鏈路首部 18字節(jié)2字節(jié)4字節(jié)圖31-9 BPF分組結(jié)構(gòu) ether_header結(jié)構(gòu)在圖4-10中給出, SLIP偽鏈路首部在圖5-14中給出,而環(huán)回接口偽鏈路首部在圖5-28中給出。 請注意, SLIP和環(huán)回接口分組需要填充2字節(jié),以強迫IP首部按4字節(jié)對齊。 3. 初始化bp

11、f_dtab表 1 0 7 8 - 1 0 8 3代碼初始化圖 3 1 - 1 0 中給出的 B P F描述符表。注意,僅在第一次調(diào)用 bpfattach時進行初始化,后續(xù)調(diào)用將跳過初始化過程。 4. 打印控制臺信息 1 0 8 4 - 1 0 8 5 系統(tǒng)向控制臺輸出一條短信息,宣告接口已配置完畢,可以支持 BPF。31.4bpf_d結(jié)構(gòu) 為了能夠選擇性地接收輸入報文,應(yīng)用進程首先打開一個 BPF設(shè)備,調(diào)用若干ictl命令規(guī)定BPF過濾程序的條件,指明接口、讀緩存大小和超時時限。每個 BPF設(shè)備都有一個相關(guān)的bpf_d結(jié)構(gòu),如圖31-10所示。 4 5 - 4 6如果同一網(wǎng)絡(luò)接口上配置了多個

12、BPF設(shè)備,與之相應(yīng)的bpf_d結(jié)構(gòu)將組成一個鏈表。 bd_next指向鏈表中的下一個結(jié)構(gòu)。 分組緩存 4 7 - 5 2每個bpf_d結(jié)構(gòu)都有兩個分組緩存。輸入分組通常保存在 bd_sbuf所對應(yīng)的緩存(存儲緩存)中。另一個緩存要么對應(yīng)于 bd_ fbuf( 空閑緩存 ),意味著緩存為空;或者對應(yīng)于bd_hbuf(暫留緩存),意味著緩存中有分組等待應(yīng)用進程讀取。 bd_slen和bd_hlen分別記 IP分組 IP分組 14字節(jié)IP分組 826TCP/IP詳解 卷2:實現(xiàn) 錄了保存在存儲緩存和暫留緩存中的字節(jié)數(shù)。 下載圖31-10 bpf_d結(jié)構(gòu)如果存儲緩存已滿,它將被連接到 bd_hbuf

13、,而空閑緩存將被連接到bd_sbuf。當(dāng)暫留緩存清空時,它會被連接到 bd_ fbuf 。宏ROT ATE_ BUFFERS負責(zé)把存儲緩存連接到bd_hbuf,空閑緩存連接到bd_sbuf,并清空bd_fbuf。存儲緩存滿或者應(yīng)用進程不想再等待更多的分組時調(diào)用該宏。 bd_bufsize記錄與設(shè)備相連的兩個緩存的大小,其默認值等于 4096(BPF_BUFSIZE)字節(jié)。修改內(nèi)核代碼可以改變默認值大小,或者通過 B I O C S B L E Nioc t l命令改變某個特定 BPF設(shè)備的bd_bufsize。BIOCGBLEN命令返回bd_bufsize的當(dāng)前值,其最大值不超過32768 (

14、BPF_MAXBUFSIZE)字節(jié),最小值為32 ( BPF_MINBUFSIZE)字節(jié)。 5 3 - 5 7bd_ bif指向BPF設(shè)備所對應(yīng)的 bpf_ if 結(jié)構(gòu)。 BIOCSETIF命令可指明設(shè)備。bd_rtout是等待分組時,延遲的滴答數(shù)。 bd_filter指向BPF設(shè)備的過濾程序代碼。兩個統(tǒng)計值,應(yīng)用進程可通過 BIOCGSTATS命令讀取,分別保存在 bd_ rcount和bd_ dcount中。 5 8 - 6 3bd_ promisc 通 過 BIOCPROMISC 命 令 置 位 , 從 而 使 接 口 工 作 在 混 雜 (promiscuous)狀態(tài)。bd_state

15、未使用。bd_immediate通過BIOCIMMEDIATE命令置位, 促使驅(qū)動程序收到分組后即返回,不再等待暫留緩存填滿。 bd_pad填棄bpf_d結(jié)構(gòu),從而與長字邊界對齊。bd_sel保存的selinfo結(jié)構(gòu),可用于select系統(tǒng)調(diào)用。我們不準備介紹如何對BPF設(shè)備使用select系統(tǒng)調(diào)用, 16.13節(jié)已介紹了select的一般用法。 31.4.1 bpfopen函數(shù) 應(yīng)用進程調(diào)用open,試圖打開一個BPF設(shè)備時,該調(diào)用將被轉(zhuǎn)到bpfopen(圖31-11)。 2 5 6 - 2 6 3系統(tǒng)編譯時, BPF設(shè)備的數(shù)目受到NBPFILTER的限制。如果設(shè)備的最小設(shè)備號大 第31章

16、BPF:BSD分組過濾程序827 下載于N B P F I L T E R ,則返回 E N X I O ,這是因為系統(tǒng)管理員創(chuàng)建的/ d e v / b p f x 項數(shù)大于NBPFILTER的值。 圖31-11 bpfopen 函數(shù)分配bpf_d結(jié)構(gòu) 2 6 4 - 2 7 5同一時間內(nèi),一個應(yīng)用進程只能訪問一個 BPF設(shè)備。如果bpf_d結(jié)構(gòu)已被激活, 則返回EBUSY。應(yīng)用程序,如tcpdump,收到此返回值時,會自動尋找下一個設(shè)備。如果該 設(shè)備已存在,最小設(shè)備號所指定的bpf_dtab表中的項被清除,分組緩存大小復(fù)位為默認值。 31.4.2 bpfioctl函數(shù) 設(shè)備打開后,可通過i

17、octl命令進行配置。圖31-12總結(jié)了與BPF設(shè)備有關(guān)的ioctl命令。圖31-13給出了bpfioctl函數(shù),只列出BIOCSETF和BIOCSETIF的處理代碼,其他未涉及到的ioctl命令則被忽略。 圖31-12 BPF ioctl 命令 命 令 第三個參數(shù) 函 數(shù) 描 述 F I ONREAD B I OCGBLEN B I OC S BL EN B I O C S E T F B I OCFLUS HB I OCPROM I SC B I OCGD L TB I OCGET I F B I OC S ET I FB I OCS RT I MEOUT BI OCGRT I MEOUT

18、 B I OC G S T A T SB I OC I MMED I ATE B I OCVER S I O Nu_int u_int u_intstruct bpf_programu_intstruct ifreq struct ifreq struct timeval struct timeval struct bpf_stat u_intstruct bpf_ versionbpfioctl bpfioctl bpfioctl bpf_setf reset_d ifpromisc bpfioctl bpf_ifname bpf_setif bpfioctl bpfioctl bpfioc

19、tl bpfioctl bpfioctl返回暫留緩存和存儲緩存中的字節(jié)數(shù)返回分組緩存大小 設(shè)定分組緩存大小安PF程序 丟棄掛起分組設(shè)定混雜方式返回bif_dlt返回所屬接口的名稱為網(wǎng)絡(luò)接口添加設(shè)備 設(shè)定“讀”操作的超時時限返回“讀”操作的超時時限返回BPF統(tǒng)計值 設(shè)定立即方式 返回BPF版本信息 828TCP/IP詳解 卷2:實現(xiàn) 下載圖31-13 bpfioctl 函數(shù)5 0 1 - 5 0 9 與bpfopen類似,通過最小設(shè)備號從bpf_dtab表中選取相應(yīng)的bpf_d結(jié)構(gòu)。整個命令處理是一個大的switch/case語句。我們給出了兩個命令,BIOCSETF和BIOCSETIF,以及d

20、efault子句。 5 1 0 - 5 2 2 bpf_setf函數(shù)安裝由addr指向的過濾程序, bpf_setif建立起指定名稱接口與bpf_d結(jié)構(gòu)間的對應(yīng)關(guān)系。本書中沒有給出bpf_setf的實現(xiàn)代碼。 6 6 8 - 6 7 3 如果命令未知,則返回EINVAL。 圖31-14的例子中, bpf_setif已把bpf_d結(jié)構(gòu)連接到LANCE接口上。 圖中,bif_dlist指向bpf_dtab0,以太網(wǎng)接口描述符鏈表中的第一個也是僅有的一個描述符。在bpf_dtab0中,bd_sbuf和bd_hbuf成員分別指向存儲緩存和暫留緩存。兩個緩存大小都等于4096(bd_bufsize)字節(jié)

21、。bd_bif回指接口的bpf_if結(jié)構(gòu)。 ifnet結(jié)構(gòu)(le_softc0)中的if_bpf也指回bpf_if結(jié)構(gòu)。如圖4-19和圖4-11所示, 如果if_bpf非空,則驅(qū)動程序開始調(diào)用bpf_tap,向BPF設(shè)備傳遞分組。 圖31-15接著圖31-10,給出了打開第二個BPF設(shè)備,并連接到同一個以太網(wǎng)網(wǎng)絡(luò)接口后的 各結(jié)構(gòu)變量的狀態(tài)。 第31章 BPF:BSD分組過濾程序829 下載到其他bpf_if結(jié)構(gòu) 存儲緩存空閑緩存圖31-14連接到以太網(wǎng)接口的BPF設(shè)備 存儲緩存空閑緩存存儲緩存空閑緩存圖31-15 連接到以太網(wǎng)接口的兩個BPF設(shè)備 bpf_dtab2至bpf_dtabNBPFI

22、LTER-1到其他bpf_if結(jié)構(gòu) bpf_dtab2至bpf_dtabNBPFILTER-1 830TCP/IP詳解 卷2:實現(xiàn) 下載第二個 B P F 設(shè)備打開時,在 b p f _ d t a b 表中分配一個新的 b p f _ d 結(jié)構(gòu),本例中為b p f _ d t a b 1 。因為第二個 BPF設(shè)備也連接到同一個以太網(wǎng)接口, b i f _ d l i s t 指向bpf_dtab1,并且bpf_dtab1.bd_next指向bpf_dtab0,即以太網(wǎng)上對應(yīng)的第一個BPF描述符。系統(tǒng)為新的描述符結(jié)構(gòu)分別分配存儲緩存和暫留緩存。 31.4.3 bpf_setif函數(shù) bpf_s

23、etif函數(shù),負責(zé)建立BPF描述符與網(wǎng)絡(luò)接口間的連接,如圖 31-16所示。 圖31-16 bpf_setif 函數(shù) 第31章 BPF:BSD分組過濾程序831 下載圖31-16 (續(xù))7 2 1 - 7 4 6 bpf_setif的第一部分完成ifreq結(jié)構(gòu)(圖4-23)中接口名的正文與數(shù)字部分的分離,數(shù)字部分保存在unit中。例如,如果ifr_name的頭4字節(jié)為“ sl10”,代碼執(zhí)行完畢后,將等于“ sl00”,且unit等于1。 1. 尋找匹配的ifnet結(jié)構(gòu) 7 4 7 - 7 5 4 for循環(huán)用于在支持BPF的接口(bpf_iflist中)中查找符合ifreq定義的接口。 7

24、5 5 - 7 6 8 如果未找到匹配的接口,則返回ENETDOWN。如果接口存在, bpf_allocate為bpf_d分配空閑緩存和存儲緩存,如果它們還未被分配的話。 2. 連接bpf_d結(jié)構(gòu) 7 6 9 - 7 7 7 如果BPF設(shè)備還未與網(wǎng)絡(luò)接口建立連接關(guān)系,或者連接的網(wǎng)絡(luò)接口不是 ifreq中指定的接口,則調(diào)用bpf_detachd丟棄原先的接口(如果存在),并調(diào)用bpf_attachd將其連接到新的接口上。 7 7 8 - 7 8 4 reset_d復(fù)位分組緩存,丟棄所有在應(yīng)用進程中等待的分組。函數(shù)返回 0,說明處理成功;或者ENXIO,說明未找到指定接口。 31.4.4 bpf_

25、attachd函數(shù) 圖31-17給出的bpf_attachd函數(shù),建立起B(yǎng)PF描述符與BPF設(shè)備和網(wǎng)絡(luò)接口間的對應(yīng)關(guān)系。圖 31-17 bpf_attachd 函 數(shù) 832TCP/IP詳解 卷2:實現(xiàn) 下載圖31-17 (續(xù))1 8 9 - 2 0 3 首先,令bd_bif指向網(wǎng)絡(luò)接口的BPF接口結(jié)構(gòu)。接著, bpf_d結(jié)構(gòu)入到與設(shè)備對應(yīng)的bpf_d結(jié)構(gòu)鏈表的頭部。最后,改變網(wǎng)絡(luò)接口中的 BPF指針,指向當(dāng)前BPF結(jié)構(gòu),從而促使接口向BPF設(shè)備傳遞分組。 31.5BPF的輸入 一旦BPF設(shè)備打開并配置完畢,應(yīng)用進程就通過 read系統(tǒng)調(diào)用從接口中接收分組。 BPF過濾程序復(fù)制輸入分組,因此,

26、不會干擾正常的網(wǎng)絡(luò)處理。輸入分組保存在與 BPF設(shè)備相連的存儲緩存和暫留緩存中。 31.5.1 bpf_tap函數(shù) 下面列出了圖 4-11中LANCE設(shè)備驅(qū)動程序調(diào)用 bpf_ tap的代碼,并利用這一調(diào)用介紹bpf_tap函數(shù)。圖4-11中的調(diào)用如下: bpf_tap(le-sc_if.if_bpf, buf, len + sizeof(struct ether_header);圖31-18給出了bpf_tap函數(shù)。 圖31-18 bpf_tap 函數(shù) 第31章 BPF:BSD分組過濾程序833 下載8 6 9 - 8 8 2 第一個參數(shù)是指向bpf_if結(jié)構(gòu)的指針,由bpfattach設(shè)定

27、。第二個參數(shù)是指向進入分組的指針,包括以太網(wǎng)首部。第三個參數(shù)等于緩存中包含的字節(jié)數(shù),本例中,等于以太網(wǎng)首部(14字節(jié))大小加上以太網(wǎng)幀的數(shù)據(jù)部分。 向一個或多個BPF設(shè)備傳遞分組 8 8 3 - 8 9 0for循環(huán)遍歷連接到網(wǎng)絡(luò)接口的 BPF設(shè)備鏈表。對每個設(shè)備,分組被遞交給bpf_filter。如果過濾程序接受了分組,它返回捕捉到的字節(jié)數(shù),并調(diào)用 catchpacket 復(fù)制分組。如果過濾程序拒絕了分組, slen等于0,循環(huán)繼續(xù)。循環(huán)終止時, bpf_tap返回。這一機制確保了同一網(wǎng)絡(luò)接口上對應(yīng)了多個 BPF設(shè)備時,每個設(shè)備都能擁有一個獨立的過濾程序。 環(huán)回驅(qū)動程序調(diào)用bpf_mtap,

28、向BPF傳遞分組。這個函數(shù)與 bpf_tap類似,然而是在 mbuf鏈,而不是在一個內(nèi)存的連續(xù)區(qū)域中復(fù)制分組。本書中不介紹這個函數(shù)。 31.5.2 catchpacket函數(shù) 圖31-18中,過濾程序接受了分組后,將調(diào)用catchpacket,圖31-19給出了這個函數(shù)。 圖 31-19 catchpacket 函 數(shù) 834TCP/IP詳解 卷2:實現(xiàn) 下載圖31-19 (續(xù))9 4 6 - 9 5 5catchpacket的參數(shù)包括: d,指向BPF設(shè)備結(jié)構(gòu)的指針; pkt,指向進入分組的通用指針; pktlen,分組被接收時的長度; snaplen,從分組中保存下來的字節(jié)數(shù); cpfn,

29、函數(shù)指針,把分組從 pkt中復(fù)制到一塊連續(xù)內(nèi)存中。如果分組已經(jīng)保存連續(xù)內(nèi)存中, 則cptn等于bcopy。如果分組被保存在mbuf中(pkt指向mbuf鏈表中的第一個mbuf,如環(huán)回 驅(qū)動程序),則cptn等于bpf_mcopy。 9 5 6 - 9 6 4 除了鏈路層首部和分組, catchpacket為每個分組添加bpf_hdr。從分組中保存的字節(jié)數(shù)等于snaplen和pktlen中較小的一個。處理過的分組和 bpf_hdr必須能放入分組緩存中(bd_bufsize字節(jié))。 1. 分組能否放入緩存 9 6 5 - 9 8 5 curlen等于存儲緩存中已有的字節(jié)數(shù)加上所需的填充字節(jié),以保證

30、下一分組能從長字邊界處開始存放。如果進入分組無法放入剩余的緩存空間,說明存儲緩存已滿。如果空閑緩存不可用(如應(yīng)用進程正從暫留緩存中讀取數(shù)據(jù)),則進入分組被丟棄。如是空閑緩存可用,則調(diào)用ROTATE_BUFFERS宏輪轉(zhuǎn)緩存,并通過bpf_wakeup喚醒所有等待輸入數(shù)據(jù)的應(yīng)用進程。 2. 立即方式處理 9 8 6 - 9 9 1 如果設(shè)備處于立即方式,則喚醒所有等待進程以處理進入分組內(nèi)核中沒有分組的緩存。 3. 添加BPF 首部 9 9 2 - 1 0 0 4 當(dāng)前時間(microtime)、分組長度和首部長度均保存在bpf_hdr中。調(diào)用cptf 所指的函數(shù),把分組復(fù)制到存儲緩存,并更新存儲

31、緩存的長度。因為在把分組從設(shè)備緩存?zhèn)魉偷侥硞€mbuf鏈表之前, bpf_tab已由leread直接調(diào)用,接收時間戳近似等于實際的接收 第31章 BPF:BSD分組過濾程序835 下載時間。 31.5.3 bpfread函數(shù) 內(nèi)核把針對BPF設(shè)備的read轉(zhuǎn)交給bpfread處理。通過BIOCSRTIMEOUT命令, BPF支持限時讀取。這個“特性”也可通過 select系統(tǒng)調(diào)用來實現(xiàn),但至少 tcpdump還是采用了BIOCSRTIMEOUT,而非select。應(yīng)用進程提供一個讀緩存,能夠與設(shè)備的暫留緩存大小相匹配。BICOGBLEN命令返回緩存大小。一般情況下,讀操作在存儲緩存已滿時返回。內(nèi)

32、核輪轉(zhuǎn)緩存,把存儲緩存轉(zhuǎn)給暫留緩存,后者在read系統(tǒng)調(diào)用時被復(fù)制到應(yīng)用進程提供的讀緩存, 同時BPF設(shè)備繼續(xù)向存儲緩存中存放進入分組。圖 31-20給出了bpfread。 圖31-20 bpfread 函數(shù) 836TCP/IP詳解 卷2:實現(xiàn) 下載圖31-20 (續(xù))3 4 4 - 3 5 7 通過最小設(shè)備號在bpf_dtab中尋找相應(yīng)的BPF設(shè)備。如果讀緩存不能匹配BPF設(shè)備緩存的大小,則返回EINVAL。 1. 等待數(shù)據(jù) 3 5 8 - 3 6 4 因為多個應(yīng)用進程能夠從同一個 BPF設(shè)備中讀取數(shù)據(jù),如果有某個進程已先讀取了數(shù)據(jù), while循環(huán)將強迫讀操作繼續(xù)。如果暫留緩存中存在數(shù)據(jù),

33、循環(huán)被跳過。這與兩個應(yīng)用進程通過兩個不同的BPF設(shè)備過濾同一個網(wǎng)絡(luò)接口的情況(見習(xí)題31.2)是不同的。 2. 立即方式 3 6 5 - 3 7 3 如果設(shè)備處于立即方式,且存儲緩存中有數(shù)據(jù),則3. 無可用的分組 緩存, while循環(huán)被終止。 3 7 4 - 3 8 4 如果設(shè)備不處于立即方式,或者存儲緩存中沒有數(shù)據(jù),則應(yīng)用進程進入休眠狀態(tài), 直到某個信號到達,讀定時器超時,或者有數(shù)據(jù)到達暫留緩存。如果有信號到達,則返回EINTR 或ERESTART。 記住,應(yīng)用進程不會見到 ERESTART,因為syscall函數(shù)將處理這一錯誤,且不會向應(yīng)用進程返回這一錯誤。 4. 查看暫留緩存 第31章

34、 BPF:BSD分組過濾程序837 下載3 8 5 - 3 9 1 如果定時器超時,且暫留緩存中存在數(shù)據(jù),則循環(huán)終止。 5. 查看存儲緩存 3 9 2 - 3 9 9 如果定時器超時,且存儲緩存中沒有數(shù)據(jù),則 read返回0。應(yīng)用進程執(zhí)行限時讀取時,必須考慮到這種情況。如果定時器超時,且存儲緩存中存在數(shù)據(jù),則把存儲緩存轉(zhuǎn)給暫留緩存,循環(huán)終止。 如果tsleep返回正常且存在數(shù)據(jù),同時while循環(huán)測試失敗,則循環(huán)終止。 6. 分組可用 4 0 0 - 4 1 6 循環(huán)終止時,暫留緩存中已有數(shù)據(jù)。uiomove從暫留緩存中移出bd_hlen個字節(jié), 交給應(yīng)用進程。把暫留緩存轉(zhuǎn)給空閑緩存,清除緩存計數(shù)器,

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論