實際上,我們常用的網路程式設計都是在應用層的報文的收發操作,也就是大多數程式設計師接觸到的流式套接字(sock_stream)和資料報式套接字(sock_dgram)。而這些資料報都是由系統提供的協議棧實現,使用者只需要填充應用層報文即可,由系統完成底層報文頭的填充並傳送。然而在某些情況下需要執行更底層的操作,比如修改報文頭、避開系統協議棧等。這個時候就需要使用其他的方式來實現。
原始套接字(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);
**:
原始套接字SOCK RAW
實際上,我們常用的網路程式設計都是在應用層的報文的收發操作,也就是大多數程式設計師接觸到的流式套接字 sock stream 和資料報式套接字 sock dgram 而這些資料報都是由系統提供的協議棧實現,使用者只需要填充應用層報文即可,由系統完成底層報文頭的填充並傳送。然而在某些情況下需要執行更底...
LWIP 原始套接字(SOCK RAW)
收錄於 lwip lwip協議 相關知識彙總 lwip學習筆記 通常情況下我們接觸到的套接字為兩類 1 位元組流套接字 sock stream 面向連線的socket套接字,用於tcp服務應用。2 資料報套接字 sock dgram 無連線 不可靠的socket套接字,用於udp服務應用。從使用者的...
UNIX網路程式設計 原始套接字SOCK RAW
實際上,我們常用的網路程式設計都是在應用層的報文的收發操作,也就是大多數程式設計師接觸到的流式套接字 sock stream 和資料報式套接字 sock dgram 而這些資料報都是由系統提供的協議棧實現,使用者只需要填充應用層報文即可,由系統完成底層報文頭的填充並傳送。然而在某些情況下需要執行更底...