Endian issue with casting a packet to a struct

十年热恋 提交于 2019-12-11 00:59:23

问题


I'm using libtrace to parse network packets but am having, what I think is, an endian issue.

Here is the libtrace definition of a Radiotap packet:

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;

So I cast my libtrace_packet_t to this Radiotap struct and check the results:

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);

On my development machine, which is little endian, the Radiotap data from the packets in my pcap file is:

806959 0 72 806959

Which is correct. My development machine is successfully parsing the data I expect to see out of the pcap file.

When run on my production box, which is big endian, I see different values:

793775104 0 18432 793775104

Same packet within the same pcap file. Different Radiotap values. I suspect the issue is with the different endianness of the two machines. However, rtap.it_version is a uint8_t which, being single byte, shouldn't be affected by endian issues, no?


回答1:


That should be a endianness issue. For 72, the hex is 0x48, and it's a uint16_t, so in the different endianness that's 0x4800 = 18432. That's right. And for 806959 = 0xC502F, in the different endianness that's 0x2F50C000 = 793775104.

This may help:

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



回答2:


The header structures returned by libtrace point to the header as it appeared on the "wire", i.e. without any attempt to convert to host byte order.

Radiotap header fields are always little-endian (as opposed to conventional network byte order, which is big-endian) so you'll need to compensate for that if you are going to try and parse the header manually. Just using ntohl won't work, as this expects the value you are converting to be big-endian.

A better approach, however, would be to use the built-in libtrace functions for accessing various radiotap fields, e.g. trace_get_wireless_rate, trace_get_wireless_signal_strength_dbm and many others. These functions will do the byte order conversion based on your host architecture, so you don't have to worry about it.

As for your problem with struct ieee80211_frame_control, this looks like a bug. I'd recommend filing a bug ticket with the libtrace developers.



来源:https://stackoverflow.com/questions/18501516/endian-issue-with-casting-a-packet-to-a-struct

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!