linux socket 操作鏈路層

2021-06-12 12:07:38 字數 4349 閱讀 5896

linux提供最常用的網路通訊應用程式開發介面--berkerley套接字(socket).它既適用於同一主機上程序間通訊(ipc),又適用於不同主機上的程序間通訊。套接字的設定通過socket呼叫完成:

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

其中family指通訊域或協議族,linux系統支援的網路協議族有pf_unix,pf_ipx,pf_packet等幾十種;type為套接字型別, 目前有sock_stream、sock_dgram、sock_raw、sock_packet等;protocol是套接字所用的特定協議型別號.

linux 系統提供的基於資料鏈路層開發應用程式的介面整合在套接字中,它是通過建立packet型別的套接宇.使應用程式可直接在資料鏈路層接收或傳送未被系統處理的原始的資料報文(如arp報文),使用者也可以使用packet型別的套接宇在物理層上定義自己特殊的網路協議。只有註冊號為0的使用者(超級使用者)程序才能建立或開啟用於訪問網路低層的套接字.在linux系統中,用以下三種方式建立的packet套接字可直接用於訪問資料鏈路層:

(1)pf_inet協議族中sock_packei型別的套接字

(2)pf_packet協議族中sock_raw型別的套接字

(3)pf_packet協議族中sock_dgram型別的套接字

linux 2.0中對資料鏈路層的操作主要使用sock_packet定義的packet套接字.初始化定義如下:

sockfd=socket(af_inet,sock_packet,protocol);

其中,protocol用於決定套接字所使用的物理層協議(在ieee802.3中定義).筆者在此選擇常用的物理層協議eth_p_ip(internet協議).sock_packet使用一種比較老的sockaddr_pkt資料結構來設定網路介面。

在linux 2 2中使用pf_packet代替sock_packet來定義packet套接字.這種套接字的初始化定義如下:

sockfd=socket(pf_packet,socket_type,protocol);

其中socket_type只能為sock_raw或sock_dgram,protocol為物理層通訊協議(同上)。sock_raw和 sock_dgram型別套接字使用一種與裝置無關的標準物理層位址結構sockaddr_ll,但具體操作的報文格式不同。sock_raw套接字直接向網路硬體驅動程式傳送(或從網路硬體驅動程式接收)沒有任何處理的完整資料報文(包括物理幀的幀頭),這就要求程式設計師必須了解對應裝置的物理幀幀頭結構,才能正確地裝載和分析報文。sock_dgram套接字收到的資料報文的物理幀幀頭會被系統自動去掉,同樣,在傳送時.系統將會根據 sockaddr_ll結構中的目的位址資訊為資料報文舔加乙個臺適的物理幀幀頭。

預設情況下.從任何介面收到的符合指定協議的所有資料報文都會被傳送到packet套接字。使用bind系統呼叫以乙個sochddr_l1位址結構將paccket套接字與某個網路介面相繫結,可使套接字只接收指定介面的

struct sockaddr_ll

;一、利用pf_lnet協議族中sock_packet型別的套接宇實現arp

(1)建套接字

建立套接宇採用socket系統呼叫,格式如下:

sockfd=socket(pf_inet,sock_packet,htons(eth_p_arp));

(2)裝載報文

對於sock_packet型別的套接字,乙太網物理幀頭應作為所傳送報文一部分由程式設計師設定,物理幀頭的格式定義如下:(in /usr/include/linux/if_ether.h)

92 struct ethhdr

93 ;

實際傳送的位址解析報文幀由乙太網物理幀頭與幀資料(arp報文)共同組成,用結構體arppacket表

示如下:

typedef struct arppacket;

上述報文結構的裝載比較簡單。對arp部分,arp_header的設定如下:

ptk.arp_header.ar_hrd=htons(arphrd_ether); //arphrd_ether is defined in linux/if_arp.h

ptk.arp_header.ar_pro=htons(ethertype_ip);

ptk.arp_header.ar_hln=6;

ptk.arp_header.ar_pln=4;

ptk.arp_header.ar_op=htons(arpop_request);

pkt.arp_header.ar_sha、 pkt.arp_header.ar_sip、pkt_arp_header.ar_tip分別填入本機的實體地址、ip位址和要解析的對方主機的ip位址.返回報文中pkt.arp_header.tha中的內容就是解析

得到的對方主機的實體地址。

