结构体边界对齐问题

结构体边界对齐问题

在构造DNS应答包的Answer字段时,我定义了一个结构体,如下所示:

typedef struct{
    __u16 name;
    __u16 type;
    __u16 class;
    __u32 ttl;
    __u16 length;
    __u32 ipv4_addr;
}DNS_ANSWER_DATA;

但是在进行数据包的构造的时候,在测试时,发送的数据包总是从length字段开始出现错误,导致DNS数据报文最终不能被正确解析,原因在于结构体的边界对其原则。
在debug的时候发现,sizeof(DNS_ANSWER_DATA) = 20,按理来说应该为16。
C语言中边界对齐原则如下所示:

  • 原则1:普通数据成员对齐规则:第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小的整数倍开始(比如int在32位机为4字节,则要从4的整数倍地址开始存储)。
  • 原则2:结构体成员对齐规则:如果一个结构里有某些结构体成员,则该结构体成员要从其内部最大元素大小的整数倍地址开始存储。(struct a里存有struct b,b里有char,int,double等元素,那b应该从8的整数倍开始存储。)
  • 原则3:结构体大小对齐规则:结构体大小也就是sizeof的结果,必须是其内部成员中最大的对齐参数的整数倍,不足的要补齐。

根据我上面定义的结构体成员的顺序以及其大小可知,其在存储的时候存储结构如下图所示:
在64位系统:
在这里插入图片描述
在32位系统
在这里插入图片描述
因此在实验中,伪造的DNS报文的结构如下所示:
在这里插入图片描述
解决方式:参考博客:

https://blog.csdn.net/zhangxiong2532/article/details/50826917
https://wenku.baidu.com/view/96c2d256f01dc281e53af026.html

当不希望编译器对结构体做对齐处理,而希望按照他原有的大小分配空间时,这里就要用到 attribute((packed)) ,这个意思是告诉编译器不要做对齐处理。

#pragma pack(push,1)
typedef struct{	
	unsigned short a_name;
	unsigned short a_type;
	unsigned short a_class;
	unsigned int a_ttl;
	unsigned short a_data_len;
	unsigned int a_ipv4_addr;
}DNS_ANSWER_DATA;
#pragma pack(pop)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章