我最近一直在用ESP8266开发wifi嗅探器,为了嗅探wifi数据包,有一个名为wifi_set_promiscuous_rx_cb(wifi_sniffer_packet_handler)的函数,它接受一个回调函数作为参数,并传递缓冲区指针,该指针将数据包信息和数据包长度作为参数传递给回调函数,wifi_sniffer_packet_handler(uint8_t *buff, uint16_t len)是回调函数。我不明白这两个语句在做什么,const wifi_promiscuous_pkt_t *ppkt = (wifi_promiscuous_pkt_t *)buff; const wifi_ieee80211_packet_t *ipkt = (wifi_ieee80211_packet_t *)ppkt->payload; wifi_promiscuous_pk_t是一个结构
typedef struct{
wifi_pkt_rx_ctrl_t rx_ctrl; /**< metadata header */
uint8_t payload[0]; /**< Data or management payload. Length of payload is described by rx_ctrl.sig_len. Type of content determined by packet type argument of callback. */
} wifi_promiscuous_pkt_t;而wifi_ieee80211_packet_t是另一种结构
typedef struct
{
wifi_ieee80211_mac_hdr_t hdr;
uint8_t payload[2]; /* network data ended with 4 bytes csum (CRC32) */
} wifi_ieee80211_packet_t;*buff中的数据是如何分配给这些结构的,上面的语句是负责分配的吗?我已经看到许多关于堆栈溢出的问题和许多其他关于这个问题的帖子,但没有一个帖子澄清了我的疑问
发布于 2021-06-04 17:28:40
来自无线电的数据包可能具有如下格式:
| metadata | mac hdr | mac payload |它最初存储为buff指向的uint8_t数组。
现在,将buffer类型转换为第一个结构类型:
const wifi_promiscuous_pkt_t *ppkt = (wifi_promiscuous_pkt_t *)buff;这就是我们的buffer现在概念上的样子:
|<---------------------- buff ---------------------->| buff
|<-- rx_ctrl -->|<------- payload ------------------>| ppkt 该结构覆盖在字节数组的顶部,由于元数据始终是固定大小的,因此ppkt->rx_ctrl现在将包含此元数据头。
但是有效载荷呢?该声明指示有效负载为零大小的数组。这是一种特殊的语法,用于告诉编译器这是一个任意大的用户管理内存数组的“占位符”。(请注意,这是一个过时的GCC扩展,可能会在大多数现代编译器上产生编译错误。post C99方法是简单地省略数组维数,如下所示:uint8_t payload[])
因此,ppkt->payload现在是一个从元数据之外的第一个字节开始的数组。因为C不需要进行边界检查,所以您可以使用ppkt->payload[i]访问此有效负载的任何字节
现在,我们需要通过解析出mac报头来获得mac有效负载,该报头也是固定大小的。这是通过以下方式实现的:
const wifi_ieee80211_packet_t *ipkt = (wifi_ieee80211_packet_t *)ppkt->payload;在这种情况下,我们丢弃报头(rx_ctrl)并将wifi_ieee80211_packet_t结构覆盖在缓冲区的有效负载部分之上。
再次查看我们的缓冲区,这是它发生的情况:
|<---------------------- buff ---------------------->| buff
|<-- rx_ctrl -->|<------- payload ------------------>| ppkt
|<-- hdr -->|<----- payload -------->| ipkt现在,您可以使用ipkt->payload轻松访问原始数据包中的mac有效负载。
这是在分析网络协议栈中的数据包时使用的一种非常常见的习惯用法。
PS:但是,请注意,不兼容类型之间的类型转换是有风险的。首先,您必须了解并说明结构构件的对齐情况。此外,根据您的结构是如何定义的,这可能会导致违反严格的别名规则,从而在某些编译器上调用未定义的行为。
发布于 2021-10-12 16:33:17
当我使用这个结构时:
|<-- rx_ctrl -->|<------- payload ------------------>|通过向左移动2个字节,我得到了有效负载数据中的未对齐。当我将rx_ctrl部件替换为字段时,例如unsigned frame_ctrl:16,我看不到这种变化。我必须将frame_ctrl类型转换为rx_ctrl才能获得详细信息。
我假设这是因为我使用了esp32-S2,它假定rx_ctrl是32位,而不管它的定义是16位。
https://stackoverflow.com/questions/67834512
复制相似问题