自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

分析數(shù)據(jù)在協(xié)議棧底層的流程

網(wǎng)絡(luò) 網(wǎng)絡(luò)管理
分析數(shù)據(jù)在協(xié)議棧底層的流程:當(dāng)網(wǎng)卡收到數(shù)據(jù)后,產(chǎn)生硬件中斷,由中斷處理程序(一般為網(wǎng)卡驅(qū)動(dòng)程序所注冊)從網(wǎng)卡內(nèi)讀取數(shù)據(jù),下面我們來具體分析一下數(shù)據(jù)在協(xié)議棧底層的流程。

分析數(shù)據(jù)在協(xié)議棧底層的流程:當(dāng)網(wǎng)卡收到數(shù)據(jù)后,產(chǎn)生硬件中斷,由中斷處理程序(一般為網(wǎng)卡驅(qū)動(dòng)程序所注冊)從網(wǎng)卡內(nèi)讀取數(shù)據(jù),并封裝稱sk_buff{}結(jié)構(gòu),然后把這些數(shù)據(jù)傳遞給函數(shù)netif_rx()進(jìn)行進(jìn)一步的處理。

函數(shù)netif_rx()根據(jù)當(dāng)前接收隊(duì)列的擁擠情況,選擇丟棄還是接收,如果是接收,則將接收到的sk_buff{}掛到接收隊(duì)列softnet_data[CPU]->input_pkt_queue上,并調(diào)用函數(shù)__cpu_raise_softirq()激活軟中斷NET_RX_SOFTIRQ,相應(yīng)的處理函數(shù)是net_rx_action()。

在函數(shù)net_rx_action()中根據(jù)數(shù)據(jù)包的協(xié)議類型,調(diào)用相應(yīng)的處理函數(shù)。對于IP包,處理函數(shù)是ip_rcv()。

函數(shù)ip_rcv()對IP包進(jìn)行了一系列必要的檢查(包括檢查校驗(yàn)和),最終調(diào)用函數(shù)ip_rcv_finish()對數(shù)據(jù)包進(jìn)行向上傳輸。

函數(shù)ip_rcv_finish()首先調(diào)用函數(shù)ip_route_input()獲取路由,檢測該包是發(fā)給本機(jī)的還是要進(jìn)行轉(zhuǎn)發(fā)的,如果要進(jìn)行轉(zhuǎn)發(fā),則調(diào)用調(diào)用函數(shù)ip_forward()進(jìn)行轉(zhuǎn)發(fā),否則調(diào)用函數(shù)ip_local_deliver()進(jìn)一步向上傳遞數(shù)據(jù)包。

函數(shù)ip_local_deliver()首先進(jìn)行了防火墻的過濾工作,最終調(diào)用函數(shù)ip_local_deliver_finish()向上傳遞數(shù)據(jù)。

在函數(shù)ip_local_deliver_finish()中,會(huì)檢查是否有匹配協(xié)議(如根據(jù)IP頭判斷我們的數(shù)據(jù)包是TCP包,則要判斷是否有接收TCP包的原始套接口。當(dāng)然,如果有接收所有IP包的原始套接口存在也是可以的)的原始套接口。如果有,則調(diào)用函數(shù)raw_v4_input()進(jìn)行處理。

在函數(shù)raw_v4_input()中,要進(jìn)一步進(jìn)行匹配,這次匹配的依據(jù)有四個(gè),依次是:協(xié)議、源地址、目的地址和接收接口。分別對每一個(gè)匹配成功的原始套接口調(diào)用函數(shù)raw_rcv()傳遞一個(gè)克隆的以sk_buff{}為結(jié)構(gòu)的數(shù)據(jù)包。

接下來的幾個(gè)函數(shù)都很簡單,調(diào)用順序依次是raw_rcv()、raw_rcv_skb()和sock_queue_rcv_skb()。這幾個(gè)函數(shù)基本上都是簡單的依次調(diào)用關(guān)系。最后調(diào)用函數(shù)sock_queue_rcv_skb(),該函數(shù)經(jīng)過skb_queue_tail()函數(shù)將數(shù)據(jù)包sk_buff{}放入了接收隊(duì)列sk->receive_queue的末尾。

原始套接口的協(xié)議棧實(shí)現(xiàn)――原始套接口的綁定

