我正在尝试使用 libpcap api 从捕获的 DNS 数据包中提取 DNS 查询,但是我的结构一定有问题,在最后一次转换(使用结构问题)之后char* name
指针指向正确的地址,查询名称的开头,但它只包含
42 45 20 00
但应该
20 45 48 45 50 45 50 45 48 45 4d 45 46 43 4f 45 44 45 50 45 4e 43 41 43 41 43
41 43 41 43 41 41 41 00 00 20 00 01
代码在这里
struct dnshdr{
uint16_t id;
uint16_t flags;
uint16_t ques;
uint16_t anRR;
uint16_t auRR;
uint16_t addRR;
};
struct question{
char * name;
uint16_t type;
uint16_t cls;
};
void packetProc(u_char *args, const struct pcap_pkthdr *header,const u_char *packet){
struct iphdr *IP_header;
struct udphdr *UDP_header;
struct dnshdr *DNS_header;
struct question *ques;
IP_header = (struct iphdr*) (packet + sizeof(struct ethhdr));
UDP_header = (struct udphdr*) (packet + sizeof(struct iphdr) + sizeof(struct ethhdr));
DNS_header = (struct dnshdr*) (packet + sizeof(struct iphdr) + sizeof(struct ethhdr) + sizeof(struct udphdr) );
ques = (struct question*) (packet + sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct udphdr) + sizeof(struct dnshdr)-1 ); //fatal
}
老实说我很困惑在这里做什么
struct question{
char * name;
uint16_t type;
uint16_t cls;
};
您使用此结构的方式无效。char *
是指向包含字符的内存位置的指针。 DNS 查询没有指向包含字符的计算机内存位置的指针值,该查询contains那些角色。然而 DNS 查询名称的长度(即char name[how much should be put here]
) 根据 udp 消息的长度计算。你可以:
struct question_after_name_s {
uint16_t type;
uint16_t cls;
};
...
const size_t namepos = 2*6; // name position in bytes form the beginning of the DNS query, this should be equal to 'sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct udphdr) + sizeof(struct dnshdr)-1 ' from your code
char *name = (char*)&packet[namepos]; // the pointer name should point to the location in packet after namepos bytes
const size_t packetlen = header->len; // I guess this is received DNS query length obtained from libcap
const size_t querytypeandclasslen = 2*2; // length of the query type and query class, should be equal to sizeof(struct question_after_name_s)
const size_t namelen = packetlen - namepos - querytypeandclasslen;
printf("DNS query name = '%.*s'\n", namelen, name);
struct question_after_name_s *ptr = (void*)&packet[namepos + namelen];
//or
struct question_after_name_s *ptr = (void*)&packet[];
当然,只有当您的编译器不在结构成员之间插入任何填充时,这种转换才是正确的(希望您使用 gcc 编译器attribute((packed))
在这些结构上)然后你打电话ntohl
家庭活动或be16toh
family 函数用于在数据包字节序和幽灵字节序之间进行转换。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)