JulianSchmid/etherparse

Confusion in payload sizes

Closed this issue · 5 comments

I'm working with ingesting packets from AF_PACKET and I'm running into some confusion in the sizes of the payload field.

I'm matching SlicedPacket::from_ethernet and if let-ing Some(Udp(header)), implying I get a valid UDP paylod (I think). But when I compare payload.len() and header.len() - 8 I get different values.

Specifically, my payloads are 8192 byte jumbo frames (which I see in wireshark and tcpdump). header.len() - 8 properly reports this, but payload.len() reports 8196 and 15956. I have no idea why sometimes it says 15956 (especially considering we've already destructured a valid payload) or why in the more normal looking case, it's 4 bytes bigger.

I'd appreciate any input. Thanks!

I'm wondering if this has to do with the AF_PACKET buffer potentially containing garbage

Hi @kiranshila,

Currently the payload field of a SlicedPacket just contains everything that was left over from the original slice you passed to SlicedPacket::from_ethernet after all headers have been separated. The length described in the UDP header and/or IP headers are currently ignored. Which probably explains what you are seeing.

I also ran into the same issue a few days ago (#35), and I will probably change the behavior in an upcoming version, so only the actual payload of the last header in present in the payload field. But I have to think about it a bit (especially if I want to also support jumbograms). Plus I have to find some time, and passed experiences have taught me to be careful with promises when it comes to timeframes. So no promises when or if it is going to happen.

In the mean time you can limit the payload size yourself by using the length in the UDP header:

let udp_payload = if let Some(Udp(udp)) = sliced.transport {
    let len = usize::from(udp.length());
    if len == 0 {
        // potential jumbogram
       None // TODO
    } else if len < UdpHeader::SERIALIZED_SIZE {
        // not enough data for the udp header itself
       todo!(); // return some error
    } else if sliced.payload.len() >= (len - UdpHeader::SERIALIZED_SIZE) {
        Some(&sliced.payload[UdpHeader::SERIALIZED_SIZE..len])
    } else {
        // not enough data in the slice return some kind of error
        todo!();
    }
} else {
    None
};

Greets
Julian

Hi,

I made an error in my example above: I forgot to take into account that the length of the header is also part of the length present in the UDP header.

I corrected the example, but it is untested, so now guarantees.

Greets
Julian

Fantastic work on the release Julian! Thank you so much!