這里我們簡略分析,對原始套接口綁定調(diào)用的是函數(shù)sk->prot->bind,在原始套接口的創(chuàng)建中我們給出了套接口的sk->prot即structproto結(jié)構(gòu)變量raw_prot,從中可以看出和sk->prot->bind指針實(shí)質(zhì)指向函數(shù)raw_bind()。

在這個(gè)函數(shù)中首先判斷套接口狀態(tài),如果是TCP_CLOSE的話,就退出。然后有對參數(shù)進(jìn)行了一些常規(guī)檢查。同時(shí),如果發(fā)現(xiàn)要綁定的地址是廣播或多播的話,也會(huì)退出。如果通過了這些檢查,就進(jìn)行一些賦值操作,將用戶要綁定的地址賦值到sk->rcv_saddr和sk->saddr中,即:

sk->rcv_saddr=sk->saddr=addr->sin_addr.s_addr

然后會(huì)正常退出。

注意,這里沒有對端口做任何操作,即使用戶指定了要綁定的端口,內(nèi)核也不予理睬。

原始套接口的協(xié)議棧實(shí)現(xiàn)――原始套接口的連接

從原始套接口的創(chuàng)建一節(jié)中給出的structproto結(jié)構(gòu)可以看出,原始套接口的連接其實(shí)調(diào)用的是函數(shù)udp_connect(),好興奮,終于見到了不那么"原始"的東西了。

在這個(gè)函數(shù)中,首先對用戶的參數(shù)進(jìn)行了一些檢查。當(dāng)然,它也檢查了用戶指定的網(wǎng)域是否是"AF_INET",如果不是,會(huì)返回一個(gè)EAFNOSUPPORT錯(cuò)誤。

然后,該函數(shù)調(diào)用了函數(shù)ip_route_connect()來獲取一個(gè)到目的地址的路由,如果失敗,也會(huì)返回錯(cuò)誤。

接下來的工作看起來就有點(diǎn)令人難以理解。

它檢查了套接口是否指定了源地址,如果沒有指定,則將尋找到的路由的源地址賦值給這個(gè)套接口的源地址,即:

if(!sk->saddr)

sk->saddr=rt->rt_src;/*Updatesourceaddress*/

if(!sk->rcv_saddr)

sk->rcv_saddr=rt->rt_src;

其中sk代表我們套接口的sock{}結(jié)構(gòu),rt代表我們找到的路由,是一個(gè)structrtable{}結(jié)構(gòu)。

最后,就是將目的地址和目的端口賦值到我們的套接口的指定字段中,同時(shí)更新套接口狀態(tài),即:

sk->daddr=rt->rt_dst;

sk->dport=usin->sin_port;

sk->state=TCP_ESTABLISHED;

原始套接口的協(xié)議棧實(shí)現(xiàn)――原始套接口的關(guān)閉

根據(jù)上面的經(jīng)驗(yàn),原始套接口的關(guān)閉應(yīng)該調(diào)用函數(shù)raw_close(),這個(gè)函數(shù)只是簡單的調(diào)用了函數(shù)ip_ra_control(),在函數(shù)ip_ra_control()中,將該套接口從鏈表ip_ra_chain中刪除,然后釋放到該套接口占用的所有空間。

原始套接口的應(yīng)用

根據(jù)前面的分析,針對原始套接口的應(yīng)用,我們可以得出以下結(jié)論。

綁定的問題

可以對原始套接口調(diào)用bind函數(shù),但并不常用。該函數(shù)僅用來設(shè)置本地地址。對于一個(gè)原始套接口而言,端口號(hào)是沒有意義的。當(dāng)進(jìn)行輸出的時(shí)候,bind設(shè)置在原始套接口上所發(fā)送的數(shù)據(jù)報(bào)中將要用到的源IP地址(僅當(dāng)IP_HDRINCL套接口選項(xiàng)未設(shè)置時(shí));若不調(diào)用bind,則由內(nèi)核將源IP地址設(shè)成外出接口的主IP地址。

連接的問題

在原始套接口上可調(diào)用connect函數(shù),但也不常用。connect函數(shù)僅設(shè)置目的地址。再重申一遍:端口號(hào)對原始套接口而言沒有意義。對于輸出而言,調(diào)用connect之后,由于目的地址已經(jīng)指定,我們可以調(diào)用write或send,而不是sendto了。

輸出的問題

1)普通輸出通常通過sendto或sendmsg并指定目的IP地址來完成,如果套接口已經(jīng)連接,也可以調(diào)用write、writev或send。

