海闊天空

          I'm on my way!
          隨筆 - 17, 文章 - 69, 評(píng)論 - 21, 引用 - 0
          數(shù)據(jù)加載中……

          libpcap的淺析

          libpcap體現(xiàn)的不是捕捉技術(shù)上的難點(diǎn),而是對(duì)細(xì)節(jié)的控制上,對(duì)跨平臺(tái)代碼的編寫上,對(duì)過濾機(jī)制的優(yōu)化上。
          大象的命門是在腳筋,也就是支撐的地方。 很顯然,得先對(duì)接口的流動(dòng)和他的數(shù)據(jù)結(jié)構(gòu)有個(gè)了解。而且在這套庫里面看到了好多人的代碼和自己的功能說明,感覺著一種合作開放的精神。
          剪枝刪節(jié),將其中l(wèi)inux部分提了出來,涉及到的文件大概有:
              inet.c  fad-getad.c pcap-linux.c pcap-int.h pcap.c
          整個(gè)的大概結(jié)構(gòu)是,查找設(shè)備,確定設(shè)備,過濾條件的嵌入,套接字的創(chuàng)建,網(wǎng)卡的設(shè)置,包的捕獲。

             
              查找設(shè)備:用到的函數(shù)有pcap_lookupdev()-pcap_findalldevs()-getifaddrs()-add_addr_to_iflist()//inet.c fad_getad.c
          該函數(shù)是將所找到的設(shè)備信息用連表連接起來,設(shè)備號(hào)小的在前,因此通常是eth0.
          數(shù)據(jù)結(jié)構(gòu)為struct pcap_if{},//pcap.h


              打開網(wǎng)絡(luò)設(shè)備:2。0以后的linux內(nèi)核版本用新的協(xié)議簇PF_PACKET來實(shí)現(xiàn)。早期是(SOCK_PACKET)他的形式可以是SOCK_RAW和SOCK_DGRAM。RAW是原始數(shù)據(jù),DGRAM是對(duì)數(shù)據(jù)包進(jìn)行加工,把數(shù)據(jù)包的鏈路層頭部去掉,使用sockaddr_ll來保存。在兩種情況下RAW不可用:某些類型設(shè)備數(shù)據(jù)鏈路層頭部不可用,當(dāng)捕捉為any時(shí),為了是包過濾機(jī)制在所有類型數(shù)據(jù)包上正常工作,要求所有數(shù)據(jù)使用相同數(shù)據(jù)鏈路頭部。
              pcap-linux.c
              pcap_open_live();用到的數(shù)據(jù)結(jié)構(gòu)是pcap_t,//pcap-int.h,這是一個(gè)比較重要的參數(shù),主要包括對(duì)socket的描述,和一些底層上的設(shè)置。比如緩沖區(qū)大小,設(shè)備類型,邊界對(duì)齊等,對(duì)應(yīng)的函數(shù)指針,可更改的鏈路數(shù),BPF過濾代碼是否能使用等。
             pcap_stat stat;//pcap.h,捕捉狀態(tài)結(jié)構(gòu),包括是否過濾,接受包的數(shù)目,丟棄的數(shù)目等。
             在函數(shù)內(nèi)部有new和old兩種版本,分別對(duì)2.0前后的版本創(chuàng)建socket.而在其內(nèi)部的選擇上,又涉及到對(duì)是否支持鏈路層頭部結(jié)構(gòu)的判斷,最后將網(wǎng)卡設(shè)為混雜模式,創(chuàng)建socket
             在這一層中,libpcap提供的用戶程序接口是pcap_next()//pcap.c,通過跟蹤可發(fā)現(xiàn),它最后是調(diào)用pcap_read_packet//pcap-linux.c接收。接收完后做的工作如下:偏移量設(shè)置,為了給偽數(shù)據(jù)鏈路層留出空間,接著要修正長度,判斷是否有用內(nèi)核級(jí)的包過濾,最后填充捕獲時(shí)間/長度/時(shí)間,對(duì)包數(shù)據(jù)累加。

             完成以上兩個(gè)步驟,發(fā)現(xiàn)最關(guān)鍵兩個(gè)步驟就是找設(shè)備的函數(shù),和socket的創(chuàng)建。但是通過查看源代碼可知,作者在跨平臺(tái),細(xì)節(jié)處理,包通用的完善性上做了很多很多的工作,這無一不給我們提供了一個(gè)很好的學(xué)習(xí)尺度。

             接下來是對(duì)過濾機(jī)制的描述:
          這個(gè)我想是最有難點(diǎn)的地方了,一些算法不做描述,查看pcap-bpf.h,gencode.c,optimize.c,grammar,c,scanner.c
          用到的特性有這么幾個(gè):因?yàn)樵诓蹲綍r(shí),是先經(jīng)過捕捉,然后把控制權(quán)再給數(shù)據(jù)鏈路,這樣就直接在內(nèi)核緩沖內(nèi)進(jìn)行過濾。而在算法是上使用BPF包過濾機(jī)制,算法上很復(fù)雜,使用偽機(jī)器碼的方式,類似于匯編語言。如果是以后做到類似多重判斷跳轉(zhuǎn)之類的可以參考里面的無環(huán)控制流圖CFG的實(shí)現(xiàn).
              個(gè)人認(rèn)為該庫很大一部分研究價(jià)值除了跨平臺(tái)編寫,還有就是對(duì)linux底層過濾器的調(diào)用使用。

          posted on 2009-07-05 22:26 石頭@ 閱讀(2120) 評(píng)論(0)  編輯  收藏 所屬分類: Tcp/Ip

          主站蜘蛛池模板: 龙山县| 泗水县| 洛扎县| 肇州县| 衡阳市| 温宿县| 广南县| 道真| 景德镇市| 汶川县| 固原市| 吉木乃县| 互助| 射阳县| 天柱县| 汕头市| 哈密市| 大足县| 吕梁市| 罗平县| 电白县| 萍乡市| 长泰县| 准格尔旗| 金昌市| 福建省| 云南省| 泰顺县| 来宾市| 兴安盟| 资溪县| 清新县| 和硕县| 广西| 东海县| 阳西县| 湄潭县| 梧州市| 高要市| 南川市| 安远县|