您好,我正在开发一个unix系统上的小型DNS客户端。 我已经阅读了关于dns协议的文档,我写了一个小函数
int makeQuestion(char* dns_addr,char *name){
int s = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
register int len_name = strlen(name);
if(s<0)
return errno;
struct sockaddr_in address;
bzero(&address,sizeof(address));
address.sin_port = htons(53);
address.sin_addr.s_addr = inet_addr(dns_addr);
dns_header header;
memset(&header,0,sizeof(dns_header));
header.id = htons(getpid());
header.q_count = htons(1);
dns_question quest = {
.qclass = htons(IN),
.qtype = htons(A)
};
register int pack_size = sizeof(dns_header)+len_name+2+sizeof(dns_question);
char *packet = malloc(pack_size);
memcpy(packet,&header,sizeof(dns_header));
for(int i = 0;i<len_name;i++)
*(packet +i +sizeof(dns_header)) = name[i];
packet[len_name+sizeof(dns_header)] = '.';
packet[len_name+sizeof(dns_header)+1] = '\0';
memcpy(packet+sizeof(dns_header)+len_name+2,&quest,sizeof(dns_question));
sendto(s,packet,pack_size,NULL,&address,sizeof(address));
return OK;
}
dns标头和dns查询的结构声明为:
//DNS header structures
typedef struct dns_header
{
uint16_t id; // identification number
uint8_t rd :1; // recursion desired
uint8_t tc :1; // truncated message
uint8_t aa :1; // authoritive answer
uint8_t opcode :4; // purpose of message
uint8_t qr :1; // query/response flag
uint8_t rcode :4; // response code
uint8_t cd :1; // checking disabled
uint8_t ad :1; // authenticated data
uint8_t z :1; // its z! reserved
uint8_t ra :1; // recursion available
uint16_t q_count; // number of question entries
uint16_t ans_count; // number of answer entries
uint16_t auth_count; // number of authority entries
uint16_t add_count; // number of resource entries
}dns_header;
typedef struct dns_question
{
uint16_t qtype;
uint16_t qclass;
}dns_question;
现在我在wireshark运行的时候执行了代码,我看到了看似正确的数据包但是在查询部分wirehark说
Name: <Unknown extended label>
所以问题是我必须使用一种方法将查询主机的dns名称存储在数据包中,或者实现中存在错误。抱歉没时间,对不起我的英语。非常感谢
答案 0 :(得分:0)
a domain name represented as a sequence of labels, where
each label consists of a length octet followed by that
number of octets. The domain name terminates with the
zero length octet for the null label of the root. Note
that this field may be an odd number of octets; no
padding is used.
所以我改变了我的代码以在3www7example3com中转换www.example.com 一切正常