2)如果IP_HDRINCL選項(xiàng)未設(shè)置,則內(nèi)核寫的數(shù)據(jù)起始地址是IP頭部之后的第一個(gè)字節(jié)。因?yàn)檫@種情況下,內(nèi)核將構(gòu)造IP頭部,并將它安在來自進(jìn)程數(shù)據(jù)之前。內(nèi)核將IPv4頭部的協(xié)議字段設(shè)置成用戶在調(diào)用socket函數(shù)時(shí)所給的第三個(gè)參數(shù)。

3)如果IP_HDRINCL選項(xiàng)已設(shè)置,則內(nèi)核寫的數(shù)據(jù)其實(shí)地址是IP頭部的第一個(gè)字節(jié)。用戶所提供的數(shù)據(jù)必須包括IP頭部。此時(shí)進(jìn)程構(gòu)造除了以下兩項(xiàng)以外的整個(gè)IP頭部:

(1)IPv4標(biāo)示字段可以設(shè)為0,要求內(nèi)核設(shè)置該值。而且僅當(dāng)該字段為0時(shí),內(nèi)核才為其設(shè)置。

(2)IPv4頭部校驗(yàn)和由內(nèi)核來計(jì)算和存儲(chǔ)。

4)如果創(chuàng)建原始套接口時(shí)指定了協(xié)議類型,即第三個(gè)參數(shù)protocol,那也并不是說只能發(fā)該類型的數(shù)據(jù)包。如,即使將protocol指定為IPPROTO_TCP,也可以發(fā)送用戶自己組裝的UDP報(bào)文,不過此時(shí)如果IP_HDRINCL選項(xiàng)未設(shè)置,那么內(nèi)核將會(huì)在IP頭的協(xié)議字段指明后面的報(bào)文為TCP報(bào)文(不過此時(shí)卻為UDP報(bào)文)。等數(shù)據(jù)包發(fā)送到對方TCP層,一般說來會(huì)因?yàn)檎也坏胶线m的TCP套接口接收該數(shù)據(jù)包而被丟棄。不過該包可以在目標(biāo)主機(jī)的原始套接口上接收到。

5)正如前面所述,任何時(shí)候,IP頭的校驗(yàn)和都是由內(nèi)核來設(shè)置的。

6)內(nèi)核任何時(shí)候那會(huì)都不會(huì)對IP包以后的字段進(jìn)行校驗(yàn)和驗(yàn)證。如,即使我們指定第三個(gè)參數(shù)protocol為IPPROTO_TCP,在數(shù)據(jù)發(fā)送時(shí)內(nèi)核也不會(huì)對進(jìn)行TCP校驗(yàn)和計(jì)算和驗(yàn)證。

7)如果IP_HDRINCL選項(xiàng)已設(shè)置,按照常規(guī),我們應(yīng)該組建自己的IP頭,但是即使我們沒有組建IP頭,用sendto或sendmsg并指定目的IP地址來發(fā)送數(shù)據(jù)是照樣可以完成的。但是這樣的數(shù)據(jù)包在目標(biāo)機(jī)上用原始套接口是接收不到的,因?yàn)樵趇p_rcv()中要對IP頭進(jìn)行驗(yàn)證,并且要分析校驗(yàn)和,所以該包會(huì)被丟棄,不過在鏈路層應(yīng)該能夠接收到該數(shù)據(jù)包。

8)如果設(shè)置了IP_HDRINCL選項(xiàng),并且數(shù)據(jù)包超長,那么數(shù)據(jù)會(huì)被丟棄,并會(huì)返回出錯(cuò)碼EMSGSIZE。如果未設(shè)置IP_HDRINCL選項(xiàng),并且數(shù)據(jù)包超長,那么數(shù)據(jù)包會(huì)被分片。

輸入的問題

1)原始套接口可以接收到任何TCP或UDP報(bào)文。

2)要想接收到原始套接口,首先要接收的數(shù)據(jù)包必須有一個(gè)完整的、正確的IP頭,否則不能通過ip_rcv()中的包頭檢查和檢驗(yàn)和驗(yàn)證。

