【问题标题】:Endian issue with casting a packet to a struct将数据包转换为结构的字节序问题
【发布时间】:2013-08-30 06:12:43
【问题描述】:

我正在使用 libtrace 来解析网络数据包,但我认为这是一个字节序问题。

这是 Radiotap 数据包的 libtrace 定义:

typedef struct libtrace_radiotap_t {
    uint8_t     it_version; /**< Radiotap version */
    uint8_t     it_pad; /**< Padding for natural alignment */
    uint16_t    it_len; /**< Length in bytes of the entire Radiotap header */
    uint32_t    it_present; /**< Which Radiotap fields are present */
} PACKED libtrace_radiotap_t;

所以我将libtrace_packet_t 转换为这个 Radiotap 结构并检查结果:

link = (char *) trace_get_packet_buffer(packet, &linktype, NULL);

if (linktype != TRACE_TYPE_80211_RADIO)
    return;

rtap = (libtrace_radiotap_t *) link;

printf("%d %d %d %d\n", rtap->it_present, rtap->it_pad, rtap->it_len,
       rtap->it_present);

在我的小端开发机器上,来自我的 pcap 文件中数据包的 Radiotap 数据是:

806959 0 72 806959

这是正确的。我的开发机器正在成功解析我希望从 pcap 文件中看到的数据。

在我的大端生产盒上运行时,我看到不同的值:

793775104 0 18432 793775104

同一个 pcap 文件中的同一个数据包。不同的 Radiotap 值。我怀疑问题出在两台机器的不同字节序上。但是,rtap.it_version 是一个 uint8_t,它是单字节的,不应该受到字节序问题的影响,不是吗?

【问题讨论】:

  • 在这两种情况下,您的 8 位值 it_pad 打印相同:0。您正在打印it_present 两次。你没有打印it_version
  • 那是我的愚蠢。你解决了我的 Radiotap 问题。不过,这让我想到了另一个问题。将我的link 转换为Frame Control struct 时,我的两台机器显示fc.typefc.subtype 的两个不同值。这是 FC 结构中 uint8_t 的字节序问题吗?
  • POSIX 有htonlntohl 等接口用于在“网络”和“主机”字节序之间进行转换。

标签: c networking packet endianness


【解决方案1】:

这应该是字节顺序问题。 对于 72,十六进制是 0x48,它是一个 uint16_t,所以在不同的字节序中,0x4800 = 18432。没错。 而对于 806959 = 0xC502F,采用不同的字节顺序,即 0x2F50C000 = 793775104。

这可能会有所帮助:

#define T(x) (((x&0xff)<<24)|((x&0xff00)<<8)|((x&0xff0000)>>8)|((x&0xff000000)>>24))

【讨论】:

  • 所以。如果这是一个 16 位字节序问题(我同意它是),那么 32 位解决方案是什么? 16 位版本的密度将大大降低。
  • 我会说这是一个 16 位问题,对于 0x2F50C000 = 793775104 也是一个 32 位问题。
  • 我认为调整代码以适应 16 位问题并不难。但是我确实弄错了这个问题,它实际上是一个“8位”问题(请参阅问题下方的cmets)。 XD
【解决方案2】:

libtrace 返回的标头结构指向出现在“线路”上的标头,即没有任何尝试转换为主机字节顺序的尝试。

Radiotap 标头字段始终为小端(与传统的网络字节顺序相反,即大端),因此如果您要尝试手动解析标头,则需要对其进行补偿。仅使用 ntohl 是行不通的,因为这会期望您转换为大端的值。

然而,更好的方法是使用内置的 libtrace 函数来访问各种 radiotap 字段,例如trace_get_wireless_ratetrace_get_wireless_signal_strength_dbm 和许多其他人。这些函数会根据你的主机架构做字节序转换,所以你不用担心。

至于struct ieee80211_frame_control 的问题,这看起来像是一个错误。我推荐filing a bug ticket with the libtrace developers

【讨论】:

    猜你喜欢
    • 2020-10-19
    • 2020-09-09
    • 2011-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-05
    • 1970-01-01
    相关资源
    最近更新 更多