linux原生以太网套接字绑定到特定的协议
我正在编写代码发送两个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
。
但我不希望我的服务器听到指定协议上未发送的流量,因此这不是解决方案。我该怎么做呢?
我已解决该问题。
根据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地址来接收以太网帧并使用该协议。
我已经照你说的去做了。但是我的客户端无法收到指定的协议包。你能粘贴你的代码吗?谢谢!电子邮件:[email protected] – 2014-08-20 02:41:05
我在过去通过使用数据包过滤器解决了此问题。
摆手(未经测试的伪代码)
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。
您可以将代码粘贴到您设置'socket_address'的地方吗? – bstpierre 2010-07-29 21:58:06