3)在原始套接口接收的數(shù)據(jù)包過程中,內(nèi)核會(huì)對接收的IP包進(jìn)行校驗(yàn)和驗(yàn)證,但不會(huì)對IP包以后的任何字段進(jìn)行檢測和驗(yàn)證。如,我們創(chuàng)建原始套接口時(shí),所指定的protocol參數(shù)為IPPROTO_TCP,內(nèi)核也不會(huì)進(jìn)行TCP校驗(yàn)和驗(yàn)證,而是直接把IP頭中協(xié)議字段為TCP的所有數(shù)據(jù)包都復(fù)制一份,提交給該原始套接口。

4)用原始套接口接收到的TCP包都是進(jìn)行了IP重組以后,TCP排序以前的報(bào)文。

5)如果在創(chuàng)建原始套接口時(shí),所指定的protocol參數(shù)不為零,(socket的第三個(gè)參數(shù)),則接收到的數(shù)據(jù)報(bào)的協(xié)議字段應(yīng)該與之匹配。否則該數(shù)據(jù)報(bào)不傳遞給該套接口。

6)如果此原始套接口上綁定了一個(gè)本地IP地址,那么接收到的數(shù)據(jù)報(bào)的目的IP地址應(yīng)該與該綁定的IP地址相匹配,否則該數(shù)據(jù)包將不傳遞到該套接口。

7)如果此原始套接口通過connect指定了一個(gè)對方IP地址,那么接收到的數(shù)據(jù)包的源IP地址應(yīng)與該以連接地址相匹配,否則該數(shù)據(jù)包不傳遞給該套接口。

8)如果一個(gè)原始套接口以protocol參數(shù)為0的方式創(chuàng)建,并且未調(diào)用connect或bind,那么對于內(nèi)核傳遞給原始套接口的每一個(gè)原始數(shù)據(jù)報(bào),該套接口都會(huì)收到一份拷貝。

9)原始套接口接收不到任何的ARP或RARP協(xié)議類型的套接口,因?yàn)閚et_rx_action()

會(huì)把ARP或RARP協(xié)議類型的數(shù)據(jù)包傳遞給ARP的接收函數(shù)類處理,不會(huì)傳遞給IP層的接收函數(shù)ip_rcv()。

10)原始套接口并不是可以接收到任何的ICMP類型的數(shù)據(jù)包,因?yàn)橛行㊣CMP類型的數(shù)據(jù)包在傳遞給原始套接口之前已經(jīng)被系統(tǒng)所響應(yīng),并不再向上層傳遞。

11)如果對方的數(shù)據(jù)包分片了,由于原始套接口的接收是在IP上層,所以會(huì)接收到重組以后的原始IP包。

【編輯推薦】

  1. 數(shù)據(jù)中心部署的最優(yōu)極性管理解決方案
  2. 協(xié)議標(biāo)準(zhǔn)化 下一代數(shù)據(jù)中心網(wǎng)絡(luò)的支點(diǎn)
  3. 數(shù)據(jù)中心網(wǎng)絡(luò)架構(gòu)的革命
  4. 瞻博數(shù)據(jù)中心架構(gòu)助力Terra公司滿足網(wǎng)絡(luò)媒體需求
責(zé)任編輯:于爽 來源: blog.chinaunix.net
相關(guān)推薦

2019-09-30 09:28:26

LinuxTCPIP

2010-09-08 17:35:31

協(xié)議棧是什么

2010-09-27 13:25:58

TCP IP協(xié)議棧

2010-06-13 13:39:46

TCP IP協(xié)議棧

2011-11-08 16:49:06

ZigBee協(xié)議棧Z-Stack

2010-07-08 14:00:02

HART協(xié)議

2010-09-09 13:09:33

協(xié)議棧開發(fā)

2011-11-09 14:59:37

LwIP協(xié)議棧

2010-06-17 15:23:38

WAP協(xié)議棧

2021-05-12 00:07:27

TCPIP協(xié)議

2010-09-09 13:30:03

Linux網(wǎng)絡(luò)協(xié)議棧

2010-09-08 12:16:18

2010-06-11 14:15:23

WAP協(xié)議棧

2010-09-08 15:34:27

TCP IP協(xié)議棧

2010-06-17 15:19:52

WAP協(xié)議棧

2010-09-09 13:19:47

H.323協(xié)議協(xié)議棧開發(fā)

2010-09-08 14:59:27

藍(lán)牙協(xié)議棧

2010-09-08 18:09:01

雙協(xié)議棧

2010-09-08 15:06:26

藍(lán)牙協(xié)議棧

2010-07-01 15:38:41

TCP IP協(xié)議棧單片機(jī)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)