DNS UDP Socket запись () проблема - PullRequest
0 голосов
/ 07 октября 2018

Я пытаюсь отправить заголовок 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-запроса, используя структуру DNS_Question.Эта структура не включает имя вопроса 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");
}

Если кто-то сможет помочь, я буду очень признателен.

...