2010-07-29 26 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

相关问题