i trying to parse a packet. till the ip header everything is fine(i’m able to retrieve all the values correctly). but for the udp header( checked if the protocol is 17) , the values are coming out to be wrong( all the 4 fields).
I’m trying to do this:
struct udp_header{
uint16_t sport;
uint16_t dport;
uint16_t len;
uint16_t chksum;
};
struct udp_header* udp= (struct udp_header*)(packet + 14 + ip_hdr->ip_hl*4);
Packet is the pointer pointing to the beginning of the packet. 14 is for ethernet header.The header length ip when checked is giving out the correct value. But after performing this operation i’m getting all the fields wrongly. when tried with uint8_t as data type( i know its wrong! ) the destintion port somehow is coming out correct.
You have run into endianness. IP packets have all fields in network byte order (aka “big-endian”), and your host system probably runs little-endian. Look into
ntohs()and friends for one approach.The proper approach is to not copy the structure as-is from the network data, but instead extract each field manually and byte-swap it if necessary. This also works around any issues with padding and alignment, there’s no guarantee that your
structis mapped into your computer’s memory in exactly the same way as the packet is serialized.So you would do e.g.:
This is also a bit iffy, since it assumes the resulting address can validly be cast into a pointer to
unsigned short. On x86 that will work, but it’s not epic.Even better, in my opinion, is to drop the use of pointers and instead write a function called e.g.
unsigned short read_u16(void *packet, size_t offset)that extracts the value byte-by-byte and returns it. Then you’d just do: