sock_raw

理解一下SOCK_RAW的原理, 比如網卡收到了一個 14+20+8+100+4(乙太網頭+ip頭+udp頭+數據+crc) 的udp的乙太網數據幀.

sock_raw使用

(注意一定要在root下使用)原始套接字編程可以接收到本機網卡上的數據幀或者數據包,對與監聽網路的流量和分析是很有作用的.一共可以有3種方式創建這種socket

1.socket(AF_INET, SOCK_RAW, IPPROTO_TCP|IPPROTO_UDP|IPPROTO_ICMP)傳送接收ip數據包,不能用IPPROTO_IP,因為如果是用了IPPROTO_IP,系統根本就不知道該用什麼協定。

2.socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP|ETH_P_ARP|ETH_P_ALL))傳送接收乙太網數據幀

3.socket(AF_INET, SOCK_PACKET, htons(ETH_P_IP|ETH_P_ARP|ETH_P_ALL))過時了,不要用啊

內容

協定類型

socket(AF_INET, SOCK_RAW, IPPROTO_UDP);

能:該套接字可以接收協定類型為(tcp udp icmp等)發往本機的ip數據包,從上面看的就是20+8+100.

不能:不能收到非發往本地ip的數據包(ip軟過濾會丟棄這些不是發往本機ip的數據包).

不能:不能收到從本機傳送出去的數據包.

傳送的話需要自己組織tcp udp icmp等頭部.可以setsockopt來自己包裝ip頭部

這種套接字用來寫個ping程式比較適合

2. socket(PF_PACKET, SOCK_RAW, htons(x));

這個套接字比較強大,創建這種套接字可以監聽網卡上的所有數據幀.從上面看就是14+20+8+100.最後一個乙太網crc從來都不算進來的,因為核心已經判斷過了,對程式來說沒有任何意義了.

能: 接收發往本地mac的數據幀

能: 接收從本機傳送出去的數據幀(第3個參數需要設定為ETH_P_ALL)

能: 接收非發往本地mac的數據幀(網卡需要設定為promisc混雜模式)

協定類型一共有四個

ETH_P_IP 0x800 只接收發往本機mac的ip類型的數據幀

ETH_P_ARP 0x806 只接受發往本機mac的arp類型的數據幀

ETH_P_RARP 0x8035 只接受發往本機mac的rarp類型的數據幀

ETH_P_ALL 0x3 接收發往本機mac的所有類型ip arp rarp的數據幀, 接收從本機發出的所有類型的數據幀.(混雜模式打開的情況下,會接收到非發往本地mac的數據幀)

傳送的時候需要自己組織整個乙太網數據幀.所有相關的地址使用struct sockaddr_ll 而不是struct sockaddr_in(因為協定簇是PF_PACKET不是AF_INET了),比如傳送給某個機器,對方的地址需要使用struct sockaddr_ll.

示例代碼

......

int sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); // 創建Socket

struct sockaddr_ll sll; // 注意結構體是sockaddr_ll

memset( &sll, 0, sizeof(sll) );

sll.sll_family = AF_PACKET;

struct ifreq ifstruct;

strcpy(ifstruct.ifr_name, "eth0");

ioctl(sockfd, SIOCGIFINDEX, &ifstruct); //控制I/O設備

sll.sll_ifindex = ifstruct.ifr_ifindex;

sll.sll_protocol = htons(ETH_P_ALL);

if(bind(fd, (struct sockaddr *) &sll, sizeof(sll)) == -1 ) { //在這裡當然仍然需要綁定的

perror("bind()");

......

相關詞條

熱門詞條

聯絡我們