dns客户端实现中格式错误的数据包

时间:2018-01-31 17:38:12

标签: c unix

您好,我正在开发一个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名称存储在数据包中,或者实现中存在错误。抱歉没时间,对不起我的英语。非常感谢

1 个答案:

答案 0 :(得分:0)

我终于解决了。更好地研究引用位于此link的协议1(域名系统),错误的部分在名为qname的部分中(在我的情况下,协议1无法确定的主机名称)尺寸) 所以文件说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 一切正常