SHARE
TWEET

Untitled

a guest Nov 16th, 2019 103 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <string.h>
  5. #include <stdbool.h>
  6.  
  7. #include <iostream>
  8. #include <string>
  9. #include <vector>
  10. #include <sstream>
  11. #include <regex>
  12.  
  13. #ifdef __WIN32__
  14. #include <winsock2.h>
  15. #include <ws2tcpip.h>
  16. #else
  17. #include <sys/socket.h>
  18. #include <netinet/in.h>
  19. #include <arpa/inet.h>
  20. #endif
  21.  
  22. #define PORT 8080
  23. #define MAXLINE 1024
  24.  
  25.     using namespace std;
  26.  
  27. /*
  28. Spuštění aplikace
  29. Použití: dns [-r] [-x] [-6] -s server [-p port] adresa
  30.  
  31. Pořadí parametrů je libovolné. Popis parametrů:
  32. -r: Požadována rekurze (Recursion Desired = 1), jinak bez rekurze.
  33. -x: Reverzní dotaz místo přímého.
  34. -6: Dotaz typu AAAA místo výchozího A.
  35. -s: IP adresa nebo doménové jméno serveru, kam se má zaslat dotaz.
  36. -p port: Číslo portu, na který se má poslat dotaz, výchozí 53.
  37. adresa: Dotazovaná adresa.
  38. */
  39.  
  40.     class DNS
  41.     {
  42.     public:
  43.         string domainName;
  44.         string IPaddress;
  45.  
  46.         void printname()
  47.         {
  48.             cout << "Domain name is: " << domainName << "\n";
  49.         }
  50.         void printIP()
  51.         {
  52.             cout << "IP address is: " << IPaddress << "\n";
  53.         }
  54.     };
  55.  
  56.     class Response
  57.     {
  58.         public:
  59.             uint16_t QDCOUNT;
  60.             uint16_t ANCOUNT;
  61.             uint16_t NSCOUNT;
  62.             uint16_t ARCOUNT;
  63.             uint16_t AA; // Authoritative Answer
  64.             uint16_t TC; // TrunCation
  65.             uint16_t RA; // Recursion Available
  66.             string QNAME; // name
  67.             uint16_t QTYPE; // type
  68.             uint16_t QCLASS; // class
  69.  
  70.             void printEverything()
  71.             {
  72.                 /**
  73.                  * @brief Debugging function that prints raw information
  74.                  * read from server answer packet.
  75.                  */
  76.                 cout << "\n\n***RECEIVED INFORMATION***\n";
  77.                 cout << "Questions: " << QDCOUNT << "\n";
  78.                 cout << "Answer RRs: " << ANCOUNT << "\n";
  79.                 cout << "Authority RRs: " << NSCOUNT << "\n";
  80.                 cout << "Additional RRs: " << ARCOUNT << "\n";
  81.                 cout << "Authoritative Answer: " << AA << "\n";
  82.                 cout << "Truncation: " << TC << "\n";
  83.                 cout << "Recursion Available: " << RA << "\n";
  84.                 cout << "Queries - Name: " << QNAME << "\n";
  85.                 cout << "Queries - Type: " << QTYPE << "\n";
  86.                 cout << "Queries - Class: " << QCLASS << "\n";
  87.                 cout << "\n\n\n";
  88.             }
  89.  
  90.             void printNicely()
  91.             {
  92.                 /**
  93.                  * @brief Printing nicely formatted information.
  94.                  */
  95.                 string a,b;  
  96.                 a = (this->AA == 1) ? "Yes, " : "No, ";
  97.                 cout << "Authoritative: " << a;
  98.                 a = (this->RA == 1) ? "Yes, " : "No, ";
  99.                 cout << "Recursive: " << a;
  100.                 a = (this->TC == 1) ? "Yes, " : "No\n";
  101.                 cout << "Truncated: " << a;
  102.  
  103.                 cout << "Question section(" << this->QDCOUNT << ")\n";
  104.                 a = (this->QTYPE == 1) ? "A" : "?";;
  105.                 b = (this->QCLASS == 1) ? "IN" : "?";
  106.                
  107.                 cout << "  " << this->QNAME << ", " << a << ", " << b << "\n";
  108.                 //A IN
  109.                 cout << "Answer section(" << this->ANCOUNT << ")\n";
  110.                 cout << "Authority section(" << this->NSCOUNT << ")\n";
  111.                 cout << "Additional section(" << this->ARCOUNT << ")\n";
  112.             }
  113.  
  114.                 int decodeDomainName(unsigned char *s)
  115.                 {
  116.                     /**
  117.                  * @brief Function gets a pointer to unsigned char array (outBuf) where
  118.                  * domain name begins (format '0x03'www'0x06'google'0x03'com'0x00'), reads the first
  119.                  * char as int to know the length of the following label, stores the
  120.                  * value, decrements that in each step. Reaching 0 indicates another
  121.                  * char representing following label length. Finally fills the Response attribute QNAME.
  122.                  * @param1 Pointer to received unsigned char array, where queried domain name begins
  123.                  * @return Lenght of the domain name in bytes
  124.                  */
  125.                     string domainName;
  126.                     unsigned char *t;
  127.                     int labelLen = (int)s[0]; // Means the lenght of the first label
  128.                     int domainLegth = 1;
  129.  
  130.                     for (t = ++s; *t != '\0'; t++)
  131.                     {
  132.                         domainLegth++;
  133.                         if (labelLen == 0)
  134.                         {
  135.                             labelLen = (int)t[0];
  136.                             domainName += '.';
  137.                         }
  138.                         else
  139.                         {
  140.                             //cout << t[0] << labelLen << "\n";
  141.                             domainName += t[0];
  142.                             labelLen--;
  143.                         }
  144.                     }
  145.                     this->QNAME = domainName;
  146.                     return (domainLegth + 1); // '\n' counts as well
  147.             }
  148.     };
  149.  
  150.     class Resource
  151.     {
  152.         public:
  153.             string NAME;
  154.             string TYPE;
  155.  
  156.  
  157.             int decodeDomainName(unsigned char *s)
  158.             {
  159.                 /**
  160.                  * @brief Function gets a pointer to unsigned char array (outBuf) where
  161.                  * domain name begins (format '0x03'www'0x06'google'0x03'com'0x00'), reads the first
  162.                  * char as int to know the length of the following label, stores the
  163.                  * value, decrements that in each step. Reaching 0 indicates another
  164.                  * char representing following label length. Finally fills the Response attribute QNAME.
  165.                  * @param1 Pointer to received unsigned char array, where queried domain name begins
  166.                  * @return Lenght of the domain name in bytes
  167.                  */
  168.                 string domainName;
  169.                 unsigned char *t;
  170.                 int labelLen = (int)s[0]; // Means the lenght of the first label
  171.                 int domainLegth = 1;
  172.  
  173.                 for (t = ++s; *t != '\0'; t++)
  174.                 {
  175.                     domainLegth++;
  176.                     if (labelLen == 0)
  177.                     {
  178.                         labelLen = (int)t[0];
  179.                         domainName += '.';
  180.                     }
  181.                     else
  182.                     {
  183.                         //cout << t[0] << labelLen << "\n";
  184.                         domainName += t[0];
  185.                         labelLen--;
  186.                     }
  187.                 }
  188.                 this->NAME = domainName;
  189.                 return (domainLegth + 1); // '\n' counts as well
  190.             }
  191.  
  192.             void hello(){
  193.                 cout << "Hello\n";
  194.             }
  195.  
  196.     };
  197.  
  198.  
  199. // GLOBAL VARIABLES
  200. DNS serverToBeAsked;
  201. int port = 53;           // Destination port, default value is 53
  202. bool ipv6 = false;  // Flag IPV4/IPV6
  203. bool reversed = false;
  204. bool recursion = false;
  205. int mySocket;
  206. string askingFor;
  207. unsigned char outBuf[MAXLINE];
  208. unsigned char inBuf[65536], *qname, *reader;
  209. struct sockaddr_in to;
  210. struct sockaddr from;
  211.  
  212.  
  213.  
  214. int kill(int erNo)
  215. {
  216.     if (erNo == 10)
  217.     {
  218.         fprintf(stderr, "Error: Empty label in the address\n");
  219.     }
  220.     else if (erNo == 11)
  221.     {
  222.         fprintf(stderr, "Error: Label has more than 63 characters\n");
  223.     }
  224.     else if (erNo == 12)
  225.     {
  226.         fprintf(stderr, "Error: Label contains forbidden character\n");
  227.     }
  228.     else if (erNo == 13)
  229.     {
  230.         fprintf(stderr, "Error: Domain name cannot end by dot character\n");
  231.     }
  232.     else if (erNo == 14)
  233.     {
  234.         fprintf(stderr, "Error: Wrong IPv4 format\n");
  235.     }
  236.     else if (erNo == 15)
  237.     {
  238.         fprintf(stderr, "Error: Port must be number\n");
  239.     }
  240.     else if (erNo == 16)
  241.     {
  242.         fprintf(stderr, "Error: No address to be asked for\n");
  243.     }
  244.     else if (erNo == 17){
  245.         fprintf(stderr, "Error: Function inet_ntop\n");  
  246.     }
  247.     else if (erNo == 18){
  248.         fprintf(stderr, "Error: Function gethostbyname\n");
  249.     }
  250.     else
  251.     {
  252.         fprintf(stderr, "Error: Wrong argument number %d \n", erNo);
  253.     }
  254.     exit(-1);
  255. }
  256.  
  257. bool checkDomainNameSyntax(string probablyDomainName)
  258. {
  259.     /**
  260.      * @brief Function checks whether given string is a domain name.
  261.      * Checks the following rules:
  262.      *  1) Label consists of 1 to 63 characters
  263.      *  2) Full domain name consists of max 253 ASCII characters
  264.      *  3) Domain name is not case-sensitive
  265.      *  
  266.      */
  267.     if (probablyDomainName.back() == '.')
  268.     {
  269.         // Domain name cannot end by dot symbol
  270.         kill(13);
  271.     }
  272.     vector<string> tokens;
  273.     stringstream check1(probablyDomainName);
  274.     string intermediate;
  275.  
  276.     // Split into tokens by dot symbol
  277.     while (getline(check1, intermediate, '.'))
  278.     {
  279.         tokens.push_back(intermediate);
  280.     }
  281.  
  282.     // Looping through the token vector, check each member
  283.     for (int i = 0; i < tokens.size(); i++)
  284.     {
  285.         if (tokens[i].empty())
  286.         {
  287.             //when label is empty
  288.             kill(10);
  289.         }
  290.         else if (tokens[i].size() > 63)
  291.         {
  292.             // when label is too long
  293.             kill(11);
  294.         }
  295.         else if (tokens[i].find_first_not_of("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890-") != std::string::npos)
  296.         {
  297.             // when label contains forbidden character
  298.             kill(12);
  299.         }
  300.     }
  301.     return true;
  302. }
  303.  
  304. bool checkIPAdressSyntax(string probablyIPAdress)
  305. {
  306.     if (probablyIPAdress.back() == '.')
  307.     {
  308.         // IP address cannot end by dot symbol
  309.         kill(13);
  310.     }
  311.     vector<string> tokens;
  312.     stringstream check1(probablyIPAdress);
  313.     string intermediate;
  314.  
  315.     // Split into tokens by dot symbol
  316.     while (getline(check1, intermediate, '.'))
  317.     {
  318.         tokens.push_back(intermediate);
  319.     }
  320.  
  321.     // Looping through the token vector, check each member
  322.     int IPv4_byte_length, IPv4_byte;
  323.     for (int i = 0; i < tokens.size(); i++)
  324.     {
  325.         IPv4_byte_length = tokens.at(i).length();
  326.         if(IPv4_byte_length > 3){
  327.             return false;
  328.         }else if(tokens[i].find_first_not_of("0123456789") != std::string::npos){
  329.             return false;
  330.         }
  331.         IPv4_byte = stoi(tokens.at(i));
  332.         if( !((IPv4_byte >= 0) && (IPv4_byte <= 255)) ){
  333.             return false;
  334.         }
  335.     //std::cout << "Byte " << i << " is: " << tokens.at(i) << IPv4_byte << "\n";
  336.     }
  337.     return true;
  338. }
  339.  
  340. int setDNS(char *probablyServer, int argNo)
  341. {
  342.     /**
  343.      * @brief Function sets the DNS domain name/IP address. Option is required after -s.
  344.      * Functions to check correct format are called. If the domain name was given, fills
  345.      * the IP address, which is needed later.
  346.      * @param1 Command line argument after -s option.
  347.      * @param2 Actual position in the array of command line arguments.
  348.      * @return Returns new position in the array of command line arguments.
  349.      */
  350.  
  351.     // converting char* to string
  352.     std::string givenDNS = probablyServer;
  353.  
  354.     if (checkIPAdressSyntax(givenDNS))
  355.     {
  356.         serverToBeAsked.IPaddress = givenDNS;
  357.     }
  358.     else if (checkDomainNameSyntax(givenDNS))
  359.     {
  360.         // Getting Ip address from structure of type hostent given by gethostbame()
  361.         #ifdef __linux__
  362.             serverToBeAsked.domainName = givenDNS;
  363.  
  364.             struct hostent *host;
  365.             char ip[16];
  366.             char *ntopRet;
  367.             int hostname;
  368.  
  369.             struct sockaddr_in sock_addr;
  370.             int n = givenDNS.length();
  371.             char givenDNS_char_array[n + 1];
  372.             strcpy(givenDNS_char_array, givenDNS.c_str());
  373.  
  374.             // Getting host information
  375.             host = gethostbyname(givenDNS_char_array);
  376.             if (NULL == host)
  377.             { //TODO: kontrola podmínky
  378.                 kill(18);
  379.             }
  380.             sock_addr.sin_addr = *((struct in_addr *)host->h_addr_list[0]);
  381.             ntopRet = inet_ntop(AF_INET, &sock_addr.sin_addr, ip, sizeof(ip));
  382.             if (NULL == ntopRet)
  383.             { //TODO: kontrola podmínky
  384.                 kill(17);
  385.             }
  386.  
  387.             string s(ip);
  388.             // save for later actions
  389.             serverToBeAsked.IPaddress = s;
  390.         #else
  391.             printf("Run this on Linux. \n");
  392.             exit(0);    
  393.         #endif
  394.     }
  395.     argNo++;
  396.     // TODO: nesmí začínat pomlčkou
  397.     return argNo;
  398. }
  399.  
  400. int setPort(char *probablyPort, int argNo)
  401. {
  402.     /**
  403.     * @brief Function sets the destination port number. Default 53, if there is no integer given.
  404.     * @param1 Command line argument after -p option.
  405.     * @param2 Actual position in the array of command line arguments.
  406.     * @return Returns new position in the array of command line arguments. Only increment if port number was given.
  407.     */
  408.     int length = strlen(probablyPort);
  409.     for (int i = 0; i < length; i++)
  410.     {
  411.         if (!isdigit(probablyPort[i]))
  412.         {
  413.             // Argument contains a non-digit character (port number was not specified) -> set default value 53
  414.             kill(15);
  415.         }
  416.     }
  417.     port = atoi(probablyPort);
  418.     argNo++;
  419.     return argNo;
  420. }
  421.  
  422.  
  423. string changeAddressFormat(string askingFor)
  424. {
  425.     /**
  426.      * @brief Function changed host address format (www.seznam.cz to '0x03'www''0x06'seznam'0x02'cz'0x00')
  427.      * @param1 Hostname given as argument to be transformed
  428.      * @return Transformed string
  429.      */
  430.     istringstream iss(askingFor);
  431.     vector<string> tokens;
  432.     string token;
  433.     string temporaryQname;
  434.     int tokenLenght;
  435.     string wwwPrefix("www");
  436.  
  437.     auto it = std::mismatch(wwwPrefix.begin(), wwwPrefix.end(), askingFor.begin());
  438.     /*if( !(it.first == wwwPrefix.end()) ){
  439.         // if 'www' is not a prefix of the given host name -> add
  440.         // 3www to the beggining of temporaryQname
  441.         temporaryQname.append("3wwww");
  442.     }*/ TODO:
  443.  
  444.     // split by dot symbol into a string vector
  445.     while (std::getline(iss, token, '.'))
  446.     {
  447.         if (!token.empty()){
  448.             tokens.push_back(token);
  449.         }
  450.     }
  451.  
  452.     for (int i = 0; i < (tokens.capacity()-1); i++)
  453.     {
  454.         if(!tokens[i].empty()){
  455.             // The length of the token is the hexadecimal value of the final char (0b01110111 -> 0x77 -> 'w')
  456.             tokenLenght = tokens[i].length();
  457.             unsigned char domainLength = 'a';
  458.             domainLength &= 0; // set all bits to 0
  459.             domainLength |= 0b00001000; // set the final value
  460.             temporaryQname.append(to_string(domainLength));
  461.             temporaryQname.append(tokens[i]);
  462.         }
  463.     }
  464.     char nullCharacter = 'a';
  465.     nullCharacter &= 0;
  466.     temporaryQname.append(to_string(nullCharacter)); // has to end by 0
  467.  
  468.     return temporaryQname;
  469. }
  470.  
  471.  
  472.  
  473. struct DNS_HEADER
  474. {
  475.     unsigned short id;         // identification number
  476.     unsigned char rd : 1;      // recursion desired
  477.     unsigned char tc : 1;      // truncated message
  478.     unsigned char aa : 1;      // authoritive answer
  479.     unsigned char opcode : 4;  // purpose of message
  480.     unsigned char qr : 1;      // query/response flag
  481.     unsigned char rcode : 4;   // response code
  482.     unsigned char cd : 1;      // checking disabled
  483.     unsigned char ad : 1;      // authenticated data
  484.     unsigned char z : 1;       // its z! reserved
  485.     unsigned char ra : 1;      // recursion available
  486.     unsigned short q_count;    // number of question entries
  487.     unsigned short ans_count;  // number of answer entries
  488.     unsigned short auth_count; // number of authority entries
  489.     unsigned short add_count;  // number of resource entries
  490. };
  491.  
  492. struct QUESTION
  493. {
  494.     unsigned short qtype;
  495.     unsigned short qclass;
  496. };
  497.  
  498. struct R_DATA
  499. {
  500.     unsigned short type;
  501.     unsigned short _class;
  502.     unsigned int ttl;
  503.     unsigned short data_len;
  504. };
  505.  
  506. struct RES_RECORD
  507. {
  508.     unsigned char *name;
  509.     struct R_DATA *resource;
  510.     unsigned char *rdata;
  511. };
  512.  
  513. typedef struct
  514. {
  515.     unsigned char *name;
  516.     struct QUESTION *ques;
  517. } QUERY;
  518.  
  519. int main(int argc, char *argv[])
  520. {
  521.     int option;
  522.     int i = 0;
  523.    
  524.     // duplicate cmd line arguments cause getopt changes order
  525.     vector<string> argVector;
  526.     for(int j = 1; j < argc; j++){
  527.         argVector.push_back(argv[j]);
  528.     }
  529.     /*for (int i = 0; i < argVector.size(); i++)
  530.     {
  531.         cout << argVector[i] << "\n";
  532.     }*/
  533.  
  534.     while ((option = getopt(argc, argv, "rx6s:p::")) != -1)
  535.     {
  536.         i++;
  537.         switch (option)
  538.         {
  539.         case 'r':
  540.             //printf("got %d) %c \n", i, option);
  541.             recursion = true;
  542.             break;
  543.         case 'x':
  544.             //printf("got %d) %c \n", i, option);
  545.             reversed = true;
  546.             break;
  547.         case '6':
  548.             //printf("got %d) %c \n", i, option);
  549.             ipv6 = true;
  550.             break;
  551.         case 's':
  552.             // Option -s is followed by IP address or domain name of the server
  553.             //printf("got %d) %c \n", i, option);
  554.             for (int j = 0; j < argc; ++j)
  555.             {
  556.                 if (strcmp(argv[j], "-s") == 0)
  557.                 {
  558.                     //cout << argv[j] << "\n";
  559.                     i = setDNS(argv[j + 1], j);
  560.                 }
  561.             }
  562.             break;
  563.         case 'p':
  564.             // Option -p is followed by port number otherwise its set to 53
  565.             //printf("got %d) %c \n", i, option);
  566.             for (int j = 0; j < argc; ++j)
  567.             {
  568.                 if (strcmp(argv[j], "-p") == 0)
  569.                 {
  570.                     //cout << argv[j] << "\n";
  571.                     i = setPort(argv[j + 1], j);
  572.                 }
  573.             }
  574.             //i = setPort(argv[i + 1], i);
  575.             break;
  576.         case ':':
  577.             fprintf(stderr, "Option requires a value\n");
  578.             kill(i);
  579.             break;
  580.         case '?':
  581.             if (strcmp(argv[i], "-s") == 0)
  582.             {
  583.                 fprintf(stderr, "Option  -s requires a value\n");
  584.                 exit(-1);
  585.             }
  586.             else
  587.             {
  588.                 kill(i);
  589.             }
  590.             break;
  591.         default:
  592.             //printf("got %d) uknown: %c \n", i, option);
  593.             //kill(i);
  594.  
  595.             break;
  596.         }
  597.     }
  598.  
  599.     // Finding requested address to ask for in the command line arguments
  600.     for (int i = 0; i < argVector.size(); i++)
  601.     {
  602.         regex flagFollowed("^-[sp]$");
  603.         regex flagSingle("^-[6rx]$");
  604.         if (regex_match(argVector[i], flagFollowed)) // matches flag with attribute
  605.         {
  606.             i++;
  607.         }
  608.         else if (regex_match(argVector[i], flagSingle)) // matches flag without attribute
  609.         {
  610.             ;
  611.         }
  612.         else
  613.         {
  614.             askingFor = argVector[i];
  615.         }
  616.     }
  617.  
  618.     // Exit when no requested address found or
  619.     if (askingFor.empty())
  620.     {
  621.         kill(16);
  622.     }
  623.  
  624.     // Cheching requested domain name syntax
  625.     checkDomainNameSyntax(askingFor);
  626.  
  627.     printf("!!!RECAP!!!\n");
  628.     printf("Port var: %d\n", port);
  629.     cout << "Asking for: " << askingFor << "\n";
  630.     printf("IPV6: %d\n", (bool)ipv6);
  631.     printf("Reverse: %d\n", (bool)reversed);
  632.     printf("Recursion: %d\n", (bool)recursion);
  633.  
  634.    
  635.     // Creating socket file descriptor
  636.  
  637. #if defined(WIN32) // TODO:
  638.     WSADATA Data;
  639.     WSAStartup(MAKEWORD(2, 2), &Data); // 2.2 version
  640. #endif
  641.  
  642.     if ((mySocket = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
  643.     {
  644.         perror("Error: Socket was no created succesfully");
  645.         exit(EXIT_FAILURE);
  646.     }
  647.  
  648.     struct RES_RECORD answ[20], auth[20], addit[20]; //the replies from the DNS server
  649.     struct DNS_HEADER *dns = NULL;
  650.     struct QUESTION *qinfo = NULL;
  651.     dns = (struct DNS_HEADER *)&inBuf;
  652.  
  653.     memset(&to, 0, sizeof(to));
  654.     // Filling server information
  655.     to.sin_family = AF_INET;
  656.     to.sin_port = htons(port);
  657.     to.sin_addr.s_addr = inet_addr(serverToBeAsked.IPaddress.c_str());
  658.  
  659.     int pid = GetCurrentProcessId();
  660.  
  661.  
  662.     //                                 1  1  1  1  1  1
  663.     //   0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
  664.     // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  665.     // |                      ID                       |
  666.     // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  667.     // |QR|   Opcode  |AA|TC|RD|RA|   Z    |   RCODE   |
  668.     // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  669.     // |                    QDCOUNT                    |
  670.     // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  671.     // |                    ANCOUNT                    |
  672.     // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  673.     // |                    NSCOUNT                    |
  674.     // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  675.     // |                    ARCOUNT                    |
  676.     // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  677.  
  678.     dns -> id = (unsigned short) htons(pid);
  679.     dns -> rd = recursion; // 1 = "Do query recursively"
  680.     dns -> tc = 0; // 0 = "Message is not truncated"
  681.     dns -> aa = 0; // authoritative answer = false(0)
  682.     dns -> opcode = 0; // 0 = "Standard query"
  683.     dns -> qr = 0;       // 0 = "Message is a query(0)", response(1)
  684.     dns -> rcode = 0; // response code (0=ok, 1=format error, 2=server failure, 3=domain doesnt exist)
  685.     dns -> cd = 0; // chesking disabled
  686.     dns -> ad = 0; // 0 = "Non-authenticated data: Unnacceptable"
  687.     dns -> z = 0; // reserved
  688.     dns -> ra = 0; // recursion available = false
  689.     dns -> q_count = htons(1); // number of questions
  690.  
  691.     dns -> ans_count = 0; // number of answers
  692.     dns -> auth_count = 0; // number of authority entries
  693.     dns -> add_count = 0; // number of resource entries
  694.  
  695.     qname = (unsigned char *)&inBuf[sizeof(struct DNS_HEADER)];
  696.  
  697.     int l = askingFor.length();
  698.     char char_array[l + 1];
  699.     char new_char_array[l + 2];
  700.     memset(new_char_array, '.', sizeof(new_char_array));
  701.     strcpy(char_array, askingFor.c_str());
  702.     uint8_t counter;
  703.  
  704.     int k;
  705.     for (k = 0; char_array[k] != '\0'; k++)
  706.     {
  707.         if (char_array[k] == '.')
  708.         {
  709.             new_char_array[k - counter] &= 0;
  710.             new_char_array[k - counter] |= counter;  
  711.             counter = 0;
  712.         }else{
  713.             new_char_array[k + 1] = char_array[k];
  714.             counter++;
  715.         }
  716.     }
  717.     //set char 0x03 before com TLD,  0x02 before cz TLD
  718.     new_char_array[k - counter] &= 0;
  719.     new_char_array[k - counter] |= counter;
  720.  
  721.     // set char after TLD to 0x00
  722.     new_char_array[sizeof(new_char_array) - 1] &= 0;
  723.  
  724.     // copy new_char_array to qname
  725.     memcpy(qname, new_char_array, sizeof(new_char_array));
  726.  
  727.     /*printf("\n");
  728.     for (int i = 0; new_char_array[i] != '\0'; i++)
  729.     {
  730.  
  731.         printf("%c", new_char_array[i]);
  732.     }
  733.     printf("\n");*/
  734.  
  735.     qinfo = (struct QUESTION *)&inBuf[sizeof(struct DNS_HEADER) + sizeof(new_char_array)];
  736.  
  737.     qinfo->qtype = htons(1);  // requesting ipv4
  738.     qinfo->qclass = htons(1); // stands for IN
  739.  
  740.     int sentBytes = sendto(mySocket, (char *)inBuf, sizeof(struct DNS_HEADER) + sizeof(new_char_array) + sizeof(struct QUESTION), 0, (sockaddr *)&to, sizeof(to));
  741.     printf("Leti paket neco si prej! %d\n", sentBytes); // TODO: check na sendto
  742.  
  743.     int len;
  744.     int addrlen = sizeof(from);  // needs to be initialized
  745.     int receivedBytes = recvfrom(mySocket, (char *)outBuf, MAXLINE, MSG_PEEK, (struct sockaddr *)&from, &addrlen); //TODO: makro MSG_WAITALL
  746.     if (receivedBytes == -1)
  747.     {
  748.         fprintf(stderr, "Error: Function recvfrom.");
  749.         exit(-1);
  750.     }
  751.  
  752.     /*---------------------------------------------------------*/
  753.     /*-------------------READING INFORMATION-------------------*/
  754.     /*---------------------------------------------------------*/
  755.     Response r;
  756.  
  757.     /* Questions 2B */
  758.     r.QDCOUNT = outBuf[4];
  759.     r.QDCOUNT = (r.QDCOUNT << sizeof(outBuf[5])) | outBuf[5];
  760.     /* Answers  2B */
  761.     r.ANCOUNT = outBuf[6];
  762.     r.ANCOUNT = (r.ANCOUNT << sizeof(outBuf[7])) | outBuf[7];
  763.     /* Authorities 2B */
  764.     r.NSCOUNT = outBuf[8];
  765.     r.NSCOUNT = (r.NSCOUNT << sizeof(outBuf[9])) | outBuf[9];
  766.     /* Additional 2B */
  767.     r.ARCOUNT = outBuf[10];
  768.     r.ARCOUNT = (r.ARCOUNT << sizeof(outBuf[11])) | outBuf[11];
  769.  
  770. /*                                     1  1  1  1  1  1
  771.          0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
  772.        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  773.        |QR|   Opcode  |AA|TC|RD|RA|   Z    |   RCODE   |
  774.        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  775. */
  776.  
  777.     /* Authoritative Answer 1b */
  778.     uint8_t bitValue = outBuf[2];
  779.     bitValue &= 0b00000100;
  780.     bitValue >>= 2;
  781.     r.AA = bitValue;
  782.  
  783.     /* TrunCation 1b */
  784.     bitValue = outBuf[2];
  785.     bitValue &= 0b00000010;
  786.     bitValue >>= 1;
  787.     r.TC = bitValue;
  788.  
  789.     /* Recursion Available 1b */
  790.     bitValue = outBuf[3];
  791.     bitValue &= 0b10000000;
  792.     bitValue >>= 7;
  793.     r.RA = bitValue;
  794.  
  795.     /* Queried name VARIABLE LENGTH */
  796.     // Asked domain starts at 12th position of array
  797.     int qnameLen = r.decodeDomainName(&outBuf[12]);
  798.     cout << qnameLen << '\n';
  799.  
  800.     /* Queried type 2B */
  801.     int qTypeIndex = 12 + qnameLen;
  802.     r.QTYPE = outBuf[qTypeIndex];
  803.     r.QTYPE = (r.QTYPE << sizeof(outBuf[qTypeIndex + 1])) | outBuf[qTypeIndex + 1];
  804.  
  805.     /* Queried class 2B */
  806.     int qClassIndex = qTypeIndex + 2;
  807.     r.QCLASS = outBuf[qClassIndex];
  808.     r.QCLASS = (r.QCLASS << sizeof(outBuf[qClassIndex + 1])) | outBuf[qClassIndex +1];
  809.  
  810.     /* Resources */
  811.     /*                              1  1  1  1  1  1
  812.       0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
  813.     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  814.     |                                               |
  815.     /                                               /
  816.     /                      NAME                     /
  817.     |                                               |
  818.     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  819.     |                      TYPE                     |
  820.     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  821.     |                     CLASS                     |
  822.     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  823.     |                      TTL                      |
  824.     |                                               |
  825.     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  826.     |                   RDLENGTH                    |
  827.     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
  828.     /                     RDATA                     /
  829.     /                                               /
  830.     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+-*/
  831.  
  832.     int questions = r.QDCOUNT;
  833.     int answers = r.ANCOUNT;
  834.     int authority = r.NSCOUNT;
  835.     int additional = r.ARCOUNT;
  836.     // array of resource object
  837.     Resource **resourceArray = new Resource *[questions + answers + authority + additional];
  838.     int rPos = 0;
  839.  
  840.     while(questions){
  841.         resourceArray[rPos] = new Resource();
  842.         resourceArray[rPos]->hello(); //TODO: do konstruktoru typ a počet výskytu danýho typu
  843.         rPos++;
  844.         questions--;
  845.     }
  846.     while (answers){
  847.         resourceArray[rPos] = new Resource();
  848.         resourceArray[rPos]->hello();
  849.         rPos++;
  850.         answers--;
  851.     }
  852.     while (authority){
  853.         resourceArray[rPos] = new Resource();
  854.         resourceArray[rPos]->hello();
  855.         rPos++;
  856.         authority--;
  857.     }
  858.     while (additional){
  859.         resourceArray[rPos] = new Resource();
  860.         resourceArray[rPos]->hello();
  861.         rPos++;
  862.         additional--;
  863.     }
  864.  
  865.     int resrcsIndex = qClassIndex + 2;
  866.     unsigned char check = outBuf[resrcsIndex];
  867.     uint16_t offset;
  868.     int rsrcLen;
  869.  
  870.     Resource alpha;
  871.     // Check whether name is a pointer. Its truth when 2 leftmost bits are set to '1'.
  872.     if ((check & (1 << 7)) && (check & (1 << 6))) // Its a pointer
  873.     {
  874.         // The rest of the bits in the 2B block define an offset from the beggining on the response
  875.         offset = outBuf[resrcsIndex];
  876.         offset = (offset << sizeof(outBuf[resrcsIndex + 1]) & 0b00111111) | outBuf[resrcsIndex + 1];
  877.         alpha.decodeDomainName(&outBuf[offset]);
  878.         rsrcLen = 2;
  879.         cout << "TUNA: " << alpha.NAME << "\n";
  880.     }else{ // Its a domain name. TODO: • a sequence of labels ending with a pointer
  881.         rsrcLen = alpha.decodeDomainName(&outBuf[resrcsIndex]);
  882.         cout << "TUNA: " << alpha.NAME << "\n";
  883.     }
  884.  
  885.     /* Type A or CTYPE*/
  886.     uint16_t type = outBuf[resrcsIndex + rsrcLen];
  887.     type = (type << sizeof(outBuf[resrcsIndex + rsrcLen + 1]) | outBuf[resrcsIndex + rsrcLen + 1]);
  888.     if(type == 5){ // CNAME code
  889.         alpha.TYPE = "CNAME";
  890.     }else if(type == 1){ // A code
  891.         alpha.TYPE = "A";
  892.     }
  893.     cout << "TUNA: " << alpha.TYPE << "\n";
  894.  
  895.     r.printEverything();
  896.     r.printNicely();
  897.  
  898.     close(mySocket);
  899.  
  900. #if defined(WIN32) //TODO:
  901.     WSACleanup();
  902. #endif
  903.     return 0;
  904. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top