Kane
Kane

Reputation: 43

Endian issue with casting a packet to a struct

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?

Upvotes: 2

Views: 603

Answers (2)

Shane Alcock
Shane Alcock

Reputation: 51

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.

Upvotes: 0

TangXC
TangXC

Reputation: 67

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

Upvotes: 1

Related Questions