我正在编写一些使用IP / UDP数据包进行通信的代码。因此,我需要能够计算两个标头的校验和。我的标题结构如下:
/* Internet protocol v4 header */
typedef struct {
uint8_t ip_ver_hl; /* ip v4, header length = 5 32 bit words */
uint8_t ip_tos; /* type of service */
uint16_t ip_len; /* total length in bytes (ip header + data) */
uint16_t ip_id; /* identification */
uint16_t ip_off; /* fragment offset field */
#define IP_DF 0x4000 /* dont fragment flag */
#define IP_MF 0x2000 /* more fragments flag */
#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
uint8_t ip_ttl; /* time to live */
uint8_t ip_proto; /* layer 4 protocol */
uint16_t ip_checksum; /* ip header checksum */
uint32_t ip_src; /* ip source address */
uint32_t ip_dst; /* ip destination addresss */
} ttev_ip_header_t;
/* Pseudo header used to calculate udp checksum */
typedef struct {
uint32_t ip_src; /* ip source address */
uint32_t ip_dst; /* ip destination addresss */
uint8_t zero; /* placeholder = 0 */
uint8_t ip_proto; /* layer 4 protocol = udp */
uint16_t udp_len; /* total length in bytes (header + data) */
} ttev_udp_pseudo_t;
/* User datagram protocol header */
typedef struct {
uint16_t udp_src_port; /* source port */
uint16_t udp_dst_port; /* destination port */
uint16_t udp_len; /* total length in bytes (udp header + data) */
uint16_t udp_checksum; /* udp header/data checksum */
} ttev_udp_header_t;
现在我的实际通用校验和功能非常有效。但是,由于结构没有打包,所以我不会打开错误,因为在对标题进行校验时,结构成员之间可能存在填充?我想避免使用 attribute ((packed))来保持可移植性。
除了校对结构中的每个16位组之外,还有其他选择吗?
答案 0 :(得分:0)
UDP和IP数据包标头的结构使它们与C的对齐方式相匹配。因此,只要uint8_t
和uint16_t
实际上是8位和16位宽(分别),那么在整个结构上永远不会有任何添加的填充和逐字校验和将是正常的
基本上,对齐意味着每个字段都在与其大小或机器的自然字大小相匹配的边界上开始(以较小者为准)。结构本身被填充为所有字段中最大对齐的倍数。