標籤:網路編程 原始通訊端
通過《Linux網路編程——原始通訊端編程》得知,我們可以通過原始通訊端以及 recvfrom( ) 可以擷取鏈路層的資料包,那我們接收的鏈路層資料包到底長什麼樣的呢?
鏈路層封包格式
MAC 頭部(有線區域網路)
注意:CRC、PAD 在組包時可以忽略
鏈路層資料包的其中一種情況:
unsigned char msg[1024] = {//--------------組MAC--------14------0xb8, 0x88, 0xe3, 0xe1, 0x10, 0xe6, // dst_mac: b8:88:e3:e1:10:e60xc8, 0x9c, 0xdc, 0xb7, 0x0f, 0x19, // src_mac: c8:9c:dc:b7:0f:190x08, 0x00, // 類型:0x0800 IP協議// …… ……// …… ……};
接收的鏈路層資料包,並對其進行簡單分析:
#include <stdio.h>#include <string.h>#include <stdlib.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <netinet/ether.h>int main(int argc,char *argv[]){int i = 0;unsigned char buf[1024] = "";int sock_raw_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));while(1){unsigned char src_mac[18] = "";unsigned char dst_mac[18] = "";//擷取鏈路層的資料幀recvfrom(sock_raw_fd, buf, sizeof(buf),0,NULL,NULL);//從buf裡提取目的mac、源macsprintf(dst_mac,"%02x:%02x:%02x:%02x:%02x:%02x", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);sprintf(src_mac,"%02x:%02x:%02x:%02x:%02x:%02x", buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]);//判斷是否為IP資料包if(buf[12]==0x08 && buf[13]==0x00){printf("______________IP資料報_______________\n");printf("MAC:%s >> %s\n",src_mac,dst_mac);}//判斷是否為ARP資料包else if(buf[12]==0x08 && buf[13]==0x06){printf("______________ARP資料報_______________\n");printf("MAC:%s >> %s\n",src_mac,dst_mac);}//判斷是否為RARP資料包else if(buf[12]==0x80 && buf[13]==0x35){printf("______________RARP資料報_______________\n");printf("MAC:%s>>%s\n",src_mac,dst_mac);}}return 0;}
記得以管理者許可權運行程式:
原始碼下載請點擊此處。
Linux網路編程——原始通訊端執行個體:簡單版網路資料分析器