Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <string.h>
- #include <stdbool.h>
- #include <iostream>
- #include <string>
- #include <vector>
- #include <sstream>
- #include <regex>
- #ifdef __WIN32__
- #include <winsock2.h>
- #include <ws2tcpip.h>
- #else
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #endif
- #define PORT 8080
- #define MAXLINE 1024
- using namespace std;
- /*
- Spuštění aplikace
- Použití: dns [-r] [-x] [-6] -s server [-p port] adresa
- Pořadí parametrů je libovolné. Popis parametrů:
- -r: Požadována rekurze (Recursion Desired = 1), jinak bez rekurze.
- -x: Reverzní dotaz místo přímého.
- -6: Dotaz typu AAAA místo výchozího A.
- -s: IP adresa nebo doménové jméno serveru, kam se má zaslat dotaz.
- -p port: Číslo portu, na který se má poslat dotaz, výchozí 53.
- adresa: Dotazovaná adresa.
- */
- class DNS
- {
- public:
- string domainName;
- string IPaddress;
- void printname()
- {
- cout << "Domain name is: " << domainName << "\n";
- }
- void printIP()
- {
- cout << "IP address is: " << IPaddress << "\n";
- }
- };
- // GLOBAL VARIABLES
- DNS serverToBeAsked;
- int port = 53; // Destination port, default value is 53
- bool ipv6 = false; // Flag IPV4/IPV6
- bool reversed = false;
- bool recursion = false;
- int mySocket;
- string askingFor;
- unsigned char outBuf[MAXLINE];
- unsigned char inBuf[65536], *qname, *reader;
- struct sockaddr_in to;
- struct sockaddr from;
- int globIndex;
- class Response
- {
- public:
- uint16_t QDCOUNT;
- uint16_t ANCOUNT;
- uint16_t NSCOUNT;
- uint16_t ARCOUNT;
- uint16_t AA; // Authoritative Answer
- uint16_t TC; // TrunCation
- uint16_t RA; // Recursion Available
- string QNAME; // name
- uint16_t QTYPE; // type
- uint16_t QCLASS; // class
- uint16_t responseEndIndex;
- uint16_t rDataFixedIndex; // beggining of the rdata block
- void
- printEverything()
- {
- /**
- * @brief Debugging function that prints raw information
- * read from server answer packet.
- */
- cout << "\n\n***RECEIVED INFORMATION***\n";
- cout << "Questions: " << QDCOUNT << "\n";
- cout << "Answer RRs: " << ANCOUNT << "\n";
- cout << "Authority RRs: " << NSCOUNT << "\n";
- cout << "Additional RRs: " << ARCOUNT << "\n";
- cout << "Authoritative Answer: " << AA << "\n";
- cout << "Truncation: " << TC << "\n";
- cout << "Recursion Available: " << RA << "\n";
- cout << "Queries - Name: " << QNAME << "\n";
- cout << "Queries - Type: " << QTYPE << "\n";
- cout << "Queries - Class: " << QCLASS << "\n";
- cout << "\n\n\n";
- }
- void printNicely()
- {
- /**
- * @brief Printing nicely formatted information.
- */
- string a, b;
- a = (this->AA == 1) ? "Yes, " : "No, ";
- cout << "Authoritative: " << a;
- a = (this->RA == 1) ? "Yes, " : "No, ";
- cout << "Recursive: " << a;
- a = (this->TC == 1) ? "Yes, " : "No\n";
- cout << "Truncated: " << a;
- cout << "Question section(" << this->QDCOUNT << ")\n";
- a = (this->QTYPE == 1) ? "A" : "?";
- ;
- b = (this->QCLASS == 1) ? "IN" : "?";
- cout << " " << this->QNAME << ", " << a << ", " << b << "\n";
- //A IN
- cout << "Answer section(" << this->ANCOUNT << ")\n";
- cout << "Authority section(" << this->NSCOUNT << ")\n";
- cout << "Additional section(" << this->ARCOUNT << ")\n";
- }
- int decodeDomainName(unsigned char *s)
- {
- /**
- * @brief Function gets a pointer to unsigned char array (outBuf) where
- * domain name begins (format '0x03'www'0x06'google'0x03'com'0x00'), reads the first
- * char as int to know the length of the following label, stores the
- * value, decrements that in each step. Reaching 0 indicates another
- * char representing following label length. Finally fills the Response attribute QNAME.
- * @param1 Pointer to received unsigned char array, where queried domain name begins
- * @return Lenght of the domain name in bytes
- */
- string domainName;
- unsigned char *t;
- int labelLen = (int)s[0]; // Means the lenght of the first label
- int domainLegth = 1;
- for (t = ++s; *t != '\0'; t++)
- {
- domainLegth++;
- if (labelLen == 0)
- {
- labelLen = (int)t[0];
- domainName += '.';
- }
- else
- {
- //cout << t[0] << labelLen << "\n";
- domainName += t[0];
- labelLen--;
- }
- }
- this->QNAME = domainName;
- return (domainLegth + 1); // '\n' counts as well
- }
- };
- Response r;
- class Resource
- {
- public:
- string NAME;
- string TYPE;
- string CLASS;
- uint32_t TTL;
- uint32_t RDLENGTH;
- string IP;
- int decodeDomainName(unsigned char *s, bool NAME)
- {
- /**
- * @brief Function gets a pointer to unsigned char array (outBuf) where
- * domain name begins (format '0x03'www'0x06'google'0x03'com'0x00'), reads the first
- * char as int to know the length of the following label, stores the
- * value, decrements that in each step. Reaching 0 indicates another
- * char representing following label length. Finally fills the Response attribute QNAME.
- * @param1 Pointer to received unsigned char array, where queried domain name begins
- * @return Lenght of the domain name in bytes
- */
- string domainName;
- unsigned char *t;
- int labelLen = (int)s[0]; // Means the lenght of the first label
- int domainLegth = 1;
- for (t = ++s; *t != '\0'; t++)
- {
- if ((((uint16_t)*t) & 0b11000000) == 192) // 0xC0 is a pointer
- {
- if (NAME)
- {
- this->NAME += domainName;
- this->NAME += '.'; // TODO: Really?
- }
- else
- {
- this->IP += domainName;
- this->IP += '.'; // TODO: Really?
- }
- uint16_t offset = (uint8_t)*t;
- offset = (offset << sizeof((uint8_t)*t) & 0b00111111);
- t++;
- offset |= (uint8_t)*t;
- this->decodeDomainName(&outBuf[offset], NAME);
- domainLegth += 2;
- //cout << "AHOOOJ" << domainLegth << "\n";
- return (domainLegth);
- }
- domainLegth++;
- if (labelLen == 0)
- {
- labelLen = (int)t[0];
- domainName += '.';
- }
- else
- {
- //cout << t[0] << labelLen << "\n";
- domainName += t[0];
- labelLen--;
- }
- }
- if(NAME){
- this->NAME += domainName;
- }else{
- this->IP += domainName;
- }
- //cout << "ahoj" << (domainLegth + 1) << "\n";
- return (domainLegth + 1); // '\n' counts as well
- }
- void hello()
- {
- cout << " " << this->NAME << ", ";
- cout << this->TYPE << ", ";
- cout << this->CLASS << ", ";
- cout << this->TTL << ", ";
- cout << this->IP << "\n";
- }
- void handleResource()
- {
- unsigned char check = outBuf[globIndex];
- //cout << "check " << (int)check << " " << globIndex <<"\n";
- uint16_t offset;
- int rsrcLen;
- /* Name *B */
- // Check whether name is a pointer. Its truth when 2 leftmost bits are set to '1'.
- if ((check & (1 << 7)) && (check & (1 << 6))) // Its a pointer
- {
- // The rest of the bits in the 2B block define an offset from the beggining on the response
- offset = outBuf[globIndex];
- offset = (offset << sizeof(outBuf[globIndex + 1]) & 0b00111111) | outBuf[globIndex + 1];
- //cout << "Volám s z offsetu získanou offsetem. na indexu " << (offset) << " je hodnota " << (int)outBuf[offset] << "\n";
- this->decodeDomainName(&outBuf[offset], true); // TODO: rly?
- rsrcLen = 2;
- }
- else
- { // Its a domain name. TODO: • a sequence of labels ending with a pointer
- rsrcLen = this->decodeDomainName(&outBuf[globIndex], true);
- }
- /* Type A or CTYPE 2B*/
- globIndex = globIndex + rsrcLen;
- uint16_t type = outBuf[globIndex];
- type = (type << sizeof(outBuf[globIndex + 1]) | outBuf[globIndex + 1]);
- if (type == 5)
- { // CNAME code
- this->TYPE = "CNAME";
- }
- else if (type == 1)
- { // A code
- this->TYPE = "A";
- }
- /* Class 2B*/
- globIndex += 2;
- uint16_t clss = outBuf[globIndex];
- clss = (clss << sizeof(outBuf[globIndex + 1]) | outBuf[globIndex + 1]);
- if (clss == 1)
- { // IN code
- this->CLASS = "IN";
- }
- else
- {
- this->CLASS = "?"; //TODO: jaké jsou jiné možnosti?
- }
- /* TTL 4B */
- globIndex += 2;
- uint32_t ttl = (uint8_t)outBuf[globIndex];
- ttl = ((ttl << 8) | (uint8_t)outBuf[globIndex + 1]);
- ttl = ((ttl << 8) | (uint8_t)outBuf[globIndex + 2]);
- ttl = ((ttl << 8) | (uint8_t)outBuf[globIndex + 3]);
- this->TTL = ttl;
- /* Data length 2B */
- globIndex += 4;
- uint32_t rData_len = outBuf[globIndex];
- rData_len = (rData_len << sizeof(outBuf[globIndex + 1]) | outBuf[globIndex + 1]);
- this->RDLENGTH = rData_len;
- /* Address *B */
- globIndex += 2;
- int rDataIndex = globIndex;
- r.rDataFixedIndex = globIndex;
- if (this->TYPE == "A")
- { // There is IP address, 4B
- for (int i = 0; i < 4; i++)
- {
- this->IP += to_string((uint8_t)outBuf[rDataIndex]);
- if (i != 3)
- {
- this->IP += "."; // Do not concatenate 4th dot
- }
- rDataIndex++;
- }
- }
- else if (this->TYPE == "CNAME")
- {
- // Check whether name is a pointer. Its truth when 2 leftmost bits are set to '1'.
- if ((outBuf[rDataIndex] & (1 << 7)) && (outBuf[rDataIndex] & (1 << 6))) // Its a pointer
- {
- // The rest of the bits in the 2B block define an offset from the beggining on the response
- offset = outBuf[rDataIndex];
- offset = (offset << sizeof(outBuf[rDataIndex + 1]) & 0b00111111) | outBuf[rDataIndex + 1];
- this->decodeDomainName(&outBuf[offset], false);
- rDataIndex += 2;
- }
- else
- { // Its a domain name. TODO: • a sequence of labels ending with a pointer
- //cout << "Před 1. volanim: " << (int)outBuf[rDataIndex] << "na indexu: " << rDataIndex << "\n";
- rsrcLen = this->decodeDomainName(&outBuf[rDataIndex], false);
- //cout << "Po navratu z 2. volani: " << (int)outBuf[rDataIndex + rsrcLen] << "na indexu: " << (rDataIndex + rsrcLen) << "\n";
- rDataIndex += (rsrcLen);
- }
- } // TODO: 0x0002 for name servers, s 0x000f for mail servers
- globIndex = rDataIndex;
- return;
- }
- };
- int kill(int erNo)
- {
- if (erNo == 10)
- {
- fprintf(stderr, "Error: Empty label in the address\n");
- }
- else if (erNo == 11)
- {
- fprintf(stderr, "Error: Label has more than 63 characters\n");
- }
- else if (erNo == 12)
- {
- fprintf(stderr, "Error: Label contains forbidden character\n");
- }
- else if (erNo == 13)
- {
- fprintf(stderr, "Error: Domain name cannot end by dot character\n");
- }
- else if (erNo == 14)
- {
- fprintf(stderr, "Error: Wrong IPv4 format\n");
- }
- else if (erNo == 15)
- {
- fprintf(stderr, "Error: Port must be number\n");
- }
- else if (erNo == 16)
- {
- fprintf(stderr, "Error: No address to be asked for\n");
- }
- else if (erNo == 17)
- {
- fprintf(stderr, "Error: Function inet_ntop\n");
- }
- else if (erNo == 18)
- {
- fprintf(stderr, "Error: Function gethostbyname\n");
- }
- else
- {
- fprintf(stderr, "Error: Wrong argument number %d \n", erNo);
- }
- exit(-1);
- }
- bool checkDomainNameSyntax(string probablyDomainName)
- {
- /**
- * @brief Function checks whether given string is a domain name.
- * Checks the following rules:
- * 1) Label consists of 1 to 63 characters
- * 2) Full domain name consists of max 253 ASCII characters
- * 3) Domain name is not case-sensitive
- *
- */
- if (probablyDomainName.back() == '.')
- {
- // Domain name cannot end by dot symbol
- kill(13);
- }
- vector<string> tokens;
- stringstream check1(probablyDomainName);
- string intermediate;
- // Split into tokens by dot symbol
- while (getline(check1, intermediate, '.'))
- {
- tokens.push_back(intermediate);
- }
- // Looping through the token vector, check each member
- for (int i = 0; i < tokens.size(); i++)
- {
- if (tokens[i].empty())
- {
- //when label is empty
- kill(10);
- }
- else if (tokens[i].size() > 63)
- {
- // when label is too long
- kill(11);
- }
- else if (tokens[i].find_first_not_of("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890-") != std::string::npos)
- {
- // when label contains forbidden character
- kill(12);
- }
- }
- return true;
- }
- bool checkIPAdressSyntax(string probablyIPAdress)
- {
- if (probablyIPAdress.back() == '.')
- {
- // IP address cannot end by dot symbol
- kill(13);
- }
- vector<string> tokens;
- stringstream check1(probablyIPAdress);
- string intermediate;
- // Split into tokens by dot symbol
- while (getline(check1, intermediate, '.'))
- {
- tokens.push_back(intermediate);
- }
- // Looping through the token vector, check each member
- int IPv4_byte_length, IPv4_byte;
- for (int i = 0; i < tokens.size(); i++)
- {
- IPv4_byte_length = tokens.at(i).length();
- if (IPv4_byte_length > 3)
- {
- return false;
- }
- else if (tokens[i].find_first_not_of("0123456789") != std::string::npos)
- {
- return false;
- }
- IPv4_byte = stoi(tokens.at(i));
- if (!((IPv4_byte >= 0) && (IPv4_byte <= 255)))
- {
- return false;
- }
- //std::cout << "Byte " << i << " is: " << tokens.at(i) << IPv4_byte << "\n";
- }
- return true;
- }
- int setDNS(char *probablyServer, int argNo)
- {
- /**
- * @brief Function sets the DNS domain name/IP address. Option is required after -s.
- * Functions to check correct format are called. If the domain name was given, fills
- * the IP address, which is needed later.
- * @param1 Command line argument after -s option.
- * @param2 Actual position in the array of command line arguments.
- * @return Returns new position in the array of command line arguments.
- */
- // converting char* to string
- std::string givenDNS = probablyServer;
- if (checkIPAdressSyntax(givenDNS))
- {
- serverToBeAsked.IPaddress = givenDNS;
- }
- else if (checkDomainNameSyntax(givenDNS))
- {
- // Getting Ip address from structure of type hostent given by gethostbame()
- #ifdef __linux__
- serverToBeAsked.domainName = givenDNS;
- struct hostent *host;
- char ip[16];
- char *ntopRet;
- int hostname;
- struct sockaddr_in sock_addr;
- int n = givenDNS.length();
- char givenDNS_char_array[n + 1];
- strcpy(givenDNS_char_array, givenDNS.c_str());
- // Getting host information
- host = gethostbyname(givenDNS_char_array);
- if (NULL == host)
- { //TODO: kontrola podmínky
- kill(18);
- }
- sock_addr.sin_addr = *((struct in_addr *)host->h_addr_list[0]);
- ntopRet = inet_ntop(AF_INET, &sock_addr.sin_addr, ip, sizeof(ip));
- if (NULL == ntopRet)
- { //TODO: kontrola podmínky
- kill(17);
- }
- string s(ip);
- // save for later actions
- serverToBeAsked.IPaddress = s;
- #else
- printf("Run this on Linux. \n");
- exit(0);
- #endif
- }
- argNo++;
- // TODO: nesmí začínat pomlčkou
- return argNo;
- }
- int setPort(char *probablyPort, int argNo)
- {
- /**
- * @brief Function sets the destination port number. Default 53, if there is no integer given.
- * @param1 Command line argument after -p option.
- * @param2 Actual position in the array of command line arguments.
- * @return Returns new position in the array of command line arguments. Only increment if port number was given.
- */
- int length = strlen(probablyPort);
- for (int i = 0; i < length; i++)
- {
- if (!isdigit(probablyPort[i]))
- {
- // Argument contains a non-digit character (port number was not specified) -> set default value 53
- kill(15);
- }
- }
- port = atoi(probablyPort);
- argNo++;
- return argNo;
- }
- string changeAddressFormat(string askingFor)
- {
- /**
- * @brief Function changed host address format (www.seznam.cz to '0x03'www''0x06'seznam'0x02'cz'0x00')
- * @param1 Hostname given as argument to be transformed
- * @return Transformed string
- */
- istringstream iss(askingFor);
- vector<string> tokens;
- string token;
- string temporaryQname;
- int tokenLenght;
- string wwwPrefix("www");
- auto it = std::mismatch(wwwPrefix.begin(), wwwPrefix.end(), askingFor.begin());
- /*if( !(it.first == wwwPrefix.end()) ){
- // if 'www' is not a prefix of the given host name -> add
- // 3www to the beggining of temporaryQname
- temporaryQname.append("3wwww");
- }*/
- TODO :
- // split by dot symbol into a string vector
- while (std::getline(iss, token, '.'))
- {
- if (!token.empty())
- {
- tokens.push_back(token);
- }
- }
- for (int i = 0; i < (tokens.capacity() - 1); i++)
- {
- if (!tokens[i].empty())
- {
- // The length of the token is the hexadecimal value of the final char (0b01110111 -> 0x77 -> 'w')
- tokenLenght = tokens[i].length();
- unsigned char domainLength = 'a';
- domainLength &= 0; // set all bits to 0
- domainLength |= 0b00001000; // set the final value
- temporaryQname.append(to_string(domainLength));
- temporaryQname.append(tokens[i]);
- }
- }
- char nullCharacter = 'a';
- nullCharacter &= 0;
- temporaryQname.append(to_string(nullCharacter)); // has to end by 0
- return temporaryQname;
- }
- struct DNS_HEADER
- {
- unsigned short id; // identification number
- unsigned char rd : 1; // recursion desired
- unsigned char tc : 1; // truncated message
- unsigned char aa : 1; // authoritive answer
- unsigned char opcode : 4; // purpose of message
- unsigned char qr : 1; // query/response flag
- unsigned char rcode : 4; // response code
- unsigned char cd : 1; // checking disabled
- unsigned char ad : 1; // authenticated data
- unsigned char z : 1; // its z! reserved
- unsigned char ra : 1; // recursion available
- unsigned short q_count; // number of question entries
- unsigned short ans_count; // number of answer entries
- unsigned short auth_count; // number of authority entries
- unsigned short add_count; // number of resource entries
- };
- struct QUESTION
- {
- unsigned short qtype;
- unsigned short qclass;
- };
- struct R_DATA
- {
- unsigned short type;
- unsigned short _class;
- unsigned int ttl;
- unsigned short data_len;
- };
- struct RES_RECORD
- {
- unsigned char *name;
- struct R_DATA *resource;
- unsigned char *rdata;
- };
- typedef struct
- {
- unsigned char *name;
- struct QUESTION *ques;
- } QUERY;
- int main(int argc, char *argv[])
- {
- int option;
- int i = 0;
- // duplicate cmd line arguments cause getopt changes order
- vector<string> argVector;
- for (int j = 1; j < argc; j++)
- {
- argVector.push_back(argv[j]);
- }
- /*for (int i = 0; i < argVector.size(); i++)
- {
- cout << argVector[i] << "\n";
- }*/
- while ((option = getopt(argc, argv, "rx6s:p::")) != -1)
- {
- i++;
- switch (option)
- {
- case 'r':
- //printf("got %d) %c \n", i, option);
- recursion = true;
- break;
- case 'x':
- //printf("got %d) %c \n", i, option);
- reversed = true;
- break;
- case '6':
- //printf("got %d) %c \n", i, option);
- ipv6 = true;
- break;
- case 's':
- // Option -s is followed by IP address or domain name of the server
- //printf("got %d) %c \n", i, option);
- for (int j = 0; j < argc; ++j)
- {
- if (strcmp(argv[j], "-s") == 0)
- {
- //cout << argv[j] << "\n";
- i = setDNS(argv[j + 1], j);
- }
- }
- break;
- case 'p':
- // Option -p is followed by port number otherwise its set to 53
- //printf("got %d) %c \n", i, option);
- for (int j = 0; j < argc; ++j)
- {
- if (strcmp(argv[j], "-p") == 0)
- {
- //cout << argv[j] << "\n";
- i = setPort(argv[j + 1], j);
- }
- }
- //i = setPort(argv[i + 1], i);
- break;
- case ':':
- fprintf(stderr, "Option requires a value\n");
- kill(i);
- break;
- case '?':
- if (strcmp(argv[i], "-s") == 0)
- {
- fprintf(stderr, "Option -s requires a value\n");
- exit(-1);
- }
- else
- {
- kill(i);
- }
- break;
- default:
- //printf("got %d) uknown: %c \n", i, option);
- //kill(i);
- break;
- }
- }
- // Finding requested address to ask for in the command line arguments
- for (int i = 0; i < argVector.size(); i++)
- {
- regex flagFollowed("^-[sp]$");
- regex flagSingle("^-[6rx]$");
- if (regex_match(argVector[i], flagFollowed)) // matches flag with attribute
- {
- i++;
- }
- else if (regex_match(argVector[i], flagSingle)) // matches flag without attribute
- {
- ;
- }
- else
- {
- askingFor = argVector[i];
- }
- }
- // Exit when no requested address found or
- if (askingFor.empty())
- {
- kill(16);
- }
- // Cheching requested domain name syntax
- checkDomainNameSyntax(askingFor);
- /*
- printf("!!!RECAP!!!\n");
- printf("Port var: %d\n", port);
- cout << "Asking for: " << askingFor << "\n";
- printf("IPV6: %d\n", (bool)ipv6);
- printf("Reverse: %d\n", (bool)reversed);
- printf("Recursion: %d\n", (bool)recursion);*/
- // Creating socket file descriptor
- #if defined(WIN32) // TODO:
- WSADATA Data;
- WSAStartup(MAKEWORD(2, 2), &Data); // 2.2 version
- #endif
- if ((mySocket = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
- {
- perror("Error: Socket was no created succesfully");
- exit(EXIT_FAILURE);
- }
- struct RES_RECORD answ[20], auth[20], addit[20]; //the replies from the DNS server
- struct DNS_HEADER *dns = NULL;
- struct QUESTION *qinfo = NULL;
- dns = (struct DNS_HEADER *)&inBuf;
- memset(&to, 0, sizeof(to));
- // Filling server information
- to.sin_family = AF_INET;
- to.sin_port = htons(port);
- to.sin_addr.s_addr = inet_addr(serverToBeAsked.IPaddress.c_str());
- int pid = GetCurrentProcessId();
- // 1 1 1 1 1 1
- // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | ID |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // |QR| Opcode |AA|TC|RD|RA| Z | RCODE |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | QDCOUNT |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | ANCOUNT |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | NSCOUNT |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- // | ARCOUNT |
- // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- dns->id = (unsigned short)htons(pid);
- dns->rd = recursion; // 1 = "Do query recursively"
- dns->tc = 0; // 0 = "Message is not truncated"
- dns->aa = 0; // authoritative answer = false(0)
- dns->opcode = 0; // 0 = "Standard query"
- dns->qr = 0; // 0 = "Message is a query(0)", response(1)
- dns->rcode = 0; // response code (0=ok, 1=format error, 2=server failure, 3=domain doesnt exist)
- dns->cd = 0; // chesking disabled
- dns->ad = 0; // 0 = "Non-authenticated data: Unnacceptable"
- dns->z = 0; // reserved
- dns->ra = 0; // recursion available = false
- dns->q_count = htons(1); // number of questions
- dns->ans_count = 0; // number of answers
- dns->auth_count = 0; // number of authority entries
- dns->add_count = 0; // number of resource entries
- qname = (unsigned char *)&inBuf[sizeof(struct DNS_HEADER)];
- int l = askingFor.length();
- char char_array[l + 1];
- char new_char_array[l + 2];
- memset(new_char_array, '.', sizeof(new_char_array));
- strcpy(char_array, askingFor.c_str());
- uint8_t counter;
- int k;
- for (k = 0; char_array[k] != '\0'; k++)
- {
- if (char_array[k] == '.')
- {
- new_char_array[k - counter] &= 0;
- new_char_array[k - counter] |= counter;
- counter = 0;
- }
- else
- {
- new_char_array[k + 1] = char_array[k];
- counter++;
- }
- }
- //set char 0x03 before com TLD, 0x02 before cz TLD
- new_char_array[k - counter] &= 0;
- new_char_array[k - counter] |= counter;
- // set char after TLD to 0x00
- new_char_array[sizeof(new_char_array) - 1] &= 0;
- // copy new_char_array to qname
- memcpy(qname, new_char_array, sizeof(new_char_array));
- /*printf("\n");
- for (int i = 0; new_char_array[i] != '\0'; i++)
- {
- printf("%c", new_char_array[i]);
- }
- printf("\n");*/
- qinfo = (struct QUESTION *)&inBuf[sizeof(struct DNS_HEADER) + sizeof(new_char_array)];
- qinfo->qtype = htons(1); // requesting ipv4
- qinfo->qclass = htons(1); // stands for IN
- int sentBytes = sendto(mySocket, (char *)inBuf, sizeof(struct DNS_HEADER) + sizeof(new_char_array) + sizeof(struct QUESTION), 0, (sockaddr *)&to, sizeof(to));
- printf("Leti paket neco si prej! %d\n", sentBytes); // TODO: check na sendto
- int len;
- int addrlen = sizeof(from); // needs to be initialized
- int receivedBytes = recvfrom(mySocket, (char *)outBuf, MAXLINE, MSG_PEEK, (struct sockaddr *)&from, &addrlen); //TODO: makro MSG_WAITALL
- if (receivedBytes == -1)
- {
- fprintf(stderr, "Error: Function recvfrom.");
- exit(-1);
- }
- /*---------------------------------------------------------*/
- /*-------------------READING INFORMATION-------------------*/
- /*---------------------------------------------------------*/
- /* Questions 2B */
- r.QDCOUNT = outBuf[4];
- r.QDCOUNT = (r.QDCOUNT << sizeof(outBuf[5])) | outBuf[5];
- /* Answers 2B */
- r.ANCOUNT = outBuf[6];
- r.ANCOUNT = (r.ANCOUNT << sizeof(outBuf[7])) | outBuf[7];
- /* Authorities 2B */
- r.NSCOUNT = outBuf[8];
- r.NSCOUNT = (r.NSCOUNT << sizeof(outBuf[9])) | outBuf[9];
- /* Additional 2B */
- r.ARCOUNT = outBuf[10];
- r.ARCOUNT = (r.ARCOUNT << sizeof(outBuf[11])) | outBuf[11];
- /* 1 1 1 1 1 1
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
- +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- |QR| Opcode |AA|TC|RD|RA| Z | RCODE |
- +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- */
- /* Authoritative Answer 1b */
- uint8_t bitValue = outBuf[2];
- bitValue &= 0b00000100;
- bitValue >>= 2;
- r.AA = bitValue;
- /* TrunCation 1b */
- bitValue = outBuf[2];
- bitValue &= 0b00000010;
- bitValue >>= 1;
- r.TC = bitValue;
- /* Recursion Available 1b */
- bitValue = outBuf[3];
- bitValue &= 0b10000000;
- bitValue >>= 7;
- r.RA = bitValue;
- /* Queried name VARIABLE LENGTH */
- // Asked domain starts at 12th position of array
- int qnameLen = r.decodeDomainName(&outBuf[12]);
- cout << qnameLen << '\n';
- /* Queried type 2B */
- int qTypeIndex = 12 + qnameLen;
- r.QTYPE = outBuf[qTypeIndex];
- r.QTYPE = (r.QTYPE << sizeof(outBuf[qTypeIndex + 1])) | outBuf[qTypeIndex + 1];
- /* Queried class 2B */
- int qClassIndex = qTypeIndex + 2;
- r.QCLASS = outBuf[qClassIndex];
- r.QCLASS = (r.QCLASS << sizeof(outBuf[qClassIndex + 1])) | outBuf[qClassIndex + 1];
- /* Resources */
- /* 1 1 1 1 1 1
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
- +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- | |
- / /
- / NAME /
- | |
- +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- | TYPE |
- +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- | CLASS |
- +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- | TTL |
- | |
- +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- | RDLENGTH |
- +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
- / RDATA /
- / /
- +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+-*/
- int questions = r.QDCOUNT;
- int answers = r.ANCOUNT;
- int authority = r.NSCOUNT;
- int additional = r.ARCOUNT;
- // array of resource object
- Resource **resourceArray = new Resource *[questions + answers + authority + additional];
- int rPos = 0;
- globIndex = qClassIndex + 2;
- r.responseEndIndex = qClassIndex + 2;
- /*** PRINT HEADER INFO ***/
- cout << "\n\n\n";
- string a, b;
- a = (r.AA == 1) ? "Yes, " : "No, ";
- cout << "Authoritative: " << a;
- a = (r.RA == 1) ? "Yes, " : "No, ";
- cout << "Recursive: " << a;
- a = (r.TC == 1) ? "Yes\n" : "No\n";
- cout << "Truncated: " << a;
- cout << "Question section(" << r.QDCOUNT << ")\n";
- while (questions)
- {
- string a, b;
- a = (r.QTYPE == 1) ? "A" : "?";
- ;
- b = (r.QCLASS == 1) ? "IN" : "?";
- /*** PRINT QUESTION INFO ***/
- cout << " " << r.QNAME << ", " << a << ", " << b << "\n";
- rPos++;
- questions--;
- }
- cout << "Answer section(" << r.ANCOUNT << ")\n";
- while (answers)
- {
- resourceArray[rPos] = new Resource();
- //cout << "Pozice před " << rPos << ". resourcem je " << globIndex <<"\n";
- resourceArray[rPos]->handleResource();
- /*** PRINT ANSWER INFO ***/
- resourceArray[rPos]->hello();
- //cout << "Pozice po " << rPos << ". resourcu je " << globIndex << "\n";
- rPos++;
- answers--;
- }
- cout << "Authority section(" << r.NSCOUNT << ")\n";
- while (authority)
- {
- resourceArray[rPos] = new Resource();
- /*** PRINT AUTHORITY INFO ***/
- resourceArray[rPos]->hello();
- rPos++;
- authority--;
- }
- cout << "Additional section(" << r.ARCOUNT << ")\n";
- while (additional)
- {
- resourceArray[rPos] = new Resource();
- /*** PRINT ADDITIONAL INFO ***/
- resourceArray[rPos]->hello();
- rPos++;
- additional--;
- }
- //r.printEverything();
- //r.printNicely();
- close(mySocket);
- #if defined(WIN32) //TODO:
- WSACleanup();
- #endif
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement