linux原生以太网套接字绑定到特定的协议

我正在编写代码在两个Linux机器之间发送原始以太网帧。 为了testing这个我只想得到一个简单的客户端发送和服务器接收。

我有客户端正确的数据包(我可以看到他们使用数据包嗅探器)。

在服务器端我像这样初始化套接字

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

其中MY_ETH_PROTOCOL是一个2字节的常量,我使用ethertype,所以我没有听到多余的networkingstream量。

当我把这个套接字绑定到我的接口时,我必须在socket_addr结构中再次传递一个协议: socket_address.sll_protocol = htons(MY_ETH_PROTOCOL);
如果我编译并运行这样的代码,那么它会失败。 我的服务器没有看到数据包。 但是,如果我改变这样的代码:
socket_address.sll_protocol = htons(ETH_P_ALL);
服务器然后可以看到从客户端发送的数据包(以及许多其他数据包),所以我必须做一些检查数据包,看看它匹配MY_ETH_PROTOCOL

但我不希望我的服务器听到指定协议上未发送的stream量,所以这不是一个解决scheme。 我该怎么做呢?

我已经解决了这个问题。

根据http://linuxreviews.org/dictionary/Ethernet/参考MAC地址后面的2字节字段:

“64到1522之间的字段的值表示使用具有长度字段的新的802.3以太网格式,而1536十进制(0600十六进制)和更大的值表示使用具有EtherType子版本的原始DIX或以太网II帧格式 – 协议标识符“。

所以我必须确保我的ethertype> = 0x0600。

根据http://standards.ieee.org/regauth/ethertype/eth.txt使用0x88b5和0x88b6是“可供公众使用的原型和供应商特定的协议开发”。 所以这就是我将用作ethertype。 我不需要任何进一步的过滤,因为内核应该确保只使用正确的目标MAC地址来访问以太网帧并使用该协议。

过去我使用数据包过滤器来解决这个问题。

挥手 (未经测试的伪代码)

 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 。