所以,我有一个程序来嗅探数据包,到目前为止它一直很好用 . 我现在正在尝试添加其他功能,但是当我尝试解码捕获的数据包的以太网头的ethertype时,我一直遇到问题 . 为了隔离发生错误的位置,我编写了一个修改过的程序,仅以十六进制转储以太网头,然后使用自定义头解码源MAC地址,目标MAC地址和ethertype,但这是输出:

Sniffing on device wlan0
308 BYTE PACKET
01 00 5e 00 00 fb 04 e5 36 4a 5d 3a 08 00       | ..^.....6J]:..
SRC 01:00:5e:00:00:fb DST 04:e5:36:4a:5d:3a TYPE 0000
328 BYTE PACKET
33 33 00 00 00 fb 04 e5 36 4a 5d 3a 86 dd       | 33......6J]:..
SRC 33:33:00:00:00:fb DST 04:e5:36:4a:5d:3a TYPE ff11
194 BYTE PACKET
01 00 5e 00 00 fb 04 e5 36 4a 5d 3a 08 00       | ..^.....6J]:..
SRC 01:00:5e:00:00:fb DST 04:e5:36:4a:5d:3a TYPE 0000
Captured 3 packets

显然,程序解码MAC地址没有问题,MAC地址是十四字节头的前十二个字节,但由于某种原因,当它到达包含ethertype的最后两个字节时,程序无法正确显示它们 . 第一个和第三个数据包的ethertypes是0x0800,或IP,第二个数据包的ethertype是0x86dd,或IPv6 . 我尝试以多种格式显示ethertype,但没有一个产生适当的结果 .

这些是负责显示MAC地址和ethertype的代码行:

ethernet_header = (const struct sniff_ethernet_hdr *)packet;
printf ("SRC %02x", ethernet_header->ether_shost[0]);
for (i = 1; i < ETH_ALEN; i++)
    printf (":%02x", ethernet_header->ether_shost[i]);
printf (" DST %02x", ethernet_header->ether_dhost[0]);
for (i = 1; i < ETH_ALEN; i++)
    printf (":%02x", ethernet_header->ether_dhost[i]);
printf (" TYPE %.4x", ethernet_header->ether_type);
printf ("\n");

有没有人有任何建议或注意代码有任何问题?

编辑:我继续玩这个程序,我发现了一些奇怪的东西 . 我设置了一个名为eth_ptr的指针,指向数据包的第13个字节,其中ethertype开始 . 当我取消引用这个指针并打印结果时,它确实是ethertype的第一个字节 . 因此,我在程序中添加了一行,用于打印eth_ptr的地址和以太网头结构的ethertype . 这些是结果:

Sniffing on device wlan0
104 BYTE PACKET
01 00 5e 00 00 fb 04 e5 36 4a 5d 3a 08 00       | ..^.....6J]:..
SRC 01:00:5e:00:00:fb DST 04:e5:36:4a:5d:3a TYPE 8
eth_ptr @ 0x7ffafd0b1944 ether_type @ 0x7ffafd0b194c
124 BYTE PACKET
33 33 00 00 00 fb 04 e5 36 4a 5d 3a 86 dd       | 33......6J]:..
SRC 33:33:00:00:00:fb DST 04:e5:36:4a:5d:3a TYPE 86
eth_ptr @ 0x7ffafd0b1944 ether_type @ 0x7ffafd0b194c
319 BYTE PACKET
01 00 5e 00 00 fb 04 e5 36 4a 5d 3a 08 00       | ..^.....6J]:..
SRC 01:00:5e:00:00:fb DST 04:e5:36:4a:5d:3a TYPE 8
eth_ptr @ 0x7ffafd0b1944 ether_type @ 0x7ffafd0b194c
Captured 3 packets
$ gdb -q
(gdb) p /x 0x7ffafd0b194c - 0x7ffafd0b1944
$1 = 0x8

正在打印的类型实际上是解除引用的指针,它指向ethertype的第一个字节 . 该指针位于内存中ethernet_header-> ether_type之前的八个字节;因此,问题是结构的ethertype元素位于它应该位于的前面八个字节 . 我不知道为什么会这样,或者如何解决这个问题 . 任何人都可以提供解释吗?

再次编辑:嗯,我是个傻瓜 . 我只是仔细看看以太网头结构:

struct sniff_ethernet_hdr
{
    uint8_t ether_shost[ETH_ALEN];
    uint8_t ether_dhost[ETH_HLEN];
    uint16_t ether_type;
} __attribute__ ((__packed__));

宏:

#define ETH_ALEN        6
#define ETH_HLEN        14

在我解决了这个粗心的错误之后,程序运行得很完美 .