原始套接字的初始化及收發流程分析

2021-06-28 17:24:08 字數 2890 閱讀 8982

這篇文章寫的很棒

下面這篇文件寫的是3個協議族的詳細敘述,pf協議族不需要繫結

原始套接字(sock_raw)

是一種不同於

sock_stream

、sock_dgram

的套接字,它實現於系統核心。然而,原始套接字能做什麼呢?首先來說,普通的套接字無法處理

icmp

、igmp

等網路報文,而

sock_raw

可以;其次,

sock_raw

也可以處理特殊的

ipv4

報文;此外,利用原始套接字,可以通過

ip_hdrincl

套接字選項由使用者構造

ip頭。總體來說,

sock_raw

可以處理普通的網路報文之外,還可以處理一些特殊協議報文以及操作

ip層及其以上的資料。

既然sock_raw

有以上特性,所以在某些處理流程上它區別於普通套接字。

· 若設定ip_hdrincl

選項,sock_raw

可以操作

ip頭資料(也就是使用者需用填充

ip頭及其以上的

payload

);否則

sock_raw

無法操作

ip頭資料

· 埠對於sock_raw

而言沒有任何意義

· 如果使用bind

函式繫結本地

ip,那麼如果

ip_hdrincl

未設定,則用此

ip填充源

ip位址;若不呼叫

bind

則將源ip

位址設定為外出介面的主

ip位址

· 如果使用connect

函式設定目標

ip,則可以使用

send

或者write

函式傳送報文,而不需要使用

sendto

函式· 

核心處理流程: · 

接收到的tcp

、udp

分組不會傳遞給任何

sock_raw

· icmp、

igmp

報文分組傳遞給

sock_raw

· 核心不識別的ip

報文傳遞給

sock_raw

· sock_raw是否接收報文:

· protocol指定型別需要匹配,否則不傳遞給該

sock_raw

· 如果使用bind

函式繫結了源

ip,則報文目的

ip必須和繫結的

ip匹配,否則不傳遞給該

sock_raw

· 如果使用connect

函式繫結了目的

ip,則報文源

ip必須和指定的

ip匹配,否則不傳遞給該

sock_raw 

綜上所述,原始套接字處理的只是ip

層及其以上的資料,比如實現

syn flood

攻擊、處理

ping

報文等。當需要操作更底層的資料的時候,就需要採用其他的方式。

如果需要從鏈路層處理報文,那麼就需要採用更加底層的套接字。還是先看下套接字函式的原型吧:

#include 

int socket(int domain, int type, int protocol);

這個函式中,domain

表示協議簇,

type

表示套接字型別,而

protocol

表示的是處理的協議型別。在

linux

下提供了多種底層套接字。下面分別進行簡單介紹。

通過pf_inet

可以構造原始套接字,如下所示:

int fd = socket (pf_inet, sock_raw, ipproto_tcp);

正如前面所講的,它工作在ip

層及其以上各層協議上(當然是在使用

ip_hdrincl

選項之後才能操作

ip層資料啦),但是這種套接字無法接收從本地傳送出去的報文。而使用

sock_packet

型別的套接字,則可以操作鏈路層資料了:

int fd = socket (pf_inet, sock_packet, ipproto_tcp);

不過據說這種方式存在一定的缺陷,而且也不能保證後續版本的系統上一定支援這種方式,因此不推薦使用

pf_packet協議簇是用來取代

sock_packet

的一種程式設計介面。作為一種協議簇,它可以對應兩種不同的套接字型別:

sock_raw

和sock_dgram

。當使用

sock_raw

時,使用者操作鏈路層資料,但是如果使用後者,則由系統處理鏈路層協議頭。這種套接字支援四種協議(

eth_p_ip

、eth_p_arp

、eth_p_rarp

、eth_p_all

)(未確認)

int fd = socket (pf_packet, sock_raw, ipproto_tcp);

int fd = socket (pf_packet, sock_dgram, ipproto_tcp);

這種方式是使用者模式和kernel的ip

網路配置之間的推薦介面

綜上所述,真正能夠實現操作鏈路層資料的只有三種方式:

int fd = socket (pf_inet, sock_packet, ipproto_tcp);

int fd = socket (pf_packet, sock_raw, ipproto_tcp);

int fd = socket (pf_packet, sock_dgram, ipproto_tcp);

關於「windows套接字初始化失敗」

週六系統更新完成之後,又更新了顯示卡驅動和一些圖形的必要驅動。更新完成之後卻出現了無法連線網路,開啟部分軟體還會出現windows套接字初始化失敗的錯誤彈窗。在網上查到了問題出現的原因,這個問題會出現是因為網路協議被分層了。可能是安裝驅動或者更新系統的時候,一些新植入的程式把網路協議更改了。第一種 ...

DPDK收發包處理流程 網絡卡初始化

本文基於dpdk 1.8.0分析。網絡卡驅動模型一般包含三層,即,pci 匯流排裝置 網絡卡裝置以及網絡卡裝置的私有資料結構,即將裝置的共性一層層的抽象,pci 匯流排裝置包含網絡卡裝置,網絡卡裝置又包含其私有資料結構。在 dpdk 中,首先會註冊裝置驅動,然後查詢當前系統有哪些 pci設 備,並通...

2410上NAND的初始化及驅動流程

2410上nand的初始化及驅動流程 一 nand裝置及資源的定義和註冊 我們通過machine start定義了smdk2410的machine desc物件,這個物件裡面有個init machine的函式指標,這裡指向smdk machine init 我們的nand裝置就是在這個函式裡註冊到系...