SHARE
TWEET

Untitled

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