我正在尝试将 DNS 标头和问题发送到 UDP 套接字。我已经调用了以下命令来建立连接:socket(PF_INET, SOCK_DGRAM, 0),inet_aton(temp, &servAddr.sin_addr)使用端口 53 和connect(sock, (const sockaddr*) &servAddr, sizeof(servAddr))。
我遇到的问题是编写包含标头和 DNS 查询问题的消息。到目前为止,我的 DNS 标头结构如下所示:
struct DNS_Header {
uint16_t id;
struct {
uint8_t rd: 1; // recursion desired
uint8_t tc: 1; // message was truncated
uint8_t aa: 1; // authoritative answer
uint8_t opcode: 4; // query type
// 0 a standard query (QUERY); 1 an inverse query (IQUERY);
// 2 a server status request (STATUS);
// 3 - 15 reserved for futre use
uint8_t qr: 1; // query(0) or response (1)
uint8_t rcode: 4; // response code
// 0: No error condition; 1:Format error; 2:Server failure;
// 3: Name Error (authoritative server, name doesn't exist)
// 4: Not implemented; 5: Refused
uint8_t z: 3; // reserved for future use. Must be zero
uint8_t ra: 1; // recursion
} flags;
uint16_t gdcount;
uint16_t ancount;
uint16_t nscount;
uint16_t arcount;
};
我创建 DNS 查询标头:
packetHeader.id = htons(1337);
packetHeader.flags.rd = 0;
packetHeader.flags.tc = 0;
packetHeader.flags.aa = 0;
packetHeader.flags.opcode = htons(0);
packetHeader.flags.qr = 0;
packetHeader.flags.rcode = htons(0);
packetHeader.flags.z = htons(0);
packetHeader.flags.ra = 0;
packetHeader.gdcount = htons(1);
packetHeader.ancount = htons(0);
packetHeader.nscount = htons(0);
packetHeader.arcount = htons(0);
我知道我需要将主机名更改为 DNS 问题名称部分的标签/数据格式。我是这样做的:
static const char* const hex = "0123456789ABCDEF";
hostname.push_back(' ');
int len = hostname.length();
int segCount = 0;
std::vector<std::string> storage;
std::string temp = "";
for (int i = 0; i < len; i++) {
if (hostname[i] == '.' || hostname[i] == ' ') {
storage.push_back(std::to_string(0));
storage.push_back(std::to_string(segCount));
storage.push_back(temp);
// reset
segCount = 0;
temp = "";
continue;
}
const unsigned char c = hostname[i];
std::cout << c << " : " << hex[c >> 4] << " " << hex[c & 15] << std::endl;
temp.push_back(hex[c >> 4]);
temp.push_back(hex[c & 15]);
segCount ++;
continue;
}
storage.push_back(std::to_string(0));
storage.push_back(std::to_string(0));
for (int i = 0; i < storage.size(); i++) { qname_labelFormat.append(storage[i]); }
std::cout << "The hex representation of qname TOTAL: " << qname_labelFormat << std::endl
我使用 DNS_Question 结构将 DNS 查询问题的所有内容放在一起。此结构不包括 DNS 查询问题名称。我将名称存储在变量中:qname_lableFormat. 查看下面的 DNS 查询问题结构:
struct DNS_Question {
uint16_t qtype;
uint16_t qclass;
};
为了填充结构 DNS_Question,我这样做了:
int queryTypeNum = 0;
if (queryType == "A") { queryTypeNum = 1; }
if (queryType == "NS") { queryTypeNum = 2; }
if (queryType == "CNAME") { queryTypeNum = 5; }
if (queryType == "SOA") { queryTypeNum = 6; }
if (queryType == "WKS") { queryTypeNum = 11; }
if (queryType == "PTR") { queryTypeNum = 12; }
if (queryType == "MX") { queryTypeNum = 15; }
if (queryType == "SRV") { queryTypeNum = 33; }
if (queryType == "AAAA") { queryTypeNum = 28; }
if (queryType == "") { queryTypeNum = 1; }
packetQuestion.qtype = htons(queryTypeNum);
std::cout << "QType value set to: " << queryTypeNum << std::endl;
packetQuestion.qclass = htons(1);
在我完成所有这些之后,我使用套接字,write(int fd, const void *buf, size_t count);我相信这是我的错误发生的地方。没有报告错误消息,但是当我调用read(int fd, void *buf, size_t count);命令时,没有收到任何内容。我的写命令如下。
int size = sizeof(struct DNS_Header);
size += sizeof(struct DNS_Question);
char *message [size];
int totalSize = 0;
int stringSize = qname_labelFormat.length() + 1;
char* temp = {0};
temp = (char*)qname_labelFormat.c_str();
std::memcpy(message, (struct DNS_Header*)&packetHeader, sizeof(packetHeader));
totalSize = sizeof(struct DNS_Header);
std::memcpy(message + totalSize, (char*)temp, sizeof(qname_labelFormat));
totalSize += sizeof(qname_labelFormat);
std::memcpy(message + totalSize, (struct DNS_Question*)&packetQuestion, sizeof(packetQuestion));
totalSize += sizeof(packetQuestion);
int bytesSent = 0;
if ((bytesSent = write(sock, message, totalSize)) < 0) {
logger->printLog ("write Failed");
std::string error = strerror(errno);
logger->printLog(error);
}
else {
logger->printLog ("write was successful");
}
如果有人能够提供帮助,我将不胜感激。