對於乙太網幀頭部分,pkt.eth_header.h_dest為目的位址,即廣播實體地址0xffffff, pkt.eth_header.source為本機實體地址(同pkt.arp_header.ar_sha),

pkt.eth_header.h_proto賦值htons(ethertype_arp)表示為位址解析型別報文。

ethertype_arp與eth_p_arp的值都是0x0806,只是定義的檔案不同。前者定義在net/ethernet.h,後者定義在linux/if_ether.h

(3)報文的傳送與接收

在資料鏈路層傳送/接收報文與在ip層傳送/接收資料報文類似,分別用系統呼叫sendto()和recvfrom()

struct sockaddr to,from;

int fromlen=0;

strcpy(to.sa_data,"eth0");

sendto(sockfd,pkt,sizeof(struct arppacket),0,&to,sizeof(struct sockaddr));

recvfrom(sockfd,buf,packet_size,0,&from,&fromlen);

其中buf為包含結構體arppacket的字元型指標。

通過檢驗所接收到的arp應答報文中arp_header.ar_op項是否為arpop_reply(arp應答)同時arp_header.ar_tip是否為已知的對方主機的ip位址來判斷所得到的解析位址是否正確.

二、利用pf_packet協議族中sock_raw型別的套接字實現arp

(1)建立套接字

sockfd=socket(pf_packet,sock_raw,htons(eth_p_arp));

(2)裝載報文

與sock_packet型別的套接字相同,sock_raw型別的套接字對鏈路層操作時,也要求乙太網物理幀頭應作為所傳送報文一部分由程式設計師設定.

(3)報文的傳送與接收

sock_raw型別套接字使用標準的物理層位址結構sockaddr_ll,所以,報文傳送之前,應將套接字繫結到(使用bind()系統呼叫)配置好的本地實體地址結構my_etheraddr,同時還需配置目的實體地址結構broad_etheraddr.

示例如下:

struct aockaddr_ll my_etheraddr,broad_etheraddr;

my_etheraddr.sll_family=af_packet;

my_etheraddr.sll_protocol=htons(eth_p_arp);

my_etheraddr.sll_ifindex=2; /*介面號2表示是eth0*/

my_etheraddr.sll_hatype=arphrd_ether;

my_etheraddr.sll_pkttype=packet_host;

my_etheraddr.sll_halen=eth_alen;

my_etheraddr.sll_addr[8]中放入本主機的實體地址。

broad_etheraddr的配置除了sll_pkttype取packet_broadcast和sll_addr取廣播實體地址(0xffffff)外,其他選項與my_etheraddr配置相同。

繫結格式如下:

bind(sockfd,(struct sockaddr *)&my_etheraddr,sizeof(my_etheraddr));

傳送與接收呼叫程式如下:

sendto(sockfd,buf,sizeof(struct arppacket),0,

(struct sockaddr *)&broad_etheraddr,sizeof(broad_etheraddr));

recvform(sockfd,buf,packet_size,&from,&fromlen);

三、利用pf_packet協議族中sock_dgram型別的套接字實現arp

sock_dgram型別的套接字不要求程式設計師配置乙太網幀頭,所以所傳送的報文只有資料區(arp報文)部分,其它與sock_raw型別的套接字相同。

go 鏈路追蹤 go micro 鏈路追蹤

本片介紹go micro中使用jaeger作為鏈路追蹤的使用 jaeger相關知識請見官方文件,這裡使用docker啟動gaeger,作為測試使用 啟動jaeger docker run d p 6831 6831 udp p 16686 16686 jaegertracing all in one...

鏈路狀態路由協議OSPF 虛鏈路(三)

1 ospf虛鏈路 a 當非主幹區域與主幹區域area0不連續時必須建立虛鏈路 b 虛鏈路配置 area area id virtual link router id area id 指虛鏈路經過的中轉區的區域id router id 指定虛鏈路另一端的路由器id 拓撲如下 r1配置 conf t ...

mac 思科 鏈路聚合 鏈路聚合的配置

使用者需求 某學校網路拓撲圖如圖所示,交換機s1和s2互連的鏈路需要較大的頻寬,怎樣用比較經濟的方式提高交換機s1和s2互連鏈路的頻寬?鏈路聚合能夠使用兩台裝置之間的多個物理鏈路建立一條個邏輯鏈路,物理鏈路之間能夠進行負載共享,而不是通過stp來阻塞一條個或多條個鏈路。乙太網通道 etherchan...