7

我正在编写代码以在两个 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

但我不希望我的服务器听到未通过指定协议发送的流量,因此这不是解决方案。我该怎么做呢?

4

2 回答 2

5

我已经解决了这个问题。

根据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 是“可用于原型和供应商特定协议开发的公共用途”。所以这就是我将用作以太类型的东西。我不需要任何进一步的过滤,因为内核应该确保只拾取具有正确目标 MAC 地址并使用该协议的以太网帧。

于 2010-07-30T13:12:17.013 回答
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

于 2010-07-29T22:16:51.897 回答