編譯包含skbuffh
A. linux 編譯compat-wireless-3.1-rc1-1時的問題
簡單的步驟在ubuntu(hardy)里安裝google-gadgets:
1. wget
2. tar zxvf google-gadgets-for-linux-0.9.1.tar.gz
3. cd google-gadgets-for-linux-0.9.1/
4. sudo apt-get install zlib1g-dev libmozjs-dev libcurl4-openssl-dev libxml2-dev libdbus-1-dev libmozjs-dev libgstreamer-plugins-base0.10-dev libcurl3-openssl-dev libdbus-1-dev libxul-dev libcurl3 libcurl3-dbg libcurl3-gnutls libcurl4-openssl-dev libcurl-ocaml libmozjs0d libmozjs0d-dbg libmozjs-dev g++-4.2-multilib g++ libqt4-dev
5. sudo ldconfig
6. ../../configure --enable-debug
7. sudo make install
(或者不用sudo,而是設置另一個安裝目錄,不同於默認的/usr/local)
1. export LD_LIBRARY_PATH=/usr/local/lib
2. ggl-gtk
B. 請問#i nclude <linux/skbuff.h>是什麼庫函數啊
skbuff.h是Linux內核的頭文件,和庫函數沒關系。
skbuff.h中最主要的是包含了Linux內核網路子系統(協議棧)用來表示數據包的數據結構——struct sk_buff,也就是大家經常說的skb以及其相關的函數。這個數據結構基本上是整個Linux網路子系統中最核心的了。
C. 如何理解連接跟蹤機制
連接跟蹤定義很簡單:用來記錄和跟蹤連接的狀態。
為什麼又需要連接跟蹤功能呢?因為它是狀態防火牆和NAT的實現基礎。
Neftiler為了實現基於數據連接狀態偵測的狀態防火牆功能和NAT地址轉換功能才開發出了連接跟蹤這套機制。那就意思是說:如果編譯內核時開啟了連接跟蹤選項,那麼Linux系統就會為它收到的每個數據包維持一個連接狀態用於記錄這條數據連接的狀態。接下來我們就來研究一下Netfilter的連接跟蹤的設計思想和實現方式。
之前有一副圖,我們可以很明確的看到:用於實現連接跟蹤入口的hook函數以較高的優先順序分別被注冊到了netfitler的NF_IP_PRE_ROUTING和NF_IP_LOCAL_OUT兩個hook點上;用於實現連接跟蹤出口的hook函數以非常低的優先順序分別被注冊到了netfilter的NF_IP_LOCAL_IN和NF_IP_POST_ROUTING兩個hook點上。
其實PRE_ROUTING和LOCAL_OUT點可以看作是整個netfilter的入口,而POST_ROUTING和LOCAL_IN可以看作是其出口。在只考慮連接跟蹤的情況下,一個數據包無外乎有以下三種流程可以走:
一、發送給本機的數據包
流程:PRE_ROUTING----LOCAL_IN---本地進程,如果是新的包,在PREROUTING處生成連接記錄,通過POSTROUTING後加到hash表
二、需要本機轉發的數據包
流程:PRE_ROUTING---FORWARD---POST_ROUTING---外出,在PREROUTING處生成連接記錄,在LOCAL_IN處把生成的連接記錄加到hash表
三、從本機發出的數據包
流程:LOCAL_OUT----POST_ROUTING---外出,在LOCAL_OUT處生成連接記錄,在POSTROUTING處把生成的連接記錄加到hash表。
我們都知道在INET層用於表示數據包的結構是大名鼎鼎的sk_buff{}(後面簡稱skb),如果你不幸的沒聽說過這個東東,那麼我強烈的建議你先補一下網路協議棧的基礎知識再繼續閱讀這篇文章。在skb中有個成員指針nfct,類型是struct nf_conntrack{},該結構定義在include/linux/skbuff.h文件中。該結構記錄了連接記錄被公開應用的計數,也方便其他地方對連接跟蹤的引用。連接跟蹤在實際應用中一般都通過強制類型轉換將nfct轉換成指向ip_conntrack{}類型(定義在include/linux/netfilter_ipv4/ip_conntrack.h里)來獲取一個數據包所屬連接跟蹤的狀態信息的。即:Neftilter框架用ip_conntrack{}來記錄一個數據包與其連接的狀態關系。
同時在include/linux/netfilter_ipv4/ip_conntrack.h文件中還提供了一個非常有用的介面:struct ip_conntrack *ip_conntrack_get(skb, ctinfo)用於獲取一個skb的nfct指針,從而得知該數據包的連接狀態和該連接狀態的相關信息ctinfo。從連接跟蹤的角度來看,這個ctinfo表示了每個數據包的幾種連接狀態:
l IP_CT_ESTABLISHED
Packet是一個已建連接的一部分,在其初始方向。
l IP_CT_RELATED
Packet屬於一個已建連接的相關連接,在其初始方向。
l IP_CT_NEW
Packet試圖建立新的連接
l IP_CT_ESTABLISHED+IP_CT_IS_REPLY
Packet是一個已建連接的一部分,在其響應方向。
l IP_CT_RELATED+IP_CT_IS_REPLY
Packet屬於一個已建連接的相關連接,在其響應方向。
在連接跟蹤內部,收到的每個skb首先被轉換成一個ip_conntrack_tuple{}結構,也就是說ip_conntrack_tuple{}結構才是連接跟蹤系統所「認識」的數據包。那麼skb和ip_conntrack_tuple{}結構之間是如何轉換的呢?這個問題沒有一個統一的答案,與具體的協議息息相關。例如,對於TCP/UDP協議,根據「源、目的IP+源、目的埠」再加序列號就可以唯一的標識一個數據包了;對於ICMP協議,根據「源、目的IP+類型+代號」再加序列號才可以唯一確定一個ICMP報文等等。對於諸如像FTP這種應用層的「活動」協議來說情況就更復雜了。本文不試圖去分析某種具體協議的連接跟蹤實現,而是探究連接跟蹤的設計原理和其工作流程,使大家掌握連接跟蹤的精髓。因為現在Linux內核更新的太快的都到3.4.x,變化之大啊。就算是2.6.22和2.6.21在連接跟蹤這塊還是有些區別呢。一旦大家理解了連接跟蹤的設計思想,掌握了其神韻,它再怎麼也萬變不離其宗,再看具體的代碼實現時就不會犯迷糊了。俗話說「授人一魚,不如授人一漁」,我們教給大家的是方法。有了方法再加上自己的勤學苦練,那就成了技能,最後可以使得大家在為自己的協議開發連接跟蹤功能時心裡有數。這也是我寫這個系列博文的初衷和目的。與君共勉。
在開始分析連接跟蹤之前,我們還是站在統帥的角度來俯視一下整個連接跟蹤的布局。這里我先用比較粗略的精簡流程圖為大家做個展示,目的是方便大家理解,好入門。當然,我的理解可能還有不太准確的地方,還請大牛們幫小弟指正。
我還是重申一下:連接跟蹤分入口和出口兩個點。謹記:入口時創建連接跟蹤記錄,出口時將該記錄加入到連接跟蹤表中。我們分別來看看。
入口:
整個入口的流程簡述如下:對於每個到來的skb,連接跟蹤都將其轉換成一個tuple結構,然後用該tuple去查連接跟蹤表。如果該類型的數據包沒有被跟蹤過,將為其在連接跟蹤的hash表裡建立一個連接記錄項,對於已經跟蹤過了的數據包則不用此操作。緊接著,調用該報文所屬協議的連接跟蹤模塊的所提供的packet()回調函數,最後根據狀態改變連接跟蹤記錄的狀態。
出口:
整個出口的流程簡述如下:對於每個即將離開Netfilter框架的數據包,如果用於處理該協議類型報文的連接跟蹤模塊提供了helper函數,那麼該數據包首先會被helper函數處理,然後才去判斷,如果該報文已經被跟蹤過了,那麼其所屬連接的狀態,決定該包是該被丟棄、或是返回協議棧繼續傳輸,又或者將其加入到連接跟蹤表中。
連接跟蹤的協議管理:
我們前面曾說過,不同協議其連接跟蹤的實現是不相同的。每種協議如果要開發自己的連接跟蹤模塊,那麼它首先必須實例化一個ip_conntrack_protocol{}結構體類型的變數,對其進行必要的填充,然後調用ip_conntrack_protocol_register()函數將該結構進行注冊,其實就是根據協議類型將其設置到全局數組ip_ct_protos[]中的相應位置上。
ip_ct_protos變數里保存連接跟蹤系統當前可以處理的所有協議,協議號作為數組唯一的下標,如下圖所示。
結構體ip_conntrack_protocol{}中的每個成員,內核源碼已經做了很詳細的注釋了,這里我就不一一解釋了,在實際開發過程中我們用到了哪些函數再具體分析。
連接跟蹤的輔助模塊:
Netfilter的連接跟蹤為我們提供了一個非常有用的功能模塊:helper。該模塊可以使我們以很小的代價來完成對連接跟蹤功能的擴展。這種應用場景需求一般是,當一個數據包即將離開Netfilter框架之前,我們可以對數據包再做一些最後的處理。從前面的圖我們也可以看出來,helper模塊以較低優先順序被注冊到了Netfilter的LOCAL_OUT和POST_ROUTING兩個hook點上。
每一個輔助模塊都是一個ip_conntrack_helper{}結構體類型的對象。也就是說,如果你所開發的協議需要連接跟蹤輔助模塊來完成一些工作的話,那麼你必須也去實例化一個ip_conntrack_helper{}對象,對其進行填充,最後調用ip_conntrack_helper_register{}函數將你的輔助模塊注冊到全局變數helpers里,該結構是個雙向鏈表,裡面保存了當前已經注冊到連接跟蹤系統里的所有協議的輔助模塊。
全局helpers變數的定義和初始化在net/netfilter/nf_conntrack_helper.c文件中完成的。
最後,我們的helpers變數所表示的雙向鏈表一般都是像下圖所示的這樣子:
由此我們基本上就可以知道,注冊在Netfilter框架里LOCAL_OUT和POST_ROUTING兩個hook點上ip_conntrack_help()回調函數所做的事情基本也就很清晰了:那就是通過依次遍歷helpers鏈表,然後調用每個ip_conntrack_helper{}對象的help()函數。
期望連接:
Netfilter的連接跟蹤為支持諸如FTP這樣的「活動」連接提供了一個叫做「期望連接」的機制。我們都知道FTP協議服務端用21埠做命令傳輸通道,主動模式下伺服器用20埠做數據傳輸通道;被動模式下伺服器隨機開一個高於1024的埠,然後客戶端來連接這個埠開始數據傳輸。也就是說無論主、被動,都需要兩條連接:命令通道的連接和數據通道的連接。連接跟蹤在處理這種應用場景時提出了一個「期望連接」的概念,即一條數據連接和另外一條數據連接是相關的,然後對於這種有「相關性」的連接給出自己的解決方案。我們說過,本文不打算分析某種具體協議連接跟蹤的實現。接下來我們就來談談期望連接。
每條期望連接都用一個ip_conntrack_expect{}結構體類型的對象來表示,所有的期望連接存儲在由全局變數ip_conntrack_expect_list所指向的雙向鏈表中,該鏈表的結構一般如下:
結構體ip_conntrack_expect{}中的成員及其意義在內核源碼中也做了充分的注釋,這里我就不逐一介紹了,等到需要的時候再詳細探討。
連接跟蹤表:
說了半天終於到我們連接跟蹤表拋頭露面的時候了。連接跟蹤表是一個用於記錄所有數據包連接信息的hash散列表,其實連接跟蹤表就是一個以數據包的hash值組成的一個雙向循環鏈表數組,每條鏈表中的每個節點都是ip_conntrack_tuple_hash{}類型的一個對象。連接跟蹤表是由一個全局的雙向鏈表指針變數ip_conntrack_hash[]來表示。為了使我們更容易理解ip_conntrack_hash[]這個雙向循環鏈表的數組,我們將前面提到的幾個重要的目前還未介紹的結構ip_conntrack_tuple{}、ip_conntrack{}和ip_conntrack_tuple_hash{}分別介紹一下。
我們可以看到ip_conntrack_tuple_hash{}僅僅是對ip_conntrack_tuple{}的封裝而已,將其組織成了一個雙向鏈表結構。因此,在理解層面上我們可以認為它們是同一個東西。
在分析ip_conntrack{}結構時,我們將前面所有和其相關的數據結構都列出來,方便大家對其理解和記憶。
參考http://bbs.chinaunix.net/thread-1925862-1-1.html
該圖可是說是連接跟蹤部分的數據核心,接下來我們來詳細說說ip_conntrack{}結構中相關成員的意義。
l ct_general:該結構記錄了連接記錄被公開應用的計數,也方便其他地方對連接跟蹤的引用。
l status:數據包連接的狀態,是一個比特點陣圖。
l timeout:不同協議的每條連接都有默認超時時間,如果在超過了該時間且沒有屬於某條連接的數據包來刷新該連接跟蹤記錄,那麼會調用這種協議類型提供的超時函數。
l counters:該成員只有在編譯內核時打開了CONFIG_IP_NF_CT_ACCT開完才會存在,代表某條連接所記錄的位元組數和包數。
l master:該成員指向另外一個ip_conntrack{}。一般用於期望連接場景。即如果當前連接是另外某條連接的期望連接的話,那麼該成員就指向那條我們所屬的主連接。
l helper:如果某種協議提供了擴展模塊,就通過該成員來調用擴展模塊的功能函數。
l proto:該結構是ip_conntrack_proto{}類型,和我們前面曾介紹過的用於存儲不同協議連接跟蹤的ip_conntrack_protocol{}結構不要混淆了。前者是個枚舉類型,後者是個結構體類型。這里的proto表示不同協議為了實現其自身的連接跟蹤功能而需要的一些額外參數信息。目前這個枚舉類型如下:
如果將來你的協議在實現連接跟蹤時也需要一些額外數據,那麼可以對該結構進行擴充。
l help:該成員代表不同的應用為了實現其自身的連接跟蹤功能而需要的一些額外參數信息,也是個枚舉類型的ip_conntrack_help{}結構,和我們前面剛介紹過的結構體類型ip_conntrack_helpers{}容易混淆。ip_conntrack_proto{}是為協議層需要而存在的,而ip_conntrack_help{}是為應用層需要而存在。
l tuplehash:該結構是個ip_conntrack_tuple_hash{}類型的數組,大小為2。tuplehash[0]表示一條數據流「初始」方向上的連接情況,tuplehash[1]表示該數據流「應答」方向的響應情況,見上圖所示。
到目前為止,我們已經了解了連接跟蹤設計思想和其工作機制:連接跟蹤是Netfilter提供的一套基礎框架,不同的協議可以根據其自身協議的特殊性在連接跟蹤機制的指導和約束下來開發本協議的連接跟蹤功能,最後將其交給連接跟蹤機制來統一管理。
轉載僅供參考,版權屬於原作者。祝你愉快,滿意請採納哦
D. 如何理解連接跟蹤機制
為什麼又需要連接跟蹤功能呢?因為它是狀態防火牆和NAT的實現基礎。
Neftiler為了實現基於數據連接狀態偵測的狀態防火牆功能和NAT地址轉換功能才開發出了連接跟蹤這套機制。那就意思是說:如果編譯內核時開啟了連接跟蹤選項,那麼我這次就以在Linux系統下操作就會為它收到的每個數據包維持一個連接狀態用於記錄這條數據連接的狀態。接下來我們就來研究一下Netfilter的連接跟蹤的設計思想和實現方式。
最簡單就是打個比喻 www.meiweirenqi.com 這個當用戶打開之後就是連接一次
只要刷新一下也會連接一次用戶和機器來回交換信息
之前有一副圖,我們可以很明確的看到:用於實現連接跟蹤入口的hook函數以較高的優先順序分別被注冊到了netfitler的NF_IP_PRE_ROUTING和NF_IP_LOCAL_OUT兩個hook點上;用於實現連接跟蹤出口的hook函數以非常低的優先順序分別被注冊到了netfilter的NF_IP_LOCAL_IN和NF_IP_POST_ROUTING兩個hook點上。
其實PRE_ROUTING和LOCAL_OUT點可以看作是整個netfilter的入口,而POST_ROUTING和LOCAL_IN可以看作是其出口。在只考慮連接跟蹤的情況下,一個數據包無外乎有以下三種流程可以走:
一、發送給本機的數據包
流程:PRE_ROUTING----LOCAL_IN---本地進程,如果是新的包,在PREROUTING處生成連接記錄,通過POSTROUTING後加到hash表
二、需要本機轉發的數據包
流程:PRE_ROUTING---FORWARD---POST_ROUTING---外出,在PREROUTING處生成連接記錄,在LOCAL_IN處把生成的連接記錄加到hash表
三、從本機發出的數據包
流程:LOCAL_OUT----POST_ROUTING---外出,在LOCAL_OUT處生成連接記錄,在POSTROUTING處把生成的連接記錄加到hash表。
我們都知道在INET層用於表示數據包的結構是大名鼎鼎的sk_buff{}(後面簡稱skb),如果你不幸的沒聽說過這個東東,那麼我強烈的建議你先補一下網路協議棧的基礎知識再繼續閱讀這篇文章。在skb中有個成員指針nfct,類型是struct nf_conntrack{},該結構定義在include/linux/skbuff.h文件中。該結構記錄了連接記錄被公開應用的計數,也方便其他地方對連接跟蹤的引用。連接跟蹤在實際應用中一般都通過強制類型轉換將nfct轉換成指向ip_conntrack{}類型(定義在include/linux/netfilter_ipv4/ip_conntrack.h里)來獲取一個數據包所屬連接跟蹤的狀態信息的。即:Neftilter框架用ip_conntrack{}來記錄一個數據包與其連接的狀態關系。
同時在include/linux/netfilter_ipv4/ip_conntrack.h文件中還提供了一個非常有用的介面:struct ip_conntrack *ip_conntrack_get(skb, ctinfo)用於獲取一個skb的nfct指針,從而得知該數據包的連接狀態和該連接狀態的相關信息ctinfo。從連接跟蹤的角度來看,這個ctinfo表示了每個數據包的幾種連接狀態:
l IP_CT_ESTABLISHED
Packet是一個已建連接的一部分,在其初始方向。
l IP_CT_RELATED
Packet屬於一個已建連接的相關連接,在其初始方向。
l IP_CT_NEW
Packet試圖建立新的連接
l IP_CT_ESTABLISHED+IP_CT_IS_REPLY
Packet是一個已建連接的一部分,在其響應方向。
l IP_CT_RELATED+IP_CT_IS_REPLY
Packet屬於一個已建連接的相關連接,在其響應方向。
在連接跟蹤內部,收到的每個skb首先被轉換成一個ip_conntrack_tuple{}結構,也就是說ip_conntrack_tuple{}結構才是連接跟蹤系統所「認識」的數據包。那麼skb和ip_conntrack_tuple{}結構之間是如何轉換的呢?這個問題沒有一個統一的答案,與具體的協議息息相關。例如,對於TCP/UDP協議,根據「源、目的IP+源、目的埠」再加序列號就可以唯一的標識一個數據包了;對於ICMP協議,根據「源、目的IP+類型+代號」再加序列號才可以唯一確定一個ICMP報文等等。對於諸如像FTP這種應用層的「活動」協議來說情況就更復雜了。本文不試圖去分析某種具體協議的連接跟蹤實現,而是探究連接跟蹤的設計原理和其工作流程,使大家掌握連接跟蹤的精髓。因為現在Linux內核更新的太快的都到3.4.x,變化之大啊。就算是2.6.22和2.6.21在連接跟蹤這塊還是有些區別呢。一旦大家理解了連接跟蹤的設計思想,掌握了其神韻,它再怎麼也萬變不離其宗,再看具體的代碼實現時就不會犯迷糊了。俗話說「授人一魚,不如授人一漁」,我們教給大家的是方法。有了方法再加上自己的勤學苦練,那就成了技能,最後可以使得大家在為自己的協議開發連接跟蹤功能時心裡有數。這也是我寫這個系列博文的初衷和目的。與君共勉。
在開始分析連接跟蹤之前,我們還是站在統帥的角度來俯視一下整個連接跟蹤的布局。這里我先用比較粗略的精簡流程圖為大家做個展示,目的是方便大家理解,好入門。當然,我的理解可能還有不太准確的地方,還請大牛們幫小弟指正。
我還是重申一下:連接跟蹤分入口和出口兩個點。謹記:入口時創建連接跟蹤記錄,出口時將該記錄加入到連接跟蹤表中。我們分別來看看。
入口:
整個入口的流程簡述如下:對於每個到來的skb,連接跟蹤都將其轉換成一個tuple結構,然後用該tuple去查連接跟蹤表。如果該類型的數據包沒有被跟蹤過,將為其在連接跟蹤的hash表裡建立一個連接記錄項,對於已經跟蹤過了的數據包則不用此操作。緊接著,調用該報文所屬協議的連接跟蹤模塊的所提供的packet()回調函數,最後根據狀態改變連接跟蹤記錄的狀態。
出口:
整個出口的流程簡述如下:對於每個即將離開Netfilter框架的數據包,如果用於處理該協議類型報文的連接跟蹤模塊提供了helper函數,那麼該數據包首先會被helper函數處理,然後才去判斷,如果該報文已經被跟蹤過了,那麼其所屬連接的狀態,決定該包是該被丟棄、或是返回協議棧繼續傳輸,又或者將其加入到連接跟蹤表中。
連接跟蹤的協議管理:
我們前面曾說過,不同協議其連接跟蹤的實現是不相同的。每種協議如果要開發自己的連接跟蹤模塊,那麼它首先必須實例化一個ip_conntrack_protocol{}結構體類型的變數,對其進行必要的填充,然後調用ip_conntrack_protocol_register()函數將該結構進行注冊,其實就是根據協議類型將其設置到全局數組ip_ct_protos[]中的相應位置上。
ip_ct_protos變數里保存連接跟蹤系統當前可以處理的所有協議,協議號作為數組唯一的下標,如下圖所示。
結構體ip_conntrack_protocol{}中的每個成員,內核源碼已經做了很詳細的注釋了,這里我就不一一解釋了,在實際開發過程中我們用到了哪些函數再具體分析。
連接跟蹤的輔助模塊:
Netfilter的連接跟蹤為我們提供了一個非常有用的功能模塊:helper。該模塊可以使我們以很小的代價來完成對連接跟蹤功能的擴展。這種應用場景需求一般是,當一個數據包即將離開Netfilter框架之前,我們可以對數據包再做一些最後的處理。從前面的圖我們也可以看出來,helper模塊以較低優先順序被注冊到了Netfilter的LOCAL_OUT和POST_ROUTING兩個hook點上。
每一個輔助模塊都是一個ip_conntrack_helper{}結構體類型的對象。也就是說,如果你所開發的協議需要連接跟蹤輔助模塊來完成一些工作的話,那麼你必須也去實例化一個ip_conntrack_helper{}對象,對其進行填充,最後調用ip_conntrack_helper_register{}函數將你的輔助模塊注冊到全局變數helpers里,該結構是個雙向鏈表,裡面保存了當前已經注冊到連接跟蹤系統里的所有協議的輔助模塊。
全局helpers變數的定義和初始化在net/netfilter/nf_conntrack_helper.c文件中完成的。
最後,我們的helpers變數所表示的雙向鏈表一般都是像下圖所示的這樣子:
由此我們基本上就可以知道,注冊在Netfilter框架里LOCAL_OUT和POST_ROUTING兩個hook點上ip_conntrack_help()回調函數所做的事情基本也就很清晰了:那就是通過依次遍歷helpers鏈表,然後調用每個ip_conntrack_helper{}對象的help()函數。
期望連接:
Netfilter的連接跟蹤為支持諸如FTP這樣的「活動」連接提供了一個叫做「期望連接」的機制。我們都知道FTP協議服務端用21埠做命令傳輸通道,主動模式下伺服器用20埠做數據傳輸通道;被動模式下伺服器隨機開一個高於1024的埠,然後客戶端來連接這個埠開始數據傳輸。也就是說無論主、被動,都需要兩條連接:命令通道的連接和數據通道的連接。連接跟蹤在處理這種應用場景時提出了一個「期望連接」的概念,即一條數據連接和另外一條數據連接是相關的,然後對於這種有「相關性」的連接給出自己的解決方案。我們說過,本文不打算分析某種具體協議連接跟蹤的實現。接下來我們就來談談期望連接。
每條期望連接都用一個ip_conntrack_expect{}結構體類型的對象來表示,所有的期望連接存儲在由全局變數ip_conntrack_expect_list所指向的雙向鏈表中,該鏈表的結構一般如下:
結構體ip_conntrack_expect{}中的成員及其意義在內核源碼中也做了充分的注釋,這里我就不逐一介紹了,等到需要的時候再詳細探討。
連接跟蹤表:
說了半天終於到我們連接跟蹤表拋頭露面的時候了。連接跟蹤表是一個用於記錄所有數據包連接信息的hash散列表,其實連接跟蹤表就是一個以數據包的hash值組成的一個雙向循環鏈表數組,每條鏈表中的每個節點都是ip_conntrack_tuple_hash{}類型的一個對象。連接跟蹤表是由一個全局的雙向鏈表指針變數ip_conntrack_hash[]來表示。為了使我們更容易理解ip_conntrack_hash[]這個雙向循環鏈表的數組,我們將前面提到的幾個重要的目前還未介紹的結構ip_conntrack_tuple{}、ip_conntrack{}和ip_conntrack_tuple_hash{}分別介紹一下。
我們可以看到ip_conntrack_tuple_hash{}僅僅是對ip_conntrack_tuple{}的封裝而已,將其組織成了一個雙向鏈表結構。因此,在理解層面上我們可以認為它們是同一個東西。
在分析ip_conntrack{}結構時,我們將前面所有和其相關的數據結構都列出來,方便大家對其理解和記憶。
該圖可是說是連接跟蹤部分的數據核心,接下來我們來詳細說說ip_conntrack{}結構中相關成員的意義。
l ct_general:該結構記錄了連接記錄被公開應用的計數,也方便其他地方對連接跟蹤的引用。
l status:數據包連接的狀態,是一個比特點陣圖。
l timeout:不同協議的每條連接都有默認超時時間,如果在超過了該時間且沒有屬於某條連接的數據包來刷新該連接跟蹤記錄,那麼會調用這種協議類型提供的超時函數。
l counters:該成員只有在編譯內核時打開了CONFIG_IP_NF_CT_ACCT開完才會存在,代表某條連接所記錄的位元組數和包數。
l master:該成員指向另外一個ip_conntrack{}。一般用於期望連接場景。即如果當前連接是另外某條連接的期望連接的話,那麼該成員就指向那條我們所屬的主連接。
l helper:如果某種協議提供了擴展模塊,就通過該成員來調用擴展模塊的功能函數。
l proto:該結構是ip_conntrack_proto{}類型,和我們前面曾介紹過的用於存儲不同協議連接跟蹤的ip_conntrack_protocol{}結構不要混淆了。前者是個枚舉類型,後者是個結構體類型。這里的proto表示不同協議為了實現其自身的連接跟蹤功能而需要的一些額外參數信息。目前這個枚舉類型如下:
如果將來你的協議在實現連接跟蹤時也需要一些額外數據,那麼可以對該結構進行擴充。
l help:該成員代表不同的應用為了實現其自身的連接跟蹤功能而需要的一些額外參數信息,也是個枚舉類型的ip_conntrack_help{}結構,和我們前面剛介紹過的結構體類型ip_conntrack_helpers{}容易混淆。ip_conntrack_proto{}是為協議層需要而存在的,而ip_conntrack_help{}是為應用層需要而存在。
l tuplehash:該結構是個ip_conntrack_tuple_hash{}類型的數組,大小為2。tuplehash[0]表示一條數據流「初始」方向上的連接情況,tuplehash[1]表示該數據流「應答」方向的響應情況,見上圖所示。
到目前為止,我們已經了解了連接跟蹤設計思想和其工作機制:連接跟蹤是Netfilter提供的一套基礎框架,不同的協議可以根據其自身協議的特殊性在連接跟蹤機制的指導和約束下來開發本協議的連接跟蹤功能,最後將其交給連接跟蹤機制來統一管理。
E. 簡單的給我介紹下網路協議中的TCP協議的數據結構是怎麼樣的
sk_buff結構可能是linux網路代碼中最重要的數據結構,它表示接收或發送數據包的包頭信息。它在<include/linux/skbuff.h>中定義,並包含很多成員變數供網路代碼中的各子系統使用。這個結構在linux內核的發展過程中改動過很多次,或者是增加新的選項,或者是重新組織已存在的成員變數以使得成員變數的布局更加清晰。它的成員變數可以大致分為以下幾類:Layout 布局General 通用Feature-specific功能相關Management functions管理函數 這個結構被不同的網路層(MAC或者其他二層鏈路協議,三層的IP,四層的TCP或UDP等)使用,並且其中的成員變數在結構從一層向另一層傳遞時改變。L4向L3傳遞前會添加一個L4的頭部,同樣,L3向L2傳遞前,會添加一個L3的頭部。添加頭部比在不同層之間拷貝數據的效率更高。由於在緩沖區的頭部添加數據意味著要修改指向緩沖區的指針,這是個復雜的操作,所以內核提供了一個函數skb_reserve(在後面的章節中描述)來完成這個功能。協議棧中的每一層在往下一層傳遞緩沖區前,第一件事就是調用skb_reserve在緩沖區的頭部給協議頭預留一定的空間。skb_reserve同樣被設備驅動使用來對齊接收到包的包頭。如果緩沖區向上層協議傳遞,舊的協議層的頭部信息就沒什麼用了。例如,L2的頭部只有在網路驅動處理L2的協議時有用,L3是不會關心它的信息的。但是,內核並沒有把L2的頭部從緩沖區中刪除,而是把有效荷載的指針指向L3的頭部,這樣做,可以節省CPU時間。1. 網路參數和內核數據結構 就像你在瀏覽TCP/IP規范或者配置內核時所看到的一樣,網路代碼提供了很多有用的功能,但是這些功能並不是必須的,比如說,防火牆,多播,還有其他一些功能。大部分的功能都需要在內核數據結構中添加自己的成員變數。因此,sk_buff裡麵包含了很多像#ifdef這樣的預編譯指令。例如,在sk_buff結構的最後,你可以找到:struct sk_buff { ... ... ...#ifdef CONFIG_NET_SCHED _ _u32 tc_index;#ifdef CONFIG_NET_CLS_ACT _ _u32 tc_verd; _ _u32 tc_classid;#endif#endif}
它表明,tc_index只有在編譯時定義了CONFIG_NET_SCHED符號才有效。這個符號可以通過選擇特定的編譯選項來定義(例如:"Device Drivers Networking supportNetworking options QoS and/or fair queueing")。這些編譯選項可以由管理員通過make config來選擇,或者通過一些自動安裝工具來選擇。前面的例子有兩個嵌套的選項:CONFIG_NET_CLS_ACT(包分類器)只有在選擇支持「QoS and/or fair queueing」時才能生效。順便提一下,QoS選項不能被編譯成內核模塊。原因就是,內核編譯之後,由某個選項所控制的數據結構是不能動態變化的。一般來說,如果某個選項會修改內核數據結構(比如說,在sk_buff
裡面增加一個項tc_index),那麼,包含這個選項的組件就不能被編譯成內核模塊。你可能經常需要查找是哪個make config編譯選項或者變種定義了某個#ifdef標記,以便理解內核中包含的某段代碼。在2.6內核中,最快的,查找它們之間關聯關系的方法,就是查找分布在內核源代碼樹中的kconfig文件中是否定義了相應的符號(每個目錄都有一個這樣的文件)。在
2.4內核中,你需要查看Documentation/Configure.help文件。2. Layout Fields有些sk_buff成員變數的作用是方便查找或者是連接數據結構本身。內核可以把sk_buff組織成一個雙向鏈表。當然,這個鏈表的結構要比常見的雙向鏈表的結構復雜一點。就像任何一個雙向鏈表一樣,sk_buff中有兩個指針next和prev,其中,next指向下一個節點,而
prev指向上一個節點。但是,這個鏈表還有另一個需求:每個sk_buff結構都必須能夠很快找到鏈表頭節點。為了滿足這個需求,在第一個節點前面會插入另一個結構sk_buff_head,這是一個輔助節點,它的定義如下:struct sk_buff_head { struct sk_buff * next; struct sk_buff * prev; _ _u32 qlen; spinlock_t lock; }; qlen代表鏈表元素的個數。lock用於防止對鏈表的並發訪問。sk_buff和sk_buff_head的前兩個元素是一樣的:next和prev指針。這使得它們可以放到同一個鏈表中,盡管sk_buff_head要比sk_buff小得多。另外,相同的函數可以同樣應用於sk_buff和sk_buff_head。為了使這個數據結構更靈活,每個sk_buff結構都包含一個指向sk_buff_head的指針。這個指針的名字是list。圖1會幫助你理解它們之間的關系。Figure 1. List of sk_buff elements
F. linux內核模塊頭文件找不到
找不到就沒辦法了
你試試 #find / -name "mole.h" 看看系統中有沒有?如果沒有,最好的辦法是完全安裝fedora6的所有軟體
G. linux內核模塊,怎麼編譯
我來說下吧 本身你這個問題問的有點歧義 不知道你問的是內核編譯 還是模塊編譯 兩個不是一個東西 盡管模塊載入後 也是內核的一部分 看看其他的回答 以為是單純的內核的編譯了 模塊本身在linux下面是可以分為靜態和動態載入的 要是採用靜態載入的話 就是從新編譯內核 和內核的編譯基本是一回事 但是多採用動態載入 這個也簡單點
從你的下面的模版可以看出 你是想寫驅動程序吧 驅動一般作為動態載入的就可以了 寫好你的c文件 格式和上面的差不多 然後GCC編譯 生成.o文件,不要生成可執行文件 ( 如果是玩Embedded 就下載到目標板了 minicom 的使用) 如果是就在linux機器上 直接執行 insmod lsmod rmmod 這些就好了 這里也是簡單的說下了 內核的編譯 寫驅動程序 本身就是個比較難得事情了 要個很長的時間去學習了 慢慢積累 好運