2010-07-29 28 views
7

我正在編寫代碼發送兩個Linux機器之間的原始以太網幀。爲了測試這個,我只想得到一個簡單的客戶端發送和服務器接收。linux原生以太網套接字綁定到特定的協議

我有客戶端正確的數據包(我可以看到他們使用數據包嗅探器)。

在服務器端,我初始化套接字像這樣:

fd = socket(PF_PACKET, SOCK_RAW, htons(MY_ETH_PROTOCOL)); 

其中MY_ETH_PROTOCOL是2字節常量我使用的以太網類型,所以我沒有聽到無關的網絡流量。

當我綁定此套接字我界面,我必須在socket_addr結構再次傳遞一個協議: socket_address.sll_protocol = htons(MY_ETH_PROTOCOL);
如果我編譯和運行這樣的代碼,然後它失敗。我的服務器沒有看到數據包。但是,如果我改變,像這樣的代碼:
socket_address.sll_protocol = htons(ETH_P_ALL);
然後,服務器可以看到從客戶端發送的數據包(以及許多其它數據包),所以我要做的分組的一些檢查,看看它匹配MY_ETH_PROTOCOL

但我不希望我的服務器聽到指定協議上未發送的流量,因此這不是解決方案。我該怎麼做呢?

+0

您可以將代碼粘貼到您設置'socket_address'的地方嗎? – bstpierre 2010-07-29 21:58:06

回答

5

我已解決該問題。

根據http://linuxreviews.org/dictionary/Ethernet/參照2字節字段之後的MAC地址:

「64和1522之間的字段的值所指示的使用,用一個長度字段中的新802.3以太網格式的,而1536十進制(0600十六進制)和更大的值表示使用具有EtherType子協議標識符的原始DIX或以太網II幀格式。「

所以我必須確保我的ethertype> = 0x0600。

根據http://standards.ieee.org/regauth/ethertype/eth.txt使用0x88b5和0x88b6是「可供公共用於原型和供應商特定的協議開發」。所以這就是我將用來作爲ethertype。我不需要任何進一步的過濾,因爲內核應該確保只使用正確的目標MAC地址來接收以太網幀並使用該協議。

+0

我已經照你說的去做了。但是我的客戶端無法收到指定的協議包。你能粘貼你的代碼嗎?謝謝!電子郵件:[email protected] – 2014-08-20 02:41:05

0

我在過去通過使用數據包過濾器解決了此問題。

擺手(未經測試的僞代碼)

struct bpf_insn my_filter[] = { 
    ... 
} 

s = socket(PF_PACKET, SOCK_DGRAM, htons(protocol)); 
struct sock_fprog pf; 
pf.filter = my_filter; 
pf.len = my_filter_len; 
setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER, &pf, sizeof(pf)); 

sll.sll_family = PF_PACKET; 
sll.sll_protocol = htons(protocol); 
sll.sll_ifindex = if_nametoindex("eth0"); 

bind(s, &sll, sizeof(sll)); 

錯誤檢查和獲取數據包過濾器右側就留給讀者做練習...

根據您的應用程序,可能更容易工作的替代品是libpcap

相關問題