Advertisement
Guest User

Untitled

a guest
Nov 17th, 2019
119
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 34.02 KB | None | 0 0
  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. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement