Вы столкнулись с порядком байтов . IP-пакеты имеют все поля в порядке байтов в сети (он же «big-endian»), и ваша хост-система, вероятно, работает с прямым порядком байтов. Посмотрите на ntohs()
и друзей для одного подхода.
Правильный подход состоит в том, чтобы не копировать структуру как есть из сетевых данных, а вместо этого извлекать каждое поле вручную и заменять его, если необходимо. Это также решает любые проблемы с заполнением и выравниванием, нет никакой гарантии, что ваш struct
сопоставлен с памятью вашего компьютера точно так же, как пакет сериализуется.
Так вы бы сделали, например ::
udp_header.sport = ntohs(*(unsigned short*) (packet + 14 + 4 * ip_hdr->ip_hl));
Это также немного ненадежно, поскольку предполагается, что результирующий адрес может быть корректно приведен к указателю на unsigned short
. На x86 это будет работать, но не эпично.
Еще лучше, на мой взгляд, отказаться от использования указателей и вместо этого написать функцию под названием, например, unsigned short read_u16(void *packet, size_t offset)
, который извлекает побайтовое значение и возвращает его. Тогда вы просто сделаете:
udp_header.sport = read_u16(packet, 14 + 4 * ip_hdr->ip_hl);