Я немного запутался в отношении выравнивания данных.На x86 мы обычно принимаем выравнивание как должное.Тем не менее, я программирую в системе, которая очень строгая и выдаст ошибку, если я попытаюсь получить доступ к невыровненным данным.
Вот моя проблема:
Сначала я покажу вамнекоторые структуры у меня есть:
struct sniff_ethernet {
u_char ether_dhost[6]; /* Destination host address */
u_char ether_shost[6]; /* Source host address */
u_short ether_type; /* IP? ARP? RARP? etc */
};
struct sniff_ip {
u_char ip_vhl; /* version << 4 | header length >> 2 */
u_char ip_tos; /* type of service */
u_short ip_len; /* total length */
u_short ip_id; /* identification */
u_short ip_off; /* fragment offset field */
u_char ip_ttl; /* time to live */
u_char ip_p; /* protocol */
u_short ip_sum; /* checksum */
struct in_addr ip_src,ip_dst; /* source and dest address */
};
Я имею дело с pcap.Pcap вернет мне указатель на пакет данных:
u_char *packet;
Предположим, пакет составляет пару сотен байтов.Обычно я выполняю приведение этого пакета к нескольким указателям структуры, чтобы я мог получить прямой доступ к данным.
struct sniff_ethernet *seth = (struct sniff_ethernet *) packet;
struct sniff_ip *sip = (struct sniff_ip *) (packet + 14); // 14 is the size of an ethernet header
Хорошо.Так что все выглядит отлично, верно?На x86 все работает нормально.На любой другой архитектуре, которая имеет строгое выравнивание, у меня возникают проблемы при доступе к некоторым значениям, и это обычно приводит к сигбусу.Например:
sip->ip_len = 0x32AA;
или
u_short val = sip->ip_len;
приводит к ошибке.Я предполагаю это, потому что это смещено в памяти от броска.Каков обычно лучший способ справиться с этим, выполняя такие броски?