C语言 DNS 客户端实现中的格式错误的数据包



嗨,为了好玩,我正在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] = '';
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 运行时执行了代码,我看到了似乎正确的数据包,但在查询部分 wireshark 说

Name: <Unknown extended label>

所以问题是我必须使用一种方法将查询主机的 dns 名称存储在数据包中,或者实现中存在错误。很抱歉浪费时间,也为我的英语感到抱歉。确实谢谢

我终于解决了。更好地研究协议(域名系统(,其中引用在此链接中,错误的部分在名为qname的部分(主机的名称,在我的情况下协议无法确定大小(所以正如文件所说,qname是:

 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一切正常

最新更新